feat: add inline editing for checklist vorlage items
This commit is contained in:
@@ -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 }} />
|
||||
|
||||
Reference in New Issue
Block a user