fix: add checklisten sidebar sub-items and replace unicode escapes with proper umlauts
This commit is contained in:
@@ -28,7 +28,7 @@ import type { ChecklistAusfuehrungItem } from '../types/checklist.types';
|
||||
// ── Helpers ──
|
||||
|
||||
const formatDate = (iso?: string) =>
|
||||
iso ? new Date(iso).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }) : '\u2013';
|
||||
iso ? new Date(iso).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }) : '–';
|
||||
|
||||
const ERGEBNIS_ICONS: Record<string, JSX.Element> = {
|
||||
ok: <CheckCircle fontSize="small" color="success" />,
|
||||
@@ -110,7 +110,7 @@ export default function ChecklistAusfuehrung() {
|
||||
queryClient.invalidateQueries({ queryKey: ['checklisten-faellig'] });
|
||||
showSuccess('Checkliste abgeschlossen');
|
||||
},
|
||||
onError: () => showError('Fehler beim Abschlie\u00dfen'),
|
||||
onError: () => showError('Fehler beim Abschließen'),
|
||||
});
|
||||
|
||||
// ── Approve ──
|
||||
@@ -145,7 +145,7 @@ export default function ChecklistAusfuehrung() {
|
||||
return (
|
||||
<DashboardLayout>
|
||||
<Alert severity="error">Checkliste konnte nicht geladen werden.</Alert>
|
||||
<Button startIcon={<ArrowBack />} onClick={() => navigate('/checklisten')} sx={{ mt: 2 }}>Zur\u00fcck</Button>
|
||||
<Button startIcon={<ArrowBack />} onClick={() => navigate('/checklisten')} sx={{ mt: 2 }}>Zurück</Button>
|
||||
</DashboardLayout>
|
||||
);
|
||||
}
|
||||
@@ -222,7 +222,7 @@ export default function ChecklistAusfuehrung() {
|
||||
{execution.vorlage_name ?? 'Checkliste'}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" color="text.secondary">
|
||||
{execution.fahrzeug_name ?? '\u2013'} · {formatDate(execution.ausgefuehrt_am ?? execution.created_at)}
|
||||
{execution.fahrzeug_name ?? '–'} · {formatDate(execution.ausgefuehrt_am ?? execution.created_at)}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Chip
|
||||
@@ -233,7 +233,7 @@ export default function ChecklistAusfuehrung() {
|
||||
|
||||
{execution.status === 'unvollstaendig' && (
|
||||
<Alert severity="warning" sx={{ mb: 2 }}>
|
||||
Diese Checkliste wurde als unvollst\u00e4ndig abgeschlossen. Einige Pflicht-Items wurden nicht mit "OK" bewertet.
|
||||
Diese Checkliste wurde als unvollständig abgeschlossen. Einige Pflicht-Items wurden nicht mit "OK" bewertet.
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
@@ -260,7 +260,7 @@ export default function ChecklistAusfuehrung() {
|
||||
fullWidth
|
||||
multiline
|
||||
rows={3}
|
||||
placeholder="Zus\u00e4tzliche Notizen..."
|
||||
placeholder="Zusätzliche Notizen..."
|
||||
value={notizen}
|
||||
onChange={(e) => setNotizen(e.target.value)}
|
||||
/>
|
||||
@@ -277,7 +277,7 @@ export default function ChecklistAusfuehrung() {
|
||||
disabled={submitMutation.isPending}
|
||||
startIcon={submitMutation.isPending ? <CircularProgress size={16} /> : undefined}
|
||||
>
|
||||
Abschlie\u00dfen
|
||||
Abschließen
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -299,7 +299,7 @@ export default function ChecklistAusfuehrung() {
|
||||
<Paper variant="outlined" sx={{ p: 2, mt: 3 }}>
|
||||
{execution.ausgefuehrt_von_name && (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Ausgef\u00fchrt von: {execution.ausgefuehrt_von_name} am {formatDate(execution.ausgefuehrt_am)}
|
||||
Ausgeführt von: {execution.ausgefuehrt_von_name} am {formatDate(execution.ausgefuehrt_am)}
|
||||
</Typography>
|
||||
)}
|
||||
{execution.freigegeben_von_name && (
|
||||
|
||||
@@ -64,12 +64,12 @@ import type {
|
||||
// ── Helpers ──
|
||||
|
||||
const formatDate = (iso?: string) =>
|
||||
iso ? new Date(iso).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' }) : '\u2013';
|
||||
iso ? new Date(iso).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' }) : '–';
|
||||
|
||||
const INTERVALL_LABELS: Record<string, string> = {
|
||||
weekly: 'W\u00f6chentlich',
|
||||
weekly: 'Wöchentlich',
|
||||
monthly: 'Monatlich',
|
||||
yearly: 'J\u00e4hrlich',
|
||||
yearly: 'Jährlich',
|
||||
custom: 'Benutzerdefiniert',
|
||||
};
|
||||
|
||||
@@ -95,7 +95,7 @@ export default function Checklisten() {
|
||||
const canManageTemplates = hasPermission('checklisten:manage_templates');
|
||||
const canExecute = hasPermission('checklisten:execute');
|
||||
|
||||
// Tabs: 0=\u00dcbersicht, 1=Vorlagen (if perm), 2=Fahrzeugtypen (if perm), 3=Historie
|
||||
// Tabs: 0=Übersicht, 1=Vorlagen (if perm), 2=Fahrzeugtypen (if perm), 3=Historie
|
||||
const manageTabs = canManageTemplates ? 2 : 0;
|
||||
const TAB_COUNT = 2 + manageTabs;
|
||||
|
||||
@@ -160,14 +160,14 @@ export default function Checklisten() {
|
||||
variant="scrollable"
|
||||
scrollButtons="auto"
|
||||
>
|
||||
<Tab label="\u00dcbersicht" />
|
||||
<Tab label="Übersicht" />
|
||||
{canManageTemplates && <Tab label="Vorlagen" />}
|
||||
{canManageTemplates && <Tab label="Fahrzeugtypen" />}
|
||||
<Tab label="Historie" />
|
||||
</Tabs>
|
||||
</Box>
|
||||
|
||||
{/* Tab 0: \u00dcbersicht */}
|
||||
{/* Tab 0: Übersicht */}
|
||||
<TabPanel value={tab} index={0}>
|
||||
{vehiclesLoading ? (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', py: 4 }}><CircularProgress /></Box>
|
||||
@@ -185,7 +185,7 @@ export default function Checklisten() {
|
||||
{vOverdue.length > 0 && (
|
||||
<Chip
|
||||
icon={<Warning />}
|
||||
label={`${vOverdue.length} f\u00e4llig`}
|
||||
label={`${vOverdue.length} fällig`}
|
||||
color="error"
|
||||
size="small"
|
||||
/>
|
||||
@@ -200,7 +200,7 @@ export default function Checklisten() {
|
||||
<Warning fontSize="small" color="error" />
|
||||
<Typography variant="body2">{f.vorlage_name}</Typography>
|
||||
<Typography variant="caption" color="error.main">
|
||||
({days > 0 ? `${days}d \u00fcberf\u00e4llig` : 'heute f\u00e4llig'})
|
||||
({days > 0 ? `${days}d überfällig` : 'heute fällig'})
|
||||
</Typography>
|
||||
</Box>
|
||||
{canExecute && (
|
||||
@@ -304,8 +304,8 @@ function VorlagenTab({ vorlagen, loading, fahrzeugTypen, queryClient, showSucces
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
mutationFn: (id: number) => checklistenApi.deleteVorlage(id),
|
||||
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['checklisten-vorlagen'] }); showSuccess('Vorlage gel\u00f6scht'); },
|
||||
onError: () => showError('Fehler beim L\u00f6schen der Vorlage'),
|
||||
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['checklisten-vorlagen'] }); showSuccess('Vorlage gelöscht'); },
|
||||
onError: () => showError('Fehler beim Löschen der Vorlage'),
|
||||
});
|
||||
|
||||
const openCreate = () => { setEditingVorlage(null); setForm(emptyForm); setDialogOpen(true); };
|
||||
@@ -353,9 +353,9 @@ function VorlagenTab({ vorlagen, loading, fahrzeugTypen, queryClient, showSucces
|
||||
<React.Fragment key={v.id}>
|
||||
<TableRow hover sx={{ cursor: 'pointer' }} onClick={() => setExpandedVorlageId(expandedVorlageId === v.id ? null : v.id)}>
|
||||
<TableCell>{v.name}</TableCell>
|
||||
<TableCell>{v.fahrzeug_typ?.name ?? '\u2013'}</TableCell>
|
||||
<TableCell>{v.fahrzeug_typ?.name ?? '–'}</TableCell>
|
||||
<TableCell>
|
||||
{v.intervall ? INTERVALL_LABELS[v.intervall] || v.intervall : '\u2013'}
|
||||
{v.intervall ? INTERVALL_LABELS[v.intervall] || v.intervall : '–'}
|
||||
{v.intervall === 'custom' && v.intervall_tage ? ` (${v.intervall_tage} Tage)` : ''}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
@@ -396,9 +396,9 @@ function VorlagenTab({ vorlagen, loading, fahrzeugTypen, queryClient, showSucces
|
||||
<InputLabel>Intervall</InputLabel>
|
||||
<Select label="Intervall" value={form.intervall ?? ''} onChange={(e) => setForm((f) => ({ ...f, intervall: (e.target.value || undefined) as CreateVorlagePayload['intervall'] }))}>
|
||||
<MenuItem value="">Kein Intervall</MenuItem>
|
||||
<MenuItem value="weekly">W\u00f6chentlich</MenuItem>
|
||||
<MenuItem value="weekly">Wöchentlich</MenuItem>
|
||||
<MenuItem value="monthly">Monatlich</MenuItem>
|
||||
<MenuItem value="yearly">J\u00e4hrlich</MenuItem>
|
||||
<MenuItem value="yearly">Jährlich</MenuItem>
|
||||
<MenuItem value="custom">Benutzerdefiniert</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
@@ -431,8 +431,8 @@ function VorlageItemsSection({ vorlageId, queryClient, showSuccess, showError }:
|
||||
|
||||
const addMutation = useMutation({
|
||||
mutationFn: (data: CreateVorlageItemPayload) => checklistenApi.addVorlageItem(vorlageId, data),
|
||||
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['checklisten-vorlage-items', vorlageId] }); setNewItem({ bezeichnung: '', pflicht: false, sort_order: 0 }); showSuccess('Item hinzugef\u00fcgt'); },
|
||||
onError: () => showError('Fehler beim Hinzuf\u00fcgen'),
|
||||
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['checklisten-vorlage-items', vorlageId] }); setNewItem({ bezeichnung: '', pflicht: false, sort_order: 0 }); showSuccess('Item hinzugefügt'); },
|
||||
onError: () => showError('Fehler beim Hinzufügen'),
|
||||
});
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
@@ -458,7 +458,7 @@ function VorlageItemsSection({ vorlageId, queryClient, showSuccess, showError }:
|
||||
<TextField size="small" placeholder="Neues Item..." value={newItem.bezeichnung} onChange={(e) => setNewItem((n) => ({ ...n, bezeichnung: e.target.value }))} sx={{ flexGrow: 1 }} />
|
||||
<FormControlLabel control={<Switch size="small" checked={newItem.pflicht} onChange={(e) => setNewItem((n) => ({ ...n, pflicht: e.target.checked }))} />} label="Pflicht" />
|
||||
<Button size="small" variant="outlined" disabled={!newItem.bezeichnung.trim() || addMutation.isPending} onClick={() => addMutation.mutate(newItem)}>
|
||||
Hinzuf\u00fcgen
|
||||
Hinzufügen
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
@@ -495,8 +495,8 @@ function FahrzeugTypenTab({ fahrzeugTypen, queryClient, showSuccess, showError }
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
mutationFn: (id: number) => fahrzeugTypenApi.delete(id),
|
||||
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['fahrzeug-typen'] }); showSuccess('Fahrzeugtyp gel\u00f6scht'); },
|
||||
onError: () => showError('Fehler beim L\u00f6schen'),
|
||||
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['fahrzeug-typen'] }); showSuccess('Fahrzeugtyp gelöscht'); },
|
||||
onError: () => showError('Fehler beim Löschen'),
|
||||
});
|
||||
|
||||
const openCreate = () => { setEditing(null); setForm({ name: '', beschreibung: '', icon: '' }); setDialogOpen(true); };
|
||||
@@ -536,8 +536,8 @@ function FahrzeugTypenTab({ fahrzeugTypen, queryClient, showSuccess, showError }
|
||||
fahrzeugTypen.map((t) => (
|
||||
<TableRow key={t.id} hover>
|
||||
<TableCell>{t.name}</TableCell>
|
||||
<TableCell>{t.beschreibung ?? '\u2013'}</TableCell>
|
||||
<TableCell>{t.icon ?? '\u2013'}</TableCell>
|
||||
<TableCell>{t.beschreibung ?? '–'}</TableCell>
|
||||
<TableCell>{t.icon ?? '–'}</TableCell>
|
||||
<TableCell align="right">
|
||||
<IconButton size="small" onClick={() => openEdit(t)}><EditIcon fontSize="small" /></IconButton>
|
||||
<IconButton size="small" color="error" onClick={() => deleteMutation.mutate(t.id)}><DeleteIcon fontSize="small" /></IconButton>
|
||||
@@ -620,24 +620,24 @@ function HistorieTab({ executions, loading, navigate }: HistorieTabProps) {
|
||||
<TableCell>Vorlage</TableCell>
|
||||
<TableCell>Datum</TableCell>
|
||||
<TableCell>Status</TableCell>
|
||||
<TableCell>Ausgef\u00fchrt von</TableCell>
|
||||
<TableCell>Ausgeführt von</TableCell>
|
||||
<TableCell>Freigegeben von</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{filtered.length === 0 ? (
|
||||
<TableRow><TableCell colSpan={6} align="center">Keine Eintr\u00e4ge</TableCell></TableRow>
|
||||
<TableRow><TableCell colSpan={6} align="center">Keine Einträge</TableCell></TableRow>
|
||||
) : (
|
||||
filtered.map((e) => (
|
||||
<TableRow key={e.id} hover sx={{ cursor: 'pointer' }} onClick={() => navigate(`/checklisten/ausfuehrung/${e.id}`)}>
|
||||
<TableCell>{e.fahrzeug_name ?? '\u2013'}</TableCell>
|
||||
<TableCell>{e.vorlage_name ?? '\u2013'}</TableCell>
|
||||
<TableCell>{e.fahrzeug_name ?? '–'}</TableCell>
|
||||
<TableCell>{e.vorlage_name ?? '–'}</TableCell>
|
||||
<TableCell>{formatDate(e.ausgefuehrt_am ?? e.created_at)}</TableCell>
|
||||
<TableCell>
|
||||
<Chip label={CHECKLIST_STATUS_LABELS[e.status]} color={CHECKLIST_STATUS_COLORS[e.status]} size="small" />
|
||||
</TableCell>
|
||||
<TableCell>{e.ausgefuehrt_von_name ?? '\u2013'}</TableCell>
|
||||
<TableCell>{e.freigegeben_von_name ?? '\u2013'}</TableCell>
|
||||
<TableCell>{e.ausgefuehrt_von_name ?? '–'}</TableCell>
|
||||
<TableCell>{e.freigegeben_von_name ?? '–'}</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user