| import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; | 
| import { | 
|     useTranslate, | 
|     ShowBase, | 
|     useDataProvider, | 
|     useNotify, | 
|     useRecordContext, | 
|     useRedirect, | 
|     useRefresh, | 
| } from 'react-admin'; | 
| import { | 
|     Box, | 
|     Button, | 
|     Chip, | 
|     Dialog, | 
|     DialogContent, | 
|     Divider, | 
|     Stack, | 
|     Typography, | 
|     Avatar, | 
|     useTheme, | 
|     TableContainer, | 
|     Table, | 
|     TableBody, | 
|     TableCell, | 
|     TableHead, | 
|     TableRow, | 
|     Paper, | 
|     Toolbar, | 
|     Tooltip, | 
|     Checkbox, | 
|     IconButton, | 
| } from '@mui/material'; | 
| import { alpha } from '@mui/material/styles'; | 
| import { Link } from 'react-router-dom'; | 
| import DialogCloseButton from "../components/DialogCloseButton"; | 
| import { format } from 'date-fns'; | 
| import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew'; | 
| import request from '@/utils/request'; | 
|   | 
| const MissionResend = ({ open, id }) => { | 
|     const redirect = useRedirect(); | 
|     const handleClose = () => { | 
|         redirect('list', 'mission'); | 
|     }; | 
|   | 
|     return ( | 
|         <Dialog | 
|             open={open} | 
|             onClose={handleClose} | 
|             fullWidth | 
|             maxWidth="md" | 
|             sx={{ | 
|                 '& .MuiDialog-container': { | 
|                     alignItems: 'flex-start', | 
|                 }, | 
|             }} | 
|         > | 
|             <DialogContent sx={{ padding: 0 }}> | 
|                 {!!id ? ( | 
|                     <ShowBase id={id}> | 
|                         <MissionResendContent handleClose={handleClose} /> | 
|                     </ShowBase> | 
|                 ) : null} | 
|             </DialogContent> | 
|         </Dialog> | 
|     ) | 
| } | 
|   | 
| const MissionResendContent = ({ handleClose }) => { | 
|     const theme = useTheme(); | 
|     const record = useRecordContext(); | 
|     const translate = useTranslate(); | 
|     if (!record) return null; | 
|   | 
|     return ( | 
|         <> | 
|             <DialogCloseButton | 
|                 onClose={handleClose} | 
|                 top={12} | 
|             /> | 
|             <Stack gap={1}> | 
|                 <Box display="flex" p={2}> | 
|                     <Box flex="1"> | 
|                         <Stack | 
|                             direction="row" | 
|                             justifyContent="space-between" | 
|                             mb={4} | 
|                         > | 
|                             <Stack direction="row" alignItems="center" gap={2}> | 
|                                 <Avatar | 
|                                     sx={{ | 
|                                         width: 30, | 
|                                         height: 30, | 
|                                         bgcolor: theme.palette.primary.main, | 
|                                     }} | 
|                                 > | 
|                                     {record.agv} | 
|                                 </Avatar> | 
|                                 <Typography variant="h5"> | 
|                                     {record.groupNo} | 
|                                 </Typography> | 
|                             </Stack> | 
|                             <Stack | 
|                                 gap={1} | 
|                                 direction="row" | 
|                                 pr={6} | 
|                             > | 
|                                 <Button | 
|                                     component={Link} | 
|                                     to={`/mission/${record.id}/show`} | 
|                                     size="small" | 
|                                     startIcon={<ArrowBackIosNewIcon />} | 
|                                 > | 
|                                     {translate('page.mission.backToMission')} | 
|                                 </Button> | 
|                             </Stack> | 
|                         </Stack> | 
|   | 
|                         {!!record.codeList?.length && ( | 
|                             <Box m={2} sx={{ whiteSpace: 'pre-line' }}> | 
|                                 <Typography | 
|                                     color="textSecondary" | 
|                                     variant="caption" | 
|                                 > | 
|                                     {translate('table.field.mission.runPath')} | 
|                                 </Typography> | 
|                                 <Typography variant="body2" sx={{ whiteSpace: 'normal', overflow: 'hidden', display: 'flex', flexWrap: 'wrap' }}> | 
|                                     [ {record.codeList.map((code, index) => ( | 
|                                         <span key={index} style={{ | 
|                                             color: record.currCode === code ? theme.palette.primary.main : 'inherit', | 
|                                         }}> | 
|                                             {code}{index < record.codeList.length - 1 && ','}  | 
|                                         </span> | 
|                                     ))} ] | 
|                                 </Typography> | 
|                             </Box> | 
|                         )} | 
|   | 
|                         <ActionTable actionIds={record?.actionIds} currCode={record.currCode} handleClose={handleClose} /> | 
|                     </Box> | 
|                 </Box> | 
|             </Stack> | 
|         </> | 
|     ) | 
| }; | 
|   | 
| const headCells = [ | 
|     { | 
|         id: 'actionType', | 
|         numeric: false, | 
|         disablePadding: true, | 
|         label: 'table.field.action.actionType', | 
|     }, | 
|     { | 
|         id: 'code', | 
|         numeric: true, | 
|         disablePadding: false, | 
|         label: 'table.field.action.code', | 
|     }, | 
|     { | 
|         id: 'taskId', | 
|         numeric: true, | 
|         disablePadding: false, | 
|         label: 'table.field.action.taskId', | 
|     }, | 
|     { | 
|         id: 'val', | 
|         numeric: true, | 
|         disablePadding: false, | 
|         label: 'table.field.action.val', | 
|     }, | 
|     { | 
|         id: 'params', | 
|         numeric: true, | 
|         disablePadding: false, | 
|         label: 'table.field.action.params', | 
|     }, | 
| ]; | 
|   | 
| const ActionTable = ({ actionIds, currCode, handleClose }) => { | 
|     const dataProvider = useDataProvider(); | 
|     const translate = useTranslate(); | 
|     const notify = useNotify(); | 
|     const [actions, setActions] = useState([]); | 
|     const [selected, setSelected] = React.useState([]); | 
|   | 
|     useEffect(() => { | 
|         if (actionIds?.length > 0) { | 
|             dataProvider.getMany('action', { ids: actionIds }).then(res => { | 
|                 if (res.data?.length > 0) { | 
|                     setActions(res.data); | 
|   | 
|                     // init selected | 
|                     const indexOfCurrCode = res.data.findIndex(item => item.code === currCode); | 
|                     if (indexOfCurrCode !== -1) { | 
|                         const selectedIds = res.data.slice(indexOfCurrCode).map(item => item.id); | 
|                         setSelected(selectedIds); | 
|                     } | 
|                 } | 
|             }) | 
|         } | 
|     }, [actionIds]) | 
|   | 
|     const handleSelectAllClick = (event) => { | 
|         if (event.target.checked) { | 
|             const newSelected = actions.map((n) => n.id); | 
|             setSelected(newSelected); | 
|             return; | 
|         } | 
|         setSelected([]); | 
|     }; | 
|   | 
|     const handleClick = (event, id) => { | 
|         const selectedIndex = selected.indexOf(id); | 
|         let newSelected = []; | 
|   | 
|         if (selectedIndex === -1) { | 
|             newSelected = newSelected.concat(selected, id); | 
|         } else if (selectedIndex === 0) { | 
|             newSelected = newSelected.concat(selected.slice(1)); | 
|         } else if (selectedIndex === selected.length - 1) { | 
|             newSelected = newSelected.concat(selected.slice(0, -1)); | 
|         } else if (selectedIndex > 0) { | 
|             newSelected = newSelected.concat( | 
|                 selected.slice(0, selectedIndex), | 
|                 selected.slice(selectedIndex + 1), | 
|             ); | 
|         } | 
|         setSelected(newSelected); | 
|     }; | 
|   | 
|     const resendSubmit = () => { | 
|         if (!!selected?.length) { | 
|             request.post("/mission/resend", selected.map(id => ({ id }))).then(res => { | 
|                 const { code, msg, data } = res.data; | 
|                 if (code === 200) { | 
|                     notify(msg || 'common.response.success', { type: 'success', messageArgs: { _: msg } }); | 
|                     handleClose(); | 
|                 } else { | 
|                     notify(msg || 'common.response.fail', { type: 'error', messageArgs: { _: msg } }); | 
|                 } | 
|             }).catch(error => { | 
|                 notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } }); | 
|             }) | 
|         } | 
|     } | 
|   | 
|     return ( | 
|         <> | 
|             <Box sx={{ width: '100%' }}> | 
|                 <Paper sx={{ | 
|                     width: '100%', | 
|                     mb: 2, | 
|                 }}> | 
|                     <Toolbar | 
|                         sx={[ | 
|                             { | 
|                                 pl: { sm: 2 }, | 
|                                 pr: { xs: 1, sm: 1 }, | 
|                                 minHeight: '52.5px !important', | 
|                             }, | 
|                             selected.length > 0 && { | 
|                                 bgcolor: (theme) => | 
|                                     alpha(theme.palette.primary.main, theme.palette.action.activatedOpacity), | 
|                             }, | 
|                         ]} | 
|                     > | 
|                         {selected.length > 0 ? ( | 
|                             <Typography | 
|                                 sx={{ flex: '1 1 100%' }} | 
|                                 color="inherit" | 
|                                 variant="subtitle1" | 
|                                 component="div" | 
|                             > | 
|                                 {selected.length} {translate('common.action.selected')} | 
|                             </Typography> | 
|                         ) : ( | 
|                             <Typography | 
|                                 sx={{ flex: '1 1 100%' }} | 
|                                 variant="subtitle1" | 
|                                 id="tableTitle" | 
|                                 component="div" | 
|                             > | 
|                                 {translate('table.field.mission.actions')} | 
|                             </Typography> | 
|                         )} | 
|                         {selected.length > 0 && ( | 
|                             <Tooltip title="Resend"> | 
|                                 <Button | 
|                                     onClick={resendSubmit} | 
|                                 > | 
|                                     {translate('ra.action.confirm')} | 
|                                 </Button> | 
|                             </Tooltip> | 
|                         )} | 
|                     </Toolbar> | 
|                     <TableContainer> | 
|                         <Table | 
|                             sx={{ minWidth: 750 }} | 
|                             aria-labelledby="tableTitle" | 
|                             // size={dense ? 'small' : 'medium'} | 
|                             size="small" | 
|                         > | 
|                             <TableHead> | 
|                                 <TableRow> | 
|                                     <TableCell padding="checkbox"> | 
|                                         <Checkbox | 
|                                             color="primary" | 
|                                             indeterminate={selected.length > 0 && selected.length < actions.length} | 
|                                             checked={actions.length > 0 && selected.length === actions.length} | 
|                                             onChange={handleSelectAllClick} | 
|                                             inputProps={{ | 
|                                                 'aria-label': 'select all desserts', | 
|                                             }} | 
|                                         /> | 
|                                     </TableCell> | 
|                                     {headCells.map((headCell) => ( | 
|                                         <TableCell | 
|                                             key={headCell.id} | 
|                                             align={headCell.numeric ? 'right' : 'left'} | 
|                                             padding={headCell.disablePadding ? 'none' : 'normal'} | 
|                                         > | 
|                                             {translate(headCell.label)} | 
|                                         </TableCell> | 
|                                     ))} | 
|                                 </TableRow> | 
|                             </TableHead> | 
|                             <TableBody> | 
|                                 {actions?.map((row, index) => { | 
|                                     const isItemSelected = selected.includes(row.id); | 
|                                     const labelId = `action-table-checkbox-${index}`; | 
|   | 
|                                     return ( | 
|                                         <TableRow | 
|                                             hover | 
|                                             onClick={(event) => handleClick(event, row.id)} | 
|                                             role="checkbox" | 
|                                             aria-checked={isItemSelected} | 
|                                             tabIndex={-1} | 
|                                             key={row.id} | 
|                                             selected={isItemSelected} | 
|                                             sx={{ cursor: 'pointer' }} | 
|                                         > | 
|                                             <TableCell padding="checkbox"> | 
|                                                 <Checkbox | 
|                                                     color="primary" | 
|                                                     checked={isItemSelected} | 
|                                                     inputProps={{ | 
|                                                         'aria-labelledby': labelId, | 
|                                                     }} | 
|                                                 /> | 
|                                             </TableCell> | 
|                                             <TableCell | 
|                                                 component="th" | 
|                                                 id={labelId} | 
|                                                 scope="row" | 
|                                                 padding="none" | 
|                                             > | 
|                                                 [ {row.priority} ] | 
|                                                    | 
|                                                 {row.actionType$} | 
|                                             </TableCell> | 
|                                             <TableCell align="right">{row.code}</TableCell> | 
|                                             <TableCell align="right">{row.taskId$}</TableCell> | 
|                                             <TableCell align="right">{row.val}</TableCell> | 
|                                             <TableCell align="right">{row.params}</TableCell> | 
|                                         </TableRow> | 
|                                     ); | 
|                                 })} | 
|                             </TableBody> | 
|                         </Table> | 
|                     </TableContainer> | 
|                 </Paper> | 
|             </Box> | 
|         </> | 
|     ) | 
| } | 
|   | 
| export default MissionResend; |