Skip to content

Commit a8b9134

Browse files
committed
feat(api+admin): removed ANNUAIRE_CERTIFICATIONS_V2 feature flag
1 parent e08740b commit a8b9134

File tree

18 files changed

+1266
-95
lines changed

18 files changed

+1266
-95
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
"use client";
2+
import { useParams, useRouter } from "next/navigation";
3+
import { useUpdateCompetenceBlocPage } from "./updateCompetenceBloc.hook";
4+
import { FormOptionalFieldsDisclaimer } from "@/components/form-optional-fields-disclaimer/FormOptionalFieldsDisclaimer";
5+
import { GrayCard } from "@/components/card/gray-card/GrayCard";
6+
import { Breadcrumb } from "@codegouvfr/react-dsfr/Breadcrumb";
7+
import {
8+
CompetenceBlocForm,
9+
CompetenceBlocFormData,
10+
} from "../../../../../../components/certifications/competence-bloc-form/CompetenceBlocForm";
11+
import { graphqlErrorToast, successToast } from "@/components/toast/toast";
12+
13+
type CertificationCompetenceBlocForPage = Exclude<
14+
ReturnType<typeof useUpdateCompetenceBlocPage>["competenceBloc"],
15+
undefined
16+
>;
17+
18+
export default function UpdateCompetenceBlocPage() {
19+
const { certificationId, certificationCompetenceBlocId } = useParams<{
20+
certificationId: string;
21+
certificationCompetenceBlocId: string;
22+
}>();
23+
24+
const router = useRouter();
25+
26+
const {
27+
competenceBloc,
28+
getCompetenceBlocQueryStatus,
29+
updateCertificationCompetenceBloc,
30+
deleteCertificationCompetenceBloc,
31+
} = useUpdateCompetenceBlocPage({ certificationCompetenceBlocId });
32+
33+
const handleFormSubmit = async (data: CompetenceBlocFormData) => {
34+
try {
35+
await updateCertificationCompetenceBloc.mutateAsync(data);
36+
successToast("modifications enregistrées");
37+
} catch (e) {
38+
graphqlErrorToast(e);
39+
}
40+
};
41+
42+
const handleCompetenceBlocDeleteButtonClick = async () => {
43+
try {
44+
await deleteCertificationCompetenceBloc.mutateAsync();
45+
successToast("modifications enregistrées");
46+
router.push(`/certifications/${certificationId}`);
47+
} catch (e) {
48+
graphqlErrorToast(e);
49+
}
50+
};
51+
return getCompetenceBlocQueryStatus === "success" && competenceBloc ? (
52+
<PageContent
53+
competenceBloc={competenceBloc}
54+
onSubmit={handleFormSubmit}
55+
onDeleteCompetenceBlocButtonClick={handleCompetenceBlocDeleteButtonClick}
56+
/>
57+
) : null;
58+
}
59+
60+
const PageContent = ({
61+
competenceBloc,
62+
onSubmit,
63+
onDeleteCompetenceBlocButtonClick,
64+
}: {
65+
competenceBloc: CertificationCompetenceBlocForPage;
66+
onSubmit(data: CompetenceBlocFormData): Promise<void>;
67+
onDeleteCompetenceBlocButtonClick?: () => void;
68+
}) => (
69+
<div data-test="update-certification-competence-bloc-page">
70+
<Breadcrumb
71+
currentPageLabel={`${competenceBloc.code} - ${competenceBloc.label}`}
72+
homeLinkProps={{
73+
href: `/`,
74+
}}
75+
segments={[
76+
{
77+
label: competenceBloc.certification.label,
78+
linkProps: {
79+
href: `/certifications/${competenceBloc.certification.id}`,
80+
},
81+
},
82+
]}
83+
/>
84+
85+
<h1>
86+
{competenceBloc.code} - {competenceBloc.label}
87+
</h1>
88+
<FormOptionalFieldsDisclaimer />
89+
<p className="mb-12 text-xl">
90+
Retrouvez toutes les informations récupérées à partir du code RNCP. Si
91+
vous souhaitez les modifier, il est préférable de contacter directement
92+
France compétences.
93+
</p>
94+
<GrayCard as="div" className="gap-6">
95+
<h2>
96+
Informations France compétences liées au code RNCP{" "}
97+
{competenceBloc.certification.codeRncp}
98+
</h2>
99+
<dl>
100+
<dd>Intitulé du bloc de compétences</dd>
101+
<dt className="font-medium">
102+
{competenceBloc.code} - {competenceBloc.label}
103+
</dt>
104+
</dl>
105+
<dl>
106+
<dd>Compétences</dd>
107+
<dt className="font-medium">{competenceBloc.FCCompetences}</dt>
108+
</dl>
109+
</GrayCard>
110+
<CompetenceBlocForm
111+
className="mt-6"
112+
backUrl={`/certifications/${competenceBloc.certification.id}`}
113+
defaultValues={{
114+
...competenceBloc,
115+
competences: competenceBloc.competences.map((c, i) => ({
116+
...c,
117+
index: i,
118+
})),
119+
}}
120+
onSubmit={onSubmit}
121+
onDeleteCompetenceBlocButtonClick={onDeleteCompetenceBlocButtonClick}
122+
/>
123+
</div>
124+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { useGraphQlClient } from "@/components/graphql/graphql-client/GraphqlClient";
2+
import { graphql } from "@/graphql/generated";
3+
import { UpdateCompetenceBlocInput } from "@/graphql/generated/graphql";
4+
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
5+
6+
const getCompetenceBlocQuery = graphql(`
7+
query getCompetenceBlocForUpdateCompetenceBlocPage(
8+
$certificationCompetenceBlocId: ID!
9+
) {
10+
getCertificationCompetenceBloc(
11+
certificationCompetenceBlocId: $certificationCompetenceBlocId
12+
) {
13+
id
14+
label
15+
code
16+
FCCompetences
17+
competences {
18+
id
19+
label
20+
}
21+
certification {
22+
id
23+
label
24+
codeRncp
25+
}
26+
}
27+
}
28+
`);
29+
30+
const updateCertificationCompetenceBlocMutation = graphql(`
31+
mutation updateCertificationCompetenceBlocForUpdateCertificationCompetenceBlocPage(
32+
$input: UpdateCompetenceBlocInput!
33+
) {
34+
referential_updateCertificationCompetenceBloc(input: $input) {
35+
id
36+
}
37+
}
38+
`);
39+
40+
const deleteCertificationCompetenceBlocMutation = graphql(`
41+
mutation deleteCertificationCompetenceBlocForUpdateCompetenceBlocPage(
42+
$certificationId: ID!
43+
$certificationCompetenceBlocId: ID!
44+
) {
45+
referential_deleteCertificationCompetenceBloc(
46+
certificationId: $certificationId
47+
certificationCompetenceBlocId: $certificationCompetenceBlocId
48+
) {
49+
id
50+
}
51+
}
52+
`);
53+
54+
export const useUpdateCompetenceBlocPage = ({
55+
certificationCompetenceBlocId,
56+
}: {
57+
certificationCompetenceBlocId: string;
58+
}) => {
59+
const { graphqlClient } = useGraphQlClient();
60+
const queryClient = useQueryClient();
61+
62+
const {
63+
data: getCompetenceBlocResponse,
64+
status: getCompetenceBlocQueryStatus,
65+
} = useQuery({
66+
queryKey: [
67+
certificationCompetenceBlocId,
68+
"competenceBlocs",
69+
"getCompetenceBlocForUpdateCompetenceBlocPage",
70+
],
71+
queryFn: () =>
72+
graphqlClient.request(getCompetenceBlocQuery, {
73+
certificationCompetenceBlocId,
74+
}),
75+
});
76+
77+
const updateCertificationCompetenceBloc = useMutation({
78+
mutationFn: (
79+
input: Omit<UpdateCompetenceBlocInput, "id" | "certificationId">,
80+
) =>
81+
graphqlClient.request(updateCertificationCompetenceBlocMutation, {
82+
input: {
83+
...input,
84+
certificationId: competenceBloc?.certification.id || "",
85+
id: certificationCompetenceBlocId,
86+
},
87+
}),
88+
onSuccess: () =>
89+
queryClient.invalidateQueries({
90+
queryKey: [certificationCompetenceBlocId],
91+
}),
92+
});
93+
94+
const deleteCertificationCompetenceBloc = useMutation({
95+
mutationFn: () =>
96+
graphqlClient.request(deleteCertificationCompetenceBlocMutation, {
97+
certificationId: competenceBloc?.certification.id || "",
98+
certificationCompetenceBlocId,
99+
}),
100+
});
101+
102+
const competenceBloc =
103+
getCompetenceBlocResponse?.getCertificationCompetenceBloc;
104+
105+
return {
106+
competenceBloc,
107+
getCompetenceBlocQueryStatus,
108+
updateCertificationCompetenceBloc,
109+
deleteCertificationCompetenceBloc,
110+
};
111+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { useGraphQlClient } from "@/components/graphql/graphql-client/GraphqlClient";
2+
import { graphql } from "@/graphql/generated";
3+
import { CreateCompetenceBlocInput } from "@/graphql/generated/graphql";
4+
import { useMutation, useQuery } from "@tanstack/react-query";
5+
6+
const getCertificationQuery = graphql(`
7+
query getCertificationForAddCompetenceBlocPage($certificationId: ID!) {
8+
getCertification(certificationId: $certificationId) {
9+
id
10+
label
11+
}
12+
}
13+
`);
14+
15+
const createCertificationCompetenceBlocMutation = graphql(`
16+
mutation createCertificationCompetenceBlocForAddCertificationCompetenceBlocPage(
17+
$input: CreateCompetenceBlocInput!
18+
) {
19+
referential_createCertificationCompetenceBloc(input: $input) {
20+
id
21+
}
22+
}
23+
`);
24+
25+
export const useAddCompetenceBlocPage = ({
26+
certificationId,
27+
}: {
28+
certificationId: string;
29+
}) => {
30+
const { graphqlClient } = useGraphQlClient();
31+
32+
const {
33+
data: getCertificationResponse,
34+
status: getCertificationQueryStatus,
35+
} = useQuery({
36+
queryKey: [
37+
certificationId,
38+
"competenceBlocs",
39+
"getCertificationForAddCompetenceBlocPage",
40+
],
41+
queryFn: () =>
42+
graphqlClient.request(getCertificationQuery, {
43+
certificationId,
44+
}),
45+
});
46+
47+
const createCertificationCompetenceBloc = useMutation({
48+
mutationFn: (input: Omit<CreateCompetenceBlocInput, "certificationId">) =>
49+
graphqlClient.request(createCertificationCompetenceBlocMutation, {
50+
input: { ...input, certificationId },
51+
}),
52+
});
53+
54+
const certification = getCertificationResponse?.getCertification;
55+
56+
return {
57+
certification,
58+
getCertificationQueryStatus,
59+
createCertificationCompetenceBloc,
60+
};
61+
};
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
"use client";
2+
import { useParams, useRouter } from "next/navigation";
3+
import { FormOptionalFieldsDisclaimer } from "@/components/form-optional-fields-disclaimer/FormOptionalFieldsDisclaimer";
4+
import { Breadcrumb } from "@codegouvfr/react-dsfr/Breadcrumb";
5+
import {
6+
CompetenceBlocForm,
7+
CompetenceBlocFormData,
8+
} from "../../../../../../components/certifications/competence-bloc-form/CompetenceBlocForm";
9+
import { graphqlErrorToast, successToast } from "@/components/toast/toast";
10+
import { useAddCompetenceBlocPage } from "./addCompetenceBloc.hook";
11+
12+
type CertificationForPage = Exclude<
13+
ReturnType<typeof useAddCompetenceBlocPage>["certification"],
14+
undefined
15+
>;
16+
17+
export default function AddCompetenceBlocPage() {
18+
const { certificationId } = useParams<{
19+
certificationId: string;
20+
}>();
21+
22+
const router = useRouter();
23+
24+
const {
25+
certification,
26+
getCertificationQueryStatus,
27+
createCertificationCompetenceBloc,
28+
} = useAddCompetenceBlocPage({ certificationId });
29+
30+
const handleFormSubmit = async (data: CompetenceBlocFormData) => {
31+
try {
32+
await createCertificationCompetenceBloc.mutateAsync(data);
33+
successToast("modifications enregistrées");
34+
router.push(`/certifications/${certificationId}`);
35+
} catch (e) {
36+
graphqlErrorToast(e);
37+
}
38+
};
39+
return getCertificationQueryStatus === "success" && certification ? (
40+
<PageContent certification={certification} onSubmit={handleFormSubmit} />
41+
) : null;
42+
}
43+
44+
const PageContent = ({
45+
certification,
46+
onSubmit,
47+
}: {
48+
onSubmit(data: CompetenceBlocFormData): Promise<void>;
49+
certification: CertificationForPage;
50+
}) => (
51+
<div data-test="add-certification-competence-bloc-page">
52+
<Breadcrumb
53+
currentPageLabel="Ajouter un bloc de compétences"
54+
homeLinkProps={{
55+
href: `/`,
56+
}}
57+
segments={[
58+
{
59+
label: certification.label,
60+
linkProps: {
61+
href: `/certifications/${certification.id}`,
62+
},
63+
},
64+
]}
65+
/>
66+
67+
<h1>Ajouter un bloc de compétences</h1>
68+
<FormOptionalFieldsDisclaimer />
69+
<p className="mb-12 text-xl">
70+
Si vous avez constaté une erreur dans la récupération des informations de
71+
France compétences, ajoutez le ou les bloc(s) manquant(s) ci-dessous.
72+
Cette démarche est réversible, vous pouvez supprimer le ou les bloc(s) si
73+
nécessaire.
74+
</p>
75+
<CompetenceBlocForm
76+
className="mt-6"
77+
backUrl={`/certifications/${certification.id}`}
78+
onSubmit={onSubmit}
79+
/>
80+
</div>
81+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Alert } from "@codegouvfr/react-dsfr/Alert";
2+
3+
export const NoCertificationAuthorityAlert = ({
4+
className,
5+
}: {
6+
className?: string;
7+
}) => (
8+
<Alert
9+
data-test="no-certification-authority-alert"
10+
className={className}
11+
severity="warning"
12+
title="Il n’y a pas de gestionnaire des candidatures pour cette certification"
13+
description="Malgré cela, elle sera visible des candidats et des AAP dès sa validation par le responsable des certifications. Lors du premier dossier de faisabilité envoyé, et s’il n’y a toujours pas de gestionnaire des candidatures, le support sera averti du problème."
14+
/>
15+
);

0 commit comments

Comments
 (0)