2025-08-22 22:57:35 +02:00
|
|
|
// Work hours management for per-column scheduling
|
|
|
|
|
|
2025-10-03 20:50:40 +02:00
|
|
|
import { DateService } from '../utils/DateService';
|
2025-09-03 20:04:47 +02:00
|
|
|
import { calendarConfig } from '../core/CalendarConfig';
|
2025-09-13 00:39:56 +02:00
|
|
|
import { PositionUtils } from '../utils/PositionUtils';
|
2025-08-22 22:57:35 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Work hours for a specific day
|
|
|
|
|
*/
|
|
|
|
|
export interface DayWorkHours {
|
|
|
|
|
start: number; // Hour (0-23)
|
|
|
|
|
end: number; // Hour (0-23)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Work schedule configuration
|
|
|
|
|
*/
|
|
|
|
|
export interface WorkScheduleConfig {
|
|
|
|
|
weeklyDefault: {
|
|
|
|
|
monday: DayWorkHours | 'off';
|
|
|
|
|
tuesday: DayWorkHours | 'off';
|
|
|
|
|
wednesday: DayWorkHours | 'off';
|
|
|
|
|
thursday: DayWorkHours | 'off';
|
|
|
|
|
friday: DayWorkHours | 'off';
|
|
|
|
|
saturday: DayWorkHours | 'off';
|
|
|
|
|
sunday: DayWorkHours | 'off';
|
|
|
|
|
};
|
|
|
|
|
dateOverrides: {
|
|
|
|
|
[dateString: string]: DayWorkHours | 'off'; // YYYY-MM-DD format
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Manages work hours scheduling with weekly defaults and date-specific overrides
|
|
|
|
|
*/
|
|
|
|
|
export class WorkHoursManager {
|
2025-10-03 20:50:40 +02:00
|
|
|
private dateService: DateService;
|
2025-08-22 22:57:35 +02:00
|
|
|
private workSchedule: WorkScheduleConfig;
|
|
|
|
|
|
2025-09-03 20:04:47 +02:00
|
|
|
constructor() {
|
2025-10-03 20:50:40 +02:00
|
|
|
const timezone = calendarConfig.getTimezone?.() || 'Europe/Copenhagen';
|
|
|
|
|
this.dateService = new DateService(timezone);
|
2025-08-22 22:57:35 +02:00
|
|
|
|
|
|
|
|
// Default work schedule - will be loaded from JSON later
|
|
|
|
|
this.workSchedule = {
|
|
|
|
|
weeklyDefault: {
|
|
|
|
|
monday: { start: 9, end: 17 },
|
|
|
|
|
tuesday: { start: 9, end: 17 },
|
|
|
|
|
wednesday: { start: 9, end: 17 },
|
|
|
|
|
thursday: { start: 9, end: 17 },
|
|
|
|
|
friday: { start: 9, end: 15 },
|
|
|
|
|
saturday: 'off',
|
|
|
|
|
sunday: 'off'
|
|
|
|
|
},
|
|
|
|
|
dateOverrides: {
|
|
|
|
|
'2025-01-20': { start: 10, end: 16 },
|
|
|
|
|
'2025-01-21': { start: 8, end: 14 },
|
|
|
|
|
'2025-01-22': 'off'
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get work hours for a specific date
|
|
|
|
|
*/
|
|
|
|
|
getWorkHoursForDate(date: Date): DayWorkHours | 'off' {
|
2025-10-03 20:50:40 +02:00
|
|
|
const dateString = this.dateService.formatISODate(date);
|
2025-08-22 22:57:35 +02:00
|
|
|
|
|
|
|
|
// Check for date-specific override first
|
|
|
|
|
if (this.workSchedule.dateOverrides[dateString]) {
|
|
|
|
|
return this.workSchedule.dateOverrides[dateString];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fall back to weekly default
|
|
|
|
|
const dayName = this.getDayName(date);
|
|
|
|
|
return this.workSchedule.weeklyDefault[dayName];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get work hours for multiple dates (used by GridManager)
|
|
|
|
|
*/
|
|
|
|
|
getWorkHoursForDateRange(dates: Date[]): Map<string, DayWorkHours | 'off'> {
|
|
|
|
|
const workHoursMap = new Map<string, DayWorkHours | 'off'>();
|
|
|
|
|
|
|
|
|
|
dates.forEach(date => {
|
2025-10-03 20:50:40 +02:00
|
|
|
const dateString = this.dateService.formatISODate(date);
|
2025-08-22 22:57:35 +02:00
|
|
|
const workHours = this.getWorkHoursForDate(date);
|
|
|
|
|
workHoursMap.set(dateString, workHours);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return workHoursMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2025-09-13 00:39:56 +02:00
|
|
|
* Calculate CSS custom properties for non-work hour overlays using PositionUtils
|
2025-08-22 22:57:35 +02:00
|
|
|
*/
|
|
|
|
|
calculateNonWorkHoursStyle(workHours: DayWorkHours | 'off'): { beforeWorkHeight: number; afterWorkTop: number } | null {
|
|
|
|
|
if (workHours === 'off') {
|
|
|
|
|
return null; // Full day will be colored via CSS background
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-03 20:04:47 +02:00
|
|
|
const gridSettings = calendarConfig.getGridSettings();
|
2025-08-22 22:57:35 +02:00
|
|
|
const dayStartHour = gridSettings.dayStartHour;
|
|
|
|
|
const hourHeight = gridSettings.hourHeight;
|
|
|
|
|
|
|
|
|
|
// Before work: from day start to work start
|
|
|
|
|
const beforeWorkHeight = (workHours.start - dayStartHour) * hourHeight;
|
|
|
|
|
|
|
|
|
|
// After work: from work end to day end
|
|
|
|
|
const afterWorkTop = (workHours.end - dayStartHour) * hourHeight;
|
|
|
|
|
|
2025-09-13 00:39:56 +02:00
|
|
|
return {
|
|
|
|
|
beforeWorkHeight: Math.max(0, beforeWorkHeight),
|
|
|
|
|
afterWorkTop: Math.max(0, afterWorkTop)
|
2025-08-22 22:57:35 +02:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2025-09-13 00:39:56 +02:00
|
|
|
* Calculate CSS custom properties for work hours overlay using PositionUtils
|
2025-08-22 22:57:35 +02:00
|
|
|
*/
|
|
|
|
|
calculateWorkHoursStyle(workHours: DayWorkHours | 'off'): { top: number; height: number } | null {
|
|
|
|
|
if (workHours === 'off') {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-13 00:39:56 +02:00
|
|
|
// Create dummy time strings for start and end of work hours
|
|
|
|
|
const startTime = `${workHours.start.toString().padStart(2, '0')}:00`;
|
|
|
|
|
const endTime = `${workHours.end.toString().padStart(2, '0')}:00`;
|
2025-08-22 22:57:35 +02:00
|
|
|
|
2025-09-13 00:39:56 +02:00
|
|
|
// Use PositionUtils for consistent position calculation
|
|
|
|
|
const position = PositionUtils.calculateEventPosition(startTime, endTime);
|
2025-08-22 22:57:35 +02:00
|
|
|
|
2025-09-13 00:39:56 +02:00
|
|
|
return { top: position.top, height: position.height };
|
2025-08-22 22:57:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Load work schedule from JSON (future implementation)
|
|
|
|
|
*/
|
|
|
|
|
async loadWorkSchedule(jsonData: WorkScheduleConfig): Promise<void> {
|
|
|
|
|
this.workSchedule = jsonData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get current work schedule configuration
|
|
|
|
|
*/
|
|
|
|
|
getWorkSchedule(): WorkScheduleConfig {
|
|
|
|
|
return this.workSchedule;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Convert Date to day name key
|
|
|
|
|
*/
|
|
|
|
|
private getDayName(date: Date): keyof WorkScheduleConfig['weeklyDefault'] {
|
|
|
|
|
const dayNames: (keyof WorkScheduleConfig['weeklyDefault'])[] = [
|
|
|
|
|
'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'
|
|
|
|
|
];
|
|
|
|
|
return dayNames[date.getDay()];
|
|
|
|
|
}
|
|
|
|
|
}
|