add fullcalendar example

This commit is contained in:
Roland Schneider
2025-11-21 08:10:49 +01:00
parent 02cad3dbcd
commit dfc3afd4a9
7 changed files with 209 additions and 14 deletions

View File

@@ -37,8 +37,19 @@ import { BookingFormComponent } from "./features/bookings/components/booking-for
import { BookingDetailsComponent } from "./features/bookings/components/booking-details/booking-details.component";
import { BookingTableComponent } from "./features/bookings/components/booking-table/booking-table.component";
import { BookingListComponent } from "./features/bookings/components/booking-list/booking-list.component";
import { CalendarView } from './features/calendar/components/calendar-view/calendar-view';
export const routes: Routes = [
{
path: 'calendar',
component: CalendarView,
canActivate: [AuthGuard],
data: {
roles: ['admin'],
},
},
{
path: 'bookings/new',
component: BookingFormComponent,

View File

@@ -3,18 +3,17 @@ import { Router, RouterOutlet } from '@angular/router';
import { AuthService } from './auth/auth.service';
import { AdminLayoutRs1 } from '../../projects/rschneider/ng-daisyui/src/lib/layout';
import { Menu, MenuItem } from './components/menu/menu';
@Component({
selector: 'app-root',
imports: [RouterOutlet, AdminLayoutRs1, Menu],
imports: [RouterOutlet, AdminLayoutRs1, Menu],
templateUrl: './app.html',
styleUrl: './app.css',
})
export class App {
protected readonly title = signal('admin');
protected menuConfig: MenuItem[] = [
];
protected menuConfig: MenuItem[] = [];
protected currentUserRoles: string[] = ['admin'];
protected menuTitle: string | undefined = 'Menü';
@@ -27,7 +26,7 @@ export class App {
svgIcon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6.429 9.75 2.25 12l4.179 2.25m0-4.5 5.571 3 5.571-3m-11.142 0L2.25 7.5 12 2.25l9.75 5.25-4.179 2.25m0 0L21.75 12l-4.179 2.25m0 0 4.179 2.25L12 21.75 2.25 16.5l4.179-2.25m11.142 0-5.571 3-5.571-3" />
</svg>
`
`,
},
{
menuText: 'Események',
@@ -35,15 +34,23 @@ export class App {
svgIcon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />
</svg>
`
`,
},
{
{
menuText: 'Naptár',
targetUrl: '/calendar',
svgIcon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5m-9-6h.008v.008H12v-.008ZM12 15h.008v.008H12V15Zm0 2.25h.008v.008H12v-.008ZM9.75 15h.008v.008H9.75V15Zm0 2.25h.008v.008H9.75v-.008ZM7.5 15h.008v.008H7.5V15Zm0 2.25h.008v.008H7.5v-.008Zm6.75-4.5h.008v.008h-.008v-.008Zm0 2.25h.008v.008h-.008V15Zm0 2.25h.008v.008h-.008v-.008Zm2.25-4.5h.008v.008H16.5v-.008Zm0 2.25h.008v.008H16.5V15Z" />
</svg>
`,
},
{
menuText: 'Felhasználók',
targetUrl: '/user/table',
svgIcon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z" />
</svg>
`
`,
},
{
menuText: 'Felhasználó Csoport',
@@ -51,19 +58,19 @@ export class App {
svgIcon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z" />
</svg>
`
`,
},
{
{
menuText: 'Felhasználó Szerepek',
targetUrl: '/user-role/table',
svgIcon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
</svg>
`
`,
},
]
];
}
logout(): void {
@@ -81,8 +88,8 @@ export class App {
});
}
loggedIn(){
return this.authService.isLoggedIn()
loggedIn() {
return this.authService.isLoggedIn();
}
}

View File

@@ -0,0 +1,8 @@
<div>
<h1>Naptár</h1>
<div>
<input type="text" name="startHour" id="starthour" #startHour>
<a class="btn" (click)="addEvent($event)">add</a>
</div>
<full-calendar #calendar [options]="calendarOptions"></full-calendar>
</div>

View File

@@ -0,0 +1,85 @@
import { Component, ElementRef, ViewChild } from '@angular/core';
import { FullCalendarComponent, FullCalendarModule } from '@fullcalendar/angular';
import { CalendarOptions } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import timeGridPlugin from '@fullcalendar/timegrid';
import listPlugin from '@fullcalendar/list';
import interactionPlugin from '@fullcalendar/interaction';
import { appConfig } from '../../../../app.config';
@Component({
selector: 'app-calendar-view',
imports: [FullCalendarModule],
templateUrl: './calendar-view.html',
styleUrl: './calendar-view.css',
})
export class CalendarView {
@ViewChild('startHour') startHour!: ElementRef;
@ViewChild('calendar') calendarComponent: FullCalendarComponent | undefined;
calendarOptions: CalendarOptions;
constructor() {
const start = new Date();
start.setHours(10,0,0)
const end = new Date();
end.setHours(11,0,0)
this.calendarOptions = {
plugins: [dayGridPlugin, timeGridPlugin, listPlugin,interactionPlugin],
initialView: 'dayGridMonth',
weekends: true,
headerToolbar: {
left: 'prev,next,today',
center: 'title',
// right: 'dayGridMonth,dayGridWeek,dayGridDay' // user can switch between the two
right: 'dayGridMonth,dayGridWeek,dayGridDay,timeGridWeek,timeGridDay,listWeek',
},
events: [
{ title: 'Meeting1 until'+end.toString(), start, end },
],
eventClick: function(info) {
console.info('Event info: ' , info);
// change the border color just for fun
info.el.style.borderColor = 'red';
},
dateClick: function(info) {
console.info('Date click on: ' , info);
const calendarApi = info.view.calendar;
const start = new Date(info.date.getTime())
start.setHours(2,0,0)
const end = new Date(info.date.getTime())
end.setHours(3,0,0)
calendarApi.addEvent({
title: 'New Event',
start,
end,
});
}
};
}
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
})
}
}