diff --git a/frontend/src/app/maps/all-events/all-events.ts b/frontend/src/app/maps/all-events/all-events.ts
index acc04ed..003adc1 100644
--- a/frontend/src/app/maps/all-events/all-events.ts
+++ b/frontend/src/app/maps/all-events/all-events.ts
@@ -101,10 +101,58 @@ export class AllEvents implements OnInit, OnDestroy {
const lat = parseFloat(this.route.snapshot.queryParams['lat']) || 48.8566;
const lon = parseFloat(this.route.snapshot.queryParams['lon']) || 2.3522;
const zoom = parseFloat(this.route.snapshot.queryParams['zoom']) || 8;
+ const basemap = (this.route.snapshot.queryParams['basemap'] || '').toLowerCase();
+
+ // Déterminer le style de fond de carte selon le query param "basemap"
+ // valeurs supportées: "vector" (défaut), "raster", "waymarked"
+ const style = (() => {
+ if (basemap === 'raster') {
+ return {
+ version: 8,
+ sources: {
+ osm: {
+ type: 'raster',
+ tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
+ tileSize: 256,
+ attribution: '© OpenStreetMap contributors'
+ }
+ },
+ layers: [
+ { id: 'osm-tiles', type: 'raster', source: 'osm', minzoom: 0, maxzoom: 19 }
+ ]
+ } as any;
+ }
+ if (basemap === 'waymarked') {
+ return {
+ version: 8,
+ sources: {
+ osm: {
+ type: 'raster',
+ tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
+ tileSize: 256,
+ attribution: '© OpenStreetMap contributors'
+ },
+ waymarked: {
+ type: 'raster',
+ // Waymarked Trails randonnée (hiking)
+ tiles: ['https://tile.waymarkedtrails.org/hiking/{z}/{x}/{y}.png'],
+ tileSize: 256,
+ attribution: '© waymarkedtrails.org'
+ }
+ },
+ layers: [
+ { id: 'osm-tiles', type: 'raster', source: 'osm', minzoom: 0, maxzoom: 19 },
+ { id: 'waymarked-overlay', type: 'raster', source: 'waymarked', minzoom: 0, maxzoom: 19 }
+ ]
+ } as any;
+ }
+ // vector (défaut)
+ return 'https://tiles.openfreemap.org/styles/liberty';
+ })();
this.map = new maplibregl.Map({
container: this.mapContainer.nativeElement,
- style: 'https://tiles.openfreemap.org/styles/liberty',
+ style,
center: [lon, lat],
zoom: zoom
});
diff --git a/frontend/src/app/pages/home/home.html b/frontend/src/app/pages/home/home.html
index c25a50a..2013fc3 100644
--- a/frontend/src/app/pages/home/home.html
+++ b/frontend/src/app/pages/home/home.html
@@ -23,6 +23,20 @@
▶
}
+
+
+
+ @if (pleinAirMode) {
+
+
+
+
+
+ }
+
@if (showFilters) {
@@ -78,11 +92,12 @@
+
-
+
}
@@ -100,7 +115,9 @@
Mettre à jour un évènement: Sélectionnez un évènement sur la carte ou dans la liste pour le modifier.
+ @if(!pleinAirMode){
+ }
}
@@ -174,6 +191,15 @@
+ @if (toasts.length) {
+
+ @for (t of toasts; track t.id) {
+
+ {{t.message}}
+
+ }
+
+ }
@if (theme()) {
Thème: {{ theme() }} — Cliquez sur la carte pour définir des coordonnées puis créez un évènement du sous-thème choisi.
diff --git a/frontend/src/app/pages/home/home.ts b/frontend/src/app/pages/home/home.ts
index 0af7996..662e23a 100644
--- a/frontend/src/app/pages/home/home.ts
+++ b/frontend/src/app/pages/home/home.ts
@@ -41,6 +41,8 @@ export class Home implements OnInit, OnDestroy {
showFilters = false;
showEditForm = false;
showOptions = false;
+ pleinAirMode = false;
+ toasts: Array<{ id: number, type: 'success' | 'error' | 'info', message: string }> = [];
selectionMode: 'none' | 'rectangle' | 'polygon' = 'none';
selectedIds: Array
= [];
@@ -76,9 +78,16 @@ export class Home implements OnInit, OnDestroy {
showUnlocatedList = false;
ngOnInit() {
+ // Écouteur global pour toasts
+ try {
+ (window as any).addEventListener('toast', (e: any) => {
+ const d = e?.detail || {}; this.pushToast(d.type || 'info', d.message || '');
+ });
+ } catch {}
this.route.queryParamMap.subscribe(map => {
const id = (map.get('id') || '').trim();
const what = (map.get('what') || '').trim();
+ const pleinAir = (map.get('pleinair') || '').trim().toLowerCase();
const limitParam = map.get('limit');
const limit = limitParam ? Number(limitParam) : null;
// Charger selon les query params
@@ -91,6 +100,10 @@ export class Home implements OnInit, OnDestroy {
if (what) {
this.selectedWhatFilter = what;
}
+ // Activer mode plein air via query param
+ if (pleinAir === '1' || pleinAir === 'true' || pleinAir === 'yes') {
+ this.enablePleinAirMode();
+ }
});
this.startAutoReload();
}
@@ -260,9 +273,49 @@ export class Home implements OnInit, OnDestroy {
});
}
+ // Mode plein air: ne garder que certains types
+ if (this.pleinAirMode) {
+ const allowed = new Set([
+ 'traffic.contestation',
+ 'traffic.interruption',
+ 'traffic.wrong_way'
+ ]);
+ filtered = filtered.filter(f => allowed.has(f?.properties?.what || ''));
+ }
+
this.filteredFeatures = filtered;
}
+ togglePleinAir() {
+ this.pleinAirMode = !this.pleinAirMode;
+ this.applyFilters();
+ }
+
+ enablePleinAirMode() {
+ if (!this.pleinAirMode) {
+ this.pleinAirMode = true;
+ this.applyFilters();
+ }
+ }
+
+ // Actions rapides plein air
+ quickCreate(what: 'traffic.contestation' | 'traffic.interruption' | 'traffic.wrong_way') {
+ const osmUsername = this.osmAuth.getUsername();
+ this.selected = {
+ id: null,
+ properties: {
+ label: '',
+ description: '',
+ what,
+ where: '',
+ ...(osmUsername && { last_modified_by: osmUsername })
+ },
+ geometry: { type: 'Point', coordinates: [0, 0] }
+ };
+ // Ensuite, l'utilisateur clique sur la carte: voir onPickCoords()
+ this.showEditForm = true;
+ }
+
goToNewCategories() {
this.router.navigate(['/nouvelles-categories']);
}
@@ -279,7 +332,35 @@ export class Home implements OnInit, OnDestroy {
geometry: { type: 'Point', coordinates: [lon, lat] }
};
this.showOptions = true;
-
+ // En mode plein air, si c'est une création rapide, proposer l'envoi direct
+ if (this.pleinAirMode && (this.selected.id == null)) {
+ const w = this.selected.properties.what;
+ const allowed = new Set(['traffic.contestation','traffic.interruption','traffic.wrong_way']);
+ if (allowed.has(w)) {
+ const ok = typeof window !== 'undefined' ? window.confirm('Envoyer cet évènement maintenant ?') : true;
+ if (ok) {
+ const now = new Date();
+ const stop = new Date(now.getTime() + 6 * 3600 * 1000);
+ const feature = {
+ type: 'Feature',
+ properties: {
+ type: 'unscheduled',
+ label: this.selected.properties.label || (oedb.presets.what as any)[w]?.label || 'Évènement',
+ description: this.selected.properties.description || (oedb.presets.what as any)[w]?.description || '',
+ what: w,
+ where: this.selected.properties.where || '',
+ start: now.toISOString(),
+ stop: stop.toISOString()
+ },
+ geometry: { type: 'Point', coordinates: [lon, lat] }
+ } as any;
+ this.OedbApi.createEvent(feature).subscribe({
+ next: () => { this.pushToast('success', 'Évènement créé'); this.selected = null; this.loadEvents(); },
+ error: () => { this.pushToast('error', 'Échec de création'); }
+ });
+ }
+ }
+ }
} else {
const osmUsername = this.osmAuth.getUsername();
const whatKey = this.activeSubtheme();
@@ -306,6 +387,15 @@ export class Home implements OnInit, OnDestroy {
}
}
+ private pushToast(type: 'success' | 'error' | 'info', message: string) {
+ if (!message) return;
+ const id = Date.now() + Math.random();
+ this.toasts.push({ id, type, message });
+ setTimeout(() => {
+ this.toasts = this.toasts.filter(t => t.id !== id);
+ }, 3000);
+ }
+
onSaved(_res: any) {
// refresh list after update
this.loadEvents();