Add an accommodations reservations module #188
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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={
|
||||||
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user