Claude m'a aidé tout au long du projet, mais la ca atteint des sommets. En meme temps, je suis en retard de fou !! Heuresuement quil explique mega bien sinon je ne comprendrais rien... et encore, je comprends deja assez peu les lignes que je rentre moi meme. trop de balises tuent les balises......

This commit is contained in:
camille
2026-03-29 12:54:47 +02:00
parent b26f3080f9
commit 7aa8912276
6 changed files with 516 additions and 13 deletions
@@ -0,0 +1,106 @@
<comparateur>
<h2>Comparateur de formations</h2>
<a href="#">← Retour à la recherche</a>
<a href="#/estimation">🎯 Estimer mes chances</a>
<div if={ state.formations.length === 0 }>
Aucune formation sélectionnée.
</div>
<div class="comparateur-grille">
<div each={ formation in state.formations } class="comparateur-colonne">
<h3>{ formation.fil_lib_voe_acc }</h3>
<h4>{ formation.g_ea_lib_vx }</h4>
<p>{ formation.ville_etab } ({ formation.dep_lib })</p>
<p>Taux d'accès : { formation.taux_acces_ens }%</p>
<p>Places : { formation.capa_fin }</p>
<p>Candidatures : { formation.voe_tot }</p>
<p>Admis : { formation.acc_tot }</p>
<p>Bac Général : { formation.pct_bg }%</p>
<p>Bac Techno : { formation.pct_bt }%</p>
<p>Bac Pro : { formation.pct_bp }%</p>
<p>Mention AB : { formation.pct_ab }%</p>
<p>Mention B : { formation.pct_b }%</p>
<p>Mention TB : { formation.pct_tb }%</p>
<button onclick={ () => retirerFormation(formation) }>
Retirer
</button>
</div>
</div>
<style>
.comparateur-grille
{
display: flex;
flex-direction: row;
gap: 20px;
}
.comparateur-colonne
{
border: 1px solid #ccc;
padding: 15px;
min-width: 200px;
}
</style>
<script>
export default
{
state:
{
formations: []
},
onMounted()
{
const saved = localStorage.getItem('comparateur')
if (saved)
{
this.update({ formations: JSON.parse(saved) })
}
},
retirerFormation(formation)
{
const formations = this.state.formations.filter(f => f.cod_aff_form !== formation.cod_aff_form)
localStorage.setItem('comparateur', JSON.stringify(formations))
this.update({ formations })
}
}
</script>
</comparateur>
File diff suppressed because one or more lines are too long
@@ -1,20 +1,16 @@
<ligne-resultat>
<div class="ligne-resultat">
<h3>{ props.formation.fil_lib_voe_acc } — { props.formation.g_ea_lib_vx }</h3>
<p>{ props.formation.ville_etab } ({ props.formation.dep_lib })</p>
<p>Taux d'accès : { props.formation.taux_acces_ens }%</p>
<a href={ '#/formation/' + props.formation.cod_aff_form }>Voir le détail</a>
<button onclick={ ajouterComparateur }>+ Comparer</button>
</div>
<style>
.ligne-resultat
.ligne-resultat
{
border: 1px solid #ccc;
padding: 10px;
@@ -22,5 +18,28 @@
}
</style>
<script>
export default
{
ajouterComparateur()
{
const saved = localStorage.getItem('comparateur')
const formations = saved ? JSON.parse(saved) : []
const dejaDedans = formations.some(f => f.cod_aff_form === this.props.formation.cod_aff_form)
if (!dejaDedans)
{
formations.push(this.props.formation)
localStorage.setItem('comparateur', JSON.stringify(formations))
}
window.location.hash = '#/comparateur'
}
}
</script>
</ligne-resultat>
+104 -1
View File
@@ -4,12 +4,34 @@
Chargement...
</div>
<div if={ state.formation }>
<h2>{ state.formation.fil_lib_voe_acc }</h2>
<h3>{ state.formation.g_ea_lib_vx }</h3>
<p>{ state.formation.ville_etab } ({ state.formation.dep_lib })</p>
<a href="#">← Retour à la recherche</a>
<button onclick={ ajouterComparateur }>+ Ajouter au comparateur</button>
<a href="#/comparateur">Voir le comparateur</a>
<h4>Phase d'admission</h4>
@@ -42,6 +64,15 @@
</table>
<h4>Profil des admis — Type de bac</h4>
<table class="charts-css bar show-labels" style="height: 150px; width: 600px;">
@@ -72,8 +103,20 @@
</table>
<h4>Profil des admis — Mentions</h4>
<table class="charts-css bar show-labels" style="height: 200px; width: 600px;">
<tbody>
@@ -116,6 +159,12 @@
</table>
<h4>Évolution du taux d'accès depuis 2020</h4>
<div if={ !state.evolution }>
@@ -135,10 +184,41 @@
</tbody>
</table>
<h4>Phase complémentaire</h4>
<div if={ state.formation.nb_voe_pc }>
<p>Candidatures en phase complémentaire : <b>{ state.formation.nb_voe_pc }</b></p>
<p>Admis en phase complémentaire : <b>{ state.formation.acc_pc }</b></p>
<p>Dont bac général : <b>{ state.formation.nb_voe_pc_bg }</b></p>
<p>Dont bac techno : <b>{ state.formation.nb_voe_pc_bt }</b></p>
<p>Dont bac pro : <b>{ state.formation.nb_voe_pc_bp }</b></p>
</div>
<div if={ !state.formation.nb_voe_pc }>
Pas de phase complémentaire pour cette formation.
</div>
</div>
<style>
@@ -185,12 +265,14 @@
export default
{
state:
{
formation: null,
evolution: null
},
async onMounted()
{
const id = this.props.id
@@ -199,9 +281,30 @@
const evolution = await recupereEvolutionFormation(id)
this.update({ evolution })
},
ajouterComparateur()
{
const saved = localStorage.getItem('comparateur')
const formations = saved ? JSON.parse(saved) : []
const dejaDedans = formations.some(f => f.cod_aff_form === this.state.formation.cod_aff_form)
if (!dejaDedans)
{
formations.push(this.state.formation)
localStorage.setItem('comparateur', JSON.stringify(formations))
}
window.location.hash = '#/comparateur'
}
}
</script>
</page-detail>
+20 -5
View File
@@ -1,29 +1,44 @@
import { component, unmount } from 'riot'
import App from './components/app.riot'
import PageDetail from './components/page-detail.riot'
import Comparateur from './components/comparateur.riot'
import 'chart.css'
import './style.css'
import EstimationChances from './components/estimation-chances.riot'
const app = document.getElementById('app')
let currentComponent = null
function navigate()
function navigate()
{
const hash = window.location.hash
if (currentComponent)
if (currentComponent)
{
unmount(app, true)
}
if (hash.startsWith('#/formation/'))
if (hash.startsWith('#/formation/'))
{
const id = hash.replace('#/formation/', '')
currentComponent = component(PageDetail)(app, { id })
}
else
}
else if (hash === '#/comparateur')
{
currentComponent = component(Comparateur)(app)
}
else if (hash === '#/estimation')
{
currentComponent = component(EstimationChances)(app)
}
else
{
currentComponent = component(App)(app)
}
}
window.addEventListener('hashchange', navigate)
+128
View File
@@ -0,0 +1,128 @@
*
{
box-sizing: border-box;
margin: 0;
padding: 0;
}
body
{
background-color: #1a1a2e;
color: #e0e0e0;
font-family: 'Segoe UI', sans-serif;
padding: 20px;
}
h1, h2, h3, h4
{
color: #e94560;
margin-bottom: 10px;
}
a
{
color: #0f3460;
background-color: #e94560;
padding: 5px 10px;
border-radius: 5px;
text-decoration: none;
display: inline-block;
margin: 5px 0;
}
a:hover
{
background-color: #c73652;
}
button
{
background-color: #0f3460;
color: #e0e0e0;
border: none;
padding: 8px 15px;
border-radius: 5px;
cursor: pointer;
margin: 5px 0;
}
button:hover
{
background-color: #16213e;
}
input, select
{
background-color: #16213e;
color: #e0e0e0;
border: 1px solid #e94560;
padding: 8px;
border-radius: 5px;
width: 100%;
}
.ligne-resultat
{
background-color: #16213e;
border: 1px solid #0f3460;
padding: 15px;
margin: 8px 0;
border-radius: 8px;
}
.ligne-resultat:hover
{
border-color: #e94560;
}
.comparateur-grille
{
display: flex;
flex-direction: row;
gap: 20px;
overflow-x: auto;
}
.comparateur-colonne
{
background-color: #16213e;
border: 1px solid #0f3460;
padding: 15px;
min-width: 250px;
border-radius: 8px;
}
.formulaire
{
background-color: #16213e;
padding: 20px;
border-radius: 8px;
max-width: 400px;
margin: 20px 0;
}
.estimation-ligne
{
background-color: #16213e;
border: 1px solid #0f3460;
padding: 15px;
margin: 10px 0;
border-radius: 8px;
}
table
{
margin: 15px 0;
}
#carte
{
border-radius: 8px;
border: 2px solid #e94560;
}
p
{
margin: 5px 0;
line-height: 1.5;
}