init: Init React Application
This commit is contained in:
		
							
								
								
									
										206
									
								
								src/widgets/DevicesTable/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								src/widgets/DevicesTable/index.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,206 @@ | ||||
| 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 Paper from "@mui/material/Paper"; | ||||
| import { Check, RotateCcw, Send, X } from "lucide-react"; | ||||
| import { devicesStore, Modal, snapshotStore, vehicleStore } from "@shared"; | ||||
| import { useEffect, useState } from "react"; | ||||
| import { observer } from "mobx-react-lite"; | ||||
| import { Button, Checkbox } from "@mui/material"; | ||||
|  | ||||
| const formatDate = (dateString: string | undefined) => { | ||||
|   if (!dateString) return "Нет данных"; | ||||
|  | ||||
|   try { | ||||
|     const date = new Date(dateString); | ||||
|     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); | ||||
|   } catch (error) { | ||||
|     console.error("Error formatting date:", error); | ||||
|     return "Некорректная дата"; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| function createData( | ||||
|   uuid: string, | ||||
|   online: boolean, | ||||
|   lastUpdate: string, | ||||
|   gps: boolean, | ||||
|   media: boolean, | ||||
|   connection: boolean | ||||
| ) { | ||||
|   return { uuid, online, lastUpdate, gps, media, connection }; | ||||
| } | ||||
|  | ||||
| const rows = (devices: any[], vehicles: any[]) => { | ||||
|   return devices.map((device) => { | ||||
|     const { device_status } = vehicles.find( | ||||
|       (v) => v?.device_status?.device_uuid === device | ||||
|     ); | ||||
|     const findVehicle = vehicles.find((v) => v?.vehicle?.uuid === device); | ||||
|  | ||||
|     console.log(findVehicle); | ||||
|     return createData( | ||||
|       findVehicle?.vehicle?.tail_number ?? "1243000", | ||||
|       device_status?.online, | ||||
|       device_status?.last_update, | ||||
|       device_status?.gps_ok, | ||||
|       device_status?.media_service_ok, | ||||
|       device_status?.is_connected | ||||
|     ); | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| export const DevicesTable = observer(() => { | ||||
|   const { | ||||
|     devices, | ||||
|     getDevices, | ||||
|     uuid, | ||||
|     setSelectedDevice, | ||||
|     sendSnapshotModalOpen, | ||||
|     toggleSendSnapshotModal, | ||||
|   } = devicesStore; | ||||
|   const { snapshots, getSnapshots } = snapshotStore; | ||||
|   const { vehicles, getVehicles } = vehicleStore; | ||||
|   const [selectedDevices, setSelectedDevices] = useState<string[]>([]); | ||||
|   useEffect(() => { | ||||
|     const fetchData = async () => { | ||||
|       await getVehicles(); | ||||
|       await getDevices(); | ||||
|       await getSnapshots(); | ||||
|     }; | ||||
|     fetchData(); | ||||
|   }, []); | ||||
|  | ||||
|   const handleSendSnapshot = (uuid: string[]) => { | ||||
|     setSelectedDevice(uuid); | ||||
|     toggleSendSnapshotModal(); | ||||
|   }; | ||||
|  | ||||
|   const handleReloadStatus = (uuid: string) => { | ||||
|     setSelectedDevice(uuid); | ||||
|   }; | ||||
|  | ||||
|   const handleSelectDevice = (event: React.ChangeEvent<HTMLInputElement>) => { | ||||
|     if (event.target.checked) { | ||||
|       setSelectedDevices([...selectedDevices, event.target.value]); | ||||
|     } else { | ||||
|       setSelectedDevices( | ||||
|         selectedDevices.filter((device) => device !== event.target.value) | ||||
|       ); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   return ( | ||||
|     <> | ||||
|       <TableContainer component={Paper}> | ||||
|         <div className="flex justify-end p-3 gap-5"> | ||||
|           <Button variant="contained" color="primary"> | ||||
|             Выбрать все | ||||
|           </Button> | ||||
|           <Button | ||||
|             variant="contained" | ||||
|             color="primary" | ||||
|             disabled={selectedDevices.length === 0} | ||||
|             className="ml-auto" | ||||
|             onClick={() => handleSendSnapshot(selectedDevices)} | ||||
|           > | ||||
|             Отправить снапшот | ||||
|           </Button> | ||||
|         </div> | ||||
|         <Table sx={{ minWidth: 650 }} aria-label="simple table"> | ||||
|           <TableHead> | ||||
|             <TableRow> | ||||
|               <TableCell align="center"></TableCell> | ||||
|               <TableCell align="center">Бортовой номер</TableCell> | ||||
|               <TableCell align="center">Онлайн</TableCell> | ||||
|               <TableCell align="center">Последнее обновление</TableCell> | ||||
|               <TableCell align="center">ГПС</TableCell> | ||||
|               <TableCell align="center">Медиа-данные</TableCell> | ||||
|               <TableCell align="center">Подключение</TableCell> | ||||
|               <TableCell align="center">Перезапросить</TableCell> | ||||
|             </TableRow> | ||||
|           </TableHead> | ||||
|           <TableBody> | ||||
|             {rows(devices, vehicles).map((row) => ( | ||||
|               <TableRow | ||||
|                 key={row?.uuid} | ||||
|                 sx={{ "&:last-child td, &:last-child th": { border: 0 } }} | ||||
|                 className="flex items-center" | ||||
|               > | ||||
|                 <TableCell align="center"> | ||||
|                   <Checkbox | ||||
|                     className="h-full" | ||||
|                     onChange={handleSelectDevice} | ||||
|                     value={row?.uuid} | ||||
|                   /> | ||||
|                 </TableCell> | ||||
|  | ||||
|                 <TableCell align="center" component="th" scope="row"> | ||||
|                   {row?.uuid} | ||||
|                 </TableCell> | ||||
|                 <TableCell align="center"> | ||||
|                   {row?.online ? ( | ||||
|                     <Check className="m-auto text-green-500" /> | ||||
|                   ) : ( | ||||
|                     <X className="m-auto text-red-500" /> | ||||
|                   )} | ||||
|                 </TableCell> | ||||
|                 <TableCell align="center"> | ||||
|                   {formatDate(row?.lastUpdate)} | ||||
|                 </TableCell> | ||||
|                 <TableCell align="center"> | ||||
|                   {row?.gps ? ( | ||||
|                     <Check className="m-auto text-green-500" /> | ||||
|                   ) : ( | ||||
|                     <X className="m-auto text-red-500" /> | ||||
|                   )} | ||||
|                 </TableCell> | ||||
|                 <TableCell align="center"> | ||||
|                   {row?.media ? ( | ||||
|                     <Check className="m-auto text-green-500" /> | ||||
|                   ) : ( | ||||
|                     <X className="m-auto text-red-500" /> | ||||
|                   )} | ||||
|                 </TableCell> | ||||
|                 <TableCell align="center"> | ||||
|                   {row?.connection ? ( | ||||
|                     <Check className="m-auto text-green-500" /> | ||||
|                   ) : ( | ||||
|                     <X className="m-auto text-red-500" /> | ||||
|                   )} | ||||
|                 </TableCell> | ||||
|                 <TableCell align="center" className="flex justify-center"> | ||||
|                   <button onClick={() => handleReloadStatus(row?.uuid ?? "")}> | ||||
|                     <RotateCcw className="m-auto" /> | ||||
|                   </button> | ||||
|                 </TableCell> | ||||
|               </TableRow> | ||||
|             ))} | ||||
|           </TableBody> | ||||
|         </Table> | ||||
|       </TableContainer> | ||||
|       <Modal open={sendSnapshotModalOpen} onClose={toggleSendSnapshotModal}> | ||||
|         <p>Выбрать снапшот</p> | ||||
|         <div className="mt-5 flex flex-col gap-2 max-h-[300px] overflow-y-auto"> | ||||
|           {snapshots && | ||||
|             snapshots.map((snapshot) => ( | ||||
|               <button className="p-2 rounded-xl bg-slate-100" key={snapshot.id}> | ||||
|                 {snapshot.Name} | ||||
|               </button> | ||||
|             ))} | ||||
|         </div> | ||||
|       </Modal> | ||||
|     </> | ||||
|   ); | ||||
| }); | ||||
		Reference in New Issue
	
	Block a user