default.php
309 lines
| 1 | <?php |
| 2 | /** |
| 3 | * @package VikAppointments |
| 4 | * @subpackage mod_vikappointments_search |
| 5 | * @author E4J s.r.l. |
| 6 | * @copyright Copyright (C) 2023 E4J s.r.l. All Rights Reserved. |
| 7 | * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL |
| 8 | * @link https://vikwp.com |
| 9 | */ |
| 10 | |
| 11 | // No direct access to this file |
| 12 | defined('ABSPATH') or die('No script kiddies please!'); |
| 13 | |
| 14 | JHtml::fetch('vaphtml.sitescripts.calendar', '#vapcalendarmod' . $module_id . ':input'); |
| 15 | |
| 16 | $last_values = $references['lastValues']; |
| 17 | $services = $references['services']; |
| 18 | $employees = $references['employees']; |
| 19 | |
| 20 | $itemid = $params->get('itemid', null); |
| 21 | |
| 22 | $has_employees = $has_random = false; |
| 23 | |
| 24 | $advancedSelect = (int) $params->get('advselect', 1); |
| 25 | |
| 26 | $employeeId = (int) $params->get('id_employee'); |
| 27 | |
| 28 | ?> |
| 29 | |
| 30 | <div class="moduletablevikapp vapmainsearchmod <?php echo $params->get('orientation', 'vertical'); ?>"> |
| 31 | |
| 32 | <form action="<?php echo JRoute::rewrite('index.php?option=com_vikappointments&view=serviceslist' . ($itemid ? '&Itemid=' . $itemid : '')); ?>" method="post" name="vapmodulesearch"> |
| 33 | |
| 34 | <div class="vapformfieldsetmod"> |
| 35 | |
| 36 | <div class="vapsearchinputdivmod"> |
| 37 | <label class="vapsearchinputlabelmod" for="vapcalendarmod<?php echo $module_id; ?>"><?php echo JText::translate('VAPDATE'); ?></label> |
| 38 | <div class="vapsearchentryinputmod"> |
| 39 | <input class="vapsearchdatemod" type="text" value="<?php echo htmlentities($last_values['date']); ?>" id="vapcalendarmod<?php echo $module_id; ?>" name="date" size="20" /> |
| 40 | </div> |
| 41 | </div> |
| 42 | |
| 43 | <div class="vapsearchinputdivmod"> |
| 44 | <label class="vapsearchinputlabelmod" for="vapserselmod<?php echo $module_id; ?>"><?php echo JText::translate('VAPSERVICE'); ?></label> |
| 45 | <div class="vapsearchentryselectmod"> |
| 46 | <select id="vapserselmod<?php echo $module_id; ?>" class="<?php echo $advancedSelect ? '' : 'form-select'; ?>"> |
| 47 | <?php |
| 48 | foreach ($services as $group) |
| 49 | { |
| 50 | if (!empty($group['id'])) |
| 51 | { |
| 52 | ?> |
| 53 | <optgroup label="<?php echo htmlspecialchars($group['name']); ?>"> |
| 54 | <?php |
| 55 | } |
| 56 | |
| 57 | foreach ($group['list'] as $s) |
| 58 | { |
| 59 | /** |
| 60 | * Hide employees list in case the pre-selected service does not |
| 61 | * allow the selection of the employees. |
| 62 | * |
| 63 | * @since 1.4.1 |
| 64 | */ |
| 65 | if ($s['id'] == $last_values['id_ser']) |
| 66 | { |
| 67 | $has_employees = $s['choose_emp']; |
| 68 | $has_random = $s['random_emp']; |
| 69 | } |
| 70 | |
| 71 | ?> |
| 72 | <option |
| 73 | value="<?php echo (int) $s['id']; ?>" |
| 74 | <?php echo $s['id'] == $last_values['id_ser'] ? 'selected="selected"' : ''; ?> |
| 75 | data-random="<?php echo (int) $s['random_emp']; ?>" |
| 76 | data-mindate="<?php echo htmlspecialchars($s['mindate']); ?>" |
| 77 | data-maxdate="<?php echo htmlspecialchars($s['maxdate']); ?>" |
| 78 | data-url="<?php echo JRoute::rewrite('index.php?option=com_vikappointments&view=servicesearch&id_service=' . $s['id'] . ($itemid ? '&Itemid=' . $itemid : '')); ?>" |
| 79 | > |
| 80 | <?php echo $s['name']; ?> |
| 81 | </option> |
| 82 | <?php |
| 83 | } |
| 84 | |
| 85 | if (!empty($group['id'])) |
| 86 | { |
| 87 | ?> |
| 88 | </optgroup> |
| 89 | <?php |
| 90 | } |
| 91 | } |
| 92 | ?> |
| 93 | </select> |
| 94 | </div> |
| 95 | </div> |
| 96 | |
| 97 | <?php |
| 98 | /** |
| 99 | * Do not display the employees dropdown in case an employee has been explicitly selected |
| 100 | * from the configuration of the module. |
| 101 | * |
| 102 | * @since 1.6 |
| 103 | */ |
| 104 | if (!$employeeId): ?> |
| 105 | <div class="vapsearchinputdivmod"> |
| 106 | <div id="vapemprowmod<?php echo $module_id; ?>" style="<?php echo (!count($employees) || !$has_employees ? 'display: none;' : ''); ?>"> |
| 107 | <label class="vapsearchinputlabelmod" for="vapempselmod<?php echo $module_id; ?>"><?php echo JText::translate('VAPEMPLOYEE'); ?></label> |
| 108 | <div class="vapsearchentryselectmod"> |
| 109 | <select name="id_employee" id="vapempselmod<?php echo $module_id; ?>" class="<?php echo $advancedSelect ? '' : 'form-select'; ?>"> |
| 110 | <?php |
| 111 | if ($has_random) |
| 112 | { |
| 113 | if ($advancedSelect) |
| 114 | { |
| 115 | ?><option></option><?php |
| 116 | } |
| 117 | else |
| 118 | { |
| 119 | ?><option value="0"><?php echo JText::translate('VAPANYEMP'); ?></option><?php |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | foreach ($employees as $e) |
| 124 | { |
| 125 | ?> |
| 126 | <option value="<?php echo (int) $e['id']; ?>" <?php echo $e['id'] == $last_values['id_emp'] ? 'selected="selected"' : ''; ?>><?php echo $e['nickname']; ?></option> |
| 127 | <?php |
| 128 | } |
| 129 | ?> |
| 130 | </select> |
| 131 | </div> |
| 132 | </div> |
| 133 | </div> |
| 134 | <?php else: ?> |
| 135 | <input type="hidden" name="id_employee" value="<?php echo (int) $employeeId; ?>" /> |
| 136 | <?php endif; ?> |
| 137 | |
| 138 | <div class="vapsearchinputdivmod mod-booknow"> |
| 139 | <button type="submit" class="vap-btn blue vapsearchsubmitmod"><?php echo JText::translate('VAPFINDAPPOINTMENT'); ?></button> |
| 140 | </div> |
| 141 | |
| 142 | </div> |
| 143 | |
| 144 | </form> |
| 145 | |
| 146 | </div> |
| 147 | |
| 148 | <?php |
| 149 | JText::script('VAPANYEMP'); |
| 150 | ?> |
| 151 | |
| 152 | <script> |
| 153 | |
| 154 | (function($) { |
| 155 | 'use strict'; |
| 156 | |
| 157 | const afterServiceChange = () => { |
| 158 | const select = $('#vapserselmod<?php echo $module_id; ?>'); |
| 159 | const option = select.find('option:selected'); |
| 160 | |
| 161 | if (!option.length) { |
| 162 | return false; |
| 163 | } |
| 164 | |
| 165 | // update form action with rewritten URL of the selected service |
| 166 | document.vapmodulesearch.action = option.data('url'); |
| 167 | |
| 168 | // create the new minimum and maximum selectable dates |
| 169 | const minDate = new Date(option.data('mindate')); |
| 170 | const maxDate = new Date(option.data('maxdate')); |
| 171 | |
| 172 | // refresh datepicker configuration |
| 173 | $('#vapcalendarmod<?php echo $module_id; ?>').datepicker('option', 'minDate', minDate); |
| 174 | $('#vapcalendarmod<?php echo $module_id; ?>').datepicker('option', 'maxDate', maxDate); |
| 175 | } |
| 176 | |
| 177 | const closingPeriods = <?php echo json_encode(VikAppointments::getClosingPeriods()); ?>; |
| 178 | const closingDays = <?php echo json_encode(VikAppointments::getClosingDays()); ?>; |
| 179 | |
| 180 | // checks whether the specified date is closed for the given service |
| 181 | const isClosingPeriod = (date, id_service) => { |
| 182 | return closingPeriods.some((period) => { |
| 183 | // make sure the service is assigned to this closing period |
| 184 | if (period.services.length && period.services.indexOf(id_service) === -1) { |
| 185 | // the selected service doesn't match this closing period |
| 186 | return false; |
| 187 | } |
| 188 | |
| 189 | // construct delimiters |
| 190 | let startDate = new Date(period.start + 'T00:00:00'); |
| 191 | let endDate = new Date(period.end + 'T23:59:59'); |
| 192 | |
| 193 | // check whether the date is contained within the closing period |
| 194 | return startDate <= date && date < endDate; |
| 195 | }); |
| 196 | } |
| 197 | |
| 198 | // checks whether the specified date is closed for the given service |
| 199 | const isClosingDay = (date, id_service) => { |
| 200 | return closingDays.some((cd) => { |
| 201 | // make sure the service is assigned to this closing day |
| 202 | if (cd.services.length && cd.services.indexOf(id_service) === -1) { |
| 203 | // the selected service doesn't match this closing period |
| 204 | return false; |
| 205 | } |
| 206 | |
| 207 | // construct closing date |
| 208 | let _d = new Date(cd.ts + 'T00:00:00'); |
| 209 | |
| 210 | if (cd.freq == 0) { |
| 211 | // single day |
| 212 | if (_d.getDate() == date.getDate() && _d.getMonth() == date.getMonth() && _d.getFullYear() == date.getFullYear()) { |
| 213 | return true; |
| 214 | } |
| 215 | } else if (cd.freq == 1) { |
| 216 | // weekly |
| 217 | if (_d.getDay() == date.getDay()) { |
| 218 | return true; |
| 219 | } |
| 220 | } else if (cd.freq == 2) { |
| 221 | // monthly |
| 222 | if (_d.getDate() == date.getDate()) { |
| 223 | return true; |
| 224 | } |
| 225 | } else if (cd.freq == 3) { |
| 226 | // yearly |
| 227 | if (_d.getDate() == date.getDate() && _d.getMonth() == date.getMonth()) { |
| 228 | return true; |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | return false; |
| 233 | }); |
| 234 | } |
| 235 | |
| 236 | $(function() { |
| 237 | // adjust configuration according to the selected service |
| 238 | afterServiceChange(); |
| 239 | |
| 240 | <?php if ($advancedSelect): ?> |
| 241 | $('#vapserselmod<?php echo $module_id; ?>, #vapempselmod<?php echo $module_id; ?>').select2({ |
| 242 | placeholder: Joomla.JText._('VAPANYEMP'), |
| 243 | allowClear: true, |
| 244 | width: '100%', |
| 245 | }); |
| 246 | <?php endif; ?> |
| 247 | |
| 248 | $('#vapserselmod<?php echo $module_id; ?>').on('change', function() { |
| 249 | |
| 250 | <?php if (!$employeeId): ?> |
| 251 | $('#vapempselmod<?php echo $module_id; ?>').prop('disabled', true); |
| 252 | |
| 253 | UIAjax.do( |
| 254 | '<?php echo $vik->ajaxUrl('index.php?option=com_vikappointments&task=modules.serviceemployees'); ?>', |
| 255 | { |
| 256 | id_ser: $(this).val(), |
| 257 | }, |
| 258 | (resp) => { |
| 259 | if (resp && resp.length) { |
| 260 | let options = []; |
| 261 | |
| 262 | if ($(this).find('option:selected').data('random')) { |
| 263 | const emptyOption = $('<option></option>'); |
| 264 | |
| 265 | if (<?php echo (int) !$advancedSelect; ?>) { |
| 266 | emptyOption.text(Joomla.JText._('VAPANYEMP')).val(0); |
| 267 | } |
| 268 | |
| 269 | options.push(emptyOption); |
| 270 | } |
| 271 | |
| 272 | resp.forEach((emp) => { |
| 273 | options.push( |
| 274 | $('<option></option>').val(emp.id).text(emp.nickname) |
| 275 | ); |
| 276 | }); |
| 277 | |
| 278 | $('#vapempselmod<?php echo $module_id; ?>').html(options).attr('disabled', false); |
| 279 | $('#vapempselmod<?php echo $module_id; ?>').trigger('change.select2'); |
| 280 | |
| 281 | $('#vapemprowmod<?php echo $module_id; ?>').show(); |
| 282 | } else { |
| 283 | $('#vapemprowmod<?php echo $module_id; ?>').hide(); |
| 284 | $('#vapempselmod<?php echo $module_id; ?>').html(''); |
| 285 | } |
| 286 | } |
| 287 | ); |
| 288 | <?php endif; ?> |
| 289 | |
| 290 | // refresh form action |
| 291 | afterServiceChange(); |
| 292 | }); |
| 293 | |
| 294 | // add callback to toggle the closing days |
| 295 | $('#vapcalendarmod<?php echo $module_id; ?>').datepicker('option', 'beforeShowDay', (date) => { |
| 296 | // get selected service ID |
| 297 | let id_service = $('#vapserselmod<?php echo $module_id; ?>').val(); |
| 298 | |
| 299 | if (isClosingDay(date, id_service) || isClosingPeriod(date, id_service)) { |
| 300 | return [false, '']; |
| 301 | } |
| 302 | |
| 303 | return [true, '']; |
| 304 | }); |
| 305 | }); |
| 306 | })(jQuery); |
| 307 | |
| 308 | </script> |
| 309 |