🔥 Migration vers TypeScript
Outils ====== Ce commit retire le tooling de Flow, et ajoute le support de TypeScript pour les fichiers .ts et .tsx. Il n'est pas nécessaire de tout migrer d'un coup ce qui facilite la transition. On garde en effet le compilateur Babel avec un preset TypeScript (ce qui permet donc de retirer à la fois les types Flow et TypeScript) plutôt que d'utiliser le compilateur standard pour la conversion du code. Cela permet aussi de mieux s'intégrer avec d'autres outils, notamment les test-runners. Ajout d'une nouvelle commande `yarn run type-check`, intégrée dans CircleCI. Par ailleurs ajout du support de l'opérateur ?? pour donner des valeurs par défaut (nullish-coalescing-operator). Typage des libraires tierces ============================ Les principales libraires que nous utilisons ont un typage TypeScript de bon niveau, ce qui facilite l'intégration. J'ai mis à jour react-i18next et i18next afin de corriger un problème de typage. Typage du code ============== Le typage est loin d'être complet dans ce commit, en particulier il manque les types relatifs au state Redux, ainsi qu'au moteur (règle, explication). Néanmoins le typage des contextes fonctionne, en particulier sitePaths (avec un type récursif non trivial !) qui a déjà permis de détecter un lien mort. Le typage des "paths" (Components/, Règles/, etc.) fonctionne bien, y compris avec l'auto-complétion automatique des import par Typescript. TypeScript se révèle déjà bien agréable dans VSCode (auto-complétion, refacto, etc.) ! Reste à migrer progressivement le reste du code !pull/764/head
parent
ac4e3cd615
commit
6de970f0e3
|
@ -18,7 +18,6 @@ parser: babel-eslint
|
|||
plugins:
|
||||
- react
|
||||
- react-hooks
|
||||
- flowtype
|
||||
env:
|
||||
browser: true
|
||||
commonjs: true
|
||||
|
@ -38,7 +37,6 @@ globals:
|
|||
|
||||
extends:
|
||||
- eslint:recommended
|
||||
- plugin:flowtype/recommended
|
||||
- plugin:react/recommended
|
||||
- prettier
|
||||
- prettier/flowtype
|
||||
|
|
33
.flowconfig
33
.flowconfig
|
@ -1,33 +0,0 @@
|
|||
[ignore]
|
||||
|
||||
<PROJECT_ROOT>/documentation/.*
|
||||
<PROJECT_ROOT>/node_modules/.*
|
||||
|
||||
[include]
|
||||
|
||||
|
||||
[libs]
|
||||
|
||||
[options]
|
||||
esproposal.class_static_fields=enable
|
||||
esproposal.class_instance_fields=enable
|
||||
esproposal.optional_chaining=enable
|
||||
|
||||
suppress_type=$FlowIssue
|
||||
suppress_type=$FlowFixMe
|
||||
suppress_type=$FixMe
|
||||
suppress_type=$FlowExpectedError
|
||||
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
|
||||
module.name_mapper='^Engine\(.*\)$' -> '<PROJECT_ROOT>/source/engine\1'
|
||||
module.name_mapper='^Règles\(.*\)$' -> '<PROJECT_ROOT>/source/règles\1'
|
||||
module.name_mapper='^Ui\(.*\)$' -> '<PROJECT_ROOT>/source/components/ui\1'
|
||||
module.name_mapper='^Components\(.*\)$' -> '<PROJECT_ROOT>/source/components\1'
|
||||
module.name_mapper='^Selectors\(.*\)$' -> '<PROJECT_ROOT>/source/selectors\1'
|
||||
module.name_mapper='^Reducers\(.*\)$' -> '<PROJECT_ROOT>/source/reducers\1'
|
||||
module.name_mapper='^Actions\(.*\)$' -> '<PROJECT_ROOT>/source/actions\1'
|
||||
module.name_mapper='^Types\(.*\)$' -> '<PROJECT_ROOT>/source/types\1'
|
||||
module.name_mapper='^Images\(.*\)$' -> '<PROJECT_ROOT>/source/images\1'
|
22
.prettierrc
22
.prettierrc
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"printWidth": 80,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": true,
|
||||
"jsxBracketSameLine": true,
|
||||
"useTabs": true,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"arrowParens": "avoid",
|
||||
"proseWrap": "preserve",
|
||||
"tabWidth": 2
|
||||
}
|
||||
"printWidth": 80,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": true,
|
||||
"jsxBracketSameLine": true,
|
||||
"useTabs": true,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"arrowParens": "avoid",
|
||||
"proseWrap": "preserve",
|
||||
"tabWidth": 2
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"flowtype.flow-for-vscode",
|
||||
"esbenp.prettier-vscode",
|
||||
"ban.spellright",
|
||||
"jpoissonnier.vscode-styled-components"
|
||||
|
|
|
@ -4,9 +4,11 @@
|
|||
"fr"
|
||||
],
|
||||
"spellright.documentTypes": [
|
||||
"yaml"
|
||||
"yaml",
|
||||
"git-commit"
|
||||
],
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib"
|
||||
}
|
||||
|
|
|
@ -18,13 +18,13 @@ L'application est écrite en JavaScript, elle est exécuté uniquement côté cl
|
|||
|
||||
Nous utilisons :
|
||||
|
||||
- [TypeScript](https://www.typescriptlang.org) pour ajouter un système de typage à notre code JavaScript. Le typage n'est pas utilisé partout et il n'est pas obligatoire de le prendre en compte pour contribuer.
|
||||
- [Yarn](https://yarnpkg.com/fr) pour la gestion des dépendances (à la place de NPM qui est souvent utilisé dans les applications JavaScript)
|
||||
- [React](https://reactjs.org) pour la gestion de l'interface utilisateur
|
||||
- [Redux](https://redux.js.org) pour gérer le “state” de l'application côté client
|
||||
- [Prettier](https://prettier.io/) pour formater le code source, l'idéal est de configurer votre éditeur de texte pour que les fichiers soit formatés automatiquement quand vous sauvegardez un fichier. Si vous utilisez [VS Code](https://code.visualstudio.com/) cette configuration est automatique.
|
||||
- [Webpack](https://webpack.js.org) pour le “bundling”
|
||||
- [Eslint](http://eslint.org) qui permet par exemple d'éviter de garder des variables inutilisées
|
||||
- [Flow](https://flow.org/) pour ajouter un système de typage à notre code JavaScript. Le typage Flow n'est pas utilisé partout et il n'est pas obligatoire de le prendre en compte pour contribuer.
|
||||
- [Ramda](https://ramdajs.com) comme libraire d'utilitaires pour manipuler les listes/objects/etc (c'est une alternative à lodash ou underscore)
|
||||
- [Mocha](https://mochajs.org), [Jest](https://jestjs.io) et [Cypress](https://www.cypress.io) pour les l'execution des tests. Plus d'informations dans la section consacrée aux tests.
|
||||
|
||||
|
|
|
@ -9,12 +9,13 @@ module.exports = {
|
|||
}
|
||||
],
|
||||
'@babel/react',
|
||||
'@babel/preset-typescript',
|
||||
'@babel/flow'
|
||||
],
|
||||
plugins: [
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
'@babel/plugin-proposal-do-expressions',
|
||||
'@babel/plugin-proposal-optional-chaining',
|
||||
'@babel/plugin-proposal-nullish-coalescing-operator',
|
||||
'@babel/plugin-proposal-object-rest-spread',
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
'react-hot-loader/babel',
|
||||
|
|
10
circle.yml
10
circle.yml
|
@ -30,13 +30,20 @@ commands:
|
|||
- run: CYPRESS_baseUrl=<< parameters.base_url >> yarn run cypress run --parallel --record --key 21660df5-36a5-4c49-b23d-801799b0c759 --env language=<< parameters.language >> --config integrationFolder=cypress/integration/<< parameters.integration_folder >>
|
||||
|
||||
jobs:
|
||||
type-check:
|
||||
docker:
|
||||
- image: node
|
||||
steps:
|
||||
- install
|
||||
- run: |
|
||||
yarn run type-check
|
||||
|
||||
unit-test:
|
||||
docker:
|
||||
- image: node
|
||||
steps:
|
||||
- install
|
||||
- run: |
|
||||
yarn run flow-typed install
|
||||
git config --global core.quotepath false
|
||||
yarn test
|
||||
yarn test-regressions
|
||||
|
@ -86,6 +93,7 @@ workflows:
|
|||
version: 2
|
||||
test:
|
||||
jobs:
|
||||
- type-check
|
||||
- unit-test
|
||||
- end-to-end-test
|
||||
- production-end-to-end-test:
|
||||
|
|
|
@ -177,7 +177,7 @@ module.exports = {
|
|||
// ie ['jest-transform-nearley', 'babel-jest'], so we removed ES6 module from nearley output.
|
||||
'\\.ne$': 'jest-transform-nearley',
|
||||
'\\.yaml$': 'yaml-jest',
|
||||
'\\.js?$': 'babel-jest'
|
||||
'\\.(js|tsx?)$': 'babel-jest'
|
||||
},
|
||||
|
||||
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
"source/**/*"
|
||||
],
|
||||
"paths": {
|
||||
"Engine": [
|
||||
"source/engine"
|
||||
],
|
||||
"Règles": [
|
||||
"source/règles"
|
||||
],
|
||||
"Actions": [
|
||||
"source/actions"
|
||||
],
|
||||
"Ui": [
|
||||
"source/components/ui"
|
||||
],
|
||||
"Components": [
|
||||
"source/components"
|
||||
],
|
||||
"Selectors": [
|
||||
"source/selectors"
|
||||
],
|
||||
"Reducers": [
|
||||
"source/reducers"
|
||||
],
|
||||
"Types": [
|
||||
"source/types"
|
||||
],
|
||||
"Images": [
|
||||
"source/image"
|
||||
]
|
||||
}
|
||||
}
|
23
package.json
23
package.json
|
@ -26,7 +26,7 @@
|
|||
"core-js": "^3.2.1",
|
||||
"focus-trap-react": "^3.1.2",
|
||||
"fuse.js": "^3.4.2",
|
||||
"i18next": "^14.1.1",
|
||||
"i18next": "^18.0.1",
|
||||
"iframe-resizer": "^4.1.1",
|
||||
"js-yaml": "^3.13.1",
|
||||
"moo": "^0.5.0",
|
||||
|
@ -41,7 +41,7 @@
|
|||
"react-easy-emoji": "^1.2.0",
|
||||
"react-helmet": "6.0.0-beta",
|
||||
"react-highlight-words": "^0.11.0",
|
||||
"react-i18next": "^10.0.1",
|
||||
"react-i18next": "^11.0.0",
|
||||
"react-loading-skeleton": "^1.1.2",
|
||||
"react-markdown": "^4.1.0",
|
||||
"react-number-format": "^4.0.8",
|
||||
|
@ -85,6 +85,7 @@
|
|||
"test-expressions": "yarn test-common --grep 'Suite expressions'",
|
||||
"test-units": "mocha-webpack --webpack-config source/webpack.test.js --require source-map-support/register --include componentTestSetup.js --require mock-local-storage --require test/helpers/browser.js test/units.test.js",
|
||||
"test-regressions": "jest",
|
||||
"type-check": "tsc --noEmit",
|
||||
"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",
|
||||
|
@ -96,13 +97,25 @@
|
|||
"devDependencies": {
|
||||
"@babel/core": "^7.6.4",
|
||||
"@babel/plugin-proposal-class-properties": "^7.1.0",
|
||||
"@babel/plugin-proposal-do-expressions": "^7.0.0",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.0.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
|
||||
"@babel/preset-env": "^7.6.3",
|
||||
"@babel/preset-flow": "^7.0.0-beta.51",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/preset-typescript": "^7.6.0",
|
||||
"@types/iframe-resizer": "^3.5.7",
|
||||
"@types/node": "^12.11.7",
|
||||
"@types/ramda": "^0.26.33",
|
||||
"@types/react": "^16.9.11",
|
||||
"@types/react-addons-css-transition-group": "^15.0.5",
|
||||
"@types/react-dom": "^16.9.3",
|
||||
"@types/react-helmet": "^5.0.13",
|
||||
"@types/react-redux": "^7.1.5",
|
||||
"@types/react-router": "^5.1.2",
|
||||
"@types/react-router-dom": "^5.1.0",
|
||||
"@types/styled-components": "^4.1.19",
|
||||
"akh": "^3.1.2",
|
||||
"autoprefixer": "^9.3.1",
|
||||
"babel-eslint": "^11.0.0-beta.0",
|
||||
|
@ -123,13 +136,10 @@
|
|||
"enzyme-adapter-react-16": "^1.1.1",
|
||||
"eslint": "^6.5.1",
|
||||
"eslint-config-prettier": "^4.0.0",
|
||||
"eslint-plugin-flowtype": "^3.2.1",
|
||||
"eslint-plugin-react": "^7.12.4",
|
||||
"eslint-plugin-react-hooks": "^2.0.1",
|
||||
"express": "^4.16.3",
|
||||
"file-loader": "^1.1.11",
|
||||
"flow-bin": "^0.92.0",
|
||||
"flow-typed": "^2.4.0",
|
||||
"html-loader": "^0.5.5",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"http-server": "^0.11.1",
|
||||
|
@ -159,6 +169,7 @@
|
|||
"style-loader": "^0.23.1",
|
||||
"styled-components": "^4.2.0",
|
||||
"toml-loader": "^1.0.0",
|
||||
"typescript": "^3.7.1-rc",
|
||||
"url-loader": "^1.0.1",
|
||||
"webpack": "^4.39.3",
|
||||
"webpack-cli": "^3.1.2",
|
||||
|
|
|
@ -23,9 +23,11 @@ if (
|
|||
navigator.serviceWorker
|
||||
.register('/sw.js')
|
||||
.then(registration => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('SW registered: ', registration)
|
||||
})
|
||||
.catch(registrationError => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('SW registration failed: ', registrationError)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
/* @flow */
|
||||
import { debounce } from './utils'
|
||||
import type { BrowserHistory } from 'history/createBrowserHistory'
|
||||
|
||||
type PushType = (
|
||||
| ['trackPageView']
|
||||
| ['trackEvent', string, string]
|
||||
| ['trackEvent', string, string, string]
|
||||
| ['trackEvent', string, string, string, number]
|
||||
) => void
|
||||
declare global {
|
||||
interface Window { _paq: any; }
|
||||
}
|
||||
|
||||
function push(args: ['trackPageView']): void
|
||||
function push(args: ['trackEvent']): void
|
||||
function push(args: ['trackEvent', string, string]): void
|
||||
function push(args: ['trackEvent', string, string, string]): void
|
||||
function push(args: ['trackEvent', string, string, string, string, string]): void
|
||||
function push(args: ['trackEvent', string, string, string, number]): void
|
||||
function push() {}
|
||||
type PushType = typeof push
|
||||
|
||||
export default class Tracker {
|
||||
push: PushType
|
||||
|
@ -16,10 +20,10 @@ export default class Tracker {
|
|||
|
||||
constructor(pushFunction: PushType = args => window._paq.push(args)) {
|
||||
if (typeof window !== 'undefined') window._paq = window._paq || []
|
||||
this.push = debounce(200, pushFunction)
|
||||
this.push = debounce(200, pushFunction) as PushType
|
||||
}
|
||||
|
||||
connectToHistory(history: BrowserHistory) {
|
||||
connectToHistory(history) {
|
||||
this.unlistenFromHistory = history.listen(loc => {
|
||||
this.track(loc)
|
||||
})
|
||||
|
@ -48,5 +52,5 @@ export default class Tracker {
|
|||
}
|
||||
|
||||
export const devTracker = new Tracker(
|
||||
(console && console.log && console.log.bind(console)) || (() => {}) // eslint-disable-line no-console
|
||||
(console?.log?.bind(console)) ?? (() => {}) // eslint-disable-line no-console
|
||||
)
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
import type {
|
||||
ResetSimulationAction,
|
||||
LoadPreviousSimulationAction,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
import type {
|
||||
InitializeCompanyCreationChecklistAction,
|
||||
CheckCompanyCreationItemAction
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
|
||||
import { dropWhile, last } from 'ramda'
|
||||
import { nextQuestionUrlSelector } from 'Selectors/companyStatusSelectors'
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
import type {
|
||||
InitializeHiringChecklistAction,
|
||||
CheckHiringItemAction
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
/* @flow */
|
||||
|
||||
import React from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { connect } from 'react-redux'
|
||||
|
@ -24,9 +22,9 @@ let Banner = ({ hidden = false, children, icon }: PropTypes) =>
|
|||
</Animate.fadeIn>
|
||||
) : null
|
||||
|
||||
export default (connect(
|
||||
export default connect(
|
||||
(state: State, { hidden }: PropTypes) => ({
|
||||
hidden: hidden || firstStepCompletedSelector(state)
|
||||
}),
|
||||
{}
|
||||
)(Banner): React$ComponentType<PropTypes>)
|
||||
)(Banner)
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { React, T } from 'Components'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { T } from 'Components'
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Skeleton from 'react-loading-skeleton'
|
||||
// $FlowFixMe
|
||||
import 'react-select/dist/react-select.css'
|
||||
import { fetchCompanyDetails } from '../api/sirene'
|
||||
|
||||
|
@ -33,8 +32,8 @@ export default function CompanyDetails({ siren, denomination }) {
|
|||
<small>({siren})</small>
|
||||
</>
|
||||
) : (
|
||||
<Skeleton width={400} />
|
||||
)}
|
||||
<Skeleton width={400} />
|
||||
)}
|
||||
</h3>
|
||||
|
||||
<p className="ui__ notice">
|
||||
|
@ -43,8 +42,8 @@ export default function CompanyDetails({ siren, denomination }) {
|
|||
{company ? (
|
||||
DateFormatter.format(new Date(company.date_creation))
|
||||
) : (
|
||||
<Skeleton width={80} />
|
||||
)}
|
||||
<Skeleton width={80} />
|
||||
)}
|
||||
</strong>
|
||||
, <T>domiciliée à</T>{' '}
|
||||
{company ? (
|
||||
|
@ -53,10 +52,9 @@ export default function CompanyDetails({ siren, denomination }) {
|
|||
{company.etablissement_siege.code_postal})
|
||||
</>
|
||||
) : (
|
||||
<Skeleton width={100} />
|
||||
)}
|
||||
<Skeleton width={100} />
|
||||
)}
|
||||
</p>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
|
||||
import { ScrollToElement } from 'Components/utils/Scroll'
|
||||
import withTracker from 'Components/utils/withTracker'
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
/* @flow */
|
||||
|
||||
import withTracker from 'Components/utils/withTracker'
|
||||
import React, { Component } from 'react'
|
||||
import { Trans } from 'react-i18next'
|
||||
|
@ -166,7 +164,7 @@ class PageFeedback extends Component<Props, State> {
|
|||
const PageFeedbackWithRouter = ({ location, ...props }) => (
|
||||
<PageFeedback {...props} location={location} key={location.pathname} />
|
||||
)
|
||||
export default (compose(
|
||||
export default compose(
|
||||
withRouter,
|
||||
withTracker
|
||||
)(PageFeedbackWithRouter): React$ComponentType<OwnProps>)
|
||||
)(PageFeedbackWithRouter)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { setEntreprise } from 'Actions/existingCompanyActions'
|
||||
import { React, T } from 'Components'
|
||||
import { T } from 'Components'
|
||||
import CompanyDetails from 'Components/CompanyDetails'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { useDispatch } from 'react-redux'
|
||||
// $FlowFixMe
|
||||
import 'react-select/dist/react-select.css'
|
||||
import { searchDenominationOrSiren } from '../api/sirene'
|
||||
import { debounce } from '../utils'
|
||||
|
@ -13,7 +12,7 @@ export default function Search() {
|
|||
const [isLoading, setLoadingState] = useState(false)
|
||||
|
||||
const handleSearch = useCallback(
|
||||
function (value) {
|
||||
function(value) {
|
||||
searchDenominationOrSiren(value).then(results => {
|
||||
setLoadingState(false)
|
||||
setSearchResults(results)
|
||||
|
@ -67,7 +66,11 @@ export default function Search() {
|
|||
debouncedHandleSearch(e.target.value)
|
||||
}}
|
||||
/>
|
||||
{!isLoading && searchResults === null && <p><T>Aucun résultat</T></p>}
|
||||
{!isLoading && searchResults === null && (
|
||||
<p>
|
||||
<T>Aucun résultat</T>
|
||||
</p>
|
||||
)}
|
||||
|
||||
{searchResults &&
|
||||
searchResults.map(({ siren, denomination }) => (
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
import type { FicheDePaie } from 'Types/ResultViewTypes'
|
||||
import withColours from 'Components/utils/withColours'
|
||||
import Value from 'Components/Value'
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { React, T } from 'Components'
|
||||
import { T } from 'Components'
|
||||
import Value from 'Components/Value'
|
||||
import React from 'react'
|
||||
import RuleLink from './RuleLink'
|
||||
|
||||
export let SalaireBrutSection = ({ getRule }) => {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
import {
|
||||
deletePreviousSimulation,
|
||||
loadPreviousSimulation
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
import { goToQuestion } from 'Actions/actions'
|
||||
import { T } from 'Components'
|
||||
import { compose, contains, filter, reject, toPairs } from 'ramda'
|
||||
|
@ -59,7 +58,7 @@ const QuickLinks = ({
|
|||
)
|
||||
}
|
||||
|
||||
export default (connect(
|
||||
export default connect(
|
||||
(state, props) => ({
|
||||
key: props.language,
|
||||
currentQuestion: currentQuestionSelector(state),
|
||||
|
@ -70,4 +69,4 @@ export default (connect(
|
|||
{
|
||||
goToQuestion
|
||||
}
|
||||
)(QuickLinks): React$ComponentType<OwnProps>)
|
||||
)(QuickLinks)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { React, T } from 'Components'
|
||||
import { T } from 'Components'
|
||||
import image from 'Images/map-directions.png'
|
||||
import React from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/* @flow */
|
||||
import withColours from 'Components/utils/withColours'
|
||||
import withSitePaths from 'Components/utils/withSitePaths'
|
||||
import { encodeRuleName, nameLeaf } from 'Engine/rules'
|
||||
import { compose } from 'ramda'
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import './RuleLink.css'
|
||||
import type { Règle } from 'Types/RegleTypes'
|
||||
import type { ThemeColours } from 'Components/utils/withColours'
|
||||
|
||||
type Props = Règle & {
|
||||
sitePaths: Object,
|
||||
style: CSSStyleDeclaration,
|
||||
colours: ThemeColours
|
||||
}
|
||||
const RuleLink = ({
|
||||
dottedName,
|
||||
title,
|
||||
colours: { colour },
|
||||
style,
|
||||
sitePaths,
|
||||
children
|
||||
}: Props) => {
|
||||
const newPath =
|
||||
sitePaths.documentation.index + '/' + encodeRuleName(dottedName)
|
||||
|
||||
return (
|
||||
<Link
|
||||
to={newPath}
|
||||
className="rule-link"
|
||||
title={title}
|
||||
style={{ color: colour, ...style }}>
|
||||
{children || title || nameLeaf(dottedName)}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withSitePaths,
|
||||
withColours
|
||||
)(RuleLink)
|
|
@ -0,0 +1,34 @@
|
|||
import { ThemeColoursContext } from 'Components/utils/withColours'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import { encodeRuleName, nameLeaf } from 'Engine/rules'
|
||||
import React, { useContext } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Règle } from 'Types/RegleTypes'
|
||||
import './RuleLink.css'
|
||||
|
||||
type RuleLinkProps = Règle & {
|
||||
style: React.CSSProperties
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export default function RuleLink({
|
||||
dottedName,
|
||||
title,
|
||||
style,
|
||||
children
|
||||
}: RuleLinkProps) {
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const { colour } = useContext(ThemeColoursContext)
|
||||
const newPath =
|
||||
sitePaths.documentation.index + '/' + encodeRuleName(dottedName)
|
||||
|
||||
return (
|
||||
<Link
|
||||
to={newPath}
|
||||
className="rule-link"
|
||||
title={title}
|
||||
style={{ color: colour, ...style }}>
|
||||
{children || title || nameLeaf(dottedName)}
|
||||
</Link>
|
||||
)
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
import { setSituationBranch } from 'Actions/actions'
|
||||
import {
|
||||
defineDirectorStatus,
|
||||
|
@ -639,7 +638,7 @@ const RuleValueLink = compose(
|
|||
}
|
||||
)
|
||||
|
||||
export default (compose(
|
||||
export default compose(
|
||||
withSimulationConfig(ComparaisonConfig),
|
||||
connect(
|
||||
state => ({
|
||||
|
@ -657,4 +656,4 @@ export default (compose(
|
|||
setSituationBranch
|
||||
}
|
||||
)
|
||||
)(SchemeComparaison): React$Component<OwnProps>)
|
||||
)(SchemeComparaison)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import withSitePaths from 'Components/utils/withSitePaths'
|
||||
import { encodeRuleName } from 'Engine/rules.js'
|
||||
import { encodeRuleName } from 'Engine/rules'
|
||||
import Fuse from 'fuse.js'
|
||||
import { compose, pick, sortBy } from 'ramda'
|
||||
import React, { useMemo, useRef, useState } from 'react'
|
||||
|
|
|
@ -5,14 +5,14 @@ import PeriodSwitch from 'Components/PeriodSwitch'
|
|||
import RuleLink from 'Components/RuleLink'
|
||||
import { ThemeColoursContext } from 'Components/utils/withColours'
|
||||
import withSitePaths from 'Components/utils/withSitePaths'
|
||||
import { formatCurrency } from 'Engine/format'
|
||||
import { encodeRuleName } from 'Engine/rules'
|
||||
import { isEmpty, isNil } from 'ramda'
|
||||
import React, { useEffect, useState, useContext } from 'react'
|
||||
import React, { useContext, useEffect, useState } from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { formatCurrency } from 'Engine/format'
|
||||
import {
|
||||
analysisWithDefaultsSelector,
|
||||
useSituation,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { React, T } from 'Components'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { T } from 'Components'
|
||||
import { formatValue } from 'Engine/format'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
// let booleanTranslations = { true: '✅', false: '❌' }
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import ReactSelect from 'react-select'
|
|||
import 'react-select/dist/react-select.css'
|
||||
import { FormDecorator } from '../FormDecorator'
|
||||
import './Select.css'
|
||||
import SelectOption from './SelectOption.js'
|
||||
import SelectOption from './SelectOption'
|
||||
|
||||
function ReactSelectWrapper({
|
||||
value,
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import React, { Component } from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import React from 'react'
|
||||
import { Trans } from 'react-i18next'
|
||||
|
||||
let T = ({ k, ...props }) => <Trans i18nKey={k} {...props} />
|
||||
|
||||
export { React, Component, T, emoji }
|
||||
|
||||
export { T }
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import classNames from 'classnames'
|
||||
import { React, T } from 'Components'
|
||||
import { T } from 'Components'
|
||||
import { makeJsx } from 'Engine/evaluation'
|
||||
import { any, identity, path } from 'ramda'
|
||||
import React from 'react'
|
||||
import { Trans } from 'react-i18next'
|
||||
import './Algorithm.css'
|
||||
// The showValues prop is passed as a context. It used to be delt in CSS (not(.showValues) display: none), both coexist right now
|
|
@ -1,7 +1,7 @@
|
|||
import { toPairs } from 'ramda'
|
||||
import React from 'react'
|
||||
import { capitalise0 } from '../../utils'
|
||||
import references from 'Règles/ressources/références/références.yaml'
|
||||
import { capitalise0 } from '../../utils'
|
||||
import './References.css'
|
||||
|
||||
const findRefKey = link =>
|
||||
|
@ -32,7 +32,11 @@ function Ref({ name, link }) {
|
|||
)
|
||||
}
|
||||
|
||||
export default function References({ refs }) {
|
||||
interface ReferencesProps {
|
||||
refs: { [key: string]: string }
|
||||
}
|
||||
|
||||
export default function References({ refs }: ReferencesProps) {
|
||||
let references = toPairs(refs)
|
||||
return (
|
||||
<ul className="references">
|
|
@ -1,13 +1,13 @@
|
|||
/* @flow */
|
||||
import { formatCurrency } from 'Engine/format'
|
||||
import React, { useRef } from 'react'
|
||||
import ReactCSSTransitionGroup from 'react-addons-css-transition-group'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { formatCurrency } from 'Engine/format'
|
||||
import { usePeriod } from 'Selectors/analyseSelectors'
|
||||
import './AnimatedTargetValue.css'
|
||||
|
||||
type Props = {
|
||||
value: ?number
|
||||
interface AnimatedTargetValueProps {
|
||||
value?: number
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
function formatDifference(difference, language) {
|
||||
|
@ -15,8 +15,11 @@ function formatDifference(difference, language) {
|
|||
return prefix + formatCurrency(difference, language)
|
||||
}
|
||||
|
||||
export default function AnimatedTargetValue({ value, children }: Props) {
|
||||
const previousValue = useRef()
|
||||
export default function AnimatedTargetValue({
|
||||
value,
|
||||
children
|
||||
}: AnimatedTargetValueProps) {
|
||||
const previousValue = useRef<number>()
|
||||
const { language } = useTranslation().i18n
|
||||
|
||||
// We don't want to show the animated if the difference comes from a change in the period
|
||||
|
@ -54,7 +57,7 @@ export default function AnimatedTargetValue({ value, children }: Props) {
|
|||
}
|
||||
|
||||
const Evaporate = React.memo(
|
||||
({ children, style }: { children: string, style: Object }) => (
|
||||
({ children, style }: { children: string; style: Object }) => (
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="evaporate"
|
||||
transitionEnterTimeout={2500}
|
|
@ -1,12 +0,0 @@
|
|||
/* @flow */
|
||||
import { React } from 'Components'
|
||||
import './button.css'
|
||||
import type { ElementConfig } from 'react'
|
||||
|
||||
export const LinkButton = (props: ElementConfig<'button'>) => (
|
||||
<button {...props} className={'ui__ link-button ' + props.className} />
|
||||
)
|
||||
|
||||
export const Button = (props: ElementConfig<'button'>) => (
|
||||
<button {...props} className={'ui__ button ' + props.className} />
|
||||
)
|
|
@ -0,0 +1,10 @@
|
|||
import React from 'react'
|
||||
import './button.css'
|
||||
|
||||
export const LinkButton = (props: React.HTMLAttributes<HTMLButtonElement>) => (
|
||||
<button {...props} className={'ui__ link-button ' + props.className} />
|
||||
)
|
||||
|
||||
export const Button = (props: React.HTMLAttributes<HTMLButtonElement>) => (
|
||||
<button {...props} className={'ui__ button ' + props.className} />
|
||||
)
|
|
@ -10,7 +10,7 @@ export default function Checkbox(props) {
|
|||
style={{ display: 'none' }}
|
||||
{...props}
|
||||
/>
|
||||
<label htmlFor={props.id} className="ui__ checkbox" tabIndex="0">
|
||||
<label htmlFor={props.id} className="ui__ checkbox" tabIndex={0}>
|
||||
<svg width="1em" height="1em" viewBox="0 0 18 18">
|
||||
<path d="M1,9 L1,3.5 C1,2 2,1 3.5,1 L14.5,1 C16,1 17,2 17,3.5 L17,14.5 C17,16 16,17 14.5,17 L3.5,17 C2,17 1,16 1,14.5 L1,9 Z" />
|
||||
<polyline points="1 9 7 14 15 4" />
|
|
@ -1,36 +1,31 @@
|
|||
/* @flow */
|
||||
import classnames from 'classnames'
|
||||
import Animate from 'Ui/animate'
|
||||
import { Markdown } from 'Components/utils/markdown'
|
||||
import { ScrollToElement } from 'Components/utils/Scroll'
|
||||
import withTracker from 'Components/utils/withTracker'
|
||||
import React, { Component, useState } from 'react'
|
||||
import Animate from 'Ui/animate'
|
||||
import { TrackerContext } from 'Components/utils/withTracker'
|
||||
import React, { Component, useContext, useState } from 'react'
|
||||
import Checkbox from '../Checkbox'
|
||||
import './index.css'
|
||||
|
||||
import type Tracker from '../../../Tracker'
|
||||
import type { ChildrenArray, Node, Element } from 'react'
|
||||
|
||||
type CheckItemProps = {
|
||||
title: Node,
|
||||
name: string,
|
||||
explanations: Node,
|
||||
onChange?: boolean => void,
|
||||
tracker: Tracker,
|
||||
title: React.ReactNode
|
||||
name: string
|
||||
explanations?: React.ReactNode
|
||||
onChange?: (checked: boolean) => void
|
||||
defaultChecked?: boolean
|
||||
}
|
||||
|
||||
function CheckItemComponent({
|
||||
export function CheckItem({
|
||||
title,
|
||||
name,
|
||||
explanations,
|
||||
onChange,
|
||||
tracker,
|
||||
defaultChecked
|
||||
}: CheckItemProps) {
|
||||
const tracker = useContext(TrackerContext)
|
||||
const [displayExplanations, setDisplayExplanations] = useState(false)
|
||||
|
||||
const handleChecked = (e: SyntheticInputEvent<HTMLInputElement>) => {
|
||||
const handleChecked = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.checked) {
|
||||
setDisplayExplanations(false)
|
||||
}
|
||||
|
@ -82,16 +77,15 @@ function CheckItemComponent({
|
|||
</ScrollToElement>
|
||||
)
|
||||
}
|
||||
export const CheckItem = withTracker(CheckItemComponent)
|
||||
|
||||
type ChecklistProps = {
|
||||
children: ChildrenArray<null | false | Element<typeof CheckItem>>,
|
||||
onItemCheck: (string, boolean) => void,
|
||||
onInitialization: (Array<string>) => void,
|
||||
defaultChecked: { [string]: boolean }
|
||||
children: React.ReactNode
|
||||
onItemCheck: (string, boolean) => void
|
||||
onInitialization: (arg: Array<string>) => void
|
||||
defaultChecked: { [key: string]: boolean }
|
||||
}
|
||||
export class Checklist extends Component<ChecklistProps> {
|
||||
checklist: Array<Element<typeof CheckItem>>
|
||||
checklist: any
|
||||
static defaultProps = {
|
||||
defaultChecked: {},
|
||||
onItemCheck: () => {},
|
||||
|
@ -101,28 +95,22 @@ export class Checklist extends Component<ChecklistProps> {
|
|||
super(props)
|
||||
this.checklist = React.Children.toArray(props.children)
|
||||
.filter(Boolean)
|
||||
.map(
|
||||
// $FlowFixMe
|
||||
(child: Element<typeof CheckItem>) =>
|
||||
// $FlowFixMe
|
||||
React.cloneElement(child, {
|
||||
// $FlowFixMe
|
||||
onChange: checked => props.onItemCheck(child.props.name, checked),
|
||||
// $FlowFixMe
|
||||
defaultChecked:
|
||||
child.props.defaultChecked ||
|
||||
props.defaultChecked[child.props.name]
|
||||
})
|
||||
.map((child: any) =>
|
||||
React.cloneElement(child, {
|
||||
onChange: checked => props.onItemCheck(child.props.name, checked),
|
||||
defaultChecked:
|
||||
child.props.defaultChecked || props.defaultChecked[child.props.name]
|
||||
})
|
||||
)
|
||||
props.onInitialization &&
|
||||
// $FlowFixMe
|
||||
props.onInitialization(this.checklist.map(child => child.props.name))
|
||||
props.onInitialization(
|
||||
this.checklist.map((child: any) => child.props.name)
|
||||
)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<ul className="ui__ no-bullet checklist">
|
||||
{this.checklist.map(checkItem => (
|
||||
// $FlowFixMe
|
||||
{this.checklist.map((checkItem: any) => (
|
||||
<li key={checkItem.props.name}>{checkItem}</li>
|
||||
))}
|
||||
</ul>
|
|
@ -4,7 +4,7 @@ import './InfoBulle.css'
|
|||
export default function InfoBulle({ children }) {
|
||||
return (
|
||||
<span style={{ position: 'relative', verticalAlign: 'bottom' }}>
|
||||
<span className="info-bulle__interrogation-mark" tabIndex="0">
|
||||
<span className="info-bulle__interrogation-mark" tabIndex={0}>
|
||||
?
|
||||
</span>
|
||||
<span className="info-bulle__text">{children}</span>
|
|
@ -1,7 +1,5 @@
|
|||
/* @flow */
|
||||
import withColours from 'Components/utils/withColours'
|
||||
import withColours, { ThemeColours } from 'Components/utils/withColours'
|
||||
import React from 'react'
|
||||
import type { ThemeColours } from 'Components/utils/withColours'
|
||||
|
||||
type OwnProps = {
|
||||
media: 'email' | 'facebook' | 'linkedin' | 'github' | 'twitter'
|
|
@ -1,161 +0,0 @@
|
|||
/* @flow */
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { animated, config as configPresets, Spring, Trail, Transition } from 'react-spring/renderprops'
|
||||
import type { SpringConfig } from 'react-spring/renderprops'
|
||||
import type { Node } from 'react'
|
||||
|
||||
type Props = {
|
||||
children: Node,
|
||||
config?: SpringConfig,
|
||||
style?: Object,
|
||||
className?: string,
|
||||
delay?: number
|
||||
}
|
||||
|
||||
// Todo : better animate with fromRight on desktop
|
||||
export const fromBottom = ({
|
||||
children,
|
||||
config = configPresets.stiff,
|
||||
style: inheritedStyle = {},
|
||||
delay = 0
|
||||
}: Props) => (
|
||||
<Trail
|
||||
keys={React.Children.map(children, (_, i) => i)}
|
||||
native={true}
|
||||
delay={delay}
|
||||
config={config}
|
||||
from={{ opacity: 0, y: 10 }}
|
||||
leave={{ opacity: 0, y: -10 }}
|
||||
to={{ opacity: 1, y: 0 }}
|
||||
items={children}>
|
||||
{/* eslint-disable-next-line react/display-name */}
|
||||
{item => ({ y, ...style }) => (
|
||||
<animated.div
|
||||
style={{
|
||||
transform: y.interpolate(y =>
|
||||
y !== 0 ? `translate3d(0, ${y}px,0)` : 'none'
|
||||
),
|
||||
...style,
|
||||
...inheritedStyle
|
||||
}}>
|
||||
{item}
|
||||
</animated.div>
|
||||
)}
|
||||
</Trail>
|
||||
)
|
||||
export const fromTop = ({
|
||||
children,
|
||||
config = configPresets.stiff,
|
||||
style: inheritedStyle = {},
|
||||
delay = 0
|
||||
}: Props) => (
|
||||
<Trail
|
||||
keys={React.Children.map(children, (_, i) => i)}
|
||||
native={true}
|
||||
delay={delay}
|
||||
config={config}
|
||||
leave={{ opacity: 0, y: 20 }}
|
||||
from={{ opacity: 0, y: -20 }}
|
||||
to={{ opacity: 1, y: 0 }}
|
||||
items={children}>
|
||||
{/* eslint-disable-next-line react/display-name */}
|
||||
{item => ({ y, ...style }) => (
|
||||
<animated.div
|
||||
style={{
|
||||
transform: y.interpolate(y =>
|
||||
y ? `translate3d(0, ${y}px,0)` : 'none'
|
||||
),
|
||||
...style,
|
||||
...inheritedStyle
|
||||
}}>
|
||||
{item}
|
||||
</animated.div>
|
||||
)}
|
||||
</Trail>
|
||||
)
|
||||
|
||||
export const leftToRight = ({
|
||||
children,
|
||||
config = configPresets.stiff,
|
||||
delay = 0
|
||||
}: Props) => (
|
||||
<Transition
|
||||
from={{
|
||||
opacity: 0,
|
||||
transform: 'translateX(100%)'
|
||||
}}
|
||||
native
|
||||
keys={location.pathname}
|
||||
enter={{
|
||||
opacity: 1,
|
||||
transform: 'translateX(0%)'
|
||||
}}
|
||||
config={config}
|
||||
delay={delay}
|
||||
leave={{
|
||||
opacity: 0,
|
||||
position: 'absolute',
|
||||
transform: 'translateX(-100%)'
|
||||
}}>
|
||||
{style => <animated.div style={style}>{children}</animated.div>}
|
||||
</Transition>
|
||||
)
|
||||
|
||||
export const fadeIn = ({
|
||||
children,
|
||||
config = configPresets.default,
|
||||
delay = 0
|
||||
}: Props) => (
|
||||
<Spring
|
||||
native={true}
|
||||
delay={delay}
|
||||
config={config}
|
||||
from={{ opacity: 0 }}
|
||||
to={{
|
||||
opacity: 1
|
||||
}}>
|
||||
{style => <animated.div style={style}>{children}</animated.div>}
|
||||
</Spring>
|
||||
)
|
||||
|
||||
export function appear({
|
||||
children,
|
||||
className,
|
||||
unless = false,
|
||||
config = configPresets.default,
|
||||
delay = 0,
|
||||
style
|
||||
}) {
|
||||
// TODO: We should rename this function Appear
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const [show, setShow] = useState(unless)
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
useEffect(() => {
|
||||
window.setTimeout(() => setShow(true), 0)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Spring
|
||||
delay={delay}
|
||||
native
|
||||
config={config}
|
||||
to={{
|
||||
opacity: show ? 1 : 0,
|
||||
height: show ? 'auto' : '0px'
|
||||
}}>
|
||||
{animStyle => (
|
||||
<animated.div style={{ ...style, ...animStyle }} className={className}>
|
||||
{children}
|
||||
</animated.div>
|
||||
)}
|
||||
</Spring>
|
||||
)
|
||||
}
|
||||
|
||||
export default {
|
||||
appear,
|
||||
fromBottom,
|
||||
leftToRight,
|
||||
fromTop,
|
||||
fadeIn
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import {
|
||||
animated,
|
||||
config as configPresets,
|
||||
interpolate,
|
||||
Spring,
|
||||
SpringConfig,
|
||||
Trail,
|
||||
Transition
|
||||
} from 'react-spring/renderprops'
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode
|
||||
config?: SpringConfig
|
||||
style?: Object
|
||||
className?: string
|
||||
delay?: number
|
||||
}
|
||||
|
||||
// Todo : better animate with fromRight on desktop
|
||||
export const fromBottom = ({
|
||||
children,
|
||||
config = configPresets.stiff,
|
||||
style: inheritedStyle = {},
|
||||
delay = 0
|
||||
}: Props) => (
|
||||
<Trail
|
||||
keys={React.Children.map(children, (_, i) => i)}
|
||||
native={true}
|
||||
delay={delay}
|
||||
config={config}
|
||||
from={{ opacity: 0, y: 10 }}
|
||||
to={{ opacity: 1, y: 0 }}
|
||||
items={children}>
|
||||
{item => ({ y, ...style }) => (
|
||||
<animated.div
|
||||
style={{
|
||||
transform: interpolate([y], y =>
|
||||
y !== 0 ? `translate3d(0, ${y}px,0)` : 'none'
|
||||
),
|
||||
...style,
|
||||
...inheritedStyle
|
||||
}}>
|
||||
{item}
|
||||
</animated.div>
|
||||
)}
|
||||
</Trail>
|
||||
)
|
||||
export const fromTop = ({
|
||||
children,
|
||||
config = configPresets.stiff,
|
||||
style: inheritedStyle = {},
|
||||
delay = 0
|
||||
}: Props) => (
|
||||
<Trail
|
||||
keys={React.Children.map(children, (_, i) => i)}
|
||||
native={true}
|
||||
delay={delay}
|
||||
config={config}
|
||||
from={{ opacity: 0, y: -20 }}
|
||||
to={{ opacity: 1, y: 0 }}
|
||||
items={children}>
|
||||
{item => ({ y, ...style }) => (
|
||||
<animated.div
|
||||
style={{
|
||||
transform: interpolate([y], y =>
|
||||
y !== 0 ? `translate3d(0, ${y}px,0)` : 'none'
|
||||
),
|
||||
...style,
|
||||
...inheritedStyle
|
||||
}}>
|
||||
{item}
|
||||
</animated.div>
|
||||
)}
|
||||
</Trail>
|
||||
)
|
||||
|
||||
export const leftToRight = ({
|
||||
children,
|
||||
config = configPresets.stiff,
|
||||
delay = 0
|
||||
}: Props) => (
|
||||
<Transition
|
||||
from={{
|
||||
opacity: 0,
|
||||
transform: 'translateX(100%)'
|
||||
}}
|
||||
native
|
||||
keys={location.pathname}
|
||||
enter={{
|
||||
opacity: 1,
|
||||
transform: 'translateX(0%)'
|
||||
}}
|
||||
config={config}
|
||||
delay={delay}
|
||||
leave={{
|
||||
opacity: 0,
|
||||
position: 'absolute',
|
||||
transform: 'translateX(-100%)'
|
||||
}}
|
||||
items={children}>
|
||||
{item => style => <animated.div style={style}>{item}</animated.div>}
|
||||
</Transition>
|
||||
)
|
||||
|
||||
export const fadeIn = ({
|
||||
children,
|
||||
config = configPresets.default,
|
||||
delay = 0
|
||||
}: Props) => (
|
||||
<Spring
|
||||
native={true}
|
||||
delay={delay}
|
||||
config={config}
|
||||
from={{ opacity: 0 }}
|
||||
to={{
|
||||
opacity: 1
|
||||
}}>
|
||||
{style => <animated.div style={style}>{children}</animated.div>}
|
||||
</Spring>
|
||||
)
|
||||
|
||||
export function appear({
|
||||
children,
|
||||
className,
|
||||
unless = false,
|
||||
config = configPresets.default,
|
||||
delay = 0,
|
||||
style
|
||||
}: Props & { unless?: boolean }) {
|
||||
// TODO: We should rename this function Appear
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const [show, setShow] = useState(unless)
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
useEffect(() => {
|
||||
window.setTimeout(() => setShow(true), 0)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Spring
|
||||
delay={delay}
|
||||
native
|
||||
config={config}
|
||||
to={{
|
||||
opacity: show ? 1 : 0,
|
||||
height: show ? 'auto' : '0px'
|
||||
}}>
|
||||
{animStyle => (
|
||||
<animated.div style={{ ...style, ...animStyle }} className={className}>
|
||||
{children}
|
||||
</animated.div>
|
||||
)}
|
||||
</Spring>
|
||||
)
|
||||
}
|
||||
|
||||
export default {
|
||||
appear,
|
||||
fromBottom,
|
||||
leftToRight,
|
||||
fromTop,
|
||||
fadeIn
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import ReactMarkdown, { ReactMarkdownProps } from 'react-markdown'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
function LinkRenderer({ href, children }) {
|
||||
|
@ -14,12 +14,19 @@ function LinkRenderer({ href, children }) {
|
|||
}
|
||||
}
|
||||
|
||||
interface MarkdownProps {
|
||||
source: string
|
||||
className?: string
|
||||
renderers?: ReactMarkdownProps['renderers']
|
||||
[other_props: string]: any
|
||||
}
|
||||
|
||||
export const Markdown = ({
|
||||
source,
|
||||
className = '',
|
||||
renderers = {},
|
||||
otherProps
|
||||
}) => (
|
||||
}: MarkdownProps) => (
|
||||
<ReactMarkdown
|
||||
source={source}
|
||||
className={`markdown ${className}`}
|
|
@ -13,12 +13,12 @@ export const getInitialState = key => {
|
|||
try {
|
||||
return JSON.parse(safeLocalStorage.getItem(key))
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
return null;
|
||||
console.warn(e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export const usePersistingState = (key, defaultState) => {
|
||||
export const usePersistingState = (key: string, defaultState?: any) => {
|
||||
const initialState = getInitialState(key)
|
||||
return persistState(key)(
|
||||
useState(initialState != null ? initialState : defaultState)
|
|
@ -1,22 +1,6 @@
|
|||
/* @flow */
|
||||
|
||||
import convert from 'color-convert'
|
||||
import SetCssColour from 'Components/utils/SetCssColour'
|
||||
import React, { Component, createContext } from 'react'
|
||||
export type ThemeColours = {
|
||||
colour: string,
|
||||
textColour: string,
|
||||
inverseTextColour: string,
|
||||
lighterTextColour: string,
|
||||
lighterInverseTextColour: string,
|
||||
textColourOnWhite: string,
|
||||
grayColour: string,
|
||||
darkColour: string,
|
||||
lightColour: string,
|
||||
lighterColour: string,
|
||||
lightestColour: string,
|
||||
darkestColour: string
|
||||
}
|
||||
import React, { createContext } from 'react'
|
||||
|
||||
/*
|
||||
Hex to RGB conversion:
|
||||
|
@ -31,7 +15,7 @@ let cutHex = h => (h.charAt(0) == '#' ? h.substring(1, 7) : h),
|
|||
Given a background color, should you write on it in black or white ?
|
||||
Taken from http://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color#comment61936401_3943023
|
||||
*/
|
||||
function findContrastedTextColour(color, simple) {
|
||||
function findContrastedTextColour(color: string, simple: boolean) {
|
||||
let r = hexToR(color),
|
||||
g = hexToG(color),
|
||||
b = hexToB(color)
|
||||
|
@ -49,18 +33,21 @@ function findContrastedTextColour(color, simple) {
|
|||
return L > 0.179 ? '#000000' : '#ffffff'
|
||||
}
|
||||
|
||||
const lightenColour = (hex, x) => {
|
||||
const lightenColour = (hex: string, x: number) => {
|
||||
const [h, s, l] = convert.hex.hsl(hex.split('#')[1])
|
||||
return '#' + convert.hsl.hex([h, s, Math.max(2, Math.min(l + x, 98))])
|
||||
}
|
||||
|
||||
const generateDarkenVariations = (numberOfVariation, [h, s, l]) => {
|
||||
const generateDarkenVariations = (
|
||||
numberOfVariation: number,
|
||||
[h, s, l]: [number, number, number]
|
||||
) => {
|
||||
return [...Array(numberOfVariation).keys()].map(
|
||||
i => '#' + convert.hsl.hex([h, s, l * 0.8 ** i])
|
||||
)
|
||||
}
|
||||
|
||||
const deriveAnalogousPalettes = hex => {
|
||||
const deriveAnalogousPalettes = (hex: string) => {
|
||||
const [h, s, l] = convert.hex.hsl(hex.split('#')[1])
|
||||
return [
|
||||
generateDarkenVariations(4, [(h - 45) % 360, 0.75 * s, l]),
|
||||
|
@ -68,7 +55,7 @@ const deriveAnalogousPalettes = hex => {
|
|||
]
|
||||
}
|
||||
|
||||
const generateTheme = (themeColour?: ?string): ThemeColours => {
|
||||
const generateTheme = (themeColour?: string) => {
|
||||
let // Use the default theme colour if the host page hasn't made a choice
|
||||
colour = themeColour || '#2975D1',
|
||||
lightColour = lightenColour(colour, 10),
|
||||
|
@ -105,13 +92,13 @@ const generateTheme = (themeColour?: ?string): ThemeColours => {
|
|||
}
|
||||
}
|
||||
|
||||
export const ThemeColoursContext: React$Context<ThemeColours> = createContext(
|
||||
generateTheme()
|
||||
)
|
||||
export type ThemeColours = ReturnType<typeof generateTheme>
|
||||
|
||||
export const ThemeColoursContext = createContext<ThemeColours>(generateTheme())
|
||||
|
||||
type ProviderProps = {
|
||||
colour: string,
|
||||
children: React$Node
|
||||
colour: string
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function ThemeColoursProvider({ colour, children }: ProviderProps) {
|
||||
|
@ -124,20 +111,26 @@ export function ThemeColoursProvider({ colour, children }: ProviderProps) {
|
|||
)
|
||||
}
|
||||
|
||||
export default function withThemeColours<Props: { colours: ThemeColours }> (
|
||||
WrappedComponent: React$ComponentType<Props>
|
||||
): React$ComponentType < $Diff < Props, { colours: ThemeColours } >> {
|
||||
class WithThemeColours extends Component <
|
||||
$Diff < Props, { colours: ThemeColours }>
|
||||
> {
|
||||
displayName = `withThemeColours(${WrappedComponent.displayName || ''})`
|
||||
render() {
|
||||
return (
|
||||
<ThemeColoursContext.Consumer>
|
||||
{colours => <WrappedComponent {...this.props} colours={colours} />}
|
||||
</ThemeColoursContext.Consumer>
|
||||
)
|
||||
}
|
||||
}
|
||||
return WithThemeColours
|
||||
interface WithColoursProps {
|
||||
colours: ThemeColours
|
||||
}
|
||||
|
||||
export default function withThemeColours<P extends object>(
|
||||
WrappedComponent: React.ComponentType<P>
|
||||
) {
|
||||
class WithThemeColours extends React.Component<
|
||||
Omit<P, keyof WithColoursProps>
|
||||
> {
|
||||
displayName = `withThemeColours(${WrappedComponent.displayName || ''})`
|
||||
render() {
|
||||
return (
|
||||
<ThemeColoursContext.Consumer>
|
||||
{colours => (
|
||||
<WrappedComponent {...(this.props as P)} colours={colours} />
|
||||
)}
|
||||
</ThemeColoursContext.Consumer>
|
||||
)
|
||||
}
|
||||
}
|
||||
return WithThemeColours
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/* @flow */
|
||||
import React, { Component, createContext } from 'react'
|
||||
import i18n from '../../i18n'
|
||||
|
||||
export const SitePathsContext: React$Context<SitePaths> = createContext({})
|
||||
|
||||
export const SitePathProvider = SitePathsContext.Provider
|
||||
export default function withSitePaths<Props: { sitePaths: SitePaths }> (
|
||||
WrappedComponent: React$ComponentType<Props>
|
||||
): React$ComponentType < $Diff < Props, { sitePaths: SitePaths } >> {
|
||||
class WithSitePaths extends Component <
|
||||
$Diff < Props, { sitePaths: SitePaths }>
|
||||
> {
|
||||
displayName = `withSitePaths(${WrappedComponent.displayName || ''})`
|
||||
constructor(props) {
|
||||
super(props)
|
||||
i18n.on('languageChanged', () => {
|
||||
this.forceUpdate()
|
||||
})
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<SitePathsContext.Consumer>
|
||||
{sitePaths => (
|
||||
<WrappedComponent {...this.props} sitePaths={sitePaths} />
|
||||
)}
|
||||
</SitePathsContext.Consumer>
|
||||
)
|
||||
}
|
||||
}
|
||||
return WithSitePaths
|
||||
}
|
||||
|
||||
export type SitePaths = Object
|
|
@ -0,0 +1,30 @@
|
|||
import React, { createContext } from 'react'
|
||||
import { SitePathsType } from 'sites/mon-entreprise.fr/sitePaths'
|
||||
|
||||
export const SitePathsContext = createContext<Partial<SitePathsType>>({})
|
||||
|
||||
export const SitePathProvider = SitePathsContext.Provider
|
||||
|
||||
export interface WithSitePathsProps {
|
||||
sitePaths: SitePathsType
|
||||
}
|
||||
|
||||
export default function withSitePaths<P extends object>(
|
||||
WrappedComponent: React.ComponentType<P>
|
||||
) {
|
||||
class WithSitePaths extends React.Component<P & WithSitePathsProps> {
|
||||
displayName = `withSitePaths(${WrappedComponent.displayName || ''})`
|
||||
render() {
|
||||
return (
|
||||
<SitePathsContext.Consumer>
|
||||
{sitePaths => (
|
||||
<WrappedComponent {...(this.props as P)} sitePaths={sitePaths} />
|
||||
)}
|
||||
</SitePathsContext.Consumer>
|
||||
)
|
||||
}
|
||||
}
|
||||
return WithSitePaths
|
||||
}
|
||||
|
||||
export type SitePaths = SitePathsType
|
|
@ -1,19 +0,0 @@
|
|||
/* @flow */
|
||||
|
||||
import React, { createContext } from 'react'
|
||||
import Tracker, { devTracker } from '../../Tracker'
|
||||
|
||||
export const TrackerContext: React$Context<Tracker> = createContext(devTracker)
|
||||
export const TrackerProvider = TrackerContext.Provider
|
||||
|
||||
export default function withTracker<Config: { tracker: Tracker }>(
|
||||
Component: React$ComponentType<Config>
|
||||
): React$ComponentType<$Diff<Config, { tracker: Tracker }>> {
|
||||
return function ConnectTracker(props: $Diff<Config, { tracker: Tracker }>) {
|
||||
return (
|
||||
<TrackerContext.Consumer>
|
||||
{(tracker: Tracker) => <Component {...props} tracker={tracker} />}
|
||||
</TrackerContext.Consumer>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
import React, { createContext } from 'react'
|
||||
import Tracker, { devTracker } from '../../Tracker'
|
||||
|
||||
export const TrackerContext = createContext(devTracker)
|
||||
export const TrackerProvider = TrackerContext.Provider
|
||||
|
||||
export interface WithTrackerProps {
|
||||
tracker: Tracker
|
||||
}
|
||||
|
||||
export default function withTracker(Component: React.ComponentType) {
|
||||
return function ConnectTracker(props) {
|
||||
return (
|
||||
<TrackerContext.Consumer>
|
||||
{(tracker: Tracker) => <Component {...props} tracker={tracker} />}
|
||||
</TrackerContext.Consumer>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
// This file exports the functions of the public computing library
|
||||
import { safeLoad } from 'js-yaml'
|
||||
import { collectDefaults, enrichRule, rulesFr } from './rules'
|
||||
import { analyseMany, parseAll } from './traverse.js'
|
||||
import { analyseMany, parseAll } from './traverse'
|
||||
|
||||
// The public evaluation function takes a nested object of input values
|
||||
let inputToStateSelector = rules => input => dottedName =>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
|
||||
import { omit } from 'ramda'
|
||||
import { combineReducers } from 'redux'
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
|
||||
import { findRuleByDottedName } from 'Engine/rules'
|
||||
import { compose, defaultTo, dissoc, identity, lensPath, omit, over, set, uniq, without } from 'ramda'
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
|
||||
import type { State } from 'Types/State'
|
||||
import type { Action } from 'Types/ActionsTypes'
|
||||
|
|
|
@ -36,5 +36,6 @@ app.use(
|
|||
app.use(require('webpack-hot-middleware')(compiler))
|
||||
|
||||
app.listen(8080, function() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Mon-entreprise listening on port 8080!\n')
|
||||
})
|
||||
|
|
|
@ -1,40 +1,37 @@
|
|||
import Route404 from 'Components/Route404'
|
||||
import withSitePaths from 'Components/utils/withSitePaths'
|
||||
import { rules as baseRulesEn, rulesFr as baseRulesFr } from 'Engine/rules'
|
||||
import 'iframe-resizer'
|
||||
import { compose } from 'ramda'
|
||||
import createRavenMiddleware from 'raven-for-redux'
|
||||
import Raven from 'raven-js'
|
||||
import React, { useEffect } from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Route, Switch } from 'react-router-dom'
|
||||
import 'Ui/index.css'
|
||||
import Provider from '../../Provider'
|
||||
import { persistEverything, retrievePersistedState } from '../../storage/persistEverything'
|
||||
import { persistSimulation, retrievePersistedSimulation } from '../../storage/persistSimulation'
|
||||
import Tracker, { devTracker } from '../../Tracker'
|
||||
import { getSessionStorage, inIframe } from '../../utils'
|
||||
import './App.css'
|
||||
import Footer from './layout/Footer/Footer'
|
||||
import Header from './layout/Header'
|
||||
import trackSimulatorActions from './middlewares/trackSimulatorActions'
|
||||
import Créer from './pages/Créer'
|
||||
import Couleur from './pages/Dev/Couleur'
|
||||
import IntegrationTest from './pages/Dev/IntegrationTest'
|
||||
import Personas from './pages/Dev/Personas'
|
||||
import Sitemap from './pages/Dev/Sitemap'
|
||||
import Documentation from './pages/Documentation'
|
||||
import Gérer from './pages/Gérer'
|
||||
import Iframes from './pages/Iframes'
|
||||
import Integration from './pages/integration/index'
|
||||
import Landing from './pages/Landing/Landing.js'
|
||||
import Simulateurs from './pages/Simulateurs'
|
||||
import ÉconomieCollaborative from './pages/ÉconomieCollaborative'
|
||||
import redirects from './redirects'
|
||||
import { constructLocalizedSitePath } from './sitePaths'
|
||||
|
||||
|
||||
import Route404 from 'Components/Route404';
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths';
|
||||
import { rules as baseRulesEn, rulesFr as baseRulesFr } from 'Engine/rules';
|
||||
import 'iframe-resizer';
|
||||
import createRavenMiddleware from 'raven-for-redux';
|
||||
import Raven from 'raven-js';
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import 'Ui/index.css';
|
||||
import Provider from '../../Provider';
|
||||
import { persistEverything, retrievePersistedState } from '../../storage/persistEverything';
|
||||
import { persistSimulation, retrievePersistedSimulation } from '../../storage/persistSimulation';
|
||||
import Tracker, { devTracker } from '../../Tracker';
|
||||
import { getSessionStorage, inIframe } from '../../utils';
|
||||
import './App.css';
|
||||
import Footer from './layout/Footer/Footer';
|
||||
import Header from './layout/Header';
|
||||
import trackSimulatorActions from './middlewares/trackSimulatorActions';
|
||||
import Créer from './pages/Créer';
|
||||
import Couleur from './pages/Dev/Couleur';
|
||||
import IntegrationTest from './pages/Dev/IntegrationTest';
|
||||
import Personas from './pages/Dev/Personas';
|
||||
import Sitemap from './pages/Dev/Sitemap';
|
||||
import Documentation from './pages/Documentation';
|
||||
import Gérer from './pages/Gérer';
|
||||
import Iframes from './pages/Iframes';
|
||||
import Integration from './pages/integration/index';
|
||||
import Landing from './pages/Landing/Landing';
|
||||
import Simulateurs from './pages/Simulateurs';
|
||||
import ÉconomieCollaborative from './pages/ÉconomieCollaborative';
|
||||
import redirects from './redirects';
|
||||
import { constructLocalizedSitePath } from './sitePaths';
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
Raven.config(
|
||||
|
@ -54,7 +51,7 @@ const middlewares = [
|
|||
|
||||
function InFranceRoute({ basename, language }) {
|
||||
useEffect(() => {
|
||||
getSessionStorage() ?.setItem('lang', language)
|
||||
getSessionStorage()?.setItem('lang', language)
|
||||
}, [language])
|
||||
const paths = constructLocalizedSitePath(language)
|
||||
const rules = language === 'en' ? baseRulesEn : baseRulesFr
|
||||
|
@ -92,8 +89,9 @@ let RouterSwitch = () => {
|
|||
)
|
||||
}
|
||||
|
||||
const App = compose(withSitePaths)(({ sitePaths }) => {
|
||||
const App = () => {
|
||||
const { t } = useTranslation()
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
return (
|
||||
<div className="app-container">
|
||||
<Helmet titleTemplate={`%s | ${t(['siteName', 'Mon-entreprise.fr'])}`} />
|
||||
|
@ -104,18 +102,12 @@ const App = compose(withSitePaths)(({ sitePaths }) => {
|
|||
<Switch>
|
||||
{redirects}
|
||||
<Route path={sitePaths.créer.index} component={Créer} />
|
||||
<Route
|
||||
path={sitePaths.gérer.index}
|
||||
component={Gérer}
|
||||
/>
|
||||
<Route path={sitePaths.gérer.index} component={Gérer} />
|
||||
<Route
|
||||
path={sitePaths.économieCollaborative.index}
|
||||
component={ÉconomieCollaborative}
|
||||
/>
|
||||
<Route
|
||||
path={sitePaths.simulateurs.index}
|
||||
component={Simulateurs}
|
||||
/>
|
||||
<Route path={sitePaths.simulateurs.index} component={Simulateurs} />
|
||||
<Route
|
||||
path={sitePaths.documentation.index}
|
||||
component={Documentation}
|
||||
|
@ -138,7 +130,7 @@ const App = compose(withSitePaths)(({ sitePaths }) => {
|
|||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
let ExportedApp = InFranceRoute
|
||||
|
|
@ -1,22 +1,18 @@
|
|||
/* @flow */
|
||||
|
||||
import PageFeedback from 'Components/Feedback/PageFeedback'
|
||||
import LegalNotice from 'Components/LegalNotice'
|
||||
import NewsletterRegister from 'Components/NewsletterRegister'
|
||||
import withSitePaths from 'Components/utils/withSitePaths'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import { lensPath, view } from 'ramda'
|
||||
import React from 'react'
|
||||
import React, { useContext } from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { Link } from 'react-router-dom'
|
||||
import SocialIcon from 'Ui/SocialIcon'
|
||||
import i18n from '../../../../i18n'
|
||||
import { hrefLangLink } from '../../sitePaths'
|
||||
import './Footer.css'
|
||||
import { Link } from 'react-router-dom'
|
||||
import Privacy from './Privacy'
|
||||
|
||||
type OwnProps = {}
|
||||
|
||||
const feedbackBlacklist = [
|
||||
['index'],
|
||||
['entreprise', 'statutJuridique', 'index'],
|
||||
|
@ -26,14 +22,15 @@ const feedbackBlacklist = [
|
|||
['simulateurs', 'salarié']
|
||||
].map(lensPath)
|
||||
|
||||
const Footer = ({ sitePaths }) => {
|
||||
const Footer = () => {
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const hrefLink =
|
||||
hrefLangLink[i18n.language][
|
||||
decodeURIComponent(
|
||||
(process.env.NODE_ENV === 'production'
|
||||
? window.location.protocol + '//' + window.location.host
|
||||
: '') + window.location.pathname
|
||||
).replace(/\/$/, '')
|
||||
decodeURIComponent(
|
||||
(process.env.NODE_ENV === 'production'
|
||||
? window.location.protocol + '//' + window.location.host
|
||||
: '') + window.location.pathname
|
||||
).replace(/\/$/, '')
|
||||
] || []
|
||||
return (
|
||||
<div className="footer-container">
|
||||
|
@ -108,8 +105,8 @@ const Footer = ({ sitePaths }) => {
|
|||
) : hrefLang === 'en' ? (
|
||||
<> Switch to English {emoji('🇬🇧')}</>
|
||||
) : (
|
||||
hrefLang
|
||||
)}
|
||||
hrefLang
|
||||
)}
|
||||
</a>
|
||||
))}
|
||||
</p>
|
||||
|
@ -118,4 +115,4 @@ const Footer = ({ sitePaths }) => {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
export default (withSitePaths(Footer): React$ComponentType<OwnProps>)
|
||||
export default Footer
|
|
@ -1,50 +0,0 @@
|
|||
import { SitePathsContext } from 'Components/utils/withSitePaths';
|
||||
import logoEnSvg from 'Images/logo-mycompany.svg';
|
||||
import logoSvg from 'Images/logo.svg';
|
||||
import marianneSvg from 'Images/marianne.svg';
|
||||
import urssafSvg from 'Images/urssaf.svg';
|
||||
import React, { useContext } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export default function Header() {
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const { i18n: { language } } = useTranslation();
|
||||
return (
|
||||
<div className="ui__ container" style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<Link style={{ height: '4rem' }} to={sitePaths.index}>
|
||||
<img
|
||||
alt="logo mon-entreprise.fr"
|
||||
style={{
|
||||
padding: '0.5rem 0',
|
||||
height: '100%'
|
||||
}}
|
||||
src={language === 'fr' ? logoSvg : logoEnSvg}
|
||||
/>
|
||||
</Link>
|
||||
<div style={{ flex: 1 }} />
|
||||
<a
|
||||
href="https://beta.gouv.fr"
|
||||
target="_blank"
|
||||
style={{
|
||||
height: '4rem',
|
||||
padding: '1rem'
|
||||
}}>
|
||||
<img alt="logo marianne" style={{ height: '100%' }} src={marianneSvg} />
|
||||
</a>
|
||||
<a
|
||||
href="https://www.urssaf.fr"
|
||||
target="_blank"
|
||||
style={{
|
||||
height: '4rem',
|
||||
padding: '1rem'
|
||||
}}
|
||||
className="landing-header__institutional-logo">
|
||||
<img alt="logo urssaf" style={{ height: '100%' }} src={urssafSvg} />
|
||||
</a>
|
||||
</div>)
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import logoEnSvg from 'Images/logo-mycompany.svg'
|
||||
import logoSvg from 'Images/logo.svg'
|
||||
import marianneSvg from 'Images/marianne.svg'
|
||||
import urssafSvg from 'Images/urssaf.svg'
|
||||
import React, { useContext } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
export default function Header() {
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const { language } = useTranslation().i18n
|
||||
return (
|
||||
<div
|
||||
className="ui__ container"
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}}>
|
||||
<Link style={{ height: '4rem' }} to={sitePaths.index}>
|
||||
<img
|
||||
alt="logo mon-entreprise.fr"
|
||||
style={{
|
||||
padding: '0.5rem 0',
|
||||
height: '100%'
|
||||
}}
|
||||
src={language === 'fr' ? logoSvg : logoEnSvg}
|
||||
/>
|
||||
</Link>
|
||||
<div style={{ flex: 1 }} />
|
||||
<a
|
||||
href="https://beta.gouv.fr"
|
||||
target="_blank"
|
||||
style={{
|
||||
height: '4rem',
|
||||
padding: '1rem'
|
||||
}}>
|
||||
<img alt="logo marianne" style={{ height: '100%' }} src={marianneSvg} />
|
||||
</a>
|
||||
<a
|
||||
href="https://www.urssaf.fr"
|
||||
target="_blank"
|
||||
style={{
|
||||
height: '4rem',
|
||||
padding: '1rem'
|
||||
}}
|
||||
className="landing-header__institutional-logo">
|
||||
<img alt="logo urssaf" style={{ height: '100%' }} src={urssafSvg} />
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,13 +1,10 @@
|
|||
/* @flow */
|
||||
import {
|
||||
currentQuestionSelector,
|
||||
situationSelector
|
||||
} from 'Selectors/analyseSelectors'
|
||||
|
||||
import type { Tracker } from 'Components/utils/withTracker'
|
||||
import Tracker from 'Tracker'
|
||||
|
||||
export default (tracker: Tracker) => {
|
||||
// $FlowFixMe
|
||||
return ({ getState }) => next => action => {
|
||||
next(action)
|
||||
const newState = getState()
|
||||
|
@ -49,7 +46,7 @@ export default (tracker: Tracker) => {
|
|||
...(action.type === 'UPDATE_PERIOD'
|
||||
? ['période', action.toPeriod]
|
||||
: [action.fieldName, action.value])
|
||||
])
|
||||
] as any)
|
||||
}
|
||||
if (action.type === 'START_CONVERSATION') {
|
||||
tracker.push([
|
|
@ -1,17 +1,18 @@
|
|||
/* @flow */
|
||||
import { React, T } from 'Components';
|
||||
import { ScrollToTop } from 'Components/utils/Scroll';
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths';
|
||||
import { useContext } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import Animate from 'Ui/animate';
|
||||
import siret from './siret.jpg';
|
||||
import { T } from 'Components'
|
||||
import { ScrollToTop } from 'Components/utils/Scroll'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import React, { useContext } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { NavLink } from 'react-router-dom'
|
||||
import Animate from 'Ui/animate'
|
||||
import siret from './siret.jpg'
|
||||
|
||||
export default function AfterRegistration() {
|
||||
const sitePaths = useContext(SitePathsContext);
|
||||
const statutChoisi = useSelector(state => state.inFranceApp.companyStatusChoice);
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const statutChoisi = useSelector<any, any>(
|
||||
state => state.inFranceApp.companyStatusChoice
|
||||
)
|
||||
const { t } = useTranslation()
|
||||
const isAutoentrepreneur = statutChoisi.match('auto-entrepreneur')
|
||||
|
||||
|
@ -72,8 +73,7 @@ export default function AfterRegistration() {
|
|||
).{' '}
|
||||
<span
|
||||
style={
|
||||
statutChoisi &&
|
||||
statutChoisi.match(/auto-entrepreneur|EI/)
|
||||
statutChoisi && statutChoisi.match(/auto-entrepreneur|EI/)
|
||||
? { display: 'none' }
|
||||
: {}
|
||||
}>
|
||||
|
@ -90,32 +90,31 @@ export default function AfterRegistration() {
|
|||
</p>
|
||||
</T>
|
||||
</p>
|
||||
{statutChoisi &&
|
||||
!statutChoisi.includes('auto-entrepreneur') && (
|
||||
<>
|
||||
<h2>
|
||||
<T k="après.kbis.titre">Le Kbis</T>
|
||||
</h2>
|
||||
<p>
|
||||
<T k="après.kbis.description.1">
|
||||
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.{' '}
|
||||
<a href="https://www.service-public.fr/professionnels-entreprises/vosdroits/F21000">
|
||||
Plus d'infos.
|
||||
</a>
|
||||
</T>
|
||||
</p>
|
||||
<p>
|
||||
<T k="après.kbis.description.2">
|
||||
Ce document est généralement demandé lors de la candidature à un
|
||||
appel d'offre public, de l'ouverture d'un compte bancaire,
|
||||
d'achats d'équipement professionnel auprès de fournisseurs, etc.
|
||||
</T>
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
{statutChoisi && !statutChoisi.includes('auto-entrepreneur') && (
|
||||
<>
|
||||
<h2>
|
||||
<T k="après.kbis.titre">Le Kbis</T>
|
||||
</h2>
|
||||
<p>
|
||||
<T k="après.kbis.description.1">
|
||||
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.{' '}
|
||||
<a href="https://www.service-public.fr/professionnels-entreprises/vosdroits/F21000">
|
||||
Plus d'infos.
|
||||
</a>
|
||||
</T>
|
||||
</p>
|
||||
<p>
|
||||
<T k="après.kbis.description.2">
|
||||
Ce document est généralement demandé lors de la candidature à un
|
||||
appel d'offre public, de l'ouverture d'un compte bancaire,
|
||||
d'achats d'équipement professionnel auprès de fournisseurs, etc.
|
||||
</T>
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</Animate.fromBottom>
|
||||
)
|
||||
}
|
|
@ -1,39 +1,33 @@
|
|||
/* @flow */
|
||||
import { checkCompanyCreationItem, initializeCompanyCreationChecklist } from 'Actions/companyCreationChecklistActions'
|
||||
import {
|
||||
checkCompanyCreationItem,
|
||||
initializeCompanyCreationChecklist
|
||||
} from 'Actions/companyCreationChecklistActions'
|
||||
import { goToCompanyStatusChoice } from 'Actions/companyStatusActions'
|
||||
import { React, T } from 'Components'
|
||||
import { T } from 'Components'
|
||||
import Scroll from 'Components/utils/Scroll'
|
||||
import withSitePaths from 'Components/utils/withSitePaths'
|
||||
import { compose } from 'ramda'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import React, { useContext } from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { connect, useSelector } from 'react-redux'
|
||||
import { Link } from 'react-router-dom'
|
||||
import * as Animate from 'Ui/animate'
|
||||
import { CheckItem, Checklist } from 'Ui/Checklist'
|
||||
import StatutDescription from './StatutDescription'
|
||||
import type { LegalStatus } from 'Selectors/companyStatusSelectors'
|
||||
import type { TFunction } from 'react-i18next'
|
||||
type Props = {
|
||||
statut: LegalStatus,
|
||||
onChecklistInitialization: (string, Array<string>) => void,
|
||||
onStatusChange: () => void,
|
||||
sitePaths: Object,
|
||||
onItemCheck: (name: string, checked: boolean) => void,
|
||||
t: TFunction,
|
||||
companyCreationChecklist: { [string]: boolean }
|
||||
}
|
||||
|
||||
const CreateCompany = ({
|
||||
function CreateCompany({
|
||||
statut,
|
||||
onChecklistInitialization,
|
||||
onItemCheck,
|
||||
sitePaths,
|
||||
companyCreationChecklist,
|
||||
onStatusChange
|
||||
}: Props) => {
|
||||
}) {
|
||||
const { t, i18n } = useTranslation()
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const companyCreationChecklist = useSelector<any, any>(
|
||||
state => state.inFranceApp.companyCreationChecklist
|
||||
)
|
||||
|
||||
// TODO : add this logic inside selector
|
||||
const isAutoentrepreneur = statut.startsWith('auto-entrepreneur')
|
||||
const multipleAssociates = ['SARL', 'SAS', 'SA'].includes(statut)
|
||||
|
@ -41,23 +35,17 @@ const CreateCompany = ({
|
|||
|
||||
const titre = isAutoentrepreneur
|
||||
? t(
|
||||
[
|
||||
'entreprise.page.autoEntrepreneur.titre',
|
||||
'Devenir {{autoEntrepreneur}}'
|
||||
],
|
||||
{
|
||||
autoEntrepreneur: statut
|
||||
}
|
||||
)
|
||||
: t(
|
||||
[
|
||||
'entreprise.page.entreprise.titre',
|
||||
'Créer une {{status}}'
|
||||
],
|
||||
{
|
||||
[
|
||||
'entreprise.page.autoEntrepreneur.titre',
|
||||
'Devenir {{autoEntrepreneur}}'
|
||||
],
|
||||
{
|
||||
autoEntrepreneur: statut
|
||||
}
|
||||
)
|
||||
: t(['entreprise.page.entreprise.titre', 'Créer une {{status}}'], {
|
||||
status: statut
|
||||
}
|
||||
)
|
||||
})
|
||||
return (
|
||||
<Animate.fromBottom>
|
||||
<Helmet>
|
||||
|
@ -67,25 +55,27 @@ const CreateCompany = ({
|
|||
content={
|
||||
isAutoentrepreneur
|
||||
? t(
|
||||
[
|
||||
'entreprise.page.autoEntrepreneur.description',
|
||||
'La liste complète des démarches à faire pour devenir {{autoEntrepreneur}}.'
|
||||
],
|
||||
{ autoEntrepreneur: t(statut) }
|
||||
)
|
||||
[
|
||||
'entreprise.page.autoEntrepreneur.description',
|
||||
'La liste complète des démarches à faire pour devenir {{autoEntrepreneur}}.'
|
||||
],
|
||||
{ autoEntrepreneur: t(statut) }
|
||||
)
|
||||
: t(
|
||||
[
|
||||
'entreprise.page.description',
|
||||
"La liste complète des démarches à faire pour créer une {{statut}} auprès de l'administration française."
|
||||
],
|
||||
{ statut: t(statut) }
|
||||
)
|
||||
[
|
||||
'entreprise.page.description',
|
||||
"La liste complète des démarches à faire pour créer une {{statut}} auprès de l'administration française."
|
||||
],
|
||||
{ statut: t(statut) }
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Helmet>
|
||||
<Scroll.toTop />
|
||||
<div css="transform: translateY(2rem);">
|
||||
<button onClick={onStatusChange} className="ui__ simple small push-left button">
|
||||
<button
|
||||
onClick={onStatusChange}
|
||||
className="ui__ simple small push-left button">
|
||||
<T k="entreprise.retour">← Choisir un autre statut</T>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -108,10 +98,8 @@ const CreateCompany = ({
|
|||
</p>
|
||||
<Checklist
|
||||
key={statut}
|
||||
onInitialization={items =>
|
||||
onChecklistInitialization(statut, items)
|
||||
}
|
||||
onItemCheck={onItemCheck}
|
||||
onInitialization={items => onChecklistInitialization(statut, items)}
|
||||
onItemCheck={x => onItemCheck}
|
||||
defaultChecked={companyCreationChecklist}>
|
||||
<CheckItem
|
||||
name="legalStatus"
|
||||
|
@ -438,7 +426,9 @@ const CreateCompany = ({
|
|||
}
|
||||
/>
|
||||
</Checklist>
|
||||
<h2>{emoji('🧰')} <T>Ressources utiles</T></h2>
|
||||
<h2>
|
||||
{emoji('🧰')} <T>Ressources utiles</T>
|
||||
</h2>
|
||||
<div
|
||||
css={`
|
||||
display: flex;
|
||||
|
@ -448,78 +438,94 @@ const CreateCompany = ({
|
|||
flex: 1;
|
||||
}
|
||||
`}>
|
||||
|
||||
{isAutoentrepreneur && <Link
|
||||
className="ui__ interactive card button-choice lighter-bg"
|
||||
to={{ pathname: sitePaths.simulateurs['auto-entrepreneur'], state: { fromCréer: true } }}>
|
||||
<T k="entreprise.ressources.simu.autoEntrepreneur"><p>Simulateur de revenus auto-entrepreneur</p>
|
||||
<small>
|
||||
Simuler le montant de vos cotisations sociales et de votre impôt et estimez votre futur revenu net.
|
||||
</small>
|
||||
</T>
|
||||
</Link>
|
||||
}
|
||||
{['EI', 'EIRL', 'EURL'].includes(statut) && <Link
|
||||
className="ui__ interactive card button-choice lighter-bg"
|
||||
to={{ pathname: sitePaths.simulateurs.indépendant, state: { fromCréer: true } }}>
|
||||
<T k="entreprise.ressources.simu.indépendant">
|
||||
<p>Simulateur de cotisations indépendant</p>
|
||||
<small>
|
||||
Simuler le montant de vos cotisations sociales pour bien préparer votre business plan.
|
||||
</small></T>
|
||||
</Link>
|
||||
}
|
||||
{['SAS', 'SASU'].includes(statut) && <Link
|
||||
className="ui__ interactive card button-choice lighter-bg"
|
||||
to={{ pathname: sitePaths.simulateurs['assimilé-salarié'], state: { fromCréer: true } }}>
|
||||
<T k="entreprise.ressources.simu.assimilé">
|
||||
<p>Simulateur de cotisations assimilé-salarié</p>
|
||||
<small>
|
||||
Simuler le montant de vos cotisations sociales pour bien préparer votre business plan.
|
||||
</small>
|
||||
</T>
|
||||
</Link>
|
||||
}
|
||||
{isAutoentrepreneur && (
|
||||
<Link
|
||||
className="ui__ interactive card button-choice lighter-bg"
|
||||
to={{
|
||||
pathname: sitePaths.simulateurs['auto-entrepreneur'],
|
||||
state: { fromCréer: true }
|
||||
}}>
|
||||
<T k="entreprise.ressources.simu.autoEntrepreneur">
|
||||
<p>Simulateur de revenus auto-entrepreneur</p>
|
||||
<small>
|
||||
Simuler le montant de vos cotisations sociales et de votre impôt
|
||||
et estimez votre futur revenu net.
|
||||
</small>
|
||||
</T>
|
||||
</Link>
|
||||
)}
|
||||
{['EI', 'EIRL', 'EURL'].includes(statut) && (
|
||||
<Link
|
||||
className="ui__ interactive card button-choice lighter-bg"
|
||||
to={{
|
||||
pathname: sitePaths.simulateurs.indépendant,
|
||||
state: { fromCréer: true }
|
||||
}}>
|
||||
<T k="entreprise.ressources.simu.indépendant">
|
||||
<p>Simulateur de cotisations indépendant</p>
|
||||
<small>
|
||||
Simuler le montant de vos cotisations sociales pour bien
|
||||
préparer votre business plan.
|
||||
</small>
|
||||
</T>
|
||||
</Link>
|
||||
)}
|
||||
{['SAS', 'SASU'].includes(statut) && (
|
||||
<Link
|
||||
className="ui__ interactive card button-choice lighter-bg"
|
||||
to={{
|
||||
pathname: sitePaths.simulateurs['assimilé-salarié'],
|
||||
state: { fromCréer: true }
|
||||
}}>
|
||||
<T k="entreprise.ressources.simu.assimilé">
|
||||
<p>Simulateur de cotisations assimilé-salarié</p>
|
||||
<small>
|
||||
Simuler le montant de vos cotisations sociales pour bien
|
||||
préparer votre business plan.
|
||||
</small>
|
||||
</T>
|
||||
</Link>
|
||||
)}
|
||||
<Link
|
||||
className="ui__ interactive card button-choice lighter-bg"
|
||||
to={sitePaths.créer.après}>
|
||||
<T k="entreprise.ressources.après">
|
||||
<p>Après la création</p>
|
||||
<small>
|
||||
SIREN, SIRET, code APE, KBis. Un petit glossaire des termes que vous pourrez (éventuellement) rencontrer après la création.
|
||||
SIREN, SIRET, code APE, KBis. Un petit glossaire des termes que
|
||||
vous pourrez (éventuellement) rencontrer après la création.
|
||||
</small>
|
||||
</T>
|
||||
</Link>
|
||||
{i18n.language === 'fr' && (<a
|
||||
target="_blank"
|
||||
className="ui__ interactive card button-choice lighter-bg"
|
||||
href="https://www.urssaf.fr/portail/files/live/sites/urssaf/files/documents/SSI-Guide-Objectif-Entreprise.pdf">
|
||||
<p>Guide de création URSSAF </p>
|
||||
<small>
|
||||
Des conseils sur comment
|
||||
préparer son projet pour se lancer dans la création et une
|
||||
présentation détaillée de votre protection sociale.
|
||||
</small><br />
|
||||
<div css="text-align: right">
|
||||
<small className="ui__ label">PDF</small>
|
||||
</div>
|
||||
</a>)}
|
||||
{i18n.language === 'fr' && (
|
||||
<a
|
||||
target="_blank"
|
||||
className="ui__ interactive card button-choice lighter-bg"
|
||||
href="https://www.urssaf.fr/portail/files/live/sites/urssaf/files/documents/SSI-Guide-Objectif-Entreprise.pdf">
|
||||
<p>Guide de création URSSAF </p>
|
||||
<small>
|
||||
Des conseils sur comment préparer son projet pour se lancer dans
|
||||
la création et une présentation détaillée de votre protection
|
||||
sociale.
|
||||
</small>
|
||||
<br />
|
||||
<div css="text-align: right">
|
||||
<small className="ui__ label">PDF</small>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</Animate.fromBottom >
|
||||
</Animate.fromBottom>
|
||||
)
|
||||
}
|
||||
export default compose(
|
||||
withSitePaths,
|
||||
connect(
|
||||
state => ({
|
||||
companyCreationChecklist: state.inFranceApp.companyCreationChecklist,
|
||||
}),
|
||||
{
|
||||
onChecklistInitialization: initializeCompanyCreationChecklist,
|
||||
onItemCheck: checkCompanyCreationItem,
|
||||
onStatusChange: goToCompanyStatusChoice
|
||||
}
|
||||
)
|
||||
|
||||
export default connect(
|
||||
null,
|
||||
{
|
||||
onChecklistInitialization: initializeCompanyCreationChecklist,
|
||||
onItemCheck: checkCompanyCreationItem,
|
||||
onStatusChange: goToCompanyStatusChoice
|
||||
}
|
||||
)(CreateCompany)
|
||||
|
||||
let StatutsExample = ({ statut }) => {
|
|
@ -1,72 +0,0 @@
|
|||
/* @flow */
|
||||
import { isAutoentrepreneur } from 'Actions/companyStatusActions'
|
||||
import { React, T } from 'Components'
|
||||
import SchemeComparaison from 'Components/SchemeComparaison'
|
||||
import { compose } from 'ramda'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { withTranslation } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
import type { TFunction } from 'react-i18next'
|
||||
|
||||
type Props = {
|
||||
isAutoentrepreneur: (?boolean) => void,
|
||||
t: TFunction
|
||||
}
|
||||
|
||||
const Autoentrepreneur = ({ isAutoentrepreneur, t }: Props) => (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{t('autoentrepreneur.page.titre', 'Auto-entrepreneur')}</title>
|
||||
<meta
|
||||
name="description"
|
||||
content={
|
||||
<T k="autoentrepreneur.page.description">
|
||||
Un auto-entrepreneur bénéficie d'un système simplifié de déclaration
|
||||
et de paiement, pour lesquelles les impôts et cotisations sociales
|
||||
sont basés sur le chiffre d'affaires réalisé chaque mois. C'est un
|
||||
choix intéressant si vous n'avez pas besoin de beaucoup de capital
|
||||
et que vous souhaitez démarrer rapidement.
|
||||
</T>
|
||||
}
|
||||
/>
|
||||
</Helmet>
|
||||
<h2>
|
||||
<T k="autoentrepreneur.titre">
|
||||
Entreprise individuelle ou auto-entrepreneur
|
||||
</T>
|
||||
</h2>
|
||||
<T k="autoentrepreneur.description">
|
||||
<p>
|
||||
À la différence de l'entreprise individuelle, l'auto-entrepreneur
|
||||
bénéficie d'un régime simplifié de déclaration et de paiement : les
|
||||
cotisations sociales et l'impôt sur le revenu sont calculés sur le
|
||||
chiffre d'affaires encaissé.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Note</strong> : Certaines activités sont exclues de ce statut (
|
||||
<a href="https://www.afecreation.fr/pid10375/pour-quelles-activites.html#principales-exclusions">
|
||||
{' '}
|
||||
voir la liste
|
||||
</a>
|
||||
). Certaines activités sont réglementées avec une qualification ou une
|
||||
expérience professionnelle (
|
||||
<a href="https://www.afecreation.fr/pid316/activites-reglementees.html">
|
||||
voir la liste
|
||||
</a>
|
||||
).
|
||||
</p>
|
||||
</T>
|
||||
<div className="ui__ full-width">
|
||||
<SchemeComparaison hideAssimiléSalarié />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
export default compose(
|
||||
withTranslation(),
|
||||
connect(
|
||||
null,
|
||||
{ isAutoentrepreneur }
|
||||
)
|
||||
)(Autoentrepreneur)
|
|
@ -0,0 +1,53 @@
|
|||
import { T } from 'Components'
|
||||
import SchemeComparaison from 'Components/SchemeComparaison'
|
||||
import React from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export default function Autoentrepreneur() {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{t('autoentrepreneur.page.titre', 'Auto-entrepreneur')}</title>
|
||||
<meta
|
||||
name="description"
|
||||
content={t(
|
||||
'autoentrepreneur.page.description',
|
||||
"Un auto-entrepreneur bénéficie d'un système simplifié de déclaration et de paiement, pour lesquelles les impôts et cotisations sociales sont basés sur le chiffre d'affaires réalisé chaque mois. C'est un choix intéressant si vous n'avez pas besoin de beaucoup de capital et que vous souhaitez démarrer rapidement."
|
||||
)}
|
||||
/>
|
||||
</Helmet>
|
||||
<h2>
|
||||
<T k="autoentrepreneur.titre">
|
||||
Entreprise individuelle ou auto-entrepreneur
|
||||
</T>
|
||||
</h2>
|
||||
<T k="autoentrepreneur.description">
|
||||
<p>
|
||||
À la différence de l'entreprise individuelle, l'auto-entrepreneur
|
||||
bénéficie d'un régime simplifié de déclaration et de paiement : les
|
||||
cotisations sociales et l'impôt sur le revenu sont calculés sur le
|
||||
chiffre d'affaires encaissé.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Note</strong> : Certaines activités sont exclues de ce statut
|
||||
(
|
||||
<a href="https://www.afecreation.fr/pid10375/pour-quelles-activites.html#principales-exclusions">
|
||||
{' '}
|
||||
voir la liste
|
||||
</a>
|
||||
). Certaines activités sont réglementées avec une qualification ou une
|
||||
expérience professionnelle (
|
||||
<a href="https://www.afecreation.fr/pid316/activites-reglementees.html">
|
||||
voir la liste
|
||||
</a>
|
||||
).
|
||||
</p>
|
||||
</T>
|
||||
<div className="ui__ full-width">
|
||||
<SchemeComparaison hideAssimiléSalarié />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -1,19 +1,10 @@
|
|||
/* @flow */
|
||||
import { defineDirectorStatus } from 'Actions/companyStatusActions'
|
||||
import { React, T } from 'Components'
|
||||
import { T } from 'Components'
|
||||
import SchemeComparaison from 'Components/SchemeComparaison'
|
||||
import { compose } from 'ramda'
|
||||
import React from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import type { DirectorStatus } from 'Types/companyTypes'
|
||||
|
||||
|
||||
type Props = {
|
||||
defineDirectorStatus: (?DirectorStatus) => void,
|
||||
sitePaths: Object
|
||||
}
|
||||
const DefineDirectorStatus = ({ defineDirectorStatus }: Props) => {
|
||||
export default function DefineDirectorStatus() {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<>
|
||||
|
@ -25,7 +16,7 @@ const DefineDirectorStatus = ({ defineDirectorStatus }: Props) => {
|
|||
name="description"
|
||||
content={t(
|
||||
'statut du dirigeant.page.description',
|
||||
'Ce choix est important parce qu\'il détermine le régime de sécurité sociale et la couverture sociale de l\'administrateur. Chaque option a des implications juridiques et conduit à un statut différent lors de la création de votre entreprise.'
|
||||
"Ce choix est important parce qu'il détermine le régime de sécurité sociale et la couverture sociale de l'administrateur. Chaque option a des implications juridiques et conduit à un statut différent lors de la création de votre entreprise."
|
||||
)}
|
||||
/>
|
||||
</Helmet>
|
||||
|
@ -45,10 +36,3 @@ const DefineDirectorStatus = ({ defineDirectorStatus }: Props) => {
|
|||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default compose(
|
||||
connect(
|
||||
null,
|
||||
{ defineDirectorStatus }
|
||||
)
|
||||
)(DefineDirectorStatus)
|
|
@ -1,18 +1,13 @@
|
|||
/* @flow */
|
||||
import { directorIsInAMinority } from 'Actions/companyStatusActions';
|
||||
import { React, T } from 'Components';
|
||||
import { compose } from 'ramda';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
import type { TFunction } from 'react-i18next'
|
||||
import { directorIsInAMinority } from 'Actions/companyStatusActions'
|
||||
import { T } from 'Components'
|
||||
import React from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useDispatch } from 'react-redux'
|
||||
|
||||
type Props = {
|
||||
directorIsInAMinority: (?boolean) => void,
|
||||
t: TFunction
|
||||
}
|
||||
|
||||
const MinorityDirector = ({ directorIsInAMinority, t }: Props) => {
|
||||
export default function MinorityDirector() {
|
||||
const { t } = useTranslation()
|
||||
const dispatch = useDispatch()
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
|
@ -26,7 +21,7 @@ const MinorityDirector = ({ directorIsInAMinority, t }: Props) => {
|
|||
name="description"
|
||||
content={t(
|
||||
'gérant minoritaire.page.description',
|
||||
'Certaines règles particulières s\'appliquent en fonction du nombre d\'actions détenues par l\'administrateur, ce qui peut conduire à un statut différent lors de la création de votre société'
|
||||
"Certaines règles particulières s'appliquent en fonction du nombre d'actions détenues par l'administrateur, ce qui peut conduire à un statut différent lors de la création de votre société"
|
||||
)}
|
||||
/>
|
||||
</Helmet>
|
||||
|
@ -40,12 +35,14 @@ const MinorityDirector = ({ directorIsInAMinority, t }: Props) => {
|
|||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Gérant majoritaire</strong> : Vous êtes l'administrateur majoritaire
|
||||
(ou faite partie d'un conseil d'administration majoritaire).
|
||||
</li>
|
||||
<strong>Gérant majoritaire</strong> : Vous êtes l'administrateur
|
||||
majoritaire (ou faite partie d'un conseil d'administration
|
||||
majoritaire).
|
||||
</li>
|
||||
<li>
|
||||
<strong>Gérant minoritaire</strong> : Vous êtes administrateur minoritaire ou égalitaire (ou faites partie d'un conseil d'administration
|
||||
minoritaire ou égalitaire).
|
||||
<strong>Gérant minoritaire</strong> : Vous êtes administrateur
|
||||
minoritaire ou égalitaire (ou faites partie d'un conseil
|
||||
d'administration minoritaire ou égalitaire).
|
||||
</li>
|
||||
</ul>
|
||||
</T>
|
||||
|
@ -53,14 +50,14 @@ const MinorityDirector = ({ directorIsInAMinority, t }: Props) => {
|
|||
<div className="ui__ answer-group">
|
||||
<button
|
||||
onClick={() => {
|
||||
directorIsInAMinority(false)
|
||||
dispatch(directorIsInAMinority(false))
|
||||
}}
|
||||
className="ui__ button">
|
||||
<T>Gérant majoritaire</T>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
directorIsInAMinority(true)
|
||||
dispatch(directorIsInAMinority(true))
|
||||
}}
|
||||
className="ui__ button">
|
||||
<T>Gérant minoritaire</T>
|
||||
|
@ -69,11 +66,3 @@ const MinorityDirector = ({ directorIsInAMinority, t }: Props) => {
|
|||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withTranslation(),
|
||||
connect(
|
||||
null,
|
||||
{ directorIsInAMinority }
|
||||
)
|
||||
)(MinorityDirector)
|
|
@ -1,75 +0,0 @@
|
|||
/* @flow */
|
||||
|
||||
import { companyHasMultipleAssociates } from 'Actions/companyStatusActions'
|
||||
import { React, T } from 'Components'
|
||||
import { compose } from 'ramda'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { withTranslation } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import type { TFunction } from 'react-i18next'
|
||||
|
||||
type Props = {
|
||||
companyHasMultipleAssociates: (?boolean) => void,
|
||||
t: TFunction
|
||||
}
|
||||
|
||||
const NumberOfAssociates = ({ companyHasMultipleAssociates, t }: Props) => (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>
|
||||
{t(
|
||||
'associés.page.titre',
|
||||
"Nombre d'associés pour créer une entreprise"
|
||||
)}
|
||||
</title>
|
||||
<meta
|
||||
name="description"
|
||||
content={t(
|
||||
'associés.page.description',
|
||||
"Découvrez quels status choisir en fonction du nombre d'associés participant à la création de l'entreprise."
|
||||
)}
|
||||
/>
|
||||
</Helmet>
|
||||
<h2>
|
||||
<T k="associés.titre">Seul ou à plusieurs</T>
|
||||
</h2>
|
||||
<T k="associés.description">
|
||||
<p>
|
||||
Une entreprise avec un seul associé est plus simple à créer et gérer. Un
|
||||
associé peut-être une personne physique (un individu) ou une personne
|
||||
morale (par exemple une société).
|
||||
</p>
|
||||
<p>
|
||||
Note : ce choix n'est pas définitif. Vous pouvez tout à fait commencer
|
||||
votre société seul, et accueillir de nouveaux associés au cours de votre
|
||||
développement.
|
||||
</p>
|
||||
</T>
|
||||
|
||||
<div className="ui__ answer-group">
|
||||
<button
|
||||
onClick={() => {
|
||||
companyHasMultipleAssociates(false)
|
||||
}}
|
||||
className="ui__ button">
|
||||
<T k="associés.choix1">Seul</T>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
companyHasMultipleAssociates(true)
|
||||
}}
|
||||
className="ui__ button">
|
||||
<T k="associés.choix2">Plusieurs personnes</T>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</>
|
||||
)
|
||||
|
||||
export default compose(
|
||||
withTranslation(),
|
||||
connect(
|
||||
null,
|
||||
{ companyHasMultipleAssociates }
|
||||
)
|
||||
)(NumberOfAssociates)
|
|
@ -0,0 +1,66 @@
|
|||
import { companyHasMultipleAssociates } from 'Actions/companyStatusActions'
|
||||
import { T } from 'Components'
|
||||
import React from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
const NumberOfAssociates = ({ companyHasMultipleAssociates }) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>
|
||||
{t(
|
||||
'associés.page.titre',
|
||||
"Nombre d'associés pour créer une entreprise"
|
||||
)}
|
||||
</title>
|
||||
<meta
|
||||
name="description"
|
||||
content={t(
|
||||
'associés.page.description',
|
||||
"Découvrez quels status choisir en fonction du nombre d'associés participant à la création de l'entreprise."
|
||||
)}
|
||||
/>
|
||||
</Helmet>
|
||||
<h2>
|
||||
<T k="associés.titre">Seul ou à plusieurs</T>
|
||||
</h2>
|
||||
<T k="associés.description">
|
||||
<p>
|
||||
Une entreprise avec un seul associé est plus simple à créer et gérer.
|
||||
Un associé peut-être une personne physique (un individu) ou une
|
||||
personne morale (par exemple une société).
|
||||
</p>
|
||||
<p>
|
||||
Note : ce choix n'est pas définitif. Vous pouvez tout à fait commencer
|
||||
votre société seul, et accueillir de nouveaux associés au cours de
|
||||
votre développement.
|
||||
</p>
|
||||
</T>
|
||||
|
||||
<div className="ui__ answer-group">
|
||||
<button
|
||||
onClick={() => {
|
||||
companyHasMultipleAssociates(false)
|
||||
}}
|
||||
className="ui__ button">
|
||||
<T k="associés.choix1">Seul</T>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
companyHasMultipleAssociates(true)
|
||||
}}
|
||||
className="ui__ button">
|
||||
<T k="associés.choix2">Plusieurs personnes</T>
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(
|
||||
null,
|
||||
{ companyHasMultipleAssociates }
|
||||
)(NumberOfAssociates)
|
|
@ -1,43 +1,34 @@
|
|||
/* @flow */
|
||||
import { React, T } from 'Components'
|
||||
import withSitePaths from 'Components/utils/withSitePaths'
|
||||
import { compose, filter } from 'ramda'
|
||||
import { T } from 'Components'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import { filter } from 'ramda'
|
||||
import React, { useContext } from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { possibleStatusSelector } from 'Selectors/companyStatusSelectors'
|
||||
import {
|
||||
LegalStatus,
|
||||
possibleStatusSelector
|
||||
} from 'Selectors/companyStatusSelectors'
|
||||
import StatutDescription from '../StatutDescription'
|
||||
import type { RouterHistory } from 'react-router'
|
||||
import type { LegalStatus } from 'Selectors/companyStatusSelectors'
|
||||
|
||||
type Props = {
|
||||
history: RouterHistory,
|
||||
possibleStatus: { [LegalStatus]: boolean },
|
||||
goBackToPreviousQuestion: () => void,
|
||||
sitePaths: Object,
|
||||
setMainStatus: LegalStatus => void,
|
||||
language: string
|
||||
const StatutButton = ({ statut }: { statut: LegalStatus }) => {
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div className="ui__ answer-group">
|
||||
<Link to={sitePaths.créer[statut]} className="ui__ button">
|
||||
{statut.includes('auto-entrepreneur') ? (
|
||||
<T>Devenir</T>
|
||||
) : (
|
||||
<T>Créer une</T>
|
||||
)}{' '}
|
||||
{t(statut)}
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const StatutButton = withSitePaths(
|
||||
({ statut, sitePaths }: { statut: LegalStatus, sitePaths: Object }) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div className="ui__ answer-group">
|
||||
<Link to={sitePaths.créer[statut]} className="ui__ button">
|
||||
{statut.includes('auto-entrepreneur') ? (
|
||||
<T>Devenir</T>
|
||||
) : (
|
||||
<T>Créer une</T>
|
||||
)}{' '}
|
||||
{t(statut)}
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
const StatutTitle = ({ statut, language }) =>
|
||||
statut === 'EI' ? (
|
||||
<>
|
||||
|
@ -85,11 +76,9 @@ const StatutTitle = ({ statut, language }) =>
|
|||
</>
|
||||
) : null
|
||||
|
||||
const SetMainStatus = ({
|
||||
history,
|
||||
possibleStatus,
|
||||
}: Props) => {
|
||||
export default function SetMainStatus() {
|
||||
const { t, i18n } = useTranslation()
|
||||
const possibleStatus = useSelector(possibleStatusSelector)
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
|
@ -101,30 +90,28 @@ const SetMainStatus = ({
|
|||
</title>
|
||||
</Helmet>
|
||||
<h2>
|
||||
{Object.keys(possibleStatus).every(Boolean) ? <T> Liste des statuts juridiques </T> : <T>Votre forme juridique</T>}
|
||||
{Object.keys(possibleStatus).every(Boolean) ? (
|
||||
<T> Liste des statuts juridiques </T>
|
||||
) : (
|
||||
<T>Votre forme juridique</T>
|
||||
)}
|
||||
</h2>
|
||||
|
||||
<ul>
|
||||
{Object.keys(filter(Boolean, possibleStatus)).map(statut => (
|
||||
<li key={statut}>
|
||||
<strong>
|
||||
<StatutTitle statut={statut} language={i18n.language} />
|
||||
</strong>{' '}
|
||||
<p>
|
||||
<StatutDescription statut={statut} />
|
||||
</p>
|
||||
<StatutButton statut={statut} history={history} />
|
||||
</li>
|
||||
))}
|
||||
{Object.keys(filter(Boolean, possibleStatus as any)).map(
|
||||
(statut: keyof typeof possibleStatus) => (
|
||||
<li key={statut}>
|
||||
<strong>
|
||||
<StatutTitle statut={statut} language={i18n.language} />
|
||||
</strong>{' '}
|
||||
<p>
|
||||
<StatutDescription statut={statut} />
|
||||
</p>
|
||||
<StatutButton statut={statut} />
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withSitePaths,
|
||||
connect(
|
||||
state => ({ possibleStatus: possibleStatusSelector(state) }),
|
||||
)
|
||||
)(SetMainStatus)
|
|
@ -1,62 +0,0 @@
|
|||
/* @flow */
|
||||
import { React, T } from 'Components'
|
||||
import withSitePaths from 'Components/utils/withSitePaths'
|
||||
import { compose, isNil } from 'ramda'
|
||||
import { connect } from 'react-redux'
|
||||
import { Link } from 'react-router-dom'
|
||||
import type { LegalStatusRequirements } from 'Types/companyTypes'
|
||||
|
||||
const requirementToText = (key, value) => {
|
||||
switch (key) {
|
||||
case 'multipleAssociates':
|
||||
return value ? <T>Plusieurs associés</T> : <T>Un seul associé</T>
|
||||
case 'soleProprietorship':
|
||||
return value ? (
|
||||
<T T k="responsabilité.bouton2">
|
||||
Entreprise individuelle
|
||||
</T>
|
||||
) : (
|
||||
<T k="responsabilité.bouton1">Société</T>
|
||||
)
|
||||
case 'directorStatus':
|
||||
return value === 'SELF_EMPLOYED' ? (
|
||||
<T>Indépendant</T>
|
||||
) : (
|
||||
<T>Assimilé salarié</T>
|
||||
)
|
||||
case 'autoEntrepreneur':
|
||||
return value ? <T>Auto-entrepreneur</T> : <T>Pas en auto-entrepreneur</T>
|
||||
case 'minorityDirector':
|
||||
return value ? <T>Gérant minoritaire</T> : <T>Gérant majoritaire</T>
|
||||
}
|
||||
}
|
||||
type OwnProps = {}
|
||||
type Props = LegalStatusRequirements & {
|
||||
goToCompanyStatusChoice: () => void,
|
||||
sitePaths: Object
|
||||
}
|
||||
|
||||
const PreviousAnswers = ({
|
||||
sitePaths,
|
||||
legalStatus
|
||||
}: Props) => !!Object.values(legalStatus).length && (
|
||||
<ul css="margin-bottom: -1rem;">
|
||||
{Object.entries(legalStatus).map(
|
||||
([key, value]) =>
|
||||
!isNil(value) && (
|
||||
<li key={key}>
|
||||
<Link to={sitePaths.créer.guideStatut[key]}>
|
||||
{requirementToText(key, value)}
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
)
|
||||
|
||||
export default (compose(
|
||||
connect(
|
||||
state => ({ legalStatus: state.inFranceApp.companyLegalStatus }),
|
||||
),
|
||||
withSitePaths
|
||||
)(PreviousAnswers): React$ComponentType<OwnProps>)
|
|
@ -0,0 +1,58 @@
|
|||
import { T } from 'Components'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import { isNil } from 'ramda'
|
||||
import React, { useContext } from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { LegalStatusRequirements } from 'Types/companyTypes'
|
||||
|
||||
const requirementToText = (
|
||||
key: keyof LegalStatusRequirements,
|
||||
value: string
|
||||
) => {
|
||||
switch (key) {
|
||||
case 'multipleAssociates':
|
||||
return value ? <T>Plusieurs associés</T> : <T>Un seul associé</T>
|
||||
case 'soleProprietorship':
|
||||
return value ? (
|
||||
<T T k="responsabilité.bouton2">
|
||||
Entreprise individuelle
|
||||
</T>
|
||||
) : (
|
||||
<T k="responsabilité.bouton1">Société</T>
|
||||
)
|
||||
case 'directorStatus':
|
||||
return value === 'SELF_EMPLOYED' ? (
|
||||
<T>Indépendant</T>
|
||||
) : (
|
||||
<T>Assimilé salarié</T>
|
||||
)
|
||||
case 'autoEntrepreneur':
|
||||
return value ? <T>Auto-entrepreneur</T> : <T>Pas en auto-entrepreneur</T>
|
||||
case 'minorityDirector':
|
||||
return value ? <T>Gérant minoritaire</T> : <T>Gérant majoritaire</T>
|
||||
}
|
||||
}
|
||||
|
||||
export default function PreviousAnswers() {
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const legalStatus = useSelector<any, any>(
|
||||
state => state.inFranceApp.companyLegalStatus
|
||||
)
|
||||
return (
|
||||
!!Object.values(legalStatus).length && (
|
||||
<ul css="margin-bottom: -1rem;">
|
||||
{Object.entries(legalStatus).map(
|
||||
([key, value]) =>
|
||||
!isNil(value) && (
|
||||
<li key={key}>
|
||||
<Link to={sitePaths.créer.guideStatut[key]}>
|
||||
{requirementToText(key as any, value as any)}
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
)
|
||||
)
|
||||
}
|
|
@ -1,16 +1,12 @@
|
|||
/* @flow */
|
||||
import { isSoleProprietorship } from 'Actions/companyStatusActions'
|
||||
import { React, T } from 'Components'
|
||||
import { T } from 'Components'
|
||||
import { compose } from 'ramda'
|
||||
import React from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
type Props = {
|
||||
isSoleProprietorship: (?boolean) => void
|
||||
}
|
||||
|
||||
const SoleProprietorship = ({ isSoleProprietorship }: Props) => {
|
||||
const SoleProprietorship = ({ isSoleProprietorship }) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<>
|
|
@ -1,91 +0,0 @@
|
|||
/* @flow */
|
||||
import { resetCompanyStatusChoice } from 'Actions/companyStatusActions';
|
||||
import { T } from 'Components';
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths';
|
||||
import { toPairs } from 'ramda';
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { NavLink, Route, Switch, useLocation } from 'react-router-dom';
|
||||
import Animate from 'Ui/animate';
|
||||
import AutoEntrepreneur from './AutoEntrepreneur';
|
||||
import DirectorStatus from './DirectorStatus';
|
||||
import MinorityDirector from './MinorityDirector';
|
||||
import NumberOfAssociate from './NumberOfAssociate';
|
||||
import PickLegalStatus from './PickLegalStatus';
|
||||
import PreviousAnswers from './PreviousAnswers';
|
||||
import SoleProprietorship from './SoleProprietorship';
|
||||
|
||||
|
||||
|
||||
const useResetFollowingAnswers = () => {
|
||||
const dispatch = useDispatch();
|
||||
const sitePaths = useContext(SitePathsContext);
|
||||
const location = useLocation();
|
||||
useEffect(() => {
|
||||
const companyStatusCurrentQuestionName = (toPairs(
|
||||
sitePaths.créer.guideStatut
|
||||
).find(([, pathname]) => location.pathname === pathname) || [])[0]
|
||||
if (!companyStatusCurrentQuestionName) {
|
||||
return
|
||||
}
|
||||
dispatch(resetCompanyStatusChoice(companyStatusCurrentQuestionName))
|
||||
}, [location.pathname, dispatch, sitePaths.créer.guideStatut])
|
||||
}
|
||||
|
||||
export default function Créer() {
|
||||
const sitePaths = useContext(SitePathsContext);
|
||||
const location = useLocation();
|
||||
useResetFollowingAnswers();
|
||||
return (
|
||||
<>
|
||||
<div css="transform: translateY(2rem)">
|
||||
<NavLink
|
||||
to={sitePaths.créer.index}
|
||||
exact
|
||||
activeClassName="ui__ hide"
|
||||
className="ui__ simple push-left small button">
|
||||
← <T>Retour</T>
|
||||
</NavLink>
|
||||
</div>
|
||||
<h1>
|
||||
<T k="formeJuridique.titre">Choix du statut juridique</T>
|
||||
</h1>
|
||||
<PreviousAnswers />
|
||||
<Animate.fromBottom key={location.pathname}>
|
||||
<Switch>
|
||||
<Route
|
||||
path={sitePaths.créer.guideStatut.soleProprietorship}
|
||||
>
|
||||
<SoleProprietorship />
|
||||
</Route>
|
||||
<Route
|
||||
path={sitePaths.créer.guideStatut.directorStatus}
|
||||
>
|
||||
<DirectorStatus />
|
||||
</Route>
|
||||
<Route
|
||||
path={sitePaths.créer.guideStatut.autoEntrepreneur}
|
||||
>
|
||||
<AutoEntrepreneur />
|
||||
</Route>
|
||||
<Route
|
||||
path={sitePaths.créer.guideStatut.multipleAssociates}
|
||||
>
|
||||
<NumberOfAssociate />
|
||||
</Route>
|
||||
<Route
|
||||
path={sitePaths.créer.guideStatut.minorityDirector}
|
||||
>
|
||||
<MinorityDirector />
|
||||
</Route>
|
||||
<Route
|
||||
path={sitePaths.créer.guideStatut.liste}
|
||||
>
|
||||
<PickLegalStatus />
|
||||
</Route>
|
||||
</Switch>
|
||||
</Animate.fromBottom>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
import { resetCompanyStatusChoice } from 'Actions/companyStatusActions'
|
||||
import { T } from 'Components'
|
||||
import Animate from 'Ui/animate'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import { toPairs } from 'ramda'
|
||||
import React, { useContext, useEffect } from 'react'
|
||||
import { useDispatch } from 'react-redux'
|
||||
import { NavLink, Route, Switch, useLocation } from 'react-router-dom'
|
||||
import AutoEntrepreneur from './AutoEntrepreneur'
|
||||
import DirectorStatus from './DirectorStatus'
|
||||
import MinorityDirector from './MinorityDirector'
|
||||
import NumberOfAssociate from './NumberOfAssociate'
|
||||
import PickLegalStatus from './PickLegalStatus'
|
||||
import PreviousAnswers from './PreviousAnswers'
|
||||
import SoleProprietorship from './SoleProprietorship'
|
||||
|
||||
const useResetFollowingAnswers = () => {
|
||||
const dispatch = useDispatch()
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const location = useLocation()
|
||||
useEffect(() => {
|
||||
const companyStatusCurrentQuestionName = (toPairs(
|
||||
sitePaths.créer.guideStatut
|
||||
).find(([, pathname]) => location.pathname === pathname) || [])[0]
|
||||
if (!companyStatusCurrentQuestionName) {
|
||||
return
|
||||
}
|
||||
dispatch(resetCompanyStatusChoice(companyStatusCurrentQuestionName))
|
||||
}, [location.pathname, dispatch, sitePaths.créer.guideStatut])
|
||||
}
|
||||
|
||||
export default function Créer() {
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const location = useLocation()
|
||||
useResetFollowingAnswers()
|
||||
return (
|
||||
<>
|
||||
<div css="transform: translateY(2rem)">
|
||||
<NavLink
|
||||
to={sitePaths.créer.index}
|
||||
exact
|
||||
activeClassName="ui__ hide"
|
||||
className="ui__ simple push-left small button">
|
||||
← <T>Retour</T>
|
||||
</NavLink>
|
||||
</div>
|
||||
<h1>
|
||||
<T k="formeJuridique.titre">Choix du statut juridique</T>
|
||||
</h1>
|
||||
<PreviousAnswers />
|
||||
<Animate.fromBottom key={location.pathname}>
|
||||
<Switch>
|
||||
<Route path={sitePaths.créer.guideStatut.soleProprietorship}>
|
||||
<SoleProprietorship />
|
||||
</Route>
|
||||
<Route path={sitePaths.créer.guideStatut.directorStatus}>
|
||||
<DirectorStatus />
|
||||
</Route>
|
||||
<Route path={sitePaths.créer.guideStatut.autoEntrepreneur}>
|
||||
<AutoEntrepreneur />
|
||||
</Route>
|
||||
<Route path={sitePaths.créer.guideStatut.multipleAssociates}>
|
||||
<NumberOfAssociate />
|
||||
</Route>
|
||||
<Route path={sitePaths.créer.guideStatut.minorityDirector}>
|
||||
<MinorityDirector />
|
||||
</Route>
|
||||
<Route path={sitePaths.créer.guideStatut.liste}>
|
||||
<PickLegalStatus />
|
||||
</Route>
|
||||
</Switch>
|
||||
</Animate.fromBottom>
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
/* @flow */
|
||||
import { T } from 'Components'
|
||||
import Animate from 'Components/ui/animate'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import React, { useContext } from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
|
@ -8,21 +6,22 @@ import { useTranslation } from 'react-i18next'
|
|||
import { useSelector } from 'react-redux'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { nextQuestionUrlSelector } from 'Selectors/companyStatusSelectors'
|
||||
import Animate from 'Ui/animate'
|
||||
import créerSvg from './créer.svg'
|
||||
|
||||
export default function Créer() {
|
||||
const { t } = useTranslation()
|
||||
const sitePaths = useContext(SitePathsContext);
|
||||
const nextQuestionUrl = useSelector(state => nextQuestionUrlSelector(state, { sitePaths }));
|
||||
const guideAlreadyStarted = useSelector(state => !!Object.keys(state.inFranceApp.companyLegalStatus)
|
||||
.length);
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const nextQuestionUrl = useSelector(state =>
|
||||
nextQuestionUrlSelector(state, { sitePaths })
|
||||
)
|
||||
const guideAlreadyStarted = useSelector<any, any>(
|
||||
state => !!Object.keys(state.inFranceApp.companyLegalStatus).length
|
||||
)
|
||||
return (
|
||||
<Animate.fromBottom>
|
||||
<Helmet>
|
||||
<title>{t(
|
||||
'créer.titre',
|
||||
'Créer une entreprise'
|
||||
)}</title>
|
||||
<title>{t('créer.titre', 'Créer une entreprise')}</title>
|
||||
</Helmet>
|
||||
|
||||
<h1>
|
||||
|
@ -30,18 +29,30 @@ export default function Créer() {
|
|||
</h1>
|
||||
<div css="display: flex; align-items: flex-start; justify-content: space-between">
|
||||
<div>
|
||||
|
||||
<p className='ui__ lead'>
|
||||
<p className="ui__ lead">
|
||||
<T k="créer.description">
|
||||
Avant d'entamer les démarches administratives pour créer votre entreprise, vous devez choisir un statut juridique adapté à votre activité
|
||||
Avant d'entamer les démarches administratives pour créer votre
|
||||
entreprise, vous devez choisir un statut juridique adapté à votre
|
||||
activité
|
||||
</T>
|
||||
</p>
|
||||
<Link
|
||||
className="ui__ button plain cta"
|
||||
to={guideAlreadyStarted && nextQuestionUrl ? nextQuestionUrl : sitePaths.créer.guideStatut.multipleAssociates}>
|
||||
{!guideAlreadyStarted ? t('créer.cta.default', 'Trouver le bon statut') : t('créer.cta.continue', 'Continuer le guide')}
|
||||
to={
|
||||
guideAlreadyStarted && nextQuestionUrl
|
||||
? nextQuestionUrl
|
||||
: sitePaths.créer.guideStatut.multipleAssociates
|
||||
}>
|
||||
{!guideAlreadyStarted
|
||||
? t('créer.cta.default', 'Trouver le bon statut')
|
||||
: t('créer.cta.continue', 'Continuer le guide')}
|
||||
</Link>
|
||||
<p className="ui__ notice"><T k="créer.warningPL">Le cas des professions libérales réglementées n'est pas encore traité</T></p>
|
||||
<p className="ui__ notice">
|
||||
<T k="créer.warningPL">
|
||||
Le cas des professions libérales réglementées n'est pas encore
|
||||
traité
|
||||
</T>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<img
|
||||
|
@ -50,7 +61,9 @@ export default function Créer() {
|
|||
css="margin-left: 3rem; max-width: 15rem; transform: translateX(2rem) scale(1.4);"
|
||||
/>
|
||||
</div>
|
||||
<h2><T>Ressources utiles</T></h2>
|
||||
<h2>
|
||||
<T>Ressources utiles</T>
|
||||
</h2>
|
||||
<div
|
||||
css={`
|
||||
display: flex;
|
||||
|
@ -66,19 +79,23 @@ export default function Créer() {
|
|||
<T k="créer.ressources.listeStatuts">
|
||||
<p>Liste des statuts juridiques </p>
|
||||
<small>
|
||||
Vous savez déjà quel statut choisir ? Accédez directement à la liste des démarches associées
|
||||
</small>
|
||||
Vous savez déjà quel statut choisir ? Accédez directement à la
|
||||
liste des démarches associées
|
||||
</small>
|
||||
</T>
|
||||
</Link>
|
||||
<Link
|
||||
className="ui__ interactive card button-choice lighter-bg"
|
||||
to={{ pathname: sitePaths.simulateurs.comparaison, state: { fromCréer: true } }}>
|
||||
to={{
|
||||
pathname: sitePaths.simulateurs.comparaison,
|
||||
state: { fromCréer: true }
|
||||
}}>
|
||||
<T k="créer.ressources.comparaison">
|
||||
|
||||
<p>Comparateur de régimes</p>
|
||||
<small>
|
||||
Indépendant, assimilé-salarié ou auto-entrepreneur ? Calculez les différences en terme de revenus, cotisations, retraite, etc
|
||||
</small>
|
||||
Indépendant, assimilé-salarié ou auto-entrepreneur ? Calculez les
|
||||
différences en terme de revenus, cotisations, retraite, etc
|
||||
</small>
|
||||
</T>
|
||||
</Link>
|
||||
|
||||
|
@ -86,15 +103,14 @@ export default function Créer() {
|
|||
className="ui__ interactive card button-choice lighter-bg"
|
||||
to={sitePaths.créer['auto-entrepreneur']}>
|
||||
<T k="créer.ressources.autoEntrepreneur">
|
||||
|
||||
<p>Démarche auto-entrepreneur</p>
|
||||
<small>
|
||||
Vous souhaitez devenir auto-entrepreneur ? Découvrez les étapes pour bien démarrer votre activité
|
||||
</small>
|
||||
Vous souhaitez devenir auto-entrepreneur ? Découvrez les étapes
|
||||
pour bien démarrer votre activité
|
||||
</small>
|
||||
</T>
|
||||
</Link>
|
||||
</div>
|
||||
</Animate.fromBottom >
|
||||
</Animate.fromBottom>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
/* @flow */
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { React, T } from 'Components'
|
||||
import type { LegalStatus } from 'Selectors/companyStatusSelectors'
|
||||
import { T } from 'Components'
|
||||
import React from 'react'
|
||||
import { LegalStatus } from 'Selectors/companyStatusSelectors'
|
||||
type Props = {
|
||||
StatutDescription: LegalStatus
|
||||
statut: LegalStatus
|
||||
}
|
||||
|
||||
const StatutDescription = ({ statut }: Props) =>
|
|
@ -1,43 +0,0 @@
|
|||
import { ScrollToTop } from 'Components/utils/Scroll';
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths';
|
||||
import React, { useContext } from 'react';
|
||||
import { Route, Switch } from 'react-router';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { LANDING_LEGAL_STATUS_LIST } from '../../sitePaths';
|
||||
import AfterRegistration from './AfterRegistration';
|
||||
import CreationChecklist from './CreationChecklist';
|
||||
import GuideStatut from './GuideStatut';
|
||||
import Home from './Home';
|
||||
|
||||
|
||||
export default function CreateMyCompany() {
|
||||
const sitePaths = useContext(SitePathsContext);
|
||||
const location = useLocation()
|
||||
return (
|
||||
<>
|
||||
<ScrollToTop key={location.pathname} />
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path={sitePaths.créer.index}
|
||||
component={Home}
|
||||
/>
|
||||
{LANDING_LEGAL_STATUS_LIST.map(statut => (
|
||||
<Route path={sitePaths.créer[statut]} key={statut} >
|
||||
<CreationChecklist statut={statut} />
|
||||
</Route>
|
||||
))
|
||||
}
|
||||
<Route
|
||||
path={sitePaths.créer.après}
|
||||
component={AfterRegistration}
|
||||
/>
|
||||
<Route
|
||||
path={sitePaths.créer.guideStatut.index}
|
||||
component={GuideStatut}
|
||||
/>
|
||||
</Switch>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
import { ScrollToTop } from 'Components/utils/Scroll'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import React, { useContext } from 'react'
|
||||
import { Route, Switch } from 'react-router'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { LANDING_LEGAL_STATUS_LIST } from '../../sitePaths'
|
||||
import AfterRegistration from './AfterRegistration'
|
||||
import CreationChecklist from './CreationChecklist'
|
||||
import GuideStatut from './GuideStatut'
|
||||
import Home from './Home'
|
||||
|
||||
export default function CreateMyCompany() {
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const location = useLocation()
|
||||
return (
|
||||
<>
|
||||
<ScrollToTop key={location.pathname} />
|
||||
<Switch>
|
||||
<Route exact path={sitePaths.créer.index} component={Home} />
|
||||
{LANDING_LEGAL_STATUS_LIST.map(statut => (
|
||||
<Route path={sitePaths.créer[statut]} key={statut}>
|
||||
<CreationChecklist statut={statut} />
|
||||
</Route>
|
||||
))}
|
||||
<Route path={sitePaths.créer.après} component={AfterRegistration} />
|
||||
<Route
|
||||
path={sitePaths.créer.guideStatut.index}
|
||||
component={GuideStatut}
|
||||
/>
|
||||
</Switch>
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
/* @flow */
|
||||
|
||||
import withColours, { ThemeColoursProvider } from 'Components/utils/withColours'
|
||||
import React, { Suspense, useState } from 'react'
|
|
@ -1,10 +1,10 @@
|
|||
// Page listing the engine's currently implemented mecanisms and their tests
|
||||
import { React, T } from 'Components'
|
||||
import withColours from 'Components/utils/withColours'
|
||||
import { T } from 'Components'
|
||||
import { ThemeColoursContext } from 'Components/utils/withColours'
|
||||
import { analyseMany } from 'Engine/traverse'
|
||||
import { compose } from 'ramda'
|
||||
import React, { useContext } from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { connect } from 'react-redux'
|
||||
import { useSelector } from 'react-redux'
|
||||
import examples from 'Règles/cas-types.yaml'
|
||||
import {
|
||||
parsedRulesSelector,
|
||||
|
@ -28,13 +28,10 @@ export default function ExampleSituations() {
|
|||
)
|
||||
}
|
||||
|
||||
const Example = compose(
|
||||
connect(state => ({
|
||||
defaults: ruleDefaultsSelector(state),
|
||||
parsedRules: parsedRulesSelector(state)
|
||||
})),
|
||||
withColours
|
||||
)(function Example({ ex: { nom, situation }, parsedRules, defaults, colours }) {
|
||||
const Example = function Example({ ex: { nom, situation } }) {
|
||||
const defaults = useSelector(ruleDefaultsSelector) as object
|
||||
const parsedRules = useSelector(parsedRulesSelector)
|
||||
const colours = useContext(ThemeColoursContext)
|
||||
let [total, net, netAprèsImpôts] = analyseMany(parsedRules, [
|
||||
'total',
|
||||
'net',
|
||||
|
@ -77,4 +74,4 @@ const Example = compose(
|
|||
</ul>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue