(
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`] = `