Add an accommodations reservations module #188

Merged
pierre merged 81 commits from accomodation_module into master 2024-06-22 21:30:26 +00:00
2 changed files with 92 additions and 12 deletions
Showing only changes of commit f6d8d6b3d1 - Show all commits

View File

@ -144,4 +144,20 @@ export class AccommodationsReservationsApi {
uri: `/family/${r.family_id}/accommodations/reservation/${r.id}`,
});
}
/**
* Validate or reject a reservation request
*/
static async Validate(
r: AccommodationReservation,
accept: boolean
): Promise<void> {
await APIClient.exec({
method: "POST",
uri: `/family/${r.family_id}/accommodations/reservation/${r.id}/validate`,
jsonData: {
validate: accept,
},
});
}
}

View File

@ -20,6 +20,8 @@ import {
FormGroup,
FormLabel,
IconButton,
Menu,
MenuItem,
Popover,
Tooltip,
Typography,
@ -92,6 +94,9 @@ export function AccommodationsReservationsRoute(): React.ReactElement {
}
>();
const [validateResaAnchorEl, setValidateResaAnchorEl] =
React.useState<null | HTMLElement>(null);
const load = async () => {
setReservations(
await AccommodationsReservationsApi.FullListOfFamily(family.family)
@ -174,8 +179,39 @@ export function AccommodationsReservationsRoute(): React.ReactElement {
});
};
const respondToResaRequest = async (
r: AccommodationReservation,
validate: boolean
) => {
try {
loadingMessage.show("Validation de la réservation en cours...");
setActiveEvent(undefined);
await AccommodationsReservationsApi.Validate(r, validate);
reload();
snackbar("La réservation a été mise à jour avec succès !");
} catch (e) {
console.error("Failed to respond to reservation request!", e);
alert(`Echec de l'enregistrement de la réponse à la réservation ! ${e}`);
} finally {
loadingMessage.hide();
}
};
const validateReservation = async (r: AccommodationReservation) => {
// TODO
respondToResaRequest(r, true);
};
const rejectReservation = async (r: AccommodationReservation) => {
if (
!(await confirm(
"Voulez-vous vraiment rejeter cette demande de réservation ?"
))
)
return;
respondToResaRequest(r, false);
};
const changeReservation = async (r: AccommodationReservation) => {
@ -473,18 +509,46 @@ export function AccommodationsReservationsRoute(): React.ReactElement {
<CardActions disableSpacing>
{activeEvent?.accommodation.need_validation &&
family.family.is_admin && (
<Tooltip
title="Valider (ou rejeter) la réservation"
arrow
>
<IconButton
onClick={() =>
validateReservation(activeEvent?.reservation)
}
<>
<Tooltip
title="Valider (ou rejeter) la réservation"
arrow
>
<RuleIcon />
</IconButton>
</Tooltip>
<IconButton
onClick={(e) =>
setValidateResaAnchorEl(e.currentTarget)
}
>
<RuleIcon />
</IconButton>
</Tooltip>
<Menu
anchorEl={validateResaAnchorEl}
open={!!validateResaAnchorEl && !!activeEvent}
onClose={() => setValidateResaAnchorEl(null)}
>
<MenuItem
disabled={
activeEvent.reservation.validated === true
}
onClick={() =>
validateReservation(activeEvent.reservation)
}
>
Valider
</MenuItem>
<MenuItem
disabled={
activeEvent.reservation.validated === false
}
onClick={() =>
rejectReservation(activeEvent.reservation)
}
>
Rejeter
</MenuItem>
</Menu>
</>
)}
{user.user.id === activeEvent?.reservation.user_id && (
<>