more style for interface; dark top

This commit is contained in:
Tykayn 2025-10-15 00:20:52 +02:00 committed by tykayn
parent e7a2d93d18
commit 2f9b91f2c7
4 changed files with 339 additions and 139 deletions

View file

@ -301,6 +301,7 @@
<input type="text" [(ngModel)]="guidePresetMoreInfoPseudo" placeholder="votre pseudo ou nom">
<textarea [(ngModel)]="presetMoreDetails" placeholder="tronc d'arbre dans le chemin"></textarea>
<button class="btn btn-primary" (click)="submitPreset()">Envoyer</button>
<button class="btn btn-secondary" (click)="cancelSubmitPreset()">Annuler</button>
</p>
}
}

View file

@ -7,9 +7,11 @@
border-radius: 10px;
padding: 10px;
cursor: pointer;
&:hover {
background-color: #f0f0f0;
}
+ button {
margin-left: 10px;
margin-bottom: 10px;
@ -23,9 +25,11 @@
grid-template-columns: 400px 1fr;
grid-template-rows: 100vh;
gap: 0;
&.is-small {
grid-template-columns: 100px 1fr;
}
/* Quand la zone principale est en plein écran */
&:has(.main.is-full) {
grid-template-columns: 1fr;
@ -50,6 +54,7 @@
flex-direction: column;
height: 100vh;
overflow: hidden;
&.is-full {
flex-grow: 1;
}
@ -129,27 +134,81 @@
flex: 1 1 auto;
min-height: 0;
}
.unlocated-layout {
display: grid;
grid-template-columns: 360px 1fr;
height: 100%;
}
.agenda-sidebar {
overflow: auto;
border-right: 1px solid #eee;
padding: 10px;
}
.event-list{ list-style: none; padding: 0; margin: 0; }
.event-item{ display: flex; gap: 8px; padding: 8px; cursor: pointer; }
.event-item.active{ background: #f0f9ff; }
.event-title{ font-weight: 600; }
.event-when{ font-size: 12px; color: #64748b; }
.agenda-main{ padding: 10px; }
.event-edit-panel{ border: 1px solid #e2e8f0; border-radius: 8px; background: #fff; }
.panel-header{ display:flex; justify-content: space-between; align-items:center; padding: 8px 12px; border-bottom: 1px solid #e2e8f0; }
.panel-content{ padding: 8px; }
.btn-close{ background: #f5f5f5; border: 1px solid #ddd; border-radius: 4px; width: 32px; height: 32px; cursor: pointer; }
.hint{ color: #64748b; padding: 20px; }
.event-list {
list-style: none;
padding: 0;
margin: 0;
}
.event-item {
display: flex;
gap: 8px;
padding: 8px;
cursor: pointer;
}
.event-item.active {
background: #f0f9ff;
}
.event-title {
font-weight: 600;
}
.event-when {
font-size: 12px;
color: #64748b;
}
.agenda-main {
padding: 10px;
}
.event-edit-panel {
border: 1px solid #e2e8f0;
border-radius: 8px;
background: #fff;
}
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
border-bottom: 1px solid #e2e8f0;
}
.panel-content {
padding: 8px;
}
.btn-close {
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 4px;
width: 32px;
height: 32px;
cursor: pointer;
}
.hint {
color: #64748b;
padding: 20px;
}
.floating-actions {
position: fixed;
right: 1rem;
@ -174,10 +233,12 @@
background: #1976d2;
color: #fff;
}
.fab.counter {
background: #0d9488;
margin-left: 0.5rem;
}
.fab.plus {
background: #1976d2;
}
@ -188,6 +249,7 @@
padding: 1rem;
display: block;
cursor: pointer;
&:hover {
background: lemonchiffon;
}
@ -207,15 +269,18 @@
margin-left: 0;
}
}
.agenda-main {
app-edit-form {
right: 2rem;
top: 3.5rem;
.actions {
right: 1rem !important;
}
}
}
app-edit-form {
position: fixed;
top: 135px;
@ -243,11 +308,34 @@ app-edit-form{
flex-direction: column;
gap: 8px;
padding: 8px 12px;
.help { font-size: 12px; color: #64748b; }
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip { border: 1px solid #e2e8f0; border-radius: 999px; padding: 6px 10px; background: #fff; cursor: pointer; }
.chip.active { background: #e3f2fd; border-color: #90caf9; }
.emoji { margin-right: 6px; }
.help {
font-size: 12px;
color: #64748b;
}
.chips {
display: flex;
gap: 6px;
flex-wrap: wrap;
}
.chip {
border: 1px solid #e2e8f0;
border-radius: 999px;
padding: 6px 10px;
background: #fff;
cursor: pointer;
}
.chip.active {
background: #e3f2fd;
border-color: #90caf9;
}
.emoji {
margin-right: 6px;
}
}
.toggle-options {
@ -258,19 +346,23 @@ app-edit-form{
background: white;
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: 10px;
padding: 10px;
padding: 2rem 1rem;
cursor: pointer;
&:hover {
background-color: #f0f0f0;
}
&:active {
background-color: #e0e0e0;
}
&:focus {
outline: none;
}
}
// presets de boutons
.quick-actions {
margin-top: 8px;
@ -281,6 +373,13 @@ app-edit-form{
right: 5rem;
bottom: 1.1rem;
z-index: 100;
.btn {
padding: 1rem 1.25rem;
cursor: pointer;
height: 3.5rem;
}
}
.guide-preset {
@ -294,6 +393,7 @@ app-edit-form{
bottom: 2rem;
right: 3.5rem;
}
.guide-preset-more {
background: white;
padding: 1rem;
@ -302,10 +402,12 @@ app-edit-form{
bottom: 1rem;
margin: 1rem;
width: 70%;
input, textarea {
width: 90%;
}
button {
margin: 1rem;
display: block;
@ -315,32 +417,40 @@ app-edit-form{
border-radius: 0.5rem;
}
}
table {
width: 100%;
border-collapse: collapse;
border: 1px solid #eee;
border-radius: 10px;
overflow: hidden;
td:nth-of-type(1) {
font-weight: bold;
width: 100px;
}
th, td {
padding: 10px;
}
tr:nth-child(even) {
background: #f0f0f0;
}
tr:nth-child(odd) {
background: #fff;
}
tr:hover {
background: #f0f0f0;
}
th {
background: #f0f0f0;
}
}
.toaster {
position: fixed;
right: 16px;
@ -353,7 +463,11 @@ table{
&.success {
background: greenyellow;
}
&.info {
background: cornflowerblue;
}
}

View file

@ -13,6 +13,7 @@ import { OsmAuth } from '../../services/osm-auth';
import {Osm} from '../../forms/osm/osm';
import {WhatFilterComponent} from '../../shared/what-filter/what-filter';
import {NgClass} from '@angular/common';
@Component({
selector: 'app-home',
standalone: true,
@ -42,7 +43,7 @@ export class Home implements OnInit, OnDestroy {
showTable = false;
showFilters = false;
showEditForm = false;
showOptions = true;
showOptions = false;
pleinAirMode = false;
civilianMode = false;
toasts: Array<{ id: number, type: 'success' | 'error' | 'info', message: string }> = [];
@ -88,14 +89,17 @@ export class Home implements OnInit, OnDestroy {
unlocatedOrOnline: Array<any> = [];
showUnlocatedList = false;
protected showQuickActions: boolean = true;
firstToastDone = 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 || '');
const d = e?.detail || {};
this.pushToast(d.type || 'info', d.message || '');
});
} catch {}
} catch {
}
// Initialiser la bbox par défaut pour l'Île-de-France
this.currentBbox = {...this.IDF_BBOX};
@ -118,11 +122,18 @@ export class Home implements OnInit, OnDestroy {
this.selectedWhatFilter = what;
}
// Activer mode plein air via query param
if (pleinAir === '1' || pleinAir === 'true' || pleinAir === 'yes') {
this.enablePleinAirMode();
}
// if (pleinAir === '1' || pleinAir === 'true' || pleinAir === 'yes') {
// this.enablePleinAirMode();
// }
// Support: preset=plein_air
if (preset === 'plein_air') {
if (!this.firstToastDone) {
this.selectedWhatFilter = "traffic"
this.pushToast('info', "mode plein air activé")
this.useBboxFilter = true;
this.loadEvents({ what: 'traffic' });
}
this.firstToastDone = true
this.enablePleinAirMode();
}
});
@ -315,7 +326,7 @@ export class Home implements OnInit, OnDestroy {
}
enablePleinAirMode() {
this.pushToast('info', "mode plein air activé")
if (!this.pleinAirMode) {
this.pleinAirMode = true;
this.applyFilters();
@ -341,6 +352,13 @@ export class Home implements OnInit, OnDestroy {
// Ensuite, l'utilisateur clique sur la carte: voir onPickCoords()
// this.showEditForm = true;
}
cancelSubmitPreset(){
this.selected = null;
this.presetMoreDetails = ''
this.showGuidePresetMoreInfo = false
this.showGuidePresetPlace = false;
this.showQuickActions = true;
}
submitPreset() {
const now = new Date();
const w = this.selected.properties.what;
@ -367,11 +385,14 @@ export class Home implements OnInit, OnDestroy {
this.selected = null;
this.presetMoreDetails = ''
this.showGuidePresetMoreInfo = false
this.showGuidePresetPlace = false;
// Après création rapide en plein air: recharger uniquement ce type pour feedback instantané
this.selectedWhatFilter = w;
this.loadEvents({what: 'traffic'});
},
error: () => { this.pushToast('error', 'Échec de création'); }
error: () => {
this.pushToast('error', 'Échec de création');
}
});
}
@ -382,6 +403,7 @@ export class Home implements OnInit, OnDestroy {
onSelect(feature: any) {
this.selected = feature;
}
onSelectFromCalendarView(feature: any) {
this.selected = feature;
this.showEditForm = false;
@ -469,9 +491,11 @@ export class Home implements OnInit, OnDestroy {
startRectSelection() {
this.selectionMode = this.selectionMode === 'rectangle' ? 'none' : 'rectangle';
}
startPolySelection() {
this.selectionMode = this.selectionMode === 'polygon' ? 'none' : 'polygon';
}
clearSelection() {
this.selectionMode = 'none';
this.selectedIds = [];
@ -490,12 +514,21 @@ export class Home implements OnInit, OnDestroy {
const doUpdate = async (id: string | number, updater: (f: any) => any) => {
const feature = this.features.find(f => (f?.properties?.id ?? f?.id) === id);
if (!feature) { failed++; return; }
if (!feature) {
failed++;
return;
}
const updated = updater(feature);
await new Promise<void>((resolve) => {
this.OedbApi.updateEvent(id, updated).subscribe({
next: () => { success++; resolve(); },
error: (err) => { (err?.status === 0 ? networkErrors++ : failed++); resolve(); }
next: () => {
success++;
resolve();
},
error: (err) => {
(err?.status === 0 ? networkErrors++ : failed++);
resolve();
}
});
});
};
@ -503,7 +536,15 @@ export class Home implements OnInit, OnDestroy {
if (this.batchAction === 'delete') {
for (const id of this.selectedIds) {
await new Promise<void>((resolve) => {
this.OedbApi.deleteEvent(id).subscribe({ next: () => { success++; resolve(); }, error: (err) => { (err?.status === 0 ? networkErrors++ : failed++); resolve(); } });
this.OedbApi.deleteEvent(id).subscribe({
next: () => {
success++;
resolve();
}, error: (err) => {
(err?.status === 0 ? networkErrors++ : failed++);
resolve();
}
});
});
}
} else if (this.batchAction === 'changeWhat') {
@ -516,7 +557,10 @@ export class Home implements OnInit, OnDestroy {
const key = this.batchFieldKey.trim();
if (!key) return;
for (const id of this.selectedIds) {
await doUpdate(id, (feature: any) => ({ ...feature, properties: { ...feature.properties, [key]: this.batchFieldValue } }));
await doUpdate(id, (feature: any) => ({
...feature,
properties: {...feature.properties, [key]: this.batchFieldValue}
}));
}
}
@ -578,7 +622,11 @@ export class Home implements OnInit, OnDestroy {
private buildSubthemes() {
const t = this.theme();
if (!t) { this.subthemes = []; this.activeSubtheme.set(null); return; }
if (!t) {
this.subthemes = [];
this.activeSubtheme.set(null);
return;
}
const what = oedb.presets.what as Record<string, any>;
const list: Array<{ key: string, label: string, emoji: string }> = [];
Object.keys(what).forEach(k => {
@ -592,7 +640,10 @@ export class Home implements OnInit, OnDestroy {
}
downloadGeoJSON() {
const blob = new Blob([JSON.stringify({ type: 'FeatureCollection', features: this.filteredFeatures }, null, 2)], { type: 'application/geo+json' });
const blob = new Blob([JSON.stringify({
type: 'FeatureCollection',
features: this.filteredFeatures
}, null, 2)], {type: 'application/geo+json'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
@ -663,6 +714,7 @@ export class Home implements OnInit, OnDestroy {
guidePresetMoreInfoPseudo: string = '';
presetMoreDetails: string = '';
selectedPreset: string = '';
onMapMove(bbox: { minLng: number, minLat: number, maxLng: number, maxLat: number }) {
this.setCurrentBbox(bbox);
}

View file

@ -131,6 +131,13 @@ label { font-size: 0.85rem; color: $color-muted; }
.search{
width: 20%;
.btn{
padding: 1rem 1.25rem;
cursor: pointer;
height: 2.7rem;
line-height: 0.7rem;
margin-top: 0.15rem;
}
}
.aside{
@ -246,3 +253,29 @@ nav{
background: linear-gradient( 135deg, #5982b1, #6992c1);
}
}
.main{
nav{
background: $color-text ;
a {
color: white;
&:hover{
background: white;
color: $color-text;
}
}
}
.content {
main{
height: calc(100vh - 0.1rem);
overflow: hidden;
}
}
}
.maplibregl-ctrl-attrib{
position: fixed;
bottom: 0 ;
right: 0;
}