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 / views / ratesoverv / tmpl / default.php

default.php in VikBooking Hotel Booking Engine & PMS 1.6.4, at admin/views/ratesoverv/tmpl/default.php

2,730 lines 108.8 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 - Extensionsforjoomla.com
6 * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. 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 $all_rooms = $this->all_rooms;
14 $categories = $this->categories;
15 $roomrows = $this->roomrows;
16 $seasoncal_nights = $this->seasons_cal_nights;
17 $seasons_cal = $this->seasons_cal;
18 $tsstart = $this->tsstart;
19 $roomrates = $this->roomrates;
20
21 // JS lang defs
22 JText::script('VBO_BOOKNOW');
23 JText::script('VBPVIEWORDERSTHREE');
24 JText::script('VBEDITORDERTHREE');
25 JText::script('VBDAYS');
26 JText::script('VBDAY');
27 JText::script('VBMAILADULTS');
28 JText::script('VBMAILADULT');
29 JText::script('VBMAILCHILDREN');
30 JText::script('VBMAILCHILD');
31 JText::script('VBO_MISSING_SUBUNIT');
32
33 $document = JFactory::getDocument();
34
35 $vbo_app = VikBooking::getVboApplication();
36 $vbo_app->loadSelect2();
37 $vbo_app->loadDatePicker();
38
39 $pdebug = VikRequest::getint('e4j_debug', '', 'request');
40
41 $currencysymb = VikBooking::getCurrencySymb();
42 $vbo_df = VikBooking::getDateFormat();
43 $datesep = VikBooking::getDateSeparator();
44 $df = $vbo_df == "%d/%m/%Y" ? 'd/m/Y' : ($vbo_df == "%m/%d/%Y" ? 'm/d/Y' : 'Y/m/d');
45 $juidf = $vbo_df == "%d/%m/%Y" ? 'dd/mm/yy' : ($vbo_df == "%m/%d/%Y" ? 'mm/dd/yy' : 'yy/mm/dd');
46
47 $mb_support = function_exists('mb_substr');
48 $short_wdays = [
49 JText::translate('VBSUNDAY'),
50 JText::translate('VBMONDAY'),
51 JText::translate('VBTUESDAY'),
52 JText::translate('VBWEDNESDAY'),
53 JText::translate('VBTHURSDAY'),
54 JText::translate('VBFRIDAY'),
55 JText::translate('VBSATURDAY'),
56 ];
57 $short_mons = [
58 JText::translate('VBMONTHONE'),
59 JText::translate('VBMONTHTWO'),
60 JText::translate('VBMONTHTHREE'),
61 JText::translate('VBMONTHFOUR'),
62 JText::translate('VBMONTHFIVE'),
63 JText::translate('VBMONTHSIX'),
64 JText::translate('VBMONTHSEVEN'),
65 JText::translate('VBMONTHEIGHT'),
66 JText::translate('VBMONTHNINE'),
67 JText::translate('VBMONTHTEN'),
68 JText::translate('VBMONTHELEVEN'),
69 JText::translate('VBMONTHTWELVE'),
70 ];
71 foreach ($short_wdays as $k => $v) {
72 if ($mb_support) {
73 $short_wdays[$k] = mb_substr($v, 0, 3, 'UTF-8');
74 } else {
75 $short_wdays[$k] = substr($v, 0, 3);
76 }
77 }
78 foreach ($short_mons as $k => $v) {
79 if ($mb_support) {
80 $short_mons[$k] = mb_substr($v, 0, 3, 'UTF-8');
81 } else {
82 $short_mons[$k] = substr($v, 0, 3);
83 }
84 }
85 $json_short_wdays = json_encode($short_wdays);
86 $json_short_mons = json_encode($short_mons);
87
88 $document->addScriptDeclaration(
89 <<<JS
90 var vboMapWdays = $json_short_wdays;
91 var vboMapMons = $json_short_mons;
92 JS
93 );
94
95 $price_types_show = true;
96 $los_show = true;
97 $cookie = JFactory::getApplication()->input->cookie;
98 $cookie_tab = $cookie->get('vboRovwRab', 'cal', 'string');
99 $collapse_status = $cookie->get('vboRovwColl', 0, 'int');
100
101 //Prepare modal
102 echo $vbo_app->getJmodalScript();
103 echo $vbo_app->getJmodalHtml('vbo-vcm-rates-res', JText::translate('VBOVCMRATESRES'), '', 'width: 90%; height: 80%; margin-left: -45%; top: 10% !important;');
104 //end Prepare modal
105
106 // access room helper to detect LOS rates
107 $room_helper = VBORoomHelper::getInstance();
108
109 ?>
110
111 <div class="vbo-ratesoverview-top-outer">
112 <div class="vbo-ratesoverview-top-outer-inner vbo-toggle-small">
113 <?php echo $vbo_app->printYesNoButtons('vbo_collapse', JText::translate('VBYES'), JText::translate('VBNO'), (!$collapse_status ? 1 : 0), 1, 0, "vboToggleCollapse();"); ?>
114 <span onclick="jQuery(this).parent().find('input').trigger('click');"><?php echo JText::translate('VBO_EXPAND'); ?></span>
115 </div>
116 </div>
117
118 <div class="vbo-ratesoverview-top-container<?php echo $collapse_status ? ' collapsed' : ''; ?>">
119 <div class="vbo-ratesoverview-roomsel-block">
120 <form method="get" action="index.php?option=com_vikbooking" name="vboratesovwform">
121 <input type="hidden" name="option" value="com_vikbooking" />
122 <input type="hidden" name="task" value="ratesoverv" />
123 <div class="vbo-ratesoverview-roomsel-entry vbo-ratesoverview-roomsel-entry-chrooms">
124 <label for="roomsel"><?php VikBookingIcons::e('bed'); ?> <?php echo JText::translate('VBPVIEWORDERSTHREE'); ?></label>
125 <select name="cid[]" <?php echo count($all_rooms) > 1 ? 'multiple="multiple"' : 'onchange="document.vboratesovwform.submit();"' ?> id="roomsel" style="min-width: 160px; max-width: 250px;">
126 <?php
127 foreach ($all_rooms as $room) {
128 ?>
129 <option value="<?php echo $room['id']; ?>"<?php echo in_array($room['id'], $this->req_room_ids) ? ' selected="selected"' : ''; ?>><?php echo $room['name']; ?></option>
130 <?php
131 }
132
133 /**
134 * Use the optgroup to separate rooms from categories in the
135 * drop down menu, only if all_rooms > 1 e categories > 1.
136 *
137 * @since 1.13
138 */
139 if (count($all_rooms) > 1 && count($categories) > 1) {
140 ?>
141 <optgroup label="<?php echo addslashes(JText::translate('VBOCATEGORYFILTER')); ?>">
142 <?php
143 foreach ($categories as $cat) {
144 // we use negative values for the IDs of the categories
145 $cat_id = ($cat['id'] - ($cat['id'] * 2));
146 ?>
147 <option value="<?php echo $cat_id; ?>"><?php echo (in_array($cat['id'], $this->reqcats) ? '- ' : '') . $cat['name']; ?></option>
148 <?php
149 }
150 ?>
151 </optgroup>
152 <?php
153 }
154 //
155 ?>
156 </select>
157 <button type="button" class="btn vbo-config-btn" title="<?php echo htmlspecialchars(JText::translate('VBODRIVERLOAD')); ?>" onclick="document.vboratesovwform.submit();"><i class="vboicn-loop2"></i></button>
158 <?php
159 if (count($all_rooms) > 1 && count($all_rooms) < 50 && count($this->req_room_ids) < count($all_rooms)) {
160 // display select all rooms button
161 ?>
162 <div class="vbo-roverview-selall-rooms">
163 <button type="button" class="btn vbo-config-btn" onclick="vboSelectAllRooms(this);"><?php VikBookingIcons::e('layer-group'); ?> <?php echo JText::translate('VBOSELECTALL'); ?></button>
164 </div>
165 <?php
166 }
167 ?>
168 </div>
169 <div class="vbo-ratesoverview-roomsel-entry vbo-ratesoverview-roomsel-entry-calc">
170 <label for="checkindate" onclick="vboCheckCollapse();"><?php VikBookingIcons::e('calculator'); ?> <?php echo JText::translate('VBRATESOVWRATESCALCULATOR'); ?></label>
171 <div class="vbo-ratesoverview-roomsel-entry-calc-inner"<?php echo $collapse_status ? ' style="display: none;"' : ''; ?>>
172 <span class="vbo-ratesoverview-entryinline vbo-ratesoverview-rcalc-srooms">
173 <select name="roomselcalc" id="roomselcalc" style="max-width: 250px;">
174 <?php
175 foreach ($all_rooms as $room) {
176 ?>
177 <option value="<?php echo $room['id']; ?>"<?php echo $room['id'] == $roomrows[$this->firstroom]['id'] ? ' selected="selected"' : ''; ?>><?php echo $room['name']; ?></option>
178 <?php
179 }
180 ?>
181 </select>
182 </span>
183 <span class="vbo-ratesoverview-entryinline">
184 <div class="vbo-field-calendar">
185 <div class="input-append">
186 <input type="text" autocomplete="off" value="" class="vbo-roverv-rcalc-cal" size="10" id="checkindate" name="checkindate" placeholder="<?php echo JText::translate('VBPICKUPAT'); ?>" />
187 <button type="button" class="btn btn-secondary" id="checkindate-trig"><?php VikBookingIcons::e('calendar', 'icn-nomargin'); ?></button>
188 </div>
189 </div>
190 </span>
191 <span class="vbo-ratesoverview-entryinline">
192 <div class="vbo-field-calendar">
193 <div class="input-append">
194 <input type="text" autocomplete="off" value="" class="vbo-roverv-rcalc-cal" size="10" id="checkoutdate" name="checkoutdate" placeholder="<?php echo JText::translate('VBRELEASEAT'); ?>" />
195 <button type="button" class="btn btn-secondary" id="checkoutdate-trig"><?php VikBookingIcons::e('calendar', 'icn-nomargin'); ?></button>
196 </div>
197 </div>
198 </span>
199 <span class="vbo-ratesoverview-entryinline"><span><?php echo JText::translate('VBRATESOVWRATESCALCNUMNIGHTS'); ?></span> <input type="number" id="vbo-numnights" value="1" min="1" max="365" step="1" /></span>
200 <span class="vbo-ratesoverview-entryinline"><span><?php echo JText::translate('VBRATESOVWRATESCALCNUMADULTS'); ?></span> <input type="number" id="vbo-numadults" value="<?php echo $roomrows[$this->firstroom]['fromadult']; ?>" step="1"/></span>
201 <span class="vbo-ratesoverview-entryinline"><span><?php echo JText::translate('VBRATESOVWRATESCALCNUMCHILDREN'); ?></span> <input type="number" id="vbo-numchildren" value="<?php echo $roomrows[$this->firstroom]['fromchild']; ?>" step="1"/></span>
202 <span class="vbo-ratesoverview-entryinline"><button type="button" class="btn vbo-config-btn" id="vbo-ratesoverview-calculate"><?php echo JText::translate('VBRATESOVWRATESCALCULATORCALC'); ?></button></span>
203 </div>
204
205 <div class="vbo-ratesoverview-calculation-response"></div>
206
207 </div>
208 <div class="vbo-ratesoverview-roomsel-entry vbo-ratesoverview-roomsel-entry-forecast"<?php echo (!empty($cookie_tab) && $cookie_tab != 'cal' ? ' style="display: none;"' : ''); ?>>
209 <label onclick="vboCheckCollapse();"><?php VikBookingIcons::e('cloud-sun-rain'); ?> <?php echo JText::translate('VBOFORECAST'); ?></label>
210 <div class="vbo-roverv-forecast-inner"<?php echo $collapse_status ? ' style="display: none;"' : ''; ?>>
211 <?php echo JLayoutHelper::render('reports.occupancy', array('vbo_page' => 'ratesoverv', 'room_ids' => $this->req_room_ids)); ?>
212 </div>
213 </div>
214 <div class="vbo-ratesoverview-roomsel-entry vbo-ratesoverview-roomsel-entry-los"<?php echo (!empty($cookie_tab) && $cookie_tab == 'cal' ? ' style="display: none;"' : ''); ?>>
215 <label><?php echo JText::translate('VBRATESOVWNUMNIGHTSACT'); ?></label>
216 <?php
217 foreach ($seasoncal_nights as $numnights) {
218 ?>
219 <span class="vbo-ratesoverview-numnight" id="numnights<?php echo $numnights; ?>"><?php echo $numnights; ?></span>
220 <input type="hidden" name="nights_cal[]" id="inpnumnights<?php echo $numnights; ?>" value="<?php echo $numnights; ?>" />
221 <?php
222 }
223 ?>
224 <input type="number" id="vbo-addnumnight" value="<?php echo isset($numnights) ? ($numnights + 1) : 1; ?>" min="1"/>
225 <span id="vbo-addnumnight-act"><?php VikBookingIcons::e('plus-square'); ?></span>
226 <button type="button" class="btn vbo-config-btn vbo-apply-los-btn" onclick="document.vboratesovwform.submit();"><?php echo JText::translate('VBRATESOVWAPPLYLOS'); ?></button>
227 </div>
228 </form>
229 </div>
230 <div class="vbo-ratesoverview-right-block">
231 <div class="vbo-ratesoverview-right-inner"></div>
232 </div>
233 </div>
234
235 <div class="vbo-ratesoverview-bottom-container">
236 <?php
237 foreach ($roomrows as $rid => $roomrow) {
238 if (count($this->req_room_ids) < 2) {
239 ?>
240 <div class="vbo-ratesoverview-bottom-head">
241 <div class="vbo-ratesoverview-roomdetails">
242 <h3 class="vbo-ratesoverview-roomname"><?php echo $roomrow['name']; ?></h3>
243 </div>
244 <div class="vbo-ratesoverview-tabscont">
245 <div class="vbo-ratesoverview-tab-cal <?php echo (!empty($cookie_tab) && $cookie_tab == 'cal' ? 'vbo-ratesoverview-tab-active' : 'vbo-ratesoverview-tab-unactive'); ?>"><i class="vboicn-calendar"></i> <?php echo JText::translate('VBRATESOVWTABCALENDAR'); ?></div>
246 <div class="vbo-ratesoverview-tab-los <?php echo (!empty($cookie_tab) && $cookie_tab == 'cal' ? 'vbo-ratesoverview-tab-unactive' : 'vbo-ratesoverview-tab-active'); ?>"><i class="vboicn-clock"></i> <?php echo JText::translate('VBRATESOVWTABLOS'); ?></div>
247 </div>
248 </div>
249 <?php
250 }
251 ?>
252
253 <div class="vbo-ratesoverview-caltab-cont" style="display: <?php echo count($this->req_room_ids) > 1 || (!empty($cookie_tab) && $cookie_tab == 'cal') ? 'block' : 'none'; ?>;">
254 <?php
255 if (count($this->req_room_ids) > 1) {
256 // display room name here when multiple rooms as well as the OBP toggle
257 if (!isset($vbo_show_toggle_obp)) {
258 // toggle button for showing/hiding the occupancy based pricing rules
259 $vbo_show_toggle_obp = 1;
260 $obp_status = $cookie->get('vboRovwObp', 1, 'int');
261 ?>
262 <div class="vbo-ratesoverview-obp-toggle" data-obpstartstatus="<?php echo $obp_status; ?>" style="display: none;">
263 <div class="vbo-ratesoverview-obp-toggle-inner vbo-toggle-small">
264 <?php echo $vbo_app->printYesNoButtons('show_obp', JText::translate('VBYES'), JText::translate('VBNO'), $obp_status, 1, 0, "vboToggleOBPRows();"); ?>
265 <span class="vbo-ratesoverview-obp-toggle-txt" onclick="jQuery(this).parent().find('input').trigger('click');"><?php echo JText::translate('VBOROVERVOBP'); ?></span>
266 </div>
267 </div>
268 <?php
269 }
270 ?>
271 <div class="vbo-ratesoverview-roomdetails">
272 <h3 class="vbo-ratesoverview-roomname" data-idroom="<?php echo $roomrow['id']; ?>"><?php echo $roomrow['name']; ?></h3>
273 </div>
274 <?php
275 } else {
276 // room name node is needed for JS
277 ?>
278 <div class="vbo-ratesoverview-roomdetails" style="display: none;">
279 <h3 class="vbo-ratesoverview-roomname" data-idroom="<?php echo $roomrow['id']; ?>"><?php echo $roomrow['name']; ?></h3>
280 </div>
281 <?php
282 }
283 ?>
284 <div class="vbo-ratesoverview-caltab-wrapper">
285 <div class="vbo-table-responsive">
286 <table class="vboverviewtable vbratesoverviewtable vbo-table" data-idroom="<?php echo $rid; ?>">
287 <tbody>
288 <tr class="vbo-roverviewrowone">
289 <td class="bluedays skip-bluedays-click">
290 <form name="vbratesoverview" method="post" action="index.php?option=com_vikbooking&amp;task=ratesoverv">
291 <div class="vbo-roverview-datecmd-top">
292 <div class="vbo-roverview-datecmd-date">
293 <span>
294 <?php VikBookingIcons::e('calendar'); ?>
295 <input type="text" autocomplete="off" value="<?php echo date($df, $tsstart); ?>" class="vbodatepicker" name="startdate" />
296 </span>
297 </div>
298 </div>
299 </form>
300 </td>
301 <?php
302 $nowts = getdate($tsstart);
303 $days_labels = array(
304 JText::translate('VBSUN'),
305 JText::translate('VBMON'),
306 JText::translate('VBTUE'),
307 JText::translate('VBWED'),
308 JText::translate('VBTHU'),
309 JText::translate('VBFRI'),
310 JText::translate('VBSAT')
311 );
312 $long_days_labels = array(
313 JText::translate('VBSUNDAY'),
314 JText::translate('VBMONDAY'),
315 JText::translate('VBTUESDAY'),
316 JText::translate('VBWEDNESDAY'),
317 JText::translate('VBTHURSDAY'),
318 JText::translate('VBFRIDAY'),
319 JText::translate('VBSATURDAY')
320 );
321 $months_labels = array(
322 JText::translate('VBMONTHONE'),
323 JText::translate('VBMONTHTWO'),
324 JText::translate('VBMONTHTHREE'),
325 JText::translate('VBMONTHFOUR'),
326 JText::translate('VBMONTHFIVE'),
327 JText::translate('VBMONTHSIX'),
328 JText::translate('VBMONTHSEVEN'),
329 JText::translate('VBMONTHEIGHT'),
330 JText::translate('VBMONTHNINE'),
331 JText::translate('VBMONTHTEN'),
332 JText::translate('VBMONTHELEVEN'),
333 JText::translate('VBMONTHTWELVE')
334 );
335 $long_months_labels = $months_labels;
336 foreach ($months_labels as $i => $v) {
337 $months_labels[$i] = function_exists('mb_substr') ? mb_substr($v, 0, 3, 'UTF-8') : substr($v, 0, 3);
338 }
339 $cell_count = 0;
340 $MAX_DAYS = 60;
341 $pcheckinh = 0;
342 $pcheckinm = 0;
343 $pcheckouth = 0;
344 $pcheckoutm = 0;
345 $timeopst = VikBooking::getTimeOpenStore();
346 if (is_array($timeopst)) {
347 $opent = VikBooking::getHoursMinutes($timeopst[0]);
348 $closet = VikBooking::getHoursMinutes($timeopst[1]);
349 $pcheckinh = $opent[0];
350 $pcheckinm = $opent[1];
351 $pcheckouth = $closet[0];
352 $pcheckoutm = $closet[1];
353 }
354 $weekend_arr = array(0, 6);
355 while ($cell_count < $MAX_DAYS) {
356 $style = '';
357 $curdayymd = date('Y-m-d', $nowts[0]);
358 $read_day = $days_labels[$nowts['wday']] . ' ' . $nowts['mday'] . ' ' . $months_labels[$nowts['mon']-1] . ' ' . $nowts['year'];
359
360 $cell_classes = array(
361 'bluedays',
362 'cell-' . $nowts['mday'] . '-' . $nowts['mon'],
363 );
364
365 /**
366 * Critical dates defined at room-day level.
367 *
368 * @since 1.13.5
369 */
370 $rdaynote_keyid = $curdayymd . '_' . $rid . '_0';
371 $rdaynote_icn = '';
372 if (isset($this->rdaynotes[$rdaynote_keyid])) {
373 // note exists for this combination of date, room ID and subunit
374 array_push($cell_classes, 'vbo-roverw-roomdaynote-full');
375 $rdaynote_icn = '<i class="' . VikBookingIcons::i('sticky-note') . '"></i>';
376 }
377 //
378
379 if (in_array((int)$nowts['wday'], $weekend_arr)) {
380 array_push($cell_classes, 'vbo-roverw-tablewday-wend');
381 }
382 if (isset($this->festivities[$curdayymd])) {
383 array_push($cell_classes, 'vbo-roverv-festcell');
384 }
385 ?>
386 <td data-ymd="<?php echo $curdayymd; ?>" data-readymd="<?php echo $read_day; ?>" data-rid="<?php echo $rid; ?>" class="<?php echo implode(' ', $cell_classes); ?>"<?php echo $style; ?>>
387 <?php
388 if (!empty($rdaynote_icn)) {
389 ?>
390 <span class="vbo-roverw-roomdaynote-icn"><?php echo $rdaynote_icn; ?></span>
391 <?php
392 }
393 ?>
394 <span class="vbo-roverw-tablewday"><?php echo $days_labels[$nowts['wday']]; ?></span>
395 <span class="vbo-roverw-tablemday"><?php echo $nowts['mday']; ?></span>
396 <span class="vbo-roverw-tablemonth"><?php echo $months_labels[$nowts['mon']-1]; ?></span>
397 </td>
398 <?php
399 $next = $nowts['mday'] + 1;
400 $dayts = mktime(0, 0, 0, $nowts['mon'], $next, $nowts['year']);
401 $nowts = getdate($dayts);
402 $cell_count++;
403 }
404 ?>
405 <td class="vbo-roverv-gonext-cell" data-rid="<?php echo $rid; ?>" rowspan="<?php echo count($roomrates[$rid]) + 3; ?>">
406 <div class="vbo-roverv-gonext-cell-inner">
407 <button type="button" class="btn vbo-config-btn vbo-config-btn-rounded vbo-config-btn-large" onclick="vboDisplayNextDays(this);"><?php VikBookingIcons::e('angle-double-right'); ?></button>
408 </div>
409 </td>
410 </tr>
411 <?php
412 $room_obp_overrides = [];
413 $closed_roomrateplans = VikBooking::getRoomRplansClosingDates($roomrow['id']);
414 foreach ($roomrates[$rid] as $roomrate) {
415 $nowts = getdate($tsstart);
416 $cell_count = 0;
417 $rplan_minlos = !empty($roomrate['minlos']) && $roomrate['minlos'] > 0 ? $roomrate['minlos'] : 0;
418 $rplan_haslos = $room_helper->hasLosRecords($roomrate['idroom'], $roomrate['idprice'], true);
419 ?>
420 <tr class="vbo-roverviewtablerow" id="vbo-roverw-<?php echo $roomrate['id'].'-'.$roomrate['idroom']; ?>">
421 <td class="vbo-roverv-rplan<?php echo $rplan_minlos || $rplan_haslos ? ' vbo-roverv-rplan-restricted' : ''; ?>" data-defrate="<?php echo $roomrate['cost']; ?>" data-roomname="<?php echo htmlspecialchars($roomrow['name']); ?>">
422 <span class="vbo-rplan-name"><?php echo $roomrate['name']; ?></span>
423 <?php
424 if ($rplan_minlos || $rplan_haslos) {
425 ?>
426 <div class="vbo-roverv-rplan-restrictions<?php echo $rplan_haslos ? ' vbo-roverv-rplan-haslosrates' : ''; ?>">
427 <?php
428 if ($rplan_haslos) {
429 ?>
430 <span class="badge badge-info vbo-roverv-rplan-restrictions-los">LOS</span>
431 <?php
432 }
433 if ($rplan_minlos) {
434 ?>
435 <span class="vbo-roverv-rplan-restrictions-lbl"><?php echo JText::translate('VBOMINIMUMSTAY'); ?></span>
436 <span class="vbo-roverv-rplan-restrictions-val"><?php echo $rplan_minlos; ?></span>
437 <?php
438 }
439 ?>
440 </div>
441 <?php
442 }
443 ?>
444 </td>
445 <?php
446 while ($cell_count < $MAX_DAYS) {
447 $style = '';
448 $dclass = "vbo-roverw-rplan-on";
449 if (count($closed_roomrateplans) > 0 && array_key_exists($roomrate['idprice'], $closed_roomrateplans) && in_array(date('Y-m-d', $nowts[0]), $closed_roomrateplans[$roomrate['idprice']])) {
450 $dclass = "vbo-roverw-rplan-off";
451 }
452 $id_block = "cell-".$nowts['mday'].'-'.$nowts['mon']."-".$nowts['year']."-".$roomrate['idprice']."-".$roomrate['idroom'];
453 $dclass .= ' day-block';
454
455 $today_tsin = mktime($pcheckinh, $pcheckinm, 0, $nowts['mon'], $nowts['mday'], $nowts['year']);
456 $today_tsout = mktime($pcheckouth, $pcheckoutm, 0, $nowts['mon'], ($nowts['mday'] + 1), $nowts['year']);
457
458 $tars = VikBooking::applySeasonsRoom(array($roomrate), $today_tsin, $today_tsout);
459
460 // store the OBP overrides for this day and rate plan
461 if (!empty($tars[0]['occupancy_ovr'])) {
462 if (!isset($room_obp_overrides[$nowts[0]])) {
463 $room_obp_overrides[$nowts[0]] = [];
464 }
465 $room_obp_overrides[$nowts[0]][] = [
466 'idprice' => $roomrate['idprice'],
467 'obp' => $tars[0]['occupancy_ovr'],
468 ];
469 }
470
471 ?>
472 <td align="center" class="<?php echo $dclass.' cell-'.$nowts['mday'].'-'.$nowts['mon']; ?>" id="<?php echo $id_block; ?>" data-vboprice="<?php echo $tars[0]['cost']; ?>" data-vbodate="<?php echo date('Y-m-d', $nowts[0]); ?>" data-vbodateread="<?php echo $days_labels[$nowts['wday']].', '.$months_labels[$nowts['mon']-1].' '.$nowts['mday']; ?>" data-vbospids="<?php echo (array_key_exists('spids', $tars[0]) && count($tars[0]['spids']) > 0 ? implode('-', $tars[0]['spids']) : ''); ?>"<?php echo $style; ?>>
473 <span class="vbo-rplan-currency"><?php echo $currencysymb; ?></span>
474 <span class="vbo-rplan-price"><?php echo $tars[0]['cost']; ?></span>
475 </td>
476 <?php
477
478 $next = $nowts['mday'] + 1;
479 $dayts = mktime(0, 0, 0, $nowts['mon'], $next, $nowts['year']);
480 $nowts = getdate($dayts);
481
482 $cell_count++;
483 }
484 ?>
485 </tr>
486 <?php
487 }
488
489 // Occupancy Based Pricing rules
490 $adultsdiff = array_reverse(VikBooking::loadRoomAdultsDiff($roomrow['id']), true);
491
492 // display the room OBP rules (must be defined at room-level or no overrides will be displayed)
493 foreach ($adultsdiff as $adults => $diffusageprice) {
494 $base_obp_rules = $diffusageprice;
495 $nowts = getdate($tsstart);
496 $cell_count = 0;
497 ?>
498 <tr class="vbo-roverviewtablerow-occupancy">
499 <td>
500 <span class="vbo-rplan-name vbo-rplan-name-occ">
501 <span><?php echo JText::translate('VBPVIEWOPTIONALSTHREE'); ?></span>
502 <span class="vbo-occ-label"><?php VikBookingIcons::e('male'); ?> x <?php echo $adults ?></span>
503 </span>
504 </td>
505 <?php
506 while ($cell_count < $MAX_DAYS) {
507 $style = '';
508 $dclass = "vbo-roverw-rplan-occ";
509
510 // check for OBP overrides
511 $compare_obp_ovr = [];
512 if (isset($room_obp_overrides[$nowts[0]]) && count($room_obp_overrides[$nowts[0]]) === count($roomrates[$rid])) {
513 // the OBP overrides affect all room rate plans, make sure the overrides are identical though
514 $compare_obp_ovr = $room_obp_overrides[$nowts[0]][0]['obp'];
515 foreach ($room_obp_overrides[$nowts[0]] as $room_obp_override) {
516 if ($compare_obp_ovr != $room_obp_override['obp']) {
517 // this OBP override does not match the first one
518 $compare_obp_ovr = [];
519 break;
520 }
521 }
522 }
523 if ($compare_obp_ovr && isset($compare_obp_ovr[$adults])) {
524 // display the OBP override value for this day
525 $diffusageprice = $compare_obp_ovr[$adults];
526 } else {
527 // display the OBP rules at room-level
528 $diffusageprice = $base_obp_rules;
529 }
530
531 if (($diffusageprice['value'] - floor($diffusageprice['value'])) <= 0) {
532 $diffusageprice['value'] = intval($diffusageprice['value']);
533 }
534
535 if ($diffusageprice['chdisc'] == 1) {
536 // charge
537 if ($diffusageprice['valpcent'] == 1) {
538 // fixed value
539 $occ_diff = '+ ' . $currencysymb . ' ' . $diffusageprice['value'];
540 } else {
541 // percentage value
542 $occ_diff = '+ ' . $diffusageprice['value'] . '%';
543 }
544 } else {
545 // discount
546 if ($diffusageprice['valpcent'] == 1) {
547 // fixed value
548 $occ_diff = '- ' . $currencysymb . ' ' . $diffusageprice['value'];
549 } else {
550 // percentage value
551 $occ_diff = '- ' . $diffusageprice['value'] . '%';
552 }
553 }
554
555 ?>
556 <td align="center" class="<?php echo $dclass; ?>"<?php echo $style; ?>>
557 <span class="vbo-roverv-priceoccdiff"><?php echo $occ_diff; ?></span>
558 </td>
559 <?php
560
561 $next = $nowts['mday'] + 1;
562 $dayts = mktime(0, 0, 0, $nowts['mon'], $next, $nowts['year']);
563 $nowts = getdate($dayts);
564
565 $cell_count++;
566 }
567 ?>
568 </tr>
569 <?php
570 }
571 ?>
572 <tr class="vbo-roverviewtableavrow">
573 <td><span class="vbo-roverview-roomunits"><?php echo $roomrow['units']; ?></span><span class="vbo-roverview-uleftlbl"><?php echo JText::translate('VBPCHOOSEBUSYCAVAIL'); ?></span></td>
574 <?php
575 $nowts = getdate($tsstart);
576 $cell_count = 0;
577 while ($cell_count < $MAX_DAYS) {
578 $style = '';
579 $dclass = "vbo-roverw-daynotbusy";
580 $id_block = "cell-".$nowts['mday'].'-'.$nowts['mon']."-".$nowts['year']."-".$nowts['wday']."-".$rid."-avail";
581
582 $totfound = 0;
583 $last_bid = 0;
584 $bids_pool = [];
585
586 if (isset($this->booked_dates[$roomrow['id']]) && $this->booked_dates[$roomrow['id']]) {
587 foreach ($this->booked_dates[$roomrow['id']] as $b) {
588 $tmpone = getdate($b['checkin']);
589 $ritts = mktime(0, 0, 0, $tmpone['mon'], $tmpone['mday'], $tmpone['year']);
590 $tmptwo = getdate($b['checkout']);
591 $conts = mktime(0, 0, 0, $tmptwo['mon'], $tmptwo['mday'], $tmptwo['year']);
592 if ($nowts[0] >= $ritts && $nowts[0] < $conts) {
593 $dclass = "vbo-roverw-daybusy";
594 $last_bid = $b['idorder'];
595 $totfound++;
596 // push bid to pool
597 $bid_str = '-' . $b['idorder'] . '-';
598 if (!in_array($bid_str, $bids_pool)) {
599 $bids_pool[] = $bid_str;
600 }
601 }
602 }
603 }
604
605 $units_remaining = $roomrow['units'] - $totfound;
606 if ($units_remaining > 0 && $units_remaining < $roomrow['units'] && $roomrow['units'] > 1) {
607 $dclass .= " vbo-roverw-daybusypartially";
608 } elseif ($units_remaining <= 0 && $roomrow['units'] <= 1 && !empty($last_bid)) {
609 //Booking color tag
610 $btag_style = '';
611 $binfo = VikBooking::getBookingInfoFromID($last_bid);
612 if (count($binfo) > 0) {
613 $bcolortag = VikBooking::applyBookingColorTag($binfo);
614 if (count($bcolortag) > 0) {
615 $bcolortag['name'] = JText::translate($bcolortag['name']);
616 $btag_style = "background-color: ".$bcolortag['color']."; color: ".(array_key_exists('fontcolor', $bcolortag) ? $bcolortag['fontcolor'] : '#ffffff').";";
617 $dclass .= ' vbo-roverw-hascolortag';
618 }
619 }
620 if (!empty($btag_style)) {
621 $style = !empty($style) ? ' style="display: none; '.$btag_style.'"' : ' style="'.$btag_style.'"';
622 $style .= ' title="'.addslashes($bcolortag['name']).'"';
623 }
624 }
625
626 ?>
627 <td align="center" class="<?php echo $dclass.' cell-'.$nowts['mday'].'-'.$nowts['mon']; ?>" id="<?php echo $id_block; ?>" data-bids="<?php echo implode(',', $bids_pool); ?>" data-vbodateread="<?php echo $days_labels[$nowts['wday']].', '.$months_labels[$nowts['mon']-1].' '.$nowts['mday']; ?>"<?php echo $style; ?>>
628 <span class="vbo-roverw-curunits"><?php echo $units_remaining; ?></span>
629 </td>
630 <?php
631
632 $next = $nowts['mday'] + 1;
633 $dayts = mktime(0, 0, 0, ($nowts['mon'] < 10 ? "0".$nowts['mon'] : $nowts['mon']), ($next < 10 ? "0".$next : $next), $nowts['year']);
634 $nowts = getdate($dayts);
635
636 $cell_count++;
637 }
638 ?>
639 </tr>
640 <?php
641 // VBO 1.11 - MinLOS restrictions row
642 ?>
643 <tr class="vbo-roverviewtablerow-restrs">
644 <td><span class="vbo-roverview-restrs"><?php echo JText::translate('VBOMINIMUMSTAY'); ?></span></td>
645 <?php
646 $nowts = getdate($tsstart);
647 $cell_count = 0;
648 $glob_minlos = VikBooking::getDefaultNightsCalendar();
649 $glob_minlos = $glob_minlos < 1 ? 1 : $glob_minlos;
650 while ($cell_count < $MAX_DAYS) {
651 $style = '';
652 $dclass = "vbo-roverw-rplan-restr";
653
654 $id_block = "cell-".$nowts['mday'].'-'.$nowts['mon']."-".$nowts['year']."-".$rid."-restr";
655
656 $today_tsin = mktime(0, 0, 0, $nowts['mon'], $nowts['mday'], $nowts['year']);
657 $today_tsout = mktime(0, 0, 0, $nowts['mon'], ($nowts['mday'] + 1), $nowts['year']);
658
659 $restr = VikBooking::parseSeasonRestrictions($today_tsin, $today_tsout, 1, (isset($this->all_restrictions[$rid]) ? $this->all_restrictions[$rid] : array()));
660 $minlos = count($restr) ? $restr['minlos'] : $glob_minlos;
661
662 ?>
663 <td align="center" class="<?php echo $dclass; ?>" id="<?php echo $id_block; ?>"<?php echo $style; ?>>
664 <span class="vbo-roverw-curminlos<?php echo $minlos > 1 ? ' vbo-roverw-curminlos-active' : ''; ?>"><?php echo $minlos; ?></span>
665 </td>
666 <?php
667
668 $next = $nowts['mday'] + 1;
669 $dayts = mktime(0, 0, 0, ($nowts['mon'] < 10 ? "0".$nowts['mon'] : $nowts['mon']), ($next < 10 ? "0".$next : $next), $nowts['year']);
670 $nowts = getdate($dayts);
671
672 $cell_count++;
673 }
674 ?>
675 </tr>
676 <?php
677 //
678 ?>
679 </tbody>
680 </table>
681 </div>
682 <div class="vbo-ratesoverview-period-container">
683 <div class="vbo-ratesoverview-period-inner">
684 <div class="vbo-ratesoverview-period-lbl">
685 <span><?php echo JText::translate('VBOROVWSELPERIOD'); ?></span>
686 </div>
687 <div class="vbo-ratesoverview-period-boxes">
688 <div class="vbo-ratesoverview-period-boxes-inner">
689 <div class="vbo-ratesoverview-period-box-left">
690 <div class="vbo-ratesoverview-period-box-lbl">
691 <span><?php echo JText::translate('VBOROVWSELPERIODFROM'); ?></span>
692 </div>
693 <div class="vbo-ratesoverview-period-box-val">
694 <div class="vbo-ratesoverview-period-from">
695 <span class="vbo-ratesoverview-period-wday"></span>
696 <span class="vbo-ratesoverview-period-mday"></span>
697 <span class="vbo-ratesoverview-period-month"></span>
698 </div>
699 <span class="vbo-ratesoverview-period-from-icon"><?php VikBookingIcons::e('calendar'); ?></span>
700 </div>
701 </div>
702 <div class="vbo-ratesoverview-period-box-right">
703 <div class="vbo-ratesoverview-period-box-lbl">
704 <span><?php echo JText::translate('VBOROVWSELPERIODTO'); ?></span>
705 </div>
706 <div class="vbo-ratesoverview-period-box-val">
707 <div class="vbo-ratesoverview-period-to">
708 <span class="vbo-ratesoverview-period-wday"></span>
709 <span class="vbo-ratesoverview-period-mday"></span>
710 <span class="vbo-ratesoverview-period-month"></span>
711 </div>
712 <span class="vbo-ratesoverview-period-to-icon"><?php VikBookingIcons::e('calendar'); ?></span>
713 </div>
714 </div>
715 </div>
716 <div class="vbo-ratesoverview-period-box-cals" style="display: none;">
717 <div class="vbo-ratesoverview-period-box-cals-inner">
718 <div class="vbo-ratesoverview-period-cal-left">
719 <h4><?php echo JText::translate('VBOROVWSELPERIODFROM'); ?></h4>
720 <div class="vbo-period-from" data-idroom="<?php echo $rid; ?>" data-roomname="<?php echo htmlspecialchars($roomrow['name']); ?>"></div>
721 <input type="hidden" class="vbo-period-from-val" value="" />
722 </div>
723 <div class="vbo-ratesoverview-period-cal-right">
724 <h4><?php echo JText::translate('VBOROVWSELPERIODTO'); ?></h4>
725 <div class="vbo-period-to" data-idroom="<?php echo $rid; ?>" data-roomname="<?php echo htmlspecialchars($roomrow['name']); ?>"></div>
726 <input type="hidden" class="vbo-period-to-val" value="" />
727 </div>
728 <div class="vbo-ratesoverview-period-cal-cmd">
729 <h4><?php echo JText::translate('VBOROVWSELRPLAN'); ?></h4>
730 <div class="vbo-ratesoverview-period-cal-cmd-inner">
731 <select class="vbo-selperiod-rplanid" onchange="vboUpdateRplan(this);">
732 <?php
733 foreach ($roomrates[$rid] as $krr => $roomrate) {
734 ?>
735 <option value="<?php echo $roomrate['idprice']; ?>" data-defrate="<?php echo $roomrate['cost']; ?>"<?php echo $krr < 1 ? ' selected="selected"' : ''; ?>><?php echo $roomrate['name']; ?></option>
736 <?php
737 }
738 ?>
739 </select>
740 </div>
741 </div>
742 </div>
743 </div>
744 </div>
745 </div>
746 <div class="vbo-ratesoverview-orphans-wrapper" id="vbo-ratesoverview-orphans-wrapper-<?php echo $rid; ?>" style="display: none;">
747 <div class="vbo-ratesoverview-orphans-lbl">
748 <span><?php echo $vbo_app->createPopover(array('title' => JText::translate('VBORPHANSFOUND'), 'content' => JText::translate('VBORPHANSFOUNDSHELP'), 'icon_class' => VikBookingIcons::i('exclamation-triangle'))); ?> <?php echo JText::translate('VBORPHANSFOUND'); ?></span>
749 </div>
750 <div class="vbo-ratesoverview-orphans-list" id="vbo-ratesoverview-orphans-list-<?php echo $rid; ?>"></div>
751 </div>
752 </div>
753 </div>
754 </div>
755
756 <?php
757 // start los pricing overview IF statement for just 1 room
758 if (count($this->req_room_ids) < 2) :
759 ?>
760 <div class="vbo-ratesoverview-lostab-cont"<?php echo (!empty($cookie_tab) && $cookie_tab == 'cal' ? ' style="display: none;"' : ''); ?>>
761 <?php
762 if (count($seasons_cal) > 0) {
763 //Special Prices Timeline
764 if (isset($seasons_cal['seasons']) && count($seasons_cal['seasons'])) {
765 ?>
766 <div class="vbo-timeline-container">
767 <ul id="vbo-timeline">
768 <?php
769 foreach ($seasons_cal['seasons'] as $ks => $timeseason) {
770 $s_val_diff = '';
771 if ($timeseason['val_pcent'] == 2) {
772 //percentage
773 $s_val_diff = (($timeseason['diffcost'] - abs($timeseason['diffcost'])) > 0.00 ? VikBooking::numberFormat($timeseason['diffcost']) : intval($timeseason['diffcost']))." %";
774 } else {
775 //absolute
776 $s_val_diff = $currencysymb.''.VikBooking::numberFormat($timeseason['diffcost']);
777 }
778 $s_explanation = array();
779 if (empty($timeseason['year'])) {
780 $s_explanation[] = JText::translate('VBSEASONANYYEARS');
781 }
782 if (!empty($timeseason['losoverride'])) {
783 $s_explanation[] = JText::translate('VBSEASONBASEDLOS');
784 }
785 ?>
786 <li data-fromts="<?php echo $timeseason['from_ts']; ?>" data-tots="<?php echo $timeseason['to_ts']; ?>">
787 <input type="radio" name="timeline" class="vbo-timeline-radio" id="vbo-timeline-dot<?php echo $ks; ?>" <?php echo $ks === 0 ? 'checked="checked"' : ''; ?>/>
788 <div class="vbo-timeline-relative">
789 <label class="vbo-timeline-label" for="vbo-timeline-dot<?php echo $ks; ?>"><?php echo $timeseason['spname']; ?></label>
790 <span class="vbo-timeline-date"><?php echo VikBooking::formatSeasonDates($timeseason['from_ts'], $timeseason['to_ts']); ?></span>
791 <span class="vbo-timeline-circle" onclick="Javascript: jQuery('#vbo-timeline-dot<?php echo $ks; ?>').trigger('click');"></span>
792 </div>
793 <div class="vbo-timeline-content">
794 <p>
795 <span class="vbo-seasons-calendar-slabel vbo-seasons-calendar-season-<?php echo $timeseason['type'] == 2 ? 'discount' : 'charge'; ?>"><?php echo $timeseason['type'] == 2 ? '-' : '+'; ?> <?php echo $s_val_diff; ?> <?php echo JText::translate('VBSEASONPERNIGHT'); ?></span>
796 <br/>
797 <?php
798 if (count($s_explanation) > 0) {
799 echo implode(' - ', $s_explanation);
800 }
801 ?>
802 </p>
803 </div>
804 </li>
805 <?php
806 }
807 ?>
808 </ul>
809 </div>
810
811 <script>
812 jQuery(function() {
813 jQuery('.vbo-timeline-container').css('min-height', (jQuery('.vbo-timeline-container').outerHeight() + 20));
814 });
815 </script>
816 <?php
817 }
818 //
819 //Begin Seasons Calendar
820 ?>
821 <div class="table-responsive">
822 <table class="table vbo-seasons-calendar-table">
823 <tr class="vbo-seasons-calendar-nightsrow">
824 <td>&nbsp;</td>
825 <?php
826 foreach ($seasons_cal['offseason'] as $numnights => $ntars) {
827 ?>
828 <td><span><?php echo JText::sprintf(($numnights > 1 ? 'VBOSEASONCALNUMNIGHTS' : 'VBOSEASONCALNUMNIGHT'), $numnights); ?></span></td>
829 <?php
830 }
831 ?>
832 </tr>
833 <tr class="vbo-seasons-calendar-offseasonrow">
834 <td>
835 <span class="vbo-seasons-calendar-offseasonname"><?php echo JText::translate('VBOSEASONSCALOFFSEASONPRICES'); ?></span>
836 </td>
837 <?php
838 foreach ($seasons_cal['offseason'] as $numnights => $tars) {
839 ?>
840 <td>
841 <div class="vbo-seasons-calendar-offseasoncosts">
842 <?php
843 foreach ($tars as $tar) {
844 ?>
845 <div class="vbo-seasons-calendar-offseasoncost">
846 <?php
847 if ($price_types_show) {
848 ?>
849 <span class="vbo-seasons-calendar-pricename"><?php echo $tar['name']; ?></span>
850 <?php
851 }
852 ?>
853 <span class="vbo-seasons-calendar-pricecost">
854 <span class="vbo_currency"><?php echo $currencysymb; ?></span><span class="vbo_price"><?php echo VikBooking::numberFormat($tar['cost']); ?></span>
855 </span>
856 </div>
857 <?php
858 if (!$price_types_show) {
859 break;
860 }
861 }
862 ?>
863 </div>
864 </td>
865 <?php
866 }
867 ?>
868 </tr>
869 <?php
870 if (!isset($seasons_cal['seasons'])) {
871 $seasons_cal['seasons'] = array();
872 }
873 foreach ($seasons_cal['seasons'] as $s_id => $s) {
874 $restr_diff_nights = array();
875 if ($los_show && array_key_exists($s_id, $seasons_cal['restrictions'])) {
876 $restr_diff_nights = VikBooking::compareSeasonRestrictionsNights($seasons_cal['restrictions'][$s_id]);
877 }
878 $s_val_diff = '';
879 if ($s['val_pcent'] == 2) {
880 //percentage
881 $s_val_diff = (($s['diffcost'] - abs($s['diffcost'])) > 0.00 ? VikBooking::numberFormat($s['diffcost']) : intval($s['diffcost']))." %";
882 } else {
883 //absolute
884 $s_val_diff = $currencysymb.''.VikBooking::numberFormat($s['diffcost']);
885 }
886 ?>
887 <tr class="vbo-seasons-calendar-seasonrow">
888 <td>
889 <div class="vbo-seasons-calendar-seasondates">
890 <span class="vbo-seasons-calendar-seasonfrom"><?php echo date(str_replace("/", $datesep, $df), $s['from_ts']); ?></span>
891 <span class="vbo-seasons-calendar-seasondates-separe">-</span>
892 <span class="vbo-seasons-calendar-seasonto"><?php echo date(str_replace("/", $datesep, $df), $s['to_ts']); ?></span>
893 </div>
894 <div class="vbo-seasons-calendar-seasonchargedisc">
895 <span class="vbo-seasons-calendar-slabel vbo-seasons-calendar-season-<?php echo $s['type'] == 2 ? 'discount' : 'charge'; ?>"><span class="vbo-seasons-calendar-operator"><?php echo $s['type'] == 2 ? '-' : '+'; ?></span><?php echo $s_val_diff; ?></span>
896 </div>
897 <span class="vbo-seasons-calendar-seasonname"><a href="index.php?option=com_vikbooking&amp;task=editseason&amp;cid[]=<?php echo $s['id']; ?>" target="_blank"><?php echo $s['spname']; ?></a></span>
898 <?php
899 if ($los_show && array_key_exists($s_id, $seasons_cal['restrictions']) && count($restr_diff_nights) == 0) {
900 //Season Restrictions
901 $season_restrictions = array();
902 foreach ($seasons_cal['restrictions'][$s_id] as $restr) {
903 $season_restrictions = $restr;
904 break;
905 }
906 ?>
907 <div class="vbo-seasons-calendar-restrictions">
908 <?php
909 if ($season_restrictions['minlos'] > 1) {
910 ?>
911 <span class="vbo-seasons-calendar-restriction-minlos"><?php echo JText::translate('VBORESTRMINLOS'); ?><span class="vbo-seasons-calendar-restriction-minlos-badge"><?php echo $season_restrictions['minlos']; ?></span></span>
912 <?php
913 }
914 if (array_key_exists('maxlos', $season_restrictions) && $season_restrictions['maxlos'] > 1) {
915 ?>
916 <span class="vbo-seasons-calendar-restriction-maxlos"><?php echo JText::translate('VBORESTRMAXLOS'); ?><span class="vbo-seasons-calendar-restriction-maxlos-badge"><?php echo $season_restrictions['maxlos']; ?></span></span>
917 <?php
918 }
919 if (array_key_exists('wdays', $season_restrictions) && count($season_restrictions['wdays']) > 0) {
920 ?>
921 <div class="vbo-seasons-calendar-restriction-wdays">
922 <label><?php echo JText::translate((count($season_restrictions['wdays']) > 1 ? 'VBORESTRARRIVWDAYS' : 'VBORESTRARRIVWDAY')); ?></label>
923 <?php
924 foreach ($season_restrictions['wdays'] as $wday) {
925 ?>
926 <span class="vbo-seasons-calendar-restriction-wday"><?php echo VikBooking::sayWeekDay($wday); ?></span>
927 <?php
928 }
929 ?>
930 </div>
931 <?php
932 } elseif ((array_key_exists('cta', $season_restrictions) && count($season_restrictions['cta']) > 0) || (array_key_exists('ctd', $season_restrictions) && count($season_restrictions['ctd']) > 0)) {
933 if (array_key_exists('cta', $season_restrictions) && count($season_restrictions['cta']) > 0) {
934 ?>
935 <div class="vbo-seasons-calendar-restriction-wdays vbo-seasons-calendar-restriction-cta">
936 <label><?php echo JText::translate('VBORESTRWDAYSCTA'); ?></label>
937 <?php
938 foreach ($season_restrictions['cta'] as $wday) {
939 ?>
940 <span class="vbo-seasons-calendar-restriction-wday"><?php echo VikBooking::sayWeekDay(str_replace('-', '', $wday)); ?></span>
941 <?php
942 }
943 ?>
944 </div>
945 <?php
946 }
947 if (array_key_exists('ctd', $season_restrictions) && count($season_restrictions['ctd']) > 0) {
948 ?>
949 <div class="vbo-seasons-calendar-restriction-wdays vbo-seasons-calendar-restriction-ctd">
950 <label><?php echo JText::translate('VBORESTRWDAYSCTD'); ?></label>
951 <?php
952 foreach ($season_restrictions['ctd'] as $wday) {
953 ?>
954 <span class="vbo-seasons-calendar-restriction-wday"><?php echo VikBooking::sayWeekDay(str_replace('-', '', $wday)); ?></span>
955 <?php
956 }
957 ?>
958 </div>
959 <?php
960 }
961 }
962 ?>
963 </div>
964 <?php
965 }
966 ?>
967 </td>
968 <?php
969 if (array_key_exists($s_id, $seasons_cal['season_prices']) && count($seasons_cal['season_prices'][$s_id]) > 0) {
970 foreach ($seasons_cal['season_prices'][$s_id] as $numnights => $tars) {
971 $show_day_cost = true;
972 if ($los_show && array_key_exists($s_id, $seasons_cal['restrictions']) && array_key_exists($numnights, $seasons_cal['restrictions'][$s_id])) {
973 if ($seasons_cal['restrictions'][$s_id][$numnights]['allowed'] === false) {
974 $show_day_cost = false;
975 }
976 }
977 ?>
978 <td>
979 <?php
980 if ($show_day_cost) {
981 ?>
982 <div class="vbo-seasons-calendar-seasoncosts">
983 <?php
984 foreach ($tars as $tar) {
985 //print the types of price that are not being modified by this special price with opacity
986 $not_affected = (!array_key_exists('origdailycost', $tar));
987 //
988 ?>
989 <div class="vbo-seasons-calendar-seasoncost<?php echo ($not_affected ? ' vbo-seasons-calendar-seasoncost-notaffected' : ''); ?>">
990 <?php
991 if ($price_types_show) {
992 ?>
993 <span class="vbo-seasons-calendar-pricename"><?php echo $tar['name']; ?></span>
994 <?php
995 }
996 ?>
997 <span class="vbo-seasons-calendar-pricecost">
998 <span class="vbo_currency"><?php echo $currencysymb; ?></span><span class="vbo_price"><?php echo VikBooking::numberFormat($tar['cost']); ?></span>
999 </span>
1000 </div>
1001 <?php
1002 if (!$price_types_show) {
1003 break;
1004 }
1005 }
1006 ?>
1007 </div>
1008 <?php
1009 } else {
1010 ?>
1011 <div class="vbo-seasons-calendar-seasoncosts-disabled"></div>
1012 <?php
1013 }
1014 ?>
1015 </td>
1016 <?php
1017 }
1018 }
1019 ?>
1020 </tr>
1021 <?php
1022 }
1023 ?>
1024 </table>
1025 </div>
1026 <?php
1027 //End Seasons Calendar
1028 } else {
1029 ?>
1030 <p class="vbo-warning"><?php echo JText::translate('VBOWARNNORATESROOM'); ?></p>
1031 <?php
1032 }
1033 ?>
1034 </div>
1035 <?php
1036 // end los pricing overview IF statement for just 1 room
1037 endif;
1038 }
1039 ?>
1040 </div>
1041 <?php
1042
1043 // overlay modal to change rates, restrictions etc..
1044 $vcm_enabled = VikBooking::vcmAutoUpdate();
1045 ?>
1046 <div class="vbo-info-overlay-block">
1047 <a class="vbo-info-overlay-close" href="javascript: void(0);"></a>
1048 <div class="vbo-info-overlay-content vbo-info-overlay-content-rovervw">
1049 <div class="vbo-roverw-infoblock">
1050 <span id="rovervw-roomname"></span>
1051 <div class="vbo-roverw-inforates">
1052 <span id="rovervw-rplan"></span>
1053 <span id="rovervw-fromdate"></span> - <span id="rovervw-todate"></span>
1054 </div>
1055 </div>
1056 <div class="vbo-roverw-alldays">
1057 <div class="vbo-roverw-alldays-inner"></div>
1058 </div>
1059 <div class="vbo-roverw-setnewrate">
1060 <div class="vbo-roverw-flexnew">
1061 <div class="vbo-roverw-newrwrap">
1062 <h4><i class="vboicn-calculator"></i> <?php echo JText::translate('VBRATESOVWSETNEWRATE'); ?></h4>
1063 <div class="vbo-roverw-newrcont">
1064 <label for="roverw-newrate" class="vbo-roverw-setnewrate-currency"><?php echo $currencysymb; ?></label>
1065 <input type="number" step="any" min="0" id="roverw-newrate" value="" placeholder="" size="7" />
1066 </div>
1067 </div>
1068 <div class="vbo-roverw-newrestr-wrap" style="display: none;">
1069 <div class="vbo-roverw-newrestrcont">
1070 <h4><i class="vboicn-blocked"></i> <?php echo JText::translate('VBOMINIMUMSTAYSET'); ?></h4>
1071 <div class="vbo-roverw-newrestrcont-inner">
1072 <label for="roverw-newrestr" class="vbo-roverw-setnewrestr-lbl"><?php echo JText::translate('VBDAYS'); ?></label>
1073 <input type="number" step="1" min="0" id="roverw-newrestr" value="" size="7" />
1074 </div>
1075 </div>
1076 </div>
1077 </div>
1078 <div class="vbo-roverw-setnewrate-inner">
1079 <div class="vbo-roverw-setnewrate-vcm">
1080 <div class="vbo-roverw-setnewrate-vcm-head">
1081 <span class="<?php echo $vcm_enabled < 0 ? 'vbo-vcm-notinstalled' : 'vbo-vcm-installed'; ?>">
1082 <?php echo $vbo_app->createPopover(array('title' => JText::translate('VBOUPDRATESONCHANNELS'), 'content' => ($vcm_enabled < 0 ? JText::translate('VBCONFIGVCMAUTOUPDMISS') : JText::translate('VBOUPDRATESONCHANNELSHELP')), 'icon_class' => VikBookingIcons::i('globe'))); ?>
1083 <?php echo JText::translate('VBOUPDRATESONCHANNELS'); ?>
1084 </span>
1085 </div>
1086 <div class="vbo-roverw-setnewrate-vcm-body">
1087 <label class="vbo-switch">
1088 <input type="checkbox" id="roverw-newrate-vcm" onchange="vboCheckVcmRestrictions();" value="1" <?php echo $vcm_enabled < 0 ? 'disabled="disabled"' : ($vcm_enabled > 0 ? 'checked="checked"' : ''); ?>/>
1089 <span class="vbo-slider<?php echo $vcm_enabled < 0 ? ' vbo-slider-disabled' : ''; ?> vbo-round"></span>
1090 </label>
1091 </div>
1092 </div>
1093 <div class="vbo-roverw-setnewrate-btns">
1094 <button type="button" class="btn btn-danger" onclick="hideVboDialog();"><?php echo JText::translate('VBANNULLA'); ?></button>
1095 <button type="button" class="btn btn-success" onclick="setNewRates();"><i class="vboicn-checkmark"></i><?php echo JText::translate('VBAPPLY'); ?></button>
1096 </div>
1097 </div>
1098 </div>
1099 <div class="vbo-roverw-closeopenrp">
1100 <h4><i class="vboicn-switch"></i><?php echo JText::translate('VBRATESOVWCLOSEOPENRRP'); ?> <span id="rovervw-closeopen-rplan"></span></h4>
1101 <div class="vbo-roverw-closeopenrp-btns">
1102 <button type="button" class="btn btn-danger" onclick="modRoomRatePlan('close');"><i class="vboicn-exit"></i><?php echo JText::translate('VBRATESOVWCLOSERRP'); ?></button>
1103 <button type="button" class="btn btn-success" onclick="modRoomRatePlan('open');"><i class="vboicn-enter"></i><?php echo JText::translate('VBRATESOVWOPENRRP'); ?></button>
1104 <br clear="all" /><br />
1105 <button type="button" class="btn btn-danger" onclick="hideVboDialog();"><?php echo JText::translate('VBANNULLA'); ?></button>
1106 </div>
1107 </div>
1108 </div>
1109 <div class="vbo-info-overlay-loading">
1110 <div><?php echo JText::translate('VIKLOADING'); ?></div>
1111 </div>
1112 </div>
1113
1114 <form name="adminForm" id="adminForm" action="index.php" method="post">
1115 <input type="hidden" name="task" value="">
1116 <input type="hidden" name="option" value="com_vikbooking">
1117 </form>
1118
1119 <a id="vbo-base-booknow-link" style="display: none;" href="index.php?option=com_vikbooking&task=calendar&cid[]=&checkin=&checkout=&adults=&children=&idprice=&booknow=1"></a>
1120 <a class="vbo-basenavuri-details" href="index.php?option=com_vikbooking&task=editorder&goto=ratesoverv&cid[]=%d" style="display: none;"></a>
1121
1122 <script type="text/Javascript">
1123 function vboFormatCalDate(elem, idc) {
1124 var vb_period = elem.parent().find('.vbo-'+idc+'-val').val();
1125 if (!vb_period || !vb_period.length) {
1126 return false;
1127 }
1128 var vb_period_parts = vb_period.split("/");
1129 if ('%d/%m/%Y' == '<?php echo $vbo_df; ?>') {
1130 var period_date = new Date(vb_period_parts[2], (parseInt(vb_period_parts[1]) - 1), parseInt(vb_period_parts[0], 10), 0, 0, 0, 0);
1131 var data = [parseInt(vb_period_parts[0], 10), parseInt(vb_period_parts[1]), vb_period_parts[2]];
1132 } else if ('%m/%d/%Y' == '<?php echo $vbo_df; ?>') {
1133 var period_date = new Date(vb_period_parts[2], (parseInt(vb_period_parts[0]) - 1), parseInt(vb_period_parts[1], 10), 0, 0, 0, 0);
1134 var data = [parseInt(vb_period_parts[1], 10), parseInt(vb_period_parts[0]), vb_period_parts[2]];
1135 } else {
1136 var period_date = new Date(vb_period_parts[0], (parseInt(vb_period_parts[1]) - 1), parseInt(vb_period_parts[2], 10), 0, 0, 0, 0);
1137 var data = [parseInt(vb_period_parts[2], 10), parseInt(vb_period_parts[1]), vb_period_parts[0]];
1138 }
1139 var elcont = elem.closest('.vbo-ratesoverview-period-boxes').find('.vbo-ratesoverview-'+idc);
1140 elcont.find('.vbo-ratesoverview-period-wday').text(vboMapWdays[period_date.getDay()]);
1141 elcont.find('.vbo-ratesoverview-period-mday').text(period_date.getDate());
1142 elcont.find('.vbo-ratesoverview-period-month').text(vboMapMons[period_date.getMonth()]);
1143 elem.closest('.vbo-ratesoverview-period-boxes').find('.vbo-ratesoverview-'+idc+'-icon').hide();
1144 data.push(elem.closest('.vbo-ratesoverview-period-boxes').find('.vbo-selperiod-rplanid').val());
1145 data.push(elem.closest('.vbo-ratesoverview-period-boxes').find('.vbo-selperiod-rplanid option:selected').text());
1146 data.push(elem.closest('.vbo-ratesoverview-period-boxes').find('.vbo-selperiod-rplanid option:selected').attr('data-defrate'));
1147 data.push(elem.attr('data-idroom'));
1148 data.push(elem.attr('data-roomname'));
1149 var struct = getPeriodStructure(data);
1150 if (idc.indexOf('from') >= 0) {
1151 //period from date selected
1152 if (!vbolistener.pickFirst(struct)) {
1153 //first already picked: update it
1154 vbolistener.first = struct;
1155 }
1156 }
1157 if (idc.indexOf('to') >= 0) {
1158 //period to date selected
1159 if (!vbolistener.pickFirst(struct)) {
1160 //first already picked
1161 if ((vbolistener.first.isBeforeThan(struct) || vbolistener.first.isSameDay(struct)) && vbolistener.first.isSameRplan(struct) && vbolistener.first.isSameRoom(struct)) {
1162 //last > first: pick last
1163 if (vbolistener.pickLast(struct)) {
1164 showVboDialogPeriod();
1165 }
1166 }
1167 }
1168 }
1169 }
1170 function vbCalcNights() {
1171 var vbcheckin = document.getElementById('checkindate').value;
1172 var vbcheckout = document.getElementById('checkoutdate').value;
1173 if (!vbcheckin.length || !vbcheckout.length) {
1174 return;
1175 }
1176 var vbcheckinp = vbcheckin.split("-");
1177 var vbcheckoutp = vbcheckout.split("-");
1178 var vbinmonth = parseInt(vbcheckinp[1]);
1179 vbinmonth = vbinmonth - 1;
1180 var vbinday = parseInt(vbcheckinp[2], 10);
1181 var vbcheckind = new Date(vbcheckinp[0], vbinmonth, vbinday);
1182 var vboutmonth = parseInt(vbcheckoutp[1]);
1183 vboutmonth = vboutmonth - 1;
1184 var vboutday = parseInt(vbcheckoutp[2], 10);
1185 var vbcheckoutd = new Date(vbcheckoutp[0], vboutmonth, vboutday);
1186 var vbdivider = 1000 * 60 * 60 * 24;
1187 var vbints = vbcheckind.getTime();
1188 var vboutts = vbcheckoutd.getTime();
1189 if (vboutts > vbints) {
1190 var utc1 = Date.UTC(vbcheckind.getFullYear(), vbcheckind.getMonth(), vbcheckind.getDate());
1191 var utc2 = Date.UTC(vbcheckoutd.getFullYear(), vbcheckoutd.getMonth(), vbcheckoutd.getDate());
1192 var vbnights = Math.ceil((utc2 - utc1) / vbdivider);
1193 if (vbnights > 0) {
1194 jQuery('#vbo-numnights').val(vbnights);
1195 }
1196 }
1197 }
1198
1199 /**
1200 * Scrollable tables will show the arrows to navigate to the next N days.
1201 *
1202 * @since 1.15.0 (J) - 1.5.0 (WP)
1203 */
1204 function vboDisplayNextDays(btn) {
1205 var cell = jQuery(btn).closest('.vbo-roverv-gonext-cell');
1206 if (!cell || !cell.length) {
1207 return;
1208 }
1209 var rid = cell.attr('data-rid');
1210 if (!rid || !rid.length) {
1211 return;
1212 }
1213 var table = jQuery('table.vbratesoverviewtable[data-idroom="' + rid + '"]');
1214 if (!table || !table.length) {
1215 return;
1216 }
1217 // get the datepicker calendar instance for this room
1218 var calendar = table.find('input.vbodatepicker');
1219 try {
1220 // calculate the new date
1221 var cur_date = calendar.datepicker('getDate');
1222 var dobj = new Date(cur_date);
1223 dobj.setDate(dobj.getDate() + <?php echo isset($MAX_DAYS) ? $MAX_DAYS : 60; ?>);
1224 // set the new date
1225 calendar.datepicker('setDate', dobj);
1226 // populate hidden form fields
1227 var parentform = calendar.closest('form');
1228 var roomsids = jQuery('#roomsel').val();
1229 if (roomsids) {
1230 if (!Array.isArray(roomsids)) {
1231 // if there is just one room type, the select is not multiple, so this is a string
1232 roomsids = [jQuery('#roomsel').val()];
1233 }
1234 jQuery.each(roomsids, function(k, v) {
1235 parentform.append('<input type="hidden" name="cid[]" value="' + v + '" />');
1236 });
1237 }
1238 // auto-submit form with new date
1239 parentform.submit();
1240 } catch(e) {
1241 console.error(e);
1242 alert('Calendar not found. Please change date manually.');
1243 }
1244 }
1245
1246 jQuery(function() {
1247 jQuery('.vbodatepicker').datepicker({
1248 showOn: 'focus',
1249 dateFormat: '<?php echo $juidf; ?>',
1250 minDate: '-1y',
1251 numberOfMonths: 2,
1252 changeMonth: true,
1253 changeYear: true,
1254 yearRange: '<?php echo (date('Y') - 1).':'.(date('Y') + 3); ?>',
1255 onSelect: function(selectedDate) {
1256 var parentform = jQuery(this).closest('form');
1257 var roomsids = jQuery('#roomsel').val();
1258 if (roomsids) {
1259 if (!Array.isArray(roomsids)) {
1260 // if there is just one room type, the select is not multiple, so this is a string
1261 roomsids = [jQuery('#roomsel').val()];
1262 }
1263 jQuery.each(roomsids, function(k, v) {
1264 parentform.append('<input type="hidden" name="cid[]" value="' + v + '" />');
1265 });
1266 }
1267 parentform.submit();
1268 }
1269 });
1270 jQuery('#checkindate').datepicker({
1271 showOn: 'focus',
1272 dateFormat: 'yy-mm-dd',
1273 minDate: '0d',
1274 numberOfMonths: 2,
1275 onSelect: function(selectedDate) {
1276 var nownights = parseInt(jQuery('#vbo-numnights').val());
1277 var nowcheckin = jQuery('#checkindate').datepicker('getDate');
1278 var nowcheckindate = new Date(nowcheckin.getTime());
1279 nowcheckindate.setDate(nowcheckindate.getDate() + nownights);
1280 jQuery('#checkoutdate').datepicker( 'option', 'minDate', nowcheckindate );
1281 jQuery('#checkoutdate').datepicker( 'setDate', nowcheckindate );
1282 vbCalcNights();
1283 }
1284 });
1285 jQuery('#checkoutdate').datepicker({
1286 showOn: 'focus',
1287 dateFormat: 'yy-mm-dd',
1288 minDate: '0d',
1289 numberOfMonths: 2,
1290 onSelect: function(selectedDate) {
1291 if (!jQuery('#checkoutdate').val().length) {
1292 return;
1293 }
1294 vbCalcNights();
1295 }
1296 });
1297 jQuery('#checkindate-trig, #checkoutdate-trig').click(function() {
1298 var jdp = jQuery(this).prev('input.hasDatepicker');
1299 if (jdp.length) {
1300 jdp.focus();
1301 }
1302 });
1303 jQuery('#vbo-numnights').on('change keyup', function() {
1304 if (!jQuery('#checkindate').length) {
1305 return;
1306 }
1307 var nownights = parseInt(jQuery(this).val());
1308 var nowcheckin = jQuery('#checkindate').datepicker('getDate');
1309 var nowcheckindate = new Date(nowcheckin.getTime());
1310 nowcheckindate.setDate(nowcheckindate.getDate() + nownights);
1311 jQuery('#checkoutdate').datepicker( 'option', 'minDate', nowcheckindate );
1312 jQuery('#checkoutdate').datepicker( 'setDate', nowcheckindate );
1313 });
1314 jQuery('.vbo-period-from').datepicker({
1315 dateFormat: '<?php echo $juidf; ?>',
1316 minDate: '0d',
1317 altField: '.vbo-period-from-val',
1318 onSelect: function(selectedDate) {
1319 jQuery(this).parent().find('.vbo-period-from-val').val(selectedDate);
1320 jQuery(this).closest('.vbo-ratesoverview-period-box-cals').find('.vbo-period-to').datepicker("option", "minDate", selectedDate);
1321 vboFormatCalDate(jQuery(this), 'period-from');
1322 }
1323 });
1324 jQuery('.vbo-period-to').datepicker({
1325 dateFormat: '<?php echo $juidf; ?>',
1326 minDate: '0d',
1327 altField: '.vbo-period-to-val',
1328 onSelect: function(selectedDate) {
1329 jQuery(this).parent().find('.vbo-period-to-val').val(selectedDate);
1330 jQuery(this).closest('.vbo-ratesoverview-period-box-cals').find('.vbo-period-from').datepicker("option", "maxDate", selectedDate);
1331 vboFormatCalDate(jQuery(this), 'period-to');
1332 }
1333 });
1334 jQuery('.vbo-ratesoverview-period-box-left, .vbo-ratesoverview-period-box-right').click(function() {
1335 jQuery(this).closest('.vbo-ratesoverview-period-boxes').find('.vbo-ratesoverview-period-box-cals').fadeToggle();
1336 });
1337 jQuery("#roomsel, #roomselcalc").select2();
1338 });
1339 <?php
1340 if ($df == "Y/m/d") {
1341 ?>
1342 Date.prototype.format = "yy/mm/dd";
1343 <?php
1344 } elseif ($df == "m/d/Y") {
1345 ?>
1346 Date.prototype.format = "mm/dd/yy";
1347 <?php
1348 } else {
1349 ?>
1350 Date.prototype.format = "dd/mm/yy";
1351 <?php
1352 }
1353 ?>
1354 Date.prototype.datesep = "<?php echo addslashes(VikBooking::getDateSeparator()); ?>";
1355 var currencysymb = '<?php echo $currencysymb; ?>';
1356 var debug_mode = '<?php echo $pdebug; ?>';
1357 var vcm_exists = <?php echo VikBooking::vcmAutoUpdate(); ?>;
1358 var roverw_messages = {
1359 "setNewRatesMissing": "<?php echo addslashes(JText::translate('VBRATESOVWERRNEWRATE')); ?>",
1360 "modRplansMissing": "<?php echo addslashes(JText::translate('VBRATESOVWERRMODRPLANS')); ?>",
1361 "openSpLink": "<?php echo addslashes(JText::translate('VBRATESOVWOPENSPL')); ?>",
1362 "vcmRatesChanged": "<?php echo addslashes(JText::translate('VBRATESOVWVCMRCHANGED')); ?>",
1363 "vcmRatesChangedOpen": "<?php echo addslashes(JText::translate('VBRATESOVWVCMRCHANGEDOPEN')); ?>",
1364 "notesForRoom": "<?php echo addslashes(JText::translate('VBONOTESFORROOM')); ?>"
1365 };
1366 var vboFests = <?php echo json_encode($this->festivities); ?>;
1367 var vboRdayNotes = <?php echo json_encode($this->rdaynotes); ?>;
1368 </script>
1369
1370 <script type="text/Javascript">
1371 /**
1372 * Open a booking in a new tab.
1373 */
1374 function vboRovervOpenBooking(bid) {
1375 var open_url = jQuery('.vbo-basenavuri-details').attr('href');
1376 open_url = open_url.replace('%d', bid);
1377 // navigate in a new tab
1378 window.open(open_url, '_blank');
1379 }
1380
1381 /* Labels for months and weekdays */
1382 var vbowdays = <?php echo json_encode($long_days_labels); ?>;
1383 var vbomonths = <?php echo json_encode($long_months_labels); ?>;
1384 /* Dates selection - Start */
1385 var vbolistener = null;
1386 var vbodialog_on = false;
1387 var vbodialogfests_on = false;
1388
1389 jQuery(function() {
1390 // fests
1391 jQuery(document.body).on("click", "td.bluedays", function() {
1392 if (jQuery(this).hasClass('skip-bluedays-click')) {
1393 return;
1394 }
1395 var ymd = jQuery(this).attr('data-ymd');
1396 var daytitle = jQuery(this).attr('data-readymd');
1397 if (jQuery(this).hasClass('vbo-roverv-festcell')) {
1398 // cell has fests
1399 if (!vboFests.hasOwnProperty(ymd)) {
1400 return;
1401 }
1402 vboRenderFests(ymd, daytitle);
1403 } else {
1404 // let the admin create a new fest
1405 // set day title
1406 jQuery('.vbo-info-overlay-content-fests').find('h3').find('span').text(daytitle);
1407 // update ymd key for the selected date, useful for adding new fests
1408 jQuery('.vbo-overlay-fests-addnew').attr('data-ymd', ymd);
1409 // unset content and display modal for just adding a new fest
1410 jQuery('.vbo-overlay-fests-list').html('');
1411 jQuery('.vbo-secondinfo-overlay-block').fadeIn();
1412 vbodialogfests_on = true;
1413 }
1414 if (jQuery(this).hasClass('vbo-roverw-roomdaynote-full')) {
1415 // display the room-day notes
1416 vboRenderRdayNotes(ymd, jQuery(this).attr('data-rid'));
1417 }
1418 });
1419 //
1420 vbolistener = new CalendarListener();
1421 jQuery('.day-block').click(function() {
1422 pickBlock(jQuery(this).attr('id'));
1423 });
1424 jQuery('.day-block').hover(
1425 function() {
1426 if (vbolistener.isFirstPicked() && !vbolistener.isLastPicked()) {
1427 var struct = initBlockStructure(jQuery(this).attr('id'));
1428 var all_blocks = getAllBlocksBetween(vbolistener.first, struct, false);
1429 if (all_blocks !== false) {
1430 jQuery.each(all_blocks, function(k, v) {
1431 if (!v.hasClass('block-picked-middle')) {
1432 v.addClass('block-picked-middle');
1433 }
1434 });
1435 jQuery(this).addClass('block-picked-end');
1436 }
1437 }
1438 },
1439 function() {
1440 if (!vbolistener.isLastPicked()) {
1441 jQuery('.day-block').removeClass('block-picked-middle block-picked-end');
1442 }
1443 }
1444 );
1445 jQuery(document).keydown(function(e) {
1446 if (e.keyCode == 27) {
1447 hideVboDialog();
1448 if (vbodialogfests_on === true) {
1449 hideVboDialogFests();
1450 }
1451 }
1452 });
1453 jQuery(document).mouseup(function(e) {
1454 if (!vbodialog_on && !vbodialogfests_on) {
1455 return false;
1456 }
1457 if (vbodialog_on) {
1458 var vbo_overlay_cont = jQuery(".vbo-info-overlay-content");
1459 if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) {
1460 hideVboDialog();
1461 }
1462 }
1463 if (vbodialogfests_on) {
1464 var vbo_overlay_cont = jQuery(".vbo-info-overlay-content");
1465 if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) {
1466 hideVboDialogFests();
1467 }
1468 }
1469 });
1470 jQuery("body").on("click", ".vbo-roverw-daymod-infospids", function() {
1471 var helem = jQuery(this).next('.vbo-roverw-daymod-infospids-outcont');
1472 if (helem.length && helem.is(":visible")) {
1473 jQuery(this).removeClass("vbo-roverw-daymod-infospids-on");
1474 helem.hide();
1475 } else {
1476 jQuery(".vbo-roverw-daymod-infospids-on").removeClass("vbo-roverw-daymod-infospids-on");
1477 jQuery(".vbo-roverw-daymod-infospids-outcont").hide();
1478 jQuery(this).addClass("vbo-roverw-daymod-infospids-on");
1479 helem.show();
1480 }
1481 });
1482 jQuery('.vbo-roverw-closeopenrp h4').click(function() {
1483 jQuery('.vbo-roverw-closeopenrp-btns').fadeToggle();
1484 });
1485 jQuery(document.body).on('click', '.vbo-ratesoverview-vcmwarn-close', function() {
1486 vcm_exists = 0;
1487 jQuery('.vbo-ratesoverview-right-inner').hide().html('');
1488 });
1489
1490 // show booking details
1491 jQuery('.vbo-roverw-daybusy[data-bids]').click(function() {
1492 var date_bids = jQuery(this).attr('data-bids');
1493 if (!date_bids || !date_bids.length) {
1494 return;
1495 }
1496
1497 // get room name, date and day-bids
1498 var rid = jQuery(this).closest('table').attr('data-idroom');
1499 var room_name = jQuery('.vbo-ratesoverview-roomname[data-idroom="' + rid + '"]').text();
1500 var date_read = jQuery(this).attr('data-vbodateread');
1501 var def_bicon = '<?php VikBookingIcons::e('user', 'vbo-dashboard-guest-activity-avatar-icon'); ?>';
1502 var closure_i = '<?php VikBookingIcons::e('ban', 'vbo-dashboard-guest-activity-avatar-icon'); ?>';
1503
1504 // display modal with booking details
1505 var rday_bookings_modal_body = VBOCore.displayModal({
1506 suffix: 'roverv-rdaybookings',
1507 extra_class: 'vbo-modal-rounded vbo-modal-tall',
1508 title: room_name + ' - ' + date_read,
1509 dismiss_event: 'vbo-dismiss-modal-roverv-rdaybookings',
1510 loading_event: 'vbo-loading-modal-roverv-rdaybookings',
1511 loading_body: '<?php VikBookingIcons::e('circle-notch', 'fa-spin fa-fw'); ?>',
1512 });
1513
1514 // show loading
1515 VBOCore.emitMultitaskEvent('vbo-loading-modal-roverv-rdaybookings');
1516
1517 // make the request to get the bookings information
1518 VBOCore.doAjax(
1519 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=getbookingsinfo'); ?>",
1520 {
1521 status: 'any',
1522 idorders: date_bids,
1523 tmpl: 'component'
1524 },
1525 (res) => {
1526 // stop loading
1527 VBOCore.emitMultitaskEvent('vbo-loading-modal-roverv-rdaybookings');
1528 try {
1529 var obj_res = typeof res === 'string' ? JSON.parse(res) : res;
1530 // build the HTML response
1531 var rday_bookings_html = '';
1532 rday_bookings_html += '<div class="vbo-dashboard-guests-latest">' + "\n";
1533 rday_bookings_html += ' <div class="vbo-dashboard-guest-messages-list">' + "\n";
1534 for (var b in obj_res) {
1535 if (!obj_res.hasOwnProperty(b)) {
1536 continue;
1537 }
1538 // nights and guests
1539 var nights_guests = [
1540 obj_res[b]['roomsnum'] + ' ' + Joomla.JText._((obj_res[b]['roomsnum'] > 1 ? 'VBPVIEWORDERSTHREE' : 'VBEDITORDERTHREE')),
1541 obj_res[b]['days'] + ' ' + Joomla.JText._((obj_res[b]['days'] > 1 ? 'VBDAYS' : 'VBDAY')),
1542 obj_res[b]['tot_adults'] + ' ' + Joomla.JText._((obj_res[b]['tot_adults'] > 1 ? 'VBMAILADULTS' : 'VBMAILADULT'))
1543 ];
1544 if (obj_res[b]['tot_children'] > 0) {
1545 nights_guests.push(obj_res[b]['tot_children'] + ' ' + Joomla.JText._((obj_res[b]['tot_children'] > 1 ? 'VBMAILCHILDREN' : 'VBMAILCHILD')));
1546 }
1547
1548 // build booking structure
1549 rday_bookings_html += ' <div class="vbo-dashboard-guest-activity vbo-w-guestmessages-message" data-idorder="' + obj_res[b]['id'] + '" onclick="vboRovervOpenBooking(\'' + obj_res[b]['id'] + '\');">' + "\n";
1550 rday_bookings_html += ' <div class="vbo-dashboard-guest-activity-avatar">' + "\n";
1551 if (obj_res[b]['avatar_src']) {
1552 rday_bookings_html += '<img class="vbo-dashboard-guest-activity-avatar-profile" src="' + obj_res[b]['avatar_src'] + '" alt="' + obj_res[b]['avatar_alt'] + '" />' + "\n";
1553 } else if (obj_res[b]['closure']) {
1554 rday_bookings_html += closure_i + "\n";
1555 } else {
1556 rday_bookings_html += def_bicon + "\n";
1557 }
1558 rday_bookings_html += ' </div>' + "\n";
1559 rday_bookings_html += ' <div class="vbo-dashboard-guest-activity-content">' + "\n";
1560 rday_bookings_html += ' <div class="vbo-dashboard-guest-activity-content-head">' + "\n";
1561 rday_bookings_html += ' <div class="vbo-dashboard-guest-activity-content-info-details">' + "\n";
1562 rday_bookings_html += ' <h4 class="vbo-w-guestmessages-message-gtitle">' + (!obj_res[b]['closure'] ? obj_res[b]['cinfo'] : obj_res[b]['closure_txt']) + '</h4>' + "\n";
1563 rday_bookings_html += ' <div class="vbo-dashboard-guest-activity-content-info-icon">' + "\n";
1564 rday_bookings_html += ' <span class="label label-info">' + obj_res[b]['id'] + '</span> ' + "\n";
1565 rday_bookings_html += ' <span class="badge badge-' + (obj_res[b]['status'] == 'confirmed' ? 'success' : 'warning') + '">' + obj_res[b]['status_lbl'] + '</span>' + "\n";
1566 rday_bookings_html += ' <span class="vbo-w-guestmessages-message-staydates">' + "\n";
1567 rday_bookings_html += ' <span class="vbo-w-guestmessages-message-staydates-in">' + obj_res[b]['checkin_short'] + '</span>' + "\n";
1568 rday_bookings_html += ' <span class="vbo-w-guestmessages-message-staydates-sep">-</span>' + "\n";
1569 rday_bookings_html += ' <span class="vbo-w-guestmessages-message-staydates-out">' + obj_res[b]['checkout_short'] + '</span>' + "\n";
1570 rday_bookings_html += ' </span>' + "\n";
1571 rday_bookings_html += ' </div>' + "\n";
1572 rday_bookings_html += ' </div>' + "\n";
1573 rday_bookings_html += ' <div class="vbo-dashboard-guest-activity-content-info-date">' + "\n";
1574 rday_bookings_html += ' <span>' + obj_res[b]['book_date'] + '</span>' + "\n";
1575 rday_bookings_html += ' <span>' + obj_res[b]['book_time'] + '</span>' + "\n";
1576 rday_bookings_html += ' </div>' + "\n";
1577 rday_bookings_html += ' </div>' + "\n";
1578 rday_bookings_html += ' <div class="vbo-dashboard-guest-activity-content-info-msg">' + "\n";
1579 rday_bookings_html += ' <div>' + nights_guests.join(', ') + '</div>' + "\n";
1580 if (obj_res[b].hasOwnProperty('sub_units_data')) {
1581 rday_bookings_html += ' <div class="vbo-rdaybooking-subunits">' + "\n";
1582 for (let sub_rname in obj_res[b]['sub_units_data']) {
1583 if (!obj_res[b]['sub_units_data'].hasOwnProperty(sub_rname)) {
1584 continue;
1585 }
1586 rday_bookings_html += '<span class="label label-success">' + (obj_res[b]['roomsnum'] > 1 ? sub_rname + ' ' : '') + '#' + obj_res[b]['sub_units_data'][sub_rname] + '</span>' + "\n";
1587 }
1588 rday_bookings_html += ' </div>' + "\n";
1589 }
1590 rday_bookings_html += ' </div>' + "\n";
1591 rday_bookings_html += ' </div>' + "\n";
1592 rday_bookings_html += ' </div>' + "\n";
1593 }
1594 rday_bookings_html += ' </div>' + "\n";
1595 rday_bookings_html += '</div>' + "\n";
1596
1597 // append the response
1598 rday_bookings_modal_body.html(rday_bookings_html);
1599 } catch(err) {
1600 console.error('could not parse JSON response', err, res);
1601 alert('Could not parse JSON response');
1602 }
1603 },
1604 (err) => {
1605 // stop loading and display alert message
1606 VBOCore.emitMultitaskEvent('vbo-loading-modal-roverv-rdaybookings');
1607 console.error(err);
1608 alert(err.responseText);
1609 }
1610 );
1611 });
1612 });
1613
1614 /**
1615 * Room-day notes
1616 */
1617 function vboRenderRdayNotes(day, rid) {
1618 // compose room-day notes information (no sub-units)
1619 var notes_html = '';
1620 var keyid = day + '_' + rid + '_0';
1621 if (vboRdayNotes.hasOwnProperty(keyid) && vboRdayNotes[keyid]['info'] && vboRdayNotes[keyid]['info'].length) {
1622 for (var i = 0; i < vboRdayNotes[keyid]['info'].length; i++) {
1623 var note_data = vboRdayNotes[keyid]['info'][i];
1624 notes_html += '<div class="vbo-overlay-fest-details vbo-roverv-roomdaynotes-note-details">';
1625 notes_html += ' <div class="vbo-fest-info vbo-roverv-roomdaynotes-note-info">';
1626 notes_html += ' <div class="vbo-fest-name vbo-roverv-roomdaynotes-note-name">' + note_data['name'] + '</div>';
1627 notes_html += ' <div class="vbo-fest-desc vbo-roverv-roomdaynotes-note-desc">' + note_data['descr'].replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br />' + '$2') + '</div>';
1628 notes_html += ' </div>';
1629 notes_html += '</div>';
1630 }
1631 }
1632 // append room-day notes to the list of festivities
1633 if (notes_html.length) {
1634 notes_html = '<h4 class="vbo-roverw-roomdaynotes-title">' + roverw_messages.notesForRoom + '</h4>' + notes_html;
1635 jQuery('.vbo-overlay-fests-list').append(notes_html);
1636 }
1637 }
1638
1639 /**
1640 * Fests
1641 */
1642 function vboRenderFests(day, daytitle) {
1643 // set day title
1644 if (daytitle) {
1645 jQuery('.vbo-info-overlay-content-fests').find('h3').find('span').text(daytitle);
1646 }
1647 // compose fests information
1648 var fests_html = '';
1649 if (vboFests[day] && vboFests[day]['festinfo'] && vboFests[day]['festinfo'].length) {
1650 for (var i = 0; i < vboFests[day]['festinfo'].length; i++) {
1651 var fest = vboFests[day]['festinfo'][i];
1652 fests_html += '<div class="vbo-overlay-fest-details">';
1653 fests_html += ' <div class="vbo-fest-info">';
1654 fests_html += ' <div class="vbo-fest-name">' + fest['trans_name'] + '</div>';
1655 fests_html += ' <div class="vbo-fest-desc">' + fest['descr'].replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br />' + '$2') + '</div>';
1656 fests_html += ' </div>';
1657 fests_html += ' <div class="vbo-fest-cmds">';
1658 fests_html += ' <button type="button" class="btn btn-danger" onclick="vboRemoveFest(\'' + day + '\', \'' + i + '\', \'' + fest['type'] + '\', this);"><?php VikBookingIcons::e('trash-alt'); ?></button>';
1659 fests_html += ' </div>';
1660 fests_html += '</div>';
1661 }
1662 }
1663 // update ymd key for the selected date, useful for adding new fests
1664 jQuery('.vbo-overlay-fests-addnew').attr('data-ymd', day);
1665 // set content and display modal
1666 jQuery('.vbo-overlay-fests-list').html(fests_html);
1667 jQuery('.vbo-secondinfo-overlay-block').fadeIn();
1668 vbodialogfests_on = true;
1669 }
1670 function vboRemoveFest(day, index, fest_type, that) {
1671 if (!confirm('<?php echo addslashes(JText::translate('VBDELCONFIRM')); ?>')) {
1672 return false;
1673 }
1674 var elem = jQuery(that);
1675 // make the AJAX request to the controller to remove this fest from the DB
1676 var jqxhr = jQuery.ajax({
1677 type: "POST",
1678 url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=remove_fest'); ?>",
1679 data: {
1680 tmpl: "component",
1681 dt: day,
1682 ind: index,
1683 type: fest_type
1684 }
1685 }).done(function(res) {
1686 if (res.indexOf('e4j.ok') >= 0) {
1687 // delete fest also from the json-decode array of objects
1688 if (vboFests[day] && vboFests[day]['festinfo']) {
1689 // use splice to remove the desired index from array, or delete would not make the length of the array change
1690 vboFests[day]['festinfo'].splice(index, 1);
1691 // re-build indexes of delete buttons, fundamental for removing the right index at next click
1692 vboRenderFests(day);
1693 if (!vboFests[day]['festinfo'].length) {
1694 // delete also this date object from fests
1695 delete vboFests[day];
1696 // no more fests, remove the class for this date from all cells
1697 jQuery('td.bluedays[data-ymd="'+day+'"]').removeClass('vbo-roverv-festcell');
1698 }
1699 }
1700 elem.closest('.vbo-overlay-fest-details').remove();
1701 } else {
1702 console.log(res);
1703 alert('Invalid response');
1704 }
1705 }).fail(function() {
1706 alert('Request failed');
1707 });
1708 }
1709 function vboAddFest(that) {
1710 var elem = jQuery(that);
1711 var ymd = elem.closest('.vbo-overlay-fests-addnew').attr('data-ymd');
1712 var fest_name = jQuery('#vbo-newfest-name').val();
1713 var fest_descr = jQuery('#vbo-newfest-descr').val();
1714 if (!fest_name.length) {
1715 return false;
1716 }
1717 // make the AJAX request to the controller to add this fest to the DB
1718 var jqxhr = jQuery.ajax({
1719 type: "POST",
1720 url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=add_fest'); ?>",
1721 data: {
1722 tmpl: "component",
1723 dt: ymd,
1724 type: "custom",
1725 name: fest_name,
1726 descr: fest_descr
1727 }
1728 }).done(function(res) {
1729 // parse the JSON response that contains the fest object for the passed date
1730 try {
1731 var stored_fest = JSON.parse(res);
1732 if (!vboFests.hasOwnProperty(stored_fest['dt'])) {
1733 // we need to add the proper class to all cells to show that there is a fest
1734 jQuery('td.bluedays[data-ymd="'+stored_fest['dt']+'"]').addClass('vbo-roverv-festcell');
1735 }
1736 vboFests[stored_fest['dt']] = stored_fest;
1737 hideVboDialogFests();
1738 // reset input fields
1739 jQuery('#vbo-newfest-name').val('');
1740 jQuery('#vbo-newfest-descr').val('');
1741 } catch (e) {
1742 console.log(res);
1743 alert('Invalid response');
1744 return false;
1745 }
1746 }).fail(function() {
1747 alert('Request failed');
1748 });
1749 }
1750 /**
1751 * Fests dialog
1752 */
1753 function hideVboDialogFests() {
1754 if (vbodialogfests_on === true) {
1755 jQuery(".vbo-secondinfo-overlay-block").fadeOut(400, function () {
1756 jQuery(".vbo-info-overlay-content").show();
1757 });
1758 vbodialogfests_on = false;
1759 }
1760 }
1761 //
1762
1763 function checkInvokeVcm() {
1764 if (!vbolistener || !vbolistener.first || !vbolistener.first.rplan) {
1765 return;
1766 }
1767 var rplanid = vbolistener.first.rplan;
1768 var idroom = vbolistener.first.idroom;
1769 var curval = document.getElementById('roverw-newrate-vcm').value;
1770 if (parseInt(curval) < 0) {
1771 return;
1772 }
1773 var buiscuits = document.cookie;
1774 if (!buiscuits.length) {
1775 return;
1776 }
1777 var vcmmatch = "vboVcmRov"+idroom+rplanid+"=";
1778 if (buiscuits.indexOf(vcmmatch) >= 0) {
1779 // last cookie does not terminate with ; so just use 0 to compare
1780 vcmmatch += "0";
1781 if (buiscuits.indexOf(vcmmatch) >= 0) {
1782 jQuery('#roverw-newrate-vcm').prop('checked', false);
1783 } else {
1784 jQuery('#roverw-newrate-vcm').prop('checked', true);
1785 }
1786 }
1787 vboCheckVcmRestrictions();
1788 }
1789
1790 /**
1791 * Restrictions can be updated only if VCM is available and toggled ON, because
1792 * the creation and transmission is made through the Connector Class of VCM.
1793 *
1794 * @since 1.11
1795 */
1796 function vboCheckVcmRestrictions() {
1797 if (!jQuery('#roverw-newrate-vcm').prop('disabled') && jQuery('#roverw-newrate-vcm').prop('checked')) {
1798 jQuery('#roverw-newrestr').val('');
1799 jQuery('.vbo-roverw-newrestr-wrap').show();
1800 } else {
1801 jQuery('.vbo-roverw-newrestr-wrap').hide();
1802 }
1803 }
1804
1805 function showVboDialog() {
1806 var format = new Date().format;
1807 format = format.replace(new RegExp("/", 'g'), new Date().datesep);
1808 jQuery("#rovervw-roomname").html(vbolistener.first.roomName);
1809 jQuery("#rovervw-rplan").html(vbolistener.first.rplanName);
1810 jQuery("#rovervw-closeopen-rplan").html('"'+vbolistener.first.rplanName+'"');
1811 jQuery("#rovervw-fromdate").html(vbolistener.first.toDate(format));
1812 jQuery("#rovervw-todate").html(vbolistener.last.toDate(format));
1813 jQuery(".vbo-roverw-alldays-inner").html("");
1814 var all_blocks = getAllBlocksBetween(vbolistener.first, vbolistener.last, true);
1815 if (all_blocks !== false) {
1816 var newdayscont = '';
1817 var highestrate = vbolistener.first.defRate;
1818 var allblocksclosed = true;
1819 jQuery.each(all_blocks, function(k, v) {
1820 if (!v.hasClass('vbo-roverw-rplan-off')) {
1821 allblocksclosed = false;
1822 }
1823 var spids = jQuery(v).attr("data-vbospids").split("-");
1824 var spids_det = '';
1825 if (jQuery(v).attr("data-vbospids").length > 0 && spids.length > 0) {
1826 spids_det += "<div class=\"vbo-roverw-daymod-infospids\"><span><i class=\"<?php echo VikBookingIcons::i('info-circle'); ?>\"></i></span></div>";
1827 spids_det += "<div class=\"vbo-roverw-daymod-infospids-outcont\">";
1828 spids_det += "<div class=\"vbo-roverw-daymod-infospids-incont\"><ul>";
1829 for (var x = 0; x < spids.length; x++) {
1830 spids_det += "<li><a target=\"_blank\" href=\"index.php?option=com_vikbooking&task=editseason&cid[]="+spids[x]+"\">"+roverw_messages.openSpLink.replace("%d", spids[x])+"</a></li>";
1831 }
1832 spids_det += "</ul></div></div>";
1833 }
1834 var dayrate = parseFloat(v.find('.vbo-rplan-price').text());
1835 if (!isNaN(dayrate) && dayrate > highestrate) {
1836 highestrate = dayrate;
1837 }
1838 newdayscont += "<div class=\"vbo-roverw-daymod\"><div class=\"vbo-roverw-daymod-inner\"><div class=\"vbo-roverw-daymod-innercell\"><span class=\"vbo-roverw-daydate\">"+jQuery(v).attr("data-vbodateread")+"</span><span class=\"vbo-roverw-dayprice\">"+v.html()+"</span>"+spids_det+"</div></div></div>";
1839 });
1840 jQuery(".vbo-roverw-alldays-inner").html(newdayscont);
1841 jQuery("#roverw-newrate").attr("placeholder", vbolistener.first.defRate).val(highestrate);
1842 // if all selected blocks have a closed rate plan, show it in red in the name of the rate plan because this will be triggered to VCM if "Apply" is clicked
1843 if (allblocksclosed) {
1844 jQuery("#rovervw-rplan").html('<span style="color: #f00"><i class="<?php echo VikBookingIcons::i('ban'); ?>"></i> '+vbolistener.first.rplanName+'</span>');
1845 }
1846 }
1847 checkInvokeVcm();
1848
1849 jQuery(".vbo-info-overlay-block").fadeIn();
1850 vbodialog_on = true;
1851 }
1852
1853 function showVboDialogPeriod() {
1854 var format = new Date().format;
1855 format = format.replace(new RegExp("/", 'g'), new Date().datesep);
1856 jQuery('.vbo-ratesoverview-period-box-cals').fadeOut();
1857 jQuery("#rovervw-roomname").html(vbolistener.first.roomName);
1858 jQuery("#rovervw-rplan").html(vbolistener.first.rplanName);
1859 jQuery("#rovervw-closeopen-rplan").html('"'+vbolistener.first.rplanName+'"');
1860 jQuery("#rovervw-fromdate").html(vbolistener.first.toDate(format));
1861 jQuery("#rovervw-todate").html(vbolistener.last.toDate(format));
1862 jQuery(".vbo-roverw-alldays-inner").html("");
1863 // reset default new price and placeholder
1864 jQuery("#roverw-newrate").attr("placeholder", "").val("");
1865 // check if all selected blocks are closed
1866 var all_blocks = getAllBlocksBetween(vbolistener.first, vbolistener.last, true);
1867 if (all_blocks !== false) {
1868 var allblocksclosed = true;
1869 jQuery.each(all_blocks, function(k, v) {
1870 if (!v.hasClass('vbo-roverw-rplan-off')) {
1871 allblocksclosed = false;
1872 return false;
1873 }
1874 });
1875 if (allblocksclosed) {
1876 jQuery("#rovervw-rplan").html('<span style="color: #f00"><i class="<?php echo VikBookingIcons::i('ban'); ?>"></i> '+vbolistener.first.rplanName+'</span>');
1877 }
1878 }
1879 //
1880 checkInvokeVcm();
1881
1882 jQuery(".vbo-info-overlay-block").fadeIn();
1883 vbodialog_on = true;
1884 }
1885
1886 function hideVboDialog() {
1887 vbolistener.clear();
1888 jQuery('.day-block').removeClass('block-picked-start block-picked-middle block-picked-end');
1889 if (vbodialog_on === true) {
1890 jQuery(".vbo-info-overlay-block").fadeOut(400, function () {
1891 jQuery(".vbo-info-overlay-content").show();
1892 });
1893 //reset period selection
1894 jQuery('.vbo-ratesoverview-period-from').find('span').text('');
1895 jQuery('.vbo-ratesoverview-period-from-icon').show();
1896 jQuery('.vbo-ratesoverview-period-to').find('span').text('');
1897 jQuery('.vbo-ratesoverview-period-to-icon').show();
1898 //
1899 vbodialog_on = false;
1900 }
1901 }
1902
1903 function vboCheckVcmRatesChanges() {
1904 if (vcm_exists < 1) {
1905 return false;
1906 }
1907 var jqxhr = jQuery.ajax({
1908 type: "POST",
1909 url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=checkvcmrateschanges'); ?>",
1910 data: {
1911 tmpl: "component",
1912 e4j_debug: debug_mode
1913 }
1914 }).done(function(res) {
1915 if (res.indexOf('e4j.error') >= 0 ) {
1916 console.log(res);
1917 alert(res.replace("e4j.error.", ""));
1918 jQuery('.vbo-ratesoverview-right-inner').hide();
1919 } else {
1920 //display the VCM link for updating the rates on the OTAs
1921 var obj_res = JSON.parse(res);
1922 var esitcont = "";
1923 if (obj_res.changesCount > 0 && obj_res.hasOwnProperty('changesData') && obj_res.changesData.hasOwnProperty('dfrom')) {
1924 esitcont += "<span class=\"vbo-ratesoverview-vcmwarn-close\"> <i class=\"vboicn-cancel-circle\"></i></span>";
1925 esitcont += "<span class=\"vbo-ratesoverview-vcmwarn-count\"><i class=\"vboicn-notification\"></i> <span>"+roverw_messages.vcmRatesChanged.replace("%d", obj_res.changesCount)+"</span></span>";
1926 esitcont += "<span class=\"vbo-ratesoverview-vcmwarn-open\"><a href=\"index.php?option=com_vikchannelmanager&amp;task=ratespush&amp;vbosess=1\" class=\"btn btn-primary\">"+roverw_messages.vcmRatesChangedOpen+"</a></span>";
1927 jQuery('.vbo-ratesoverview-right-inner').html(esitcont).fadeIn();
1928 } else {
1929 jQuery('.vbo-ratesoverview-right-inner').hide().html('');
1930 }
1931 }
1932 }).fail(function() {
1933 console.log("vboCheckVcmRatesChanges Request Failed");
1934 jQuery('.vbo-ratesoverview-right-inner').hide();
1935 });
1936 }
1937
1938 /* Delay and launch the check VCM rates modification function, when the page loads */
1939 setTimeout(function() {
1940 vboCheckVcmRatesChanges();
1941 }, 1000);
1942 /* - */
1943
1944 function renderChannelManagerResult(obj) {
1945 console.log(obj);
1946 //compose modal body
1947 var htmlres = '<div class="vbo-vcm-rates-res-container">';
1948 if (obj.hasOwnProperty('channels_success')) {
1949 htmlres += '<div class="vbo-vcm-rates-res-success">';
1950 for (var ch_id in obj['channels_success']) {
1951 htmlres += '<div class="vbo-vcm-rates-res-channel">';
1952 htmlres += ' <div class="vbo-vcm-rates-res-channel-esit">';
1953 htmlres += ' <i class="<?php echo VikBookingIcons::i('check'); ?>"></i>';
1954 htmlres += ' </div>';
1955 htmlres += ' <div class="vbo-vcm-rates-res-channel-logo">';
1956 if (obj['channels_updated'].hasOwnProperty(ch_id) && obj['channels_updated'][ch_id]['logo'].length) {
1957 htmlres += '<img src="'+obj['channels_updated'][ch_id]['logo']+'" />';
1958 } else {
1959 htmlres += '<span>'+obj['channels_success'][ch_id]+'</span>';
1960 }
1961 htmlres += ' </div>';
1962 htmlres += '</div>';
1963 }
1964 if (obj.hasOwnProperty('channels_bkdown')) {
1965 htmlres += '<div class="vbo-vcm-rates-res-bkdown">';
1966 htmlres += ' <div><pre>'+obj['channels_bkdown']+'</pre></div>';
1967 htmlres += '</div>';
1968 }
1969 htmlres += '</div>';
1970 }
1971 if (obj.hasOwnProperty('channels_warnings')) {
1972 htmlres += '<div class="vbo-vcm-rates-res-warning">';
1973 for (var ch_id in obj['channels_warnings']) {
1974 htmlres += '<div class="vbo-vcm-rates-res-channel">';
1975 htmlres += ' <div class="vbo-vcm-rates-res-channel-esit">';
1976 htmlres += ' <i class="<?php echo VikBookingIcons::i('exclamation-triangle'); ?>"></i>';
1977 htmlres += ' </div>';
1978 htmlres += ' <div class="vbo-vcm-rates-res-channel-logo">';
1979 if (obj['channels_updated'].hasOwnProperty(ch_id) && obj['channels_updated'][ch_id]['logo'].length) {
1980 htmlres += '<img src="'+obj['channels_updated'][ch_id]['logo']+'" />';
1981 } else if (obj['channels_updated'].hasOwnProperty(ch_id)) {
1982 htmlres += '<span>'+obj['channels_updated'][ch_id]['name']+'</span>';
1983 }
1984 htmlres += ' </div>';
1985 htmlres += ' <div class="vbo-vcm-rates-res-channel-det">';
1986 htmlres += ' <pre>'+obj['channels_warnings'][ch_id]+'</pre>';
1987 htmlres += ' </div>';
1988 htmlres += '</div>';
1989 }
1990 htmlres += '</div>';
1991 }
1992 if (obj.hasOwnProperty('channels_errors')) {
1993 htmlres += '<div class="vbo-vcm-rates-res-error">';
1994 for (var ch_id in obj['channels_errors']) {
1995 htmlres += '<div class="vbo-vcm-rates-res-channel">';
1996 htmlres += ' <div class="vbo-vcm-rates-res-channel-esit">';
1997 htmlres += ' <i class="<?php echo VikBookingIcons::i('times'); ?>"></i>';
1998 htmlres += ' </div>';
1999 htmlres += ' <div class="vbo-vcm-rates-res-channel-logo">';
2000 if (obj['channels_updated'].hasOwnProperty(ch_id) && obj['channels_updated'][ch_id]['logo'].length) {
2001 htmlres += ' <img src="'+obj['channels_updated'][ch_id]['logo']+'" />';
2002 } else if (obj['channels_updated'].hasOwnProperty(ch_id)) {
2003 htmlres += ' <span>'+obj['channels_updated'][ch_id]['name']+'</span>';
2004 }
2005 htmlres += ' </div>';
2006 htmlres += ' <div class="vbo-vcm-rates-res-channel-det">';
2007 htmlres += ' <pre>'+obj['channels_errors'][ch_id]+'</pre>';
2008 htmlres += ' </div>';
2009 htmlres += '</div>';
2010 }
2011 htmlres += '</div>';
2012 }
2013 htmlres += '</div>';
2014 //update modal body
2015 if (!jQuery('#jmodal-vbo-vcm-rates-res').find('.modal-body').length) {
2016 /**
2017 * The class modal-body is appended (in WP) by the function vboOpenJModal,
2018 * so it may not be available at this point of the code.
2019 */
2020 jQuery('#jmodal-vbo-vcm-rates-res').find('.modal-body-wrapper').html('<div class="modal-body"></div>');
2021 }
2022 jQuery('#jmodal-vbo-vcm-rates-res').find('.modal-body').html(htmlres);
2023 //display modal with the results
2024 vboOpenJModal('vbo-vcm-rates-res');
2025 }
2026
2027 function setNewRates() {
2028 var all_blocks = getAllBlocksBetween(vbolistener.first, vbolistener.last, true);
2029 var toval = jQuery("#roverw-newrate").val();
2030 var tovalint = parseFloat(toval);
2031 var invoke_vcm = jQuery("#roverw-newrate-vcm").is(":checked") ? 1 : 0;
2032 var setminlos = jQuery("#roverw-newrestr").val();
2033 var closerplan = 0;
2034 if (all_blocks !== false && toval.length > 0 && !isNaN(tovalint) && tovalint > 0.00) {
2035 // set cookie to remember the action to invoke VCM for this combination of room-rateplan
2036 var nd = new Date();
2037 nd.setTime(nd.getTime() + (365*24*60*60*1000));
2038 document.cookie = "vboVcmRov"+vbolistener.first.idroom+vbolistener.first.rplan+"="+invoke_vcm+"; expires=" + nd.toUTCString() + "; path=/; SameSite=Lax";
2039 // check whether all blocks have closed the rate plan
2040 var allblocksclosed = true;
2041 jQuery.each(all_blocks, function(k, v) {
2042 if (!v.hasClass('vbo-roverw-rplan-off')) {
2043 allblocksclosed = false;
2044 // break
2045 return false;
2046 }
2047 });
2048 closerplan = allblocksclosed ? 1 : closerplan;
2049 //
2050 jQuery(".vbo-info-overlay-content").hide();
2051 jQuery(".vbo-info-overlay-loading").prepend('<i class="<?php echo VikBookingIcons::i('refresh', 'fa-spin fa-3x fa-fw'); ?>"></i>').fadeIn();
2052 var jqxhr = jQuery.ajax({
2053 type: "POST",
2054 url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=pricing.setnewrates'); ?>",
2055 data: {
2056 tmpl: "component",
2057 e4j_debug: debug_mode,
2058 id_room: vbolistener.first.idroom,
2059 id_price: vbolistener.first.rplan,
2060 rate: toval,
2061 vcm: invoke_vcm,
2062 minlos: setminlos,
2063 fromdate: vbolistener.first.toDate("yy-mm-dd"),
2064 todate: vbolistener.last.toDate("yy-mm-dd"),
2065 rateclosed: closerplan
2066 }
2067 }).done(function(res) {
2068 if (res.indexOf('e4j.error') >= 0) {
2069 console.log(res);
2070 alert(res.replace("e4j.error.", ""));
2071 jQuery(".vbo-info-overlay-content").show();
2072 jQuery(".vbo-info-overlay-loading").hide().find("i").remove();
2073 } else {
2074 //display new rates in all_blocks IDs
2075 var restr_set = false;
2076 var obj_res = JSON.parse(res);
2077 jQuery.each(obj_res, function(k, v) {
2078 if (k == 'vcm') {
2079 return true;
2080 }
2081 var elem = jQuery("#cell-"+k+"-"+vbolistener.first.idroom);
2082 if (elem.length) {
2083 elem.find(".vbo-rplan-price").html(v.cost);
2084 var spids = '';
2085 if (v.hasOwnProperty('spids')) {
2086 jQuery.each(v.spids, function(spk, spv) {
2087 spids += spv+'-';
2088 });
2089 //right trim dash
2090 spids = spids.replace(/-+$/, '');
2091 }
2092 elem.attr('data-vbospids', spids);
2093 // check if restrictions were set
2094 if (v.hasOwnProperty('newminlos')) {
2095 // always convert v.newminlos to a string to avoid errors with indexOf
2096 var newminlos = v.newminlos+'';
2097 if (newminlos.indexOf('e4j.error') >= 0) {
2098 // an error occurred
2099 alert(newminlos.replace("e4j.error.", ""));
2100 } else {
2101 // get cell identifier part
2102 restr_set = true;
2103 var cell_parts = k.split('-');
2104 var restr_elem = jQuery('#cell-'+cell_parts[0]+'-'+cell_parts[1]+'-'+cell_parts[2]+'-'+vbolistener.first.idroom+'-restr');
2105 if (restr_elem.length) {
2106 var restr_cont = restr_elem.find('.vbo-roverw-curminlos');
2107 restr_cont.html(newminlos);
2108 if (parseInt(newminlos) > 1) {
2109 restr_cont.addClass('vbo-roverw-curminlos-active');
2110 } else {
2111 restr_cont.removeClass('vbo-roverw-curminlos-active');
2112 }
2113 }
2114 // attempt to remove an eventual orphan list
2115 var orphan_elem = jQuery('.vbo-ratesoverview-orphan-dt[data-dt="'+cell_parts[0]+'-'+cell_parts[1]+'-'+cell_parts[2]+'-'+vbolistener.first.idroom+'"]');
2116 if (orphan_elem.length) {
2117 if (orphan_elem.length < 2) {
2118 jQuery('#vbo-ratesoverview-orphans-wrapper-'+vbolistener.first.idroom).fadeOut(400, function() {
2119 orphan_elem.remove();
2120 });
2121 } else {
2122 orphan_elem.remove();
2123 }
2124 }
2125 }
2126 }
2127 //
2128 }
2129 });
2130 jQuery(".vbo-info-overlay-loading").hide().find("i").remove();
2131 hideVboDialog();
2132 if (obj_res.hasOwnProperty('vcm')) {
2133 renderChannelManagerResult(obj_res['vcm']);
2134 } else {
2135 setTimeout(function() {
2136 vboCheckVcmRatesChanges();
2137 }, 500);
2138 }
2139 if (restr_set) {
2140 // re-calculate orphans after setting the restriction
2141 setTimeout(function() {
2142 vboCheckOrphans();
2143 }, 200);
2144 }
2145 }
2146 }).fail(function() {
2147 alert("Request Failed");
2148 jQuery(".vbo-info-overlay-content").show();
2149 jQuery(".vbo-info-overlay-loading").hide().find("i").remove();
2150 });
2151 } else {
2152 alert(roverw_messages.setNewRatesMissing);
2153 return false;
2154 }
2155 }
2156
2157 function modRoomRatePlan(mode) {
2158 var all_blocks = getAllBlocksBetween(vbolistener.first, vbolistener.last, true);
2159 if (all_blocks !== false && mode.length > 0) {
2160 jQuery(".vbo-info-overlay-content").hide();
2161 jQuery(".vbo-info-overlay-loading").prepend('<i class="<?php echo VikBookingIcons::i('refresh', 'fa-spin fa-3x fa-fw'); ?>"></i>').fadeIn();
2162 var jqxhr = jQuery.ajax({
2163 type: "POST",
2164 url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=modroomrateplans'); ?>",
2165 data: {
2166 tmpl: "component",
2167 e4j_debug: debug_mode,
2168 id_room: vbolistener.first.idroom,
2169 id_price: vbolistener.first.rplan,
2170 type: mode,
2171 fromdate: vbolistener.first.toDate("yy-mm-dd"),
2172 todate: vbolistener.last.toDate("yy-mm-dd")
2173 }
2174 }).done(function(res) {
2175 if (res.indexOf('e4j.error') >= 0 ) {
2176 console.log(res);
2177 alert(res.replace("e4j.error.", ""));
2178 jQuery(".vbo-info-overlay-content").show();
2179 jQuery(".vbo-info-overlay-loading").hide().find("i").remove();
2180 } else {
2181 //apply new classes in all_blocks IDs
2182 var obj_res = JSON.parse(res);
2183 jQuery.each(obj_res, function(k, v) {
2184 var elem = jQuery("#cell-"+k+"-"+vbolistener.first.idroom);
2185 if (elem.length) {
2186 elem.removeClass(v.oldcls).addClass(v.newcls);
2187 }
2188 });
2189 jQuery(".vbo-info-overlay-loading").hide().find("i").remove();
2190 hideVboDialog();
2191 setTimeout(function() {
2192 vboCheckVcmRatesChanges();
2193 }, 500);
2194 }
2195 }).fail(function() {
2196 alert("Request Failed");
2197 jQuery(".vbo-info-overlay-content").show();
2198 jQuery(".vbo-info-overlay-loading").hide().find("i").remove();
2199 });
2200 } else {
2201 alert(roverw_messages.modRplansMissing);
2202 return false;
2203 }
2204 }
2205
2206 function vboUpdateRplan(that) {
2207 if (vbolistener === null || vbolistener.first === null) {
2208 return true;
2209 }
2210 vbolistener.first.rplan = jQuery(that).val();
2211 vbolistener.first.rplanName = jQuery(that).find('option:selected').text();
2212 vbolistener.first.defRate = jQuery(that).find('option:selected').attr('data-defrate');
2213 }
2214
2215 function pickBlock(id) {
2216 var struct = initBlockStructure(id);
2217
2218 if (!vbolistener.pickFirst(struct)) {
2219 // first already picked
2220 if ((vbolistener.first.isBeforeThan(struct) || vbolistener.first.isSameDay(struct)) && vbolistener.first.isSameRplan(struct) && vbolistener.first.isSameRoom(struct)) {
2221 // last > first : pick last
2222 if (vbolistener.pickLast(struct)) {
2223 var all_blocks = getAllBlocksBetween(vbolistener.first, vbolistener.last, false);
2224 if (all_blocks !== false) {
2225 jQuery.each(all_blocks, function(k, v){
2226 if ( !v.hasClass('block-picked-middle') ) {
2227 v.addClass('block-picked-middle');
2228 }
2229 });
2230 jQuery('#'+vbolistener.last.id).addClass('block-picked-end');
2231 showVboDialog();
2232 }
2233 }
2234 } else {
2235 // last < first : clear selection
2236 vbolistener.clear();
2237 jQuery('.day-block').removeClass('block-picked-start block-picked-middle block-picked-end');
2238 }
2239 } else {
2240 // first picked
2241 jQuery('#'+vbolistener.first.id).addClass('block-picked-start');
2242 }
2243 }
2244
2245 function getAllBlocksBetween(start, end, outers_included) {
2246 if (!start.isSameRplan(end) || !start.isSameRoom(end)) {
2247 return false;
2248 }
2249
2250 if (start.isAfterThan(end)) {
2251 return false;
2252 }
2253
2254 var queue = new Array();
2255
2256 if (outers_included) {
2257 queue.push(jQuery('#'+start.id));
2258 }
2259
2260 if (start.isSameDay(end)) {
2261 return queue;
2262 }
2263
2264 var node = jQuery('#'+start.id).next();
2265 var end_id = jQuery('#'+end.id).attr('id');
2266 while (node.length > 0 && node.attr('id') != end_id) {
2267 queue.push(node);
2268 node = node.next();
2269 }
2270
2271 if (outers_included) {
2272 queue.push(jQuery('#'+end.id));
2273 }
2274
2275 return queue;
2276 }
2277
2278 function getPeriodStructure(data) {
2279 return {
2280 "day": parseInt(data[0]),
2281 "month": parseInt(data[1]),
2282 "year": parseInt(data[2]),
2283 "rplan": data[3],
2284 "idroom": data[6],
2285 "roomName": data[7],
2286 "rplanName": data[4],
2287 "defRate": data[5],
2288 "id": "cell-"+parseInt(data[0])+"-"+parseInt(data[1])+"-"+parseInt(data[2])+"-"+data[3]+"-"+data[6],
2289 "isSameDay": function(block) {
2290 return (this.month == block.month && this.day == block.day && this.year == block.year);
2291 },
2292 "isBeforeThan": function(block) {
2293 return (
2294 (this.year < block.year) ||
2295 (this.year == block.year && this.month < block.month) ||
2296 (this.year == block.year && this.month == block.month && this.day < block.day)
2297 );
2298 },
2299 "isAfterThan": function(block) {
2300 return (
2301 (this.year > block.year) ||
2302 (this.year == block.year && this.month > block.month) ||
2303 (this.year == block.year && this.month == block.month && this.day > block.day)
2304 );
2305 },
2306 "isSameRplan": function(block) {
2307 return (this.rplan == block.rplan);
2308 },
2309 "isSameRoom": function(block) {
2310 return (this.idroom == block.idroom);
2311 },
2312 "toDate": function(format) {
2313 return format.replace(
2314 'dd', (this.day < 10 ? '0' : '' ) + this.day
2315 ).replace(
2316 'mm', (this.month < 10 ? '0' : '') + this.month
2317 ).replace(
2318 'yy', this.year
2319 );
2320 }
2321 };
2322 }
2323
2324 function initBlockStructure(id) {
2325 var s = id.split("-");
2326 if (s.length != 6) {
2327 return {};
2328 }
2329 var elem = jQuery("#"+id);
2330 return {
2331 "day": parseInt(s[1]),
2332 "month": parseInt(s[2]),
2333 "year": parseInt(s[3]),
2334 "rplan": s[4],
2335 "idroom": s[5],
2336 "roomName": elem.parent("tr").find("td").first().attr("data-roomname"),
2337 "rplanName": elem.parent("tr").find("td").first().find(".vbo-rplan-name").text(),
2338 "defRate": elem.parent("tr").find("td").first().attr("data-defrate"),
2339 "id": id,
2340 "isSameDay": function(block) {
2341 return (this.month == block.month && this.day == block.day && this.year == block.year);
2342 },
2343 "isBeforeThan": function(block) {
2344 return (
2345 (this.year < block.year) ||
2346 (this.year == block.year && this.month < block.month) ||
2347 (this.year == block.year && this.month == block.month && this.day < block.day)
2348 );
2349 },
2350 "isAfterThan": function(block) {
2351 return (
2352 (this.year > block.year) ||
2353 (this.year == block.year && this.month > block.month) ||
2354 (this.year == block.year && this.month == block.month && this.day > block.day)
2355 );
2356 },
2357 "isSameRplan": function(block) {
2358 return (this.rplan == block.rplan);
2359 },
2360 "isSameRoom": function(block) {
2361 return (this.idroom == block.idroom);
2362 },
2363 "toDate": function(format) {
2364 return format.replace(
2365 'dd', (this.day < 10 ? '0' : '') + this.day
2366 ).replace(
2367 'mm', (this.month < 10 ? '0' : '') + this.month
2368 ).replace(
2369 'yy', this.year
2370 );
2371 }
2372 };
2373 }
2374
2375 function CalendarListener() {
2376 this.first = null;
2377 this.last = null;
2378 }
2379
2380 CalendarListener.prototype.pickFirst = function(struct) {
2381 if (!this.isFirstPicked()) {
2382 this.first = struct;
2383 return true;
2384 }
2385 return false;
2386 }
2387
2388 CalendarListener.prototype.pickLast = function(struct) {
2389 if (!this.isLastPicked() && this.isFirstPicked()) {
2390 this.last = struct;
2391 return true;
2392 }
2393 return false;
2394 }
2395
2396 CalendarListener.prototype.clear = function() {
2397 this.first = null;
2398 this.last = null;
2399 }
2400
2401 CalendarListener.prototype.isFirstPicked = function() {
2402 return this.first != null;
2403 }
2404
2405 CalendarListener.prototype.isLastPicked = function() {
2406 return this.last != null;
2407 }
2408
2409 /* Dates selection - End */
2410
2411 function vboToggleOBPRows() {
2412 jQuery('tr.vbo-roverviewtablerow-occupancy').toggle();
2413 var newcookieval = 0;
2414 if (jQuery('tr.vbo-roverviewtablerow-occupancy').length && jQuery('tr.vbo-roverviewtablerow-occupancy').is(':visible')) {
2415 newcookieval = 1;
2416 }
2417 var nd = new Date();
2418 nd.setTime(nd.getTime() + (365*24*60*60*1000));
2419 document.cookie = "vboRovwObp=" + newcookieval + "; expires=" + nd.toUTCString() + "; path=/; SameSite=Lax";
2420 }
2421
2422 function vboToggleCollapse() {
2423 var expand = jQuery('input[name="vbo_collapse"]').is(':checked');
2424 var collapse = expand ? 0 : 1;
2425 if (expand) {
2426 jQuery('.vbo-ratesoverview-roomsel-entry-calc-inner, .vbo-roverv-forecast-inner').show();
2427 jQuery('.vbo-ratesoverview-top-container').removeClass('collapsed');
2428 } else {
2429 jQuery('.vbo-ratesoverview-roomsel-entry-calc-inner, .vbo-roverv-forecast-inner').hide();
2430 jQuery('.vbo-ratesoverview-top-container').addClass('collapsed');
2431 }
2432 var nd = new Date();
2433 nd.setTime(nd.getTime() + (365*24*60*60*1000));
2434 document.cookie = "vboRovwColl=" + collapse + "; expires=" + nd.toUTCString() + "; path=/; SameSite=Lax";
2435 }
2436
2437 function vboCheckCollapse() {
2438 if (jQuery('.vbo-ratesoverview-roomsel-entry-calc-inner').is(':visible') && jQuery('.vbo-roverv-forecast-inner').is(':visible')) {
2439 // all elements are visible, expanded
2440 return;
2441 }
2442 jQuery('input[name="vbo_collapse"]').trigger('click');
2443 }
2444
2445 function vboSelectAllRooms(btn) {
2446 var sel_elem = jQuery('#roomsel');
2447 sel_elem.find('option').prop('selected', true);
2448 sel_elem.trigger('change');
2449 // hide button
2450 jQuery(btn).parent().remove();
2451 // auto-submit form
2452 document.vboratesovwform.submit();
2453 }
2454
2455 var timeline_height_set = false;
2456
2457 jQuery(function() {
2458 // register to the event emitted when a new booking is created through an admin widget
2459 document.addEventListener('vbo_new_booking_created', (e) => {
2460 if (!e || !e.detail || !e.detail.hasOwnProperty('bid') || !e.detail['bid']) {
2461 // do nothing
2462 return;
2463 }
2464 // reload the page to display the new booking just created
2465 location.reload();
2466 });
2467
2468 // toggle OBP rows
2469 if (jQuery('.vbo-ratesoverview-obp-toggle').length && jQuery('tr.vbo-roverviewtablerow-occupancy').length) {
2470 jQuery('.vbo-ratesoverview-obp-toggle').show();
2471 var initial = jQuery('.vbo-ratesoverview-obp-toggle').attr('data-obpstartstatus');
2472 if (initial == '0') {
2473 jQuery('tr.vbo-roverviewtablerow-occupancy').hide();
2474 }
2475 }
2476 //
2477 jQuery(".vbo-ratesoverview-tab-los").click(function() {
2478 var nd = new Date();
2479 nd.setTime(nd.getTime() + (365*24*60*60*1000));
2480 document.cookie = "vboRovwRab=los; expires=" + nd.toUTCString() + "; path=/; SameSite=Lax";
2481 jQuery(this).removeClass("vbo-ratesoverview-tab-unactive").addClass("vbo-ratesoverview-tab-active");
2482 jQuery(".vbo-ratesoverview-tab-cal").removeClass("vbo-ratesoverview-tab-active").addClass("vbo-ratesoverview-tab-unactive");
2483 jQuery(".vbo-ratesoverview-roomsel-entry-los").show();
2484 jQuery(".vbo-ratesoverview-roomsel-entry-forecast").hide();
2485 jQuery(".vbo-ratesoverview-caltab-cont").hide();
2486 jQuery(".vbo-ratesoverview-lostab-cont").fadeIn();
2487 if (!timeline_height_set) {
2488 jQuery('.vbo-timeline-container').css('min-height', (jQuery('.vbo-timeline-container').outerHeight() + 20));
2489 timeline_height_set = true;
2490 }
2491 });
2492 jQuery(".vbo-ratesoverview-tab-cal").click(function() {
2493 var nd = new Date();
2494 nd.setTime(nd.getTime() + (365*24*60*60*1000));
2495 document.cookie = "vboRovwRab=cal; expires=" + nd.toUTCString() + "; path=/; SameSite=Lax";
2496 jQuery(this).removeClass("vbo-ratesoverview-tab-unactive").addClass("vbo-ratesoverview-tab-active");
2497 jQuery(".vbo-ratesoverview-tab-los").removeClass("vbo-ratesoverview-tab-active").addClass("vbo-ratesoverview-tab-unactive");
2498 jQuery(".vbo-ratesoverview-roomsel-entry-los").hide();
2499 jQuery(".vbo-ratesoverview-roomsel-entry-forecast").show();
2500 jQuery(".vbo-ratesoverview-lostab-cont").hide();
2501 jQuery(".vbo-ratesoverview-caltab-cont").fadeIn();
2502 });
2503 if (window.location.hash == '#tabcal') {
2504 jQuery(".vbo-ratesoverview-tab-cal").trigger("click");
2505 }
2506 jQuery("body").on("click", ".vbo-ratesoverview-numnight", function() {
2507 var inpnight = jQuery(this).attr('id');
2508 if (jQuery('.vbo-ratesoverview-numnight').length > 1) {
2509 jQuery('#inp'+inpnight).remove();
2510 jQuery(this).remove();
2511 }
2512 });
2513 jQuery("body").on("dblclick", ".vbo-calcrates-rateblock", function() {
2514 if (jQuery(this).parent('.vbo-ratesoverview-calculation-response-room').find('.vbo-calcrates-rateblock').length < 2) {
2515 // remove the whole container as there is just one rate plan
2516 jQuery(this).parent('.vbo-ratesoverview-calculation-response-room').remove();
2517 } else {
2518 // remove only this rate plan
2519 jQuery(this).remove();
2520 }
2521 });
2522 jQuery('#vbo-addnumnight-act').click(function() {
2523 var setnights = jQuery('#vbo-addnumnight').val();
2524 if (parseInt(setnights) > 0) {
2525 var los_exists = false;
2526 jQuery('.vbo-ratesoverview-numnight').each(function() {
2527 if (parseInt(jQuery(this).text()) == parseInt(setnights)) {
2528 los_exists = true;
2529 }
2530 });
2531 if (!los_exists) {
2532 jQuery('.vbo-ratesoverview-numnight').last().after("<span class=\"vbo-ratesoverview-numnight\" id=\"numnights"+setnights+"\">"+setnights+"</span><input type=\"hidden\" name=\"nights_cal[]\" id=\"inpnumnights"+setnights+"\" value=\""+setnights+"\" />");
2533 } else {
2534 jQuery('#vbo-addnumnight').val((parseInt(setnights) + 1));
2535 }
2536 }
2537 });
2538 jQuery('#vbo-ratesoverview-calculate').click(function() {
2539 jQuery(this).text('<?php echo addslashes(JText::translate('VBRATESOVWRATESCALCULATORCALCING')); ?>').prop('disabled', true);
2540 var checkindate = jQuery("#checkindate").val();
2541 if (!(checkindate.length > 0)) {
2542 checkindate = '<?php echo date('Y-m-d') ?>';
2543 jQuery("#checkindate").val(checkindate);
2544 }
2545 var nights = jQuery("#vbo-numnights").val();
2546 var adults = jQuery("#vbo-numadults").val();
2547 var children = jQuery("#vbo-numchildren").val();
2548 var idroom = jQuery("#roomselcalc").val();
2549 // always remove warning messages
2550 jQuery(".vbo-ratesoverview-calculation-response").find('.vbo-warning').remove();
2551 if (jQuery("#vbo-ratesoverview-calculation-response-room"+idroom).length) {
2552 // remove previous containers for this room
2553 jQuery("#vbo-ratesoverview-calculation-response-room"+idroom).remove();
2554 }
2555 if (!jQuery(".vbo-ratesoverview-calculation-response-room").length) {
2556 // if no rooms responses, empty the whole container
2557 jQuery('.vbo-ratesoverview-calculation-response').html('');
2558 }
2559 var jqxhr = jQuery.ajax({
2560 type: "POST",
2561 url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=calc_rates'); ?>",
2562 data: {
2563 tmpl: "component",
2564 id_room: idroom,
2565 checkin: checkindate,
2566 num_nights: nights,
2567 num_adults: adults,
2568 num_children: children
2569 }
2570 }).done(function(res) {
2571 res = JSON.parse(res);
2572 res = res[0];
2573 if (res.indexOf('e4j.error') >= 0 ) {
2574 jQuery(".vbo-ratesoverview-calculation-response").html("<p class='vbo-warning'>" + res.replace("e4j.error.", "") + "</p>").fadeIn();
2575 } else {
2576 var titlecont = '<span class="vbo-ratesoverview-calculation-response-room-name">'+jQuery("#roomselcalc option:selected").text() + '</span> ' + checkindate + ' - ' + jQuery("#checkoutdate").val() + ', ' + nights + ' <?php echo addslashes(JText::translate('VBRATESOVWRATESCALCNUMNIGHTS')); ?>, ' + adults + ' <?php echo addslashes(JText::translate('VBRATESOVWRATESCALCNUMADULTS')); ?>';
2577 var newcont = '<div class="vbo-ratesoverview-calculation-response-room" id="vbo-ratesoverview-calculation-response-room'+idroom+'"><h4>'+titlecont+'</h4>'+res+'</div>';
2578 // check whether the content should be appended
2579 if (jQuery(".vbo-ratesoverview-calculation-response").find('.vbo-ratesoverview-calculation-response-room').length) {
2580 newcont = jQuery(".vbo-ratesoverview-calculation-response").html() + newcont;
2581 }
2582 //
2583 jQuery(".vbo-ratesoverview-calculation-response").html(newcont).fadeIn();
2584 // loop over every room response and pricing to append the book-now button for the page calendar
2585 var base_booknow_link_orig = jQuery('#vbo-base-booknow-link').attr('href');
2586 jQuery('.vbo-calcrates-rateblock').each(function(k, v) {
2587 var elem = jQuery(v);
2588 var base_booknow_link = base_booknow_link_orig;
2589 // remove existing button
2590 elem.find('.vbo-room-booknow-rct').remove();
2591 //
2592 var b_idprice = elem.attr('data-idprice');
2593 base_booknow_link = base_booknow_link.replace('idprice=', 'idprice=' + b_idprice);
2594 var b_idroom = elem.attr('data-idroom');
2595 base_booknow_link = base_booknow_link.replace('cid[]=', 'cid[]=' + b_idroom);
2596 var b_checkin = elem.attr('data-checkin');
2597 base_booknow_link = base_booknow_link.replace('checkin=', 'checkin=' + b_checkin);
2598 var b_checkout = elem.attr('data-checkout');
2599 base_booknow_link = base_booknow_link.replace('checkout=', 'checkout=' + b_checkout);
2600 var b_adults = elem.attr('data-adults');
2601 base_booknow_link = base_booknow_link.replace('adults=', 'adults=' + b_adults);
2602 var b_children = elem.attr('data-children');
2603 base_booknow_link = base_booknow_link.replace('children=', 'children=' + b_children);
2604 var booknow = '<a href="' + base_booknow_link + '" class="btn btn-primary vbo-room-booknow-rct" target="_blank">' + Joomla.JText._('VBO_BOOKNOW') + '</a>';
2605 elem.append(booknow);
2606 });
2607 //
2608 }
2609 jQuery('#vbo-ratesoverview-calculate').text('<?php echo addslashes(JText::translate('VBRATESOVWRATESCALCULATORCALC')); ?>').prop('disabled', false);
2610 }).fail(function() {
2611 jQuery(".vbo-ratesoverview-calculation-response").fadeOut();
2612 jQuery('#vbo-ratesoverview-calculate').text('<?php echo addslashes(JText::translate('VBRATESOVWRATESCALCULATORCALC')); ?>').prop('disabled', false);
2613 alert("Error Performing Ajax Request");
2614 });
2615 });
2616
2617 /* Orphans Calculation */
2618 vboCheckOrphans();
2619 //
2620 });
2621
2622 function vboCheckOrphans() {
2623 /* Orphans Calculation - Start */
2624 var calc_method = '<?php echo VikBooking::orphansCalculation(); ?>';
2625 jQuery('table.vbratesoverviewtable').each(function() {
2626 var current_room = jQuery(this).attr('data-idroom');
2627 var orphans_pool = new Array;
2628 var avcells = jQuery(this).find('tr.vbo-roverviewtableavrow').find('td');
2629 var restrcells = jQuery(this).find('tr.vbo-roverviewtablerow-restrs').find('td');
2630 avcells.each(function(k, v) {
2631 if (!jQuery(v).find('.vbo-roverw-curunits').length) {
2632 // continue
2633 return true;
2634 }
2635 var todayav = parseInt(jQuery(v).find('.vbo-roverw-curunits').text());
2636 if (!restrcells.hasOwnProperty(k) || isNaN(todayav) || todayav < 1) {
2637 // continue, no restriction cell found or no availability for this day
2638 return true;
2639 }
2640 var todayminlos = parseInt(jQuery(restrcells[k]).find('.vbo-roverw-curminlos').text());
2641 if (isNaN(todayminlos) || todayminlos < 2) {
2642 // continue, no min los > 1 set for this day
2643 return true;
2644 }
2645 // check if any night after today, until min los, is fully booked
2646 var cell_queue = new Array;
2647 var hasorphans = false;
2648 var forward_count = 0;
2649 cell_queue.push(v);
2650 for (var i = 1; i < todayminlos; i++) {
2651 if (!avcells.hasOwnProperty((k + i))) {
2652 // break loop, no info for this day after
2653 break;
2654 }
2655 var tomorrowav = parseInt(jQuery(avcells[(k + i)]).find('.vbo-roverw-curunits').text());
2656 if (isNaN(tomorrowav) || tomorrowav != 0) {
2657 // continue, availability found for tomorrow, we need a non available next-day
2658 continue;
2659 }
2660 // orphan found for this day
2661 hasorphans = true;
2662 forward_count = i;
2663 break;
2664 }
2665 // backward calculation method only if "prevnext".
2666 var backward_count = 0;
2667 for (var i = 1; i <= todayminlos; i++) {
2668 if (!avcells.hasOwnProperty((k - i))) {
2669 // break loop, no info for this prev day
2670 break;
2671 }
2672 var yesterdayav = parseInt(jQuery(avcells[(k - i)]).find('.vbo-roverw-curunits').text());
2673 if (isNaN(yesterdayav) || yesterdayav != 0) {
2674 // increase free nights going backward
2675 backward_count++;
2676 }
2677 }
2678 if (calc_method == 'prevnext' && hasorphans && backward_count > 0 && (backward_count >= todayminlos || (backward_count + forward_count) >= todayminlos)) {
2679 // this should not be an orphan date because of enough free days back, or enough free days in between
2680 hasorphans = false;
2681 }
2682
2683 if (hasorphans && cell_queue.length) {
2684 for (var i in cell_queue) {
2685 if (cell_queue.hasOwnProperty(i)) {
2686 // push the cell
2687 orphans_pool.push(cell_queue[i]);
2688 }
2689 }
2690 }
2691 });
2692 if (orphans_pool.length) {
2693 var orphans_list = '';
2694 for (var i in orphans_pool) {
2695 if (!orphans_pool.hasOwnProperty(i)) {
2696 continue;
2697 }
2698 var idparts = jQuery(orphans_pool[i]).attr('id').split('-');
2699 orphans_list += '<div class="vbo-ratesoverview-orphan-dt" data-dt="'+idparts[1]+'-'+idparts[2]+'-'+idparts[3]+'-'+current_room+'">'+vbowdays[idparts[4]]+', '+vbomonths[(parseInt(idparts[2]) - 1)]+' '+idparts[1]+' '+idparts[3]+'</div>';
2700 }
2701 jQuery('#vbo-ratesoverview-orphans-list-'+current_room).html(orphans_list);
2702 jQuery('#vbo-ratesoverview-orphans-wrapper-'+current_room).fadeIn();
2703 }
2704 });
2705 /* Orphans Calculation - End */
2706 }
2707 </script>
2708
2709 <div class="vbo-secondinfo-overlay-block">
2710 <a class="vbo-info-overlay-close" href="javascript: void(0);"></a>
2711 <div class="vbo-info-overlay-content vbo-info-overlay-content-fests">
2712 <h3><?php VikBookingIcons::e('star'); ?> <span></span></h3>
2713 <div class="vbo-overlay-fests-list"></div>
2714 <div class="vbo-overlay-fests-addnew" data-ymd="">
2715 <h4><?php echo JText::translate('VBOADDCUSTOMFESTTODAY'); ?></h4>
2716 <div class="vbo-overlay-fests-addnew-elem">
2717 <label for="vbo-newfest-name"><?php echo JText::translate('VBPVIEWPLACESONE'); ?></label>
2718 <input type="text" id="vbo-newfest-name" value="" />
2719 </div>
2720 <div class="vbo-overlay-fests-addnew-elem">
2721 <label for="vbo-newfest-descr"><?php echo JText::translate('VBPLACEDESCR'); ?></label>
2722 <textarea id="vbo-newfest-descr"></textarea>
2723 </div>
2724 <div class="vbo-overlay-fests-addnew-save">
2725 <button type="button" class="btn btn-success" onclick="vboAddFest(this);"><?php echo JText::translate('VBSAVE'); ?></button>
2726 </div>
2727 </div>
2728 </div>
2729 </div>
2730