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 [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({
|
const addMutation = useMutation({
|
||||||
mutationFn: (data: CreateVorlageItemPayload) => checklistenApi.addVorlageItem(vorlageId, data),
|
mutationFn: (data: CreateVorlageItemPayload) => checklistenApi.addVorlageItem(vorlageId, data),
|
||||||
@@ -630,24 +632,63 @@ function VorlageItemsSection({ vorlageId, queryClient, showSuccess, showError }:
|
|||||||
onError: () => showError('Fehler beim Hinzufügen'),
|
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({
|
const deleteMutation = useMutation({
|
||||||
mutationFn: (id: number) => checklistenApi.deleteVorlageItem(id),
|
mutationFn: (id: number) => checklistenApi.deleteVorlageItem(id),
|
||||||
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['checklisten-vorlage-items', vorlageId] }); showSuccess('Item entfernt'); },
|
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['checklisten-vorlage-items', vorlageId] }); showSuccess('Item entfernt'); },
|
||||||
onError: () => showError('Fehler beim Entfernen'),
|
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} />;
|
if (isLoading) return <CircularProgress size={20} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="subtitle2" sx={{ mb: 1 }}>Checklisten-Items</Typography>
|
<Typography variant="subtitle2" sx={{ mb: 1 }}>Checklisten-Items</Typography>
|
||||||
{items.map((item) => (
|
{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 }}>
|
<Typography variant="body2" sx={{ flexGrow: 1 }}>
|
||||||
{item.bezeichnung} {item.pflicht && <Chip label="Pflicht" size="small" color="warning" sx={{ ml: 0.5 }} />}
|
{item.bezeichnung} {item.pflicht && <Chip label="Pflicht" size="small" color="warning" sx={{ ml: 0.5 }} />}
|
||||||
</Typography>
|
</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>
|
<IconButton size="small" color="error" onClick={() => deleteMutation.mutate(item.id)}><DeleteIcon fontSize="small" /></IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
))}
|
))}
|
||||||
<Box sx={{ display: 'flex', gap: 1, mt: 1, alignItems: 'center' }}>
|
<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 }} />
|
<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