PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.7
VikBooking Hotel Booking Engine & PMS v1.6.7
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.7, at admin/views/ratesoverv/tmpl/default.php

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