Commit 1e4426e9 by sawit

หน้าจองห้องประชุม

parent 26ac6e17
......@@ -48,6 +48,7 @@
"@syncfusion/ej2-angular-pivotview": "^31.1.17",
"@syncfusion/ej2-angular-popups": "^31.1.17",
"@syncfusion/ej2-angular-progressbar": "^31.1.17",
"@syncfusion/ej2-angular-schedule": "^31.1.21",
"@syncfusion/ej2-angular-treemap": "^31.1.17",
"@syncfusion/ej2-base": "^31.1.17",
"@syncfusion/ej2-buttons": "^31.1.17",
......@@ -6334,6 +6335,17 @@
"@syncfusion/ej2-progressbar": "31.1.17"
}
},
"node_modules/@syncfusion/ej2-angular-schedule": {
"version": "31.1.21",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-angular-schedule/-/ej2-angular-schedule-31.1.21.tgz",
"integrity": "sha512-mRlZmqimr980wWSu595e0s/zkIHlpV9EfvQua9EeveGvaZaf8fHoXysuL1GaUvjj4dCtEbJRrvuj3gDsaUqdlg==",
"license": "SEE LICENSE IN license",
"dependencies": {
"@syncfusion/ej2-angular-base": "~31.1.17",
"@syncfusion/ej2-base": "~31.1.20",
"@syncfusion/ej2-schedule": "31.1.21"
}
},
"node_modules/@syncfusion/ej2-angular-treemap": {
"version": "31.1.17",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-angular-treemap/-/ej2-angular-treemap-31.1.17.tgz",
......@@ -6346,9 +6358,9 @@
}
},
"node_modules/@syncfusion/ej2-base": {
"version": "31.1.17",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-base/-/ej2-base-31.1.17.tgz",
"integrity": "sha512-Jl2Ls77kMfX13VwrAEow/kdDrefX3gh76Uwh943NUtEuChOXzvoe+CHecxJ+49VFRCrLYhB4Hj/7R9UOh65VCg==",
"version": "31.1.22",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-base/-/ej2-base-31.1.22.tgz",
"integrity": "sha512-zgNULXYUFG8Cr2ML8VcUqj8EcQSVd/eXNnD8APZdOjELJPE1ZzeNmRzCab16A/hqCZ+wAXwKmjaTC0I6xiXjSQ==",
"license": "SEE LICENSE IN license",
"dependencies": {
"@syncfusion/ej2-icons": "~31.1.17"
......@@ -6611,6 +6623,97 @@
"@syncfusion/ej2-svg-base": "~31.1.17"
}
},
"node_modules/@syncfusion/ej2-schedule": {
"version": "31.1.21",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-schedule/-/ej2-schedule-31.1.21.tgz",
"integrity": "sha512-OXwKKNvkZ06Y66A0yvu0lV6Xd/xafz2LokTB/bXa+0v05txzxAxbjAC95C3yDJUkRA2Mtq1cdyyETxrJX768pA==",
"license": "SEE LICENSE IN license",
"dependencies": {
"@syncfusion/ej2-base": "~31.1.20",
"@syncfusion/ej2-buttons": "~31.1.21",
"@syncfusion/ej2-calendars": "~31.1.21",
"@syncfusion/ej2-data": "~31.1.17",
"@syncfusion/ej2-dropdowns": "~31.1.20",
"@syncfusion/ej2-excel-export": "~31.1.17",
"@syncfusion/ej2-inputs": "~31.1.21",
"@syncfusion/ej2-lists": "~31.1.17",
"@syncfusion/ej2-navigations": "~31.1.20",
"@syncfusion/ej2-popups": "~31.1.20"
}
},
"node_modules/@syncfusion/ej2-schedule/node_modules/@syncfusion/ej2-buttons": {
"version": "31.1.21",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-buttons/-/ej2-buttons-31.1.21.tgz",
"integrity": "sha512-NcBMK19Yn7//bwbREsdvqy3v1237AzulrphSmeS9SrKMd7L5H6apeqFe1BAkvAs/K+JPpt6A3Dv6Fhl3SkVcUg==",
"license": "SEE LICENSE IN license",
"dependencies": {
"@syncfusion/ej2-base": "~31.1.20"
}
},
"node_modules/@syncfusion/ej2-schedule/node_modules/@syncfusion/ej2-calendars": {
"version": "31.1.22",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-calendars/-/ej2-calendars-31.1.22.tgz",
"integrity": "sha512-eepI70LowYogxOVQRA+pEFoHpFdqge2wyyVkz/ixhRzniVi2WwA5nN6AXJtYvS9fOMKRUThmzXXfjUdO/TP/4g==",
"license": "SEE LICENSE IN license",
"dependencies": {
"@syncfusion/ej2-base": "~31.1.22",
"@syncfusion/ej2-buttons": "~31.1.21",
"@syncfusion/ej2-inputs": "~31.1.22",
"@syncfusion/ej2-lists": "~31.1.17",
"@syncfusion/ej2-popups": "~31.1.20"
}
},
"node_modules/@syncfusion/ej2-schedule/node_modules/@syncfusion/ej2-dropdowns": {
"version": "31.1.22",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-dropdowns/-/ej2-dropdowns-31.1.22.tgz",
"integrity": "sha512-UQaBh/7DudnkUAf//XOEPezc/mmmTTqdNMaKchEUlRErKOcAulY+HxDK8lsJegusxNiMz6vM8gxviiMhqW0uDg==",
"license": "SEE LICENSE IN license",
"dependencies": {
"@syncfusion/ej2-base": "~31.1.22",
"@syncfusion/ej2-data": "~31.1.17",
"@syncfusion/ej2-inputs": "~31.1.22",
"@syncfusion/ej2-lists": "~31.1.17",
"@syncfusion/ej2-navigations": "~31.1.20",
"@syncfusion/ej2-notifications": "~31.1.17",
"@syncfusion/ej2-popups": "~31.1.20"
}
},
"node_modules/@syncfusion/ej2-schedule/node_modules/@syncfusion/ej2-inputs": {
"version": "31.1.22",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-inputs/-/ej2-inputs-31.1.22.tgz",
"integrity": "sha512-XkF69fWeYcDpbokpiqIgjSEyVlsG7G8qGYUslUpT0ynZZ60+tz/DWemxh7gfQicJ3QCI9dzQFxxTnzEe/aRAzw==",
"license": "SEE LICENSE IN license",
"dependencies": {
"@syncfusion/ej2-base": "~31.1.22",
"@syncfusion/ej2-buttons": "~31.1.21",
"@syncfusion/ej2-popups": "~31.1.20",
"@syncfusion/ej2-splitbuttons": "~31.1.17"
}
},
"node_modules/@syncfusion/ej2-schedule/node_modules/@syncfusion/ej2-navigations": {
"version": "31.1.20",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-navigations/-/ej2-navigations-31.1.20.tgz",
"integrity": "sha512-KzJT4vHbMF9ooq8o41xwYUJX70Dr96mMEaRYJusRv/RJ+1zM/UvHhgX8n15TIFTXexH1y+KwkFvYaGchcokBgA==",
"license": "SEE LICENSE IN license",
"dependencies": {
"@syncfusion/ej2-base": "~31.1.20",
"@syncfusion/ej2-buttons": "~31.1.17",
"@syncfusion/ej2-data": "~31.1.17",
"@syncfusion/ej2-inputs": "~31.1.20",
"@syncfusion/ej2-lists": "~31.1.17",
"@syncfusion/ej2-popups": "~31.1.20"
}
},
"node_modules/@syncfusion/ej2-schedule/node_modules/@syncfusion/ej2-popups": {
"version": "31.1.20",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-popups/-/ej2-popups-31.1.20.tgz",
"integrity": "sha512-GRPZWX2ZRNS73GpG8NbhC12eBNNqdMR80nhJrun1ZBVfvPTvd6y5/qvJLWg6/kYN02tM+smgyxfxfwOH4HGi3w==",
"license": "SEE LICENSE IN license",
"dependencies": {
"@syncfusion/ej2-base": "~31.1.20",
"@syncfusion/ej2-buttons": "~31.1.17"
}
},
"node_modules/@syncfusion/ej2-splitbuttons": {
"version": "31.1.17",
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-splitbuttons/-/ej2-splitbuttons-31.1.17.tgz",
......
......@@ -21,6 +21,11 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { TranslateModule } from '@ngx-translate/core';
import { Observable } from 'rxjs';
// Syncfusion Schedule imports
import { ScheduleModule, View, EventSettingsModel, DayService, WeekService, WorkWeekService, MonthService, AgendaService, ResizeService, DragAndDropService } from '@syncfusion/ej2-angular-schedule';
import { DateTimePickerModule } from '@syncfusion/ej2-angular-calendars';
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns';
import { MeetingBookingService } from '../services/meeting-booking.service';
import { MeetingRoom, MeetingBooking, BookingTimeSlot, BookingStatistics } from '../models/meeting-booking.model';
......@@ -47,7 +52,20 @@ import { MeetingRoom, MeetingBooking, BookingTimeSlot, BookingStatistics } from
MatTabsModule,
MatSnackBarModule,
MatProgressSpinnerModule,
TranslateModule
TranslateModule,
// Syncfusion modules
ScheduleModule,
DateTimePickerModule,
DropDownListModule
],
providers: [
DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
ResizeService,
DragAndDropService
],
templateUrl: './meeting-booking.component.html',
styleUrls: ['./meeting-booking.component.scss']
......@@ -69,6 +87,19 @@ export class MeetingBookingComponent implements OnInit {
separatorKeysCodes: number[] = [13, 188]; // ENTER and COMMA key codes
// Syncfusion Schedule properties
public selectedDate_schedule: Date = new Date();
public currentView: View = 'Month';
public eventSettings: EventSettingsModel = {
dataSource: []
};
public scheduleData: any[] = [];
public showQuickInfo: boolean = true;
public allowDragAndDrop: boolean = true;
// UI State properties
public showBookingForm: boolean = false;
constructor(
private meetingBookingService: MeetingBookingService,
private fb: FormBuilder,
......@@ -95,6 +126,8 @@ export class MeetingBookingComponent implements OnInit {
ngOnInit(): void {
this.loadTimeSlots();
this.loadScheduleData();
this.loadSampleData(); // เพิ่มข้อมูลตัวอย่าง
}
onDateChange(): void {
......@@ -233,4 +266,167 @@ export class MeetingBookingComponent implements OnInit {
});
return roomName;
}
// Syncfusion Schedule methods
loadScheduleData(): void {
if (this.bookings$) {
this.bookings$.subscribe(bookings => {
if (bookings && bookings.length > 0) {
this.scheduleData = bookings.map(booking => ({
Id: booking.id,
Subject: booking.title,
StartTime: new Date(booking.startDateTime),
EndTime: new Date(booking.endDateTime),
Location: booking.roomName,
Description: booking.description,
IsAllDay: false,
CategoryColor: this.getStatusColor(booking.status),
Status: booking.status,
Organizer: booking.organizerName,
Attendees: booking.attendees.map(a => a.userName).join(', ')
}));
} else {
// ถ้าไม่มีข้อมูลจาก service ให้ใช้ข้อมูลตัวอย่าง
this.loadSampleData();
}
this.eventSettings = {
dataSource: this.scheduleData
};
console.log('Schedule data loaded:', this.scheduleData);
});
} else {
// ถ้าไม่มี bookings$ observable ให้ใช้ข้อมูลตัวอย่าง
this.loadSampleData();
}
}
onEventClick(args: any): void {
console.log('Event clicked:', args);
// Handle event click - show details or edit
this.snackBar.open(`ดูรายละเอียดการจอง: ${args.event.Subject}`, 'ปิด', { duration: 3000 });
}
onEventCreate(args: any): void {
console.log('Event created:', args);
// Handle new event creation
const newEvent = args.data;
const booking = {
roomId: this.selectedRoom,
roomName: newEvent.Location || '',
title: newEvent.Subject,
description: newEvent.Description || '',
startDateTime: newEvent.StartTime,
endDateTime: newEvent.EndTime,
organizerId: 'current-user',
organizerName: 'Current User',
attendees: [],
status: 'pending' as const
};
this.meetingBookingService.createBooking(booking).subscribe({
next: () => {
this.snackBar.open('จองห้องประชุมสำเร็จ', 'ปิด', { duration: 3000 });
this.loadScheduleData();
},
error: (error) => {
this.snackBar.open('เกิดข้อผิดพลาดในการจอง: ' + error.message, 'ปิด', { duration: 5000 });
}
});
}
onEventUpdate(args: any): void {
console.log('Event updated:', args);
// Handle event update
}
onEventDelete(args: any): void {
console.log('Event deleted:', args);
// Handle event deletion
const eventId = args.data.Id;
this.cancelBooking(eventId);
}
onViewChange(args: any): void {
console.log('View changed:', args);
this.currentView = args.currentView;
}
onDateChange_schedule(args: any): void {
console.log('Date changed:', args);
this.selectedDate_schedule = args.selectedDate;
}
// ฟังก์ชันสำหรับโหลดข้อมูลตัวอย่าง
loadSampleData(): void {
const today = new Date();
const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
const nextWeek = new Date(today);
nextWeek.setDate(nextWeek.getDate() + 7);
const sampleData = [
{
Id: 1,
Subject: 'ประชุมทีมพัฒนา',
StartTime: new Date(today.getFullYear(), today.getMonth(), today.getDate(), 9, 0),
EndTime: new Date(today.getFullYear(), today.getMonth(), today.getDate(), 10, 30),
Location: 'ห้องประชุม A',
Description: 'ประชุมทบทวนความคืบหน้าโปรเจค',
IsAllDay: false,
CategoryColor: 'success',
Status: 'confirmed',
Organizer: 'John Doe',
Attendees: 'Jane Smith, Bob Johnson'
},
{
Id: 2,
Subject: 'การนำเสนอผลงาน',
StartTime: new Date(tomorrow.getFullYear(), tomorrow.getMonth(), tomorrow.getDate(), 14, 0),
EndTime: new Date(tomorrow.getFullYear(), tomorrow.getMonth(), tomorrow.getDate(), 15, 30),
Location: 'ห้องประชุม B',
Description: 'นำเสนอผลงานไตรมาสที่ 1',
IsAllDay: false,
CategoryColor: 'info',
Status: 'pending',
Organizer: 'Alice Brown',
Attendees: 'Charlie Wilson, Diana Lee'
},
{
Id: 3,
Subject: 'อบรมเทคโนโลยีใหม่',
StartTime: new Date(nextWeek.getFullYear(), nextWeek.getMonth(), nextWeek.getDate(), 10, 0),
EndTime: new Date(nextWeek.getFullYear(), nextWeek.getMonth(), nextWeek.getDate(), 12, 0),
Location: 'ห้องประชุม C',
Description: 'อบรม Angular 17 และ TypeScript',
IsAllDay: false,
CategoryColor: 'warning',
Status: 'confirmed',
Organizer: 'Tech Lead',
Attendees: 'ทีมพัฒนา'
}
];
this.scheduleData = sampleData;
this.eventSettings = {
dataSource: this.scheduleData
};
console.log('Sample data loaded:', this.scheduleData);
}
// Statistics methods
getConfirmedCount(): number {
return this.scheduleData.filter(booking => booking.Status === 'confirmed').length;
}
getPendingCount(): number {
return this.scheduleData.filter(booking => booking.Status === 'pending').length;
}
getUniqueRoomsCount(): number {
const uniqueRooms = new Set(this.scheduleData.map(booking => booking.Location));
return uniqueRooms.size;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment