diff --git a/parcoursup/api.js b/parcoursup/api.js index a263180..20b2c65 100644 --- a/parcoursup/api.js +++ b/parcoursup/api.js @@ -1,19 +1,45 @@ -export function buildURL(query, limit = 20, offset = 0) { +export function buildURL(query, limit = 20, offset = 0, filters = {}) { let url = "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup/records?" url += "limit=" + limit url += "&offset=" + offset + var conditions = [] + if (query && query.trim() !== "") { - url += "&where=search(lib_for_voe_ins, '" + query + "')" + conditions.push("search(lib_for_voe_ins, '" + query + "')") + } + + if (filters.filiere && filters.filiere !== "") { + conditions.push("fili='" + filters.filiere + "'") + } + + if (filters.selectivite && filters.selectivite !== "") { + conditions.push("select_form='" + filters.selectivite + "'") + } + + if (filters.region && filters.region !== "") { + conditions.push("region_etab_aff='" + filters.region + "'") + } + + if (filters.tauxMin && filters.tauxMin > 0) { + conditions.push("taux_acces_ens>=" + filters.tauxMin) + } + + if (filters.tauxMax && filters.tauxMax < 100) { + conditions.push("taux_acces_ens<=" + filters.tauxMax) + } + + if (conditions.length > 0) { + url += "&where=" + conditions.join(" AND ") } return url } -export async function fetchFormations(query, limit = 20, offset = 0) { - const url = buildURL(query, limit, offset) +export async function fetchFormations(query, limit = 20, offset = 0, filters = {}) { + const url = buildURL(query, limit, offset, filters) const response = await fetch(url) if (!response.ok) { @@ -21,4 +47,66 @@ export async function fetchFormations(query, limit = 20, offset = 0) { } return await response.json() -} \ No newline at end of file +} + +export async function fetchFormationHistory(codUai, nomFormation) { + var datasets = { + 2020: "fr-esr-parcoursup_2020", + 2021: "fr-esr-parcoursup_2021", + 2022: "fr-esr-parcoursup_2022", + 2023: "fr-esr-parcoursup_2023", + 2024: "fr-esr-parcoursup_2024", + 2025: "fr-esr-parcoursup" + } + + var history = [] + var searchName = nomFormation.substring(0, 40).replace(/'/g, "\\'") + var years = [2020, 2021, 2022, 2023, 2024, 2025] + + for (var i = 0; i < years.length; i++) { + var year = years[i] + var dataset = datasets[year] + + try { + var url = "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/" + + dataset + "/records?" + + "limit=5" + + "&where=cod_uai%3D'" + codUai + "' AND search(lib_for_voe_ins, '" + searchName + "')" + + "&select=cod_uai,lib_for_voe_ins,voe_tot,acc_tot,pct_sansmention,pct_ab,pct_b,pct_tb,pct_tbf,pct_bg,pct_bt,pct_bp" + + var response = await fetch(url) + + if (response.ok) { + var data = await response.json() + + if (data.results && data.results.length > 0) { + var r = data.results[0] + var taux = 0 + + if (r.voe_tot && r.voe_tot > 0) { + taux = Math.round((r.acc_tot / r.voe_tot) * 100) + } + + history.push({ + annee: year, + tauxAcces: taux, + candidats: r.voe_tot || 0, + admis: r.acc_tot || 0, + pctSansMention: r.pct_sansmention || 0, + pctAB: r.pct_ab || 0, + pctB: r.pct_b || 0, + pctTB: r.pct_tb || 0, + pctTBF: r.pct_tbf || 0, + pctGeneral: r.pct_bg || 0, + pctTechno: r.pct_bt || 0, + pctPro: r.pct_bp || 0 + }) + } + } + } catch (e) { + console.warn("Erreur pour " + year + ":", e) + } + } + + return history +} diff --git a/parcoursup/app.riot b/parcoursup/app.riot index 3ba175f..51b6009 100644 --- a/parcoursup/app.riot +++ b/parcoursup/app.riot @@ -1,25 +1,72 @@
-
+ +
-
0 }> -

Comparateur

+

+ { state.query } — { state.total } rĂ©sultat(s) +

-

Choisis ton profil pour comparer les formations sélectionnées.

+ + +
+
+ + + + +
+
+
+ + +
+ + +
+ +
+ Chargement de la formation... +
+ + +
+ + + +
0 }> +

Comparateur de formations

+ +

Choisis ton profil pour estimer tes chances d'intégration.

@@ -49,6 +96,7 @@ +
@@ -57,27 +105,27 @@
-

Formations sélectionnées

- -
+

{ f.nom }

+

Établissement : { f.etablissement }

Ville : { f.ville }

FiliĂšre : { f.filiere }

+

Capacité : { f.capacite }

Taux d'accĂšs : { f.tauxAcces }%

- Profil admis : + Intégrés : Général { f.pctGeneral }% / Techno { f.pctTechno }% / Pro { f.pctPro }%

-

- Estimation : +

{ estimateFormation(f) } + { getEstimateDetail(f) }

-

- { state.query } — { state.total } rĂ©sultat(s) -

- - - -
-
- - - - -
+
+

Aucune formation sélectionnée

+

Retourne à la recherche et clique sur "Ajouter à la sélection" pour comparer des formations.

-
- - -
diff --git a/parcoursup/components/detail-view.riot b/parcoursup/components/detail-view.riot index 82258d4..55c5dc0 100644 --- a/parcoursup/components/detail-view.riot +++ b/parcoursup/components/detail-view.riot @@ -1,9 +1,7 @@

Formation

-

{ props.formation.etablissement } - { props.formation.nom }

-

Ville : { props.formation.ville }

Département : { props.formation.departement } { props.formation.departementLib }

@@ -15,7 +13,6 @@

Phase principale d'admission

- @@ -68,7 +65,6 @@

Vitesse de remplissage

-
@@ -77,7 +73,6 @@ { props.formation.pctDebutPhase }%
-
@@ -85,7 +80,6 @@ { props.formation.pctDateBac }%
-
@@ -98,7 +92,6 @@

Phase complémentaire d'admission

-
@@ -153,127 +146,49 @@

Profil des admis

- -

Répartition par type de bac

- -
-
- - - - - - - - - - - - - - - - - - - - -
TypePourcentage
Général - { props.formation.pctGeneral || 0 }% -
Techno - { props.formation.pctTechno || 0 }% -
Pro - { props.formation.pctPro || 0 }% -
-
+
-

Mentions au bac des admis

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MentionPourcentage
Sans - { props.formation.pctSansMention || 0 }% -
AB - { props.formation.pctAB || 0 }% -
Bien - { props.formation.pctB || 0 }% -
TB - { props.formation.pctTB || 0 }% -
TB Féli. - { props.formation.pctTBF || 0 }% -
-
+
-

Profil sociologique

+
+
+
-
- - - - - - - - - - - - - - - - - - - - - -
CatégoriePourcentage
Femmes - { props.formation.pctFemmes || 0 }% -
Boursiers - { props.formation.pctBoursiers || 0 }% -
Néo-bac - { props.formation.pctNeoBac || 0 }% -
-
+ + +

Évolution depuis 2020

+ +
+ Chargement de l'historique... +
+ +
+ Aucune donnée historique disponible pour cette formation. +
+ +
0 }> +
+

Taux d'accÚs par année

+
+
+

Nombre de candidats et admis

+
+
+ +
+

Évolution des mentions au bac

+
+
@@ -281,12 +196,191 @@ diff --git a/parcoursup/components/map-view.riot b/parcoursup/components/map-view.riot index 067b92f..ded32ae 100644 --- a/parcoursup/components/map-view.riot +++ b/parcoursup/components/map-view.riot @@ -7,7 +7,7 @@ - \ No newline at end of file + diff --git a/parcoursup/components/result-list.riot b/parcoursup/components/result-list.riot index 8b66167..e84a631 100644 --- a/parcoursup/components/result-list.riot +++ b/parcoursup/components/result-list.riot @@ -17,6 +17,17 @@ +
- \ No newline at end of file + + + diff --git a/parcoursup/components/search-bar.riot b/parcoursup/components/search-bar.riot index 01861a4..1511402 100644 --- a/parcoursup/components/search-bar.riot +++ b/parcoursup/components/search-bar.riot @@ -2,26 +2,133 @@ +
+ +
+ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+
+ - \ No newline at end of file + diff --git a/parcoursup/firebase.js b/parcoursup/firebase.js new file mode 100644 index 0000000..e69de29 diff --git a/parcoursup/index.html b/parcoursup/index.html index a614ea9..134b207 100644 --- a/parcoursup/index.html +++ b/parcoursup/index.html @@ -12,27 +12,46 @@ - - + + - - - - - + + + + + - + window.fetchFormations = fetchFormations + window.createFormation = createFormation + window.fetchFormationHistory = fetchFormationHistory - - + + \ No newline at end of file diff --git a/parcoursup/style.css b/parcoursup/style.css index 3f221b4..cb7159b 100644 --- a/parcoursup/style.css +++ b/parcoursup/style.css @@ -20,7 +20,6 @@ --rayon: 6px; } - /* --- Reset & base --- */ *, *::before, *::after { box-sizing: border-box; } @@ -35,7 +34,7 @@ } /* =========================================================== - HEADER — Bandeau Parcoursup + HEADER =========================================================== */ .site-header { @@ -66,9 +65,7 @@ gap: 10px; } - .logo-icon { - font-size: 22px; - } + .logo-icon { font-size: 22px; } .logo-text { font-size: 18px; @@ -92,6 +89,46 @@ border: 1px solid #b8e0cd; } + /* --- Header nav --- */ + .header-nav { + display: flex; + align-items: center; + gap: 4px; + } + + .nav-link { + color: var(--gris-500); + text-decoration: none; + padding: 6px 14px; + border-radius: var(--rayon); + font-size: 14px; + font-weight: 600; + transition: all 0.15s; + display: inline-flex; + align-items: center; + gap: 6px; + } + + .nav-link:hover { + color: var(--vert); + background: var(--vert-clair); + } + + .nav-active { + color: var(--vert-fonce); + background: var(--vert-clair); + border: 1px solid #b8e0cd; + } + + .nav-badge { + background: var(--vert); + color: white; + font-size: 11px; + font-weight: 800; + padding: 1px 7px; + border-radius: 10px; + } + /* =========================================================== PAGE =========================================================== */ @@ -119,41 +156,18 @@ transition: all 0.15s; } - .btn:disabled { - opacity: 0.4; - cursor: not-allowed; - } + .btn:disabled { opacity: 0.4; cursor: not-allowed; } - .btn-primary { - background: var(--vert); - color: white; - } - .btn-primary:hover:not(:disabled) { - background: var(--vert-fonce); - } + .btn-primary { background: var(--vert); color: white; } + .btn-primary:hover:not(:disabled) { background: var(--vert-fonce); } - .btn-outline { - background: white; - color: var(--vert); - border: 1.5px solid var(--vert); - } - .btn-outline:hover:not(:disabled) { - background: var(--vert-clair); - } + .btn-outline { background: white; color: var(--vert); border: 1.5px solid var(--vert); } + .btn-outline:hover:not(:disabled) { background: var(--vert-clair); } - .btn-danger { - background: #fef2f2; - color: var(--rouge); - border: 1px solid #f5c6cb; - } - .btn-danger:hover { - background: #fde8e8; - } + .btn-danger { background: #fef2f2; color: var(--rouge); border: 1px solid #f5c6cb; } + .btn-danger:hover { background: #fde8e8; } - .btn-small { - padding: 5px 12px; - font-size: 13px; - } + .btn-small { padding: 5px 12px; font-size: 13px; } /* =========================================================== SEARCH BAR @@ -193,13 +207,7 @@ transition: background 0.15s; } - .search-bar button:hover { - background: var(--vert-fonce); - } - - /* =========================================================== - RESULT COUNT - =========================================================== */ + .search-bar button:hover { background: var(--vert-fonce); } .result-count { font-size: 14px; @@ -208,7 +216,7 @@ } /* =========================================================== - CARDS — RĂ©sultats + comparateur items + CARDS =========================================================== */ .card { @@ -219,9 +227,14 @@ transition: border-color 0.15s; } - .card:hover { - border-color: var(--vert); - } + .card:hover { border-color: var(--vert); } + + /* Pas de hover vert sur les cards colorĂ©es du comparateur */ + .card-tres-favorable:hover { border-color: #6ec89b; } + .card-favorable:hover { border-color: #a3d9b8; } + .card-possible:hover { border-color: #f6e05e; } + .card-difficile:hover { border-color: #f5c6cb; } + .card-tres-difficile:hover { border-color: #f5a3a3; } .card h3, .card h4 { margin-top: 0; @@ -249,12 +262,91 @@ transition: all 0.15s; } - .card button:hover { - background: var(--vert-clair); + .card button:hover { background: var(--vert-clair); } + .card button + button { margin-left: 8px; } + + /* --- Cards colorĂ©es du comparateur --- */ + .card-tres-favorable { + background: #e8f5ef; + border-color: #6ec89b; + border-left: 4px solid #147a5c; } - .card button + button { - margin-left: 8px; + .card-favorable { + background: #eaf7ed; + border-color: #a3d9b8; + border-left: 4px solid #1a936f; + } + + .card-possible { + background: #fef9e7; + border-color: #f6e05e; + border-left: 4px solid #d69e2e; + } + + .card-difficile { + background: #fef2f2; + border-color: #f5c6cb; + border-left: 4px solid #e67e22; + } + + .card-tres-difficile { + background: #fde8e8; + border-color: #f5a3a3; + border-left: 4px solid #c0392b; + } + + /* =========================================================== + BADGES ESTIMATION — 5 niveaux + =========================================================== */ + + .estimate { + display: inline-block; + padding: 4px 14px; + border-radius: 4px; + font-size: 13px; + font-weight: 700; + } + + .tres-favorable { + background: #147a5c; + color: white; + } + + .favorable { + background: var(--vert-clair); + color: var(--vert-fonce); + border: 1px solid #a3d9c0; + } + + .possible { + background: #fef9e7; + color: #b7791f; + border: 1px solid #f6e05e; + } + + .difficile { + background: #fef2f2; + color: #c05621; + border: 1px solid #f5c6cb; + } + + .tres-difficile { + background: var(--rouge); + color: white; + } + + .estimation-result { + margin-top: 10px; + display: flex; + align-items: center; + gap: 10px; + flex-wrap: wrap; + } + + .estimation-detail { + font-size: 12px; + color: var(--gris-500); } /* =========================================================== @@ -342,36 +434,6 @@ color: var(--gris-500); } - /* =========================================================== - BADGES ESTIMATION - =========================================================== */ - - .estimate { - display: inline-block; - padding: 3px 12px; - border-radius: 4px; - font-size: 13px; - font-weight: 700; - } - - .favorable { - background: var(--vert-clair); - color: var(--vert-fonce); - border: 1px solid #a3d9c0; - } - - .possible { - background: #fef9e7; - color: #b7791f; - border: 1px solid #f6e05e; - } - - .difficile { - background: #fef2f2; - color: var(--rouge); - border: 1px solid #f5c6cb; - } - /* =========================================================== LAYOUT =========================================================== */ @@ -387,10 +449,6 @@ gap: 12px; } - /* =========================================================== - MESSAGE (loading / no result) - =========================================================== */ - .message { padding: 16px; background: white; @@ -423,12 +481,10 @@ } /* =========================================================== - DETAIL VIEW — Fiche formation + DETAIL VIEW =========================================================== */ - .detail-page { - background: transparent; - } + .detail-page { background: transparent; } .formation-title { color: var(--bleu); @@ -461,7 +517,6 @@ margin-bottom: 28px; } - /* --- Tableaux --- */ .detail-table { width: 100%; border-collapse: collapse; @@ -490,7 +545,6 @@ background: var(--gris-100); } - /* --- Timeline --- */ .timeline-box { background: white; padding: 18px 22px; @@ -498,10 +552,7 @@ border: 1px solid var(--gris-200); } - .timeline-box h3 { - margin-top: 0; - color: var(--gris-900); - } + .timeline-box h3 { margin-top: 0; color: var(--gris-900); } .timeline { position: relative; @@ -510,10 +561,7 @@ border-left: 3px solid #b8e0cd; } - .timeline-item { - position: relative; - margin-bottom: 32px; - } + .timeline-item { position: relative; margin-bottom: 32px; } .timeline-dot { position: absolute; @@ -557,9 +605,7 @@ font-weight: 600; } - .chart-full { - grid-column: 1 / -1; - } + .chart-full { grid-column: 1 / -1; } #chart-bac .column, #chart-mentions .column { @@ -579,6 +625,18 @@ font-size: 13px; } + #chart-evolution-taux .column { + height: 220px; + max-width: 100%; + margin: 0 auto; + } + + #chart-evolution-candidats .column { + height: 220px; + max-width: 100%; + margin: 0 auto; + } + .chart-wrapper .data { font-size: 11px; font-weight: 700; @@ -586,7 +644,6 @@ text-shadow: 0 1px 2px rgba(0,0,0,0.25); } - /* --- Bouton retour --- */ .btn-retour { display: inline-flex; align-items: center; @@ -603,42 +660,86 @@ transition: background 0.15s; } - .btn-retour:hover { - background: var(--vert-fonce); - } + .btn-retour:hover { background: var(--vert-fonce); } /* =========================================================== RESPONSIVE =========================================================== */ + /* --- Badge cliquable --- */ + .badge-clickable { + cursor: pointer; + transition: all 0.15s; + } + + .badge-clickable:hover { + background: #c6f0dc; + border-color: #6ec89b; + } + + /* --- Filtres avancĂ©s --- */ + .filters-toggle { + margin: -10px 0 16px; + } + + .filters-panel { + background: white; + border: 1px solid var(--gris-200); + border-radius: var(--rayon); + padding: 16px 20px; + margin-bottom: 20px; + } + + .filter-row { + display: flex; + gap: 16px; + flex-wrap: wrap; + margin-bottom: 12px; + } + + .filter-row:last-child { + margin-bottom: 0; + } + + .filter-item { + display: flex; + flex-direction: column; + gap: 4px; + min-width: 160px; + flex: 1; + } + + .filter-item label { + font-size: 12px; + font-weight: 600; + color: var(--gris-500); + } + + .filter-item select, + .filter-item input { + padding: 8px 10px; + font-size: 14px; + border: 1.5px solid var(--gris-300); + border-radius: var(--rayon); + background: white; + outline: none; + } + + .filter-item select:focus, + .filter-item input:focus { + border-color: var(--vert); + } + @media (max-width: 900px) { - .detail-grid { - grid-template-columns: 1fr; - } + .detail-grid { grid-template-columns: 1fr; } } @media (max-width: 700px) { - .charts-section { - grid-template-columns: 1fr; - } - - .site-header { - padding: 0 14px; - } - - .logo-text { - font-size: 16px; - } - - .page { - padding: 16px 12px 30px; - } - - .search-bar { - flex-direction: column; - } - - .search-bar button { - width: 100%; - } - } \ No newline at end of file + .charts-section { grid-template-columns: 1fr; } + .site-header { padding: 0 14px; } + .logo-text { font-size: 16px; } + .page { padding: 16px 12px 30px; } + .search-bar { flex-direction: column; } + .search-bar button { width: 100%; } + } + \ No newline at end of file