import type { Fach, Material } from "../../api/types"; interface PositionZeile { materialId: number | ""; fach: string; sollmenge: string; } interface Props { zeilen: PositionZeile[]; onZeilenChange: (zeilen: PositionZeile[]) => void; materialien: Material[]; faecher: Fach[]; } const OHNE_FACH = "__ohne_fach__"; /** Shelf-inspiriert (Nutzer-Vorgabe 2026-09-05: gute Inhalte aus Vergleichsprojekten * übernehmen): Beladungsplanung per Drag&Drop statt Zeile-für-Zeile-Formular - * Material aus dem Pool links in eine Fach-Spalte rechts ziehen, weiterziehen * verschiebt es ins andere Fach, "×" entfernt es wieder in den Pool. */ export function BeladungsplanerBoard({ zeilen, onZeilenChange, materialien, faecher }: Props) { const zugewieseneIds = new Set(zeilen.filter((z) => z.materialId !== "").map((z) => z.materialId)); const pool = materialien.filter((m) => !zugewieseneIds.has(m.id)); const spalten = [...faecher.map((f) => f.name), OHNE_FACH]; function materialName(id: number | ""): string { if (id === "") return ""; return materialien.find((m) => m.id === id)?.name ?? `#${id}`; } function onDropAufSpalte(e: React.DragEvent, fachName: string) { e.preventDefault(); const materialId = Number(e.dataTransfer.getData("text/plain")); if (!materialId) return; const zielFach = fachName === OHNE_FACH ? "" : fachName; const vorhanden = zeilen.find((z) => z.materialId === materialId); if (vorhanden) { onZeilenChange(zeilen.map((z) => (z.materialId === materialId ? { ...z, fach: zielFach } : z))); } else { onZeilenChange([...zeilen, { materialId, fach: zielFach, sollmenge: "1" }]); } } function sollmengeAendern(materialId: number, sollmenge: string) { onZeilenChange(zeilen.map((z) => (z.materialId === materialId ? { ...z, sollmenge } : z))); } function entfernen(materialId: number) { onZeilenChange(zeilen.filter((z) => z.materialId !== materialId)); } return (
Alles zugeordnet.
}Material hierher ziehen…
)}