PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.4
VikBooking Hotel Booking Engine & PMS v1.6.4
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
vikbooking / admin / helpers / widgets / reminders.php

reminders.php in VikBooking Hotel Booking Engine & PMS 1.6.4, at admin/helpers/widgets/reminders.php

1,314 lines 44.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - E4J srl
6 * @copyright Copyright (C) 2022 E4J srl. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 * @link https://vikwp.com
9 */
10
11 defined('ABSPATH') or die('No script kiddies please!');
12
13 /**
14 * Class handler for admin widget "reminders".
15 *
16 * @since 1.15.0 (J) - 1.5.0 (WP)
17 */
18 class VikBookingAdminWidgetReminders extends VikBookingAdminWidget
19 {
20 /**
21 * The instance counter of this widget. Since we do not load individual parameters
22 * for each widget's instance, we use a static counter to determine its settings.
23 *
24 * @var int
25 */
26 protected static $instance_counter = -1;
27
28 /**
29 * Default number of reminders per page.
30 *
31 * @var int
32 */
33 protected $reminders_per_page = 6;
34
35 /**
36 * Tells whether VCM is installed.
37 *
38 * @var bool
39 */
40 protected $vcm_exists = false;
41
42 /**
43 * Class constructor will define the widget name and identifier.
44 */
45 public function __construct()
46 {
47 // call parent constructor
48 parent::__construct();
49
50 $this->widgetName = JText::translate('VBO_W_REMINDERS_TITLE');
51 $this->widgetDescr = JText::translate('VBO_W_REMINDERS_DESCR');
52 $this->widgetId = basename(__FILE__, '.php');
53
54 // define widget and icon and style name
55 $this->widgetIcon = '<i class="' . VikBookingIcons::i('bell') . '"></i>';
56 $this->widgetStyleName = 'green';
57
58 // load widget's settings
59 $this->widgetSettings = $this->loadSettings();
60 if (!is_object($this->widgetSettings)) {
61 $this->widgetSettings = new stdClass;
62 }
63
64 // check if VCM is available
65 if (is_file(VCM_SITE_PATH . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'lib.vikchannelmanager.php')) {
66 $this->vcm_exists = true;
67 }
68 }
69
70 /**
71 * This widget does not actually need to preload data to be watched for
72 * dispatching notifications, and the reminders due are automatically
73 * scheduled for being dispatched as a browser notification. However,
74 * we make use of this method to periodically check if some reminders
75 * should be automatically created for specific reasons, such as the
76 * Airbnb host-to-guest reviews to remind the host to review the guest.
77 * We also preload the necessary CSS/JS assets and schedule the imminent
78 * reminders for notifications, if any.
79 *
80 * @return void
81 */
82 public function preload()
83 {
84 // declare JS lang vars
85 JText::script('VBO_PLEASE_FILL_FIELDS');
86 JText::script('VBDELCONFIRM');
87 JText::script('VBCONFIGCLOSINGDATEADD');
88 JText::script('VBADMINNOTESUPD');
89
90 // load assets
91 $this->vbo_app->loadDatePicker();
92
93 // check if VCM is available
94 if ($this->vcm_exists) {
95 $today_dt = date('Y-m-d');
96 $yesterday_dt = date('Y-m-d', strtotime('yesterday'));
97
98 // check the last time this check was made
99 $last_check_dt = isset($this->widgetSettings->last_check_dt) ? $this->widgetSettings->last_check_dt : $yesterday_dt;
100
101 if ($last_check_dt != $today_dt) {
102 // update last check date
103 $this->widgetSettings->last_check_dt = $today_dt;
104 $this->updateSettings(json_encode($this->widgetSettings));
105
106 // check for any Channel Manager reservation that requires an auto-reminder
107 $this->scheduleChannelManagerReminders();
108 }
109 }
110
111 // load the 10 next (imminent) reminders
112 $overdue = VBORemindersHelper::getInstance()->getImminents(10);
113 if ($overdue) {
114 // schedule browser notifications for the next reminders
115 VBONotificationScheduler::getInstance()->enqueueReminders($overdue);
116 }
117
118 // nothing should be actually watched, ever
119 return null;
120 }
121
122 /**
123 * Custom method for this widget only to load the reminder records.
124 * The method is called by the admin controller through an AJAX request.
125 * The visibility should be public, it should not exit the process, and
126 * any content sent to output will be returned to the AJAX response.
127 * In this case we return an array because this method requires "return":1.
128 *
129 * It's the actual rendering of the widget which also allows navigation.
130 *
131 * @return array
132 */
133 public function loadReminders()
134 {
135 $offset = VikRequest::getInt('offset', 0, 'request');
136 $length = VikRequest::getInt('length', $this->reminders_per_page, 'request');
137 $completed = VikRequest::getInt('completed', 0, 'request');
138 $expired = VikRequest::getInt('expired', 0, 'request');
139 $bid = VikRequest::getInt('bid', 0, 'request');
140 $wrapper = VikRequest::getString('wrapper', '', 'request');
141
142 // load reminders starting from today at 00:00:00
143 $now_info = getdate();
144 $lim_min_date = date('Y-m-d H:i:s', mktime(0, 0, 0, $now_info['mon'], $now_info['mday'], $now_info['year']));
145
146 // prepare fetch options
147 $fetch = [
148 'after' => $lim_min_date,
149 'completed' => $completed,
150 'expired' => $expired,
151 'idorder' => $bid,
152 ];
153
154 // load reminders
155 $helper = VBORemindersHelper::getInstance();
156 $reminders = $helper->loadReminders($fetch, $offset, $length);
157
158 // check if a next page can be available
159 $has_next_page = (count($reminders) >= $length);
160
161 // compose bookings base URI
162 $bookings_base_uri = 'index.php?option=com_vikbooking&task=editorder&cid[]=%d';
163 if (VBOPlatformDetection::isWordPress()) {
164 $bookings_base_uri = str_replace('index.php', 'admin.php', $bookings_base_uri);
165 }
166
167 // start output buffering
168 ob_start();
169
170 if (!count($reminders)) {
171 ?>
172 <p class="info"><?php echo JText::translate('VBONORESULTS'); ?></p>
173 <?php
174 } else {
175 // update widget's settings with the lastly used filters
176 $this->widgetSettings->show_completed = $completed;
177 $this->widgetSettings->show_expired = $expired;
178 $this->updateSettings(json_encode($this->widgetSettings));
179 }
180
181 foreach ($reminders as $reminder) {
182 $use_icn_status = $reminder->completed ? 'dot-circle' : 'far fa-circle';
183 $hidden_date = '';
184 $hidden_hours = '';
185 $hidden_minutes = '';
186 if (!empty($reminder->duedate)) {
187 $date_parts = explode(' ', $reminder->duedate);
188 $hidden_date = date($this->df, strtotime($date_parts[0]));
189 if ($reminder->usetime) {
190 $time_parts = explode(':', $date_parts[1]);
191 $hidden_hours = (int)$time_parts[0];
192 $hidden_minutes = (int)$time_parts[1];
193 }
194 }
195 $is_past_reminder = false;
196 if (!empty($reminder->duedate)) {
197 // calculate distance to expiration date from today
198 $diff_data = $helper->relativeDatesDiff($reminder->duedate);
199 $is_past_reminder = $diff_data['past'];
200 }
201
202 // list of extra classes for the reminder
203 $extra_classes = [];
204 if ($is_past_reminder) {
205 $extra_classes[] = 'vbo-reminder-past';
206 } else {
207 $extra_classes[] = 'vbo-reminder-future';
208 }
209 if ($reminder->completed) {
210 $extra_classes[] = 'vbo-reminder-ok';
211 } else {
212 $extra_classes[] = 'vbo-reminder-nok';
213 }
214
215 ?>
216 <div class="vbo-widget-reminders-record <?php echo implode(' ', $extra_classes); ?>" data-reminderid="<?php echo $reminder->id; ?>">
217 <div class="vbo-widget-reminders-record-status">
218 <button type="button" class="vbo-reminder-status-dot" onclick="vboWidgetRemindersComplete('<?php echo $wrapper; ?>', '<?php echo $reminder->id; ?>');"><?php VikBookingIcons::e($use_icn_status); ?></button>
219 </div>
220 <div class="vbo-widget-reminders-record-info">
221 <div class="vbo-widget-reminders-record-txt">
222 <span class="vbo-widget-reminder-title"><?php echo htmlspecialchars($reminder->title); ?></span>
223 <?php
224 if (!empty($reminder->descr)) {
225 ?>
226 <span class="vbo-widget-reminder-descr"><?php echo htmlspecialchars($reminder->descr); ?></span>
227 <?php
228 }
229 ?>
230 </div>
231 <div class="vbo-widget-reminders-record-due">
232 <span class="vbo-widget-reminder-date" style="display: none;"><?php echo $hidden_date; ?></span>
233 <span class="vbo-widget-reminder-hours" style="display: none;"><?php echo $hidden_hours; ?></span>
234 <span class="vbo-widget-reminder-minutes" style="display: none;"><?php echo $hidden_minutes; ?></span>
235 <?php
236 if (!empty($reminder->idorder) && $reminder->idorder > 0) {
237 ?>
238 <span class="vbo-widget-reminder-idorder" style="display: none;"><?php echo $reminder->idorder; ?></span>
239 <div class="vbo-widget-reminders-record-due-booking">
240 <a class="label label-info" href="<?php echo sprintf($bookings_base_uri, $reminder->idorder); ?>" target="_blank"><?php echo $reminder->idorder; ?></a>
241 </div>
242 <?php
243 }
244 if (!empty($reminder->duedate)) {
245 ?>
246 <div class="vbo-widget-reminders-record-due-datetime">
247 <div class="vbo-widget-reminders-record-due-date">
248 <span title="<?php echo $reminder->duedate; ?>"><?php echo $diff_data['relative']; ?></span>
249 </div>
250 <?php
251 if ($reminder->usetime) {
252 ?>
253 <div class="vbo-widget-reminders-record-due-time">
254 <span><?php echo $diff_data['date_a']->format('H:i'); ?></span>
255 </div>
256 <?php
257 }
258 ?>
259 </div>
260 <?php
261 }
262 ?>
263 </div>
264 </div>
265 <div class="vbo-widget-reminders-record-edit">
266 <button type="button" class="vbo-reminder-record-edit" onclick="vboWidgetRemindersEdit('<?php echo $wrapper; ?>', '<?php echo $reminder->id; ?>');"><?php VikBookingIcons::e('edit'); ?></button>
267 </div>
268 </div>
269 <?php
270 }
271
272 // append navigation
273 ?>
274 <div class="vbo-widget-commands vbo-widget-commands-right">
275 <div class="vbo-widget-commands-main">
276 <?php
277 if ($offset > 0) {
278 // show backward navigation button
279 ?>
280 <div class="vbo-widget-command-chevron vbo-widget-command-prev">
281 <span class="vbo-widget-command-chevron-prev" onclick="vboWidgetRemindersNavigate('<?php echo $wrapper; ?>', -1);"><?php VikBookingIcons::e('chevron-left'); ?></span>
282 </div>
283 <?php
284 }
285 if ($has_next_page) {
286 // show forward navigation button
287 ?>
288 <div class="vbo-widget-command-chevron vbo-widget-command-next">
289 <span class="vbo-widget-command-chevron-next" onclick="vboWidgetRemindersNavigate('<?php echo $wrapper; ?>', 1);"><?php VikBookingIcons::e('chevron-right'); ?></span>
290 </div>
291 <?php
292 }
293 ?>
294 </div>
295 </div>
296 <?php
297
298 // get the HTML buffer
299 $html_content = ob_get_contents();
300 ob_end_clean();
301
302 // return an associative array of values
303 return array(
304 'html' => $html_content,
305 'tot_records' => count($reminders),
306 'next_page' => (int)$has_next_page,
307 );
308 }
309
310 /**
311 * Custom method for this widget only.
312 * Creates a new reminder.
313 *
314 * @return array
315 */
316 public function saveReminder()
317 {
318 $title = VikRequest::getString('title', '', 'request');
319 $descr = VikRequest::getString('descr', '', 'request');
320 $date = VikRequest::getString('date', '', 'request');
321 $hours = VikRequest::getInt('hours', 0, 'request');
322 $minutes = VikRequest::getInt('minutes', 0, 'request');
323 $bid = VikRequest::getInt('bid', 0, 'request');
324
325 // create reminder object
326 $reminder = new stdClass;
327 $reminder->title = $title;
328 $reminder->descr = $descr;
329 $use_time = 0;
330 if (!empty($date)) {
331 if ($hours >= 0) {
332 $use_time = 1;
333 $minutes = $minutes >= 0 ? $minutes : 0;
334 $due_ts = VikBooking::getDateTimestamp($date, $hours, $minutes);
335 } else {
336 $due_ts = VikBooking::getDateTimestamp($date);
337 }
338 $reminder->duedate = date('Y-m-d H:i:s', $due_ts);
339 }
340 $reminder->usetime = $use_time;
341 if (!empty($bid)) {
342 $reminder->idorder = $bid;
343 }
344
345 if (!VBORemindersHelper::getInstance()->saveReminder($reminder)) {
346 VBOHttpDocument::getInstance()->close(400, 'Could not create the reminder');
347 }
348
349 // compose the notification payload for the newly created reminder
350 $notif_data = VBONotificationScheduler::getInstance()->getReminderDataObject($reminder, $max_future_hours = 12);
351
352 return [
353 'status' => true,
354 'notification' => $notif_data,
355 'debug' => print_r($reminder, true)
356 ];
357 }
358
359 /**
360 * Custom method for this widget only.
361 * Updates an existing reminder.
362 *
363 * @return array
364 */
365 public function updateReminder()
366 {
367 $rid = VikRequest::getInt('rid', 0, 'request');
368 $title = VikRequest::getString('title', '', 'request');
369 $descr = VikRequest::getString('descr', '', 'request');
370 $date = VikRequest::getString('date', '', 'request');
371 $hours = VikRequest::getInt('hours', 0, 'request');
372 $minutes = VikRequest::getInt('minutes', 0, 'request');
373 $bid = VikRequest::getInt('bid', 0, 'request');
374
375 if (empty($rid)) {
376 VBOHttpDocument::getInstance()->close(400, 'Missing reminder ID to update');
377 }
378
379 // create reminder object
380 $reminder = new stdClass;
381 $reminder->id = $rid;
382 $reminder->title = $title;
383 $reminder->descr = $descr;
384 $use_time = 0;
385 if (!empty($date)) {
386 if ($hours >= 0) {
387 $use_time = 1;
388 $minutes = $minutes >= 0 ? $minutes : 0;
389 $due_ts = VikBooking::getDateTimestamp($date, $hours, $minutes);
390 } else {
391 $due_ts = VikBooking::getDateTimestamp($date);
392 }
393 $reminder->duedate = date('Y-m-d H:i:s', $due_ts);
394 }
395 $reminder->usetime = $use_time;
396 $reminder->idorder = !empty($bid) ? $bid : 0;
397
398 if (!VBORemindersHelper::getInstance()->updateReminder($reminder)) {
399 VBOHttpDocument::getInstance()->close(400, 'Could not update the reminder');
400 }
401
402 // compose the notification paylod for the newly created reminder
403 $notif_data = VBONotificationScheduler::getInstance()->getReminderDataObject($reminder, $max_future_hours = 12);
404
405 return [
406 'status' => true,
407 'notification' => $notif_data,
408 ];
409 }
410
411 /**
412 * Custom method for this widget only.
413 * Toggles the completed status for an existing reminder.
414 *
415 * @return array
416 */
417 public function toggleReminderCompleted()
418 {
419 $rid = VikRequest::getInt('rid', 0, 'request');
420
421 if (empty($rid)) {
422 VBOHttpDocument::getInstance()->close(400, 'Missing reminder ID to update');
423 }
424
425 $helper = VBORemindersHelper::getInstance();
426 $reminder = $helper->getReminder($rid);
427 if (!$reminder) {
428 VBOHttpDocument::getInstance()->close(400, 'Record not found');
429 }
430
431 // toggle completed status
432 $reminder->completed = (int) !$reminder->completed;
433
434 if (!$helper->updateReminder($reminder)) {
435 VBOHttpDocument::getInstance()->close(400, 'Could not update the reminder');
436 }
437
438 $notif_data = null;
439 if (!$reminder->completed) {
440 // compose the notification paylod for the uncompleted reminder
441 $notif_data = VBONotificationScheduler::getInstance()->getReminderDataObject($reminder, $max_future_hours = 12);
442 }
443
444 return [
445 'status' => $reminder->completed,
446 'notification' => $notif_data,
447 ];
448 }
449
450 /**
451 * Custom method for this widget only.
452 * Deletes an existing reminder.
453 *
454 * @return bool
455 */
456 public function deleteReminder()
457 {
458 $rid = VikRequest::getInt('rid', 0, 'request');
459
460 if (empty($rid)) {
461 VBOHttpDocument::getInstance()->close(400, 'Missing reminder ID to delete');
462 }
463
464 $helper = VBORemindersHelper::getInstance();
465 $reminder = $helper->getReminder($rid);
466 if (!$reminder) {
467 VBOHttpDocument::getInstance()->close(400, 'Record not found');
468 }
469
470 if (!$helper->deleteReminder($reminder)) {
471 VBOHttpDocument::getInstance()->close(400, 'Could not delete the reminder');
472 }
473
474 return true;
475 }
476
477 /**
478 * Main method to invoke the widget. Contents will be loaded
479 * through AJAX requests, not via PHP when the page loads.
480 *
481 * @param VBOMultitaskData $data multitask data object.
482 *
483 * @return void
484 */
485 public function render(VBOMultitaskData $data = null)
486 {
487 // increase widget's instance counter
488 static::$instance_counter++;
489
490 // check whether the widget is being rendered via AJAX when adding it through the customizer
491 $is_ajax = $this->isAjaxRendering();
492
493 // generate a unique ID for the sticky notes wrapper instance
494 $wrapper_instance = !$is_ajax ? static::$instance_counter : rand();
495 $wrapper_id = 'vbo-widget-reminders-' . $wrapper_instance;
496
497 // default filters
498 $def_completed = 0;
499 $def_expired = 0;
500 $def_duedate = time();
501 $def_duehours = -1;
502 $def_duemins = -1;
503
504 // check multitask data
505 $page_bid = '';
506 if ($data) {
507 $page_bid = $data->getBookingID();
508 $booking_info = VikBooking::getBookingInfoFromID($page_bid);
509 if ($booking_info) {
510 $def_time_info = [];
511 if ($booking_info['checkin'] > $def_duedate) {
512 $def_duedate = $booking_info['checkin'];
513 $def_time_info = getdate($def_duedate);
514 } elseif ($booking_info['checkout'] > $def_duedate) {
515 $def_duedate = $booking_info['checkout'];
516 $def_time_info = getdate($def_duedate);
517 }
518 if ($def_time_info) {
519 $def_duehours = (int)$def_time_info['hours'];
520 $def_duemins = (int)$def_time_info['minutes'];
521 }
522 }
523 } else {
524 // load settings
525 $def_completed = isset($this->widgetSettings->show_completed) ? (int)$this->widgetSettings->show_completed : $def_completed;
526 $def_expired = isset($this->widgetSettings->show_expired) ? (int)$this->widgetSettings->show_expired : $def_expired;
527 }
528
529 ?>
530 <div id="<?php echo $wrapper_id; ?>" class="vbo-admin-widget-wrapper" data-instance="<?php echo $wrapper_instance; ?>" data-offset="0" data-pagebid="<?php echo $page_bid; ?>" data-length="<?php echo $this->reminders_per_page; ?>">
531 <div class="vbo-admin-widget-head">
532 <div class="vbo-admin-widget-head-inline">
533 <h4><?php echo $this->widgetIcon; ?> <span><?php echo $this->widgetName; ?></span></h4>
534 <div class="vbo-admin-widget-head-commands">
535
536 <div class="vbo-reportwidget-commands">
537 <div class="vbo-reportwidget-commands-main">
538 <div class="vbo-reportwidget-command-add">
539 <span class="vbo-widget-command-addnew" onclick="vboWidgetRemindersAdd('<?php echo $wrapper_id; ?>');"><?php VikBookingIcons::e('plus-circle'); ?></span>
540 </div>
541 </div>
542 <div class="vbo-reportwidget-command-dots">
543 <span class="vbo-widget-command-togglefilters vbo-widget-reminders-togglefilters" onclick="vboWidgetRemindersToggleFilters('<?php echo $wrapper_id; ?>');"><?php VikBookingIcons::e('ellipsis-v'); ?></span>
544 </div>
545 </div>
546 <div class="vbo-reportwidget-filters">
547 <div class="vbo-reportwidget-filter">
548 <label for="show_completed<?php echo $wrapper_instance; ?>-on"><?php echo JText::translate('VBO_SHOW_COMPLETED'); ?></label>
549 <?php echo $this->vbo_app->printYesNoButtons('show_completed' . $wrapper_instance, JText::translate('VBYES'), JText::translate('VBNO'), $def_completed, 1, 0); ?>
550 </div>
551 <div class="vbo-reportwidget-filter">
552 <label for="show_expired<?php echo $wrapper_instance; ?>-on"><?php echo JText::translate('VBO_SHOW_EXPIRED'); ?></label>
553 <?php echo $this->vbo_app->printYesNoButtons('show_expired' . $wrapper_instance, JText::translate('VBYES'), JText::translate('VBNO'), $def_expired, 1, 0); ?>
554 </div>
555 <div class="vbo-reportwidget-filter vbo-reportwidget-filter-confirm">
556 <button type="button" class="btn vbo-config-btn" onclick="vboWidgetRemindersChangeParams('<?php echo $wrapper_id; ?>');"><?php echo JText::translate('VBADMINNOTESUPD'); ?></button>
557 </div>
558 </div>
559
560 </div>
561 </div>
562 </div>
563 <div class="vbo-widget-reminders-wrap">
564 <div class="vbo-widget-reminders-inner">
565 <div class="vbo-widget-reminders-manage" style="display: none;">
566
567 <div class="vbo-widget-reminders-goback">
568 <a href="JavaScript: void(0);" onclick="vboWidgetRemindersToggleManage('<?php echo $wrapper_id; ?>');"><?php VikBookingIcons::e('chevron-left'); ?> <?php echo JText::translate('VBBACK'); ?></a>
569 </div>
570
571 <div class="vbo-widget-reminders-manage-wrap">
572 <div class="vbo-widget-reminders-filter vbo-widget-reminders-filter-title">
573 <input type="text" class="vbo-widget-reminders-ftitle" value="" placeholder="<?php echo htmlspecialchars(JText::translate('VBO_REMINDER_TITLE')); ?>" />
574 </div>
575 <div class="vbo-widget-reminders-filter vbo-widget-reminders-filter-descr">
576 <textarea class="vbo-widget-reminders-fdescr" placeholder="<?php echo htmlspecialchars(JText::translate('VBPVIEWOPTIONALSTWO')); ?>" maxlength="2000"></textarea>
577 </div>
578 <div class="vbo-widget-reminders-filter vbo-widget-reminders-filter-booking vbo-toggle-small" style="<?php echo empty($page_bid) ? 'display: none;' : ''; ?>">
579 <label for="assign_booking<?php echo $wrapper_instance; ?>-on"><span class="label label-info vbo-widget-reminders-filter-booking-id"><?php echo $page_bid; ?></span> <?php echo JText::translate('VBO_ASSIGN_TO_BOOKING'); ?></label>
580 <?php echo $this->vbo_app->printYesNoButtons('assign_booking' . $wrapper_instance, JText::translate('VBYES'), JText::translate('VBNO'), (!empty($page_bid) ? 1 : 0), 1, 0); ?>
581 </div>
582 <div class="vbo-widget-reminders-filter-datetime">
583 <div class="vbo-widget-reminders-filter vbo-widget-reminders-filter-date">
584 <div class="vbo-field-calendar">
585 <div class="input-append">
586 <input type="text" class="vbo-reminders-dtpicker" value="<?php echo date($this->df, $def_duedate); ?>" placeholder="<?php echo htmlspecialchars(JText::translate('VBO_REMINDER_DUE_DATE')); ?>" />
587 <button type="button" class="btn btn-secondary vbo-widget-reminders-caltrigger"><?php VikBookingIcons::e('calendar'); ?></button>
588 </div>
589 </div>
590 </div>
591 <div class="vbo-widget-reminders-filter vbo-widget-reminders-filter-time">
592 <select class="vbo-widget-reminders-fh">
593 <option value=""><?php echo ucfirst(JText::translate('VBCONFIGONETENEIGHT')); ?></option>
594 <?php
595 for ($i = 0; $i < 24; $i++) {
596 ?>
597 <option value="<?php echo $i; ?>"<?php echo $i == $def_duehours ? ' selected="selected"' : ''; ?>><?php echo $i < 10 ? "0{$i}" : $i; ?></option>
598 <?php
599 }
600 ?>
601 </select>
602 <select class="vbo-widget-reminders-fm">
603 <option value=""><?php echo ucfirst(JText::translate('VBTRKDIFFMINS')); ?></option>
604 <?php
605 for ($i = 0; $i < 60; $i++) {
606 ?>
607 <option value="<?php echo $i; ?>"<?php echo $i == $def_duemins ? ' selected="selected"' : ''; ?>><?php echo $i < 10 ? "0{$i}" : $i; ?></option>
608 <?php
609 }
610 ?>
611 </select>
612 </div>
613 </div>
614 <div class="vbo-widget-reminders-filter vbo-widget-reminders-filter-save">
615 <input type="hidden" class="vbo-widget-reminders-rid" value="" />
616 <button type="button" class="btn btn-success vbo-widget-reminder-confirm" onclick="vboWidgetRemindersSaveNew('<?php echo $wrapper_id; ?>');"><?php VikBookingIcons::e('bell'); ?> <span><?php echo JText::translate('VBCONFIGCLOSINGDATEADD'); ?></span></button>
617 <button type="button" class="btn btn-danger vbo-widget-reminder-delete" onclick="vboWidgetRemindersDelete('<?php echo $wrapper_id; ?>');" style="display: none;"><?php VikBookingIcons::e('trash'); ?> <?php echo JText::translate('VBELIMINA'); ?></button>
618 </div>
619 </div>
620
621 </div>
622 <div class="vbo-widget-reminders-list">
623 <?php
624 for ($i = 0; $i < floor($this->reminders_per_page / 2); $i++) {
625 ?>
626 <div class="vbo-dashboard-guest-activity vbo-dashboard-guest-activity-skeleton">
627 <div class="vbo-dashboard-guest-activity-avatar">
628 <div class="vbo-skeleton-loading vbo-skeleton-loading-avatar"></div>
629 </div>
630 <div class="vbo-dashboard-guest-activity-content">
631 <div class="vbo-dashboard-guest-activity-content-head">
632 <div class="vbo-skeleton-loading vbo-skeleton-loading-title"></div>
633 </div>
634 <div class="vbo-dashboard-guest-activity-content-info-msg">
635 <div class="vbo-skeleton-loading vbo-skeleton-loading-content"></div>
636 </div>
637 </div>
638 </div>
639 <?php
640 }
641 ?>
642 </div>
643 </div>
644 </div>
645 </div>
646 <?php
647
648 if (static::$instance_counter === 0 || $is_ajax) {
649 /**
650 * Print the JS code only once for all instances of this widget.
651 * The real rendering is made through AJAX, not when the page loads.
652 */
653 ?>
654 <script type="text/javascript">
655
656 /**
657 * Display the loading skeletons.
658 */
659 function vboWidgetRemindersSkeletons(wrapper) {
660 var widget_instance = jQuery('#' + wrapper);
661 if (!widget_instance.length) {
662 return false;
663 }
664 widget_instance.find('.vbo-widget-reminders-list').html('');
665 for (var i = 0; i < <?php echo floor($this->reminders_per_page / 2); ?>; i++) {
666 var skeleton = '';
667 skeleton += '<div class="vbo-dashboard-guest-activity vbo-dashboard-guest-activity-skeleton">';
668 skeleton += ' <div class="vbo-dashboard-guest-activity-avatar">';
669 skeleton += ' <div class="vbo-skeleton-loading vbo-skeleton-loading-avatar"></div>';
670 skeleton += ' </div>';
671 skeleton += ' <div class="vbo-dashboard-guest-activity-content">';
672 skeleton += ' <div class="vbo-dashboard-guest-activity-content-head">';
673 skeleton += ' <div class="vbo-skeleton-loading vbo-skeleton-loading-title"></div>';
674 skeleton += ' </div>';
675 skeleton += ' <div class="vbo-dashboard-guest-activity-content-info-msg">';
676 skeleton += ' <div class="vbo-skeleton-loading vbo-skeleton-loading-content"></div>';
677 skeleton += ' </div>';
678 skeleton += ' </div>';
679 skeleton += '</div>';
680 // append skeleton
681 jQuery(skeleton).appendTo(widget_instance.find('.vbo-widget-reminders-list'));
682 }
683 }
684
685 /**
686 * Toggles the layout to add or edit a reminder.
687 */
688 function vboWidgetRemindersToggleManage(wrapper) {
689 var widget_instance = jQuery('#' + wrapper);
690 if (!widget_instance.length) {
691 return false;
692 }
693
694 var mng_cont = widget_instance.find('.vbo-widget-reminders-manage');
695 if (mng_cont.is(':visible')) {
696 mng_cont.hide();
697 widget_instance.find('.vbo-widget-reminders-list').show();
698 } else {
699 widget_instance.find('.vbo-widget-reminders-list').hide();
700 mng_cont.show();
701 }
702 }
703
704 /**
705 * Toggle filters.
706 */
707 function vboWidgetRemindersToggleFilters(wrapper) {
708 var widget_instance = jQuery('#' + wrapper);
709 if (!widget_instance.length) {
710 return false;
711 }
712
713 widget_instance.find('.vbo-reportwidget-filters').toggle();
714 }
715
716 /**
717 * Reload records with new params.
718 */
719 function vboWidgetRemindersChangeParams(wrapper) {
720 var widget_instance = jQuery('#' + wrapper);
721 if (!widget_instance.length) {
722 return false;
723 }
724
725 // hide filters when making a new request
726 widget_instance.find('.vbo-reportwidget-filters').hide();
727
728 // reset offset to 0
729 widget_instance.attr('data-offset', 0);
730
731 // show loading skeletons
732 vboWidgetRemindersSkeletons(wrapper);
733
734 // reload the first page
735 vboWidgetRemindersLoad(wrapper);
736 }
737
738 /**
739 * Prepare the layout to add a new reminder.
740 */
741 function vboWidgetRemindersAdd(wrapper) {
742 var widget_instance = jQuery('#' + wrapper);
743 if (!widget_instance.length) {
744 return false;
745 }
746
747 // always reset the reminder id in the hidden input and hide delete
748 widget_instance.find('.vbo-widget-reminders-rid').val('');
749 widget_instance.find('.vbo-widget-reminder-delete').hide();
750 widget_instance.find('.vbo-widget-reminder-confirm span').text(Joomla.JText._('VBCONFIGCLOSINGDATEADD'));
751
752 // check if we need to hide the assign-to-booking option
753 var page_bid = widget_instance.attr('data-pagebid');
754 if (page_bid.length && page_bid > 0) {
755 // show assign-to-booking option
756 widget_instance.find('.vbo-widget-reminders-filter-booking-id').text(page_bid);
757 widget_instance.find('input[name^="assign_booking"]').prop('checked', true);
758 widget_instance.find('.vbo-widget-reminders-filter-booking').show();
759 } else {
760 // hide assign-to-booking option
761 widget_instance.find('input[name^="assign_booking"]').prop('checked', false);
762 widget_instance.find('.vbo-widget-reminders-filter-booking').hide();
763 }
764
765 // reset the rest of the fields in case of previous editing
766 if (widget_instance.find('.vbo-widget-reminders-ftitle').val() || widget_instance.find('.vbo-widget-reminders-fdescr').val()) {
767 widget_instance.find('.vbo-widget-reminders-ftitle').val('');
768 widget_instance.find('.vbo-widget-reminders-fdescr').val('');
769 widget_instance.find('.vbo-reminders-dtpicker').val('');
770 widget_instance.find('.vbo-widget-reminders-fh').val('');
771 widget_instance.find('.vbo-widget-reminders-fm').val('');
772 }
773
774 // toggle edit mode
775 vboWidgetRemindersToggleManage(wrapper);
776 }
777
778 /**
779 * Prepare the reminder edit mode by populating data.
780 */
781 function vboWidgetRemindersEdit(wrapper, rid) {
782 var widget_instance = jQuery('#' + wrapper);
783 if (!widget_instance.length) {
784 return false;
785 }
786 var reminder_instance = widget_instance.find('[data-reminderid="' + rid + '"]');
787 if (!reminder_instance.length) {
788 return false;
789 }
790
791 // populate fields for edit mode
792 widget_instance.find('.vbo-widget-reminder-confirm span').text(Joomla.JText._('VBADMINNOTESUPD'));
793 widget_instance.find('.vbo-widget-reminder-delete').show();
794 widget_instance.find('.vbo-widget-reminders-rid').val(rid);
795 widget_instance.find('.vbo-widget-reminders-ftitle').val(reminder_instance.find('.vbo-widget-reminder-title').text());
796 widget_instance.find('.vbo-widget-reminders-fdescr').val(reminder_instance.find('.vbo-widget-reminder-descr').text());
797 widget_instance.find('.vbo-reminders-dtpicker').val(reminder_instance.find('.vbo-widget-reminder-date').text());
798 widget_instance.find('.vbo-widget-reminders-fh').val(reminder_instance.find('.vbo-widget-reminder-hours').text());
799 widget_instance.find('.vbo-widget-reminders-fm').val(reminder_instance.find('.vbo-widget-reminder-minutes').text());
800 // handle booking ID assignment
801 var booking_assigned = null;
802 var booking_container = reminder_instance.find('.vbo-widget-reminder-idorder');
803 if (booking_container.length) {
804 booking_assigned = booking_container.text();
805 }
806 if (booking_assigned) {
807 // show assign-to-booking option
808 widget_instance.find('.vbo-widget-reminders-filter-booking-id').text(booking_assigned);
809 widget_instance.find('input[name^="assign_booking"]').prop('checked', true);
810 widget_instance.find('.vbo-widget-reminders-filter-booking').show();
811 } else {
812 // hide assign-to-booking option
813 widget_instance.find('input[name^="assign_booking"]').prop('checked', false);
814 widget_instance.find('.vbo-widget-reminders-filter-booking').hide();
815 }
816
817 // enter edit mode
818 vboWidgetRemindersToggleManage(wrapper);
819 }
820
821 /**
822 * Toggle reminder completed status.
823 */
824 function vboWidgetRemindersComplete(wrapper, rid) {
825 var widget_instance = jQuery('#' + wrapper);
826 if (!widget_instance.length) {
827 return false;
828 }
829 var reminder_instance = widget_instance.find('[data-reminderid="' + rid + '"]');
830 if (!reminder_instance.length) {
831 return false;
832 }
833
834 // the widget method to call
835 var call_method = 'toggleReminderCompleted';
836
837 // make a request to update the reminder
838 VBOCore.doAjax(
839 "<?php echo $this->getExecWidgetAjaxUri(); ?>",
840 {
841 widget_id: "<?php echo $this->getIdentifier(); ?>",
842 call: call_method,
843 return: 1,
844 rid: rid,
845 wrapper: wrapper,
846 tmpl: "component"
847 },
848 function(response) {
849 try {
850 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
851 if (!obj_res.hasOwnProperty(call_method)) {
852 console.error('Unexpected or invalid JSON response', obj_res);
853 return false;
854 }
855
856 if (obj_res[call_method]['status'] > 0) {
857 // new status is completed
858 reminder_instance
859 .removeClass('vbo-reminder-nok')
860 .addClass('vbo-reminder-ok')
861 .find('.vbo-reminder-status-dot').html('<?php VikBookingIcons::e('dot-circle'); ?>');
862 // check current params
863 var show_completed = widget_instance.find('input[name^="show_completed"]').prop('checked');
864 if (!show_completed) {
865 reminder_instance.fadeOut();
866 }
867 // attempt to unset any scheduled notification for this reminder
868 VBOCore.updateNotification({
869 id: rid,
870 type: "reminder"
871 }, 0);
872 } else {
873 // new status is un-completed
874 reminder_instance
875 .removeClass('vbo-reminder-ok')
876 .addClass('vbo-reminder-nok')
877 .find('.vbo-reminder-status-dot').html('<?php VikBookingIcons::e('far fa-circle'); ?>');
878 if (obj_res[call_method]['notification'] != null) {
879 // attempt to schedule a notification for this reminder
880 VBOCore.enqueueNotifications(obj_res[call_method]['notification']);
881 }
882 }
883 } catch(err) {
884 console.error('could not parse JSON response', err, response);
885 }
886 },
887 function(error) {
888 // log the error and display the message
889 console.error(error);
890 alert(error.responseText);
891 }
892 );
893 }
894
895 /**
896 * Delete one reminder record.
897 */
898 function vboWidgetRemindersDelete(wrapper) {
899 var widget_instance = jQuery('#' + wrapper);
900 if (!widget_instance.length) {
901 return false;
902 }
903
904 var rid = widget_instance.find('.vbo-widget-reminders-rid').val();
905 if (!rid || !rid.length) {
906 return false;
907 }
908
909 if (!confirm(Joomla.JText._('VBDELCONFIRM'))) {
910 return false;
911 }
912
913 // disable delete button
914 var del_btn = widget_instance.find('button.vbo-widget-reminder-delete');
915 del_btn.prop('disabled', true);
916
917 // the widget method to call
918 var call_method = 'deleteReminder';
919
920 // make a request to update the reminder
921 VBOCore.doAjax(
922 "<?php echo $this->getExecWidgetAjaxUri(); ?>",
923 {
924 widget_id: "<?php echo $this->getIdentifier(); ?>",
925 call: call_method,
926 return: 1,
927 rid: rid,
928 wrapper: wrapper,
929 tmpl: "component"
930 },
931 function(response) {
932 try {
933 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
934 if (!obj_res.hasOwnProperty(call_method) || !obj_res[call_method]) {
935 console.error('Unexpected or invalid JSON response', obj_res);
936 return false;
937 }
938
939 // toggle edit mode
940 vboWidgetRemindersToggleManage(wrapper);
941
942 // enable delete button
943 del_btn.prop('disabled', false);
944
945 // reset offset to 0
946 widget_instance.attr('data-offset', 0);
947
948 // show loading skeletons
949 vboWidgetRemindersSkeletons(wrapper);
950
951 // reload the first page
952 vboWidgetRemindersLoad(wrapper);
953
954 // attempt to unset any scheduled notification for this reminder
955 VBOCore.updateNotification({
956 id: rid,
957 type: "reminder"
958 }, 0);
959 } catch(err) {
960 console.error('could not parse JSON response', err, response);
961 }
962 },
963 function(error) {
964 // log the error and display the message
965 console.error(error);
966 alert(error.responseText);
967 // enable delete button
968 del_btn.prop('disabled', false);
969 }
970 );
971 }
972
973 /**
974 * Perform the request to load the reminders.
975 */
976 function vboWidgetRemindersLoad(wrapper) {
977 var widget_instance = jQuery('#' + wrapper);
978 if (!widget_instance.length) {
979 return false;
980 }
981
982 // get vars for making the request
983 var current_offset = parseInt(widget_instance.attr('data-offset'));
984 var length_per_page = parseInt(widget_instance.attr('data-length'));
985 var show_completed = widget_instance.find('input[name^="show_completed"]').prop('checked');
986 var show_expired = widget_instance.find('input[name^="show_expired"]').prop('checked');
987 show_completed = show_completed ? 1 : 0;
988 show_expired = show_expired ? 1 : 0;
989 var page_bid = widget_instance.attr('data-pagebid');
990
991 // the widget method to call
992 var call_method = 'loadReminders';
993
994 // make a request to load the reminder records
995 VBOCore.doAjax(
996 "<?php echo $this->getExecWidgetAjaxUri(); ?>",
997 {
998 widget_id: "<?php echo $this->getIdentifier(); ?>",
999 call: call_method,
1000 return: 1,
1001 offset: current_offset,
1002 length: length_per_page,
1003 completed: show_completed,
1004 expired: show_expired,
1005 bid: page_bid,
1006 wrapper: wrapper,
1007 tmpl: "component"
1008 },
1009 (response) => {
1010 try {
1011 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
1012 if (!obj_res.hasOwnProperty(call_method)) {
1013 console.error('Unexpected JSON response', obj_res);
1014 return false;
1015 }
1016
1017 // replace HTML with month-day reservations
1018 widget_instance.find('.vbo-widget-reminders-list').html(obj_res[call_method]['html']);
1019
1020 // check results
1021 var tot_records = obj_res[call_method]['tot_records'] || 0;
1022 if (!isNaN(tot_records) && parseInt(tot_records) < 1) {
1023 // no results can indicate the offset is invalid or too high
1024 if (!isNaN(current_offset) && current_offset > 0) {
1025 // reset offset to 0
1026 widget_instance.attr('data-offset', 0);
1027 // show loading skeletons
1028 vboWidgetRemindersSkeletons(wrapper);
1029 // reload the first page
1030 vboWidgetRemindersLoad(wrapper);
1031 }
1032 }
1033 } catch(err) {
1034 console.error('could not parse JSON response', err, response);
1035 }
1036 },
1037 (error) => {
1038 // remove the skeleton loading
1039 widget_instance.find('.vbo-widget-reminders-list').find('.vbo-dashboard-guest-activity-skeleton').remove();
1040 console.error(error);
1041 }
1042 );
1043 }
1044
1045 /**
1046 * Save a new reminder or update an existing one.
1047 */
1048 function vboWidgetRemindersSaveNew(wrapper) {
1049 var widget_instance = jQuery('#' + wrapper);
1050 if (!widget_instance.length) {
1051 return false;
1052 }
1053
1054 // either save or update
1055 var mode = 'saveReminder';
1056
1057 // collect new reminder details
1058 var r_title = widget_instance.find('.vbo-widget-reminders-ftitle').val();
1059 var r_descr = widget_instance.find('.vbo-widget-reminders-fdescr').val();
1060 var r_date = widget_instance.find('.vbo-reminders-dtpicker').val();
1061 var r_hours = widget_instance.find('.vbo-widget-reminders-fh').val();
1062 var r_mins = widget_instance.find('.vbo-widget-reminders-fm').val();
1063 // adjust time
1064 if (!r_hours.length) {
1065 r_hours = -1;
1066 r_mins = 0;
1067 }
1068 // check if we are editing an existing reminder id
1069 var r_id = widget_instance.find('.vbo-widget-reminders-rid').val();
1070 if (r_id && r_id.length) {
1071 mode = 'updateReminder';
1072 } else {
1073 r_id = 0;
1074 }
1075
1076 if ((!r_title.length && !r_descr.length) || !r_date.length) {
1077 alert(Joomla.JText._('VBO_PLEASE_FILL_FIELDS'));
1078 return false;
1079 }
1080
1081 // check if we are saving/updating a reminder for a booking ID
1082 var r_bid = null;
1083 var assign_to_bid = widget_instance.find('input[name^="assign_booking"]').prop('checked');
1084 if (assign_to_bid) {
1085 // validate the booking id depending on save/update mode
1086 if (mode == 'saveReminder') {
1087 // the booking id must have been set from the current page
1088 var validate_bid = widget_instance.attr('data-pagebid');
1089 if (validate_bid && validate_bid.length) {
1090 // valid
1091 r_bid = validate_bid;
1092 }
1093 } else {
1094 // the booking id must be part of a hidden field
1095 var reminder_instance = widget_instance.find('[data-reminderid="' + r_id + '"]');
1096 if (reminder_instance.length) {
1097 var validate_bid = reminder_instance.find('.vbo-widget-reminder-idorder').text();
1098 if (validate_bid && validate_bid.length) {
1099 // valid
1100 r_bid = validate_bid;
1101 }
1102 }
1103 }
1104 }
1105
1106 // disable save button
1107 var save_btn = widget_instance.find('.vbo-widget-reminders-filter-save button');
1108 save_btn.prop('disabled', true);
1109
1110 // the widget method to call
1111 var call_method = mode;
1112
1113 // make a request to save a new reminder or to update it
1114 VBOCore.doAjax(
1115 "<?php echo $this->getExecWidgetAjaxUri(); ?>",
1116 {
1117 widget_id: "<?php echo $this->getIdentifier(); ?>",
1118 call: call_method,
1119 return: 1,
1120 rid: r_id,
1121 bid: r_bid,
1122 title: r_title,
1123 descr: r_descr,
1124 date: r_date,
1125 hours: r_hours,
1126 minutes: r_mins,
1127 wrapper: wrapper,
1128 tmpl: "component"
1129 },
1130 (response) => {
1131 try {
1132 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
1133 if (!obj_res.hasOwnProperty(call_method) || !obj_res[call_method]['status']) {
1134 console.error('Unexpected or invalid JSON response', obj_res);
1135 return false;
1136 }
1137
1138 // toggle edit mode
1139 vboWidgetRemindersToggleManage(wrapper);
1140
1141 // enable save button
1142 save_btn.prop('disabled', false);
1143
1144 // reset offset to 0
1145 widget_instance.attr('data-offset', 0);
1146
1147 // show loading skeletons
1148 vboWidgetRemindersSkeletons(wrapper);
1149
1150 // reload the first page
1151 vboWidgetRemindersLoad(wrapper);
1152
1153 // handle browser notifications
1154 if (call_method == 'saveReminder') {
1155 if (obj_res[call_method]['notification'] != null) {
1156 // attempt to schedule a notification for the new reminder
1157 VBOCore.enqueueNotifications(obj_res[call_method]['notification']);
1158 }
1159 } else {
1160 if (obj_res[call_method]['notification'] != null) {
1161 // attempt to update the notification scheduling time for this reminder
1162 let updated = VBOCore.updateNotification({
1163 id: r_id,
1164 type: "reminder"
1165 }, obj_res[call_method]['notification']['dtime']);
1166 if (updated !== true) {
1167 // attempt to schedule this anticipated reminder as a new notification
1168 VBOCore.enqueueNotifications(obj_res[call_method]['notification']);
1169 }
1170 } else {
1171 // the notification may have been set to a far-ahead date, delete it
1172 VBOCore.updateNotification({
1173 id: r_id,
1174 type: "reminder"
1175 }, 0);
1176 }
1177 }
1178 } catch(err) {
1179 console.error('could not parse JSON response', err, response);
1180 }
1181 },
1182 (error) => {
1183 // log the error and display the message
1184 console.error(error);
1185 alert(error.responseText);
1186 // enable save button
1187 save_btn.prop('disabled', false);
1188 }
1189 );
1190 }
1191
1192 /**
1193 * Navigate between the various pages of the reminders.
1194 */
1195 function vboWidgetRemindersNavigate(wrapper, direction) {
1196 var widget_instance = jQuery('#' + wrapper);
1197 if (!widget_instance.length) {
1198 return false;
1199 }
1200
1201 // show loading skeletons
1202 vboWidgetRemindersSkeletons(wrapper);
1203
1204 // current offset
1205 var current_offset = parseInt(widget_instance.attr('data-offset'));
1206
1207 // records per page
1208 var steps = parseInt(widget_instance.attr('data-length'));
1209
1210 // check direction and update offsets for nav
1211 if (direction > 0) {
1212 // navigate forward
1213 widget_instance.attr('data-offset', (current_offset + steps));
1214 } else {
1215 // navigate backward
1216 var new_offset = current_offset - steps;
1217 new_offset = new_offset >= 0 ? new_offset : 0;
1218 widget_instance.attr('data-offset', new_offset);
1219 }
1220
1221 // launch navigation
1222 vboWidgetRemindersLoad(wrapper);
1223 }
1224
1225 </script>
1226 <?php
1227 }
1228 ?>
1229
1230 <script type="text/javascript">
1231
1232 jQuery(function() {
1233
1234 // render datepicker calendar
1235 jQuery('#<?php echo $wrapper_id; ?>').find('.vbo-reminders-dtpicker').datepicker({
1236 minDate: "0",
1237 maxDate: "+5y",
1238 yearRange: "<?php echo date('Y'); ?>:<?php echo (date('Y') + 5); ?>",
1239 changeMonth: true,
1240 changeYear: true,
1241 dateFormat: "<?php echo $this->getDateFormat('jui'); ?>",
1242 defaultDate: "<?php echo date($this->df, $def_duedate); ?>"
1243 });
1244
1245 // triggering for datepicker calendar icons
1246 jQuery('#<?php echo $wrapper_id; ?>').find('.vbo-widget-reminders-caltrigger').click(function() {
1247 var jdp = jQuery(this).parent().find('input.hasDatepicker');
1248 if (jdp.length) {
1249 jdp.focus();
1250 }
1251 });
1252
1253 // when document is ready, load reminders for this widget's instance
1254 vboWidgetRemindersLoad('<?php echo $wrapper_id; ?>');
1255
1256 });
1257
1258 </script>
1259
1260 <?php
1261 }
1262
1263 /**
1264 * Checks if any reminders should be automatically scheduled due to
1265 * important events related to reservations downloaded through VCM.
1266 *
1267 * @return int number of reminders that were automatically scheduled.
1268 *
1269 * @since 1.16.3 (J) - 1.6.3 (WP)
1270 */
1271 protected function scheduleChannelManagerReminders()
1272 {
1273 $scheduled = 0;
1274
1275 if (!method_exists('VikChannelManager', 'hostToGuestReviewSupported')) {
1276 // prevent server errors
1277 return $scheduled;
1278 }
1279
1280 // get the reminders helper object
1281 $helper = VBORemindersHelper::getInstance();
1282
1283 // get a list of Airbnb reservations with a proper checkout date
1284 $airbnb_checkouts = $helper->gatherAirbnbReservationsCheckedOut();
1285
1286 // default due-date for the newly added reminders
1287 $def_due_date = date('Y-m-d H:i:s', strtotime("+1 minute"));
1288
1289 // parse all eligible reservations
1290 foreach ($airbnb_checkouts as $airbnb_res) {
1291 // make sure this airbnb reservation requires a host-to-guest review
1292 if (!$helper->bookingHasReminder($airbnb_res['id']) && VikChannelManager::hostToGuestReviewSupported($airbnb_res)) {
1293 // build and schedule an automatic reminder
1294 $reminder = new stdClass;
1295 $reminder->title = JText::translate('VBO_REVIEW_YOUR_GUEST');
1296 $reminder->descr = 'Airbnb - ' . JText::translate('VBDASHBOOKINGID') . ' ' . $airbnb_res['id'];
1297 $reminder->duedate = $def_due_date;
1298 $reminder->usetime = 1;
1299 $reminder->idorder = $airbnb_res['id'];
1300 $reminder->payload = [
1301 'airbnb_host_guest_review' => 1,
1302 ];
1303
1304 if ($helper->saveReminder($reminder)) {
1305 // increase counter
1306 $scheduled++;
1307 }
1308 }
1309 }
1310
1311 return $scheduled;
1312 }
1313 }
1314