diff --git a/geneit_app/src/api/accommodations/AccommodationListApi.tsx b/geneit_app/src/api/accommodations/AccommodationListApi.tsx index f51d2e1..9125d3f 100644 --- a/geneit_app/src/api/accommodations/AccommodationListApi.tsx +++ b/geneit_app/src/api/accommodations/AccommodationListApi.tsx @@ -87,4 +87,32 @@ export class AccommodationListApi { }) ).data; } + + /** + * Update an accommodation + */ + static async Update( + accommodation: Accommodation, + update: UpdateAccommodation + ): Promise { + return ( + await APIClient.exec({ + method: "PUT", + uri: `/family/${accommodation.family_id}/accommodations/list/${accommodation.id}`, + jsonData: update, + }) + ).data; + } + + /** + * Delete an accommodation + */ + static async Delete(accommodation: Accommodation): Promise { + return ( + await APIClient.exec({ + method: "DELETE", + uri: `/family/${accommodation.family_id}/accommodations/list/${accommodation.id}`, + }) + ).data; + } } diff --git a/geneit_app/src/routes/family/accommodations/AccommodationsSettingsRoute.tsx b/geneit_app/src/routes/family/accommodations/AccommodationsSettingsRoute.tsx index 43613fc..24bd50b 100644 --- a/geneit_app/src/routes/family/accommodations/AccommodationsSettingsRoute.tsx +++ b/geneit_app/src/routes/family/accommodations/AccommodationsSettingsRoute.tsx @@ -1,4 +1,11 @@ -import { CardContent, Typography, Alert, Button } from "@mui/material"; +import { + CardContent, + Typography, + Alert, + Button, + Card, + CardActions, +} from "@mui/material"; import React from "react"; import { useAlert } from "../../../hooks/context_providers/AlertDialogProvider"; import { useConfirm } from "../../../hooks/context_providers/ConfirmDialogProvider"; @@ -7,9 +14,15 @@ import { useFamily } from "../../../widgets/BaseFamilyRoute"; import { FamilyCard } from "../../../widgets/FamilyCard"; import AddIcon from "@mui/icons-material/Add"; import { useUpdateAccommodation } from "../../../hooks/context_providers/accommodations/UpdateAccommodationDialogProvider"; -import { AccommodationListApi } from "../../../api/accommodations/AccommodationListApi"; +import { + Accommodation, + AccommodationListApi, +} from "../../../api/accommodations/AccommodationListApi"; import { useSnackbar } from "../../../hooks/context_providers/SnackbarProvider"; import { useAccommodations } from "../../../widgets/accommodations/BaseAccommodationsRoute"; +import { TimeWidget } from "../../../widgets/TimeWidget"; +import CheckIcon from "@mui/icons-material/Check"; +import CloseIcon from "@mui/icons-material/Close"; export function AccommodationsSettingsRoute(): React.ReactElement { return ( @@ -34,6 +47,8 @@ function AccommodationsListCard(): React.ReactElement { const updateAccommodation = useUpdateAccommodation(); const createAccommodation = async () => { + setError(undefined); + setSuccess(undefined); try { const accommodation = await updateAccommodation( { @@ -51,11 +66,55 @@ function AccommodationsListCard(): React.ReactElement { await AccommodationListApi.Create(family.family, accommodation); snackbar("Le logement a été créé avec succès !"); - await accommodations.reloadAccommodationsList(); } catch (e) { console.error("Failed to create accommodation!", e); - alert(`Échec de la création du logement! ${e}`); + setError(`Échec de la création du logement! ${e}`); + } finally { + loading.hide(); + } + }; + + const requestUpdateAccommodation = async (a: Accommodation) => { + setError(undefined); + setSuccess(undefined); + try { + const update = await updateAccommodation(a, false); + if (!update) return; + + loading.show("Mise à jour du logement en cours..."); + + await AccommodationListApi.Update(a, update); + + snackbar("Le logement a été créé avec succès !"); + await accommodations.reloadAccommodationsList(); + } catch (e) { + console.error("Failed to update accommodation!", e); + setError(`Échec de la mise à jour du logement! ${e}`); + } finally { + loading.hide(); + } + }; + + const deleteAccommodation = async (a: Accommodation) => { + setError(undefined); + setSuccess(undefined); + try { + if ( + !(await confirm( + `Voulez-vous vraiment supprimer le logement '${a.name}' ? Cette opération est définitive !` + )) + ) + return; + loading.show("Suppression du logement en cours..."); + + await AccommodationListApi.Delete(a); + + snackbar("Le logement a été supprimé avec succès !"); + await accommodations.reloadAccommodationsList(); + } catch (e) { + console.error("Failed to delete accommodation!", e); + setError(`Échec de la suppression du logement! ${e}`); } finally { loading.hide(); } @@ -67,18 +126,90 @@ function AccommodationsListCard(): React.ReactElement { Logements - + + {/* Display the list of accommodations */} + {accommodations.accommodations.isEmpty && ( +
+ Aucun logement enregistré pour le moment ! +
+ )} + {accommodations.accommodations.fullList.map((a) => ( + + ))} + + {family.family.is_admin && ( + + )} ); } + +function AccommodationCard(p: { + accommodation: Accommodation; + onRequestUpdate: (a: Accommodation) => void; + onRequestDelete: (a: Accommodation) => void; +}): React.ReactElement { + const family = useFamily(); + return ( + + + + Mis à jour il y a + + + {p.accommodation.name} + + + {p.accommodation.description} + + + Ouvert aux + réservations +
+ Réservation + sans validation d'un administrateur +
+
+ {family.family.is_admin && ( + + + + + + )} +
+ ); +} + +function BoolIcon(p: { checked?: boolean }): React.ReactElement { + return p.checked ? ( + + ) : ( + + ); +}