feature/webgl-preview-update (#21)
Co-authored-by: itoshi <kkzemeow@gmail.com> Reviewed-on: #21
This commit was merged in pull request #21.
This commit is contained in:
180
src/widgets/DevicesTable/VehicleSessionsModal.tsx
Normal file
180
src/widgets/DevicesTable/VehicleSessionsModal.tsx
Normal file
@@ -0,0 +1,180 @@
|
||||
import { Modal, vehicleStore } from "@shared";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
CircularProgress,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useEffect } from "react";
|
||||
|
||||
interface VehicleSessionsModalProps {
|
||||
open: boolean;
|
||||
vehicleId: number | null;
|
||||
tailNumber?: string | null;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const formatDateTime = (value: string) => {
|
||||
if (!value) return "-";
|
||||
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) return value;
|
||||
|
||||
return new Intl.DateTimeFormat("ru-RU", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
hour12: false,
|
||||
}).format(date);
|
||||
};
|
||||
|
||||
const formatDuration = (durationSeconds: number) => {
|
||||
if (!Number.isFinite(durationSeconds) || durationSeconds < 0) {
|
||||
return "-";
|
||||
}
|
||||
|
||||
const hours = Math.floor(durationSeconds / 3600);
|
||||
const minutes = Math.floor((durationSeconds % 3600) / 60);
|
||||
const seconds = durationSeconds % 60;
|
||||
|
||||
return [hours, minutes, seconds]
|
||||
.map((part) => String(part).padStart(2, "0"))
|
||||
.join(":");
|
||||
};
|
||||
|
||||
export const VehicleSessionsModal = observer(
|
||||
({ open, vehicleId, tailNumber, onClose }: VehicleSessionsModalProps) => {
|
||||
const {
|
||||
vehicleSessions,
|
||||
vehicleSessionsLoading,
|
||||
vehicleSessionsError,
|
||||
getVehicleSessions,
|
||||
} = vehicleStore;
|
||||
|
||||
useEffect(() => {
|
||||
if (!open || vehicleId == null) return;
|
||||
|
||||
getVehicleSessions(vehicleId).catch(() => undefined);
|
||||
}, [open, vehicleId, getVehicleSessions]);
|
||||
|
||||
const title =
|
||||
tailNumber && tailNumber !== ""
|
||||
? `Сессии ТО: ${tailNumber}`
|
||||
: "Сессии ТО";
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
sx={{ width: "min(1080px, 95vw)", p: 3 }}
|
||||
>
|
||||
<div className="flex flex-col gap-4 max-h-[82vh]">
|
||||
<Typography variant="h6" component="h2">
|
||||
{title}
|
||||
</Typography>
|
||||
|
||||
<Box sx={{ minHeight: 220 }}>
|
||||
{vehicleSessionsLoading && (
|
||||
<Box
|
||||
sx={{
|
||||
minHeight: 220,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<CircularProgress size={24} />
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{!vehicleSessionsLoading && vehicleSessionsError && (
|
||||
<Box
|
||||
sx={{
|
||||
minHeight: 220,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
color: "error.main",
|
||||
}}
|
||||
>
|
||||
{vehicleSessionsError}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{!vehicleSessionsLoading &&
|
||||
!vehicleSessionsError &&
|
||||
vehicleSessions &&
|
||||
vehicleSessions.length === 0 && (
|
||||
<Box
|
||||
sx={{
|
||||
minHeight: 220,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
color: "text.secondary",
|
||||
}}
|
||||
>
|
||||
По этому транспорту нет сессий ТО.
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{!vehicleSessionsLoading &&
|
||||
!vehicleSessionsError &&
|
||||
vehicleSessions &&
|
||||
vehicleSessions.length > 0 && (
|
||||
<TableContainer
|
||||
sx={{ maxHeight: "60vh", border: 1, borderColor: "divider" }}
|
||||
>
|
||||
<Table stickyHeader size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>ID</TableCell>
|
||||
<TableCell>Начало</TableCell>
|
||||
<TableCell>Окончание</TableCell>
|
||||
<TableCell align="right">Длительность</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{vehicleSessions.map((session) => (
|
||||
<TableRow key={session.id} hover>
|
||||
<TableCell>{session.id}</TableCell>
|
||||
<TableCell>
|
||||
{formatDateTime(session.started_at)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{formatDateTime(session.ended_at)}
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
{formatDuration(session.duration_seconds)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="inherit"
|
||||
onClick={onClose}
|
||||
fullWidth
|
||||
>
|
||||
Закрыть
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user