diff --git a/exoneration-covid/règles/exonération-covid.yaml b/exoneration-covid/règles/exonération-covid.yaml index 6a8f4f46c..060d4a2b2 100644 --- a/exoneration-covid/règles/exonération-covid.yaml +++ b/exoneration-covid/règles/exonération-covid.yaml @@ -242,6 +242,7 @@ mois . décembre 2021: mois . décembre 2021 . LFSS 600: valeur: décembre 2021 = 'LFSS 600' + percent: 65% mois . décembre 2021 . LFSS 300: valeur: décembre 2021 = 'LFSS 300' @@ -253,6 +254,7 @@ mois . janvier 2022: mois . janvier 2022 . LFSS 600: valeur: janvier 2022 = 'LFSS 600' + percent: 65% mois . janvier 2022 . LFSS 300: valeur: janvier 2022 = 'LFSS 300' @@ -264,6 +266,7 @@ mois . février 2022: mois . février 2022 . LFSS 600: valeur: février 2022 = 'LFSS 600' + percent: 65% mois . février 2022 . LFSS 300: valeur: février 2022 = 'LFSS 300' diff --git a/site/source/pages/Simulateurs/ExonerationCovid/FormulaireS1S1Bis.tsx b/site/source/pages/Simulateurs/ExonerationCovid/FormulaireS1S1Bis.tsx index 5c197a432..cfd3397be 100644 --- a/site/source/pages/Simulateurs/ExonerationCovid/FormulaireS1S1Bis.tsx +++ b/site/source/pages/Simulateurs/ExonerationCovid/FormulaireS1S1Bis.tsx @@ -1,84 +1,23 @@ +import { EngineContext } from '@/components/utils/EngineContext' +import { Spacing } from '@/design-system/layout' +import { H3 } from '@/design-system/typography/heading' +import { baseParagraphStyle } from '@/design-system/typography/paragraphs' +import { Grid } from '@mui/material' import { DottedNames } from 'exoneration-covid' import Engine, { ASTNode, - EvaluatedNode, Evaluation, formatValue, PublicodesExpression, } from 'publicodes' -import { EngineContext } from '@/components/utils/EngineContext' -import { useContext, Key } from 'react' -import { H3 } from '@/design-system/typography/heading' +import { useContext } from 'react' import { Trans, useTranslation } from 'react-i18next' -import { Grid } from '@mui/material' -import { Spacing } from '@/design-system/layout' -import { Item, Select } from '@/design-system/field/Select' import styled from 'styled-components' -import { baseParagraphStyle } from '@/design-system/typography/paragraphs' +import { Row, Table, Tbody, Th, Thead, Tr } from './Table' -const Json = (props: any) =>
{JSON.stringify(props, null, 2)}
- -const Th = styled.th` - flex: 2; - word-break: break-word; -` - -const Td = styled.td` - flex: 2; - word-break: break-word; -` - -const Tr = styled.tr` - display: flex; - align-items: center; - flex: 1; - word-break: break-word; - padding: 1rem; - - ${Td}:last-child { - text-align: right; - } - ${Td}:first-child, ${Td}:last-child { - flex: 1; - } -` - -const Thead = styled.thead` - background: ${({ theme }) => theme.colors.bases.primary[200]}; - color: ${({ theme }) => theme.colors.bases.primary[700]}; - border-radius: 0.35rem 0.35rem 0 0; - - ${Th}:first-child, ${Th}:last-child { - flex: 1; - } -` - -const Tbody = styled.tbody` - border-radius: 0 0 0.35rem 0.35rem; - - ${Tr}:nth-child(odd) { - background: ${({ theme }) => theme.colors.extended.grey[200]}; - } -` - -const Table = styled.table` - display: flex; - flex-direction: column; - text-align: left; - border: 1px solid ${({ theme }) => theme.colors.extended.grey[400]}; - border-radius: 0.35rem; - ${baseParagraphStyle} - font-weight: bold; -` - -const Empty = styled.div` - display: inline-block; - background: ${({ theme }) => theme.colors.extended.grey[300]}; - padding: 0.25rem 1rem; - border-radius: 0.25rem; - font-weight: 500; - font-size: 0.9rem; -` +const Json = (props: any) => ( +
{JSON.stringify(props, null, 2)}
+) const Recap = styled.div` background: ${({ theme }) => theme.colors.bases.primary[600]}; @@ -117,66 +56,6 @@ const Total = styled.div` margin-bottom: 0.5rem; ` -type RowProps = { - title?: string - total?: number - items: EvaluatedNode[] - onSelectionChange?: (key: Key) => void - defaultSelectedKey?: Key -} - -const Row = ({ - title, - total, - items, - onSelectionChange, - defaultSelectedKey, -}: RowProps) => { - const { t } = useTranslation() - - const choices = { - 'LFSS 600': [ - t('Interdiction d’accueil du public (600 €)'), - t('Baisse d’au moins 50% du chiffre d’affaires (600 €)'), - t('Baisse d’au moins 65% du chiffre d’affaires (600 €)'), - ], - 'LFSS 300': [t("Baisse entre 30% à 64% du chiffre d'affaires (300 €)")], - LFR1: [t('Eligibilité aux mois de mars, avril ou mai 2021 (250 €)')], - } - - return ( - - {title} - - {items.length > 0 ? ( - - ) : ( - - Mois non concerné - - )} - - {total ? total : '–'} - - ) -} - const getTotalByMonth = (engine: Engine) => { type ParsedSituation = typeof engine.parsedSituation @@ -212,7 +91,8 @@ const getTotalByMonth = (engine: Engine) => { const ret = Object.fromEntries( Object.entries(onlyMonthSituation).map(([monthDottedName, node]) => { - const targetDottedName = 'nodeValue' in node && (node.nodeValue as string) + const targetDottedName = + 'nodeValue' in node && (node.nodeValue as Evaluation) const monthEngine = notMonthEngine.shallowCopy().setSituation({ ...notMonthSituation, @@ -255,6 +135,22 @@ export const FormulaireS1S1Bis = ({ const totalByMonth = getTotalByMonth(engine) + const { t } = useTranslation() + + const choices = { + non: [t('Aucun')], + 'LFSS 600': [ + t('Interdiction d’accueil du public (600 €)'), + t('Baisse d’au moins 50% du chiffre d’affaires (600 €)'), + ], + 'LFSS 600 65%': [ + t('Interdiction d’accueil du public (600 €)'), + t('Baisse d’au moins 65% du chiffre d’affaires (600 €)'), + ], + 'LFSS 300': [t("Baisse entre 30% à 64% du chiffre d'affaires (300 €)")], + LFR1: [t('Eligibilité aux mois de mars, avril ou mai 2021 (250 €)')], + } + if (!engine.evaluate('mois').nodeValue) { return null } @@ -282,8 +178,8 @@ export const FormulaireS1S1Bis = ({ Mois - Situation liée à la crise sanitaire - Montant de la réduction + Situation liée à la crise sanitaire + Montant de la réduction @@ -308,22 +204,54 @@ export const FormulaireS1S1Bis = ({ ) emptyMonthIndex = [] - const items = [step1LFSS600, step1LFSS300, step1LFR1].filter( - (node) => - node.nodeKind === 'reference' && - node.dottedName && - dotName + ' . ' + node.dottedName in engine.parsedRules && - engine.evaluate(dotName + ' . ' + node.dottedName).nodeValue !== - null - ) + const items = [step1LFSS600, step1LFSS300, step1LFR1] + .filter( + (node) => + node.nodeKind === 'reference' && + node.dottedName && + dotName + ' . ' + node.dottedName in engine.parsedRules && + engine.evaluate(dotName + ' . ' + node.dottedName) + .nodeValue !== null + ) + .flatMap((node) => { + if ( + node.nodeKind !== 'reference' || + typeof node.dottedName !== 'string' + ) { + return null + } + + const name = (dotName + ' . ' + node.dottedName) as DottedNames + const rawNode = engine.getRule(name).rawNode + const { percent } = rawNode as { percent?: string } + const choice = (node.name + + (percent ? ' ' + percent : '')) as keyof typeof choices + + return choices[choice].map((text, i) => ({ + key: (node.dottedName as string) + `.${i}`, + text, + })) + }) + .filter((x: T | null): x is T => Boolean(x)) + + items.unshift({ key: 'non', text: choices['non'][0] }) const astNode = engine.parsedSituation[dotName] + const total = formatValue(totalByMonth[dotName]) as + | string + | null + | undefined return [ ...previousEmptyMonth, { - onChange?.(dotName as DottedNames, `'${key}'`) + const val = (key as string).replace(/\.\d+$/, '') + onChange?.(dotName as DottedNames, `'${val}'`) }} key={dotName} />, diff --git a/site/source/pages/Simulateurs/ExonerationCovid/Table.tsx b/site/source/pages/Simulateurs/ExonerationCovid/Table.tsx new file mode 100644 index 000000000..878ce77df --- /dev/null +++ b/site/source/pages/Simulateurs/ExonerationCovid/Table.tsx @@ -0,0 +1,126 @@ +import { Item, Select } from '@/design-system/field/Select' +import { baseParagraphStyle } from '@/design-system/typography/paragraphs' +import { Key } from 'react' +import { Trans } from 'react-i18next' +import styled, { css } from 'styled-components' + +export const Th = styled.th<{ alignSelf?: string }>` + flex: 2; + word-break: break-word; + ${({ alignSelf }) => + alignSelf + ? css` + align-self: ${alignSelf}; + ` + : ''} +` + +const Td = styled.td` + flex: 2; + word-break: break-word; + margin: 0.5rem 0; +` + +export const Tr = styled.tr` + display: flex; + flex-direction: column; + align-items: stretch; + flex: 1; + word-break: break-word; + padding: 1rem; + + ${Td}:last-child { + text-align: right; + } + ${Td}:first-child, ${Td}:last-child { + flex: 1; + } + @media (min-width: ${({ theme }) => theme.breakpointsWidth.sm}) { + flex-direction: initial; + align-items: center; + } +` + +export const Thead = styled.thead` + background: ${({ theme }) => theme.colors.bases.primary[200]}; + color: ${({ theme }) => theme.colors.bases.primary[700]}; + border-radius: 0.35rem 0.35rem 0 0; + + ${Th}:first-child, ${Th}:last-child { + flex: 1; + } +` + +export const Tbody = styled.tbody` + border-radius: 0 0 0.35rem 0.35rem; + + ${Tr}:nth-child(odd) { + background: ${({ theme }) => theme.colors.extended.grey[200]}; + } +` + +export const Table = styled.table` + display: flex; + flex-direction: column; + text-align: left; + border: 1px solid ${({ theme }) => theme.colors.extended.grey[400]}; + border-radius: 0.35rem; + ${baseParagraphStyle} + font-weight: bold; +` + +const Empty = styled.div` + display: inline-block; + background: ${({ theme }) => theme.colors.extended.grey[300]}; + padding: 0.25rem 1rem; + border-radius: 0.25rem; + font-weight: 500; + font-size: 0.9rem; +` + +type RowProps = { + title?: string + total?: string + label?: string + items: { + key: string + text: string + }[] + onSelectionChange?: (key: Key) => void + defaultSelectedKey?: Key +} + +export const Row = ({ + title, + total, + items, + label, + onSelectionChange, + defaultSelectedKey, +}: RowProps) => { + return ( + + {title} + + {items.length > 0 ? ( + + ) : ( + + Mois non concerné + + )} + + {total} + + ) +} diff --git a/site/source/pages/Simulateurs/ExonerationCovid/index.tsx b/site/source/pages/Simulateurs/ExonerationCovid/index.tsx index c4e14d86c..3361725cf 100644 --- a/site/source/pages/Simulateurs/ExonerationCovid/index.tsx +++ b/site/source/pages/Simulateurs/ExonerationCovid/index.tsx @@ -3,7 +3,6 @@ import Engine, { PublicodesExpression } from 'publicodes' import { EngineProvider } from '@/components/utils/EngineContext' import RuleInput from '@/components/conversation/RuleInput' import { useState, useCallback, useRef, useEffect } from 'react' -import Value from '@/components/EngineValue' import { H3 } from '@/design-system/typography/heading' import { Trans } from 'react-i18next' import { Grid } from '@mui/material' @@ -138,10 +137,6 @@ export default function ExonérationCovid() { - -
- - )