new features
This commit is contained in:
@@ -21,6 +21,12 @@ import {
|
||||
Select,
|
||||
Stack,
|
||||
Tab,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
Tabs,
|
||||
TextField,
|
||||
Tooltip,
|
||||
@@ -34,6 +40,7 @@ import {
|
||||
DeleteOutline,
|
||||
Edit,
|
||||
Error as ErrorIcon,
|
||||
History,
|
||||
MoreHoriz,
|
||||
PauseCircle,
|
||||
RemoveCircle,
|
||||
@@ -97,6 +104,65 @@ function fmtDate(iso: string | null | undefined): string {
|
||||
});
|
||||
}
|
||||
|
||||
function fmtDatetime(iso: string | null | undefined): string {
|
||||
if (!iso) return '---';
|
||||
return new Date(iso).toLocaleString('de-DE', {
|
||||
day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit',
|
||||
});
|
||||
}
|
||||
|
||||
// -- Status History Section ---------------------------------------------------
|
||||
|
||||
const StatusHistorySection: React.FC<{ equipmentId: string }> = ({ equipmentId }) => {
|
||||
const [history, setHistory] = useState<{ alter_status: string; neuer_status: string; bemerkung?: string; geaendert_von_name?: string; erstellt_am: string }[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
equipmentApi.getStatusHistory(equipmentId)
|
||||
.then(setHistory)
|
||||
.catch(() => setHistory([]))
|
||||
.finally(() => setLoading(false));
|
||||
}, [equipmentId]);
|
||||
|
||||
if (loading || history.length === 0) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h6" sx={{ mt: 3, mb: 1.5, display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<History fontSize="small" /> Status-Verlauf
|
||||
</Typography>
|
||||
<TableContainer component={Paper} variant="outlined">
|
||||
<Table size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Datum</TableCell>
|
||||
<TableCell>Von</TableCell>
|
||||
<TableCell>Nach</TableCell>
|
||||
<TableCell>Bemerkung</TableCell>
|
||||
<TableCell>Geändert von</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{history.map((h, idx) => (
|
||||
<TableRow key={idx}>
|
||||
<TableCell>{fmtDatetime(h.erstellt_am)}</TableCell>
|
||||
<TableCell>
|
||||
<Chip size="small" label={AusruestungStatusLabel[h.alter_status as AusruestungStatus] || h.alter_status} color={STATUS_CHIP_COLOR[h.alter_status as AusruestungStatus] || 'default'} />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Chip size="small" label={AusruestungStatusLabel[h.neuer_status as AusruestungStatus] || h.neuer_status} color={STATUS_CHIP_COLOR[h.neuer_status as AusruestungStatus] || 'default'} />
|
||||
</TableCell>
|
||||
<TableCell>{h.bemerkung || '—'}</TableCell>
|
||||
<TableCell>{h.geaendert_von_name || '—'}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
// -- Wartungslog Art config ---------------------------------------------------
|
||||
|
||||
const WARTUNG_ART_CHIP_COLOR: Record<AusruestungWartungslogArt, 'info' | 'warning' | 'default'> = {
|
||||
@@ -337,6 +403,8 @@ const UebersichtTab: React.FC<UebersichtTabProps> = ({ equipment, onStatusUpdate
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
<StatusHistorySection equipmentId={equipment.id} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -430,7 +498,7 @@ const WartungTab: React.FC<WartungTabProps> = ({ equipmentId, wartungslog, onAdd
|
||||
<Typography variant="body2">{entry.beschreibung}</Typography>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mt: 0.25 }}>
|
||||
{[
|
||||
entry.kosten != null && `${entry.kosten.toFixed(2)} EUR`,
|
||||
entry.kosten != null && `${Number(entry.kosten).toFixed(2)} EUR`,
|
||||
entry.pruefende_stelle && entry.pruefende_stelle,
|
||||
].filter(Boolean).join(' · ')}
|
||||
</Typography>
|
||||
@@ -563,7 +631,7 @@ const WartungTab: React.FC<WartungTabProps> = ({ equipmentId, wartungslog, onAdd
|
||||
function AusruestungDetailPage() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const navigate = useNavigate();
|
||||
const { isAdmin, canManageCategory } = usePermissions();
|
||||
const { isAdmin, canManageCategory, canManageEquipmentMaintenance } = usePermissions();
|
||||
const notification = useNotification();
|
||||
|
||||
const [equipment, setEquipment] = useState<AusruestungDetail | null>(null);
|
||||
@@ -706,6 +774,8 @@ function AusruestungDetailPage() {
|
||||
value={activeTab}
|
||||
onChange={(_, v) => setActiveTab(v)}
|
||||
aria-label="Ausrüstung Detailansicht"
|
||||
variant="scrollable"
|
||||
scrollButtons="auto"
|
||||
>
|
||||
<Tab label="Übersicht" />
|
||||
<Tab
|
||||
@@ -733,7 +803,7 @@ function AusruestungDetailPage() {
|
||||
equipmentId={equipment.id}
|
||||
wartungslog={equipment.wartungslog ?? []}
|
||||
onAdded={fetchEquipment}
|
||||
canWrite={canWrite}
|
||||
canWrite={canManageEquipmentMaintenance}
|
||||
/>
|
||||
</TabPanel>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user