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 {TravelEntity} from '../../generated/graphql';
13import usePermissions from '../../hooks/usePermissions';
14import Chip from '@mui/material/Chip';
15import useProfile from '../../hooks/useProfile';
16
17interface Props {
18 travel: TravelEntity;
19 toggleEditing: () => void;
20}
21
22const Header = (props: Props) => {
23 const {travel, toggleEditing} = props;
24 const theme = useTheme();
25 const {t} = useTranslation();
26 const {
27 userPermissions: {canEditTravel},
28 } = usePermissions();
29 const {setFocusOnTravel, focusedTravel} = useMapStore();
30 const {userId} = useProfile();
31 const isUserTripCreator =
32 userId && userId === travel.attributes.user?.data?.id;
33
34 const passengersCount = travel?.attributes.passengers?.data.length || 0;
35 const availableSeats = travel?.attributes.seats - passengersCount || 0;
36
37 return (
38 <Box
39 p={2}
40 onClick={() => {
41 setFocusOnTravel(travel);
42 const mapElement = document?.getElementById('map');
43 mapElement?.scrollIntoView({behavior: 'smooth'});
44 }}
45 >
46 {canEditTravel(travel) && (
47 <IconButton
48 size="small"
49 color="primary"
50 sx={{
51 position: 'absolute',
52 top: theme.spacing(1),
53 right: 0,
54 margin: theme.spacing(1),
55 }}
56 onClick={e => {
57 e.stopPropagation();
58 toggleEditing();
59 }}
60 id="EditTravelBtn"
61 >
62 <TuneIcon />
63 </IconButton>
64 )}
65 {!!travel.attributes.departureDate && (
66 <Typography
67 variant="overline"
68 sx={{color: 'GrayText', textTransform: 'capitalize'}}
69 id="TravelDeparture"
70 >
71 {moment(travel.attributes.departureDate).format('dddd LL')}{' '}
72 {travel.attributes.departureTime}
73 </Typography>
74 )}
75 <Typography variant="subtitle1">
76 {travel.attributes.vehicleName}
77 {isUserTripCreator && (
78 <Typography component="span">
79 <Chip sx={{mx: 1}} label={t`generic.me`} variant="outlined" />
80 </Typography>
81 )}
82 </Typography>
83
84 {!!travel.attributes.phone_number && (
85 <Box sx={{marginTop: 2}}>
86 <Typography variant="overline" sx={{color: 'GrayText'}}>
87 {t('travel.fields.phone')}
88 </Typography>
89 <Typography variant="body1" id="TravelPhone">
90 {travel.attributes.phone_number}
91 </Typography>
92 </Box>
93 )}
94 {!!travel.attributes.meeting && (
95 <Box sx={{marginTop: 2}}>
96 <Typography variant="overline" sx={{color: 'GrayText'}}>
97 {t('travel.fields.meeting_point')}
98 </Typography>
99 <Typography variant="body1">
100 <Link
101 component="a"
102 target="_blank"
103 rel="noopener noreferrer"
104 href={getMapsLink(travel.attributes.meeting)}
105 >
106 {travel.attributes.meeting}
107 </Link>
108 </Typography>
109 </Box>
110 )}
111 {!!travel.attributes.details && (
112 <Box sx={{marginTop: 2}}>
113 <Typography variant="overline" sx={{color: 'GrayText'}}>
114 {t('travel.fields.details')}
115 </Typography>
116 <Typography variant="body1">{travel.attributes.details}</Typography>
117 </Box>
118 )}
119 <LinearProgress
120 sx={{
121 width: 1,
122 mt: 2,
123 mb: 1,
124 backgroundColor: 'LightGray',
125 '& .MuiLinearProgress-bar': {
126 backgroundColor: 'Gray',
127 },
128 }}
129 value={(passengersCount / travel?.attributes.seats) * 100}
130 variant="determinate"
131 />
132 <Box display="flex" justifyContent="space-between" sx={{width: 1}}>
133 <Typography variant="body1" sx={{color: 'GrayText'}}>
134 {t('passenger.assign.seats', {count: availableSeats})}
135 </Typography>
136 </Box>
137 </Box>
138 );
139};
140
141export default Header;