From ac8ff918b1d46afa2caf164b4c636d6c1526e583 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Fri, 21 Jun 2024 19:13:01 +0200 Subject: [PATCH] Can delete a reservation --- .../AccommodationsReservationsApi.tsx | 10 ++ .../AccommodationsReservationsRoute.tsx | 138 +++++++++++++++++- 2 files changed, 143 insertions(+), 5 deletions(-) diff --git a/geneit_app/src/api/accommodations/AccommodationsReservationsApi.tsx b/geneit_app/src/api/accommodations/AccommodationsReservationsApi.tsx index 232ea8b..3cb5a1a 100644 --- a/geneit_app/src/api/accommodations/AccommodationsReservationsApi.tsx +++ b/geneit_app/src/api/accommodations/AccommodationsReservationsApi.tsx @@ -117,4 +117,14 @@ export class AccommodationsReservationsApi { return new AccommodationsReservationsList(data); } + + /** + * Delete a reservation + */ + static async Delete(r: AccommodationReservation): Promise { + await APIClient.exec({ + method: "DELETE", + uri: `/family/${r.family_id}/accommodations/reservation/${r.id}`, + }); + } } diff --git a/geneit_app/src/routes/family/accommodations/AccommodationsReservationsRoute.tsx b/geneit_app/src/routes/family/accommodations/AccommodationsReservationsRoute.tsx index 20b3e4f..9d99e99 100644 --- a/geneit_app/src/routes/family/accommodations/AccommodationsReservationsRoute.tsx +++ b/geneit_app/src/routes/family/accommodations/AccommodationsReservationsRoute.tsx @@ -4,29 +4,44 @@ import dayGridPlugin from "@fullcalendar/daygrid"; import interactionPlugin from "@fullcalendar/interaction"; import listPlugin from "@fullcalendar/list"; import FullCalendar from "@fullcalendar/react"; +import DeleteIcon from "@mui/icons-material/Delete"; import { Alert, + Avatar, + Card, + CardActions, + CardContent, + CardHeader, Checkbox, FormControl, FormControlLabel, FormGroup, FormLabel, + IconButton, Popover, + Tooltip, Typography, - fabClasses, } from "@mui/material"; +import { red } from "@mui/material/colors"; import React from "react"; import { FamilyApi, FamilyUser } from "../../../api/FamilyApi"; +import { Accommodation } from "../../../api/accommodations/AccommodationListApi"; import { + AccommodationReservation, AccommodationsReservationsApi, AccommodationsReservationsList, } from "../../../api/accommodations/AccommodationsReservationsApi"; import { useAlert } from "../../../hooks/context_providers/AlertDialogProvider"; +import { useConfirm } from "../../../hooks/context_providers/ConfirmDialogProvider"; import { useLoadingMessage } from "../../../hooks/context_providers/LoadingMessageProvider"; import { useSnackbar } from "../../../hooks/context_providers/SnackbarProvider"; import { useUpdateAccommodationReservation } from "../../../hooks/context_providers/accommodations/UpdateReservationDialogProvider"; -import { fmtUnixDateFullCalendar } from "../../../utils/time_utils"; +import { + fmtUnixDate, + fmtUnixDateFullCalendar, +} from "../../../utils/time_utils"; import { AsyncWidget } from "../../../widgets/AsyncWidget"; +import { useUser } from "../../../widgets/BaseAuthenticatedPage"; import { useFamily } from "../../../widgets/BaseFamilyRoute"; import { FamilyPageTitle } from "../../../widgets/FamilyPageTitle"; import { useAccommodations } from "../../../widgets/accommodations/BaseAccommodationsRoute"; @@ -34,10 +49,12 @@ import { useAccommodations } from "../../../widgets/accommodations/BaseAccommoda export function AccommodationsReservationsRoute(): React.ReactElement { const snackbar = useSnackbar(); const alert = useAlert(); + const confirm = useConfirm(); const loadingMessage = useLoadingMessage(); const loadKey = React.useRef(1); + const user = useUser(); const family = useFamily(); const accommodations = useAccommodations(); const updateReservation = useUpdateAccommodationReservation(); @@ -62,6 +79,10 @@ export function AccommodationsReservationsRoute(): React.ReactElement { const [activeEvent, setActiveEvent] = React.useState< | undefined | { + user: FamilyUser; + accommodation: Accommodation; + reservation: AccommodationReservation; + x: number; y: number; w: number; @@ -127,9 +148,52 @@ export function AccommodationsReservationsRoute(): React.ReactElement { }; const onEventClick = (ev: EventClickArg) => { + const id: number = ev.event.extendedProps.id; + const resa = reservations?.get(id)!; + const acc = accommodations.accommodations.get(resa.accommodation_id)!; + + const user = users?.find((u) => u.user_id === resa.user_id); + + if (!user) { + console.error(`User ${resa.user_id} not found!`); + return; + } + const loc = ev.el.getBoundingClientRect(); - setActiveEvent({ x: loc.left, y: loc.top, w: loc.width, h: loc.height }); - console.log(ev); + setActiveEvent({ + reservation: resa, + accommodation: acc, + user: user, + + x: loc.left, + y: loc.top, + w: loc.width, + h: loc.height, + }); + }; + + const deleteReservation = async (r: AccommodationReservation) => { + try { + if ( + !(await confirm( + "Voulez-vous vraiment supprimer cette réservation ? L'opération n'est pas réversible !" + )) + ) + return; + + setActiveEvent(undefined); + loadingMessage.show("Suppression de la réservation en cours..."); + + await AccommodationsReservationsApi.Delete(r); + + reload(); + snackbar("La réservation a été supprimée avec succès !"); + } catch (e) { + console.error("Failed to delete a reservation!", e); + alert("Échec de la suppression de la réservation!"); + } finally { + loadingMessage.hide(); + } }; return ( @@ -283,6 +347,9 @@ export function AccommodationsReservationsRoute(): React.ReactElement { : r.validated === false ? "red dotted" : "grey dotted", + extendedProps: { + id: r.id, + }, }; })} /> @@ -299,6 +366,7 @@ export function AccommodationsReservationsRoute(): React.ReactElement { width: activeEvent?.w + "px", height: activeEvent?.h + "px", backgroundColor: "pink", + zIndex: 0, }} > - The content of the Popover. + + + {activeEvent?.user.user_name + .substring(0, 1) + .toLocaleUpperCase()} + + } + title={activeEvent?.user.user_name} + subheader={activeEvent?.user.user_mail} + /> + + + +

+ Réservation de {activeEvent?.accommodation.name} +
+ {activeEvent?.accommodation.description} +

+

+ Du{" "} + {fmtUnixDate( + activeEvent?.reservation.reservation_start ?? 0 + )}{" "} +
+ Au{" "} + {fmtUnixDate( + activeEvent?.reservation.reservation_end ?? 0 + )} +

+

+ + {activeEvent?.reservation.validated === false ? ( + Refusée + ) : activeEvent?.reservation.validated === true ? ( + Validée + ) : ( + + En attente de validation + + )} + +

+
+
+ + {user.user.id === activeEvent?.reservation.user_id && ( + + + deleteReservation(activeEvent?.reservation) + } + > + + + + )} + +
)}