frontend/containers/Travel/Header.tsx (view raw)
1import moment from 'moment';
2import Typography from '@mui/material/Typography';
3import IconButton from '@mui/material/IconButton';
4import TuneIcon from '@mui/icons-material/Tune';
5import Box from '@mui/material/Box';
6import Link from '@mui/material/Link';
7import LinearProgress from '@mui/material/LinearProgress';
8import {useTheme} from '@mui/material/styles';
9import {useTranslation} from 'react-i18next';
10import getMapsLink from '../../lib/getMapsLink';
11import useMapStore from '../../stores/useMapStore';
12import {Travel} from '../../generated/graphql';
13
14interface Props {
15 travel: Travel & {id: string};
16 toggleEditing: () => void;
17}
18
19const Header = (props: Props) => {
20 const {travel, toggleEditing} = props;
21 const theme = useTheme();
22 const {t} = useTranslation();
23 const {setFocusOnTravel, focusedTravel} = useMapStore();
24
25 const passengersCount = travel?.passengers?.data.length || 0;
26 const availableSeats = travel?.seats - passengersCount || 0;
27
28 return (
29 <Box
30 sx={{padding: 2}}
31 onClick={() => {
32 setFocusOnTravel(focusedTravel === travel.id ? undefined : travel);
33 const mapElement = document?.getElementById('map');
34 mapElement?.scrollIntoView({behavior: 'smooth'});
35 }}
36 >
37 <IconButton
38 size="small"
39 color="primary"
40 sx={{position: 'absolute', top: 0, right: 0, margin: theme.spacing(1)}}
41 onClick={e => {
42 e.stopPropagation();
43 toggleEditing();
44 }}
45 id="EditTravelBtn"
46 >
47 <TuneIcon />
48 </IconButton>
49 {!!travel.departure && (
50 <Typography
51 variant="overline"
52 sx={{color: 'GrayText', textTransform: 'capitalize'}}
53 id="TravelDeparture"
54 >
55 {moment(travel.departure).format('LLLL')}
56 </Typography>
57 )}
58 <Typography variant="subtitle1">{travel.vehicleName}</Typography>
59 {!!travel.phone_number && (
60 <Box sx={{marginTop: 2}}>
61 <Typography variant="overline" sx={{color: 'GrayText'}}>
62 {t('travel.fields.phone')}
63 </Typography>
64 <Typography variant="body1" id="TravelPhone">
65 {travel.phone_number}
66 </Typography>
67 </Box>
68 )}
69 {!!travel.meeting && (
70 <Box sx={{marginTop: 2}}>
71 <Typography variant="overline" sx={{color: 'GrayText'}}>
72 {t('travel.fields.meeting_point')}
73 </Typography>
74 <Typography variant="body1">
75 <Link
76 component="a"
77 target="_blank"
78 rel="noopener noreferrer"
79 href={getMapsLink(travel.meeting)}
80 >
81 {travel.meeting}
82 </Link>
83 </Typography>
84 </Box>
85 )}
86 {!!travel.details && (
87 <Box sx={{marginTop: 2}}>
88 <Typography variant="overline" sx={{color: 'GrayText'}}>
89 {t('travel.fields.details')}
90 </Typography>
91 <Typography variant="body1">{travel.details}</Typography>
92 </Box>
93 )}
94 <LinearProgress
95 sx={{
96 width: 1,
97 mt: 2,
98 mb: 1,
99 backgroundColor: 'LightGray',
100 '& .MuiLinearProgress-bar': {
101 backgroundColor: 'Gray',
102 },
103 }}
104 value={(passengersCount / travel?.seats) * 100}
105 variant="determinate"
106 />
107 <Box display="flex" justifyContent="space-between" sx={{width: 1}}>
108 <Typography variant="body1" sx={{color: 'GrayText'}}>
109 {t('passenger.assign.seats', {count: availableSeats})}
110 </Typography>
111 </Box>
112 </Box>
113 );
114};
115
116export default Header;