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