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 = [...event.waitingList, removedPassenger].map(
42 ({__typename, user, ...item}) =>
43 user && user.id ? {...item, user: user.id} : item
44 );
45 const passengers = existingPassengers.filter(
46 item => item.id !== passengerId
47 );
48 await updateEventMutation({
49 variables: {
50 uuid: event.uuid,
51 eventUpdate: {
52 waitingList,
53 },
54 },
55 });
56 await updateTravelMutation({
57 variables: {
58 id: travel.id,
59 travelUpdate: {
60 passengers,
61 },
62 },
63 refetchQueries: ['eventByUUID'],
64 });
65 } catch (error) {
66 console.error(error);
67 addToast(t('travel.errors.cant_remove_passenger'));
68 }
69 }
70 };
71
72 const updateTravel = async update => {
73 try {
74 // If new seats count is under current passengers count, put excedent in event waiting list
75 // TODO: Move these logics to backend
76 if (travel.passengers?.length > update.vehicle?.seats) {
77 const lostPassengers = travel.passengers.slice(update.vehicle?.seats);
78 if (lostPassengers.length > 0)
79 await updateEventMutation({
80 variables: {
81 uuid: event.uuid,
82 eventUpdate: {
83 waitingList: formatPassengers([
84 ...(event.waitingList || []),
85 ...lostPassengers.map(({name}) => ({name})),
86 ]),
87 },
88 },
89 refetchQueries: ['eventByUUID'],
90 });
91 }
92 const departure = moment(
93 `${moment(update.travel.date).format('YYYY-MM-DD')} ${moment(
94 update.travel.time
95 ).format('HH:mm')}`,
96 'YYYY-MM-DD HH:mm'
97 ).toISOString();
98 await updateTravelMutation({
99 variables: {
100 id: travel.id,
101 travelUpdate: {
102 departure,
103 passengers: formatPassengers(
104 travel.passengers,
105 travel.vehicle?.seats
106 ),
107 },
108 },
109 });
110 await updateVehicleMutation({
111 variables: {
112 id: travel?.vehicle?.id,
113 vehicleUpdate: update.vehicle,
114 },
115 });
116 } catch (error) {
117 console.error(error);
118 addToast('travel.errors.cant_update');
119 }
120 return false;
121 };
122
123 const removeTravel = async () => {
124 try {
125 // Put passengers in event waiting list (if any)
126 // TODO Move these logics to backend and delete vehicle if no user linked
127 if (Array.isArray(travel?.passengers) && travel.passengers.length > 0)
128 await updateEventMutation({
129 variables: {
130 uuid: event.uuid,
131 eventUpdate: {
132 waitingList: formatPassengers([
133 ...(event.waitingList || []),
134 ...travel.passengers.map(({name}) => ({name})),
135 ]),
136 },
137 },
138 refetchQueries: [
139 {query: EventByUuidDocument, variables: {uuid: event.uuid}},
140 ],
141 });
142 await deleteTravelMutation({
143 variables: {
144 id: travel.id,
145 },
146 });
147 addToast(t('travel.actions.removed'));
148 } catch (error) {
149 console.error(error);
150 addToast('travel.errors.cant_remove');
151 }
152 };
153
154 return {sendPassengerToWaitingList, updateTravel, removeTravel};
155};
156
157const formatPassengers = (passengers = [], seats: number = 1000) => {
158 if (!passengers) return [];
159 return passengers
160 .slice(0, seats)
161 .map(({__typename, ...passenger}) => passenger);
162};
163
164export default useActions;