This commit is contained in:
2026-03-30 14:54:53 +02:00
parent 71773df0ee
commit bd24e921a7
16 changed files with 1240 additions and 683 deletions
+174
View File
@@ -0,0 +1,174 @@
<auth-panel>
<!-- Bouton connexion dans le header (utilisateur non connecté) -->
<div class="auth-header-btn" if={ !props.user }>
<button class="btn btn-auth" onclick={ ouvrirModale }>
<span class="auth-icon"></span> Connexion
</button>
</div>
<!-- Email + bouton déconnexion dans le header (utilisateur connecté) -->
<div class="auth-user-info" if={ props.user }>
<span class="auth-email">{ props.user.email }</span>
<button class="btn btn-auth-logout" onclick={ seDeconnecter }>Déconnexion</button>
</div>
<!-- Modale d'authentification -->
<div class="auth-modal-overlay" if={ state.visible } onclick={ cliquerFond }>
<div class="auth-modal">
<button class="auth-modal-close" onclick={ fermerModale }>✕</button>
<h2 class="auth-modal-title">{ state.titre }</h2>
<!-- Onglets Connexion / Inscription -->
<div class="auth-tabs">
<button class={ state.classBtnConnexion } onclick={ afficherConnexion }>
Connexion
</button>
<button class={ state.classBtnInscription } onclick={ afficherInscription }>
Inscription
</button>
</div>
<!-- Formulaire -->
<form onsubmit={ validerFormulaire } class="auth-form">
<div class="auth-field">
<label>Adresse e-mail</label>
<input
type="email"
name="email"
placeholder="exemple@email.com"
required
/>
</div>
<div class="auth-field">
<label>Mot de passe</label>
<input
type="password"
name="password"
placeholder="••••••••"
required
minlength="6"
/>
</div>
<!-- Message d'erreur -->
<div class="auth-error" if={ state.erreur }>
{ state.erreur }
</div>
<button type="submit" class="btn btn-primary auth-submit" disabled={ state.chargement }>
{ state.labelBouton }
</button>
</form>
</div>
</div>
<script>
export default {
state: {
visible: false,
mode: 'connexion',
chargement: false,
erreur: null,
titre: 'Connexion',
labelBouton: 'Se connecter',
classBtnConnexion: 'auth-tab active',
classBtnInscription: 'auth-tab'
},
ouvrirModale() {
this.update({ visible: true, erreur: null })
},
fermerModale() {
this.update({ visible: false, erreur: null })
},
// Fermer si l'utilisateur clique en dehors de la modale
cliquerFond(e) {
if (e.target === e.currentTarget) {
this.fermerModale()
}
},
afficherConnexion() {
this.update({
mode: 'connexion',
erreur: null,
titre: 'Connexion',
labelBouton: 'Se connecter',
classBtnConnexion: 'auth-tab active',
classBtnInscription: 'auth-tab'
})
},
afficherInscription() {
this.update({
mode: 'inscription',
erreur: null,
titre: 'Créer un compte',
labelBouton: 'Créer le compte',
classBtnConnexion: 'auth-tab',
classBtnInscription: 'auth-tab active'
})
},
async validerFormulaire(e) {
e.preventDefault()
var email = e.target.email.value.trim()
var password = e.target.password.value
var services = window.firebaseServices
this.update({ chargement: true, erreur: null })
try {
if (this.state.mode === 'inscription') {
await services.createAccount(email, password)
} else {
await services.login(email, password)
}
this.update({ visible: false, chargement: false })
this.props.onauth && this.props.onauth()
} catch (err) {
var messageErreur = 'Une erreur est survenue.'
if (err.code === 'auth/email-already-in-use') {
messageErreur = 'Cet e-mail est déjà utilisé.'
} else if (err.code === 'auth/invalid-email') {
messageErreur = 'Adresse e-mail invalide.'
} else if (err.code === 'auth/wrong-password' || err.code === 'auth/invalid-credential') {
messageErreur = 'E-mail ou mot de passe incorrect.'
} else if (err.code === 'auth/weak-password') {
messageErreur = 'Le mot de passe doit faire au moins 6 caractères.'
} else if (err.code === 'auth/user-not-found') {
messageErreur = 'Aucun compte trouvé avec cet e-mail.'
}
this.update({ chargement: false, erreur: messageErreur })
}
},
async seDeconnecter() {
try {
await window.firebaseServices.logout()
this.props.onlogout && this.props.onlogout()
} catch (err) {
console.error('Erreur déconnexion :', err)
}
}
}
</script>
</auth-panel>
+258 -123
View File
@@ -1,9 +1,7 @@
<detail-view>
<div if={ props.formation } class="detail-page">
<h2>Formation</h2>
<h1 class="formation-title">{ props.formation.etablissement } - { props.formation.nom }</h1>
<div class="formation-meta">
<p><b>Ville :</b> { props.formation.ville }</p>
<p><b>Département :</b> { props.formation.departement } { props.formation.departementLib }</p>
@@ -15,7 +13,6 @@
<div class="detail-grid">
<div>
<h2>Phase principale d'admission</h2>
<table class="detail-table">
<thead>
<tr>
@@ -68,7 +65,6 @@
<div class="timeline-box">
<h3>Vitesse de remplissage</h3>
<div class="timeline">
<div class="timeline-item">
<div class="timeline-dot"></div>
@@ -77,7 +73,6 @@
{ props.formation.pctDebutPhase }%
</div>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<div>
@@ -85,7 +80,6 @@
{ props.formation.pctDateBac }%
</div>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<div>
@@ -98,7 +92,6 @@
</div>
<h2>Phase complémentaire d'admission</h2>
<table class="detail-table">
<thead>
<tr>
@@ -148,146 +141,288 @@
</tbody>
</table>
<!-- ===================== GRAPHIQUES CHARTS.CSS ===================== -->
<!-- ==================== GRAPHIQUES CHARTS.CSS ==================== -->
<h2 class="charts-heading">Profil des admis</h2>
<div class="charts-section">
<!-- Graphique 1 : Répartition par type de bac -->
<div class="chart-wrapper">
<h3>Répartition par type de bac</h3>
<div id="chart-bac">
<table class="charts-css column show-labels show-primary-axis show-4-secondary-axes data-spacing-10">
<thead>
<tr>
<th scope="col">Type</th>
<th scope="col">Pourcentage</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Général</th>
<td style="--size: { safe(props.formation.pctGeneral) }; --color: #3d7fff;">
<span class="data">{ props.formation.pctGeneral || 0 }%</span>
</td>
</tr>
<tr>
<th scope="row">Techno</th>
<td style="--size: { safe(props.formation.pctTechno) }; --color: #f59e0b;">
<span class="data">{ props.formation.pctTechno || 0 }%</span>
</td>
</tr>
<tr>
<th scope="row">Pro</th>
<td style="--size: { safe(props.formation.pctPro) }; --color: #10b981;">
<span class="data">{ props.formation.pctPro || 0 }%</span>
</td>
</tr>
</tbody>
</table>
</div>
<div id="chart-bac" ref="graphBac"></div>
</div>
<!-- Graphique 2 : Mentions au bac -->
<div class="chart-wrapper">
<h3>Mentions au bac des admis</h3>
<div id="chart-mentions">
<table class="charts-css column show-labels show-primary-axis show-4-secondary-axes data-spacing-10">
<thead>
<tr>
<th scope="col">Mention</th>
<th scope="col">Pourcentage</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Sans</th>
<td style="--size: { safe(props.formation.pctSansMention) }; --color: #94a3b8;">
<span class="data">{ props.formation.pctSansMention || 0 }%</span>
</td>
</tr>
<tr>
<th scope="row">AB</th>
<td style="--size: { safe(props.formation.pctAB) }; --color: #60a5fa;">
<span class="data">{ props.formation.pctAB || 0 }%</span>
</td>
</tr>
<tr>
<th scope="row">Bien</th>
<td style="--size: { safe(props.formation.pctB) }; --color: #34d399;">
<span class="data">{ props.formation.pctB || 0 }%</span>
</td>
</tr>
<tr>
<th scope="row">TB</th>
<td style="--size: { safe(props.formation.pctTB) }; --color: #fbbf24;">
<span class="data">{ props.formation.pctTB || 0 }%</span>
</td>
</tr>
<tr>
<th scope="row">TB Féli.</th>
<td style="--size: { safe(props.formation.pctTBF) }; --color: #f472b6;">
<span class="data">{ props.formation.pctTBF || 0 }%</span>
</td>
</tr>
</tbody>
</table>
</div>
<div id="chart-mentions" ref="graphMentions"></div>
</div>
<!-- Graphique 3 : Profil sociologique (barres horizontales, pleine largeur) -->
<div class="chart-wrapper chart-full">
<h3>Profil sociologique</h3>
<div id="chart-profil">
<table class="charts-css bar show-labels show-primary-axis show-4-secondary-axes data-spacing-14">
<thead>
<tr>
<th scope="col">Catégorie</th>
<th scope="col">Pourcentage</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Femmes</th>
<td style="--size: { safe(props.formation.pctFemmes) }; --color: #a78bfa;">
<span class="data">{ props.formation.pctFemmes || 0 }%</span>
</td>
</tr>
<tr>
<th scope="row">Boursiers</th>
<td style="--size: { safe(props.formation.pctBoursiers) }; --color: #fb923c;">
<span class="data">{ props.formation.pctBoursiers || 0 }%</span>
</td>
</tr>
<tr>
<th scope="row">Néo-bac</th>
<td style="--size: { safe(props.formation.pctNeoBac) }; --color: #2dd4bf;">
<span class="data">{ props.formation.pctNeoBac || 0 }%</span>
</td>
</tr>
</tbody>
</table>
</div>
<div id="chart-profil" ref="graphProfil"></div>
</div>
</div>
<button onclick={ () => props.onback() } class="btn-retour">Retour à la liste</button>
<!-- ==================== ÉVOLUTION HISTORIQUE ==================== -->
<h2 class="charts-heading">Évolution depuis 2020</h2>
<div if={ state.chargementHistorique } class="message">
Chargement de l'historique...
</div>
<div if={ !state.chargementHistorique && state.historique.length === 0 } class="message">
Aucune donnée historique disponible pour cette formation.
</div>
<div class="charts-section" if={ state.historique.length > 0 }>
<div class="chart-wrapper">
<h3>Taux d'accès par année</h3>
<div id="chart-evolution-taux" ref="graphTaux"></div>
</div>
<div class="chart-wrapper">
<h3>Nombre de candidats et admis</h3>
<div id="chart-evolution-candidats" ref="graphCandidats"></div>
</div>
<div class="chart-wrapper chart-full">
<h3>Évolution des mentions au bac</h3>
<div ref="graphMentionsHist"></div>
</div>
</div>
<button onclick={ retourListe } class="btn-retour">Retour à la liste</button>
</div>
<script>
export default {
safe(val) {
if (val === null || val === undefined || isNaN(val)) return 0
state: {
historique: [],
chargementHistorique: false
},
onMounted() {
this.afficherGraphiques()
this.chargerHistorique()
},
onUpdated() {
this.afficherGraphiques()
if (this.state.historique.length > 0) {
this.afficherGraphiquesHistoriques()
}
},
// Retour à la liste des résultats
retourListe() {
this.props.onback()
},
// Limiter une valeur entre 0 et 1 pour Charts.css
limiterValeur(val) {
if (val === null || val === undefined || isNaN(val)) {
return 0
}
var v = val / 100
if (v > 1) return 1
if (v < 0) return 0
if (v > 1) {
return 1
}
if (v < 0) {
return 0
}
return Math.round(v * 100) / 100
},
afficherGraphiques() {
var f = this.props.formation
if (!f) {
return
}
var graphBac = this.$('[ref="graphBac"]')
var graphMentions = this.$('[ref="graphMentions"]')
var graphProfil = this.$('[ref="graphProfil"]')
if (graphBac) {
graphBac.innerHTML = this.construireGraphiqueColonnes([
{ label: 'Général', valeur: f.pctGeneral, couleur: '#3d7fff' },
{ label: 'Techno', valeur: f.pctTechno, couleur: '#f59e0b' },
{ label: 'Pro', valeur: f.pctPro, couleur: '#10b981' }
])
}
if (graphMentions) {
graphMentions.innerHTML = this.construireGraphiqueColonnes([
{ label: 'Sans', valeur: f.pctSansMention, couleur: '#94a3b8' },
{ label: 'AB', valeur: f.pctAB, couleur: '#60a5fa' },
{ label: 'Bien', valeur: f.pctB, couleur: '#34d399' },
{ label: 'TB', valeur: f.pctTB, couleur: '#fbbf24' },
{ label: 'TB Féli.', valeur: f.pctTBF, couleur: '#f472b6' }
])
}
if (graphProfil) {
graphProfil.innerHTML = this.construireGraphiqueBarres([
{ label: 'Femmes', valeur: f.pctFemmes, couleur: '#a78bfa' },
{ label: 'Boursiers', valeur: f.pctBoursiers, couleur: '#fb923c' },
{ label: 'Néo-bac', valeur: f.pctNeoBac, couleur: '#2dd4bf' }
])
}
},
async chargerHistorique() {
var f = this.props.formation
if (!f) {
return
}
var codUai = f.id.split('-')[0]
if (!codUai || !window.chargerHistoriqueFormation) {
return
}
this.update({ chargementHistorique: true })
try {
var historique = await window.chargerHistoriqueFormation(codUai, f.nom)
this.update({ historique: historique, chargementHistorique: false })
} catch (e) {
console.error('Erreur chargement historique :', e)
this.update({ historique: [], chargementHistorique: false })
}
},
afficherGraphiquesHistoriques() {
var historique = this.state.historique
if (!historique || historique.length === 0) {
return
}
var graphTaux = this.$('[ref="graphTaux"]')
var graphCandidats = this.$('[ref="graphCandidats"]')
var graphMentionsHist = this.$('[ref="graphMentionsHist"]')
// Graphique : taux d'accès par année
if (graphTaux) {
var elementsAnnee = []
for (var i = 0; i < historique.length; i++) {
elementsAnnee.push({
label: '' + historique[i].annee,
valeur: historique[i].tauxAcces,
couleur: '#1a936f'
})
}
graphTaux.innerHTML = this.construireGraphiqueColonnes(elementsAnnee)
}
// Graphique : candidats vs admis
if (graphCandidats) {
var maxCandidats = 0
for (var i = 0; i < historique.length; i++) {
if (historique[i].candidats > maxCandidats) {
maxCandidats = historique[i].candidats
}
}
var lignes = ''
for (var i = 0; i < historique.length; i++) {
var h = historique[i]
var tailleCand = 0
var tailleAdmis = 0
if (maxCandidats > 0) {
tailleCand = Math.round((h.candidats / maxCandidats) * 100) / 100
tailleAdmis = Math.round((h.admis / maxCandidats) * 100) / 100
}
lignes += '<tr>'
lignes += '<th scope="row">' + h.annee + '</th>'
lignes += '<td style="--size: ' + tailleCand + '; --color: #2a5298;">'
lignes += '<span class="data">' + h.candidats + '</span></td>'
lignes += '<td style="--size: ' + tailleAdmis + '; --color: #1a936f;">'
lignes += '<span class="data">' + h.admis + '</span></td>'
lignes += '</tr>'
}
graphCandidats.innerHTML = '<table class="charts-css column multiple show-labels show-primary-axis show-4-secondary-axes data-spacing-10">'
+ '<thead><tr><th scope="col">Année</th><th scope="col">Candidats</th><th scope="col">Admis</th></tr></thead>'
+ '<tbody>' + lignes + '</tbody></table>'
}
// Tableau : évolution des mentions
if (graphMentionsHist) {
var tableau = '<table class="detail-table">'
tableau += '<thead><tr><th>Année</th><th>Sans mention</th><th>AB</th><th>Bien</th><th>TB</th><th>TB Féli.</th></tr></thead>'
tableau += '<tbody>'
for (var i = 0; i < historique.length; i++) {
var h = historique[i]
tableau += '<tr>'
tableau += '<td><b>' + h.annee + '</b></td>'
tableau += '<td>' + h.pctSansMention + '%</td>'
tableau += '<td>' + h.pctAB + '%</td>'
tableau += '<td>' + h.pctB + '%</td>'
tableau += '<td>' + h.pctTB + '%</td>'
tableau += '<td>' + h.pctTBF + '%</td>'
tableau += '</tr>'
}
tableau += '</tbody></table>'
graphMentionsHist.innerHTML = tableau
}
},
construireGraphiqueColonnes(elements) {
var lignes = ''
for (var i = 0; i < elements.length; i++) {
var el = elements[i]
var taille = this.limiterValeur(el.valeur)
var affiche = el.valeur || 0
lignes += '<tr>'
lignes += '<th scope="row">' + el.label + '</th>'
lignes += '<td style="--size: ' + taille + '; --color: ' + el.couleur + ';">'
lignes += '<span class="data">' + affiche + '%</span>'
lignes += '</td></tr>'
}
return '<table class="charts-css column show-labels show-primary-axis show-4-secondary-axes data-spacing-10">'
+ '<thead><tr><th scope="col">Type</th><th scope="col">%</th></tr></thead>'
+ '<tbody>' + lignes + '</tbody></table>'
},
construireGraphiqueBarres(elements) {
var lignes = ''
for (var i = 0; i < elements.length; i++) {
var el = elements[i]
var taille = this.limiterValeur(el.valeur)
var affiche = el.valeur || 0
lignes += '<tr>'
lignes += '<th scope="row">' + el.label + '</th>'
lignes += '<td style="--size: ' + taille + '; --color: ' + el.couleur + ';">'
lignes += '<span class="data">' + affiche + '%</span>'
lignes += '</td></tr>'
}
return '<table class="charts-css bar show-labels show-primary-axis show-4-secondary-axes data-spacing-14">'
+ '<thead><tr><th scope="col">Catégorie</th><th scope="col">%</th></tr></thead>'
+ '<tbody>' + lignes + '</tbody></table>'
}
}
</script>
</detail-view>
+69 -49
View File
@@ -1,100 +1,120 @@
<map-view>
<div class="map-box">
<h3>Carte des formations</h3>
<div class="map" ref="map"></div>
<div class="map" ref="carte"></div>
</div>
<script>
export default {
onMounted() {
const mapElement = this.$('div[ref="map"]')
this.map = L.map(mapElement).setView([46.8, 2.5], 6)
onMounted() {
var divCarte = this.$('div[ref="carte"]')
this.carte = L.map(divCarte).setView([46.8, 2.5], 6)
this.groupeMarqueurs = L.layerGroup().addTo(this.carte)
this.marqueursIndex = {}
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; OpenStreetMap contributors'
}).addTo(this.map)
}).addTo(this.carte)
this.markersLayer = L.layerGroup().addTo(this.map)
this.markersById = {}
this.refreshMarkers()
this.afficherMarqueurs()
setTimeout(() => {
this.map.invalidateSize()
}, 100)
var composant = this
// Exposer globalement pour que result-list puisse appeler
window.mapFocus = (id) => {
this.focusFormation(id)
setTimeout(function() {
if (composant.carte) {
composant.carte.invalidateSize()
}
}, 200)
setTimeout(function() {
if (composant.carte) {
composant.carte.invalidateSize()
}
}, 500)
window.mapFocus = function(id) {
composant.centrerSurFormation(id)
}
},
onUpdated() {
this.refreshMarkers()
this.afficherMarqueurs()
if (this.map) {
setTimeout(() => {
this.map.invalidateSize()
}, 50)
var composant = this
if (this.carte) {
setTimeout(function() {
composant.carte.invalidateSize()
}, 100)
setTimeout(function() {
composant.carte.invalidateSize()
}, 300)
}
},
onBeforeUnmount() {
if (this.map) {
this.map.remove()
this.map = null
if (this.carte) {
this.carte.remove()
this.carte = null
}
window.mapFocus = null
},
refreshMarkers() {
if (!this.map || !this.markersLayer) {
afficherMarqueurs() {
if (!this.carte || !this.groupeMarqueurs) {
return
}
this.markersLayer.clearLayers()
this.markersById = {}
this.groupeMarqueurs.clearLayers()
this.marqueursIndex = {}
const points = []
const results = this.props.results || []
var coordonnees = []
var formations = this.props.results || []
for (let i = 0; i < results.length; i++) {
const f = results[i]
for (var i = 0; i < formations.length; i++) {
var f = formations[i]
if (f.latitude != null && f.longitude != null) {
const marker = L.marker([f.latitude, f.longitude])
marker.bindPopup('<b>' + f.nom + '</b><br>' + f.ville)
marker.addTo(this.markersLayer)
var marqueur = L.marker([f.latitude, f.longitude])
marqueur.bindPopup('<b>' + f.nom + '</b><br>' + f.ville)
marqueur.addTo(this.groupeMarqueurs)
this.markersById[f.id] = marker
points.push([f.latitude, f.longitude])
this.marqueursIndex[f.id] = marqueur
coordonnees.push([f.latitude, f.longitude])
}
}
if (points.length > 0) {
this.map.fitBounds(points, { padding: [20, 20] })
if (coordonnees.length > 0) {
this.carte.fitBounds(coordonnees, { padding: [20, 20] })
} else {
this.map.setView([46.8, 2.5], 6)
this.carte.setView([46.8, 2.5], 6)
}
},
focusFormation(id) {
var marker = this.markersById[id]
centrerSurFormation(id) {
var marqueur = this.marqueursIndex[id]
if (marker && this.map) {
// Scroll vers la carte
var mapEl = this.$('div[ref="map"]')
if (mapEl) {
mapEl.scrollIntoView({ behavior: 'smooth', block: 'center' })
if (marqueur && this.carte) {
var divCarte = this.$('div[ref="carte"]')
if (divCarte) {
divCarte.scrollIntoView({ behavior: 'smooth', block: 'center' })
}
// Zoom sur le marqueur et ouvrir le popup
setTimeout(() => {
this.map.setView(marker.getLatLng(), 13, { animate: true })
marker.openPopup()
var composant = this
setTimeout(function() {
composant.carte.invalidateSize()
composant.carte.setView(marqueur.getLatLng(), 13, { animate: true })
marqueur.openPopup()
}, 400)
}
}
}
</script>
</map-view>
+27 -11
View File
@@ -1,5 +1,6 @@
<result-list>
<div class="results">
<div class="message" if={ props.results.length === 0 && props.hasSearched && !props.loading }>
Aucun résultat trouvé
</div>
@@ -8,26 +9,41 @@
Chargement...
</div>
<div each={ (f, i) in props.results } key={ f.id } class="card">
<h3>{ f.nom }</h3>
<p><b>Établissement :</b> { f.etablissement }</p>
<p><b>Ville :</b> { f.ville } ({ f.departement })</p>
<p><b>Filière :</b> { f.filiere }</p>
<p><b>Taux d'accès :</b> { f.tauxAcces }%</p>
<div each={ (formation, index) in props.results } key={ formation.id } class="card">
<h3>{ formation.nom }</h3>
<p><b>Établissement :</b> { formation.etablissement }</p>
<p><b>Ville :</b> { formation.ville } ({ formation.departement })</p>
<p><b>Filière :</b> { formation.filiere }</p>
<p><b>Taux d'accès :</b> { formation.tauxAcces }%</p>
<button onclick={ () => props.ondetail(i) }>Voir détail</button>
<button onclick={ () => props.onselect(i) }>Ajouter à la sélection</button>
<button onclick={ () => locateOnMap(f) } if={ f.latitude != null }>Localiser</button>
<button onclick={ afficherDetail.bind(this, index) }>Voir détail</button>
<button onclick={ ajouterALaSelection.bind(this, index) }>Ajouter à la sélection</button>
<button onclick={ localiserSurCarte.bind(this, formation) } if={ formation.latitude != null }>Localiser</button>
</div>
</div>
<script>
export default {
locateOnMap(f) {
// Déclencher l'affichage du détail d'une formation
afficherDetail(index) {
this.props.ondetail(index)
},
// Ajouter une formation à la sélection
ajouterALaSelection(index) {
this.props.onselect(index)
},
// Centrer la carte sur la formation
localiserSurCarte(formation) {
if (window.mapFocus) {
window.mapFocus(f.id)
window.mapFocus(formation.id)
}
}
}
</script>
</result-list>
+24 -7
View File
@@ -12,7 +12,7 @@
<div class="filters-toggle">
<button class="btn btn-small btn-outline" onclick={ toggleFilters }>
{ state.showFilters ? 'Masquer les filtres' : 'Filtres avancés' }
{ state.labelFiltres }
</button>
</div>
@@ -91,6 +91,7 @@
state: {
query: '',
showFilters: false,
labelFiltres: 'Filtres avancés',
filiere: '',
selectivite: '',
region: '',
@@ -109,14 +110,30 @@
},
toggleFilters() {
this.update({ showFilters: !this.state.showFilters })
var visible = !this.state.showFilters
var label = visible ? 'Masquer les filtres' : 'Filtres avancés'
this.update({ showFilters: visible, labelFiltres: label })
},
updateFiliere(e) { this.update({ filiere: e.target.value }) },
updateSelectivite(e) { this.update({ selectivite: e.target.value }) },
updateRegion(e) { this.update({ region: e.target.value }) },
updateTauxMin(e) { this.update({ tauxMin: Number(e.target.value) }) },
updateTauxMax(e) { this.update({ tauxMax: Number(e.target.value) }) },
updateFiliere(e) {
this.update({ filiere: e.target.value })
},
updateSelectivite(e) {
this.update({ selectivite: e.target.value })
},
updateRegion(e) {
this.update({ region: e.target.value })
},
updateTauxMin(e) {
this.update({ tauxMin: Number(e.target.value) })
},
updateTauxMax(e) {
this.update({ tauxMax: Number(e.target.value) })
},
submitSearch() {
var filters = {