Add an accommodations reservations module #188

Merged
pierre merged 81 commits from accomodation_module into master 2024-06-22 21:30:26 +00:00
3 changed files with 148 additions and 5 deletions
Showing only changes of commit 76b186ca0f - Show all commits

View File

@ -40,4 +40,30 @@ export class AccommodationsCalendarURLApi {
static CalendarURL(c: AccommodationCalendarURL): string { static CalendarURL(c: AccommodationCalendarURL): string {
return `${APIClient.backendURL()}/acccommodations_calendar/${c.token}`; return `${APIClient.backendURL()}/acccommodations_calendar/${c.token}`;
} }
/**
* Get accommodations calendars list
*/
static async GetList(family: Family): Promise<AccommodationCalendarURL[]> {
return (
await APIClient.exec({
method: "GET",
uri: `/family/${family.family_id}/accommodations/reservations_calendars/list`,
})
).data;
}
/**
* Delete an accommodation calendar
*/
static async Delete(
calendar: AccommodationCalendarURL
): Promise<AccommodationCalendarURL> {
return (
await APIClient.exec({
method: "DELETE",
uri: `/family/${calendar.family_id}/accommodations/reservations_calendars/${calendar.id}`,
})
).data;
}
} }

View File

@ -9,7 +9,6 @@ import {
FormControl, FormControl,
IconButton, IconButton,
InputAdornment, InputAdornment,
InputLabel,
OutlinedInput, OutlinedInput,
Typography, Typography,
} from "@mui/material"; } from "@mui/material";
@ -37,7 +36,6 @@ export function InstallCalendarDialog(p: {
</Typography> </Typography>
<br /> <br />
<FormControl fullWidth variant="outlined"> <FormControl fullWidth variant="outlined">
<InputLabel>URL</InputLabel>
<OutlinedInput <OutlinedInput
value={AccommodationsCalendarURLApi.CalendarURL(p.cal!)} value={AccommodationsCalendarURLApi.CalendarURL(p.cal!)}
endAdornment={ endAdornment={

View File

@ -13,13 +13,17 @@ import {
Accommodation, Accommodation,
AccommodationListApi, AccommodationListApi,
} from "../../../api/accommodations/AccommodationListApi"; } from "../../../api/accommodations/AccommodationListApi";
import { AccommodationsCalendarURLApi } from "../../../api/accommodations/AccommodationsCalendarURLApi"; import {
AccommodationCalendarURL,
AccommodationsCalendarURLApi,
} from "../../../api/accommodations/AccommodationsCalendarURLApi";
import { useConfirm } from "../../../hooks/context_providers/ConfirmDialogProvider"; import { useConfirm } from "../../../hooks/context_providers/ConfirmDialogProvider";
import { useLoadingMessage } from "../../../hooks/context_providers/LoadingMessageProvider"; import { useLoadingMessage } from "../../../hooks/context_providers/LoadingMessageProvider";
import { useSnackbar } from "../../../hooks/context_providers/SnackbarProvider"; import { useSnackbar } from "../../../hooks/context_providers/SnackbarProvider";
import { useCreateAccommodationCalendarURL } from "../../../hooks/context_providers/accommodations/CreateAccommodationCalendarURLDialogProvider"; import { useCreateAccommodationCalendarURL } from "../../../hooks/context_providers/accommodations/CreateAccommodationCalendarURLDialogProvider";
import { useInstallCalendarDialog } from "../../../hooks/context_providers/accommodations/InstallCalendarDialogProvider"; import { useInstallCalendarDialog } from "../../../hooks/context_providers/accommodations/InstallCalendarDialogProvider";
import { useUpdateAccommodation } from "../../../hooks/context_providers/accommodations/UpdateAccommodationDialogProvider"; import { useUpdateAccommodation } from "../../../hooks/context_providers/accommodations/UpdateAccommodationDialogProvider";
import { AsyncWidget } from "../../../widgets/AsyncWidget";
import { useFamily } from "../../../widgets/BaseFamilyRoute"; import { useFamily } from "../../../widgets/BaseFamilyRoute";
import { FamilyCard } from "../../../widgets/FamilyCard"; import { FamilyCard } from "../../../widgets/FamilyCard";
import { TimeWidget } from "../../../widgets/TimeWidget"; import { TimeWidget } from "../../../widgets/TimeWidget";
@ -216,23 +220,65 @@ function BoolIcon(p: { checked?: boolean }): React.ReactElement {
} }
function AccommodationsCalURLsCard(): React.ReactElement { function AccommodationsCalURLsCard(): React.ReactElement {
const key = React.useRef(0);
const snackbar = useSnackbar();
const confirm = useConfirm();
const loading = useLoadingMessage(); const loading = useLoadingMessage();
const [error, setError] = React.useState<string>(); const [error, setError] = React.useState<string>();
const [success, setSuccess] = React.useState<string>(); const [success, setSuccess] = React.useState<string>();
const [list, setList] = React.useState<
AccommodationCalendarURL[] | undefined
>();
const family = useFamily(); const family = useFamily();
const createCalendarURLDialog = useCreateAccommodationCalendarURL(); const createCalendarURLDialog = useCreateAccommodationCalendarURL();
const calendarURLDialog = useInstallCalendarDialog(); const calendarURLDialog = useInstallCalendarDialog();
const load = async () => {
setList(await AccommodationsCalendarURLApi.GetList(family.family));
};
const reload = () => {
key.current += 1;
setList(undefined);
};
const onRequestDelete = async (c: AccommodationCalendarURL) => {
setError(undefined);
setSuccess(undefined);
try {
if (
!(await confirm(
`Voulez-vous vraiment supprimer le calendrier '${c.name}' ? Cette opération est définitive !`
))
)
return;
loading.show("Suppression du calendrier en cours...");
await AccommodationsCalendarURLApi.Delete(c);
snackbar("Le calendrier a été supprimé avec succès !");
reload();
} catch (e) {
console.error("Failed to delete accommodation!", e);
setError(`Échec de la suppression du logement! ${e}`);
} finally {
loading.hide();
}
};
const createCalendarURL = async () => { const createCalendarURL = async () => {
try { try {
const newCal = await createCalendarURLDialog(); const newCal = await createCalendarURLDialog();
if (!newCal) return; if (!newCal) return;
loading.show("Création du logement en cours..."); loading.show("Création du calendrier en cours...");
const cal = await AccommodationsCalendarURLApi.Create( const cal = await AccommodationsCalendarURLApi.Create(
family.family, family.family,
@ -241,7 +287,7 @@ function AccommodationsCalURLsCard(): React.ReactElement {
setSuccess("Le calendrier a été créé avec succès !"); setSuccess("Le calendrier a été créé avec succès !");
// TODO : reload URLS list reload();
calendarURLDialog(cal); calendarURLDialog(cal);
} catch (e) { } catch (e) {
@ -274,7 +320,80 @@ function AccommodationsCalURLsCard(): React.ReactElement {
> >
Créer un calendrier Créer un calendrier
</Button> </Button>
<br />
<br />
<AsyncWidget
ready={list !== undefined}
loadKey={key.current}
load={load}
errMsg="Echec du chargement de la liste des calendriers !"
build={() =>
list?.length === 0 ? (
<>
<p style={{ textAlign: "center" }}>
Vous n'avez créé aucun calendrier pour le moment !
</p>
</>
) : (
<>
{list?.map((c) => (
<CalendarItem c={c} onRequestDelete={onRequestDelete} />
))}
</>
)
}
/>
</CardContent> </CardContent>
</FamilyCard> </FamilyCard>
); );
} }
function CalendarItem(p: {
c: AccommodationCalendarURL;
onRequestDelete: (c: AccommodationCalendarURL) => void;
}): React.ReactElement {
const accommodations = useAccommodations();
const installCal = useInstallCalendarDialog();
return (
<Card sx={{ minWidth: 275, margin: "10px 0px" }} variant="outlined">
<CardContent>
<Typography
sx={{ fontSize: 14 }}
color="text.secondary"
gutterBottom
></Typography>
<Typography variant="h5" component="div">
{p.c.name}
</Typography>
<Typography sx={{ mb: 1.5 }} color="text.secondary">
{p.c.accommodation_id
? accommodations.accommodations.get(p.c.accommodation_id)?.name
: "Tous les logements"}
</Typography>
<Typography variant="body2">
Créé il y a <TimeWidget time={p.c.time_create} />
<br />
Utilisé il y a <TimeWidget time={p.c.time_used} />
</Typography>
</CardContent>
<CardActions>
<span style={{ flex: 1 }}></span>
<Button size="small" onClick={() => installCal(p.c)}>
Installer
</Button>
<Button
size="small"
color="error"
onClick={() => p.onRequestDelete(p.c)}
>
Supprimer
</Button>
</CardActions>
</Card>
);
}