diff --git a/packages/code-du-travail-frontend/pages/outils/[slug].tsx b/packages/code-du-travail-frontend/pages/outils/[slug].tsx
index 3a2ee4a47e..7f54ab37b1 100644
--- a/packages/code-du-travail-frontend/pages/outils/[slug].tsx
+++ b/packages/code-du-travail-frontend/pages/outils/[slug].tsx
@@ -70,18 +70,20 @@ function Outils({
+
+
+
-
-
-
-
+ {router.asPath !== "/outils/indemnite-licenciement" && (
+
+ )}
@@ -149,5 +151,5 @@ export const ShareContainer = styled.div`
export const Flex = styled.div`
display: flex;
- flex-direction: column-reverse;
+ flex-direction: column;
`;
diff --git a/packages/code-du-travail-frontend/src/outils/IndemniteLicenciement/index.tsx b/packages/code-du-travail-frontend/src/outils/IndemniteLicenciement/index.tsx
index d38bb96d7d..c8848c761c 100644
--- a/packages/code-du-travail-frontend/src/outils/IndemniteLicenciement/index.tsx
+++ b/packages/code-du-travail-frontend/src/outils/IndemniteLicenciement/index.tsx
@@ -18,6 +18,7 @@ import {
} from "./store";
import { ToolName } from "../types";
import { PublicodesSimulator } from "@socialgouv/modeles-social";
+import { Feedback } from "../common/Feedback";
type Props = {
icon: string;
@@ -119,42 +120,45 @@ const IndemniteLicenciementSimulator = ({
};
return (
-
- simulator={PublicodesSimulator.INDEMNITE_LICENCIEMENT}
- title={title}
- displayTitle={displayTitle}
- icon={icon}
- duration="5 à 10 min"
- steps={steps}
- onStepChange={[
- {
- stepName: IndemniteLicenciementStepName.ContratTravail,
- isStepValid: isStepContratTravailValid,
- onNextStep: onNextStepContratTravail,
- },
- {
- stepName: IndemniteLicenciementStepName.Agreement,
- isStepValid: isStepAgreementValid,
- onNextStep: onNextStepAgreement,
- },
- {
- stepName: IndemniteLicenciementStepName.Anciennete,
- isStepValid: isStepAncienneteValid,
- onNextStep: onNextStepAnciennete,
- },
- {
- stepName: IndemniteLicenciementStepName.Salaires,
- isStepValid: isStepSalairesValid,
- onNextStep: onNextStepSalaires,
- },
- {
- stepName: IndemniteLicenciementStepName.Informations,
- isStepValid: isStepInformationsValid,
- onNextStep: onNextStepInformations,
- },
- ]}
- hiddenStep={getHiddenSteps()}
- />
+ <>
+
+ simulator={PublicodesSimulator.INDEMNITE_LICENCIEMENT}
+ title={title}
+ displayTitle={displayTitle}
+ icon={icon}
+ duration="5 à 10 min"
+ steps={steps}
+ onStepChange={[
+ {
+ stepName: IndemniteLicenciementStepName.ContratTravail,
+ isStepValid: isStepContratTravailValid,
+ onNextStep: onNextStepContratTravail,
+ },
+ {
+ stepName: IndemniteLicenciementStepName.Agreement,
+ isStepValid: isStepAgreementValid,
+ onNextStep: onNextStepAgreement,
+ },
+ {
+ stepName: IndemniteLicenciementStepName.Anciennete,
+ isStepValid: isStepAncienneteValid,
+ onNextStep: onNextStepAnciennete,
+ },
+ {
+ stepName: IndemniteLicenciementStepName.Salaires,
+ isStepValid: isStepSalairesValid,
+ onNextStep: onNextStepSalaires,
+ },
+ {
+ stepName: IndemniteLicenciementStepName.Informations,
+ isStepValid: isStepInformationsValid,
+ onNextStep: onNextStepInformations,
+ },
+ ]}
+ hiddenStep={getHiddenSteps()}
+ />
+
+ >
);
};
diff --git a/packages/code-du-travail-frontend/src/outils/common/Feedback/Questionnaire.tsx b/packages/code-du-travail-frontend/src/outils/common/Feedback/Questionnaire.tsx
new file mode 100644
index 0000000000..edbbc97545
--- /dev/null
+++ b/packages/code-du-travail-frontend/src/outils/common/Feedback/Questionnaire.tsx
@@ -0,0 +1,60 @@
+import styled from "styled-components";
+import { Button, Heading } from "@socialgouv/cdtn-ui";
+
+import { QuestionnaireItem, Status } from "./QuestionnaireItem";
+import { trackFeedback, EVENT_ACTION, FEEDBACK_RESULT } from "./tracking";
+import { useState } from "react";
+
+type QuestionnaireProps = {
+ onClick: () => void;
+};
+
+export const Questionnaire = ({ onClick }: QuestionnaireProps): JSX.Element => {
+ const [status, setStatus] = useState();
+ const [displayError, setDisplayError] = useState(false);
+ return (
+ <>
+
+ Comment s'est passée cette simulation pour vous ?
+
+ {
+ setStatus(status);
+ setDisplayError(false);
+ }}
+ displayError={displayError}
+ />
+ {
+ if (!status) {
+ setDisplayError(true);
+ } else {
+ trackFeedback(EVENT_ACTION.GLOBAL, status);
+ onClick();
+ }
+ }}
+ variant="primary"
+ >
+ Envoyer
+
+ >
+ );
+};
+
+const StyledHeading = styled(Heading)`
+ margin-left: 0;
+ margin-bottom: 0;
+ padding-top: 6px;
+`;
+
+const StyledButton = styled(Button)`
+ margin: 12px auto 24px 24px;
+`;
+
+const StyledQuestionnaireItem = styled(QuestionnaireItem)`
+ padding: 24px;
+`;
diff --git a/packages/code-du-travail-frontend/src/outils/common/Feedback/QuestionnaireAdvanced.tsx b/packages/code-du-travail-frontend/src/outils/common/Feedback/QuestionnaireAdvanced.tsx
new file mode 100644
index 0000000000..a1ec4a87b7
--- /dev/null
+++ b/packages/code-du-travail-frontend/src/outils/common/Feedback/QuestionnaireAdvanced.tsx
@@ -0,0 +1,115 @@
+import { Button, Heading } from "@socialgouv/cdtn-ui";
+import { QuestionnaireItem } from "./QuestionnaireItem";
+import { QuestionnaireText } from "./QuestionnaireText";
+import styled from "styled-components";
+import { useState } from "react";
+import {
+ trackFeedback,
+ trackFeedbackText,
+ FEEDBACK_RESULT,
+ EVENT_ACTION,
+} from "./tracking";
+import { useRouter } from "next/router";
+
+type QuestionnaireAdvancedProps = {
+ onClick: () => void;
+};
+
+export const QuestionnaireAdvanced = ({
+ onClick,
+}: QuestionnaireAdvancedProps): React.ReactElement => {
+ const router = useRouter();
+ const [statusSimulator, setStatusSimulator] = useState();
+ const [statusQuestion, setStatusQuestion] = useState();
+ const [statusExplanation, setStatusExplanation] = useState();
+ const [feedbackText, setFeedbackText] = useState();
+ return (
+ <>
+
+ Merci pour votre aide ! Pouvez-vous nous en dire plus ?
+
+
+ {
+ setStatusSimulator(status);
+ }}
+ dataTestId="simulator"
+ />
+ {
+ setStatusQuestion(status);
+ }}
+ dataTestId="questionClarity"
+ />
+ {
+ setStatusExplanation(status);
+ }}
+ dataTestId="resultClarity"
+ />
+
+
+ {
+ if (statusSimulator) {
+ trackFeedback(EVENT_ACTION.EASINESS, statusSimulator);
+ }
+ if (statusQuestion) {
+ trackFeedback(EVENT_ACTION.QUESTION_CLARITY, statusQuestion);
+ }
+ if (statusExplanation) {
+ trackFeedback(EVENT_ACTION.RESULT_CLARITY, statusExplanation);
+ }
+ if (feedbackText) {
+ trackFeedbackText(feedbackText, router.asPath);
+ }
+ onClick();
+ }}
+ >
+ Envoyer
+
+ >
+ );
+};
+
+const StyledHeading = styled(Heading)`
+ margin-left: 0;
+ margin-bottom: 0;
+ padding-top: 6px;
+`;
+
+const StyledButton = styled(Button)`
+ margin: 12px auto 24px 24px;
+`;
+
+const FormContainer = styled.div`
+ padding: 0 24px;
+`;
+
+const StyledQuestionnaireItem = styled(QuestionnaireItem)`
+ margin: 24px 0;
+`;
diff --git a/packages/code-du-travail-frontend/src/outils/common/Feedback/QuestionnaireEnd.tsx b/packages/code-du-travail-frontend/src/outils/common/Feedback/QuestionnaireEnd.tsx
new file mode 100644
index 0000000000..9155f6bc8a
--- /dev/null
+++ b/packages/code-du-travail-frontend/src/outils/common/Feedback/QuestionnaireEnd.tsx
@@ -0,0 +1,24 @@
+import { Heading } from "@socialgouv/cdtn-ui";
+import styled from "styled-components";
+
+export const QuestionnaireEnd = (): JSX.Element => {
+ return (
+ <>
+
+ Merci pour votre aide !
+
+
+ Votre évaluation sera étudiée au plus vite par nos équipes
+
+ >
+ );
+};
+
+const StyledHeading = styled(Heading)`
+ margin-left: 0;
+ padding-top: 6px;
+`;
+
+const StyledText = styled.span`
+ margin: 12px auto 24px 24px;
+`;
diff --git a/packages/code-du-travail-frontend/src/outils/common/Feedback/QuestionnaireItem.tsx b/packages/code-du-travail-frontend/src/outils/common/Feedback/QuestionnaireItem.tsx
new file mode 100644
index 0000000000..f02122f1d7
--- /dev/null
+++ b/packages/code-du-travail-frontend/src/outils/common/Feedback/QuestionnaireItem.tsx
@@ -0,0 +1,110 @@
+import { Button } from "@socialgouv/cdtn-ui";
+import { icons, theme } from "@socialgouv/cdtn-ui";
+import { useState } from "react";
+import styled from "styled-components";
+import { FEEDBACK_RESULT } from "./tracking";
+
+type QuestionnaireItemProps = {
+ badEventValue: FEEDBACK_RESULT;
+ averageEventValue: FEEDBACK_RESULT;
+ goodEventValue: FEEDBACK_RESULT;
+ badText?: string;
+ averageText?: string;
+ goodText?: string;
+ className?: string;
+ title?: string;
+ displayError?: boolean;
+ onChange: (status: FEEDBACK_RESULT) => void;
+ dataTestId?: string;
+};
+
+export enum Status {
+ BAD = "bad",
+ AVERAGE = "average",
+ GOOD = "good",
+}
+
+export const QuestionnaireItem = ({
+ badEventValue,
+ averageEventValue,
+ goodEventValue,
+ badText,
+ averageText,
+ goodText,
+ className,
+ title,
+ displayError,
+ onChange,
+ dataTestId,
+}: QuestionnaireItemProps): JSX.Element => {
+ const [status, setStatus] = useState();
+ return (
+
+ {title && {title}}
+
+ {
+ setStatus(Status.BAD);
+ onChange(badEventValue);
+ }}
+ data-testId={`${dataTestId}-bad`}
+ >
+
+ {badText ?? "Pas bien"}
+
+ {
+ setStatus(Status.AVERAGE);
+ onChange(averageEventValue);
+ }}
+ data-testId={`${dataTestId}-average`}
+ >
+
+ {averageText ?? "Moyen"}
+
+ {
+ setStatus(Status.GOOD);
+ onChange(goodEventValue);
+ }}
+ data-testId={`${dataTestId}-good`}
+ >
+
+ {goodText ?? "Très bien"}
+
+
+ {displayError && (
+ Vous devez choisir une des réponses
+ )}
+
+ );
+};
+
+const { colors } = theme;
+
+const ButtonContainer = styled.div`
+ display: flex;
+ flex-direction: row;
+ padding: 6px 0;
+ max-width: 300px;
+ justify-content: space-between;
+`;
+
+const StyledButton = styled(Button)`
+ display: flex;
+ flex-direction: column;
+ width: 80px;
+ height: 60px;
+ padding: 0;
+ border: 1px solid ${colors.secondary};
+ border-radius: 3px;
+ font-size: 12px;
+ font-weight: bold;
+`;
+
+const StyledError = styled.span`
+ color: ${colors.error};
+`;
diff --git a/packages/code-du-travail-frontend/src/outils/common/Feedback/QuestionnaireText.tsx b/packages/code-du-travail-frontend/src/outils/common/Feedback/QuestionnaireText.tsx
new file mode 100644
index 0000000000..b84e037bf7
--- /dev/null
+++ b/packages/code-du-travail-frontend/src/outils/common/Feedback/QuestionnaireText.tsx
@@ -0,0 +1,47 @@
+import { Textarea } from "@socialgouv/cdtn-ui";
+import styled from "styled-components";
+
+type QuestionnaireItemProps = {
+ className?: string;
+ title?: string;
+ placeholder?: string;
+ onChange: (text: string) => void;
+ dataTestId?: string;
+};
+
+export const QuestionnaireText = ({
+ className,
+ title,
+ placeholder,
+ onChange,
+ dataTestId,
+}: QuestionnaireItemProps): JSX.Element => {
+ const maxCharacters = 200;
+ return (
+
+ {title && {title}}
+ onChange(event.target.value)}
+ data-testid={dataTestId}
+ />
+ {maxCharacters} caractères maximum
+
+ );
+};
+
+const StyledContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+`;
+
+const StyledTextarea = styled(Textarea)`
+ width: 420px;
+ max-width: 100%;
+`;
+
+const MaxCharacterText = styled.span`
+ margin: 12px 0;
+ font-size: 14px;
+`;
diff --git a/packages/code-du-travail-frontend/src/outils/common/Feedback/__tests__/feedback.test.tsx b/packages/code-du-travail-frontend/src/outils/common/Feedback/__tests__/feedback.test.tsx
new file mode 100644
index 0000000000..115839e943
--- /dev/null
+++ b/packages/code-du-travail-frontend/src/outils/common/Feedback/__tests__/feedback.test.tsx
@@ -0,0 +1,134 @@
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Feedback } from "..";
+import { ui } from "./ui";
+import { push as matopush } from "@socialgouv/matomo-next";
+
+jest.mock("@socialgouv/matomo-next", () => {
+ return {
+ push: jest.fn(),
+ };
+});
+
+describe("Etant donné un composant Feedback", () => {
+ beforeEach(() => {
+ render();
+ });
+ test("Vérification que l'introduction s'affiche", () => {
+ expect(ui.introduction.title.query()).toBeInTheDocument();
+ expect(ui.introduction.button.query()).toBeInTheDocument();
+ });
+ describe("Lors d'un clique sur le bouton 'Fermer'", () => {
+ beforeEach(() => {
+ fireEvent.click(ui.closeButton.get());
+ });
+ test("Vérification que le composant ne s'affiche plus", () => {
+ expect(ui.introduction.title.query()).not.toBeInTheDocument();
+ expect(ui.introduction.button.query()).not.toBeInTheDocument();
+ });
+ });
+ describe("Lors d'un clique sur le bouton 'Donner mon avis'", () => {
+ beforeEach(() => {
+ fireEvent.click(ui.introduction.button.get());
+ });
+ test("Vérification que le 1er questionnaire s'affiche bien", () => {
+ expect(ui.questionnaire1.title.query()).toBeInTheDocument();
+ expect(ui.questionnaire1.bad.query()).toBeInTheDocument();
+ expect(ui.questionnaire1.average.query()).toBeInTheDocument();
+ expect(ui.questionnaire1.good.query()).toBeInTheDocument();
+ expect(ui.sendButton.query()).toBeInTheDocument();
+ });
+ describe("Lors d'un clic directement sur le bouton 'Envoyer'", () => {
+ beforeEach(() => {
+ fireEvent.click(ui.sendButton.get());
+ });
+ test("Vérification que le message d'erreur s'affiche bien", () => {
+ expect(ui.questionnaire1.requiredError.query()).toBeInTheDocument();
+ });
+ });
+ describe("Lors d'une sélection et clique sur le bouton 'Envoyer'", () => {
+ beforeEach(() => {
+ fireEvent.click(ui.questionnaire1.average.get());
+ fireEvent.click(ui.sendButton.get());
+ });
+ test("Vérification du tracking et que le 2e questionnaire s'affiche", () => {
+ expect(matopush).toHaveBeenCalledWith([
+ "trackEvent",
+ "feedback_simulateurs",
+ "Comment_s_est_passée_la_simulation",
+ "moyen",
+ ]);
+
+ expect(ui.questionnaire2.simulator.title.query()).toBeInTheDocument();
+ expect(ui.questionnaire2.simulator.bad.query()).toBeInTheDocument();
+ expect(ui.questionnaire2.simulator.average.query()).toBeInTheDocument();
+ expect(ui.questionnaire2.simulator.good.query()).toBeInTheDocument();
+
+ expect(
+ ui.questionnaire2.questionClarity.title.query()
+ ).toBeInTheDocument();
+ expect(
+ ui.questionnaire2.questionClarity.bad.query()
+ ).toBeInTheDocument();
+ expect(
+ ui.questionnaire2.questionClarity.average.query()
+ ).toBeInTheDocument();
+ expect(
+ ui.questionnaire2.questionClarity.good.query()
+ ).toBeInTheDocument();
+
+ expect(
+ ui.questionnaire2.resultClarity.title.query()
+ ).toBeInTheDocument();
+ expect(ui.questionnaire2.resultClarity.bad.query()).toBeInTheDocument();
+ expect(
+ ui.questionnaire2.resultClarity.average.query()
+ ).toBeInTheDocument();
+ expect(
+ ui.questionnaire2.resultClarity.good.query()
+ ).toBeInTheDocument();
+
+ expect(ui.questionnaire2.more.title.query()).toBeInTheDocument();
+ expect(ui.questionnaire2.more.input.query()).toBeInTheDocument();
+ });
+ describe("Lors d'une sélection et clique sur le bouton 'Envoyer'", () => {
+ beforeEach(() => {
+ fireEvent.click(ui.questionnaire2.simulator.bad.get());
+ fireEvent.click(ui.questionnaire2.questionClarity.average.get());
+ fireEvent.click(ui.questionnaire2.resultClarity.good.get());
+ fireEvent.change(ui.questionnaire2.more.input.get(), {
+ target: { value: "test" },
+ });
+ fireEvent.click(ui.sendButton.get());
+ });
+ test("Vérification du tracking et que la fin du questionnaire s'affiche", () => {
+ expect(matopush).toHaveBeenCalledWith([
+ "trackEvent",
+ "feedback_simulateurs",
+ "Facilité_utilisation_simulateur",
+ "pas_du_tout",
+ ]);
+ expect(matopush).toHaveBeenCalledWith([
+ "trackEvent",
+ "feedback_simulateurs",
+ "Clarté_questions",
+ "moyen",
+ ]);
+ expect(matopush).toHaveBeenCalledWith([
+ "trackEvent",
+ "feedback_simulateurs",
+ "Clarté_résultat",
+ "oui",
+ ]);
+ expect(matopush).toHaveBeenCalledWith([
+ "trackEvent",
+ "feedback_suggestion",
+ "test",
+ "mock",
+ ]);
+ expect(ui.questionnaireEnd.title.query()).toBeInTheDocument();
+ expect(ui.questionnaireEnd.description.query()).toBeInTheDocument();
+ });
+ });
+ });
+ });
+});
diff --git a/packages/code-du-travail-frontend/src/outils/common/Feedback/__tests__/ui.ts b/packages/code-du-travail-frontend/src/outils/common/Feedback/__tests__/ui.ts
new file mode 100644
index 0000000000..3ca0dd5542
--- /dev/null
+++ b/packages/code-du-travail-frontend/src/outils/common/Feedback/__tests__/ui.ts
@@ -0,0 +1,53 @@
+import { byTestId, byText } from "testing-library-selector";
+
+export const ui = {
+ closeButton: byTestId("feedbackCloseButton"),
+ sendButton: byText("Envoyer"),
+ introduction: {
+ title: byText("Votre avis sur ce simulateur nous intéresse"),
+ button: byText("Donner mon avis"),
+ },
+ questionnaire1: {
+ title: byText(/Comment s'est passée cette simulation pour vous \?/),
+ bad: byText("Pas bien"),
+ average: byText("Moyen"),
+ good: byText("Très bien"),
+ requiredError: byText("Vous devez choisir une des réponses"),
+ },
+ questionnaire2: {
+ title: byText(/Merci pour votre aide ! Pouvez-vous nous en dire plus \?/),
+ simulator: {
+ title: byText(/Le simulateur était-il facile à utiliser \?/),
+ bad: byTestId("simulator-bad"),
+ average: byTestId("simulator-average"),
+ good: byTestId("simulator-good"),
+ },
+ questionClarity: {
+ title: byText(
+ /Les questions étaient-elles claires et compréhensibles \?/
+ ),
+ bad: byTestId("questionClarity-bad"),
+ average: byTestId("questionClarity-average"),
+ good: byTestId("questionClarity-good"),
+ },
+ resultClarity: {
+ title: byText(
+ /Les explications du résultat obtenu étaient-elles claires et compréhensibles \?/
+ ),
+ bad: byTestId("resultClarity-bad"),
+ average: byTestId("resultClarity-average"),
+ good: byTestId("resultClarity-good"),
+ },
+ more: {
+ title: byText(/Vous souhaitez nous en dire davantage \?/),
+ input: byTestId("more-input"),
+ },
+ requiredError: byText("Vous devez choisir une des réponses"),
+ },
+ questionnaireEnd: {
+ title: byText(/Merci pour votre aide !/),
+ description: byText(
+ /Votre évaluation sera étudiée au plus vite par nos équipes/
+ ),
+ },
+};
diff --git a/packages/code-du-travail-frontend/src/outils/common/Feedback/index.tsx b/packages/code-du-travail-frontend/src/outils/common/Feedback/index.tsx
new file mode 100644
index 0000000000..41757ce632
--- /dev/null
+++ b/packages/code-du-travail-frontend/src/outils/common/Feedback/index.tsx
@@ -0,0 +1,99 @@
+import styled from "styled-components";
+import { theme, icons, Wrapper } from "@socialgouv/cdtn-ui";
+import { Introduction } from "./introduction";
+import { useState } from "react";
+import { Questionnaire } from "./Questionnaire";
+import { QuestionnaireAdvanced } from "./QuestionnaireAdvanced";
+import { QuestionnaireEnd } from "./QuestionnaireEnd";
+
+export const Feedback = (): JSX.Element => {
+ const [status, setStatus] = useState<
+ "questionnaire" | "questionnaireAdvanced" | "questionnaireEnd"
+ >();
+ const [closed, setClosed] = useState(false);
+ const [position, setPosition] = useState(0);
+ const [bodyPosition, setBodyPosition] = useState(0);
+ return !closed ? (
+ <>
+ {!status && (
+ {
+ setStatus("questionnaire");
+ }}
+ variant="main"
+ >
+ setClosed(true)}
+ data-testid="feedbackCloseButton"
+ />
+ {
+ setStatus("questionnaire");
+ }}
+ />
+
+ )}
+ {status && (
+ {
+ if (!el) return;
+
+ setPosition(el.getBoundingClientRect().top);
+ setBodyPosition(document.body.getBoundingClientRect().top);
+ }}
+ >
+ setClosed(true)}
+ data-testid="feedbackCloseButton"
+ />
+ {status === "questionnaire" && (
+ {
+ setStatus("questionnaireAdvanced");
+ }}
+ />
+ )}
+ {status === "questionnaireAdvanced" && (
+ {
+ setStatus("questionnaireEnd");
+ window.scrollTo(0, position - bodyPosition - 220);
+ }}
+ />
+ )}
+ {status === "questionnaireEnd" && }
+
+ )}
+ >
+ ) : (
+ <>>
+ );
+};
+
+const { colors } = theme;
+
+const IntroContainer = styled(Wrapper)`
+ border: 1px solid ${colors.secondary};
+ border-radius: 6px;
+ width: 460px;
+ max-width: 100%;
+ display: flex;
+ flex-direction: column;
+ margin: 42px 0 0 auto;
+ padding: 0 0 28px 0 !important;
+ position: relative;
+`;
+
+const StyledContainer = styled(IntroContainer)`
+ width: 520px;
+`;
+
+const StyledCloseIcon = styled(icons.Close)`
+ position: absolute;
+ top: 8px;
+ right: 8px;
+ width: 24px;
+ cursor: pointer;
+ margin: 3px;
+`;
diff --git a/packages/code-du-travail-frontend/src/outils/common/Feedback/introduction.tsx b/packages/code-du-travail-frontend/src/outils/common/Feedback/introduction.tsx
new file mode 100644
index 0000000000..ab2e441e68
--- /dev/null
+++ b/packages/code-du-travail-frontend/src/outils/common/Feedback/introduction.tsx
@@ -0,0 +1,26 @@
+import styled from "styled-components";
+import { Button, Heading } from "@socialgouv/cdtn-ui";
+
+type IntroductionProps = {
+ onClick: () => void;
+};
+
+export const Introduction = ({ onClick }: IntroductionProps): JSX.Element => {
+ return (
+ <>
+
+ Votre avis sur ce simulateur nous intéresse
+
+ Donner mon avis
+ >
+ );
+};
+
+const StyledHeading = styled(Heading)`
+ text-align: center;
+ margin-top: 16px;
+`;
+
+const StyledButton = styled(Button)`
+ margin: 0 auto;
+`;
diff --git a/packages/code-du-travail-frontend/src/outils/common/Feedback/tracking.ts b/packages/code-du-travail-frontend/src/outils/common/Feedback/tracking.ts
new file mode 100644
index 0000000000..896077e56b
--- /dev/null
+++ b/packages/code-du-travail-frontend/src/outils/common/Feedback/tracking.ts
@@ -0,0 +1,36 @@
+import { MatomoBaseEvent } from "../../../lib/matomo";
+import { push as matopush } from "@socialgouv/matomo-next";
+
+const EVENT_CATEGORY = "feedback_simulateurs";
+export enum EVENT_ACTION {
+ GLOBAL = "Comment_s_est_passée_la_simulation",
+ EASINESS = "Facilité_utilisation_simulateur",
+ QUESTION_CLARITY = "Clarté_questions",
+ RESULT_CLARITY = "Clarté_résultat",
+ SUGGESTION = "Suggestion",
+}
+
+export enum FEEDBACK_RESULT {
+ NOT_GOOD = "pas_bien",
+ NOT_AT_ALL = "pas_du_tout",
+ AVERAGE = "moyen",
+ GOOD = "très_bien",
+ EASY = "facile",
+ YES = "oui",
+}
+
+export const trackFeedback = (
+ event: EVENT_ACTION,
+ feedback: FEEDBACK_RESULT
+) => {
+ matopush([MatomoBaseEvent.TRACK_EVENT, EVENT_CATEGORY, event, feedback]);
+};
+
+export const trackFeedbackText = (text: string, url: string) => {
+ matopush([
+ "trackEvent",
+ "feedback_suggestion",
+ text,
+ url.replace(/\?.*$/, ""),
+ ]);
+};
diff --git a/packages/react-ui/src/Button/index.js b/packages/react-ui/src/Button/index.js
index ff049218b0..6680b7ebe8 100644
--- a/packages/react-ui/src/Button/index.js
+++ b/packages/react-ui/src/Button/index.js
@@ -84,6 +84,27 @@ export const StyledButton = styled.button`
}
`;
}
+ if (variant === "light") {
+ return css`
+ padding: 0;
+ color: ${theme.paragraph};
+ font-weight: normal;
+ font-size: ${fonts.sizes.default};
+ line-height: ${fonts.lineHeight};
+ vertical-align: baseline;
+ text-decoration: none;
+ text-align: left;
+ background-color: rgba(
+ ${theme.secondary},
+ 0.26
+ )};
+ border: none;
+ border-radius: 0;
+ overflow: visible;
+ transition: color ${animations.transitionTiming} linear,
+ text-decoration ${animations.transitionTiming} linear;
+ `;
+ }
let height = "5.2rem";
let backgroundColor = theme[variant];
@@ -128,7 +149,7 @@ export const StyledButton = styled.button`
opacity = "0.6";
}
- if (variant === "primary") {
+ if (variant === "primary" || variant === "light") {
boxShadow = `${largeShadow} ${rgba(
theme.primary,
0.26
@@ -212,6 +233,7 @@ Button.propTypes = {
"naked",
"primary",
"secondary",
+ "light",
]),
};
diff --git a/packages/react-ui/src/Titles/Heading/index.tsx b/packages/react-ui/src/Titles/Heading/index.tsx
index dc8eebfc94..bac1a7d924 100644
--- a/packages/react-ui/src/Titles/Heading/index.tsx
+++ b/packages/react-ui/src/Titles/Heading/index.tsx
@@ -16,6 +16,7 @@ type Props = {
ariaLevel?: number | string;
id?: string;
dataTestid?: string;
+ className?: string;
};
export const Heading = (props: Props) => (
@@ -29,6 +30,7 @@ export const Heading = (props: Props) => (
aria-level={props.ariaLevel}
id={props.id}
data-testid={props.dataTestid ?? "heading"}
+ className={props.className}
>
{props.stripe !== "none" && (
(
+
+);
+
+const Memo = memo(SvgArrowTurn);
+export default Memo;
diff --git a/packages/react-ui/src/icons/components/monochrome/Good.js b/packages/react-ui/src/icons/components/monochrome/Good.js
new file mode 100644
index 0000000000..faf8c88329
--- /dev/null
+++ b/packages/react-ui/src/icons/components/monochrome/Good.js
@@ -0,0 +1,47 @@
+import * as React from "react";
+import { memo } from "react";
+
+const SvgArrowTurn = (props) => (
+
+);
+
+const Memo = memo(SvgArrowTurn);
+export default Memo;
diff --git a/packages/react-ui/src/icons/components/monochrome/Medium.js b/packages/react-ui/src/icons/components/monochrome/Medium.js
new file mode 100644
index 0000000000..ff9eddecf0
--- /dev/null
+++ b/packages/react-ui/src/icons/components/monochrome/Medium.js
@@ -0,0 +1,47 @@
+import * as React from "react";
+import { memo } from "react";
+
+const SvgArrowTurn = (props) => (
+
+);
+
+const Memo = memo(SvgArrowTurn);
+export default Memo;
diff --git a/packages/react-ui/src/icons/components/monochrome/index.js b/packages/react-ui/src/icons/components/monochrome/index.js
index cd9b75b35f..93a9d24933 100644
--- a/packages/react-ui/src/icons/components/monochrome/index.js
+++ b/packages/react-ui/src/icons/components/monochrome/index.js
@@ -1,6 +1,7 @@
export { default as ArrowDown } from "./ArrowDown";
export { default as ArrowRight } from "./ArrowRight";
export { default as ArrowTurn } from "./ArrowTurn";
+export { default as Bad } from "./Bad";
export { default as Burger } from "./Burger";
export { default as Calendar } from "./Calendar";
export { default as Check } from "./Check";
@@ -11,10 +12,12 @@ export { default as DirectionRight } from "./DirectionRight";
export { default as Download } from "./Download";
export { default as Euro } from "./Euro";
export { default as External } from "./External";
+export { default as Good } from "./Good";
export { default as Help } from "./Help";
export { default as Home } from "./Home";
export { default as Link } from "./Link";
export { default as Mail } from "./Mail";
+export { default as Medium } from "./Medium";
export { default as More } from "./More";
export { default as Search } from "./Search";
export { default as Shade } from "./Shade";
diff --git a/packages/react-ui/src/icons/index.js b/packages/react-ui/src/icons/index.js
index e83a1cbb67..d703e170d7 100644
--- a/packages/react-ui/src/icons/index.js
+++ b/packages/react-ui/src/icons/index.js
@@ -49,6 +49,7 @@ export { default as Youth } from "./components/bicolor/Youth.js";
export { default as ArrowDown } from "./components/monochrome/ArrowDown";
export { default as ArrowRight } from "./components/monochrome/ArrowRight";
export { default as ArrowTurn } from "./components/monochrome/ArrowTurn";
+export { default as Bad } from "./components/monochrome/Bad";
export { default as Burger } from "./components/monochrome/Burger";
export { default as Calendar } from "./components/monochrome/Calendar";
export { default as External } from "./components/monochrome/Calendar";
@@ -59,10 +60,12 @@ export { default as DirectionLeft } from "./components/monochrome/DirectionLeft"
export { default as DirectionRight } from "./components/monochrome/DirectionRight";
export { default as Download } from "./components/monochrome/Download";
export { default as Euro } from "./components/monochrome/Euro";
+export { default as Good } from "./components/monochrome/Good";
export { default as Help } from "./components/monochrome/Help";
export { default as Home } from "./components/monochrome/Home";
export { default as Link } from "./components/monochrome/Link";
export { default as Mail } from "./components/monochrome/Mail";
+export { default as Medium } from "./components/monochrome/Medium";
export { default as More } from "./components/monochrome/More";
export { default as Search } from "./components/monochrome/Search";
export { default as Shade } from "./components/monochrome/Shade";
diff --git a/packages/react-ui/src/icons/src/monochrome/bad.svg b/packages/react-ui/src/icons/src/monochrome/bad.svg
new file mode 100644
index 0000000000..976f92cf24
--- /dev/null
+++ b/packages/react-ui/src/icons/src/monochrome/bad.svg
@@ -0,0 +1,13 @@
+
+
+
diff --git a/packages/react-ui/src/icons/src/monochrome/good.svg b/packages/react-ui/src/icons/src/monochrome/good.svg
new file mode 100644
index 0000000000..fd6425218c
--- /dev/null
+++ b/packages/react-ui/src/icons/src/monochrome/good.svg
@@ -0,0 +1,12 @@
+
+
diff --git a/packages/react-ui/src/icons/src/monochrome/medium.svg b/packages/react-ui/src/icons/src/monochrome/medium.svg
new file mode 100644
index 0000000000..12761dee33
--- /dev/null
+++ b/packages/react-ui/src/icons/src/monochrome/medium.svg
@@ -0,0 +1,12 @@
+
+