diff --git a/server/public/mails/activate_account.mjml.ejs b/server/public/mails/activate_account.mjml.ejs index 615864bcd..9349003d7 100644 --- a/server/public/mails/activate_account.mjml.ejs +++ b/server/public/mails/activate_account.mjml.ejs @@ -22,24 +22,15 @@ background-color="#0e4194" color="white" > - Lien d'activation + Activer votre compte - Concernant la saisie des demandes d’ouverture, fermeture… :
- - vous devez enregistrer la liste des demandes qui seront soumises - au vote du Conseil Régional et non pas toutes les demandes que vous - avez examinées.
- - vous pouvez enregistrer les demandes en mode brouillon ou - soumettre à la validation
- - lorsque la saisie de toutes les demandes pour la Région Académique - sera terminée, l’utilisateur “Pilote” (Recteur ou SGA) devra valider - la liste
-
Pour toute question, consultez la documentation dans Orion - ou contactez-nous.
+ ou contactez-nous à l'adresse suivante: + orion@inserjeunes.beta.gouv.fr
<%- include('./common/signature.ejs'); %> diff --git a/server/public/mails/activate_account_pilote.mjml.ejs b/server/public/mails/activate_account_pilote.mjml.ejs index 35a95deb7..52cd3041f 100644 --- a/server/public/mails/activate_account_pilote.mjml.ejs +++ b/server/public/mails/activate_account_pilote.mjml.ejs @@ -21,7 +21,7 @@ background-color="#0e4194" color="white" > - Lien d'activation + Activer votre compte Pour toute question, consultez la diff --git a/server/public/mails/activate_account_region.mjml.ejs b/server/public/mails/activate_account_region.mjml.ejs new file mode 100644 index 000000000..bf6ce058d --- /dev/null +++ b/server/public/mails/activate_account_region.mjml.ejs @@ -0,0 +1,54 @@ + + <%- include('./common/head.ejs'); %> + + <%- include('./common/header.ejs'); %> + + + + + Bonjour <%= data.recipient.firstname %> <%= data.recipient.lastname + %>,
+
+ Orion vous donne accès à différentes données et indicateurs qui + outillent les réflexions autour de la transformation de la carte des + formations professionnelles en voie initiale.
+
+ À compter d’aujourd’hui, vous pouvez saisir les demandes + d’ouverture/fermeture de formations dans Orion, ce qui permettra + d’initier le dialogue de gestion avec la DGESCO.
+
+ Pour y accéder, activez votre compte en cliquant sur le lien + ci-dessous :
+
+ + Activer votre compte + + + À venir pour compléter ce module de saisie : +
+
    +
  • + Le 16/10, une console d’analyse des demandes enrichie par les + indicateurs InserJeunes ; +
  • +
  • + Le 23/10, une page de pilotage du taux de transformation de la + carte. +
  • +
+
+ + Si vous rencontrez des problèmes lors de la connexion ou de la + saisie, vous pouvez contacter notre équipe à l’adresse suivante : + orion@inserjeunes.beta.gouv.fr + + <%- include('./common/signature.ejs'); %> +
+
+
+
+
diff --git a/server/src/modules/core/services/mailer/mailer.ts b/server/src/modules/core/services/mailer/mailer.ts index 920b36ba4..9a3a58aff 100644 --- a/server/src/modules/core/services/mailer/mailer.ts +++ b/server/src/modules/core/services/mailer/mailer.ts @@ -37,6 +37,15 @@ export type TemplatePayloads = { }; activationToken: string; }; + activate_account_region: { + recipient: { + lastname?: string | undefined; + firstname?: string | undefined; + email: string; + role: string; + }; + activationToken: string; + }; }; function createTransporter(smtp: SMTPTransport & { secure: boolean }) { diff --git a/server/src/modules/core/usecases/createUser/createUser.usecase.ts b/server/src/modules/core/usecases/createUser/createUser.usecase.ts index 4636834a1..6dc7757dc 100644 --- a/server/src/modules/core/usecases/createUser/createUser.usecase.ts +++ b/server/src/modules/core/usecases/createUser/createUser.usecase.ts @@ -49,8 +49,14 @@ export const [createUser, createUserFactory] = inject( ); const template = - ({ pilote: "activate_account_pilote" } as const)[role] ?? - ("activate_account" as const); + ( + { + pilote: "activate_account_pilote", + pilote_region: "activate_account_region", + gestionnaire_region: "activate_account_region", + expert_region: "activate_account_region", + } as const + )[role] ?? ("activate_account" as const); deps.shootTemplate({ to: email, diff --git a/server/src/modules/intentions/routes/demande.routes.ts b/server/src/modules/intentions/routes/demande.routes.ts index 1f1f7b139..23c8ee219 100644 --- a/server/src/modules/intentions/routes/demande.routes.ts +++ b/server/src/modules/intentions/routes/demande.routes.ts @@ -13,6 +13,7 @@ import { hasPermissionHandler } from "../../core"; import { countDemandes } from "../queries/countDemandes.query"; import { findDemande } from "../queries/findDemande.query"; import { findDemandes } from "../queries/findDemandes.query"; +import { deleteDemande } from "../usecases/deleteDemande/deleteDemande.usecase"; import { submitDemande } from "../usecases/submitDemande/submitDemande.usecase"; import { submitDraftDemande } from "../usecases/submitDraftDemande/submitDraftDemande.usecase"; @@ -21,7 +22,7 @@ export const demandeRoutes = ({ server }: { server: Server }) => { "/demande/submit", { schema: ROUTES_CONFIG.submitDemande, - preHandler: hasPermissionHandler("intentions/envoi"), + preHandler: hasPermissionHandler("intentions/ecriture"), }, async (request, response) => { const { demande } = request.body; @@ -39,7 +40,7 @@ export const demandeRoutes = ({ server }: { server: Server }) => { "/demande/draft", { schema: ROUTES_CONFIG.submitDraftDemande, - preHandler: hasPermissionHandler("intentions/envoi"), + preHandler: hasPermissionHandler("intentions/ecriture"), }, async (request, response) => { const { demande } = request.body; @@ -65,7 +66,7 @@ export const demandeRoutes = ({ server }: { server: Server }) => { const demande = await findDemande({ id: request.params.id, user }); if (!demande) return response.status(404).send(); - const scope = getPermissionScope(user.role, "intentions/envoi"); + const scope = getPermissionScope(user.role, "intentions/ecriture"); const canEdit = guardScope(scope?.default, { user: () => user.id === demande.createurId, region: () => user.codeRegion === demande.codeRegion, @@ -76,6 +77,20 @@ export const demandeRoutes = ({ server }: { server: Server }) => { } ); + server.delete( + "/demande/:id", + { + schema: ROUTES_CONFIG.deleteDemande, + preHandler: hasPermissionHandler("intentions/ecriture"), + }, + async (request, response) => { + const user = request.user; + if (!user) throw Boom.forbidden(); + await deleteDemande({ id: request.params.id, user }); + response.status(200).send(); + } + ); + server.get( "/demandes", { diff --git a/server/src/modules/intentions/usecases/deleteDemande/deleteDemande.dep.ts b/server/src/modules/intentions/usecases/deleteDemande/deleteDemande.dep.ts new file mode 100644 index 000000000..ec6a8aadb --- /dev/null +++ b/server/src/modules/intentions/usecases/deleteDemande/deleteDemande.dep.ts @@ -0,0 +1,5 @@ +import { kdb } from "../../../../db/db"; + +export const deleteDemandeQuery = async (id: string) => { + await kdb.deleteFrom("demande").where("id", "=", id).execute(); +}; diff --git a/server/src/modules/intentions/usecases/deleteDemande/deleteDemande.usecase.ts b/server/src/modules/intentions/usecases/deleteDemande/deleteDemande.usecase.ts new file mode 100644 index 000000000..d8a85d0cf --- /dev/null +++ b/server/src/modules/intentions/usecases/deleteDemande/deleteDemande.usecase.ts @@ -0,0 +1,30 @@ +import Boom from "@hapi/boom"; +import { getPermissionScope, guardScope } from "shared"; + +import { RequestUser } from "../../../core/model/User"; +import { findOneDemande } from "../../repositories/findOneDemande.query"; +import { deleteDemandeQuery } from "./deleteDemande.dep"; + +export const deleteDemandeFactory = + (deps = { findOneDemande, deleteDemandeQuery }) => + async ({ + id, + user, + }: { + id: string; + user: Pick; + }) => { + const demande = await deps.findOneDemande(id); + if (!demande) throw Boom.notFound(); + + const scope = getPermissionScope(user.role, "intentions/ecriture"); + const isAllowed = guardScope(scope?.default, { + user: () => user.id === demande.createurId, + region: () => user.codeRegion === demande.codeRegion, + national: () => true, + }); + if (!isAllowed) throw Boom.forbidden(); + await deps.deleteDemandeQuery(demande.id); + }; + +export const deleteDemande = deleteDemandeFactory(); diff --git a/server/src/modules/intentions/usecases/submitDemande/submitDemande.usecase.ts b/server/src/modules/intentions/usecases/submitDemande/submitDemande.usecase.ts index 70e181149..fc43b38b4 100644 --- a/server/src/modules/intentions/usecases/submitDemande/submitDemande.usecase.ts +++ b/server/src/modules/intentions/usecases/submitDemande/submitDemande.usecase.ts @@ -74,7 +74,7 @@ export const [submitDemande, submitDemandeFactory] = inject( if (!dataEtablissement) throw Boom.badRequest("Code uai non valide"); if (!dataEtablissement.codeRegion) throw Boom.badData(); - const scope = getPermissionScope(user.role, "intentions/envoi"); + const scope = getPermissionScope(user.role, "intentions/ecriture"); const isAllowed = guardScope(scope?.default, { user: () => user.codeRegion === dataEtablissement.codeRegion && diff --git a/server/src/modules/intentions/usecases/submitDraftDemande/submitDraftDemande.usecase.ts b/server/src/modules/intentions/usecases/submitDraftDemande/submitDraftDemande.usecase.ts index 05f571e60..c812f61cf 100644 --- a/server/src/modules/intentions/usecases/submitDraftDemande/submitDraftDemande.usecase.ts +++ b/server/src/modules/intentions/usecases/submitDraftDemande/submitDraftDemande.usecase.ts @@ -74,7 +74,7 @@ export const [submitDraftDemande] = inject( if (!dataEtablissement) throw Boom.badRequest("Code uai non valide"); if (!dataEtablissement.codeRegion) throw Boom.badData(); - const scope = getPermissionScope(user.role, "intentions/envoi"); + const scope = getPermissionScope(user.role, "intentions/ecriture"); const isAllowed = guardScope(scope?.default, { user: () => user.codeRegion === dataEtablissement.codeRegion && diff --git a/shared/client/intentions/intentions.client.ts b/shared/client/intentions/intentions.client.ts index 448357304..19543933e 100644 --- a/shared/client/intentions/intentions.client.ts +++ b/shared/client/intentions/intentions.client.ts @@ -31,6 +31,11 @@ export const createIntentionsClient = (instance: AxiosInstance) => ({ url: "/demande/draft", instance, }), + deleteDemande: createClientMethod({ + method: "DELETE", + url: ({ params: { id } }) => `/demande/${id}`, + instance, + }), getDemande: createClientMethod({ method: "GET", url: ({ params: { id } }) => `/demande/${id}`, diff --git a/shared/client/intentions/intentions.schema.ts b/shared/client/intentions/intentions.schema.ts index 24134752b..b999df759 100644 --- a/shared/client/intentions/intentions.schema.ts +++ b/shared/client/intentions/intentions.schema.ts @@ -175,6 +175,12 @@ export const intentionsSchemas = { }), }, }, + deleteDemande: { + params: Type.Object({ id: Type.String() }), + response: { + 200: Type.Void(), + }, + }, getDemandes: { querystring: Type.Intersect([ FiltersSchema, diff --git a/shared/security/permissions.ts b/shared/security/permissions.ts index 30169841e..9cce6e4c5 100644 --- a/shared/security/permissions.ts +++ b/shared/security/permissions.ts @@ -11,8 +11,7 @@ export const PERMISSIONS = { admin: { "pilotage_reforme/lecture": { default: "national" }, "intentions/lecture": { default: "national", draft: "national" }, - "intentions/suppression": { default: "national" }, - "intentions/envoi": { default: "national" }, + "intentions/ecriture": { default: "national" }, }, pilote: { // "intentions/lecture": { default: "national", draft: "national" }, @@ -23,13 +22,11 @@ export const PERMISSIONS = { }, expert_region: { "intentions/lecture": { default: "region", draft: "region" }, - "intentions/suppression": { default: "region" }, - "intentions/envoi": { default: "region" }, + "intentions/ecriture": { default: "region" }, }, gestionnaire_region: { "intentions/lecture": { draft: "user", default: "region" }, - "intentions/suppression": { default: "user" }, - "intentions/envoi": { default: "user" }, + "intentions/ecriture": { default: "user" }, }, } satisfies { [R: string]: { diff --git a/ui/app/(wrapped)/intentions/[intentionId]/page.client.tsx b/ui/app/(wrapped)/intentions/[intentionId]/page.client.tsx index d18d109f9..ef8b132a7 100644 --- a/ui/app/(wrapped)/intentions/[intentionId]/page.client.tsx +++ b/ui/app/(wrapped)/intentions/[intentionId]/page.client.tsx @@ -24,7 +24,7 @@ export default ({ <> {data && ( }>; + onConfirm: () => Promise; +}) => { + const { isOpen, onOpen, onClose } = useDisclosure(); + const cancelRef = useRef(null); + + return ( + <> + + + + + + + + Confirmation de suppression + + + Êtes-vous sûr de vouloir supprimer la demande ? + + + Cette action est irréversible, vous perdrez l’ensemble des + données associées à votre demande. + + + + + + + + + + + + ); +}; diff --git a/ui/app/(wrapped)/intentions/intentionForm/InfoBox.tsx b/ui/app/(wrapped)/intentions/components/InfoBox.tsx similarity index 100% rename from ui/app/(wrapped)/intentions/intentionForm/InfoBox.tsx rename to ui/app/(wrapped)/intentions/components/InfoBox.tsx diff --git a/ui/app/(wrapped)/intentions/menuIntention/MenuIntention.tsx b/ui/app/(wrapped)/intentions/components/MenuIntention.tsx similarity index 100% rename from ui/app/(wrapped)/intentions/menuIntention/MenuIntention.tsx rename to ui/app/(wrapped)/intentions/components/MenuIntention.tsx diff --git a/ui/app/(wrapped)/intentions/intentionForm/InformationsBlock.tsx b/ui/app/(wrapped)/intentions/intentionForm/InformationsBlock.tsx index 6750da67d..15cf8deb7 100644 --- a/ui/app/(wrapped)/intentions/intentionForm/InformationsBlock.tsx +++ b/ui/app/(wrapped)/intentions/intentionForm/InformationsBlock.tsx @@ -4,12 +4,11 @@ import { AlertIcon, AlertTitle, Box, - Button, Divider, Flex, - Text, UnorderedList, } from "@chakra-ui/react"; +import { ReactNode } from "react"; import { ApiType } from "shared"; import { api } from "../../../../api.client"; @@ -17,27 +16,23 @@ import { CapaciteSection } from "./capaciteSection/CapaciteSection"; import { TypeDemandeSection } from "./typeDemandeSection/TypeDemandeSection"; export const InformationsBlock = ({ - canEdit, + disabled, errors, - isSubmitting, - onDraftSubmit, - isDraftSubmitting, formMetadata, + footerActions, }: { - canEdit: boolean; + disabled: boolean; errors?: Record; - isSubmitting?: boolean; - onDraftSubmit: () => void; - isDraftSubmitting?: boolean; formMetadata?: ApiType["metadata"]; + footerActions: ReactNode; }) => { return ( <> - + - + {errors && ( @@ -54,34 +49,11 @@ export const InformationsBlock = ({ )} - - - - - (Phase d'enregistrement du 02 au 16 octobre) - - - - - - Pour soumission au vote du Conseil Régional - - - + {footerActions && ( + + {footerActions} + + )} ); diff --git a/ui/app/(wrapped)/intentions/intentionForm/IntentionForm.tsx b/ui/app/(wrapped)/intentions/intentionForm/IntentionForm.tsx index 211a9361d..0c5b8cc7a 100644 --- a/ui/app/(wrapped)/intentions/intentionForm/IntentionForm.tsx +++ b/ui/app/(wrapped)/intentions/intentionForm/IntentionForm.tsx @@ -1,6 +1,7 @@ "use client"; -import { Box, Collapse, Container } from "@chakra-ui/react"; +import { DeleteIcon } from "@chakra-ui/icons"; +import { Box, Button, Collapse, Container, Text } from "@chakra-ui/react"; import { useMutation } from "@tanstack/react-query"; import { AxiosError } from "axios"; import { usePathname, useRouter } from "next/navigation"; @@ -8,6 +9,7 @@ import { useEffect, useRef, useState } from "react"; import { FormProvider, useForm } from "react-hook-form"; import { ApiType } from "shared"; +import { ConfirmationDelete } from "@/app/(wrapped)/intentions/components/ConfirmationDelete"; import { IntentionForms, PartialIntentionForms, @@ -19,16 +21,17 @@ import { CfdUaiSection } from "./cfdUaiSection/CfdUaiSection"; import { InformationsBlock } from "./InformationsBlock"; export const IntentionForm = ({ - canEdit = false, + disabled = true, formId, defaultValues, formMetadata, }: { - canEdit?: boolean; + disabled?: boolean; formId?: string; defaultValues: PartialIntentionForms; formMetadata?: ApiType["metadata"]; }) => { + const { push } = useRouter(); const pathname = usePathname(); const form = useForm({ defaultValues, @@ -41,12 +44,9 @@ export const IntentionForm = ({ const [errors, setErrors] = useState>(); const { isLoading: isSubmitting, mutateAsync: submit } = useMutation({ - mutationFn: ({ forms }: { forms: IntentionForms }) => - api - .submitDemande({ - body: { demande: { id: formId, ...forms } }, - }) - .call(), + mutationFn: (forms: IntentionForms) => + api.submitDemande({ body: { demande: { id: formId, ...forms } } }).call(), + onSuccess: () => push("/intentions"), onError: (e: AxiosError<{ errors: Record }>) => { const errors = e.response?.data.errors; setErrors(errors); @@ -55,18 +55,25 @@ export const IntentionForm = ({ const { isLoading: isDraftSubmitting, mutateAsync: submitDraft } = useMutation({ - mutationFn: ({ forms }: { forms: IntentionForms }) => + mutationFn: (forms: IntentionForms) => api - .submitDraftDemande({ - body: { demande: { id: formId, ...forms } }, - }) + .submitDraftDemande({ body: { demande: { id: formId, ...forms } } }) .call(), + onSuccess: () => push("/intentions"), onError: (e: AxiosError<{ errors: Record }>) => { const errors = e.response?.data.errors; setErrors(errors); }, }); + const { isLoading: isDeleting, mutateAsync: deleteDemande } = useMutation({ + mutationFn: async () => { + if (!formId) return; + await api.deleteDemande({ params: { id: formId } }).call(); + }, + onSuccess: () => push("/intentions"), + }); + const [isFCIL, setIsFCIL] = useState( formMetadata?.formation?.isFCIL ?? false ); @@ -86,18 +93,6 @@ export const IntentionForm = ({ const onEditUaiCfdSection = () => setStep(1); - const { push } = useRouter(); - - const onSubmit = async () => { - await submit({ forms: getValues() }); - push("/intentions"); - }; - - const onDraftSubmit = handleSubmit(async () => { - await submitDraft({ forms: getValues() }); - push("/intentions"); - }); - useEffect(() => { if (isCFDUaiSectionValid(getValues())) { submitCFDUAISection(); @@ -120,7 +115,7 @@ export const IntentionForm = ({ bg="#E2E7F8" as="form" noValidate - onSubmit={handleSubmit(onSubmit)} + onSubmit={handleSubmit((values) => submit(values))} > + {formId && ( + ( + + )} + /> + )} + + + + (Phase d'enregistrement du 02 au 16 octobre) + + + + + + Pour soumission au vote du Conseil Régional + + + + } /> diff --git a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/AmiCmaField.tsx b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/AmiCmaField.tsx index caaf6d1b2..906c9f5ca 100644 --- a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/AmiCmaField.tsx +++ b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/AmiCmaField.tsx @@ -13,41 +13,45 @@ import { IntentionForms } from "@/app/(wrapped)/intentions/intentionForm/default import { toBoolean } from "../../utils/toBoolean"; -export const AmiCmaField = chakra(({ className }: { className?: string }) => { - const { - formState: { errors }, - control, - } = useFormContext(); +export const AmiCmaField = chakra( + ({ disabled, className }: { disabled?: boolean; className?: string }) => { + const { + formState: { errors }, + control, + } = useFormContext(); - return ( - - AMI / CMA - - typeof value === "boolean" || "Le champ est obligatoire", - }} - render={({ field: { onChange, value, onBlur, ref } }) => ( - onChange(toBoolean(v))} - value={JSON.stringify(value)} - > - - Oui - - - Non - - + return ( + + AMI / CMA + + typeof value === "boolean" || "Le champ est obligatoire", + }} + render={({ field: { onChange, value, onBlur, ref, disabled } }) => ( + onChange(toBoolean(v))} + value={JSON.stringify(value)} + > + + Oui + + + Non + + + )} + /> + {errors.amiCma && ( + {errors.amiCma?.message} )} - /> - {errors.amiCma && ( - {errors.amiCma?.message} - )} - - ); -}); + + ); + } +); diff --git a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteApprentissageActuelleField.tsx b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteApprentissageActuelleField.tsx index 050fffa23..398c67e25 100644 --- a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteApprentissageActuelleField.tsx +++ b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteApprentissageActuelleField.tsx @@ -13,7 +13,7 @@ import { isTypeOuverture } from "../../utils/typeDemandeUtils"; import { IntentionForms } from "../defaultFormValues"; export const CapaciteApprentissageActuelleField = chakra( - ({ className }: { className?: string }) => { + ({ disabled, className }: { disabled?: boolean; className?: string }) => { const { formState: { errors }, register, @@ -44,6 +44,7 @@ export const CapaciteApprentissageActuelleField = chakra( type="number" {...register("capaciteApprentissageActuelle", { shouldUnregister: true, + disabled, setValueAs: safeParseInt, value: null as unknown as undefined, validate: (value) => { diff --git a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteApprentissageColoreeField.tsx b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteApprentissageColoreeField.tsx index d15ee847f..6c970ad41 100644 --- a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteApprentissageColoreeField.tsx +++ b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteApprentissageColoreeField.tsx @@ -14,7 +14,7 @@ import { isTypeFermeture } from "@/app/(wrapped)/intentions/utils/typeDemandeUti import { IntentionForms } from "../defaultFormValues"; export const CapaciteApprentissageColoreeField = chakra( - ({ className }: { className?: string }) => { + ({ disabled, className }: { disabled?: boolean; className?: string }) => { const { formState: { errors }, register, @@ -47,6 +47,7 @@ export const CapaciteApprentissageColoreeField = chakra( {...register("capaciteApprentissageColoree", { shouldUnregister: true, setValueAs: safeParseInt, + disabled, value: null as unknown as undefined, validate: (value) => { if (value === undefined) return "Le champ est obligatoire"; diff --git a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteApprentissageField.tsx b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteApprentissageField.tsx index f9df86156..5eb658e32 100644 --- a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteApprentissageField.tsx +++ b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteApprentissageField.tsx @@ -14,7 +14,7 @@ import { isTypeFermeture, isTypeOuverture } from "../../utils/typeDemandeUtils"; import { IntentionForms } from "../defaultFormValues"; export const CapaciteApprentissageField = chakra( - ({ className }: { className?: string }) => { + ({ disabled, className }: { disabled?: boolean; className?: string }) => { const { formState: { errors }, register, @@ -48,6 +48,7 @@ export const CapaciteApprentissageField = chakra( type="number" {...register("capaciteApprentissage", { shouldUnregister: true, + disabled, setValueAs: safeParseInt, value: null as unknown as undefined, validate: (value) => { diff --git a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteScolaireActuelleField.tsx b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteScolaireActuelleField.tsx index 9e0020ad5..8967f16e4 100644 --- a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteScolaireActuelleField.tsx +++ b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteScolaireActuelleField.tsx @@ -13,7 +13,7 @@ import { isTypeOuverture } from "../../utils/typeDemandeUtils"; import { IntentionForms } from "../defaultFormValues"; export const CapaciteScolaireActuelleField = chakra( - ({ className }: { className?: string }) => { + ({ disabled, className }: { disabled?: boolean; className?: string }) => { const { formState: { errors }, register, @@ -44,6 +44,7 @@ export const CapaciteScolaireActuelleField = chakra( type="number" {...register("capaciteScolaireActuelle", { shouldUnregister: true, + disabled, setValueAs: safeParseInt, value: null as unknown as undefined, validate: (value) => { diff --git a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteScolaireColoreeField.tsx b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteScolaireColoreeField.tsx index d59175ea5..27aab25f0 100644 --- a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteScolaireColoreeField.tsx +++ b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteScolaireColoreeField.tsx @@ -14,7 +14,7 @@ import { isTypeFermeture } from "@/app/(wrapped)/intentions/utils/typeDemandeUti import { IntentionForms } from "../defaultFormValues"; export const CapaciteScolaireColoreeField = chakra( - ({ className }: { className?: string }) => { + ({ disabled, className }: { disabled?: boolean; className?: string }) => { const { formState: { errors }, register, @@ -46,6 +46,7 @@ export const CapaciteScolaireColoreeField = chakra( type="number" {...register("capaciteScolaireColoree", { shouldUnregister: true, + disabled, setValueAs: safeParseInt, value: null as unknown as undefined, validate: (value) => { diff --git a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteScolaireField.tsx b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteScolaireField.tsx index 79e792a18..9991ad9e9 100644 --- a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteScolaireField.tsx +++ b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteScolaireField.tsx @@ -14,7 +14,7 @@ import { isTypeFermeture, isTypeOuverture } from "../../utils/typeDemandeUtils"; import { IntentionForms } from "../defaultFormValues"; export const CapaciteScolaireField = chakra( - ({ className }: { className?: string }) => { + ({ disabled, className }: { disabled?: boolean; className?: string }) => { const { formState: { errors }, register, @@ -48,6 +48,7 @@ export const CapaciteScolaireField = chakra( type="number" {...register("capaciteScolaire", { shouldUnregister: true, + disabled: disabled || fermeture, setValueAs: safeParseInt, value: null as unknown as undefined, validate: (value) => { @@ -58,7 +59,6 @@ export const CapaciteScolaireField = chakra( }, })} placeholder={fermeture ? "0" : ""} - disabled={fermeture} /> {errors.capaciteScolaire && ( {errors.capaciteScolaire.message} diff --git a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteSection.tsx b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteSection.tsx index af8ff0a0b..a678b6cdd 100644 --- a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteSection.tsx +++ b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CapaciteSection.tsx @@ -66,7 +66,7 @@ const ConstanteSection = ({ ); }; -export const CapaciteSection = () => { +export const CapaciteSection = ({ disabled }: { disabled: boolean }) => { const { watch } = useFormContext(); const [capaciteScolaire, capaciteScolaireActuelle] = watch([ @@ -92,22 +92,26 @@ export const CapaciteSection = () => { {!isTypeFermeture(typeDemande) && ( - - + + )} - - + + - + Capacité en voie scolaire {mixte ? " uniquement" : null} - - - + + + { Capacité en apprentissage - - - + + + { /> )} - + ); }; diff --git a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/ColorationField.tsx b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/ColorationField.tsx index a8ec84e0a..39b61a883 100644 --- a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/ColorationField.tsx +++ b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/ColorationField.tsx @@ -14,7 +14,7 @@ import { IntentionForms } from "@/app/(wrapped)/intentions/intentionForm/default import { toBoolean } from "../../utils/toBoolean"; export const ColorationField = chakra( - ({ className }: { className?: string }) => { + ({ disabled, className }: { disabled?: boolean; className?: string }) => { const { formState: { errors }, control, @@ -31,17 +31,21 @@ export const ColorationField = chakra( name="coloration" control={control} shouldUnregister={true} + disabled={disabled} rules={{ validate: (value) => typeof value === "boolean" || "Le champ est obligatoire", }} - render={({ field: { onChange, ref, name, onBlur, value } }) => ( + render={({ + field: { onChange, ref, name, onBlur, value, disabled }, + }) => ( onChange(toBoolean(v))} value={JSON.stringify(value)} + isDisabled={disabled} > Oui diff --git a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CommentaireField.tsx b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CommentaireField.tsx index d9b04117b..2e84169e7 100644 --- a/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CommentaireField.tsx +++ b/ui/app/(wrapped)/intentions/intentionForm/capaciteSection/CommentaireField.tsx @@ -10,7 +10,7 @@ import { useFormContext } from "react-hook-form"; import { IntentionForms } from "@/app/(wrapped)/intentions/intentionForm/defaultFormValues"; export const CommentaireField = chakra( - ({ className }: { className?: string }) => { + ({ disabled, className }: { disabled?: boolean; className?: string }) => { const { formState: { errors }, register, @@ -19,7 +19,10 @@ export const CommentaireField = chakra( return ( Commentaires / Observations sur la demande -