From a98b16ac4cf6b7999fae42e0e8343af145ae5220 Mon Sep 17 00:00:00 2001 From: clement-duport Date: Thu, 8 Jun 2023 13:50:40 +0200 Subject: [PATCH] modify contact by mail modal add inputs and modify mail request v1 dto and schema --- .../input/ContactEstablishmentPublicV1.dto.ts | 13 +- .../ContactEstablishmentPublicV1.schema.ts | 39 ++++- .../contactEstablishment.e2e.test.ts | 2 + .../ContactEstablishment.unit.test.ts | 2 + ...onAggregateFromContactRequest.unit.test.ts | 4 + .../NotifyContactRequest.unit.test.ts | 2 + .../app/components/search/ContactByEmail.tsx | 147 ++++++++++++++---- .../components/search/ContactModalContent.tsx | 16 +- .../components/search/SearchListResults.tsx | 7 +- .../src/app/pages/group/GroupListResults.tsx | 1 + .../contactEstablishmentRequest.dto.ts | 3 + .../contactEstablishmentRequest.schema.ts | 3 + shared/src/domElementIds.ts | 2 + 13 files changed, 202 insertions(+), 39 deletions(-) diff --git a/back/src/adapters/primary/routers/DtoAndSchemas/v1/input/ContactEstablishmentPublicV1.dto.ts b/back/src/adapters/primary/routers/DtoAndSchemas/v1/input/ContactEstablishmentPublicV1.dto.ts index d3eeabd239..a20dc81ec9 100644 --- a/back/src/adapters/primary/routers/DtoAndSchemas/v1/input/ContactEstablishmentPublicV1.dto.ts +++ b/back/src/adapters/primary/routers/DtoAndSchemas/v1/input/ContactEstablishmentPublicV1.dto.ts @@ -14,7 +14,7 @@ type ContactInformationPublicV1 = { contactMode: T; }; -type ContactEstablishmentByMailPublicV1Dto = +export type ContactEstablishmentByMailPublicV1Dto = ContactInformationPublicV1<"EMAIL"> & { message: string; }; @@ -30,4 +30,13 @@ export type ContactEstablishmentPublicV1Dto = export const contactEstablishmentPublicV1ToDomain = ( contactRequest: ContactEstablishmentPublicV1Dto, -): ContactEstablishmentRequestDto => contactRequest; +): ContactEstablishmentRequestDto => { + if (contactRequest.contactMode === "EMAIL") + return { + ...contactRequest, + potentialBeneficiaryPhone: "Numéro de téléphone Non communiqué", + immersionObjective: "Object non communiqué", + }; + + return contactRequest; +}; diff --git a/back/src/adapters/primary/routers/DtoAndSchemas/v1/input/ContactEstablishmentPublicV1.schema.ts b/back/src/adapters/primary/routers/DtoAndSchemas/v1/input/ContactEstablishmentPublicV1.schema.ts index 986d6b4906..b94eef73fc 100644 --- a/back/src/adapters/primary/routers/DtoAndSchemas/v1/input/ContactEstablishmentPublicV1.schema.ts +++ b/back/src/adapters/primary/routers/DtoAndSchemas/v1/input/ContactEstablishmentPublicV1.schema.ts @@ -1,6 +1,39 @@ import { z } from "zod"; -import { contactEstablishmentRequestSchema } from "shared"; -import { ContactEstablishmentPublicV1Dto } from "./ContactEstablishmentPublicV1.dto"; +import { + contactEstablishmentByPhoneSchema, + contactEstablishmentInPersonSchema, + emailSchema, + preferEmailContactSchema, + romeSchema, + siretSchema, + zTrimmedString, +} from "shared"; +import { + ContactEstablishmentByMailPublicV1Dto, + ContactEstablishmentPublicV1Dto, +} from "./ContactEstablishmentPublicV1.dto"; + +const commonFields = { + offer: romeSchema, + siret: siretSchema, + potentialBeneficiaryFirstName: zTrimmedString, + potentialBeneficiaryLastName: zTrimmedString, + potentialBeneficiaryEmail: emailSchema, +}; + +const contactEstablishmentByMailSchemaV1: z.Schema = + z.object({ + ...commonFields, + contactMode: preferEmailContactSchema, + message: zTrimmedString, + }); + +const contactEstablishmentRequestSchemaV1: z.Schema = + z.union([ + contactEstablishmentByMailSchemaV1, + contactEstablishmentByPhoneSchema, + contactEstablishmentInPersonSchema, + ]); export const contactEstablishmentPublicV1Schema: z.Schema = - contactEstablishmentRequestSchema; + contactEstablishmentRequestSchemaV1; diff --git a/back/src/adapters/primary/routers/createEstablishment/contactEstablishment.e2e.test.ts b/back/src/adapters/primary/routers/createEstablishment/contactEstablishment.e2e.test.ts index ee95d41b79..7b15b8e2a8 100644 --- a/back/src/adapters/primary/routers/createEstablishment/contactEstablishment.e2e.test.ts +++ b/back/src/adapters/primary/routers/createEstablishment/contactEstablishment.e2e.test.ts @@ -27,6 +27,8 @@ const validRequest: ContactEstablishmentRequestDto = { potentialBeneficiaryLastName: "potential_beneficiary_last_name", potentialBeneficiaryEmail: "potential_beneficiary@email.fr", message: "message_to_send", + immersionObjective: "Confirmer un projet professionnel", + potentialBeneficiaryPhone: "0654783402", }; describe(`/${contactEstablishmentRoute} route`, () => { diff --git a/back/src/domain/immersionOffer/useCases/ContactEstablishment.unit.test.ts b/back/src/domain/immersionOffer/useCases/ContactEstablishment.unit.test.ts index b7cf80f7dc..0dc601f1b0 100644 --- a/back/src/domain/immersionOffer/useCases/ContactEstablishment.unit.test.ts +++ b/back/src/domain/immersionOffer/useCases/ContactEstablishment.unit.test.ts @@ -87,6 +87,8 @@ describe("ContactEstablishment", () => { ...validRequest, contactMode: "EMAIL", message: "message_to_send", + immersionObjective: "Confirmer un projet professionnel", + potentialBeneficiaryPhone: "0654783402", }; await contactEstablishment.execute(validEmailRequest); diff --git a/back/src/domain/immersionOffer/useCases/InsertDiscussionAggregateFromContactRequest.unit.test.ts b/back/src/domain/immersionOffer/useCases/InsertDiscussionAggregateFromContactRequest.unit.test.ts index faec3ad465..258b3fa801 100644 --- a/back/src/domain/immersionOffer/useCases/InsertDiscussionAggregateFromContactRequest.unit.test.ts +++ b/back/src/domain/immersionOffer/useCases/InsertDiscussionAggregateFromContactRequest.unit.test.ts @@ -59,6 +59,8 @@ describe("Insert discussion aggregate from contact request DTO", () => { potentialBeneficiaryEmail: "antoine.tourasse@email.com", contactMode: "EMAIL", message: "Bonjour, j'aimerais venir jouer chez vous. Je suis sympa.", + immersionObjective: "Confirmer un projet professionnel", + potentialBeneficiaryPhone: "0654783402", }; await insertDiscussionAggregate.execute(contactRequestDto); @@ -141,6 +143,8 @@ describe("Insert discussion aggregate from contact request DTO", () => { potentialBeneficiaryEmail: "bob.marley@email.com", contactMode: "EMAIL", message: "Bonjour, j'aimerais venir jouer chez vous. Je suis sympa.", + immersionObjective: "Confirmer un projet professionnel", + potentialBeneficiaryPhone: "0654783402", }; await insertDiscussionAggregate.execute(secondContactRequestDto); diff --git a/back/src/domain/immersionOffer/useCases/notifications/NotifyContactRequest.unit.test.ts b/back/src/domain/immersionOffer/useCases/notifications/NotifyContactRequest.unit.test.ts index 18bc4763cf..17a97b8193 100644 --- a/back/src/domain/immersionOffer/useCases/notifications/NotifyContactRequest.unit.test.ts +++ b/back/src/domain/immersionOffer/useCases/notifications/NotifyContactRequest.unit.test.ts @@ -68,6 +68,8 @@ describe("NotifyContactRequest", () => { ...payload, contactMode: "EMAIL", message: "message_to_send", + immersionObjective: "Confirmer un projet professionnel", + potentialBeneficiaryPhone: "0654783402", }; const establishment = new EstablishmentEntityBuilder() .withSiret(siret) diff --git a/front/src/app/components/search/ContactByEmail.tsx b/front/src/app/components/search/ContactByEmail.tsx index f2e43f9ed1..0597b3ea96 100644 --- a/front/src/app/components/search/ContactByEmail.tsx +++ b/front/src/app/components/search/ContactByEmail.tsx @@ -1,13 +1,16 @@ import React from "react"; import { FormProvider, useForm } from "react-hook-form"; import { fr } from "@codegouvfr/react-dsfr"; -import { Button } from "@codegouvfr/react-dsfr/Button"; +import Alert from "@codegouvfr/react-dsfr/Alert"; +import { ButtonsGroup } from "@codegouvfr/react-dsfr/ButtonsGroup"; import { Input } from "@codegouvfr/react-dsfr/Input"; +import Select from "@codegouvfr/react-dsfr/SelectNext"; import { zodResolver } from "@hookform/resolvers/zod"; import { ContactEstablishmentByMailDto, contactEstablishmentByMailSchema, domElementIds, + ImmersionObjective, RomeDto, SiretDto, } from "shared"; @@ -19,22 +22,23 @@ type ContactByEmailProps = { siret: SiretDto; offer: RomeDto; onSuccess: () => void; + onClose: () => void; }; -const initialMessage = - "Bonjour, \n\n\ -J’ai trouvé votre entreprise sur 'Immersion Facilitée.'\n\ -Je souhaiterais passer quelques jours dans votre entreprise en immersion professionnelle auprès de vos salariés pour découvrir ce métier.\n\ +const initialMessage = `Bonjour, \n\n\ +J’ai trouvé votre entreprise sur le site https://immersion-facile.beta.gouv.fr\n\ +***Rédigez ici votre email de motivation en suivant nos conseils.***\n\ \n\ -Pourriez-vous me contacter par mail pour me proposer un rendez-vous ? \n\ +Pourriez-vous me contacter par mail ou par téléphone pour me proposer un rendez-vous ? \n\ Je pourrais alors vous expliquer directement mon projet. \n\ \n\ -En vous remerciant,"; +En vous remerciant,`; export const ContactByEmail = ({ siret, offer, onSuccess, + onClose, }: ContactByEmailProps) => { const initialValues: ContactEstablishmentByMailDto = { siret, @@ -44,6 +48,9 @@ export const ContactByEmail = ({ potentialBeneficiaryLastName: "", potentialBeneficiaryEmail: "", message: initialMessage, + immersionObjective: "", + potentialBeneficiaryLinkedinOrCv: "", + potentialBeneficiaryPhone: "", }; const methods = useForm({ @@ -68,50 +75,128 @@ export const ContactByEmail = ({
<> -

+

Cette entreprise a choisi d'être contactée par mail. Veuillez compléter ce formulaire qui sera transmis à l'entreprise.

- + + Besoin d’aide ? {""} + + Nos conseils pour choisir l’objet et rédiger un bon email de + motivation. + + + } + className={fr.cx("fr-mt-1w")} + /> + +

+ Votre email de motivation +

+ + +

Vos informations

+ + + - + /> + +
); }; + +const immersionObjective: ImmersionObjective[] = [ + "Confirmer un projet professionnel", + "Découvrir un métier ou un secteur d'activité", + "Initier une démarche de recrutement", +]; + +export const immersionObjectiveListOfOptions = immersionObjective.map( + (immersionObjective) => ({ + value: immersionObjective, + label: immersionObjective, + }), +); diff --git a/front/src/app/components/search/ContactModalContent.tsx b/front/src/app/components/search/ContactModalContent.tsx index 760e0c0164..1060cb9944 100644 --- a/front/src/app/components/search/ContactModalContent.tsx +++ b/front/src/app/components/search/ContactModalContent.tsx @@ -15,6 +15,7 @@ export type ContactModalContentProps = { offer: RomeDto; searchResultData?: SearchImmersionResultDto; onSuccess: () => void; + onClose: () => void; }; export const ModalContactContent = ({ @@ -23,11 +24,17 @@ export const ModalContactContent = ({ offer, onSuccess, searchResultData, + onClose, }: ContactModalContentProps) => { switch (contactMethod) { case "EMAIL": return ( - + ); case "PHONE": return ( @@ -35,7 +42,12 @@ export const ModalContactContent = ({ ); case "IN_PERSON": return ( - + ); default: return ; diff --git a/front/src/app/components/search/SearchListResults.tsx b/front/src/app/components/search/SearchListResults.tsx index f01e0f2b55..af681927e2 100644 --- a/front/src/app/components/search/SearchListResults.tsx +++ b/front/src/app/components/search/SearchListResults.tsx @@ -106,6 +106,7 @@ export const SearchListResults = () => { }, contactMethod: searchResult.contactMode, searchResultData: searchResult, + onClose: () => closeContactModal(), }); openContactModal(); }} @@ -164,9 +165,10 @@ export const SearchListResults = () => { {modalContent && ( { setSuccessfullyValidated(true); closeContactModal(); }} + onClose={() => { + closeContactModal(); + }} /> )} diff --git a/front/src/app/pages/group/GroupListResults.tsx b/front/src/app/pages/group/GroupListResults.tsx index 63015f3e03..5cb07be2b0 100644 --- a/front/src/app/pages/group/GroupListResults.tsx +++ b/front/src/app/pages/group/GroupListResults.tsx @@ -77,6 +77,7 @@ export const GroupListResults = ({ results }: GroupListResultsProps) => { }, contactMethod: searchResult.contactMode, searchResultData: searchResult, + onClose: () => closeContactModal(), }); openContactModal(); }} diff --git a/shared/src/contactEstablishmentRequest/contactEstablishmentRequest.dto.ts b/shared/src/contactEstablishmentRequest/contactEstablishmentRequest.dto.ts index 716c895b97..d11fc6f05f 100644 --- a/shared/src/contactEstablishmentRequest/contactEstablishmentRequest.dto.ts +++ b/shared/src/contactEstablishmentRequest/contactEstablishmentRequest.dto.ts @@ -13,6 +13,9 @@ export type ContactInformations = { export type ContactEstablishmentByMailDto = ContactInformations<"EMAIL"> & { message: string; + potentialBeneficiaryPhone: string; + immersionObjective: string; + potentialBeneficiaryLinkedinOrCv?: string; }; export type ContactEstablishmentInPersonDto = ContactInformations<"IN_PERSON">; diff --git a/shared/src/contactEstablishmentRequest/contactEstablishmentRequest.schema.ts b/shared/src/contactEstablishmentRequest/contactEstablishmentRequest.schema.ts index 3dd9f04097..6390ec5aaf 100644 --- a/shared/src/contactEstablishmentRequest/contactEstablishmentRequest.schema.ts +++ b/shared/src/contactEstablishmentRequest/contactEstablishmentRequest.schema.ts @@ -27,6 +27,9 @@ export const contactEstablishmentByMailSchema: z.Schema = diff --git a/shared/src/domElementIds.ts b/shared/src/domElementIds.ts index 982d2fe2de..d8871c6800 100644 --- a/shared/src/domElementIds.ts +++ b/shared/src/domElementIds.ts @@ -100,6 +100,8 @@ export const domElementIds = { searchSubmitButton: "im-search__submit-search", searchSortOptionBase: "search-sort-option-", contactByMailButton: "im-contact-establishment__contact-email-button", + contactByMailCloseButton: + "im-contact-establishment__contact-email-close-button", contactByPhoneButton: "im-contact-establishment__contact-phone-button", contactInPersonButton: "im-contact-establishment__contact-in-person-button", },