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(''); selectedDate = signal(undefined); selectedEvent = signal(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; componentInputs?: () => { [key: string]: any }; closeClick: () => void, modalBoxStyleClass: string isRendered: () => boolean; componentOutputs: () => Injector }