From b8a74013090f82bce612bb16b6cd53b701122385 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Tue, 18 Jun 2024 18:23:57 +0200 Subject: [PATCH] Start to build create reservation dialog --- .../accommodations/AccommodationListApi.tsx | 4 + .../AccommodationsReservationsApi.tsx | 7 +- .../UpdateReservationDialog.tsx | 86 +++++++++++++++++++ .../UpdateReservationDialogProvider.tsx | 64 ++++++++++++++ .../AccommodationsReservationsRoute.tsx | 12 +++ .../BaseAccommodationsRoute.tsx | 7 +- 6 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 geneit_app/src/dialogs/accommodations/UpdateReservationDialog.tsx create mode 100644 geneit_app/src/hooks/context_providers/accommodations/UpdateReservationDialogProvider.tsx diff --git a/geneit_app/src/api/accommodations/AccommodationListApi.tsx b/geneit_app/src/api/accommodations/AccommodationListApi.tsx index 9125d3f..e9a595d 100644 --- a/geneit_app/src/api/accommodations/AccommodationListApi.tsx +++ b/geneit_app/src/api/accommodations/AccommodationListApi.tsx @@ -45,6 +45,10 @@ export class AccommodationsList { return this.list.filter(predicate); } + get openToReservationList(): Accommodation[] { + return this.filter((a) => a.open_to_reservations); + } + get(id: number): Accommodation | undefined { return this.map.get(id); } diff --git a/geneit_app/src/api/accommodations/AccommodationsReservationsApi.tsx b/geneit_app/src/api/accommodations/AccommodationsReservationsApi.tsx index b5d469f..845372a 100644 --- a/geneit_app/src/api/accommodations/AccommodationsReservationsApi.tsx +++ b/geneit_app/src/api/accommodations/AccommodationsReservationsApi.tsx @@ -1,6 +1,5 @@ import { APIClient } from "../ApiClient"; import { Family } from "../FamilyApi"; -import moment from "moment"; export interface AccommodationReservation { id: number; @@ -56,6 +55,12 @@ export class AccommodationsReservationsList { } } +export interface UpdateAccommodationReservation { + start: number; + end: number; + accommodation_id: number; +} + export class AccommodationsReservationsApi { /** * Get the entire list of accommodations of a family diff --git a/geneit_app/src/dialogs/accommodations/UpdateReservationDialog.tsx b/geneit_app/src/dialogs/accommodations/UpdateReservationDialog.tsx new file mode 100644 index 0000000..75fc5e4 --- /dev/null +++ b/geneit_app/src/dialogs/accommodations/UpdateReservationDialog.tsx @@ -0,0 +1,86 @@ +import { + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, +} from "@mui/material"; +import React from "react"; +import { UpdateAccommodationReservation } from "../../api/accommodations/AccommodationsReservationsApi"; +import { useAccommodations } from "../../widgets/accommodations/BaseAccommodationsRoute"; +import { PropSelect } from "../../widgets/forms/PropSelect"; + +export function UpdateReservationDialog(p: { + open: boolean; + create: boolean; + reservation?: UpdateAccommodationReservation; + onClose: () => void; + onSubmitted: (c: UpdateAccommodationReservation) => void; +}): React.ReactElement { + const accommodations = useAccommodations(); + + const [reservation, setReservation] = React.useState< + UpdateAccommodationReservation | undefined + >(); + + const clearForm = () => { + setReservation(undefined); + }; + + const cancel = () => { + clearForm(); + p.onClose(); + }; + + const submit = async () => { + clearForm(); + p.onSubmitted(reservation!); + }; + + React.useEffect(() => { + if (!reservation) setReservation(p.reservation); + }, [p.open, p.reservation]); + + return ( + + + {p.create ? "Création" : "Mise à jour"} d'une réservation + + + { + setReservation((a) => { + return { + ...a!, + accommodation_id: Number(v), + }; + }); + }} + options={accommodations.accommodations.openToReservationList.map( + (a) => { + return { label: a.name, value: a.id.toString() }; + } + )} + value={reservation?.accommodation_id?.toString()} + /> + + {/* TODO : la suite */} + + + + + + + ); +} diff --git a/geneit_app/src/hooks/context_providers/accommodations/UpdateReservationDialogProvider.tsx b/geneit_app/src/hooks/context_providers/accommodations/UpdateReservationDialogProvider.tsx new file mode 100644 index 0000000..e22b6ab --- /dev/null +++ b/geneit_app/src/hooks/context_providers/accommodations/UpdateReservationDialogProvider.tsx @@ -0,0 +1,64 @@ +import React, { PropsWithChildren } from "react"; +import { UpdateAccommodationReservation } from "../../../api/accommodations/AccommodationsReservationsApi"; +import { UpdateReservationDialog } from "../../../dialogs/accommodations/UpdateReservationDialog"; + +type DialogContext = ( + reservation: UpdateAccommodationReservation, + create: boolean +) => Promise; + +const DialogContextK = React.createContext(null); + +export function UpdateReservationDialogProvider( + p: PropsWithChildren +): React.ReactElement { + const [open, setOpen] = React.useState(false); + + const [reservation, setReservation] = React.useState< + UpdateAccommodationReservation | undefined + >(undefined); + const [create, setCreate] = React.useState(false); + + const cb = React.useRef< + null | ((a: UpdateAccommodationReservation | undefined) => void) + >(null); + + const handleClose = (res?: UpdateAccommodationReservation) => { + setOpen(false); + + if (cb.current !== null) cb.current(res); + cb.current = null; + }; + + const hook: DialogContext = (accommodation, create) => { + setReservation(accommodation); + setCreate(create); + setOpen(true); + + return new Promise((res) => { + cb.current = res; + }); + }; + + return ( + <> + + {p.children} + + + {open && ( + + )} + + ); +} + +export function useUpdateAccommodationReservation(): DialogContext { + return React.useContext(DialogContextK)!; +} diff --git a/geneit_app/src/routes/family/accommodations/AccommodationsReservationsRoute.tsx b/geneit_app/src/routes/family/accommodations/AccommodationsReservationsRoute.tsx index 4bcb28f..2fa5c6e 100644 --- a/geneit_app/src/routes/family/accommodations/AccommodationsReservationsRoute.tsx +++ b/geneit_app/src/routes/family/accommodations/AccommodationsReservationsRoute.tsx @@ -17,6 +17,7 @@ import { AccommodationsReservationsApi, AccommodationsReservationsList, } from "../../../api/accommodations/AccommodationsReservationsApi"; +import { useUpdateAccommodationReservation } from "../../../hooks/context_providers/accommodations/UpdateReservationDialogProvider"; import { AsyncWidget } from "../../../widgets/AsyncWidget"; import { useFamily } from "../../../widgets/BaseFamilyRoute"; import { FamilyPageTitle } from "../../../widgets/FamilyPageTitle"; @@ -27,6 +28,7 @@ export function AccommodationsReservationsRoute(): React.ReactElement { const family = useFamily(); const accommodations = useAccommodations(); + const updateReservation = useUpdateAccommodationReservation(); const [reservations, setReservations] = React.useState< AccommodationsReservationsList | undefined @@ -57,7 +59,17 @@ export function AccommodationsReservationsRoute(): React.ReactElement { }; const onSelect = (d: DateSelectArg) => { + // TODO : render this functional + // TODO : handle busy case console.info(d); + updateReservation( + { + accommodation_id: -1, + start: Math.floor(d.start.getDate() / 1000), + end: Math.floor(d.end.getDate() / 1000), + }, + true + ); }; return ( diff --git a/geneit_app/src/widgets/accommodations/BaseAccommodationsRoute.tsx b/geneit_app/src/widgets/accommodations/BaseAccommodationsRoute.tsx index 5e6b24b..b34ae3d 100644 --- a/geneit_app/src/widgets/accommodations/BaseAccommodationsRoute.tsx +++ b/geneit_app/src/widgets/accommodations/BaseAccommodationsRoute.tsx @@ -5,10 +5,11 @@ import { AccommodationsList, } from "../../api/accommodations/AccommodationListApi"; import { CreateAccommodationCalendarURLDialogProvider } from "../../hooks/context_providers/accommodations/CreateAccommodationCalendarURLDialogProvider"; +import { InstallCalendarDialogProvider } from "../../hooks/context_providers/accommodations/InstallCalendarDialogProvider"; import { UpdateAccommodationDialogProvider } from "../../hooks/context_providers/accommodations/UpdateAccommodationDialogProvider"; +import { UpdateReservationDialogProvider } from "../../hooks/context_providers/accommodations/UpdateReservationDialogProvider"; import { AsyncWidget } from "../AsyncWidget"; import { useFamily } from "../BaseFamilyRoute"; -import { InstallCalendarDialogProvider } from "../../hooks/context_providers/accommodations/InstallCalendarDialogProvider"; interface AccommodationsContext { accommodations: AccommodationsList; @@ -65,7 +66,9 @@ export function BaseAccommodationsRoute(): React.ReactElement { - + + +