From 50d4f2f0ad4d1379992c8c4b99c67661e8a0165f Mon Sep 17 00:00:00 2001 From: Alexandre Garbe Date: Thu, 5 Dec 2024 15:49:12 +0100 Subject: [PATCH] feat(admin): added update competence bloc page to certification registry manager update certification page --- ...fication-competence-bloc-bp-boucher-1.json | 33 ++++ ...nce-bloc-bp-boucher-mutation-response.json | 7 + ...e-certification-competence-bloc-page.cy.ts | 163 ++++++++++++++++++ .../[certificationCompetenceBlocId]/page.tsx | 126 ++++++++++++++ .../updateCompetenceBloc.hook.ts | 102 +++++++++++ 5 files changed, 431 insertions(+) create mode 100644 packages/reva-admin-react/cypress/e2e/responsable-certifications/certifications/update-certification-competence-bloc-page/fixtures/certification-competence-bloc-bp-boucher-1.json create mode 100644 packages/reva-admin-react/cypress/e2e/responsable-certifications/certifications/update-certification-competence-bloc-page/fixtures/update-competence-bloc-bp-boucher-mutation-response.json create mode 100644 packages/reva-admin-react/cypress/e2e/responsable-certifications/certifications/update-certification-competence-bloc-page/update-certification-competence-bloc-page.cy.ts create mode 100644 packages/reva-admin-react/src/app/responsable-certifications/certifications/[certificationId]/bloc-competence/[certificationCompetenceBlocId]/page.tsx create mode 100644 packages/reva-admin-react/src/app/responsable-certifications/certifications/[certificationId]/bloc-competence/[certificationCompetenceBlocId]/updateCompetenceBloc.hook.ts diff --git a/packages/reva-admin-react/cypress/e2e/responsable-certifications/certifications/update-certification-competence-bloc-page/fixtures/certification-competence-bloc-bp-boucher-1.json b/packages/reva-admin-react/cypress/e2e/responsable-certifications/certifications/update-certification-competence-bloc-page/fixtures/certification-competence-bloc-bp-boucher-1.json new file mode 100644 index 000000000..f56933369 --- /dev/null +++ b/packages/reva-admin-react/cypress/e2e/responsable-certifications/certifications/update-certification-competence-bloc-page/fixtures/certification-competence-bloc-bp-boucher-1.json @@ -0,0 +1,33 @@ +{ + "data": { + "getCertificationCompetenceBloc": { + "id": "008a6fab-55ad-4412-ab17-56bc4b8e2fd0", + "label": "Préparation, présentation, décoration et vente en boucherie", + "code": "RNCP37310BC01", + "FCCompetences": "* Réaliser les opérations de préparations des viandes * Mettre en valeur les produits notamment l’intégralité de la carcasse dans une démarche de développement durable * Vendre les produits au client en argumentant et en proposant des conseils culinaires * Communiquer sur l’étiquetage, la conservation, la traçabilité, les signes officiels de qualité et l’origine des viandes", + "competences": [ + { + "id": "b8786018-6d24-4538-9622-f4ac62eb1742", + "label": "Réaliser les opérations de préparations des viandes" + }, + { + "id": "2cbb6688-7b80-416f-940a-e348246484f8", + "label": "Mettre en valeur les produits notamment l’intégralité de la carcasse dans une démarche de développement durable" + }, + { + "id": "2c829da9-ed10-48a3-ae1b-2f7db433c6d8", + "label": "Vendre les produits au client en argumentant et en proposant des conseils culinaires" + }, + { + "id": "5aad9206-27a0-4afa-ac28-06d30bab6504", + "label": "Communiquer sur l’étiquetage, la conservation, la traçabilité, les signes officiels de qualité et l’origine des viandes" + } + ], + "certification": { + "id": "bf78b4d6-f6ac-4c8f-9e6b-d6c6ae9e891b", + "codeRncp": "37310", + "label": "BP Boucher" + } + } + } +} diff --git a/packages/reva-admin-react/cypress/e2e/responsable-certifications/certifications/update-certification-competence-bloc-page/fixtures/update-competence-bloc-bp-boucher-mutation-response.json b/packages/reva-admin-react/cypress/e2e/responsable-certifications/certifications/update-certification-competence-bloc-page/fixtures/update-competence-bloc-bp-boucher-mutation-response.json new file mode 100644 index 000000000..7535c2382 --- /dev/null +++ b/packages/reva-admin-react/cypress/e2e/responsable-certifications/certifications/update-certification-competence-bloc-page/fixtures/update-competence-bloc-bp-boucher-mutation-response.json @@ -0,0 +1,7 @@ +{ + "data": { + "referential_updateCertificationCompetenceBloc": { + "id": "008a6fab-55ad-4412-ab17-56bc4b8e2fd0" + } + } +} diff --git a/packages/reva-admin-react/cypress/e2e/responsable-certifications/certifications/update-certification-competence-bloc-page/update-certification-competence-bloc-page.cy.ts b/packages/reva-admin-react/cypress/e2e/responsable-certifications/certifications/update-certification-competence-bloc-page/update-certification-competence-bloc-page.cy.ts new file mode 100644 index 000000000..bd7783d9f --- /dev/null +++ b/packages/reva-admin-react/cypress/e2e/responsable-certifications/certifications/update-certification-competence-bloc-page/update-certification-competence-bloc-page.cy.ts @@ -0,0 +1,163 @@ +import { stubMutation, stubQuery } from "../../../../utils/graphql"; +import certificationCBBPBoucher1 from "./fixtures/certification-competence-bloc-bp-boucher-1.json"; +import updateCertificationBlocMutationResponse from "./fixtures/update-competence-bloc-bp-boucher-mutation-response.json"; + +function interceptCertificationCompetenceBloc() { + cy.intercept("POST", "/api/graphql", (req) => { + stubQuery( + req, + "activeFeaturesForConnectedUser", + "features/active-features.json", + ); + stubQuery( + req, + "getMaisonMereCGUQuery", + "account/gestionnaire-cgu-accepted.json", + ); + stubQuery( + req, + "getCompetenceBlocForCertificationRegistryManagerUpdateCompetenceBlocPage", + certificationCBBPBoucher1, + ); + }); +} + +function interceptUpdateCertificationCompetenceBlocMutation() { + cy.intercept("POST", "/api/graphql", (req) => { + stubMutation( + req, + "updateCertificationCompetenceBlocForCertificationRegistryManagerUpdateCertificationCompetenceBlocPage", + updateCertificationBlocMutationResponse, + ); + }); +} + +function interceptDeleteCertificationCompetenceBlocMutation() { + cy.intercept("POST", "/api/graphql", (req) => { + stubMutation( + req, + "deleteCertificationCompetenceBlocForCertificationRegistryManagerUpdateCompetenceBlocPage", + updateCertificationBlocMutationResponse, + ); + }); +} + +context("when i access the update certification page ", () => { + it("display the page with a correct title", function () { + interceptCertificationCompetenceBloc(); + + cy.admin( + "http://localhost:3003/admin2/responsable-certifications/certifications/bf78b4d6-f6ac-4c8f-9e6b-d6c6ae9e891b/bloc-competence/008a6fab-55ad-4412-ab17-56bc4b8e2fd0/", + ); + cy.wait("@activeFeaturesForConnectedUser"); + cy.wait("@getMaisonMereCGUQuery"); + cy.wait( + "@getCompetenceBlocForCertificationRegistryManagerUpdateCompetenceBlocPage", + ); + + cy.get( + '[data-test="certification-registry-manager-update-certification-competence-bloc-page"]', + ) + .children("h1") + .should( + "have.text", + "RNCP37310BC01 - Préparation, présentation, décoration et vente en boucherie", + ); + }); + + it("dont let me submit the form if no edit has been made", function () { + interceptCertificationCompetenceBloc(); + cy.admin( + "http://localhost:3003/admin2/responsable-certifications/certifications/bf78b4d6-f6ac-4c8f-9e6b-d6c6ae9e891b/bloc-competence/008a6fab-55ad-4412-ab17-56bc4b8e2fd0/", + ); + cy.wait("@activeFeaturesForConnectedUser"); + cy.wait("@getMaisonMereCGUQuery"); + cy.wait( + "@getCompetenceBlocForCertificationRegistryManagerUpdateCompetenceBlocPage", + ); + + cy.get("button").contains("Enregistrer").should("be.disabled"); + }); + + it("let me update a competence bloc and submit the form", function () { + interceptCertificationCompetenceBloc(); + interceptUpdateCertificationCompetenceBlocMutation(); + cy.admin( + "http://localhost:3003/admin2/responsable-certifications/certifications/bf78b4d6-f6ac-4c8f-9e6b-d6c6ae9e891b/bloc-competence/008a6fab-55ad-4412-ab17-56bc4b8e2fd0/", + ); + cy.wait("@activeFeaturesForConnectedUser"); + cy.wait("@getMaisonMereCGUQuery"); + cy.wait( + "@getCompetenceBlocForCertificationRegistryManagerUpdateCompetenceBlocPage", + ); + + cy.get('[data-test="competence-bloc-label-input"] input') + .clear() + .type("updated competence bloc label"); + + cy.get("button").contains("Enregistrer").click(); + cy.wait( + "@updateCertificationCompetenceBlocForCertificationRegistryManagerUpdateCertificationCompetenceBlocPage", + ); + }); + + it("let me add a new competence to the competence bloc", function () { + interceptCertificationCompetenceBloc(); + cy.admin( + "http://localhost:3003/admin2/responsable-certifications/certifications/bf78b4d6-f6ac-4c8f-9e6b-d6c6ae9e891b/bloc-competence/008a6fab-55ad-4412-ab17-56bc4b8e2fd0/", + ); + cy.wait("@activeFeaturesForConnectedUser"); + cy.wait("@getMaisonMereCGUQuery"); + cy.wait( + "@getCompetenceBlocForCertificationRegistryManagerUpdateCompetenceBlocPage", + ); + + cy.get('[data-test="competence-list"] input').should("have.length", 4); + + cy.get('[data-test="add-competence-button"]').click(); + + cy.get('[data-test="competence-list"] input').should("have.length", 5); + }); + + it("let me delete a competence from the competence bloc", function () { + interceptCertificationCompetenceBloc(); + cy.admin( + "http://localhost:3003/admin2/responsable-certifications/certifications/bf78b4d6-f6ac-4c8f-9e6b-d6c6ae9e891b/bloc-competence/008a6fab-55ad-4412-ab17-56bc4b8e2fd0/", + ); + cy.wait("@activeFeaturesForConnectedUser"); + cy.wait("@getMaisonMereCGUQuery"); + cy.wait( + "@getCompetenceBlocForCertificationRegistryManagerUpdateCompetenceBlocPage", + ); + + cy.get('[data-test="competence-list"] input').should("have.length", 4); + + cy.get('[data-test="delete-competence-button"]').eq(1).click(); + + cy.get('[data-test="competence-list"] input').should("have.length", 3); + }); + + it("let me delete a competence bloc", function () { + interceptCertificationCompetenceBloc(); + interceptDeleteCertificationCompetenceBlocMutation(); + cy.admin( + "http://localhost:3003/admin2/responsable-certifications/certifications/bf78b4d6-f6ac-4c8f-9e6b-d6c6ae9e891b/bloc-competence/008a6fab-55ad-4412-ab17-56bc4b8e2fd0/", + ); + cy.wait("@activeFeaturesForConnectedUser"); + cy.wait("@getMaisonMereCGUQuery"); + cy.wait( + "@getCompetenceBlocForCertificationRegistryManagerUpdateCompetenceBlocPage", + ); + + cy.get('[data-test="delete-competence-bloc-button"]').click(); + + cy.wait( + "@deleteCertificationCompetenceBlocForCertificationRegistryManagerUpdateCompetenceBlocPage", + ); + + cy.url().should( + "eq", + "http://localhost:3003/admin2/responsable-certifications/certifications/bf78b4d6-f6ac-4c8f-9e6b-d6c6ae9e891b/", + ); + }); +}); diff --git a/packages/reva-admin-react/src/app/responsable-certifications/certifications/[certificationId]/bloc-competence/[certificationCompetenceBlocId]/page.tsx b/packages/reva-admin-react/src/app/responsable-certifications/certifications/[certificationId]/bloc-competence/[certificationCompetenceBlocId]/page.tsx new file mode 100644 index 000000000..a258e01c8 --- /dev/null +++ b/packages/reva-admin-react/src/app/responsable-certifications/certifications/[certificationId]/bloc-competence/[certificationCompetenceBlocId]/page.tsx @@ -0,0 +1,126 @@ +"use client"; +import { useParams, useRouter } from "next/navigation"; +import { useUpdateCompetenceBlocPage } from "./updateCompetenceBloc.hook"; +import { FormOptionalFieldsDisclaimer } from "@/components/form-optional-fields-disclaimer/FormOptionalFieldsDisclaimer"; +import { GrayCard } from "@/components/card/gray-card/GrayCard"; +import { Breadcrumb } from "@codegouvfr/react-dsfr/Breadcrumb"; +import { + CompetenceBlocForm, + CompetenceBlocFormData, +} from "../../../../../../components/certifications/competence-bloc-form/CompetenceBlocForm"; +import { graphqlErrorToast, successToast } from "@/components/toast/toast"; + +type CertificationCompetenceBlocForPage = Exclude< + ReturnType["competenceBloc"], + undefined +>; + +export default function UpdateCompetenceBlocPage() { + const { certificationId, certificationCompetenceBlocId } = useParams<{ + certificationId: string; + certificationCompetenceBlocId: string; + }>(); + + const router = useRouter(); + + const { + competenceBloc, + getCompetenceBlocQueryStatus, + updateCertificationCompetenceBloc, + deleteCertificationCompetenceBloc, + } = useUpdateCompetenceBlocPage({ certificationCompetenceBlocId }); + + const handleFormSubmit = async (data: CompetenceBlocFormData) => { + try { + await updateCertificationCompetenceBloc.mutateAsync(data); + successToast("modifications enregistrées"); + } catch (e) { + graphqlErrorToast(e); + } + }; + + const handleCompetenceBlocDeleteButtonClick = async () => { + try { + await deleteCertificationCompetenceBloc.mutateAsync(); + successToast("modifications enregistrées"); + router.push( + `/responsable-certifications/certifications/${certificationId}`, + ); + } catch (e) { + graphqlErrorToast(e); + } + }; + return getCompetenceBlocQueryStatus === "success" && competenceBloc ? ( + + ) : null; +} + +const PageContent = ({ + competenceBloc, + onSubmit, + onDeleteCompetenceBlocButtonClick, +}: { + competenceBloc: CertificationCompetenceBlocForPage; + onSubmit(data: CompetenceBlocFormData): Promise; + onDeleteCompetenceBlocButtonClick?: () => void; +}) => ( +
+ + +

+ {competenceBloc.code} - {competenceBloc.label} +

+ +

+ Retrouvez toutes les informations récupérées à partir du code RNCP. Si + vous souhaitez les modifier, il est préférable de contacter directement + France compétences. +

+ +

+ Informations France compétences liées au code RNCP{" "} + {competenceBloc.certification.codeRncp} +

+
+
Intitulé du bloc de compétences
+
+ {competenceBloc.code} - {competenceBloc.label} +
+
+
+
Compétences
+
{competenceBloc.FCCompetences}
+
+
+ ({ + ...c, + index: i, + })), + }} + onSubmit={onSubmit} + onDeleteCompetenceBlocButtonClick={onDeleteCompetenceBlocButtonClick} + /> +
+); diff --git a/packages/reva-admin-react/src/app/responsable-certifications/certifications/[certificationId]/bloc-competence/[certificationCompetenceBlocId]/updateCompetenceBloc.hook.ts b/packages/reva-admin-react/src/app/responsable-certifications/certifications/[certificationId]/bloc-competence/[certificationCompetenceBlocId]/updateCompetenceBloc.hook.ts new file mode 100644 index 000000000..58b453a55 --- /dev/null +++ b/packages/reva-admin-react/src/app/responsable-certifications/certifications/[certificationId]/bloc-competence/[certificationCompetenceBlocId]/updateCompetenceBloc.hook.ts @@ -0,0 +1,102 @@ +import { useGraphQlClient } from "@/components/graphql/graphql-client/GraphqlClient"; +import { graphql } from "@/graphql/generated"; +import { UpdateCompetenceBlocInput } from "@/graphql/generated/graphql"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; + +const getCompetenceBlocQuery = graphql(` + query getCompetenceBlocForCertificationRegistryManagerUpdateCompetenceBlocPage( + $certificationCompetenceBlocId: ID! + ) { + getCertificationCompetenceBloc( + certificationCompetenceBlocId: $certificationCompetenceBlocId + ) { + id + label + code + FCCompetences + competences { + id + label + } + certification { + id + label + codeRncp + } + } + } +`); + +const updateCertificationCompetenceBlocMutation = graphql(` + mutation updateCertificationCompetenceBlocForCertificationRegistryManagerUpdateCertificationCompetenceBlocPage( + $input: UpdateCompetenceBlocInput! + ) { + referential_updateCertificationCompetenceBloc(input: $input) { + id + } + } +`); + +const deleteCertificationCompetenceBlocMutation = graphql(` + mutation deleteCertificationCompetenceBlocForCertificationRegistryManagerUpdateCompetenceBlocPage( + $certificationCompetenceBlocId: String! + ) { + referential_deleteCertificationCompetenceBloc( + certificationCompetenceBlocId: $certificationCompetenceBlocId + ) { + id + } + } +`); + +export const useUpdateCompetenceBlocPage = ({ + certificationCompetenceBlocId, +}: { + certificationCompetenceBlocId: string; +}) => { + const { graphqlClient } = useGraphQlClient(); + const queryClient = useQueryClient(); + + const { + data: getCompetenceBlocResponse, + status: getCompetenceBlocQueryStatus, + } = useQuery({ + queryKey: [ + certificationCompetenceBlocId, + "competenceBlocs", + "getCompetenceBlocForUpdateCompetenceBlocPage", + ], + queryFn: () => + graphqlClient.request(getCompetenceBlocQuery, { + certificationCompetenceBlocId, + }), + }); + + const updateCertificationCompetenceBloc = useMutation({ + mutationFn: (input: UpdateCompetenceBlocInput) => + graphqlClient.request(updateCertificationCompetenceBlocMutation, { + input: { id: certificationCompetenceBlocId, ...input }, + }), + onSuccess: () => + queryClient.invalidateQueries({ + queryKey: [certificationCompetenceBlocId], + }), + }); + + const deleteCertificationCompetenceBloc = useMutation({ + mutationFn: () => + graphqlClient.request(deleteCertificationCompetenceBlocMutation, { + certificationCompetenceBlocId, + }), + }); + + const competenceBloc = + getCompetenceBlocResponse?.getCertificationCompetenceBloc; + + return { + competenceBloc, + getCompetenceBlocQueryStatus, + updateCertificationCompetenceBloc, + deleteCertificationCompetenceBloc, + }; +};