simulateurs.yaml -> simulateurs à générer; refonte de l'introduction au [cdd]
parent
7e1cb62385
commit
a87c98fad3
|
@ -20,11 +20,11 @@
|
|||
"nearley": "^2.7.14",
|
||||
"npm": "^4.4.1",
|
||||
"ramda": "^0.23.0",
|
||||
"react": "^15.5.3",
|
||||
"react-dom": "^15.5.3",
|
||||
"react": "^15.5.4",
|
||||
"react-dom": "^15.5.4",
|
||||
"react-json-tree": "^0.10.0",
|
||||
"react-redux": "^5.0.3",
|
||||
"react-router": "^3.0.2",
|
||||
"react-router-dom": "^4.1.1",
|
||||
"reduce-reducers": "^0.1.2",
|
||||
"redux": "^3.6.0",
|
||||
"redux-form": "^6.4.3",
|
||||
|
|
|
@ -3,9 +3,19 @@
|
|||
- Variable: CDD
|
||||
attache: Salariat
|
||||
nom complet: CDD
|
||||
description: Contrat de travail pour lequel un employeur (société, entreprise) peut recruter directement un salarié pour une durée déterminée, car la cause de cette détermination, de la date ou échéance de fin de contrat est prévue explicitement par le Code du travail.
|
||||
description: Contrat de travail pour lequel un employeur peut recruter un salarié pour une durée déterminée, car la cause de cette détermination, de la date ou échéance de fin de contrat est prévue explicitement par le Code du travail.
|
||||
référence: https://fr.wikipedia.org/wiki/Contrat_de_travail_%C3%A0_dur%C3%A9e_d%C3%A9termin%C3%A9e_en_France
|
||||
# TODO: règle de type : il faut q'un motif et une durée soient sélectionnés pour qu'un contrat soit un CDD. Cela revient à dire que les variables CDD et motif sont obligatoires *dans le contexte* de leur attache
|
||||
# implique:
|
||||
# - emploi temporaire
|
||||
# - motif de recours
|
||||
|
||||
# - Variable: emploi temporaire
|
||||
# attache: Salariat . CDD
|
||||
# description: Le contrat n'a ni pour objet ni pour effet de pourvoir durablement un emploi lié à l'activité normale et permanente de l'entreprise.
|
||||
# références:
|
||||
# Code du travail - Article L1242-1 : https://www.legifrance.gouv.fr/affichCodeArticle.do;jsessionid=BF6DDD5AADF2010EFD3ED78B7CC00691.tpdila20v_1?idArticle=LEGIARTI000006901194&cidTexte=LEGITEXT000006072050&dateTexte=20100508
|
||||
|
||||
|
||||
- Variable: durée contrat
|
||||
attache: Salariat . CDD
|
||||
|
@ -22,6 +32,7 @@
|
|||
6 mois: 6
|
||||
3 mois: 3
|
||||
|
||||
|
||||
- Variable: motif # alias utilisé dans l'article L. 1242-1
|
||||
nom complet: motif de recours
|
||||
attache: Salariat . CDD
|
||||
|
@ -94,6 +105,10 @@
|
|||
références:
|
||||
service-public.fr: https://www.service-public.fr/professionnels-entreprises/vosdroits/F33693
|
||||
# concerne: emploi temporaire par nature
|
||||
notes: |
|
||||
- exprimer la justification du CDD d'usage au delà des secteurs.
|
||||
" l'usage exclut le recours au CDI en raison de la nature de l'activité et du caractère temporaire de ces emplois."
|
||||
+ interdictions explicites (grève et travaux dangereux)
|
||||
|
||||
formule-futur: #TODO intégrer ça dans le formulaire. Comment ?
|
||||
contrainte:
|
||||
|
@ -125,8 +140,8 @@
|
|||
titre: Événement de contrat
|
||||
question: Pensez-vous être confronté à l'un de ces événements au cours du contrat ?
|
||||
description: |
|
||||
Certains de ces événements impactent fortement les objectifs de la simulation.
|
||||
Par exemple, si le CDD est poursuivi en CDI, aucune majoration ou indemnité ne sera à verser !
|
||||
Certains de ces événements impactent fortement les résultats de la simulation, et peuvent donc la racourcir.
|
||||
Par exemple, dans l'hypothèse d'un CDD poursuivi en CDI, aucune majoration ou indemnité ne sera à verser !
|
||||
# au lieu de lister tous les cas, l'alternative est de simplement indiquer qu'ils sont exclusifs,
|
||||
# et les identifier dynamiquement par leur attribut "attache" :
|
||||
langue au chat possible: oui
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# Les simulateurs sont définis ici. Ils ont une variable comme objectif de calcul. Le moteur va analyser cette variable et son arbre pour produire un formulaire. Il sera exposé sur /simulateurs/:id
|
||||
|
||||
- titre: Simulateur CDD
|
||||
sous-titre: Découvrir le surcoût employeur du CDD par rapport au CDI
|
||||
id: cdd
|
||||
introduction:
|
||||
- icône: fa-handshake-o
|
||||
texte: Vous avez embauché ou vous réfléchissez à l'embauche d'un salarié en CDD.
|
||||
titre: Votre situation
|
||||
- icône: fa-balance-scale
|
||||
texte: Votre contrat ne peut donc avoir ni pour objet ni pour effet de pourvoir durablement un emploi lié à l'activité normale et permanente de l'entreprise.
|
||||
titre: Votre obligation
|
||||
|
||||
action:
|
||||
texte: Répondez à quelques questions pour estimer le montant des 4 obligations du CDD.
|
||||
bouton: C'est parti !
|
||||
objectif: surcoût CDD
|
||||
conclusion: |
|
||||
Nous n'avons plus de questions : votre simulation est terminée.
|
||||
|
||||
Cliquez sur les obligations en bas pour comprendre vos résultats.
|
||||
|
||||
Une remarque ? [Écrivez-nous](mailto:contact@embauche.beta.gouv.fr) !
|
||||
# <i
|
||||
# style={{cursor: 'pointer'}}
|
||||
# className="fa fa-envelope-o"
|
||||
# />
|
||||
|
||||
|
||||
# - titre: Du brut au net
|
|
@ -16,7 +16,7 @@ p {
|
|||
|
||||
|
||||
#conversation {
|
||||
margin: 1em auto;
|
||||
margin: 3em auto;
|
||||
font-size: 110%;
|
||||
line-height: normal;
|
||||
display: flex;
|
||||
|
@ -24,6 +24,7 @@ p {
|
|||
align-items: flex-start;
|
||||
min-height: 10em;
|
||||
max-width: 90%;
|
||||
max-height: 85%;
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,25 +35,11 @@ p {
|
|||
text-align: center;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#fin p:first-of-type {
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
#questions-answers {
|
||||
min-width: 60%;
|
||||
min-width: 55%;
|
||||
transition: width 1s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#sim #results {
|
||||
padding: .1em;
|
||||
background: #333350;
|
||||
box-shadow: 1px -7px 20px 2px #ccc;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
font-size: 80%;
|
||||
color: white;
|
||||
height: 12em;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#CDDIntro {
|
||||
#simulateurIntro {
|
||||
background: radial-gradient(ellipse at center, #4A89DC -160%,#333350 100%);
|
||||
color: white;
|
||||
position: fixed;
|
||||
|
@ -8,24 +8,24 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
#CDDIntro h1 {
|
||||
#simulateurIntro h1 {
|
||||
margin-top: 3%;
|
||||
text-align: center;
|
||||
font-size: 350%;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
#CDDIntro .subtitle {
|
||||
#simulateurIntro .subtitle {
|
||||
text-align: center;
|
||||
font-size: 110%;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
#CDDIntro #introduction {
|
||||
#simulateurIntro {
|
||||
margin-top: 4%;
|
||||
}
|
||||
|
||||
#CDDIntro p {
|
||||
#simulateurIntro p {
|
||||
font-size: 120%;
|
||||
color: white;
|
||||
opacity: .9;
|
||||
|
@ -33,19 +33,19 @@
|
|||
margin: 2em auto;
|
||||
}
|
||||
|
||||
#CDDIntro #introduction .insist {
|
||||
#simulateurIntro #introduction .insist {
|
||||
font-weight: 600;
|
||||
/*font-style: italic;*/
|
||||
}
|
||||
|
||||
|
||||
#CDDIntro #action {
|
||||
#simulateurIntro #action {
|
||||
color: white;
|
||||
margin-top: 3%;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
#CDDIntro #action button {
|
||||
#simulateurIntro #action button {
|
||||
color: inherit;
|
||||
background: #4A89DC;
|
||||
padding: .6em 1.2em;
|
||||
|
@ -55,7 +55,7 @@
|
|||
border: none;
|
||||
box-shadow: 0px 9px 14px 0px rgba(0, 0, 0, 0.1)
|
||||
}
|
||||
#CDDIntro #action button:hover {
|
||||
#simulateurIntro #action button:hover {
|
||||
box-shadow: none;
|
||||
opacity: .95;
|
||||
}
|
||||
|
|
|
@ -2,14 +2,14 @@ import React from 'react'
|
|||
import colours from './themeColours'
|
||||
import PageTypeIcon from './PageTypeIcon'
|
||||
import './CDDIntro.css'
|
||||
import {Link} from 'react-router'
|
||||
import {Link} from 'react-router-dom'
|
||||
|
||||
export default () => (
|
||||
<div id="CDDIntro">
|
||||
<PageTypeIcon type="simulation" />
|
||||
<h1>Simulateur CDD</h1>
|
||||
<div className="subtitle">
|
||||
Découvrir le surcoût pour l'employeur du CDD par rapport au CDI
|
||||
Découvrir le surcoût employeur du CDD par rapport au CDI
|
||||
</div>
|
||||
<section id="introduction">
|
||||
<p>
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
import React from 'react'
|
||||
|
||||
export default () =>
|
||||
<div style={{color: '#333350', margin: '15% auto', width: '20em', textAlign: 'center'}}>
|
||||
<p style={{fontWeight: 'bold'}}>
|
||||
Pour nous écrire : contact@embauche.beta.gouv.fr
|
||||
</p>
|
||||
{/* TODO: credits for the image to add: https://thenounproject.com/search/?q=post+card&i=715677 */}
|
||||
<img style={{margin: '3%'}} width="200px" src={require('../images/contact.png')} />
|
||||
</div>
|
|
@ -1,4 +1,23 @@
|
|||
|
||||
#results {
|
||||
padding: .1em;
|
||||
background: #333350;
|
||||
font-size: 80%;
|
||||
color: white;
|
||||
padding-top: 2em;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-top: 3px solid white;
|
||||
}
|
||||
#results.started {
|
||||
border: none;
|
||||
box-shadow: 1px -7px 20px 2px #ccc;
|
||||
}
|
||||
|
||||
|
||||
#results #results-titles {
|
||||
color: white;
|
||||
width: 18%;
|
||||
|
@ -42,6 +61,7 @@
|
|||
border-radius: 3px;
|
||||
white-space: nowrap;
|
||||
color: #333350;
|
||||
min-width: 15em;
|
||||
}
|
||||
#results li.irrelevant .rule-box {
|
||||
background: rgba(255, 255, 255, 0.65);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { Component } from 'react'
|
||||
import classNames from 'classnames'
|
||||
import {Link} from 'react-router'
|
||||
import {Link} from 'react-router-dom'
|
||||
import {connect} from 'react-redux'
|
||||
import R from 'ramda'
|
||||
import './Results.css'
|
||||
|
@ -10,21 +10,24 @@ let humanFigure = decimalDigits => value => fmt(value.toFixed(decimalDigits))
|
|||
|
||||
@connect(
|
||||
state => ({
|
||||
pointedOutObjectives: state.pointedOutObjectives
|
||||
pointedOutObjectives: state.pointedOutObjectives,
|
||||
analysedSituation: state.analysedSituation,
|
||||
conversationStarted: !R.isEmpty(state.form)
|
||||
})
|
||||
)
|
||||
export default class Results extends Component {
|
||||
render() {
|
||||
let {analysedSituation, pointedOutObjectives} = this.props
|
||||
let {analysedSituation, pointedOutObjectives, conversationStarted} = this.props
|
||||
// On travaille pour l'instant sur un objectif qui est une somme de plusieurs variables, et c'est ces variables que nous affichons comme résultats. D'où ce chemin :
|
||||
let explanation = R.path(['formule', 'explanation', 'explanation'])(analysedSituation)
|
||||
if (!explanation) return null
|
||||
|
||||
return (
|
||||
<section id="results">
|
||||
<section id="results" className={classNames({started: conversationStarted})}>
|
||||
<div id="results-titles">
|
||||
<h2>Vos obligations</h2>
|
||||
<div>Cliquez pour comprendre chaque calcul <i className="fa fa-hand-o-right" aria-hidden="true"></i></div>
|
||||
{conversationStarted &&
|
||||
<div>Cliquez pour comprendre chaque calcul <i className="fa fa-hand-o-right" aria-hidden="true"></i></div>}
|
||||
</div>
|
||||
<ul>
|
||||
{explanation.map(
|
||||
|
@ -47,12 +50,13 @@ export default class Results extends Component {
|
|||
{name}
|
||||
</div>
|
||||
<p>
|
||||
{irrelevant ?
|
||||
"Vous n'êtes pas concerné"
|
||||
: unsatisfied ?
|
||||
'En attente de vos réponses...'
|
||||
: <span className="figure">{humanFigure(2)(computedValue) + '€'}</span>
|
||||
}
|
||||
{conversationStarted && (
|
||||
irrelevant ?
|
||||
"Vous n'êtes pas concerné"
|
||||
: unsatisfied ?
|
||||
'En attente de vos réponses...'
|
||||
: <span className="figure">{humanFigure(2)(computedValue) + '€'}</span>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react'
|
||||
import {Link} from 'react-router-dom'
|
||||
|
||||
export default () =>
|
||||
<div style={{color: '#333350', margin: '15% auto', width: '15em', textAlign: 'center'}}>
|
||||
<h2>
|
||||
On peut facilement se perdre dans la législation...
|
||||
</h2>
|
||||
<Link to="/">
|
||||
{/* TODO: credits for the image to add: https://thenounproject.com/term/treasure-map/96666/ */}
|
||||
<img style={{margin: '3%'}} width="250px" src={require('../images/map-directions.png')} />
|
||||
Revenir en lieu sûr
|
||||
</Link>
|
||||
</div>
|
|
@ -1,5 +1,7 @@
|
|||
#rule {
|
||||
font-size: 110%;
|
||||
height: 100%;
|
||||
padding-bottom: 10%;
|
||||
}
|
||||
|
||||
#rule pre {
|
||||
|
@ -125,16 +127,23 @@
|
|||
margin-top: 3em;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dictionaryWrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.dictionaryPanelWrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255, 255, 255, 0.86);
|
||||
z-index: 1;
|
||||
}
|
||||
.dictionaryPanel {
|
||||
background: white;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
width: 33%;
|
||||
border: 1px dashed #aaa;
|
||||
border: 2px solid #333350;
|
||||
margin: 1em;
|
||||
padding: 0em 1.5em;
|
||||
min-height: 6em;
|
||||
|
|
|
@ -36,7 +36,7 @@ export default class Rule extends Component {
|
|||
}
|
||||
render() {
|
||||
let {
|
||||
params: {name},
|
||||
match: {params: {name}},
|
||||
analysedSituation,
|
||||
form
|
||||
} = this.props,
|
||||
|
@ -131,8 +131,13 @@ let AttachDictionary = dictionary => Decorated =>
|
|||
<div className="dictionaryWrapper">
|
||||
<Decorated ref={decorated => this.decorated = decorated} {...this.props} explain={this.explain}/>
|
||||
{explanation &&
|
||||
<div className="dictionaryPanel" dangerouslySetInnerHTML={{__html: this.renderExplanationMarkdown(explanation, term)}}>
|
||||
<div className="dictionaryPanelWrapper" onClick={() => this.setState({term: null, explanation: null})}>
|
||||
<div className="dictionaryPanel"
|
||||
onClick={e => {e.preventDefault(); e.stopPropagation()}}
|
||||
dangerouslySetInnerHTML={{__html: this.renderExplanationMarkdown(explanation, term)}}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
#sim {
|
||||
padding: 3em 0; /* For the warning message */
|
||||
background-color: #333350;
|
||||
/*background-image: radial-gradient(ellipse at center, white -160%, rgba(255,255,255,0) 100%);*/
|
||||
background-image: radial-gradient(ellipse at center, #4A89DC -160%,#333350 70%);
|
||||
color: white;
|
||||
transition: background-color .5s;
|
||||
height: 100%;
|
||||
padding-bottom: 10%;
|
||||
|
||||
}
|
||||
|
||||
#sim p {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#sim.started {
|
||||
background: none;
|
||||
background-color: white;
|
||||
color: #333350;
|
||||
}
|
||||
|
||||
|
||||
#sim > h1 {
|
||||
color: inherit;
|
||||
margin-top: 0;
|
||||
text-align: center;
|
||||
font-size: 350%;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
|
||||
#simSubtitle {
|
||||
margin-top: -.5em;
|
||||
text-align: center;
|
||||
font-size: 110%;
|
||||
font-weight: 300;
|
||||
margin-bottom: 2%;
|
||||
}
|
||||
|
||||
#sim .centered {
|
||||
width: 40%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#sim .intro {
|
||||
font-style: italic;
|
||||
font-size: 100%;
|
||||
margin-bottom: 4%;
|
||||
}
|
||||
#sim .intro > div {
|
||||
margin: 1em 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
#sim .intro i {
|
||||
opacity: .9;
|
||||
font-size: 250%;
|
||||
margin-right: .6em;
|
||||
}
|
||||
#sim .intro span {
|
||||
display: inline-block;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
#sim .remarks p {
|
||||
opacity: .9;
|
||||
padding-left: 1em;
|
||||
border-left: 10px solid rgba(255, 255, 255, 0.2);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#sim .action {
|
||||
margin-top: 5%;
|
||||
margin-bottom: 3%;
|
||||
}
|
||||
#sim .action p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#sim .action button {
|
||||
color: white;
|
||||
display: block;
|
||||
text-align: center;
|
||||
color: inherit;
|
||||
background: #4A89DC;
|
||||
padding: .6em 1.2em;
|
||||
font-size: 140%;
|
||||
margin: 1em auto;
|
||||
width: 12em;
|
||||
border: none;
|
||||
box-shadow: 0px 9px 14px 0px rgba(0, 0, 0, 0.1)
|
||||
}
|
||||
#sim .action:hover {
|
||||
box-shadow: none;
|
||||
opacity: .95;
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
import React, {Component} from 'react'
|
||||
import './CDD.css'
|
||||
import {reduxForm, formValueSelector} from 'redux-form'
|
||||
import {connect} from 'react-redux'
|
||||
import './conversation/conversation.css'
|
||||
import {START_CONVERSATION} from '../actions'
|
||||
import Aide from './Aide'
|
||||
import PageTypeIcon from './PageTypeIcon'
|
||||
import simulateurs from '../../règles/simulateurs.yaml'
|
||||
import R from 'ramda'
|
||||
import {Redirect, Link} from 'react-router-dom'
|
||||
import {createMarkdownDiv} from '../engine/marked'
|
||||
import './Simulateur.css'
|
||||
import classNames from 'classnames'
|
||||
let situationSelector = formValueSelector('conversation')
|
||||
|
||||
@reduxForm({form: 'conversation', destroyOnUnmount: false})
|
||||
@connect(
|
||||
state => ({
|
||||
situation: variableName => situationSelector(state, variableName),
|
||||
foldedSteps: state.foldedSteps,
|
||||
unfoldedSteps: state.unfoldedSteps,
|
||||
themeColours: state.themeColours,
|
||||
analysedSituation: state.analysedSituation,
|
||||
}),
|
||||
dispatch => ({
|
||||
startConversation: rootVariable => dispatch({type: START_CONVERSATION, rootVariable}),
|
||||
})
|
||||
)
|
||||
export default class extends React.Component {
|
||||
componentWillMount() {
|
||||
let {
|
||||
match: {
|
||||
params: {
|
||||
simulateurId
|
||||
}
|
||||
}
|
||||
} = this.props
|
||||
|
||||
this.simulateur = R.find(R.propEq('id', simulateurId))(simulateurs)
|
||||
|
||||
// C'est ici que la génération du formulaire, et donc la traversée des variables commence
|
||||
if (this.simulateur)
|
||||
this.props.startConversation(this.simulateur.objectif)
|
||||
}
|
||||
state = {
|
||||
started: null
|
||||
}
|
||||
render(){
|
||||
if (!this.simulateur) return <Redirect to="/404"/>
|
||||
|
||||
let
|
||||
{foldedSteps, unfoldedSteps, situation} = this.props,
|
||||
sim = path =>
|
||||
R.path(R.unless(R.is(Array), R.of)(path))(this.simulateur)
|
||||
,
|
||||
{started} = this.state
|
||||
|
||||
return (
|
||||
<div id="sim" className={classNames({started})}>
|
||||
<PageTypeIcon type="simulation" />
|
||||
<h1>{sim('titre')}</h1>
|
||||
<div id="simSubtitle">{sim('sous-titre')}</div>
|
||||
<div className="intro centered">
|
||||
{sim('introduction').map( ({icône, texte, titre}) =>
|
||||
<div key={titre}>
|
||||
<i title={titre} className={"fa "+icône} aria-hidden="true"></i>
|
||||
<span>
|
||||
{texte}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{
|
||||
// Tant que le bouton 'C'est parti' n'est pas cliqué, on affiche l'intro
|
||||
!this.state.started ?
|
||||
<div>
|
||||
<div className="action centered">
|
||||
<p>{sim(['action', 'texte'])}</p>
|
||||
<button onClick={() => this.setState({started: true})}>
|
||||
{sim(['action', 'bouton'])}
|
||||
</button>
|
||||
</div>
|
||||
<div className="remarks centered">
|
||||
<p>
|
||||
Pour simplifier, les résultats sont calculés par mois de contrat.
|
||||
</p>
|
||||
<p>
|
||||
N'hésitez pas à <Link to="/contact">nous écrire</Link> ! La loi française est complexe, car très ciblée. Nous pouvons la rendre plus transparente.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
: (
|
||||
<div>
|
||||
<div id="conversation">
|
||||
<div id="questions-answers">
|
||||
{ !R.isEmpty(foldedSteps) &&
|
||||
<div id="foldedSteps">
|
||||
{foldedSteps
|
||||
.map(step => (
|
||||
<step.component
|
||||
key={step.name}
|
||||
{...step}
|
||||
step={step}
|
||||
answer={situation(step.name)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
<div id="unfoldedSteps">
|
||||
{ !R.isEmpty(unfoldedSteps) && do {
|
||||
let step = R.head(unfoldedSteps)
|
||||
;<step.component
|
||||
key={step.name}
|
||||
{...step}
|
||||
step={step}
|
||||
unfolded={true}
|
||||
answer={situation(step.name)}
|
||||
/>
|
||||
}}
|
||||
</div>
|
||||
{unfoldedSteps.length == 0 &&
|
||||
<div id="fin">
|
||||
<img src={require('../images/fin.png')} />
|
||||
{createMarkdownDiv(sim('conclusion'))}
|
||||
</div>}
|
||||
</div>
|
||||
<Aide />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -8,8 +8,6 @@ import {START_CONVERSATION} from '../actions'
|
|||
import Aide from './Aide'
|
||||
import PageTypeIcon from './PageTypeIcon'
|
||||
|
||||
//TODO fusionner SimulationCDD & SimulationNet
|
||||
|
||||
let situationSelector = formValueSelector('conversation')
|
||||
|
||||
@reduxForm({form: 'conversation', destroyOnUnmount: false})
|
||||
|
@ -66,7 +64,11 @@ export default class CDD extends Component {
|
|||
<img src={require('../images/fin.png')} />
|
||||
<p>
|
||||
Nous n'avons plus de questions : votre simulation est terminée.
|
||||
</p><p>
|
||||
</p>
|
||||
<p>
|
||||
Cliquez sur les obligations en bas pour comprendre vos résultats.
|
||||
</p>
|
||||
<p>
|
||||
Une remarque ?
|
||||
<a href="mailto:contact@embauche.beta.gouv.fr">
|
||||
Écrivez-nous
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
border-radius: .2em;
|
||||
display: inline-block;
|
||||
margin-left: .8em;
|
||||
opacity: .4;
|
||||
opacity: .35;
|
||||
border: 1px solid transparent;
|
||||
cursor: pointer;
|
||||
vertical-align: baseline;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
.explicable:hover .icon {
|
||||
|
@ -15,7 +17,7 @@
|
|||
border-color: white;
|
||||
}
|
||||
.explicable.dark:hover .icon {
|
||||
border-color: #222;
|
||||
border-color: #333350;
|
||||
}
|
||||
|
||||
.explicable .icon:hover {
|
||||
|
@ -24,7 +26,7 @@
|
|||
color: #4A89DC;
|
||||
}
|
||||
.explicable.dark .icon:hover {
|
||||
background: #222;
|
||||
background: #333350;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
@ -34,6 +36,6 @@
|
|||
color: white;
|
||||
}
|
||||
.explicable.dark.explained .icon {
|
||||
background: #222;
|
||||
background: #333350;
|
||||
color: white;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,8 @@ export default class Explicable extends React.Component {
|
|||
<span
|
||||
className="icon"
|
||||
onClick={e => {e.preventDefault(); e.stopPropagation(); explain(name)}}>
|
||||
{ hover ? 'ℹ' : '•' }</span>
|
||||
<i className="fa fa-info" aria-hidden="true"></i>
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
}
|
||||
|
||||
.step-question {
|
||||
margin-bottom: 1em;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.step h1 {
|
||||
|
|
|
@ -2,9 +2,7 @@ import React, {Component} from 'react'
|
|||
|
||||
import { Provider } from 'react-redux'
|
||||
import DevTools from '../DevTools'
|
||||
import routes from '../routes'
|
||||
import {Router, browserHistory} from 'react-router'
|
||||
|
||||
import Layout from './Layout'
|
||||
|
||||
export default class App extends Component {
|
||||
render() {
|
||||
|
@ -12,7 +10,7 @@ export default class App extends Component {
|
|||
return (
|
||||
<Provider store={store}>
|
||||
<div>
|
||||
<Router routes={routes} history={browserHistory} />
|
||||
<Layout />
|
||||
<DevTools />
|
||||
</div>
|
||||
</Provider>
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
// App.dev without the redux DevTools
|
||||
import React, {Component} from 'react'
|
||||
|
||||
import { Provider } from 'react-redux'
|
||||
import routes from '../routes'
|
||||
import {Router} from 'react-router'
|
||||
import DevTools from '../DevTools'
|
||||
import Layout from './Layout'
|
||||
|
||||
export default class App extends Component {
|
||||
render() {
|
||||
const { store } = this.props
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<Router routes={routes} history={history} />
|
||||
<div>
|
||||
<Layout />
|
||||
</div>
|
||||
</Provider>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {Component} from 'react'
|
||||
import './Home.css'
|
||||
import {searchRules} from '../engine/rules.js'
|
||||
import {Link} from 'react-router'
|
||||
import {Link} from 'react-router-dom'
|
||||
import '../components/Rule.css'
|
||||
import R from 'ramda'
|
||||
|
||||
|
@ -60,11 +60,11 @@ export default class Home extends Component {
|
|||
<ul>
|
||||
<li key="cdd">
|
||||
<span className="simulateur">Surcoût du CDD</span>
|
||||
<Link to="/cdd-intro"><button>Essayer</button></Link>
|
||||
<Link to="/simulateurs/cdd"><button>Essayer</button></Link>
|
||||
</li>
|
||||
<li key="embauche">
|
||||
<span className="simulateur">Prix global de l'embauche</span>
|
||||
<Link><button className="disabled">Bientôt disponible</button></Link>
|
||||
<a href="#"><button className="disabled">Bientôt disponible</button></a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
body {
|
||||
font-family: 'Open Sans';
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#content {
|
||||
|
@ -13,6 +15,10 @@ body {
|
|||
top: 4.5%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 6% 3% 0;
|
||||
font-size: 250%;
|
||||
|
@ -31,6 +37,18 @@ h1 {
|
|||
text-align: center;
|
||||
z-index: 1000000;
|
||||
}
|
||||
#main {
|
||||
min-height: 100vh;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#ninetyPercent {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#page-type {
|
||||
display: inline-block;
|
||||
|
|
|
@ -1,27 +1,42 @@
|
|||
import React, { Component } from 'react'
|
||||
import './Layout.css'
|
||||
import './reset.css'
|
||||
import {Link} from 'react-router'
|
||||
import {Link, Route, BrowserRouter as Router, Switch} from 'react-router-dom'
|
||||
import Home from './Home'
|
||||
import Rule from '../components/Rule'
|
||||
import Route404 from '../components/Route404'
|
||||
import Contact from '../components/Contact'
|
||||
import Simulateur from '../components/Simulateur'
|
||||
import Results from '../components/Results'
|
||||
|
||||
export default class Layout extends Component {
|
||||
render() {
|
||||
return (<div>
|
||||
<div id="header">
|
||||
<div id="warning">
|
||||
Attention ! Tout le contenu de ce site est hautement expérimental.
|
||||
return (
|
||||
<Router>
|
||||
<div id="main">
|
||||
<div id="ninetyPercent">
|
||||
<div id="header">
|
||||
<div id="warning">
|
||||
Attention ! Ce site est expérimental.
|
||||
</div>
|
||||
{
|
||||
// this.props.location.pathname != '/' &&
|
||||
// <Link to="/">
|
||||
// <img id="site-logo" src={require('../images/logo.png')} />
|
||||
// </Link>
|
||||
}
|
||||
</div>
|
||||
<Switch>
|
||||
<Route exact path="/" component={Home}/>
|
||||
<Route path="/contact" component={Contact} />
|
||||
<Route path="/regle/:name" component={Rule} />
|
||||
<Route path="/simulateurs/:simulateurId" component={Simulateur} />
|
||||
<Route component={Route404} />
|
||||
</Switch>
|
||||
</div>
|
||||
<Results />
|
||||
</div>
|
||||
{
|
||||
this.props.location.pathname != '/' &&
|
||||
<Link to="/">
|
||||
<img id="site-logo" src={require('../images/logo.png')} />
|
||||
</Link>
|
||||
}
|
||||
</div>
|
||||
<div id="content">
|
||||
{this.props.children}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</Router>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ taux:
|
|||
|
||||
multiplication:
|
||||
description: |
|
||||
C'est une multiplication un peu améliorée, très utile pour exprimer les cotisations, souvent linéaires.
|
||||
C'est une multiplication un peu améliorée, très utile pour exprimer les cotisations.
|
||||
|
||||
Sa propriété `assiette` est multipliée par un pourcentage, `taux`, ou par un `facteur` quand ce nom est plus approprié.
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import marked from 'marked'
|
||||
import React from 'react'
|
||||
|
||||
let customMarked = new marked.Renderer()
|
||||
customMarked.link = ( href, title, text ) =>
|
||||
|
@ -7,4 +8,8 @@ marked.setOptions({
|
|||
renderer: customMarked
|
||||
})
|
||||
|
||||
export let createMarkdownDiv = markdown =>
|
||||
<div dangerouslySetInnerHTML={{__html: marked(markdown)}}></div>
|
||||
|
||||
|
||||
export default marked
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import R from 'ramda'
|
||||
import classNames from 'classnames'
|
||||
|
||||
let treatValue = data => console.log('data', data) ||
|
||||
let treatValue = data =>
|
||||
data == null
|
||||
? '?'
|
||||
: !isNaN(data) ? Math.round(+data) : data ? 'oui' : 'non'
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 100 125"
|
||||
enable-background="new 0 0 100 100"
|
||||
xml:space="preserve"
|
||||
id="svg12"
|
||||
sodipodi:docname="contact.svg"
|
||||
inkscape:version="0.92.1 r15371"><metadata
|
||||
id="metadata18"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs16" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1046"
|
||||
id="namedview14"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.888"
|
||||
inkscape:cx="-1.9067797"
|
||||
inkscape:cy="62.5"
|
||||
inkscape:window-x="122"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg12" /><path
|
||||
d="M93.1,35.5l-9.3-7v-9.6c0-2.5-2-4.5-4.5-4.5H65l-6.2-4.6c-5.2-3.9-12.4-3.9-17.6,0L35,14.4H20.7c-2.5,0-4.5,2-4.5,4.5v9.6 l-9.3,7c-1.2,0.9-2,2.4-2,3.9v48.9c0,2.7,2.2,4.9,4.9,4.9h80.3c2.7,0,4.9-2.2,4.9-4.9V39.4C95,37.8,94.3,36.4,93.1,35.5z M79.3,36.9 v6.2L50,65.1L20.7,43.1v-6.2v-18h58.5V36.9z"
|
||||
id="path2"
|
||||
style="fill:#333350;fill-opacity:1" /><rect
|
||||
x="27.5"
|
||||
y="24.6"
|
||||
width="45"
|
||||
height="6.8"
|
||||
id="rect4"
|
||||
style="fill:#4a89dc;fill-opacity:1" /><rect
|
||||
x="27.5"
|
||||
y="35.8"
|
||||
width="36"
|
||||
height="6.8"
|
||||
id="rect6"
|
||||
style="fill:#4a89dc;fill-opacity:1" /></svg>
|
After Width: | Height: | Size: 2.0 KiB |
|
@ -1,33 +0,0 @@
|
|||
import React from 'react'
|
||||
import { Route, IndexRoute, Link } from 'react-router'
|
||||
import Layout from './containers/Layout'
|
||||
import Home from './containers/Home'
|
||||
import Rule from './components/Rule'
|
||||
import SimulationCDD from './components/SimulationCDD'
|
||||
import SimulationNet from './components/SimulationNet'
|
||||
import CDDIntro from './components/CDDIntro'
|
||||
|
||||
|
||||
let RouteNotFound = () =>
|
||||
<div style={{color: '#333350', margin: '15% auto', width: '15em', textAlign: 'center'}}>
|
||||
<h2>
|
||||
On peut facilement se perdre dans la législation...
|
||||
</h2>
|
||||
<Link to="/">
|
||||
{/* TODO: credits for the image to add: https://thenounproject.com/term/treasure-map/96666/ */}
|
||||
<img style={{margin: '3%'}} width="250px" src={require('./images/map-directions.png')} />
|
||||
Revenir en lieu sûr
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
|
||||
export default (
|
||||
<Route path="/" component={Layout}>
|
||||
<Route path="regle/:name" component={Rule} />
|
||||
<Route path="cdd-intro" component={CDDIntro} />
|
||||
<Route path="cdd" component={SimulationCDD} />
|
||||
<Route path="net" component={SimulationNet} />
|
||||
<IndexRoute component={Home} />
|
||||
<Route path="*" component={RouteNotFound} />
|
||||
</Route>
|
||||
)
|
Loading…
Reference in New Issue