feat: add inline editing for checklist vorlage items

This commit is contained in:
Matthias Hochmeister
2026-03-28 18:17:32 +01:00
parent 4c1f188371
commit 15337f768d

View File

@@ -623,6 +623,8 @@ function VorlageItemsSection({ vorlageId, queryClient, showSuccess, showError }:
});
const [newItem, setNewItem] = useState<CreateVorlageItemPayload>({ bezeichnung: '', pflicht: false, sort_order: 0 });
const [editingId, setEditingId] = useState<number | null>(null);
const [editForm, setEditForm] = useState<{ bezeichnung: string; pflicht: boolean }>({ bezeichnung: '', pflicht: false });
const addMutation = useMutation({
mutationFn: (data: CreateVorlageItemPayload) => checklistenApi.addVorlageItem(vorlageId, data),
@@ -630,24 +632,63 @@ function VorlageItemsSection({ vorlageId, queryClient, showSuccess, showError }:
onError: () => showError('Fehler beim Hinzufügen'),
});
const updateMutation = useMutation({
mutationFn: ({ id, data }: { id: number; data: { bezeichnung: string; pflicht: boolean } }) => checklistenApi.updateVorlageItem(id, data),
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['checklisten-vorlage-items', vorlageId] }); setEditingId(null); showSuccess('Item aktualisiert'); },
onError: () => showError('Fehler beim Aktualisieren'),
});
const deleteMutation = useMutation({
mutationFn: (id: number) => checklistenApi.deleteVorlageItem(id),
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['checklisten-vorlage-items', vorlageId] }); showSuccess('Item entfernt'); },
onError: () => showError('Fehler beim Entfernen'),
});
const startEdit = (item: ChecklistVorlageItem) => {
setEditingId(item.id);
setEditForm({ bezeichnung: item.bezeichnung, pflicht: item.pflicht });
};
if (isLoading) return <CircularProgress size={20} />;
return (
<Box>
<Typography variant="subtitle2" sx={{ mb: 1 }}>Checklisten-Items</Typography>
{items.map((item) => (
<Box key={item.id} sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 0.5 }}>
<Box key={item.id} sx={{ mb: 0.5 }}>
{editingId === item.id ? (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<TextField
size="small"
value={editForm.bezeichnung}
onChange={(e) => setEditForm((f) => ({ ...f, bezeichnung: e.target.value }))}
sx={{ flexGrow: 1 }}
autoFocus
/>
<FormControlLabel
control={<Switch size="small" checked={editForm.pflicht} onChange={(e) => setEditForm((f) => ({ ...f, pflicht: e.target.checked }))} />}
label="Pflicht"
/>
<Button
size="small"
variant="contained"
disabled={!editForm.bezeichnung.trim() || updateMutation.isPending}
onClick={() => updateMutation.mutate({ id: item.id, data: editForm })}
>
Speichern
</Button>
<Button size="small" onClick={() => setEditingId(null)}>Abbrechen</Button>
</Box>
) : (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<Typography variant="body2" sx={{ flexGrow: 1 }}>
{item.bezeichnung} {item.pflicht && <Chip label="Pflicht" size="small" color="warning" sx={{ ml: 0.5 }} />}
</Typography>
<IconButton size="small" onClick={() => startEdit(item)}><EditIcon fontSize="small" /></IconButton>
<IconButton size="small" color="error" onClick={() => deleteMutation.mutate(item.id)}><DeleteIcon fontSize="small" /></IconButton>
</Box>
)}
</Box>
))}
<Box sx={{ display: 'flex', gap: 1, mt: 1, alignItems: 'center' }}>
<TextField size="small" placeholder="Neues Item..." value={newItem.bezeichnung} onChange={(e) => setNewItem((n) => ({ ...n, bezeichnung: e.target.value }))} sx={{ flexGrow: 1 }} />