Skip to content

Commit 10abd21

Browse files
authored
feat(infographics): ajout des infographies sur le front (#6911)
* feat(infographics): ajout des infographies sur le front * feat(infographics): ajout de la page infographie * feat(infographics): ajout des références sur la page infographie * feat: ajout des documents liés * feat: ajout de la pages des infographies * fix: review feedbacks * fix: review feedbacks * fix: test e2e * fix: back
1 parent 26ced5f commit 10abd21

File tree

44 files changed

+2783
-323
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2783
-323
lines changed
Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
1-
import { DsfrLayout } from "../../src/modules/layout";
1+
import { DsfrLayout, ListLayout } from "../../src/modules/layout";
22
import { generateDefaultMetadata } from "../../src/modules/common/metas";
3-
import { ContributionsList } from "../../src/modules/contributions";
4-
import { getGenericContributionsGroupByThemes } from "../../src/api";
3+
import { fetchContributions } from "../../src/modules/contributions";
4+
import { groupByThemes } from "../../src/modules/utils";
5+
import { SOURCES } from "@socialgouv/cdtn-utils";
6+
import { Metadata } from "next";
57

6-
export const metadata = generateDefaultMetadata({
8+
export const metadata: Metadata = generateDefaultMetadata({
79
title: "Fiches pratiques",
810
description:
911
"Obtenez une réponse personnalisée selon votre convention collective",
1012
path: "/contribution",
1113
});
1214

1315
async function Index() {
14-
const { documents } = await getContributions();
16+
const documents = await getContributions();
1517

1618
return (
1719
<DsfrLayout>
18-
<ContributionsList
19-
contributions={documents}
20-
popularContributionSlugs={[
20+
<ListLayout
21+
title="Fiches pratiques"
22+
description="Obtenez une réponse personnalisée selon votre convention collective"
23+
source={SOURCES.CONTRIBUTIONS}
24+
data={documents}
25+
popularSlugs={[
2126
"en-cas-darret-maladie-du-salarie-lemployeur-doit-il-assurer-le-maintien-de-salaire",
2227
"les-conges-pour-evenements-familiaux",
2328
"a-quelles-indemnites-peut-pretendre-un-salarie-qui-part-a-la-retraite",
@@ -31,8 +36,11 @@ async function Index() {
3136
}
3237

3338
const getContributions = async () => {
34-
const data = await getGenericContributionsGroupByThemes();
35-
return data;
39+
const data = await fetchContributions(
40+
["title", "source", "description", "slug", "breadcrumbs"],
41+
{ generic: true }
42+
);
43+
return groupByThemes(data);
3644
};
3745

3846
export default Index;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { notFound } from "next/navigation";
2+
import { DsfrLayout } from "src/modules/layout";
3+
4+
import { generateDefaultMetadata } from "src/modules/common/metas";
5+
import { getRouteBySource, SOURCES } from "@socialgouv/cdtn-utils";
6+
import {
7+
fetchInfographic,
8+
format,
9+
Infographic,
10+
Infographie,
11+
} from "src/modules/infographie";
12+
import { Metadata } from "next";
13+
14+
export async function generateMetadata(
15+
props: PageProps<"/infographie/[slug]">
16+
): Promise<Metadata> {
17+
const params = await props.params;
18+
const information = await fetchInfographic(params.slug, [
19+
"title",
20+
"metaDescription",
21+
]);
22+
23+
if (!information) {
24+
return notFound();
25+
}
26+
27+
return generateDefaultMetadata({
28+
title: information?.title,
29+
description: information?.metaDescription,
30+
path: `/${getRouteBySource(SOURCES.INFOGRAPHICS)}/${params.slug}`,
31+
});
32+
}
33+
34+
async function InfographiePage(props: PageProps<"/infographie/[slug]">) {
35+
const params = await props.params;
36+
const infographic = await getInfographic(params.slug);
37+
38+
if (!infographic) {
39+
return notFound();
40+
}
41+
42+
return (
43+
<DsfrLayout>
44+
<Infographie infographic={infographic} />
45+
</DsfrLayout>
46+
);
47+
}
48+
49+
const getInfographic = async (slug: string): Promise<Infographic> => {
50+
const infographic = await fetchInfographic(slug, [
51+
"title",
52+
"meta_title",
53+
"date",
54+
"description",
55+
"meta_description",
56+
"svgFilename",
57+
"pdfFilename",
58+
"pdfFilesizeOctet",
59+
"transcription",
60+
"breadcrumbs",
61+
"references",
62+
"linkedContent",
63+
]);
64+
65+
if (!infographic) {
66+
return notFound();
67+
}
68+
return format(infographic);
69+
};
70+
71+
export default InfographiePage;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { DsfrLayout, ListLayout } from "../../src/modules/layout";
2+
import { generateDefaultMetadata } from "../../src/modules/common/metas";
3+
import { fetchInfographics } from "../../src/modules/infographie";
4+
import { groupByThemes } from "../../src/modules/utils";
5+
import { SOURCES } from "@socialgouv/cdtn-utils";
6+
import { Metadata } from "next";
7+
8+
export const metadata: Metadata = generateDefaultMetadata({
9+
title: "Infographies",
10+
description:
11+
"Découvrez toutes nos infographies : des visuels clairs pour comprendre vos droits, obligations et démarches en un coup d'oeil.",
12+
path: "/infographie",
13+
});
14+
15+
async function Index() {
16+
const documents = await getInfographics();
17+
18+
return (
19+
<DsfrLayout>
20+
<ListLayout
21+
title="Infographies"
22+
description="Découvrez toutes nos infographies : des visuels clairs pour comprendre vos droits, obligations et démarches en un coup d'oeil."
23+
source={SOURCES.INFOGRAPHICS}
24+
data={documents}
25+
popularSlugs={[
26+
"licenciement-pour-inaptitude-medicale",
27+
"rupture-conventionnelle-les-etapes-de-la-procedure-et-les-delais",
28+
"report-des-conges-en-cas-de-maladie-de-courte-duree-moins-de-1-an",
29+
"que-se-passe-t-il-en-cas-dabandon-de-poste",
30+
"partage-de-la-valeur-nouvelles-regles-pour-les-entreprises-de-11-a-49-salaries",
31+
"refus-des-propositions-de-cdi-quelles-consequences",
32+
]}
33+
/>
34+
</DsfrLayout>
35+
);
36+
}
37+
38+
const getInfographics = async () => {
39+
const data = await fetchInfographics([
40+
"title",
41+
"source",
42+
"meta_description",
43+
"slug",
44+
"breadcrumbs",
45+
]);
46+
return groupByThemes(
47+
data.map((item) => ({
48+
...item,
49+
description: item.meta_description,
50+
}))
51+
);
52+
};
53+
54+
export default Index;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
describe("Pages infographies", () => {
2+
it("je vois la liste de toutes les infographies par thèmes", () => {
3+
cy.visit("/");
4+
cy.findByRole("heading", { level: 1 })
5+
.should("have.text", "Bienvenue sur le Code du travail numérique")
6+
.click();
7+
cy.get("#fr-header-main-navigation").contains("Code du travail").click();
8+
cy.get("#fr-header-main-navigation").contains("Nos infographies").click();
9+
cy.isIndexable();
10+
cy.urlEqual("/infographie");
11+
cy.canonicalUrlEqual("/infographie");
12+
cy.titleAndMetaDescriptionEqual(
13+
"Infographies - Code du travail numérique",
14+
"Découvrez toutes nos infographies : des visuels clairs pour comprendre vos droits, obligations et démarches en un coup d'oeil."
15+
);
16+
cy.get("h1").should("have.text", "Infographies");
17+
cy.get("body").should(
18+
"contain",
19+
"Découvrez toutes nos infographies : des visuels clairs pour comprendre vos droits, obligations et démarches en un coup d'oeil."
20+
);
21+
cy.findAllByRole("heading", { level: 2 }).should("have.length", 8);
22+
cy.findAllByRole("heading", { level: 2 }).eq(0).should("contain", "Résumé");
23+
cy.findAllByRole("heading", { level: 2 })
24+
.eq(1)
25+
.should("contain", "Contenus populaires");
26+
cy.findAllByRole("heading", { level: 2 })
27+
.eq(2)
28+
.should("contain", "Embauche et contrat de travail");
29+
cy.findAllByRole("heading", { level: 3 }).should("have.length.at.least", 1);
30+
cy.findAllByRole("heading", { level: 3 }).first().click();
31+
cy.urlEqual("/infographie/licenciement-pour-inaptitude-medicale");
32+
});
33+
34+
it("je vois une page infographie classique", () => {
35+
cy.visit("/infographie/que-se-passe-t-il-en-cas-dabandon-de-poste");
36+
cy.isIndexable();
37+
cy.canonicalUrlEqual(
38+
"/infographie/que-se-passe-t-il-en-cas-dabandon-de-poste"
39+
);
40+
41+
cy.titleAndMetaDescriptionEqual(
42+
"Que se passe-t-il en cas d'abandon de poste ? - Code du travail numérique",
43+
"Cette infographie détaille la marche à suivre pour l’employeur en cas d’abandon de poste d’un salarié. Elle précise les effets possibles sur le contrat de travail selon que le salarié justifie son absence, reprenne son poste dans le délai imparti ou ne le fasse pas."
44+
);
45+
cy.findByRole("heading", { level: 1 }).should(
46+
"have.text",
47+
"Que se passe-t-il en cas d'abandon de poste ?"
48+
);
49+
cy.get("body").should(
50+
"contain",
51+
"Cette infographie détaille la marche à suivre pour l’employeur en cas d’abandon de poste d’un salarié."
52+
);
53+
});
54+
});

packages/code-du-travail-frontend/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"@opentelemetry/instrumentation-net": "^0.47.0",
4242
"@sentry/nextjs": "10.9.0",
4343
"@socialgouv/cdtn-elasticsearch": "^2.44.2",
44-
"@socialgouv/cdtn-types": "^2.57.0",
44+
"@socialgouv/cdtn-types": "^2.61.0",
4545
"@socialgouv/cdtn-utils": "workspace:^",
4646
"@socialgouv/matomo-next": "1.10.0",
4747
"@socialgouv/modeles-social": "workspace:^",
@@ -54,7 +54,7 @@
5454
"katex": "^0.16.21",
5555
"lodash.deburr": "^4.1.0",
5656
"memoizee": "^0.4.15",
57-
"next": "16.0.1",
57+
"next": "16.0.3",
5858
"publicodes": "1.0.0-beta.60",
5959
"react": "19.2.0",
6060
"react-dom": "19.2.0",
Lines changed: 56 additions & 0 deletions
Loading

packages/code-du-travail-frontend/src/api/modules/contributions/__tests__/__snapshots__/service.es.test.ts.snap

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -55,61 +55,3 @@ exports[`Contributions getByIdsContributions 1`] = `
5555
},
5656
]
5757
`;
58-
59-
exports[`Contributions getGenericContributions 1`] = `
60-
{
61-
"documents": {
62-
"Congés et repos": [
63-
{
64-
"breadcrumbs": [
65-
{
66-
"label": "Congés et repos",
67-
"position": 3,
68-
"slug": "/themes/conges-et-repos",
69-
},
70-
{
71-
"label": "Congés",
72-
"position": 1,
73-
"slug": "/themes/conges",
74-
},
75-
{
76-
"label": "Congés pour événement familial",
77-
"position": 3,
78-
"slug": "/themes/conges-pour-evenement-familial",
79-
},
80-
],
81-
"description": "Le code du travail prévoit que le salarié bénéficie de congés à l’occasion de certains événements familiaux. Ils n’entrainent aucune diminution de la rémunération…",
82-
"slug": "les-conges-pour-evenements-familiaux",
83-
"source": "contributions",
84-
"theme": "Congés et repos",
85-
"title": "Les congés pour événements familiaux",
86-
},
87-
],
88-
"Départ de l’entreprise": [
89-
{
90-
"breadcrumbs": [
91-
{
92-
"label": "Départ de l’entreprise",
93-
"position": 7,
94-
"slug": "/themes/depart-de-lentreprise",
95-
},
96-
{
97-
"label": "Autres départs",
98-
"position": 6,
99-
"slug": "/themes/autres-departs",
100-
},
101-
],
102-
"description": "Le décès de l’employeur a des conséquences différentes sur le contrat de travail, selon que l’employeur est une entreprise individuelle ou un employeur…",
103-
"slug": "quand-le-salarie-a-t-il-droit-a-une-prime-danciennete-quel-est-son-montant",
104-
"source": "contributions",
105-
"theme": "Départ de l’entreprise",
106-
"title": "Quand le salarié a-t-il droit à une prime d’ancienneté ? Quel est son montant ?",
107-
},
108-
],
109-
},
110-
"themes": [
111-
"Congés et repos",
112-
"Départ de l’entreprise",
113-
],
114-
}
115-
`;

packages/code-du-travail-frontend/src/api/modules/contributions/__tests__/service.es.test.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,10 @@
33
import {
44
getAllContributionsGroupByQuestion,
55
getByIdsContributions,
6-
getGenericContributionsGroupByThemes,
76
} from "../service";
87
import { getAllAgreements } from "../../agreements";
98

109
describe("Contributions", () => {
11-
it("getGenericContributions", async () => {
12-
const result = await getGenericContributionsGroupByThemes();
13-
expect(result).toHaveProperty("themes");
14-
expect(result).toHaveProperty("documents");
15-
expect(result).toMatchSnapshot();
16-
});
17-
1810
it("getByIdsContributions", async () => {
1911
const result = await getByIdsContributions(["eba7a4592f"]);
2012
expect(result).toMatchSnapshot();

0 commit comments

Comments
 (0)