diff --git a/cypress/integration/external/external-integrations.js b/cypress/integration/external/external-integrations.js index 7adf2b478..c43e06c2e 100644 --- a/cypress/integration/external/external-integrations.js +++ b/cypress/integration/external/external-integrations.js @@ -6,7 +6,7 @@ describe('Pole emploi', function() { cy.visit('https://entreprise.pole-emploi.fr/cout-salarie/') cy.get('#simulateurEmbauche') .iframe() - .contains('Versé sur son compte bancaire') + .contains('Salaire net') }) }) @@ -17,6 +17,6 @@ describe('URSSAF', function() { ) cy.get('#simulateurEmbauche') .iframe() - .contains('Versé sur son compte bancaire') + .contains('Salaire net') }) }) diff --git a/cypress/integration/mon-entreprise/iframe.js b/cypress/integration/mon-entreprise/iframe.js index d434096fb..f6f0cd8ac 100644 --- a/cypress/integration/mon-entreprise/iframe.js +++ b/cypress/integration/mon-entreprise/iframe.js @@ -3,6 +3,6 @@ describe('Iframe integration test', function() { cy.visit('/dev/integration-test') cy.get('#simulateurEmbauche') .iframe() - .contains('Versé sur son compte bancaire') + .contains('Salaire net') }) }) diff --git a/cypress/integration/mon-entreprise/landing.js b/cypress/integration/mon-entreprise/landing.js index 0c20bf493..5ab98b047 100644 --- a/cypress/integration/mon-entreprise/landing.js +++ b/cypress/integration/mon-entreprise/landing.js @@ -2,7 +2,7 @@ describe('Landing test', function() { const fr = Cypress.env('language') === 'fr' it('should not crash', function() { cy.visit('/') - cy.contains(fr ? 'Mon-entreprise.fr' : 'My company in France') + cy.get('img[alt="logo mon-entreprise.fr"]').should('be.visible') }) it('should display urssaf and marianne logo', function() { cy.visit('/') @@ -11,11 +11,11 @@ describe('Landing test', function() { }) it('should display actionnable items', function() { cy.visit('/') - cy.contains(fr ? 'Créer une entreprise' : 'Create a company in France') + cy.contains(fr ? 'Créer mon entreprise' : 'Create my company in France') cy.contains( fr - ? 'Estimer les cotisations et les taxes' - : 'Estimate contributions and taxes' + ? 'Simuler les cotisations et les taxes' + : 'Simulate contributions and taxes' ) }) }) diff --git a/cypress/integration/mon-entreprise/simulateur-salarié.js b/cypress/integration/mon-entreprise/simulateur-salarié.js index 260b63b67..76924cb1c 100644 --- a/cypress/integration/mon-entreprise/simulateur-salarié.js +++ b/cypress/integration/mon-entreprise/simulateur-salarié.js @@ -14,7 +14,7 @@ if (fr) { }) describe('Basic test', function() { it('should display the simulateur after loading', function() { - cy.contains('Versé sur son compte bancaire') + cy.contains('Salaire net') }) it('should display cotisation repartition when entering net salary', function() { salaryInput('Salaire net').type('2000') @@ -33,9 +33,9 @@ if (fr) { it('should save the current simulation', function() { salaryInput('Salaire net').type('471') cy.wait(1000) - cy.contains('CDD').click() - cy.contains('passer').click() - cy.contains('passer').click() + cy.contains('Passer').click() + cy.contains('Passer').click() + cy.contains('Passer').click() // Wanted to use cypress.clock(), but can't because of piwik changing Date prototype (!) cy.wait(1100) cy.visit('/sécurité-sociale/salarié') diff --git a/cypress/integration/mon-entreprise/simulateurs.js b/cypress/integration/mon-entreprise/simulateurs.js index ed0a56aa7..098934741 100644 --- a/cypress/integration/mon-entreprise/simulateurs.js +++ b/cypress/integration/mon-entreprise/simulateurs.js @@ -7,7 +7,7 @@ const salaryInput = inputTitle => { return inputContainer.find('input') } -describe('Landing test', function() { +describe('Simulateurs test', function() { const fr = Cypress.env('language') === 'fr' it('should not crash', function() { @@ -18,15 +18,13 @@ describe('Landing test', function() { }) it('should display selection page', function() { cy.visit(fr ? '/sécurité-sociale' : '/social-security') - cy.contains( - fr ? 'La rémunération du dirigeant' : "The director's remuneration" - ).click() + cy.contains(fr ? 'Mon revenu' : 'My income').click() cy.contains( fr ? 'Quel régime souhaitez-vous explorer ?' : 'Which social scheme would you like to explore?' ) - cy.contains(fr ? 'Indépendant' : 'Self-employed').click({ force: true }) + cy.contains('Indépendant').click({ force: true }) cy.contains( fr ? 'Simulateur de revenus pour indépendants' @@ -41,9 +39,11 @@ describe('Landing test', function() { force: true }) cy.contains(fr ? 'Cotisations et contributions' : 'All contributions') - cy.contains(fr ? "Année d'activité" : 'Years of activity').click() + cy.contains(fr ? "Type d'activité" : 'Activity type').click() cy.contains( - fr ? "Quel est l'âge de l'entreprise" : 'How old is the company' + fr + ? "Quelle est votre catégorie d'activité" + : 'What is your category of activity' ) }) }) diff --git a/cypress/integration/mon-entreprise/status.js b/cypress/integration/mon-entreprise/status.js index 2baa35893..cac11a345 100644 --- a/cypress/integration/mon-entreprise/status.js +++ b/cypress/integration/mon-entreprise/status.js @@ -1,10 +1,7 @@ describe('Status guide', function() { const fr = Cypress.env('language') === 'fr' beforeEach(() => { - cy.visit('/') - cy.contains( - fr ? 'Créer une entreprise' : 'Create a company in France' - ).click() + cy.visit(fr ? '/entreprise' : '/company') cy.get('a.ui__.button.plain').click() }) @@ -31,8 +28,8 @@ describe('Status guide', function() { cy.get('.ui__.answer-group') .contains(fr ? 'Société' : 'Limited liability company') .click() - cy.get('.ui__.answer-group') - .contains(fr ? 'Assimilé salarié' : 'Assimilated salaried') + cy.get('.answer-group button') + .contains('Assimilé') .click() cy.contains(fr ? 'Créer une SASU' : 'Create a SASU').click() }) diff --git a/index.html b/index.html index e8febc4c3..704d81b5f 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,28 @@ + + + + + + + + @@ -188,7 +210,7 @@ style="position: fixed; top: 0; left: 0; bottom: 0; right: 0; display: none; background-color: white" >

- Nous vous invitons à réessayer avec un autre, ou depuis un mobile récent. + Nous vous invitons à réessayer avec un autre, ou depuis un mobile + récent.



diff --git a/manifest.webmanifest b/manifest.webmanifest index 409f3acdf..c99900fc3 100644 --- a/manifest.webmanifest +++ b/manifest.webmanifest @@ -1,26 +1,21 @@ { - "name": "Simulateur d'embauche", - "short_name": "Embauche", - "description": "Jongler entre les différents salaires lors d'une embauche", + "name": "Mon entreprise", + "short_name": "Mon entreprise", + "description": "L'assistant officiel du créateur d'entreprise", "display": "standalone", "lang": "fr", "orientation": "portrait-primary", "theme_color": "#2975d1", "icons": [ { - "src": "/source/images/logo/logo-simulateur-48.png", - "sizes": "48x48", - "type": "image/png" - }, - { - "src": "/source/images/logo/logo-simulateur-144.png", - "sizes": "144x144", - "type": "image/png" - }, - { - "src": "/source/images/logo/logo-simulateur-192.png", + "src": "/favicon/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" + }, + { + "src": "/favicon/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" } ] } diff --git a/netlify.toml b/netlify.toml index 0212c45ac..7683a032c 100644 --- a/netlify.toml +++ b/netlify.toml @@ -59,6 +59,11 @@ from = "https://embauche.beta.gouv.fr/" to = "https://mon-entreprise.fr/sécurité-sociale/salarié" status = 301 +[[redirects]] +from = "https://embauche.beta.gouv.fr/simulation" +to = "https://mon-entreprise.fr/sécurité-sociale/salarié" +status = 301 + [[redirects]] from = "https://embauche.beta.gouv.fr/documentation/*" to = "https://mon-entreprise.fr/documentation/:splat" diff --git a/package.json b/package.json index b6b41423f..f68c91491 100644 --- a/package.json +++ b/package.json @@ -84,9 +84,9 @@ "compile-lib": "yarn webpack --config source/webpack.lib.js", "compile-dev": "FR_SITE='http://localhost:5000${path}' EN_SITE='http://localhost:5001${path}' yarn run compile", "mon-entreprise:serve": "PORT=5000 serve --config serve.mon-entreprise.json --no-clipboard", - "mon-entreprise:test": "cypress open", + "mon-entreprise:test": "cypress open --browser chromium", "mycompanyinfrance:serve": "PORT=5001 serve --config serve.infrance.json --no-clipboard", - "mycompanyinfrance:test": "cypress open --env language=en --config baseUrl=http://localhost:8080/infrance", + "mycompanyinfrance:test": "cypress open --browser chromium --env language=en --config baseUrl=http://localhost:8080/infrance", "serve-dev": "yarn run mon-entreprise:serve & yarn run mycompanyinfrance:serve" }, "devDependencies": { diff --git a/source/actions/actions.js b/source/actions/actions.js index 5a5f46783..395706a18 100644 --- a/source/actions/actions.js +++ b/source/actions/actions.js @@ -2,13 +2,13 @@ import type { ResetSimulationAction, LoadPreviousSimulationAction, + StepAction, DeletePreviousSimulationAction, - StartConversationAction, SetSimulationConfigAction, SetSituationBranchAction } from 'Types/ActionsTypes' // $FlowFixMe -import { reset } from 'redux-form' +import { clearFields, reset } from 'redux-form' import { deletePersistedSimulation } from '../storage/persistSimulation' import type { Thunk } from 'Types/ActionsTypes' @@ -20,6 +20,21 @@ export const resetSimulation = () => (dispatch: any => void): void => { ) dispatch(reset('conversation')) } +export const goToQuestion = (question: string): StepAction => ({ + type: 'STEP_ACTION', + name: 'unfold', + step: question +}) +export const skipQuestion = ( + question: string +): Thunk => dispatch => { + dispatch(clearFields('conversation', false, false, question)) + dispatch({ + type: 'STEP_ACTION', + name: 'fold', + step: question + }) +} export const setSituationBranch = (id: number): SetSituationBranchAction => ({ type: 'SET_SITUATION_BRANCH', @@ -46,15 +61,6 @@ export const deletePreviousSimulation = () => ( deletePersistedSimulation() } -export const startConversation = (priorityNamespace: ?string) => ( - dispatch: StartConversationAction => void -) => { - dispatch({ - type: 'START_CONVERSATION', - ...(priorityNamespace ? { priorityNamespace } : {}) - }) -} - // $FlowFixMe export function setExample(name, situation, dottedName) { return { type: 'SET_EXAMPLE', name, situation, dottedName } diff --git a/source/components/Banner.css b/source/components/Banner.css index 59007bf86..b28543a63 100644 --- a/source/components/Banner.css +++ b/source/components/Banner.css @@ -1,15 +1,14 @@ .ui__.banner { display: flex; align-items: center; - margin: 1rem auto; + margin: 1rem 0; max-width: 100%; color: var(--lighterInverseTextColour); width: 45rem; - justify-content: center; } .ui__.banner img { - margin-right: 1rem !important; - font-size: 2rem; + margin-right: 0.6rem !important; + font-size: 1.4rem; margin-bottom: 0.6rem !important; } diff --git a/source/components/Banner.js b/source/components/Banner.js index d3f7c9ab6..68b912bc6 100644 --- a/source/components/Banner.js +++ b/source/components/Banner.js @@ -3,6 +3,7 @@ import React from 'react' import emoji from 'react-easy-emoji' import { connect } from 'react-redux' +import { firstStepCompletedSelector } from 'Selectors/analyseSelectors' import Animate from 'Ui/animate' import './Banner.css' import type { Node } from 'react' @@ -10,7 +11,7 @@ import type { State } from 'Types/State' type PropTypes = { hidden: boolean, children: Node, - icon?: String + icon?: string } let Banner = ({ hidden = false, children, icon }: PropTypes) => @@ -25,7 +26,7 @@ let Banner = ({ hidden = false, children, icon }: PropTypes) => export default (connect( (state: State, { hidden }: PropTypes) => ({ - hidden: hidden || state.conversationStarted + hidden: hidden || firstStepCompletedSelector(state) }), {} )(Banner): React$ComponentType) diff --git a/source/components/ComparativeTargets.css b/source/components/ComparativeTargets.css deleted file mode 100644 index f38ee42ff..000000000 --- a/source/components/ComparativeTargets.css +++ /dev/null @@ -1,11 +0,0 @@ -.comparative-targets { - display: flex; - flex-wrap: wrap; - justify-content: center; -} -@media (max-width: 800px) { - .comparative-targets { - flex-direction: column; - align-items: center; - } -} diff --git a/source/components/ComparativeTargets.js b/source/components/ComparativeTargets.js deleted file mode 100644 index 2aae0c470..000000000 --- a/source/components/ComparativeTargets.js +++ /dev/null @@ -1,169 +0,0 @@ -/* @flow */ -import { setSituationBranch } from 'Actions/actions' -import { - defineDirectorStatus, - isAutoentrepreneur -} from 'Actions/companyStatusActions' -import RuleLink from 'Components/RuleLink' -import React from 'react' -import { connect } from 'react-redux' -import { config } from 'react-spring' -import { branchAnalyseSelector } from 'Selectors/analyseSelectors' -import { règleAvecMontantSelector } from 'Selectors/regleSelectors' -import Animate from 'Ui/animate' -import { noUserInputSelector } from '../selectors/analyseSelectors' -import './ComparativeTargets.css' -import SchemeCard from './ui/SchemeCard' - -import type { RègleAvecMontant } from 'Types/RegleTypes' - -const connectRègles = (situationBranchName: string) => - connect( - state => { - return ({ - revenuDisponible: - !noUserInputSelector(state) && - règleAvecMontantSelector(state, { - situationBranchName - })('revenu net') - }: { - revenuDisponible: boolean | RègleAvecMontant - }) - }, - { - setSituationBranch, - isAutoentrepreneur, - defineDirectorStatus - } - ) - -type ComparativeTargetsProps = { - plafondAutoEntrepreneurDépassé: ?{ message: string } -} -const ComparativeTargets: React$ComponentType<{}> = connect(state => { - const analyse = branchAnalyseSelector(state, { - situationBranchName: 'Auto-entrepreneur' - }) - return { - plafondAutoEntrepreneurDépassé: - analyse.controls && - analyse.controls.find(({ test }) => - test.includes('base des cotisations > plafond') - ) - } -})(({ plafondAutoEntrepreneurDépassé }: ComparativeTargetsProps) => ( - -
- - - -
-
-)) - -const Indépendant = connectRègles('Indépendant')( - ({ - revenuDisponible, - branchIndex, - setSituationBranch, - defineDirectorStatus, - isAutoentrepreneur - }) => ( - setSituationBranch(branchIndex)} - amount={revenuDisponible.montant} - icon="👩‍🔧" - amountDesc={} - features={[ - 'Régime des indépendants', - 'Complémentaire santé et prévoyance non incluses', - 'Accidents du travail non couverts', - 'Retraite faible (41% du dernier brut)', - 'Indemnités journalières plus faibles', - 'Montant minimum de cotisations', - 'Cotisations en décalage de deux ans' - ]} - onSchemeChoice={() => { - defineDirectorStatus('SELF_EMPLOYED') - isAutoentrepreneur(false) - }} - /> - ) -) - -const AssimiléSalarié = connectRègles('Assimilé salarié')( - ({ - revenuDisponible, - branchIndex, - setSituationBranch, - defineDirectorStatus - }) => ( - setSituationBranch(branchIndex)} - subtitle="Le régime tout compris" - amount={revenuDisponible.montant} - featured="Le choix de 58% des dirigeants de sociétés" - icon="☂" - amountDesc={} - features={[ - 'Régime général', - 'Complémentaires santé et prévoyance incluses', - 'Accidents du travail couverts', - 'Retraite élevée (62 % du dernier brut)', - 'Pas de cotisations minimales', - "Seuil pour l'activation des droits (4000€/an)", - 'Fiches de paie mensuelles', - 'Prélèvement des cotisations à la source' - ]} - onSchemeChoice={() => { - defineDirectorStatus('SALARIED') - isAutoentrepreneur(false) - }} - /> - ) -) - -const AutoEntrepreneur = connectRègles('Auto-entrepreneur')( - ({ - revenuDisponible, - setSituationBranch, - isAutoentrepreneur, - branchIndex, - plafondDépassé - }) => { - return ( - setSituationBranch(branchIndex)} - disabled={plafondDépassé} - amountDesc={} - icon="🚶‍♂️" - amount={revenuDisponible.montant} - features={[ - 'Régime des indépendants', - 'Pas de déduction des charges', - 'Pas de déduction fiscale pour la mutuelle (Madelin)', - "Chiffre d'affaires plafonné", - "Durée de l'ACRE plus élevée", - 'Comptabilité réduite au minimum' - ]} - onSchemeChoice={() => { - defineDirectorStatus('SELF_EMPLOYED') - isAutoentrepreneur(true) - }} - /> - ) - } -) - -export default ComparativeTargets diff --git a/source/components/Controls.js b/source/components/Controls.js index 4f1247f61..476094adb 100644 --- a/source/components/Controls.js +++ b/source/components/Controls.js @@ -1,4 +1,4 @@ -import { hideControl, startConversation } from 'Actions/actions' +import { goToQuestion, hideControl } from 'Actions/actions' import { makeJsx } from 'Engine/evaluation' import { createMarkdownDiv } from 'Engine/marked' import { compose } from 'ramda' @@ -6,19 +6,23 @@ import React from 'react' import emoji from 'react-easy-emoji' import { withTranslation } from 'react-i18next' import { connect } from 'react-redux' +import { analysisWithDefaultsSelector } from 'Selectors/analyseSelectors' import animate from 'Ui/animate' import './Controls.css' import withColours from './utils/withColours' function Controls({ controls, - startConversation, + goToQuestion, hideControl, foldedSteps, hiddenControls, t, inversionFail }) { + if (!controls) { + return null + } let messages = [ ...controls, ...(inversionFail @@ -56,7 +60,7 @@ function Controls({
@@ -81,13 +85,15 @@ export default compose( connect( (state, props) => ({ foldedSteps: state.conversationSteps.foldedSteps, + controls: analysisWithDefaultsSelector(state)?.controls, + inversionFail: analysisWithDefaultsSelector(state)?.cache?.inversionFail, key: props.language, hiddenControls: state.hiddenControls }), - dispatch => ({ - startConversation: cible => dispatch(startConversation(cible)), - hideControl: id => dispatch(hideControl(id)) - }) + { + goToQuestion, + hideControl + } ), withColours, withTranslation() diff --git a/source/components/Distribution.css b/source/components/Distribution.css index 74c50f7e5..a2b927417 100644 --- a/source/components/Distribution.css +++ b/source/components/Distribution.css @@ -5,9 +5,8 @@ padding: 0; width: 100%; border: none; - font-weight: normal; align-items: center; - font-size: 90%; + position: relative; } .distribution-chart__bar-container { @@ -26,9 +25,8 @@ } .distribution-chart__counterparts { - width: 25em; + width: 28em; line-height: 1.2em; - font-weight: 300; } .distribution-chart__item:hover .distribution-chart__bar { @@ -97,9 +95,6 @@ flex-shrink: 0; } -.distribution-chart__branche-name { - font-weight: 500; -} .distribution-chart__icon { font-size: 200%; height: 1.2em; @@ -116,7 +111,7 @@ grid-template-columns: 1fr auto auto; grid-column-gap: 1em; grid-row-gap: 0.4em; - align-items: end; + align-items: flex-end; text-align: right; margin-bottom: 1em; } diff --git a/source/components/Distribution.js b/source/components/Distribution.js index ce3119427..e86af7c62 100644 --- a/source/components/Distribution.js +++ b/source/components/Distribution.js @@ -68,7 +68,7 @@ class Distribution extends Component { return ( { - {' : '} - {branche.descriptionCourte} +
+ {branche.résumé}

diff --git a/source/components/Feedback/Feedback.css b/source/components/Feedback/Feedback.css index 27ec52a9f..80f5e14d6 100644 --- a/source/components/Feedback/Feedback.css +++ b/source/components/Feedback/Feedback.css @@ -4,16 +4,11 @@ flex-wrap: wrap; padding-top: 0.6rem; padding-bottom: 0.6rem; - background: var(--lighterColour); + background: var(--lightestColour); border-radius: 0.9rem; padding: 0.6rem 1rem; margin: 1rem 0; } -.feedback-page.stickToFooter { - margin-bottom: 0; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; -} .feedback-page button.link-button { margin: 0 0.6rem; } diff --git a/source/components/Feedback/PageFeedback.js b/source/components/Feedback/PageFeedback.js index 29f7ee76e..a90adac4b 100644 --- a/source/components/Feedback/PageFeedback.js +++ b/source/components/Feedback/PageFeedback.js @@ -1,6 +1,5 @@ /* @flow */ -import classNames from 'classnames' import withTracker from 'Components/utils/withTracker' import React, { Component } from 'react' import { Trans, withTranslation } from 'react-i18next' @@ -16,8 +15,7 @@ import type { Node } from 'react' type OwnProps = { blacklist: Array, customMessage?: Node, - customEventName?: string, - stickToFooter: boolean + customEventName?: string } type Props = OwnProps & { location: Location, @@ -93,7 +91,6 @@ class PageFeedback extends Component { this.setState({ showForm: true }) } render() { - let { stickToFooter = false } = this.props if ( this.state.feedbackAlreadyGiven && !this.state.showForm && @@ -105,11 +102,10 @@ class PageFeedback extends Component { this.props.location.pathname === '/' ? '' : this.props.location.pathname return ( !this.props.blacklist.includes(pathname) && ( -
-
+
+
{!this.state.showForm && !this.state.showThanks && ( <>
diff --git a/source/components/PaySlip.css b/source/components/PaySlip.css index b26a78237..7a468d373 100644 --- a/source/components/PaySlip.css +++ b/source/components/PaySlip.css @@ -18,7 +18,7 @@ margin-top: 1.5em; padding-bottom: 0.5em; padding-left: 0.5em; - align-self: end; + align-self: flex-end; margin-bottom: 0.5em; } .payslip__container h4:first-child { diff --git a/source/components/PaySlip.js b/source/components/PaySlip.js index 7fc8ebb7d..d2b935228 100644 --- a/source/components/PaySlip.js +++ b/source/components/PaySlip.js @@ -151,29 +151,6 @@ const PaySlip = ({ {salaireNetAprèsImpôt.montant}
-
-

- - Le simulateur vous aide à comprendre votre bulletin de paie, sans lui - être opposable. Pour plus d'informations, rendez vous sur  - - service-public.fr - - . - -

-

- - Il ne prend pour l'instant pas en compte les accords et conventions - collectives, ni la myriade d'aides aux entreprises. Trouvez votre - convention collective{' '} - ici - , et explorez les aides sur  - aides-entreprises.fr. - -

) } diff --git a/source/components/PercentageField.css b/source/components/PercentageField.css new file mode 100644 index 000000000..b19eaf060 --- /dev/null +++ b/source/components/PercentageField.css @@ -0,0 +1,97 @@ +.range { + -webkit-appearance: none; + vertical-align: middle; + outline: none; + border: none; + cursor: pointer; + padding: 0; + background: none; +} + +.range::-webkit-slider-runnable-track { + background-color: white; + height: 6px; + border-radius: 3px; + border: 1px solid transparent; +} + +.range[disabled]::-webkit-slider-runnable-track { + border: 1px solid white; + background-color: transparent; + opacity: 0.4; +} + +.range::-moz-range-track { + background-color: white; + height: 6px; + border-radius: 3px; + border: none; +} + +.range::-ms-track { + color: transparent; + border: none; + background: none; + height: 6px; +} + +.range::-ms-fill-lower { + background-color: white; + border-radius: 3px; +} + +.range::-ms-fill-upper { + background-color: white; + border-radius: 3px; +} + +.range::-ms-tooltip { + display: none; /* display and visibility only */ +} + +.range::-moz-range-thumb { + border-radius: 20px; + height: 18px; + width: 18px; + border: 2px solid white; + background: none; + background-color: var(--colour); + cursor: pointer; +} + +.range:active::-moz-range-thumb { + outline: none; +} + +.range::-webkit-slider-thumb { + -webkit-appearance: none !important; + border-radius: 100%; + border: 2px solid white; + background-color: var(--colour); + cursor: pointer; + height: 18px; + width: 18px; + margin-top: -7px; +} + +.range[disabled]::-webkit-slider-thumb { + background-color: transparent; + border: 1px solid white; +} + +.range:active::-webkit-slider-thumb { + outline: none; +} + +.range::-ms-thumb { + border-radius: 100%; + border: 2px solid white; + background-color: var(--colour); + cursor: pointer; + height: 18px; + width: 18px; +} + +.range:active::-ms-thumb { + border: none; +} diff --git a/source/components/PercentageField.js b/source/components/PercentageField.js new file mode 100644 index 000000000..ce3bd2aff --- /dev/null +++ b/source/components/PercentageField.js @@ -0,0 +1,35 @@ +import React from 'react' +import { debounce } from '../utils' +import './PercentageField.css' + +export default class PercentageField extends React.Component { + debouncedOnChange = this.props.debounce + ? debounce(this.props.debounce, this.props.input.onChange) + : this.props.input.onChange + state = { + value: this.props.input?.value + } + onChange(value) { + this.setState({ value }) + this.debouncedOnChange(value) + } + render() { + return ( +
+ this.onChange(e.target.value)} + type="range" + value={this.state.value} + name="volume" + min="0" + step="0.05" + max="1" + /> + + {Math.round(this.state.value * 100)} % + +
+ ) + } +} diff --git a/source/components/PreviousSimulationBanner.js b/source/components/PreviousSimulationBanner.js index 76ed6d194..069c00e43 100644 --- a/source/components/PreviousSimulationBanner.js +++ b/source/components/PreviousSimulationBanner.js @@ -25,7 +25,7 @@ const PreviousSimulationBanner = ({ newSimulationStarted, loadPreviousSimulation }: ConnectedPropTypes) => ( -
+ + ) : ( +
+

+ {emoji('🌟')}{' '} + Vous avez complété cette simulation{' '} +

+

+ {customEndMessages ? ( + customEndMessages + ) : ( + + Vous avez maintenant accès à l'estimation la plus précise possible. + + )} +

+ +
+ ) +}) diff --git a/source/components/conversation/FormDecorator.js b/source/components/conversation/FormDecorator.js index 8d9fd3723..66969fbe1 100644 --- a/source/components/conversation/FormDecorator.js +++ b/source/components/conversation/FormDecorator.js @@ -1,11 +1,10 @@ -import classNames from 'classnames'; -import Explicable from 'Components/conversation/Explicable'; -import { compose } from 'ramda'; -import React, { Component } from 'react'; -import { withTranslation } from 'react-i18next'; -import { connect } from 'react-redux'; -import { change, Field } from 'redux-form'; -import IgnoreStepButton from './IgnoreStepButton'; +import classNames from 'classnames' +import Explicable from 'Components/conversation/Explicable' +import { compose } from 'ramda' +import React, { Component } from 'react' +import { withTranslation } from 'react-i18next' +import { connect } from 'react-redux' +import { change, Field } from 'redux-form' export let buildValidationFunction = valueType => { let validator = valueType ? valueType.validator : {}, @@ -48,7 +47,7 @@ export var FormDecorator = formType => RenderField => defaultValue, fieldName, inversion, - setFormValue, + setFormValue } = this.props let validate = buildValidationFunction(valueType) let submit = cause => stepAction('fold', fieldName, cause), @@ -63,36 +62,20 @@ export var FormDecorator = formType => RenderField =>
-

+

{' '} {this.props.question}{' '} {!inversion && } -

+
- {defaultValue != null && ( - { - setFormValue( - fieldName, - typeof defaultValue == 'object' - ? JSON.stringify(defaultValue) - : '' + defaultValue - ) - submit('ignore') - }} - /> - )} +
- +
) diff --git a/source/components/conversation/IgnoreStepButton.js b/source/components/conversation/IgnoreStepButton.js deleted file mode 100644 index 875b09234..000000000 --- a/source/components/conversation/IgnoreStepButton.js +++ /dev/null @@ -1,51 +0,0 @@ -import withColours from 'Components/utils/withColours' -import { compose } from 'ramda' -import React, { Component } from 'react' -import { Trans, withTranslation } from 'react-i18next' - -export default compose( - withTranslation(), - withColours -)( - class IgnoreStepButton extends Component { - componentDidMount() { - // removeEventListener will need the exact same function instance - this.boundHandleKeyDown = this.handleKeyDown.bind(this) - - window.addEventListener('keydown', this.boundHandleKeyDown) - } - handleKeyDown({ key }) { - if (key !== 'Escape') return - document.activeElement.blur() - this.props.action() - } - componentWillUnmount() { - window.removeEventListener('keydown', this.boundHandleKeyDown) - } - render() { - return ( -
- - - Échap - -
- ) - } - } -) diff --git a/source/components/conversation/ResultReliability.js b/source/components/conversation/ResultReliability.js new file mode 100644 index 000000000..db2885d1b --- /dev/null +++ b/source/components/conversation/ResultReliability.js @@ -0,0 +1,36 @@ +import { T } from 'Components' +import React from 'react' +import InfoBulle from 'Ui/InfoBulle' + +export default function ResultReliability({ progress }) { + return ( + + + {progress === 0 && ( + + Affinez la simulation en répondant aux questions suivantes : + + )} + + {progress > 0 && ( + <> + + {progress < 0.2 ? ( + Précision faible + ) : progress < 0.5 ? ( + Précision moyenne + ) : progress > 0.5 ? ( + Bonne précision + ) : ( + '' + )} + {' '} + + Le résultat peut varier énormément en fonction de votre situation. + Répondez aux questions pour en améliorer la précision. + {' '} + + )} + + ) +} diff --git a/source/components/conversation/SeeAnswersButton.js b/source/components/conversation/SeeAnswersButton.js new file mode 100644 index 000000000..66624febb --- /dev/null +++ b/source/components/conversation/SeeAnswersButton.js @@ -0,0 +1,23 @@ +import { T } from 'Components' +import React, { useState } from 'react' +import { connect } from 'react-redux' +import Answers from './AnswerList' +import './conversation.css' + +export default connect(state => ({ + arePreviousAnswers: !!state.conversationSteps.foldedSteps.length +}))(function SeeAnswersButton({ arePreviousAnswers }) { + const [showAnswerModal, setShowAnswerModal] = useState(false) + return ( + <> + {arePreviousAnswers && ( + + )} + {showAnswerModal && setShowAnswerModal(false)} />} + + ) +}) diff --git a/source/components/conversation/conversation.css b/source/components/conversation/conversation.css index 8a69fd3af..65e7a321d 100644 --- a/source/components/conversation/conversation.css +++ b/source/components/conversation/conversation.css @@ -59,8 +59,8 @@ } .step-question h1 { - font-size: 1.7rem; - color: rgba(0, 0, 0, 0.8); + font-size: 1.3rem; + line-height: 2.2rem; } .unfoldedHeader { @@ -164,7 +164,7 @@ .step label.radio { text-align: center; margin-left: 1em; - margin-top: 1em; + /* margin-top: 1em; */ cursor: pointer; background: none; border-radius: 1em; @@ -216,6 +216,7 @@ .step input.suffixed { padding: 0.1em 1em 0; + margin: 0.6rem 0; border-radius: 0.2em; font-size: 120%; } @@ -298,6 +299,7 @@ .answer { display: flex; + flex-wrap: wrap; justify-content: flex-end; align-items: center; } @@ -414,7 +416,8 @@ for the appearing element to appear without stacking up below the first one */ .conversationContainer { flex: 1; - margin-bottom: 2em; + padding-bottom: 1rem; + margin-bottom: 1rem; } .step label.userAnswerButton { diff --git a/source/components/simulationConfigs/assimilé.yaml b/source/components/simulationConfigs/assimilé.yaml index 9ecc28ebe..5d8a08f42 100644 --- a/source/components/simulationConfigs/assimilé.yaml +++ b/source/components/simulationConfigs/assimilé.yaml @@ -1,19 +1,28 @@ objectifs: - - entreprise . chiffre d'affaires - - entreprise . charges - - contrat salarié . cotisations - - contrat salarié . réduction ACRE - - impôt . neutre - - contrat salarié . salaire . net après impôt + - icône: 🏢 + nom: Mon entreprise + objectifs: + - entreprise . chiffre d'affaires + - entreprise . charges + - icône: 👩‍💼 + nom: Mon revenu + objectifs: + - contrat salarié . rémunération . total + - contrat salarié . cotisations + - contrat salarié . salaire . net + - impôt . neutre + - contrat salarié . salaire . net après impôt -questions à l'affiche: - Année d'activité: entreprise . année d'activité - Mutuelle: contrat salarié . complémentaire santé . part employeur - Localisation: établissement . localisation questions: blacklist: - - entreprise . charges - contrat salarié . avantages en nature . montant + - entreprise . rémunération du dirigeant + +questions à l'affiche: + ACRE: entreprise . année d'activité + Commune: établissement . localisation + Charges: entreprise . charges + situation: auto entrepreneur: non indépendant: non @@ -22,4 +31,5 @@ situation: contrat salarié . CDD: non contrat salarié . temps partiel: non contrat salarié . ATMP . taux réduit: oui + entreprise . association non lucrative: non période: année diff --git a/source/components/simulationConfigs/auto-entrepreneur.yaml b/source/components/simulationConfigs/auto-entrepreneur.yaml index 1becf55be..0b033cd41 100644 --- a/source/components/simulationConfigs/auto-entrepreneur.yaml +++ b/source/components/simulationConfigs/auto-entrepreneur.yaml @@ -1,21 +1,14 @@ objectifs: - entreprise . chiffre d'affaires - entreprise . charges - - auto entrepreneur . cotisations sociales + - auto entrepreneur . cotisations et contributions - impôt . impôt sur le revenu à payer - revenu net -questions: - - entreprise . catégorie d'activité - - entreprise . catégorie d'activité . service ou vente - - entreprise . catégorie d'activité . restauration ou hébergement - - entreprise . catégorie d'activité . libérale règlementée - - entreprise . ACCRE obtenu - - entreprise . année d'activité - questions à l'affiche: - Commerçant, artisan, ou libéral ?: entreprise . catégorie d'activité - Année d'activité: entreprise . année d'activité + Type d'activité: entreprise . catégorie d'activité + ACRE: entreprise . année d'activité + Charges: entreprise . charges situation: auto entrepreneur: oui diff --git a/source/components/simulationConfigs/indépendant.yaml b/source/components/simulationConfigs/indépendant.yaml index 97f18041c..cb4634d0e 100644 --- a/source/components/simulationConfigs/indépendant.yaml +++ b/source/components/simulationConfigs/indépendant.yaml @@ -1,24 +1,27 @@ objectifs: - - entreprise . chiffre d'affaires - - entreprise . charges - - indépendant . cotisations et contributions - - indépendant . revenu professionnel - - indépendant . impôt et contributions non déductibles - - revenu net + - icône: 🏢 + nom: Mon entreprise + objectifs: + - entreprise . chiffre d'affaires + - entreprise . charges + - icône: 👩‍💼 + nom: Mon revenu + objectifs: + - indépendant . revenu total du dirigeant + - indépendant . cotisations et contributions + - indépendant . revenu professionnel + - indépendant . impôt et contributions non déductibles + - revenu net questions: - - entreprise . catégorie d'activité - - entreprise . catégorie d'activité . service ou vente - - entreprise . catégorie d'activité . restauration ou hébergement - - entreprise . catégorie d'activité . libérale règlementée - # pour l'instant pas utilisées - # - entreprise . catégorie d'activité . libérale règlementée . type d'activité libérale règlementée - - entreprise . année d'activité - - situation personnelle . RSA + blacklist: + - entreprise . charges + - entreprise . rémunération du dirigeant questions à l'affiche: - Commerçant, artisan, ou libéral ?: entreprise . catégorie d'activité - Année d'activité: entreprise . année d'activité + Type d'activité: entreprise . catégorie d'activité + ACRE: entreprise . année d'activité + Charges: entreprise . charges situation: indépendant: oui diff --git a/source/components/simulationConfigs/rémunération-dirigeant.yaml b/source/components/simulationConfigs/rémunération-dirigeant.yaml index f032ce159..01c03ae74 100644 --- a/source/components/simulationConfigs/rémunération-dirigeant.yaml +++ b/source/components/simulationConfigs/rémunération-dirigeant.yaml @@ -3,30 +3,23 @@ titre: | objectifs: - revenu net + - protection sociale . retraite + - protection sociale . retraite . trimestres validés par an + - protection sociale . santé . indemnités journalières + - protection sociale . accidents du travail et maladies professionnelles questions: - entreprise . chiffre d'affaires - entreprise . charges - entreprise . catégorie d'activité - entreprise . catégorie d'activité . service ou vente - entreprise . catégorie d'activité . restauration ou hébergement - - entreprise . catégorie d'activité . libérale règlementée -bloquant: - - entreprise . chiffre d'affaires + situation: période: année + entreprise . année d'activité: non branches: - - nom: Auto-entrepreneur - situation: - auto entrepreneur: oui - indépendant: non - contrat salarié: non - - nom: Indépendant - situation: - indépendant: oui - auto entrepreneur: non - contrat salarié: non - nom: Assimilé salarié situation: auto entrepreneur: non @@ -34,3 +27,13 @@ branches: contrat salarié: oui contrat salarié . assimilé salarié: oui contrat salarié . ATMP . taux réduit: oui + - nom: Indépendant + situation: + indépendant: oui + auto entrepreneur: non + contrat salarié: non + - nom: Auto-entrepreneur + situation: + auto entrepreneur: oui + indépendant: non + contrat salarié: non diff --git a/source/components/simulationConfigs/salarié.yaml b/source/components/simulationConfigs/salarié.yaml index fdcf8dd79..b62d4bdfb 100644 --- a/source/components/simulationConfigs/salarié.yaml +++ b/source/components/simulationConfigs/salarié.yaml @@ -6,10 +6,12 @@ objectifs: - contrat salarié . salaire . net après impôt questions à l'affiche: - Cadre: contrat salarié . statut cadre - Temps partiel: contrat salarié . temps partiel - Localisation: établissement . localisation + Cadre: contrat salarié . statut cadre . choix statut cadre CDD: contrat salarié . CDD + Temps partiel: contrat salarié . temps partiel + Commune: établissement . localisation + JEI: contrat salarié . statut JEI + Association: entreprise . association non lucrative situation: contrat salarié: oui diff --git a/source/components/targetSelectionSelectors.js b/source/components/targetSelectionSelectors.js deleted file mode 100644 index d91523a89..000000000 --- a/source/components/targetSelectionSelectors.js +++ /dev/null @@ -1,32 +0,0 @@ -import { createSelector } from 'reselect' -import { - formattedSituationSelector, - targetNamesSelector, - parsedRulesSelector -} from 'Selectors/analyseSelectors' -import { findRuleByDottedName } from 'Engine/rules' - -export let firstStepCompletedSelector = createSelector( - [ - formattedSituationSelector, - targetNamesSelector, - parsedRulesSelector, - state => state.simulation?.config?.bloquant - ], - (situation, targetNames, parsedRules, bloquant) => { - if (!situation) { - return true - } - const situations = Object.keys(situation) - const allBlockingAreAnswered = - bloquant && bloquant.every(rule => situations.includes(rule)) - const targetIsAnswered = - targetNames && - targetNames.some( - targetName => - findRuleByDottedName(parsedRules, targetName)?.formule && - targetName in situation - ) - return allBlockingAreAnswered || targetIsAnswered - } -) diff --git a/source/components/ui/Button/button.css b/source/components/ui/Button/button.css index 6bf309906..793dcc257 100644 --- a/source/components/ui/Button/button.css +++ b/source/components/ui/Button/button.css @@ -5,7 +5,7 @@ .ui__.button, .ui__.inverted-button { - font-size: 1.1rem; + font-size: 1.2rem; display: inline-block; padding: 0.6rem 1.2rem; text-decoration: none; @@ -17,6 +17,7 @@ transition: all 0.15s; text-align: center; text-transform: uppercase; + font-family: 'Roboto', sans-serif; font-weight: normal; cursor: pointer; @@ -42,8 +43,8 @@ ); background-image: linear-gradient( 50deg, - rgba(39, 69, 195, 0.87) 5%, - var(--colour) 50%, + var(--colour) 5%, + var(--lightColour) 50%, rgba(255, 255, 255, 0.52) 55% ); background-size: 280%; @@ -53,15 +54,16 @@ background-image: linear-gradient( 50deg, rgba(39, 69, 195, 0.87) 5%, - rgb(41, 117, 209) 50%, + var(--colour) 50%, rgba(41, 117, 209, 0.9) 55% ); background-image: linear-gradient( 50deg, - rgba(39, 69, 195, 0.87) 5%, + var(--darkColour) -50%, var(--colour) 50%, - rgba(41, 117, 209, 0.9) 55% + var(--lightColour) 55% ); + color: white; } .ui__.button:not(:disabled):not(.simple):hover, @@ -74,6 +76,7 @@ .ui__.button.simple, .ui__.button.simple.small { border: none; + background: transparent; padding-left: 0; padding-right: 0; } @@ -81,9 +84,12 @@ .ui__.button.simple.selected { opacity: 0.8; } +.ui__.button.simple:not(:last-of-type) { + margin-right: 0.6em; +} .ui__.button.cta, .ui__.inverted-button.cta { - margin: 3rem auto; + margin: 1rem; display: inline-block; align-self: center; font-size: 120%; @@ -106,7 +112,7 @@ .ui__.dashed-button, .ui__.text-button { border: none; - display: inline-block; + display: inline; font-size: inherit; font-weight: inherit; font-family: inherit; @@ -183,26 +189,41 @@ .ui__.small.button, .ui__.small.inverted-button { - font-size: 80%; + font-size: 90%; line-height: 1rem; transition: all 0.08s; padding: 0.4rem 0.8rem; border-radius: 0.3rem; } - +.ui__.button-choice:first-of-type { + margin-top: 2rem; +} +.ui__.button-choice:last-of-type { + margin-bottom: 2rem; +} .ui__.button-choice { - display: block; + display: flex; + align-items: baseline; + flex-wrap: wrap; + padding: 1rem; + background: white; + color: var(--darkColour); + line-height: 2rem; margin: 1rem 0; - border: 1px solid; position: relative; - border-color: rgba(41, 117, 209); - opacity: 0.8 !important; border-radius: 0.3rem; text-decoration: none; font-size: 1.2rem; - transition: opacity, box-shadow 0.2s; + box-shadow: 0 1px 3px rgba(41, 117, 209, 0.12), + 0 1px 2px rgba(41, 117, 209, 0.24); + transition: box-shadow 0.2s; } +.ui__.button-choice small { + margin-left: 0.2rem; + flex-grow: 1; +} + .ui__.button-choice--soon { border-color: lightgray; color: gray; @@ -210,43 +231,43 @@ opacity: 0.8; pointer-events: none; cursor: default; + justify-content: flex-end; } + .ui__.button-choice--soon img { filter: saturate(0%); } .ui__.button-choice-label { - position: absolute; - top: 0; - font-size: 66%; - right: 0; - padding: 0.2rem 0.4rem; + font-size: 80%; + padding: 0 0.8rem; color: white; background: gray; + margin-left: 0.8rem; + + font-weight: 500; opacity: 0.8; - border-bottom-left-radius: 0.3rem; - border-top-right-radius: 0.3rem; + border-radius: 0.3rem; } .ui__.button-choice img { - margin-right: 0.5rem !important; - transition: transform 0.2s; + margin-right: 2rem !important; + margin-left: 0.5rem !important; + transform: scale(1.5) translateY(0.1em); } .ui__.button-choice:hover, .ui__.button-choice:focus { opacity: 1 !important; - box-shadow: 0 1px 3px rgba(41, 117, 209, 0.12), - 0 1px 2px rgba(41, 117, 209, 0.24); -} -.ui__.button-choice:hover img, -.ui__.button-choice:focus img { - transform: scale(1.5); + box-shadow: 0px 2px 4px -1px rgba(41, 117, 209, 0.2), + 0px 4px 5px 0px rgba(41, 117, 209, 0.14), + 0px 1px 10px 0px rgba(41, 117, 209, 0.12); } @media (min-width: 600px) { - .ui__.button-choice:hover::after, - .ui__.button-choice:focus::after { + .ui__.button-choice:not(.button-choice--soon)::after { content: '›'; position: absolute; - right: 40px; + right: 20px; + + font-size: 2rem; } } diff --git a/source/components/ui/Button/index.js b/source/components/ui/Button/index.js index 628e292c8..24c956647 100644 --- a/source/components/ui/Button/index.js +++ b/source/components/ui/Button/index.js @@ -1,18 +1,8 @@ /* @flow */ -import { React, T } from 'Components' +import { React } from 'Components' import './button.css' import type { ElementConfig } from 'react' -export const SkipButton = (props: ElementConfig<'button'>) => ( - -) - export const LinkButton = (props: ElementConfig<'button'>) => (
{this.state.displayExplanations && this.props.explanations && ( - +
{this.props.explanations}
-
+ )} ) diff --git a/source/components/ui/InfoBulle.css b/source/components/ui/InfoBulle.css new file mode 100644 index 000000000..d23835a5e --- /dev/null +++ b/source/components/ui/InfoBulle.css @@ -0,0 +1,44 @@ +.info-bulle__interrogation-mark { + color: var(--colour); + border: 1px solid var(--colour); + display: inline-block; + font-weight: bold; + user-select: none; + font-size: 75%; + width: 2.8ex; + border-radius: 50%; + margin-right: 0.2em; + padding: 1px; + text-align: center; + text-decoration: none; +} +.info-bulle__interrogation-mark:focus { + outline: 1px dotted var(--darkColour); +} +.info-bulle__text { + text-align: left; + position: absolute; + z-index: -1; + border: 1px solid var(--colour); + padding: 0.3rem; + min-width: 10rem; + font-weight: normal; + display: block; + border-radius: 3px; + font-family: 'Roboto'; + font-size: 0.8rem; + background-color: white; + transition: opacity 0.2s, transform 0.2s; + opacity: 0; + transform: translateY(-5px); +} + +.info-bulle__interrogation-mark:hover + .info-bulle__text, +.info-bulle__interrogation-mark:focus + .info-bulle__text { + transform: translateY(1px); + z-index: 1; + opacity: 1; +} +.info-bulle__interrogation-mark:focus { + position: relative; +} diff --git a/source/components/ui/InfoBulle.js b/source/components/ui/InfoBulle.js new file mode 100644 index 000000000..a2f26eb3c --- /dev/null +++ b/source/components/ui/InfoBulle.js @@ -0,0 +1,13 @@ +import React from 'react' +import './InfoBulle.css' + +export default function InfoBulle({ children }) { + return ( + + + ? + + {children} + + ) +} diff --git a/source/components/ui/Progress.css b/source/components/ui/Progress.css new file mode 100644 index 000000000..5ab4e179f --- /dev/null +++ b/source/components/ui/Progress.css @@ -0,0 +1,11 @@ +.progress__container { + height: 0.2rem; + background-color: var(--lighterColour); + overflow: hidden; +} +.progress__bar { + height: 100%; + transition: width 0.2s; + min-width: 6px; + background-color: var(--colour); +} diff --git a/source/components/ui/Progress.js b/source/components/ui/Progress.js new file mode 100644 index 000000000..ba6ea7890 --- /dev/null +++ b/source/components/ui/Progress.js @@ -0,0 +1,10 @@ +import React from 'react' +import './Progress.css' + +export default function Progress({ progress, style, className }) { + return ( +
+
+
+ ) +} diff --git a/source/components/ui/SchemeCard.css b/source/components/ui/SchemeCard.css deleted file mode 100644 index 0981cf121..000000000 --- a/source/components/ui/SchemeCard.css +++ /dev/null @@ -1,141 +0,0 @@ -.scheme-card__container { - min-width: 20rem; - max-width: 26rem; - margin: 1rem; - flex: 1; -} -.scheme-card__container:not(.is-IE) { - display: flex; - flex-direction: column; -} - -.scheme-card__inside { - flex: 1; -} -.scheme-card__inside:not(.is-IE) { - display: flex; - align-items: center; - flex-direction: column; -} -.scheme-card__header { - text-align: center; -} -.scheme-card__icon { - font-size: 2rem; -} -.scheme-card__title { - margin: 0.5rem 0; -} -.scheme-card__subtitle { - color: var(--grayColour); - margin-top: 1rem; - margin-bottom: 1rem; -} -.scheme-card__top-text { - text-transform: uppercase; - text-align: center; - margin: -1rem -1rem 1rem; - align-self: stretch; - font-size: 0.8rem; - font-family: 'IBM Plex Sans', sans-serif; - padding: 0.5rem; -} -.scheme-card__top-text--hidden { - visibility: hidden; -} -.scheme-card__top-text--featured { - color: var(--colour); - border-bottom: 1px solid var(--colour); -} -.scheme-card__top-text--disabled { - color: var(--grayColour); - border-bottom: 1px solid #d4d4d5; -} -.scheme-card__content { - flex: 1; - align-self: stretch; - margin-top: 1rem; -} -.scheme-card__cta { - text-align: center; -} -.scheme-card__amount { - display: flex; - align-self: stretch; - align-items: center; - margin-top: 1rem; -} - -.scheme-card__amount p { - margin: 0rem; -} -.scheme-card__amount-separator { - flex: 1; -} -@media (max-width: 800px) { - .scheme-card__title::before { - content: '▶'; - font-size: 1rem; - margin-right: 0.6rem; - transition: transform 0.3s; - } - .scheme-card__title--unfold::before { - transform: rotate(90deg); - } - - .scheme-card__title { - position: relative; - display: flex; - align-items: center; - font-weight: 500; - order: -1; - } - .scheme-card__icon { - margin-left: 0.3rem; - flex: 1; - text-align: right; - font-size: 1.6rem; - } - .scheme-card__subtitle { - margin: 0; - font-size: 1.2rem; - } - .scheme-card__container { - margin: 0; - } - .scheme-card__container--featured { - order: -1; - } - .scheme-card__container--disabled { - order: 1; - margin-top: 2rem; - } - .scheme-card__header { - display: flex; - flex-wrap: wrap; - align-items: center; - cursor: pointer; - justify-content: flex-start; - font-size: 1rem; - } - .scheme-card__amount { - flex-direction: row; - display: flex; - align-items: center; - width: 100%; - } - .scheme-card__amount p { - margin: 0; - } - .scheme-card__amount + p { - margin: 0; - text-align: center; - } - .scheme-card__cta:not(.scheme-card__cta--visible) { - display: none; - } - - .scheme-card__content:not(.scheme-card__content--visible) { - display: none; - } -} diff --git a/source/components/ui/SchemeCard.js b/source/components/ui/SchemeCard.js deleted file mode 100644 index 8d9877748..000000000 --- a/source/components/ui/SchemeCard.js +++ /dev/null @@ -1,118 +0,0 @@ -/* @flow */ -import classnames from 'classnames' -import { isNil } from 'ramda' -import React, { useState } from 'react' -import emoji from 'react-easy-emoji' -import Animate from 'Ui/animate' -import { isIE } from '../../utils' -import AnimatedTargetValue from './AnimatedTargetValue' -import './SchemeCard.css' -import type { Node } from 'react' -type Props = { - title: Node, - subtitle: Node, - amount: number, - modifier?: { - stared?: boolean, - inactive?: boolean - }, - features: Array, - amountDesc: Node, - onSchemeChoice: () => void, - onAmountClick: () => void, - disabled?: ?Node, - featured?: Node, - icon: string -} -function SchemeCard({ - title, - subtitle, - amount, - amountDesc, - onSchemeChoice, - icon, - disabled, - onAmountClick, - featured, - features -}: Props) { - const [descriptionVisibility, setDescriptionVisibility] = useState(false) - const toggleDescriptionVisibility = () => - setDescriptionVisibility(!descriptionVisibility) - - return ( -
-
- {featured || disabled || 'nop'} -
-
-
- {emoji(icon)} -

- {title} -

-

{subtitle}

-
- {!isNil(amount) && ( - -
- {amountDesc} : - -

- {disabled ? ( - 'CA dépassé' - ) : ( - - )} -

-
-
- )} -
    - {features.map((feature, index) => ( -
  • {feature}
  • - ))} -
-

- -

-
-
- ) -} - -export default SchemeCard diff --git a/source/components/ui/Typography.css b/source/components/ui/Typography.css index 82dcf17ae..c15e30b91 100644 --- a/source/components/ui/Typography.css +++ b/source/components/ui/Typography.css @@ -25,30 +25,34 @@ html { body { font-weight: 400; color: #040e19; + color: var(--darkColour); font-family: 'Roboto', sans-serif; } h1 { + margin-top: 2rem; margin-bottom: 1rem; - margin-top: 1.5rem; - font-size: 2.3rem; + font-size: 1.9rem; + line-height: 3rem; } h2 { - margin-bottom: 1rem; - margin-top: 1.5rem; - font-size: 1.5rem; -} -h3 { - font-size: 1.5rem; -} -h4 { - margin-top: 1rem; + margin-top: 2rem; margin-bottom: 1rem; font-size: 1.3rem; } +h3 { + margin-top: 1rem; + margin-bottom: 0.6rem; + font-size: 1.1rem; +} +h4 { + margin-top: 1rem; + margin-bottom: 0.6rem; + font-size: 1.1rem; +} h5 { font-size: 1.1rem; - font-style: italic; + font-weight: normal; } h6 { font-size: 1rem; @@ -61,9 +65,9 @@ h3, h4, h5, h6 { - font-family: 'IBM Plex Sans', sans-serif; - font-weight: 300; - line-height: initial; + color: var(--darkColour); + font-family: 'Montserrat', sans-serif; + font-weight: 600; } button { @@ -76,8 +80,9 @@ ul { margin: 0 0 0.6rem; } p.ui__.lead { - font-size: 150%; - font-weight: 300; + font-size: 120%; + line-height: 2rem; + color: var(--darkColour); } ul { list-style: '› '; @@ -112,3 +117,10 @@ b { textarea { font-family: inherit; } + +small, +.ui__.notice { + color: rgba(0, 0, 0, 0.6); + color: var(--lighterTextColour); + font-size: 85%; +} diff --git a/source/components/ui/animate.js b/source/components/ui/animate.js index 510fbdbfb..3fa542395 100644 --- a/source/components/ui/animate.js +++ b/source/components/ui/animate.js @@ -39,6 +39,7 @@ export const fromBottom = ({ key={i} style={{ transform: y.interpolate(y => `translate3d(0, ${y}px,0)`), + ...style, ...inheritedStyle }}> @@ -66,7 +67,9 @@ export const fromTop = ({ `translate3d(0, ${y}px,0)`), + transform: y.interpolate(y => + y ? `translate3d(0, ${y}px,0)` : 'none' + ), ...style, ...inheritedStyle }}> diff --git a/source/components/ui/index.css b/source/components/ui/index.css index cd643e1ee..9a0e67bba 100644 --- a/source/components/ui/index.css +++ b/source/components/ui/index.css @@ -26,8 +26,9 @@ button { display: flex; align-items: center; justify-content: flex-end; - flex-wrap: wrap; - margin: 1rem 0; +} +.ui__.answer-group > * { + margin: 0.6rem 0 0 1rem !important; } @media (min-width: 500px) { .ui__.answer-group > :not(:last-child) { @@ -45,6 +46,13 @@ button { } } +.ui__.choice-group { + background-color: var(--lightestColour); + padding: 1rem 0; +} +section.ui__:not(:first-of-type) { + margin-top: 2rem; +} .ui__.container { width: 100%; max-width: 850px; @@ -54,18 +62,18 @@ button { padding-left: 0.6rem; } .ui__.container .ui__.full-width { - margin: 0 calc((850px - 100vw) / 2); + --margin: calc((850px - 100vw - 0.6rem) / 2); + margin-right: var(--margin); + margin-left: var(--margin); } @media (max-width: 850px) { .ui__.container .ui__.full-width { - margin: 0; + margin: 0 -0.6rem; } } -.ui__.notice { - font-size: 85%; - color: rgba(0, 0, 0, 0.6); - color: var(--lighterInverseTextColour); +.ui__ .colored-bg { + background: var(--lightestColour); } ul.ui__.no-bullet { list-style: none; diff --git a/source/components/utils/withColours.js b/source/components/utils/withColours.js index a5c0ce303..17822c1a4 100644 --- a/source/components/utils/withColours.js +++ b/source/components/utils/withColours.js @@ -57,7 +57,7 @@ const generateTheme = (themeColour?: ?string): ThemeColours => { let // Use the default theme colour if the host page hasn't made a choice colour = themeColour || '#2975D1', lightColour = lightenColour(colour, 10), - darkColour = lightenColour(colour, -10), + darkColour = lightenColour(colour, -20), lighterColour = lightenColour(colour, 45), lightestColour = lightenColour(colour, 100), darkestColour = lightenColour(colour, -100), @@ -68,7 +68,7 @@ const generateTheme = (themeColour?: ?string): ThemeColours => { textColour === '#ffffff' ? 'rgba(255, 255, 255, .6)' : 'rgba(0, 0, 0, .6)', - lighterTextColour = lightenTextColour(textColour), + lighterTextColour = darkColour + '99', lighterInverseTextColour = lightenTextColour(inverseTextColour), textColourOnWhite = textColour === '#ffffff' ? colour : '#333' diff --git a/source/engine/mecanismViews/Barème.js b/source/engine/mecanismViews/Barème.js index a562f1002..dd781f2bc 100644 --- a/source/engine/mecanismViews/Barème.js +++ b/source/engine/mecanismViews/Barème.js @@ -1,13 +1,13 @@ -import React from 'react' -import { Node, NodeValuePointer, formatNumber } from './common' -import { makeJsx } from '../evaluation' -import { Trans } from 'react-i18next' -import { trancheValue } from 'Engine/mecanisms/barème' -import './Barème.css' import classNames from 'classnames' import { ShowValuesConsumer } from 'Components/rule/ShowValuesContext' import withLanguage from 'Components/utils/withLanguage' +import { trancheValue } from 'Engine/mecanisms/barème' import { identity } from 'ramda' +import React from 'react' +import { Trans } from 'react-i18next' +import { makeJsx } from '../evaluation' +import './Barème.css' +import { formatNumber, Node, NodeValuePointer } from './common' export let BarèmeAttributes = ({ explanation, lazyEval = identity }) => ( <> diff --git a/source/engine/mecanisms.js b/source/engine/mecanisms.js index 5e85d20a3..c672d9732 100644 --- a/source/engine/mecanisms.js +++ b/source/engine/mecanisms.js @@ -1,63 +1,21 @@ -import { desugarScale } from 'Engine/mecanisms/barème' -import { decompose, devariateExplanation } from 'Engine/mecanisms/utils' -import { - add, - any, - aperture, - curry, - equals, - evolve, - filter, - find, - head, - is, - isEmpty, - isNil, - keys, - last, - map, - max, - mergeWith, - min, - path, - pipe, - pluck, - prop, - propEq, - reduce, - reduced, - reject, - sort, - subtract, - toPairs -} from 'ramda' -import React from 'react' -import { Trans } from 'react-i18next' -import 'react-virtualized/styles.css' -import { - bonus, - collectNodeMissing, - defaultNode, - evaluateArray, - evaluateNode, - evaluateObject, - makeJsx, - mergeAllMissing, - mergeMissing, - parseObject, - rewriteNode -} from './evaluation' -import Allègement from './mecanismViews/Allègement' -import Barème from './mecanismViews/Barème' -import BarèmeContinu from './mecanismViews/BarèmeContinu' -import { Node, SimpleRuleLink } from './mecanismViews/common' -import InversionNumérique from './mecanismViews/InversionNumérique' -import Product from './mecanismViews/Product' -import Somme from './mecanismViews/Somme' -import Variations from './mecanismViews/Variations' -import { disambiguateRuleReference, findRuleByDottedName } from './rules' -import { anyNull, val } from './traverse-common-functions' -import uniroot from './uniroot' +import { desugarScale } from 'Engine/mecanisms/barème'; +import { decompose, devariateExplanation } from 'Engine/mecanisms/utils'; +import { add, any, aperture, curry, equals, evolve, filter, find, head, is, isEmpty, isNil, keys, last, map, max, mergeWith, min, path, pipe, pluck, prop, propEq, reduce, reduced, reject, sort, subtract, toPairs } from 'ramda'; +import React from 'react'; +import { Trans } from 'react-i18next'; +import 'react-virtualized/styles.css'; +import { bonus, collectNodeMissing, defaultNode, evaluateArray, evaluateNode, evaluateObject, makeJsx, mergeAllMissing, mergeMissing, parseObject, rewriteNode } from './evaluation'; +import Allègement from './mecanismViews/Allègement'; +import Barème from './mecanismViews/Barème'; +import BarèmeContinu from './mecanismViews/BarèmeContinu'; +import { Node, SimpleRuleLink } from './mecanismViews/common'; +import InversionNumérique from './mecanismViews/InversionNumérique'; +import Product from './mecanismViews/Product'; +import Somme from './mecanismViews/Somme'; +import Variations from './mecanismViews/Variations'; +import { disambiguateRuleReference, findRuleByDottedName } from './rules'; +import { anyNull, val } from './traverse-common-functions'; +import uniroot from './uniroot'; /* @devariate = true => This function will produce variations of a same mecanism (e.g. product) that share some common properties */ export let mecanismVariations = (recurse, k, v, devariate) => { @@ -657,16 +615,17 @@ export let mecanismLinearScale = (recurse, k, v) => { } let tranches = desugarScale(recurse)(v['tranches']), objectShape = { - assiette: false + assiette: false, + multiplicateur: defaultNode(1) } - let effect = ({ assiette, tranches }) => { + let effect = ({ assiette, multiplicateur, tranches }) => { if (val(assiette) === null) return null let roundedAssiette = Math.round(val(assiette)) let matchedTranche = tranches.find( - ({ de: min, à: max }) => roundedAssiette >= min && roundedAssiette <= max + ({ de: min, à: max }) => roundedAssiette >= (val(multiplicateur) * min) && roundedAssiette <= (max * val(multiplicateur)) ) if (!matchedTranche) return 0 diff --git a/source/engine/mecanisms/barème.js b/source/engine/mecanisms/barème.js index d8d73aea8..a7b7c6754 100644 --- a/source/engine/mecanisms/barème.js +++ b/source/engine/mecanisms/barème.js @@ -1,10 +1,9 @@ -import { val } from 'Engine/traverse-common-functions' -import { decompose } from 'Engine/mecanisms/utils' +import { defaultNode, E, rewriteNode } from 'Engine/evaluation' import { mecanismVariations } from 'Engine/mecanisms' -import { has, evolve, sum, pluck } from 'ramda' -import { defaultNode, rewriteNode, E } from 'Engine/evaluation' - +import { decompose } from 'Engine/mecanisms/utils' import Barème from 'Engine/mecanismViews/Barème' +import { val } from 'Engine/traverse-common-functions' +import { evolve, has, pluck, sum } from 'ramda' export let desugarScale = recurse => tranches => tranches @@ -18,8 +17,14 @@ export let desugarScale = recurse => tranches => .map(evolve({ taux: recurse })) // This function was also used for marginal barèmes, but now only for linear ones -export let trancheValue = assiette => ({ de: min, à: max, taux, montant }) => - Math.round(val(assiette)) >= min && (!max || Math.round(val(assiette)) <= max) +export let trancheValue = (assiette, multiplicateur) => ({ + de: min, + à: max, + taux, + montant +}) => + Math.round(val(assiette)) >= min * val(multiplicateur) && + (!max || Math.round(val(assiette)) <= max * val(multiplicateur)) ? taux != null ? val(assiette) * val(taux) : montant diff --git a/source/engine/rules.js b/source/engine/rules.js index 93e529f56..099420ae7 100644 --- a/source/engine/rules.js +++ b/source/engine/rules.js @@ -52,7 +52,7 @@ export let enrichRule = rule => { defaultValue = rule['par défaut'], examples = rule['exemples'], icon = rule['icônes'], - shortDescription = rule['description courte'] + summary = rule['résumé'] return { ...rule, @@ -66,7 +66,7 @@ export let enrichRule = rule => { raw: rule, examples, icon, - shortDescription + summary } } catch (e) { console.log(e) @@ -247,7 +247,6 @@ export let translateAll = (translations, flatRules) => { 'titre', 'description', 'question', - 'description courte', 'sous-question', 'résumé', 'suggestions', diff --git a/source/images/logo.svg b/source/images/logo.svg new file mode 100644 index 000000000..8505ec959 --- /dev/null +++ b/source/images/logo.svg @@ -0,0 +1,218 @@ + + + + + + image/svg+xml + + + + + + + + + mon-entreprise_logo + + diff --git a/source/images/revenus.svg b/source/images/revenus.svg new file mode 100644 index 000000000..96052b880 --- /dev/null +++ b/source/images/revenus.svg @@ -0,0 +1 @@ +savings \ No newline at end of file diff --git a/source/locales/en.yaml b/source/locales/en.yaml index f094cd830..b2b9f39ff 100644 --- a/source/locales/en.yaml +++ b/source/locales/en.yaml @@ -58,6 +58,7 @@ Envoyez-nous un commentaire !: Send us a comment ! Qu'est-ce qui n'a pas été ?: What went wrong ? satisfaction-email-ou: To start a conversation with us, fill your email address or satisfaction-mailto: click here to directly write an email +Votre adresse e-mail: Your email address envoyer: send Rechercher: Search Règle non applicable: Not applicable @@ -101,7 +102,7 @@ Part salariale: Employee share Total des retenues: Total withheld Fiche de paie mensuelle: Monthly payslip Fiche de paie: Payslip -Détail annuel des cotisations: Annual detail of your contributions +Détail annuel des cotisations: Annual detail of my contributions Voir la répartition des cotisations: View contribution breakdown Cotisations: Contributions payslip: @@ -114,11 +115,16 @@ Faire une simulation personnalisée: Do a customized simulation custom-simulation: This is currently a <1>rough estimate based on a generic contract. French legislation provides for a multitude of special cases and specific rules which considerably modify the costs of recruitment. Effacer: Reset Continuer: Continue -CDI: Permanent -CDD: Fixed-term -Cadre: '"Cadre" status' -Temps partiel: Part time -Autres: Other situations +quicklinks: + CDI: Permanent + Commune: Town + JEI: Innovating company (JEI) + CDD: Fixed-term + Cadre: '"Cadre" status' + Temps partiel: Part time + Type d'activité: Activity type + Charges: Expenses + Autres questions: Other questions Mes réponses: My answers Voir mes réponses: See my answers simulation-end: @@ -245,7 +251,7 @@ entreprise: formulaire: - titre: Register your company online + titre: Register my company online description: <0>You can start your online registration process anytime, save it and come back to it as you wish.<1><0>Start registration process titre2: Recommended before starting your activity comptable: @@ -330,27 +336,14 @@ autoentrepreneur: description: > <0> The auto-entrepreneur benefits from a simplified scheme of declaration and payment, for which tax and social contributions - are based on the turnover achieved each month. Available for companies whose annual - turnover does not exceed €70,000 for services providers or €170,000 when the main activity - is the sale of goods, catering or the provision of housing. + are based on the turnover achieved each month. <1> - This is an interesting choice if: - - <2> - <0>You do not need a lot of capital and important expenses to run your activity - <1>You want to test the viability of your business - <2>You want the minimum amount of paperwork to get started - - <3> <0>Note: Some activities are excluded from this status (<2>see the list [fr]). Some activities are regulated with a qualification or a professional experience (<4>see the list [fr])). - - <4> - For all the other cases, it is advised to choose the standard status, which - is <1>Individual Business. - + + associés: page: titre: Number of partners to start a business in France @@ -415,11 +408,11 @@ sécu: choix: titre: What do you want to estimate? auto-entrepreneur: Estimate my remuneration as an auto-entrepreneur - dirigeant1: Your remuneration as a {{legalStatus}} director - dirigeant2: The director's remuneration + dirigeant1: My income as a {{legalStatus}} director + dirigeant2: My income as a company director employé: An employee's salary - -Votre entreprise: Your company +Mon entreprise: My company +Mon revenu: My income Ce n'est pas mon entreprise: This is not my company Simuler une embauche: Simulate a hire @@ -429,7 +422,7 @@ Simulateur de salaire: Employee salary simulation Exemples de simulation de salaire: Examples of salary simulations Quelques exemples de salaires: Some salary exemples Embauche: Hiring process -Entreprise Individuelle: Individual Business + listeformejuridique: page: titre: Legal status list for creating your company in France @@ -438,8 +431,7 @@ statut du dirigeant: description: This choice is important because it determines the director's Social Security scheme and coverage. Each option has legal implications, and leads to a different status when creating your company in France titre: Defining the director's status description: <0>This choice is important because it determines the director's Social Security scheme and coverage.<1><0><0>Salaried employee: The company director joins and is covered by France’s general Social Security scheme. Social Security contributions are calculated on the basis of the executive's actual pay and are paid monthly. Although more expensive, this scheme offers full social protection (except unemployment).<1><0>Self-employed: The company director joins and is covered by France’s self-employed scheme called « Sécurité sociale des indépendants ». Contributions due are generally calculated based on professional income as reported to the tax authorities. Although less expensive, this scheme provides basic social protection (additional options and private insurance are recommended). -Assimilé salarié: Assimilated salaried -Indépendant: Self-employed + gérant minoritaire: page: description: Some special rules apply depending on the amount of shares owned by the director and this can lead to a different status when creating your company in France @@ -522,7 +514,8 @@ path: indépendant: '/self-employed' auto-entrepreneur: '/auto-entrepreneur' salarié: '/salaried' - selection: '/scheme-selection' + selection: '/social-scheme-selection' + comparaison: '/social-scheme-comparaison' démarcheEmbauche: index: '/hiring-process' documentation: @@ -560,7 +553,6 @@ Plusieurs associés: Several partners Un seul associé: Only one partner Responsabilité limitée: Limited liability Sans responsabilité limitée: Without limited liability -Auto-entrepreneur: Auto-entrepreneur Pas en auto entrepreneur: Not in auto-entrepreneur Précédent: Previous @@ -580,14 +572,16 @@ Exemples: Examples Intégrer le simulateur: Integrate the simulator # Landing infrance -Que souhaitez-vous faire ?: What do you want to do? -Créer votre entreprise: Create your company -subtitle: The official guide for entrepreneurs -Connaître les démarches d'embauche: Know the hiring procedures -Estimer les cotisations et les taxes: Estimate contributions and taxes -Créer une entreprise: Create a company in France +Que désirez-vous faire ?: What do you want to do? +Créer mon entreprise: Create my company +landing: + title: The official assistant for entrepreneurs + subtitle: All the resources you need to develop your business, from legal status to hiring. + choix3: Know the hiring procedures + choix2: Simulate contributions and taxes <2>(company director or employee) + choix1: Create my company in France Déclarer mon activité d'économie collaborative: Declare my activity in the sharing economy -prochainement: soon +Prochainement: Soon Estimer les cotisations sociales pour une embauche: Estimate the social security contributions for a hiring À quoi servent mes cotisations ?: How are my contributions distributed? @@ -599,8 +593,9 @@ Accueil: Home newsletter: register: - description1: Do you want to have <2>official advice on creating a company and access the new features in preview? - description2: 'Register to our <1>monthly newsletter by leaving your email:' + titre: Stay informed + description: | + Subscribe to our monthly newsletter to receive <2>official advice on starting a business and access new features in advance. S'inscrire: Register simulationWarning: This is an estimate based on <2>purely theoretical data on turnover, charges and the single tax base without children, excluding any other income, which <5>cannot be the responsibility of the social security bodies concerned with regard to the actual declarations and calculations. @@ -609,8 +604,7 @@ Simulations personnalisées: Customized simulations indicationTempsPlein: in full-time gross salary equivalent auto-entreprise: auto-enterprise -SAS, SASU ou SARL minoritaires: SAS, SASU or SARL minority shareholders -EI, EURL, SARL ou SARL majoritaires: EI, EURL, SARL or SARL majority shareholders + Comparer les trois régimes: Compare the three schemes simulateurs: inversionFail: The amount entered is too small or results in an impossible situation, try another one @@ -620,12 +614,16 @@ simulateurs: line1: the turnover deducted from expenses goes to 100% in the director's remuneration line2: income tax is calculated for a single person without children and without other income. line3: the figures are indicative and do not replace the actual accounts of the Urssaf, impots.gouv.fr, etc + précision: + défaut: 'Refine the simulation by answering the following questions:' + faible: Low accuracy + moyenne: Medium accuracy + bonne: Good accuracy salarié: page: - titre: Official net and gross salary simulator + titre: 'Calculation of net and gross salary: official simulator' description: Estimate the contributions for an employee based on gross, net or "super gross" salary. All contributions from the general system and income tax are taken into account. Discover the counterparties guaranteed by social security'. - titre: Salary simulator - description: As soon as an employee's employment is declared and paid, he or she is covered by the general social security system (health, maternity, invalidity, old age, occupational disease and accidents) and unemployment. + titre: Income simulator for employees assimilé-salarié: page: titre: Official salary simulator for SASU and SAS directors @@ -644,11 +642,125 @@ simulateurs: titre: Official income simulator for auto-entrepreneur description: Estimate your income as an auto-entrepreneur based on your turnover. All contributions and income tax are taken into account. Official URSSAF simulator. titre: 'Auto-entrepreneur income simulator' + +selectionRégime: + page: + titre: Social scheme selection + titre: Which social scheme would you like to explore? + comparer: + titre: Not sure which one to choose? + description: The executive's social scheme has a very strong influence on the level of social protection and the perceived income. To help you see more clearly and choose the plan that suits you best, we have designed a quick comparator. + cta: Compare social schemes +comparaisonRégimes: + page: + titre: | + Self-employed, assimilated employee or auto-entrepreneur: discover the social scheme that best suits you + description: | + What is the best scheme for your situation? Discover their differences and simulate your income and retirement in one minute for each of the options. + titre: | + Self-employed, assimilated employee or <2>auto-entrepreneur: which scheme to choose? + description: | + When you create your company, the choice of legal status will determine to which social scheme the executive is affiliated. There are three different ones, each with its advantages and disadvantages. Thanks to this comparison, you will be able to select the one that best suits you. + AS: + tagline: The all-inclusive plan + indep: + tagline: A la carte protection + auto: + tagline: Start without risk + status: + legend: Possible legal status + AS: SAS, SASU or SARL with minority director + indep: + 1: EI, EIRL, EURL or SARL with majority director + 2: EI or EIRL + auto: Auto-entreprise + sécuritéSociale: | + <0> Social security + <1> General scheme <1>(Régime général) + <2> Self-employed scheme <1>(Sécurité sociale des indépendants) + AT: <0> Work-related accidents covered + assuranceMaladie: | + <0> Public health insurance <1>(medicines, care, hospitalizations) + <1> Same for all + mutuelle: | + <0> Additional health insurance <1>(mutuelle santé) + <1> Compulsory + <2> Highly recommended + indemnités: | + <0> Sickness allowances + plafondCA: | + <0> Turnover ceiling + <1>No + <2> + Yes<1>(€70,000 in services, €170,000 for sale of properties, food or accommodation) + + période: | + <0>Period + retraite: | + <0>Retirement pay + + comparaisonDétaillée: | + <0><0> View more information + + comptabilité: | + <0> Accounting, social, legal management.... + <1> Support strongly recommended <1>(chartered accountant, accountant, chartered management centre...) + <2> Simplified <1>(can be managed by the auto-entrepreneur) + + ACRE: | + <0>ACRE + <1>1 year<1>(partial contribution exemption) + <2>3 years<1>(application of reduced contribution rates) + déduction: | + <0> Deduction of expenses + <1>Yes <1>(tax regime of the actual) + <2>No <1>(but lump-sum deduction for calculating income tax) + simulationText: | + <0> + Compare my income, retirement pay and sickness allowance + + <1/> + <2>Start simulation + cotisations: | + <0> Payment of social contributions + <1> Monthly + <2> Monthly or quaterly advance <1>(with posterior regularization based on real income) + <3> Montly or quaterly + complémentaireDeductible: | + <0> Optional health and pension policies deductible + <1> Yes <1>(under certain conditions) + <2> Yes <1>("Madelin" Law) + revenuNetApresImpots: | + <0>Net income after taxes + revenuNetAvantImpots: | + <0>Net contribution income<1>(before income tax) + retraiteEstimation: + legend: | + <0>Retirement pay + <1>(before taxes) + infobulle: + AS: Pension calculated for 172 quarters contributed to the general scheme with no change in income. + indep: Pension calculated for 172 quarters contributed to the self-employed scheme with no change in income. + auto: Pension calculated for 172 quarters contributed as auto-entrepreneur with no change in income. + cotisationMinimale: | + <0> Minimum contributions + + seuil: | + <0> Minimum income for eligibility for benefits + <1>Yes + <2> No <1>(mandatory minimum contributions) + <3>Yes + titreSelection: | + Create my company as: + J'ai compris: understood +trimestres validés: validated quarters Année d'activité: Years of activity Commerçant, artisan, ou libéral ?: Trader, craftsman, or liberal? Revenir à la documentation: Go back to documentation Voir le code source: See the source code -Quel régime souhaitez-vous explorer ?: Which social scheme would you like to explore? +pour les accidents de trajet/travail et maladie pro: for commuting accidents, work accidents and professional illness +jour: day +Pas implémenté: Not implemented diff --git a/source/reducers/rootReducer.js b/source/reducers/rootReducer.js index b962ca76f..02b186aa6 100644 --- a/source/reducers/rootReducer.js +++ b/source/reducers/rootReducer.js @@ -1,13 +1,22 @@ /* @flow */ -import { compose, defaultTo, isNil, lensPath, over, set, uniq, without } from 'ramda'; -import reduceReducers from 'reduce-reducers'; -import { combineReducers } from 'redux'; +import { + compose, + defaultTo, + isNil, + lensPath, + over, + set, + uniq, + without +} from 'ramda' +import reduceReducers from 'reduce-reducers' +import { combineReducers } from 'redux' // $FlowFixMe -import { reducer as formReducer } from 'redux-form'; -import i18n from '../i18n'; -import inFranceAppReducer from './inFranceAppReducer'; -import storageReducer from './storageReducer'; +import { reducer as formReducer } from 'redux-form' +import i18n from '../i18n' +import inFranceAppReducer from './inFranceAppReducer' +import storageReducer from './storageReducer' import type { Action } from 'Types/ActionsTypes' function explainedVariable(state = null, { type, variableName = null }) { @@ -37,16 +46,6 @@ function situationBranch(state = null, { type, id }) { } } -function conversationStarted(state = false, action: Action) { - switch (action.type) { - case 'START_CONVERSATION': - return true - case 'RESET_SIMULATION': - return false - default: - return state - } -} function activeTargetInput(state = null, { type, name }) { switch (type) { case 'SET_ACTIVE_TARGET_INPUT': @@ -99,13 +98,8 @@ function conversationSteps( priorityNamespace: state.priorityNamespace } if (name === 'unfold') { - // if a step had already been unfolded, bring it back ! return { - foldedSteps: [ - ...without([step], state.foldedSteps), - ...(state.unfoldedStep ? [state.unfoldedStep] : []) - ], - + foldedSteps: without([step], state.foldedSteps), unfoldedStep: step, priorityNamespace: state.priorityNamespace } @@ -171,7 +165,6 @@ export default reduceReducers( currentExample, situationBranch, hiddenControls, - conversationStarted, activeTargetInput, inFranceApp: inFranceAppReducer }) diff --git a/source/règles/base.yaml b/source/règles/base.yaml index 2457212ef..8a4ce584d 100644 --- a/source/règles/base.yaml +++ b/source/règles/base.yaml @@ -739,9 +739,7 @@ niveau: avertissement message: | Le salaire saisi est inférieur au SMIC. - solution: - cible: contrat salarié . temps partiel - texte: Est-ce un temps partiel ? + - si: toutes ces conditions: - brut de base [mensuel] > 10000 @@ -876,6 +874,13 @@ références: décret: https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000037833206 +- nom: SMIC horaire + formule: 10.03 + format: euros + références: + décret: https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000037833206 + service-public.fr: https://www.service-public.fr/particuliers/vosdroits/F2300 + - espace: contrat salarié nom: SMIC période: flexible @@ -987,7 +992,7 @@ - espace: contrat salarié . salaire nom: net après impôt titre: Salaire net après impôt - résumé: Versé sur son compte bancaire + résumé: Versé sur le compte bancaire question: Quel est le revenu net du salarié après impôt ? type: salaire format: euros @@ -1327,7 +1332,7 @@ nom: total titre: Total chargé question: Quel est la rémunération chargée ? - résumé: Dépensé par l'employeur + résumé: Dépensé par l'entreprise type: salaire format: euros période: flexible @@ -2578,7 +2583,7 @@ - espace: impôt nom: revenu abattu par défaut période: flexible - description: Dans le cas général, l'impôt est calculé après l'application d'un abattement forfaitaire fixe. Chacun peut néanmoins opter pour la déclaration de ses *frais réels*, qui viendront remplacer ce forfait par défaut. + description: Dans le cas général, l'impôt est calculé apr��s l'application d'un abattement forfaitaire fixe. Chacun peut néanmoins opter pour la déclaration de ses *frais réels*, qui viendront remplacer ce forfait par défaut. formule: allègement: assiette: @@ -2693,6 +2698,7 @@ Autrement dit, c'est ce que vous gagnez à la fin sur votre compte en banque. formule: revenu net d'impôt - entreprise . charges non déductibles + - espace: entreprise nom: année d'activité question: Quel est l'âge de l'entreprise en année d'activité ? @@ -2704,13 +2710,12 @@ Pour les auto-entreprises, cette réduction est même prolongée pendant un total de 3 ans, de façon dégressive. formule: une possibilité: - choix obligatoire: oui possibilités: - première année - deuxième année - troisième année - régime de croisière - par défaut: régime de croisière + par défaut: non - espace: entreprise . année d'activité nom: première année @@ -2737,8 +2742,59 @@ - revenu net - sinon: rémunération totale du dirigeant + charges +- espace: entreprise + + nom: chiffre d'affaires de société + période: flexible + formule: + somme: + - rémunération totale du dirigeant / rémunération du dirigeant + - charges + +- espace: entreprise + nom: rémunération du dirigeant + description: | + C'est la part du chiffre d'affaires après charges qui est allouée à la rémunération du dirigeant. Plus cette part est élevée, plus la rémunération du dirigeant augmente, et plus le bénéfice de l'entreprise diminue. + question: Quelle part du chiffre d'affaires après charge est allouée à la rémunération du dirigeant ? + format: pourcentage + par défaut: 1 + +- espace: entreprise + nom: bénéfice + période: flexible + formule: chiffre d'affaires - charges dont rémunération dirigeant + +- espace: entreprise + nom: résultat net + résumé: Ce qu'il reste après impôt sur les sociétés + période: flexible + formule: bénéfice - impôt sur les sociétés + +- espace: entreprise + nom: impôt sur les sociétés + période: année + formule: + barème: + assiette: bénéfice + tranches: + - en-dessous de: 38120 + taux: 15% + - de: 38120 + à: 500000 + taux: 28% + - au-dessus de: 500000 + taux: 33.3% + références: + fiche service-public.fr: https://www.service-public.fr/professionnels-entreprises/vosdroits/F23575 + +- espace: entreprise + nom: charges dont rémunération dirigeant + période: flexible + formule: charges + rémunération totale du dirigeant + - espace: entreprise nom: rémunération totale du dirigeant + format: euros description: C'est la rémunération "super-brute" du dirigeant, qui inclut toutes les cotisations sociales à payer. C'est aussi la valeur monétaire du travail du dirigeant. période: flexible formule: @@ -2747,13 +2803,14 @@ - indépendant . revenu total du dirigeant - auto entrepreneur . base des cotisations + - espace: entreprise nom: charges résumé: Toutes les dépenses nécessaires à l'entreprise question: Quelles sont les charges H.T. de l'entreprise (hors rémunération dirigeant) ? description: | - Ce sont les dépenses de l'entreprise engagées dans l'intérêt de celle-ci, hors rémunération du dirigeant. Pour les sociétés et entreprises hors auto entrepreneur, ces charges sont dites déductibles du résultat : l'entreprise ne paiera pas de cotisations ou impôt dessus. Pour la auto entrepreneur, elles ne sont pas déductibles : l'entrepreneur les paie avec son salaire personnel net de cotisation et de revenu. + Ce sont les dépenses de l'entreprise engagées dans l'intérêt de celle-ci, hors rémunération du dirigeant. Pour les sociétés et entreprises hors auto entrepreneur, ces charges sont dites déductibles du résultat : l'entreprise ne paiera pas de cotisations ou impôt dessus. Pour l'auto entrepreneur, elles ne sont pas déductibles : l'entrepreneur les paie avec son salaire personnel net de cotisation et de revenu. Nous ne traitons pas encore la TVA : les charges sont à renseigner hors taxe. @@ -2813,6 +2870,7 @@ résumé: Après cotisations et charges question: Quel est votre revenu professionnel ? période: flexible + format: euros description: | C'est le revenu net de cotisations du travailleur indépendant. @@ -2832,7 +2890,7 @@ nom: catégorie d'activité question: Quelle est votre catégorie d'activité ? description: Votre catégorie d'activité va déterminer une grande partie des calculs de cotisation, contribution et impôt. - par défaut: libérale + par défaut: commerciale ou industrielle formule: une possibilité: choix obligatoire: oui @@ -3054,28 +3112,37 @@ format: euros période: flexible -- espace: indépendant +- espace: entreprise nom: rattachement libéral règlementé description: | - Les entreprises libérales non règlementées créées avant 2019 étaient rattachées aux règlementées pour le calcul des cotisations sociales. Depuis 2019 ce n'est plus le cas, elles sont rattachées aux artisans-commerçants, donc dépendent de la sécurité sociale des indépendants. + Les entreprises libérales non règlementées créées étaient rattachées aux règlementées pour le calcul des cotisations sociales. Depuis 2018 ce n'est plus le cas pour les auto-entrepreneur (2019 pour les entreprise individuelles). Elles sont maintenant rattachées aux artisans-commerçants, donc dépendent de la sécurité sociale des indépendants. références: article de loi (chercher "travailleurs indépendants créant leur activité"): https://www.legifrance.gouv.fr/eli/loi/2017/12/30/CPAX1725580L/jo/texte#JORFARTI000036339157 formule: une de ces conditions: - - entreprise . catégorie d'activité . libérale règlementée - toutes ces conditions: + - ≠ contrat salarié + - entreprise . catégorie d'activité . libérale règlementée + - toutes ces conditions: + - entreprise . année d'activité - entreprise . année d'activité != 'première année' - entreprise . catégorie d'activité = 'libérale' + - indépendant + - toutes ces conditions: + - entreprise . année d'activité + - entreprise . année d'activité != 'première année' + - entreprise . année d'activité != 'deuxième année' + - entreprise . catégorie d'activité = 'libérale' + - auto entrepreneur - période: flexible - format: euros + période: aucune - espace: indépendant . cotisations et contributions . cotisations nom: maladie période: flexible formule: variations: - - si: rattachement libéral règlementé + - si: entreprise . rattachement libéral règlementé alors: libérale règlementée - sinon: artisans commerçants libéraux @@ -3111,9 +3178,9 @@ - espace: indépendant . cotisations et contributions . cotisations nom: indemnités journalières maladie titre: Maladie 2 - description: Cotisations pour les indémnités journalières des indépendants. Si l'état de santé des artisans, commerçants, industriels et conjoints collaborateurs nécessite un arrêt de travail, une part de leur ancien revenu leur sera versé. + description: Cotisations pour les indemnités journalières des indépendants. Si l'état de santé des artisans, commerçants, industriels et conjoints collaborateurs nécessite un arrêt de travail, une part de leur ancien revenu leur sera versé. période: flexible - non applicable si: rattachement libéral règlementé + non applicable si: entreprise . rattachement libéral règlementé formule: multiplication: assiette: maladie . assiette @@ -3201,7 +3268,7 @@ période: année formule: variations: - - si: rattachement libéral règlementé + - si: entreprise . rattachement libéral règlementé alors: multiplication: assiette: assiette @@ -3245,7 +3312,7 @@ note: Pour les professions libérales, nous avons retenu un des 8 régimes de retraite, celui de la CIPAV, la caisse interprofessionnelle. formule: variations: - - si: rattachement libéral règlementé + - si: entreprise . rattachement libéral règlementé alors: barème linéaire: assiette: revenu professionnel @@ -3367,6 +3434,9 @@ - espace: indépendant nom: revenu total du dirigeant + question: Quel est le revenu total du dirigeant ? + résumé: Dépensé par l'entreprise + format: euros période: flexible formule: somme: @@ -3411,9 +3481,11 @@ formule: variations: - si: - une de ces conditions: - - entreprise . catégorie d'activité . service ou vente = 'vente de biens' - - entreprise . catégorie d'activité . restauration ou hébergement + toutes ces conditions: + - entreprise . catégorie d'activité != 'libérale' + - une de ces conditions: + - entreprise . catégorie d'activité . service ou vente = 'vente de biens' + - entreprise . catégorie d'activité . restauration ou hébergement alors: 170000 - sinon: 70000 @@ -3422,12 +3494,13 @@ titre: Revenu net auto-entrepreneur formule: base des cotisations - cotisations et contributions période: flexible + format: euros - espace: auto entrepreneur nom: cotisations et contributions formule: somme: - - cotisations sociales + - cotisations - taxe pour frais de chambre - contribution formation professionnelle - entreprise . prélèvements obligatoires @@ -3435,7 +3508,8 @@ Imposition du micro-entrepreneur: https://www.service-public.fr/professionnels-entreprises/vosdroits/F23267 période: flexible -- espace: auto entrepreneur + +- espace: auto entrepreneur . cotisations et contributions nom: taxe pour frais de chambre période: flexible note: | @@ -3463,14 +3537,13 @@ - si: une de ces conditions: - entreprise . catégorie d'activité . service ou vente = 'vente de biens' - - entreprise . catégorie d'activité . restauration ou hébergement alors: 0.015% - si: entreprise . catégorie d'activité . libérale règlementée alors: 0.2% - sinon: 0.44% -- espace: auto entrepreneur +- espace: auto entrepreneur . cotisations et contributions nom: contribution formation professionnelle titre: Contribution à la formation professionnelle période: flexible @@ -3492,8 +3565,8 @@ alors: 0.1% - sinon: 0 -- espace: auto entrepreneur - nom: cotisations sociales +- espace: auto entrepreneur . cotisations et contributions + nom: cotisations description: | Les cotisations sociales donnent à l'auto-entrepreneur accès à une protection sociale minimale : une retraite, des soins de santé, des allocations familiales, etc. @@ -3504,7 +3577,7 @@ formule: barème: assiette: base des cotisations - multiplicateur: ACRE . plafond + multiplicateur: plafond ACRE tranches: - en-dessous de: 1 taux: taux ACRE * taux de cotisation @@ -3513,7 +3586,32 @@ références: La protection sociale du micro-entrepreneur: https://bpifrance-creation.fr/encyclopedie/micro-entreprise-regime-auto-entrepreneur/fiscal-social-comptable/protection-sociale -- espace: auto entrepreneur . cotisations sociales +- espace: auto entrepreneur . cotisations et contributions . cotisations + nom: retraite complémentaire + description: Le montant total qui est alloué à la retraite complémentaire, utile pour estimer le montant total de la pension de retraite des auto-entrepreneurs + format: euros + # L'ACOSS ne veut pas communiquer sur le pourcentage des cotisations fléchés pour la retraite complémentaire pour les PL + non applicable si: entreprise . catégorie d'activité = 'libérale' + période: flexible + formule: + multiplication: + assiette: base des cotisations + taux: + variations: + - si: + une de ces conditions: + - entreprise . catégorie d'activité . service ou vente = 'vente de biens' + - entreprise . catégorie d'activité . restauration ou hébergement + alors: 2.04% + - si: + une de ces conditions: + - entreprise . catégorie d'activité = 'commerciale ou industrielle' + - entreprise . catégorie d'activité = 'artisanale' + alors: 3.50% + + + +- espace: auto entrepreneur . cotisations et contributions . cotisations nom: taux de cotisation description: | Les cotisations sociales de l'auto-entreprise sont simplifiées : il n'y a qu'une ligne unique dont le taux dépend de la catégorie d'activité. @@ -3533,13 +3631,15 @@ Pour les entreprises créées avant 2019, la réduction de cotisation ACRE s'appellait ACCRE et n'était pas automatique : il fallait notamment être indemnisé par pôle-emploi et faire la demande. par défaut: non -- espace: auto entrepreneur . cotisations sociales + +- espace: auto entrepreneur . cotisations et contributions . cotisations nom: taux ACRE période: flexible formule: 100% - réduction ACRE -- espace: auto entrepreneur . cotisations sociales +- espace: auto entrepreneur . cotisations et contributions . cotisations nom: réduction ACRE + titre: réduction ACRE applicable si: une de ces conditions: - entreprise . année d'activité = 'première année' @@ -3558,9 +3658,9 @@ références: Fiche URSSAF: https://www.urssaf.fr/portail/home/independant/je-beneficie-dexonerations/accre.html -- espace: auto entrepreneur . cotisations sociales . ACRE - nom: plafond - titre: Plafond ACRE +- espace: auto entrepreneur . cotisations et contributions . cotisations + nom: plafond ACRE + formule: plafond sécurité sociale temps plein / impôt . abattement . taux inversé période: flexible @@ -3608,7 +3708,7 @@ espace: protection sociale icônes: 👵 type: branche - description courte: Garantit en moyenne 60 à 70 % du dernier revenu d'activité après 65 ans. + résumé: Garantit en moyenne 60 à 70 % du dernier revenu d'activité après 65 ans. description: | Tous les salariés en France cotisent tout au long de leur vie professionnelle pour bénéficier d’un régime de retraite dès lors qu’ils ont l’âge de cesser leur activité. @@ -3624,14 +3724,287 @@ Simulez et gérez votre retraite sur [info-retraite.fr](https://www.info-retraite.fr/portail-info/home.html). références: + CNAV: https://www.lassuranceretraite.fr OCDE: https://read.oecd-ilibrary.org/social-issues-migration-health/pensions-at-a-glance-2017_pension_glance-2017-en#page135 INSEE: https://www.insee.fr/fr/statistiques/fichier/3549496/REVPMEN18_F1.21_niv-pauv-pers-agees.pdf + non applicable si: entreprise . rattachement libéral règlementé + + format: euros + période: flexible + formule: + somme: + - base + - complémentaire salarié + - complémentaire sécurité des indépendants + + note: | + Il s'agit d'une estimation a but purement indicatif, afin de comparer la retraite des différents régimes. + On se limite notamment aux hypothèses suivantes : + - On considère que le travailleur a pris sa retraite à taux plein, en cotisant le nombre de trimestres requis (172), ou en partant à l'âge taux plein (67 ans) + - On considère que le travailleur a eu le même revenu tout au long de sa carrière + - On considère que le travailleur est resté dans le même régime tout au long de sa carrière + - On ne prend pas en compte les minorations / majorations + - On ne prend pas en compte les caisses de retraite des professions libérales réglementées (les 10 sections de la Cnavpl et la Cnbf) + - On ne calcule pas le nombre de trimestres validés par année + + Ces limites seront amenées à évoluer au fur et à mesure du développement du simulateur + +- nom: base + espace: protection sociale . retraite + titre: pension de retraite de base + format: euros + période: flexible + formule: + multiplication: + plafond: plafond sécurité sociale temps plein + taux: taux de la pension + assiette: revenu moyen + références: + service-public.fr: https://www.service-public.fr/particuliers/vosdroits/F21552 + +- nom: taux de la pension + espace: protection sociale . retraite . base + description: Le taux appliqué, avec décote ou surcote en fonction du nombre de trimestres cotisés. + période: flexible + formule: + variations: + - si: trimestres validés par an = 0 + alors: 0% + - sinon: 50% + note: On ne prends pas en compte la décote du taux suite aux trimestres manquant. On considère donc que le cotisant part à taux plein, donc à 67 ans (ou avant si tous les trimestres sont validés). + références: + service-public.fr: https://www.service-public.fr/particuliers/vosdroits/F19666 + +- espace: protection sociale . retraite + nom: trimestres validés par an + période: aucune + format: nombre + formule: + le minimum de: + - somme: + - trimestres salarié + - trimestres indépendant + - trimestres auto entrepreneur + - 4 + + +- nom: trimestres salarié + période: aucune + applicable si: contrat salarié + format: nombre + espace: protection sociale . retraite . trimestres validés par an + formule: barème trimestres générique + +- nom: trimestres indépendant + période: aucune + applicable si: indépendant + format: nombre + espace: protection sociale . retraite . trimestres validés par an + formule: + variations: + - si: situation personnelle . RSA + alors: barème trimestres générique + - sinon: + le maximum de: + - 3 + - barème trimestres générique + +- nom: barème trimestres générique + espace: protection sociale . retraite . trimestres validés par an + format: nombre + période: aucune + formule: + variations: + - si: oui + alors: + barème linéaire: + assiette: revenu moyen [annuel] + multiplicateur: SMIC horaire + tranches: + - en-dessous de: 150 + montant: 0 + - de: 150 + à: 300 + montant: 1 + - de: 300 + à: 450 + montant: 2 + - de: 450 + à: 600 + montant: 3 + - au-dessus de: 600 + montant: 4 + références: + cnav.fr: https://www.legislation.cnav.fr/Pages/bareme.aspx?Nom=salaire_validant_un_trimestre_montant_bar + + +- nom: trimestres auto entrepreneur + applicable si: auto entrepreneur + espace: protection sociale . retraite . trimestres validés par an + format: nombre + période: aucune + description: Les seuils de chiffre d'affaires minimum pour la validation des trimestres pour la retraite en auto entrepreneur. En-dessous du montant minimum, vous n'aurez accès qu'à l'allocation de solidarité. + formule: + variations: + - si: entreprise . catégorie d'activité = 'libérale' + alors: + barème linéaire: + assiette: entreprise . chiffre d'affaires [annuel] + tranches: + - en-dessous de: 2880 + montant: 0 + - de: 2880 + à: 5062 + montant: 1 + - de: 5062 + à: 7266 + montant: 2 + - de: 7266 + à: 9675 + montant: 3 + - au-dessus de: 9675 + montant: 4 + - si: + une de ces conditions: + - entreprise . catégorie d'activité . service ou vente = 'vente de biens' + - entreprise . catégorie d'activité . restauration ou hébergement + alors: + barème linéaire: + assiette: entreprise . chiffre d'affaires [annuel] + tranches: + - en-dessous de: 4137 + montant: 0 + - de: 4137 + à: 7286 + montant: 1 + - de: 7286 + à: 10426 + montant: 2 + - de: 10426 + à: 20740 + montant: 3 + - au-dessus de: 20740 + montant: 4 + - sinon: + barème linéaire: + assiette: entreprise . chiffre d'affaires [annuel] + tranches: + - en-dessous de: 2412 + montant: 0 + - de: 2412 + à: 4239 + montant: 1 + - de: 4239 + à: 6071 + montant: 2 + - de: 6071 + à: 12030 + montant: 3 + - au-dessus de: 12030 + montant: 4 + références: + service-public.fr: https://www.service-public.fr/professionnels-entreprises/vosdroits/F23369 + + +- espace: protection sociale + nom: revenu moyen + description: Le revenu utilisé pour le calcul du montant des pensions de retraite et des indemnités journalières de sécurité sociale lors d'un arrêt de travail. + notes: Normalement, on prends le revenu moyen des 25 meilleures années pour la retraite et des 3 derniers mois pour les indémnités. Vu qu'on intègre pas la notions de temporalité avec notre simulateur, on simplifie en prenant le même. + format: euros + période: année + formule: + le maximum de: + - indépendant . revenu net de cotisations + - auto entrepreneur . impôt . revenu abattu + - contrat salarié . rémunération . brut + +- espace: protection sociale . retraite + nom: mois cotisés + formule: 172 * 3 + notes: On prends l'hypotèse d'une retraite à taux plein pour un travailleur né en 1973 ou après + format: euros + +- espace: protection sociale . retraite + nom: complémentaire salarié + formule: points acquis * valeur du point + période: année + références: + service-public.fr: https://www.service-public.fr/particuliers/vosdroits/F15396 + +- espace: protection sociale . retraite . complémentaire salarié + nom: valeur du point + formule: 1.2588 + période: année + format: euros + références: + service-public.fr: https://www.service-public.fr/particuliers/vosdroits/F15396 + agirc-arrco: https://www.agirc-arrco.fr/ressources-documentaires/chiffres-cles/ + +- espace: protection sociale . retraite . complémentaire salarié + nom: points acquis + formule: points acquis par mois * mois cotisés + période: aucune + références: + service-public.fr: https://www.service-public.fr/particuliers/vosdroits/F15396 + +- espace: protection sociale . retraite . complémentaire salarié + nom: points acquis par mois + période: mois + formule: contrat salarié . retraite complémentaire / prix d'achat du point + +- espace: protection sociale . retraite . complémentaire salarié + nom: prix d'achat du point + formule: 16.7226 + période: mois + format: euros + références: + service-public.fr: https://www.service-public.fr/particuliers/vosdroits/F15396 + +- espace: protection sociale . retraite + nom: complémentaire sécurité des indépendants + formule: points acquis * valeur du point + période: année + références: + secu-independants.fr: https://www.secu-independants.fr/retraite/calcul-retraite/retraite-complementaire/ + +- espace: protection sociale . retraite . complémentaire sécurité des indépendants + nom: valeur du point + formule: 1.187 + période: année + format: euros + références: + secu-independants.fr: https://www.secu-independants.fr/baremes/prestations-vieillesse-et-invalidite-deces + +- espace: protection sociale . retraite . complémentaire sécurité des indépendants + nom: points acquis + formule: points acquis par mois * mois cotisés + période: aucune + +- espace: protection sociale . retraite . complémentaire sécurité des indépendants + nom: points acquis par mois + période: mois + formule: + multiplication: + assiette: + somme: + - indépendant . cotisations et contributions . cotisations . retraite complémentaire + - auto entrepreneur . cotisations et contributions . cotisations . retraite complémentaire + facteur: 1 / prix d'achat du point + +- espace: protection sociale . retraite . complémentaire sécurité des indépendants + nom: prix d'achat du point + formule: 17.456 + période: mois + format: euros + notes: il s'agit du prix d'achat 2018 (la valeur pour 2019 sur le site secu-independants.fr est marquée comme N.C) + références: + secu-independants.fr: https://www.secu-independants.fr/baremes/baremes-2018/baremesprestations-maladie-maternite/?reg=ile-de-france-centre&ae=oui - nom: santé espace: protection sociale icônes: 🏥 type: branche - description courte: Couvre la plupart des soins de santé de la vie quotidienne et 100 % des maladies graves comme les séjours à l'hôpital. + résumé: Couvre la plupart des soins de santé de la vie quotidienne et 100 % des maladies graves comme les séjours à l'hôpital. description: | L’Assurance Maladie protège durablement la santé de chacun dans sa vie personnelle ou professionnelle. @@ -3641,7 +4014,7 @@ ## L'assurance maladie en France en quelques chiffres - **92 %** des dépenses de santé remboursées en moyenne par l'assurance maladie et la complémentaire - - **30 000 € / an / patient** : dépense de santé d'une personne atteinte de [mucoviscidose](https://fr.wikipedia.org/wiki/Mucoviscidose), entièrement prise en charge par la sécurité sociale + - **30 000 € / an / patient** : exemple de prise en charge complète pour une personne atteinte de mucoviscidose - **1 468 € / mois** : indémnité versée par la sécurité sociale pour un congé maternité (salaire moyen) - **82,4 ans** d’espérance de vie moyenne en france (dans le top 10 mondial 🏅) @@ -3649,11 +4022,77 @@ ameli.fr: https://assurance-maladie.ameli.fr/sites/default/files/ra-2017_agir-ensemble-proteger-chacun.pdf OCDE: https://read.oecd-ilibrary.org/social-issues-migration-health/health-at-a-glance-europe-2018_health_glance_eur-2018-en#page89 +- espace: protection sociale . santé + nom: indemnités journalières + description: >- + Les indemnités journalières vous sont versées par l'Assurance Maladie pour compenser + votre revenu pendant un arrêt de travail. Elles sont calculées à partir de votre revenu + brut et versées tous les 14 jours en moyenne. + # TODO : période : jour + période: aucune + format: euros + formule: + somme: + - indemnités journalières . auto entrepreneur + - indemnités journalières . indépendant + - indemnités journalières . salarié + +- espace: protection sociale . santé . indemnités journalières + nom: auto entrepreneur + applicable si: auto entrepreneur + période: aucune + format: euros + formule: + variations: + - si: revenu moyen [annuel] < 3919.20 + alors: 0 + - sinon: + le minimum de : + - multiplication: + assiette: revenu moyen [annuel] + facteur: 1 / 730 + - 55.51 + reférences: + - secu-independants.fr: https://www.secu-independants.fr/sante/indemnites-journalieres/montant-de-lindemnite + +- espace: protection sociale . santé . indemnités journalières + nom: indépendant + applicable si: indépendant + période: aucune + format: euros + formule: + le maximum de : + - 21 + - le minimum de : + - multiplication: + assiette: revenu moyen [annuel] + facteur: 1 / 730 + - 55.51 + reférences: + - secu-independants.fr: https://www.secu-independants.fr/sante/indemnites-journalieres/montant-de-lindemnite + +- espace: protection sociale . santé . indemnités journalières + nom: salarié + période: aucune + format: euros + notes: + Vu que le simulateur ne permet pas encore la conversion de période vers le jour, on multiplie le salaire moyen par 3 pour avoir le salaire trimestrielle, puis on le divise par 91.25, conformément à la fiche service-public.fr + applicable si: contrat salarié + formule: + multiplication: + assiette: revenu moyen [mensuel] + taux: 50% + facteur: 3 / 91.25 + plafond: 1.8 * contrat salarié . SMIC temps plein + reférences: + service-public.fr: https://www.service-public.fr/particuliers/vosdroits/F3053 + + - nom: assurance chômage espace: protection sociale icônes: 💸 type: assurance - description courte: Assure un revenu aux travailleurs à la recherche d'un nouvel emploi. + résumé: Assure un revenu aux travailleurs à la recherche d'un nouvel emploi. description: > Depuis 1958, l’Assurance chômage protège tous les salariés du privé et certains du secteur public lorsqu’ils perdent leur emploi. Elle leur verse une allocation et favorise leur retour à l’emploi grâce à des aides. @@ -3668,14 +4107,15 @@ - **51 %** des allocataires cumulent allocation et salaire références: + Pôle-emploi: https://www.pole-emploi.fr/accueil Unédic: https://www.unedic.org/a-propos/quest-ce-que-lassurance-chomage - ameli.fr: https://www.ameli.fr/simulateur/public/index.php/index/calcul - nom: famille espace: protection sociale icônes: 👶 type: branche - description courte: Offre une vie professionnelle et familiale équilibrée. Finance des crèches et divers services de garde d'enfants. + résumé: | + Assure des prestations en soutien aux familles : garde d'enfants, aide au logement... description: | Créée en 1945, la branche Famille est l’un des principaux acteurs de la politique familiale française. Actuellement, elle a deux missions prioritaires : - Aider les familles dans leur vie quotidienne, faciliter, en particulier, la conciliation entre vie familiale et vie professionnelle @@ -3688,8 +4128,8 @@ ## Les allocations familiales en France en quelques chiffres - **19 %** part des dépenses allouées à la petite enfance - - **900 € / mois**: montant de l'allocation aux adultes handicapés - - **75 %** des mères avec un enfant à charge travaillent (dont seulement 30% en temps partiel) + - **860 € / mois** : montant de l'allocation aux adultes handicapés + - **75 %** des mères avec un enfant à charge travaillent (dont 70% à temps plein) références: CAF: https://www.caf.fr/sites/default/files/plaquette branche famille francais.pdf @@ -3698,7 +4138,7 @@ - nom: accidents du travail et maladies professionnelles espace: protection sociale icônes: ☣️ - description courte: Offre une couverture complète des maladies ou accidents du travail. + résumé: Offre une couverture complète des maladies ou accidents du travail. description: | L’assurance AT/MP (accident du travail et maladie professionnelle) est la plus ancienne branche de la Sécurité sociale : elle relève de principes qui remontent à l’année 1898 et qui ont été repris dans la loi du 31 décembre 1946. @@ -3712,6 +4152,20 @@ En cas d’AT/MP, les soins médicaux et chirurgicaux sont remboursés intégralement dans la limite des tarifs de la Sécurité sociale. + période: mois + format: euros + applicable si: contrat salarié + formule: + le minimum de: + - multiplication: + assiette: revenu moyen [mensuel] + taux: 60% + facteur: 1 / 30.42 + - 202.78 + # TODO + # - 0.834% * plafond sécurité sociale temps plein [annuel] + + références: ameli.fr: https://www.ameli.fr/paris/entreprise/cotisations/mp-tarification-calculs-baremes/compte-mp service-public.fr (AT): https://www.service-public.fr/particuliers/vosdroits/F31881 @@ -3720,16 +4174,16 @@ - nom: formation espace: protection sociale icônes: 👩‍🎓 - description courte: Donne aux employés l'accès à la formation professionnelle. + résumé: Donne aux employés la possibilité de suivre des formations professionnelles. description: | La formation professionnelle permet à chaque personne, indépendamment de son statut, d’acquérir et d’actualiser ses connaissances et ses compétences, d’accroître son niveau de qualification et de favoriser son évolution professionnelle. - Pour avoir un compte rendu personnalisé de vos droits à la formation, rendez vous sur [www.moncompteactivite.gouv.fr](https://www.moncompteactivite.gouv.fr) + Pour avoir un compte-rendu personnalisé de vos droits à la formation, rendez-vous sur [www.moncompteactivite.gouv.fr](https://www.moncompteactivite.gouv.fr). - nom: autres espace: protection sociale icônes: 🔧 - description courte: Autres contributions au système social. + résumé: Autres contributions au système social. description: | Toutes les contributions transverses au système social. @@ -3738,7 +4192,7 @@ - nom: transport espace: protection sociale icônes: 🚌 - description courte: Permet de maintenir le prix d'un billet de transport en commun à un bas prix + résumé: Permet de maintenir le prix d'un billet de transport en commun à un bas prix description: | Cette contribution est reversée intégralement à l'[autorité organisatrice de la mobilité](https://fr.wikipedia.org/wiki/Autorit%C3%A9_organisatrice_de_la_mobilit%C3%A9) de la zone ou est implantée l'entreprise. Celle-ci peut ensuite l'utiliser pour subventionner les transports en commun existants ou pour développer de nouvelles infrastructures de transport (tramway, métro, bus...). diff --git a/source/règles/externalized.yaml b/source/règles/externalized.yaml index 74ac2b323..588b2126e 100644 --- a/source/règles/externalized.yaml +++ b/source/règles/externalized.yaml @@ -177,7 +177,7 @@ contrat salarié . ATMP . taux collectif ATMP: concerne en ligne sur [net-entreprise](http://www.net-entreprises.fr/html/compte-accident-travail.htm). - suggestions.en: 'atmp-2017' + suggestions.en: atmp-2017 suggestions.fr: atmp-2017 contrat salarié . CDD . événement: titre.en: Contract related event @@ -400,7 +400,7 @@ contrat salarié . CDD . congés non pris: '10': 10 contrôles.en: - si: congés non pris > congés dus en jours ouvrés - message: Attention, an employee acquires 2.08 working days off per month. + message: 'Attention, an employee acquires 2.08 working days off per month.' niveau: avertissement solution: cible: contrat salarié . CDD . durée contrat @@ -510,8 +510,8 @@ contrat salarié . CDD: - si: CDD niveau: information message: > - Remember that a fixed-term contract must always correspond to a temporary need of the company. - + Remember that a fixed-term contract must always correspond to a + temporary need of the company. contrôles.fr: - si: CDD niveau: information @@ -556,7 +556,7 @@ contrat salarié . salaire . brut de base: description.fr: > C'est le salaire *brut* régulier inscrit dans le contrat de travail. Il ne change jamais entre les mois et ne peut pas être modifié sans signature des - deux partis. + deux parties. Il ne comprend pas les indemnités, avantages sociaux, avantages en nature et @@ -584,7 +584,8 @@ contrat salarié . salaire . brut de base: - période = 'mois' niveau: information message: > - The monthly wage seized is high. Are you sure the calculation period isn't set to month instead of year? + The monthly wage seized is high. Are you sure the calculation period + isn't set to month instead of year? contrôles.fr: - si: toutes ces conditions: @@ -593,9 +594,6 @@ contrat salarié . salaire . brut de base: niveau: avertissement message: | Le salaire saisi est inférieur au SMIC. - solution: - cible: contrat salarié . temps partiel - texte: Est-ce un temps partiel ? - si: toutes ces conditions: - 'brut de base [mensuel] > 10000' @@ -604,6 +602,7 @@ contrat salarié . salaire . brut de base: message: > Le salaire mensuel saisi est élevé. Ne vous êtes-vous pas trompé de période de calcul ? + contrat salarié . salaire . brut de base . équivalent temps plein: titre.en: Full-time equivalent gross salary titre.fr: Salaire brut équivalent temps plein @@ -635,9 +634,9 @@ contrat salarié . avantages sociaux: company, and provided by private structures. They are subject to income taxes. description.fr: > - Ce sont les avantages sociaux payés par l'employeur. Ils sont spécifique à - l'entreprise, et fourni par des structure privées (mutuelle, assurance...). - Ils sont soumis à l'impots sur le revenus. + Ce sont les avantages sociaux payés par l'employeur. Ils sont spécifiques à + l'entreprise, et fournis par des structures privées (mutuelle, + assurance...). Ils sont soumis à l'impôt sur le revenu. titre.en: employee benefits titre.fr: avantages sociaux contrat salarié . avantages en nature: @@ -670,9 +669,11 @@ contrat salarié . avantages en nature . montant: question.en: What is the monthly amount of benefits in kind? question.fr: Quel est le montant des avantages en nature ? suggestions.en: + aucun: none nourriture: food véhicule: car suggestions.fr: + aucun: 0 nourriture: 80 véhicule: 260 contrat salarié . indemnités salarié: @@ -707,6 +708,9 @@ contrat salarié . plafond sécurité sociale: contrat salarié . SMIC temps plein: titre.en: full-time mimimum wage (SMIC) titre.fr: SMIC temps plein +SMIC horaire: + titre.en: 'hourly minimum wage (SMIC)' + titre.fr: SMIC horaire contrat salarié . SMIC: titre.en: minimum wage (SMIC) titre.fr: SMIC @@ -773,7 +777,7 @@ contrat salarié . salaire . net après impôt: titre.en: Net salary after income tax titre.fr: Salaire net après impôt résumé.en: Transfered on the bank account - résumé.fr: Versé sur son compte bancaire + résumé.fr: Versé sur le compte bancaire question.en: What is the net income of the employee after income tax? question.fr: Quel est le revenu net du salarié après impôt ? description.en: >- @@ -810,7 +814,7 @@ impôt . neutre . barème métropolitain: titre.fr: barème métropolitain impôt . neutre: titre.en: neutral income tax - titre.fr: Impôt neutre sur le revenu + titre.fr: Impôt sur le revenu au taux neutre description.en: >- This is the scale to be applied to the monthly taxable salary to obtain the tax to be paid monthly for employees who do not want to reveal their taxe @@ -829,8 +833,8 @@ contrat salarié . rémunération . total: titre.fr: Total chargé question.en: 'What is the monthly remuneration, contributions included ?' question.fr: Quel est la rémunération chargée ? - résumé.en: Spent by the employer - résumé.fr: Dépensé par l'employeur + résumé.en: Spent by the company + résumé.fr: Dépensé par l'entreprise description.en: >- It is the gross salary, plus the employer contributions. It is the total that the employer must in principle plan to pay to employ an employee, but @@ -1047,7 +1051,9 @@ contrat salarié . temps partiel . heures par semaine: - si: heures par semaine < 24 niveau: avertissement message: >- - The minimum number of hours per week is 24 and it is possible to go lower in some cases only. [More info](https://www.service-public.fr/particuliers/vosdroits/F32428). + The minimum number of hours per week is 24 and it is possible to go + lower in some cases only. [More + info](https://www.service-public.fr/particuliers/vosdroits/F32428). - si: heures par semaine > 35 niveau: avertissement message: The simulator does not yet manage overtime. @@ -1217,7 +1223,9 @@ contrat salarié . complémentaire santé . part employeur: contrôles.en: - si: part employeur < 50 niveau: avertissement - message: The employer's share of complementary health insurance must be at least 50%. + message: >- + The employer's share of complementary health insurance must be at least + 50%. contrôles.fr: - si: part employeur < 50 niveau: avertissement @@ -1250,7 +1258,8 @@ contrat salarié . complémentaire santé . forfait: contrôles.en: - si: 'complémentaire santé . forfait [mensuel] < 15' message: >- - Make sure that such an inexpensive health supplement covers the minimum care basket defined in the law. + Make sure that such an inexpensive health supplement covers the minimum + care basket defined in the law. niveau: avertissement contrôles.fr: - si: 'complémentaire santé . forfait [mensuel] < 15' @@ -1520,9 +1529,9 @@ impôt . revenu abattu par défaut: lump-sum allowance. However, anyone can opt for the declaration of its *real costs*, which will replace this default package. description.fr: >- - Dans le cas général, l'impôt est calculé après l'application d'un abattement - forfaitaire fixe. Chacun peut néanmoins opter pour la déclaration de ses - *frais réels*, qui viendront remplacer ce forfait par défaut. + Dans le cas général, l'impôt est calculé après l'application d'un + abattement forfaitaire fixe. Chacun peut néanmoins opter pour la déclaration + de ses *frais réels*, qui viendront remplacer ce forfait par défaut. titre.en: default reduced income titre.fr: revenu abattu par défaut impôt . impôt sur le revenu: @@ -1620,6 +1629,37 @@ entreprise . chiffre d'affaires: question.fr: Quel est votre chiffre d'affaires envisagé (H.T.) ? résumé.en: The amount of sales made résumé.fr: Le montant des ventes réalisées +entreprise . chiffre d'affaires de société: + titre.en: 'company turnover' + titre.fr: chiffre d'affaires de société +entreprise . rémunération du dirigeant: + description.en: > + This is the portion of revenue after expenses that is allocated to the executive's compensation. The higher this share, the higher the executive's compensation increases, and the lower the company's profit. + description.fr: > + C'est la part du chiffre d'affaires après charges qui est allouée à la + rémunération du dirigeant. Plus cette part est élevée, plus la rémunération + du dirigeant augmente, et plus le bénéfice de l'entreprise diminue. + question.en: >- + How much of the after-charge revenue is allocated to the executive's compensation? + question.fr: >- + Quelle part du chiffre d'affaires après charge est allouée à la rémunération + du dirigeant ? + titre.en: 'executive compensation' + titre.fr: rémunération du dirigeant +entreprise . bénéfice: + titre.en: 'profit' + titre.fr: bénéfice +entreprise . résultat net: + résumé.en: 'What remains after corporate income tax' + résumé.fr: Ce qu'il reste après impôt sur les sociétés + titre.en: net result + titre.fr: résultat net +entreprise . impôt sur les sociétés: + titre.en: corporate income tax + titre.fr: impôt sur les sociétés +entreprise . charges dont rémunération dirigeant: + titre.en: expenses of which executive compensation + titre.fr: charges dont rémunération dirigeant entreprise . rémunération totale du dirigeant: description.en: >- This is the "super gross" remuneration of the manager, which includes all @@ -1674,7 +1714,7 @@ entreprise . charges: Ce sont les dépenses de l'entreprise engagées dans l'intérêt de celle-ci, hors rémunération du dirigeant. Pour les sociétés et entreprises hors auto entrepreneur, ces charges sont dites déductibles du résultat : l'entreprise - ne paiera pas de cotisations ou impôt dessus. Pour la auto entrepreneur, + ne paiera pas de cotisations ou impôt dessus. Pour l'auto entrepreneur, elles ne sont pas déductibles : l'entrepreneur les paie avec son salaire personnel net de cotisation et de revenu. @@ -1716,7 +1756,7 @@ entreprise . charges non déductibles: sont pas déductibles. Par exemple, un auto-entrepreneur qui achète un ordinateur pour les besoins de sa société, le fera avec son revenu net. Il aura donc payé des cotisations sociales et l'impôt sur le revenu sur son CA - avant pouvoir l'utiliser pour s'acheter ce bien. + avant de pouvoir l'utiliser pour s'acheter ce bien. titre.en: non-deductible expenses titre.fr: charges non déductibles indépendant . cotisations et contributions . réduction ACRE: @@ -1912,7 +1952,6 @@ entreprise . catégorie d'activité . libérale règlementée: > Exemples de professions non-règlementées : développeur, historien, urbaniste... - contrôles.fr: - si: libérale règlementée niveau: avertissement @@ -1998,19 +2037,20 @@ indépendant . cotisations et contributions . cotisations: indépendant . cotisations et contributions: titre.en: all contributions titre.fr: cotisations et contributions -indépendant . rattachement libéral règlementé: +entreprise . rattachement libéral règlementé: description.en: > - The unregulated liberal companies created before 2019 were related to the - regulations for the calculation of social security contributions. Since - then, since 2019 this is no longer the case, they are attached to the - craftsmen-merchants, so they depend on the social security of the - self-employed. - description.fr: > - Les entreprises libérales non règlementées créées avant 2019 étaient - rattachées aux règlementées pour le calcul des cotisations sociales. Depuis - 2019 ce n'est plus le cas, elles sont rattachées aux artisans-commerçants, + !!Les entreprises libérales non règlementées créées étaient rattachées aux + règlementées pour le calcul des cotisations sociales. Depuis 2018 ce n'est + plus le cas pour les auto-entrepreneur (2019 pour les entreprise + individuelles). Elles sont maintenant rattachées aux artisans-commerçants, donc dépendent de la sécurité sociale des indépendants. - titre.en: attached to regulated liberal + description.fr: > + Les entreprises libérales non règlementées créées étaient rattachées aux + règlementées pour le calcul des cotisations sociales. Depuis 2018 ce n'est + plus le cas pour les auto-entrepreneur (2019 pour les entreprise + individuelles). Elles sont maintenant rattachées aux artisans-commerçants, + donc dépendent de la sécurité sociale des indépendants. + titre.en: '!!rattachement libéral règlementé' titre.fr: rattachement libéral règlementé indépendant . cotisations et contributions . cotisations . maladie: titre.en: health insurance @@ -2029,7 +2069,7 @@ indépendant . cotisations et contributions . cotisations . maladie . assiette: health of craftsmen, traders, industrialists and collaborating spouses requires a work stoppage, a portion of their former income will be paid. description.fr: >- - Cotisations pour les indémnités journalières des indépendants. Si l'état de + Cotisations pour les indemnités journalières des indépendants. Si l'état de santé des artisans, commerçants, industriels et conjoints collaborateurs nécessite un arrêt de travail, une part de leur ancien revenu leur sera versé. @@ -2079,6 +2119,10 @@ indépendant . cotisations et contributions . formation professionnelle: : titre.en: family allowances titre.fr: allocations familiales indépendant . revenu total du dirigeant: + question.en: 'What is the total income of the executive?' + question.fr: Quel est le revenu total du dirigeant ? + résumé.en: 'Spent by the company' + résumé.fr: Dépensé par l'entreprise titre.en: total income of the executive titre.fr: revenu total du dirigeant indépendant . impôt et contributions non déductibles: @@ -2104,7 +2148,8 @@ auto entrepreneur . base des cotisations: contrôles.en: - si: base des cotisations > plafond message: >- - Turnover threshold exceeded. [More information](/documentation/auto-entrepreneur/plafond) + Turnover threshold exceeded. [More + information](/documentation/auto-entrepreneur/plafond) niveau: avertissement contrôles.fr: - si: base des cotisations > plafond @@ -2140,13 +2185,13 @@ auto entrepreneur . revenu net de cotisations: auto entrepreneur . cotisations et contributions: titre.en: Contributions titre.fr: cotisations et contributions -auto entrepreneur . taxe pour frais de chambre: - titre.en: tax for chamber expenses +auto entrepreneur . cotisations et contributions . taxe pour frais de chambre: + titre.en: tax for chamber fees titre.fr: taxe pour frais de chambre -auto entrepreneur . contribution formation professionnelle: - titre.en: Contribution for professional training +? auto entrepreneur . cotisations et contributions . contribution formation professionnelle +: titre.en: Contribution to vocational training titre.fr: Contribution à la formation professionnelle -auto entrepreneur . cotisations sociales: +auto entrepreneur . cotisations et contributions . cotisations: description.en: > Social security contributions give the self-employed entrepreneur access to a minimum social protection: a pension, health care, social security, social @@ -2173,10 +2218,18 @@ auto entrepreneur . cotisations sociales: Depuis janvier 2019, toute nouvelle auto-entreprise peut bénéficier de l'ACRE, une réduction de cotisations, dégressive sur 3 ans. - titre.en: social contributions - titre.fr: cotisations sociales -auto entrepreneur . cotisations sociales . taux de cotisation: - description.en: > + titre.en: contributions + titre.fr: cotisations +? auto entrepreneur . cotisations et contributions . cotisations . retraite complémentaire +: description.en: >- + The total amount that is allocated to the supplementary pension, useful to estimate the total amount of the retirement pension for auto-entrepreneurs + description.fr: >- + Le montant total qui est alloué à la retraite complémentaire, utile pour + caluler la retraite des auto entrepreneurs + titre.en: supplementary pension + titre.fr: retraite complémentaire +? auto entrepreneur . cotisations et contributions . cotisations . taux de cotisation +: description.en: > The social contributions of the self-employed are simplified: there is no than a single line whose rate depends on the category of activity. description.fr: > @@ -2197,18 +2250,21 @@ entreprise . ACCRE obtenu: indemnisé par pôle-emploi et faire la demande. titre.en: ACCRE obtained titre.fr: ACCRE obtenu -auto entrepreneur . cotisations sociales . ACRE: - titre.en: ACRE rate - titre.fr: Taux ACRE +auto entrepreneur . cotisations et contributions . cotisations . taux ACRE: + titre.en: '!!taux ACRE' + titre.fr: taux ACRE +auto entrepreneur . cotisations et contributions . cotisations . réduction ACRE: + titre.en: '!!réduction ACRE' + titre.fr: réduction ACRE description.en: >- - This rate reduces the amount of social security contributions for the - auto-entrepreneur to help him in his first years of activity. + !!Ce taux peut dans certains cas réduire le montant des cotisations sociales + de l'auto-entrepreneur pour l'aider dans ses premières année d'activité. description.fr: >- - Ce taux réduit le montant des cotisations sociales de l'auto-entrepreneur - pour l'aider dans ses premières année d'activité. -auto entrepreneur . cotisations sociales . ACRE . plafond: + Ce taux peut dans certains cas réduire le montant des cotisations sociales + de l'auto-entrepreneur pour l'aider dans ses premières année d'activité. +auto entrepreneur . cotisations et contributions . cotisations . plafond ACRE: titre.en: ACRE upper limit - titre.fr: Plafond ACRE + titre.fr: plafond ACRE auto entrepreneur . impôt . abattement: titre.en: allowance titre.fr: abattement @@ -2239,22 +2295,127 @@ protection sociale: training and transport. description.fr: > La protection sociale est composée de 5 branches principales : maladie, - famille, accidents du travail et maladie professionnelles, retraite et + famille, accidents du travail et maladies professionnelles, retraite et chômage. A cela s'ajoutent aussi les cotisations pour la formation professionnelle et le transport. titre.en: social welfare titre.fr: protection sociale protection sociale . retraite: + résumé.en: Guarantees on average 60 to 70% of the last income from employment after age 65. + résumé.fr: Garantit en moyenne 60 à 70 % du dernier revenu d'activité après 65 ans. description.en: "All employees in France contribute throughout their working lives to benefit from a pension plan as soon as they are old enough to stop working their activity.\n\nThe pension system is currently based on the principle of the \"distribution\". This means that asset contributions finance retirement pensions.\n\n## Retirement in France in a few figures\n - **2094 € / month**: Average standard of living for people over 65 (compared to the rest of the population, it is the highest in the OECD \U0001F947)\n - **25 years**: the average number of years spent in retirement (the highest in the OECD)\n - **75%**: the replacement rate as a percentage of net salary after full annuities\n\nPensions are the highest of social security contributions. It can be considered a deferred salary, since your contributions will provide you with income when you retire.\n" description.fr: "Tous les salariés en France cotisent tout au long de leur vie professionnelle pour bénéficier d’un régime de retraite dès lors qu’ils ont l’âge de cesser leur activité.\n\nLe système des retraites est actuellement fondé sur le principe de la « répartition ». Cela veut dire que les cotisations des actifs financent les pensions des retraités.\n\n## La retraite en France en quelques chiffres\n - ** 2094 € / mois** : Niveau de vie moyen des plus de 65 ans (en comparaison du reste de la population, c'est le plus élevé de l'OCDE \U0001F947)\n - **25 ans** : le nombre d'années passées en moyenne à la retraite (le plus élevé de l'OCDE \U0001F947)\n - **75 %** : le taux de remplacement en pourcentage du salaire net à taux plein\n\nLa retraite est la plus élevée des cotisations sociales. Elle peut être considérée comme un salaire différé, puisque vos cotisations vous assurerons un revenu futur.\n\nSimulez et gérez votre retraite sur [info-retraite.fr](https://www.info-retraite.fr/portail-info/home.html).\n" titre.en: pensions titre.fr: retraite +protection sociale . retraite . base: + titre.en: basic retirement pension + titre.fr: pension de retraite de base +protection sociale . retraite . base . taux de la pension: + description.en: >- + The rate applied, with a discount or surcharge depending on the number of quarters contributed. + description.fr: >- + Le taux appliqué, avec décote ou surcote en fonction du nombre de trimestre + cotisé. + titre.en: rate of the pension + titre.fr: taux de la pension +protection sociale . retraite . trimestres validés par an: + titre.en: quarters validated per year + titre.fr: trimestres validés par an +protection sociale . retraite . trimestres validés par an . trimestres salarié: + titre.en: employee quarters + titre.fr: trimestres salarié +? protection sociale . retraite . trimestres validés par an . trimestres indépendant +: titre.en: self-employed quarters + titre.fr: trimestres indépendant +? protection sociale . retraite . trimestres validés par an . barème trimestres générique +: titre.en: generic quarters scale + titre.fr: barème trimestres générique +? protection sociale . retraite . trimestres validés par an . trimestres auto entrepreneur +: description.en: >- + Minimum turnover thresholds for the validation of quarters for retirement as a self-employed entrepreneur. Below the minimum amount, you will only have access to the solidarity allowance. + description.fr: >- + Les seuils de chiffre d'affaires minimum pour la validation des trimestres + pour la retraite en auto entrepreneur. En-dessous du montant minimum, vous + n'aurez accès qu'à l'allocation de solidarité. + titre.en: auto-entrepreneur quarters + titre.fr: trimestres auto entrepreneur +protection sociale . revenu moyen: + description.en: >- + The income used to calculate the amount of retirement pensions and daily social security allowances during a work stoppage. + description.fr: >- + Le revenu utilisé pour le calcul du montant des pensions de retraite et des + indemnités journalières de sécurité sociale lors d'un arrêt de travail. + titre.en: 'average income' + titre.fr: revenu moyen +protection sociale . retraite . mois cotisés: + titre.en: 'contributed months' + titre.fr: mois cotisés +protection sociale . retraite . complémentaire salarié: + titre.en: 'supplementary pension for employees' + titre.fr: complémentaire salarié +protection sociale . retraite . complémentaire salarié . valeur du point: + titre.en: 'value of the point' + titre.fr: valeur du point +protection sociale . retraite . complémentaire salarié . points acquis: + titre.en: 'acquired points' + titre.fr: points acquis +protection sociale . retraite . complémentaire salarié . points acquis par mois: + titre.en: 'acquired points per month' + titre.fr: points acquis par mois +protection sociale . retraite . complémentaire salarié . prix d'achat du point: + titre.en: 'buying cost of the point' + titre.fr: prix d'achat du point +protection sociale . retraite . complémentaire sécurité des indépendants: + titre.en: 'supplementary pension for self-employed' + titre.fr: complémentaire sécurité des indépendants +? protection sociale . retraite . complémentaire sécurité des indépendants . valeur du point +: titre.en: 'value of the point' + titre.fr: valeur du point +? protection sociale . retraite . complémentaire sécurité des indépendants . points acquis +: titre.en: 'acquired points' + titre.fr: points acquis +? protection sociale . retraite . complémentaire sécurité des indépendants . points acquis par mois +: titre.en: acquired points per month + titre.fr: points acquis par mois +? protection sociale . retraite . complémentaire sécurité des indépendants . prix d'achat du point +: titre.en: buying cost of the point + titre.fr: prix d'achat du point protection sociale . santé: + résumé.en: >- + !!Couvre la plupart des soins de santé de la vie quotidienne et 100 % des + maladies graves comme les séjours à l'hôpital. + résumé.fr: >- + Couvre la plupart des soins de santé de la vie quotidienne et 100 % des + maladies graves comme les séjours à l'hôpital. description.en: "Health Insurance protects the health of everyone on a long-term basis - in their personal or professional life - by acting on behalf of everyone.\n\nIn concrete terms, it supports 60 million insured throughout their lives, by taking charge of their care regardless of their resources, situation or state of health. It thus guarantees universal access to rights and allows access to health care.\n\nThanks to it, you are covered on most health care services. In the event of a serious or long-term illness, 100% of the care is reimbursed.\n\n## Health insurance in France in a few figures\n - **92%** of health expenses reimbursed by health and supplementary insurance (one of the highest in the world)\n - **€30,000 / year / patient** : health expenditure of a person with [cystic fibrosis](https://en.wikipedia.org/wiki/Cystic_fibrosis), **fully covered by social security**\n - **11.7%** of GDP spent on health expenditure, the 5th of the OECD\n - **82.4 years** of average life expectancy in France (in the top 10 worldwide \U0001F3C5)\n - **€1,468 / month** : allowance paid by the social security system for maternity leave (average salary)\n" - description.fr: "L’Assurance Maladie protège durablement la santé de chacun dans sa vie personnelle ou professionnelle.\n\nConcrètement, elle accompagne 60 millions d’assurés tout au long de leur vie, en prenant en charge leurs soins quels que soient leurs ressources, leur situation ou leur état de santé. Elle garantit ainsi un accès universel aux droits et elle permet l’accès aux soins.\n\nGrâce à elle, vous êtes couvert sur la plupart des soins de santé. En cas de maladie grave ou de longue durée, 100 % des soins sont remboursés.\n\n## L'assurance maladie en France en quelques chiffres\n - **92 %** des dépenses de santé remboursées en moyenne par l'assurance maladie et la complémentaire\n - **30 000 € / an / patient** : dépense de santé d'une personne atteinte de [mucoviscidose](https://fr.wikipedia.org/wiki/Mucoviscidose), entièrement prise en charge par la sécurité sociale\n - **1 468 € / mois** : indémnité versée par la sécurité sociale pour un congé maternité (salaire moyen)\n - **82,4 ans** d’espérance de vie moyenne en france (dans le top 10 mondial \U0001F3C5)\n" + description.fr: "L’Assurance Maladie protège durablement la santé de chacun dans sa vie personnelle ou professionnelle.\n\nConcrètement, elle accompagne 60 millions d’assurés tout au long de leur vie, en prenant en charge leurs soins quels que soient leurs ressources, leur situation ou leur état de santé. Elle garantit ainsi un accès universel aux droits et elle permet l’accès aux soins.\n\nGrâce à elle, vous êtes couvert sur la plupart des soins de santé. En cas de maladie grave ou de longue durée, 100 % des soins sont remboursés.\n\n## L'assurance maladie en France en quelques chiffres\n - **92 %** des dépenses de santé remboursées en moyenne par l'assurance maladie et la complémentaire\n - **30 000 € / an / patient** : exemple de prise en charge complète pour une personne atteinte de mucoviscidose\n - **1 468 € / mois** : indémnité versée par la sécurité sociale pour un congé maternité (salaire moyen)\n - **82,4 ans** d’espérance de vie moyenne en france (dans le top 10 mondial \U0001F3C5)\n" titre.en: healthcare titre.fr: santé +protection sociale . santé . indemnités journalières: + description.en: >- + Daily allowances are paid to you by the Health Insurance to compensate for your income during a work stoppage. They are calculated on the basis of your gross income and paid every 14 days on average. + description.fr: > + Les indemnités journalières vous sont versées par l'Assurance Maladie pour + compenser + + votre revenu pendant un arrêt de travail. Elles sont calculées à partir de + votre revenu + + brut et versées tous les 14 jours en moyenne. + titre.en: 'Daily allowances' + titre.fr: indemnités journalières +protection sociale . santé . indemnités journalières . auto entrepreneur: + titre.en: 'auto entrepreneur' + titre.fr: auto entrepreneur +protection sociale . santé . indemnités journalières . indépendant: + titre.en: 'self employed' + titre.fr: indépendant +protection sociale . santé . indemnités journalières . salarié: + titre.en: 'employee' + titre.fr: salarié protection sociale . assurance chômage: + résumé.en: 'Provides income for workers looking for a new job.' + résumé.fr: Assure un revenu aux travailleurs à la recherche d'un nouvel emploi. description.en: > Since 1958, the Unemployment Insurance has been protecting all private and some public sector employees when they lose their jobs. It provides them @@ -2299,6 +2460,11 @@ protection sociale . assurance chômage: titre.en: unemployment insurance titre.fr: assurance chômage protection sociale . famille: + résumé.en: > + Provides services in support of families: childcare, housing assistance, etc. + résumé.fr: > + Assure des prestations en soutien aux familles : garde d'enfants, aide au + logement... description.en: > Created in 1945, the Family branch is one of the main actors of French family policy. Currently, it has two priority missions: @@ -2332,16 +2498,21 @@ protection sociale . famille: ## Les allocations familiales en France en quelques chiffres - **19 %** part des dépenses allouées à la petite enfance - - **900 € / mois**: montant de l'allocation aux adultes handicapés - - **75 %** des mères avec un enfant à charge travaillent (dont seulement 30% en temps partiel) + - **860 € / mois** : montant de l'allocation aux adultes handicapés + - **75 %** des mères avec un enfant à charge travaillent (dont 70% à temps plein) titre.en: family titre.fr: famille protection sociale . accidents du travail et maladies professionnelles: + résumé.en: Provides comprehensive coverage for occupational diseases or accidents. + résumé.fr: Offre une couverture complète des maladies ou accidents du travail. description.en: "Occupational injury and disease insurance (AT/MP) is the oldest branch of social security: it is based on principles dating back to 1898 and which were incorporated into the law of 31 December 1946.\n\n[\U0001F39E️ See video [fr]](https://www.youtube.com/watch?v=NaGI_deZJD8)\n\nThe AT/MP contribution covers the risks of accidents at work, commuting accidents and occupational diseases for employees covered by the general scheme.\n\nThis contribution is mandatory and is the sole responsibility of the employer.\n\nTo find out about occupational risks and set up preventive actions, the [AT/MP account [fr]](https://www.ameli.fr/paris/entreprise/cotisations/mp-tarification-calculs-baremes/compte-mp) is a service open to all companies in the general social security system\n\nIn the case of accidents at work, medical and surgical care is reimbursed at 100% on the basis of social security reimbursement (BRSS) within the limits of the Social Security rates.\n" description.fr: "L’assurance AT/MP (accident du travail et maladie professionnelle) est la plus ancienne branche de la Sécurité sociale : elle relève de principes qui remontent à l’année 1898 et qui ont été repris dans la loi du 31 décembre 1946.\n\n[\U0001F39E️ Voir la vidéo](https://www.youtube.com/watch?v=NaGI_deZJD8 )\n\nLa cotisation AT/MP couvre les risques accidents du travail, accidents de trajet et maladies professionnelles pour les salariés relevant du régime général.\n\nCette cotisation est obligatoire et à la charge exclusive de l’employeur.\n\nPour connaître les risques professionnels et mettre en place des actions de prévention, le [compte AT/MP](https://www.ameli.fr/paris/entreprise/cotisations/mp-tarification-calculs-baremes/compte-mp) est un service ouvert à toutes les entreprises du régime général de la Sécurité sociale.\n\nEn cas d’AT/MP, les soins médicaux et chirurgicaux sont remboursés intégralement dans la limite des tarifs de la Sécurité sociale.\n" titre.en: Work accidents / occupational diseases titre.fr: accidents du travail et maladies professionnelles protection sociale . formation: + résumé.en: >- + Gives employees the opportunity to take vocationnal training. + résumé.fr: Donne aux employés la possibilité de suivre des formations professionnelles. description.en: > Vocational training enables each person, regardless of their status, to acquire and update their knowledge and skills, to increase their level of @@ -2355,12 +2526,14 @@ protection sociale . formation: professionnelle. - Pour avoir un compte rendu personnalisé de vos droits à la formation, rendez - vous sur - [www.moncompteactivite.gouv.fr](https://www.moncompteactivite.gouv.fr) + Pour avoir un compte-rendu personnalisé de vos droits à la formation, + rendez-vous sur + [www.moncompteactivite.gouv.fr](https://www.moncompteactivite.gouv.fr). titre.en: training titre.fr: formation protection sociale . autres: + résumé.en: Other contributions to the social system. + résumé.fr: Autres contributions au système social. description.en: > Cross-cutting contributions to the social system. @@ -2380,6 +2553,9 @@ protection sociale . autres: titre.en: other titre.fr: autres protection sociale . transport: + résumé.en: >- + Keeps the price of a public transit ticket low + résumé.fr: Permet de maintenir le prix d'un billet de transport en commun à un bas prix description.en: > This contribution is paid in full to the [mobility authority](https://fr.wikipedia.org/wiki/Autorit%C3%A9_mobility_organiser%C3%A9) diff --git a/source/règles/sasu.yaml b/source/règles/sasu.yaml index 416d077be..4ba527f1f 100644 --- a/source/règles/sasu.yaml +++ b/source/règles/sasu.yaml @@ -1,3 +1,5 @@ +# Ce petit ensemble de règles a été historiquement utilisé pour tester l'externalisation du moteur, et est en train d'être réintégré progressivement dans la base centrale + - nom: chiffre affaires période: flexible format: euros diff --git a/source/selectors/analyseSelectors.js b/source/selectors/analyseSelectors.js index c29a84dea..9766da2b2 100644 --- a/source/selectors/analyseSelectors.js +++ b/source/selectors/analyseSelectors.js @@ -54,7 +54,21 @@ export let ruleDefaultsSelector = createSelector( rules => collectDefaults(rules) ) -export let targetNamesSelector = state => state.simulation?.config.objectifs +export let targetNamesSelector = state => { + let objectifs = state.simulation?.config.objectifs + if (!objectifs || !Array.isArray(objectifs)) { + return null + } + const targetNames = [].concat( + ...objectifs.map(objectifOrGroup => + typeof objectifOrGroup === 'string' + ? [objectifOrGroup] + : objectifOrGroup.objectifs + ) + ) + + return targetNames +} export let situationSelector = createDeepEqualSelector( getFormValues('conversation'), @@ -71,6 +85,31 @@ export let noUserInputSelector = createSelector( situation => !situation || isEmpty(dissoc('période', situation)) ) +export let firstStepCompletedSelector = createSelector( + [ + formattedSituationSelector, + targetNamesSelector, + parsedRulesSelector, + state => state.simulation?.config?.bloquant + ], + (situation, targetNames, parsedRules, bloquant) => { + if (!situation) { + return true + } + const situations = Object.keys(situation) + const allBlockingAreAnswered = + bloquant && bloquant.every(rule => situations.includes(rule)) + const targetIsAnswered = + targetNames && + targetNames.some( + targetName => + findRuleByDottedName(parsedRules, targetName)?.formule && + targetName in situation + ) + return allBlockingAreAnswered || targetIsAnswered + } +) + let validatedStepsSelector = createSelector( [ state => state.conversationSteps.foldedSteps, @@ -221,11 +260,11 @@ let currentMissingVariablesByTargetSelector = createSelector( export let nextStepsSelector = createSelector( [ currentMissingVariablesByTargetSelector, - state => state.simulation?.config.questions + state => state.simulation?.config.questions, + state => state.conversationSteps.foldedSteps ], - (mv, questions) => { - let nextSteps = getNextSteps(mv) - + (mv, questions, foldedSteps) => { + let nextSteps = difference(getNextSteps(mv), foldedSteps) if (questions && questions.blacklist) { return difference(nextSteps, questions.blacklist) } diff --git a/source/selectors/progressSelectors.js b/source/selectors/progressSelectors.js new file mode 100644 index 000000000..989fad64e --- /dev/null +++ b/source/selectors/progressSelectors.js @@ -0,0 +1,7 @@ +import { nextStepsSelector } from './analyseSelectors' + +export const simulationProgressSelector = state => { + const numberQuestionAnswered = state.conversationSteps.foldedSteps.length + const numberQuestionLeft = nextStepsSelector(state).length + return numberQuestionAnswered / (numberQuestionAnswered + numberQuestionLeft) +} diff --git a/source/selectors/regleSelectors.js b/source/selectors/regleSelectors.js index 7ab59da68..9ddf8065a 100644 --- a/source/selectors/regleSelectors.js +++ b/source/selectors/regleSelectors.js @@ -4,6 +4,7 @@ import { findRuleByDottedName } from 'Engine/rules' import { encodeRuleName } from 'Engine/rules.js' import { isNil } from 'ramda' import { createSelector } from 'reselect' +import { coerceArray } from '../utils' import { branchAnalyseSelector, flatRulesSelector, @@ -34,7 +35,7 @@ export const règleLocaliséeSelector: InputSelector< const localizedRule = findRuleByDottedName(localizedFlatRules, dottedName) if (!localizedRule) { throw new Error( - `[LocalizedRègleSelector] Impossible de trouver la règle "${dottedName}" dans les flatRules. Pensez à vérifier l'orthographe et que l'écriture est bien sous forme dottedName` + `[LocalizedRègleSelector] Impossible de trouver la règle "${dottedName}" dans les flatRules. Pensez à vérifier l'orthographe et que l'écriture est bien sous forme dottedName, et que la règles est bien calculée (dans les objectifs de la simulation)` ) } return { @@ -42,9 +43,7 @@ export const règleLocaliséeSelector: InputSelector< lien: encodeRuleName(dottedName), id: dottedName, - ...(localizedRule.shortDescription - ? { descriptionCourte: localizedRule.shortDescription } - : {}), + ...(localizedRule.summary ? { résumé: localizedRule.summary } : {}), ...(localizedRule.icon ? { icône: localizedRule.icon } : {}), ...(localizedRule.format ? { type: localizedRule.format } : {}) } @@ -67,10 +66,13 @@ export const règleValeurSelector: InputSelector< `[règleValeurSelector] L'analyse fournie ne doit pas être 'undefined' ou 'null'` ) } - const rule = - !Array.isArray(analysis) && // It's an array if we're in a comparative simulation. - (analysis.cache[dottedName] || - analysis.targets.find(target => target.dottedName === dottedName)) + const rule = coerceArray(analysis) + .map( + analysis => + analysis.cache[dottedName] || + analysis.targets.find(target => target.dottedName === dottedName) + ) + .filter(Boolean)[0] let valeur = rule && !isNil(rule.nodeValue) @@ -78,7 +80,6 @@ export const règleValeurSelector: InputSelector< : Array.isArray(situation) ? situation[0][dottedName] : situation[dottedName] - if (isNil(valeur)) { console.warn( `[règleValeurSelector] Impossible de trouver la valeur associée à la règle "${dottedName}". Pensez à vérifier l'orthographe et que l'écriture est bien sous forme dottedName. Vérifiez aussi qu'il ne manque pas une valeur par défaut à une règle nécessaire au calcul.` @@ -106,6 +107,9 @@ export const règleValeurSelector: InputSelector< return { type, + ...(rule && 'isApplicable' in rule + ? { applicable: rule.isApplicable } + : {}), valeur: type === 'string' ? règleLocalisée(`${dottedName} . ${valeur}`).nom @@ -125,11 +129,12 @@ export const règleAvecMontantSelector: InputSelector< const valeur = règleValeur(dottedName) if (!valeur || valeur.type !== 'euros') { throw new Error( - `[règleAvecMontantSelector] Le type de valeur de "${dottedName}" n'est pas celui d'un montant` + `[règleAvecMontantSelector] Le type de valeur de "${dottedName}" n'est pas celui d'un montant. \n Pour faire disparaitre cette erreur, ajouter la propriété 'format: euros' à cette règle ` ) } return { ...règleLocalisée(dottedName), + ...('applicable' in valeur ? { applicable: valeur.applicable } : {}), montant: valeur.valeur } } diff --git a/source/selectors/storageSelectors.js b/source/selectors/storageSelectors.js index 50aa65b69..0f1863b71 100644 --- a/source/selectors/storageSelectors.js +++ b/source/selectors/storageSelectors.js @@ -24,6 +24,5 @@ export const createStateFromSavedSimulation: ( conversationSteps: { foldedSteps: simulation.foldedSteps }, - conversationStarted: true, previousSimulation: null } diff --git a/source/sites/mon-entreprise.fr/App.js b/source/sites/mon-entreprise.fr/App.js index ada37929c..1ad8b24c5 100644 --- a/source/sites/mon-entreprise.fr/App.js +++ b/source/sites/mon-entreprise.fr/App.js @@ -34,7 +34,7 @@ import Sitemap from './pages/Dev/Sitemap' import Documentation from './pages/Documentation' import HiringProcess from './pages/HiringProcess' import Iframes from './pages/Iframes' -import Landing from './pages/Landing' +import Landing from './pages/Landing/Landing.js' import SocialSecurity from './pages/SocialSecurity' import { constructLocalizedSitePath } from './sitePaths' @@ -90,11 +90,14 @@ class InFranceRoute extends Component { let RouterSwitch = compose(withTranslation())(() => { return ( - - - - - + <> + {!inIframe() && } + + + + + + ) }) @@ -105,7 +108,6 @@ const App = compose(
{/* Passing location down to prevent update blocking */} - {!inIframe() && }
{!inIframe() &&
} diff --git a/source/sites/mon-entreprise.fr/favicon/android-chrome-192x192.png b/source/sites/mon-entreprise.fr/favicon/android-chrome-192x192.png new file mode 100644 index 000000000..f479301cd Binary files /dev/null and b/source/sites/mon-entreprise.fr/favicon/android-chrome-192x192.png differ diff --git a/source/sites/mon-entreprise.fr/favicon/android-chrome-512x512.png b/source/sites/mon-entreprise.fr/favicon/android-chrome-512x512.png new file mode 100644 index 000000000..c599f5428 Binary files /dev/null and b/source/sites/mon-entreprise.fr/favicon/android-chrome-512x512.png differ diff --git a/source/sites/mon-entreprise.fr/favicon/apple-touch-icon.png b/source/sites/mon-entreprise.fr/favicon/apple-touch-icon.png new file mode 100644 index 000000000..9912d73fb Binary files /dev/null and b/source/sites/mon-entreprise.fr/favicon/apple-touch-icon.png differ diff --git a/source/sites/mon-entreprise.fr/favicon/browserconfig.xml b/source/sites/mon-entreprise.fr/favicon/browserconfig.xml new file mode 100644 index 000000000..70cb989d3 --- /dev/null +++ b/source/sites/mon-entreprise.fr/favicon/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #da532c + + + diff --git a/source/sites/mon-entreprise.fr/favicon/favicon-16x16.png b/source/sites/mon-entreprise.fr/favicon/favicon-16x16.png new file mode 100644 index 000000000..2fb0b0a40 Binary files /dev/null and b/source/sites/mon-entreprise.fr/favicon/favicon-16x16.png differ diff --git a/source/sites/mon-entreprise.fr/favicon/favicon-32x32.png b/source/sites/mon-entreprise.fr/favicon/favicon-32x32.png new file mode 100644 index 000000000..73def5967 Binary files /dev/null and b/source/sites/mon-entreprise.fr/favicon/favicon-32x32.png differ diff --git a/source/sites/mon-entreprise.fr/favicon/favicon.ico b/source/sites/mon-entreprise.fr/favicon/favicon.ico new file mode 100644 index 000000000..65e6c0efd Binary files /dev/null and b/source/sites/mon-entreprise.fr/favicon/favicon.ico differ diff --git a/source/sites/mon-entreprise.fr/favicon/mstile-150x150.png b/source/sites/mon-entreprise.fr/favicon/mstile-150x150.png new file mode 100644 index 000000000..c25727728 Binary files /dev/null and b/source/sites/mon-entreprise.fr/favicon/mstile-150x150.png differ diff --git a/source/sites/mon-entreprise.fr/favicon/safari-pinned-tab.svg b/source/sites/mon-entreprise.fr/favicon/safari-pinned-tab.svg new file mode 100644 index 000000000..aebf9f447 --- /dev/null +++ b/source/sites/mon-entreprise.fr/favicon/safari-pinned-tab.svg @@ -0,0 +1,77 @@ + + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + + + + diff --git a/source/sites/mon-entreprise.fr/layout/Footer/Footer.css b/source/sites/mon-entreprise.fr/layout/Footer/Footer.css index 6f01d4253..ef6448624 100644 --- a/source/sites/mon-entreprise.fr/layout/Footer/Footer.css +++ b/source/sites/mon-entreprise.fr/layout/Footer/Footer.css @@ -1,12 +1,6 @@ -.footer-container { - margin-top: 3rem; -} .footer { - background-color: rgba(41, 117, 209, 0.133); - background-color: var(--lighterColour); - padding: 1rem 0; + margin-top: 5rem; } - .footer img { height: 2.5rem; } @@ -14,7 +8,6 @@ .footer a { text-decoration: none; } - #footerIcons { display: flex; margin: 2rem 0; @@ -23,10 +16,30 @@ #footerIcons a::after { display: none; } +.footer__newsletterContainer { + display: flex; + + justify-content: center; +} +@media (max-width: 800px) { + .footer__newsletterContainer { + flex-wrap: wrap; + } + .footer__registerContainer { + margin-left: 0rem; + margin-top: 1rem; + } +} + .footer__registerContainer { display: flex; - flex-direction: column; - margin-bottom: 2rem; + margin-left: 1rem; +} +.footer__registerContainer label { + text-transform: uppercase; + font-size: 85%; + color: var(--darkColour); + font-weight: 500; } .footer__registerField { display: flex; @@ -37,6 +50,11 @@ border-radius: 0.3rem; align-self: center; } +.footer__separator { + margin: 2rem 0; + border-top: 1px solid var(--lighterColour); + border-bottom: none; +} .footer__registerField > input[type='submit'] { border-top-left-radius: 0 !important; border-bottom-left-radius: 0 !important; diff --git a/source/sites/mon-entreprise.fr/layout/Footer/Footer.js b/source/sites/mon-entreprise.fr/layout/Footer/Footer.js index 40d199ec4..7e567414b 100644 --- a/source/sites/mon-entreprise.fr/layout/Footer/Footer.js +++ b/source/sites/mon-entreprise.fr/layout/Footer/Footer.js @@ -6,7 +6,6 @@ import LegalNotice from 'Components/LegalNotice' import usePersistingState from 'Components/utils/usePersistingState' import withSitePaths from 'Components/utils/withSitePaths' import withTracker from 'Components/utils/withTracker' -import urssafSvg from 'Images/urssaf.svg' import { compose, lensPath, view } from 'ramda' import React from 'react' import emoji from 'react-easy-emoji' @@ -16,7 +15,6 @@ import SocialIcon from 'Ui/SocialIcon' import i18n from '../../../../i18n' import { hrefLangLink } from '../../sitePaths' import './Footer.css' -import betaGouvSvg from './images/logo-betagouv.svg' import Integration from './Integration' import Privacy from './Privacy' @@ -60,63 +58,59 @@ const Footer = ({ tracker, t, sitePaths }) => { /> ))} - view(lens, sitePaths))} - />