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