ajout du style global et de la carte leaflet

This commit is contained in:
2026-03-18 13:21:19 +01:00
parent 43d0cf4abe
commit c97bda935e
7 changed files with 196 additions and 34 deletions
+22 -16
View File
@@ -1,23 +1,29 @@
<app> <app>
<h1>Mini projet Parcoursup</h1> <div class="page">
<p>Recherche de formations Parcoursup avec Riot</p> <h1>Mini projet Parcoursup</h1>
<p class="subtitle">Recherche de formations Parcoursup avec Riot</p>
<div if={ !state.selected }> <div if={ !state.selected }>
<search-bar onsearch={ launchSearch }></search-bar> <search-bar onsearch={ launchSearch }></search-bar>
<result-list <div class="layout">
results={ state.results } <result-list
hasSearched={ state.hasSearched } results={ state.results }
loading={ state.loading } hasSearched={ state.hasSearched }
ondetail={ showDetail }> loading={ state.loading }
</result-list> ondetail={ showDetail }>
</div> </result-list>
<div if={ state.selected }> <map-view results={ state.results }></map-view>
<detail-view </div>
formation={ state.selected } </div>
onback={ backToList }>
</detail-view> <div if={ state.selected }>
<detail-view
formation={ state.selected }
onback={ backToList }>
</detail-view>
</div>
</div> </div>
<script> <script>
+1 -3
View File
@@ -1,6 +1,5 @@
<detail-view> <detail-view>
<div if={ props.formation } <div if={ props.formation } class="detail-card">
style="border:1px solid #ccc; padding:10px; margin:10px;">
<h2>{ props.formation.nom }</h2> <h2>{ props.formation.nom }</h2>
<p><b>Établissement :</b> { props.formation.etablissement }</p> <p><b>Établissement :</b> { props.formation.etablissement }</p>
<p><b>Ville :</b> { props.formation.ville }</p> <p><b>Ville :</b> { props.formation.ville }</p>
@@ -11,7 +10,6 @@
<p><b>Candidats :</b> { props.formation.candidats }</p> <p><b>Candidats :</b> { props.formation.candidats }</p>
<p><b>Admis :</b> { props.formation.admis }</p> <p><b>Admis :</b> { props.formation.admis }</p>
<p><b>Taux d'accès :</b> { props.formation.tauxAcces }%</p> <p><b>Taux d'accès :</b> { props.formation.tauxAcces }%</p>
<button onclick={ () => props.onback() }>Retour</button> <button onclick={ () => props.onback() }>Retour</button>
</div> </div>
</detail-view> </detail-view>
+53
View File
@@ -0,0 +1,53 @@
<map-view>
<div class="map-box">
<h3>Carte des formations</h3>
<div id="map"></div>
</div>
<script>
export default {
onMounted() {
this.map = L.map(this.root.querySelector('#map')).setView([46.8, 2.5], 6)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; OpenStreetMap contributors'
}).addTo(this.map)
this.markersLayer = L.layerGroup().addTo(this.map)
this.refreshMarkers()
},
onUpdated() {
this.refreshMarkers()
},
refreshMarkers() {
if (!this.map || !this.markersLayer) {
return
}
this.markersLayer.clearLayers()
const points = []
for (let i = 0; i < this.props.results.length; i++) {
const f = this.props.results[i]
if (f.latitude && f.longitude) {
const marker = L.marker([f.latitude, f.longitude])
marker.bindPopup(`<b>${f.nom}</b><br>${f.ville}`)
marker.addTo(this.markersLayer)
points.push([f.latitude, f.longitude])
}
}
if (points.length > 0) {
this.map.fitBounds(points, { padding: [20, 20] })
} else {
this.map.setView([46.8, 2.5], 6)
}
}
}
</script>
</map-view>
+4 -4
View File
@@ -1,14 +1,14 @@
<result-list> <result-list>
<div> <div class="results">
<div if={ props.results.length === 0 && props.hasSearched && !props.loading }> <div class="message" if={ props.results.length === 0 && props.hasSearched && !props.loading }>
Aucun résultat trouvé Aucun résultat trouvé
</div> </div>
<div if={ props.loading }> <div class="message" if={ props.loading }>
Chargement... Chargement...
</div> </div>
<div each={ (f, i) in props.results } key={ f.id } style="border:1px solid #ccc; padding:10px; margin:10px;"> <div each={ (f, i) in props.results } key={ f.id } class="card">
<h3>{ f.nom }</h3> <h3>{ f.nom }</h3>
<p><b>Établissement :</b> { f.etablissement }</p> <p><b>Établissement :</b> { f.etablissement }</p>
<p><b>Ville :</b> { f.ville } ({ f.departement })</p> <p><b>Ville :</b> { f.ville } ({ f.departement })</p>
+1 -1
View File
@@ -1,5 +1,5 @@
<search-bar> <search-bar>
<div> <div class="search-bar">
<input <input
type="text" type="text"
placeholder="Ex : BUT informatique" placeholder="Ex : BUT informatique"
+18 -10
View File
@@ -1,19 +1,27 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="fr"> <html lang="fr">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Parcoursup Riot</title> <title>Parcoursup Riot</title>
<script src="https://cdn.jsdelivr.net/npm/riot@9/riot+compiler.min.js"></script> <link rel="stylesheet" href="./style.css" />
</head> <link
rel="stylesheet"
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
/>
<script src="https://cdn.jsdelivr.net/npm/riot@9/riot+compiler.min.js"></script>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
</head>
<body> <body>
<app></app> <app></app>
<script src="./components/search-bar.riot" type="riot"></script> <script src="./components/search-bar.riot" type="riot"></script>
<script src="./components/result-list.riot" type="riot"></script> <script src="./components/result-list.riot" type="riot"></script>
<script src="./components/detail-view.riot" type="riot"></script> <script src="./components/detail-view.riot" type="riot"></script>
<script src="./app.riot" type="riot"></script> <script src="./components/map-view.riot" type="riot"></script>
<script src="./app.riot" type="riot"></script>
<script type="module"> <script type="module">
import { fetchFormations } from './api.js' import { fetchFormations } from './api.js'
+97
View File
@@ -0,0 +1,97 @@
body {
font-family: Arial, sans-serif;
margin: 0;
background: #f5f5f5;
color: #222;
}
.page {
max-width: 1100px;
margin: 0 auto;
padding: 20px;
}
h1 {
margin-bottom: 8px;
}
.subtitle {
margin-top: 0;
color: #555;
}
.search-bar {
display: flex;
gap: 10px;
margin: 20px 0;
}
.search-bar input {
flex: 1;
padding: 10px;
font-size: 16px;
}
.search-bar button,
.card button,
.detail-card button {
padding: 10px 14px;
font-size: 14px;
cursor: pointer;
}
.layout {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
.results {
display: grid;
gap: 16px;
}
.card {
border: 1px solid #d8d8d8;
background: white;
padding: 16px;
border-radius: 8px;
}
.card h3 {
margin-top: 0;
}
.detail-card {
border: 1px solid #d8d8d8;
background: white;
padding: 20px;
border-radius: 8px;
}
.map-box {
border: 1px solid #d8d8d8;
background: white;
border-radius: 8px;
padding: 12px;
}
#map {
height: 420px;
width: 100%;
border-radius: 6px;
}
.message {
padding: 12px;
background: white;
border: 1px solid #d8d8d8;
border-radius: 8px;
}
@media (min-width: 900px) {
.layout {
grid-template-columns: 1.2fr 1fr;
align-items: start;
}
}