All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			Add a new module to enable accommodations reservation  Reviewed-on: #188
		
			
				
	
	
		
			193 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import {
 | 
						|
  Alert,
 | 
						|
  Button,
 | 
						|
  Dialog,
 | 
						|
  DialogActions,
 | 
						|
  DialogContent,
 | 
						|
  DialogTitle,
 | 
						|
} from "@mui/material";
 | 
						|
import React from "react";
 | 
						|
import {
 | 
						|
  AccommodationReservation,
 | 
						|
  AccommodationsReservationsApi,
 | 
						|
  UpdateAccommodationReservation,
 | 
						|
} from "../../api/accommodations/AccommodationsReservationsApi";
 | 
						|
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
 | 
						|
import { fmtUnixDate } from "../../utils/time_utils";
 | 
						|
import { useFamily } from "../../widgets/BaseFamilyRoute";
 | 
						|
import { useAccommodations } from "../../widgets/accommodations/BaseAccommodationsRoute";
 | 
						|
import { PropDateInput } from "../../widgets/forms/PropDateInput";
 | 
						|
import { PropSelect } from "../../widgets/forms/PropSelect";
 | 
						|
 | 
						|
export function UpdateReservationDialog(p: {
 | 
						|
  open: boolean;
 | 
						|
  create: boolean;
 | 
						|
  reservation?: UpdateAccommodationReservation;
 | 
						|
  onClose: () => void;
 | 
						|
  onSubmitted: (c: UpdateAccommodationReservation) => void;
 | 
						|
}): React.ReactElement {
 | 
						|
  const alert = useAlert();
 | 
						|
 | 
						|
  const family = useFamily();
 | 
						|
  const accommodations = useAccommodations();
 | 
						|
 | 
						|
  const [reservation, setReservation] = React.useState<
 | 
						|
    UpdateAccommodationReservation | undefined
 | 
						|
  >();
 | 
						|
 | 
						|
  const [conflicts, setConflicts] = React.useState<
 | 
						|
    AccommodationReservation[] | undefined
 | 
						|
  >(undefined);
 | 
						|
 | 
						|
  const clearForm = () => {
 | 
						|
    setReservation(undefined);
 | 
						|
  };
 | 
						|
 | 
						|
  const cancel = () => {
 | 
						|
    clearForm();
 | 
						|
    p.onClose();
 | 
						|
  };
 | 
						|
 | 
						|
  const submit = async () => {
 | 
						|
    clearForm();
 | 
						|
    p.onSubmitted(reservation!);
 | 
						|
  };
 | 
						|
 | 
						|
  React.useEffect(() => {
 | 
						|
    if (!reservation) setReservation(p.reservation);
 | 
						|
  }, [p.open, p.reservation]);
 | 
						|
 | 
						|
  React.useEffect(() => {
 | 
						|
    setConflicts(undefined);
 | 
						|
    (async () => {
 | 
						|
      try {
 | 
						|
        if (
 | 
						|
          !reservation ||
 | 
						|
          reservation.accommodation_id < 1 ||
 | 
						|
          reservation.start < 1 ||
 | 
						|
          reservation.start > reservation.end
 | 
						|
        ) {
 | 
						|
          setConflicts([]);
 | 
						|
          return;
 | 
						|
        }
 | 
						|
 | 
						|
        setConflicts(
 | 
						|
          (
 | 
						|
            await AccommodationsReservationsApi.ReservationsForInterval(
 | 
						|
              family.family,
 | 
						|
              accommodations.accommodations.get(reservation.accommodation_id)!,
 | 
						|
              reservation.start,
 | 
						|
              reservation.end
 | 
						|
            )
 | 
						|
          ).filter(
 | 
						|
            (r) =>
 | 
						|
              r.id !== p.reservation?.reservation_id && r.validated !== false
 | 
						|
          )
 | 
						|
        );
 | 
						|
      } catch (e) {
 | 
						|
        console.error(e);
 | 
						|
        alert(
 | 
						|
          "Echec de la vérification de la présence de conflits de calendrier !"
 | 
						|
        );
 | 
						|
      }
 | 
						|
    })();
 | 
						|
  }, [
 | 
						|
    p.open,
 | 
						|
    reservation?.accommodation_id,
 | 
						|
    reservation?.start,
 | 
						|
    reservation?.end,
 | 
						|
  ]);
 | 
						|
 | 
						|
  return (
 | 
						|
    <Dialog open={p.open} onClose={cancel}>
 | 
						|
      <DialogTitle>
 | 
						|
        {p.create ? "Création" : "Mise à jour"} d'une réservation
 | 
						|
      </DialogTitle>
 | 
						|
      <DialogContent style={{ display: "flex", flexDirection: "column" }}>
 | 
						|
        <PropSelect
 | 
						|
          editing={p.create}
 | 
						|
          label="Logement ciblé"
 | 
						|
          onValueChange={(v) => {
 | 
						|
            setReservation((a) => {
 | 
						|
              return {
 | 
						|
                ...a!,
 | 
						|
                accommodation_id: Number(v),
 | 
						|
              };
 | 
						|
            });
 | 
						|
          }}
 | 
						|
          options={accommodations.accommodations.openToReservationList.map(
 | 
						|
            (a) => {
 | 
						|
              return { label: a.name, value: a.id.toString() };
 | 
						|
            }
 | 
						|
          )}
 | 
						|
          value={
 | 
						|
            reservation?.accommodation_id === -1
 | 
						|
              ? ""
 | 
						|
              : reservation?.accommodation_id?.toString()
 | 
						|
          }
 | 
						|
        />
 | 
						|
 | 
						|
        <PropDateInput
 | 
						|
          editable
 | 
						|
          label="Date de début"
 | 
						|
          value={reservation?.start}
 | 
						|
          onChange={(s) => {
 | 
						|
            setReservation((r) => {
 | 
						|
              return { ...r!, start: s ?? -1 };
 | 
						|
            });
 | 
						|
          }}
 | 
						|
          minDate={Math.floor(new Date().getTime() / 1000) - 3600 * 24 * 60}
 | 
						|
          canSetMiddleDay
 | 
						|
        />
 | 
						|
 | 
						|
        <PropDateInput
 | 
						|
          editable
 | 
						|
          label="Date de fin"
 | 
						|
          value={reservation?.end}
 | 
						|
          lastSecOfDay={true}
 | 
						|
          onChange={(s) => {
 | 
						|
            setReservation((r) => {
 | 
						|
              return { ...r!, end: s ?? -1 };
 | 
						|
            });
 | 
						|
          }}
 | 
						|
          minDate={reservation?.start}
 | 
						|
          canSetMiddleDay
 | 
						|
        />
 | 
						|
 | 
						|
        {conflicts && conflicts.length > 0 && (
 | 
						|
          <Alert severity="error">
 | 
						|
            <p>
 | 
						|
              Cette réservation est en conflit avec d'autres réservations sur
 | 
						|
              les intervalles suivants :
 | 
						|
            </p>
 | 
						|
            <ul>
 | 
						|
              {conflicts.map((c, num) => (
 | 
						|
                <li key={num}>
 | 
						|
                  Réservation du {fmtUnixDate(c.reservation_start)} au{" "}
 | 
						|
                  {fmtUnixDate(c.reservation_end)}
 | 
						|
                </li>
 | 
						|
              ))}
 | 
						|
            </ul>
 | 
						|
          </Alert>
 | 
						|
        )}
 | 
						|
      </DialogContent>
 | 
						|
      <DialogActions>
 | 
						|
        <Button onClick={cancel}>Annuler</Button>
 | 
						|
        <Button
 | 
						|
          onClick={submit}
 | 
						|
          disabled={
 | 
						|
            !(
 | 
						|
              (reservation?.accommodation_id ?? -1) > 0 &&
 | 
						|
              (reservation?.start ?? -1) > 0 &&
 | 
						|
              (reservation?.end ?? -1) > (reservation?.start ?? 0) &&
 | 
						|
              (conflicts?.length ?? 0) === 0
 | 
						|
            )
 | 
						|
          }
 | 
						|
        >
 | 
						|
          {p.create ? "Créer" : "Mettre à jour"}
 | 
						|
        </Button>
 | 
						|
      </DialogActions>
 | 
						|
    </Dialog>
 | 
						|
  );
 | 
						|
}
 |