| | |
| | | import * as React from 'react'; |
| | | import { useState } from 'react'; |
| | | import { Paper, Typography, Box } from '@mui/material'; |
| | | import ContactsIcon from '@mui/icons-material/AccountCircle'; |
| | | import DealIcon from '@mui/icons-material/MonetizationOn'; |
| | | import { Paper, Typography, Box, AvatarGroup, Avatar } from '@mui/material'; |
| | | import { |
| | | useCreatePath, |
| | | SelectField, |
| | | useRecordContext, |
| | | Link, |
| | | useResourceContext, |
| | | useDataProvider, |
| | | } from 'react-admin'; |
| | | |
| | | import PulseSignal from '../components/PulseSignal'; |
| | | import { AgvAvatar } from './AgvAvatar'; |
| | | import { red, blue, blueGrey } from '@mui/material/colors'; |
| | | |
| | | export const AgvCard = (props) => { |
| | | const resource = useResourceContext(); |
| | |
| | | flexDirection: 'column', |
| | | justifyContent: 'space-between', |
| | | padding: '1em', |
| | | ...(!record.online && { |
| | | animation: 'cardBorderPulse 2s infinite', |
| | | '@keyframes cardBorderPulse': { |
| | | '0%': { |
| | | boxShadow: '0 0 2px 1px rgba(255, 0, 0, 0.1)', |
| | | }, |
| | | '50%': { |
| | | boxShadow: '0 0 3px 2px rgba(255, 0, 0, 0.3)', |
| | | }, |
| | | '100%': { |
| | | boxShadow: '0 0 2px 1px rgba(255, 0, 0, 0.1)', |
| | | }, |
| | | }, |
| | | }) |
| | | }} |
| | | elevation={elevation} |
| | | > |
| | | <Box display="flex" flexDirection="row" alignItems="center" justifyContent='space-between'> |
| | | <PulseSignal |
| | | flag={record.online} |
| | | /> |
| | | <Typography variant="caption" > |
| | | vol: |
| | | <Box |
| | | component={"span"} |
| | | sx={{ |
| | | color: record.vol < record.chargeLine ? red[400] : 'inherit' |
| | | }}> |
| | | {record.vol} |
| | | </Box> |
| | | </Typography> |
| | | </Box> |
| | | <Box display="flex" flexDirection="column" alignItems="center"> |
| | | <AgvAvatar /> |
| | | <Box textAlign="center" marginTop={1}> |
| | | <Typography variant="subtitle2"> |
| | | {record.name} |
| | | </Typography> |
| | | <SelectField |
| | | <Box textAlign="center" marginTop={2}> |
| | | <Typography |
| | | variant="subtitle2" |
| | | color="textSecondary" |
| | | source="sector" |
| | | choices={[ |
| | | { id: '1', name: '1' } |
| | | ]} |
| | | /> |
| | | component="div" |
| | | sx={{ fontWeight: 'bold' }} |
| | | > |
| | | {record.agvStatus} |
| | | </Typography> |
| | | <Typography variant="overline" sx={{ opacity: .7 }}> |
| | | code: {record.code} |
| | | </Typography> |
| | | </Box> |
| | | </Box> |
| | | <Box display="flex" justifyContent="space-around" width="100%"> |
| | | <Box display="flex" alignItems="center"> |
| | | <ContactsIcon color="disabled" sx={{ mr: 1 }} /> |
| | | <div> |
| | | <Typography variant="subtitle2" sx={{ mb: -1 }}> |
| | | {record.nb_contacts} |
| | | </Typography> |
| | | <Typography variant="caption" color="textSecondary"> |
| | | {record.nb_contacts |
| | | ? record.nb_contacts > 1 |
| | | ? 'contacts' |
| | | : 'contact' |
| | | : 'contact'} |
| | | </Typography> |
| | | </div> |
| | | </Box> |
| | | <Box sx={{ display: 'flex', alignItems: 'center' }}> |
| | | <DealIcon color="disabled" sx={{ mr: 1 }} /> |
| | | <div> |
| | | <Typography variant="subtitle2" sx={{ mb: -1 }}> |
| | | {record.nb_deals} |
| | | </Typography> |
| | | <Typography variant="caption" color="textSecondary"> |
| | | {record.nb_deals |
| | | ? record.nb_deals > 1 |
| | | ? 'deals' |
| | | : 'deal' |
| | | : 'deal'} |
| | | </Typography> |
| | | </div> |
| | | <TaskAvatarGroupIterator taskIds={record.taskIds} /> |
| | | </Box> |
| | | </Box> |
| | | </Paper> |
| | | </Link> |
| | | ); |
| | | }; |
| | | |
| | | const TaskAvatarGroupIterator = ({ taskIds }) => { |
| | | const dataProvider = useDataProvider(); |
| | | const [data, setData] = React.useState([]); |
| | | const [total, setTotal] = React.useState(0); |
| | | |
| | | React.useEffect(() => { |
| | | if (taskIds?.length > 0) { |
| | | dataProvider.getMany('task', { ids: taskIds }).then(res => { |
| | | if (res.data?.length > 0) { |
| | | setTotal(res.data.length); |
| | | setData(res.data); |
| | | } |
| | | }) |
| | | } |
| | | }, [taskIds]) |
| | | |
| | | return ( |
| | | <AvatarGroup |
| | | max={4} |
| | | total={total} |
| | | spacing="medium" |
| | | sx={{ |
| | | '& .MuiAvatar-circular': { |
| | | width: 35, |
| | | height: 25, |
| | | fontSize: '0.7rem', |
| | | }, |
| | | }} |
| | | > |
| | | {data.length > 0 ? ( |
| | | data.map((record) => ( |
| | | <Avatar |
| | | key={record.id} |
| | | title={`${record.seqNum}`} |
| | | sx={{ bgcolor: blueGrey[500] }} |
| | | > |
| | | {record.seqNum.slice(0, 4)} |
| | | </Avatar> |
| | | )) |
| | | ) : ( |
| | | <Avatar title="No tasks" > |
| | | N/A |
| | | </Avatar> |
| | | )} |
| | | </AvatarGroup> |
| | | ); |
| | | } |