diff --git a/parcoursup/api.js b/parcoursup/api.js index 789a836..a263180 100644 --- a/parcoursup/api.js +++ b/parcoursup/api.js @@ -1,6 +1,9 @@ -export function buildURL(query) { +export function buildURL(query, limit = 20, offset = 0) { let url = - "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup/records?limit=10" + "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup/records?" + + url += "limit=" + limit + url += "&offset=" + offset if (query && query.trim() !== "") { url += "&where=search(lib_for_voe_ins, '" + query + "')" @@ -9,8 +12,8 @@ export function buildURL(query) { return url } -export async function fetchFormations(query) { - const url = buildURL(query) +export async function fetchFormations(query, limit = 20, offset = 0) { + const url = buildURL(query, limit, offset) const response = await fetch(url) if (!response.ok) { diff --git a/parcoursup/app.riot b/parcoursup/app.riot index 93fce33..f12f713 100644 --- a/parcoursup/app.riot +++ b/parcoursup/app.riot @@ -1,6 +1,6 @@
-

Mini projet Parcoursup

+

Open Data Parcoursup

Recherche de formations Parcoursup avec Riot

{ state.selectedFormations.length } formation(s) sélectionnée(s)

@@ -8,14 +8,32 @@
+

+ { state.query } : { state.total } résultat(s) +

+
- - +
+ + + +
state.limit }> + + +

Page { state.page } / { getTotalPages() }

+ + +
+
@@ -109,7 +127,11 @@ selectedFormations: [], note: 12, serie: 'general', - sortBy: 'nom' + sortBy: 'nom', + query: '', + page: 1, + limit: 20, + total: 0 }, onMounted() { @@ -130,11 +152,28 @@ this.update({ loading: true, hasSearched: true, - selected: null + selected: null, + query: query, + page: 1 + }) + + await this.loadPage(1) + }, + + async loadPage(page) { + this.update({ + loading: true }) try { - const data = await window.fetchFormations(query) + const offset = (page - 1) * this.state.limit + + const data = await window.fetchFormations( + this.state.query, + this.state.limit, + offset + ) + const formations = [] if (data.results) { @@ -146,17 +185,36 @@ this.update({ results: formations, + total: data.total_count ? data.total_count : 0, + page: page, loading: false }) } catch (error) { console.error(error) this.update({ results: [], + total: 0, loading: false }) } }, + getTotalPages() { + return Math.ceil(this.state.total / this.state.limit) + }, + + async nextPage() { + if (this.state.page < this.getTotalPages()) { + await this.loadPage(this.state.page + 1) + } + }, + + async previousPage() { + if (this.state.page > 1) { + await this.loadPage(this.state.page - 1) + } + }, + showDetail(index) { this.update({ selected: this.state.results[index] diff --git a/parcoursup/components/detail-view.riot b/parcoursup/components/detail-view.riot index cde24b5..cffa2bb 100644 --- a/parcoursup/components/detail-view.riot +++ b/parcoursup/components/detail-view.riot @@ -1,89 +1,153 @@ -
-

{ props.formation.nom }

+
+

Formation

-

Établissement : { props.formation.etablissement }

-

Ville : { props.formation.ville }

-

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

-

Académie : { props.formation.academie }

-

Région : { props.formation.region }

-

Contrat : { props.formation.contrat }

+

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

-
+
+

Ville : { props.formation.ville }

+

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

+

Académie : { props.formation.academie }

+

{ props.formation.contrat }

+

Capacité : { props.formation.capacite }

+
-

Formation

-

Filière : { props.formation.filiere }

-

Sélectivité : { props.formation.selectivite }

-

Capacité : { props.formation.capacite }

-

Candidats : { props.formation.candidats }

-

Admis : { props.formation.admis }

-

Taux d'accès : { props.formation.tauxAcces }%

+
+
+

Phase principale d'admission

-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BacVoeuxClassésPropositionsAcceptés
Gén{ props.formation.voePPGeneral }{ props.formation.classesPPGeneral }{ props.formation.propositionsPPGeneral }{ props.formation.acceptesPPGeneral }
Techno{ props.formation.voePPTechno }{ props.formation.classesPPTechno }{ props.formation.propositionsPPTechno }{ props.formation.acceptesPPTechno }
Pro{ props.formation.voePPPro }{ props.formation.classesPPPro }{ props.formation.propositionsPPPro }{ props.formation.acceptesPPPro }
Autres{ props.formation.voePPAutres }{ props.formation.classesPPAutres }{ props.formation.propositionsPPAutres }{ props.formation.acceptesPPAutres }
Total{ props.formation.voePPTotal }{ props.formation.classesPPTotal }{ props.formation.propositionsPPTotal }{ props.formation.acceptesPPTotal }
+
-

Profil des admis

+
+

Vitesse de remplissage

-
-
Répartition des bacs
+
+
+
+
+ Ouverture 30 mai
+ { props.formation.pctDebutPhase }% +
+
- - - - - - - - - - - - - - - -
Général - { props.formation.pctGeneral }% -
Technologique - { props.formation.pctTechno }% -
Professionnel - { props.formation.pctPro }% -
-
+
+
+
+ 16 juin
+ { props.formation.pctDateBac }% +
+
-
+
+
+
+ 11 juillet
+ { props.formation.pctFinPhase }% +
+
+
+
+
-

Mentions au bac

+

Phase complémentaire d'admission

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BacVoeuxClassésPropositionsAcceptés
Gén{ props.formation.voePCGeneral }
Techno{ props.formation.voePCTechno }
Pro{ props.formation.voePCPro }
Autres{ props.formation.voePCAutres }
Total{ props.formation.voePCTotal }{ props.formation.classesPCTotal }{ props.formation.acceptesPCTotal }{ props.formation.acceptesPCTotal }
-
- - - - - - - - - - - - - - - - - - - -
Sans mention - { props.formation.pctSansMention }% -
AB - { props.formation.pctAB }% -
B - { props.formation.pctB }% -
TB - { props.formation.pctTB }% -
-
\ No newline at end of file diff --git a/parcoursup/formation.js b/parcoursup/formation.js index a658ac6..0bfa12b 100644 --- a/parcoursup/formation.js +++ b/parcoursup/formation.js @@ -33,7 +33,6 @@ export function createFormation(raw) { ? raw.g_olocalisation_des_formations.lon : null, - // profils admis pctFemmes: raw.pct_f, pctBoursiers: raw.pct_bours, pctNeoBac: raw.pct_neobac, @@ -48,19 +47,47 @@ export function createFormation(raw) { pctTB: raw.pct_tb, pctTBF: raw.pct_tbf, - // vitesse de remplissage / phase principale pctDebutPhase: raw.pct_acc_debutpp, pctDateBac: raw.pct_acc_datebac, pctFinPhase: raw.pct_acc_finpp, - // chiffres bruts utiles admisDebutPhase: raw.acc_debutpp, admisDateBac: raw.acc_datebac, admisFinPhase: raw.acc_finpp, - admisGeneral: raw.acc_bg, - admisTechno: raw.acc_bt, - admisPro: raw.acc_bp, - admisAutres: raw.acc_at + // phase principale + voePPGeneral: raw.nb_voe_pp_bg, + voePPTechno: raw.nb_voe_pp_bt, + voePPPro: raw.nb_voe_pp_bp, + voePPAutres: raw.nb_voe_pp_at, + voePPTotal: raw.nb_voe_pp, + + classesPPGeneral: raw.nb_cla_pp_bg, + classesPPTechno: raw.nb_cla_pp_bt, + classesPPPro: raw.nb_cla_pp_bp, + classesPPAutres: raw.nb_cla_pp_at, + classesPPTotal: raw.nb_cla_pp, + + propositionsPPGeneral: raw.prop_tot_bg, + propositionsPPTechno: raw.prop_tot_bt, + propositionsPPPro: raw.prop_tot_bp, + propositionsPPAutres: raw.prop_tot_at, + propositionsPPTotal: raw.prop_tot, + + acceptesPPGeneral: raw.acc_bg, + acceptesPPTechno: raw.acc_bt, + acceptesPPPro: raw.acc_bp, + acceptesPPAutres: raw.acc_at, + acceptesPPTotal: raw.acc_pp, + + // phase complémentaire + voePCGeneral: raw.nb_voe_pc_bg, + voePCTechno: raw.nb_voe_pc_bt, + voePCPro: raw.nb_voe_pc_bp, + voePCAutres: raw.nb_voe_pc_at, + voePCTotal: raw.nb_voe_pc, + + classesPCTotal: raw.nb_cla_pc, + acceptesPCTotal: raw.acc_pc } } \ No newline at end of file diff --git a/parcoursup/style.css b/parcoursup/style.css index 53ed84d..9164398 100644 --- a/parcoursup/style.css +++ b/parcoursup/style.css @@ -164,9 +164,81 @@ body { font-weight: bold; } - @media (min-width: 900px) { - .layout { - grid-template-columns: 1.2fr 1fr; - align-items: start; + .detail-page { + background: #f5f5f5; + } + + .formation-title { + color: #3d4fff; + font-size: 2rem; + line-height: 1.15; + margin-bottom: 20px; + } + + .formation-meta p { + margin: 8px 0; + font-size: 1.1rem; + } + + .detail-grid { + display: grid; + grid-template-columns: 2fr 1fr; + gap: 40px; + align-items: start; + margin-top: 20px; + margin-bottom: 30px; + } + + .detail-table { + width: 100%; + border-collapse: collapse; + background: white; + } + + .detail-table th, + .detail-table td { + border: 1px solid #d7d7d7; + padding: 14px 12px; + text-align: left; + } + + .detail-table th { + background: #fafafa; + font-size: 1.05rem; + } + + .total-row td { + font-weight: bold; + } + + .timeline-box { + padding-top: 10px; + } + + .timeline { + position: relative; + margin-top: 30px; + padding-left: 30px; + border-left: 2px solid #d9d9d9; + } + + .timeline-item { + position: relative; + margin-bottom: 45px; + } + + .timeline-dot { + position: absolute; + left: -39px; + top: 6px; + width: 14px; + height: 14px; + background: #21c8b4; + border-radius: 50%; + } + + @media (max-width: 900px) { + .detail-grid { + grid-template-columns: 1fr; } } \ No newline at end of file