Frontend: gemeinsamer Hook useLiveData, Komponenten nach Bereichen, große Seiten aufgeteilt

- useLiveData: Laden, Nachladen (sichtbarer Tab) und Speichern mit
  Fehlerbehandlung an einer Stelle; genutzt von Vorrat, Reisen,
  Kanban-Übersicht und Kanban-Board (Monitoring/Benutzer arbeiten anders)
- components/<bereich>/: haushalt, reisen, kanban, monitoring, projekte,
  start, design (per git mv, Historie bleibt)
- Reisen.jsx 783 → 227 Zeilen (CitySearch, VisitedList, InfoCard,
  ExportDialog, laender.js), Haushalt.jsx 634 → 193 (ListPanel,
  ListSwitcher, ListDialog, ProductsDialog), KanbanBoard.jsx 452 → 277
  (board.js, TaskCard, TaskDialog)
- storage.js für Einstellungen pro Browser; Städteliste in Reisen memoisiert
- Verhalten unverändert (Browser-Durchlauf aller Seiten und Abläufe)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
guyg1474andClaude Opus 5.5 committed 2026-10-15 18:14:32 +02:00
1 parent 4aba48ce51
commit fa58708e2d
41 files changed
+1264 -1241

No files matched your search

@@ -0,0 +1,40 @@
import { initials, PRIORITIES } from './board.js';
// Karte einer Aufgabe im Board (ziehbar) und Anzeige des Bearbeiters
export function Assignee({ id, users }) {
const person = users.find((u) => u.id === id);
if (!person) return <span className="assignee none">Niemand</span>;
return (
<span className="assignee">
<span className="avatar" aria-hidden="true">{initials(person.name)}</span>
{person.name}
</span>
);
}
export default function TaskCard({ task, users, dragging, onOpen, onDragStart, onDragEnd }) {
return (
<button
type="button"
className={`task-card prio-card-${task.priority}${dragging ? ' dragging' : ''}`}
draggable
onDragStart={onDragStart}
onDragEnd={onDragEnd}
onClick={onOpen}
>
<span className="task-top">
<strong className="task-title">{task.title}</strong>
{task.priority !== 'mittel' && (
<span className={`prio prio-${task.priority}`} title={`Priorität: ${PRIORITIES.find((p) => p.key === task.priority)?.title}`}>
{PRIORITIES.find((p) => p.key === task.priority)?.title}
</span>
)}
</span>
{task.description && <span className="task-desc">{task.description}</span>}
<span className="task-meta">
<Assignee id={task.assignee} users={users} />
</span>
</button>
);
}