From 312e60781e1c776c5b039d17090e8cb15a77422d Mon Sep 17 00:00:00 2001 From: Alexandre Garbe Date: Fri, 30 Aug 2024 15:20:22 +0200 Subject: [PATCH] feat(admin): added organism remote information page to agencies settings v3 --- .../information/informationRemote.hook.ts | 100 +++++++ .../informationRemoteFormSchema.ts | 98 ++++++ .../[organismId]/remote/information/page.tsx | 282 ++++++++++++++++++ .../organisms/[organismId]/remote/page.tsx | 10 + 4 files changed, 490 insertions(+) create mode 100644 packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/information/informationRemote.hook.ts create mode 100644 packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/information/informationRemoteFormSchema.ts create mode 100644 packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/information/page.tsx diff --git a/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/information/informationRemote.hook.ts b/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/information/informationRemote.hook.ts new file mode 100644 index 000000000..2854489e8 --- /dev/null +++ b/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/information/informationRemote.hook.ts @@ -0,0 +1,100 @@ +import { useGraphQlClient } from "@/components/graphql/graphql-client/GraphqlClient"; +import { graphql } from "@/graphql/generated"; +import { RemoteZone } from "@/graphql/generated/graphql"; + +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { useParams } from "next/navigation"; + +const getOrganismQuery = graphql(` + query getOrganismForInformationRemotePage($organismId: ID!) { + organism_getOrganism(id: $organismId) { + id + isRemote + remoteZones + informationsCommerciales { + id + nom + telephone + siteInternet + emailContact + } + } + } +`); + +const createOrUpdateInformationsCommercialesAndRemoteStatusMutation = graphql(` + mutation createOrUpdateInformationsCommercialesAndRemoteStatusMutation( + $createOrUpdateInformationsCommercialesInput: CreateOrUpdateInformationsCommercialesInput! + $organismId: String! + $isRemote: Boolean! + $remoteZones: [RemoteZone!]! + ) { + organism_createOrUpdateInformationsCommerciales( + informationsCommerciales: $createOrUpdateInformationsCommercialesInput + ) { + id + } + organism_updateOrganismOnSiteAndRemoteStatus( + organismId: $organismId + isOnSite: false + isRemote: $isRemote + remoteZones: $remoteZones + ) { + id + } + } +`); + +export const useInformationRemotePage = () => { + const queryClient = useQueryClient(); + const { graphqlClient } = useGraphQlClient(); + + const { organismId } = useParams<{ organismId: string }>(); + + const { data: getOrganismResponse, status: getOrganismStatus } = useQuery({ + queryKey: [organismId, "organism"], + queryFn: () => + graphqlClient.request(getOrganismQuery, { + organismId, + }), + }); + + const organism = getOrganismResponse?.organism_getOrganism; + + const createOrUpdateInformationsCommercialesAndRemoteStatus = useMutation({ + mutationFn: ({ + organismId, + informationsCommerciales, + isRemote, + remoteZones, + }: { + organismId: string; + isRemote: boolean; + remoteZones: RemoteZone[]; + informationsCommerciales: { + nom: string; + }; + }) => + graphqlClient.request( + createOrUpdateInformationsCommercialesAndRemoteStatusMutation, + { + organismId, + isRemote, + remoteZones, + createOrUpdateInformationsCommercialesInput: { + organismId, + ...informationsCommerciales, + }, + }, + ), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: [organismId, "organisms"] }); + }, + }); + + return { + organism, + getOrganismStatus, + createOrUpdateInformationsCommercialesAndRemoteStatus, + }; +}; diff --git a/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/information/informationRemoteFormSchema.ts b/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/information/informationRemoteFormSchema.ts new file mode 100644 index 000000000..d00e6924a --- /dev/null +++ b/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/information/informationRemoteFormSchema.ts @@ -0,0 +1,98 @@ +import { z } from "zod"; + +export const informationRemoteFormSchema = z + .object({ + nom: z.string(), + telephone: z.string().optional(), + siteInternet: z.string().optional(), + emailContact: z + .union([ + z + .string() + .length(0, "Le champ doit être vide ou contenir une adresse email"), + z + .string() + .email("Le champ doit être vide ou contenir une adresse email"), + ]) + .optional() + .default(""), + isNotRemote: z.boolean(), + isRemoteFranceMetropolitaine: z.boolean(), + isRemoteGuadeloupe: z.boolean(), + isRemoteGuyane: z.boolean(), + isRemoteMartinique: z.boolean(), + isRemoteMayotte: z.boolean(), + isRemoteLaReunion: z.boolean(), + isRemoteSaintPierreEtMiquelon: z.boolean(), + isRemoteSainteLucieSaintMartin: z.boolean(), + }) + .superRefine( + ( + { + isNotRemote, + isRemoteFranceMetropolitaine, + isRemoteGuadeloupe, + isRemoteGuyane, + isRemoteLaReunion, + isRemoteMartinique, + isRemoteMayotte, + nom, + emailContact, + telephone, + }, + { addIssue }, + ) => { + const assertRequiredField = ({ + fieldName, + fieldValue, + }: { + fieldName: string; + fieldValue: unknown; + }) => { + if (!fieldValue) { + console.log({ fieldValue }); + addIssue({ + path: [fieldName], + message: "Merci de remplir ce champ", + code: z.ZodIssueCode.custom, + }); + } + }; + if (!isNotRemote) { + [ + { + fieldName: "nom", + fieldValue: nom, + }, + { + fieldName: "emailContact", + fieldValue: emailContact, + }, + { + fieldName: "telephone", + fieldValue: telephone, + }, + ].forEach(assertRequiredField); + if ( + ![ + isRemoteFranceMetropolitaine, + isRemoteGuadeloupe, + isRemoteGuyane, + isRemoteLaReunion, + isRemoteMartinique, + isRemoteMayotte, + ].some((r) => !!r) + ) { + addIssue({ + path: ["isRemoteFranceMetropolitaine"], + message: "Au moins une case doit être cochée", + code: z.ZodIssueCode.custom, + }); + } + } + }, + ); + +export type InformationRemoteFormData = z.infer< + typeof informationRemoteFormSchema +>; diff --git a/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/information/page.tsx b/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/information/page.tsx new file mode 100644 index 000000000..b88b0b1e2 --- /dev/null +++ b/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/information/page.tsx @@ -0,0 +1,282 @@ +"use client"; +import { FormOptionalFieldsDisclaimer } from "@/components/form-optional-fields-disclaimer/FormOptionalFieldsDisclaimer"; +import { graphqlErrorToast, successToast } from "@/components/toast/toast"; +import { RemoteZone } from "@/graphql/generated/graphql"; +import Checkbox from "@codegouvfr/react-dsfr/Checkbox"; +import { Input } from "@codegouvfr/react-dsfr/Input"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useCallback, useEffect } from "react"; +import { useForm, useWatch } from "react-hook-form"; +import { useInformationRemotePage } from "./informationRemote.hook"; +import { + InformationRemoteFormData, + informationRemoteFormSchema, +} from "./informationRemoteFormSchema"; +import { useQueryClient } from "@tanstack/react-query"; +import { FormButtons } from "@/components/form/form-footer/FormButtons"; +import { useParams } from "next/navigation"; +import { Breadcrumb } from "@codegouvfr/react-dsfr/Breadcrumb"; + +const InformationsRemotePage = () => { + const { organismId } = useParams<{ organismId: string }>(); + const { + organism, + getOrganismStatus, + createOrUpdateInformationsCommercialesAndRemoteStatus, + } = useInformationRemotePage(); + + const queryClient = useQueryClient(); + const { + register, + handleSubmit, + reset, + control, + formState: { errors, isSubmitting, isDirty }, + } = useForm({ + resolver: zodResolver(informationRemoteFormSchema), + }); + + const handleReset = useCallback(() => { + reset({ + ...organism?.informationsCommerciales, + isRemoteFranceMetropolitaine: organism?.remoteZones?.includes( + "FRANCE_METROPOLITAINE", + ), + isRemoteGuadeloupe: organism?.remoteZones?.includes("GUADELOUPE"), + isRemoteGuyane: organism?.remoteZones?.includes("GUYANE"), + isRemoteLaReunion: organism?.remoteZones?.includes("LA_REUNION"), + isRemoteMartinique: organism?.remoteZones?.includes("MARTINIQUE"), + isRemoteMayotte: organism?.remoteZones?.includes("MAYOTTE"), + isRemoteSaintPierreEtMiquelon: organism?.remoteZones?.includes( + "SAINT_PIERRE_ET_MIQUELON", + ), + isRemoteSainteLucieSaintMartin: organism?.remoteZones?.includes( + "SAINTE_LUCIE_SAINT_MARTIN", + ), + isNotRemote: !organism?.isRemote, + } as InformationRemoteFormData); + }, [organism, reset]); + + useEffect(() => handleReset(), [handleReset]); + + const handleFormSubmit = handleSubmit(async (data) => { + try { + const { + isNotRemote, + isRemoteFranceMetropolitaine, + isRemoteGuadeloupe, + isRemoteGuyane, + isRemoteLaReunion, + isRemoteMartinique, + isRemoteMayotte, + isRemoteSaintPierreEtMiquelon, + isRemoteSainteLucieSaintMartin, + ...informationsCommerciales + } = data; + + const remoteZones: RemoteZone[] = []; + + if (!isNotRemote) { + if (isRemoteFranceMetropolitaine) { + remoteZones.push("FRANCE_METROPOLITAINE"); + } + if (isRemoteGuadeloupe) { + remoteZones.push("GUADELOUPE"); + } + if (isRemoteGuyane) { + remoteZones.push("GUYANE"); + } + if (isRemoteLaReunion) { + remoteZones.push("LA_REUNION"); + } + if (isRemoteMartinique) { + remoteZones.push("MARTINIQUE"); + } + if (isRemoteMayotte) { + remoteZones.push("MAYOTTE"); + } + if (isRemoteSaintPierreEtMiquelon) { + remoteZones.push("SAINT_PIERRE_ET_MIQUELON"); + } + if (isRemoteSainteLucieSaintMartin) { + remoteZones.push("SAINTE_LUCIE_SAINT_MARTIN"); + } + } + + await createOrUpdateInformationsCommercialesAndRemoteStatus.mutateAsync({ + organismId: organism?.id, + isRemote: !isNotRemote, + remoteZones, + informationsCommerciales, + }); + queryClient.invalidateQueries({ + queryKey: [organism?.id], + }); + successToast("modifications enregistrées"); + } catch (e) { + graphqlErrorToast(e); + } + }); + + const { isNotRemote } = useWatch({ control }); + + return ( +
+ +

Informations affichées au candidat

+ +

+ Renseignez les informations qui seront affichées dans les résultats de + recherche des candidats puis sélectionnez les zones où se dérouleront + vos accompagnements à distance. +

+ + {getOrganismStatus === "success" && ( + <> +
{ + e.preventDefault(); + handleReset(); + }} + > + +
+ + + + +
+
+ +
+ + + + )} +
+ ); +}; + +export default InformationsRemotePage; diff --git a/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/page.tsx b/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/page.tsx index d91a64dd9..4267c74df 100644 --- a/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/page.tsx +++ b/packages/reva-admin-react/src/app/(aap)/agencies-settings-v3/organisms/[organismId]/remote/page.tsx @@ -1,6 +1,10 @@ +"use client"; +import { EnhancedSectionCard } from "@/components/card/enhanced-section-card/EnhancedSectionCard"; import { Breadcrumb } from "@codegouvfr/react-dsfr/Breadcrumb"; +import { useParams } from "next/navigation"; export default function RemotePage() { + const { organismId } = useParams<{ organismId: string }>(); return (
Pour être visible complétez tout et mettez l’interrupteur sur visible.

+
); }