UNPKG

worker-calendar

Version:

A customizable, responsive Angular calendar component for scheduling worker appointments or shifts

269 lines (240 loc) 10.8 kB
<div class="worker-calendar"> <!-- Calendar Header --> <div class="calendar-header"> <div class="calendar-controls"> <button class="btn-control" (click)="onPrevious()">{{ language === 'fr' ? 'Précédent' : 'Previous' }}</button> <button class="btn-control" (click)="onToday()">{{ language === 'fr' ? 'Aujourd\'hui' : 'Today' }}</button> <button class="btn-control" (click)="onNext()">{{ language === 'fr' ? 'Suivant' : 'Next' }}</button> </div> <div class="calendar-title"> {{ displayDate }} </div> <div class="view-mode-selector"> <button class="btn-view-mode" [class.active]="viewMode === 'day'" (click)="changeViewMode('day')"> {{ language === 'fr' ? 'Jour' : 'Day' }} </button> <button class="btn-view-mode" [class.active]="viewMode === 'week'" (click)="changeViewMode('week')"> {{ language === 'fr' ? 'Semaine' : 'Week' }} </button> <button class="btn-view-mode" [class.active]="viewMode === 'month'" (click)="changeViewMode('month')"> {{ language === 'fr' ? 'Mois' : 'Month' }} </button> </div> </div> <!-- Drag Preview Element --> <div class="drag-preview" *ngIf="dragPreview.visible" [ngStyle]="{ top: dragPreview.top, left: dragPreview.left, width: dragPreview.width, height: dragPreview.height }"> </div> <!-- Day View --> <div class="day-view" *ngIf="viewMode === 'day'" cdkDropListGroup> <!-- Time Header --> <div class="time-header"> <div class="worker-column-header">{{ language === 'fr' ? 'Employés' : 'Workers' }}</div> <ng-container *ngFor="let hour of hours"> <div class="hour-column">{{ hour }}:00</div> </ng-container> </div> <!-- Workers Rows --> <div class="worker-row" *ngFor="let worker of workers"> <div class="worker-info"> <div class="worker-name">{{ worker.name }}</div> <div class="worker-description" *ngIf="worker.description">{{ worker.description }}</div> </div> <ng-container *ngFor="let hour of hours"> <div class="time-cell" cdkDropList [cdkDropListData]="{workerId: worker.id, hour: hour}" (cdkDropListDropped)="handleDrop($event)" (cdkDropListEntered)="handleDragEnter($event)" (click)="handleDayCellClick(hour, worker.id)"> <!-- Show only events that start in this hour cell --> <ng-container *ngFor="let event of getEventsForWorkerAndHour(worker.id, hour)"> <div *ngIf="shouldRenderEvent(event, worker.id, hour)" class="spanning-event" [ngStyle]="getEventStyle(event, worker.id)" cdkDrag [cdkDragData]="event" cdkDragBoundary=".day-view" (cdkDragStarted)="handleDragStarted($event, event)" (cdkDragEnded)="handleDragEnded($event)" (click)="handleEventClick(event); $event.stopPropagation()"> <!-- Remove button --> <div class="remove-button" (click)="handleEventRemove(event, $event)">&times;</div> <!-- Left resize handle (hidden but still in DOM) --> <div class="resize-handle left" (mousedown)="handleResizeStart($event, event, 'left')"> </div> <div class="event-content">{{ event.title }}</div> <!-- Right resize handle (visible) --> <div class="resize-handle right" (mousedown)="handleResizeStart($event, event, 'right')"> </div> <!-- Custom preview when dragging --> <ng-template cdkDragPreview> <div class="event-preview" [style.background-color]="event.color || '#4285f4'"> {{ event.title }} </div> </ng-template> <!-- Custom placeholder when dragging --> <div *cdkDragPlaceholder class="event-placeholder"></div> </div> </ng-container> <!-- Drop preview element --> <div *ngIf="dropPreview.visible && dropPreview.workerId === worker.id && dropPreview.hour === hour" class="drop-preview" [ngStyle]="{ width: dropPreview.width, height: dropPreview.height, 'background-color': dropPreview.color }"> {{ dropPreview.title }} </div> </div> </ng-container> </div> </div> <!-- Week View --> <div class="week-view" *ngIf="viewMode === 'week'" cdkDropListGroup> <!-- Week Header --> <div class="week-header"> <div class="time-column-header">{{ language === 'fr' ? 'Heure' : 'Time' }}</div> <ng-container *ngFor="let day of weekDays"> <div class="day-column-header" [class.today]="day.isToday"> <span class="day-name">{{ day.dayName }}</span> <span class="day-date">{{ day.dayNumber }}</span> </div> </ng-container> </div> <!-- Week Body --> <div class="week-body"> <!-- Hours Column --> <div class="hours-column"> <ng-container *ngFor="let hour of hours"> <div class="hour-cell">{{ hour }}:00</div> </ng-container> </div> <!-- Day Columns --> <ng-container *ngFor="let day of weekDays"> <div class="day-column" [class.today]="day.isToday"> <ng-container *ngFor="let hour of hours"> <div class="hour-cell" cdkDropList [cdkDropListData]="{date: day.date, hour: hour}" (cdkDropListDropped)="handleWeekDrop($event)" (cdkDropListEntered)="handleWeekDragEnter($event)" (click)="handleWeekCellClick(hour, day.date)"> <!-- Show only events that start in this hour cell --> <ng-container *ngFor="let event of getEventsForHourAndDay(hour, day.date)"> <div *ngIf="shouldRenderWeekEvent(event, day.date, hour)" class="spanning-event" [ngStyle]="getWeekEventStyle(event, day.date)" cdkDrag [cdkDragData]="event" cdkDragBoundary=".week-view" (cdkDragStarted)="handleDragStarted($event, event)" (cdkDragEnded)="handleDragEnded($event)" (click)="handleEventClick(event); $event.stopPropagation()"> <!-- Remove button --> <div class="remove-button" (click)="handleEventRemove(event, $event)">&times;</div> <!-- Left resize handle (hidden but still in DOM) --> <div class="resize-handle left" (mousedown)="handleResizeStart($event, event, 'left')"> </div> <div class="event-content">{{ event.title }}</div> <!-- Right resize handle (visible) --> <div class="resize-handle right" (mousedown)="handleResizeStart($event, event, 'right')"> </div> <!-- Custom preview when dragging --> <ng-template cdkDragPreview> <div class="event-preview" [style.background-color]="event.color || '#4285f4'"> {{ event.title }} </div> </ng-template> <!-- Custom placeholder when dragging --> <div *cdkDragPlaceholder class="event-placeholder"></div> </div> </ng-container> <!-- Drop preview element for week view --> <div *ngIf="dropPreview.visible && dropPreview.date && isSameDay(dropPreview.date, day.date) && dropPreview.hour === hour" class="drop-preview" [ngStyle]="{ width: dropPreview.width, height: dropPreview.height, 'background-color': dropPreview.color }"> {{ dropPreview.title }} </div> </div> </ng-container> </div> </ng-container> </div> </div> <!-- Month View --> <div class="month-view" *ngIf="viewMode === 'month'"> <!-- Month Header --> <div class="month-header"> <div class="day-name" *ngFor="let dayName of weekDayNames"> {{ dayName.slice(0, 3) }} </div> </div> <!-- Month Grid --> <div class="month-grid"> <div class="month-day" *ngFor="let day of monthDays" [class.other-month]="!day.isCurrentMonth" [class.today]="day.isToday" (click)="handleMonthDayClick(day.date)"> <div class="date-number">{{ day.dayNumber }}</div> <div class="month-events"> <ng-container *ngIf="getDisplayedEvents(day.date, 3) as displayData"> <div class="month-event" *ngFor="let event of displayData.events" [style.background-color]="event.color || '#4285f4'" (click)="handleEventClick(event); $event.stopPropagation()"> <span class="month-event-time">{{ formatMonthEventTime(event) }}</span> <span class="month-event-title">{{ event.title }}</span> <span class="month-event-remove" (click)="handleEventRemove(event, $event)">&times;</span> </div> <div class="more-events" *ngIf="displayData.overflow > 0"> {{ language === 'fr' ? '+' + displayData.overflow + ' autres' : '+' + displayData.overflow + ' more' }} </div> </ng-container> </div> </div> </div> </div> </div>