🎨 Améliore le style des champs de saisi principaux dex simulateurs

pull/1421/head
Johan Girod 2021-01-25 17:39:27 +01:00
parent f49fc6aaa6
commit 9714525a9c
13 changed files with 285 additions and 261 deletions

View File

@ -128,6 +128,7 @@ dirigeant . auto-entrepreneur . seuils dépassés . notification:
dirigeant . auto-entrepreneur . net de cotisations:
titre: Revenu net de cotisations
arrondi: oui
unité: €/an
identifiant court: auto-entrepreneur-net
résumé: Avant impôt
question: Quel revenu avant impôt voulez-vous toucher ?
@ -234,10 +235,9 @@ dirigeant . auto-entrepreneur . cotisations et contributions . contribution form
- sinon: 0.1%
dirigeant . auto-entrepreneur . chiffre d'affaires:
question: Quel est votre chiffre d'affaires ?
résumé: Montant total des recettes brutes
résumé: Montant total des recettes brutes (hors taxe)
unité: €/an
arrondi: oui
non applicable si: entreprise . activité . mixte
inversion numérique:
avec:
- net de cotisations

View File

@ -72,13 +72,8 @@ aide déclaration revenu indépendant 2020 . nature de l'activité . libérale:
références:
fiche Wikipedia: https://fr.m.wikipedia.org/wiki/Profession_libérale
<<<<<<< HEAD
aide déclaration revenu indépendant 2020 . nature de l'activité . commerciale ou industrielle:
remplace: entreprise . catégorie d'activité . commerciale ou industrielle
=======
aide déclaration revenu indépendant 2019 . nature de l'activité . commerciale ou industrielle:
remplace: entreprise . activité . commerciale ou industrielle
>>>>>>> 76a45672 ((auto-entrepreneur) Ajoute les revenus mixtes)
formule: nature de l'activité = 'commerciale ou industrielle'
description: |
### Activité commerciale

View File

@ -68,22 +68,19 @@ entreprise . chiffre d'affaires . vente restauration hébergement:
- activité . service ou vente = 'vente'
- activité . mixte
titre: Vente de biens, restauration, hebergement
par défaut:
le maximum de:
- dirigeant . auto-entrepreneur . chiffre d'affaires
- 0 €/an
résumé: Chiffre d'affaires hors taxe
question: Quel est le chiffre d'affaires issus de la vente de bien, restauration ou hébergement ?
unité: €/an
par défaut:
produit:
assiette: dirigeant . auto-entrepreneur . chiffre d'affaires
facteur:
variations:
- si: activité = 'libérale'
alors: 30%
- sinon: 70%
arrondi: oui
plancher: 0€/an
inversion numérique:
avec:
- dirigeant . auto-entrepreneur . net de cotisations
- dirigeant . auto-entrepreneur . net après impôt
abattement:
applicable si: activité . mixte
valeur: 2 / 3
unité: '%'
description: |
### Vente de biens
Il sagit du chiffre d'affaires de toutes les opérations comportant
@ -114,19 +111,16 @@ entreprise . chiffre d'affaires . prestations de service . BIC:
- activité . service ou vente = 'service'
- activité . mixte
unité: €/an
par défaut:
le maximum de:
- dirigeant . auto-entrepreneur . chiffre d'affaires
- 0 €/an
par défaut:
produit:
assiette: dirigeant . auto-entrepreneur . chiffre d'affaires
facteur:
variations:
- si: activité = 'libérale'
alors: 0
- sinon: 30%
plancher: 0€/an
inversion numérique:
avec:
- dirigeant . auto-entrepreneur . net de cotisations
- dirigeant . auto-entrepreneur . net après impôt
abattement:
applicable si: activité . mixte
valeur: 2 / 3
unité: '%'
arrondi: oui
résumé: Chiffre d'affaires hors taxe
titre: Prestations de service commerciales ou artisanales
question: Quel est le chiffre d'affaires issus de prestations de service commerciales ou artisanales ?
@ -146,23 +140,21 @@ entreprise . chiffre d'affaires . prestations de service . BNC:
titre: Prestations de service libérale
résumé: Chiffre d'affaires hors taxe
question: Quel est le chiffre d'affaires issus de prestations de service libérale ?
par défaut:
le maximum de:
- dirigeant . auto-entrepreneur . chiffre d'affaires
- 0 €/an
par défaut:
produit:
assiette: dirigeant . auto-entrepreneur . chiffre d'affaires
facteur:
variations:
- si: activité = 'libérale'
alors: 70%
- sinon: 0.0000001% # On veut qu'elle reste manquante en fonction du CA
arrondi: oui
applicable si:
une de ces conditions:
- activité = 'libérale'
- activité . mixte
plancher: 0€/an
inversion numérique:
avec:
- dirigeant . auto-entrepreneur . net de cotisations
- dirigeant . auto-entrepreneur . net après impôt
abattement:
applicable si: activité . mixte
valeur: 2 / 3
unité: '%'
description: |
Ce sont toutes les opérations dont l'activité intellectuelle tient
un rôle essentiel.

View File

@ -18,12 +18,16 @@ export default function CurrencyInput({
currencySymbol = '€',
onChange,
language,
missing,
className,
style,
dottedName,
...forwardedProps
}: CurrencyInputProps) {
const valueProp = value ?? ''
const [initialValue, setInitialValue] = useState(valueProp)
const [currentValue, setCurrentValue] = useState(valueProp)
const onChangeDebounced = useMemo(
() =>
debounceTimeout && onChange
@ -48,7 +52,10 @@ export default function CurrencyInput({
// Only trigger the `onChange` event if the value has changed -- and not
// only its formating, we don't want to call it when a dot is added in `12.`
// for instance
if (!nextValue.current || /(\.$)|(^\.)|(-$)/.exec(nextValue.current)) {
if (
!nextValue.current ||
/(\.$)|(^\.)|(-$)|(^0+$)/.exec(nextValue.current)
) {
return
}
event.persist()
@ -68,14 +75,13 @@ export default function CurrencyInput({
// Autogrow the input
const valueLength = currentValue.toString().length
const width = `${5 + (valueLength - 5) * 0.75}em`
return (
<div
className={classnames(className, 'currencyInput__container')}
{...(valueLength > 5 ? { style: { width } } : {})}
style={{ ...(valueLength > 5 ? { width } : {}), ...style }}
onFocus={() => inputRef.current?.select()}
onClick={() => inputRef.current?.focus()}
>
{!currentValue && isCurrencyPrefixed && currencySymbol}
<NumberFormat
{...forwardedProps}
thousandSeparator={thousandSeparator}
@ -93,7 +99,7 @@ export default function CurrencyInput({
//.replace(/^0+/, '')
}}
onChange={handleChange}
value={currentValue ? +currentValue : ''}
value={currentValue != null ? currentValue : ''}
autoComplete="off"
/>
{!isCurrencyPrefixed && <>&nbsp;</>}

View File

@ -1,11 +1,14 @@
import { updateSituation } from 'Actions/actions'
import classnames from 'classnames'
import Animate from 'Components/ui/animate'
import { DottedName } from 'modele-social'
import { UNSAFE_isNotApplicable } from 'publicodes'
import { formatValue, UNSAFE_isNotApplicable } from 'publicodes'
import { createContext, useContext, useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { situationSelector } from 'Selectors/simulationSelectors'
import RuleInput from './conversation/RuleInput'
import RuleLink from './RuleLink'
import AnimatedTargetValue from './ui/AnimatedTargetValue'
import { useEngine } from './utils/EngineContext'
type SimulationGoalsProps = {
@ -13,7 +16,7 @@ type SimulationGoalsProps = {
children: React.ReactNode
}
const InitialRenderContext = createContext(false)
const InitialRenderContext = createContext(true)
export function SimulationGoals({
className = '',
@ -44,14 +47,16 @@ type SimulationGoalProps = {
dottedName: DottedName
labelWithTitle?: boolean
small?: boolean
titleLevel?: number
appear?: boolean
editable?: boolean
}
export function SimulationGoal({
dottedName,
labelWithTitle = false,
small = false,
titleLevel = 2,
appear = true,
editable = true,
}: SimulationGoalProps) {
const dispatch = useDispatch()
const engine = useEngine()
@ -60,6 +65,7 @@ export function SimulationGoal({
const evaluation = engine.evaluate(dottedName)
const rule = engine.getRule(dottedName)
const initialRender = useContext(InitialRenderContext)
const [isFocused, setFocused] = useState(false)
if (
isNotApplicable === true ||
(!(dottedName in situation) &&
@ -68,11 +74,15 @@ export function SimulationGoal({
) {
return null
}
const displayAsInput =
dottedName in situation ||
isFocused ||
initialRender ||
Object.keys(situation).length === 0
return (
<li className={small ? 'small-target' : ''}>
<Animate.appear unless={initialRender}>
<div className="main">
<Animate.appear unless={!appear || initialRender}>
<div className="main" style={small ? { alignItems: 'baseline' } : {}}>
<div className="header">
<label htmlFor={dottedName}>
<span className="optionTitle">
@ -81,14 +91,39 @@ export function SimulationGoal({
<p className="ui__ notice">{rule.rawNode.résumé}</p>
</label>
</div>
{small && <span className="guide-lecture" />}
<div className="targetInputOrValue">
<RuleInput
className="targetInput"
isTarget
dottedName={dottedName}
onChange={(x) => dispatch(updateSituation(dottedName, x))}
useSwitch
/>
{editable ? (
<>
<RuleInput
className={classnames(
displayAsInput ? 'targetInput' : 'editableTarget',
{ focused: isFocused }
)}
isTarget
dottedName={dottedName}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
onChange={(x) => dispatch(updateSituation(dottedName, x))}
useSwitch
/>
</>
) : (
<>
<AnimatedTargetValue value={evaluation.nodeValue} />
<RuleLink
dottedName={dottedName}
css={`
padding-right: 0.6rem
&:not(:hover) {
text-decoration: none;
}
`}
>
{formatValue(evaluation, { displayedUnit: '€' })}
</RuleLink>
</>
)}
</div>
</div>
</Animate.appear>

View File

@ -24,29 +24,42 @@
#targetSelection .targets > li.small-target {
border-top: none;
padding: 0.4rem 1rem;
}
#targetSelection .targets > li.small-target .targetInput {
#targetSelection .targets > li.small-target .targetInput,
#targetSelection .targets > li.small-target .editableTarget {
border-width: 1px;
border-radius: 0.2rem;
padding-top: 0;
padding-bottom: 0;
}
#targetSelection .targets > li {
border-top: 1px solid rgba(255, 255, 255, 0.5);
border-top: 1px dashed rgba(255, 255, 255, 0.6);
padding: 0.8rem 1rem;
margin-left: -1rem;
margin-right: -1rem;
}
.light #targetSelection .targets > li:not(:first-child) {
.light #targetSelection .targets > li {
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.light #targetSelection .targets > li.small-target,
.light #targetSelection .targets > li:not(.small-target):first-of-type {
border-top: none;
}
#targetSelection .targets > li .main {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
#targetSelection .targets > li .guide-lecture {
flex: 1;
border-bottom: 1px dashed rgba(255, 255, 255, 0.25);
margin-left: 1rem;
}
#targetSelection li .header {
display: flex;
@ -94,7 +107,7 @@
#targetSelection .targetInputOrValue {
font-size: 115%;
margin-left: 0.6rem;
min-width: 5.5rem;
text-align: right;
display: flex;
flex-direction: column;
@ -110,26 +123,26 @@
text-decoration: none;
}
#targetSelection .targetInputOrValue > :not(.targetInput) {
margin: 0 0.6rem;
}
#targetSelection input {
margin: 2.7px 0;
}
#targetSelection .targetInput {
width: 5.5em;
margin-left: 1rem;
max-width: 7.5em;
text-align: right;
background: rgba(255, 255, 255, 0.2);
padding: 0;
padding: 0.2rem 0.6rem;
border-radius: 0.3rem;
border: 2px solid;
border: 1px solid;
font-size: inherit;
}
#targetSelection .targetInput.focused {
box-shadow: 0 0 0px 1px white;
}
.light #targetSelection .targetInput {
color: var(--darkColor);
border-color: var(--darkColor);
@ -142,23 +155,19 @@
#targetSelection .editableTarget {
max-width: 7.5em;
width: 5.5em;
display: inline-block;
text-align: right;
padding: 0 2px;
padding: 0.2rem 0.6rem;
background: transparent;
border: 1px dashed rgba(255, 255, 255, 0.5);
border-radius: 0.3rem;
font-size: inherit;
}
#targetSelection .targetInputBottomBorder {
margin: 0;
padding: 0 2px;
height: 0;
overflow: hidden;
}
#targetSelection .editableTarget + .targetInputBottomBorder {
border-bottom: 1px dashed #ffffff91;
}
#targetSelection .unit {
margin-left: 0.4em;
font-size: 110%;

View File

@ -1,5 +1,5 @@
import { setActiveTarget, updateSituation } from 'Actions/actions'
import InputSuggestions from 'Components/conversation/InputSuggestions'
import { updateSituation } from 'Actions/actions'
import classnames from 'classnames'
import Value, { Condition } from 'Components/EngineValue'
import PeriodSwitch from 'Components/PeriodSwitch'
import RuleLink from 'Components/RuleLink'
@ -21,18 +21,17 @@ import {
reduceAST,
RuleNode,
} from 'publicodes'
import { isNil } from 'ramda'
import { Fragment, useCallback, useContext, useEffect, useState } from 'react'
import { Fragment, useCallback, useContext, useState } from 'react'
import emoji from 'react-easy-emoji'
import { Trans, useTranslation } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
import { useLocation } from 'react-router-dom'
import { RootState } from 'Reducers/rootReducer'
import {
firstStepCompletedSelector,
situationSelector,
targetUnitSelector,
} from 'Selectors/simulationSelectors'
import InputSuggestions from './conversation/InputSuggestions'
import CurrencyInput from './CurrencyInput/CurrencyInput'
import './TargetSelection.css'
@ -102,19 +101,7 @@ const Target = ({ dottedName }: TargetProps) => {
unité: useSelector(targetUnitSelector),
arrondi: 'oui',
})
const situation = useSelector(situationSelector)
const target: TargetType = { ...evaluation, ...rule.rawNode, ...rule }
const dispatch = useDispatch()
const onSuggestionClick = useCallback(
(value) => {
dispatch(updateSituation(dottedName, value))
},
[target.dottedName, dispatch]
)
const isActive =
dottedName in situation || Object.keys(situation).length === 0
const isSmallTarget =
!rule.rawNode.question ||
(dottedName in evaluation.missingVariables &&
@ -134,34 +121,14 @@ const Target = ({ dottedName }: TargetProps) => {
<div>
<div className="main">
<Header target={target} />
{isSmallTarget && (
<span
style={{
flex: 1,
borderBottom: '1px dashed #ffffff91',
marginLeft: '1rem',
}}
/>
)}
{isSmallTarget && <span className="guide-lecture" />}
<TargetInputOrValue
{...{
target,
isActive,
isSmallTarget,
}}
/>
</div>
{isActive && (
<Animate.fromTop>
<div css="display: flex; justify-content: flex-end; margin-bottom: -0.4rem">
<InputSuggestions
suggestions={target.suggestions}
onFirstClick={onSuggestionClick}
/>
</div>
</Animate.fromTop>
)}
</div>
</Animate.appear>
</li>
@ -193,30 +160,35 @@ const Header = ({ target }: { target: TargetType }) => {
type TargetInputOrValueProps = {
target: TargetType
isActive: boolean
isSmallTarget: boolean
}
function TargetInputOrValue({
target,
isActive,
isSmallTarget,
}: TargetInputOrValueProps) {
const { language } = useTranslation().i18n
const colors = useContext(ThemeColorsContext)
const dispatch = useDispatch()
const [isActiveOrFocused, setActive] = useState(isActive)
useEffect(() => setActive(isActive), [isActive])
const [isFocused, setFocused] = useState(false)
const targetUnit = useSelector(targetUnitSelector)
const engine = useContext(EngineContext)
const situation = useSelector(situationSelector)
const value =
(engine.evaluate({
valeur: target.dottedName,
unité: targetUnit,
arrondi: 'oui',
}).nodeValue as number) ?? undefined
const blurValue = useInversionFail() && !isActiveOrFocused
const blurValue = useInversionFail() && !isFocused
const onSuggestionClick = useCallback(
(value) => {
dispatch(updateSituation(target.dottedName, value))
},
[target.dottedName, dispatch]
)
const isSituationEmpty = Object.keys(situation).length === 0
const isActive = target.dottedName in situation
const onChange = useCallback(
(evt) =>
dispatch(
@ -228,54 +200,68 @@ function TargetInputOrValue({
[targetUnit, target, dispatch]
)
return (
<span
className="targetInputOrValue"
style={blurValue ? { filter: 'blur(3px)' } : {}}
>
{target.question ? (
<>
{!isActiveOrFocused && <AnimatedTargetValue value={value} />}
<CurrencyInput
style={{
color: colors.textColor,
borderColor: colors.textColor,
}}
debounce={750}
name={target.dottedName}
value={value}
className={
isActiveOrFocused ||
isNil(value) ||
(target.question && isSmallTarget)
? 'targetInput'
: 'editableTarget'
}
onChange={onChange}
onFocus={() => {
setActive(true)
}}
language={language}
/>
<span className="targetInputBottomBorder">
{formatValue(value, { language, displayedUnit: '€' })}
<>
<span
className="targetInputOrValue"
style={blurValue ? { filter: 'blur(3px)' } : {}}
>
{target.question ? (
<>
{!isFocused && <AnimatedTargetValue value={value} />}
<CurrencyInput
style={{
color: colors.textColor,
borderColor: colors.textColor,
}}
debounce={750}
name={target.dottedName}
value={value}
className={classnames(
isFocused ||
isActive ||
isSituationEmpty ||
(target.question && isSmallTarget)
? 'targetInput'
: 'editableTarget',
{ focused: isFocused }
)}
onChange={onChange}
onFocus={() => {
setFocused(true)
}}
onBlur={() => setTimeout(() => setFocused(false), 100)}
language={language}
/>
</>
) : (
<span>
{value && Number.isNaN(value) ? (
'—'
) : (
<RuleLink dottedName={target.dottedName}>
{formatValue(value, { displayedUnit: '€', language })}
</RuleLink>
)}
</span>
</>
) : (
<span>
{value && Number.isNaN(value) ? (
'—'
) : (
<RuleLink dottedName={target.dottedName}>
{formatValue(value, { displayedUnit: '€', language })}
</RuleLink>
)}
</span>
)}
{target.dottedName.includes('prix du travail') && <AidesGlimpse />}
{target.dottedName === 'contrat salarié . rémunération . net' && (
<TitreRestaurant />
)}
</span>
{(isActive || isFocused) && (
<div style={{ minWidth: '100%' }}>
<Animate.fromTop>
<div css="display: flex; justify-content: flex-end; margin-bottom: -0.4rem">
<InputSuggestions
suggestions={target.suggestions}
onFirstClick={onSuggestionClick}
/>
</div>
</Animate.fromTop>
</div>
)}
{target.dottedName.includes('prix du travail') && <AidesGlimpse />}
{target.dottedName === 'contrat salarié . rémunération . net' && (
<TitreRestaurant />
)}
</span>
</>
)
}
function TitreRestaurant() {

View File

@ -1,5 +1,5 @@
import { stepAction, goToQuestion, updateSituation } from 'Actions/actions'
import RuleInput, { RuleInputProps } from 'Components/conversation/RuleInput'
import { goToQuestion, stepAction, updateSituation } from 'Actions/actions'
import RuleInput, { InputProps } from 'Components/conversation/RuleInput'
import QuickLinks from 'Components/QuickLinks'
import * as Animate from 'Components/ui/animate'
import { EngineContext } from 'Components/utils/EngineContext'
@ -41,7 +41,7 @@ export default function Conversation({ customEndMessages }: ConversationProps) {
dispatch(stepAction(currentQuestion, source))
}
const onChange: RuleInputProps['onChange'] = (value) => {
const onChange: InputProps['onChange'] = (value) => {
dispatch(updateSituation(currentQuestion, value))
}

View File

@ -1,21 +1,8 @@
import {
InputCommonProps,
RuleInputProps,
} from 'Components/conversation/RuleInput'
import { RuleNode } from 'publicodes'
import { InputProps } from 'Components/conversation/RuleInput'
import { useCallback, useMemo } from 'react'
import styled from 'styled-components'
import InputSuggestions from './InputSuggestions'
type DateInputProps = {
onChange: InputCommonProps['onChange']
id: InputCommonProps['id']
onSubmit: RuleInputProps['onSubmit']
value: InputCommonProps['value']
suggestions: RuleNode['suggestions']
required: RuleInputProps['required']
}
export default function DateInput({
suggestions,
onChange,
@ -23,7 +10,7 @@ export default function DateInput({
onSubmit,
required,
value,
}: DateInputProps) {
}: InputProps) {
const dateValue = useMemo(() => {
if (!value || typeof value !== 'string') return undefined
const [day, month, year] = value.split('/')

View File

@ -8,7 +8,7 @@ import ToggleSwitch from 'Components/ui/ToggleSwitch'
import { EngineContext } from 'Components/utils/EngineContext'
import { DottedName } from 'modele-social'
import Engine, { ASTNode, formatValue, reduceAST } from 'publicodes'
import { Evaluation } from 'publicodes/dist/types/AST/types'
import { EvaluatedNode, Evaluation } from 'publicodes/dist/types/AST/types'
import { RuleNode } from 'publicodes/dist/types/rule'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
@ -17,30 +17,23 @@ import ParagrapheInput from './ParagrapheInput'
import SelectEuropeCountry from './select/SelectEuropeCountry'
import TextInput from './TextInput'
type Value = any
export type RuleInputProps<Name extends string = DottedName> = {
export type Props<Name extends string = DottedName> = Omit<
React.HTMLAttributes<HTMLInputElement>,
'onChange' | 'defaultValue'
> & {
required?: boolean
dottedName: Name
onChange: (value: Value | null) => void
onChange: (value: Parameters<Engine<Name>['evaluate']>[0]) => void
useSwitch?: boolean
isTarget?: boolean
autoFocus?: boolean
required?: boolean
id?: string
className?: string
onSubmit?: (source: string) => void
}
export type InputCommonProps<Name extends string = string> = Pick<
RuleInputProps<Name>,
'onChange' | 'autoFocus' | 'className'
> &
export type InputProps<Name extends string = string> = Props<Name> &
Pick<RuleNode, 'title' | 'suggestions'> & {
question: RuleNode['rawNode']['question']
key: string
id: string
value: any //TODO EvaluatedRule['nodeValue']
value: EvaluatedNode['nodeValue']
missing: boolean
required: boolean
}
export const binaryQuestion = [
@ -56,30 +49,25 @@ export default function RuleInput({
dottedName,
onChange,
useSwitch = false,
id,
isTarget = false,
autoFocus = false,
required = true,
className,
onSubmit = () => null,
}: RuleInputProps) {
...props
}: Props<DottedName>) {
const engine = useContext(EngineContext)
const rule = engine.getRule(dottedName)
const evaluation = engine.evaluate(dottedName)
const language = useTranslation().i18n.language
const value = evaluation.nodeValue
const commonProps: InputCommonProps = {
key: dottedName,
const commonProps: InputProps<DottedName> = {
dottedName,
value,
missing: !!evaluation.missingVariables[dottedName],
onChange,
autoFocus,
className,
required,
title: rule.title,
id: id ?? dottedName,
id: props.id ?? dottedName,
question: rule.rawNode.question,
suggestions: rule.suggestions,
...props,
}
if (getVariant(engine.getRule(dottedName))) {
return (
@ -149,12 +137,12 @@ export default function RuleInput({
return (
<>
<CurrencyInput
{...commonProps}
className="targetInput"
language={language}
debounce={750}
value={value as any}
name={dottedName}
className="targetInput"
{...commonProps}
value={value as number}
onChange={(evt) => onChange({ valeur: evt.target.value, unité })}
/>
</>

View File

@ -1,6 +1,7 @@
import { updateSituation } from 'Actions/actions'
import Conversation from 'Components/conversation/Conversation'
import { Condition } from 'Components/EngineValue'
import RuleLink from 'Components/RuleLink'
import SearchButton from 'Components/SearchButton'
import SimulateurWarning from 'Components/SimulateurWarning'
import { SimulationGoal, SimulationGoals } from 'Components/SimulationGoals'
import StackedBarChart from 'Components/StackedBarChart'
@ -12,41 +13,47 @@ import { useDispatch } from 'react-redux'
import AidesCovid from '../../components/simulationExplanation/AidesCovid'
export default function AutoEntrepreneur() {
const dispatch = useDispatch()
return (
<>
<SimulateurWarning simulateur="auto-entrepreneur" />
<SimulationGoals className="plain">
<ActivitéMixte />
<SearchButton invisibleButton />
<SimulationGoals className="plain">
<Condition expression="entreprise . activité . mixte = non">
<SimulationGoal
appear={false}
labelWithTitle
dottedName="dirigeant . auto-entrepreneur . chiffre d'affaires"
/>
<ActivitéMixte />
</Condition>
<Condition expression="entreprise . activité . mixte">
<h2 className="optionTitle">
<RuleLink dottedName="entreprise . chiffre d'affaires" />
</h2>
<SimulationGoal
small
appear={false}
editable={false}
labelWithTitle
dottedName="entreprise . chiffre d'affaires . vente restauration hébergement"
/>
<SimulationGoal
labelWithTitle
small
titleLevel={3}
dottedName="entreprise . chiffre d'affaires . prestations de service . BIC"
/>
<SimulationGoal
labelWithTitle
small
dottedName="entreprise . chiffre d'affaires . prestations de service . BNC"
dottedName="entreprise . chiffre d'affaires"
/>
<ActivitéMixte />
<li>
<ul>
<SimulationGoal
small
labelWithTitle
dottedName="entreprise . chiffre d'affaires . vente restauration hébergement"
/>
<SimulationGoal
labelWithTitle
small
dottedName="entreprise . chiffre d'affaires . prestations de service . BIC"
/>
<SimulationGoal
labelWithTitle
small
dottedName="entreprise . chiffre d'affaires . prestations de service . BNC"
/>
</ul>
</li>
</Condition>
<SimulationGoal
@ -58,6 +65,7 @@ export default function AutoEntrepreneur() {
dottedName="dirigeant . auto-entrepreneur . net après impôt"
/>
</SimulationGoals>
<Conversation />
<Explanation />
</>
)
@ -67,22 +75,37 @@ function ActivitéMixte() {
const defaultCheked = !!useEngine().evaluate('entreprise . activité . mixte')
.nodeValue
const dispatch = useDispatch()
return (
<label>
Activité mixte{' '}
<input
type="checkbox"
defaultChecked={defaultCheked}
onChange={(evt) =>
dispatch(
updateSituation(
'entreprise . activité . mixte',
evt.target.checked ? 'oui' : 'non'
<li
className="ui__ notice small-target"
css={`
margin-top: -0.4rem;
`}
>
<label
css={`
display: flex;
align-items: center;
`}
>
Activité mixte&nbsp;{' '}
<input
type="checkbox"
defaultChecked={defaultCheked}
onChange={(evt) =>
setTimeout(() =>
dispatch(
updateSituation(
'entreprise . activité . mixte',
evt.target.checked ? 'oui' : 'non'
)
)
)
)
}
/>
</label>
}
/>{' '}
</label>
</li>
)
}

View File

@ -1,4 +1,7 @@
objectifs:
- dirigeant . auto-entrepreneur . chiffre d'affaires
- dirigeant . auto-entrepreneur . net de cotisations
- dirigeant . auto-entrepreneur . net après impôt
- dirigeant . auto-entrepreneur . cotisations et contributions
- dirigeant . auto-entrepreneur . net après impôt . impôt
@ -23,5 +26,5 @@ questions:
- entreprise . chiffre d'affaires . prestations de service . BNC
unité par défaut: €/an
situation:
entreprise . activité . mixte: oui
entreprise . activité . mixte: non
dirigeant: "'auto-entrepreneur'"

View File

@ -150,11 +150,11 @@ ${e.message}`
const chainableMecanisms = [
applicable,
nonApplicable,
parDéfaut,
arrondi,
unité,
plancher,
plafond,
parDéfaut,
situation,
abattement,
]