all repos — caroster @ d880deea29e93447a5cfc03f48ec9d377eb0628d

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

🎨 Clean and fix code for passengers addition
Tim Izzo tim@5ika.ch
Mon, 12 Feb 2024 14:35:34 +0100
commit

d880deea29e93447a5cfc03f48ec9d377eb0628d

parent

2514e64e14324d01eada51f08410194d01a169c4

M frontend/containers/AddPassengerButtons/index.tsxfrontend/containers/AddPassengerButtons/index.tsx

@@ -1,4 +1,3 @@

-import {useTheme} from '@mui/material/styles'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import {useTranslation} from 'react-i18next';

@@ -24,26 +23,17 @@ registered,

variant, disabled, }: Props) => { - const theme = useTheme(); const {t} = useTranslation(); const { userPermissions: {canJoinTravels, canAddToTravel}, } = usePermissions(); - const containerSx = {padding: theme.spacing(1), textAlign: 'center'}; - const textSx = { - padding: theme.spacing(1, 8), - [theme.breakpoints.down(440)]: { - padding: theme.spacing(1, 4), - }, - }; - return ( - <Box sx={containerSx}> + <Box textAlign="center"> {canJoinTravels && ( - <Box sx={containerSx}> + <Box p={1} pt={2}> <Button - sx={textSx} + sx={buttonStyle} variant="contained" color="primary" fullWidth

@@ -59,9 +49,9 @@ </Button>

</Box> )} {canAddToTravel && ( - <Box sx={containerSx}> + <Box p={1} pt={2}> <Button - sx={textSx} + sx={buttonStyle} variant="outlined" color="primary" fullWidth

@@ -74,6 +64,14 @@ </Box>

)} </Box> ); +}; + +const buttonStyle = { + py: 1, + px: 8, + md: { + px: 4, + }, }; export default AddPassengerButtons;
M frontend/containers/NewPassengerDialog/AddPassengerToTravel.tsxfrontend/containers/NewPassengerDialog/AddPassengerToTravel.tsx

@@ -6,7 +6,7 @@ import Icon from '@mui/material/Icon';

import {useTranslation} from 'react-i18next'; import useAddToEvents from '../../hooks/useAddToEvents'; import useEventStore from '../../stores/useEventStore'; -import {Travel as TravelType} from '../../generated/graphql'; +import {TravelEntity} from '../../generated/graphql'; import SubmitButton from './SubmitButton'; import Transition from './Transition'; import AddPassengerCommonFields from './AddPassengerCommonFields';

@@ -16,7 +16,7 @@ import usePassengersActions from '../../hooks/usePassengersActions';

import {validateEmail} from '../../lib/validation'; interface Props { - travel: TravelType & {id: string}; + travel: TravelEntity; toggle: () => void; open: boolean; }

@@ -64,7 +64,7 @@ TransitionComponent={Transition}

> <form onSubmit={onSubmit}> <DialogTitle className={classes.title}> - {travel.vehicleName} + {travel.attributes.vehicleName} <Icon className={classes.closeIcon} onClick={toggle}
M frontend/containers/Travel/Header.tsxfrontend/containers/Travel/Header.tsx

@@ -9,11 +9,11 @@ import {useTheme} from '@mui/material/styles';

import {useTranslation} from 'react-i18next'; import getMapsLink from '../../lib/getMapsLink'; import useMapStore from '../../stores/useMapStore'; -import {Travel} from '../../generated/graphql'; +import {TravelEntity} from '../../generated/graphql'; import usePermissions from '../../hooks/usePermissions'; interface Props { - travel: Travel & {id: string}; + travel: TravelEntity; toggleEditing: () => void; }

@@ -26,8 +26,8 @@ userPermissions: {editableTravels},

} = usePermissions(); const {setFocusOnTravel, focusedTravel} = useMapStore(); - const passengersCount = travel?.passengers?.data.length || 0; - const availableSeats = travel?.seats - passengersCount || 0; + const passengersCount = travel?.attributes.passengers?.data.length || 0; + const availableSeats = travel?.attributes.seats - passengersCount || 0; return ( <Box

@@ -57,27 +57,29 @@ >

<TuneIcon /> </IconButton> )} - {!!travel.departure && ( + {!!travel.attributes.departure && ( <Typography variant="overline" sx={{color: 'GrayText', textTransform: 'capitalize'}} id="TravelDeparture" > - {moment(travel.departure).format('LLLL')} + {moment(travel.attributes.departure).format('LLLL')} </Typography> )} - <Typography variant="subtitle1">{travel.vehicleName}</Typography> - {!!travel.phone_number && ( + <Typography variant="subtitle1"> + {travel.attributes.vehicleName} + </Typography> + {!!travel.attributes.phone_number && ( <Box sx={{marginTop: 2}}> <Typography variant="overline" sx={{color: 'GrayText'}}> {t('travel.fields.phone')} </Typography> <Typography variant="body1" id="TravelPhone"> - {travel.phone_number} + {travel.attributes.phone_number} </Typography> </Box> )} - {!!travel.meeting && ( + {!!travel.attributes.meeting && ( <Box sx={{marginTop: 2}}> <Typography variant="overline" sx={{color: 'GrayText'}}> {t('travel.fields.meeting_point')}

@@ -87,19 +89,19 @@ <Link

component="a" target="_blank" rel="noopener noreferrer" - href={getMapsLink(travel.meeting)} + href={getMapsLink(travel.attributes.meeting)} > - {travel.meeting} + {travel.attributes.meeting} </Link> </Typography> </Box> )} - {!!travel.details && ( + {!!travel.attributes.details && ( <Box sx={{marginTop: 2}}> <Typography variant="overline" sx={{color: 'GrayText'}}> {t('travel.fields.details')} </Typography> - <Typography variant="body1">{travel.details}</Typography> + <Typography variant="body1">{travel.attributes.details}</Typography> </Box> )} <LinearProgress

@@ -112,7 +114,7 @@ '& .MuiLinearProgress-bar': {

backgroundColor: 'Gray', }, }} - value={(passengersCount / travel?.seats) * 100} + value={(passengersCount / travel?.attributes.seats) * 100} variant="determinate" /> <Box display="flex" justifyContent="space-between" sx={{width: 1}}>
M frontend/containers/Travel/index.tsxfrontend/containers/Travel/index.tsx

@@ -13,11 +13,12 @@ import AddPassengerButtons from '../AddPassengerButtons';

import useProfile from '../../hooks/useProfile'; import usePermissions from '../../hooks/usePermissions'; import useMapStore from '../../stores/useMapStore'; -import {Travel as TravelType} from '../../generated/graphql'; +import {TravelEntity} from '../../generated/graphql'; interface Props { - travel: TravelType & {id: string}; - getAddPassengerFunction: (addSelf: boolean) => () => void; + travel: TravelEntity; + onAddSelf: () => void; + onAddOther: () => void; } const Travel = (props: Props) => {

@@ -32,15 +33,18 @@ const actions = useActions({travel});

const {userId, connected} = useProfile(); const {focusedTravel} = useMapStore(); const focused = focusedTravel === travel.id; - const disableNewPassengers = travel?.passengers.data?.length >= travel.seats; + const disableNewPassengers = + travel.attributes.passengers?.data?.length >= travel.attributes.seats; const registered = useMemo(() => { if (!connected) return false; - const isInTravel = travel.passengers?.data.some( + const isInTravel = travel.attributes.passengers?.data.some( passenger => passenger.attributes.user?.data?.id === `${userId}` ); return isInTravel; }, [travel, userId]); + + if (!travel) return null; return ( <Paper

@@ -63,16 +67,17 @@ {(canJoinTravels || canAddToTravel) && (

<> <Divider /> <AddPassengerButtons - getOnClickFunction={props.getAddPassengerFunction} registered={registered} variant="travel" disabled={disableNewPassengers} + onAddOther={props.onAddOther} + onAddSelf={props.onAddSelf} /> </> )} - {travel.passengers.data.length > 0 && <Divider />} + {travel.attributes.passengers.data.length > 0 && <Divider />} <PassengersList - passengers={travel.passengers.data} + passengers={travel.attributes.passengers.data} onClick={actions.sendPassengerToWaitingList} isTravel Button={({onClick}: {onClick: () => void}) =>
M frontend/containers/Travel/useActions.tsxfrontend/containers/Travel/useActions.tsx

@@ -7,13 +7,13 @@ import {

useUpdateTravelMutation, useDeleteTravelMutation, EventByUuidDocument, - Travel, useUpdatePassengerMutation, TravelInput, + TravelEntity, } from '../../generated/graphql'; interface Props { - travel: Travel & {id: string}; + travel: TravelEntity; } const useActions = (props: Props) => {
M frontend/containers/TravelColumns/index.tsxfrontend/containers/TravelColumns/index.tsx

@@ -14,13 +14,11 @@ import usePassengersActions from '../../hooks/usePassengersActions';

import Map from '../Map'; import Travel from '../Travel'; import NoCar from './NoCar'; -import {Travel as TravelData, TravelEntity} from '../../generated/graphql'; +import {TravelEntity} from '../../generated/graphql'; import {AddPassengerToTravel} from '../NewPassengerDialog'; const EventMarker = dynamic(() => import('../EventMarker'), {ssr: false}); const TravelMarker = dynamic(() => import('../TravelMarker'), {ssr: false}); - -type TravelType = TravelData & {id: string}; interface Props { toggle: () => void;

@@ -42,13 +40,11 @@ const addToast = useToastStore(s => s.addToast);

const {addToEvent} = useAddToEvents(); const {profile, userId} = useProfile(); - const [newPassengerTravelContext, toggleNewPassengerToTravel] = useState<{ - travel: TravelType; - } | null>(null); + const [selectedTravel, setSelectedTravel] = useState<TravelEntity>(); const {addPassenger} = usePassengersActions(); const sortedTravels = travels?.slice().sort(sortTravels); - const addSelfToTravel = async (travel: TravelType) => { + const addSelfToTravel = async (travel: TravelEntity) => { const hasName = profile.firstName && profile.lastName; const userName = profile.firstName + ' ' + profile.lastName; try {

@@ -140,15 +136,14 @@ },

}} > <Masonry columns={{xl: 4, lg: 3, md: 2, sm: 2, xs: 1}} spacing={0}> - {sortedTravels?.map(({id, attributes}) => { - const travel = {id, ...attributes}; + {sortedTravels?.map(travel => { return ( <Container key={travel.id} maxWidth="sm" sx={{ - padding: theme.spacing(1), - marginBottom: theme.spacing(10), + p: 1, + mb: 10, outline: 'none', '& > *': { cursor: 'default',

@@ -161,11 +156,9 @@ }}

> <Travel travel={travel} + onAddSelf={() => addSelfToTravel(travel)} + onAddOther={() => setSelectedTravel(travel)} {...props} - getAddPassengerFunction={(addSelf: boolean) => () => - addSelf - ? addSelfToTravel(travel) - : toggleNewPassengerToTravel({travel})} /> </Container> );

@@ -192,11 +185,11 @@ />

</Container> </Masonry> </Box> - {!!newPassengerTravelContext && ( + {!!selectedTravel && ( <AddPassengerToTravel - open={!!newPassengerTravelContext} - toggle={() => toggleNewPassengerToTravel(null)} - travel={newPassengerTravelContext.travel} + open={!!selectedTravel} + toggle={() => setSelectedTravel(null)} + travel={selectedTravel} /> )} </>
M frontend/stores/useMapStore.tsfrontend/stores/useMapStore.ts

@@ -1,7 +1,7 @@

import {ReactNode} from 'react'; -import {type LatLngExpression, LatLngBoundsExpression} from 'leaflet'; +import type {LatLngExpression} from 'leaflet'; import {create} from 'zustand'; -import {Travel} from '../generated/graphql'; +import {TravelEntity} from '../generated/graphql'; type State = { map?: any;

@@ -12,7 +12,7 @@ bounds: Array<LatLngExpression>;

setMap: (map: any) => void; setPreventUpdateKey: (preventUpdateKey: string) => void; setMarkers: (markers: Array<ReactNode>) => void; - setFocusOnTravel: (travel?: Travel & {id: string}) => void; + setFocusOnTravel: (travel?: TravelEntity) => void; setBounds: (bounds: Array<LatLngExpression>) => void; };

@@ -30,8 +30,8 @@ if (!travel) {

set({focusedTravel: undefined}); } else { set({focusedTravel: travel.id}); - const lat = travel.meeting_latitude; - const long = travel.meeting_longitude; + const lat = travel.attributes.meeting_latitude; + const long = travel.attributes.meeting_longitude; if (lat && long) get().map?.panTo([lat, long]); } },