From 28ed131b9e8b77bc71c894a87997a29781518743 Mon Sep 17 00:00:00 2001 From: Janus Knudsen Date: Sat, 2 Aug 2025 23:59:52 +0200 Subject: [PATCH] wip --- src/managers/EventManager.ts | 121 +++++++++++----------------- src/managers/EventRenderer.ts | 107 +++++++++++++++++++++--- src/managers/GridManager.ts | 8 +- wwwroot/css/calendar-base-css.css | 2 +- wwwroot/css/calendar-layout-css.css | 2 +- wwwroot/css/calendar.css | 1 - 6 files changed, 151 insertions(+), 90 deletions(-) diff --git a/src/managers/EventManager.ts b/src/managers/EventManager.ts index 5fe6c04..592fe16 100644 --- a/src/managers/EventManager.ts +++ b/src/managers/EventManager.ts @@ -31,10 +31,22 @@ export class EventManager { } private loadMockData(): void { - // Mock events baseret på POC data med korrekt CalendarEvent struktur + // Mock events for current week (July 27 - August 2, 2025) this.events = [ + // Sunday July 27, 2025 { id: '1', + title: 'Weekend Planning', + start: '2025-07-27T10:00:00', + end: '2025-07-27T11:00:00', + type: 'work', + allDay: false, + syncStatus: 'synced', + metadata: { duration: 60 } + }, + // Monday July 28, 2025 + { + id: '2', title: 'Team Standup', start: '2025-07-28T09:00:00', end: '2025-07-28T09:30:00', @@ -44,8 +56,8 @@ export class EventManager { metadata: { duration: 30 } }, { - id: '2', - title: 'Client Meeting', + id: '3', + title: 'Project Kickoff', start: '2025-07-28T14:00:00', end: '2025-07-28T15:30:00', type: 'meeting', @@ -53,16 +65,7 @@ export class EventManager { syncStatus: 'synced', metadata: { duration: 90 } }, - { - id: '3', - title: 'Lunch', - start: '2025-07-28T12:00:00', - end: '2025-07-28T13:00:00', - type: 'meal', - allDay: false, - syncStatus: 'synced', - metadata: { duration: 60 } - }, + // Tuesday July 29, 2025 { id: '4', title: 'Deep Work Session', @@ -75,17 +78,7 @@ export class EventManager { }, { id: '5', - title: 'Team Standup', - start: '2025-07-29T09:00:00', - end: '2025-07-29T09:30:00', - type: 'meeting', - allDay: false, - syncStatus: 'synced', - metadata: { duration: 30 } - }, - { - id: '6', - title: 'Lunch', + title: 'Lunch Meeting', start: '2025-07-29T12:30:00', end: '2025-07-29T13:30:00', type: 'meal', @@ -93,9 +86,10 @@ export class EventManager { syncStatus: 'synced', metadata: { duration: 60 } }, + // Wednesday July 30, 2025 { - id: '7', - title: 'Project Review', + id: '6', + title: 'Client Review', start: '2025-07-30T15:00:00', end: '2025-07-30T16:00:00', type: 'meeting', @@ -103,71 +97,54 @@ export class EventManager { syncStatus: 'synced', metadata: { duration: 60 } }, + // Thursday July 31, 2025 + { + id: '7', + title: 'Sprint Planning', + start: '2025-07-31T09:00:00', + end: '2025-07-31T10:30:00', + type: 'meeting', + allDay: false, + syncStatus: 'synced', + metadata: { duration: 90 } + }, { id: '8', - title: 'Lunch', - start: '2025-07-30T12:00:00', - end: '2025-07-30T13:00:00', - type: 'meal', + title: 'Code Review', + start: '2025-07-31T14:00:00', + end: '2025-07-31T15:00:00', + type: 'work', allDay: false, syncStatus: 'synced', metadata: { duration: 60 } }, + // Friday August 1, 2025 { id: '9', - title: 'Sprint Planning', - start: '2025-07-31T10:00:00', - end: '2025-07-31T12:00:00', + title: 'Team Standup', + start: '2025-08-01T09:00:00', + end: '2025-08-01T09:30:00', type: 'meeting', allDay: false, syncStatus: 'synced', - metadata: { duration: 120 } - }, - { - id: '10', - title: 'Coffee Break', - start: '2025-07-31T15:00:00', - end: '2025-07-31T15:30:00', - type: 'meal', - allDay: false, - syncStatus: 'synced', metadata: { duration: 30 } }, { - id: '11', - title: 'Documentation', - start: '2025-08-01T13:00:00', - end: '2025-08-01T16:00:00', - type: 'work', - allDay: false, - syncStatus: 'synced', - metadata: { duration: 180 } - }, - { - id: '12', - title: 'Early Morning Workout', - start: '2025-07-29T06:00:00', - end: '2025-07-29T07:00:00', - type: 'work', - allDay: false, - syncStatus: 'synced', - metadata: { duration: 60 } - }, - { - id: '13', - title: 'Late Evening Call', - start: '2025-07-30T21:00:00', - end: '2025-07-30T22:00:00', + id: '10', + title: 'Client Meeting', + start: '2025-08-01T14:00:00', + end: '2025-08-01T15:30:00', type: 'meeting', allDay: false, syncStatus: 'synced', - metadata: { duration: 60 } + metadata: { duration: 90 } }, + // Saturday August 2, 2025 { - id: '14', - title: 'Midnight Release', - start: '2025-07-31T23:00:00', - end: '2025-08-01T01:00:00', + id: '11', + title: 'Weekend Project', + start: '2025-08-02T10:00:00', + end: '2025-08-02T12:00:00', type: 'work', allDay: false, syncStatus: 'synced', diff --git a/src/managers/EventRenderer.ts b/src/managers/EventRenderer.ts index 9ab3567..61ca05b 100644 --- a/src/managers/EventRenderer.ts +++ b/src/managers/EventRenderer.ts @@ -2,6 +2,7 @@ import { EventBus } from '../core/EventBus'; import { IEventBus, CalendarEvent } from '../types/CalendarTypes'; import { EventTypes } from '../constants/EventTypes'; import { calendarConfig } from '../core/CalendarConfig'; +import { DateUtils } from '../utils/DateUtils'; /** * EventRenderer - Render events i DOM med positionering @@ -52,13 +53,76 @@ export class EventRenderer { } private renderEvents(events: CalendarEvent[]): void { + console.log('EventRenderer: renderEvents called with', events.length, 'events'); + // Clear existing events first this.clearEvents(); - // For now, just emit event rendered - proper rendering will be implemented later - this.eventBus.emit(EventTypes.EVENT_RENDERED, { - count: events.length + // Get current week dates for filtering + const currentWeekDates = this.getCurrentWeekDates(); + console.log('EventRenderer: Current week dates:', currentWeekDates.map(d => DateUtils.formatDate(d))); + + // Filter events for current week + const currentWeekEvents = events.filter(event => { + const eventDate = new Date(event.start); + const eventDateStr = DateUtils.formatDate(eventDate); + const isInCurrentWeek = currentWeekDates.some(weekDate => + DateUtils.formatDate(weekDate) === eventDateStr + ); + console.log('EventRenderer: Event', event.title, 'on', eventDateStr, 'is in current week:', isInCurrentWeek); + return isInCurrentWeek; }); + + console.log('EventRenderer: Rendering', currentWeekEvents.length, 'events for current week'); + + // Render each event in the correct day column + currentWeekEvents.forEach(event => { + const eventDate = new Date(event.start); + const dayColumn = this.findDayColumn(eventDate); + + if (dayColumn) { + const eventsLayer = dayColumn.querySelector('swp-events-layer'); + if (eventsLayer) { + console.log('EventRenderer: Rendering event', event.title, 'in day column for', DateUtils.formatDate(eventDate)); + this.renderEvent(event, eventsLayer); + } else { + console.warn('EventRenderer: No events layer found in day column for', DateUtils.formatDate(eventDate)); + } + } else { + console.warn('EventRenderer: No day column found for event date', DateUtils.formatDate(eventDate)); + } + }); + + // Emit event rendered + this.eventBus.emit(EventTypes.EVENT_RENDERED, { + count: currentWeekEvents.length + }); + } + + /** + * Get current week dates (Sunday to Saturday) + */ + private getCurrentWeekDates(): Date[] { + const today = new Date(); + const weekStart = DateUtils.getWeekStart(today, 0); // Sunday start + const dates: Date[] = []; + + for (let i = 0; i < 7; i++) { + const date = DateUtils.addDays(weekStart, i); + dates.push(date); + } + + return dates; + } + + /** + * Find day column for specific date + */ + private findDayColumn(date: Date): HTMLElement | null { + const dateStr = DateUtils.formatDate(date); + const dayColumn = document.querySelector(`swp-day-column[data-date="${dateStr}"]`) as HTMLElement; + console.log('EventRenderer: Looking for day column with date', dateStr, 'found:', !!dayColumn); + return dayColumn; } private renderEvent(event: CalendarEvent, container: Element): void { @@ -95,17 +159,42 @@ export class EventRenderer { const startDate = new Date(event.start); const endDate = new Date(event.end); - const startHour = calendarConfig.get('dayStartHour'); + // Use dayStartHour to match time-axis positioning + const dayStartHour = calendarConfig.get('dayStartHour'); // 0 (midnight) const hourHeight = calendarConfig.get('hourHeight'); - // Calculate minutes from day start - const startMinutes = (startDate.getHours() - startHour) * 60 + startDate.getMinutes(); - const duration = (endDate.getTime() - startDate.getTime()) / (1000 * 60); // Duration in minutes + // Calculate minutes from day start (midnight) + const eventHour = startDate.getHours(); + const eventMinutes = startDate.getMinutes(); + const startMinutes = (eventHour - dayStartHour) * 60 + eventMinutes; + + // Calculate duration in minutes + const duration = (endDate.getTime() - startDate.getTime()) / (1000 * 60); - // Convert to pixels - const top = startMinutes * (hourHeight / 60); + // Convert to pixels - this gives absolute position from top of time-grid + const absoluteTop = startMinutes * (hourHeight / 60); const height = duration * (hourHeight / 60); + // Get current scroll position to adjust for viewport + const scrollableContent = document.querySelector('swp-scrollable-content') as HTMLElement; + const scrollTop = scrollableContent ? scrollableContent.scrollTop : 0; + + // Calculate relative position within the visible viewport + // Events are positioned relative to their day-column, not the scrollable content + // So we use the absolute position directly + const top = absoluteTop; + + console.log('EventRenderer: Position calculation for', event.title, { + eventTime: `${eventHour}:${eventMinutes.toString().padStart(2, '0')}`, + dayStartHour, + startMinutes, + duration, + absoluteTop, + scrollTop, + finalTop: top, + height + }); + return { top, height }; } diff --git a/src/managers/GridManager.ts b/src/managers/GridManager.ts index bf35d12..c7589be 100644 --- a/src/managers/GridManager.ts +++ b/src/managers/GridManager.ts @@ -40,12 +40,8 @@ export class GridManager { } private getWeekStart(date: Date): Date { - const weekStart = new Date(date); - const day = weekStart.getDay(); - const diff = weekStart.getDate() - day; // Sunday is 0 - weekStart.setDate(diff); - weekStart.setHours(0, 0, 0, 0); - return weekStart; + // Use DateUtils for consistent week calculation (Sunday = 0) + return DateUtils.getWeekStart(date, 0); } private findElements(): void { diff --git a/wwwroot/css/calendar-base-css.css b/wwwroot/css/calendar-base-css.css index 6c67e76..1e4bc1f 100644 --- a/wwwroot/css/calendar-base-css.css +++ b/wwwroot/css/calendar-base-css.css @@ -32,7 +32,7 @@ /* Grid colors */ --color-grid-line: #e0e0e0; --color-grid-line-light: rgba(0, 0, 0, 0.05); - --color-work-hours: rgba(0, 100, 0, 0.02); + --color-work-hours: rgba(0, 100, 0, 0.06); --color-current-time: #ff0000; /* Event colors */ diff --git a/wwwroot/css/calendar-layout-css.css b/wwwroot/css/calendar-layout-css.css index ebb0f92..0417420 100644 --- a/wwwroot/css/calendar-layout-css.css +++ b/wwwroot/css/calendar-layout-css.css @@ -303,7 +303,7 @@ swp-time-grid::before { /* Grid lines */ swp-grid-lines { position: absolute; - top: 0; + top: 15px; left: 0; right: 0; bottom: 0; diff --git a/wwwroot/css/calendar.css b/wwwroot/css/calendar.css index ecbdb62..796cfb8 100644 --- a/wwwroot/css/calendar.css +++ b/wwwroot/css/calendar.css @@ -213,7 +213,6 @@ swp-time-axis { position: sticky; left: 0; z-index: 4; - padding-top: 80px; /* Match header height */ } swp-hour-marker {