all repos — caroster @ bbafee0ffd3194319111522addee8e0f66914e0b

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

🎨 Clean code for 'add new travel'
Tim Izzo tim@octree.ch
Thu, 08 Feb 2024 09:55:04 +0000
commit

bbafee0ffd3194319111522addee8e0f66914e0b

parent

35309ef0acbe64753679fc84022199d730edead2

M backend/src/api/passenger/content-types/passenger/lifecycles.tsbackend/src/api/passenger/content-types/passenger/lifecycles.ts

@@ -11,7 +11,7 @@ );

if (travel) strapi.entityService.create("api::notification.notification", { data: { - type: "NewTrip", + type: "NewPassengerInYourTrip", event: params.data.event, user: travel.user?.id, },
M frontend/containers/NewTravelDialog/index.tsxfrontend/containers/NewTravelDialog/index.tsx

@@ -17,18 +17,16 @@ import {useTranslation} from 'react-i18next';

import useEventStore from '../../stores/useEventStore'; import useActions from './useActions'; import FAQLink from './FAQLink'; -import {Vehicle} from '../../generated/graphql'; +import {VehicleEntity} from '../../generated/graphql'; import PlaceInput from '../PlaceInput'; interface Props { - context: { - vehicle: Vehicle; - opened: boolean; - }; - toggle: ({opened: boolean}) => void; + selectedVehicle: VehicleEntity; + opened: boolean; + toggle: (opts: {opened: boolean}) => void; } -const NewTravelDialog = ({context, toggle}: Props) => { +const NewTravelDialog = ({selectedVehicle, opened, toggle}: Props) => { const {t} = useTranslation(); const theme = useTheme(); const event = useEventStore(s => s.event);

@@ -40,14 +38,16 @@ [event?.date]

); // States - const [name, setName] = useState(context.vehicle?.name || ''); - const [seats, setSeats] = useState(context.vehicle?.seats || 4); + const [name, setName] = useState(selectedVehicle?.attributes.name || ''); + const [seats, setSeats] = useState(selectedVehicle?.attributes.seats || 4); const [meeting, setMeeting] = useState(''); const [meeting_latitude, setMeetingLatitude] = useState(null); const [meeting_longitude, setMeetingLongitude] = useState(null); const [date, setDate] = useState(dateMoment); const [time, setTime] = useState(dateMoment); - const [phone, setPhone] = useState(context.vehicle?.phone_number || ''); + const [phone, setPhone] = useState( + selectedVehicle?.attributes.phone_number || '' + ); const [details, setDetails] = useState(''); const canCreate = !!name && !!seats;

@@ -76,7 +76,7 @@ phone_number: phone,

departure: formatDate(date, time), event: event.id, }; - const createVehicle = !context.vehicle; + const createVehicle = !selectedVehicle; await createTravel(travel, createVehicle); toggle({opened: false});

@@ -100,7 +100,7 @@ return (

<Dialog fullWidth maxWidth="xs" - open={context?.opened} + open={opened} onClose={() => { toggle({opened: false}); clearState();
M frontend/containers/VehicleChoiceDialog/VehicleItem.tsxfrontend/containers/VehicleChoiceDialog/VehicleItem.tsx

@@ -1,52 +1,18 @@

import Typography from '@mui/material/Typography'; -import {styled} from '@mui/material/styles'; import ListItem from '@mui/material/ListItem'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import {useTranslation} from 'react-i18next'; import { - Vehicle, FindUserVehiclesDocument, useDeleteVehicleMutation, + VehicleEntity, } from '../../generated/graphql'; import useProfile from '../../hooks/useProfile'; import useTheme from '@mui/styles/useTheme'; -const PREFIX = 'VehicleItem'; - -const classes = { - item: `${PREFIX}-item`, - section: `${PREFIX}-section`, - label: `${PREFIX}-label`, - select: `${PREFIX}-select`, -}; - -const StyledListItem = styled(ListItem)(({theme}) => ({ - [`&.${classes.item}`]: { - display: 'block', - padding: theme.spacing(2, 3), - }, - - [`& .${classes.section}`]: { - maxWidth: '75%', - marginBottom: theme.spacing(1), - }, - - [`& .${classes.label}`]: { - fontWeight: 'bold', - opacity: 0.6, - marginRight: theme.spacing(2), - }, - - [`& .${classes.select}`]: { - display: 'block', - maxWidth: '300px', - margin: `0 auto ${theme.spacing(1.5)} auto`, - }, -})); - interface Props { - vehicle: Vehicle & {id: string}; + vehicle: VehicleEntity; select: () => void; }

@@ -61,7 +27,9 @@ refetchQueries: [{query: FindUserVehiclesDocument, variables: {userId}}],

}); return ( - <StyledListItem sx={{display: 'block', padding: theme.spacing(2, 3)}}> + <ListItem + sx={{py: 2, px: 3, flexDirection: 'column', alignItems: 'flex-start'}} + > <Box> <Typography variant="overline"

@@ -82,7 +50,7 @@ <Typography

variant="body1" sx={{maxWidth: '75%', marginBottom: theme.spacing(1)}} > - {vehicle.name} + {vehicle.attributes.name} </Typography> <Typography variant="overline"

@@ -94,7 +62,7 @@ <Typography

variant="body1" sx={{maxWidth: '75%', marginBottom: theme.spacing(1)}} > - {vehicle.seats} + {vehicle.attributes.seats} </Typography> <Button sx={{

@@ -109,7 +77,7 @@ onClick={select}

> {t('generic.select')} </Button> - </StyledListItem> + </ListItem> ); };
M frontend/containers/VehicleChoiceDialog/index.tsxfrontend/containers/VehicleChoiceDialog/index.tsx

@@ -1,5 +1,5 @@

import {forwardRef, Fragment} from 'react'; -import {styled, useTheme} from '@mui/material/styles'; +import {useTheme} from '@mui/material/styles'; import Dialog from '@mui/material/Dialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent';

@@ -12,26 +12,22 @@ import Slide from '@mui/material/Slide';

import {useTranslation} from 'react-i18next'; import VehicleItem from './VehicleItem'; import Typography from '@mui/material/Typography'; -import {Vehicle, VehicleEntity} from '../../generated/graphql'; +import {VehicleEntity} from '../../generated/graphql'; import Icon from '@mui/material/Icon'; interface Props { open: boolean; + setSelectedVehicle: (vehicle: VehicleEntity) => void; + setNewTravelDialog: (open: boolean) => void; toggle: () => void; - toggleNewTravel: ({ - opened, - vehicle, - }: { - opened: boolean; - vehicle?: Vehicle & {id: string}; - }) => void; vehicles: Array<VehicleEntity>; } const VehicleChoiceDialog = ({ open, + setSelectedVehicle, + setNewTravelDialog, toggle, - toggleNewTravel, vehicles, }: Props) => { const theme = useTheme();

@@ -66,15 +62,13 @@ </DialogTitle>

<DialogContent dividers sx={{padding: 0}}> {(vehicles && vehicles.length != 0 && ( <List> - {vehicles.map(({id, attributes}, index, {length}) => ( + {vehicles.map((vehicle, index, {length}) => ( <Fragment key={index}> <VehicleItem - vehicle={{id, ...attributes}} + vehicle={vehicle} select={() => { - toggleNewTravel({ - vehicle: {id, ...attributes}, - opened: true, - }); + setNewTravelDialog(true); + setSelectedVehicle(vehicle); toggle(); }} />

@@ -95,7 +89,7 @@ color="primary"

fullWidth variant="outlined" onClick={() => { - toggleNewTravel({opened: true}); + setNewTravelDialog(true); toggle(); }} >
M frontend/hooks/usePermissions.tsfrontend/hooks/usePermissions.ts

@@ -45,7 +45,7 @@ };

if (carosterPlus) { if (userIsAnonymous) return {userPermissions: noPermissions}; - if (userIsEventCreator || userIsEventAdmin) + else if (userIsEventCreator || userIsEventAdmin) return {userPermissions: {...allPermissions, canAddToTravel: false}}; const editableTravelsCollection = travels.filter(({attributes}) => {

@@ -57,19 +57,20 @@ const carosterPlusPermissions: UserPermissions = {

...noPermissions, editableTravels: editableTravelsCollection.map(({id}) => id), canJoinTravels: true, + canAddTravel: true, }; return {userPermissions: carosterPlusPermissions}; } - // Caroster Vanilla permissions - return { - userPermissions: { - ...allPermissions, - canEditEventOptions: userIsEventCreator, - canJoinTravels: connected, - }, - }; + else + return { + userPermissions: { + ...allPermissions, + canEditEventOptions: userIsEventCreator, + canJoinTravels: connected, + }, + }; }; export default usePermissions;
M frontend/pages/e/[uuid]/index.tsxfrontend/pages/e/[uuid]/index.tsx

@@ -12,6 +12,7 @@ import EventLayout, {TabComponent} from '../../../layouts/Event';

import { EventByUuidDocument, FindUserVehiclesDocument, + VehicleEntity, useFindUserVehiclesQuery, } from '../../../generated/graphql';

@@ -27,9 +28,12 @@

const TravelsTab: TabComponent = () => { const {t} = useTranslation(); const session = useSession(); - const {userPermissions: {canAddTravel}} = usePermissions() - const [openNewTravelContext, toggleNewTravel] = useState({opened: false}); + const { + userPermissions: {canAddTravel}, + } = usePermissions(); + const [openNewTravelDialog, setNewTravelDialog] = useState(false); const [openVehicleChoice, toggleVehicleChoice] = useReducer(i => !i, false); + const [selectedVehicle, setSelectedVehicle] = useState<VehicleEntity>(); const isAuthenticated = session.status === 'authenticated'; const {data} = useFindUserVehiclesQuery({

@@ -40,27 +44,27 @@

const addTravelClickHandler = isAuthenticated && vehicles?.length != 0 ? toggleVehicleChoice - : () => toggleNewTravel({opened: true}); + : () => setNewTravelDialog(true); return ( <Box> <TravelColumns toggle={addTravelClickHandler} /> - <Fab - onClick={addTravelClickHandler} - aria-label="add-car" - disabled={!canAddTravel} - > - {t('travel.creation.title')} - </Fab> + {canAddTravel && ( + <Fab onClick={addTravelClickHandler} aria-label="add-car"> + {t('travel.creation.title')} + </Fab> + )} <NewTravelDialog - key={openNewTravelContext.vehicle?.id || 'noVehicle'} - context={openNewTravelContext} - toggle={() => toggleNewTravel({opened: false})} + key={selectedVehicle?.id || 'noVehicle'} + opened={openNewTravelDialog} + toggle={() => setNewTravelDialog(false)} + selectedVehicle={selectedVehicle} /> <VehicleChoiceDialog open={openVehicleChoice} toggle={toggleVehicleChoice} - toggleNewTravel={toggleNewTravel} + setNewTravelDialog={setNewTravelDialog} + setSelectedVehicle={setSelectedVehicle} vehicles={vehicles} /> </Box>