dvbooking/admin/src/app/features/calendar/components/calendar-view/calendar-view.ts
2025-11-28 23:02:00 +01:00

214 lines
5.8 KiB
TypeScript

import {
AfterViewInit,
Component,
effect,
ElementRef,
inject,
Injector,
OnInit,
signal,
Type,
ViewChild,
} from '@angular/core';
import { FullCalendarComponent, FullCalendarModule } from '@fullcalendar/angular';
import { CalendarOptions, EventInput } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import timeGridPlugin from '@fullcalendar/timegrid';
import listPlugin from '@fullcalendar/list';
import interactionPlugin from '@fullcalendar/interaction';
import { Button, Modal } from '@rschneider/ng-daisyui';
import { CreateEventForm } from '../create-event-form/create-event-form';
import { CalendarService } from '../../services/calendar.service';
import { CalendarEventDto, EventsInRangeDTO } from '../../models/events-in-range-dto.model';
import { map } from 'rxjs';
import { SingleEventDashboard } from './single-event-dashboard/single-event-dashboard';
import { CommonModule, JsonPipe, NgComponentOutlet } from '@angular/common';
import {
SingleEventDashboardEventDelete
} from './single-event-dashboard-event-delete/single-event-dashboard-event-delete';
@Component({
selector: 'app-calendar-view',
imports: [FullCalendarModule, CommonModule, Modal,NgComponentOutlet, CreateEventForm, SingleEventDashboard, JsonPipe],
templateUrl: './calendar-view.html',
styleUrl: './calendar-view.css',
})
export class CalendarView implements OnInit, AfterViewInit {
@ViewChild('startHour') startHour!: ElementRef;
@ViewChild('calendar') calendarComponent: FullCalendarComponent | undefined;
calendarService = inject(CalendarService);
workflow = signal<string>('');
selectedDate = signal<Date|undefined>(undefined);
selectedEvent = signal<CalendarEventDto|undefined>(undefined)
calendarOptions: CalendarOptions;
dialogs: DialogConfig[] = [];
constructor() {
this.calendarOptions = {
plugins: [dayGridPlugin, timeGridPlugin, listPlugin, interactionPlugin],
initialView: 'dayGridMonth',
weekends: true,
firstDay: 1,
headerToolbar: {
left: 'prev,next,today',
center: 'title',
right: 'dayGridMonth,dayGridWeek,dayGridDay,timeGridWeek,timeGridDay,listWeek',
},
events: this.fetchEvents.bind(this), // Bind the context
eventClick: (info) => {
this.selectedEvent.set(info.event.extendedProps['event']);
this.workflow.set('event-dashboard');
},
dateClick: (info) => {
console.info('create new evet for day ',info);
this.workflow.set('create');
this.selectedDate.set(info.date);
this.selectedEvent.set(undefined);
},
};
const injector = Injector.create({
providers: [
{
provide: 'closeDialog',
useValue: () => this.closeDialog()
}
]
});
this.dialogs = [
{
component: SingleEventDashboardEventDelete,
isRendered: () => this.workflow() == 'event-delete',
// isRendered: () => true,
closeClick: () => this.closeDialog(),
modalBoxStyleClass: 'max-w-none w-2xl',
componentInputs: () => {
return {
'event': this.selectedEvent(),
'onAction': this.handleAction
}
},
componentOutputs: () => injector
}
]
}
fetchEvents(fetchInfo: any, successCallback: (events: EventInput[]) => void, failureCallback: (error: any) => void): void {
console.info('fetching events', fetchInfo);
const start = fetchInfo.start;
const end = fetchInfo.end;
// if ( fetchInfo ){
// console.info("fetchinfo", fetchInfo);
// successCallback([]);
// return;
// }
this.calendarService.getEventsInRange({
startTime: start,
endTime: end,
})
.pipe(
map(value => {
console.info("vent got" , value );
const events: EventInput[] = value.map( (model) => {
const calendarEvent: EventInput = {
start: new Date(model.startTime),
// end: model.end_time,
title: model.title,
extendedProps: {
event: model
}
};
if ( model.eventType){
calendarEvent.borderColor = model.eventType.color;
}
// calendarEvent.backgroundColor = "#00ff00"
return calendarEvent;
})
return events;
}),
)
.subscribe({
next: (events) => {
console.info("calendar events", events);
successCallback(events);
}
,
error: (error) => {
console.error('Error fetching events', error);
failureCallback(error);
},
},
);
}
ngAfterViewInit(): void {
}
ngOnInit(): void {
}
protected addEvent($event: PointerEvent) {
let hourStr = this.startHour.nativeElement.value;
const hour = parseInt(hourStr, 10);
const date = new Date();
const start = new Date(date.getTime());
start.setHours(hour, 0, 0);
const end = new Date(date.getTime());
// end.setHours(3,0,0)
this.calendarComponent?.getApi().addEvent({
title: 'Event at ' + hour,
start,
});
}
closeDialog() {
this.workflow.set('');
}
onDashboardAction(action: string){
console.info("dashboard event", action);
switch (action) {
case 'event_delete':
this.workflow.set('event-delete');
break;
}
}
// This function is passed into the child
handleAction = (msg: string) => {
console.log('Parent received:', msg);
if ( msg == 'close'){
this.closeDialog();
}
};
}
export interface DialogConfig{
component: Type<any>;
componentInputs?: () => { [key: string]: any };
closeClick: () => void,
modalBoxStyleClass: string
isRendered: () => boolean;
componentOutputs: () => Injector
}