frontend/containers/Travel/index.tsx (view raw)
1import {useMemo, useReducer} from 'react';
2import Divider from '@mui/material/Divider';
3import Paper from '@mui/material/Paper';
4import Button from '@mui/material/Button';
5import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction';
6import {useTheme} from '@mui/styles';
7import {useTranslation} from 'react-i18next';
8import HeaderEditing from './HeaderEditing';
9import Header from './Header';
10import RequestTripModal from './RequestTripModal';
11import useActions from './useActions';
12import PassengersList from '../PassengersList';
13import AddPassengerButtons from '../AddPassengerButtons';
14import useProfile from '../../hooks/useProfile';
15import usePermissions from '../../hooks/usePermissions';
16import useMapStore from '../../stores/useMapStore';
17import useEventStore from '../../stores/useEventStore';
18import {TravelEntity} from '../../generated/graphql';
19interface Props {
20 travel: TravelEntity;
21 onAddSelf: () => void;
22 onAddOther: () => void;
23}
24
25const Travel = (props: Props) => {
26 const {travel} = props;
27 const isCarosterPlus = useEventStore(s =>
28 s.event.enabled_modules?.includes('caroster-plus')
29 );
30 const {
31 userPermissions: {canDeletePassenger, canJoinTravels, canAddToTravel},
32 } = usePermissions();
33 const {t} = useTranslation();
34 const theme = useTheme();
35 const [isEditing, toggleEditing] = useReducer(i => !i, false);
36 const [requestTripModalOpen, toggleRequestTripModal] = useReducer(
37 i => !i,
38 false
39 );
40 const actions = useActions({travel});
41 const {userId, connected} = useProfile();
42 const {focusedTravel} = useMapStore();
43 const focused = focusedTravel === travel.id;
44 const disableNewPassengers =
45 travel.attributes.passengers?.data?.length >= travel.attributes.seats;
46
47 const registered = useMemo(() => {
48 if (!connected) return false;
49 const isInTravel = travel.attributes.passengers?.data.some(
50 passenger => passenger.attributes.user?.data?.id === `${userId}`
51 );
52 return isInTravel;
53 }, [travel, userId]);
54
55 if (!travel) return null;
56
57 return (
58 <Paper
59 sx={{
60 position: 'relative',
61 boxShadow: focused
62 ? `0px 0px 5px 2px ${theme.palette.primary.main}`
63 : 'none',
64 scrollMarginTop: theme.spacing(2),
65 }}
66 id={travel.id}
67 >
68 <RequestTripModal
69 open={requestTripModalOpen}
70 toggle={toggleRequestTripModal}
71 travel={travel}
72 />
73 {isEditing && (
74 <HeaderEditing travel={travel} toggleEditing={toggleEditing} />
75 )}
76 {!isEditing && (
77 <>
78 <Header travel={travel} toggleEditing={toggleEditing} />
79 {(canJoinTravels() || canAddToTravel()) && (
80 <>
81 <Divider />
82 <AddPassengerButtons
83 registered={registered}
84 variant="travel"
85 disabled={disableNewPassengers}
86 onAddOther={props.onAddOther}
87 onAddSelf={
88 isCarosterPlus ? toggleRequestTripModal : props.onAddSelf
89 }
90 />
91 </>
92 )}
93 {travel.attributes.passengers.data.length > 0 && <Divider />}
94 <PassengersList
95 passengers={travel.attributes.passengers.data}
96 onClick={actions.sendPassengerToWaitingList}
97 travel={travel}
98 Button={({onClick, passenger}) =>
99 canDeletePassenger({
100 id: passenger.id,
101 attributes: {...passenger.attributes, travel: {data: travel}},
102 }) && (
103 <ListItemSecondaryAction>
104 <Button color="primary" onClick={onClick} tabIndex={-1}>
105 {t`travel.passengers.remove`}
106 </Button>
107 </ListItemSecondaryAction>
108 )
109 }
110 />
111 </>
112 )}
113 </Paper>
114 );
115};
116
117export default Travel;