style marqueurs events, page nouvelles catégories

This commit is contained in:
Tykayn 2025-10-04 16:14:42 +02:00 committed by tykayn
parent 20a8445a5f
commit 9fb9986a2c
15 changed files with 987 additions and 203 deletions

View file

@ -1,9 +1,12 @@
import { Component, inject, OnInit } from '@angular/core';
import { Component, inject, OnInit, ViewChild, TemplateRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OedbApi } from '../../services/oedb-api';
import { EditForm } from '../../forms/edit-form/edit-form';
import { CalendarModule, CalendarView, CalendarEvent } from 'angular-calendar';
import { CalendarEventAction, CalendarEventTimesChangedEvent } from 'angular-calendar';
import oedb from '../../../oedb-types';
interface Event {
interface OedbEvent {
id: string;
properties: {
label?: string;
@ -23,23 +26,31 @@ interface Event {
interface DayEvents {
date: Date;
events: Event[];
events: OedbEvent[];
}
@Component({
selector: 'app-agenda',
standalone: true,
imports: [CommonModule, EditForm],
imports: [CommonModule, EditForm, CalendarModule],
templateUrl: './agenda.html',
styleUrl: './agenda.scss'
})
export class Agenda implements OnInit {
private oedbApi = inject(OedbApi);
events: Event[] = [];
daysWithEvents: DayEvents[] = [];
selectedEvent: Event | null = null;
@ViewChild('eventTitleTemplate', { static: true }) eventTitleTemplate!: TemplateRef<any>;
events: OedbEvent[] = [];
calendarEvents: CalendarEvent[] = [];
selectedEvent: OedbEvent | null = null;
showSidePanel = false;
view: CalendarView = CalendarView.Month;
viewDate: Date = new Date();
oedbPresets = oedb.presets.what;
// Exposer CalendarView pour l'utiliser dans le template
CalendarView = CalendarView;
ngOnInit() {
this.loadEvents();
@ -66,37 +77,24 @@ export class Agenda implements OnInit {
}
organizeEventsByDay() {
const daysMap = new Map<string, DayEvents>();
// Initialiser les 20 jours
for (let i = -10; i <= 10; i++) {
const date = new Date();
date.setDate(date.getDate() + i);
const dateKey = date.toISOString().split('T')[0];
daysMap.set(dateKey, {
date: new Date(date),
events: []
});
}
// Organiser les événements par jour
this.events.forEach(event => {
this.calendarEvents = this.events.map(event => {
const eventDate = this.getEventDate(event);
if (eventDate) {
const dateKey = eventDate.toISOString().split('T')[0];
const dayEvents = daysMap.get(dateKey);
if (dayEvents) {
dayEvents.events.push(event);
const preset = this.getEventPreset(event);
return {
id: event.id,
title: this.getEventTitle(event),
start: eventDate || new Date(),
color: this.getEventColor(preset),
meta: {
event: event,
preset: preset
}
}
};
});
this.daysWithEvents = Array.from(daysMap.values()).sort((a, b) =>
a.date.getTime() - b.date.getTime()
);
}
getEventDate(event: Event): Date | null {
getEventDate(event: OedbEvent): Date | null {
const startDate = event.properties.start || event.properties.when;
if (startDate) {
return new Date(startDate);
@ -104,11 +102,11 @@ export class Agenda implements OnInit {
return null;
}
getEventTitle(event: Event): string {
getEventTitle(event: OedbEvent): string {
return event.properties.label || event.properties.name || 'Événement sans titre';
}
getEventTime(event: Event): string {
getEventTime(event: OedbEvent): string {
const startDate = event.properties.start || event.properties.when;
if (startDate) {
const date = new Date(startDate);
@ -120,11 +118,55 @@ export class Agenda implements OnInit {
return '';
}
selectEvent(event: Event) {
selectEvent(event: OedbEvent) {
this.selectedEvent = event;
this.showSidePanel = true;
}
onEventClicked({ event }: { event: CalendarEvent; sourceEvent: MouseEvent | KeyboardEvent }) {
if (event.meta && event.meta.event) {
this.selectEvent(event.meta.event);
}
}
getEventPreset(event: OedbEvent): any {
const what = event.properties.what;
if (what && (this.oedbPresets as any)[what]) {
return (this.oedbPresets as any)[what];
}
return null;
}
getEventIcon(preset: any): string {
if (preset) {
return preset.emoji || '📅';
}
return '📅';
}
getEventColor(preset: any): any {
if (preset) {
// Couleurs basées sur la catégorie
const categoryColors: { [key: string]: any } = {
'Communauté': { primary: '#007bff', secondary: '#cce7ff' },
'Culture': { primary: '#28a745', secondary: '#d4edda' },
'Musique': { primary: '#ffc107', secondary: '#fff3cd' },
'Énergie': { primary: '#dc3545', secondary: '#f8d7da' },
'Commerce': { primary: '#6f42c1', secondary: '#e2d9f3' },
'Temps': { primary: '#17a2b8', secondary: '#d1ecf1' },
'Tourisme': { primary: '#fd7e14', secondary: '#ffeaa7' },
'Circulation': { primary: '#6c757d', secondary: '#e9ecef' },
'Randonnée': { primary: '#20c997', secondary: '#d1f2eb' },
'Vie sauvage': { primary: '#795548', secondary: '#efebe9' },
'Météo': { primary: '#2196f3', secondary: '#e3f2fd' }
};
const category = preset.category || 'Communauté';
return categoryColors[category] || { primary: '#6c757d', secondary: '#e9ecef' };
}
return { primary: '#6c757d', secondary: '#e9ecef' };
}
closeSidePanel() {
this.showSidePanel = false;
this.selectedEvent = null;
@ -145,22 +187,19 @@ export class Agenda implements OnInit {
this.closeSidePanel();
}
isToday(date: Date): boolean {
const today = new Date();
return date.toDateString() === today.toDateString();
setView(view: CalendarView) {
this.view = view;
}
isPast(date: Date): boolean {
const today = new Date();
today.setHours(0, 0, 0, 0);
return date < today;
dayClicked({ date, events }: { date: Date; events: CalendarEvent[] }): void {
console.log('Day clicked:', date, events);
}
formatDate(date: Date): string {
return date.toLocaleDateString('fr-FR', {
weekday: 'long',
day: 'numeric',
month: 'long'
});
eventTimesChanged({
event,
newStart,
newEnd,
}: CalendarEventTimesChangedEvent): void {
console.log('Event times changed:', event, newStart, newEnd);
}
}