PageSourceSearch

https://holidayhomeapartments.com/wp-content/plugins/wp-hotel-book…/admin/admin.hotel-booking-v2.js?ver=2.3.0

js holidayhomeapartments.com collected 2026-10-10 00:34:39 UTC 22,200 bytes, 591 lines download raw bytes

1const getFirstDayOfMonth = (year, month) => {
2    return new Date(year, month, 1);
3}
4
5/**
6 * It adds a click event listener to each link in the tabs, and when clicked, it removes the active
7 * class from all tabs and tab content, and then adds the active class to the clicked tab and its
8 * corresponding tab content
9 */
10const MetaboxRoomTabs = () => {
11    const roomID = hotel_settings.room_id;
12    if ( roomID == 0 ) return;
13
14    const url = new URL(document.URL);
15    const linkTabs = document.querySelectorAll('.wphb-meta-box__room-tab__tabs li a');
16    const elemTabs = document.querySelectorAll('.wphb-meta-box__room-tab__tabs li');
17    const elemContent = document.querySelectorAll('.wphb-meta-box-room-panels');
18
19
20    // show tab active when update post;
21    const tabActive = window.localStorage.getItem('tabActive');
22    url.searchParams.set('tab', tabActive);
23    window.history.pushState( '', '', url.href );
24    // end show tab active when update post;
25
26    if ( linkTabs.length == 0 || elemTabs.length == 0 || elemContent.length == 0 ) return ;
27    //hide first load
28    elemTabs[0].classList.add('active');
29    elemContent[0].classList.add('active');
30
31    linkTabs.forEach( function( link ) {
32        const tabID = link.getAttribute('href');
33        const tabContent = document.querySelector( '#' + tabID );
34        //active tab when reload page
35
36        if ( url.searchParams.get('tab') == tabActive ) {
37            tabContent.classList.remove('active');
38            link.parentNode.classList.remove('active');
39            if ( tabContent.getAttribute('id') == tabActive ) {
40                tabContent.classList.add('active');
41                link.parentNode.classList.add('active');
42                if( tabContent.getAttribute('id') == 'block_room_data' ) {
43                    roomBlockDate();
44                }
45            }
46        }
47
48        link.addEventListener('click', function (e) {
49            e.preventDefault();
50            clear();
51            url.searchParams.set('tab', tabID);
52            link.parentNode.classList.add('active');
53            window.history.pushState( '', '', url.href );
54            window.localStorage.setItem('tabActive', tabID );
55            if ( tabContent !== null || url.searchParams.get('tab') == tabContent.getAttribute('id') ) {
56                tabContent.classList.add('active');
57                if( tabContent.getAttribute('id') == 'block_room_data' ) {
58                    roomBlockDate();
59                }
60            }
61        })
62    })
63    const clear = () => {
64        linkTabs.forEach( function( link ) {
65            link.parentNode.classList.remove('active');
66            const tabID = link.getAttribute('href');
67            const tabContent = document.querySelector( '#' + tabID );
68            if ( tabContent !== null ) {
69                tabContent.classList.remove('active');
70            }
71        })
72    }
73};
74
75/**
76 * It fetches the pricing plans for the current month and renders them on the calendar
77 */
78const viewAllPlanSingleRoom = () => {
79
80    const getPrices = async ( dayElem ) => {
81        const events = [];
82        const roomID = hotel_settings.room_id;
83
84        if ( roomID == null ) return events;
85
86		try {
87			const response = await wp.apiFetch( {
88				path: 'wphb/v1/admin/rooms/pricing-plans',
89				method: 'POST',
90				data: { date:dayElem , roomID },
91			} );
92
93			const {status , data } = response;
94			if ( 'success' === status ) {
95				const bookings = JSON.parse(data)
96        		for (var i = 0; i < bookings.length; ++i) {
97        			const booking = bookings[i],
98        				day = new Date(booking.d),
99        				today = new Date();
100                    const MyDateString = (day.getFullYear() + '-' + ('0' + (day.getMonth() + 1 )).slice(-2) + '-' + ('0' + day.getDate()).slice(-2));
101        			if ( booking.price > 0 ) {
102        				events.push({
103        					title: booking.price + '$',
104                            start: MyDateString,
105                            textColor: '#d04a61',
106                            backgroundColor: '#FFFFFF',
107                            borderColor: '#FFFFFF',
108                            classNames: ['wphb-pricing-plan-event'],
109        				});
110        			}
111        		}
112                return events;
113			}
114
115		} catch ( error ) {
116			alert( error.message && error.message );
117		}
118    }
119
120    const calendarEl = document.getElementById('calendar_room_pricing');
121    if ( calendarEl == null ) return;
122    const calendar = new FullCalendar.Calendar(calendarEl, {
123        events: function(info, successCallback, failureCallback) {
124            const date = new Date(info.end);
125            const firstDayCurrentMonth = getFirstDayOfMonth(
126                date.getFullYear(),
127                date.getMonth(),
128            );
129
130            const events = getPrices( firstDayCurrentMonth );
131
132            (async () => {
133                successCallback( await events )
134            })()
135        },
136        selectable: true,
137        height: 500,
138    });
139
140    const btn = document.querySelector('button.show-all-plan');
141
142    if( btn == null ) return;
143
144    btn.addEventListener('click', function (e) {
145        e.preventDefault();
146        if ( calendarEl.hasChildNodes() ) {
147            btn.textContent = btn.dataset.textView;
148            calendar.destroy();
149        } else {
150            btn.textContent = btn.dataset.textClose;
151            calendar.render();
152        }
153
154    });
155}
156
157/**
158 * It creates a calendar that allows you to select dates and then save them to the database
159 * @returns A function.
160 */
161const roomBlockDate = () => {
162    //submit block room
163    const roomID = hotel_settings.room_id;
164    let removeMonth = false;
165    let argsBlock = hotel_settings.block_dates ?? [];
166
167    if ( roomID == null ) return;
168
169    const submit = async () => {
170
171        try {
172			const response = await wp.apiFetch( {
173				path: 'wphb/v1/admin/rooms/block-date',
174				method: 'POST',
175				data: { argsBlock , roomID , removeMonth },
176			} );
177
178			const {status , message } = response;
179			if ( 'success' === status ) {
180                alert( message );
181			}
182            removeMonth = false;
183		} catch ( error ) {
184			alert( error.message && error.message );
185		}
186    }
187
188    /**
189     * It checks if the date is already selected, if it is, it removes the selected class and removes
190     * the date from the array, if it isn't, it adds the selected class and adds the date to the array
191     * @param date - The date of the day you clicked on.
192     * @param ele - The element that was clicked.
193     * @param args - an array of dates that have been selected.
194     * @returns the array of dates that have been selected.
195     */
196    const checkedBlock = ( date, ele , args ) => {
197        const eleHighLight = ele.querySelector('.fc-highlight');
198        if ( ele.classList.contains( 'selected') ) {
199            ele.classList.remove('selected');
200            ele.style.backgroundColor = '#fff';
201            const childNodeEvent = ele.querySelector('._hb_event_selected');
202            if ( childNodeEvent != null ) {
203                childNodeEvent.style.background = '#fff';
204                childNodeEvent.classList.remove('_hb_event_selected');
205                if ( eleHighLight != null) {
206                    eleHighLight.style.background = '#fff';
207                }
208            }
209            const index = args.indexOf( String( date.valueOf() / 1000) );
210            if ( index != -1 ) {
211                args.splice( index, 1 );
212            }
213        } else {
214            if ( eleHighLight != null) {
215                eleHighLight.style.backgroundColor = '#27262240';
216            }
217            ele.style.backgroundColor = '#27262240';
218            ele.className += ' selected';
219            const index = args.indexOf( String( date.valueOf() / 1000) );
220            if ( index == -1 ) {
221                args.push( String( date.valueOf() / 1000 ) );
222            }
223        }
224        argsBlock = args;
225        return argsBlock;
226    }
227
228
229    /**
230     * It removes all the block dates from the calendar.
231     * @param ele - The element that is clicked
232     * @param date - The date you want to check
233     * @param argsBlock - an array of dates that are blocked
234     */
235    const removeAllBlockDate = async ( ele , date, argsBlock ) => {
236        if ( ele === null ) return;
237        const yearCurrent = date.getFullYear();
238        const monthCurrent = date.getMonth() + 1;
239        const daysOfMonth = document.querySelectorAll('#calender_block .fc-daygri
239d-day:not(.fc-day-other)');
240
241        for ( var i = 0; i < daysOfMonth.length; ++i ) {
242            const elem = daysOfMonth[i];
243            const dateEle = new Date(elem.dataset.date);
244            const index = ( dateEle.valueOf() / 1000).toString();
245            if ( argsBlock.includes( index ) ) {
246                const bgBanner = elem.querySelector('.fc-daygrid-bg-harness');
247                if( bgBanner != null){
248                    bgBanner.remove();
249                }
250                if ( dateEle.getFullYear() == yearCurrent && ( dateEle.getMonth()  + 1 ) == monthCurrent ) {
251                    checkedBlock( dateEle, elem, argsBlock );
252                }
253            }
254        }
255
256        removeMonth = true;
257    }
258
259    /**
260     * It takes a date, and checks if it's in the block list. If it is, it adds a class to the date
261     * element
262     * @param ele - The element that was clicked.
263     * @param argsBlock - an object that contains the following properties:
264     */
265    const addAllMonthBlockDate = async ( ele , argsBlock ) => {
266        if ( ele === null ) return;
267        const daysOfMonth = document.querySelectorAll('#calender_block .fc-daygri
267d-day:not(.fc-day-other):not(.selected)');
268        if ( daysOfMonth.length == 0 ) return;
269
270        for ( var i = 0; i < daysOfMonth.length; ++i ) {
271            const elem = daysOfMonth[i];
272            const date = new Date(elem.getAttribute('data-date'));
273            checkedBlock( date, elem, argsBlock );
274        }
275
276    }
277
278    /* The above code is a function that is used to sync the calendar with the selected dates. */
279    syncCalendar = () => {
280        const daysOfMonth = document.querySelectorAll('#calender_block .fc-daygrid-day:not(.fc-day-other):not(.selected)');
281        if ( daysOfMonth.length > 0 ) {
282            daysOfMonth.forEach( function( el ) {
283                el.classList.remove('selected');
284                const eleBg = el.querySelector('.fc-daygrid-bg-harness');
285                if( eleBg != null){
286                    eleBg.remove();
287                }
288            });
289        }
290        argsBlock.forEach( function( date ) {
291            const day = new Date( date * 1000 );
292            const MyDateString = (day.getFullYear() + '-' + ('0' + (day.getMonth() + 1 )).slice(-2) + '-' + ('0' + day.getDate()).slice(-2));
293            const daySelected = document.querySelector('.fc-daygrid-day[data-date="'+MyDateString+'"]');
294            if(daySelected != null){
295                daySelected.classList.add('selected');
296                daySelected.style.backgroundColor = '#27262261';
297            }
298        });
299        const selectedEvents = document.querySelectorAll('._hb_event_selected');
300        if ( selectedEvents.length > 0 ) {
301            selectedEvents.forEach( function( el ) {
302                const parentBg = el.closest('.fc-daygrid-day');
303                parentBg.classList.add('selected');
304            });
305        };
306        const daysOther = document.querySelectorAll('#calender_block .fc-daygri
306d-day.fc-day-other');
307        if ( daysOther.length > 0 ) {
308            daysOther.forEach( function( el ) {
309                el.classList.remove('selected');
310                const eleBg = el.querySelector('.fc-daygrid-bg-harness');
311                if( eleBg != null){
312                    eleBg.remove();
313                }
314            });
315        }
316    }
317
318    const events = [];
319    argsBlock.map( function( date ) {
320        const day = new Date( date * 1000 );
321        const MyDateString = (day.getFullYear() + '-' + ('0' + (day.getMonth() + 1 )).slice(-2) + '-' + ('0' + day.getDate()).slice(-2));
322        events.push({
323            start: MyDateString,
324            backgroundColor : '#ffdc2926',
325            display: 'background',
326            classNames:['_hb_event_selected'],
327        });
328    });
329
330    const eleShowBlock = document.getElementById('calender_block');
331    if ( eleShowBlock == null ) return;
332
333	const calendarBlock = new FullCalendar.Calendar(eleShowBlock, {
334        headerToolbar: {
335            right: 'add_month disable_all prev,next'
336        },
337        initialView: 'dayGridMonth',
338		selectable: true,
339		height: 500,
340        events: events,
341        dateClick: function(info) {
342            const date = new Date(info.dateStr);
343            checkedBlock( date, info.dayEl, argsBlock );
344        },
345        customButtons: {
346            prev: {
347                click: function(e) {
348                    calendarBlock.prev();
349                    syncCalendar();
350                },
351            },
352            next: {
353                click: function() {
354                    calendarBlock.next();
355                    syncCalendar();
356                },
357            },
358            disable_all: {
359                text: 'Open This Month',
360                click: function() {
361                    const date = calendarBlock.getDate();
362                    removeAllBlockDate( this , date, argsBlock );
363                }
364            },
365            add_month: {
366                text: 'Block This Month',
367                click: function() {
368                    addAllMonthBlockDate( this , argsBlock );
369                }
370            }
371        }
372	});
373
374    const btnUpdate = document.querySelector('#tp_hotel_booking_block_date button.update_block');
375
376    if( btnUpdate === null ) return;
377    btnUpdate.addEventListener('click', function (e) {
378        e.preventDefault();
379        submit( argsBlock );
380    });
381
382    // render when active tab;
383    calendarBlock.render();
384    const selectedEvents = document.querySelectorAll('._hb_event_selected');
385    if ( selectedEvents.length > 0 ) {
386        selectedEvents.forEach( function( el ) {
387            const parentBg = el.closest('.fc-daygrid-day');
388            parentBg.classList.add('selected');
389        });
390    };
391}
392/**
393 * It creates a new FullCalendar instance, and then renders it
394 * @returns A function that returns a function.
395 */
396const CalendarManager = () => {
397    const getBookings = async ( info ) => {
398        const start = new Date( info.start );
399        const timeStart = (start.getFullYear() + '-' + ('0' + (start.getMonth() + 1 )).slice(-2) + '-' + ('0' + start.getDate()).slice(-2));
400        const end = new Date( info.end );
401        const timeEnd = (end.getFullYear() + '-' + ('0' + (end.getMonth() + 1 )).slice(-2) + '-' + ('0' + end.getDate()).slice(-2));
402
403		try {
404			const response = await wp.apiFetch( {
405				path: 'wphb/v1/admin/rooms/manager-bookings?startDay=' + timeStart + '&endDay=' + timeEnd,
406				method: 'GET',
407			} );
408
409			const {status , data } = response;
410			if ( 'success' === status ) {
411                return data;
412			} else {
413                return [];
414            }
415		} catch ( error ) {
416			alert( error.message && error.message );
417		}
418    }
419    const eleBooking = document.getElementById('manager_booking');
420    if( eleBooking == null ) return;
421	const calendarBooking = new FullCalendar.Calendar(eleBooking, {
422
423		height: 700,
424		events: function(info, successCallback, failureCallback) {
425            const bookings = getBookings( info );
426
427            (async () => {
428                successCallback( await bookings )
429            })()
430        },
431        dayMaxEvents: true,
432        eventDidMount: function(info) {
433
434            info.el.addEventListener('click',function(e){
435                const parent = this.closest('body.wp-hotel-booking_page_tp_hotel_booking_c
435alender_manager');
436                if( parent == null ) return;
437                if( parent.classList.contains('active') ) {
438                    return;
439                }
440                parent.classList.add('active');
441                parent.insertAdjacentHTML("afterbegin", htmlShow( info ));
442                const popup = document.getElementById("popup-events");
443                if ( popup == null ) return;
444                popup.style.display = 'block';
445                clickOutside( popup , parent);
446                closePopup( parent );
447
448            });
449
450            const htmlShow = (info) => {
451                const html =
452                '<div id="popup-events">' +
453                    '<div id="popup-container">' +
454                        '<div class="popup">' +
455                            '<div class="popup-header">' +
456                                '<h2>Booking Info</h2>' +
457                                '<div class="close-popup">X</div>' +
458                            '</div>' +
459                            '<div class="info">' +
460                                '<div class="info_detail">' +
461                                    '<div class="info_detail_left">' +
462                                        '<span id="heading">Order Created Date: </span><br>' +
463                                        '<span id="details">'+ info.event.extendedProps?.data_order?.order_date +'</span>' +
464                                    '</div>'+
465                                    '<div class="info_detail_right">' +
466                                        '<span id="heading">Order No.</span><br>' +
467                                        '<span id="details"><a href="'+info.event.extendedProps?.data_order?.link_edit +'" target="_blank">' +
468                                        '#' + info.event.extendedProps?.data_order?.id +'</a></span>' +
469                                    '</div>'+
470                                    '<div class="info_detail_left">' +
471                                        '<span id="heading">Check in date: </span><br>' +
472                                        '<span id="details">'+ info.event.extendedProps?.data_order?.start_date_popup  +'</span>' +
473                                    '</div>'+
474                                    '<div class="info_detail_right">' +
475                                        '<span id="heading">Check out date: </span><br>' +
476                                        '<span id="details">'+ info.event.extendedProps?.data_order?.end_date_popup +'</span>' +
477                                    '</div>'+
478                                '</div>'+
479                                '<div class="pricing">' +
480                                    '<div class="pricing_detail">' +
481                                        '<div class="pricing_detail_left">' +
482                                            '<span id="name">'+ info.event.extendedProps?.data_order?.title +'</span>' +
483                                        '</div>'+
484                                        '<div class="pricing_detail_right">' +
485                                            '<span id="price">'+ info.event.extendedProps?.data_order?.total +'</span>' +
486                                        '</div>'+
487                                    '</div>'+
488                                '</div>'+
489                            '</div>' +
490                        '</div>' +
491                    '</div>' +
492                '</div>';
493                return html;
494            }
495            const clickOutside = ( popup , parent) => {
496                document.addEventListener('click', function(e) {
497                    if( e.target.id == 'popup-container' ) {
498                        popup.style.display = 'none';
499                        parent.classList.remove('active');
500                    }
501                });
502            }
503
504            const closePopup = ( parent ) => {
505                const btn = document.querySelector('#popup-events .close-popup');
506                if ( btn == null ) return;
507                btn.addEventListener('click', function(e) {
508                    const popup = document.getElementById("popup-events");
509                    popup.style.display = 'none';
510                    parent.classList.remove('active');
511                });
512            }
513        },
514	});
515    calendarBooking.render();
516}
517
518/**
519 * It adds an event listener to the checkbox with the id of `_hb_room_preview` and when the checkbox is
520 * checked, it removes the class `hidden` from the element with the class `room_preview_url`
521 */
522const RoomPreview = () => {
523
524    const enablePreview = document.getElementById('_hb_room_preview');
525    if( enablePreview == null ) return;
526
527    enablePreview.addEventListener('change', function (e) {
528        const contentPreview = document.querySelector('.room_preview_url');
529        if ( contentPreview == null ) return;
530        if ( enablePreview.checked ) {
531            contentPreview.classList.remove('hidden');
532        } else{
533            contentPreview.classList.add('hidden');
534        }
535    });
536}
537
538const adminUpdateField = () => {
539    const btn = document.querySelector('._wphb_update_field');
540    if ( btn == null ) return;
541
542    const submit = async () => {
543		try {
544			const response = await wp.apiFetch( {
545				path: 'wphb/v1/admin/rooms/update-field',
546				method: 'POST',
547			} );
548
549			const {status , message } = response;
550			if ( 'success' === status ) {
551                alert( message );
552                window.location.reload(true);
553			} else {
554                throw new Error( message );
555            }
556		} catch ( error ) {
557			alert( error.message && error.message );
558		}
559    }
560    btn.addEventListener('click', function(e) {
561        e.preventDefault();
562        btn.classList.add('wphb_loading');
563        submit();
564    });
565}
566
567const toggleDeposit = () => {
568    const ele = document.querySelector('#deposit_room');
569    if ( ele == null ) return;
570
571    const checked = ele.querySelector('#_hb_enable_deposit');
572    if ( checked.checked ) {
573        ele.classList.remove('blocked');
574    }
575    checked.addEventListener('change',function(e) {
576        if ( checked.checked ) {
577            ele.classList.remove('blocked');
578        } else{
579            ele.classList.add('blocked');
580        }
581    });
582}
583
584document.addEventListener( 'DOMContentLoaded', () => {
585    MetaboxRoomTabs();
586    viewAllPlanSingleRoom();
587    CalendarManager();
588    RoomPreview();
589    adminUpdateField();
590    toggleDeposit();
591} );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.