Updates mock event data to reflect a more recent week and includes events spanning early/late hours. Enhances event rendering by adjusting the top and height styles for better visual appearance. Refactors CSS to improve grid line display and event hover effects, and moves hour marker styles to a more appropriate CSS file. Provides default fallback values for time boundaries using CSS variables.
264 lines
No EOL
8 KiB
TypeScript
264 lines
No EOL
8 KiB
TypeScript
import { EventBus } from '../core/EventBus';
|
|
import { IEventBus, CalendarEvent } from '../types/CalendarTypes';
|
|
import { EventTypes } from '../constants/EventTypes';
|
|
|
|
/**
|
|
* EventManager - Administrerer event lifecycle og CRUD operationer
|
|
* Håndterer mock data og event synchronization
|
|
*/
|
|
export class EventManager {
|
|
private eventBus: IEventBus;
|
|
private events: CalendarEvent[] = [];
|
|
|
|
constructor(eventBus: IEventBus) {
|
|
this.eventBus = eventBus;
|
|
this.setupEventListeners();
|
|
this.loadMockData();
|
|
}
|
|
|
|
private setupEventListeners(): void {
|
|
this.eventBus.on(EventTypes.CALENDAR_INITIALIZED, () => {
|
|
this.syncEvents();
|
|
});
|
|
|
|
this.eventBus.on(EventTypes.DATE_CHANGED, () => {
|
|
this.syncEvents();
|
|
});
|
|
|
|
this.eventBus.on(EventTypes.VIEW_RENDERED, () => {
|
|
this.syncEvents();
|
|
});
|
|
}
|
|
|
|
private loadMockData(): void {
|
|
// Mock events for current week (July 27 - August 2, 2025)
|
|
this.events = [
|
|
// Sunday August 3, 2025
|
|
{
|
|
id: '1',
|
|
title: 'Weekend Planning',
|
|
start: '2025-08-03T10:00:00',
|
|
end: '2025-08-03T11:00:00',
|
|
type: 'work',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 60 }
|
|
},
|
|
// Monday August 4, 2025
|
|
{
|
|
id: '2',
|
|
title: 'Team Standup',
|
|
start: '2025-08-04T09:00:00',
|
|
end: '2025-08-04T09:30:00',
|
|
type: 'meeting',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 30 }
|
|
},
|
|
{
|
|
id: '3',
|
|
title: 'Project Kickoff',
|
|
start: '2025-08-04T14:00:00',
|
|
end: '2025-08-04T15:30:00',
|
|
type: 'meeting',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 90 }
|
|
},
|
|
// Tuesday August 5, 2025
|
|
{
|
|
id: '4',
|
|
title: 'Deep Work Session',
|
|
start: '2025-08-05T10:00:00',
|
|
end: '2025-08-05T12:00:00',
|
|
type: 'work',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 120 }
|
|
},
|
|
{
|
|
id: '5',
|
|
title: 'Lunch Meeting',
|
|
start: '2025-08-05T12:30:00',
|
|
end: '2025-08-05T13:30:00',
|
|
type: 'meal',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 60 }
|
|
},
|
|
// Wednesday August 6, 2025
|
|
{
|
|
id: '6',
|
|
title: 'Client Review',
|
|
start: '2025-08-06T15:00:00',
|
|
end: '2025-08-06T16:00:00',
|
|
type: 'meeting',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 60 }
|
|
},
|
|
// Thursday August 7, 2025
|
|
{
|
|
id: '7',
|
|
title: 'Sprint Planning',
|
|
start: '2025-08-07T09:00:00',
|
|
end: '2025-08-07T10:30:00',
|
|
type: 'meeting',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 90 }
|
|
},
|
|
{
|
|
id: '8',
|
|
title: 'Code Review',
|
|
start: '2025-08-07T14:00:00',
|
|
end: '2025-08-07T15:00:00',
|
|
type: 'work',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 60 }
|
|
},
|
|
// Friday August 8, 2025
|
|
{
|
|
id: '9',
|
|
title: 'Team Standup',
|
|
start: '2025-08-08T09:00:00',
|
|
end: '2025-08-08T09:30:00',
|
|
type: 'meeting',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 30 }
|
|
},
|
|
{
|
|
id: '10',
|
|
title: 'Client Meeting',
|
|
start: '2025-08-08T14:00:00',
|
|
end: '2025-08-08T15:30:00',
|
|
type: 'meeting',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 90 }
|
|
},
|
|
// Saturday August 9, 2025
|
|
{
|
|
id: '11',
|
|
title: 'Weekend Project',
|
|
start: '2025-08-09T10:00:00',
|
|
end: '2025-08-09T12:00:00',
|
|
type: 'work',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 120 }
|
|
},
|
|
// Test events for early/late hours
|
|
{
|
|
id: '12',
|
|
title: 'Early Morning Workout',
|
|
start: '2025-08-05T06:00:00',
|
|
end: '2025-08-05T07:00:00',
|
|
type: 'work',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 60 }
|
|
},
|
|
{
|
|
id: '13',
|
|
title: 'Late Evening Call',
|
|
start: '2025-08-06T21:00:00',
|
|
end: '2025-08-06T22:00:00',
|
|
type: 'meeting',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 60 }
|
|
},
|
|
{
|
|
id: '14',
|
|
title: 'Midnight Deployment',
|
|
start: '2025-08-07T23:00:00',
|
|
end: '2025-08-08T01:00:00',
|
|
type: 'work',
|
|
allDay: false,
|
|
syncStatus: 'synced',
|
|
metadata: { duration: 120 }
|
|
}
|
|
];
|
|
|
|
console.log(`EventManager: Loaded ${this.events.length} mock events`);
|
|
console.log('EventManager: First event:', this.events[0]);
|
|
console.log('EventManager: Last event:', this.events[this.events.length - 1]);
|
|
}
|
|
|
|
private syncEvents(): void {
|
|
// Emit events for rendering
|
|
this.eventBus.emit(EventTypes.EVENTS_LOADED, {
|
|
events: this.events
|
|
});
|
|
|
|
console.log(`EventManager: Synced ${this.events.length} events`);
|
|
}
|
|
|
|
public getEvents(): CalendarEvent[] {
|
|
return [...this.events];
|
|
}
|
|
|
|
|
|
public getEventById(id: string): CalendarEvent | undefined {
|
|
return this.events.find(event => event.id === id);
|
|
}
|
|
|
|
public addEvent(event: Omit<CalendarEvent, 'id'>): CalendarEvent {
|
|
const newEvent: CalendarEvent = {
|
|
...event,
|
|
id: Date.now().toString()
|
|
};
|
|
|
|
this.events.push(newEvent);
|
|
this.syncEvents();
|
|
|
|
this.eventBus.emit(EventTypes.EVENT_CREATED, {
|
|
event: newEvent
|
|
});
|
|
|
|
return newEvent;
|
|
}
|
|
|
|
public updateEvent(id: string, updates: Partial<CalendarEvent>): CalendarEvent | null {
|
|
const eventIndex = this.events.findIndex(event => event.id === id);
|
|
if (eventIndex === -1) return null;
|
|
|
|
const updatedEvent = { ...this.events[eventIndex], ...updates };
|
|
this.events[eventIndex] = updatedEvent;
|
|
|
|
this.syncEvents();
|
|
|
|
this.eventBus.emit(EventTypes.EVENT_UPDATED, {
|
|
event: updatedEvent
|
|
});
|
|
|
|
return updatedEvent;
|
|
}
|
|
|
|
public deleteEvent(id: string): boolean {
|
|
const eventIndex = this.events.findIndex(event => event.id === id);
|
|
if (eventIndex === -1) return false;
|
|
|
|
const deletedEvent = this.events[eventIndex];
|
|
this.events.splice(eventIndex, 1);
|
|
|
|
this.syncEvents();
|
|
|
|
this.eventBus.emit(EventTypes.EVENT_DELETED, {
|
|
event: deletedEvent
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
public refresh(): void {
|
|
this.syncEvents();
|
|
}
|
|
|
|
public destroy(): void {
|
|
this.events = [];
|
|
}
|
|
} |