import Alert from '@mui/material/Alert'; import Box from '@mui/material/Box'; import CircularProgress from '@mui/material/CircularProgress'; import CssBaseline from '@mui/material/CssBaseline'; import Paper from '@mui/material/Paper'; import Table from '@mui/material/Table'; import TableBody from '@mui/material/TableBody'; import TableCell from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; import Typography from '@mui/material/Typography'; import { ThemeProvider } from '@mui/material/styles'; import { useEffect, useMemo, useState } from 'react'; import { useEmbeddedParentTheme } from '../embed/useEmbeddedParentTheme'; import { buildToirMuiTheme } from '../theme/toirMuiTheme'; import { env } from '../config/env'; import { ensureFreshToken, getAccessToken } from '../auth/keycloak'; type EquipmentRecord = { id: string; name: string; serialNumber: string; dateOfInspection: string | null; commissionedAt: string | null; installationDate: string | null; }; function formatDate(value: string | null) { if (!value) { return '—'; } const date = new Date(value); if (Number.isNaN(date.getTime())) { return value; } return new Intl.DateTimeFormat('ru-RU').format(date); } export function EmbeddedActiveEquipmentPage() { const paletteMode = useEmbeddedParentTheme(); const muiTheme = useMemo( () => buildToirMuiTheme(paletteMode), [paletteMode], ); const [data, setData] = useState([]); const [total, setTotal] = useState(null); const [isPending, setIsPending] = useState(true); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; const load = async () => { setIsPending(true); setError(null); try { await ensureFreshToken(); const token = getAccessToken(); const headers = new Headers({ Accept: 'application/json', }); if (token) { headers.set('Authorization', `Bearer ${token}`); } const query = new URLSearchParams({ _start: '0', _end: '100', _sort: 'name', _order: 'ASC', }); query.append('status', 'Active'); const response = await fetch(`${env.apiUrl}/equipment?${query.toString()}`, { headers, }); if (!response.ok) { const requestError = new Error(`Request failed with status ${response.status}`) as Error & { status?: number; }; requestError.status = response.status; throw requestError; } const payload = (await response.json()) as EquipmentRecord[]; const contentRange = response.headers.get('Content-Range'); const parsedTotal = contentRange?.match(/\/(\d+)$/)?.[1]; if (!cancelled) { setData(payload); setTotal(parsedTotal ? Number(parsedTotal) : payload.length); } } catch (caughtError) { if (!cancelled) { setError(caughtError instanceof Error ? caughtError : new Error('Unknown error')); } } finally { if (!cancelled) { setIsPending(false); } } }; void load(); return () => { cancelled = true; }; }, []); return ( `1px solid ${theme.palette.divider}`, background: paletteMode === 'dark' ? 'linear-gradient(145deg, rgba(255,255,255,0.06), rgba(0,0,0,0.1))' : 'linear-gradient(145deg, rgba(255,255,255,0.9), rgba(255,255,255,0.62))', }} > Оборудование в эксплуатации Отображаются записи со статусом 'Active' {typeof total === 'number' ? `: ${total}` : ''} {isPending ? ( ) : error ? ( Не удалось загрузить активное оборудование. ) : ( Наименование Заводской номер Дата установки Дата поверки {(data ?? []).map((item) => ( {item.name} {item.serialNumber} {formatDate(item.installationDate)} {formatDate(item.dateOfInspection)} ))}
)}
); }