diff --git a/site/source/components/conversation/EntrepriseInput.tsx b/site/source/components/conversation/EntrepriseInput.tsx new file mode 100644 index 000000000..bb6e47a74 --- /dev/null +++ b/site/source/components/conversation/EntrepriseInput.tsx @@ -0,0 +1,78 @@ +import { useEffect } from 'react' +import { useDispatch } from 'react-redux' + +import { EntrepriseSearchField } from '@/components/entreprise/EntrepriseSearchField' +import { useEngine } from '@/components/utils/EngineContext' +import { Spacing } from '@/design-system/layout' +import { Entreprise } from '@/domaine/Entreprise' +import { useEntreprisesRepository } from '@/hooks/useRepositories' +import { useSetEntreprise } from '@/hooks/useSetEntreprise' +import { getCookieValue } from '@/storage/readCookie' +import { resetCompany } from '@/store/actions/companyActions' + +import SelectedEntrepriseDetails from '../entreprise/SelectedEntrepriseDetails' + +export default function EntrepriseInput() { + const companySIREN = useEngine().evaluate('entreprise . SIREN').nodeValue + useSetEntrepriseFromUrssafConnection() + const setEntreprise = useSetEntreprise() + const dispatch = useDispatch() + const handleCompanySubmit = (établissement: Entreprise | null) => { + setEntreprise(établissement) + } + const handleCompanyClear = () => { + dispatch(resetCompany()) + } + + return ( + <> + : null} + /> + + + ) +} + +function useSetEntrepriseFromUrssafConnection() { + const setEntreprise = useSetEntreprise() + const siret = siretFromUrssafFrConnection() + const companySIREN = useEngine().evaluate('entreprise . SIREN').nodeValue + const entreprisesRepository = useEntreprisesRepository() + + useEffect(() => { + if (siret && !companySIREN) { + entreprisesRepository + .rechercheTexteLibre(siret) + .then((results) => { + if (results?.length !== 1) { + return + } + setEntreprise(results[0]) + }) + .catch((err) => { + console.log(err) + console.log(`Could not fetch company details for ${siret}`) + }) + } + }, [siret, companySIREN]) +} + +// We can read cookies set on the urssaf.fr domain, which contain informations +// such as the SIRET number. The cookie format could change at any time so we +// wrap its read access in a `try / catch`. +function siretFromUrssafFrConnection(): string | null { + try { + // Note: The `ctxUrssaf` contains more informations, but currently we only + // need to retreive the SIRET which is slightly more easy to read from the + // `EnLigne` cookie. + const cookieValue = decodeURIComponent(getCookieValue('EnLigne')) + const siret = cookieValue.match('siret=([0-9]{14})')?.pop() + + return siret ?? null + } catch { + return null + } +} diff --git a/site/source/components/company/Details.tsx b/site/source/components/entreprise/EntrepriseDetails.tsx similarity index 98% rename from site/source/components/company/Details.tsx rename to site/source/components/entreprise/EntrepriseDetails.tsx index a91817cf3..1d9c9e256 100644 --- a/site/source/components/company/Details.tsx +++ b/site/source/components/entreprise/EntrepriseDetails.tsx @@ -11,7 +11,7 @@ import { Body } from '@/design-system/typography/paragraphs' import SeeAnswersButton from '../conversation/SeeAnswersButton' import Value from '../EngineValue/Value' -export function CompanyDetails({ +export function EntrepriseDetails({ showSituation = false, headingTag = 'h3', }: { diff --git a/site/source/components/company/SearchDetails.tsx b/site/source/components/entreprise/EntrepriseSearchDetails.tsx similarity index 100% rename from site/source/components/company/SearchDetails.tsx rename to site/source/components/entreprise/EntrepriseSearchDetails.tsx diff --git a/site/source/components/entreprise/EntrepriseSearchField.tsx b/site/source/components/entreprise/EntrepriseSearchField.tsx new file mode 100644 index 000000000..377469ad3 --- /dev/null +++ b/site/source/components/entreprise/EntrepriseSearchField.tsx @@ -0,0 +1,84 @@ +import { useSearchFieldState } from '@react-stately/searchfield' +import { ReactNode, useEffect, useRef } from 'react' +import { useTranslation } from 'react-i18next' + +import { SearchableSelectField } from '@/design-system/field/SearchableSelectField/SearchableSelectField' +import { Grid } from '@/design-system/layout' +import { Entreprise } from '@/domaine/Entreprise' +import useSearchCompany from '@/hooks/useSearchCompany' + +import { Appear } from '../ui/animate' +import EntrepriseSearchResults from './EntrepriseSearchResults' + +export function EntrepriseSearchField(props: { + label?: ReactNode + selectedValue?: ReactNode | null + onValue?: () => void + onClear?: () => void + onSubmit?: (search: Entreprise | null) => void +}) { + const { t } = useTranslation() + const refResults = useRef(null) + + const searchFieldProps = { + ...props, + label: + !props.selectedValue && + t('EntrepriseSearchField.label', "Nom de l'entreprise, SIREN ou SIRET"), + description: + !props.selectedValue && + t( + 'EntrepriseSearchField.description', + 'Le numéro Siret est un numéro de 14 chiffres unique pour chaque entreprise. Exemple : 40123778000127' + ), + onSubmit() { + const results = refResults.current + props.onSubmit?.(results?.[0] ?? null) + }, + onClear() { + props.onClear?.() + }, + placeholder: t( + 'EntrepriseSearchField.placeholder', + 'Exemple : Café de la gare ou 40123778000127' + ), + } + + const state = useSearchFieldState(searchFieldProps) + + const { onSubmit } = props + + const [searchPending, results] = useSearchCompany(state.value) + + useEffect(() => { + refResults.current = results ?? null + }, [results]) + + return ( + + + + + + + + {state.value && !searchPending && !props.selectedValue && ( + + )} + + + + ) +} diff --git a/site/source/components/company/SearchField.tsx b/site/source/components/entreprise/EntrepriseSearchResults.tsx similarity index 55% rename from site/source/components/company/SearchField.tsx rename to site/source/components/entreprise/EntrepriseSearchResults.tsx index 6fa44b24a..787a78291 100644 --- a/site/source/components/company/SearchField.tsx +++ b/site/source/components/entreprise/EntrepriseSearchResults.tsx @@ -1,24 +1,19 @@ -import { useSearchFieldState } from '@react-stately/searchfield' -import { ReactNode, useEffect, useRef } from 'react' import { Trans, useTranslation } from 'react-i18next' import { styled } from 'styled-components' import { ForceThemeProvider } from '@/components/utils/DarkModeContext' import { Message } from '@/design-system' import { Card } from '@/design-system/card' -import { SearchableSelectField } from '@/design-system/field/SearchableSelectField/SearchableSelectField' import { FocusStyle } from '@/design-system/global-style' import { ChevronIcon } from '@/design-system/icons' -import { Grid } from '@/design-system/layout' import { Strong } from '@/design-system/typography' import { StyledLink } from '@/design-system/typography/link' import { Li, Ul } from '@/design-system/typography/list' import { Body } from '@/design-system/typography/paragraphs' import { Entreprise } from '@/domaine/Entreprise' -import useSearchCompany from '@/hooks/useSearchCompany' -import { Appear, FromTop } from '../ui/animate' -import EntrepriseSearchDetails from './SearchDetails' +import { FromTop } from '../ui/animate' +import EntrepriseSearchDetails from './EntrepriseSearchDetails' const StyledCard = styled(Card)` flex-direction: row; // for Safari <= 13 @@ -28,80 +23,7 @@ const StyledCard = styled(Card)` } ` -export function EntrepriseSearchField(props: { - label?: ReactNode - selectedValue?: ReactNode | null - onValue?: () => void - onClear?: () => void - onSubmit?: (search: Entreprise | null) => void -}) { - const { t } = useTranslation() - const refResults = useRef(null) - - const searchFieldProps = { - ...props, - label: - !props.selectedValue && - t('CompanySearchField.label', "Nom de l'entreprise, SIREN ou SIRET"), - description: - !props.selectedValue && - t( - 'CompanySearchField.description', - 'Le numéro Siret est un numéro de 14 chiffres unique pour chaque entreprise. Exemple : 40123778000127' - ), - onSubmit() { - const results = refResults.current - props.onSubmit?.(results?.[0] ?? null) - }, - onClear() { - props.onClear?.() - }, - placeholder: t( - 'CompanySearchField.placeholder', - 'Exemple : Café de la gare ou 40123778000127' - ), - } - - const state = useSearchFieldState(searchFieldProps) - - const { onSubmit } = props - - const [searchPending, results] = useSearchCompany(state.value) - - useEffect(() => { - refResults.current = results ?? null - }, [results]) - - return ( - - - - - - - - {state.value && !searchPending && !props.selectedValue && ( - - )} - - - - ) -} - -function Results({ +export default function EntrepriseSearchResults({ results, onSubmit, }: { diff --git a/site/source/components/entreprise/SelectedEntrepriseDetails.tsx b/site/source/components/entreprise/SelectedEntrepriseDetails.tsx new file mode 100644 index 000000000..46ccdd3e3 --- /dev/null +++ b/site/source/components/entreprise/SelectedEntrepriseDetails.tsx @@ -0,0 +1,44 @@ +import { Trans } from 'react-i18next' +import { styled } from 'styled-components' + +import { Strong } from '@/design-system/typography' +import { H4 } from '@/design-system/typography/heading' +import { Body } from '@/design-system/typography/paragraphs' + +import Value from '../EngineValue/Value' + +const StyledH4 = styled(H4)` + margin: ${({ theme }) => theme.spacings.xxs} 0; +` +const StyledBody = styled(Body)` + margin: ${({ theme }) => theme.spacings.xxs} 0; +` +const StyledEntrepriseContainer = styled.div` + padding: 0 ${({ theme }) => theme.spacings.xs}; +` + +export default function SelectedEntrepriseDetails() { + return ( + + + {' '} + + + + + Entreprise créée le{' '} + + + {' '} + et domiciliée à{' '} + + + + + + + ) +} diff --git a/site/source/locales/ui-en.yaml b/site/source/locales/ui-en.yaml index ea8743515..f4e5a7ff9 100644 --- a/site/source/locales/ui-en.yaml +++ b/site/source/locales/ui-en.yaml @@ -73,11 +73,6 @@ Comment ça marche ? Voir la page explicative sur la page du dépôt github, nou How does it work? See the explanatory page on the github repository page, new window Commune ou code postal: Town or zip code -CompanySearchField: - description: "The Siret number is a 14-digit number unique to each company. - Example: 40123778000127" - label: Company name, SIREN or SIRET - placeholder: "Example: Café de la gare or 40123778000127" Comparer...: Compare... Confirmer: Confirm Cotisations: Contributions @@ -119,6 +114,11 @@ English version of the website enabled.: English version of the website enabled. Enregistrer et continuer: Save and continue Enregistrer et voir le résultat: Save and view results Entreprise créée le <2><0> et domiciliée à <6><0>: Company founded on <2><0> and domiciled at <6><0> +EntrepriseSearchField: + description: "The Siret number is a 14-digit number unique to each company. + Example: 40123778000127" + label: Company name, SIREN or SIRET + placeholder: "Example: Café de la gare or 40123778000127" Envoyer: Send "Exemple : Des informations plus claires, un calcul détaillé...": "Example: clearer information, detailed calculation..." Exonérations: Exemptions @@ -365,6 +365,7 @@ Votre avis nous intéresse: We value your opinion Votre chiffre d'affaires estimé: Your estimated sales Votre couverture invalidité et décès: Your disability and death coverage Votre domaine d'activité: Your field of activity +Votre entreprise: Your company Votre message (requis): Your message (required) Votre rémunération totale estimée: Your estimated total remuneration Vous allez dépasser le plafond de la micro-entreprise: You will exceed the micro-business limit diff --git a/site/source/locales/ui-fr.yaml b/site/source/locales/ui-fr.yaml index 4756c8943..37878c242 100644 --- a/site/source/locales/ui-fr.yaml +++ b/site/source/locales/ui-fr.yaml @@ -78,11 +78,6 @@ Comment ça marche ? Voir la page explicative sur la page du dépôt github, nou Comment ça marche ? Voir la page explicative sur la page du dépôt github, nouvelle fenêtre Commune ou code postal: Commune ou code postal -CompanySearchField: - description: "Le numéro Siret est un numéro de 14 chiffres unique pour chaque - entreprise. Exemple : 40123778000127" - label: Nom de l'entreprise, SIREN ou SIRET - placeholder: "Exemple : Café de la gare ou 40123778000127" Comparer...: Comparer... Confirmer: Confirmer Cotisations: Cotisations @@ -126,6 +121,11 @@ English version of the website enabled.: English version of the website enabled. Enregistrer et continuer: Enregistrer et continuer Enregistrer et voir le résultat: Enregistrer et voir le résultat Entreprise créée le <2><0> et domiciliée à <6><0>: Entreprise créée le <2><0> et domiciliée à <6><0> +EntrepriseSearchField: + description: "Le numéro Siret est un numéro de 14 chiffres unique pour chaque + entreprise. Exemple : 40123778000127" + label: Nom de l'entreprise, SIREN ou SIRET + placeholder: "Exemple : Café de la gare ou 40123778000127" Envoyer: Envoyer "Exemple : Des informations plus claires, un calcul détaillé...": "Exemple : Des informations plus claires, un calcul détaillé..." Exonérations: Exonérations @@ -384,6 +384,7 @@ Votre avis nous intéresse: Votre avis nous intéresse Votre chiffre d'affaires estimé: Votre chiffre d'affaires estimé Votre couverture invalidité et décès: Votre couverture invalidité et décès Votre domaine d'activité: Votre domaine d'activité +Votre entreprise: Votre entreprise Votre message (requis): Votre message (requis) Votre rémunération totale estimée: Votre rémunération totale estimée Vous allez dépasser le plafond de la micro-entreprise: Vous allez dépasser le plafond de la micro-entreprise diff --git a/site/source/pages/_landing/SearchOrCreate.tsx b/site/source/pages/_landing/SearchOrCreate.tsx index 29a7c7b7a..de6f3a2ea 100644 --- a/site/source/pages/_landing/SearchOrCreate.tsx +++ b/site/source/pages/_landing/SearchOrCreate.tsx @@ -3,8 +3,8 @@ import { Trans, useTranslation } from 'react-i18next' import { useDispatch } from 'react-redux' import { generatePath, useNavigate } from 'react-router-dom' -import { CompanyDetails } from '@/components/company/Details' -import { EntrepriseSearchField } from '@/components/company/SearchField' +import { EntrepriseDetails } from '@/components/entreprise/EntrepriseDetails' +import { EntrepriseSearchField } from '@/components/entreprise/EntrepriseSearchField' import { useEngine } from '@/components/utils/EngineContext' import AnswerGroup from '@/design-system/answer-group' import { Button } from '@/design-system/buttons' @@ -38,8 +38,8 @@ export default function SearchOrCreate() { {companySIREN ? ( <> -

Votre entreprise

- +

{t('Votre entreprise')}

+