diff --git a/packages/code-du-travail-frontend/app/outils/simulateur-embauche/page.tsx b/packages/code-du-travail-frontend/app/outils/simulateur-embauche/page.tsx new file mode 100644 index 0000000000..2984d26565 --- /dev/null +++ b/packages/code-du-travail-frontend/app/outils/simulateur-embauche/page.tsx @@ -0,0 +1,45 @@ +import { DsfrLayout } from "../../../src/modules/layout"; +import { fetchRelatedItems } from "../../../src/modules/documents"; +import { fetchTool } from "../../../src/modules/outils"; +import { notFound } from "next/navigation"; +import { generateDefaultMetadata } from "../../../src/modules/common/metas"; +import HiringSimulator from "../../../src/modules/outils/simulateur-embauche/HiringSimulator"; + +export async function generateMetadata() { + const { metaTitle, metaDescription } = await getTool(); + + return generateDefaultMetadata({ + title: metaTitle, + description: metaDescription, + path: `/outils/simulateur-embauche`, + }); +} + +async function HiringSimulatorPage() { + const tool = await getTool(); + const relatedItems = await fetchRelatedItems( + { _id: tool._id }, + "simulateur-embauche" + ); + return ( + + + + ); +} + +const getTool = async () => { + const tool = await fetchTool("simulateur-embauche"); + + if (!tool) { + return notFound(); + } + return tool; +}; + +export default HiringSimulatorPage; diff --git a/packages/code-du-travail-frontend/cypress/integration/light/outils/brut-net.spec.ts b/packages/code-du-travail-frontend/cypress/integration/light/outils/brut-net.spec.ts index ee482c9a54..6f9a81e4d6 100644 --- a/packages/code-du-travail-frontend/cypress/integration/light/outils/brut-net.spec.ts +++ b/packages/code-du-travail-frontend/cypress/integration/light/outils/brut-net.spec.ts @@ -3,7 +3,11 @@ import "cypress-iframe"; describe("Outil - Salaire brut/net", () => { it("Valider que le simulateur s'affiche correctement dans l'iframe", () => { cy.visit("/outils/simulateur-embauche"); - cy.get("h1").should("have.text", "Calculer le salaire brut/net"); + cy.findByRole("heading", { level: 1 }).should( + "have.text", + "Calculer le salaire brut/net" + ); + cy.findByRole("heading", { level: 1 }).click(); cy.iframe("#simulateurEmbauche") .contains("Coût total employeur") .should("be.visible"); diff --git a/packages/code-du-travail-frontend/pages/outils/[slug].tsx b/packages/code-du-travail-frontend/pages/outils/[slug].tsx index bc41f877aa..18e9ed2fd9 100644 --- a/packages/code-du-travail-frontend/pages/outils/[slug].tsx +++ b/packages/code-du-travail-frontend/pages/outils/[slug].tsx @@ -19,7 +19,6 @@ import { DureePreavisDemission, DureePreavisLicenciement, HeuresRechercheEmploi, - SimulateurEmbauche, SimulateurIndemnitePrecarite, CalculateurPreavisRetraite, } from "../../src/outils"; @@ -38,7 +37,6 @@ const toolsBySlug = { "preavis-demission": DureePreavisDemission, "preavis-licenciement": DureePreavisLicenciement, "preavis-retraite": CalculateurPreavisRetraite, - "simulateur-embauche": SimulateurEmbauche, "procedure-licenciement": DismissalProcess, "indemnite-rupture-conventionnelle": CalculateurRuptureConventionnelle, }; diff --git a/packages/code-du-travail-frontend/src/common/tiles/CallToAction.tsx b/packages/code-du-travail-frontend/src/common/tiles/CallToAction.tsx index 821fa43648..5fcb922de9 100644 --- a/packages/code-du-travail-frontend/src/common/tiles/CallToAction.tsx +++ b/packages/code-du-travail-frontend/src/common/tiles/CallToAction.tsx @@ -82,7 +82,7 @@ const StyledDiv = styled.div` height: 1.4rem; margin: 0 ${spacings.tiny} 0 ${spacings.small}; transition: transform ${theme.animations.transitionTiming} linear; - fill: ${theme.primary}; + fill: ${theme.colors.primary}; } } `; diff --git a/packages/code-du-travail-frontend/src/common/tiles/__tests__/__snapshots__/Custom.test.js.snap b/packages/code-du-travail-frontend/src/common/tiles/__tests__/__snapshots__/Custom.test.js.snap index 57d582f2e9..f6c0296898 100644 --- a/packages/code-du-travail-frontend/src/common/tiles/__tests__/__snapshots__/Custom.test.js.snap +++ b/packages/code-du-travail-frontend/src/common/tiles/__tests__/__snapshots__/Custom.test.js.snap @@ -3,7 +3,7 @@ exports[` should render 1`] = `
should render 1`] = ` class="sc-d47d8018-6 ipSAXR" >

Cette tuile vous fera dire bonjour !

( fields: K[] @@ -53,3 +55,27 @@ export const fetchAllTools = async ( .map(({ _source }) => _source) .filter((source) => source !== undefined); }; + +export const fetchTool = async ( + slug: string +): Promise> => { + const result = await fetchDocument< + ElasticTool, + keyof DocumentElasticResult + >(["description", "metaDescription", "metaTitle", "title", "displayTitle"], { + query: { + bool: { + filter: [ + { term: { source: SOURCES.TOOLS } }, + { term: { slug } }, + { term: { isPublished: true } }, + ], + }, + }, + size: 1, + }); + if (!result) { + throw new Error("Outils non trouvé"); + } + return result; +}; diff --git a/packages/code-du-travail-frontend/src/modules/outils/simulateur-embauche/HiringSimulator.tsx b/packages/code-du-travail-frontend/src/modules/outils/simulateur-embauche/HiringSimulator.tsx new file mode 100644 index 0000000000..938d534221 --- /dev/null +++ b/packages/code-du-travail-frontend/src/modules/outils/simulateur-embauche/HiringSimulator.tsx @@ -0,0 +1,102 @@ +"use client"; +import { Highlight } from "@codegouvfr/react-dsfr/Highlight"; +import { fr } from "@codegouvfr/react-dsfr"; +import { createRef, memo, useEffect, useState } from "react"; +import { ContainerSimulator } from "../../layout/ContainerSimulator"; +import { RelatedItem } from "../../documents"; +import * as Sentry from "@sentry/nextjs"; + +type Props = { + relatedItems: { + items: RelatedItem[]; + title: string; + }[]; + title: string; + breadcrumbTitle: string; + description: string; +}; + +const HiringSimulator = memo(function HiringSimulator({ + relatedItems, + description, + title, + breadcrumbTitle, +}: Props) { + const simRef = createRef(); + const [state, setState] = useState({ + error: "", + simulator: "loading", + }); + const onError = (error) => { + console.log(`Erreur durant le chargement de l'iframe brut/net ${error}`); + setState({ error, simulator: "error" }); + Sentry.captureMessage(`Erreur durant le chargement de l'iframe brut/net`); + }; + + const onLoad = () => { + setState({ simulator: "success", error: "" }); + if (!simRef.current?.querySelector("#simulateurEmbauche")) { + console.log( + `Erreur durant le chargement de l'iframe brut/net, "empty child"` + ); + setState({ error: "empty child", simulator: "error" }); + Sentry.captureMessage( + `Erreur durant le chargement de l'iframe brut/net "empty child"` + ); + } + }; + useEffect(() => { + const script = document.createElement("script"); + + script.src = + "https://mon-entreprise.urssaf.fr/simulateur-iframe-integration.js"; + script.id = "script-simulateur-embauche"; + script.onload = onLoad; + script.onerror = onError; + + if (simRef.current) { + simRef.current.appendChild(script); + } + + return () => { + if (simRef.current) { + simRef.current.removeChild(script); + } + }; + }, []); + const { simulator } = state; + return ( + +

{title}

+ + Pour information, l'estimation du salaire net après impôt est basée + sur la situation d'une personne célibataire sans enfants ni + patrimoine. + + {simulator === "loading" &&

Chargement de l’outil

} + {simulator === "error" ? ( +

+ Le simulateur d’embauche n’est pas disponible actuellement. +
+ Retrouvez les autres simulateurs autour du thème de l’entreprise, sur + le site:{" "} + + https://mon-entreprise.urssaf.fr/ + +

+ ) : ( +
+ )} + + ); +}); + +export default HiringSimulator; diff --git a/packages/code-du-travail-frontend/src/modules/outils/simulateur-embauche/index.ts b/packages/code-du-travail-frontend/src/modules/outils/simulateur-embauche/index.ts new file mode 100644 index 0000000000..910a3e0db4 --- /dev/null +++ b/packages/code-du-travail-frontend/src/modules/outils/simulateur-embauche/index.ts @@ -0,0 +1 @@ +export * from "./HiringSimulator"; diff --git a/packages/code-du-travail-frontend/src/modules/outils/type.ts b/packages/code-du-travail-frontend/src/modules/outils/type.ts new file mode 100644 index 0000000000..99e771ea59 --- /dev/null +++ b/packages/code-du-travail-frontend/src/modules/outils/type.ts @@ -0,0 +1,3 @@ +import { DocumentElasticWithSource, Tool } from "@socialgouv/cdtn-types"; + +export type ElasticTool = DocumentElasticWithSource; diff --git a/packages/code-du-travail-frontend/src/outils/SimulateurEmbauche.js b/packages/code-du-travail-frontend/src/outils/SimulateurEmbauche.js deleted file mode 100644 index 0593abebd4..0000000000 --- a/packages/code-du-travail-frontend/src/outils/SimulateurEmbauche.js +++ /dev/null @@ -1,80 +0,0 @@ -import { Alert, PageTitle, Section, Wrapper } from "@socialgouv/cdtn-ui"; -import React from "react"; -import Spinner from "react-svg-spinner"; - -class SimulateurEmbauche extends React.PureComponent { - simRef = React.createRef(); - state = { - simulator: "loading", - }; - - onError = (error) => { - this.setState({ error, simulator: "error" }); - }; - - onLoad = () => { - this.setState({ simulator: "success" }); - if ( - !this.simRef.current || - !this.simRef.current.querySelector("#simulateurEmbauche") - ) { - this.setState({ error: "empty child", simulator: "error" }); - } - }; - - componentDidMount() { - const script = document.createElement("script"); - script.src = - "https://mon-entreprise.urssaf.fr/simulateur-iframe-integration.js"; - script.async = true; - script.dataset.couleur = "#2975D1"; - script.id = "script-simulateur-embauche"; - script.onload = this.onLoad; - script.onerror = this.onError; - - if (this.simRef.current) { - this.simRef.current.appendChild(script); - } - } - - render() { - const { simulator } = this.state; - return ( - - Calculer le salaire brut/net - -

- Pour information, l’estimation du salaire net après impôt est basée - sur la situation d’une personne célibataire sans enfants ni - patrimoine. -

-
- {simulator === "loading" && ( -

- Chargement de l’outil -

- )} - {simulator === "error" ? ( -

- Le simulateur d’embauche n’est pas disponible actuellement. -
- Retrouvez les autres simulateurs autour du thème de l’entreprise, - sur le site:{" "} - - https://mon-entreprise.urssaf.fr/ - -

- ) : ( -
-
-
- )} -
- ); - } -} - -export { SimulateurEmbauche }; diff --git a/packages/code-du-travail-frontend/src/outils/index.ts b/packages/code-du-travail-frontend/src/outils/index.ts index 8acb7da47c..82a0f5a8b9 100644 --- a/packages/code-du-travail-frontend/src/outils/index.ts +++ b/packages/code-du-travail-frontend/src/outils/index.ts @@ -5,7 +5,6 @@ export * from "./DureePreavisLicenciement"; export * from "./IndemniteLicenciement"; export * from "./HeuresRechercheEmploi"; export * from "./IndemnitePrecarite"; -export * from "./SimulateurEmbauche"; export * from "./DismissalProcess"; export * from "./RuptureCoventionnelle"; export * from "./api"; diff --git a/packages/code-du-travail-frontend/src/search/__tests__/__snapshots__/SearchResults.test.js.snap b/packages/code-du-travail-frontend/src/search/__tests__/__snapshots__/SearchResults.test.js.snap index 256fa55067..3d0716f7dc 100644 --- a/packages/code-du-travail-frontend/src/search/__tests__/__snapshots__/SearchResults.test.js.snap +++ b/packages/code-du-travail-frontend/src/search/__tests__/__snapshots__/SearchResults.test.js.snap @@ -65,7 +65,7 @@ exports[` should render results 1`] = ` class="sc-546484b7-0 fIRXSF" >
should render results 1`] = ` class="sc-d47d8018-6 ipSAXR" >
should render results 1`] = `

should render results 1`] = ` >

should render results 1`] = ` class="sc-d47d8018-6 ipSAXR" >
should render results 1`] = `

should render results 1`] = ` class="sc-546484b7-0 fIRXSF" >

should render results 1`] = ` class="sc-d47d8018-6 ipSAXR" >
should render results 1`] = `