Replaces DateCalculator with DateService for improved date and time operations, including timezone handling. This change enhances the calendar's accuracy and flexibility in managing dates, especially concerning timezone configurations. It also corrects a typo in the `allDay` dataset attribute.
159 lines
No EOL
4.7 KiB
TypeScript
159 lines
No EOL
4.7 KiB
TypeScript
// Work hours management for per-column scheduling
|
|
|
|
import { DateService } from '../utils/DateService';
|
|
import { calendarConfig } from '../core/CalendarConfig';
|
|
import { PositionUtils } from '../utils/PositionUtils';
|
|
|
|
/**
|
|
* 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 {
|
|
private dateService: DateService;
|
|
private workSchedule: WorkScheduleConfig;
|
|
|
|
constructor() {
|
|
const timezone = calendarConfig.getTimezone?.() || 'Europe/Copenhagen';
|
|
this.dateService = new DateService(timezone);
|
|
|
|
// 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' {
|
|
const dateString = this.dateService.formatISODate(date);
|
|
|
|
// 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 => {
|
|
const dateString = this.dateService.formatISODate(date);
|
|
const workHours = this.getWorkHoursForDate(date);
|
|
workHoursMap.set(dateString, workHours);
|
|
});
|
|
|
|
return workHoursMap;
|
|
}
|
|
|
|
/**
|
|
* Calculate CSS custom properties for non-work hour overlays using PositionUtils
|
|
*/
|
|
calculateNonWorkHoursStyle(workHours: DayWorkHours | 'off'): { beforeWorkHeight: number; afterWorkTop: number } | null {
|
|
if (workHours === 'off') {
|
|
return null; // Full day will be colored via CSS background
|
|
}
|
|
|
|
const gridSettings = calendarConfig.getGridSettings();
|
|
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;
|
|
|
|
return {
|
|
beforeWorkHeight: Math.max(0, beforeWorkHeight),
|
|
afterWorkTop: Math.max(0, afterWorkTop)
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Calculate CSS custom properties for work hours overlay using PositionUtils
|
|
*/
|
|
calculateWorkHoursStyle(workHours: DayWorkHours | 'off'): { top: number; height: number } | null {
|
|
if (workHours === 'off') {
|
|
return null;
|
|
}
|
|
|
|
// 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`;
|
|
|
|
// Use PositionUtils for consistent position calculation
|
|
const position = PositionUtils.calculateEventPosition(startTime, endTime);
|
|
|
|
return { top: position.top, height: position.height };
|
|
}
|
|
|
|
/**
|
|
* 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()];
|
|
}
|
|
} |