Commit ab9c46fc authored by David Foucher's avatar David Foucher
Browse files

Merge branch 'new-simulator' into 'master'

New simulator

See merge request !45
parents 531eb5da 02b4b7dc
Pipeline #2879 passed with stage
in 1 minute and 28 seconds
<template>
<div id="Eligibilite">
<ul>
<li v-for="(props, id) in this.conditions" :key="id" :class="{passed: props.status, failed: !props.status}">
<span v-html="transformData(props.condition)"/>
<span v-if="props.children">
<eligibilite :conditions="props.children"/>
</span>
</li>
</ul>
</div>
</template>
<script>
import Eligibilite from './Eligibilite.vue';
export default {
name: 'Eligibilite',
props: ['conditions', 'schema'],
components: {
Eligibilite,
},
methods: {
transformData: function (data) {
return data
.replace(/Ou /g, '<span style="font-style: italic">&nbsp;Ou&nbsp; </span>')
.replace(/OU /g, '<span style="font-style: italic">&nbsp;OU&nbsp; </span>')
.replace(/, ou /g, '<span style="font-style: italic">&nbsp;, ou&nbsp; </span>')
.replace(/Et /g, '<span style="font-style: italic">&nbsp;Et&nbsp; </span>')
.replace(/ET /g, '<span style="font-style: italic">&nbsp;ET&nbsp; </span>')
.replace(/, et /g, '<span style="font-style: italic">&nbsp;, et&nbsp; </span>');
}
}
}
</script>
<style scoped>
.failed:before {
content: '✗';
color: crimson;
}
.passed:before {
content: '✔';
color: forestgreen;
}
li li {
padding-left: 1.5rem;
}
li ul, li.sub {
display: inline;
padding-left: 0;
}
.connective {
font-style: italic !important;
}
</style>
\ No newline at end of file
This diff is collapsed.
<template>
<div id="SimulateurContext">
<br>
<table class="table-responsive table table-striped table-hover">
<caption> Contexte de simulation </caption>
<thead>
<tr>
<th>Nom</th>
<th>Valeur</th>
</tr>
</thead>
<tbody>
<tr v-for="(value, key) in this.context" :key="key">
<td> {{ renderLabel(key) }} </td>
<td> {{ renderValue(key,value,schema[key]) }} </td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: 'SimulateurContext',
props: ['schema', 'context',],
data: function () {
return {
test: [],
}
},
methods: {
renderValue: function (key, value, schema_tmp) {
schema_tmp = schema_tmp || this.schema[key]
if (schema_tmp['type'] === 'array') return value.map(v => this.renderValue(key, v, schema_tmp['items'])).join(', ')
if (schema_tmp['type'] === "boolean") return value ? 'oui' : 'non'
if (schema_tmp['format'] === 'date') return (new Date(value * 1000)).toLocaleDateString()
if (schema_tmp['enum']) return schema_tmp === undefined ? schema_tmp['enum'][value]+' ('+value+')' : ''
return value
},
renderLabel: function (key) {
return this.schema[key]['label'].charAt(0).toUpperCase() + this.schema[key]['label'].slice(1)
}
}
}
</script>
<style scoped>
td {
width: 50%;
max-width:50%;
}
table{
width:100%;
table-layout:fixed;
}
</style>
<template>
<div id="SimulateurExplain">
<br>
<div class="filter">
<span v-for="(tag, i) in this.tags" :key="i" class="filter-tags label" :class="{eligible: tagsEligibles.includes(tag), selected: selectedTags.includes(tag)}" v-on:click="setFilter(tag)">
{{tag}}
</span>
</div>
<br>
<div>
<span v-if="this.showReinitFilterButton" v-on:click="initFilter();" class="btn main-button pull-right">Réinitialiser les filtres</span>
</div>
<br>
<br>
<ul>
<li v-for="(financement, financement_id) in this.financements" :key="financement_id" class="result" :class="{hide:showFinancement(financement)}">
<br>
<h5 :class="{passed: financement.eligible, failed: !financement.eligible}" data-toggle="collapse" :data-target="'#details_'+financement_id" aria-expanded="false" aria-controls="explain" style="cursor:pointer;" >{{ financement.intitule }}
<div class="pull-right">
<label v-for="(tag, tag_id) in financement.tags" :key="tag_id" class="label">{{ tag }}</label>
</div>
</h5>
<div :id="'details_'+financement_id" class="collapse">
<p><strong>Description</strong> {{ financement.description }}</p>
<p><strong>Démarches</strong> {{ financement.demarches }}</p>
<div v-if="financement.eligible">
<p><strong>Prise en charge</strong> {{ financement.prise_en_charge }}</p>
<p v-if="financement.prise_en_charge_texte"><strong>Prise en charge</strong> {{ financement.prise_en_charge_texte }}</p>
<p><strong>Plafond de prise en charge</strong> {{ financement.plafond_prise_en_charge }}</p>
<p><strong>Plafond de prix horaire</strong> {{ financement.plafond_prix_horaire }}</p>
<p><strong>Nombre d'heures prises en charge</strong> {{ financement.heures }}</p>
<p><strong>Rémunération</strong> {{ financement.remuneration }}</p>
<p v-if="financement.remuneration_texte"><strong>Rémunération</strong> {{ financement.remuneration_texte }}</p>
<p v-if="financement.fin_remuneration"><strong>Fin de la rémunération</strong> {{ renderValue('financement.fin_remuneration', financement.fin_remuneration,schema) }}</p>
<p v-if="financement.rff"><strong>RFF</strong> {{ financement.rff }}</p>
<p v-if="financement.debut_rff"><strong>Début de la RFF</strong> {{ renderValue('financement.debut_rff', financement.debut_rff,schema) }}</p>
<p v-if="financement.fin_rff"><strong>Fin de la RFF</strong> {{ renderValue('financement.fin_rff', financement.fin_rff,schema) }}</p>
<p v-if="financement.organisme"><strong>Organisme</strong> {{ financement.organisme.nom }}</p>
</div>
<p>
<strong>Règles de gestion</strong><br><br>
<eligibilite :conditions="financement.explain" :schema="schema"/>
</p>
</div>
<br>
</li>
</ul>
</div>
</template>
<script>
import Eligibilite from './Eligibilite.vue';
export default {
name: 'SimulateurExplain',
props: ['schema', 'financements', 'financements_eligibles'],
components: {
Eligibilite,
},
data : function () {
return {
tags: [],
tagsEligibles: [],
selectedTags : [],
showReinitFilterButton: [],
}
},
mounted : function () {
this.initFilter();
},
methods: {
initFilter : function () {
this.filteredFinancements = this.financements;
for (var i = 0; i < this.financements.length; i++) {
this.tags = this.tags.concat(this.financements[i]['tags']);
if(this.financements[i]['eligible']) this.tagsEligibles = this.tagsEligibles.concat(this.financements[i]['tags']);
}
if(this.tags) this.tags = [...new Set(this.tags)].sort()
if(this.tagsEligibles) this.tagsEligibles = [...new Set(this.tagsEligibles)]
this.selectedTags = this.tags
this.showReinitFilterButton=false;
},
setFilter: function (tag) {
var tag_array = [tag]
this.selectedTags=tag_array;
this.showReinitFilterButton = true;
this.filteredFinancements = this.filterFinancements(tag);
},
filterFinancements: function (tag) {
return this.financements.filter(financement => {
if (tag != "") {
//replace all accents characters in the search string by their non-accented equivalent
var searchWithoutAccents = tag.normalize('NFD').replace(/[\u0300-\u036f]/g, "")
//create a RegExp for the search string to be case-insensitive
var searchRegExp = new RegExp(searchWithoutAccents,'ig')
return this.filterable(financement.tags).match(searchRegExp);
}
return true
})
},
filterable: function (tags) {
//replace all accents characters in the search string by their non-accented equivalent
return "".concat(tags.join(",")).normalize('NFD').replace(/[\u0300-\u036f]/g, "");
},
showFinancement: function (financement) {
if (this.selectedTags != this.tags) {
console.log("hello");
for(var i = 0; i< financement.tags.length; i++) {
if (this.selectedTags.includes(financement.tags[i])) return false;
}
return true;
} else {
return !financement.eligible;
}
},
renderValue: function (key, value, schema_tmp) {
schema_tmp = schema_tmp || this.schema[key]
if (schema_tmp['type'] === 'array') return value.map(v => this.renderValue(key, v, schema_tmp['items'])).join(', ')
if (schema_tmp['type'] === "boolean") return value ? 'oui' : 'non'
if (schema_tmp['format'] === 'date') return (new Date(value * 1000)).toLocaleDateString()
if (schema_tmp['enum']) return schema_tmp === undefined ? schema_tmp['enum'][value]+' ('+value+')' : ''
return value
},
renderLabel: function (key) {
return this.schema[key]['label'].charAt(0).toUpperCase() + this.schema[key]['label'].slice(1)
}
}
}
</script>
<style scoped>
pre {
padding: 1rem;
border-radius: 5px;
border: solid 2px #CAD6E6;
background-color: #F1F1F1;
max-width: 1200px;
font-family: 'mono';
white-space: pre-wrap;
}
.results {
padding: 10px;
border-left: 1px solid #ddd;
}
.result {
border-bottom: 1px solid #eee;
}
.result.hide {
display: none;
}
.result.visible p {
display: block;
}
.result.visible {
border: 1px solid #eee;
padding: 5px;
}
.result h3 {
font-weight: normal;
}
.label {
color: white;
font-size: small;
display: inline-block;
background-color: slategray;
border-radius: 0.25em;
padding: 0.2em;
margin: 0.2em 0.2em;
cursor: pointer;
}
.filter-tags {
opacity: 0.5;
}
.selected {
opacity: 1 !important;
}
.filter .eligible {
background-color: forestgreen !important;
}
.filter .eligible {
background-color: forestgreen !important;
}
.filter .label {
background-color: crimson;
}
.failed:before {
content: '✗';
color: crimson;
}
.passed:before {
content: '✔';
color: forestgreen;
}
</style>
<template>
<div id="SimulateurResultats">
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>
Résultats de simulation de financement
<button v-on:click="newSimulation();" class="btn main-button-primary pull-right"><span class="mr-1">Nouvelle simulation</span><i class="ml-1 fas fa-redo"></i></button>
</h2>
</div>
</div>
<hr class="simulateur-horizontal-separator">
<div class="row">
<div class="col-md-12 text-center mb-3">
<h3>
<span v-if="this.financements_eligibles.length == 0">
Aucun financement n'est disponible pour ce profil
</span>
<span v-else>
Nous avons trouvé {{this.financements_eligibles.length }} financement<span v-if="this.financements_eligibles.length > 1">s</span> pour réaliser votre formation
</span>
</h3>
</div>
</div>
<div v-for="(financement, id) in this.financements_eligibles" :key="id" class="mb-5">
<div id="financements" class="row">
<div class="col-md-12 col-sm-12 droits">
<div data-type="FORMATION FINANCEE" class="row">
<div class="col-md-8 block-description">
<div class="row mt-3">
<div class="col-md-12">
<h3 class="financement">{{ financement.intitule }}</h3>
</div>
</div>
<div class="row explication">
<div class="col-md-12">
<div class="row">
<div class="col-md-12">
<strong>Je souhaite bénéficier de ce financement :</strong><br/>
{{ financement.demarches }}
<a rel="nofollow noopener noreferrer" target="_blank" href="https://www.moncompteactivite.gouv.fr">moncompteactivite.gouv.fr</a><br/>
</div>
</div>
<div class="row explication">
<div class="col-md-12">
<span class="savoir-plus" data-toggle="collapse" :data-target="'#more-explication-'+id" aria-expanded="false" aria-controls="moreexplication">
<strong style="cursor:pointer; text-decoration:underline">En savoir plus&nbsp;</strong><strong>&gt;</strong>
</span>
</div>
</div>
<div class="row collapse" :id="'more-explication-'+id">
<div class="col-md-12">
{{ financement.description }}
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4 block-cout-remu">
<div class="mt-3">
<div class="cout"></div>
<div class="priseencharge remu">
<strong>Prise en charge</strong><br/>
{{ financement.prise_en_charge_texte }}
</div>
<div v-if="financement.plafond_prise_en_charge != 0" class="plafondpriseencharge remu">
<strong>Plafond de prise en charge</strong><br/>
{{ financement.plafond_prise_en_charge}}
</div>
<div class="remu">
<strong>Rémunération mensuelle</strong>
<br/>
<span v-if="financement.remuneration == 0">
Vous ne percevez pas de rémunération pendant la formation
</span>
<span v-else>
{{ financement.remuneration }}
</span>
</div>
<div class="remu"></div>
<div class="organisme remu">
</div>
<div class="aides-a-la-formation">
<a rel="noopener noreferrer" href="https://clara.pole-emploi.fr/aides/detail/aides-a-la-formation" target="_blank" style="color:blue;">Aides possibles à la formation</a>
</div>
</div>
</div>
</div>
</div>
</div>
<hr class="simulateur-horizontal-separator">
</div>
</div>
<div id="explainCollapseGroup">
<div class="row" id="explainButtonsGroup">
<div class="col-md-4">
<span class="ml-5" data-toggle="collapse" data-target="#scenario" aria-expanded="false" aria-controls="scenario" style="cursor:pointer;">
<button class="btn main-button-primary">Voir le scénario de simulation</button>
</span>
</div>
<div class="col-md-4">
<span class="ml-5" data-toggle="collapse" data-target="#context" aria-expanded="false" aria-controls="context" style="cursor:pointer;">
<button class="btn main-button-primary">Voir le contexte de simulation</button>
</span>
</div>
<div class="col-md-4">
<span class="ml-5" data-toggle="collapse" data-target="#explain" aria-expanded="false" aria-controls="explain" style="cursor:pointer;">
<button class="btn main-button-primary">Voir l'explication de simulation</button>
</span>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12">
<div id="scenario" data-parent="#explainCollapseGroup" class="collapse">
<SimulateurScenario :scenario="scenario"></SimulateurScenario>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div id="context" data-parent="#explainCollapseGroup" class="collapse">
<SimulateurContext :schema="schema" :context="context"></SimulateurContext>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div id="explain" data-parent="#explainCollapseGroup" class="collapse">
<SimulateurExplain :schema="schema" :financements="financements"></SimulateurExplain>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import SimulateurScenario from './SimulateurScenario.vue';
import SimulateurExplain from './SimulateurExplain.vue';
import SimulateurContext from './SimulateurContext.vue';
export default {
name: 'SimulateurResultats',
components: {
SimulateurScenario,
SimulateurExplain,
SimulateurContext
},
props: ['schema','financements', 'financements_eligibles', 'scenario', 'context', 'isLoading'],
methods: {
newSimulation : function () {
location.reload();
}
}
}
</script>
<style scoped>
#explainButtonsGroup {
position: -webkit-sticky; /* Safari */
position: sticky;
top: 0;
z-index:2;
background: white;
padding-bottom: 1.5rem;
padding-top: 1.5rem;
margin:0;
}
</style>
<template>
<div id="SimulateurScenario">
<br>
<pre v-html="this.transformed_scenario"/>
</div>
</template>
<script>
export default {
name: 'SimulateurScenario',
props: ['', 'scenario'],
computed : {
/*plainExplanation : function () {
for (var condition in this.explain) {
condition
}
}*/
transformed_scenario: function() {
return this.scenario
.replace(/Scénario: Donne-moi un nom/g, 'Scénario :\n')
.replace(/Si /g, '<span class="bold text-dark">Si </span>')
.replace(/ {4}Soit /g, '<span class="bold text-dark">Soit </span>')
.replace(/Quand /g, '<span class="bold text-dark">\nQuand </span>')
.replace(/Scénario: /g, '<span class="bold text-dark">Scénario: </span>')
.replace(/Ou /g, '<span class="bold text-dark">Ou </span>')
.replace(/, ou /g, '<span class="bold text-dark">, ou </span>')
.replace(/Et /g, '<span class="bold text-dark">Et </span>')
.replace(/, et /g, '<span class="bold text-dark">, et </span>')
.replace(/Alors /g, '<span class="bold text-dark">Alors </span>')
.replace(/vaut/g, '<u>vaut</u>')
.replace(/' {4}'/g,'&nbsp&nbsp')
.replace(/(«.+»)/g, "<span class=\"string\">$1</span>")
.replace(/,([^ ])/g, ", $1");
},
}
}
</script>
<style scoped>
pre {
padding: 1rem;
border-radius: 5px;
border: solid 2px #CAD6E6;
background-color: #F1F1F1;
max-width: 1200px;
font-family: 'mono';
white-space: pre-wrap;
}
</style>
<template>
<div id="SimulateurStepFive">
<div v-if="$parent.situation_inscrit == 1">
<div class="row">
<div class="col-md-12">
<h4>Situation particulière</h4>
</div>
</div>
<div class="row">
<div class="col-md-12 form-check">
<input v-model="$parent.situation_th" name="situation_th" id="situation_th" type="checkbox" class="form-check-input"/>&nbsp;
<label for="situation_th" class="label-after">Vous êtes reconnu travailleur handicapé</label>
</div>
</div>
<div class="row">
<div class="col-md-12 form-check">
<input v-model="$parent.situation_travailleurnonsal12dont6dans3ans" name="situation_travailleurnonsal12dont6dans3ans" id="situation_travailleurnonsal12dont6dans3ans" type="checkbox" class="form-check-input"/>&nbsp;
<label for="situation_travailleurnonsal12dont6dans3ans" class="label-after">
Vous êtes un travailleur non salarié et vous avez travaillé durant 12 mois, dont 6 mois consécutifs, dans les 3 ans précédant l’entrée en stage
</label>
</div>
</div>
<div class="row">
<div class="col-md-12 form-check">
<input v-model="$parent.situation_parentisole" name="situation_parentisole" id="situation_parentisole" type="checkbox" class="form-check-input"/>&nbsp;
<label for="situation_parentisole" class="label-after">Vous êtes parent isolé <span class="mini-info">*</span></label><br>
<div v-if="$parent.situation_parentisole" class="text-muted group-indent1">
* Personnes veuves, divorcées, séparées, abandonnées ou célibataires assumant seules la charge effective et permanente d’un ou de plusieurs enfants résidant en France et Femmes seules enceintes ayant effectué la déclaration de grossesse et les examens prénataux prévus par la loi
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 form-check">
<input v-model="$parent.situation_mere3enfants" name="situation_mere3enfants" id="situation_mere3enfants" type="checkbox" class="form-check-input"/>&nbsp;
<label for="situation_mere3enfants" class="label-after">Vous êtes mère de famille ayant eu au moins 3 enfants</label>
</div>
</div>
<div class="row">
<div class="col-md-12 form-check">
<input v-model="$parent.situation_divorceeveuve" name="situation_divorceeveuve" id="situation_divorceeveuve" type="checkbox" class="form-check-input"/>&nbsp;
<label for="situation_divorceeveuve" class="label-after">Vous êtes une femme divorcée, veuve, ou séparée judiciairement depuis moins de 3 ans</label>
</div>
</div>
<div class="row">
<div class="col-md-12 form-check">
<input v-model="$parent.situation_projetcreationentreprise" name="situation_projetcreationentreprise" id="situation_projetcreationentreprise" type="checkbox" class="form-check-input"/>&nbsp;
<label for="situation_projetcreationentreprise" class="label-after">Vous avez un projet de création d'entreprise qui nécessite cette formation</label>