Add an accommodations reservations module #188
@ -0,0 +1,75 @@
|
||||
import { APIClient } from "../ApiClient";
|
||||
import { Family } from "../FamilyApi";
|
||||
import moment from "moment";
|
||||
|
||||
export interface AccommodationReservation {
|
||||
id: number;
|
||||
family_id: number;
|
||||
accommodation_id: number;
|
||||
user_id: number;
|
||||
time_create: number;
|
||||
time_update: number;
|
||||
reservation_start: number;
|
||||
reservation_end: number;
|
||||
validated?: boolean;
|
||||
}
|
||||
|
||||
export class AccommodationsReservationsList {
|
||||
private list: AccommodationReservation[];
|
||||
private map: Map<number, AccommodationReservation>;
|
||||
|
||||
constructor(list: AccommodationReservation[]) {
|
||||
this.list = list;
|
||||
this.map = new Map();
|
||||
|
||||
for (const m of list) {
|
||||
this.map.set(m.id, m);
|
||||
}
|
||||
|
||||
this.list.sort((a, b) => a.reservation_start - b.reservation_start);
|
||||
}
|
||||
|
||||
public get isEmpty(): boolean {
|
||||
return this.list.length === 0;
|
||||
}
|
||||
|
||||
public get size(): number {
|
||||
return this.list.length;
|
||||
}
|
||||
|
||||
public get fullList(): AccommodationReservation[] {
|
||||
return this.list;
|
||||
}
|
||||
|
||||
filter(
|
||||
predicate: (m: AccommodationReservation) => boolean
|
||||
): AccommodationReservation[] {
|
||||
return this.list.filter(predicate);
|
||||
}
|
||||
|
||||
forAccommodation(id: number): AccommodationReservation[] {
|
||||
return this.filter((a) => a.accommodation_id === id);
|
||||
}
|
||||
|
||||
get(id: number): AccommodationReservation | undefined {
|
||||
return this.map.get(id);
|
||||
}
|
||||
}
|
||||
|
||||
export class AccommodationsReservationsApi {
|
||||
/**
|
||||
* Get the entire list of accommodations of a family
|
||||
*/
|
||||
static async FullListOfFamily(
|
||||
family: Family
|
||||
): Promise<AccommodationsReservationsList> {
|
||||
const data = (
|
||||
await APIClient.exec({
|
||||
method: "GET",
|
||||
uri: `/family/${family.family_id}/accommodations/reservations/full_list`,
|
||||
})
|
||||
).data;
|
||||
|
||||
return new AccommodationsReservationsList(data);
|
||||
}
|
||||
}
|
@ -1,3 +1,181 @@
|
||||
import React from "react";
|
||||
import { FamilyApi, FamilyUser } from "../../../api/FamilyApi";
|
||||
import {
|
||||
AccommodationsReservationsApi,
|
||||
AccommodationsReservationsList,
|
||||
} from "../../../api/accommodations/AccommodationsReservationsApi";
|
||||
import { AsyncWidget } from "../../../widgets/AsyncWidget";
|
||||
import { useFamily } from "../../../widgets/BaseFamilyRoute";
|
||||
import { FamilyPageTitle } from "../../../widgets/FamilyPageTitle";
|
||||
import {
|
||||
FormControl,
|
||||
FormLabel,
|
||||
FormGroup,
|
||||
FormControlLabel,
|
||||
Checkbox,
|
||||
FormHelperText,
|
||||
} from "@mui/material";
|
||||
import { useAccommodations } from "../../../widgets/accommodations/BaseAccommodationsRoute";
|
||||
import {
|
||||
Calendar,
|
||||
DateLocalizer,
|
||||
Views,
|
||||
momentLocalizer,
|
||||
} from "react-big-calendar";
|
||||
import moment from "moment";
|
||||
|
||||
const localizer = momentLocalizer(moment);
|
||||
|
||||
export function AccommodationsReservationsRoute(): React.ReactElement {
|
||||
return <>TODO</>;
|
||||
const loadKey = React.useRef(1);
|
||||
|
||||
const family = useFamily();
|
||||
const accommodations = useAccommodations();
|
||||
|
||||
const [reservations, setReservations] = React.useState<
|
||||
AccommodationsReservationsList | undefined
|
||||
>();
|
||||
const [users, setUsers] = React.useState<FamilyUser[] | null>(null);
|
||||
|
||||
const [showValidated, setShowValidated] = React.useState(true);
|
||||
const [showRejected, setShowRejected] = React.useState(true);
|
||||
const [showPending, setShowPending] = React.useState(true);
|
||||
|
||||
const [hiddenPeople, setHiddenPeople] = React.useState<Set<number>>(
|
||||
new Set()
|
||||
);
|
||||
const [hiddenAccommodations, setHiddenAccommodations] = React.useState<
|
||||
Set<number>
|
||||
>(new Set());
|
||||
|
||||
const load = async () => {
|
||||
setReservations(
|
||||
await AccommodationsReservationsApi.FullListOfFamily(family.family)
|
||||
);
|
||||
setUsers(await FamilyApi.GetUsersList(family.family.family_id));
|
||||
};
|
||||
|
||||
const reload = async () => {
|
||||
loadKey.current += 1;
|
||||
setUsers(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<FamilyPageTitle title="Réservation" />
|
||||
<AsyncWidget
|
||||
loadKey={loadKey.current}
|
||||
load={load}
|
||||
errMsg="Echec du chargement de la liste des réservations !"
|
||||
build={() => (
|
||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||
<div style={{ flex: 1, maxWidth: "250px" }}>
|
||||
{/* Invitation status */}
|
||||
<FormControl
|
||||
sx={{ m: 3 }}
|
||||
component="fieldset"
|
||||
variant="standard"
|
||||
>
|
||||
<FormLabel component="legend">Status</FormLabel>
|
||||
<FormGroup>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={showValidated}
|
||||
onChange={(_ev, v) => setShowValidated(v)}
|
||||
/>
|
||||
}
|
||||
label="Validé"
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={showRejected}
|
||||
onChange={(_ev, v) => setShowRejected(v)}
|
||||
/>
|
||||
}
|
||||
label="Rejetés"
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={showPending}
|
||||
onChange={(_ev, v) => setShowPending(v)}
|
||||
/>
|
||||
}
|
||||
label="En attente de validation"
|
||||
/>
|
||||
</FormGroup>
|
||||
</FormControl>
|
||||
|
||||
{/* Accommodations */}
|
||||
<FormControl
|
||||
sx={{ m: 3 }}
|
||||
component="fieldset"
|
||||
variant="standard"
|
||||
>
|
||||
<FormLabel component="legend">Logements</FormLabel>
|
||||
<FormGroup>
|
||||
{accommodations.accommodations.fullList.map((a) => (
|
||||
<FormControlLabel
|
||||
key={a.id}
|
||||
control={
|
||||
<Checkbox
|
||||
checked={!hiddenAccommodations.has(a.id)}
|
||||
onChange={(_ev, v) => {
|
||||
if (v) hiddenAccommodations.delete(a.id);
|
||||
else hiddenAccommodations.add(a.id);
|
||||
setHiddenAccommodations(
|
||||
new Set(hiddenAccommodations)
|
||||
);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={a.name}
|
||||
/>
|
||||
))}
|
||||
</FormGroup>
|
||||
</FormControl>
|
||||
|
||||
{/* People */}
|
||||
<FormControl
|
||||
sx={{ m: 3 }}
|
||||
component="fieldset"
|
||||
variant="standard"
|
||||
>
|
||||
<FormLabel component="legend">Personnes</FormLabel>
|
||||
<FormGroup>
|
||||
{users?.map((u) => (
|
||||
<FormControlLabel
|
||||
key={u.user_id}
|
||||
control={
|
||||
<Checkbox
|
||||
checked={!hiddenPeople.has(u.user_id)}
|
||||
onChange={(_ev, v) => {
|
||||
if (v) hiddenPeople.delete(u.user_id);
|
||||
else hiddenPeople.add(u.user_id);
|
||||
setHiddenPeople(new Set(hiddenPeople));
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={u.user_name}
|
||||
/>
|
||||
))}
|
||||
</FormGroup>
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
{/* The calendar */}
|
||||
<div style={{ flex: 5 }}>
|
||||
<Calendar
|
||||
defaultView={Views.MONTH}
|
||||
localizer={localizer}
|
||||
culture={"fr"}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user