Skip to content

Commit

Permalink
ts
Browse files Browse the repository at this point in the history
  • Loading branch information
achorein committed Oct 30, 2024
1 parent 3af6845 commit e2c16d2
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 53 deletions.
14 changes: 8 additions & 6 deletions admin/src/scenes/plan-transport/ligne-bus/View/View.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import SelectAction from "@/components/SelectAction";
import { capture } from "@/sentry";
import api from "@/services/api";

import InfoMessage from "../../../dashboardV2/components/ui/InfoMessage";
import { Title } from "../../components/commons";
import { exportLigneBusJeune } from "../../util";
import Creation from "../modificationPanel/Creation";
Expand All @@ -34,7 +35,12 @@ import Info from "./components/Info";
import Itineraire from "./components/Itineraire";
import Modification from "./components/Modification";
import PointDeRassemblement from "./components/PointDeRassemblement";
import InfoMessage from "../../../dashboardV2/components/ui/InfoMessage";

export interface DataForCheck {
meetingPoints: { youngsCount: number; meetingPointId: string }[];
youngsCountBus: number;
busVolume: number;
}

export default function View(props: RouteComponentProps<{ id: string }>) {
const user = useSelector((state: AuthState) => state.Auth.user);
Expand All @@ -43,11 +49,7 @@ export default function View(props: RouteComponentProps<{ id: string }>) {
null,
);
const [cohort, setCohort] = React.useState<CohortType | null>(null);
const [dataForCheck, setDataForCheck] = React.useState<{
meetingPoints: { youngsCount: number; meetingPointId: string }[];
youngsCountBus: number;
busVolume: number;
} | null>(null);
const [dataForCheck, setDataForCheck] = React.useState<DataForCheck | null>(null);
const [demandeDeModification, setDemandeDeModification] = React.useState(null);
const [panelOpen, setPanelOpen] = React.useState(false);
const [nbYoung, setNbYoung] = React.useState();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import React from "react";
import { useSelector } from "react-redux";
import { toastr } from "react-redux-toastr";
import { canEditLigneBusTeam, CohortType, isBusEditionOpen, isTeamLeaderOrSupervisorEditable, LigneBusType, translate } from "snu-lib";
import validator from "validator";
import Bin from "../../../../../assets/Bin";
import Pencil from "../../../../../assets/icons/Pencil";
import Toggle from "../../../../../components/Toggle";
import { capture } from "../../../../../sentry";
import api from "../../../../../services/api";

import { canEditLigneBusTeam, CohortType, isBusEditionOpen, isTeamLeaderOrSupervisorEditable, LigneBusType, translate } from "snu-lib";

import { AuthState } from "@/redux/auth/reducer";
import Bin from "@/assets/Bin";
import Pencil from "@/assets/icons/Pencil";
import Toggle from "@/components/Toggle";
import { capture } from "@/sentry";
import api from "@/services/api";

import DatePickerList from "../../components/DatePickerList";
import Field from "../../components/Field";
import { AuthState } from "@/redux/auth/reducer";

interface BusTeamProps {
bus: LigneBusType;
Expand Down Expand Up @@ -209,7 +212,9 @@ export default function BusTeam({ bus, setBus, title, role, addOpen, setAddOpen,
<div className="flex items-center gap-4">
<DatePickerList
label="Date de naissance"
// @ts-ignore
onChange={(e) => setData({ ...data, birthdate: e })}
// @ts-ignore
value={data.birthdate ? new Date(data.birthdate) : null}
error={errors?.birthdate}
readOnly={!editInfo}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,49 @@ import { BsArrowLeft, BsArrowRight } from "react-icons/bs";
import { useSelector } from "react-redux";
import { toastr } from "react-redux-toastr";
import { useHistory, Link } from "react-router-dom";
import { canEditLigneBusGeneralInfo, getZonedDate, isBusEditionOpen, translate } from "snu-lib";
import Pencil from "../../../../../assets/icons/Pencil";
import Loader from "../../../../../components/Loader";
import { capture } from "../../../../../sentry";
import api from "../../../../../services/api";

import { canEditLigneBusGeneralInfo, CohortType, getZonedDate, isBusEditionOpen, LigneBusType, translate } from "snu-lib";

import Pencil from "@/assets/icons/Pencil";
import Loader from "@/components/Loader";
import { capture } from "@/sentry";
import api from "@/services/api";
import { Button } from "@snu/ds/admin";
import { AuthState } from "@/redux/auth/reducer";

import DatePickerList from "../../components/DatePickerList";
import Field from "../../components/Field";
import Select from "../../components/Select";
import { Button } from "@snu/ds/admin";
import { DataForCheck } from "../View";

const options = [
{ label: "Oui", value: true },
{ label: "Non", value: false },
];

export default function Info({ bus, setBus, dataForCheck, nbYoung, cohort }) {
const user = useSelector((state) => state.Auth.user);
interface FormErrors {
busId?: string;
departuredDate?: string;
returnDate?: string;
youngCapacity?: string;
totalCapacity?: string;
followerCapacity?: string;
travelTime?: string;
}

interface InfoProps {
bus: LigneBusType;
setBus: React.Dispatch<React.SetStateAction<LigneBusType>>;
dataForCheck: DataForCheck | null;
nbYoung?: number;
cohort: CohortType | null;
}

export default function Info({ bus, setBus, dataForCheck, nbYoung, cohort }: InfoProps) {
const user = useSelector((state: AuthState) => state.Auth.user);
const [editInfo, setEditInfo] = React.useState(false);
const [isLoading, setIsLoading] = React.useState(false);
const [errors, setErrors] = React.useState({});
const [errors, setErrors] = React.useState<FormErrors>({});
const [data, setData] = React.useState({
busId: bus.busId || "",
departuredDate: bus.departuredDate || "",
Expand Down Expand Up @@ -56,28 +79,28 @@ export default function Info({ bus, setBus, dataForCheck, nbYoung, cohort }) {
try {
setIsLoading(true);
setErrors({});
let errors = {};
const errors: FormErrors = {};
if (!data.busId) errors.busId = "Ce champ est obligatoire";
if (!data.departuredDate) errors.departuredDate = "Ce champ est obligatoire";
if (!data.returnDate) errors.returnDate = "Ce champ est obligatoire";
if (!data.youngCapacity) errors.youngCapacity = "Ce champ est obligatoire";
if (!data.totalCapacity) errors.totalCapacity = "Ce champ est obligatoire";
if (!data.followerCapacity) errors.followerCapacity = "Ce champ est obligatoire";
if (!data.travelTime) errors.travelTime = "Ce champ est obligatoire";
if (isNaN(data?.youngCapacity)) errors.youngCapacity = "La capacité doit être un nombre";
if (isNaN(data?.followerCapacity)) errors.followerCapacity = "La capacité doit être un nombre";
if (isNaN(data?.totalCapacity)) errors.totalCapacity = "La capacité doit être un nombre";
if (isNaN(data?.youngCapacity as number)) errors.youngCapacity = "La capacité doit être un nombre";
if (isNaN(data?.followerCapacity as number)) errors.followerCapacity = "La capacité doit être un nombre";
if (isNaN(data?.totalCapacity as number)) errors.totalCapacity = "La capacité doit être un nombre";

data.totalCapacity = parseInt(data.totalCapacity);
data.youngCapacity = parseInt(data.youngCapacity);
data.followerCapacity = parseInt(data.followerCapacity);
data.totalCapacity = parseInt(data.totalCapacity as string);
data.youngCapacity = parseInt(data.youngCapacity as string);
data.followerCapacity = parseInt(data.followerCapacity as string);

//total capacity must be greater than young capacity + follower capacity
if (data?.totalCapacity < data?.youngCapacity + data?.followerCapacity) {
errors.totalCapacity = "La capacité totale doit être supérieure ou égale à la capacité volontaire + la capacité accompagnateurs";
}

if (dataForCheck.youngsCountBus > data.youngCapacity) {
if (dataForCheck && dataForCheck.youngsCountBus > data.youngCapacity) {
errors.youngCapacity = "La capacité volontaire est trop faible par rapport au nombre de volontaire deja affectés à cette ligne";
}

Expand All @@ -99,7 +122,7 @@ export default function Info({ bus, setBus, dataForCheck, nbYoung, cohort }) {
setIsLoading(false);
} catch (e) {
capture(e);
toastr.error("Oups, une erreur est survenue lors de la modification de la ligne");
toastr.error("Oups, une erreur est survenue lors de la modification de la ligne", "");
setIsLoading(false);
}
};
Expand Down Expand Up @@ -153,15 +176,19 @@ export default function Info({ bus, setBus, dataForCheck, nbYoung, cohort }) {
<DatePickerList
label="Date de départ"
Icon={BsArrowRight}
// @ts-ignore
onChange={(e) => setData({ ...data, departuredDate: e })}
// @ts-ignore
value={getZonedDate(data.departuredDate)}
error={errors?.departuredDate}
readOnly={!editInfo}
/>
<DatePickerList
label="Date de retour"
Icon={BsArrowLeft}
// @ts-ignore
onChange={(e) => setData({ ...data, returnDate: e })}
// @ts-ignore
value={getZonedDate(data.returnDate)}
error={errors?.returnDate}
readOnly={!editInfo}
Expand All @@ -185,14 +212,14 @@ export default function Info({ bus, setBus, dataForCheck, nbYoung, cohort }) {
<Field
label="Capacité accompagnateur"
onChange={(e) => setData({ ...data, followerCapacity: e.target.value })}
value={data.followerCapacity}
value={data.followerCapacity as string}
error={errors?.followerCapacity}
readOnly={!editInfo}
/>
<Field
label="Capacité volontaire"
onChange={(e) => setData({ ...data, youngCapacity: e.target.value })}
value={data.youngCapacity}
value={data.youngCapacity as string}
error={errors?.youngCapacity}
readOnly={!editInfo}
/>
Expand All @@ -201,7 +228,7 @@ export default function Info({ bus, setBus, dataForCheck, nbYoung, cohort }) {
<Field
label="Capacité totale"
onChange={(e) => setData({ ...data, totalCapacity: e.target.value })}
value={data.totalCapacity}
value={data.totalCapacity as string}
error={errors?.totalCapacity}
readOnly={!editInfo}
/>
Expand All @@ -216,15 +243,21 @@ export default function Info({ bus, setBus, dataForCheck, nbYoung, cohort }) {
<div className="flex items-center gap-4">
<Select
label="Pause déjeuner aller"
// @ts-ignore
options={options}
// @ts-ignore
selected={options.find((e) => e.value === data.lunchBreak)}
// @ts-ignore
setSelected={(e) => setData({ ...data, lunchBreak: e.value })}
readOnly={!editInfo}
/>
<Select
label="Pause déjeuner retour"
// @ts-ignore
options={options}
// @ts-ignore
selected={options.find((e) => e.value === data.lunchBreakReturn)}
// @ts-ignore
setSelected={(e) => setData({ ...data, lunchBreakReturn: e.value })}
readOnly={!editInfo}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,21 @@ import React from "react";
import DatePicker, { registerLocale } from "react-datepicker";
import fr from "date-fns/locale/fr";
import "react-datepicker/dist/react-datepicker.css";
import { IconType } from "react-icons";
import { FiCalendar } from "react-icons/fi";
registerLocale("fr", fr);

export default function DatePickerList({ value, label, onChange, error = "", disabled = false, readOnly = false, Icon = false }) {
interface DatePickerListProps {
value: string;
label: string;
onChange: (date: string) => void;
error?: string;
disabled?: boolean;
readOnly?: boolean;
Icon?: IconType;
}

export default function DatePickerList({ value, label, onChange, error = "", disabled = false, readOnly = false, Icon }: DatePickerListProps) {
return (
<div className={`flex w-full flex-col rounded-lg border-[1px] border-gray-300 py-2 px-2.5 ${disabled ? "bg-gray-100" : ""} ${error ? "border-red-500" : ""}`}>
<div className="flex w-full items-center gap-x-2">
Expand Down
38 changes: 20 additions & 18 deletions api/src/controllers/planDeTransport/ligne-de-bus.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
const express = require("express");
const router = express.Router();
const passport = require("passport");
const { LigneBusModel } = require("../../models");
const { LigneToPointModel } = require("../../models");
const { PlanTransportModel } = require("../../models");
const { PointDeRassemblementModel } = require("../../models");
const { CohesionCenterModel } = require("../../models");
const { SchemaDeRepartitionModel } = require("../../models");
const { ReferentModel } = require("../../models");
const { CohortModel } = require("../../models");
const Joi = require("joi");
const { ObjectId } = require("mongoose").Types;
const mongoose = require("mongoose");
const config = require("config");

const {
canViewLigneBus,
canEditLigneBusTeam,
Expand All @@ -26,13 +23,22 @@ const {
SENDINBLUE_TEMPLATES,
isTeamLeaderOrSupervisorEditable,
} = require("snu-lib");
const { ERRORS } = require("../../utils");

const {
LigneBusModel,
LigneToPointModel,
PlanTransportModel,
PointDeRassemblementModel,
CohesionCenterModel,
SchemaDeRepartitionModel,
ReferentModel,
CohortModel,
} = require("../../models");

const { capture } = require("../../sentry");
const Joi = require("joi");
const { ObjectId } = require("mongoose").Types;
const mongoose = require("mongoose");
const { sendTemplate } = require("../../brevo");
const config = require("config");
const { ERRORS } = require("../../utils");
const { validateId } = require("../../utils/validator");

/**
* Récupère toutes les ligneBus + les points de rassemblemnts associés
Expand Down Expand Up @@ -557,15 +563,11 @@ router.get("/:id/ligne-to-points", passport.authenticate("referent", { session:

router.get("/:id/data-for-check", passport.authenticate("referent", { session: false, failWithError: true }), async (req, res) => {
try {
const { error, value } = Joi.object({
id: Joi.string().required(),
}).validate(req.params);
const { error, value: id } = validateId(req.params.id);

if (error) return res.status(400).send({ ok: false, code: ERRORS.INVALID_PARAMS });
if (!canViewLigneBus(req.user)) return res.status(403).send({ ok: false, code: ERRORS.OPERATION_UNAUTHORIZED });

const { id } = value;

const ligneBus = await LigneBusModel.findById(id);
if (!ligneBus) return res.status(404).send({ ok: false, code: ERRORS.NOT_FOUND });
//Get all youngs for this ligne and by meeting point
Expand Down

0 comments on commit e2c16d2

Please sign in to comment.