This commit is contained in:
Janus C. H. Knudsen 2025-10-06 21:39:57 +02:00
parent faa59f6a3c
commit 69495ce00f
9 changed files with 337 additions and 1306 deletions

View file

@ -1,167 +0,0 @@
/**
* MonthViewStrategy - Strategy for month view rendering
* Completely different from week view - no time axis, cell-based events
*/
import { ViewStrategy, ViewContext, ViewLayoutConfig } from './ViewStrategy';
import { DateService } from '../utils/DateService';
import { calendarConfig } from '../core/CalendarConfig';
import { CalendarEvent } from '../types/CalendarTypes';
export class MonthViewStrategy implements ViewStrategy {
private dateService: DateService;
constructor() {
this.dateService = new DateService('Europe/Copenhagen');
}
getLayoutConfig(): ViewLayoutConfig {
return {
needsTimeAxis: false, // No time axis in month view!
columnCount: 7, // Always 7 days (Mon-Sun)
scrollable: false, // Month fits in viewport
eventPositioning: 'cell-based' // Events go in day cells
};
}
renderGrid(context: ViewContext): void {
// Clear existing content
context.container.innerHTML = '';
// Create month grid (completely different from week!)
this.createMonthGrid(context);
}
private createMonthGrid(context: ViewContext): void {
const monthGrid = document.createElement('div');
monthGrid.className = 'month-grid';
monthGrid.style.display = 'grid';
monthGrid.style.gridTemplateColumns = 'repeat(7, 1fr)';
monthGrid.style.gridTemplateRows = 'auto repeat(6, 1fr)';
monthGrid.style.height = '100%';
// Add day headers (Mon, Tue, Wed, etc.)
this.createDayHeaders(monthGrid);
// Add 6 weeks of day cells
this.createDayCells(monthGrid, context.currentDate);
// Render events in day cells (will be handled by EventRendererManager)
// this.renderMonthEvents(monthGrid, context.allDayEvents);
context.container.appendChild(monthGrid);
}
private createDayHeaders(container: HTMLElement): void {
const dayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
dayNames.forEach(dayName => {
const header = document.createElement('div');
header.className = 'month-day-header';
header.textContent = dayName;
header.style.padding = '8px';
header.style.fontWeight = 'bold';
header.style.textAlign = 'center';
header.style.borderBottom = '1px solid #e0e0e0';
container.appendChild(header);
});
}
private createDayCells(container: HTMLElement, monthDate: Date): void {
const dates = this.getMonthDates(monthDate);
dates.forEach(date => {
const cell = document.createElement('div');
cell.className = 'month-day-cell';
cell.dataset.date = this.dateService.formatISODate(date);
cell.style.border = '1px solid #e0e0e0';
cell.style.minHeight = '100px';
cell.style.padding = '4px';
cell.style.position = 'relative';
// Day number
const dayNumber = document.createElement('div');
dayNumber.className = 'month-day-number';
dayNumber.textContent = date.getDate().toString();
dayNumber.style.fontWeight = 'bold';
dayNumber.style.marginBottom = '4px';
// Check if today
if (this.dateService.isSameDay(date, new Date())) {
dayNumber.style.color = '#1976d2';
cell.style.backgroundColor = '#f5f5f5';
}
cell.appendChild(dayNumber);
container.appendChild(cell);
});
}
private getMonthDates(monthDate: Date): Date[] {
// Get first day of month using DateService
const year = monthDate.getFullYear();
const month = monthDate.getMonth();
const firstOfMonth = this.dateService.startOfDay(new Date(year, month, 1));
// Get Monday of the week containing first day
const weekBounds = this.dateService.getWeekBounds(firstOfMonth);
const startDate = this.dateService.startOfDay(weekBounds.start);
// Generate 42 days (6 weeks)
const dates: Date[] = [];
for (let i = 0; i < 42; i++) {
dates.push(this.dateService.addDays(startDate, i));
}
return dates;
}
private renderMonthEvents(container: HTMLElement, events: CalendarEvent[]): void {
// TODO: Implement month event rendering
// Events will be small blocks in day cells
}
getNextPeriod(currentDate: Date): Date {
const nextMonth = this.dateService.addMonths(currentDate, 1);
const year = nextMonth.getFullYear();
const month = nextMonth.getMonth();
return this.dateService.startOfDay(new Date(year, month, 1));
}
getPreviousPeriod(currentDate: Date): Date {
const prevMonth = this.dateService.addMonths(currentDate, -1);
const year = prevMonth.getFullYear();
const month = prevMonth.getMonth();
return this.dateService.startOfDay(new Date(year, month, 1));
}
getPeriodLabel(date: Date): string {
const monthNames = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'];
return `${monthNames[date.getMonth()]} ${date.getFullYear()}`;
}
getDisplayDates(baseDate: Date): Date[] {
return this.getMonthDates(baseDate);
}
getPeriodRange(baseDate: Date): { startDate: Date; endDate: Date } {
// Month view shows events for the entire month grid (including partial weeks)
const year = baseDate.getFullYear();
const month = baseDate.getMonth();
const firstOfMonth = this.dateService.startOfDay(new Date(year, month, 1));
// Get Monday of the week containing first day
const weekBounds = this.dateService.getWeekBounds(firstOfMonth);
const startDate = this.dateService.startOfDay(weekBounds.start);
// End date is 41 days after start (42 total days)
const endDate = this.dateService.addDays(startDate, 41);
return {
startDate,
endDate
};
}
}

View file

@ -1,77 +0,0 @@
/**
* WeekViewStrategy - Strategy for week/day view rendering
* Extracts the time-based grid logic from GridManager
*/
import { ViewStrategy, ViewContext, ViewLayoutConfig } from './ViewStrategy';
import { DateService } from '../utils/DateService';
import { calendarConfig } from '../core/CalendarConfig';
import { GridRenderer } from '../renderers/GridRenderer';
import { GridStyleManager } from '../renderers/GridStyleManager';
export class WeekViewStrategy implements ViewStrategy {
private dateService: DateService;
private gridRenderer: GridRenderer;
private styleManager: GridStyleManager;
constructor() {
const timezone = calendarConfig.getTimezone?.();
this.dateService = new DateService(timezone);
this.gridRenderer = new GridRenderer();
this.styleManager = new GridStyleManager();
}
getLayoutConfig(): ViewLayoutConfig {
return {
needsTimeAxis: true,
columnCount: calendarConfig.getWorkWeekSettings().totalDays,
scrollable: true,
eventPositioning: 'time-based'
};
}
renderGrid(context: ViewContext): void {
// Update grid styles
this.styleManager.updateGridStyles(context.resourceData);
// Render the grid structure (time axis + day columns)
this.gridRenderer.renderGrid(
context.container,
context.currentDate,
context.resourceData
);
}
getNextPeriod(currentDate: Date): Date {
return this.dateService.addWeeks(currentDate, 1);
}
getPreviousPeriod(currentDate: Date): Date {
return this.dateService.addWeeks(currentDate, -1);
}
getPeriodLabel(date: Date): string {
const weekBounds = this.dateService.getWeekBounds(date);
const weekStart = this.dateService.startOfDay(weekBounds.start);
const weekEnd = this.dateService.addDays(weekStart, 6);
const weekNumber = this.dateService.getWeekNumber(date);
return `Week ${weekNumber}: ${this.dateService.formatDateRange(weekStart, weekEnd)}`;
}
getDisplayDates(baseDate: Date): Date[] {
const workWeekSettings = calendarConfig.getWorkWeekSettings();
return this.dateService.getWorkWeekDates(baseDate, workWeekSettings.workDays);
}
getPeriodRange(baseDate: Date): { startDate: Date; endDate: Date } {
const weekBounds = this.dateService.getWeekBounds(baseDate);
const weekStart = this.dateService.startOfDay(weekBounds.start);
const weekEnd = this.dateService.addDays(weekStart, 6);
return {
startDate: weekStart,
endDate: weekEnd
};
}
}