frontend/containers/Travel/useActions.ts (view raw)
1import moment from 'moment';
2import {useTranslation} from 'react-i18next';
3import useEventStore from '../../stores/useEventStore';
4import useToastStore from '../../stores/useToastStore';
5import {
6 useUpdateTravelMutation,
7 useUpdateEventMutation,
8 useUpdateVehicleMutation,
9 useDeleteTravelMutation,
10 EventByUuidDocument,
11 Travel,
12} from '../../generated/graphql';
13
14interface Props {
15 travel: Travel;
16}
17
18const useActions = (props: Props) => {
19 const {travel} = props;
20 const {t} = useTranslation();
21 const event = useEventStore(s => s.event);
22 const addToast = useToastStore(s => s.addToast);
23 const [updateEventMutation] = useUpdateEventMutation();
24 const [updateTravelMutation] = useUpdateTravelMutation();
25 const [updateVehicleMutation] = useUpdateVehicleMutation();
26 const [deleteTravelMutation] = useDeleteTravelMutation();
27
28 const sendPassengerToWaitingList = async (passengerId: string) => {
29 if (travel?.passengers) {
30 try {
31 const {id, ...removedPassenger} = travel.passengers?.find(
32 item => item.id === passengerId
33 );
34 if (!removedPassenger) {
35 throw 'No corresponding passenger';
36 }
37 const existingPassengers =
38 travel.passengers?.map(({__typename, user, ...item}) =>
39 user && user.id ? {...item, user: user.id} : item
40 ) || [];
41 const waitingList = [
42 ...event.waitingList,
43 removedPassenger,
44 ].map(({__typename, user, ...item}) =>
45 user && user.id ? {...item, user: user.id} : item
46 );
47 const passengers = existingPassengers.filter(
48 item => item.id !== passengerId
49 );
50 await updateEventMutation({
51 variables: {
52 uuid: event.uuid,
53 eventUpdate: {
54 waitingList,
55 },
56 },
57 });
58 await updateTravelMutation({
59 variables: {
60 id: travel.id,
61 travelUpdate: {
62 passengers,
63 },
64 },
65 refetchQueries: ['eventByUUID'],
66 });
67 } catch (error) {
68 console.error(error);
69 addToast(t('travel.errors.cant_remove_passenger'));
70 }
71 }
72 };
73
74 const updateTravel = async update => {
75 try {
76 // If new seats count is under current passengers count, put excedent in event waiting list
77 // TODO: Move these logics to backend
78 if (travel.passengers?.length > update.vehicle?.seats) {
79 const lostPassengers = travel.passengers.slice(update.vehicle?.seats);
80 if (lostPassengers.length > 0)
81 await updateEventMutation({
82 variables: {
83 uuid: event.uuid,
84 eventUpdate: {
85 waitingList: formatPassengers([
86 ...(event.waitingList || []),
87 ...lostPassengers.map(({name}) => ({name})),
88 ]),
89 },
90 },
91 refetchQueries: ['eventByUUID'],
92 });
93 }
94 const departure = moment(
95 `${moment(update.travel.date).format('YYYY-MM-DD')} ${moment(
96 update.travel.time
97 ).format('HH:mm')}`,
98 'YYYY-MM-DD HH:mm'
99 ).toISOString();
100 await updateTravelMutation({
101 variables: {
102 id: travel.id,
103 travelUpdate: {
104 departure,
105 meeting: update.travel.meeting,
106 details: update.travel.details,
107 passengers: formatPassengers(
108 travel.passengers,
109 travel.vehicle?.seats
110 ),
111 },
112 },
113 });
114 await updateVehicleMutation({
115 variables: {
116 id: travel?.vehicle?.id,
117 vehicleUpdate: update.vehicle,
118 },
119 });
120 } catch (error) {
121 console.error(error);
122 addToast(t('travel.errors.cant_update'));
123 }
124 return false;
125 };
126
127 const removeTravel = async () => {
128 try {
129 // Put passengers in event waiting list (if any)
130 // TODO Move these logics to backend and delete vehicle if no user linked
131 if (Array.isArray(travel?.passengers) && travel.passengers.length > 0)
132 await updateEventMutation({
133 variables: {
134 uuid: event.uuid,
135 eventUpdate: {
136 waitingList: formatPassengers([
137 ...(event.waitingList || []),
138 ...travel.passengers.map(({name}) => ({name})),
139 ]),
140 },
141 },
142 refetchQueries: [
143 {query: EventByUuidDocument, variables: {uuid: event.uuid}},
144 ],
145 });
146 await deleteTravelMutation({
147 variables: {
148 id: travel.id,
149 },
150 });
151 addToast(t('travel.actions.removed'));
152 } catch (error) {
153 console.error(error);
154 addToast(t('travel.errors.cant_remove'));
155 }
156 };
157
158 return {sendPassengerToWaitingList, updateTravel, removeTravel};
159};
160
161const formatPassengers = (passengers = [], seats: number = 1000) => {
162 if (!passengers) return [];
163 return passengers
164 .slice(0, seats)
165 .map(({__typename, ...passenger}) => passenger);
166};
167
168export default useActions;