all repos — caroster @ 6bfdac741a7ee015a9da60c8346986ca651bb97b

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

feat: ✨ No confirmation when removing passenger from a vehicle
Simon Mulquin simon@octree.ch
Wed, 08 May 2024 06:58:31 +0000
commit

6bfdac741a7ee015a9da60c8346986ca651bb97b

parent

416c06690cbdd3c3ea2e6dd37614ff066ffc6933

M frontend/containers/Travel/PassengerActions.tsxfrontend/containers/Travel/PassengerActions.tsx

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

+import {useState} from 'react'; import {Box, Icon, IconButton} from '@mui/material'; import usePermissions from '../../hooks/usePermissions'; +import RemovePassengerModal from './RemovePassengerModal'; import useActions from './useActions'; import {PassengerEntity, TravelEntity} from '../../generated/graphql';

@@ -11,37 +13,45 @@ };

const PassengerActions = (props: Props) => { const {passenger, travel, setFocusPassenger} = props; + const [isRemovingPassenger, setIsRemovingPassenger] = useState(false); const { userPermissions: {canDeletePassenger, canSeePassengerDetails}, } = usePermissions(); - const actions = useActions({travel}); + const {removePassengerFromTravel} = useActions({travel}); return ( - <Box display="flex"> - {canDeletePassenger(passenger) && { - id: passenger.id, - attributes: { - ...passenger.attributes, - travel: {data: travel}, - }, - } && ( + <> + <Box display="flex"> + {canDeletePassenger(passenger) && { + id: passenger.id, + attributes: { + ...passenger.attributes, + travel: {data: travel}, + }, + } && ( + <IconButton + color="primary" + onClick={() => setIsRemovingPassenger(true)} + tabIndex={-1} + > + <Icon>delete_outline</Icon> + </IconButton> + )} + {canSeePassengerDetails(passenger) && ( <IconButton color="primary" - onClick={() => actions.removePassengerFromTravel(passenger.id)} - tabIndex={-1} + onClick={() => setFocusPassenger(passenger)} > - <Icon>delete_outline</Icon> + <Icon>info_outlined</Icon> </IconButton> )} - {canSeePassengerDetails(passenger) && ( - <IconButton - color="primary" - onClick={() => setFocusPassenger(passenger)} - > - <Icon>info_outlined</Icon> - </IconButton> - )} - </Box> + </Box> + <RemovePassengerModal + passenger={isRemovingPassenger && passenger} + close={() => setIsRemovingPassenger(false)} + removePassenger={removePassengerFromTravel} + /> + </> ); };
A frontend/containers/Travel/RemovePassengerModal.tsx

@@ -0,0 +1,70 @@

+import {useTranslation} from 'react-i18next'; +import { + Typography, + Dialog, + Button, + DialogContent, + DialogActions, + DialogTitle, +} from '@mui/material'; +import useProfile from '../../hooks/useProfile'; +import useEventStore from '../../stores/useEventStore'; +import {PassengerEntity} from '../../generated/graphql'; + +interface Props { + passenger: PassengerEntity; + close: () => void; + removePassenger: (id: string) => void; +} + +const RemovePassengerModal = ({passenger, close, removePassenger}: Props) => { + const {t} = useTranslation(); + const event = useEventStore(s => s.event); + const isCarosterPlus = event.enabled_modules?.includes('caroster-plus'); + const {userId} = useProfile(); + const IsPassengerIsUser = passenger.attributes?.user?.data?.id === userId; + + const getDescriptionKey = () => { + if (IsPassengerIsUser && isCarosterPlus) { + return 'travel.removePassengerModal.plus.self.description'; + } else if (isCarosterPlus) { + return 'travel.removePassengerModal.plus.description'; + } else if (IsPassengerIsUser) { + return 'travel.removePassengerModal.self.description'; + } else { + return 'travel.removePassengerModal.description'; + } + }; + + return ( + <Dialog open={!!passenger} onClose={close}> + <DialogTitle> + {t( + IsPassengerIsUser + ? 'travel.removePassengerModal.self.title' + : 'travel.removePassengerModal.title' + )} + </DialogTitle> + <DialogContent> + <Typography>{t(getDescriptionKey())}</Typography> + </DialogContent> + <DialogActions> + <Button onClick={close}> + {t('travel.removePassengerModal.cancel')} + </Button> + <Button + variant="contained" + onClick={() => removePassenger(passenger.id)} + > + {t( + IsPassengerIsUser + ? 'travel.removePassengerModal.self.remove' + : 'travel.removePassengerModal.remove' + )} + </Button> + </DialogActions> + </Dialog> + ); +}; + +export default RemovePassengerModal;
M frontend/locales/en.jsonfrontend/locales/en.json

@@ -286,6 +286,15 @@ "travel.passengers.location_placeholder": "Meeting place (optionnal)",

"travel.passengers.name": "Name", "travel.passengers.name_placeholder": "Name", "travel.passengers.register_to_waiting_list": "Register to waiting list", + "travel.removePassengerModal.title": "Remove the passenger from the trip", + "travel.removePassengerModal.description": "The passenger will be moved to the waiting list.", + "travel.removePassengerModal.cancel": "Cancel", + "travel.removePassengerModal.remove": "Remove the passenger", + "travel.removePassengerModal.self.title": "Leave this trip", + "travel.removePassengerModal.self.description": "You'll be moved to the waiting list.", + "travel.removePassengerModal.self.remove": "Leave the trip", + "travel.removePassengerModal.plus.description": "The user will receive a notification.", + "travel.removePassengerModal.plus.self.description": "You'll have to find a new trip.", "travel.requestTrip.title": "Information sent", "travel.requestTrip.description": "The following information will be sent to the trip driver.", "travel.requestTrip.phone": "Phone",
M frontend/locales/fr.jsonfrontend/locales/fr.json

@@ -286,6 +286,15 @@ "travel.passengers.location_placeholder": "Lieu de rencontre (optionnel)",

"travel.passengers.name": "Nom", "travel.passengers.name_placeholder": "Nom", "travel.passengers.register_to_waiting_list": "Inscription à la liste d'attente", + "travel.removePassengerModal.title": "Retirer le passager du trajet?", + "travel.removePassengerModal.description": "Le passager sera placé en liste d'attente.", + "travel.removePassengerModal.cancel": "Annuler", + "travel.removePassengerModal.remove": "Retirer le passager", + "travel.removePassengerModal.self.title": "Vous retirer du trajet?", + "travel.removePassengerModal.self.description": "Vous serez placé en liste d'attente.", + "travel.removePassengerModal.self.remove": "Me retirer", + "travel.removePassengerModal.plus.description": "L'utilisateur sera notifié.", + "travel.removePassengerModal.plus.self.description": "Vous devrez trouver un nouveau trajet.", "travel.requestTrip.title": "Informations transmises", "travel.requestTrip.description": "Les informations suivantes vont être transmises au conducteur du trajet.", "travel.requestTrip.phone": "Téléphone",
M frontend/locales/nl.jsonfrontend/locales/nl.json

@@ -251,6 +251,15 @@ "travel.passengers.location_placeholder": "Afspraaklocatie (optioneel)",

"travel.passengers.name": "Naam", "travel.passengers.name_placeholder": "Naam", "travel.passengers.register_to_waiting_list": "Op wachtlijst zetten", + "travel.removePassengerModal.title": "Verwijder de passagier van de reis", + "travel.removePassengerModal.description": "De passagier wordt op de wachtlijst geplaatst.", + "travel.removePassengerModal.cancel": "Annuleren", + "travel.removePassengerModal.remove": "Verwijder de passagier", + "travel.removePassengerModal.self.title": "Verlaat deze reis", + "travel.removePassengerModal.self.description": "Je wordt verplaatst op de wachtlijst.", + "travel.removePassengerModal.self.remove": "Verlaat de reis", + "travel.removePassengerModal.plus.description": "De gebruiker ontvangt een melding.", + "travel.removePassengerModal.plus.self.description": "Je zult een nieuwe reis moeten vinden.", "travel.requestTrip.title": "Informatie verzonden", "travel.requestTrip.description": "De volgende informatie wordt doorgegeven aan de bestuurder van de reis.", "travel.requestTrip.phone": "Telefoonnummer",