From fb57b99daa67b25152c91508b01906ab2e22e083 Mon Sep 17 00:00:00 2001 From: Johan Girod Date: Mon, 24 Apr 2023 17:54:20 +0200 Subject: [PATCH] Ajoute la selection du guichet unique sur l'assistant au choix du statut --- modele-social/règles/entreprise/activité.yaml | 5 +- site/source/components/utils/persistState.ts | 8 +- .../_components/Navigation.tsx | 4 +- .../choix-du-statut/détails-activité.tsx | 147 +++++++++++++----- .../choix-du-statut/recherche-activité.tsx | 6 +- .../recherche-code-ape/GuichetInfo.tsx | 123 ++++++++------- .../assistants/recherche-code-ape/Result.tsx | 65 ++++---- .../recherche-code-ape/SearchCodeAPE.tsx | 40 +++-- 8 files changed, 246 insertions(+), 152 deletions(-) diff --git a/modele-social/règles/entreprise/activité.yaml b/modele-social/règles/entreprise/activité.yaml index b4c40ddc1..f2a96629b 100644 --- a/modele-social/règles/entreprise/activité.yaml +++ b/modele-social/règles/entreprise/activité.yaml @@ -314,10 +314,13 @@ entreprise . activités . principale: titre: Activité principale avec: code APE: - titre: Code APE description: | Le code APE est un code qui permet d'identifier l'activité principale de l'entreprise. Il est composé de 5 chiffres. + code guichet: + description: | + Le code guichet est utilisé pour identifier l'activité principale lors de la déclaration de + la nouvelle entreprise via le guichet unique # une possibilité: # choix obligatoire: oui diff --git a/site/source/components/utils/persistState.ts b/site/source/components/utils/persistState.ts index 3ca1bea4c..a80acf73c 100644 --- a/site/source/components/utils/persistState.ts +++ b/site/source/components/utils/persistState.ts @@ -2,7 +2,13 @@ import { useEffect, useState } from 'react' import * as safeLocalStorage from '../../storage/safeLocalStorage' -type Storage = Record | boolean | number | null +type Storage = + | Record + | Array + | boolean + | number + | null + | string export const getInitialState = (key: string): T | null => { const value = safeLocalStorage.getItem(key) diff --git a/site/source/pages/assistants/choix-du-statut/_components/Navigation.tsx b/site/source/pages/assistants/choix-du-statut/_components/Navigation.tsx index d24d3deeb..9b963da6d 100644 --- a/site/source/pages/assistants/choix-du-statut/_components/Navigation.tsx +++ b/site/source/pages/assistants/choix-du-statut/_components/Navigation.tsx @@ -47,7 +47,7 @@ export default function Navigation({ onNextStep, }: { currentStepIsComplete: boolean - nextStepLabel?: string + nextStepLabel?: false | string onNextStep?: () => void }) { const { t } = useTranslation() @@ -84,7 +84,7 @@ export default function Navigation({ isDisabled={!currentStepIsComplete} aria-label={t("Suivant, passer à l'étape suivante")} > - {nextStepLabel || Suivant}{' '} + {nextStepLabel || Enregistrer et passer à la suite}{' '} diff --git a/site/source/pages/assistants/choix-du-statut/détails-activité.tsx b/site/source/pages/assistants/choix-du-statut/détails-activité.tsx index c13aad8b5..06d14b978 100644 --- a/site/source/pages/assistants/choix-du-statut/détails-activité.tsx +++ b/site/source/pages/assistants/choix-du-statut/détails-activité.tsx @@ -1,62 +1,79 @@ -import { useState } from 'react' +import { useEffect, useState } from 'react' import { Trans, useTranslation } from 'react-i18next' import { useDispatch } from 'react-redux' +import { Navigate } from 'react-router-dom' -import { Message } from '@/design-system' -import { HelpButtonWithPopover } from '@/design-system/buttons' +import Skeleton from '@/components/ui/Skeleton' +import { useEngine } from '@/components/utils/EngineContext' +import { Message, RadioCardGroup } from '@/design-system' +import { StyledRadioSkeleton } from '@/design-system/field/Radio/RadioCard' +import { Spacing } from '@/design-system/layout' import { H3, H5 } from '@/design-system/typography/heading' -import { Link } from '@/design-system/typography/link' import { Body } from '@/design-system/typography/paragraphs' +import { useSitePaths } from '@/sitePaths' import { updateSituation } from '@/store/actions/actions' +import { + GuichetDescription, + GuichetEntry, + getGuichetTitle, + useGuichetInfo, +} from '../recherche-code-ape/GuichetInfo' import Layout from './_components/Layout' import Navigation from './_components/Navigation' export default function Activité() { - const [codeApe, setCodeApe] = useState('') const { t } = useTranslation() + const codeApe = useEngine().evaluate( + 'entreprise . activités . principale . code APE' + ).nodeValue as string | undefined + const dispatch = useDispatch() + + const [codeGuichet, setCodeGuichet] = useState(undefined) + const guichetEntries = useGuichetInfo(codeApe) + + useEffect(() => { + if (guichetEntries && guichetEntries.length === 1) + setCodeGuichet(guichetEntries[0].code) + }, [guichetEntries]) + + if (!codeApe) return return ( <> - -

- Mon activité principale est... - - - Le choix du statut et les cotisations diffèrent en fonction de - l'activité professionnelle que vous exercez. Renseigner votre - métier vous donnera de la visibilité sur les statuts possibles - et permettra de simuler vos revenus de manière plus précise. - - -
Vous cumulez plusieurs activités ?
- - Votre entreprise doit tout de même déclarer une activité - principale à l'administration. Pour savoir comment la - déterminer, voir ce guide. - -
-
-

+ +

Précisions sur votre activité

+ + {!guichetEntries ? ( + + ) : guichetEntries.length === 1 ? ( + <> + +
{getGuichetTitle(guichetEntries[0].label)}
+ + +
+ + ) : ( + + )} + codeGuichet && dispatch( updateSituation( - 'entreprise . activités . principale . code APE', - codeApe + 'entreprise . activités . principale . code guichet', + `'${codeGuichet}'` ) ) } @@ -65,3 +82,57 @@ export default function Activité() { ) } + +function CodeAPENonConnu() { + const { absoluteSitePaths } = useSitePaths() + + return ( + // For now, we don't handle the case where the user doesn't find his code APE + + ) +} + +function GuichetSelection({ + entries, + onGuichetSelected, + codeGuichet, +}: { + entries: GuichetEntry[] + onGuichetSelected: (code: string) => void + codeGuichet?: string +}) { + return ( + <> + Sectionnez la description d'activité qui correspond le mieux. + + {entries.map((guichetEntry) => { + return ( + +
{getGuichetTitle(guichetEntry.label)}
+ +
+ ) + })} +
+ + ) +} + +function GuichetSkeleton() { + return ( + + + + + + + + ) +} diff --git a/site/source/pages/assistants/choix-du-statut/recherche-activité.tsx b/site/source/pages/assistants/choix-du-statut/recherche-activité.tsx index 81b0df812..7c2698717 100644 --- a/site/source/pages/assistants/choix-du-statut/recherche-activité.tsx +++ b/site/source/pages/assistants/choix-du-statut/recherche-activité.tsx @@ -55,15 +55,11 @@ export default function Activité() { dispatch( updateSituation( 'entreprise . activités . principale . code APE', - codeApe + `'${codeApe}'` ) ) } diff --git a/site/source/pages/assistants/recherche-code-ape/GuichetInfo.tsx b/site/source/pages/assistants/recherche-code-ape/GuichetInfo.tsx index 21b3561b6..a829bb989 100644 --- a/site/source/pages/assistants/recherche-code-ape/GuichetInfo.tsx +++ b/site/source/pages/assistants/recherche-code-ape/GuichetInfo.tsx @@ -4,75 +4,92 @@ import { H5 } from '@/design-system/typography/heading' import { Li, Ul } from '@/design-system/typography/list' import { Body } from '@/design-system/typography/paragraphs' import { useAsyncData } from '@/hooks/useAsyncData' +import { capitalise0 } from '@/utils' const lazyApeToGuichet = () => import('@/public/data/ape-to-guichet.json') type ApeToGuichet = typeof import('@/public/data/ape-to-guichet.json') const lazyGuichet = () => import('@/public/data/guichet.json') type Guichet = typeof import('@/public/data/guichet.json') -export default function GuichetInfo({ apeCode }: { apeCode: string }) { +export type GuichetEntry = Guichet[keyof Guichet] + +export function useGuichetInfo(codeApe?: string): GuichetEntry[] | null { const guichet = useAsyncData(lazyGuichet)?.default const apeToGuichet = useAsyncData(lazyApeToGuichet)?.default - if (!guichet || !apeToGuichet || !(apeCode in apeToGuichet)) { + if (!codeApe || !guichet || !apeToGuichet || !(codeApe in apeToGuichet)) { return null } - const guichetEntries = apeToGuichet[apeCode as keyof ApeToGuichet].map( + + return apeToGuichet[codeApe as keyof ApeToGuichet].map( (code) => guichet[code as keyof Guichet] ) +} + +export function getGuichetTitle(label: GuichetEntry['label']) { + return capitalise0( + [ + (!label.niv3 || label.niv3 === 'Autre') && label.niv2, + (!label.niv4 || label.niv4 === 'Autre') && label.niv3, + label.niv4, + ] + .filter(Boolean) + .join(' - ') + ) +} + +export default function GuichetInfo({ codeApe }: { codeApe: string }) { + const guichetEntries = useGuichetInfo(codeApe) + if (!guichetEntries) { + return null + } return (
    - {guichetEntries.map( - ({ - label, - caisseDeRetraiteSpéciale, - typeBénéfice, - artisteAuteurPossible, - catégorieActivité, - code, - }) => { - return ( -
  • - -
    - {[ - (!label.niv3 || label.niv3 === 'Autre') && label.niv2, - (!label.niv4 || label.niv4 === 'Autre') && label.niv3, - label.niv4, - ] - .filter(Boolean) - .join(' - ')} - {code} -
    - - Activité{' '} - {catégorieActivité.replace(/_/g, ' ')} avec - des revenus déclarés en {typeBénéfice} - {caisseDeRetraiteSpéciale && ( - <> - , affiliée à la{' '} - {caisseDeRetraiteSpéciale} pour la - retraite - - )} - . - - - {artisteAuteurPossible && ( - <> - Possibilitée d'exercer en tant qu' - ARTISTE AUTEUR - - )} - - - {/*
*/} - - - ) - } - )} + {guichetEntries.map((guichetEntry) => { + return ( +
  • + +
    + {getGuichetTitle(guichetEntry.label)}{' '} + {guichetEntry.code} +
    + +
    +
  • + ) + })} ) } + +export function GuichetDescription({ + caisseDeRetraiteSpéciale, + typeBénéfice, + artisteAuteurPossible, + catégorieActivité, +}: GuichetEntry) { + return ( + <> + + Activité {catégorieActivité.replace(/_/g, ' ')} avec + des revenus déclarés en {typeBénéfice} + {caisseDeRetraiteSpéciale && ( + <> + , affiliée à la {caisseDeRetraiteSpéciale} pour la + retraite + + )} + . + + + {artisteAuteurPossible && ( + <> + Possibilitée d'exercer en tant qu' + ARTISTE AUTEUR + + )} + + + ) +} diff --git a/site/source/pages/assistants/recherche-code-ape/Result.tsx b/site/source/pages/assistants/recherche-code-ape/Result.tsx index 71cd503dc..6a470047a 100644 --- a/site/source/pages/assistants/recherche-code-ape/Result.tsx +++ b/site/source/pages/assistants/recherche-code-ape/Result.tsx @@ -5,8 +5,6 @@ import styled, { css } from 'styled-components' import { Appear } from '@/components/ui/animate' import { Button, HelpButtonWithPopover } from '@/design-system/buttons' import { ChevronIcon } from '@/design-system/icons' -import InfoBulle from '@/design-system/InfoBulle' -import { Grid } from '@/design-system/layout' import { Strong } from '@/design-system/typography' import { H4, H5 } from '@/design-system/typography/heading' import { Link } from '@/design-system/typography/link' @@ -27,21 +25,14 @@ interface ResultProps { hideGuichetUnique: boolean } -export const Result = ({ item, debug, hideGuichetUnique }: ResultProps) => { +export const Result = ({ item, hideGuichetUnique }: ResultProps) => { const { title, codeApe, contenuCentral, contenuAnnexe, contenuExclu } = item const [open, setOpen] = useState(false) const { t } = useTranslation() return ( <> -

    - {title} - {debug && ( - -
    {debug}
    -
    - )} -

    +

    {title}

    { align-items: center; `} > - Code : {codeApe} + Code APE : {codeApe}