Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // .. imports
- export class ScheduleComponent implements OnInit, CanNavigateAway {
- public days = [];
- public date: Date = new Date();
- public slotsCount: number = 0;
- public times = [];
- public slots = [];
- public boardHeight = 500;
- public status: string;
- public infoStep: number = 0;
- public readonly RATE_MODULES = RATE_MODULES;
- public rateButtonTitle = {
- yes: 'I like it!',
- ok: 'Not sure'
- };
- private isActive: boolean = false;
- private startSlot?: number;
- private startTime?: number;
- private provider: Provider;
- private appointments: Appointment[];
- private schedule: Schedule;
- private headerHeight = 221;
- private headerFooterHeight = 298;
- private newDay;
- private newUrl: string;
- private confirmDialogConfig: MatDialogConfig;
- @ViewChild('sidebar') private leftSidebar: ElementRef;
- constructor(
- private storageService: StorageService,
- private providerService: ProviderService,
- private appointmentService: AppointmentService,
- private scheduleService: ScheduleService,
- private intercomService: IntercomService,
- public dialog: MatDialog,
- public router: Router,
- public environment: AppConfig) {
- this.confirmDialogConfig = new MatDialogConfig();
- this.confirmDialogConfig.disableClose = true;
- }
- public async ngOnInit() {
- let schedules;
- [this.provider, this.appointments, schedules] = await Promise.all([
- this.providerService.getProvider(),
- this.appointmentService.getProviderAppointments(this.date),
- this.scheduleService.getProviderSchedule()
- ]);
- this.initSchedule(schedules);
- this.initDays(schedules);
- this.initSlots();
- this.initTutorial();
- // to set the board directly inside the viewport
- this.boardHeight = window.innerHeight - this.headerHeight;
- }
- public getDateString() {
- const dayName = stringUtils.getWeekDay(this.date);
- return `${dayName}, ${this.date.toLocaleDateString('en-us', {month: 'long'})}
- ${this.date.getDate()}, ${this.date.getFullYear()}`;
- }
- public initSlots() {
- this.appointments = this.appointments.filter((a) => {
- return a.duration && a.status !== 'canceled' && a.status !== 'lateCanceled' &&
- !(a.status === 'failed' && a.failedAction === 'lateCanceled');
- });
- this.initTimes();
- const maxs = this.times.map((t) => {
- return t.appointments.length > t.freeSlots ? t.appointments.length : t.freeSlots;
- });
- this.slotsCount = Math.max.apply(null, maxs);
- if (!this.slotsCount) {
- this.slotsCount = 5;
- }
- this.slots = new Array(this.slotsCount);
- }
- public changeSlotsCount() {
- this.slots = new Array(this.slotsCount);
- this.times.forEach((t) => {
- if (t.freeSlots > this.slotsCount) {
- t.freeSlots = this.slotsCount;
- this.changeStatus('save');
- }
- });
- }
- public async selectDay(day) {
- if (!day.disabled) {
- if (this.status) {
- this.newDay = day;
- let dialogRef = this.dialog.open(ConfirmDialogComponent, this.confirmDialogConfig);
- dialogRef.componentInstance.caption =
- 'If you don’t save, your schedule changes will be lost.';
- dialogRef.afterClosed().subscribe((result) => {
- this.status = undefined;
- if (result) {
- this.saveScheduleSlots();
- }
- this.selectDay(this.newDay);
- this.changeStatus();
- });
- } else {
- this.date = day.date;
- let schedules;
- [this.appointments, schedules] = await Promise.all([
- this.appointmentService.getProviderAppointments(this.date),
- this.scheduleService.getProviderSchedule()
- ]);
- this.initSchedule(schedules);
- this.initSlots();
- }
- }
- }
- public hoverIn(slotIndex, timeIndex) {
- if (!this.isActive) {
- this.startSlot = slotIndex;
- this.startTime = timeIndex;
- this.changePickedCells(false);
- this.changeCellState(slotIndex, timeIndex);
- }
- }
- public selectStart(slotIndex, timeIndex) {
- this.isActive = true;
- this.startSlot = slotIndex;
- this.startTime = timeIndex;
- this.changeCellState(slotIndex, timeIndex);
- if (this.infoStep === 2) this.infoStep = 3;
- }
- public selectEnd() {
- this.changePickedCells(true);
- this.isActive = false;
- this.startSlot = undefined;
- this.startTime = undefined;
- }
- public cellOver(slotIndex, timeIndex) {
- if (this.isActive) {
- this.changePickedCells(false);
- this.changeCellState(slotIndex, timeIndex);
- }
- }
- public changeCellState(slotIndex, timeIndex) {
- const index: number = this.startSlot > slotIndex ? this.startSlot : slotIndex;
- if (this.startTime === timeIndex) {
- this.times[timeIndex].picked = index + 1;
- } else {
- const [fromTime, toTime] = this.startTime > timeIndex ? [timeIndex, this.startTime] :
- [this.startTime, timeIndex];
- for (let t = fromTime; t <= toTime; t++) {
- this.times[t].picked = index + 1;
- }
- }
- }
- public getCellContent(t) {
- const chunk = this.provider.publishStatus === 'virtual' ? 15 : 30;
- const endTime = t.time.clone().addMinutes(chunk);
- const result = `${t.freeSlots} at ${t.time.toString(false)}-${endTime.toString(false)}`;
- return result;
- }
- public removeSlots(t) {
- t.freeSlots = 0;
- }
- public changeStatus(status?: string) {
- this.status = status;
- switch (status) {
- case 'save':
- this.boardHeight = window.innerHeight - this.headerFooterHeight;
- this.intercomService.hide();
- break;
- case 'saving':
- this.saveScheduleSlots();
- this.intercomService.hide();
- break;
- case 'saved': setTimeout(() => {
- this.changeStatus();
- this.intercomService.show();
- }, 500); break;
- default: this.boardHeight = window.innerHeight - this.headerHeight;
- }
- }
- public canNavigateAway(nextUrl: string): boolean {
- if (this.status) {
- let dialogRef = this.dialog.open(ConfirmDialogComponent, this.confirmDialogConfig);
- dialogRef.componentInstance.caption =
- 'If you don’t save, your schedule changes will be lost.';
- dialogRef.afterClosed().subscribe((result) => {
- this.changeStatus();
- if (result) {
- this.saveScheduleSlots();
- }
- this.router.navigate([nextUrl]);
- });
- return false;
- }
- return true;
- }
- public onScroll(event) {
- this.leftSidebar.nativeElement.scrollTop = event.target.scrollTop;
- }
- public nextStep() {
- this.infoStep++;
- if (this.infoStep > 3) {
- this.infoStep = 0;
- const passedArray = this.storageService.getConfigItem('scheduleTutorialPassed') || [];
- passedArray.push(this.provider.id);
- this.storageService.setConfigItem('scheduleTutorialPassed', passedArray);
- }
- }
- // ----- window events -----
- @HostListener('window:resize', ['$event'])
- public onResize(event) {
- this.boardHeight = window.innerHeight -
- (this.status ? this.headerFooterHeight : this.headerHeight);
- }
- @HostListener('window:beforeunload', ['$event'])
- public beforeUnload(event) {
- return !this.status;
- }
- // ----- private functions -----
- private initTutorial() {
- const passedArray = this.storageService.getConfigItem('scheduleTutorialPassed') || [];
- if (passedArray.indexOf(this.provider.id) === -1) {
- if (!this.schedule || !this.schedule.slots || !this.schedule.slots.length) {
- this.infoStep = 1;
- } else {
- passedArray.push(this.provider.id);
- this.storageService.setConfigItem('scheduleTutorialPassed', passedArray);
- }
- }
- }
- private initDays(schedules) {
- for (let i = 0; i < 7; i++) {
- this.days.push(this.initDayByOffest(i, schedules));
- }
- if (this.schedule.dayoff) {
- const availableDate = this.days.find((d) => !d.disabled);
- if (availableDate) {
- this.selectDay(availableDate);
- }
- }
- }
- private initDayByOffest(offset: number, schedules: Schedule[]) {
- const data: any = {};
- const date: Date = new Date();
- date.setDate(date.getDate() + offset);
- data.day = stringUtils.getWeekDay(date);
- data.dateString = `${date.getMonth() + 1}/${date.getDate()}`;
- data.date = date;
- if (schedules) {
- const schedule = schedules.find((s) => s.weekDay === date.getDay());
- if (schedule) {
- data.disabled = schedule.dayoff;
- }
- }
- return data;
- }
- private initTimes() {
- this.times = [];
- const chunk = this.provider.publishStatus === 'virtual' ? 15 : 30;
- const endDate = new Time(this.schedule.end.hours, this.schedule.end.minutes).getDate();
- for (let step = new Time(this.schedule.start.hours, this.schedule.start.minutes);
- step.getDate() < endDate; step.addMinutes(chunk)) {
- const time = {
- id: null,
- time: step.clone(),
- appointments: [],
- freeSlots: 0
- };
- const schedule = this.schedule.slots.find((s) => time.time.isEqual(s.time));
- if (schedule) {
- time.freeSlots = schedule.slotsCount;
- }
- const appointments = this.appointments
- .filter((a) => {
- const serviceDate = new Date(a.serviceDate);
- const serviceTime = new Time(serviceDate.getHours(), serviceDate.getMinutes());
- return time.time.isEqual(serviceTime);
- });
- if (appointments && appointments.length) {
- appointments.forEach((a) => {
- time.appointments.push({
- service: a.service,
- name: `${a.client.firstName} ${a.client.lastName}`,
- duration: a.duration / chunk
- });
- });
- }
- this.times.push(time);
- }
- for (let i = 1; i < this.times.length; i++) {
- const prevApps = this.times[i - 1].appointments;
- const currApps = this.times[i].appointments;
- if (prevApps && prevApps.length) {
- for (let a = 0; a < prevApps.length; a++) {
- if (prevApps[a] && prevApps[a].duration > 1) {
- const prolongedApp = { duration: prevApps[a].duration - 1 };
- if (currApps.length < a) {
- currApps[a] = prolongedApp;
- } else {
- currApps.splice(a, 0, prolongedApp);
- }
- }
- }
- }
- }
- }
- private changePickedCells(isFinish: boolean) {
- this.times.forEach((t) => {
- if (isFinish && t.picked && t.picked > t.freeSlots) {
- t.freeSlots = t.picked;
- }
- t.picked = 0;
- });
- if (isFinish) {
- this.changeStatus('save');
- }
- }
- private async initSchedule(schedules) {
- const dayNum = this.date.getDay();
- this.schedule = schedules.find((s) => s.weekDay === dayNum);
- if (!this.schedule) {
- this.schedule = new Schedule();
- this.schedule.start = new Time(9, 0);
- this.schedule.end = new Time(18, 30);
- this.schedule.providerId = this.provider.id;
- this.schedule.weekDay = this.date.getDay();
- this.schedule.slots = [];
- this.schedule = await this.scheduleService.saveSchedule(this.schedule);
- }
- }
- private async saveScheduleSlots() {
- let result = [];
- result = this.times.filter((t) => t.freeSlots).map((t) => {
- return {
- time: t.time,
- slotsCount: t.freeSlots
- };
- });
- this.schedule.slots = result;
- await this.scheduleService.updateSchedule(this.schedule);
- this.changeStatus('saved');
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement