From 5d636b00279ec609a004b2ac9596574fe98d3694 Mon Sep 17 00:00:00 2001 From: Tykayn Date: Sun, 2 Nov 2025 23:54:35 +0100 Subject: [PATCH] filtre agenda, page de stats, queryparam add --- frontend/src/app/app.html | 2 +- frontend/src/app/app.routes.ts | 5 + .../src/app/forms/edit-form/edit-form.html | 5 + .../src/app/forms/edit-form/edit-form.scss | 17 + frontend/src/app/forms/edit-form/edit-form.ts | 46 +- frontend/src/app/pages/agenda/agenda.html | 161 ++++- frontend/src/app/pages/agenda/agenda.scss | 384 +++++++++++- frontend/src/app/pages/agenda/agenda.ts | 577 +++++++++++++++++- .../app/pages/agenda/calendar/calendar.html | 172 +++++- .../app/pages/agenda/calendar/calendar.scss | 360 +++++++++++ .../src/app/pages/agenda/calendar/calendar.ts | 180 +++++- frontend/src/app/pages/home/home.html | 12 +- frontend/src/app/pages/home/home.ts | 139 ++++- frontend/src/app/pages/home/menu/menu.html | 2 +- frontend/src/app/pages/stats/stats.html | 131 ++++ frontend/src/app/pages/stats/stats.scss | 353 +++++++++++ frontend/src/app/pages/stats/stats.spec.ts | 23 + frontend/src/app/pages/stats/stats.ts | 298 +++++++++ frontend/src/oedb-types.ts | 6 + frontend/src/styles.scss | 2 +- 20 files changed, 2800 insertions(+), 75 deletions(-) create mode 100644 frontend/src/app/pages/stats/stats.html create mode 100644 frontend/src/app/pages/stats/stats.scss create mode 100644 frontend/src/app/pages/stats/stats.spec.ts create mode 100644 frontend/src/app/pages/stats/stats.ts diff --git a/frontend/src/app/app.html b/frontend/src/app/app.html index deeb430..c2d8a52 100644 --- a/frontend/src/app/app.html +++ b/frontend/src/app/app.html @@ -31,7 +31,7 @@ events docs research nouvelles catégories - stats + stats sources diff --git a/frontend/src/app/app.routes.ts b/frontend/src/app/app.routes.ts index 0f38507..10b7184 100644 --- a/frontend/src/app/app.routes.ts +++ b/frontend/src/app/app.routes.ts @@ -8,6 +8,7 @@ import { NouvellesCategories } from './pages/nouvelles-categories/nouvelles-cate import { UnlocatedEventsPage } from './pages/unlocated-events/unlocated-events'; import { CommunityUpcoming } from './pages/community-upcoming/community-upcoming'; import { EventsDocs } from './pages/events-docs/events-docs'; +import { Stats } from './pages/stats/stats'; export const routes: Routes = [ { @@ -34,6 +35,10 @@ export const routes: Routes = [ path: 'embed', component: Embed }, + { + path: 'stats', + component: Stats + }, { path: 'batch-edit', component: BatchEdit diff --git a/frontend/src/app/forms/edit-form/edit-form.html b/frontend/src/app/forms/edit-form/edit-form.html index 6a08a89..937412a 100644 --- a/frontend/src/app/forms/edit-form/edit-form.html +++ b/frontend/src/app/forms/edit-form/edit-form.html @@ -7,6 +7,11 @@ Presets ({{filteredPresetCount()}}) + @if (presetFilterPrefix) { + + }
@for (g of filteredGroups(); track g.category) { diff --git a/frontend/src/app/forms/edit-form/edit-form.scss b/frontend/src/app/forms/edit-form/edit-form.scss index 1da5abf..664338c 100644 --- a/frontend/src/app/forms/edit-form/edit-form.scss +++ b/frontend/src/app/forms/edit-form/edit-form.scss @@ -51,3 +51,20 @@ form { .group-title { font-weight: 700; opacity: 0.8; margin-bottom: 6px; } .group { background: #fff; border: 1px solid rgba(0,0,0,0.06); border-radius: 10px; padding: 8px; } +.btn-reset-filter { + margin-left: 10px; + padding: 4px 12px; + background: #667eea; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 0.85rem; + transition: all 0.2s ease; +} + +.btn-reset-filter:hover { + background: #5a67d8; + transform: translateY(-1px); +} + diff --git a/frontend/src/app/forms/edit-form/edit-form.ts b/frontend/src/app/forms/edit-form/edit-form.ts index e28af89..e09b74d 100644 --- a/frontend/src/app/forms/edit-form/edit-form.ts +++ b/frontend/src/app/forms/edit-form/edit-form.ts @@ -20,7 +20,11 @@ export class EditForm implements OnChanges { form: FormGroup; allPresets: Array<{ key: string, label: string, emoji: string, category: string, description?: string, durationHours?: number, properties?: Record }>; - filteredGroups = computed(() => this.groupPresets(this.form.get('what')?.value || '')); + filteredGroups = computed(() => { + // Inclure presetFilterPrefix dans la dépendance du computed pour qu'il se mette à jour + const _ = this.presetFilterPrefix; + return this.groupPresets(this.form.get('what')?.value || ''); + }); currentPreset = computed(() => { const key = this.form.get('what')?.value || ''; return (oedb.presets.what as any)[key] || null; @@ -172,9 +176,31 @@ export class EditForm implements OnChanges { this.extraPropertyKeys.set(extra); } + presetFilterPrefix: string | null = null; + private groupPresets(query: string): Array<{ category: string, items: Array<{ key: string, label: string, emoji: string }> }> { const q = String(query || '').trim().toLowerCase(); + const filterPrefix = this.presetFilterPrefix ? this.presetFilterPrefix.toLowerCase() : null; + const matches = (p: typeof this.allPresets[number]) => { + // Si un préfixe de filtre est défini, filtrer par ce préfixe + if (filterPrefix) { + const keyLower = p.key.toLowerCase(); + // Soit correspondance exacte, soit commence par le préfixe suivi d'un point + if (keyLower === filterPrefix || keyLower.startsWith(filterPrefix + '.')) { + // Si une query est aussi présente, appliquer aussi ce filtre + if (!q) return true; + return ( + keyLower.includes(q) || + (p.label || '').toLowerCase().includes(q) || + (p.description || '').toLowerCase().includes(q) || + (p.category || '').toLowerCase().includes(q) + ); + } + return false; + } + + // Comportement normal sans filtre de préfixe if (!q) return true; return ( p.key.toLowerCase().includes(q) || @@ -357,10 +383,26 @@ export class EditForm implements OnChanges { } resetPresetFilter() { - // Réinitialise le champ what pour afficher tous les presets + // Réinitialise le champ what et le filtre de préfixe pour afficher tous les presets + this.presetFilterPrefix = null; this.form.patchValue({ what: '' }); } + private _filterByPrefix: string | null = null; + + @Input() set filterByPrefix(prefix: string | null) { + this._filterByPrefix = prefix; + this.presetFilterPrefix = prefix; + // Si un préfixe est défini et que le champ what est vide, pré-remplir avec le préfixe + if (prefix && !this.form.get('what')?.value) { + this.form.patchValue({ what: prefix }, { emitEvent: false }); + } + } + + get filterByPrefix(): string | null { + return this._filterByPrefix; + } + onCancelEdit() { this.selected = null; diff --git a/frontend/src/app/pages/agenda/agenda.html b/frontend/src/app/pages/agenda/agenda.html index 8625554..d38720c 100644 --- a/frontend/src/app/pages/agenda/agenda.html +++ b/frontend/src/app/pages/agenda/agenda.html @@ -14,6 +14,58 @@ {{filteredCalendarEvents.length}} évènements