all repos — caroster @ 6a778a00a5bb7e86d12260b5efd5421a375e7382

[Octree] Group carpool to your event https://caroster.io

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 useActions from './useActions';
11import PassengersList from '../PassengersList';
12import AddPassengerButtons from '../AddPassengerButtons';
13import useProfile from '../../hooks/useProfile';
14import usePermissions from '../../hooks/usePermissions';
15import useMapStore from '../../stores/useMapStore';
16import {TravelEntity} from '../../generated/graphql';
17
18interface Props {
19  travel: TravelEntity;
20  onAddSelf: () => void;
21  onAddOther: () => void;
22}
23
24const Travel = (props: Props) => {
25  const {travel} = props;
26  const {
27    userPermissions: {editableTravels, canJoinTravels, canAddToTravel},
28  } = usePermissions();
29  const {t} = useTranslation();
30  const theme = useTheme();
31  const [isEditing, toggleEditing] = useReducer(i => !i, false);
32  const actions = useActions({travel});
33  const {userId, connected} = useProfile();
34  const {focusedTravel} = useMapStore();
35  const focused = focusedTravel === travel.id;
36  const disableNewPassengers =
37    travel.attributes.passengers?.data?.length >= travel.attributes.seats;
38
39  const registered = useMemo(() => {
40    if (!connected) return false;
41    const isInTravel = travel.attributes.passengers?.data.some(
42      passenger => passenger.attributes.user?.data?.id === `${userId}`
43    );
44    return isInTravel;
45  }, [travel, userId]);
46
47  if (!travel) return null;
48
49  return (
50    <Paper
51      sx={{
52        position: 'relative',
53        boxShadow: focused
54          ? `0px 0px 5px 2px ${theme.palette.primary.main}`
55          : 'none',
56        scrollMarginTop: theme.spacing(2),
57      }}
58      id={travel.id}
59    >
60      {isEditing && (
61        <HeaderEditing travel={travel} toggleEditing={toggleEditing} />
62      )}
63      {!isEditing && (
64        <>
65          <Header travel={travel} toggleEditing={toggleEditing} />
66          {(canJoinTravels || canAddToTravel) && (
67            <>
68              <Divider />
69              <AddPassengerButtons
70                registered={registered}
71                variant="travel"
72                disabled={disableNewPassengers}
73                onAddOther={props.onAddOther}
74                onAddSelf={props.onAddSelf}
75              />
76            </>
77          )}
78          {travel.attributes.passengers.data.length > 0 && <Divider />}
79          <PassengersList
80            passengers={travel.attributes.passengers.data}
81            onClick={actions.sendPassengerToWaitingList}
82            isTravel
83            Button={({onClick}: {onClick: () => void}) =>
84              editableTravels.includes(travel.id) && (
85                <ListItemSecondaryAction>
86                  <Button color="primary" onClick={onClick} tabIndex={-1}>
87                    {t`travel.passengers.remove`}
88                  </Button>
89                </ListItemSecondaryAction>
90              )
91            }
92          />
93        </>
94      )}
95    </Paper>
96  );
97};
98
99export default Travel;