Adds work hours management with day-specific overrides
Introduces work hours management with weekly default and date-specific overrides to support per-column scheduling. Calculates and applies non-work hour overlays to columns. This allows users to visualize working and non-working times. Adjusts event rendering to prevent overlap with horizontal timelines.
This commit is contained in:
parent
18c12cd3e6
commit
a3ed03ff44
5 changed files with 252 additions and 13 deletions
160
src/managers/WorkHoursManager.ts
Normal file
160
src/managers/WorkHoursManager.ts
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// Work hours management for per-column scheduling
|
||||
|
||||
import { DateCalculator } from '../utils/DateCalculator';
|
||||
import { CalendarConfig } from '../core/CalendarConfig';
|
||||
|
||||
/**
|
||||
* 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 config: CalendarConfig;
|
||||
private dateCalculator: DateCalculator;
|
||||
private workSchedule: WorkScheduleConfig;
|
||||
|
||||
constructor(config: CalendarConfig) {
|
||||
this.config = config;
|
||||
this.dateCalculator = new DateCalculator(config);
|
||||
|
||||
// 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.dateCalculator.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.dateCalculator.formatISODate(date);
|
||||
const workHours = this.getWorkHoursForDate(date);
|
||||
workHoursMap.set(dateString, workHours);
|
||||
});
|
||||
|
||||
return workHoursMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate CSS custom properties for non-work hour overlays (before and after work)
|
||||
*/
|
||||
calculateNonWorkHoursStyle(workHours: DayWorkHours | 'off'): { beforeWorkHeight: number; afterWorkTop: number } | null {
|
||||
if (workHours === 'off') {
|
||||
return null; // Full day will be colored via CSS background
|
||||
}
|
||||
|
||||
const gridSettings = this.config.getGridSettings();
|
||||
const dayStartHour = gridSettings.dayStartHour;
|
||||
const dayEndHour = gridSettings.dayEndHour;
|
||||
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 (legacy - for backward compatibility)
|
||||
*/
|
||||
calculateWorkHoursStyle(workHours: DayWorkHours | 'off'): { top: number; height: number } | null {
|
||||
if (workHours === 'off') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const gridSettings = this.config.getGridSettings();
|
||||
const dayStartHour = gridSettings.dayStartHour;
|
||||
const hourHeight = gridSettings.hourHeight;
|
||||
|
||||
const top = (workHours.start - dayStartHour) * hourHeight;
|
||||
const height = (workHours.end - workHours.start) * hourHeight;
|
||||
|
||||
return { top, 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()];
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue