Implements configurable work week presets, allowing users to customize the days displayed in the calendar. This includes: - Defining work week settings (work days, day names, total days). - Providing predefined work week presets (standard, compressed, weekend, full week). - Adding UI elements to switch between presets. - Updating grid and header rendering logic to reflect the selected work week. - Emitting events when the work week changes, triggering necessary UI updates and data re-renders. This provides a more flexible and personalized calendar experience.
162 lines
No EOL
5.3 KiB
TypeScript
162 lines
No EOL
5.3 KiB
TypeScript
// Header rendering strategy interface and implementations
|
|
|
|
import { CalendarConfig } from '../core/CalendarConfig';
|
|
import { ResourceCalendarData } from '../types/CalendarTypes';
|
|
|
|
/**
|
|
* Interface for header rendering strategies
|
|
*/
|
|
export interface HeaderRenderer {
|
|
render(calendarHeader: HTMLElement, context: HeaderRenderContext): void;
|
|
}
|
|
|
|
/**
|
|
* Context for header rendering
|
|
*/
|
|
export interface HeaderRenderContext {
|
|
currentWeek: Date;
|
|
config: CalendarConfig;
|
|
allDayEvents?: any[];
|
|
resourceData?: ResourceCalendarData | null;
|
|
}
|
|
|
|
/**
|
|
* Date-based header renderer (original functionality)
|
|
*/
|
|
export class DateHeaderRenderer implements HeaderRenderer {
|
|
render(calendarHeader: HTMLElement, context: HeaderRenderContext): void {
|
|
const { currentWeek, config, allDayEvents = [] } = context;
|
|
|
|
const dates = this.getWeekDates(currentWeek, config);
|
|
const weekDays = config.get('weekDays');
|
|
const daysToShow = dates.slice(0, weekDays);
|
|
|
|
const workWeekSettings = config.getWorkWeekSettings();
|
|
daysToShow.forEach((date, index) => {
|
|
const header = document.createElement('swp-day-header');
|
|
if (this.isToday(date)) {
|
|
(header as any).dataset.today = 'true';
|
|
}
|
|
|
|
header.innerHTML = `
|
|
<swp-day-name>${workWeekSettings.dayNames[index]}</swp-day-name>
|
|
<swp-day-date>${date.getDate()}</swp-day-date>
|
|
`;
|
|
(header as any).dataset.date = this.formatDate(date);
|
|
|
|
calendarHeader.appendChild(header);
|
|
});
|
|
|
|
// Render all-day events in row 2
|
|
this.renderAllDayEvents(calendarHeader, context);
|
|
}
|
|
|
|
private renderAllDayEvents(calendarHeader: HTMLElement, context: HeaderRenderContext): void {
|
|
const { currentWeek, config, allDayEvents = [] } = context;
|
|
|
|
const dates = this.getWeekDates(currentWeek, config);
|
|
const weekDays = config.get('weekDays');
|
|
const daysToShow = dates.slice(0, weekDays);
|
|
|
|
// Process each all-day event to calculate its span
|
|
allDayEvents.forEach(event => {
|
|
const startDate = new Date(event.start);
|
|
const endDate = new Date(event.end);
|
|
|
|
// Find start and end column indices
|
|
let startColumnIndex = -1;
|
|
let endColumnIndex = -1;
|
|
|
|
daysToShow.forEach((date, index) => {
|
|
const dateStr = this.formatDate(date);
|
|
const startDateStr = this.formatDate(startDate);
|
|
|
|
if (dateStr === startDateStr) {
|
|
startColumnIndex = index;
|
|
}
|
|
|
|
// For end date, we need to check if the event spans to this day
|
|
if (date <= endDate) {
|
|
endColumnIndex = index;
|
|
}
|
|
});
|
|
|
|
// Only render if the event starts within the visible week
|
|
if (startColumnIndex >= 0) {
|
|
// If end column is not found or is before start, default to single day
|
|
if (endColumnIndex < startColumnIndex) {
|
|
endColumnIndex = startColumnIndex;
|
|
}
|
|
|
|
const allDayEvent = document.createElement('swp-allday-event');
|
|
allDayEvent.textContent = event.title;
|
|
|
|
// Set grid column span: start column (1-based) to end column + 1 (1-based)
|
|
const gridColumnStart = startColumnIndex + 1;
|
|
const gridColumnEnd = endColumnIndex + 2;
|
|
allDayEvent.style.gridColumn = `${gridColumnStart} / ${gridColumnEnd}`;
|
|
allDayEvent.style.backgroundColor = event.metadata?.color || '#ff9800';
|
|
|
|
calendarHeader.appendChild(allDayEvent);
|
|
}
|
|
});
|
|
}
|
|
|
|
private getWeekDates(weekStart: Date, config: CalendarConfig): Date[] {
|
|
const dates: Date[] = [];
|
|
const workWeekSettings = config.getWorkWeekSettings();
|
|
|
|
// Calculate dates based on actual work days (e.g., [1,2,3,4] for Mon-Thu)
|
|
workWeekSettings.workDays.forEach(dayOfWeek => {
|
|
const date = new Date(weekStart);
|
|
// Set to the start of the week (Sunday = 0)
|
|
date.setDate(weekStart.getDate() - weekStart.getDay());
|
|
// Add the specific day of week
|
|
date.setDate(date.getDate() + dayOfWeek);
|
|
dates.push(date);
|
|
});
|
|
|
|
return dates;
|
|
}
|
|
|
|
private isToday(date: Date): boolean {
|
|
const today = new Date();
|
|
return date.toDateString() === today.toDateString();
|
|
}
|
|
|
|
private formatDate(date: Date): string {
|
|
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Resource-based header renderer
|
|
*/
|
|
export class ResourceHeaderRenderer implements HeaderRenderer {
|
|
render(calendarHeader: HTMLElement, context: HeaderRenderContext): void {
|
|
const { resourceData } = context;
|
|
|
|
if (!resourceData) {
|
|
console.warn('ResourceHeaderRenderer: No resource data available for resource headers');
|
|
return;
|
|
}
|
|
|
|
resourceData.resources.forEach((resource) => {
|
|
const header = document.createElement('swp-resource-header');
|
|
header.setAttribute('data-resource', resource.name);
|
|
header.setAttribute('data-employee-id', resource.employeeId);
|
|
|
|
header.innerHTML = `
|
|
<swp-resource-avatar>
|
|
<img src="${resource.avatarUrl}" alt="${resource.displayName}" onerror="this.style.display='none'">
|
|
</swp-resource-avatar>
|
|
<swp-resource-name>${resource.displayName}</swp-resource-name>
|
|
`;
|
|
|
|
calendarHeader.appendChild(header);
|
|
});
|
|
|
|
console.log(`ResourceHeaderRenderer: Rendered ${resourceData.resources.length} resource headers`);
|
|
}
|
|
} |