Materialliste: zweispaltiges Layout mit Suche
Formular (Anlegen/Bearbeiten) links fix, Liste rechts mit Suchfeld oben (Name/Artikelnummer) - bei 153 Materialien war die reine Scroll-Liste ohne Suche kaum nutzbar. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
@@ -26,6 +26,7 @@ export function MaterialSection({ materialien, onGeaendert, onFehler }: Props) {
|
||||
const [formular, setFormular] = useState(LEERES_FORMULAR);
|
||||
const [bearbeiteteId, setBearbeiteteId] = useState<number | null>(null);
|
||||
const [wirdGespeichert, setWirdGespeichert] = useState(false);
|
||||
const [suche, setSuche] = useState("");
|
||||
|
||||
function bearbeiten(material: Material) {
|
||||
setBearbeiteteId(material.id);
|
||||
@@ -65,11 +66,22 @@ export function MaterialSection({ materialien, onGeaendert, onFehler }: Props) {
|
||||
}
|
||||
}
|
||||
|
||||
const sucheNormalisiert = suche.trim().toLowerCase();
|
||||
const gefiltert = sucheNormalisiert
|
||||
? materialien.filter(
|
||||
(m) =>
|
||||
m.name.toLowerCase().includes(sucheNormalisiert) ||
|
||||
(m.artikelnummer ?? "").toLowerCase().includes(sucheNormalisiert)
|
||||
)
|
||||
: materialien;
|
||||
|
||||
return (
|
||||
<section className="section">
|
||||
<h2>Material {bearbeiteteId !== null ? "bearbeiten" : "anlegen"}</h2>
|
||||
<div className="card">
|
||||
<div className="stack" style={{ marginBottom: "1.25rem" }}>
|
||||
<h2>Material</h2>
|
||||
<div style={{ display: "flex", flexDirection: "row", alignItems: "flex-start", gap: "1.25rem" }}>
|
||||
<div className="card" style={{ flex: "0 0 20rem", width: "20rem", boxSizing: "border-box" }}>
|
||||
<h3 style={{ marginTop: 0 }}>{bearbeiteteId !== null ? "Material bearbeiten" : "Material anlegen"}</h3>
|
||||
<div className="stack">
|
||||
<div className="field">
|
||||
<label>Name</label>
|
||||
<input
|
||||
@@ -78,8 +90,7 @@ export function MaterialSection({ materialien, onGeaendert, onFehler }: Props) {
|
||||
onChange={(e) => setFormular({ ...formular, name: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="field" style={{ flex: 1 }}>
|
||||
<div className="field">
|
||||
<label>Artikelnummer</label>
|
||||
<input
|
||||
className="input"
|
||||
@@ -87,7 +98,7 @@ export function MaterialSection({ materialien, onGeaendert, onFehler }: Props) {
|
||||
onChange={(e) => setFormular({ ...formular, artikelnummer: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
<div className="field" style={{ width: "7rem" }}>
|
||||
<div className="field">
|
||||
<label>Einheit</label>
|
||||
<input
|
||||
className="input"
|
||||
@@ -95,7 +106,6 @@ export function MaterialSection({ materialien, onGeaendert, onFehler }: Props) {
|
||||
onChange={(e) => setFormular({ ...formular, einheit: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label>Materialtyp</label>
|
||||
<select
|
||||
@@ -125,13 +135,29 @@ export function MaterialSection({ materialien, onGeaendert, onFehler }: Props) {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{materialien.length > 0 && (
|
||||
<div style={{ flex: "1 1 0%", minWidth: 0 }}>
|
||||
<input
|
||||
className="input input-search"
|
||||
style={{ marginBottom: "1rem" }}
|
||||
placeholder={`Suche in ${materialien.length} Materialien…`}
|
||||
value={suche}
|
||||
onChange={(e) => setSuche(e.target.value)}
|
||||
/>
|
||||
{gefiltert.length === 0 && <p className="text-muted">Keine Treffer.</p>}
|
||||
{gefiltert.length > 0 && (
|
||||
<ul className="card-list">
|
||||
{materialien.map((m) => (
|
||||
<li key={m.id} className="row-between" style={{ padding: "0.4rem 0" }}>
|
||||
{gefiltert.map((m) => (
|
||||
<li key={m.id} className="card row-between" style={{ padding: "0.6rem 1rem" }}>
|
||||
<span>
|
||||
{m.name} <span className="text-muted">({m.einheit})</span>
|
||||
{m.artikelnummer && <span className="text-muted"> · {m.artikelnummer}</span>}
|
||||
{m.materialtyp !== "standard" && (
|
||||
<span className="badge badge-neutral" style={{ marginLeft: "0.5rem" }}>
|
||||
{m.materialtyp}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
<button className="btn btn-secondary" onClick={() => bearbeiten(m)}>
|
||||
Bearbeiten
|
||||
@@ -141,6 +167,7 @@ export function MaterialSection({ materialien, onGeaendert, onFehler }: Props) {
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user