WIP calendar integration
This commit is contained in:
		@@ -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>
 | 
			
		||||
        )}
 | 
			
		||||
      />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user