Merge pull request #530 from betagouv/comparaison-régime-v2

Comparaison régime améliorée
pull/569/head v1.0.0
Johan Girod 2019-06-12 17:57:33 +02:00 committed by GitHub
commit 2b49965940
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
137 changed files with 4889 additions and 3412 deletions

View File

@ -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')
})
})

View File

@ -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')
})
})

View File

@ -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'
)
})
})

View File

@ -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é')

View File

@ -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'
)
})
})

View File

@ -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()
})

View File

@ -5,6 +5,28 @@
<base href="/" />
<meta name="viewport" content="initial-scale=1" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link
rel="apple-touch-icon"
sizes="180x180"
href="/favicon/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/favicon/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/favicon/favicon-16x16.png"
/>
<link rel="shortcut icon" href="/favicon/favicon.ico" />
<meta name="msapplication-TileColor" content="#da532c" />
<meta name="msapplication-config" content="/favicon/browserconfig.xml" />
<meta
name="google-site-verification"
content="y1B_PVRQAlMoLd7La3AlOt_0Ja8Lp-lrkoXGat9-uMA"
@ -38,7 +60,7 @@
/>
<!-- data-helmet pour que React Helmet puisse écraser ce meta par défaut -->
<link
href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,500,600|IBM+Plex+Sans:300,400"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,500,600|Montserrat:400,600"
rel="stylesheet"
type="text/css"
/>
@ -188,7 +210,7 @@
style="position: fixed; top: 0; left: 0; bottom: 0; right: 0; display: none; background-color: white"
>
<div
style="margin: 100px auto; max-width: 800px; text-align: center; font-family: 'IBM Plex Sans', sans-serif; font-weight: 300;"
style="margin: 100px auto; max-width: 800px; text-align: center; font-family: 'Montserrat', sans-serif; font-weight: 300;"
>
<img
src="images/marianne.svg"
@ -199,7 +221,8 @@
Votre navigateur n'est plus supporté.
</h1>
<h2>
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.
</h2>
<br />
<br />

View File

@ -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"
}
]
}

View File

@ -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"

View File

@ -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": {

View File

@ -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<StepAction> => 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 }

View File

@ -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;
}

View File

@ -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<PropTypes>)

View File

@ -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;
}
}

View File

@ -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) => (
<Animate.fromBottom config={config.gentle}>
<div className="comparative-targets ui__ full-width">
<AutoEntrepreneur
branchIndex={0}
plafondDépassé={
plafondAutoEntrepreneurDépassé &&
plafondAutoEntrepreneurDépassé.message
}
/>
<AssimiléSalarié branchIndex={2} />
<Indépendant branchIndex={1} />
</div>
</Animate.fromBottom>
))
const Indépendant = connectRègles('Indépendant')(
({
revenuDisponible,
branchIndex,
setSituationBranch,
defineDirectorStatus,
isAutoentrepreneur
}) => (
<SchemeCard
title="Indépendant"
subtitle="La protection à la carte"
onAmountClick={() => setSituationBranch(branchIndex)}
amount={revenuDisponible.montant}
icon="👩‍🔧"
amountDesc={<RuleLink {...revenuDisponible} />}
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
}) => (
<SchemeCard
title="Assimilé salarié"
onAmountClick={() => setSituationBranch(branchIndex)}
subtitle="Le régime tout compris"
amount={revenuDisponible.montant}
featured="Le choix de 58% des dirigeants de sociétés"
icon="☂"
amountDesc={<RuleLink {...revenuDisponible} />}
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 (
<SchemeCard
title="Auto-entrepreneur"
subtitle="Pour les petites activités"
onAmountClick={() => setSituationBranch(branchIndex)}
disabled={plafondDépassé}
amountDesc={<RuleLink {...revenuDisponible} />}
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

View File

@ -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({
<button
key={solution.cible}
className="ui__ link-button"
onClick={() => startConversation(solution.cible)}>
onClick={() => goToQuestion(solution.cible)}>
{solution.texte}
</button>
</div>
@ -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()

View File

@ -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;
}

View File

@ -68,7 +68,7 @@ class Distribution extends Component<Props, State> {
return (
<Observer
key={branche.id}
threshold={[0.33]}
threshold={[0.5]}
onChange={this.handleBrancheInViewport(branche.id)}>
<Spring
config={ANIMATION_SPRING}
@ -88,8 +88,8 @@ class Distribution extends Component<Props, State> {
<span className="distribution-chart__branche-name">
<RuleLink {...branche} />
</span>
{' : '}
{branche.descriptionCourte}
<br />
<small>{branche.résumé}</small>
</p>
<ChartItemBar {...{ styles, colour, montant, total }} />
</div>

View File

@ -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;
}

View File

@ -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<string>,
customMessage?: Node,
customEventName?: string,
stickToFooter: boolean
customEventName?: string
}
type Props = OwnProps & {
location: Location,
@ -93,7 +91,6 @@ class PageFeedback extends Component<Props, State> {
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<Props, State> {
this.props.location.pathname === '/' ? '' : this.props.location.pathname
return (
!this.props.blacklist.includes(pathname) && (
<div style={{ display: 'flex', justifyContent: 'center' }}>
<div
className={classNames('feedback-page', 'ui__', 'notice', {
stickToFooter
})}>
<div
className="ui__ container"
style={{ display: 'flex', justifyContent: 'center' }}>
<div className="feedback-page ui__ notice ">
{!this.state.showForm && !this.state.showThanks && (
<>
<div style={{ flexShrink: 0 }}>

View File

@ -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 {

View File

@ -151,29 +151,6 @@ const PaySlip = ({
<RuleLink {...salaireNetAprèsImpôt} />
<Montant>{salaireNetAprèsImpôt.montant}</Montant>
</div>
<br />
<p className="ui__ notice">
<Trans i18nKey="payslip.notice">
Le simulateur vous aide à comprendre votre bulletin de paie, sans lui
être opposable. Pour plus d&apos;informations, rendez vous sur&nbsp;
<a
alt="service-public.fr"
href="https://www.service-public.fr/particuliers/vosdroits/F559">
service-public.fr
</a>
.
</Trans>
</p>
<p className="ui__ notice">
<Trans i18nKey="payslip.disclaimer">
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{' '}
<a href="https://socialgouv.github.io/conventions-collectives">ici</a>
, et explorez les aides sur&nbsp;
<a href="https://www.aides-entreprises.fr">aides-entreprises.fr</a>.
</Trans>
</p>
</div>
)
}

View File

@ -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;
}

View File

@ -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 (
<div>
<input
className="range"
onChange={e => this.onChange(e.target.value)}
type="range"
value={this.state.value}
name="volume"
min="0"
step="0.05"
max="1"
/>
<span style={{ display: 'inline-block', width: '3em' }}>
{Math.round(this.state.value * 100)} %
</span>
</div>
)
}
}

View File

@ -25,7 +25,7 @@ const PreviousSimulationBanner = ({
newSimulationStarted,
loadPreviousSimulation
}: ConnectedPropTypes) => (
<Banner hidden={!previousSimulation || newSimulationStarted}>
<Banner hidden={!previousSimulation || newSimulationStarted} icon="💾">
<Trans i18nKey="previousSimulationBanner.info">
Votre précédente simulation a été sauvegardée.
</Trans>{' '}

View File

@ -1,54 +1,52 @@
/* @flow */
import { startConversation } from 'Actions/actions'
import { goToQuestion } from 'Actions/actions'
import { T } from 'Components'
import withLanguage from 'Components/utils/withLanguage'
import { compose, toPairs } from 'ramda'
import { compose, contains, reject, toPairs } from 'ramda'
import React from 'react'
import { Trans } from 'react-i18next'
import { connect } from 'react-redux'
import { withRouter } from 'react-router'
import { animated, Spring } from 'react-spring'
import { currentQuestionSelector } from 'Selectors/analyseSelectors'
import type { Location } from 'react-router'
type OwnProps = {
quickLinks: { [string]: string }
}
type Props = OwnProps & {
startConversation: (?string) => void,
goToQuestion: string => void,
location: Location,
quickLinksToHide: Array<string>,
show: boolean
}
const QuickLinks = ({ startConversation, show, quickLinks }: Props) => {
const QuickLinks = ({ goToQuestion, quickLinks, quickLinksToHide }: Props) => {
if (!quickLinks) {
return null
}
console.log(quickLinksToHide)
const links = compose(
toPairs,
reject(dottedName => contains(dottedName, quickLinksToHide))
)(quickLinks)
return (
<Spring
to={{
height: show ? 'auto' : 0,
opacity: show ? 1 : 0
}}
native>
{styles => (
<animated.div
className="ui__ answer-group"
style={{
...styles,
display: 'flex',
overflow: 'hidden',
flexWrap: 'wrap-reverse',
fontSize: '110%',
justifyContent: 'space-evenly',
marginBottom: '1rem'
}}>
{toPairs(quickLinks).map(([label, dottedName]) => (
<button
key={label}
className="ui__ small button"
onClick={() => startConversation(dottedName)}>
<Trans>{label}</Trans>
</button>
))}
</animated.div>
)}
</Spring>
<span>
<small>
<T k="quicklinks.autres">Autres questions :</T>
</small>{' '}
{links.map(([label, dottedName]) => (
<>
<button
key={dottedName}
className="ui__ link-button"
onClick={() => goToQuestion(dottedName)}>
<T k={'quicklinks.' + label}>{label}</T>
</button>{' '}
/{' '}
</>
))}{' '}
{/* <button className="ui__ link-button">Voir la liste</button> */}
</span>
)
}
@ -58,10 +56,14 @@ export default (compose(
connect(
(state, props) => ({
key: props.language,
quickLinks: state.simulation?.config["questions à l'affiche"]
quickLinks: state.simulation?.config["questions à l'affiche"],
quickLinksToHide: [
...state.conversationSteps.foldedSteps,
currentQuestionSelector(state)
]
}),
{
startConversation
goToQuestion
}
)
)(QuickLinks): React$ComponentType<OwnProps>)

View File

@ -1,31 +0,0 @@
.result-view__tabs {
display: flex;
align-items: center;
box-shadow: 0 -1px 0 0 #d4d4d5, 1px 0 0 0 #d4d4d5, -1px 0 0 0 #d4d4d5;
border-top-right-radius: 0.6em;
border: none;
border-top-left-radius: 0.6em;
margin-bottom: -1px;
border-bottom: 1px solid transparent;
}
.result-view__tabs button {
padding: 1em !important;
border-right: 1px solid #d4d4d5 !important;
text-decoration: none !important;
}
.result-view__tabs button.selected {
border-bottom: 1px solid white;
}
.result-view__tabs button:last-of-type {
border-right: none !important;
}
.result-view__header {
margin-top: 2em;
display: flex;
justify-content: space-between;
}
.result-view__body {
border-top-left-radius: 0 !important;
margin-bottom: 2em;
}

View File

@ -1,60 +0,0 @@
/* @flow */
import Distribution from 'Components/Distribution'
import PaySlip from 'Components/PaySlip'
import SearchButton from 'Components/SearchButton'
import React, { Component } from 'react'
import { Trans } from 'react-i18next'
import './SalaryCompactExplanation.css'
import type { Tracker } from 'Components/utils/withTracker'
type ResultView = 'distribution' | 'payslip'
type State = {
resultView: ResultView
}
type Props = {
conversationStarted: boolean,
tracker: Tracker,
displayResults: boolean
}
const resultViewTitle = {
distribution: 'Cotisations',
payslip: 'Fiche de paie'
}
export default class SalaryCompactExplanation extends Component<Props, State> {
state = {
resultView: this.props.conversationStarted ? 'payslip' : 'distribution'
}
handleClickOnTab = (resultView: ResultView) => () => {
this.setState({ resultView })
this.props.tracker.push(['trackEvent', 'results', 'selectView', resultView])
}
render() {
return (
<>
<div className="result-view__header">
<div className="result-view__tabs">
{['payslip', 'distribution'].map(resultView => (
<button
key={resultView}
className={
'ui__ link-button ' +
(this.state.resultView === resultView ? 'selected' : '')
}
onClick={this.handleClickOnTab(resultView)}>
<Trans>{resultViewTitle[resultView]}</Trans>
</button>
))}
</div>
<SearchButton />
</div>
<div className="ui__ card result-view__body">
{this.state.resultView === 'payslip' ? <PaySlip /> : <Distribution />}
</div>
</>
)
}
}

View File

@ -1,51 +1,79 @@
import { React, T } from 'Components'
import PageFeedback from 'Components/Feedback/PageFeedback'
import Distribution from 'Components/Distribution'
import PaySlip from 'Components/PaySlip'
import withTracker from 'Components/utils/withTracker'
import { compose } from 'ramda'
import React from 'react'
import { Trans } from 'react-i18next'
import { connect } from 'react-redux'
import { formValueSelector } from 'redux-form'
import * as Animate from 'Ui/animate'
import SalaryCompactExplanation from './SalaryCompactExplanation'
import SalaryFirstExplanation from './SalaryFirstExplanation'
export default compose(
withTracker,
connect(state => ({
conversationStarted: state.conversationStarted
showDistributionFirst: !state.conversationSteps.foldedSteps.length
}))
)(
class SalaryExplanation extends React.Component {
render() {
return (
<Animate.fromTop>
{!this.props.conversationStarted ? (
<>
{this.props.protectionText}
<PageFeedback
customMessage={
<T k="feedback.simulator">
Êtes-vous satisfait de ce simulateur ?
</T>
}
customEventName="rate simulator"
/>
<SalaryFirstExplanation {...this.props} />
</>
) : (
<>
<SalaryCompactExplanation {...this.props} />
<PageFeedback
customMessage={
<T k="feedback.simulator">
Êtes-vous satisfait de ce simulateur ?
</T>
}
customEventName="rate simulator"
/>
</>
)}
<div style={{ textAlign: 'center' }} />
</Animate.fromTop>
)
}
}
)(function SalaryExplanation({ showDistributionFirst }) {
return (
<Animate.fromTop key={showDistributionFirst}>
{showDistributionFirst ? (
<>
<DistributionSection />
<PaySlipSection />
</>
) : (
<>
<PaySlipSection />
<DistributionSection />
</>
)}
<br />
<p className="ui__ notice">
<Trans i18nKey="payslip.notice">
Le simulateur vous aide à comprendre votre bulletin de paie, sans lui
être opposable. Pour plus d&apos;informations, rendez vous sur&nbsp;
<a
alt="service-public.fr"
href="https://www.service-public.fr/particuliers/vosdroits/F559">
service-public.fr
</a>
.
</Trans>
</p>
<p className="ui__ notice">
<Trans i18nKey="payslip.disclaimer">
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{' '}
<a href="https://socialgouv.github.io/conventions-collectives">ici</a>
, et explorez les aides sur&nbsp;
<a href="https://www.aides-entreprises.fr">aides-entreprises.fr</a>.
</Trans>
</p>
</Animate.fromTop>
)
})
const PaySlipSection = connect(state => ({
period: formValueSelector('conversation')(state, 'période')
}))(({ period }) => (
<section>
<h2>
<Trans>
{period === 'mois'
? 'Fiche de paie mensuelle'
: 'Détail annuel des cotisations'}
</Trans>
</h2>
<PaySlip />
</section>
))
const DistributionSection = () => (
<section>
<h2>
<Trans>À quoi servent mes cotisations ?</Trans>
</h2>
<Distribution />
</section>
)

View File

@ -1,70 +0,0 @@
/* @flow */
import { startConversation } from 'Actions/actions'
import Distribution from 'Components/Distribution'
import PaySlip from 'Components/PaySlip'
import React, { Component } from 'react'
import { Trans } from 'react-i18next'
import { connect } from 'react-redux'
// $FlowFixMe
import { formValueSelector } from 'redux-form'
type OwnProps = {}
type Props = OwnProps & {
conversationStarted: boolean,
startConversation: () => void,
period: 'mois' | 'année'
}
export default (connect(
state => ({
conversationStarted: state.conversationStarted,
period: formValueSelector('conversation')(state, 'période')
}),
{ startConversation }
)(
class SalaryFirstExplanation extends Component<Props> {
render() {
return (
<>
<h2>
<Trans>À quoi servent mes cotisations ?</Trans>
</h2>
<Distribution />
{!this.props.conversationStarted && (
<>
<h2>
<Trans>Simulation personnalisée</Trans>
</h2>
<p>
<Trans i18nKey="custom-simulation">
Il s'agit pour l'instant d'une
<strong> première estimation</strong> sur la base d'un contrat
générique. La législation française prévoit une multitude de
cas particuliers et de règles spécifiques qui modifient
considérablement les montants de l'embauche.
</Trans>
</p>
<p style={{ textAlign: 'center' }}>
<button
className="ui__ button"
onClick={() => this.props.startConversation()}>
<Trans>Faire une simulation personnalisée</Trans>
</button>
</p>
</>
)}
<h2>
<Trans>
{this.props.period === 'mois'
? 'Fiche de paie mensuelle'
: 'Détail annuel des cotisations'}
</Trans>
</h2>
<PaySlip />
</>
)
}
}
): React$ComponentType<OwnProps>)

View File

@ -0,0 +1,207 @@
.comparaison-grid {
display: grid;
justify-items: stretch;
justify-content: center;
grid-template-columns:
[row-legend] auto [assimilé-salarié] minmax(20%, 20rem)
[indépendant] minmax(20%, 20rem) [auto-entrepreneur] minmax(20%, 20rem) [end];
}
.comparaison-grid.hideAutoEntrepreneur {
grid-template-columns:
[row-legend] auto [assimilé-salarié] minmax(20%, 20rem)
[indépendant] minmax(20%, 20rem) [auto-entrepreneur] 0 [end];
}
.comparaison-grid.hideAssimiléSalarié {
grid-template-columns:
[row-legend] auto [assimilé-salarié] 0
[indépendant] minmax(20%, 20rem) [auto-entrepreneur] minmax(20%, 20rem) [end];
}
.comparaison-grid > * {
border-bottom: 1px solid var(--lighterColour);
padding: 0.6rem 1.2rem;
border-right: 1px solid var(--lighterColour);
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
text-align: center;
flex-wrap: wrap;
}
.comparaison-grid > h2 {
margin: 0;
border: none;
align-self: stretch;
}
.comparaison-grid > h2 img {
height: 1.6rem !important;
width: 1.6rem !important;
}
.comparaison-grid > .legend {
max-width: 15rem;
align-items: flex-end;
grid-column: row-legend;
text-align: right;
}
.comparaison-grid > .AS-et-indep {
grid-column: assimilé-salarié / auto-entrepreneur;
}
.comparaison-grid > .AS {
grid-column: assimilé-salarié;
min-width: 11rem;
}
.comparaison-grid > .indep {
grid-column: indépendant;
}
.comparaison-grid > .auto {
grid-column: auto-entrepreneur;
border-right: none;
min-width: 14rem;
}
.comparaison-grid > .all {
border-right: none;
grid-column: row-legend / end;
}
.comparaison-grid > .all.colored {
background-color: var(--lightestColour);
}
.comparaison-grid > .indep-et-auto {
grid-column: indépendant / end;
border-right: none;
}
.comparaison-grid > .AS-indep-et-auto {
grid-column: assimilé-salarié / end;
border-right: none;
}
.comparaison-grid.hideAutoEntrepreneur > .auto {
display: none;
}
.comparaison-grid.hideAutoEntrepreneur > .indep-et-auto {
border-right: 1px solid var(--lighterColour);
}
.comparaison-grid.hideAssimiléSalarié > .AS {
display: none;
}
.comparaison-grid > .green {
font-weight: bold;
color: limegreen;
}
.comparaison-grid > .red {
font-weight: bold;
color: red;
}
.comparaison-grid > .no-border {
border: none;
}
.comparaison-grid .button {
align-self: stretch;
}
@media (max-width: 800px) {
.comparaison-grid > * {
padding: 0.6rem;
}
}
@media (max-width: 600px) {
.comparaison-grid {
display: block;
padding: 0 0.6rem;
}
.comparaison-grid h2 {
flex-direction: column;
}
.comparaison-grid small {
margin-left: 0.2rem;
}
.comparaison-grid > *::before {
flex: 1;
text-align: left;
flex-shrink: 0;
white-space: nowrap;
user-select: text;
font-weight: normal;
}
.comparaison-grid > :not(.button)::before {
color: var(--darkestColour) !important;
opacity: 0.6;
}
.comparaison-grid > .AS::before {
content: 'Assimilé-salarié :';
}
.comparaison-grid > .indep::before,
.comparaison-grid.hideAutoEntrepreneur > .indep-et-auto::before {
content: 'Indépendant :';
}
.comparaison-grid.hideAssimiléSalarié > .AS-et-indep::before,
.comparaison-grid.hideAssimiléSalarié > .indep::before {
content: 'Entreprise individuelle :';
}
.comparaison-grid > .auto::before {
content: 'Auto-entrepreneur :';
}
.comparaison-grid > .indep-et-auto::before {
content: 'Indépendant / auto-entrepreneur :';
}
.comparaison-grid > .AS-et-indep::before {
content: 'Assimilé salarié / indépendant ';
}
.comparaison-grid > h2::before {
display: none;
}
.comparaison-grid > h2.AS::after,
.comparaison-grid:not(.hideAutoEntrepreneur) > h2.indep::after {
display: block;
font-size: 1rem;
margin-top: 1rem;
content: 'vs';
color: var(--lightColour);
}
.comparaison-grid > .legend {
justify-content: flex-start;
align-items: baseline;
text-align: left;
}
.comparaison-grid > * {
border: none;
max-width: inherit !important;
flex-direction: row;
text-align: right;
justify-content: right;
}
.comparaison-grid > :not(.all):not(.button) {
padding-left: 0;
}
.comparaison-grid > .all {
margin: 0 -0.6rem;
text-align: center;
justify-content: center;
margin-top: 2rem;
}
.comparaison-grid > .no-border > .button {
flex: 1;
}
.comparaison-grid > .no-border::before {
display: none;
}
}
@media (min-width: 600px) {
.comparaison-grid > h3 {
margin: 0;
font-weight: normal;
font-size: 1rem;
}
}

View File

@ -0,0 +1,692 @@
/* @flow */
import { setSituationBranch } from 'Actions/actions'
import {
defineDirectorStatus,
isAutoentrepreneur
} from 'Actions/companyStatusActions'
import classnames from 'classnames'
import { T } from 'Components'
import Conversation from 'Components/conversation/Conversation'
import SeeAnswersButton from 'Components/conversation/SeeAnswersButton'
import PeriodSwitch from 'Components/PeriodSwitch'
// $FlowFixMe
import ComparaisonConfig from 'Components/simulationConfigs/rémunération-dirigeant.yaml'
import withSimulationConfig from 'Components/simulationConfigs/withSimulationConfig'
import withSitePaths from 'Components/utils/withSitePaths'
import revenusSVG from 'Images/revenus.svg'
import { compose, tryCatch } from 'ramda'
import React, { useCallback, useState } from 'react'
import emoji from 'react-easy-emoji'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import { branchAnalyseSelector } from 'Selectors/analyseSelectors'
import {
règleAvecMontantSelector,
règleAvecValeurSelector
} from 'Selectors/regleSelectors'
import Animate from 'Ui/animate'
import AnimatedTargetValue from 'Ui/AnimatedTargetValue'
import InfoBulle from 'Ui/InfoBulle'
import Montant from 'Ui/Montant'
import './SchemeComparaison.css'
import type { RègleAvecMontant, RègleAvecValeur } from 'Types/RegleTypes'
type OwnProps = {
hideAutoEntrepreneur?: boolean,
hideAssimiléSalarié?: boolean
}
type Props = OwnProps & {
assimiléSalarié: SimulationResult,
indépendant: SimulationResult,
autoEntrepreneur: SimulationResult,
setSituationBranch: number => void,
defineDirectorStatus: string => void,
sitePaths: any,
isAutoentrepreneur: boolean => void,
plafondAutoEntrepreneurDépassé: boolean
}
type SimulationResult = {
retraite: RègleAvecMontant,
trimestreValidés: RègleAvecValeur,
indemnitésJournalières: RègleAvecMontant,
indemnitésJournalièresATMP?: RègleAvecMontant,
revenuNetAvantImpôts: RègleAvecMontant,
revenuNetAprèsImpôts: RègleAvecMontant,
plafondDépassé?: boolean
}
const SchemeComparaison = ({
/* Own Props */
hideAutoEntrepreneur = false,
hideAssimiléSalarié = false,
/* Injected Props */
assimiléSalarié,
indépendant,
autoEntrepreneur,
defineDirectorStatus,
isAutoentrepreneur,
setSituationBranch
}: Props) => {
const [showMore, setShowMore] = useState(false)
const [conversationStarted, setConversationStarted] = useState(false)
const startConversation = useCallback(() => setConversationStarted(true), [
setConversationStarted
])
return (
<>
<div
className={classnames('comparaison-grid', {
hideAutoEntrepreneur,
hideAssimiléSalarié
})}>
<h2 className="AS">
{emoji('☂')} <T>Assimilé salarié</T>
<small>
<T k="comparaisonRégimes.AS.tagline">Le régime tout compris</T>
</small>
</h2>
<h2 className="indep">
{emoji('👩‍🔧')}{' '}
{hideAssimiléSalarié ? (
<T>Entreprise Individuelle</T>
) : (
<T>Indépendant</T>
)}
<small>
<T k="comparaisonRégimes.indep.tagline">
La protection sociale à la carte
</T>
</small>
</h2>
<h2 className="auto">
{emoji('🚶‍♂️')} <T>Auto-entrepreneur</T>
<small>
<T k="comparaisonRégimes.auto.tagline">
Pour commencer sans risques
</T>
</small>
</h2>
<h3 className="legend">
<T k="comparaisonRégimes.status.legend">
Statuts juridiques possibles
</T>
</h3>
<div className="AS">
<div>
<T k="comparaisonRégimes.status.AS">
SAS, SASU ou SARL avec gérant minoritaire
</T>
</div>
</div>
<div className="indep">
<div>
{hideAssimiléSalarié ? (
<T k="comparaisonRégimes.status.indep.2">EI ou EIRL</T>
) : (
<T k="comparaisonRégimes.status.indep.1">
EI, EIRL, EURL ou SARL avec gérant majoritaire
</T>
)}
</div>
</div>
<div className="auto">
<T k="comparaisonRégimes.status.auto">Auto-entreprise</T>
</div>
<T k="comparaisonRégimes.sécuritéSociale">
<h3 className="legend">Sécurité sociale</h3>
<div className="AS">
Régime général <small />
</div>
<div className="indep-et-auto">
Sécurité sociale des indépendants <small />
</div>
</T>
<T k="comparaisonRégimes.AT">
<h3 className="legend">Couverture accidents du travail</h3>
</T>
<div className="AS">
<T>
<T>Oui</T>
</T>
</div>
<div className="indep-et-auto">
<T>Non</T>
</div>
<T k="comparaisonRégimes.assuranceMaladie">
<h3 className="legend">
Assurance maladie{' '}
<small>(médicaments, soins, hospitalisations)</small>
</h3>
<div className="AS-indep-et-auto">Identique pour tous</div>
</T>
<T k="comparaisonRégimes.mutuelle">
<h3 className="legend">
Mutuelle santé
<small />
</h3>
<div className="AS">Obligatoire</div>
<div className="indep-et-auto">Fortement conseillée</div>
</T>
<T k="comparaisonRégimes.indemnités">
<h3 className="legend">Indemnités journalières</h3>
</T>
<div className="green AS">++</div>
<div className="green indep">++</div>
<div className="green auto">+</div>
<T k="comparaisonRégimes.retraite">
<h3 className="legend">Retraite</h3>
</T>
<div className="green AS">+++</div>
<div className="green indep">++</div>
<div className="green auto">+</div>
{showMore ? (
<>
<T k="comparaisonRégimes.ACRE">
<h3 className="legend">ACRE</h3>
<div className="AS-et-indep">
1 an <small>(exonération partielle de cotisations)</small>
</div>
<div className="auto">
3 ans
<small>(application de taux réduits de cotisations)</small>
</div>
</T>
<T k="comparaisonRégimes.déduction">
<h3 className="legend">Déduction des charges</h3>
<div className="AS-et-indep">
Oui <small>(régime fiscal du réel)</small>
</div>
<div className="auto">
Non
<small>
(mais abattement forfaitaire pour le calcul de l'impôt sur le
revenu)
</small>
</div>
</T>
<T k="comparaisonRégimes.cotisations">
<h3 className="legend">Paiement des cotisations</h3>
<div className="AS">Mensuel</div>
<div className="indep">
Provision mensuelle ou trimestrielle
<small>
(avec régularisation après coup en fonction du revenu réel)
</small>
</div>
<div className="auto">Mensuel ou trimestriel</div>
</T>
<T k="comparaisonRégimes.complémentaireDeductible">
<h3 className="legend">
Contrats prévoyance et retraite facultatives déductibles
</h3>
<div className="AS">
Oui <small>(sous certaines conditions)</small>
</div>
<div className="indep">
Oui <small>(Loi Madelin)</small>
</div>
</T>
<div className="auto">
<T>Non</T>
</div>
<T k="comparaisonRégimes.cotisationMinimale">
<h3 className="legend">Paiement de cotisations minimales</h3>
</T>
<div className="AS">
<T>Non</T>
</div>
<div className="indep">
<T>Oui</T>
</div>
<div className="auto">
<T>Non</T>
</div>
<T k="comparaisonRégimes.seuil">
<h3 className="legend">
Revenu minimum pour l'ouverture des droits aux prestations
</h3>
<div className="AS">Oui</div>
<div className="indep">
Non <small>(cotisations minimales obligatoires)</small>
</div>
<div className="auto">Oui</div>
</T>
{!hideAutoEntrepreneur && (
<T k="comparaisonRégimes.plafondCA">
<h3 className="legend">Plafond de chiffre d'affaires</h3>
<div className="AS-et-indep">
<T>Non</T>
</div>
<div className="auto">
<T>Oui</T>
<small>
(70 000 en services / 170 000 en vente de biens,
restauration ou hébergement)
</small>
</div>
</T>
)}
<T k="comparaisonRégimes.comptabilité">
<h3 className="legend">
Gestion comptable, sociale, juridique...
</h3>
<div className="AS-et-indep">
Accompagnement fortement conseillé
<small>
(expert comptable, comptable, centre de gestion agrée...)
</small>
</div>
<div className="auto">
Simplifiée{' '}
<small>(peut être gérée par l'auto-entrepreneur)</small>
</div>
</T>
</>
) : (
<T k="comparaisonRégimes.comparaisonDétaillée">
<div className="all">
<button
onClick={() => setShowMore(true)}
className="ui__ simple small button">
Afficher plus d'informations
</button>
</div>
</T>
)}
{conversationStarted && (
<>
<T k="comparaisonRégimes.période">
<h3 className="legend">Période</h3>
</T>
<div className="AS-indep-et-auto" style={{ alignSelf: 'start' }}>
<PeriodSwitch />
</div>
</>
)}
<div className="all colored">
{!conversationStarted ? (
<>
<T k="comparaisonRégimes.simulationText">
<h3>
Comparer mes revenus, pension de retraite et indemnité maladie
</h3>
<img src={revenusSVG} css="height: 8rem" />
<button
className="ui__ cta plain button"
onClick={startConversation}>
Lancer la simulation
</button>
</T>
</>
) : (
<div className="ui__ container">
<SeeAnswersButton />
<Conversation />
</div>
)}
</div>
{conversationStarted && !!assimiléSalarié.revenuNetAprèsImpôts.montant && (
<>
<T k="comparaisonRégimes.revenuNetApresImpots">
<h3 className="legend">Revenu net après impôts</h3>
</T>
<div className="AS">
<Animate.appear className="ui__ plain card">
<RuleValueLink
onClick={() => setSituationBranch(0)}
{...assimiléSalarié.revenuNetAprèsImpôts}
/>
</Animate.appear>
</div>
<div className="indep">
<Animate.appear className="ui__ plain card">
<RuleValueLink
onClick={() => setSituationBranch(1)}
{...indépendant.revenuNetAprèsImpôts}
/>
</Animate.appear>
</div>
<div className="auto">
<Animate.appear
className={classnames(
'ui__ plain card',
autoEntrepreneur.plafondDépassé && 'disabled'
)}>
{autoEntrepreneur.plafondDépassé ? (
'Plafond de CA dépassé'
) : (
<RuleValueLink
onClick={() => setSituationBranch(2)}
{...autoEntrepreneur.revenuNetAprèsImpôts}
/>
)}
</Animate.appear>
</div>
<T k="comparaisonRégimes.revenuNetAvantImpots">
<h3 className="legend">
Revenu net de cotisations <small>(avant impôts)</small>
</h3>
</T>
<div className="AS">
<RuleValueLink
onClick={() => setSituationBranch(0)}
{...assimiléSalarié.revenuNetAvantImpôts}
/>
</div>
<div className="indep">
<RuleValueLink
onClick={() => setSituationBranch(1)}
{...indépendant.revenuNetAvantImpôts}
/>
</div>
<div className="auto">
{autoEntrepreneur.plafondDépassé ? (
'—'
) : (
<RuleValueLink
onClick={() => setSituationBranch(2)}
{...autoEntrepreneur.revenuNetAvantImpôts}
/>
)}
</div>
<h3 className="legend">
<T k="comparaisonRégimes.retraiteEstimation.legend">
<span>Pension de retraite</span>
<small>(avant impôts)</small>
</T>
</h3>
<div className="AS">
<span>
<RuleValueLink
onClick={() => setSituationBranch(0)}
{...assimiléSalarié.retraite}
/>{' '}
<InfoBulle>
<T k="comparaisonRégimes.retraiteEstimation.infobulles.AS">
Pension calculée pour 172 trimestres cotisés au régime
général sans variations de revenus.
</T>
</InfoBulle>
</span>
</div>
<div className="indep">
{indépendant.retraite.applicable !== false ? (
<span>
<RuleValueLink
onClick={() => setSituationBranch(1)}
{...indépendant.retraite}
/>{' '}
<InfoBulle>
<T k="comparaisonRégimes.retraiteEstimation.infobulles.indep">
Pension calculée pour 172 trimestres cotisés au régime des
indépendants sans variations de revenus.
</T>
</InfoBulle>
</span>
) : (
<span className="ui__ notice">
<T>Pas implémenté</T>
</span>
)}
</div>
<div className="auto">
{autoEntrepreneur.plafondDépassé ? (
'—'
) : autoEntrepreneur.retraite.applicable !== false ? (
<span>
<RuleValueLink
onClick={() => setSituationBranch(2)}
{...autoEntrepreneur.retraite}
/>{' '}
<InfoBulle>
<T k="comparaisonRégimes.retraiteEstimation.infobulles.auto">
Pension calculée pour 172 trimestres cotisés en
auto-entrepreneur sans variations de revenus.
</T>
</InfoBulle>
</span>
) : (
<span className="ui__ notice">
<T>Pas implémenté</T>
</span>
)}
</div>
<T k="comparaisonRégimes.trimestreValidés">
<h3 className="legend">
Nombre de trimestres validés <small>(pour la retraite)</small>
</h3>
</T>
<div className="AS">
<RuleValueLink
onClick={() => setSituationBranch(0)}
appendText={<T>trimestres</T>}
{...assimiléSalarié.trimestreValidés}
/>
</div>
<div className="indep">
<RuleValueLink
onClick={() => setSituationBranch(1)}
appendText={<T>trimestres</T>}
{...indépendant.trimestreValidés}
/>
</div>
<div className="auto">
{autoEntrepreneur.plafondDépassé ? (
'—'
) : (
<RuleValueLink
onClick={() => setSituationBranch(2)}
appendText={<T>trimestres</T>}
{...autoEntrepreneur.trimestreValidés}
/>
)}
</div>
<T k="comparaisonRégimes.indemnités">
<h3 className="legend">
Indemnités journalières <small>(en cas d'arrêt maladie)</small>
</h3>
</T>
<div className="AS">
<span>
<RuleValueLink
onClick={() => setSituationBranch(0)}
appendText={
<>
/ <T>jour</T>
</>
}
{...assimiléSalarié.indemnitésJournalières}
/>
</span>
<small>
(
<RuleValueLink
onClick={() => setSituationBranch(0)}
{...assimiléSalarié.indemnitésJournalièresATMP}
/>{' '}
<T>pour les accidents de trajet/travail et maladie pro</T>)
</small>
</div>
<div className="indep">
<span>
<RuleValueLink
onClick={() => setSituationBranch(1)}
appendText={
<>
/ <T>jour</T>
</>
}
{...indépendant.indemnitésJournalières}
/>
</span>
</div>
<div className="auto">
{autoEntrepreneur.plafondDépassé ? (
'—'
) : (
<span>
<RuleValueLink
onClick={() => setSituationBranch(2)}
appendText={
<>
/ <T>jour</T>
</>
}
{...autoEntrepreneur.indemnitésJournalières}
/>
</span>
)}
</div>
</>
)}
</div>
<div className="ui__ container">
<br />
<h3>
<T k="comparaisonRégimes.titreSelection">
Créer mon entreprise en tant que :
</T>
</h3>
<div className="ui__ answer-group">
{!hideAssimiléSalarié && (
<button
className="ui__ button"
onClick={() => {
defineDirectorStatus('SALARIED')
!hideAutoEntrepreneur && isAutoentrepreneur(false)
}}>
<T k="comparaisonRégimes.choix.AS">Assimilé&nbsp;salarié</T>
</button>
)}
<button
className="ui__ button"
onClick={() => {
!hideAssimiléSalarié && defineDirectorStatus('SELF_EMPLOYED')
!hideAutoEntrepreneur && isAutoentrepreneur(false)
}}>
{hideAssimiléSalarié ? (
<T k="comparaisonRégimes.choix.EI">Entreprise individuelle</T>
) : (
<T k="comparaisonRégimes.choix.indep">Indépendant</T>
)}
</button>
{!hideAutoEntrepreneur && (
<button
className="ui__ button"
onClick={() => {
!hideAssimiléSalarié && defineDirectorStatus('SELF_EMPLOYED')
isAutoentrepreneur(true)
}}>
<T k="comparaisonRégimes.choix.auto">Auto-entrepreneur</T>
</button>
)}
</div>
</div>
</>
)
}
const RuleValueLink = withSitePaths(
({ lien, montant, valeur, sitePaths, onClick, appendText }) => (
<Link onClick={onClick} to={sitePaths.documentation.index + '/' + lien}>
{montant != undefined && <AnimatedTargetValue value={montant} />}
{valeur != undefined && (
<Montant numFractionDigit={0} type="decimal">
{valeur}
</Montant>
)}
{appendText && <> {appendText}</>}
</Link>
)
)
export default (compose(
withSimulationConfig(ComparaisonConfig),
connect(
tryCatch(
state => ({
autoEntrepreneur: {
retraite: règleAvecMontantSelector(state, {
situationBranchName: 'Auto-entrepreneur'
})('protection sociale . retraite'),
trimestreValidés: règleAvecValeurSelector(state, {
situationBranchName: 'Auto-entrepreneur'
})('protection sociale . retraite . trimestres validés par an'),
indemnitésJournalières: règleAvecMontantSelector(state, {
situationBranchName: 'Auto-entrepreneur'
})('protection sociale . santé . indemnités journalières'),
revenuNetAprèsImpôts: règleAvecMontantSelector(state, {
situationBranchName: 'Auto-entrepreneur'
})('revenu net'),
revenuNetAvantImpôts: règleAvecMontantSelector(state, {
situationBranchName: 'Auto-entrepreneur'
})('auto entrepreneur . revenu net de cotisations'),
// $FlowFixMe
plafondDépassé: branchAnalyseSelector(state, {
situationBranchName: 'Auto-entrepreneur'
}).controls?.find(
({ test }) =>
test.includes && test.includes('base des cotisations > plafond')
)
},
indépendant: {
retraite: règleAvecMontantSelector(state, {
situationBranchName: 'Indépendant'
})('protection sociale . retraite'),
trimestreValidés: règleAvecValeurSelector(state, {
situationBranchName: 'Indépendant'
})('protection sociale . retraite . trimestres validés par an'),
indemnitésJournalières: règleAvecMontantSelector(state, {
situationBranchName: 'Indépendant'
})('protection sociale . santé . indemnités journalières'),
revenuNetAprèsImpôts: règleAvecMontantSelector(state, {
situationBranchName: 'Indépendant'
})('revenu net'),
revenuNetAvantImpôts: règleAvecMontantSelector(state, {
situationBranchName: 'Indépendant'
})('indépendant . revenu professionnel')
},
assimiléSalarié: {
retraite: règleAvecMontantSelector(state, {
situationBranchName: 'Assimilé salarié'
})('protection sociale . retraite'),
trimestreValidés: règleAvecValeurSelector(state, {
situationBranchName: 'Assimilé salarié'
})('protection sociale . retraite . trimestres validés par an'),
indemnitésJournalières: règleAvecMontantSelector(state, {
situationBranchName: 'Assimilé salarié'
})('protection sociale . santé . indemnités journalières'),
indemnitésJournalièresATMP: règleAvecMontantSelector(state, {
situationBranchName: 'Assimilé salarié'
})(
'protection sociale . accidents du travail et maladies professionnelles'
),
revenuNetAprèsImpôts: règleAvecMontantSelector(state, {
situationBranchName: 'Assimilé salarié'
})('revenu net'),
revenuNetAvantImpôts: règleAvecMontantSelector(state, {
situationBranchName: 'Assimilé salarié'
})('contrat salarié . salaire . net')
}
}),
e => console.log(e) || {}
),
{
defineDirectorStatus,
isAutoentrepreneur,
setSituationBranch
}
)
)(SchemeComparaison): React$Component<OwnProps>)

View File

@ -30,14 +30,15 @@ export default withLanguage(function SimulateurWarning({
<div className={`content ${folded ? '' : 'ui__ card'}`}>
{!folded && (
<ul style={{ marginLeft: '1em' }}>
{simulateur !== 'auto-entreprise' && (
<li>
<T k="simulateurs.warning.line1">
le chiffre d'affaires déduit des charges va à 100% dans la
rémunération du dirigeant
</T>
</li>
)}
{simulateur !== 'auto-entreprise' &&
simulateur !== 'assimilé-salarié' && (
<li>
<T k="simulateurs.warning.line1">
le chiffre d'affaires déduit des charges va à 100% dans la
rémunération du dirigeant
</T>
</li>
)}
<li>
<T k="simulateurs.warning.line2">
l'impôt sur le revenu est calculé pour un célibataire sans

View File

@ -1,11 +0,0 @@
#simu {
margin: 1rem auto;
max-width: 40em;
}
.change-answer-link {
text-align: center;
}
#updateMessage a::after {
display: none
}

View File

@ -1,104 +1,65 @@
/* @flow */
import { resetSimulation } from 'Actions/actions'
import { React, T } from 'Components'
import Answers from 'Components/AnswerList'
import { T } from 'Components'
import Controls from 'Components/Controls'
import Conversation from 'Components/conversation/Conversation'
import withColours from 'Components/utils/withColours'
import { compose } from 'ramda'
import emoji from 'react-easy-emoji'
import ResultReliability from 'Components/conversation/ResultReliability'
import SeeAnswersButton from 'Components/conversation/SeeAnswersButton'
import PageFeedback from 'Components/Feedback/PageFeedback'
import TargetSelection from 'Components/TargetSelection'
import React from 'react'
import { connect } from 'react-redux'
import {
nextStepsSelector,
noUserInputSelector
} from 'Selectors/analyseSelectors'
import { firstStepCompletedSelector } from 'Selectors/analyseSelectors'
import { simulationProgressSelector } from 'Selectors/progressSelectors'
import * as Animate from 'Ui/animate'
import Progress from 'Ui/Progress'
export default compose(
withColours,
connect(
state => ({
conversationStarted: state.conversationStarted,
previousAnswers: state.conversationSteps.foldedSteps,
noNextSteps:
state.conversationStarted && nextStepsSelector(state).length == 0,
noUserInput: noUserInputSelector(state)
}),
{ resetSimulation }
)
)(
class Simulation extends React.Component {
state = {
displayAnswers: false
}
render() {
let {
noNextSteps,
previousAnswers,
noUserInput,
conversationStarted,
resetSimulation,
showTargetsAnyway,
targetsTriggerConversation
} = this.props
let arePreviousAnswers = previousAnswers.length > 0,
displayConversation =
!targetsTriggerConversation || conversationStarted,
showTargets = targetsTriggerConversation || showTargetsAnyway
return (
export default connect(state => ({
firstStepCompleted: firstStepCompletedSelector(state),
progress: simulationProgressSelector(state)
}))(function Simulation({
firstStepCompleted,
explanations,
customEndMessages,
progress
}) {
return (
<>
<TargetSelection />
{firstStepCompleted && (
<>
{this.state.displayAnswers && (
<Answers onClose={() => this.setState({ displayAnswers: false })} />
)}
<div
style={{
display: 'flex',
justifyContent: 'flex-start',
alignItems: 'baseline'
}}>
{arePreviousAnswers ? (
<button
style={{ marginRight: '1em' }}
className="ui__ small button "
onClick={() => this.setState({ displayAnswers: true })}>
<T>Voir mes réponses</T>
</button>
) : (
<span />
<Animate.fromTop>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
marginTop: '1.2rem',
marginBottom: '0.6rem',
alignItems: 'flex-end'
}}>
<ResultReliability progress={progress} />
<SeeAnswersButton />
</div>
<div className="ui__ full-width choice-group">
<div className="ui__ container">
<Controls />
<Conversation customEndMessages={customEndMessages} />
</div>
</div>
{progress < 1 && (
<Progress progress={progress} className="ui__ full-width" />
)}
{displayConversation && !noUserInput && (
<button
className="ui__ small simple skip button left"
onClick={() => resetSimulation()}>
<T>Recommencer</T>
</button>
)}
</div>
{displayConversation && (
<>
<Conversation
textColourOnWhite={this.props.colours.textColourOnWhite}
/>
{noNextSteps && (
<>
<h2>
{emoji('🌟')}{' '}
<T k="simulation-end.title">Situation complétée à 100%</T>{' '}
</h2>
<p>
<T k="simulation-end.text">
Nous n'avons plus de questions à poser, vous avez atteint
l'estimation la plus précise.
</T>
{this.props.customEndMessages}
</p>
</>
)}
</>
)}
{showTargets && this.props.targets}
<br />
<PageFeedback
customMessage={
<T k="feedback.simulator">
Êtes-vous satisfait de ce simulateur ?
</T>
}
customEventName="rate simulator"
/>{' '}
{explanations}
</Animate.fromTop>
</>
)
}
}
)
)}
</>
)
})

View File

@ -5,45 +5,45 @@
font-size: 180%;
}
#targetSelection #targets {
#targetSelection .targets {
list-style: none;
padding: 0;
margin: 0;
}
#targetSelection #targets > li:last-child {
#targetSelection .targets > li:last-child {
margin-bottom: -1rem;
}
#targetSelection #targets > li:first-child {
#targetSelection .targets > li:first-child {
border-top: none;
margin-top: -1rem;
}
#targetSelection #targets > li.small-target * {
#targetSelection .targets > li.small-target * {
font-size: 1rem;
font-weight: normal;
}
#targetSelection #targets > li.small-target {
#targetSelection .targets > li.small-target {
border-top: none;
}
#targetSelection #targets > li.small-target .targetInput {
#targetSelection .targets > li.small-target .targetInput {
border-width: 1px;
padding-top: 0;
padding-bottom: 0;
}
#targetSelection #targets > li {
#targetSelection .targets > li {
border-top: 1px solid rgba(255, 255, 255, 0.5);
padding: 0.6rem 1rem;
margin-left: -1rem;
margin-right: -1rem;
}
#targetSelection #targets > li .main {
#targetSelection .targets > li .main {
display: flex;
align-items: center;
justify-content: space-between;
}
#targetSelection #targets > li p {
#targetSelection .targets > li p {
margin: 0.2em 0 0;
font-style: italic;
opacity: 0.8;
@ -54,7 +54,7 @@
display: flex;
align-items: center;
}
#targetSelection #targets > li.small-target .header p {
#targetSelection .targets > li.small-target .header p {
display: none;
}

View File

@ -1,6 +1,7 @@
import classNames from 'classnames'
import Controls from 'Components/Controls'
import { T } from 'Components'
import InputSuggestions from 'Components/conversation/InputSuggestions'
import PercentageField from 'Components/PercentageField'
import PeriodSwitch from 'Components/PeriodSwitch'
import withColours from 'Components/utils/withColours'
import withLanguage from 'Components/utils/withLanguage'
@ -8,6 +9,7 @@ import withSitePaths from 'Components/utils/withSitePaths'
import { encodeRuleName } from 'Engine/rules'
import { compose, isEmpty, isNil, propEq } from 'ramda'
import React, { Component, PureComponent } from 'react'
import emoji from 'react-easy-emoji'
import { withTranslation } from 'react-i18next'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
@ -19,9 +21,7 @@ import {
import Animate from 'Ui/animate'
import AnimatedTargetValue from 'Ui/AnimatedTargetValue'
import CurrencyInput from './CurrencyInput/CurrencyInput'
import QuickLinks from './QuickLinks'
import './TargetSelection.css'
import { firstStepCompletedSelector } from './targetSelectionSelectors'
export default compose(
withTranslation(),
@ -36,8 +36,6 @@ export default compose(
formValueSelector('conversation')(state, dottedName),
analysis: analysisWithDefaultsSelector(state),
flatRules: flatRulesSelector(state),
firstStepCompleted: firstStepCompletedSelector(state),
conversationStarted: state.conversationStarted,
activeInput: state.activeTargetInput,
objectifs: state.simulation?.config.objectifs || []
}),
@ -82,94 +80,103 @@ export default compose(
render() {
let {
colours,
firstStepCompleted,
conversationStarted,
analysis,
explanation
activeInput,
setActiveInput,
setFormValue,
objectifs
} = this.props,
inversionFail = analysis.cache.inversionFail
targets = analysis?.targets || []
return (
<div id="targetSelection">
{firstStepCompleted && (
<Controls
inversionFail={inversionFail}
controls={analysis.controls}
/>
)}
<PeriodSwitch />
<section
className="ui__ plain card"
style={{
marginTop: '.6em',
color: colours.textColour,
background: `linear-gradient(
{(typeof objectifs[0] === 'string' ? [{ objectifs }] : objectifs).map(
({ icône, objectifs: groupTargets, nom }, index) => (
<React.Fragment key={nom}>
<div style={{ display: 'flex', alignItems: 'end' }}>
<div style={{ flex: 1 }}>
{nom && (
<h2 style={{ marginBottom: 0 }}>
{emoji(icône)} <T>{nom}</T>
</h2>
)}
</div>
{index === 0 && <PeriodSwitch />}
</div>
<section
className="ui__ plain card"
style={{
marginTop: '.6em',
color: colours.textColour,
background: `linear-gradient(
60deg,
${colours.darkColour} 0%,
${colours.colour} 100%
)`
}}>
{this.renderOutputList()}
</section>
<QuickLinks show={firstStepCompleted && !conversationStarted} />
{firstStepCompleted && explanation}
</div>
)
}
renderOutputList() {
let {
conversationStarted,
activeInput,
setActiveInput,
setFormValue,
analysis
} = this.props,
targets = analysis ? analysis.targets : [],
inversionFail = analysis.cache.inversionFail
return (
<div>
<ul id="targets">
{targets
.map(target => target.explanation || target)
.filter(target => {
return (
target.isApplicable !== false &&
(target.question || target.nodeValue)
)
})
.map(target => (
<Target
key={target.dottedName}
initialRender={this.state.initialRender}
{...{
conversationStarted,
target,
setFormValue,
activeInput,
setActiveInput,
targets,
inversionFail
}}
/>
))}
</ul>
}}>
<Targets
{...{
activeInput,
setActiveInput,
setFormValue,
targets: targets.filter(({ dottedName }) =>
groupTargets.includes(dottedName)
),
initialRender: this.state.initialRender
}}
/>
</section>
</React.Fragment>
)
)}
</div>
)
}
}
)
let Targets = ({
activeInput,
setActiveInput,
setFormValue,
targets,
initialRender
}) => (
<div>
<ul className="targets">
{targets
.map(target => target.explanation || target)
.filter(target => {
return (
target.isApplicable !== false &&
(target.question || target.nodeValue)
)
})
.map(target => (
<Target
key={target.dottedName}
initialRender={initialRender}
{...{
target,
setFormValue,
activeInput,
setActiveInput,
targets
}}
/>
))}
</ul>
</div>
)
const Target = ({
target,
activeInput,
conversationStarted,
targets,
setActiveInput,
setFormValue,
initialRender,
inversionFail
initialRender
}) => {
const isSmallTarget =
!target.question || !target.formule || isEmpty(target.formule)
@ -184,7 +191,7 @@ const Target = ({
<Header
{...{
target,
conversationStarted,
isActiveInput: activeInput === target.dottedName
}}
/>
@ -203,12 +210,11 @@ const Target = ({
targets,
activeInput,
setActiveInput,
setFormValue,
inversionFail
setFormValue
}}
/>
</div>
{activeInput === target.dottedName && !conversationStarted && (
{activeInput === target.dottedName && (
<Animate.fromTop>
<InputSuggestions
suggestions={target.suggestions}
@ -226,7 +232,7 @@ const Target = ({
)
}
let Header = withSitePaths(({ target, conversationStarted, sitePaths }) => {
let Header = withSitePaths(({ target, sitePaths }) => {
const ruleLink =
sitePaths.documentation.index + '/' + encodeRuleName(target.dottedName)
return (
@ -235,7 +241,7 @@ let Header = withSitePaths(({ target, conversationStarted, sitePaths }) => {
<span className="optionTitle">
<Link to={ruleLink}>{target.title || target.name}</Link>
</span>
{!conversationStarted && <p>{target['résumé']}</p>}
<p>{target.summary}</p>
</span>
</span>
)
@ -256,6 +262,9 @@ let CurrencyField = withColours(props => {
/>
)
})
let DebouncedPercentageField = props => (
<PercentageField debounce={600} {...props} />
)
let TargetInputOrValue = withLanguage(
({
@ -264,8 +273,7 @@ let TargetInputOrValue = withLanguage(
activeInput,
setActiveInput,
language,
firstStepCompleted,
inversionFail
firstStepCompleted
}) => {
let inputIsActive = activeInput === target.dottedName
return (
@ -273,8 +281,12 @@ let TargetInputOrValue = withLanguage(
{inputIsActive || !target.formule || isEmpty(target.formule) ? (
<Field
name={target.dottedName}
component={CurrencyField}
onBlur={event => event.preventDefault()}
component={
{ euros: CurrencyField, pourcentage: DebouncedPercentageField }[
target.format
]
}
{...(inputIsActive ? { autoFocus: true } : {})}
language={language}
/>
@ -285,8 +297,7 @@ let TargetInputOrValue = withLanguage(
target,
activeInput,
setActiveInput,
firstStepCompleted,
inversionFail
firstStepCompleted
}}
/>
)}
@ -296,14 +307,16 @@ let TargetInputOrValue = withLanguage(
)
const TargetValue = connect(
null,
state => ({
blurValue: analysisWithDefaultsSelector(state)?.cache.inversionFail
}),
dispatch => ({
setFormValue: (field, name) => dispatch(change('conversation', field, name))
})
)(
class TargetValue extends Component {
render() {
let { targets, target, inversionFail } = this.props
let { targets, target, blurValue } = this.props
let targetWithValue =
targets && targets.find(propEq('dottedName', target.dottedName)),
@ -315,7 +328,7 @@ const TargetValue = connect(
editable: target.question,
attractClick: target.question && isNil(target.nodeValue)
})}
style={inversionFail ? { filter: 'blur(3px)' } : {}}
style={blurValue ? { filter: 'blur(3px)' } : {}}
{...(target.question ? { tabIndex: 0 } : {})}
onClick={this.showField(value)}
onFocus={this.showField(value)}>

View File

@ -6,8 +6,8 @@ import { compose } from 'ramda'
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { flatRulesSelector } from 'Selectors/analyseSelectors'
import References from '../rule/References'
import './Aide.css'
import References from './rule/References'
export default compose(
connect(

View File

@ -1,4 +1,4 @@
import { resetSimulation } from 'Actions/actions'
import { goToQuestion, resetSimulation } from 'Actions/actions'
import Overlay from 'Components/Overlay'
import RuleLink from 'Components/RuleLink'
import withColours from 'Components/utils/withColours'
@ -11,7 +11,7 @@ import { connect } from 'react-redux'
import { createSelector } from 'reselect'
import { règleAvecValeurSelector } from 'Selectors/regleSelectors'
import Montant from 'Ui/Montant'
import { softCatch } from '../utils'
import { softCatch } from '../../utils'
import './AnswerList.css'
const formatAnswer = (answer, language) => {
@ -37,7 +37,7 @@ const AnswerList = ({
onClose,
language,
colours,
changeAnswer,
goToQuestion,
resetSimulation
}) => (
<Overlay onClose={onClose} className="answer-list">
@ -66,7 +66,7 @@ const AnswerList = ({
<button
className="answer"
onClick={() => {
changeAnswer(answer.id)
goToQuestion(answer.id)
onClose()
}}>
<span
@ -94,16 +94,9 @@ export default compose(
withColours,
connect(
state => ({ answers: answerWithValueSelector(state) }),
dispatch => ({
resetSimulation: () => {
dispatch(resetSimulation())
},
changeAnswer: question =>
dispatch({
type: 'STEP_ACTION',
name: 'unfold',
step: question
})
})
{
resetSimulation,
goToQuestion
}
)
)(AnswerList)

View File

@ -1,16 +1,19 @@
import Scroll from 'Components/utils/Scroll'
import { goToQuestion, resetSimulation, skipQuestion } from 'Actions/actions'
import { T } from 'Components'
import QuickLinks from 'Components/QuickLinks'
import { getInputComponent } from 'Engine/generateQuestions'
import { compose } from 'ramda'
import React, { Component } from 'react'
import { withTranslation } from 'react-i18next'
import React from 'react'
import emoji from 'react-easy-emoji'
import { connect } from 'react-redux'
import { reduxForm } from 'redux-form'
import {
currentQuestionSelector,
flatRulesSelector
flatRulesSelector,
nextStepsSelector
} from 'Selectors/analyseSelectors'
import * as Animate from 'Ui/animate'
import Aide from '../Aide'
import Aide from './Aide'
import './conversation.css'
export default compose(
@ -18,30 +21,80 @@ export default compose(
form: 'conversation',
destroyOnUnmount: false
}),
withTranslation(),
connect(state => ({
conversationStarted: state.conversationStarted,
flatRules: flatRulesSelector(state),
currentQuestion: currentQuestionSelector(state)
}))
)(
class Conversation extends Component {
render() {
let { currentQuestion, flatRules } = this.props
return (
<Scroll.toElement onlyIfNotVisible>
<div className="conversationContainer">
<Aide />
<div id="currentQuestion">
{currentQuestion && (
<Animate.fadeIn>
{getInputComponent(flatRules)(currentQuestion)}
</Animate.fadeIn>
)}
</div>
</div>
</Scroll.toElement>
)
connect(
state => ({
flatRules: flatRulesSelector(state),
currentQuestion: currentQuestionSelector(state),
previousAnswers: state.conversationSteps.foldedSteps,
nextSteps: nextStepsSelector(state)
}),
{ resetSimulation, skipQuestion, goToQuestion }
)
)(function Conversation({
nextSteps,
previousAnswers,
currentQuestion,
customEndMessages,
flatRules,
resetSimulation,
skipQuestion,
goToQuestion
}) {
const goToNext = () => skipQuestion(nextSteps[0])
const goToPrevious = () => goToQuestion(previousAnswers.slice(-1)[0])
const handleKeyDown = ({ key }) => {
if (['Escape'].includes(key)) {
goToNext()
}
}
)
return nextSteps.length ? (
<>
<Aide />
<div tabIndex="0" style={{ outline: 'none' }} onKeyDown={handleKeyDown}>
{currentQuestion && (
<React.Fragment key={currentQuestion}>
<Animate.fadeIn>
{getInputComponent(flatRules)(currentQuestion)}
</Animate.fadeIn>
<div className="ui__ answer-group">
{previousAnswers.length > 0 && (
<>
<button
onClick={goToPrevious}
className="ui__ simple small skip button left">
Précédent
</button>
</>
)}
<button
onClick={goToNext}
className="ui__ simple small skip button right">
Passer
</button>
</div>
</React.Fragment>
)}
<QuickLinks />
</div>
</>
) : (
<div style={{ textAlign: 'center' }}>
<h3>
{emoji('🌟')}{' '}
<T k="simulation-end.title">Vous avez complété cette simulation</T>{' '}
</h3>
<p>
{customEndMessages ? (
customEndMessages
) : (
<T k="simulation-end.text">
Vous avez maintenant accès à l'estimation la plus précise possible.
</T>
)}
</p>
<button className="ui__ small simple button " onClick={resetSimulation}>
<T>Recommencer</T>
</button>
</div>
)
})

View File

@ -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 =>
<div className={classNames('step', formType)}>
<div className="unfoldedHeader">
<div className="step-question">
<h1>
<h3>
{' '}
{this.props.question}{' '}
{!inversion && <Explicable dottedName={fieldName} />}
</h1>
</h3>
<div
className="step-subquestion"
dangerouslySetInnerHTML={{ __html: subquestion }}
/>
</div>
</div>
{defaultValue != null && (
<IgnoreStepButton
action={() => {
setFormValue(
fieldName,
typeof defaultValue == 'object'
? JSON.stringify(defaultValue)
: '' + defaultValue
)
submit('ignore')
}}
/>
)}
<fieldset>
<Field
component={RenderField}
name={fieldName}
{...stepProps}
/>
<Field component={RenderField} name={fieldName} {...stepProps} />
</fieldset>
</div>
)

View File

@ -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 (
<div
css={`
position: relative;
text-align: right;
.keyIcon {
opacity: 0;
}
:hover .keyIcon {
opacity: 1;
}
`}>
<button
className="ui__ small simple skip button"
onClick={this.props.action}>
<Trans>passer</Trans>
</button>
<span className="keyIcon">
<Trans>Échap</Trans>
</span>
</div>
)
}
}
)

View File

@ -0,0 +1,36 @@
import { T } from 'Components'
import React from 'react'
import InfoBulle from 'Ui/InfoBulle'
export default function ResultReliability({ progress }) {
return (
<span>
<small>
{progress === 0 && (
<T k="simulateurs.précision.défaut">
Affinez la simulation en répondant aux questions suivantes :
</T>
)}
</small>
{progress > 0 && (
<>
<small>
{progress < 0.2 ? (
<T k="simulateurs.précision.faible">Précision faible</T>
) : progress < 0.5 ? (
<T k="simulateurs.précision.moyenne">Précision moyenne</T>
) : progress > 0.5 ? (
<T k="simulateurs.précision.bonne">Bonne précision</T>
) : (
''
)}
</small>{' '}
<InfoBulle>
Le résultat peut varier énormément en fonction de votre situation.
Répondez aux questions pour en améliorer la précision.
</InfoBulle>{' '}
</>
)}
</span>
)
}

View File

@ -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 && (
<button
className="ui__ small simple button "
onClick={() => setShowAnswerModal(true)}>
<T>Voir mes réponses</T>
</button>
)}
{showAnswerModal && <Answers onClose={() => setShowAnswerModal(false)} />}
</>
)
})

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
}
)

View File

@ -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;
}
}

View File

@ -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'>) => (
<button {...props} className={'ui__ simple skip button ' + props.className}>
{props.children || (
<>
<T>Passer</T>
</>
)}
</button>
)
export const LinkButton = (props: ElementConfig<'button'>) => (
<button {...props} className={'ui__ link-button ' + props.className} />
)

View File

@ -14,7 +14,11 @@
color: white;
color: var(--textColour);
background: linear-gradient(60deg, #215da6 0%, #297da1 100%);
background: linear-gradient(60deg, var(--darkColour) 0%, var(--colour) 100%);
background: linear-gradient(
60deg,
var(--darkColour) -100%,
var(--colour) 100%
);
}
.ui__.card.disabled img {
filter: saturate(0);

View File

@ -95,7 +95,7 @@ ul.ui__.checklist {
}
.ui__.checklist-explanation {
padding-left: calc(0.6rem + 8px);
border-left: 2px dashed var(--colour);
padding-left: calc(0.6rem + 10px);
border-left: 1px solid var(--lighterColour);
margin: 0 0 -1rem 8px;
}

View File

@ -78,11 +78,11 @@ class CheckItemComponent extends Component<CheckItemProps, CheckItemState> {
</button>
</div>
{this.state.displayExplanations && this.props.explanations && (
<Animate.fadeIn>
<Animate.appear>
<div className="ui__ checklist-explanation">
{this.props.explanations}
</div>
</Animate.fadeIn>
</Animate.appear>
)}
</ScrollToElement>
)

View File

@ -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;
}

View File

@ -0,0 +1,13 @@
import React from 'react'
import './InfoBulle.css'
export default function InfoBulle({ children }) {
return (
<span style={{ position: 'relative', verticalAlign: 'bottom' }}>
<span className="info-bulle__interrogation-mark" tabIndex="0">
?
</span>
<span className="info-bulle__text">{children}</span>
</span>
)
}

View File

@ -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);
}

View File

@ -0,0 +1,10 @@
import React from 'react'
import './Progress.css'
export default function Progress({ progress, style, className }) {
return (
<div className={'progress__container ' + className} style={style}>
<div className="progress__bar" style={{ width: `${progress * 100}%` }} />
</div>
)
}

View File

@ -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;
}
}

View File

@ -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<Node>,
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 (
<div
className={classnames('scheme-card__container', {
'ui__ card disabled scheme-card__container--disabled': disabled,
'ui__ card coloured scheme-card__container--featured': featured,
'is-IE': isIE()
})}>
<div
className={`scheme-card__top-text scheme-card__top-text--${
featured ? 'featured' : disabled ? 'disabled' : 'hidden'
}`}
style={{ visibility: featured || disabled ? 'visible' : 'hidden' }}>
{featured || disabled || 'nop'}
</div>
<div
className={classnames('scheme-card__inside', {
'ui__ card': !featured && !disabled,
'is-IE': isIE()
})}>
<header
className="scheme-card__header"
onClick={toggleDescriptionVisibility}>
<span className="scheme-card__icon">{emoji(icon)} </span>
<h3
className={
'scheme-card__title ' +
(descriptionVisibility ? 'scheme-card__title--unfold' : '')
}>
{title}
</h3>
<h4 className="scheme-card__subtitle">{subtitle}</h4>
</header>
{!isNil(amount) && (
<Animate.appear style={{ alignSelf: 'stretch' }}>
<div
className={
'ui__ card scheme-card__amount plain ' +
(Number.isNaN(amount) ? 'disabled' : '')
}
onClick={onAmountClick}>
{amountDesc}&nbsp;:
<span className="scheme-card__amount-separator" />
<p className="ui__ lead">
{disabled ? (
'CA dépassé'
) : (
<AnimatedTargetValue value={amount} />
)}
</p>
</div>
</Animate.appear>
)}
<ul
className={
'scheme-card__content ' +
(descriptionVisibility ? 'scheme-card__content--visible' : '')
}>
{features.map((feature, index) => (
<li key={index}>{feature}</li>
))}
</ul>
<p
className={
'scheme-card__cta ' +
(descriptionVisibility ? 'scheme-card__cta--visible' : '')
}>
<button onClick={onSchemeChoice} className={'ui__ button'}>
Choisir ce régime
</button>
</p>
</div>
</div>
)
}
export default SchemeCard

View File

@ -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%;
}

View File

@ -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 = ({
<animated.div
key={i}
style={{
transform: y.interpolate(y => `translate3d(0, ${y}px,0)`),
transform: y.interpolate(y =>
y ? `translate3d(0, ${y}px,0)` : 'none'
),
...style,
...inheritedStyle
}}>

View File

@ -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;

View File

@ -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'

View File

@ -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 }) => (
<>

View File

@ -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

View File

@ -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

View File

@ -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',

218
source/images/logo.svg Normal file
View File

@ -0,0 +1,218 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 433.46228 162.40294"
version="1.1"
id="svg61"
sodipodi:docname="logo.svg"
width="433.46228"
height="162.40294"
inkscape:version="0.92.4 5da689c313, 2019-01-14">
<metadata
id="metadata65">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2512"
inkscape:window-height="1386"
id="namedview63"
showgrid="false"
inkscape:zoom="0.95898438"
inkscape:cx="216.77"
inkscape:cy="81.2"
inkscape:window-x="48"
inkscape:window-y="28"
inkscape:window-maximized="1"
inkscape:current-layer="svg61" />
<defs
id="defs4">
<style
id="style2">.cls-1{fill:#1e286e;}.cls-2{fill:#4b508c;}.cls-3{fill:#fad750;}.cls-4{fill:#f5c328;}.cls-5{fill:#cd0a5a;}.cls-6{fill:#ff2d96;}.cls-7{fill:#1ea0f5;}.cls-8{fill:#197dbe;}.cls-9{fill:#46dcc3;}.cls-10{fill:#91ebc3;}</style>
</defs>
<title
id="title6">mon-entreprise_logo</title>
<g
id="mon-entrerpise_logo"
transform="translate(-39.23,-24.797057)">
<path
class="cls-1"
d="m 151.27,91.07 h 10.88 v 3.78 a 14.07,14.07 0 0 1 10,-4.26 11.59,11.59 0 0 1 10.46,5.77 11.66,11.66 0 0 1 10.39,-5.83 13.07,13.07 0 0 1 4.09,0.63 8.49,8.49 0 0 1 3.31,2 9.44,9.44 0 0 1 2.19,3.52 14.93,14.93 0 0 1 0.81,5.23 v 20 H 192.56 V 106.7 a 18.42,18.42 0 0 0 -0.33,-3.85 6.19,6.19 0 0 0 -1,-2.35 3.18,3.18 0 0 0 -1.47,-1.14 5.37,5.37 0 0 0 -1.81,-0.3 q -5.22,0 -5.23,7.64 v 15.2 h -10.84 v -15.2 a 20.7,20.7 0 0 0 -0.3,-3.88 7.19,7.19 0 0 0 -0.87,-2.44 2.91,2.91 0 0 0 -1.47,-1.23 6.11,6.11 0 0 0 -2.11,-0.33 6,6 0 0 0 -1.92,0.3 3.41,3.41 0 0 0 -1.59,1.17 6.43,6.43 0 0 0 -1.08,2.41 16.18,16.18 0 0 0 -0.39,4 v 15.2 h -10.88 z"
id="path8"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<path
class="cls-1"
d="m 209.69,106.21 a 14.91,14.91 0 0 1 1.39,-6.4 15.84,15.84 0 0 1 3.84,-5.17 18.42,18.42 0 0 1 5.86,-3.45 21,21 0 0 1 7.43,-1.27 21.45,21.45 0 0 1 7.36,1.24 18.24,18.24 0 0 1 5.89,3.42 15.5,15.5 0 0 1 3.88,5.23 16,16 0 0 1 1.38,6.7 15.75,15.75 0 0 1 -1.41,6.71 16.05,16.05 0 0 1 -3.88,5.23 17.29,17.29 0 0 1 -5.92,3.39 22.65,22.65 0 0 1 -7.48,1.21 21.73,21.73 0 0 1 -7.34,-1.21 17,17 0 0 1 -5.8,-3.42 16,16 0 0 1 -3.81,-5.32 16.6,16.6 0 0 1 -1.39,-6.89 z m 11.48,0.12 a 6.83,6.83 0 0 0 0.58,2.86 7.64,7.64 0 0 0 1.5,2.25 6.48,6.48 0 0 0 2.22,1.51 7.2,7.2 0 0 0 5.47,0 6.62,6.62 0 0 0 2.23,-1.51 7.64,7.64 0 0 0 1.5,-2.25 6.84,6.84 0 0 0 0.57,-2.8 6.68,6.68 0 0 0 -0.57,-2.73 7.64,7.64 0 0 0 -1.5,-2.25 6.62,6.62 0 0 0 -2.23,-1.51 7.2,7.2 0 0 0 -5.47,0 6.48,6.48 0 0 0 -2.22,1.51 7.76,7.76 0 0 0 -1.5,2.22 6.33,6.33 0 0 0 -0.58,2.7 z"
id="path10"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<path
class="cls-1"
d="m 253,91.07 h 10.88 V 95 a 12,12 0 0 1 4.51,-3.63 14.13,14.13 0 0 1 5.35,-0.94 13.35,13.35 0 0 1 5.56,1.06 11.1,11.1 0 0 1 3.94,3 8.63,8.63 0 0 1 1.8,3.49 18.15,18.15 0 0 1 0.48,4.39 v 19.53 h -10.91 v -15.57 a 16.73,16.73 0 0 0 -0.33,-3.69 4.65,4.65 0 0 0 -1.17,-2.26 4.12,4.12 0 0 0 -1.62,-1 6.1,6.1 0 0 0 -1.93,-0.3 5.37,5.37 0 0 0 -4.23,1.65 6.85,6.85 0 0 0 -1.48,4.72 V 121.9 H 253 Z"
id="path12"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<path
class="cls-1"
d="m 162.27,158.23 q 0,7 6.61,7 a 5.91,5.91 0 0 0 5.35,-2.88 h 10.52 Q 181.56,173 168.82,173 a 21,21 0 0 1 -7.16,-1.17 16.25,16.25 0 0 1 -5.56,-3.34 14.88,14.88 0 0 1 -3.57,-5.17 17.25,17.25 0 0 1 -1.26,-6.73 18.91,18.91 0 0 1 1.2,-7 14.7,14.7 0 0 1 3.42,-5.26 15.28,15.28 0 0 1 5.38,-3.33 20.43,20.43 0 0 1 7.13,-1.17 19.93,19.93 0 0 1 7,1.17 14.15,14.15 0 0 1 5.29,3.4 14.89,14.89 0 0 1 3.31,5.43 21.63,21.63 0 0 1 1.14,7.25 v 1.14 z M 175,151.92 a 6.56,6.56 0 0 0 -2.22,-3.67 6.92,6.92 0 0 0 -8.21,-0.06 6,6 0 0 0 -2,3.73 z"
id="path14"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<path
class="cls-1"
d="m 191.36,141 h 10.88 v 3.91 a 11.78,11.78 0 0 1 4.51,-3.64 14.1,14.1 0 0 1 5.35,-0.93 13.42,13.42 0 0 1 5.56,1.05 11.19,11.19 0 0 1 3.94,3 8.63,8.63 0 0 1 1.8,3.49 18.21,18.21 0 0 1 0.48,4.39 v 19.6 H 213 v -15.62 a 16.77,16.77 0 0 0 -0.33,-3.7 4.57,4.57 0 0 0 -1.17,-2.25 4.06,4.06 0 0 0 -1.63,-1 6,6 0 0 0 -1.87,-0.3 5.36,5.36 0 0 0 -4.24,1.66 6.86,6.86 0 0 0 -1.47,4.72 v 16.47 h -10.93 z"
id="path16"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<path
class="cls-1"
d="m 243.42,150.06 v 21.76 h -10.88 v -21.76 h -3.61 V 141 h 3.61 v -9.26 h 10.88 V 141 h 6.19 v 9.08 z"
id="path18"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<path
class="cls-1"
d="m 253.69,141 h 10.88 v 5 a 12.62,12.62 0 0 1 4.27,-4.24 11.5,11.5 0 0 1 5.89,-1.47 h 0.93 a 6.82,6.82 0 0 1 1.18,0.12 v 10.4 a 10.4,10.4 0 0 0 -4.69,-1.09 7,7 0 0 0 -5.68,2.26 c -1.27,1.5 -1.9,3.7 -1.9,6.58 v 13.23 h -10.88 z"
id="path20"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<path
class="cls-1"
d="m 291.86,158.23 q 0,7 6.62,7 a 5.92,5.92 0 0 0 5.35,-2.88 h 10.52 Q 311.16,173 298.42,173 a 21,21 0 0 1 -7.16,-1.17 16.16,16.16 0 0 1 -5.56,-3.34 14.88,14.88 0 0 1 -3.57,-5.17 17.07,17.07 0 0 1 -1.27,-6.73 18.91,18.91 0 0 1 1.21,-7 14.7,14.7 0 0 1 3.42,-5.26 15.2,15.2 0 0 1 5.38,-3.33 20.43,20.43 0 0 1 7.13,-1.17 20,20 0 0 1 7,1.17 14.15,14.15 0 0 1 5.29,3.4 14.73,14.73 0 0 1 3.3,5.43 21.62,21.62 0 0 1 1.15,7.25 v 1.14 z m 12.75,-6.31 a 6.57,6.57 0 0 0 -2.23,-3.67 6.9,6.9 0 0 0 -8.2,-0.06 6,6 0 0 0 -2,3.73 z"
id="path22"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<path
class="cls-1"
d="M 331.84,187.2 H 321 V 141 h 10.88 v 3.43 a 11.46,11.46 0 0 1 9.49,-4.39 14.83,14.83 0 0 1 6.17,1.29 15.61,15.61 0 0 1 5,3.52 15.87,15.87 0 0 1 3.27,5.23 17.53,17.53 0 0 1 1.17,6.43 17.1,17.1 0 0 1 -1.17,6.37 16.25,16.25 0 0 1 -3.25,5.17 15,15 0 0 1 -4.89,3.48 14.77,14.77 0 0 1 -6.14,1.27 12.82,12.82 0 0 1 -9.61,-4 z m 13.7,-30.71 a 7.41,7.41 0 0 0 -0.51,-2.74 6.55,6.55 0 0 0 -1.47,-2.25 7.28,7.28 0 0 0 -2.26,-1.5 6.87,6.87 0 0 0 -7.69,1.47 7.64,7.64 0 0 0 -1.5,2.25 6.85,6.85 0 0 0 1.47,7.64 7.64,7.64 0 0 0 2.25,1.5 6.94,6.94 0 0 0 5.44,0 6.62,6.62 0 0 0 2.2,-1.5 7.81,7.81 0 0 0 1.5,-2.23 6.33,6.33 0 0 0 0.57,-2.64 z"
id="path24"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<path
class="cls-1"
d="M 363.09,141 H 374 v 5 a 12.62,12.62 0 0 1 4.27,-4.24 11.52,11.52 0 0 1 5.89,-1.47 h 0.94 a 6.63,6.63 0 0 1 1.17,0.12 v 10.4 a 10.4,10.4 0 0 0 -4.69,-1.09 7,7 0 0 0 -5.68,2.26 c -1.26,1.5 -1.9,3.7 -1.9,6.58 v 13.23 h -10.91 z"
id="path26"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<path
class="cls-1"
d="m 390.38,129.14 a 5.92,5.92 0 0 1 0.48,-2.38 6.29,6.29 0 0 1 3.28,-3.27 6,6 0 0 1 4.75,0 6.22,6.22 0 0 1 1.95,1.32 6.43,6.43 0 0 1 1.33,2 6.12,6.12 0 0 1 0,4.75 6.43,6.43 0 0 1 -1.33,2 6.09,6.09 0 0 1 -1.95,1.33 6.12,6.12 0 0 1 -4.75,0 6.09,6.09 0 0 1 -1.95,-1.33 6.25,6.25 0 0 1 -1.33,-2 5.91,5.91 0 0 1 -0.48,-2.42 z M 402,141 v 30.84 H 391.1 V 141 Z"
id="path28"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<path
class="cls-1"
d="m 429.88,148.91 a 12.76,12.76 0 0 0 -5.89,-1.56 4.43,4.43 0 0 0 -2.44,0.6 1.84,1.84 0 0 0 -0.93,1.62 2.14,2.14 0 0 0 0.15,0.88 1.55,1.55 0 0 0 0.66,0.63 5.72,5.72 0 0 0 1.5,0.54 l 2.62,0.6 a 12.44,12.44 0 0 1 6.73,3.22 8.19,8.19 0 0 1 2.22,5.92 10.79,10.79 0 0 1 -1.08,4.87 10.34,10.34 0 0 1 -3,3.63 14.43,14.43 0 0 1 -4.63,2.29 20.68,20.68 0 0 1 -6,0.81 24.16,24.16 0 0 1 -12.33,-3.55 l 4,-7.69 a 15.53,15.53 0 0 0 8.66,3.12 4.25,4.25 0 0 0 2.46,-0.66 2,2 0 0 0 1,-1.68 2.79,2.79 0 0 0 -0.15,-1 1.61,1.61 0 0 0 -0.63,-0.72 5,5 0 0 0 -1.41,-0.61 q -0.93,-0.27 -2.43,-0.57 c -3.37,-0.68 -5.72,-1.69 -7.07,-3 a 7.52,7.52 0 0 1 -2,-5.56 10.94,10.94 0 0 1 1,-4.66 9.58,9.58 0 0 1 2.77,-3.52 12.94,12.94 0 0 1 4.35,-2.22 19.45,19.45 0 0 1 5.68,-0.78 25.79,25.79 0 0 1 9.92,2 z"
id="path30"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<path
class="cls-1"
d="m 449.83,158.23 q 0,7 6.61,7 a 5.9,5.9 0 0 0 5.35,-2.88 h 10.52 Q 469.13,173 456.38,173 a 21,21 0 0 1 -7.15,-1.17 16.16,16.16 0 0 1 -5.56,-3.34 15,15 0 0 1 -3.58,-5.17 17.25,17.25 0 0 1 -1.26,-6.73 19.12,19.12 0 0 1 1.2,-7 14.86,14.86 0 0 1 3.43,-5.26 15.2,15.2 0 0 1 5.38,-3.33 20.37,20.37 0 0 1 7.12,-1.17 20,20 0 0 1 7,1.17 14.23,14.23 0 0 1 5.29,3.4 14.73,14.73 0 0 1 3.3,5.43 21.63,21.63 0 0 1 1.14,7.25 v 1.14 z m 12.75,-6.31 a 6.57,6.57 0 0 0 -2.23,-3.67 6.9,6.9 0 0 0 -8.2,-0.06 6,6 0 0 0 -2,3.73 z"
id="path32"
inkscape:connector-curvature="0"
style="fill:#1e286e" />
<polygon
class="cls-1"
points="87.14,28.17 102.89,28.17 100.64,32.67 105.14,37.17 89.39,37.17 "
id="polygon34"
style="fill:#1e286e" />
<polygon
class="cls-2"
points="80.39,25.92 91.64,25.92 95.05,34.89 83.8,34.89 "
id="polygon36"
style="fill:#4b508c" />
<path
class="cls-3"
d="m 40.47,127.05 h 39.6 a 1.2,1.2 0 0 0 1.2,-1.2 v -39.6 a 1.2,1.2 0 0 0 -1.2,-1.2 h -18.6 a 1.19,1.19 0 0 0 -1.2,1.2 v 18.6 a 1.2,1.2 0 0 1 -1.2,1.2 h -18.6 a 1.19,1.19 0 0 0 -1.2,1.2 v 18.6 a 1.2,1.2 0 0 0 1.2,1.2 z"
id="path38"
inkscape:connector-curvature="0"
style="fill:#fad750" />
<path
class="cls-4"
d="m 80.86,85.35 a 1.17,1.17 0 0 0 -0.79,-0.3 h -18.6 a 1.19,1.19 0 0 0 -1.2,1.2 v 14.14 c 0,0 20.84,-14.82 20.59,-15.04 z"
id="path40"
inkscape:connector-curvature="0"
style="fill:#f5c328" />
<path
class="cls-4"
d="M 52.22,106.05 H 40.47 a 1.19,1.19 0 0 0 -1.2,1.2 v 8.57 z"
id="path42"
inkscape:connector-curvature="0"
style="fill:#f5c328" />
<path
class="cls-5"
d="m 106.11,77.33 -20.65,-35.76 -4,-15.92 a 1.1229426,1.1229426 0 0 0 -2.18,0.54 L 83.1,41.48 62.42,77.33 a 1.15,1.15 0 0 0 1,1.72 h 41.71 a 1.15,1.15 0 0 0 0.98,-1.72 z"
id="path44"
inkscape:connector-curvature="0"
style="fill:#cd0a5a" />
<path
class="cls-6"
d="m 63.09,76.17 -0.67,1.16 a 1.15,1.15 0 0 0 1,1.72 h 41.71 a 1.15,1.15 0 0 0 1,-1.72 L 90,49.47 Z"
id="path46"
inkscape:connector-curvature="0"
style="fill:#ff2d96" />
<path
class="cls-7"
d="m 39.27,134.22 v 41.83 a 1,1 0 0 0 1,1 h 20 a 1,1 0 0 0 1,-1 22,22 0 0 1 43.95,0 1,1 0 0 0 1,1 h 20 a 1,1 0 0 0 1,-1 v -42 a 1,1 0 0 0 -1,-1 H 40.44 a 1.17,1.17 0 0 0 -1.17,1.17 z"
id="path48"
inkscape:connector-curvature="0"
style="fill:#1ea0f5" />
<path
class="cls-8"
d="m 79.23,133.05 h -39 a 1,1 0 0 0 -1,1 v 25 z"
id="path50"
inkscape:connector-curvature="0"
style="fill:#197dbe" />
<rect
class="cls-5"
x="293.26999"
y="102.63"
width="15.43"
height="7.7199998"
rx="0.76999998"
ry="0.76999998"
id="rect52"
style="fill:#cd0a5a" />
<path
class="cls-6"
d="m 307.93,110.34 h -13.09 l 10.3,-7.71 h 2.79 a 0.77,0.77 0 0 1 0.77,0.77 v 6.17 a 0.77,0.77 0 0 1 -0.77,0.77 z"
id="path54"
inkscape:connector-curvature="0"
style="fill:#ff2d96" />
<circle
class="cls-9"
cx="106.27"
cy="106.05"
r="21"
id="circle56"
style="fill:#46dcc3" />
<path
class="cls-10"
d="m 98.09,125.39 a 21,21 0 0 0 29.18,-19.34 c 0,-0.45 0,-0.89 0,-1.32 z"
id="path58"
inkscape:connector-curvature="0"
style="fill:#91ebc3" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -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</1> 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:
</3>
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.</0><1><0>Start registration process</0></1>
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.
</0>
<1>
This is an interesting choice if:
</1>
<2>
<0>You do not need a lot of capital and important expenses to run your activity</0>
<1>You want to test the viability of your business</1>
<2>You want the minimum amount of paperwork to get started</2>
</2>
<3>
<0>Note:</0>
Some activities are excluded from this status (<2>see the list [fr]</2>). Some activities
are regulated with a qualification or a professional experience (<4>see the list [fr])</4>).
</3>
<4>
For all the other cases, it is advised to choose the standard status, which
is <1>Individual Business.</1>
</4>
</1>
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.</0><1><0><0>Salaried employee:</0> The company director joins and is covered by Frances 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).</0><1><0>Self-employed:</0> The company director joins and is covered by Frances 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).</1></1>
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)</2>
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</2> and access the new features in preview?
description2: 'Register to our <1>monthly newsletter</1> by leaving your email:'
titre: Stay informed
description: |
Subscribe to our monthly newsletter to receive <2>official advice on starting a business</2> and access new features in advance.
S'inscrire: Register
simulationWarning: This is an estimate based on <2>purely theoretical data</2> 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.</5>
@ -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</2>: 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</0>
<1> General scheme <1>(Régime général)</1></1>
<2> Self-employed scheme <1>(Sécurité sociale des indépendants)</1></2>
AT: <0> Work-related accidents covered</0>
assuranceMaladie: |
<0> Public health insurance <1>(medicines, care, hospitalizations)</1></0>
<1> Same for all </1>
mutuelle: |
<0> Additional health insurance <1>(mutuelle santé)</1></0>
<1> Compulsory </1>
<2> Highly recommended </2>
indemnités: |
<0> Sickness allowances</0>
plafondCA: |
<0> Turnover ceiling</0>
<1>No</1>
<2>
Yes<1>(€70,000 in services, €170,000 for sale of properties, food or accommodation)</1>
</2>
période: |
<0>Period</0>
retraite: |
<0>Retirement pay</0>
comparaisonDétaillée: |
<0><0> View more information </0></0>
comptabilité: |
<0> Accounting, social, legal management....</0>
<1> Support strongly recommended <1>(chartered accountant, accountant, chartered management centre...)</1></1>
<2> Simplified <1>(can be managed by the auto-entrepreneur)</1></1>
ACRE: |
<0>ACRE</0>
<1>1 year<1>(partial contribution exemption)</1></1>
<2>3 years<1>(application of reduced contribution rates)</1></2>
déduction: |
<0> Deduction of expenses</0>
<1>Yes <1>(tax regime of the actual)</1></1>
<2>No <1>(but lump-sum deduction for calculating income tax)</1></2>
simulationText: |
<0>
Compare my income, retirement pay and sickness allowance
</0>
<1/>
<2>Start simulation</2>
cotisations: |
<0> Payment of social contributions</0>
<1> Monthly</1>
<2> Monthly or quaterly advance <1>(with posterior regularization based on real income)</1></2>
<3> Montly or quaterly</3>
complémentaireDeductible: |
<0> Optional health and pension policies deductible</0>
<1> Yes <1>(under certain conditions)</1></1>
<2> Yes <1>("Madelin" Law)</1></2>
revenuNetApresImpots: |
<0>Net income after taxes</0>
revenuNetAvantImpots: |
<0>Net contribution income<1>(before income tax)</1></0>
retraiteEstimation:
legend: |
<0>Retirement pay</0>
<1>(before taxes)</1>
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</0>
seuil: |
<0> Minimum income for eligibility for benefits</0>
<1>Yes</1>
<2> No <1>(mandatory minimum contributions)</1></2>
<3>Yes</3>
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

View File

@ -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
})

View File

@ -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<EFBFBD><EFBFBD>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 dun régime de retraite dès lors quils 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: |
LAssurance 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** despé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, lAssurance chômage protège tous les salariés du privé et certains du secteur public lorsquils perdent leur emploi. Elle leur verse une allocation et favorise leur retour à lemploi 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 lun 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: |
Lassurance 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 à lannée 1898 et qui ont été repris dans la loi du 31 décembre 1946.
@ -3712,6 +4152,20 @@
En cas dAT/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, dacquérir et dactualiser ses connaissances et ses compétences, daccroî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...).

View File

@ -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 dun régime de retraite dès lors quils 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: "LAssurance Maladie protège durablement la santé de chacun dans sa vie personnelle ou professionnelle.\n\nConcrètement, elle accompagne 60 millions dassuré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 laccè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** despérance de vie moyenne en france (dans le top 10 mondial \U0001F3C5)\n"
description.fr: "LAssurance Maladie protège durablement la santé de chacun dans sa vie personnelle ou professionnelle.\n\nConcrètement, elle accompagne 60 millions dassuré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 laccè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** despé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: "Lassurance 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 à lanné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 lemployeur.\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 dAT/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)

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -24,6 +24,5 @@ export const createStateFromSavedSimulation: (
conversationSteps: {
foldedSteps: simulation.foldedSteps
},
conversationStarted: true,
previousSimulation: null
}

View File

@ -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 (
<Switch>
<Route exact path="/" component={Landing} />
<Route path="/iframes" component={Iframes} />
<Route component={App} />
</Switch>
<>
{!inIframe() && <Navigation location={location} />}
<Switch>
<Route exact path="/" component={Landing} />
<Route path="/iframes" component={Iframes} />
<Route component={App} />
</Switch>
</>
)
})
@ -105,7 +108,6 @@ const App = compose(
<div className="app-container">
<Helmet titleTemplate={`%s | ${t(['siteName', 'Mon-entreprise.fr'])}`} />
{/* Passing location down to prevent update blocking */}
{!inIframe() && <Navigation location={location} />}
<div className="app-content">
{!inIframe() && <Header />}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/favicon/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1,77 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1216.000000pt" height="1216.000000pt" viewBox="0 0 1216.000000 1216.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,1216.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M5810 12147 c-30 -24 -48 -59 -44 -86 3 -14 18 -78 34 -141 43 -169
141 -563 145 -580 2 -8 22 -89 45 -180 43 -172 48 -189 56 -229 3 -14 7 -28 9
-32 3 -4 7 -22 10 -41 5 -31 -8 -59 -115 -244 -66 -115 -124 -216 -129 -224
-31 -49 -101 -175 -101 -182 0 -4 -4 -8 -10 -8 -5 0 -10 -6 -10 -14 0 -8 -7
-22 -16 -30 -8 -9 -13 -16 -10 -16 3 0 -9 -24 -27 -52 -18 -29 -38 -64 -45
-78 -7 -14 -25 -46 -41 -72 -16 -25 -42 -68 -57 -95 -59 -104 -125 -219 -134
-233 -31 -48 -110 -193 -110 -201 0 -5 -3 -9 -8 -9 -7 0 -10 -5 -46 -77 -11
-21 -31 -56 -45 -78 -14 -22 -36 -60 -50 -85 -13 -25 -29 -48 -35 -52 -6 -4
-7 -8 -3 -8 5 0 0 -12 -11 -27 -10 -16 -31 -48 -44 -73 -14 -25 -38 -67 -54
-95 -15 -27 -33 -53 -38 -57 -6 -4 -7 -8 -3 -8 4 0 -4 -17 -18 -37 -14 -21
-25 -43 -25 -50 0 -7 -4 -13 -9 -13 -5 0 -11 -8 -14 -17 -4 -10 -20 -40 -37
-68 -17 -27 -33 -58 -37 -67 -3 -10 -8 -18 -12 -18 -4 0 -13 -16 -21 -35 -8
-19 -17 -35 -21 -35 -4 0 -9 -6 -11 -13 -2 -10 -143 -259 -178 -317 -5 -8 -24
-40 -41 -70 -102 -177 -108 -199 -63 -244 15 -14 29 -26 33 -27 51 -4 3376 1
3399 6 18 3 30 11 26 16 -3 5 -1 9 4 9 12 0 30 49 27 71 -2 13 -90 171 -152
274 -7 11 -15 27 -19 35 -4 8 -25 43 -46 78 -21 34 -38 66 -38 71 0 5 -3 11
-7 13 -5 2 -17 21 -28 43 -11 22 -22 42 -25 45 -5 5 -115 195 -133 230 -4 8
-18 33 -32 55 -14 22 -28 47 -32 55 -4 8 -9 17 -13 20 -3 3 -14 21 -23 40 -10
19 -26 49 -37 65 -10 17 -25 41 -33 55 -57 102 -71 126 -77 135 -4 6 -19 30
-32 55 -45 80 -140 244 -156 270 -9 14 -17 27 -17 30 0 5 -26 48 -132 228 -24
41 -43 78 -43 83 0 5 -4 9 -10 9 -5 0 -10 5 -10 11 0 6 -20 43 -43 82 -24 40
-55 92 -69 117 -14 25 -58 101 -98 170 -40 69 -80 139 -90 155 -9 17 -32 56
-51 88 -19 33 -43 75 -55 95 -11 21 -47 82 -79 137 -32 55 -64 111 -71 125
-10 20 -55 182 -69 250 -2 8 -4 15 -5 15 -1 0 -3 9 -5 21 -3 11 -12 47 -20 80
-9 32 -19 73 -22 89 -3 17 -9 38 -14 48 -5 9 -7 17 -3 17 3 0 1 7 -6 15 -15
18 -27 16 207 19 89 0 172 -2 185 -6 13 -3 20 -6 16 -7 -4 -1 -2 -16 3 -33 6
-18 12 -42 14 -53 2 -11 8 -33 12 -50 l9 -30 629 -1 628 -2 -180 182 -180 181
47 90 c26 50 46 93 44 97 -2 3 0 8 4 10 7 3 82 143 82 154 0 2 -186 4 -414 4
l-413 0 -28 78 c-15 42 -32 83 -38 90 -7 9 -101 12 -407 12 l-398 0 -16 34
c-9 19 -24 37 -33 42 -32 13 -78 14 -93 1z"/>
<path d="M4305 7336 c-59 -27 -57 9 -56 -822 0 -560 -3 -771 -11 -790 -26 -55
-3 -54 -833 -54 -847 0 -802 4 -825 -64 -7 -23 -10 -271 -9 -787 2 -812 0
-782 53 -812 32 -18 3210 -19 3247 -1 58 29 54 -92 55 1658 1 1757 4 1649 -54
1675 -15 8 -271 11 -780 11 -611 -1 -763 -3 -787 -14z"/>
<path d="M7756 7342 c-2 -2 -18 -5 -35 -7 -68 -9 -117 -16 -131 -20 -8 -2 -31
-7 -50 -10 -62 -10 -242 -76 -345 -125 -207 -100 -390 -240 -550 -424 -27 -31
-54 -66 -59 -76 -5 -11 -13 -20 -18 -20 -4 0 -8 -6 -8 -14 0 -8 -4 -16 -9 -18
-25 -9 -167 -273 -192 -358 -7 -22 -17 -40 -22 -40 -6 0 -8 -3 -4 -6 3 -3 -3
-30 -13 -60 -11 -30 -17 -54 -15 -54 3 0 0 -11 -5 -26 -6 -14 -12 -39 -15 -57
-3 -18 -8 -39 -10 -47 -4 -15 -13 -73 -21 -135 -11 -97 -5 -332 12 -430 3 -16
7 -41 9 -55 13 -79 71 -278 86 -294 5 -6 9 -15 9 -22 0 -12 70 -162 93 -199
59 -95 121 -186 142 -209 14 -15 25 -30 25 -34 0 -13 213 -217 277 -265 237
-180 519 -295 820 -334 66 -8 338 -8 393 1 25 4 61 9 81 11 76 8 265 63 367
106 23 10 46 19 50 20 7 2 71 36 156 84 150 84 344 252 461 399 157 197 287
476 331 706 2 14 7 36 10 49 19 84 26 382 12 491 -14 102 -19 135 -25 150 -3
8 -7 28 -10 43 -5 35 -59 200 -77 242 -139 311 -292 508 -552 713 -23 17 -46
32 -52 32 -6 0 -12 4 -14 8 -3 7 -75 53 -144 92 -17 10 -64 32 -105 50 -41 17
-83 35 -94 40 -23 11 -139 48 -175 56 -96 22 -147 31 -220 40 -51 7 -359 12
-364 6z"/>
<path d="M2620 3508 c-10 -4 -26 -18 -35 -31 -14 -22 -16 -183 -14 -1713 1
-996 5 -1699 11 -1715 5 -14 20 -31 34 -38 18 -8 253 -11 843 -11 l818 0 27
25 c15 14 26 35 27 52 2 75 12 166 24 223 3 14 8 39 11 55 24 135 83 300 158
445 21 41 44 85 50 97 6 13 14 23 19 23 4 0 7 7 7 15 0 8 5 15 10 15 6 0 10 5
10 10 0 6 5 16 10 23 6 7 34 44 62 82 57 78 216 241 293 301 28 21 52 42 53
47 2 4 10 7 18 7 8 0 14 4 14 8 0 5 19 19 41 33 23 13 58 34 78 46 42 26 170
94 174 92 1 -1 22 8 47 19 97 43 250 88 365 107 17 3 40 8 51 10 31 7 199 18
264 18 59 0 206 -11 255 -19 17 -3 44 -7 60 -9 31 -5 159 -37 185 -47 8 -4 29
-9 45 -13 17 -4 44 -13 60 -20 17 -8 57 -25 91 -39 99 -41 311 -164 354 -206
9 -8 31 -26 50 -40 19 -14 56 -46 82 -71 27 -26 48 -44 48 -42 0 3 12 -10 28
-28 15 -18 40 -46 56 -63 125 -128 285 -409 346 -606 13 -41 25 -82 28 -90 8
-23 10 -33 16 -60 3 -14 9 -38 13 -55 3 -16 7 -37 8 -45 1 -8 5 -33 9 -55 3
-22 8 -69 10 -105 6 -79 18 -115 45 -130 14 -7 277 -10 845 -10 l826 0 20 22
c11 12 21 27 21 32 4 31 5 3394 1 3409 -3 10 -16 26 -30 35 -23 15 -279 16
-3474 17 -1897 0 -3457 -3 -3468 -7z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -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;

View File

@ -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 }) => {
/>
))}
</Helmet>
<PageFeedback
stickToFooter={true}
blacklist={feedbackBlacklist.map(lens => view(lens, sitePaths))}
/>
<footer className="footer">
<PageFeedback
blacklist={feedbackBlacklist.map(lens => view(lens, sitePaths))}
/>
<div className="ui__ container">
<div id="footerIcons">
<a href="https://www.urssaf.fr">
<img src={urssafSvg} alt="un service fourni par l'Urssaf" />
</a>
<a href="https://beta.gouv.fr">
<img
src={betaGouvSvg}
alt="un service de lEtat français incubé par beta.gouv.fr"
/>
</a>
</div>
{!registered && (
<>
<p>
<T k="newsletter.register.description1">
Vous voulez des{' '}
<strong>
conseils officiels sur la création dentreprise
</strong>{' '}
et accéder aux nouvelles fonctionnalités en avant-première ?
</T>
</p>
<p>
<T k="newsletter.register.description2">
Inscrivez-vous à notre <strong>newsletter mensuelle</strong>{' '}
en laissant votre email :
</T>
</p>
<form
className="footer__registerContainer"
action="https://gouv.us13.list-manage.com/subscribe/post?u=732a4d1b0d2e8a1a1fd3d01db&amp;id=f146678e48"
method="post"
onSubmit={onSubmit}
id="mc-embedded-subscribe-form"
name="mc-embedded-subscribe-form"
target="_blank">
<div className="footer__registerField">
<input type="email" name="EMAIL" id="mce-EMAIL" />
<input
className="ui__ plain button"
type="submit"
value={t("S'inscrire")}
name="subscribe"
id="mc-embedded-subscribe"
/>
</div>
</form>
{' '}
<h2>
<T k="newsletter.register.titre">Restez informé</T>
</h2>
<div className="footer__newsletterContainer">
<p>
<T k="newsletter.register.description">
Inscrivez-vous à notre newsletter mensuelle pour recevoir
des{' '}
<strong>
conseils officiels sur la création dentreprise
</strong>{' '}
et accéder aux nouvelles fonctionnalités en avant-première.
</T>
</p>
<form
className="footer__registerContainer"
action="https://gouv.us13.list-manage.com/subscribe/post?u=732a4d1b0d2e8a1a1fd3d01db&amp;id=f146678e48"
method="post"
onSubmit={onSubmit}
id="mc-embedded-subscribe-form"
name="mc-embedded-subscribe-form"
target="_blank">
<div>
<label htmlFor="mce-EMAIL">
<T>Votre adresse e-mail</T>
</label>
<div className="footer__registerField">
<input type="email" name="EMAIL" id="mce-EMAIL" />
<input
className="ui__ plain small button"
type="submit"
value={t("S'inscrire")}
name="subscribe"
id="mc-embedded-subscribe"
/>
</div>
</div>
</form>
</div>
</>
)}
<hr className="footer__separator" />
{i18n.language === 'en' && (
<p className="ui__ notice">
This website is provided by the{' '}
@ -126,6 +120,7 @@ const Footer = ({ tracker, t, sitePaths }) => {
.
</p>
)}
<div style={{ display: 'flex', justifyContent: 'center' }}>
<a href="https://www.facebook.com/monentreprisefr/">
<SocialIcon media="facebook" />

View File

@ -33,7 +33,7 @@ const StepsHeader = ({ showHiring, tracker, sitePaths }: Props) => (
}>
<img src={companySvg} />
<div>
<T>Votre entreprise</T>
<T>Mon entreprise</T>
</div>
</NavLink>
<NavLink

View File

@ -90,9 +90,10 @@
.navigation > ul > li > :first-child * {
text-decoration: none !important;
line-height: 2rem;
font-family: 'IBM Plex Sans', sans-serif;
font-weight: 300;
font-size: 1.5rem;
font-family: 'Montserrat', sans-serif;
font-weight: 600;
color: var(--darkColour);
font-size: 1.3rem;
}
.navigation > ul > li > :first-child .navigation__caret {
visibility: hidden;

View File

@ -39,7 +39,7 @@ const StepsHeader = ({ t, sitePaths, companyStatusChoice }: Props) => (
exact={false}
title={
<>
<T>Votre entreprise</T>
<T>Mon entreprise</T>
<img
style={{ height: '2.5rem', marginBottom: '-0.8rem' }}
src={companySvg}
@ -48,7 +48,7 @@ const StepsHeader = ({ t, sitePaths, companyStatusChoice }: Props) => (
}>
<ul>
<li>
<NavOpener title={t('Créer votre entreprise')}>
<NavOpener title={t('Créer mon entreprise')}>
<ul>
<li>
<NavOpener
@ -181,7 +181,7 @@ const StepsHeader = ({ t, sitePaths, companyStatusChoice }: Props) => (
</li>
<li>
<NavLink to={sitePaths.entreprise.trouver}>
<T k="trouver.titre">Retrouver votre entreprise</T>
<T k="trouver.titre">Retrouver mon entreprise</T>
</NavLink>
</li>
</ul>
@ -227,15 +227,13 @@ const StepsHeader = ({ t, sitePaths, companyStatusChoice }: Props) => (
<T>Auto-entrepreneur</T>
</NavLink>
</li>
{process.env.MASTER && (
<li>
<NavLink
exact
to={sitePaths.sécuritéSociale.comparaison}>
<T>Comparaison des régimes</T>
</NavLink>
</li>
)}
<li>
<NavLink
exact
to={sitePaths.sécuritéSociale.comparaison}>
<T>Comparer les régimes</T>
</NavLink>
</li>
</ul>
</NavOpener>
</li>

View File

@ -17,7 +17,7 @@ type OwnProps = {|
type Props = OwnProps & {
tracker: Tracker,
location: Location,
location: Location
}
type State = {
opened: boolean,
@ -97,5 +97,5 @@ class SideBar extends React.Component<Props, State> {
export default (compose(
withTracker,
withRouter,
withRouter
)(SideBar): React$ComponentType<OwnProps>)

View File

@ -30,13 +30,13 @@ const AfterRegistration = ({ t, companyStatusChoice, sitePaths }: Props) => {
</h1>
<p>
<T k="après.intro">
Une fois que votre{' '}
Une fois votre{' '}
{{
companyStatusChoice: isAutoentrepreneur
? t('auto-entreprise')
: companyStatusChoice || t(['après.entreprise', 'entreprise'])
}}{' '}
aura été créée, vous recevrez les informations suivantes :
créée, vous recevez les informations suivantes :
</T>
</p>
<h2>
@ -63,7 +63,11 @@ const AfterRegistration = ({ t, companyStatusChoice, sitePaths }: Props) => {
<T k="après.ape.description">
Le code APE correspond au <strong>secteur d'activité</strong> de votre
entreprise. Il classifie la branche principale de votre entreprise
dans la nomenclature nationale d'activités françaises (code « NAF »).{' '}
dans la nomenclature nationale d'activités françaises « NAF » (
<a href="https://www.insee.fr/fr/metadonnees/nafr2/section/A?champRecherche=false">
voir la liste
</a>
).{' '}
<span
style={
companyStatusChoice &&
@ -72,9 +76,16 @@ const AfterRegistration = ({ t, companyStatusChoice, sitePaths }: Props) => {
: {}
}>
Il détermine aussi la convention collective applicable à
l'entreprise, et en partie le taux de la cotisation accident du
l'entreprise, et en partie le taux de la cotisation accidents du
travail et maladies professionnelles à payer.
</span>
<p>
En cas de code APE erroné, vous pouvez{' '}
<a href="https://www.insee.fr/fr/information/2015441">
demander une modification
</a>{' '}
à l'INSEE.
</p>
</T>
</p>
{companyStatusChoice &&
@ -88,7 +99,10 @@ const AfterRegistration = ({ t, companyStatusChoice, sitePaths }: Props) => {
C'est le document officiel qui atteste de{' '}
<strong>l'existence légale d'une entreprise commerciale</strong>
. Le plus souvent, pour être valable par les procédures
administratives, il doit dater de moins de 3 mois.
administratives, il doit dater de moins de 3 mois.{' '}
<a href="https://www.service-public.fr/professionnels-entreprises/vosdroits/F21000">
Plus d'infos.
</a>
</T>
</p>
<p>
@ -100,9 +114,7 @@ const AfterRegistration = ({ t, companyStatusChoice, sitePaths }: Props) => {
</p>
</>
)}
<p
className="ui__ answer-group"
style={{ justifyContent: 'space-between' }}>
<p className="ui__ answer-group">
<Link
to={sitePaths.entreprise.index}
className="ui__ simple skip button left">

Some files were not shown because too many files have changed in this diff Show More