PageSourceSearch

https://taksu.org/wp-content/plugins/bookly-addon-staff-cabinet/fr…/js/staff-cabinet-appointments.js?ver=27.7

js taksu.org collected 2026-10-04 16:52:09 UTC 24,205 bytes, 496 lines download raw bytes

1(function ($) {
2    window.booklyStaffAppointments = function (Options) {
3        let $container = $('.bookly-staff-cabinet-appointments.' + Options.wrapper);
4        if (!$container.length) {
5            return;
6        }
7        let $list = $('.bookly-js-appointments-list', $container),
8            $customerFilter = $('#bookly-filter-customer', $container),
9            $idFilter = $('#bookly-filter-id', $container),
10            $appointmentDateFilter = $('#bookly-filter-date', $container),
11            $creationDateFilter = $('#bookly-filter-creation-date', $container),
12            $statusFilter = $('#bookly-filter-status', $container),
13            $serviceFilter = $('#bookly-filter-service', $container),
14            $locationFilter = $('#bookly-filter-location', $container),
15            $newAppointmentBtn = $('#bookly-new-appointment', $container),
16            isMobile = false,
17            columns = [],
18            order = [],
19            pickers = {
20                dateFormat: 'YYYY-MM-DD',
21                appointmentDate: {
22                    startDate: moment().startOf('month'),
23                    endDate: moment().endOf('month'),
24                },
25                creationDate: {
26                    startDate: moment(),
27                    endDate: moment().add(100, 'years'),
28                },
29            }
30        ;
31
32        try {
33            document.createEvent('TouchEvent');
34            isMobile = true;
35        } catch (e) {}
36
37        function onChangeFilter() {
38            dt.ajax.reload();
39        }
40
41        $statusFilter.booklyDropdown({onChange: onChangeFilter});
42
43        $('.bookly-js-select', $container).val(null);
44
45        $.each(BooklySCAppointmentsL10n.datatables.appointments.settings.filter, function (field, value) {
46            if (field !== 'status') {
47                if (value != '') {
48                    $('#bookly-filter-' + field, $container).val(value);
49                }
50                // check if select has correct values
51                if ($('#bookly-filter-' + field, $container).prop('type') == 'select-one') {
52                    if ($('#bookly-filter-' + field + ' option[value="' + value + '"]', $container).length == 0) {
53                        $('#bookly-filter-' + field, $container).val(null);
54                    }
55                }
56            }
57        });
58
59        if (BooklySCAppointmentsL10n.datatables.appointments.settings.filter.hasOwnProperty('status')) {
60            $statusFilter.booklyDropdown('setSelected', BooklySCAppointmentsL10n.datatables.appointments.settings.filter.status);
61        } else {
62            $statusFilter.booklyDropdown('selectAll');
63        }
64
65        /**
66         * Init date range pickers.
67         */
68
69        let
70            pickerRanges1 = {},
71            pickerRanges2 = {}
72        ;
73        pickerRanges1[BooklySCAppointmentsL10n.dateRange.anyTime] = [moment().subtract(100, 'years'), moment().add(100, 'years')];
74        pickerRanges1[BooklySCAppointmentsL10n.dateRange.yesterday] = [moment().subtract(1, 'days'), moment().subtract(1, 'days')];
75        pickerRanges1[BooklySCAppointmentsL10n.dateRange.today] = [moment(), moment()];
76        pickerRanges1[BooklySCAppointmentsL10n.dateRange.tomorrow] = [moment().add(1, 'days'), moment().add(1, 'days')];
77        pickerRanges1[BooklySCAppointmentsL10n.dateRange.last_7] = [moment().subtract(7, 'days'), moment()];
78        pickerRanges1[BooklySCAppointmentsL10n.dateRange.last_30] = [moment().subtract(30, 'days'), moment()];
79        pickerRanges1[BooklySCAppointmentsL10n.dateRange.next_7] = [moment(), moment().add(7, 'days')];
80        pickerRanges1[BooklySCAppointmentsL10n.dateRange.next_30] = [moment(), moment().add(30, 'days')];
81        pickerRanges1[BooklySCAppointmentsL10n.dateRange.thisMonth] = [moment().startOf('month'), moment().endOf('month')];
82        pickerRanges1[BooklySCAppointmentsL10n.dateRange.nextMonth] = [moment().add(1, 'month').startOf('month'), moment().add(1, 'month').endOf('month')];
83
84        pickerRanges2[BooklySCAppointmentsL10n.dateRange.anyTime] = pickerRanges1[BooklySCAppointmentsL10n.dateRange.anyTime];
85        pickerRanges2[BooklySCAppointmentsL10n.dateRange.yesterday] = pickerRanges1[BooklySCAppointmentsL10n.dateRange.yesterday];
86        pickerRanges2[BooklySCAppointmentsL10n.dateRange.today] = pickerRanges1[BooklySCAppointmentsL10n.dateRange.today];
87        pickerRanges2[BooklySCAppointmentsL10n.dateRange.last_7] = pickerRanges1[BooklySCAppointmentsL10n.dateRange.last_7];
88        pickerRanges2[BooklySCAppointmentsL10n.dateRange.last_30] = pickerRanges1[BooklySCAppointmentsL10n.dateRange.last_30];
89        pickerRanges2[BooklySCAppointmentsL10n.dateRange.thisMonth] = pickerRanges1[BooklySCAppointmentsL10n.dateRange.thisMonth];
90
91        if (BooklySCAppointmentsL10n.tasks.enabled) {
92            pickerRanges1[BooklySCAppointmentsL10n.tasks.title] = [moment(), moment().add(1, 'days')];
93        }
94
95        $appointmentDateFilter.daterangepicker(
96            {
97                parentEl: $appointmentDateFilter.parent(),
98                startDate: pickers.appointmentDate.startDate,
99                endDate: pickers.appointmentDate.endDate,
100                ranges: pickerRanges1,
101                showDropdowns: true,
102                linkedCalendars: false,
103                autoUpdateInput: false,
104                locale: $.extend({}, BooklySCAppointmentsL10n.dateRange, BooklySCAppointmentsL10n.datePicker)
105            },
106            function (start, end, label) {
107                switch (label) {
108                    case BooklySCAppointmentsL10n.tasks.title:
109                        $appointmentDateFilter
110                            .data('date', 'null')
111                            .find('span')
112                            .html(BooklySCAppointmentsL10n.tasks.title);
113                        break;
114                    case BooklySCAppointmentsL10n.dateRange.anyTime:
115                        $appointmentDateFilter
116                            .data('date', 'any')
117                            .find('span')
118                            .html(BooklySCAppointmentsL10n.dateRange.anyTime);
119                        break;
120                    default:
121                        $appointmentDateFilter
122                            .data('date', start.format(pickers.dateFormat) + ' - ' + end.format(pickers.dateFormat))
123                            .find('span')
124                            .html(start.format(BooklySCAppointmentsL10n.dateRange.format) + ' - ' + end.format(BooklySCAppointmentsL10n.dateRange.format));
125                }
126            }
127        );
128
129        $creationDateFilter.daterangepicker(
130            {
131                parentEl: $creationDateFilter.parent(),
132                startDate: pickers.creationDate.startDate,
133                endDate: pickers.creationDate.endDate,
134                ranges: pickerRanges2,
135                showDropdowns: true,
136                linkedCalendars: false,
137                autoUpdateInput: false,
138                locale: $.extend(BooklySCAppointmentsL10n.dateRange, BooklySCAppointmentsL10n.datePicker)
139            },
140            function (start, end, label) {
141                switch (label) {
142                    case BooklySCAppointmentsL10n.tasks.title:
143                        $creationDateFilter
144                            .data('date', 'null')
145                            .find('span')
146                            .html(BooklySCAppointmentsL10n.tasks.title);
147                        break;
148                    case BooklySCAppointmentsL10n.dateRange.anyTime:
149                        $creationDateFilter
150                            .data('date', 'any')
151                            .find('span')
152                            .html(BooklySCAppointmentsL10n.dateRange.createdAtAnyTime);
153                        break;
154                    default:
155                        $creationDateFilter
156                            .data('date', start.format(pickers.dateFormat) + ' - ' + end.format(pickers.dateFormat))
157                            .find('span')
158                            .html(start.format(BooklySCAppointmentsL10n.dateRange.format) + ' - ' + end.format(BooklySCAppointmentsL10n.dateRange.format));
159                }
160            }
161        );
162
163        /**
164         * Init table columns.
165         */
166        $.each(BooklySCAppointmentsL10n.datatables.appointments.settings.columns, function (column, show) {
167            if (show) {
168                switch (column) {
169                    case 'customer_full_name':
170                        columns.push({data: 'customer.full_name', render: $.fn.dataTable.render.text()});
171                        break;
172                    case 'customer_phone':
173                        columns.push({
174                            data: 'customer.phone',
175                            render: function (data, type, row, meta) {
176                                if (isMobile) {
177                                    return '<a href="tel:' + window.booklyIntlTelInput.utils.formatNumber($.fn.dataTable.render.text().display(data), null, window.booklyIntlTelInput.utils.numberFormat.INTERNATIONAL) + '">' + $.fn.dataTable.render.text().display(data) + '</a>';
178                                } else {
179                                    return data ? '<span style="white-space: nowrap;">' + window.booklyIntlTelInput.utils.formatNumber($.fn.dataTable.render.text().display(data), null, window.booklyIntlTelInput.utils.numberFormat.INTERNATIONAL) + '</span>' : '';
180                                }
181                            }
182                        });
183                        break;
184                    case 'customer_email':
185                        columns.push({data: 'customer.email', render: $.fn.dataTable.render.text()});
186                        break;
187                    case 'customer_address':
188                        columns.push({data: 'customer.address', render: $.fn.dataTable.render.text(), orderable: false});
189                        break;
190                    case 'customer_birthday':
191                        columns.push({data: 'customer.birthday', render: $.fn.dataTable.render.text()});
192                        break;
193                    case 'staff_name':
194                        columns.push({data: 'staff.name', render: $.fn.dataTable.render.text()});
195                        break;
196                    case 'service_title':
197                        columns.push({
198                            data: 'service.title',
199                            render: function (data, type, row, meta) {
200                                data = $.fn.dataTable.render.text().display(data);
201                                if (row.service.extras.length) {
202                                    var extras = '<ul class="bookly-list list-dots">';
203                                    $.each(row.service.extras, function (key, item) {
204                                        extras += '<li><nobr>' + item.title + '</nobr></li>';
205                                    });
206                                    extras += '</ul>';
207                                    return data + extras;
208                                } else {
209                                    return data;
210                                }
211                            }
212                        });
213                        break;
214                    case 'payment':
215                        columns.push({
216                            data: 'payment',
217                            render: function (data, type, row, meta) {
218                                if (row.payment_id) {
219                                    if (Options.read_only) {
220                                        return data;
221                                    }
222                                    return '<a type="button" data-action="show-payment" class="text-primary" data-payment_id="' + row.payment_id + '">' + data + '</a>';
223                                }
224                                return '';
225                            }
226                        });
227                        break;
228                    case 'service_duration':
229                        columns.push({data: 'service.duration'});
230                        break;
231                    case 'attachments':
232                        columns.push({
233                            data: 'attachment',
234                            render: function (data, type, row, meta) {
235                                if (data == '1') {
236                                    if (Options.read_only) {
237                                        return '<i class="fas fa-fw fa-paperclip"></i>';
238                                    }
239                                    return '<button type="button" class="btn btn-link" data-action="show-attachments" title="' + BooklySCAppointmentsL10n.attachments + '"><i class="fas fa-fw fa-paperclip"></i></button>';
240                                }
241                                return '';
242                            }
243                        });
244                        break;
245                    case 'rating':
246                        columns.push({
247                            data: 'rating',
248                            render: function (data, type, row, meta) {
249                                if (row.rating_comment == null) {
250                                    return row.rating;
251                                } else {
252                                    return '<a href="#" data-toggle="bookly-popover" data-trigger="hover" data-placement="bottom" data-content="' + $.fn.dataTable.render.text().display(row.rating_comment) + '" data-container="#bookly-appointments-list">' + $.fn.dataTable.render.text().display(row.rating) + '</a>';
253                                }
254                            },
255                        });
256                        break;
257                    case 'internal_note':
258                    case 'locations':
259                    case 'notes':
260                    case 'number_of_persons':
261                        columns.push({data: column, render: $.fn.dataTable.render.text()});
262                        break;
263                    case 'online_meeting':
264                        columns.push({
265                            data: 'online_meeting_provider',
266                            render: function (data, type, row, meta) {
267                                switch (data) {
268                                    case 'zoom':
269                                        return '<a class="badge badge-primary" href="https://zoom.us/j/' + $.fn.dataTable.render.text().display(row.online_meeting_start_url) + '" target="_blank"><i class="fas fa-video fa-fw"></i> Zoom <i class="fas fa-external-link-alt fa-fw"></i></a>';
270                                    case 'google_meet':
271                                        return '<a class="badge badge-primary" href="' + $.fn.dataTable.render.text().display(row.online_meeting_start_url) + '" target="_blank"><i class="fas fa-video fa-fw"></i> Google Meet <i class="fas fa-external-link-alt fa-fw"></i></a>';
272                                    case 'jitsi':
273                                        return '<a class="badge badge-primary" href="' + $.fn.dataTable.render.text().display(row.online_meeting_start_url) + '" target="_blank"><i class="fas fa-video fa-fw"></i> Jitsi Meet <i class="fas fa-external-link-alt fa-fw"></i></a>';
274                                    case 'bbb':
275                                        return '<a class="badge badge-primary" href="' + $.fn.dataTable.render.text().display(row.online_meeting_start_url) + '" target="_blank"><i class="fas fa-video fa-fw"></i> BigBlueButton <i class="fas fa-external-link-alt fa-fw"></i></a>';
276                                    case 'teams':
277                                        return '<a class="badge badge-primary" href="' + $.fn.dataTable.render.text().display(row.online_meeting_start_url) + '" target="_blank"><i class="fas fa-video fa-fw"></i> Microsoft Teams <i class="fas fa-external-link-alt fa-fw"></i></a>';
278                                    default:
279                                        return '';
280                                }
281                            },
282                        });
283                        break;
284                    default:
285                        if (column.startsWith('custom_fields_')) {
286                            columns.push({
287                                data: column.replace(/_([^_]*)$/, '.$1'),
288                                render: $.fn.dataTable.render.text(),
289                                orderable: false
290                            });
291                        } else {
292                            columns.push({data: column, render: $.fn.dataTable.render.text()});
293                        }
294                        break;
295                }
296            }
297        });
298
299        if (!Options.read_only) {
300            columns.push({
301                data: null,
302                responsivePriority: 1,
303                orderable: false,
304                width: 120,
305                render: function(data, type, row, meta) {
306                    return '<button type="button" class="btn btn-default" data-action="edit"><i class="far fa-fw fa-edit mr-lg-1"></i><span class="d-none d-lg-inline">' + BooklySCAppointmentsL10n.edit + '…</span></button>';
307                }
308            });
309        }
310
311        columns[0].responsivePriority = 0;
312
313        $.each(BooklySCAppointmentsL10n.datatables.appointments.settings.order, function (_, value) {
314            const index = columns.findIndex(function (c) { return c.data === value.column; });
315            if (index !== -1) {
316                order.push([index, value.order]);
317            }
318        });
319
320        /**
321         * Init DataTables.
322         */
323        var dt = $list.DataTable({
324            order: order,
325            info: false,
326            searching: false,
327            lengthChange: false,
328            processing: true,
329            responsive: true,
330            pageLength: 25,
331            pagingType: 'numbers',
332            serverSide: true,
333            drawCallback: function (settings) {
334                $('[data-toggle="bookly-popover"]', $list).on('click', function (e) {
335                    e.preventDefault();
336                }).booklyPopover();
337                dt.responsive.recalc();
338            },
339            ajax: {
340                url: ajaxurl,
341                type: 'POST',
342                data: function (d) {
343                    return $.extend({action: 'bookly_staff_cabinet_get_appointments', csrf_token: BooklyL10nGlobal.csrf_token}, {
344                        filter: {
345                            id: $idFilter.val(),
346                            date: $appointmentDateFilter.data('date'),
347                            created_date: $creationDateFilter.data('date'),
348                            customer: $customerFilter.val(),
349                            service: $serviceFilter.val(),
350                            status: $statusFilter.booklyDropdown('getSelected'),
351                            location: $locationFilter.val()
352                        }
353                    }, d);
354                }
355            },
356            columns: columns,
357            language: {
358                zeroRecords: BooklySCAppointmentsL10n.zeroRecords,
359                processing: BooklySCAppointmentsL10n.processing,
360                emptyTable: BooklySCAppointmentsL10n.emptyTable,
361                loadingRecords: BooklySCAppointmentsL10n.loadingRecords
362            },
363            layout: {
364                bottomStart: 'paging',
365                bottomEnd: null
366            }
367        });
368
369        dt.on('responsive-display', function (e, datatable, row, showHide, update) {
370            if (showHide) {
371                $('[data-toggle="bookly-popover"]', row.child()).on('click', function (e) {
372                    e.preventDefault();
373                }).booklyPopover();
374            }
375        });
376
377        if (!Options.read_only) {
378            $list
379                // Show payment details
380                .on('click', '[data-action=show-payment]', function() {
381                    BooklyPaymentDetailsDialog.showDialog({
382                        payment_id: getDTRowData(this).payment_id,
383                        done: function(event) {
384                            dt.ajax.reload(null, false);
385                        }
386                    });
387                })
388                // Edit appointment.
389                .on('click', '[data-action=edit]', function(e) {
390                    e.preventDefault();
391                    BooklyAppointmentDialog.showDialog(
392                        getDTRowData(this).id,
393                        null,
394                        null,
395                        function(event) {
396                            dt.ajax.reload(null, false);
397                        }
398                    )
399                });
400
401            /**
402             * Add appointment.
403             */
404            $newAppointmentBtn.on('click', function() {
405                BooklyAppointmentDialog.showDialog(
406                    null,
407                    null,
408                    moment(),
409                    function(event) {
410                        dt.ajax.reload(null, false);
411                    }
412                )
413            });
414        }
415
416        /**
417         * On filters change.
418         */
419        $('.bookly-js-select')
420            .booklySelect2({
421                width: '100%',
422                theme: 'bootstrap4',
423                dropdownParent: $container,
424                allowClear: true,
425                placeholder: '',
426                language: {
427                    noResults: function () {
428                        return BooklySCAppointmentsL10n.no_result_found;
429                    }
430                },
431                matcher: function (params, data) {
432                    const term = $.trim(params.term).toLowerCase();
433                    if (term === '' || data.text.toLowerCase().indexOf(term) !== -1) {
434                        return data;
435                    }
436
437                    let result = null;
438                    const search = $(data.element).data('search');
439                    search &&
440                    search.find(function (text) {
441                        if (result === null && text.toLowerCase().indexOf(term) !== -1) {
442                            result = data;
443                        }
444                    });
445
446                    return result;
447                }
448            });
449
450        $('.bookly-js-select-ajax')
451            .booklySelect2({
452                width: '100%',
453                theme: 'bootstrap4',
454                dropdownParent: $container,
455                allowClear: true,
456                placeholder: '',
457                language: {
458                    noResults: function () {
459                        return BooklySCAppointmentsL10n.no_result_found;
460                    },
461                    searching: function () {
462                        return BooklySCAppointmentsL10n.searching;
463                    }
464                },
465                ajax: {
466                    url: ajaxurl,
467                    dataType: 'json',
468                    delay: 250,
469                    data: function (params) {
470                        params.page = params.page || 1;
471                        return {
472                            action: this.action === undefined ? $(this).data('ajax--action') : this.action,
473                            filter: params.term,
474                            page: params.page,
475                            csrf_token: BooklyL10nGlobal.csrf_token
476                        };
477                    }
478                },
479            });
480
481        function getDTRowData(element) {
482            let $el = $(element).closest('td');
483            if ($el.hasClass('child')) {
484                $el = $el.closest('tr').prev();
485            }
486            return dt.row($el).data();
487        }
488
489        $idFilter.on('keyup', onChangeFilter);
490        $appointmentDateFilter.on('apply.daterangepicker', onChangeFilter);
491        $creationDateFilter.on('apply.daterangepicker', onChangeFilter);
492        $customerFilter.on('change', onChangeFilter);
493        $serviceFilter.on('change', onChangeFilter);
494        $locationFilter.on('change', onChangeFilter);
495    }
496})(jQuery);

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.