| 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 |
$rows = $this->rows; |
| 14 |
$arrbusy = $this->arrbusy; |
| 15 |
$wmonthsel = $this->wmonthsel; |
| 16 |
$tsstart = $this->tsstart; |
| 17 |
$lim0 = $this->lim0; |
| 18 |
$navbut = $this->navbut; |
| 19 |
|
| 20 |
$vbo_auth_pricing = JFactory::getUser()->authorise('core.vbo.pricing', 'com_vikbooking'); |
| 21 |
$vbo_app = VikBooking::getVboApplication(); |
| 22 |
JHtml::fetch('script', VBO_SITE_URI.'resources/jquery-ui.min.js'); |
| 23 |
JHtml::fetch('script', VBO_ADMIN_URI.'resources/js_upload/jquery.stickytableheaders.min.js'); |
| 24 |
|
| 25 |
// JS lang defs |
| 26 |
JText::script('VBSAVE'); |
| 27 |
JText::script('VBPVIEWORDERSTHREE'); |
| 28 |
JText::script('VBEDITORDERTHREE'); |
| 29 |
JText::script('VBDAYS'); |
| 30 |
JText::script('VBDAY'); |
| 31 |
JText::script('VBMAILADULTS'); |
| 32 |
JText::script('VBMAILADULT'); |
| 33 |
JText::script('VBMAILCHILDREN'); |
| 34 |
JText::script('VBMAILCHILD'); |
| 35 |
JText::script('VBO_MISSING_SUBUNIT'); |
| 36 |
JText::script('VBO_SHOW_CANCELLATIONS'); |
| 37 |
JText::script('VBO_DRAG_SUBUNITS_SAMEDATE'); |
| 38 |
JText::script('VBPVIEWORDERCHANNEL'); |
| 39 |
JText::script('VBANNULLA'); |
| 40 |
JText::script('VIKLOADING'); |
| 41 |
JText::script('VBOVWDNDERRNOTENCELLS'); |
| 42 |
JText::script('VBOVWDNDMOVINGBID'); |
| 43 |
JText::script('VBOVWDNDMOVINGROOM'); |
| 44 |
JText::script('VBOVWDNDMOVINGDATES'); |
| 45 |
JText::script('VBEDITORDERROOMSNUM'); |
| 46 |
JText::script('VBEDITORDERADULTS'); |
| 47 |
JText::script('VBPICKUPAT'); |
| 48 |
JText::script('VBRELEASEAT'); |
| 49 |
JText::script('VBEDITORDERCHILDREN'); |
| 50 |
JText::script('VBEDITORDERNINE'); |
| 51 |
JText::script('VBPEDITBUSYTOTPAID'); |
| 52 |
JText::script('VBOFEATASSIGNUNIT'); |
| 53 |
JText::script('VBO_SPLIT_STAY'); |
| 54 |
JText::script('VBO_CONF_SWAP_RNUMB'); |
| 55 |
JText::script('VBO_ERR_SUBUN_MOVE_SUBUN'); |
| 56 |
|
| 57 |
$days_labels = [ |
| 58 |
JText::translate('VBSUN'), |
| 59 |
JText::translate('VBMON'), |
| 60 |
JText::translate('VBTUE'), |
| 61 |
JText::translate('VBWED'), |
| 62 |
JText::translate('VBTHU'), |
| 63 |
JText::translate('VBFRI'), |
| 64 |
JText::translate('VBSAT') |
| 65 |
]; |
| 66 |
|
| 67 |
$nowdf = VikBooking::getDateFormat(); |
| 68 |
if ($nowdf == "%d/%m/%Y") { |
| 69 |
$df = 'd/m/Y'; |
| 70 |
} elseif ($nowdf == "%m/%d/%Y") { |
| 71 |
$df = 'm/d/Y'; |
| 72 |
} else { |
| 73 |
$df = 'Y/m/d'; |
| 74 |
} |
| 75 |
$currencysymb = VikBooking::getCurrencySymb(true); |
| 76 |
|
| 77 |
$pdebug = VikRequest::getInt('e4j_debug', '', 'request'); |
| 78 |
$session = JFactory::getSession(); |
| 79 |
$show_type = $session->get('vbUnitsShowType', ''); |
| 80 |
$mnum = $session->get('vbOvwMnum', '1'); |
| 81 |
$mnum = intval($mnum); |
| 82 |
$pcategory_id = $session->get('vbOvwCatid', 0); |
| 83 |
$cookie = JFactory::getApplication()->input->cookie; |
| 84 |
$cookie_uleft = $cookie->get('vboAovwUleft', '', 'string'); |
| 85 |
$cookie_sticky_heads = $cookie->get('vboAovwStheads', 'off', 'string'); |
| 86 |
$colortags = VikBooking::loadBookingsColorTags(); |
| 87 |
|
| 88 |
// View mode - Classic or Tags |
| 89 |
$pbmode = $session->get('vbTagsMode', 'classic'); |
| 90 |
$tags_view_supported = false; |
| 91 |
|
| 92 |
// Room Units Distinctive Features |
| 93 |
$rooms_features_map = []; |
| 94 |
$rooms_features_bookings = []; |
| 95 |
$rooms_bids_pools = []; |
| 96 |
$room_bookings_pool = []; |
| 97 |
$bids_checkins = []; |
| 98 |
$index_loop = 0; |
| 99 |
foreach ($rows as $kr => $room) { |
| 100 |
if ($room['units'] <= 1) { |
| 101 |
$tags_view_supported = true; |
| 102 |
} else { |
| 103 |
if (!empty($room['params']) && $room['units'] <= 150) { |
| 104 |
//sub-room units only if room type has 150 units at most |
| 105 |
$room_params = json_decode($room['params'], true); |
| 106 |
if (is_array($room_params) && isset($room_params['features']) && is_array($room_params['features'])) { |
| 107 |
$rooms_features_map[$room['id']] = []; |
| 108 |
foreach ($room_params['features'] as $rind => $rfeatures) { |
| 109 |
foreach ($rfeatures as $fname => $fval) { |
| 110 |
if (strlen($fval)) { |
| 111 |
// $rooms_features_map[$room['id']][$rind] = '#'.$rind.' - '.JText::translate($fname).': '.$fval; |
| 112 |
$rooms_features_map[$room['id']][$rind] = "#{$rind} - {$fval}"; |
| 113 |
break; |
| 114 |
} |
| 115 |
} |
| 116 |
} |
| 117 |
if (!$rooms_features_map[$room['id']]) { |
| 118 |
unset($rooms_features_map[$room['id']]); |
| 119 |
} else { |
| 120 |
foreach ($rooms_features_map[$room['id']] as $rind => $indexdata) { |
| 121 |
$clone_room = $room; |
| 122 |
$clone_room['unit_index'] = (int)$rind; |
| 123 |
$clone_room['unit_index_str'] = $indexdata; |
| 124 |
array_splice($rows, ($kr + 1 + $index_loop), 0, [$clone_room]); |
| 125 |
$index_loop++; |
| 126 |
} |
| 127 |
} |
| 128 |
} |
| 129 |
} |
| 130 |
} |
| 131 |
} |
| 132 |
|
| 133 |
if (!$tags_view_supported) { |
| 134 |
$pbmode = 'classic'; |
| 135 |
} |
| 136 |
|
| 137 |
// locked (stand-by) records |
| 138 |
$arrlocked = []; |
| 139 |
if (array_key_exists('tmplock', $arrbusy)) { |
| 140 |
if (count($arrbusy['tmplock']) > 0) { |
| 141 |
$arrlocked = $arrbusy['tmplock']; |
| 142 |
} |
| 143 |
unset($arrbusy['tmplock']); |
| 144 |
} |
| 145 |
|
| 146 |
?> |
| 147 |
<script type="text/Javascript"> |
| 148 |
function vboUnitsLeftOrBooked() { |
| 149 |
var set_to = jQuery('#uleftorbooked').val(); |
| 150 |
jQuery('.vbo-overv-avcell[data-units-booked]').each(function() { |
| 151 |
var counter_el = jQuery(this).find('a'); |
| 152 |
if (!counter_el.length) { |
| 153 |
return; |
| 154 |
} |
| 155 |
counter_el.first().text(jQuery(this).attr('data-'+set_to)); |
| 156 |
}); |
| 157 |
var nd = new Date(); |
| 158 |
nd.setTime(nd.getTime() + (365*24*60*60*1000)); |
| 159 |
document.cookie = "vboAovwUleft="+set_to+"; expires=" + nd.toUTCString() + "; path=/; SameSite=Lax"; |
| 160 |
} |
| 161 |
if (jQuery.isFunction(jQuery.fn.tooltip)) { |
| 162 |
jQuery(".hasTooltip").tooltip(); |
| 163 |
} else { |
| 164 |
jQuery.fn.tooltip = function(){}; |
| 165 |
} |
| 166 |
var vboFests = <?php echo json_encode($this->festivities); ?>; |
| 167 |
var vboRdayNotes = <?php echo json_encode($this->rdaynotes); ?>; |
| 168 |
</script> |
| 169 |
<form action="index.php?option=com_vikbooking&task=overv" method="post" name="vboverview" class="vbo-avov-form"> |
| 170 |
<div class="btn-toolbar vbo-avov-toolbar" id="filter-bar" style="width: 100%; display: inline-block;"> |
| 171 |
<div class="btn-group pull-left"> |
| 172 |
<?php echo $wmonthsel; ?> |
| 173 |
</div> |
| 174 |
<div class="btn-group pull-left"> |
| 175 |
<select name="mnum" onchange="document.vboverview.submit();"> |
| 176 |
<?php |
| 177 |
for($i = 1; $i <= 18; $i++) { |
| 178 |
?> |
| 179 |
<option value="<?php echo $i; ?>"<?php echo $i == $mnum ? ' selected="selected"' : ''; ?>><?php echo JText::translate('VBOVWNUMMONTHS').' '.$i; ?></option> |
| 180 |
<?php |
| 181 |
} |
| 182 |
?> |
| 183 |
</select> |
| 184 |
</div> |
| 185 |
<?php |
| 186 |
if (count($this->categories)) { |
| 187 |
?> |
| 188 |
<div class="btn-group pull-left"> |
| 189 |
<select name="category_id" onchange="document.vboverview.submit();"> |
| 190 |
<option value="0">- <?php echo JText::translate('VBPVIEWROOMTWO'); ?> -</option> |
| 191 |
<?php |
| 192 |
foreach ($this->categories as $catid => $catname) { |
| 193 |
?> |
| 194 |
<option value="<?php echo $catid; ?>"<?php echo $catid == $pcategory_id ? ' selected="selected"' : ''; ?>><?php echo $catname; ?></option> |
| 195 |
<?php |
| 196 |
} |
| 197 |
?> |
| 198 |
</select> |
| 199 |
</div> |
| 200 |
<?php |
| 201 |
} |
| 202 |
|
| 203 |
$stickyheaders_cmd_on = ''; |
| 204 |
$stickyheaders_cmd_off = ''; |
| 205 |
if ((count($rows) * $mnum) > 10) { |
| 206 |
if (VBOPlatformDetection::isJoomla()) { |
| 207 |
/** |
| 208 |
* @joomlaonly fixed offset selector is ".navbar" |
| 209 |
*/ |
| 210 |
$stickyheaders_cmd_on = "jQuery('table.vboverviewtable').stickyTableHeaders({cacheHeaderHeight: true, fixedOffset: (jQuery('.navbar').length ? jQuery('.navbar') : jQuery('#subhead-container'))});"; |
| 211 |
} else { |
| 212 |
/** |
| 213 |
* @wponly fixed offset selector is "#wpadminbar" |
| 214 |
*/ |
| 215 |
$stickyheaders_cmd_on = "jQuery('table.vboverviewtable').stickyTableHeaders({cacheHeaderHeight: true, fixedOffset: jQuery('#wpadminbar')});"; |
| 216 |
} |
| 217 |
$stickyheaders_cmd_off = "jQuery('table.vboverviewtable').stickyTableHeaders('destroy'); jQuery('th.bluedays').attr('style', '');"; |
| 218 |
} |
| 219 |
?> |
| 220 |
<script type="text/javascript"> |
| 221 |
function vboToggleStickyTableHeaders(val) { |
| 222 |
var sticky_heads_cval = 'off'; |
| 223 |
if (val > 0) { |
| 224 |
sticky_heads_cval = 'on'; |
| 225 |
jQuery('table.vboverviewtable').addClass('vbo-overv-sticky-table-head-on'); |
| 226 |
jQuery('table.vboverviewtable').removeClass('vbo-overv-sticky-table-head-off'); |
| 227 |
<?php echo $stickyheaders_cmd_on; ?> |
| 228 |
} else { |
| 229 |
jQuery('table.vboverviewtable').addClass('vbo-overv-sticky-table-head-off'); |
| 230 |
jQuery('table.vboverviewtable').removeClass('vbo-overv-sticky-table-head-on'); |
| 231 |
<?php echo $stickyheaders_cmd_off; ?> |
| 232 |
} |
| 233 |
var nd = new Date(); |
| 234 |
nd.setTime(nd.getTime() + (365*24*60*60*1000)); |
| 235 |
document.cookie = "vboAovwStheads=" + sticky_heads_cval + "; expires=" + nd.toUTCString() + "; path=/; SameSite=Lax"; |
| 236 |
} |
| 237 |
</script> |
| 238 |
<?php |
| 239 |
if ((count($rows) * $mnum) > 10) { |
| 240 |
?> |
| 241 |
<div class="btn-group pull-left"> |
| 242 |
<select name="stickytheads" onchange="vboToggleStickyTableHeaders(this.value);"> |
| 243 |
<option value="1"<?php echo empty($cookie_sticky_heads) || $cookie_sticky_heads == 'on' ? ' selected="selected"' : ''; ?>><?php echo JText::translate('VBOVERVIEWSTICKYTHEADON'); ?></option> |
| 244 |
<option value="0"<?php echo $cookie_sticky_heads == 'off' ? ' selected="selected"' : ''; ?>><?php echo JText::translate('VBOVERVIEWSTICKYTHEADOFF'); ?></option> |
| 245 |
</select> |
| 246 |
</div> |
| 247 |
<?php |
| 248 |
} |
| 249 |
|
| 250 |
if ($tags_view_supported === true) { |
| 251 |
?> |
| 252 |
<div class="btn-group pull-left"> |
| 253 |
<div class="vbo-overview-tagsorclassic"> |
| 254 |
<select name="bmode" onchange="document.vboverview.submit();"> |
| 255 |
<option value="classic"><?php echo JText::translate('VBOAVOVWBMODECLASSIC'); ?></option> |
| 256 |
<option value="tags"<?php echo $pbmode == 'tags' ? ' selected="selected"' : ''; ?>><?php echo JText::translate('VBOAVOVWBMODETAGS'); ?></option> |
| 257 |
</select> |
| 258 |
</div> |
| 259 |
<?php |
| 260 |
if ($pbmode == 'tags' && count($colortags) > 0) { |
| 261 |
?> |
| 262 |
<div class="vbo-overview-tagslegend"> |
| 263 |
<span class="vbo-overview-tagslegend-lbl"><?php echo JText::translate('VBOAVOVWBMODETAGSLBL'); ?></span> |
| 264 |
<?php |
| 265 |
foreach ($colortags as $ctagk => $ctagv) { |
| 266 |
?> |
| 267 |
<div class="vbo-overview-legend-tag"> |
| 268 |
<div class="vbo-colortag-circle hasTooltip" style="background-color: <?php echo $ctagv['color']; ?>;" title="<?php echo JText::translate($ctagv['name']); ?>"></div> |
| 269 |
</div> |
| 270 |
<?php |
| 271 |
} |
| 272 |
?> |
| 273 |
</div> |
| 274 |
<?php |
| 275 |
} |
| 276 |
?> |
| 277 |
</div> |
| 278 |
<?php |
| 279 |
} |
| 280 |
?> |
| 281 |
<div class="btn-group pull-right"> |
| 282 |
<select name="units_show_type" id="uleftorbooked" onchange="vboUnitsLeftOrBooked();"><option value="units-booked"<?php echo (!empty($cookie_uleft) && $cookie_uleft == 'units-booked' ? ' selected="selected"' : ''); ?>><?php echo JText::translate('VBOVERVIEWUBOOKEDFILT'); ?></option><option value="units-left"<?php echo $show_type == 'units-left' || (!empty($cookie_uleft) && $cookie_uleft == 'units-left') ? ' selected="selected"' : ''; ?>><?php echo JText::translate('VBOVERVIEWULEFTFILT'); ?></option></select> |
| 283 |
</div> |
| 284 |
<div class="btn-group pull-right vbo-avov-legend"> |
| 285 |
<span class="vbo-overview-legend-init"><?php echo JText::translate('VBOVERVIEWLEGEND'); ?></span> |
| 286 |
<div class="vbo-overview-legend-red"> |
| 287 |
<span class="vbo-overview-legend-box"> </span> |
| 288 |
<span class="vbo-overview-legend-title"><?php echo JText::translate('VBOVERVIEWLEGRED'); ?></span> |
| 289 |
</div> |
| 290 |
<div class="vbo-overview-legend-yellow"> |
| 291 |
<span class="vbo-overview-legend-box"> </span> |
| 292 |
<span class="vbo-overview-legend-title"><?php echo JText::translate('VBOVERVIEWLEGYELLOW'); ?></span> |
| 293 |
</div> |
| 294 |
<div class="vbo-overview-legend-green"> |
| 295 |
<span class="vbo-overview-legend-box"> </span> |
| 296 |
<span class="vbo-overview-legend-title"><?php echo JText::translate('VBOVERVIEWLEGGREEN'); ?></span> |
| 297 |
</div> |
| 298 |
<div class="vbo-overview-legend-green vbo-overview-legend-dnd"> |
| 299 |
<span class="vbo-overview-legend-box"><i class="vboicn-enlarge" style="margin: 1px; display: block; text-align: center;"></i></span> |
| 300 |
<span class="vbo-overview-legend-title"><?php echo JText::translate('VBOVERVIEWLEGDND'); ?></span> |
| 301 |
</div> |
| 302 |
</div> |
| 303 |
</div> |
| 304 |
</form> |
| 305 |
|
| 306 |
<?php |
| 307 |
$todayymd = date('Y-m-d'); |
| 308 |
$nowts = getdate($tsstart); |
| 309 |
$curts = $nowts; |
| 310 |
for ($mind = 1; $mind <= $mnum; $mind++) { |
| 311 |
$monthname = VikBooking::sayMonth($curts['mon']); |
| 312 |
?> |
| 313 |
<div class="vbo-overv-montable-wrap"> |
| 314 |
<div class="vbo-table-responsive"> |
| 315 |
<table class="vboverviewtable vbo-roverview-table vbo-table <?php echo $cookie_sticky_heads == 'off' ? 'vbo-overv-sticky-table-head-off' : 'vbo-overv-sticky-table-head-on'; ?>"> |
| 316 |
<thead> |
| 317 |
<tr class="vboverviewtablerowone"> |
| 318 |
<th class="bluedays skip-bluedays-click vbo-overview-month"><?php echo $monthname . " " . $curts['year']; ?></th> |
| 319 |
<?php |
| 320 |
$moncurts = $curts; |
| 321 |
$mon = $moncurts['mon']; |
| 322 |
while ($moncurts['mon'] == $mon) { |
| 323 |
$curdayymd = date('Y-m-d', $moncurts[0]); |
| 324 |
$read_day = $days_labels[$moncurts['wday']] . ' ' . $moncurts['mday'] . ' ' . $monthname . ' ' . $curts['year']; |
| 325 |
?> |
| 326 |
<th class="bluedays<?php echo ($todayymd == $curdayymd ? ' vbo-overv-todaycell' : '') . (isset($this->festivities[$curdayymd]) ? ' vbo-overv-festcell' : ''); ?>" data-ymd="<?php echo $curdayymd; ?>" data-readymd="<?php echo $read_day; ?>"> |
| 327 |
<span class="vbo-overw-tablewday"><?php echo $days_labels[$moncurts['wday']]; ?></span> |
| 328 |
<span class="vbo-overw-tablemday"><?php echo $moncurts['mday']; ?></span> |
| 329 |
</th> |
| 330 |
<?php |
| 331 |
// parse the next day |
| 332 |
$moncurts = getdate(mktime(0, 0, 0, $moncurts['mon'], ($moncurts['mday'] + 1), $moncurts['year'])); |
| 333 |
} |
| 334 |
?> |
| 335 |
</tr> |
| 336 |
</thead> |
| 337 |
<tbody> |
| 338 |
<?php |
| 339 |
foreach ($rows as $room) { |
| 340 |
$moncurts = $curts; |
| 341 |
$mon = $moncurts['mon']; |
| 342 |
$room_tags_view = $pbmode == 'tags' && $tags_view_supported === true && $room['units'] <= 1 ? true : false; |
| 343 |
$is_subunit = array_key_exists('unit_index', $room); |
| 344 |
|
| 345 |
?> |
| 346 |
<tr class="vboverviewtablerow<?php echo $is_subunit ? ' vboverviewtablerow-subunit' : ''; ?><?php echo ($is_subunit || $room['units'] == 1) && $cookie_sticky_heads == 'off' ? ' vbo-overv-row-snake' : ''; ?>"<?php echo $is_subunit ? ' data-subroomid="' . $room['id'] . '-' . $room['unit_index'] . '"' : ''; ?>> |
| 347 |
<?php |
| 348 |
if ($is_subunit) { |
| 349 |
?> |
| 350 |
<td class="roomname subroomname" data-roomid="<?php echo '-' . $room['id']; ?>"> |
| 351 |
<span class="vbo-overview-subroomunits"><?php VikBookingIcons::e('bed'); ?></span> |
| 352 |
<span class="vbo-overview-subroomname"><?php echo $room['unit_index_str']; ?></span> |
| 353 |
</td> |
| 354 |
<?php |
| 355 |
} else { |
| 356 |
?> |
| 357 |
<td class="roomname" data-roomid="<?php echo $room['id']; ?>"> |
| 358 |
<span class="vbo-overview-room-info"> |
| 359 |
<span class="vbo-overview-roomunits"><?php echo $room['units']; ?></span> |
| 360 |
<span class="vbo-overview-roomname"><?php echo $room['name']; ?></span> |
| 361 |
<?php |
| 362 |
if (isset($rooms_features_map[$room['id']])) { |
| 363 |
?> |
| 364 |
<span class="vbo-overview-subroom-toggle"><i class="<?php echo VikBookingIcons::i('chevron-down', 'hasTooltip'); ?>" style="margin: 0;" title="<?php echo JHtml::fetch('esc_attr', JText::translate('VBOVERVIEWTOGGLESUBROOM')); ?>"></i></span> |
| 365 |
<?php |
| 366 |
} |
| 367 |
?> |
| 368 |
</span> |
| 369 |
</td> |
| 370 |
<?php |
| 371 |
} |
| 372 |
|
| 373 |
// loop through every day of the month |
| 374 |
$room_bids_pool = []; |
| 375 |
$room_bookings = []; |
| 376 |
while ($moncurts['mon'] == $mon) { |
| 377 |
$dclass = 'vbo-overv-avcell ' . (!$is_subunit ? "notbusy" : "subnotbusy"); |
| 378 |
$is_checkin = false; |
| 379 |
$is_sharedcal = false; |
| 380 |
$is_closure = false; |
| 381 |
$lastbidcheckout = null; |
| 382 |
$dalt = ""; |
| 383 |
$bid = ""; |
| 384 |
$bids_pool = []; |
| 385 |
$totfound = 0; |
| 386 |
$prev_day_key = date('Y-m-d', strtotime('-1 day', $moncurts[0])); |
| 387 |
$cur_day_key = date('Y-m-d', $moncurts[0]); |
| 388 |
if (!empty($arrbusy[$room['id']]) && !$is_subunit) { |
| 389 |
foreach ($arrbusy[$room['id']] as $b) { |
| 390 |
$tmpone = getdate($b['checkin']); |
| 391 |
$ritts = mktime(0, 0, 0, $tmpone['mon'], $tmpone['mday'], $tmpone['year']); |
| 392 |
$tmptwo = getdate($b['checkout']); |
| 393 |
$conts = mktime(0, 0, 0, $tmptwo['mon'], $tmptwo['mday'], $tmptwo['year']); |
| 394 |
if (!($moncurts[0] >= $ritts && $moncurts[0] < $conts)) { |
| 395 |
// booking does not involve the current day |
| 396 |
continue; |
| 397 |
} |
| 398 |
$dclass = "vbo-overv-avcell busy"; |
| 399 |
$bid = $b['idorder']; |
| 400 |
$is_sharedcal = !empty($b['sharedcal']) ? true : $is_sharedcal; |
| 401 |
$is_closure = !empty($b['closure']) ? true : $is_closure; |
| 402 |
$bid_str = '-' . $bid . '-'; |
| 403 |
if (!in_array($bid_str, $bids_pool)) { |
| 404 |
$bids_pool[] = $bid_str; |
| 405 |
} |
| 406 |
if (isset($rooms_features_map[$room['id']])) { |
| 407 |
// multi-unit room with distinctive features defined |
| 408 |
if (!isset($room_bids_pool[$cur_day_key])) { |
| 409 |
$room_bids_pool[$cur_day_key] = []; |
| 410 |
$room_bookings[$cur_day_key] = []; |
| 411 |
} |
| 412 |
$room_bids_pool[$cur_day_key][] = (int)$bid; |
| 413 |
$room_bookings[$cur_day_key][] = $b; |
| 414 |
} elseif ($room['units'] == 1) { |
| 415 |
// single-unit room |
| 416 |
if (!isset($room_bookings[$cur_day_key])) { |
| 417 |
$room_bookings[$cur_day_key] = []; |
| 418 |
} |
| 419 |
$room_bookings[$cur_day_key][] = $b; |
| 420 |
} |
| 421 |
if ($moncurts[0] == $ritts) { |
| 422 |
$dalt = JText::translate('VBPICKUPAT')." ".date('H:i', $b['checkin']); |
| 423 |
$is_checkin = true; |
| 424 |
$lastbidcheckout = $b['checkout']; |
| 425 |
$bids_checkins[$bid] = $cur_day_key; |
| 426 |
} elseif ($moncurts[0] == $conts) { |
| 427 |
$dalt = JText::translate('VBRELEASEAT')." ".date('H:i', $b['checkout']); |
| 428 |
} |
| 429 |
$totfound++; |
| 430 |
} |
| 431 |
} |
| 432 |
|
| 433 |
// locked (stand-by) records |
| 434 |
if ($room_tags_view === true && isset($arrlocked[$room['id']]) && $arrlocked[$room['id']] && !$is_subunit) { |
| 435 |
foreach ($arrlocked[$room['id']] as $l) { |
| 436 |
$tmpone = getdate($l['checkin']); |
| 437 |
$ritts = mktime(0, 0, 0, $tmpone['mon'], $tmpone['mday'], $tmpone['year']); |
| 438 |
$tmptwo = getdate($l['checkout']); |
| 439 |
$conts = mktime(0, 0, 0, $tmptwo['mon'], $tmptwo['mday'], $tmptwo['year']); |
| 440 |
if ($moncurts[0] >= $ritts && $moncurts[0] < $conts) { |
| 441 |
$dclass = strpos($dclass, "notbusy") !== false ? "busytmplock" : "busy busytmplock"; |
| 442 |
$bid = $l['idorder']; |
| 443 |
if (!in_array($bid, $bids_pool)) { |
| 444 |
if (count($bids_pool) > 0) { |
| 445 |
array_unshift($bids_pool, '-'.$bid.'-'); |
| 446 |
} else { |
| 447 |
$bids_pool[] = '-'.$bid.'-'; |
| 448 |
} |
| 449 |
} |
| 450 |
if ($moncurts[0] == $ritts) { |
| 451 |
$dalt = JText::translate('VBPICKUPAT')." ".date('H:i', $l['checkin']); |
| 452 |
} elseif ($moncurts[0] == $conts) { |
| 453 |
$dalt = JText::translate('VBRELEASEAT')." ".date('H:i', $l['checkout']); |
| 454 |
} |
| 455 |
$totfound++; |
| 456 |
} |
| 457 |
} |
| 458 |
} |
| 459 |
|
| 460 |
// handle single-unit room reservations |
| 461 |
if ($room['units'] == 1 && !isset($rooms_features_map[$room['id']]) && isset($room_bookings[$cur_day_key]) && $room_bookings[$cur_day_key]) { |
| 462 |
// set the first (and only) booking |
| 463 |
$day_booking = []; |
| 464 |
foreach ($room_bookings[$cur_day_key] as $day_res) { |
| 465 |
if (!$day_res['closure'] && !$day_res['sharedcal']) { |
| 466 |
$day_booking = $day_res; |
| 467 |
break; |
| 468 |
} |
| 469 |
} |
| 470 |
if ($day_booking) { |
| 471 |
if (!isset($room_bookings_pool[$room['id']])) { |
| 472 |
$room_bookings_pool[$room['id']] = []; |
| 473 |
} |
| 474 |
if (!isset($room_bookings_pool[$room['id']][$cur_day_key])) { |
| 475 |
$room_bookings_pool[$room['id']][$cur_day_key] = []; |
| 476 |
} |
| 477 |
$room_bookings_pool[$room['id']][$cur_day_key][0] = $day_booking; |
| 478 |
} |
| 479 |
} |
| 480 |
|
| 481 |
$useday = $moncurts['mday'] < 10 ? "0{$moncurts['mday']}" : $moncurts['mday']; |
| 482 |
$dclass .= $totfound < $room['units'] && $totfound > 0 ? ' vbo-partially' : ''; |
| 483 |
$dclass .= $is_sharedcal ? ' busy-sharedcalendar' : ''; |
| 484 |
$dclass .= $is_closure ? ' busy-closure' : ''; |
| 485 |
$dstyle = ''; |
| 486 |
$astyle = ''; |
| 487 |
if ($room_tags_view === true && $totfound > 0) { |
| 488 |
$last_bid = intval(str_replace('-', '', $bids_pool[(count($bids_pool) - 1)])); |
| 489 |
$binfo = VikBooking::getBookingInfoFromID($last_bid); |
| 490 |
if (count($binfo) > 0) { |
| 491 |
$bcolortag = VikBooking::applyBookingColorTag($binfo); |
| 492 |
if (count($bcolortag) > 0) { |
| 493 |
$bcolortag['name'] = JText::translate($bcolortag['name']); |
| 494 |
$dstyle = " style=\"background-color: ".$bcolortag['color']."; color: ".(array_key_exists('fontcolor', $bcolortag) ? $bcolortag['fontcolor'] : '#ffffff').";\" data-lastbid=\"".$last_bid."\""; |
| 495 |
$astyle = " style=\"color: ".(array_key_exists('fontcolor', $bcolortag) ? $bcolortag['fontcolor'] : '#ffffff').";\""; |
| 496 |
$dclass .= ' vbo-hascolortag'; |
| 497 |
} |
| 498 |
} |
| 499 |
} |
| 500 |
if ($is_subunit && isset($rooms_features_bookings[$room['id']]) && isset($rooms_bids_pools[$room['id']][$cur_day_key]) && isset($rooms_features_bookings[$room['id']][$room['unit_index']])) { |
| 501 |
foreach ($rooms_bids_pools[$room['id']][$cur_day_key] as $bid) { |
| 502 |
$bid = intval(str_replace('-', '', $bid)); |
| 503 |
if (in_array($bid, $rooms_features_bookings[$room['id']][$room['unit_index']])) { |
| 504 |
$room['units'] = 1; |
| 505 |
$totfound = 1; |
| 506 |
$dclass = "vbo-overv-avcell subroom-busy"; |
| 507 |
$is_checkin = isset($bids_checkins[$bid]) && $bids_checkins[$bid] == $cur_day_key ? true : $is_checkin; |
| 508 |
break; |
| 509 |
} |
| 510 |
} |
| 511 |
} |
| 512 |
$write_units = $show_type == 'units-left' || (!empty($cookie_uleft) && $cookie_uleft == 'units-left') ? ($room['units'] - $totfound) : $totfound; |
| 513 |
// check today's date |
| 514 |
$curdayymd = date('Y-m-d', $moncurts[0]); |
| 515 |
if ($todayymd == $curdayymd) { |
| 516 |
$dclass .= ' vbo-overv-todaycell'; |
| 517 |
} |
| 518 |
if (isset($this->festivities[$curdayymd])) { |
| 519 |
$dclass .= ' vbo-overv-festcell'; |
| 520 |
} |
| 521 |
|
| 522 |
/** |
| 523 |
* Critical dates defined at room-day level. |
| 524 |
* |
| 525 |
* @since 1.13.5 (J) - 1.3.5 (WP) |
| 526 |
*/ |
| 527 |
$rdaynote_keyid = $cur_day_key . '_' . $room['id'] . '_' . (isset($room['unit_index']) ? $room['unit_index'] : '0'); |
| 528 |
if (isset($this->rdaynotes[$rdaynote_keyid])) { |
| 529 |
// note exists for this combination of date, room ID and subunit |
| 530 |
$dclass .= ' vbo-roomdaynote-full'; |
| 531 |
$rdaynote_icn = 'sticky-note'; |
| 532 |
} else { |
| 533 |
// no notes for this cell |
| 534 |
$dclass .= ' vbo-roomdaynote-empty'; |
| 535 |
$rdaynote_icn = 'far fa-sticky-note'; |
| 536 |
} |
| 537 |
$critical_note = '<span class="vbo-roomdaynote-trigger" data-roomday="' . $rdaynote_keyid . '"><i class="' . VikBookingIcons::i($rdaynote_icn, 'vbo-roomdaynote-display') . '"></i></span>'; |
| 538 |
|
| 539 |
/** |
| 540 |
* Closures overlapping one real reservation for a single-unit room should still |
| 541 |
* allow the display of the booking snake if it's just one real reservation. |
| 542 |
*/ |
| 543 |
$closure_on_real_res = false; |
| 544 |
if ($totfound === 2 && !$is_subunit && $room['units'] == 1 && $cookie_sticky_heads == 'off' && strpos($dclass, "busy-closure") !== false) { |
| 545 |
if (isset($room_bookings_pool[$room['id']]) && isset($room_bookings_pool[$room['id']][$cur_day_key]) && $room_bookings_pool[$room['id']][$cur_day_key]) { |
| 546 |
if (isset($room_bookings_pool[$room['id']][$cur_day_key][0]) && !$room_bookings_pool[$room['id']][$cur_day_key][0]['closure']) { |
| 547 |
// found a real booking on a date with at least one closure |
| 548 |
$closure_on_real_res = true; |
| 549 |
} |
| 550 |
} |
| 551 |
} |
| 552 |
|
| 553 |
// prepare cell content |
| 554 |
if ($totfound === 1 || $closure_on_real_res) { |
| 555 |
$day_booking_snake = ''; |
| 556 |
$day_booking_data = []; |
| 557 |
if (isset($room_bookings_pool[$room['id']]) && isset($room_bookings_pool[$room['id']][$cur_day_key]) && $room_bookings_pool[$room['id']][$cur_day_key]) { |
| 558 |
if ($is_subunit && isset($room_bookings_pool[$room['id']][$cur_day_key][$room['unit_index']])) { |
| 559 |
$day_booking_data = $room_bookings_pool[$room['id']][$cur_day_key][$room['unit_index']]; |
| 560 |
} elseif (!$is_subunit && isset($room_bookings_pool[$room['id']][$cur_day_key][0])) { |
| 561 |
$day_booking_data = $room_bookings_pool[$room['id']][$cur_day_key][0]; |
| 562 |
} |
| 563 |
} |
| 564 |
if (isset($room_bookings_pool[$room['id']]) && isset($room_bookings_pool[$room['id']][$prev_day_key]) && $room_bookings_pool[$room['id']][$prev_day_key]) { |
| 565 |
if ($is_subunit && isset($room_bookings_pool[$room['id']][$prev_day_key][$room['unit_index']])) { |
| 566 |
if (date('Y-m-d', $room_bookings_pool[$room['id']][$prev_day_key][$room['unit_index']]['checkout']) == $cur_day_key) { |
| 567 |
// prepend checkout snake |
| 568 |
$day_booking_snake .= '<div class="vbo-tableaux-booking vbo-tableaux-booking-singleunit vbo-tableaux-booking-checkout"><span> </span></div>'; |
| 569 |
} |
| 570 |
} elseif (!$is_subunit && $room['units'] == 1 && isset($room_bookings_pool[$room['id']][$prev_day_key][0])) { |
| 571 |
if (date('Y-m-d', $room_bookings_pool[$room['id']][$prev_day_key][0]['checkout']) == $cur_day_key) { |
| 572 |
// prepend checkout snake |
| 573 |
$day_booking_snake .= '<div class="vbo-tableaux-booking vbo-tableaux-booking-singleunit vbo-tableaux-booking-checkout"><span> </span></div>'; |
| 574 |
} |
| 575 |
} |
| 576 |
} |
| 577 |
if ($room['units'] == 1 && $day_booking_data && !$day_booking_data['closure']) { |
| 578 |
// build tableaux-style snake container for guest |
| 579 |
$customer_descr = ''; |
| 580 |
if ($is_checkin) { |
| 581 |
// customer details |
| 582 |
if (!empty($day_booking_data['first_name']) || !empty($day_booking_data['last_name'])) { |
| 583 |
// check if we need to display a profile picture or a channel logo |
| 584 |
$booking_avatar_src = null; |
| 585 |
$booking_avatar_alt = null; |
| 586 |
if (!empty($day_booking_data['pic'])) { |
| 587 |
// customer profile picture |
| 588 |
$booking_avatar_src = strpos($day_booking_data['pic'], 'http') === 0 ? $day_booking_data['pic'] : VBO_SITE_URI . 'resources/uploads/' . $day_booking_data['pic']; |
| 589 |
$booking_avatar_alt = basename($booking_avatar_src); |
| 590 |
} elseif (!empty($day_booking_data['idorderota']) && !empty($day_booking_data['channel'])) { |
| 591 |
// channel logo |
| 592 |
$logo_helper = VikBooking::getVcmChannelsLogo($day_booking_data['channel'], $get_istance = true); |
| 593 |
if ($logo_helper !== false) { |
| 594 |
$booking_avatar_src = $logo_helper->getSmallLogoURL(); |
| 595 |
$booking_avatar_alt = $logo_helper->provenience; |
| 596 |
} |
| 597 |
} |
| 598 |
|
| 599 |
if (!empty($booking_avatar_src)) { |
| 600 |
// make sure the alt attribute is not too long in case of broken images |
| 601 |
$booking_avatar_alt = !empty($booking_avatar_alt) && strlen($booking_avatar_alt) > 15 ? '...' . substr($booking_avatar_alt, -12) : $booking_avatar_alt; |
| 602 |
// append booking avatar image |
| 603 |
$customer_descr .= '<span class="vbo-tableaux-booking-avatar"><img src="' . $booking_avatar_src . '" class="vbo-tableaux-booking-avatar-img" ' . (!empty($booking_avatar_alt) ? 'alt="' . htmlspecialchars($booking_avatar_alt) . '" ' : '') . '/></span>'; |
| 604 |
} |
| 605 |
|
| 606 |
// customer name |
| 607 |
$customer_fullname = trim($day_booking_data['first_name'] . ' ' . $day_booking_data['last_name']); |
| 608 |
if (strlen($customer_fullname) > 26) { |
| 609 |
if (function_exists('mb_substr')) { |
| 610 |
$customer_fullname = trim(mb_substr($customer_fullname, 0, 26, 'UTF-8')) . '..'; |
| 611 |
} else { |
| 612 |
$customer_fullname = trim(substr($customer_fullname, 0, 26)) . '..'; |
| 613 |
} |
| 614 |
} |
| 615 |
$customer_descr .= '<span class="vbo-tableaux-guest-name">' . $customer_fullname . '</span>'; |
| 616 |
} else { |
| 617 |
// parse the customer data string |
| 618 |
$custdata_parts = explode("\n", $day_booking_data['custdata']); |
| 619 |
$enoughinfo = false; |
| 620 |
if (count($custdata_parts) > 2 && strpos($custdata_parts[0], ':') !== false && strpos($custdata_parts[1], ':') !== false) { |
| 621 |
// get the first two fields |
| 622 |
$custvalues = array(); |
| 623 |
foreach ($custdata_parts as $custdet) { |
| 624 |
if (strlen($custdet) < 1) { |
| 625 |
continue; |
| 626 |
} |
| 627 |
$custdet_parts = explode(':', $custdet); |
| 628 |
if (count($custdet_parts) >= 2) { |
| 629 |
unset($custdet_parts[0]); |
| 630 |
array_push($custvalues, trim(implode(':', $custdet_parts))); |
| 631 |
} |
| 632 |
if (count($custvalues) > 1) { |
| 633 |
break; |
| 634 |
} |
| 635 |
} |
| 636 |
if (count($custvalues) > 1) { |
| 637 |
$enoughinfo = true; |
| 638 |
$customer_nominative = trim(implode(' ', $custvalues)); |
| 639 |
if (strlen($customer_nominative) > 26) { |
| 640 |
if (function_exists('mb_substr')) { |
| 641 |
$customer_nominative = trim(mb_substr($customer_nominative, 0, 26, 'UTF-8')) . '..'; |
| 642 |
} else { |
| 643 |
$customer_nominative = trim(substr($customer_nominative, 0, 26)) . '..'; |
| 644 |
} |
| 645 |
} |
| 646 |
if (!empty($day_booking_data['idorderota']) && !empty($day_booking_data['channel'])) { |
| 647 |
// add support for the channel logo for the imported OTA reservations with no customer record |
| 648 |
$logo_helper = VikBooking::getVcmChannelsLogo($day_booking_data['channel'], $get_istance = true); |
| 649 |
if ($logo_helper !== false) { |
| 650 |
$booking_avatar_src = $logo_helper->getSmallLogoURL(); |
| 651 |
$booking_avatar_alt = $logo_helper->provenience; |
| 652 |
// make sure the alt attribute is not too long in case of broken images |
| 653 |
$booking_avatar_alt = !empty($booking_avatar_alt) && strlen($booking_avatar_alt) > 15 ? '...' . substr($booking_avatar_alt, -12) : $booking_avatar_alt; |
| 654 |
// append booking avatar image |
| 655 |
$customer_descr .= '<span class="vbo-tableaux-booking-avatar"><img src="' . $booking_avatar_src . '" class="vbo-tableaux-booking-avatar-img" ' . (!empty($booking_avatar_alt) ? 'alt="' . htmlspecialchars($booking_avatar_alt) . '" ' : '') . '/></span>'; |
| 656 |
} |
| 657 |
} |
| 658 |
// set customer nominative built |
| 659 |
$customer_descr .= '<span class="vbo-tableaux-guest-name">' . $customer_nominative . '</span>';; |
| 660 |
} |
| 661 |
} |
| 662 |
if (!$enoughinfo) { |
| 663 |
$customer_descr .= '<span class="vbo-tableaux-guest-name">#' . $day_booking_data['idorder'] . '</span>';; |
| 664 |
} |
| 665 |
} |
| 666 |
} |
| 667 |
// set value |
| 668 |
$day_booking_snake .= '<div class="vbo-tableaux-booking vbo-tableaux-booking-singleunit ' . ($is_checkin ? 'vbo-tableaux-booking-checkin' : 'vbo-tableaux-booking-stay') . '"' . ($is_checkin ? ' data-nights="' . $day_booking_data['days'] . '" draggable="true"' : '') . '><span>' . ($is_checkin ? $customer_descr : ' ') . '</span></div>'; |
| 669 |
} |
| 670 |
|
| 671 |
if ($cookie_sticky_heads != 'off') { |
| 672 |
// not supported with the sticky table headers layout |
| 673 |
$day_booking_snake = ''; |
| 674 |
} |
| 675 |
|
| 676 |
$write_units = strpos($dclass, "subroom-busy") !== false ? '' : $write_units; |
| 677 |
$stopdrag = ($mind == $mnum && !is_null($lastbidcheckout) && (int)date('n', $lastbidcheckout) != (int)$mon); |
| 678 |
$dclass .= $is_checkin === true ? ' vbo-checkinday' : ''; |
| 679 |
|
| 680 |
// build proper link |
| 681 |
if ($totfound > 1) { |
| 682 |
// there must be a closure overlapping a real booking |
| 683 |
$cell_link = 'index.php?option=com_vikbooking&task=choosebusy&idroom=' . $room['id'] . '&ts=' . $moncurts[0] . '&goto=overv'; |
| 684 |
} else { |
| 685 |
// regular situation with one booking only |
| 686 |
$cell_link = 'index.php?option=com_vikbooking&task=editbusy&cid[]=' . $bid . '&goto=overv'; |
| 687 |
} |
| 688 |
?> |
| 689 |
<td align="center" class="<?php echo $dclass; ?>"<?php echo $dstyle; ?> data-day="<?php echo $cur_day_key; ?>" data-units-booked="<?php echo $totfound; ?>" data-units-left="<?php echo ($room['units'] - $totfound); ?>" data-bids="<?php echo strpos($dclass, "subroom-busy") !== false ? "-{$bid}-" : implode(',', $bids_pool); ?>"> |
| 690 |
<?php |
| 691 |
if (!$day_booking_snake) { |
| 692 |
if ($is_checkin === true && !$stopdrag) { |
| 693 |
?> |
| 694 |
<span class="vbo-draggable-sp" draggable="true"> |
| 695 |
<a href="<?php echo $cell_link; ?>" class="<?php echo strpos($dclass, "subroom-busy") === false ? 'vbo-overview-redday' : 'vbo-overview-subredday'; ?>"<?php echo $astyle . (!empty($dalt) ? ' title="' . JHtml::fetch('esc_attr', $dalt) . '"' : ''); ?>><?php echo $write_units; ?></a> |
| 696 |
</span> |
| 697 |
<?php |
| 698 |
} else { |
| 699 |
?> |
| 700 |
<a href="<?php echo $cell_link; ?>" class="<?php echo strpos($dclass, "subroom-busy") === false ? 'vbo-overview-redday' : 'vbo-overview-subredday'; ?>"<?php echo $astyle . (!empty($dalt) ? ' title="' . JHtml::fetch('esc_attr', $dalt) . '"' : ''); ?>><?php echo $write_units; ?></a> |
| 701 |
<?php |
| 702 |
} |
| 703 |
} |
| 704 |
echo $day_booking_snake . $critical_note; |
| 705 |
?> |
| 706 |
</td> |
| 707 |
<?php |
| 708 |
} elseif ($totfound > 1) { |
| 709 |
?> |
| 710 |
<td align="center" class="<?php echo $dclass; ?>"<?php echo $dstyle; ?> data-day="<?php echo $cur_day_key; ?>" data-units-booked="<?php echo $totfound; ?>" data-units-left="<?php echo ($room['units'] - $totfound); ?>" data-bids="<?php echo implode(',', $bids_pool); ?>"> |
| 711 |
<a href="index.php?option=com_vikbooking&task=choosebusy&idroom=<?php echo $room['id']; ?>&ts=<?php echo $moncurts[0]; ?>&goto=overv" class="vbo-overview-redday"<?php echo $astyle; ?>><?php echo $write_units; ?></a> |
| 712 |
<?php echo $critical_note; ?> |
| 713 |
</td> |
| 714 |
<?php |
| 715 |
} else { |
| 716 |
// no booked records |
| 717 |
?> |
| 718 |
<td align="center" class="<?php echo $dclass; ?>" data-day="<?php echo $cur_day_key; ?>" data-bids=""> |
| 719 |
<?php |
| 720 |
if ($cookie_sticky_heads == 'off' && isset($room_bookings_pool[$room['id']]) && isset($room_bookings_pool[$room['id']][$prev_day_key]) && $room_bookings_pool[$room['id']][$prev_day_key]) { |
| 721 |
if ($is_subunit && isset($room_bookings_pool[$room['id']][$prev_day_key][$room['unit_index']])) { |
| 722 |
if (date('Y-m-d', $room_bookings_pool[$room['id']][$prev_day_key][$room['unit_index']]['checkout']) == $cur_day_key) { |
| 723 |
// prepend checkout snake |
| 724 |
echo '<div class="vbo-tableaux-booking vbo-tableaux-booking-singleunit vbo-tableaux-booking-checkout"><span> </span></div>'; |
| 725 |
} |
| 726 |
} elseif (!$is_subunit && $room['units'] == 1 && isset($room_bookings_pool[$room['id']][$prev_day_key][0])) { |
| 727 |
if (date('Y-m-d', $room_bookings_pool[$room['id']][$prev_day_key][0]['checkout']) == $cur_day_key) { |
| 728 |
// prepend checkout snake |
| 729 |
echo '<div class="vbo-tableaux-booking vbo-tableaux-booking-singleunit vbo-tableaux-booking-checkout"><span> </span></div>'; |
| 730 |
} |
| 731 |
} |
| 732 |
} |
| 733 |
echo $critical_note; |
| 734 |
?> |
| 735 |
</td> |
| 736 |
<?php |
| 737 |
} |
| 738 |
|
| 739 |
// iterate to next day |
| 740 |
$moncurts = getdate(mktime(0, 0, 0, $moncurts['mon'], ($moncurts['mday'] + 1), $moncurts['year'])); |
| 741 |
} |
| 742 |
|
| 743 |
// room row parsed, check if we have to parse a sub-unit next |
| 744 |
if (!$is_subunit && $room_bids_pool && isset($rooms_features_map[$room['id']])) { |
| 745 |
// load bookings for distinctive features when parsing the parent $room array |
| 746 |
$room_indexes_bids = VikBooking::loadRoomIndexesBookings($room['id'], $room_bids_pool); |
| 747 |
if ($room_indexes_bids) { |
| 748 |
$rooms_features_bookings[$room['id']] = $room_indexes_bids; |
| 749 |
$rooms_bids_pools[$room['id']] = $room_bids_pool; |
| 750 |
// map sub-unit room bookings |
| 751 |
foreach ($room_indexes_bids as $rindex => $rindex_bids) { |
| 752 |
if (!is_array($rindex_bids) || !$rindex_bids) { |
| 753 |
continue; |
| 754 |
} |
| 755 |
foreach ($rindex_bids as $seek_bid) { |
| 756 |
foreach ($room_bookings as $day_key => $day_ress) { |
| 757 |
foreach ($day_ress as $day_res) { |
| 758 |
if ($day_res['idorder'] != $seek_bid) { |
| 759 |
continue; |
| 760 |
} |
| 761 |
if (!isset($room_bookings_pool[$room['id']])) { |
| 762 |
$room_bookings_pool[$room['id']] = []; |
| 763 |
} |
| 764 |
if (!isset($room_bookings_pool[$room['id']][$day_key])) { |
| 765 |
$room_bookings_pool[$room['id']][$day_key] = []; |
| 766 |
} |
| 767 |
$room_bookings_pool[$room['id']][$day_key][$rindex] = $day_res; |
| 768 |
} |
| 769 |
} |
| 770 |
} |
| 771 |
} |
| 772 |
} |
| 773 |
} |
| 774 |
|
| 775 |
// close row |
| 776 |
?> |
| 777 |
</tr> |
| 778 |
<?php |
| 779 |
} |
| 780 |
?> |
| 781 |
</tbody> |
| 782 |
</table> |
| 783 |
</div> |
| 784 |
</div> |
| 785 |
<?php |
| 786 |
// iterate to next month |
| 787 |
$curts = getdate(mktime(0, 0, 0, ($nowts['mon'] + $mind), $nowts['mday'], $nowts['year'])); |
| 788 |
} |
| 789 |
|
| 790 |
//Prepare modal |
| 791 |
?> |
| 792 |
<script type="text/javascript"> |
| 793 |
var hasNewBooking = false; |
| 794 |
var last_room_click = '', |
| 795 |
last_date_click = '', |
| 796 |
next_date_click = ''; |
| 797 |
function vboJModalHideCallback() { |
| 798 |
if (hasNewBooking === true) { |
| 799 |
location.reload(); |
| 800 |
} |
| 801 |
} |
| 802 |
function vboCallOpenJModal(identif, baseurl) { |
| 803 |
if (last_room_click && last_room_click.length) { |
| 804 |
baseurl += '&cid[]='+last_room_click; |
| 805 |
last_room_click = ''; |
| 806 |
} |
| 807 |
if (last_date_click && last_date_click.length) { |
| 808 |
baseurl += '&checkin='+last_date_click; |
| 809 |
last_date_click = ''; |
| 810 |
} |
| 811 |
if (next_date_click && next_date_click.length) { |
| 812 |
baseurl += '&checkout='+next_date_click; |
| 813 |
next_date_click = ''; |
| 814 |
} |
| 815 |
vboOpenJModal(identif, baseurl); |
| 816 |
} |
| 817 |
</script> |
| 818 |
<?php |
| 819 |
echo $vbo_app->getJmodalScript('', 'vboJModalHideCallback();', ''); |
| 820 |
echo $vbo_app->getJmodalHtml('vbo-new-res', JText::translate('VBOSHOWQUICKRES')); |
| 821 |
//end Prepare modal |
| 822 |
?> |
| 823 |
<div class="vbo-ovrv-flt-butn" onclick="vboCallOpenJModal('vbo-new-res', 'index.php?option=com_vikbooking&task=calendar&overv=1&tmpl=component');"><span><i class="vboicn-user-plus"></i> <?php echo JText::translate('VBOSHOWQUICKRES'); ?></span></div> |
| 824 |
<div class="vbo-info-overlay-block"> |
| 825 |
<div class="vbo-info-overlay-loading-dnd"> |
| 826 |
<span class="vbo-loading-dnd-head"></span> |
| 827 |
<span class="vbo-loading-dnd-body"></span> |
| 828 |
<span class="vbo-loading-dnd-footer"><?php echo JText::translate('VIKLOADING'); ?></span> |
| 829 |
<span id="vbo-dnd-response" class="vbo-loading-dnd-response"></span> |
| 830 |
<canvas id="vbo-dnd-canvas-success" height="250"></canvas> |
| 831 |
</div> |
| 832 |
</div> |
| 833 |
|
| 834 |
<form action="index.php?option=com_vikbooking" method="post" name="adminForm" id="adminForm"> |
| 835 |
<input type="hidden" name="option" value="com_vikbooking" /> |
| 836 |
<input type="hidden" name="task" value="overv" /> |
| 837 |
<input type="hidden" name="month" value="<?php echo $tsstart; ?>" /> |
| 838 |
<input type="hidden" name="mnum" value="<?php echo $mnum; ?>" /> |
| 839 |
<input type="hidden" name="category_id" value="<?php echo $pcategory_id; ?>" /> |
| 840 |
<?php echo '<br/>'.$navbut; ?> |
| 841 |
</form> |
| 842 |
|
| 843 |
<a class="vbo-basenavuri-details" href="index.php?option=com_vikbooking&task=editorder&goto=overv&cid[]=%d" style="display: none;"></a> |
| 844 |
<a class="vbo-basenavuri-edit" href="index.php?option=com_vikbooking&task=editbusy&goto=overv&cid[]=%d" style="display: none;"></a> |
| 845 |
|
| 846 |
<script type="text/Javascript"> |
| 847 |
var hovtimer; |
| 848 |
var hovtip = false; |
| 849 |
var vbodialogorph_on = false; |
| 850 |
var isdragging = false; |
| 851 |
var vboMessages = { |
| 852 |
currencySymb: "<?php echo $currencysymb; ?>" |
| 853 |
}; |
| 854 |
var debug_mode = '<?php echo $pdebug; ?>'; |
| 855 |
var bctags_count = <?php echo count($colortags); ?>; |
| 856 |
var bctags_pool = <?php echo json_encode($colortags); ?>; |
| 857 |
<?php |
| 858 |
if (count($colortags) > 0) { |
| 859 |
$bctags_tip = '<div class=\"vbo-overview-tip-bctag-subtip-inner\">'; |
| 860 |
foreach ($colortags as $ctagk => $ctagv) { |
| 861 |
$bctags_tip .= '<div class=\"vbo-overview-tip-bctag-subtip-circle hasTooltip\" data-ctagkey=\"'.$ctagk.'\" data-ctagcolor=\"'.$ctagv['color'].'\" title=\"'.addslashes(JText::translate($ctagv['name'])).'\"><div class=\"vbo-overview-tip-bctag-subtip-circlecont\" style=\"background-color: '.$ctagv['color'].';\"></div></div>'; |
| 862 |
} |
| 863 |
$bctags_tip .= '</div>'; |
| 864 |
?> |
| 865 |
var bctags_tip = "<?php echo $bctags_tip; ?>"; |
| 866 |
<?php |
| 867 |
} |
| 868 |
?> |
| 869 |
</script> |
| 870 |
|
| 871 |
<script type="text/Javascript"> |
| 872 |
/** |
| 873 |
* Render the units view mode |
| 874 |
*/ |
| 875 |
vboUnitsLeftOrBooked(); |
| 876 |
|
| 877 |
/** |
| 878 |
* Orphans dialog |
| 879 |
*/ |
| 880 |
function hideVboDialogOverv(action) { |
| 881 |
if (vbodialogorph_on === true) { |
| 882 |
jQuery(".vbo-orphans-overlay-block").fadeOut(400, function () { |
| 883 |
jQuery(".vbo-info-overlay-content").show(); |
| 884 |
}); |
| 885 |
vbodialogorph_on = false; |
| 886 |
} |
| 887 |
// check action |
| 888 |
if (action < 0) { |
| 889 |
// stop reminding, set cookie |
| 890 |
var nd = new Date(); |
| 891 |
nd.setTime(nd.getTime() + (365*24*60*60*1000)); |
| 892 |
document.cookie = "vboHideOrphans=1; expires=" + nd.toUTCString() + "; path=/; SameSite=Lax"; |
| 893 |
} |
| 894 |
} |
| 895 |
|
| 896 |
/* DnD global vars */ |
| 897 |
var cellspool = []; |
| 898 |
var newcellspool = []; |
| 899 |
|
| 900 |
/* DnD Count the number of consecutive cells for this booking */ |
| 901 |
function countBookingCells(cellobj, bidstart, roomid) { |
| 902 |
var totnights = 1; |
| 903 |
var loop = true; |
| 904 |
var cellelem = cellobj; |
| 905 |
cellspool.push(cellelem); |
| 906 |
while (loop === true) { |
| 907 |
var next = cellelem.next('td'); |
| 908 |
if (next === undefined || !next.length) { |
| 909 |
//attempt to go to the month after |
| 910 |
var partable = cellelem.closest('tr').closest('table').nextAll('table.vboverviewtable').first(); |
| 911 |
var nextmonth = false; |
| 912 |
if (partable !== undefined && partable.length) { |
| 913 |
partable.find('tr.vboverviewtablerow').each(function() { |
| 914 |
var roomexists = jQuery(this).find('td').first(); |
| 915 |
if (roomexists !== undefined && roomexists.length) { |
| 916 |
if (roomexists.attr('data-roomid') == roomid) { |
| 917 |
nextmonth = true; |
| 918 |
next = roomexists.next('td'); |
| 919 |
return true; |
| 920 |
} |
| 921 |
} |
| 922 |
}); |
| 923 |
} |
| 924 |
if (nextmonth === false) { |
| 925 |
//nothing was found in the month after |
| 926 |
loop = false; |
| 927 |
break; |
| 928 |
} |
| 929 |
} |
| 930 |
cellelem = next; |
| 931 |
var nextbids = cellelem.attr('data-bids'); |
| 932 |
if (nextbids.length && nextbids.indexOf(bidstart) >= 0) { |
| 933 |
cellspool.push(cellelem); |
| 934 |
totnights++; |
| 935 |
} else { |
| 936 |
loop = false; |
| 937 |
break; |
| 938 |
} |
| 939 |
} |
| 940 |
return totnights; |
| 941 |
} |
| 942 |
|
| 943 |
/* DnD Count the number of consecutive free date-cells for moving the booking onto the landing cell selected for drop */ |
| 944 |
function countCellFreeNights(landobj, roomid, totnights, moving_bids) { |
| 945 |
var freenights = 1; |
| 946 |
var loop = true; |
| 947 |
var cellelem = landobj; |
| 948 |
|
| 949 |
// populate cells pool |
| 950 |
newcellspool.push(cellelem); |
| 951 |
|
| 952 |
while (loop === true) { |
| 953 |
var next = cellelem.next('td'); |
| 954 |
if (next === undefined || !next.length) { |
| 955 |
// attempt to go to the month after |
| 956 |
var partable = cellelem.closest('tr').closest('table').nextAll('table.vboverviewtable').first(); |
| 957 |
var nextmonth = false; |
| 958 |
if (partable !== undefined && partable.length) { |
| 959 |
partable.find('tr.vboverviewtablerow').each(function() { |
| 960 |
var roomexists = jQuery(this).find('td').first(); |
| 961 |
if (roomexists !== undefined && roomexists.length) { |
| 962 |
if (roomexists.attr('data-roomid') == roomid) { |
| 963 |
nextmonth = true; |
| 964 |
next = roomexists.next('td'); |
| 965 |
return true; |
| 966 |
} |
| 967 |
} |
| 968 |
}); |
| 969 |
} |
| 970 |
if (nextmonth === false) { |
| 971 |
// nothing was found in the month after |
| 972 |
loop = false; |
| 973 |
break; |
| 974 |
} |
| 975 |
} |
| 976 |
cellelem = next; |
| 977 |
var cell_bids = cellelem.attr('data-bids'); |
| 978 |
if (!cellelem.hasClass('busy') || (cellelem.hasClass('busy') && cellelem.hasClass('vbo-partially'))) { |
| 979 |
// bookings of 1 night can stop here because there is availability for one day |
| 980 |
if (parseInt(totnights) === 1) { |
| 981 |
loop = false; |
| 982 |
break; |
| 983 |
} |
| 984 |
// push free cell |
| 985 |
newcellspool.push(cellelem); |
| 986 |
freenights++; |
| 987 |
if (freenights >= totnights) { |
| 988 |
loop = false; |
| 989 |
break; |
| 990 |
} |
| 991 |
} else { |
| 992 |
// cell is occupied, check if it's occupied by the booking we are moving or not |
| 993 |
if (!cell_bids || cell_bids != moving_bids) { |
| 994 |
loop = false; |
| 995 |
break; |
| 996 |
} |
| 997 |
// cell is occupied by the same booking we are moving, so this cell counts as free |
| 998 |
newcellspool.push(cellelem); |
| 999 |
freenights++; |
| 1000 |
if (freenights >= totnights) { |
| 1001 |
loop = false; |
| 1002 |
break; |
| 1003 |
} |
| 1004 |
} |
| 1005 |
} |
| 1006 |
|
| 1007 |
return freenights; |
| 1008 |
} |
| 1009 |
|
| 1010 |
/* DnD function to perform the ajax request of the booking modification */ |
| 1011 |
function doAlterBooking(bid, roomid, landrid) { |
| 1012 |
var nowdatefrom = jQuery(newcellspool[0]).attr('data-day'); |
| 1013 |
var nowdateto = jQuery(newcellspool[(newcellspool.length -1)]).attr('data-day'); |
| 1014 |
|
| 1015 |
// perform the request |
| 1016 |
VBOCore.doAjax( |
| 1017 |
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=alterbooking'); ?>", |
| 1018 |
{ |
| 1019 |
tmpl: "component", |
| 1020 |
idorder: bid, |
| 1021 |
oldidroom: roomid, |
| 1022 |
idroom: landrid, |
| 1023 |
fromdate: nowdatefrom, |
| 1024 |
todate: nowdateto, |
| 1025 |
e4j_debug: debug_mode |
| 1026 |
}, |
| 1027 |
(res) => { |
| 1028 |
if (res.indexOf('e4j.error') >= 0 ) { |
| 1029 |
console.log('doAlterBooking-- Booking ID: '+bid+' - Old Room ID: '+roomid+' - New Room ID: '+landrid+' - New Date From: '+nowdatefrom+' - New Date To: '+nowdateto); |
| 1030 |
console.log(res); |
| 1031 |
alert(res.replace("e4j.error.", "")); |
| 1032 |
//restore the old cells |
| 1033 |
jQuery('td.vbo-dragging-cells-tmp').removeClass('vbo-dragging-cells-tmp'); |
| 1034 |
jQuery('td.vbo-dragged-cells-tmp').removeClass('vbo-dragged-cells-tmp'); |
| 1035 |
// |
| 1036 |
jQuery(".vbo-info-overlay-block").hide(); |
| 1037 |
} else { |
| 1038 |
//move to the new cells and if there are already bookings on those dates, reload the page without moving the blocks |
| 1039 |
var obj_res = typeof res === 'string' ? JSON.parse(res) : res; |
| 1040 |
var mustReload = obj_res.esit < 1 ? true : false; |
| 1041 |
//always force reload if booking was made for more than one room |
| 1042 |
var samebidcells = jQuery("td.vbo-checkinday[data-bids='"+bid+"']"); |
| 1043 |
if (samebidcells.length > 1) { |
| 1044 |
mustReload = true; |
| 1045 |
} |
| 1046 |
// |
| 1047 |
jQuery(newcellspool).each(function(k, v) { |
| 1048 |
var cur_units_booked = parseInt(jQuery(cellspool[k]).find('a').parent('td').attr('data-units-booked')); |
| 1049 |
if ((v.hasClass('busy') && v.attr('data-bids') != jQuery(cellspool[k]).attr('data-bids')) || isNaN(cur_units_booked) || cur_units_booked > 1) { |
| 1050 |
mustReload = true; |
| 1051 |
return false; |
| 1052 |
} |
| 1053 |
}); |
| 1054 |
if (mustReload !== true) { |
| 1055 |
/* switch cells */ |
| 1056 |
var switchmap = []; |
| 1057 |
jQuery(cellspool).each(function(k, v) { |
| 1058 |
var switchcell = { |
| 1059 |
hcont: v.html(), |
| 1060 |
cl: v.attr('class'), |
| 1061 |
bids: v.attr('data-bids'), |
| 1062 |
tit: v.attr('title') |
| 1063 |
}; |
| 1064 |
switchmap[k] = switchcell; |
| 1065 |
v.html("").attr('class', 'notbusy').attr('data-bids', '').attr('title', ''); |
| 1066 |
}); |
| 1067 |
jQuery(switchmap).each(function(k, v) { |
| 1068 |
jQuery(newcellspool[k]).html(v.hcont).attr('class', v.cl).attr('data-bids', v.bids).attr('title', v.tit); |
| 1069 |
// re-bind hover event |
| 1070 |
jQuery(newcellspool[k]).hover(function() { |
| 1071 |
registerHoveringTooltip(this); |
| 1072 |
}, unregisterHoveringTooltip); |
| 1073 |
// |
| 1074 |
}); |
| 1075 |
jQuery('td.vbo-dragging-cells-tmp').removeClass('vbo-dragging-cells-tmp'); |
| 1076 |
jQuery('td.vbo-dragged-cells-tmp').removeClass('vbo-dragged-cells-tmp'); |
| 1077 |
} |
| 1078 |
if (obj_res.esit < 1) { |
| 1079 |
//some errors occurred after executing certain functions |
| 1080 |
if (obj_res.message.length) { |
| 1081 |
alert(obj_res.message); |
| 1082 |
} |
| 1083 |
document.location.href='index.php?option=com_vikbooking&task=overv'; |
| 1084 |
} else { |
| 1085 |
finalizeDndUpdate(mustReload, obj_res); |
| 1086 |
} |
| 1087 |
} |
| 1088 |
}, |
| 1089 |
(err) => { |
| 1090 |
alert("Request Failed"); |
| 1091 |
// restore the old cells |
| 1092 |
jQuery('td.vbo-dragging-cells-tmp').removeClass('vbo-dragging-cells-tmp'); |
| 1093 |
jQuery('td.vbo-dragged-cells-tmp').removeClass('vbo-dragged-cells-tmp'); |
| 1094 |
// |
| 1095 |
jQuery(".vbo-info-overlay-block").hide(); |
| 1096 |
} |
| 1097 |
); |
| 1098 |
} |
| 1099 |
|
| 1100 |
/* DnD function to animate a success checkmark. The function may refresh the page once complete as this could be launched when there are multiple units for the rooms */ |
| 1101 |
function finalizeDndUpdate(mustReload, obj_res) { |
| 1102 |
jQuery('#vbo-dnd-response').html(obj_res.message+' '+obj_res.vcm); |
| 1103 |
jQuery('.vbo-loading-dnd-footer').hide(); |
| 1104 |
var start = 100; |
| 1105 |
var mid = 145; |
| 1106 |
var end = 250; |
| 1107 |
var width = 22; |
| 1108 |
var leftX = start; |
| 1109 |
var leftY = start; |
| 1110 |
var rightX = mid - (width / 2.7); |
| 1111 |
var rightY = mid + (width / 2.7); |
| 1112 |
var animationSpeed = 20; |
| 1113 |
var closingdelay = 700; |
| 1114 |
var ctx = document.getElementById('vbo-dnd-canvas-success').getContext('2d'); |
| 1115 |
ctx.lineWidth = width; |
| 1116 |
ctx.strokeStyle = 'rgba(0, 150, 0, 1)'; |
| 1117 |
for (var i = start; i < mid; i++) { |
| 1118 |
var drawLeft = window.setTimeout(function () { |
| 1119 |
ctx.beginPath(); |
| 1120 |
ctx.moveTo(start, start); |
| 1121 |
ctx.lineTo(leftX, leftY); |
| 1122 |
ctx.stroke(); |
| 1123 |
leftX++; |
| 1124 |
leftY++; |
| 1125 |
}, 1 + (i * animationSpeed) / 3); |
| 1126 |
} |
| 1127 |
for (var i = mid; i < end; i++) { |
| 1128 |
var drawRight = window.setTimeout(function () { |
| 1129 |
ctx.beginPath(); |
| 1130 |
ctx.moveTo(leftX, leftY); |
| 1131 |
ctx.lineTo(rightX, rightY); |
| 1132 |
ctx.stroke(); |
| 1133 |
rightX++; |
| 1134 |
rightY--; |
| 1135 |
}, 1 + (i * animationSpeed) / 3); |
| 1136 |
} |
| 1137 |
//hide modal window |
| 1138 |
window.setTimeout(function () { |
| 1139 |
if (obj_res.vcm.length) { |
| 1140 |
var vcmbtn = '<br clear="all"/><button type="button" class="btn btn-danger" onclick="'+(mustReload === true ? 'document.location.href=\'index.php?option=com_vikbooking&task=overv\'' : 'closeEsitDialog();')+'">' + Joomla.JText._('VBANNULLA') + '</button>'; |
| 1141 |
jQuery('#vbo-dnd-response').append(vcmbtn); |
| 1142 |
} else { |
| 1143 |
if (mustReload === true) { |
| 1144 |
document.location.href='index.php?option=com_vikbooking&task=overv'; |
| 1145 |
} else { |
| 1146 |
jQuery('.vbo-info-overlay-block').fadeOut(400, function(){ |
| 1147 |
//clear/reset canvas in case of previous drawing and response text |
| 1148 |
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); |
| 1149 |
jQuery('#vbo-dnd-response').html(""); |
| 1150 |
// |
| 1151 |
}); |
| 1152 |
} |
| 1153 |
} |
| 1154 |
}, closingdelay + (i * animationSpeed) / 3); |
| 1155 |
// |
| 1156 |
} |
| 1157 |
|
| 1158 |
/* DnD function that can be called by those with VCM that have disabled the automated updates. Simply closes the modal window */ |
| 1159 |
function closeEsitDialog() { |
| 1160 |
jQuery('.vbo-info-overlay-block').fadeOut(400, function(){ |
| 1161 |
//clear/reset canvas in case of previous drawing and response text |
| 1162 |
var ctx = document.getElementById('vbo-dnd-canvas-success').getContext('2d'); |
| 1163 |
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); |
| 1164 |
jQuery('#vbo-dnd-response').html(""); |
| 1165 |
// |
| 1166 |
}); |
| 1167 |
} |
| 1168 |
|
| 1169 |
/* Hover Tooltip functions */ |
| 1170 |
function registerHoveringTooltip(that) { |
| 1171 |
if (hovtip) { |
| 1172 |
return false; |
| 1173 |
} |
| 1174 |
if (hovtimer) { |
| 1175 |
clearTimeout(hovtimer); |
| 1176 |
hovtimer = null; |
| 1177 |
} |
| 1178 |
var elem = jQuery(that); |
| 1179 |
var cellheight = elem.outerHeight(); |
| 1180 |
var celldata = new Array(); |
| 1181 |
if (elem.hasClass('subroom-busy')) { |
| 1182 |
celldata.push(elem.parent('tr').attr('data-subroomid')); |
| 1183 |
celldata.push(elem.attr('data-day')); |
| 1184 |
} |
| 1185 |
hovtimer = setTimeout(() => { |
| 1186 |
if (isdragging) { |
| 1187 |
// prevent tooltip from popping up if dragging |
| 1188 |
unregisterHoveringTooltip(); |
| 1189 |
|
| 1190 |
return; |
| 1191 |
} |
| 1192 |
|
| 1193 |
// turn flag on |
| 1194 |
hovtip = true; |
| 1195 |
|
| 1196 |
// set default content |
| 1197 |
jQuery( |
| 1198 |
"<div class=\"vbo-overview-tipblock\">" + |
| 1199 |
"<div class=\"vbo-overview-tipinner\"><span class=\"vbo-overview-tiploading\">" + Joomla.JText._('VIKLOADING') + "</span></div>" + |
| 1200 |
"<div class=\"vbo-overview-tipexpander\" style=\"display: none;\"><div class=\"vbo-overview-expandtoggle\"><i class=\"<?php echo VikBookingIcons::i('expand'); ?>\"></i></div></div>" + |
| 1201 |
"</div>" |
| 1202 |
).appendTo(elem); |
| 1203 |
|
| 1204 |
// set default bottom value to have the tooptip displayed above the cell |
| 1205 |
jQuery(".vbo-overview-tipblock").css("bottom", "+=" + cellheight); |
| 1206 |
|
| 1207 |
// load tooltip bookings |
| 1208 |
loadTooltipBookings(elem.attr('data-bids'), celldata); |
| 1209 |
}, 1500); |
| 1210 |
} |
| 1211 |
|
| 1212 |
function unregisterHoveringTooltip() { |
| 1213 |
clearTimeout(hovtimer); |
| 1214 |
hovtimer = null; |
| 1215 |
} |
| 1216 |
|
| 1217 |
function adjustHoveringTooltip() { |
| 1218 |
setTimeout(() => { |
| 1219 |
var ver_difflim = 35; |
| 1220 |
var hor_difflim = 20; |
| 1221 |
var tip_block = jQuery('.vbo-overview-tipblock'); |
| 1222 |
if (!tip_block || !tip_block.length) { |
| 1223 |
return; |
| 1224 |
} |
| 1225 |
var table_wrap = tip_block.closest('.vbo-overv-montable-wrap'); |
| 1226 |
|
| 1227 |
if (tip_block.outerHeight() > table_wrap.outerHeight()) { |
| 1228 |
// tooltip is too tall to fit in the table, render the modal instead |
| 1229 |
tip_block.hide().closest('td.busy').trigger('click'); |
| 1230 |
return; |
| 1231 |
} |
| 1232 |
|
| 1233 |
// vertical positioning |
| 1234 |
var otop = tip_block.offset().top; |
| 1235 |
if (otop > 0 && otop < ver_difflim) { |
| 1236 |
// adjust tooltip position |
| 1237 |
tip_block.css('bottom', '-=' + (ver_difflim - otop)); |
| 1238 |
} else if (otop < table_wrap.offset().top) { |
| 1239 |
// tooltip exceeds wrapping table, move it underneath the cell |
| 1240 |
var extra_padding_top = 0; |
| 1241 |
var tip_inner_padtop = tip_block.find('.vbo-overview-tipinner').css('padding-top'); |
| 1242 |
if (tip_inner_padtop) { |
| 1243 |
// get only numbers |
| 1244 |
extra_padding_top = tip_inner_padtop.replace(/[^0-9]/g, ''); |
| 1245 |
extra_padding_top = !isNaN(extra_padding_top) ? parseInt(extra_padding_top) : 0; |
| 1246 |
} |
| 1247 |
tip_block.css('bottom', 'auto').css('top', (tip_block.parent('td').outerHeight() - extra_padding_top)); |
| 1248 |
} |
| 1249 |
|
| 1250 |
// horizontal positioning |
| 1251 |
if (tip_block.offset().left < table_wrap.offset().left) { |
| 1252 |
var left_diff = table_wrap.offset().left - tip_block.offset().left; |
| 1253 |
if (left_diff > hor_difflim) { |
| 1254 |
// tooltip exceeds table on the left, move it to the right of the cell (i.e 1st day of month) |
| 1255 |
tip_block.css('right', tip_block.css('left')); |
| 1256 |
tip_block.css('left', 'unset'); |
| 1257 |
} |
| 1258 |
} |
| 1259 |
}, 60); |
| 1260 |
} |
| 1261 |
|
| 1262 |
function hideVboTooltip() { |
| 1263 |
jQuery('.vbo-overview-tipblock').remove(); |
| 1264 |
hovtip = false; |
| 1265 |
} |
| 1266 |
|
| 1267 |
function loadTooltipBookings(bids, celldata) { |
| 1268 |
if (!bids || bids === undefined || !bids.length) { |
| 1269 |
hideVboTooltip(); |
| 1270 |
return false; |
| 1271 |
} |
| 1272 |
|
| 1273 |
var subroomdata = celldata.length ? celldata[0] : ''; |
| 1274 |
|
| 1275 |
// perform the request |
| 1276 |
VBOCore.doAjax( |
| 1277 |
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=getbookingsinfo'); ?>", |
| 1278 |
{ |
| 1279 |
tmpl: "component", |
| 1280 |
idorders: bids, |
| 1281 |
subroom: subroomdata |
| 1282 |
}, |
| 1283 |
(res) => { |
| 1284 |
try { |
| 1285 |
var obj_res = typeof res === 'string' ? JSON.parse(res) : res; |
| 1286 |
jQuery('.vbo-overview-tiploading').remove(); |
| 1287 |
var container = jQuery('.vbo-overview-tipinner'); |
| 1288 |
jQuery(obj_res).each(function(k, v) { |
| 1289 |
// get base navigation URIs |
| 1290 |
var base_uri_details = jQuery('.vbo-basenavuri-details').attr('href'); |
| 1291 |
var base_uri_edit = jQuery('.vbo-basenavuri-edit').attr('href'); |
| 1292 |
|
| 1293 |
// build content |
| 1294 |
var bcont = "<div class=\"vbo-overview-tip-bookingcont\">"; |
| 1295 |
bcont += "<div class=\"vbo-overview-tip-bookingcont-left\">"; |
| 1296 |
bcont += "<div class=\"vbo-overview-tip-bid\"><span class=\"vbo-overview-tip-lbl\">ID <span class=\"vbo-overview-tip-lbl-innerleft\"><a href=\"" + base_uri_edit.replace('%d', v.id) + "\"><i class=\"<?php echo VikBookingIcons::i('edit'); ?>\"></i></a></span></span><span class=\"vbo-overview-tip-cnt\">"+v.id+"</span></div>"; |
| 1297 |
bcont += "<div class=\"vbo-overview-tip-bstatus\"><span class=\"vbo-overview-tip-lbl\"><?php echo addslashes(JText::translate('VBPVIEWORDERSEIGHT')); ?></span><span class=\"vbo-overview-tip-cnt\"><div class=\"label "+(v.status == 'confirmed' ? 'label-success' : 'label-warning')+"\">"+v.status_lbl+"</div></span></div>"; |
| 1298 |
bcont += "<div class=\"vbo-overview-tip-bdate\"><span class=\"vbo-overview-tip-lbl\"><?php echo addslashes(JText::translate('VBPVIEWORDERSONE')); ?></span><span class=\"vbo-overview-tip-cnt\"><a href=\"" + base_uri_details.replace('%d', v.id) + "\">"+v.ts+"</a></span></div>"; |
| 1299 |
if (bctags_count > 0) { |
| 1300 |
var bctag_title = ''; |
| 1301 |
var bctag_color = '#ffffff'; |
| 1302 |
if (v.colortag.hasOwnProperty('color')) { |
| 1303 |
bctag_color = v.colortag.color; |
| 1304 |
bctag_title = v.colortag.name; |
| 1305 |
} |
| 1306 |
bcont += "<div class=\"vbo-overview-tip-bctag-wrap\"><div class=\"vbo-overview-tip-bctag\" data-bid=\""+v.id+"\" data-ctagcolor=\""+bctag_color+"\" style=\"background-color: "+bctag_color+"; color: "+v.colortag.fontcolor+";\" title=\""+bctag_title+"\"><i class=\"vboicn-price-tags\"></i></div></div>"; |
| 1307 |
} |
| 1308 |
bcont += "</div>"; |
| 1309 |
bcont += "<div class=\"vbo-overview-tip-bookingcont-right\">"; |
| 1310 |
bcont += "<div class=\"vbo-overview-tip-bcustomer\"><span class=\"vbo-overview-tip-lbl\"><?php echo addslashes(JText::translate('VBOCUSTOMER')); ?></span><span class=\"vbo-overview-tip-cnt\">"+v.cinfo+"</span></div>"; |
| 1311 |
if (v.roomsnum > 1) { |
| 1312 |
bcont += "<div class=\"vbo-overview-tip-brooms\"><span class=\"vbo-overview-tip-lbl\">" + Joomla.JText._('VBEDITORDERROOMSNUM') + (parseInt(v.roomsnum) > 1 ? " (" + v.roomsnum + ")" : "") + "</span><span class=\"vbo-overview-tip-cnt\">" + v.room_names + "</span></div>"; |
| 1313 |
} |
| 1314 |
bcont += "<div class=\"vbo-overview-tip-bguests\"><span class=\"vbo-overview-tip-lbl\">" + Joomla.JText._('VBDAYS') + (v.split_stay > 0 ? ' (' + Joomla.JText._('VBO_SPLIT_STAY') + ')' : '') + "</span><span class=\"vbo-overview-tip-cnt hasTooltip\" title=\"" + Joomla.JText._('VBPICKUPAT') + " " + v.checkin + " - " + Joomla.JText._('VBRELEASEAT') + " " + v.checkout + "\">" + v.days + ", " + Joomla.JText._('VBEDITORDERADULTS') + ": " + v.tot_adults + (v.tot_children > 0 ? ", " + Joomla.JText._('VBEDITORDERCHILDREN') + ": " + v.tot_children : "") + "</span></div>"; |
| 1315 |
if (v.hasOwnProperty('rindexes')) { |
| 1316 |
for (var rindexk in v.rindexes) { |
| 1317 |
if (v.rindexes.hasOwnProperty(rindexk)) { |
| 1318 |
bcont += "<div class=\"vbo-overview-tip-brindexes\"><span class=\"vbo-overview-tip-lbl\">" + rindexk + "</span><span class=\"vbo-overview-tip-cnt\">" + v.rindexes[rindexk] + "</span></div>"; |
| 1319 |
} |
| 1320 |
} |
| 1321 |
} |
| 1322 |
if (v.hasOwnProperty('channelimg')) { |
| 1323 |
bcont += "<div class=\"vbo-overview-tip-bprovenience\"><span class=\"vbo-overview-tip-lbl\">" + Joomla.JText._('VBPVIEWORDERCHANNEL') + "</span><span class=\"vbo-overview-tip-cnt\">" + v.channelimg + "</span></div>"; |
| 1324 |
} |
| 1325 |
if (v.hasOwnProperty('optindexes') && celldata.length) { |
| 1326 |
var subroomids = celldata[0].split('-'); |
| 1327 |
bcont += "<div class=\"vbo-overview-tip-optindexes\"><span class=\"vbo-overview-tip-lbl\"> </span><span class=\"vbo-overview-tip-cnt\"><select onchange=\"vboMoveSubunit('" + v.id + "', '" + subroomids[0] + "', '" + subroomids[1] + "', this.value, '" + celldata[1] + "');\">" + v.optindexes + "</select></span></div>"; |
| 1328 |
} |
| 1329 |
bcont += "<div class=\"vbo-overview-tip-bookingcont-total\">"; |
| 1330 |
bcont += "<div class=\"vbo-overview-tip-btot\"><span class=\"vbo-overview-tip-lbl\">" + Joomla.JText._('VBEDITORDERNINE') + "</span><span class=\"vbo-overview-tip-cnt\">" + vboMessages.currencySymb + " " + v.format_tot + "</span></div>"; |
| 1331 |
if (v.totpaid > 0.00) { |
| 1332 |
bcont += "<div class=\"vbo-overview-tip-btot\"><span class=\"vbo-overview-tip-lbl\">" + Joomla.JText._('VBPEDITBUSYTOTPAID') + "</span><span class=\"vbo-overview-tip-cnt\">" + vboMessages.currencySymb + " " + v.format_totpaid + "</span></div>"; |
| 1333 |
} |
| 1334 |
var getnotes = v.adminnotes; |
| 1335 |
if (getnotes !== null && getnotes.length) { |
| 1336 |
bcont += "<div class=\"vbo-overview-tip-notes\"><span class=\"vbo-overview-tip-lbl\"><span class=\"vbo-overview-tip-notes-inner\"><i class=\"vboicn-info hasTooltip\" title=\"" + getnotes + "\"></i></span></span></div>"; |
| 1337 |
} |
| 1338 |
bcont += "</div>"; |
| 1339 |
bcont += "</div>"; |
| 1340 |
bcont += "</div>"; |
| 1341 |
container.append(bcont); |
| 1342 |
jQuery('.vbo-overview-tipexpander').show(); |
| 1343 |
}); |
| 1344 |
// adjust the position so that it won't go under other contents |
| 1345 |
adjustHoveringTooltip() |
| 1346 |
// |
| 1347 |
jQuery(".hasTooltip").tooltip(); |
| 1348 |
} catch(err) { |
| 1349 |
// restore |
| 1350 |
hideVboTooltip(); |
| 1351 |
// display error |
| 1352 |
console.error('could not parse JSON response', err, res); |
| 1353 |
alert('Could not parse JSON response'); |
| 1354 |
} |
| 1355 |
}, |
| 1356 |
(err) => { |
| 1357 |
// restore |
| 1358 |
hideVboTooltip(); |
| 1359 |
// display error |
| 1360 |
console.error(err); |
| 1361 |
alert(err.responseText); |
| 1362 |
} |
| 1363 |
); |
| 1364 |
} |
| 1365 |
|
| 1366 |
/** |
| 1367 |
* Set a sub-unit to a room booking. Triggered by the room-day bookings modal |
| 1368 |
*/ |
| 1369 |
function vboSetSubunit(bid, rid, orkey, rindex) { |
| 1370 |
if (!(rindex + '').length) { |
| 1371 |
return false; |
| 1372 |
} |
| 1373 |
|
| 1374 |
if (!confirm(Joomla.JText._('VBOFEATASSIGNUNIT') + rindex + '?')) { |
| 1375 |
return false; |
| 1376 |
} |
| 1377 |
|
| 1378 |
// show loading |
| 1379 |
VBOCore.emitEvent('vbo-loading-modal-overv-rdaybookings'); |
| 1380 |
|
| 1381 |
// make the request to set the room sub-unit |
| 1382 |
VBOCore.doAjax( |
| 1383 |
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=bookings.set_room_booking_subunit'); ?>", |
| 1384 |
{ |
| 1385 |
bid: bid, |
| 1386 |
rid: rid, |
| 1387 |
orkey: orkey, |
| 1388 |
rindex: rindex, |
| 1389 |
tmpl: 'component' |
| 1390 |
}, |
| 1391 |
(res) => { |
| 1392 |
// dismiss the modal (no need to stop the loading) |
| 1393 |
VBOCore.emitEvent('vbo-dismiss-modal-overv-rdaybookings'); |
| 1394 |
|
| 1395 |
try { |
| 1396 |
var obj_res = typeof res === 'string' ? JSON.parse(res) : res; |
| 1397 |
if (!obj_res.hasOwnProperty('nights') || !Array.isArray(obj_res['nights']) || !obj_res['nights'].length) { |
| 1398 |
// invalid response |
| 1399 |
throw new Error('Invalid response'); |
| 1400 |
} |
| 1401 |
|
| 1402 |
// check if cells can be occupied |
| 1403 |
var sub_rows = jQuery('tr.vboverviewtablerow-subunit[data-subroomid="' + rid + '-' + rindex + '"]'); |
| 1404 |
if (!sub_rows || !sub_rows.length) { |
| 1405 |
console.error('Could not find any room sub-unit row'); |
| 1406 |
return false; |
| 1407 |
} |
| 1408 |
|
| 1409 |
// loop through all sub-unit rows to match the cells for the nights affected |
| 1410 |
sub_rows.each(function() { |
| 1411 |
var sub_row = jQuery(this); |
| 1412 |
obj_res['nights'].forEach((ymd, kindex) => { |
| 1413 |
let sub_row_cell = sub_row.find('td[data-day="' + ymd + '"]'); |
| 1414 |
if (sub_row_cell.length) { |
| 1415 |
sub_row_cell.removeClass('subnotbusy').addClass('subroom-busy'); |
| 1416 |
if (kindex == 0) { |
| 1417 |
sub_row_cell.addClass('vbo-checkinday'); |
| 1418 |
} |
| 1419 |
sub_row_cell.attr('data-bids', '-' + obj_res['bid'] + '-'); |
| 1420 |
if (!sub_row_cell.find('span.vbo-draggable-sp').length) { |
| 1421 |
sub_row_cell.prepend('<span class="vbo-draggable-sp"><a class="vbo-overview-subredday">•</a></span>'); |
| 1422 |
} |
| 1423 |
} |
| 1424 |
}); |
| 1425 |
}); |
| 1426 |
} catch(err) { |
| 1427 |
console.error('could not parse JSON response', err, res); |
| 1428 |
alert('Could not parse JSON response'); |
| 1429 |
} |
| 1430 |
}, |
| 1431 |
(err) => { |
| 1432 |
// stop loading |
| 1433 |
VBOCore.emitEvent('vbo-loading-modal-overv-rdaybookings'); |
| 1434 |
|
| 1435 |
// log and display the error |
| 1436 |
console.error(err); |
| 1437 |
alert(err.responseText); |
| 1438 |
} |
| 1439 |
); |
| 1440 |
} |
| 1441 |
|
| 1442 |
/** |
| 1443 |
* Move a subunit group of cells to another subroom row. Triggered by the Hover Tooltip, by the room-day bookings modal, or by DnD. |
| 1444 |
*/ |
| 1445 |
function vboMoveSubunit(bid, rid, old_rindex, new_rindex, dday) { |
| 1446 |
if (!confirm(Joomla.JText._('VBOFEATASSIGNUNIT') + new_rindex.replace('#', '') + '?')) { |
| 1447 |
return false; |
| 1448 |
} |
| 1449 |
// check if movement can be made |
| 1450 |
var cur_tr = jQuery('tr.vboverviewtablerow-subunit[data-subroomid="' + rid + '-' + old_rindex + '"]'); |
| 1451 |
if (!cur_tr || !cur_tr.length) { |
| 1452 |
console.error('could not find the parent row of the subunit cells'); |
| 1453 |
return false; |
| 1454 |
} |
| 1455 |
var maincell = cur_tr.find('td.subroom-busy[data-day="' + dday + '"]'); |
| 1456 |
if (!maincell || !maincell.length) { |
| 1457 |
console.error('could not find the main cell of the subunit to move'); |
| 1458 |
return false; |
| 1459 |
} |
| 1460 |
var dest_tr = jQuery('tr.vboverviewtablerow-subunit[data-subroomid="' + rid + '-' + new_rindex + '"]'); |
| 1461 |
if (!dest_tr || !dest_tr.length) { |
| 1462 |
console.error('could not find the destination row for the subunit cells'); |
| 1463 |
return false; |
| 1464 |
} |
| 1465 |
var targetbids = maincell.attr('data-bids'); |
| 1466 |
if (targetbids.indexOf('-' + bid + '-') < 0) { |
| 1467 |
console.error('given bid does not match with cell bids', bid, targetbids); |
| 1468 |
return false; |
| 1469 |
} |
| 1470 |
var firstcell = maincell; |
| 1471 |
var loop = true; |
| 1472 |
while (loop === true) { |
| 1473 |
var prevsib = firstcell.prev(); |
| 1474 |
if (prevsib && prevsib.length && prevsib.attr('data-bids') && prevsib.attr('data-bids').indexOf('-' + bid + '-') >= 0) { |
| 1475 |
firstcell = prevsib; |
| 1476 |
} else { |
| 1477 |
loop = false; |
| 1478 |
} |
| 1479 |
} |
| 1480 |
// make sure to get the check-in day (first cell) |
| 1481 |
dday = firstcell.attr('data-day'); |
| 1482 |
var destcell = dest_tr.find('td.subnotbusy[data-day="' + dday + '"]'); |
| 1483 |
if (!destcell || !destcell.length) { |
| 1484 |
// first destination cell is occupied, check if swap is allowed |
| 1485 |
if (dest_tr.find('td.subroom-busy[data-day="' + dday + '"]').length) { |
| 1486 |
var landbids = dest_tr.find('td.subroom-busy[data-day="' + dday + '"]').attr('data-bids'); |
| 1487 |
return vboSwapRoomSubunits(bid, landbids.replaceAll('-', ''), rid, old_rindex, new_rindex, dday); |
| 1488 |
} |
| 1489 |
console.error('could not find the first free destination cell'); |
| 1490 |
return false; |
| 1491 |
} |
| 1492 |
// check if all dates are free before making movements. Redundant, but useful. |
| 1493 |
var freedates = true; |
| 1494 |
var copyfirstcell = firstcell; |
| 1495 |
var copydday = dday; |
| 1496 |
loop = true; |
| 1497 |
while (loop === true) { |
| 1498 |
var nextsib = copyfirstcell.next(); |
| 1499 |
if (nextsib && nextsib.length && nextsib.attr('data-bids') && nextsib.attr('data-bids').indexOf('-' + bid + '-') >= 0) { |
| 1500 |
copyfirstcell = nextsib; |
| 1501 |
copydday = copyfirstcell.attr('data-day'); |
| 1502 |
var copydestcell = dest_tr.find('td.subnotbusy[data-day="' + copydday + '"]'); |
| 1503 |
if (!copydestcell || !copydestcell.length) { |
| 1504 |
console.error('could not find the next free destination cell for ' + copydday); |
| 1505 |
freedates = false; |
| 1506 |
loop = false; |
| 1507 |
} |
| 1508 |
} else { |
| 1509 |
loop = false; |
| 1510 |
} |
| 1511 |
} |
| 1512 |
if (freedates === false) { |
| 1513 |
return false; |
| 1514 |
} |
| 1515 |
|
| 1516 |
// loading opacity |
| 1517 |
jQuery('.vbo-overview-tipblock').css('opacity', '0.6'); |
| 1518 |
|
| 1519 |
// perform the request |
| 1520 |
VBOCore.doAjax( |
| 1521 |
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=switchRoomIndex'); ?>", |
| 1522 |
{ |
| 1523 |
tmpl: "component", |
| 1524 |
bid: bid, |
| 1525 |
rid: rid, |
| 1526 |
old_rindex: old_rindex, |
| 1527 |
new_rindex: new_rindex |
| 1528 |
}, |
| 1529 |
(res) => { |
| 1530 |
if (res.indexOf('e4j.error') >= 0 ) { |
| 1531 |
console.log(res); |
| 1532 |
alert(res.replace("e4j.error.", "")); |
| 1533 |
|
| 1534 |
// restore loading opacity in container |
| 1535 |
jQuery('.vbo-overview-tipblock').css('opacity', '1'); |
| 1536 |
|
| 1537 |
// abort |
| 1538 |
return; |
| 1539 |
} |
| 1540 |
|
| 1541 |
// hide tooltip |
| 1542 |
hideVboTooltip(); |
| 1543 |
|
| 1544 |
// loop for moving cells |
| 1545 |
loop = true; |
| 1546 |
while (loop === true) { |
| 1547 |
// populate destination cell attributes, classes and content |
| 1548 |
destcell.removeClass('subnotbusy').addClass('subroom-busy').attr('data-bids', firstcell.attr('data-bids')); |
| 1549 |
if (firstcell.hasClass('vbo-checkinday')) { |
| 1550 |
firstcell.removeClass('vbo-checkinday'); |
| 1551 |
destcell.addClass('vbo-checkinday'); |
| 1552 |
} |
| 1553 |
firstcell.children().not('.vbo-tableaux-booking-checkout').not('.vbo-roomdaynote-trigger').appendTo(destcell); |
| 1554 |
|
| 1555 |
// re-bind hover event for tooltip |
| 1556 |
jQuery(destcell).hover(function() { |
| 1557 |
registerHoveringTooltip(this); |
| 1558 |
}, unregisterHoveringTooltip); |
| 1559 |
|
| 1560 |
// clean up the previous cell from which we moved data |
| 1561 |
firstcell.removeClass('subroom-busy').addClass('subnotbusy').attr('data-bids', ''); |
| 1562 |
|
| 1563 |
// check if we have a next iteration to perform |
| 1564 |
var nextsib = firstcell.next(); |
| 1565 |
if (nextsib && nextsib.length && nextsib.attr('data-bids') && nextsib.attr('data-bids').indexOf('-' + bid + '-') >= 0) { |
| 1566 |
// prepare data for the next iteration |
| 1567 |
firstcell = nextsib; |
| 1568 |
dday = firstcell.attr('data-day'); |
| 1569 |
destcell = dest_tr.find('td.subnotbusy[data-day="' + dday + '"]'); |
| 1570 |
if (!destcell || !destcell.length) { |
| 1571 |
console.error('could not find the next free destination cell'); |
| 1572 |
loop = false; |
| 1573 |
} |
| 1574 |
} else { |
| 1575 |
// all cells were moved, break the loop |
| 1576 |
loop = false; |
| 1577 |
// check if we need to move the checkout snake as well |
| 1578 |
if (nextsib && nextsib.find('.vbo-tableaux-booking-checkout').length) { |
| 1579 |
dday = nextsib.attr('data-day'); |
| 1580 |
destcell = dest_tr.find('td.subnotbusy[data-day="' + dday + '"]'); |
| 1581 |
if (!destcell || !destcell.length) { |
| 1582 |
// the landing checkout snake may be on an occupied date |
| 1583 |
destcell = dest_tr.find('td.subroom-busy[data-day="' + dday + '"]'); |
| 1584 |
} |
| 1585 |
if (destcell && destcell.length) { |
| 1586 |
// prepend the checkout snake to the next cell |
| 1587 |
nextsib.find('.vbo-tableaux-booking-checkout').prependTo(destcell); |
| 1588 |
} |
| 1589 |
} |
| 1590 |
} |
| 1591 |
} |
| 1592 |
}, |
| 1593 |
(err) => { |
| 1594 |
alert("Request Failed"); |
| 1595 |
// restore loading opacity in container |
| 1596 |
jQuery('.vbo-overview-tipblock').css('opacity', '1'); |
| 1597 |
} |
| 1598 |
); |
| 1599 |
|
| 1600 |
return true; |
| 1601 |
} |
| 1602 |
|
| 1603 |
/** |
| 1604 |
* Swap room sub-unit with another sub-unit on an occupied date. Triggered by DnD. |
| 1605 |
*/ |
| 1606 |
function vboSwapRoomSubunits(bid, bidtwo, rid, old_rindex, new_rindex, dday) { |
| 1607 |
if (!confirm(Joomla.JText._('VBO_CONF_SWAP_RNUMB').replace('%s', old_rindex).replace('%s', new_rindex))) { |
| 1608 |
return false; |
| 1609 |
} |
| 1610 |
if (!bid || !bidtwo || !rid || !old_rindex || !new_rindex || !dday) { |
| 1611 |
console.error('Missing required arguments', bid, bidtwo, rid, old_rindex, new_rindex, dday); |
| 1612 |
return false; |
| 1613 |
} |
| 1614 |
// check if movement can be made |
| 1615 |
var cur_tr = jQuery('tr.vboverviewtablerow-subunit[data-subroomid="' + rid + '-' + old_rindex + '"]'); |
| 1616 |
if (!cur_tr || !cur_tr.length) { |
| 1617 |
console.error('could not find the parent row of the subunit cells'); |
| 1618 |
return false; |
| 1619 |
} |
| 1620 |
var maincell = cur_tr.find('td.subroom-busy[data-day="' + dday + '"]'); |
| 1621 |
if (!maincell || !maincell.length) { |
| 1622 |
console.error('could not find the main cell of the subunit to move'); |
| 1623 |
return false; |
| 1624 |
} |
| 1625 |
var dest_tr = jQuery('tr.vboverviewtablerow-subunit[data-subroomid="' + rid + '-' + new_rindex + '"]'); |
| 1626 |
if (!dest_tr || !dest_tr.length) { |
| 1627 |
console.error('could not find the destination row for the subunit cells'); |
| 1628 |
return false; |
| 1629 |
} |
| 1630 |
var destcell = dest_tr.find('td.subroom-busy[data-day="' + dday + '"]'); |
| 1631 |
if (!destcell || !destcell.length) { |
| 1632 |
console.error('could not find the destination cell of the subunit to move'); |
| 1633 |
return false; |
| 1634 |
} |
| 1635 |
|
| 1636 |
// gather the cells for the swop |
| 1637 |
var swap_cells_one = []; |
| 1638 |
var swap_cells_two = []; |
| 1639 |
var swap_dates_one = []; |
| 1640 |
var swap_dates_two = []; |
| 1641 |
var swap_cell_from = maincell; |
| 1642 |
var swap_cell_to = destcell; |
| 1643 |
|
| 1644 |
// register the elements to swap of the first sub-unit |
| 1645 |
while (true) { |
| 1646 |
if (!swap_cell_from || !swap_cell_from.length) { |
| 1647 |
// next cell not found |
| 1648 |
break; |
| 1649 |
} |
| 1650 |
var swap_bids = swap_cell_from.attr('data-bids'); |
| 1651 |
if (!swap_bids || swap_bids.indexOf('-' + bid + '-') < 0) { |
| 1652 |
// last occupied cell reached |
| 1653 |
break; |
| 1654 |
} |
| 1655 |
// push cloned cell data to move |
| 1656 |
swap_cells_one.push(swap_cell_from.children().not('.vbo-tableaux-booking-checkout').not('.vbo-roomdaynote-trigger').clone(true)); |
| 1657 |
swap_dates_one.push(swap_cell_from.attr('data-day')); |
| 1658 |
// set next iteration cell |
| 1659 |
swap_cell_from = swap_cell_from.next(); |
| 1660 |
} |
| 1661 |
|
| 1662 |
// register the elements to swap of the second sub-unit |
| 1663 |
while (true) { |
| 1664 |
if (!swap_cell_to || !swap_cell_to.length) { |
| 1665 |
// next cell not found |
| 1666 |
break; |
| 1667 |
} |
| 1668 |
var swap_bids = swap_cell_to.attr('data-bids'); |
| 1669 |
if (!swap_bids || swap_bids.indexOf('-' + bidtwo + '-') < 0) { |
| 1670 |
// last occupied cell reached |
| 1671 |
break; |
| 1672 |
} |
| 1673 |
// make sure we are swapping with the check-in day, or if it's a stay-date we need to unshift until the check-in |
| 1674 |
if (!swap_cells_two.length && !swap_cell_to.hasClass('vbo-checkinday')) { |
| 1675 |
// prepend first the cells until the check-in or until not found |
| 1676 |
var prev_cell = swap_cell_to; |
| 1677 |
while (true) { |
| 1678 |
prev_cell = prev_cell.prev(); |
| 1679 |
if (!prev_cell || !prev_cell.length) { |
| 1680 |
break; |
| 1681 |
} |
| 1682 |
var prev_cell_snake = prev_cell.find('.vbo-tableaux-booking').not('.vbo-tableaux-booking-checkout'); |
| 1683 |
if (prev_cell_snake && prev_cell_snake.length && (prev_cell_snake.hasClass('vbo-tableaux-booking-checkin') || prev_cell_snake.hasClass('vbo-tableaux-booking-stay'))) { |
| 1684 |
// prepend cloned cell data to move |
| 1685 |
swap_cells_two.unshift(prev_cell.children().not('.vbo-tableaux-booking-checkout').not('.vbo-roomdaynote-trigger').clone(true)); |
| 1686 |
swap_dates_two.unshift(prev_cell.attr('data-day')); |
| 1687 |
} else { |
| 1688 |
// no more previous cells |
| 1689 |
break; |
| 1690 |
} |
| 1691 |
} |
| 1692 |
} |
| 1693 |
// push cloned cell data to move |
| 1694 |
swap_cells_two.push(swap_cell_to.children().not('.vbo-tableaux-booking-checkout').not('.vbo-roomdaynote-trigger').clone(true)); |
| 1695 |
swap_dates_two.push(swap_cell_to.attr('data-day')); |
| 1696 |
// set next iteration cell |
| 1697 |
swap_cell_to = swap_cell_to.next(); |
| 1698 |
} |
| 1699 |
|
| 1700 |
if (!swap_cells_one.length || !swap_cells_two.length) { |
| 1701 |
console.error('could not gather the cells to swap', swap_cells_one, swap_cells_two); |
| 1702 |
return false; |
| 1703 |
} |
| 1704 |
|
| 1705 |
// walk over the cells of the first room to swap and check the corresponding destination |
| 1706 |
var check_destcell = destcell; |
| 1707 |
for (let i = 0; i < swap_cells_one.length; i++) { |
| 1708 |
if (!check_destcell || !check_destcell.length) { |
| 1709 |
// this cell does not exist, abort |
| 1710 |
console.error('destination cell to #' + (i + 1) + ' was not found'); |
| 1711 |
return false; |
| 1712 |
} |
| 1713 |
var dest_bids = check_destcell.attr('data-bids'); |
| 1714 |
if (dest_bids && dest_bids.length && dest_bids.indexOf('-' + bidtwo + '-') < 0) { |
| 1715 |
// this cell is already occupied, abort |
| 1716 |
console.error('destination cell to #' + (i + 1) + ' is occupied by another reservation'); |
| 1717 |
return false; |
| 1718 |
} |
| 1719 |
// set next destination cell |
| 1720 |
check_destcell = check_destcell.next(); |
| 1721 |
} |
| 1722 |
|
| 1723 |
// walk over the cells of the second room to swap and check the corresponding destination |
| 1724 |
check_destcell = maincell; |
| 1725 |
for (let i = 0; i < swap_cells_two.length; i++) { |
| 1726 |
if (!check_destcell || !check_destcell.length) { |
| 1727 |
// this cell does not exist, abort |
| 1728 |
console.error('destination cell from #' + (i + 1) + ' was not found'); |
| 1729 |
return false; |
| 1730 |
} |
| 1731 |
var dest_bids = check_destcell.attr('data-bids'); |
| 1732 |
if (dest_bids && dest_bids.length && dest_bids.indexOf('-' + bid + '-') < 0) { |
| 1733 |
// this cell is already occupied, abort |
| 1734 |
console.error('destination cell from #' + (i + 1) + ' is occupied by another reservation'); |
| 1735 |
return false; |
| 1736 |
} |
| 1737 |
// set next destination cell |
| 1738 |
check_destcell = check_destcell.next(); |
| 1739 |
} |
| 1740 |
|
| 1741 |
// make the AJAX request and swap cells only in case of success |
| 1742 |
VBOCore.doAjax( |
| 1743 |
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=bookings.swap_room_subunits'); ?>", |
| 1744 |
{ |
| 1745 |
bid_one: bid, |
| 1746 |
bid_two: bidtwo, |
| 1747 |
rid: rid, |
| 1748 |
index_one: old_rindex, |
| 1749 |
index_two: new_rindex, |
| 1750 |
checkin: dday, |
| 1751 |
tmpl: 'component' |
| 1752 |
}, |
| 1753 |
(res) => { |
| 1754 |
// move the cells of the first sub-unit onto the cells of the second sub-unit |
| 1755 |
var target_cell = destcell; |
| 1756 |
var current_cell = maincell; |
| 1757 |
var swap_diff_dates = false; |
| 1758 |
for (let counter = 0; counter < swap_cells_one.length; counter++) { |
| 1759 |
// remove elements from target |
| 1760 |
target_cell.children().not('.vbo-tableaux-booking-checkout').not('.vbo-roomdaynote-trigger').remove(); |
| 1761 |
// swap cell elements |
| 1762 |
swap_cells_one[counter].appendTo(target_cell); |
| 1763 |
// set proper bids attribute |
| 1764 |
target_cell.attr('data-bids', '-' + bid + '-'); |
| 1765 |
// check if we are swapping with a non check-in day sub-unit occupied cell |
| 1766 |
if (counter === 0 && !target_cell.hasClass('vbo-checkinday')) { |
| 1767 |
target_cell.addClass('vbo-checkinday'); |
| 1768 |
swap_diff_dates = true; |
| 1769 |
} else if (counter > 0 && !target_cell.hasClass('subroom-busy')) { |
| 1770 |
target_cell.removeClass('subnotbusy').addClass('subroom-busy'); |
| 1771 |
} |
| 1772 |
// check if the reservations have different nights of stay |
| 1773 |
var cell_will_occupy = true; |
| 1774 |
if (counter > 0 && swap_diff_dates && !swap_dates_two.includes(swap_dates_one[counter])) { |
| 1775 |
// the swapped unit will not occupy this cell, so clean it |
| 1776 |
cell_will_occupy = false; |
| 1777 |
} else if ((counter + 1) > swap_cells_two.length) { |
| 1778 |
// this reservation is longer than the other |
| 1779 |
cell_will_occupy = false; |
| 1780 |
} |
| 1781 |
if (!cell_will_occupy) { |
| 1782 |
// remove the children elements from this longer reservation |
| 1783 |
current_cell.children().not('.vbo-tableaux-booking-checkout').not('.vbo-roomdaynote-trigger').remove(); |
| 1784 |
// remove the occupied class as well |
| 1785 |
current_cell.removeClass('subroom-busy').addClass('subnotbusy').attr('data-bids', ''); |
| 1786 |
} |
| 1787 |
// set next target cell |
| 1788 |
target_cell = target_cell.next(); |
| 1789 |
// update current cell |
| 1790 |
current_cell = current_cell.next(); |
| 1791 |
} |
| 1792 |
|
| 1793 |
// move the checkout snake of the first sub-unit |
| 1794 |
if (target_cell && target_cell.length && current_cell && current_cell.length && current_cell.find('.vbo-tableaux-booking-checkout').length) { |
| 1795 |
current_cell.find('.vbo-tableaux-booking-checkout').prependTo(target_cell); |
| 1796 |
} |
| 1797 |
|
| 1798 |
// move the cells of the second sub-unit onto the cells of the first sub-unit |
| 1799 |
target_cell = maincell; |
| 1800 |
current_cell = destcell; |
| 1801 |
// check if we are swapping with a non check-in day sub-unit occupied cell |
| 1802 |
if (swap_diff_dates) { |
| 1803 |
var prev_land_cell = current_cell; |
| 1804 |
while (true) { |
| 1805 |
prev_land_cell = prev_land_cell.prev(); |
| 1806 |
if (!prev_land_cell || !prev_land_cell.length) { |
| 1807 |
break; |
| 1808 |
} |
| 1809 |
if (prev_land_cell.hasClass('subroom-busy')) { |
| 1810 |
// overwrite first cell to move and to land |
| 1811 |
current_cell = prev_land_cell; |
| 1812 |
target_cell = target_cell.prev(); |
| 1813 |
// empty this cell because no one will occupy it |
| 1814 |
current_cell.children().not('.vbo-tableaux-booking-checkout').not('.vbo-roomdaynote-trigger').remove(); |
| 1815 |
// make the cell free |
| 1816 |
current_cell.removeClass('subroom-busy').addClass('subnotbusy').attr('data-bids', ''); |
| 1817 |
} |
| 1818 |
if (prev_land_cell.hasClass('vbo-checkinday')) { |
| 1819 |
// we have reached the first cell of this booking |
| 1820 |
break; |
| 1821 |
} |
| 1822 |
} |
| 1823 |
} |
| 1824 |
for (let counter = 0; counter < swap_cells_two.length; counter++) { |
| 1825 |
// remove elements from target |
| 1826 |
target_cell.children().not('.vbo-tableaux-booking-checkout').not('.vbo-roomdaynote-trigger').remove(); |
| 1827 |
// swap cell elements |
| 1828 |
swap_cells_two[counter].appendTo(target_cell); |
| 1829 |
// set proper bids attribute |
| 1830 |
target_cell.attr('data-bids', '-' + bidtwo + '-'); |
| 1831 |
// check if we are swapping with a non check-in day sub-unit occupied cell |
| 1832 |
if (counter === 0 && !target_cell.hasClass('vbo-checkinday')) { |
| 1833 |
target_cell.addClass('vbo-checkinday'); |
| 1834 |
if (current_cell.hasClass('vbo-checkinday') && !swap_dates_one.includes(swap_dates_two[counter])) { |
| 1835 |
current_cell.removeClass('vbo-checkinday'); |
| 1836 |
} |
| 1837 |
} else if (counter > 0 && target_cell.hasClass('vbo-checkinday')) { |
| 1838 |
target_cell.removeClass('vbo-checkinday'); |
| 1839 |
} |
| 1840 |
if (!target_cell.hasClass('subroom-busy')) { |
| 1841 |
target_cell.removeClass('subnotbusy').addClass('subroom-busy'); |
| 1842 |
} |
| 1843 |
// check if the reservations have different nights of stay |
| 1844 |
if ((counter + 1) > swap_cells_one.length) { |
| 1845 |
// remove the children elements from this longer reservation |
| 1846 |
current_cell.children().not('.vbo-tableaux-booking-checkout').not('.vbo-roomdaynote-trigger').remove(); |
| 1847 |
// remove the occupied class as well |
| 1848 |
current_cell.removeClass('subroom-busy').addClass('subnotbusy').attr('data-bids', ''); |
| 1849 |
// set the occupied class onto the target |
| 1850 |
target_cell.removeClass('subnotbusy').addClass('subroom-busy'); |
| 1851 |
} |
| 1852 |
// set next target cell |
| 1853 |
target_cell = target_cell.next(); |
| 1854 |
// update current cell |
| 1855 |
current_cell = current_cell.next(); |
| 1856 |
} |
| 1857 |
|
| 1858 |
// move the checkout snake of the second sub-unit |
| 1859 |
if (target_cell && target_cell.length && current_cell && current_cell.length && current_cell.find('.vbo-tableaux-booking-checkout').length) { |
| 1860 |
// make sure to move just the first check-out snake, because snakes with equal duration may have moved the check-out here already |
| 1861 |
current_cell.find('.vbo-tableaux-booking-checkout').first().prependTo(target_cell); |
| 1862 |
} |
| 1863 |
}, |
| 1864 |
(err) => { |
| 1865 |
alert(err.responseText); |
| 1866 |
console.error(err.responseText); |
| 1867 |
} |
| 1868 |
); |
| 1869 |
|
| 1870 |
return true; |
| 1871 |
} |
| 1872 |
|
| 1873 |
/** |
| 1874 |
* Open a booking in a new tab. |
| 1875 |
*/ |
| 1876 |
function vboOvervOpenBooking(bid) { |
| 1877 |
var open_url = jQuery('.vbo-basenavuri-details').attr('href'); |
| 1878 |
open_url = open_url.replace('%d', bid); |
| 1879 |
// navigate in a new tab |
| 1880 |
window.open(open_url, '_blank'); |
| 1881 |
} |
| 1882 |
|
| 1883 |
/** |
| 1884 |
* DOM ready state |
| 1885 |
*/ |
| 1886 |
jQuery(function() { |
| 1887 |
// register to the event emitted when a new booking is created through an admin widget |
| 1888 |
document.addEventListener('vbo_new_booking_created', (e) => { |
| 1889 |
if (!e || !e.detail || !e.detail.hasOwnProperty('bid') || !e.detail['bid']) { |
| 1890 |
// do nothing |
| 1891 |
return; |
| 1892 |
} |
| 1893 |
// reload the page to display the new booking just created |
| 1894 |
location.reload(); |
| 1895 |
}); |
| 1896 |
|
| 1897 |
/* calculate padding to increase draggable area and avoid "display: table" for the parent TD and "display: table-cell" for the draggable SPAN with 100% width and height, middle aligns */ |
| 1898 |
jQuery("td.vbo-checkinday span.vbo-draggable-sp").each(function(k, v) { |
| 1899 |
var parentheight = jQuery(this).closest('td').height(); |
| 1900 |
var spheight = jQuery(this).height(); |
| 1901 |
var padsp = Math.floor((parentheight - spheight) / 2); |
| 1902 |
jQuery(this).css({"padding": padsp + "px 0"}); |
| 1903 |
}); |
| 1904 |
|
| 1905 |
/* Expand/Collapse tooltip */ |
| 1906 |
jQuery(document.body).on("click", ".vbo-overview-expandtoggle", function() { |
| 1907 |
jQuery(this).closest('.vbo-overview-tipblock').toggleClass('vbo-overview-tipblock-expanded'); |
| 1908 |
}); |
| 1909 |
|
| 1910 |
/* DnD Start */ |
| 1911 |
|
| 1912 |
/* DnD Event dragstart */ |
| 1913 |
jQuery(document.body).on("dragstart", "td.vbo-checkinday span, td.vbo-checkinday .vbo-tableaux-booking-checkin", function(e) { |
| 1914 |
// start dragging and prevent tooltip from popping up |
| 1915 |
isdragging = true; |
| 1916 |
if (hovtip === true) { |
| 1917 |
hideVboTooltip(); |
| 1918 |
} |
| 1919 |
|
| 1920 |
var parentcell = jQuery(this).closest('td'); |
| 1921 |
if (parentcell.hasClass('busytmplock') || parentcell.hasClass('busy-sharedcalendar')) { |
| 1922 |
return false; |
| 1923 |
} |
| 1924 |
|
| 1925 |
// reset pool of booked date cells |
| 1926 |
cellspool = []; |
| 1927 |
var dt = e.originalEvent.dataTransfer; |
| 1928 |
var bidstart = parentcell.attr('data-bids'); |
| 1929 |
var checkind = parentcell.attr('data-day'); |
| 1930 |
var roomid = parentcell.parent('tr').find('td').first().attr('data-roomid'); |
| 1931 |
if (!bidstart.length || !checkind.length || !roomid.length) { |
| 1932 |
return false; |
| 1933 |
} |
| 1934 |
|
| 1935 |
// count booking nights and set booked date cells |
| 1936 |
var totnights = countBookingCells(parentcell, bidstart, roomid); |
| 1937 |
|
| 1938 |
// add dragging class |
| 1939 |
if (jQuery(this).find('.vbo-tableaux-guest-name').length) { |
| 1940 |
jQuery(this).find('.vbo-tableaux-guest-name').addClass('vbo-dragging-sp'); |
| 1941 |
} else { |
| 1942 |
if (!jQuery(this).hasClass('vbo-tableaux-booking-avatar')) { |
| 1943 |
jQuery(this).addClass('vbo-dragging-sp'); |
| 1944 |
} |
| 1945 |
} |
| 1946 |
|
| 1947 |
// populate dataTransfer data |
| 1948 |
var parent_rid = ''; |
| 1949 |
var subunit_id = ''; |
| 1950 |
if (parentcell.hasClass('subroom-busy')) { |
| 1951 |
var subdata = parentcell.parent('tr').attr('data-subroomid').split('-'); |
| 1952 |
parent_rid = subdata[0]; |
| 1953 |
subunit_id = subdata[1]; |
| 1954 |
} |
| 1955 |
dt.setData('Checkin', checkind); |
| 1956 |
dt.setData('Roomid', roomid); |
| 1957 |
dt.setData('Bid', bidstart); |
| 1958 |
dt.setData('Nights', totnights); |
| 1959 |
dt.setData('Parentrid', parent_rid); |
| 1960 |
dt.setData('Subunit', subunit_id); |
| 1961 |
}); |
| 1962 |
|
| 1963 |
/* DnD Events dragenter dragover drop */ |
| 1964 |
jQuery(document.body).on("dragenter dragover drop", "td.notbusy, td.busy, td.subnotbusy, td.subroom-busy", function(e) { |
| 1965 |
// always prevent default |
| 1966 |
e.preventDefault(); |
| 1967 |
|
| 1968 |
// gather dragging cell data |
| 1969 |
var dt = e.originalEvent.dataTransfer; |
| 1970 |
var checkind = dt.getData('Checkin'); |
| 1971 |
var roomid = dt.getData('Roomid'); |
| 1972 |
var bid = dt.getData('Bid'); |
| 1973 |
var totnights = dt.getData('Nights'); |
| 1974 |
var parent_rid = dt.getData('Parentrid'); |
| 1975 |
var subunit_id = dt.getData('Subunit'); |
| 1976 |
|
| 1977 |
// check if we are hovering something that requires styling |
| 1978 |
if (e.type === 'dragover') { |
| 1979 |
var hover_cell = jQuery(this); |
| 1980 |
if (hover_cell.hasClass('subroom-busy') && hover_cell.hasClass('vbo-checkinday')) { |
| 1981 |
if (hover_cell.attr('data-day') != checkind && totnights > 1) { |
| 1982 |
hover_cell.find('.vbo-tableaux-booking-checkin').addClass('vbo-droppable-cell'); |
| 1983 |
} |
| 1984 |
} |
| 1985 |
// do not proceed any further |
| 1986 |
return; |
| 1987 |
} |
| 1988 |
|
| 1989 |
// only look for drop |
| 1990 |
if (e.type !== 'drop') { |
| 1991 |
// ignore if we are not dropping the element |
| 1992 |
return; |
| 1993 |
} |
| 1994 |
|
| 1995 |
// always reset pool of cells |
| 1996 |
newcellspool = []; |
| 1997 |
|
| 1998 |
/* check if drop is allowed */ |
| 1999 |
var landrow = jQuery(this).closest('tr'); |
| 2000 |
var landrid = landrow.find('td').first().attr('data-roomid'); |
| 2001 |
var landbids = jQuery(this).attr('data-bids'); |
| 2002 |
if (landrid === undefined || !landrid.length) { |
| 2003 |
return false; |
| 2004 |
} |
| 2005 |
|
| 2006 |
if (jQuery(this).hasClass('busy') && !jQuery(this).hasClass('vbo-partially')) { |
| 2007 |
if (bid != landbids) { |
| 2008 |
// landed on an occupied date but not for the same booking ID so drop is not allowed on this day |
| 2009 |
return false; |
| 2010 |
} |
| 2011 |
} |
| 2012 |
|
| 2013 |
// build pool of cells |
| 2014 |
var freenights = countCellFreeNights(jQuery(this), landrid, totnights, bid); |
| 2015 |
if (freenights < totnights) { |
| 2016 |
alert(Joomla.JText._('VBOVWDNDERRNOTENCELLS').replace('%s', freenights).replace('%d', totnights)); |
| 2017 |
return false; |
| 2018 |
} |
| 2019 |
|
| 2020 |
// collect the new dates |
| 2021 |
var nowdatefrom = jQuery(newcellspool[0]).attr('data-day'); |
| 2022 |
var nowdateto = jQuery(newcellspool[(newcellspool.length -1)]).attr('data-day'); |
| 2023 |
|
| 2024 |
// check if we are just moving a sub-unit onto another for the same dates |
| 2025 |
if (jQuery(this).hasClass('subnotbusy') || jQuery(this).hasClass('subroom-busy')) { |
| 2026 |
// dropping on a sub-unit is only allowed onto the same room ID, for the same dates (switch room index only) |
| 2027 |
var subdata = landrow.attr('data-subroomid').split('-'); |
| 2028 |
if (!subdata || !parent_rid || !subunit_id || parent_rid != subdata[0] || !subdata[1] || subunit_id == subdata[1]) { |
| 2029 |
// display proper error |
| 2030 |
if (subdata[1] && subunit_id == subdata[1]) { |
| 2031 |
// must use the same dates for sub-units |
| 2032 |
alert(Joomla.JText._('VBO_DRAG_SUBUNITS_SAMEDATE')); |
| 2033 |
} else { |
| 2034 |
// only sub-units can be moved onto rows for sub-units |
| 2035 |
alert(Joomla.JText._('VBO_ERR_SUBUN_MOVE_SUBUN')); |
| 2036 |
} |
| 2037 |
return false; |
| 2038 |
} |
| 2039 |
|
| 2040 |
// sub-unit drag&drop is only allowed on the same date to change sub-unit index |
| 2041 |
if (nowdatefrom != checkind) { |
| 2042 |
alert(Joomla.JText._('VBO_DRAG_SUBUNITS_SAMEDATE')); |
| 2043 |
return false; |
| 2044 |
} |
| 2045 |
|
| 2046 |
// attempt to perform the switch-room-index request |
| 2047 |
if (jQuery(this).hasClass('subnotbusy')) { |
| 2048 |
// move sub-unit to a different index |
| 2049 |
if (!vboMoveSubunit(bid.replaceAll('-', ''), parent_rid, subunit_id, subdata[1], checkind)) { |
| 2050 |
return false; |
| 2051 |
} |
| 2052 |
} else { |
| 2053 |
// dropped on an occupied sub-unit, so ask for swap confirmation |
| 2054 |
if (!vboSwapRoomSubunits(bid.replaceAll('-', ''), landbids.replaceAll('-', ''), parent_rid, subunit_id, subdata[1], checkind)) { |
| 2055 |
return false; |
| 2056 |
} |
| 2057 |
} |
| 2058 |
|
| 2059 |
// do not proceed |
| 2060 |
return; |
| 2061 |
} |
| 2062 |
|
| 2063 |
/* populate temporary class for the new cells */ |
| 2064 |
jQuery(cellspool).each(function(k, v) { |
| 2065 |
v.addClass('vbo-dragging-cells-tmp'); |
| 2066 |
}); |
| 2067 |
|
| 2068 |
// bookings for multiple rooms should add the same dragging class also to the booking for the other rooms |
| 2069 |
var samebidcells = jQuery("td.vbo-checkinday[data-bids='" + bid + "']"); |
| 2070 |
if (samebidcells.length > 1) { |
| 2071 |
jQuery("td[data-bids='" + bid + "']").each(function(k, v) { |
| 2072 |
if (!jQuery(v).hasClass('vbo-dragging-cells-tmp')) { |
| 2073 |
jQuery(v).addClass('vbo-dragging-cells-tmp'); |
| 2074 |
} |
| 2075 |
}); |
| 2076 |
} |
| 2077 |
jQuery(newcellspool).each(function(k, v) { |
| 2078 |
v.addClass('vbo-dragged-cells-tmp'); |
| 2079 |
}); |
| 2080 |
|
| 2081 |
/* populate and showing loading message */ |
| 2082 |
jQuery('.vbo-loading-dnd-head').text(Joomla.JText._('VBOVWDNDMOVINGBID').replace('%d', bid)); |
| 2083 |
var movingmess = ''; |
| 2084 |
if (roomid != landrid) { |
| 2085 |
movingmess += Joomla.JText._('VBOVWDNDMOVINGROOM').replace('%s', jQuery("td[data-roomid='"+landrid+"']").first().find('span.vbo-overview-roomname').text() ); |
| 2086 |
} |
| 2087 |
if (nowdatefrom != jQuery(cellspool[0]).attr('data-day') || nowdateto != jQuery(cellspool[(cellspool.length -1)]).attr('data-day')) { |
| 2088 |
if (roomid != landrid) { |
| 2089 |
movingmess += ', '; |
| 2090 |
} |
| 2091 |
movingmess += Joomla.JText._('VBOVWDNDMOVINGDATES').replace('%s', nowdatefrom + ' - ' + nowdateto); |
| 2092 |
} |
| 2093 |
|
| 2094 |
// hide tooltip, if any |
| 2095 |
hideVboTooltip(); |
| 2096 |
|
| 2097 |
// display moving message |
| 2098 |
jQuery('.vbo-loading-dnd-body').text(movingmess); |
| 2099 |
jQuery('.vbo-info-overlay-block').fadeIn(); |
| 2100 |
jQuery('.vbo-loading-dnd-footer').show(); |
| 2101 |
|
| 2102 |
/* fire the Ajax request after 1.5 seconds just for giving visibility to the loading message */ |
| 2103 |
setTimeout(function() { |
| 2104 |
doAlterBooking(bid, roomid, landrid); |
| 2105 |
}, 1500); |
| 2106 |
}); |
| 2107 |
|
| 2108 |
/* DnD Event dragend: remove class, attribute and dataTransfer Data if drag ends on the same position as dragstart or onto an invalid date */ |
| 2109 |
jQuery(document.body).on("dragend", "td.vbo-checkinday span, td.vbo-checkinday .vbo-tableaux-booking-checkin", function(e) { |
| 2110 |
// stop dragging to restore tooltip functions |
| 2111 |
isdragging = false; |
| 2112 |
// we could also access the originally dragged cell |
| 2113 |
var dt = e.originalEvent.dataTransfer; |
| 2114 |
// restore temporary classes |
| 2115 |
jQuery('.vbo-dragging-sp').removeClass('vbo-dragging-sp'); |
| 2116 |
jQuery('.vbo-droppable-cell').removeClass('vbo-droppable-cell'); |
| 2117 |
}); |
| 2118 |
/* DnD End */ |
| 2119 |
|
| 2120 |
/* Show New Reservation Form & Modal with bookings - Start */ |
| 2121 |
jQuery('td.busy, td.notbusy').dblclick(function() { |
| 2122 |
var curday = jQuery(this).attr('data-day'); |
| 2123 |
var roomid = jQuery(this).parent('tr').find('td.roomname').attr('data-roomid'); |
| 2124 |
roomid = roomid && roomid.length ? roomid : ''; |
| 2125 |
last_room_click = ''; |
| 2126 |
last_date_click = ''; |
| 2127 |
next_date_click = ''; |
| 2128 |
vboCallOpenJModal('vbo-new-res', 'index.php?option=com_vikbooking&task=calendar&cid[]='+roomid+'&checkin='+curday+'&overv=1&tmpl=component'); |
| 2129 |
}); |
| 2130 |
|
| 2131 |
jQuery(document.body).on('click', 'td.busy, td.notbusy, td.busytmplock, td.subroom-busy', function(e) { |
| 2132 |
if (jQuery(this).hasClass('vbo-widget-booskcal-cell-mday')) { |
| 2133 |
return; |
| 2134 |
} |
| 2135 |
|
| 2136 |
if (jQuery(this).hasClass('busy') || jQuery(this).hasClass('busytmplock') || jQuery(this).hasClass('subroom-busy')) { |
| 2137 |
// make sure the clicked target is not inside the tooltip |
| 2138 |
if (e && e.target) { |
| 2139 |
if (jQuery(e.target).closest('.vbo-overview-tipblock').length) { |
| 2140 |
// abort when click originated from the tooltip |
| 2141 |
return; |
| 2142 |
} |
| 2143 |
if (jQuery(e.target).is('a')) { |
| 2144 |
// abort when click is made on a link (View choosebusy) |
| 2145 |
return; |
| 2146 |
} |
| 2147 |
if (jQuery(e.target).hasClass('vbo-roomdaynote-display') || jQuery(e.target).hasClass('vbo-roomdaynote-trigger')) { |
| 2148 |
// abort when click is made on a room-day note |
| 2149 |
return; |
| 2150 |
} |
| 2151 |
} |
| 2152 |
|
| 2153 |
// trigger mouseleave event to prevent tooltip from showing |
| 2154 |
jQuery(this).trigger('mouseleave'); |
| 2155 |
|
| 2156 |
// get room name, date and day-bids |
| 2157 |
var room_name = ''; |
| 2158 |
var sub_room_data = ''; |
| 2159 |
var room_id = 0; |
| 2160 |
if (jQuery(this).hasClass('subroom-busy')) { |
| 2161 |
sub_room_data = jQuery(this).parent('tr').attr('data-subroomid'); |
| 2162 |
room_id = sub_room_data.split('-')[0]; |
| 2163 |
room_name = jQuery('td.roomname[data-roomid="' + room_id + '"]').not('.subroomname').first().find('.vbo-overview-roomname').text(); |
| 2164 |
} else { |
| 2165 |
var main_room_cell = jQuery(this).parent('tr').find('td.roomname'); |
| 2166 |
room_id = main_room_cell.attr('data-roomid'); |
| 2167 |
room_name = main_room_cell.find('.vbo-overview-roomname').text(); |
| 2168 |
} |
| 2169 |
var date_ymd = jQuery(this).attr('data-day'); |
| 2170 |
var date_read = jQuery('.bluedays[data-ymd="' + date_ymd + '"]').attr('data-readymd'); |
| 2171 |
var date_bids = jQuery(this).attr('data-bids'); |
| 2172 |
var def_bicon = '<?php VikBookingIcons::e('user', 'vbo-dashboard-guest-activity-avatar-icon'); ?>'; |
| 2173 |
var closure_i = '<?php VikBookingIcons::e('ban', 'vbo-dashboard-guest-activity-avatar-icon'); ?>'; |
| 2174 |
|
| 2175 |
// display modal with booking details |
| 2176 |
var rday_bookings_modal_body = VBOCore.displayModal({ |
| 2177 |
suffix: 'overv-rdaybookings', |
| 2178 |
extra_class: 'vbo-modal-rounded vbo-modal-tall vbo-modal-nofooter', |
| 2179 |
title: room_name + (sub_room_data ? ' #' + sub_room_data.split('-')[1] : '') + ' - ' + date_read, |
| 2180 |
dismiss_event: 'vbo-dismiss-modal-overv-rdaybookings', |
| 2181 |
loading_event: 'vbo-loading-modal-overv-rdaybookings', |
| 2182 |
loading_body: '<?php VikBookingIcons::e('circle-notch', 'fa-spin fa-fw'); ?>', |
| 2183 |
}); |
| 2184 |
|
| 2185 |
// show loading |
| 2186 |
VBOCore.emitEvent('vbo-loading-modal-overv-rdaybookings'); |
| 2187 |
|
| 2188 |
// make the request to get the bookings information |
| 2189 |
VBOCore.doAjax( |
| 2190 |
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=getbookingsinfo'); ?>", |
| 2191 |
{ |
| 2192 |
status: 'any', |
| 2193 |
idroom: room_id, |
| 2194 |
stay_date: date_ymd, |
| 2195 |
idorders: date_bids, |
| 2196 |
subroom: sub_room_data, |
| 2197 |
sharedcal: (jQuery(this).hasClass('busy-sharedcalendar') ? 1 : 0), |
| 2198 |
tmpl: 'component' |
| 2199 |
}, |
| 2200 |
(res) => { |
| 2201 |
// stop loading |
| 2202 |
VBOCore.emitEvent('vbo-loading-modal-overv-rdaybookings'); |
| 2203 |
try { |
| 2204 |
var obj_res = typeof res === 'string' ? JSON.parse(res) : res; |
| 2205 |
|
| 2206 |
// build the HTML response nodes |
| 2207 |
var rday_bookings_wrap = jQuery('<div></div>').addClass('vbo-dashboard-guests-latest'); |
| 2208 |
var rday_bookings_list = jQuery('<div></div>').addClass('vbo-dashboard-guest-messages-list'); |
| 2209 |
|
| 2210 |
// flag to indicate if the button to toggle the cancelled reservations was displayed |
| 2211 |
var show_canc_res_flag = false; |
| 2212 |
|
| 2213 |
// loop through all bookings |
| 2214 |
for (var b in obj_res) { |
| 2215 |
if (!obj_res.hasOwnProperty(b)) { |
| 2216 |
continue; |
| 2217 |
} |
| 2218 |
// nights and guests |
| 2219 |
var nights_guests = [ |
| 2220 |
obj_res[b]['roomsnum'] + ' ' + Joomla.JText._((obj_res[b]['roomsnum'] > 1 ? 'VBPVIEWORDERSTHREE' : 'VBEDITORDERTHREE')), |
| 2221 |
obj_res[b]['days'] + ' ' + Joomla.JText._((obj_res[b]['days'] > 1 ? 'VBDAYS' : 'VBDAY')), |
| 2222 |
obj_res[b]['tot_adults'] + ' ' + Joomla.JText._((obj_res[b]['tot_adults'] > 1 ? 'VBMAILADULTS' : 'VBMAILADULT')) |
| 2223 |
]; |
| 2224 |
if (obj_res[b]['tot_children'] > 0) { |
| 2225 |
nights_guests.push(obj_res[b]['tot_children'] + ' ' + Joomla.JText._((obj_res[b]['tot_children'] > 1 ? 'VBMAILCHILDREN' : 'VBMAILCHILD'))); |
| 2226 |
} |
| 2227 |
|
| 2228 |
// OTA booking ID |
| 2229 |
var ota_bid_info = ''; |
| 2230 |
if (obj_res[b].hasOwnProperty('idorderota') && obj_res[b].hasOwnProperty('channel') && obj_res[b]['idorderota'] && obj_res[b]['channel']) { |
| 2231 |
if (obj_res[b]['idorderota'].length <= 16) { |
| 2232 |
// try to display the information only for API channels |
| 2233 |
ota_bid_info = '<span class="label label-info">' + obj_res[b]['idorderota'] + '</span> '; |
| 2234 |
} |
| 2235 |
} |
| 2236 |
|
| 2237 |
// the separator between confirmed and cancelled reservations |
| 2238 |
var res_type_separator = null; |
| 2239 |
|
| 2240 |
// booking status and badge |
| 2241 |
var badge_type = 'warning'; |
| 2242 |
if (obj_res[b]['status'] == 'confirmed') { |
| 2243 |
badge_type = 'success'; |
| 2244 |
} else if (obj_res[b]['status'] == 'cancelled') { |
| 2245 |
badge_type = 'danger'; |
| 2246 |
if (!show_canc_res_flag) { |
| 2247 |
// build the separator between confirmed and cancelled reservations to toggle the latter ones |
| 2248 |
res_type_separator = jQuery('<div></div>').addClass('vbo-bookings-status-separator'); |
| 2249 |
var btn_separator = jQuery('<button></button>').attr('type', 'button').addClass('btn btn-small btn-secondary').text(Joomla.JText._('VBO_SHOW_CANCELLATIONS')); |
| 2250 |
btn_separator.on('click', function() { |
| 2251 |
jQuery(this).closest('.vbo-dashboard-guest-messages-list').find('[data-type="cancelled"]').toggle(); |
| 2252 |
}); |
| 2253 |
res_type_separator.append(btn_separator); |
| 2254 |
// turn flag on at the very first cancelled reservation found |
| 2255 |
show_canc_res_flag = true; |
| 2256 |
} |
| 2257 |
} |
| 2258 |
|
| 2259 |
// build main booking node |
| 2260 |
var rday_booking = jQuery('<div></div>').addClass('vbo-dashboard-guest-activity vbo-w-guestmessages-message'); |
| 2261 |
if (badge_type == 'danger') { |
| 2262 |
// hide cancelled booking by default and set proper attribute |
| 2263 |
rday_booking.attr('data-type', 'cancelled').css('display', 'none'); |
| 2264 |
} |
| 2265 |
rday_booking.attr('data-idorder', obj_res[b]['id']); |
| 2266 |
rday_booking.on('click', function(e) { |
| 2267 |
var click_target = jQuery(e.target); |
| 2268 |
if (click_target.is('a') || click_target.is('select') || click_target.is('option')) { |
| 2269 |
return false; |
| 2270 |
} |
| 2271 |
vboOvervOpenBooking(jQuery(this).attr('data-idorder')); |
| 2272 |
}); |
| 2273 |
|
| 2274 |
// build booking structure |
| 2275 |
var rday_booking_html = ''; |
| 2276 |
rday_booking_html += '<div class="vbo-dashboard-guest-activity-avatar">' + "\n"; |
| 2277 |
if (obj_res[b]['avatar_src']) { |
| 2278 |
rday_booking_html += '<img class="vbo-dashboard-guest-activity-avatar-profile" src="' + obj_res[b]['avatar_src'] + '" alt="' + obj_res[b]['avatar_alt'] + '" />' + "\n"; |
| 2279 |
} else if (obj_res[b]['closure']) { |
| 2280 |
rday_booking_html += closure_i + "\n"; |
| 2281 |
} else { |
| 2282 |
rday_booking_html += def_bicon + "\n"; |
| 2283 |
} |
| 2284 |
rday_booking_html += '</div>' + "\n"; |
| 2285 |
rday_booking_html += '<div class="vbo-dashboard-guest-activity-content">' + "\n"; |
| 2286 |
rday_booking_html += ' <div class="vbo-dashboard-guest-activity-content-head">' + "\n"; |
| 2287 |
rday_booking_html += ' <div class="vbo-dashboard-guest-activity-content-info-details">' + "\n"; |
| 2288 |
rday_booking_html += ' <h4 class="vbo-w-guestmessages-message-gtitle">' + (!obj_res[b]['closure'] ? obj_res[b]['cinfo'] : obj_res[b]['closure_txt']) + '</h4>' + "\n"; |
| 2289 |
rday_booking_html += ' <div class="vbo-dashboard-guest-activity-content-info-icon">' + "\n"; |
| 2290 |
rday_booking_html += ' <span class="label label-info">' + obj_res[b]['id'] + '</span> ' + "\n"; |
| 2291 |
rday_booking_html += ' <span class="badge badge-' + badge_type + '">' + obj_res[b]['status_lbl'] + '</span>' + "\n"; |
| 2292 |
rday_booking_html += ' <span class="vbo-w-guestmessages-message-staydates">' + "\n"; |
| 2293 |
rday_booking_html += ' <span class="vbo-w-guestmessages-message-staydates-in">' + obj_res[b]['checkin_short'] + '</span>' + "\n"; |
| 2294 |
rday_booking_html += ' <span class="vbo-w-guestmessages-message-staydates-sep">-</span>' + "\n"; |
| 2295 |
rday_booking_html += ' <span class="vbo-w-guestmessages-message-staydates-out">' + obj_res[b]['checkout_short'] + '</span>' + "\n"; |
| 2296 |
rday_booking_html += ' </span>' + "\n"; |
| 2297 |
rday_booking_html += ' </div>' + "\n"; |
| 2298 |
rday_booking_html += ' </div>' + "\n"; |
| 2299 |
rday_booking_html += ' <div class="vbo-dashboard-guest-activity-content-info-date">' + "\n"; |
| 2300 |
rday_booking_html += ' <span>' + obj_res[b]['book_date'] + '</span>' + "\n"; |
| 2301 |
rday_booking_html += ' <span>' + obj_res[b]['book_time'] + '</span>' + "\n"; |
| 2302 |
if (obj_res[b].hasOwnProperty('meals_included')) { |
| 2303 |
rday_booking_html += ' <div class="vbo-wider-badges-wrap">' + "\n"; |
| 2304 |
obj_res[b]['meals_included'].forEach((meal_enum) => { |
| 2305 |
rday_booking_html += ' <div class="badge badge-info">' + meal_enum + '</div>' + "\n"; |
| 2306 |
}); |
| 2307 |
rday_booking_html += ' </div>' + "\n"; |
| 2308 |
} |
| 2309 |
rday_booking_html += ' </div>' + "\n"; |
| 2310 |
rday_booking_html += ' </div>' + "\n"; |
| 2311 |
rday_booking_html += ' <div class="vbo-dashboard-guest-activity-content-info-msg">' + "\n"; |
| 2312 |
rday_booking_html += ' <div>' + ota_bid_info + nights_guests.join(', ') + '</div>' + "\n"; |
| 2313 |
if (obj_res[b].hasOwnProperty('sub_units_data')) { |
| 2314 |
rday_booking_html += ' <div class="vbo-rdaybooking-subunits">' + "\n"; |
| 2315 |
for (let sub_rname in obj_res[b]['sub_units_data']) { |
| 2316 |
if (!obj_res[b]['sub_units_data'].hasOwnProperty(sub_rname)) { |
| 2317 |
continue; |
| 2318 |
} |
| 2319 |
rday_booking_html += '<span class="label label-success">' + (obj_res[b]['roomsnum'] > 1 ? sub_rname + ' ' : '') + '#' + obj_res[b]['sub_units_data'][sub_rname] + '</span>' + "\n"; |
| 2320 |
} |
| 2321 |
rday_booking_html += ' </div>' + "\n"; |
| 2322 |
} else if (obj_res[b].hasOwnProperty('missing_index') && obj_res[b]['missing_index']) { |
| 2323 |
rday_booking_html += ' <div class="vbo-rdaybooking-subunits">' + "\n"; |
| 2324 |
rday_booking_html += ' <span class="label label-warning">' + Joomla.JText._('VBO_MISSING_SUBUNIT') + '</span>' + "\n"; |
| 2325 |
if (obj_res[b].hasOwnProperty('av_room_indexes')) { |
| 2326 |
// build drop downs to set the sub-unit to each room with no data |
| 2327 |
rday_booking_html += ' <div class="vbo-rdaybooking-subunits-list">' + "\n"; |
| 2328 |
for (var av_rindex in obj_res[b]['av_room_indexes']) { |
| 2329 |
if (!obj_res[b]['av_room_indexes'].hasOwnProperty(av_rindex) || !obj_res[b]['av_room_indexes'][av_rindex].hasOwnProperty('name') || !obj_res[b]['av_room_indexes'][av_rindex].hasOwnProperty('list')) { |
| 2330 |
continue; |
| 2331 |
} |
| 2332 |
var set_subunit_node = '<select onchange="vboSetSubunit(\'' + obj_res[b]['id'] + '\', \'' + obj_res[b]['av_room_indexes'][av_rindex]['rid'] + '\', \'' + av_rindex + '\', this.value);">' + "\n"; |
| 2333 |
set_subunit_node += '<option value="">' + obj_res[b]['av_room_indexes'][av_rindex]['name'] + '</option>' + "\n"; |
| 2334 |
for (var rindex_k in obj_res[b]['av_room_indexes'][av_rindex]['list']) { |
| 2335 |
if (!obj_res[b]['av_room_indexes'][av_rindex]['list'].hasOwnProperty(rindex_k)) { |
| 2336 |
continue; |
| 2337 |
} |
| 2338 |
set_subunit_node += '<option value="' + rindex_k + '">' + obj_res[b]['av_room_indexes'][av_rindex]['list'][rindex_k] + '</option>' + "\n"; |
| 2339 |
} |
| 2340 |
set_subunit_node += '</select>' + "\n"; |
| 2341 |
// append drop down |
| 2342 |
rday_booking_html += set_subunit_node; |
| 2343 |
} |
| 2344 |
rday_booking_html += ' </div>' + "\n"; |
| 2345 |
} |
| 2346 |
rday_booking_html += ' </div>' + "\n"; |
| 2347 |
} |
| 2348 |
rday_booking_html += ' </div>' + "\n"; |
| 2349 |
rday_booking_html += '</div>' + "\n"; |
| 2350 |
|
| 2351 |
// set booking HTML to node |
| 2352 |
rday_booking.append(rday_booking_html); |
| 2353 |
|
| 2354 |
if (res_type_separator !== null) { |
| 2355 |
// append the separator to toggle the cancelled reservations |
| 2356 |
rday_bookings_list.append(res_type_separator); |
| 2357 |
} |
| 2358 |
|
| 2359 |
// append booking node to list |
| 2360 |
rday_bookings_list.append(rday_booking); |
| 2361 |
} |
| 2362 |
|
| 2363 |
// finalize response nodes |
| 2364 |
rday_bookings_wrap.append(rday_bookings_list); |
| 2365 |
|
| 2366 |
// append the response |
| 2367 |
rday_bookings_modal_body.append(rday_bookings_wrap); |
| 2368 |
} catch(err) { |
| 2369 |
console.error('could not parse JSON response', err, res); |
| 2370 |
alert('Could not parse JSON response'); |
| 2371 |
} |
| 2372 |
}, |
| 2373 |
(err) => { |
| 2374 |
// stop loading and display alert message |
| 2375 |
VBOCore.emitEvent('vbo-loading-modal-overv-rdaybookings'); |
| 2376 |
console.error(err); |
| 2377 |
alert(err.responseText); |
| 2378 |
} |
| 2379 |
); |
| 2380 |
} |
| 2381 |
|
| 2382 |
if (jQuery(this).hasClass('busy') && !jQuery(this).hasClass('vbo-partially')) { |
| 2383 |
// abort when fully booked date |
| 2384 |
return; |
| 2385 |
} |
| 2386 |
|
| 2387 |
if (jQuery(this).hasClass('busytmplock') || jQuery(this).hasClass('subroom-busy')) { |
| 2388 |
// abort when pending record or sub-room |
| 2389 |
return; |
| 2390 |
} |
| 2391 |
|
| 2392 |
// update clicked dates info |
| 2393 |
var curday = jQuery(this).attr('data-day'); |
| 2394 |
var roomid = jQuery(this).parent('tr').find('td.roomname').attr('data-roomid'); |
| 2395 |
roomid = roomid && roomid.length ? roomid : ''; |
| 2396 |
last_room_click = roomid; |
| 2397 |
if (!last_date_click) { |
| 2398 |
last_date_click = curday; |
| 2399 |
} else if (last_date_click && next_date_click) { |
| 2400 |
last_date_click = curday; |
| 2401 |
next_date_click = ''; |
| 2402 |
} else { |
| 2403 |
var from_info = new Date(last_date_click); |
| 2404 |
var to_info = new Date(curday); |
| 2405 |
if (from_info.getTime() < to_info.getTime()) { |
| 2406 |
next_date_click = curday; |
| 2407 |
} else { |
| 2408 |
last_date_click = curday; |
| 2409 |
next_date_click = ''; |
| 2410 |
} |
| 2411 |
} |
| 2412 |
|
| 2413 |
// button shake effect |
| 2414 |
jQuery('.vbo-ovrv-flt-butn').addClass('vbo-ovrv-flt-butn-shake'); |
| 2415 |
setTimeout(function() { |
| 2416 |
jQuery('.vbo-ovrv-flt-butn').removeClass('vbo-ovrv-flt-butn-shake'); |
| 2417 |
}, 1000); |
| 2418 |
}); |
| 2419 |
/* Show New Reservation Form & Modal with bookings - End */ |
| 2420 |
|
| 2421 |
/* Hover Tooltip Start */ |
| 2422 |
jQuery('td.busy, td.busytmplock, td.subroom-busy').not('.vbo-widget-booskcal-cell-mday').hover(function() { |
| 2423 |
registerHoveringTooltip(this); |
| 2424 |
}, unregisterHoveringTooltip); |
| 2425 |
|
| 2426 |
jQuery(document.body).on('click', '.vbo-overview-tip-bctag', function() { |
| 2427 |
if (!jQuery(this).parent().find(".vbo-overview-tip-bctag-subtip").length) { |
| 2428 |
jQuery(".vbo-overview-tip-bctag-subtip").remove(); |
| 2429 |
var cur_color = jQuery(this).attr("data-ctagcolor"); |
| 2430 |
var cur_bid = jQuery(this).attr("data-bid"); |
| 2431 |
jQuery(this).after("<div class=\"vbo-overview-tip-bctag-subtip\">"+bctags_tip+"</div>"); |
| 2432 |
jQuery(this).parent().find(".vbo-overview-tip-bctag-subtip").find(".vbo-overview-tip-bctag-subtip-circle[data-ctagcolor='"+cur_color+"']").addClass("vbo-overview-tip-bctag-activecircle").css('border-color', cur_color); |
| 2433 |
jQuery(this).parent().find(".vbo-overview-tip-bctag-subtip").find(".vbo-overview-tip-bctag-subtip-circle").attr('data-bid', cur_bid); |
| 2434 |
jQuery(".vbo-overview-tip-bctag-subtip .hasTooltip").tooltip(); |
| 2435 |
} else { |
| 2436 |
jQuery(".vbo-overview-tip-bctag-subtip").remove(); |
| 2437 |
} |
| 2438 |
}); |
| 2439 |
|
| 2440 |
var applying_tag = false; |
| 2441 |
|
| 2442 |
jQuery(document.body).on('click', '.vbo-overview-tip-bctag-subtip-circle', function() { |
| 2443 |
if (applying_tag === true) { |
| 2444 |
return false; |
| 2445 |
} |
| 2446 |
applying_tag = true; |
| 2447 |
var clickelem = jQuery(this); |
| 2448 |
var ctagkey = clickelem.attr('data-ctagkey'); |
| 2449 |
var bid = clickelem.attr('data-bid'); |
| 2450 |
// set opacity to circles as loading |
| 2451 |
jQuery('.vbo-overview-tip-bctag-subtip-circle').css('opacity', '0.6'); |
| 2452 |
|
| 2453 |
// perform the request |
| 2454 |
VBOCore.doAjax( |
| 2455 |
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=setbookingtag'); ?>", |
| 2456 |
{ |
| 2457 |
tmpl: "component", |
| 2458 |
idorder: bid, |
| 2459 |
tagkey: ctagkey |
| 2460 |
}, |
| 2461 |
(res) => { |
| 2462 |
applying_tag = false; |
| 2463 |
if (res.indexOf('e4j.error') >= 0 ) { |
| 2464 |
console.log(res); |
| 2465 |
alert(res.replace("e4j.error.", "")); |
| 2466 |
//restore loading opacity in circles |
| 2467 |
jQuery('.vbo-overview-tip-bctag-subtip-circle').css('opacity', '1'); |
| 2468 |
} else { |
| 2469 |
var obj_res = typeof res === 'string' ? JSON.parse(res) : res; |
| 2470 |
var last_bid = jQuery(clickelem).closest(".vbo-hascolortag").attr('data-lastbid'); |
| 2471 |
<?php if ($pbmode == 'tags') { echo 'jQuery(".vbo-hascolortag[data-lastbid=\'"+last_bid+"\']").each(function(k, v) { jQuery(this).css("background-color", obj_res.color).find("a").first().css("color", obj_res.fontcolor); });'; } ?> |
| 2472 |
hideVboTooltip(); |
| 2473 |
} |
| 2474 |
}, |
| 2475 |
(err) => { |
| 2476 |
applying_tag = false; |
| 2477 |
alert("Request Failed"); |
| 2478 |
// restore loading opacity in circles |
| 2479 |
jQuery('.vbo-overview-tip-bctag-subtip-circle').css('opacity', '1'); |
| 2480 |
} |
| 2481 |
); |
| 2482 |
}); |
| 2483 |
|
| 2484 |
jQuery(document).keydown(function(e) { |
| 2485 |
if ( e.keyCode == 27 ) { |
| 2486 |
if (hovtip === true) { |
| 2487 |
hideVboTooltip(); |
| 2488 |
} |
| 2489 |
if (vbodialogorph_on === true) { |
| 2490 |
hideVboDialogOverv(1); |
| 2491 |
} |
| 2492 |
} |
| 2493 |
}); |
| 2494 |
|
| 2495 |
jQuery(document).mouseup(function(e) { |
| 2496 |
if (!hovtip && !vbodialogorph_on) { |
| 2497 |
return false; |
| 2498 |
} |
| 2499 |
if (hovtip) { |
| 2500 |
var vbo_overlay_cont = jQuery(".vbo-overview-tipblock"); |
| 2501 |
if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) { |
| 2502 |
hideVboTooltip(); |
| 2503 |
return true; |
| 2504 |
} |
| 2505 |
if (jQuery(".vbo-overview-tip-bctag-subtip").length) { |
| 2506 |
var vbo_overlay_subtip_cont = jQuery(".vbo-overview-tip-bctag-wrap"); |
| 2507 |
if (!vbo_overlay_subtip_cont.is(e.target) && vbo_overlay_subtip_cont.has(e.target).length === 0) { |
| 2508 |
jQuery(".vbo-overview-tip-bctag-subtip").remove(); |
| 2509 |
return true; |
| 2510 |
} |
| 2511 |
} |
| 2512 |
} |
| 2513 |
if (vbodialogorph_on) { |
| 2514 |
var vbo_overlay_cont = jQuery(".vbo-info-overlay-content"); |
| 2515 |
if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0) { |
| 2516 |
hideVboDialogOverv(1); |
| 2517 |
} |
| 2518 |
} |
| 2519 |
}); |
| 2520 |
/* Hover Tooltip End */ |
| 2521 |
|
| 2522 |
/* Toggle Sub-units */ |
| 2523 |
jQuery('.vbo-overview-subroom-toggle').click(function() { |
| 2524 |
var roomid = jQuery(this).closest('td').attr('data-roomid'); |
| 2525 |
if (jQuery(this).hasClass('vbo-overview-subroom-toggle-active')) { |
| 2526 |
jQuery("td.roomname[data-roomid='" + roomid + "']").find('span.vbo-overview-subroom-toggle').removeClass('vbo-overview-subroom-toggle-active').find('i').removeClass('fa-chevron-up').addClass('fa-chevron-down'); |
| 2527 |
// do not use .hide() or "display: none" may not work due to forced "display: table-row" |
| 2528 |
jQuery("td.subroomname[data-roomid='-" + roomid + "']").parent('tr').css('display', 'none'); |
| 2529 |
// update storage object |
| 2530 |
var storage_subunits_status = VBOCore.storageGetItem('vbo_overv_subunits_status'); |
| 2531 |
try { |
| 2532 |
storage_subunits_status = JSON.parse(storage_subunits_status); |
| 2533 |
storage_subunits_status = storage_subunits_status || {}; |
| 2534 |
} catch(e) { |
| 2535 |
storage_subunits_status = {}; |
| 2536 |
} |
| 2537 |
storage_subunits_status[roomid] = 0; |
| 2538 |
VBOCore.storageSetItem('vbo_overv_subunits_status', storage_subunits_status); |
| 2539 |
} else { |
| 2540 |
jQuery("td.roomname[data-roomid='" + roomid + "']").find('span.vbo-overview-subroom-toggle').addClass('vbo-overview-subroom-toggle-active').find('i').removeClass('fa-chevron-down').addClass('fa-chevron-up'); |
| 2541 |
// do not use .show() or "display: block" may be added rather than "display: table-row" |
| 2542 |
jQuery("td.subroomname[data-roomid='-" + roomid + "']").parent('tr').css('display', 'table-row'); |
| 2543 |
// update storage object |
| 2544 |
var storage_subunits_status = VBOCore.storageGetItem('vbo_overv_subunits_status'); |
| 2545 |
try { |
| 2546 |
storage_subunits_status = JSON.parse(storage_subunits_status); |
| 2547 |
storage_subunits_status = storage_subunits_status || {}; |
| 2548 |
} catch(e) { |
| 2549 |
storage_subunits_status = {}; |
| 2550 |
} |
| 2551 |
storage_subunits_status[roomid] = 1; |
| 2552 |
VBOCore.storageSetItem('vbo_overv_subunits_status', storage_subunits_status); |
| 2553 |
} |
| 2554 |
}); |
| 2555 |
|
| 2556 |
/* Display sub-units based on storage status */ |
| 2557 |
var storage_subunits_defstatus = VBOCore.storageGetItem('vbo_overv_subunits_status'); |
| 2558 |
try { |
| 2559 |
storage_subunits_defstatus = JSON.parse(storage_subunits_defstatus); |
| 2560 |
storage_subunits_defstatus = storage_subunits_defstatus || {}; |
| 2561 |
for (let rid in storage_subunits_defstatus) { |
| 2562 |
if (!storage_subunits_defstatus.hasOwnProperty(rid)) { |
| 2563 |
continue; |
| 2564 |
} |
| 2565 |
if (storage_subunits_defstatus[rid]) { |
| 2566 |
// trigger click event to display the sub-units |
| 2567 |
jQuery('td.roomname[data-roomid="' + rid + '"]').find('.vbo-overview-subroom-toggle').trigger('click'); |
| 2568 |
} |
| 2569 |
} |
| 2570 |
} catch(e) { |
| 2571 |
// do nothing |
| 2572 |
} |
| 2573 |
|
| 2574 |
/* Default state for sticky table heads */ |
| 2575 |
vboToggleStickyTableHeaders(<?php echo (count($rows) * $mnum) > 10 && $cookie_sticky_heads != 'off' ? 1 : 0; ?>); |
| 2576 |
|
| 2577 |
// check orphans (only if not disabled with the cookie) |
| 2578 |
var hideorphans = false; |
| 2579 |
var buiscuits = document.cookie; |
| 2580 |
if (buiscuits.length) { |
| 2581 |
var hideorphansck = "vboHideOrphans=1"; |
| 2582 |
if (buiscuits.indexOf(hideorphansck) >= 0) { |
| 2583 |
hideorphans = true; |
| 2584 |
} |
| 2585 |
} |
| 2586 |
if (!hideorphans && <?php echo $vbo_auth_pricing ? 'true' : 'false'; ?>) { |
| 2587 |
// make the request |
| 2588 |
|
| 2589 |
VBOCore.doAjax( |
| 2590 |
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=orphanscount'); ?>", |
| 2591 |
{ |
| 2592 |
from: '<?php echo date($df, $tsstart); ?>', |
| 2593 |
months: <?php echo $mnum; ?>, |
| 2594 |
tmpl: "component" |
| 2595 |
}, |
| 2596 |
(res) => { |
| 2597 |
var obj_res = typeof res === 'string' ? JSON.parse(res) : res; |
| 2598 |
var orphans_list = ''; |
| 2599 |
for (var rid in obj_res) { |
| 2600 |
if (!obj_res.hasOwnProperty(rid)) { |
| 2601 |
continue; |
| 2602 |
} |
| 2603 |
orphans_list += '<div class="vbo-orphans-info-room">'; |
| 2604 |
orphans_list += ' <h4 class="vbo-orphans-roomname">'+obj_res[rid]['name']+'</h4>'; |
| 2605 |
orphans_list += ' <div class="vbo-orphans-info-dates">'; |
| 2606 |
for (var dind in obj_res[rid]['rdates']) { |
| 2607 |
if (!obj_res[rid]['rdates'].hasOwnProperty(dind)) { |
| 2608 |
continue; |
| 2609 |
} |
| 2610 |
orphans_list += ' <div class="vbo-orphans-info-date">'+obj_res[rid]['rdates'][dind]+'</div>'; |
| 2611 |
} |
| 2612 |
orphans_list += ' </div>'; |
| 2613 |
orphans_list += ' <div class="vbo-orphans-info-btn">'; |
| 2614 |
orphans_list += ' <a href="index.php?option=com_vikbooking&task=ratesoverv&cid[]='+rid+'&startdate='+obj_res[rid]['linkd']+'" class="btn btn-primary" target="_blank"><?php echo addslashes(JText::translate('VBORPHANSCHECKBTN')); ?></a>'; |
| 2615 |
orphans_list += ' </div>'; |
| 2616 |
orphans_list += '</div>'; |
| 2617 |
} |
| 2618 |
if (orphans_list.length) { |
| 2619 |
// show the modal |
| 2620 |
jQuery('.vbo-orphans-info-list').html(orphans_list); |
| 2621 |
jQuery('.vbo-orphans-overlay-block').fadeIn(); |
| 2622 |
vbodialogorph_on = true; |
| 2623 |
} |
| 2624 |
}, |
| 2625 |
(err) => { |
| 2626 |
console.log("orphanscount Request Failed"); |
| 2627 |
} |
| 2628 |
); |
| 2629 |
} |
| 2630 |
// |
| 2631 |
|
| 2632 |
// fests |
| 2633 |
jQuery(document.body).on("click", "th.bluedays", function() { |
| 2634 |
if (jQuery(this).hasClass('skip-bluedays-click')) { |
| 2635 |
return; |
| 2636 |
} |
| 2637 |
var ymd = jQuery(this).attr('data-ymd'); |
| 2638 |
var daytitle = jQuery(this).attr('data-readymd'); |
| 2639 |
if (jQuery(this).hasClass('vbo-overv-festcell')) { |
| 2640 |
// cell has fests |
| 2641 |
if (!vboFests.hasOwnProperty(ymd)) { |
| 2642 |
return; |
| 2643 |
} |
| 2644 |
vboRenderFests(ymd, daytitle); |
| 2645 |
} else { |
| 2646 |
// let the admin create a new fest |
| 2647 |
|
| 2648 |
// update ymd key for the selected date, useful for adding new fests |
| 2649 |
jQuery('.vbo-overlay-fests-addnew').attr('data-ymd', ymd); |
| 2650 |
|
| 2651 |
// unset content and display modal for just adding a new fest |
| 2652 |
jQuery('.vbo-overlay-fests-list').html(''); |
| 2653 |
var fests_modal = VBOCore.displayModal({ |
| 2654 |
suffix: 'overv-mng-fests', |
| 2655 |
extra_class: 'vbo-modal-rounded vbo-modal-tall', |
| 2656 |
title: '<?php VikBookingIcons::e('star'); ?> <span>' + daytitle + '</span>', |
| 2657 |
footer_right: '<button type="button" class="btn btn-success" onclick="vboAddFest();">' + Joomla.JText._('VBSAVE') + '</button>', |
| 2658 |
dismiss_event: 'vbo-dismiss-modal-overv-mng-fests', |
| 2659 |
onDismiss: () => { |
| 2660 |
jQuery('.vbo-overv-mngfest-wrap').appendTo('.vbo-overv-mngfest-block'); |
| 2661 |
}, |
| 2662 |
}); |
| 2663 |
|
| 2664 |
// set modal body |
| 2665 |
jQuery('.vbo-overv-mngfest-wrap').appendTo(fests_modal); |
| 2666 |
} |
| 2667 |
}); |
| 2668 |
// |
| 2669 |
|
| 2670 |
// room-day notes |
| 2671 |
jQuery(document.body).on("click", ".vbo-roomdaynote-display", function() { |
| 2672 |
if (!jQuery(this).closest('.vbo-roomdaynote-trigger').length) { |
| 2673 |
return; |
| 2674 |
} |
| 2675 |
var daytitle = new Array; |
| 2676 |
var roomday_info = jQuery(this).closest('.vbo-roomdaynote-trigger').attr('data-roomday').split('_'); |
| 2677 |
// readable day |
| 2678 |
var readymd = roomday_info[0]; |
| 2679 |
if (jQuery('.bluedays[data-ymd="' + roomday_info[0] + '"]').length) { |
| 2680 |
readymd = jQuery('.bluedays[data-ymd="' + roomday_info[0] + '"]').attr('data-readymd'); |
| 2681 |
} |
| 2682 |
daytitle.push(readymd); |
| 2683 |
// room name |
| 2684 |
if (jQuery('.roomname[data-roomid="' + roomday_info[1] + '"]').length) { |
| 2685 |
daytitle.push(jQuery('.roomname[data-roomid="' + roomday_info[1] + '"]').first().find('.vbo-overview-roomname').text()); |
| 2686 |
} |
| 2687 |
// sub-unit |
| 2688 |
if (parseInt(roomday_info[2]) > 0 && jQuery('.subroomname[data-roomid="-' + roomday_info[1] + '"]').length) { |
| 2689 |
daytitle.push(jQuery('.subroomname[data-roomid="-' + roomday_info[1] + '"]').find('.vbo-overview-subroomname').eq((parseInt(roomday_info[2]) - 1)).text()); |
| 2690 |
} |
| 2691 |
|
| 2692 |
// display modal |
| 2693 |
var rdaynotes_modal = VBOCore.displayModal({ |
| 2694 |
suffix: 'overv-mng-rdaynotes', |
| 2695 |
extra_class: 'vbo-modal-rounded vbo-modal-tall', |
| 2696 |
title: '<?php VikBookingIcons::e('comment'); ?> <span>' + daytitle.join(', ') + '</span>', |
| 2697 |
footer_right: '<button type="button" class="btn btn-success" onclick="vboAddRoomDayNote();">' + Joomla.JText._('VBSAVE') + '</button>', |
| 2698 |
dismiss_event: 'vbo-dismiss-modal-overv-mng-rdaynotes', |
| 2699 |
onDismiss: () => { |
| 2700 |
jQuery('.vbo-overv-mngroomdaynotes-wrap').appendTo('.vbo-overv-mngroomdaynotes-block'); |
| 2701 |
}, |
| 2702 |
}); |
| 2703 |
|
| 2704 |
// set modal body |
| 2705 |
jQuery('.vbo-overv-mngroomdaynotes-wrap').appendTo(rdaynotes_modal); |
| 2706 |
|
| 2707 |
// populate current room day notes |
| 2708 |
vboRenderRdayNotes(roomday_info[0], roomday_info[1], roomday_info[2], readymd); |
| 2709 |
}); |
| 2710 |
// |
| 2711 |
}); |
| 2712 |
|
| 2713 |
/** |
| 2714 |
* Fests |
| 2715 |
*/ |
| 2716 |
function vboRenderFests(day, daytitle) { |
| 2717 |
// compose fests information |
| 2718 |
var fests_html = ''; |
| 2719 |
if (vboFests[day] && vboFests[day]['festinfo'] && vboFests[day]['festinfo'].length) { |
| 2720 |
for (var i = 0; i < vboFests[day]['festinfo'].length; i++) { |
| 2721 |
var fest = vboFests[day]['festinfo'][i]; |
| 2722 |
fests_html += '<div class="vbo-overlay-fest-details">'; |
| 2723 |
fests_html += ' <div class="vbo-fest-info">'; |
| 2724 |
fests_html += ' <div class="vbo-fest-name">' + fest['trans_name'] + '</div>'; |
| 2725 |
fests_html += ' <div class="vbo-fest-desc">' + fest['descr'].replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br />' + '$2') + '</div>'; |
| 2726 |
fests_html += ' </div>'; |
| 2727 |
fests_html += ' <div class="vbo-fest-cmds">'; |
| 2728 |
fests_html += ' <button type="button" class="btn btn-danger" onclick="vboRemoveFest(\'' + day + '\', \'' + i + '\', \'' + fest['type'] + '\', this);"><?php VikBookingIcons::e('trash-alt', 'no-margin'); ?></button>'; |
| 2729 |
fests_html += ' </div>'; |
| 2730 |
fests_html += '</div>'; |
| 2731 |
} |
| 2732 |
} |
| 2733 |
|
| 2734 |
// update ymd key for the selected date, useful for adding new fests |
| 2735 |
jQuery('.vbo-overlay-fests-addnew').attr('data-ymd', day); |
| 2736 |
|
| 2737 |
// set content and display modal |
| 2738 |
jQuery('.vbo-overlay-fests-list').html(fests_html); |
| 2739 |
|
| 2740 |
if (typeof daytitle !== 'undefined') { |
| 2741 |
// display modal only when we are not deleting a fest |
| 2742 |
var fests_modal = VBOCore.displayModal({ |
| 2743 |
suffix: 'overv-mng-fests', |
| 2744 |
extra_class: 'vbo-modal-rounded vbo-modal-tall', |
| 2745 |
title: '<?php VikBookingIcons::e('star'); ?> <span>' + daytitle + '</span>', |
| 2746 |
footer_right: '<button type="button" class="btn btn-success" onclick="vboAddFest();">' + Joomla.JText._('VBSAVE') + '</button>', |
| 2747 |
dismiss_event: 'vbo-dismiss-modal-overv-mng-fests', |
| 2748 |
onDismiss: () => { |
| 2749 |
jQuery('.vbo-overv-mngfest-wrap').appendTo('.vbo-overv-mngfest-block'); |
| 2750 |
}, |
| 2751 |
}); |
| 2752 |
|
| 2753 |
// set modal body |
| 2754 |
jQuery('.vbo-overv-mngfest-wrap').appendTo(fests_modal); |
| 2755 |
} |
| 2756 |
} |
| 2757 |
|
| 2758 |
function vboRemoveFest(day, index, fest_type, that) { |
| 2759 |
if (!confirm('<?php echo addslashes(JText::translate('VBDELCONFIRM')); ?>')) { |
| 2760 |
return false; |
| 2761 |
} |
| 2762 |
var elem = jQuery(that); |
| 2763 |
// make the AJAX request to the controller to remove this fest from the DB |
| 2764 |
VBOCore.doAjax( |
| 2765 |
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=remove_fest'); ?>", |
| 2766 |
{ |
| 2767 |
tmpl: "component", |
| 2768 |
dt: day, |
| 2769 |
ind: index, |
| 2770 |
type: fest_type |
| 2771 |
}, |
| 2772 |
(res) => { |
| 2773 |
if (res.indexOf('e4j.ok') >= 0) { |
| 2774 |
// delete fest also from the json-decode array of objects |
| 2775 |
if (vboFests[day] && vboFests[day]['festinfo']) { |
| 2776 |
// use splice to remove the desired index from array, or delete would not make the length of the array change |
| 2777 |
vboFests[day]['festinfo'].splice(index, 1); |
| 2778 |
// re-build indexes of delete buttons, fundamental for removing the right index at next click |
| 2779 |
vboRenderFests(day); |
| 2780 |
if (!vboFests[day]['festinfo'].length) { |
| 2781 |
// delete also this date object from fests |
| 2782 |
delete vboFests[day]; |
| 2783 |
// no more fests, remove the class for this date from all cells |
| 2784 |
jQuery('th.bluedays[data-ymd="'+day+'"]').removeClass('vbo-overv-festcell'); |
| 2785 |
jQuery('td.notbusy[data-day="'+day+'"]').removeClass('vbo-overv-festcell'); |
| 2786 |
jQuery('td.subnotbusy[data-day="'+day+'"]').removeClass('vbo-overv-festcell'); |
| 2787 |
jQuery('td.busy[data-day="'+day+'"]').removeClass('vbo-overv-festcell'); |
| 2788 |
jQuery('td.subroom-busy[data-day="'+day+'"]').removeClass('vbo-overv-festcell'); |
| 2789 |
} |
| 2790 |
} |
| 2791 |
elem.closest('.vbo-overlay-fest-details').remove(); |
| 2792 |
} else { |
| 2793 |
console.log(res); |
| 2794 |
alert('Invalid response'); |
| 2795 |
} |
| 2796 |
}, |
| 2797 |
(err) => { |
| 2798 |
alert('Request failed'); |
| 2799 |
} |
| 2800 |
); |
| 2801 |
} |
| 2802 |
|
| 2803 |
function vboAddFest() { |
| 2804 |
var ymd = jQuery('.vbo-overlay-fests-addnew').attr('data-ymd'); |
| 2805 |
var fest_name = jQuery('#vbo-newfest-name').val(); |
| 2806 |
var fest_descr = jQuery('#vbo-newfest-descr').val(); |
| 2807 |
if (!fest_name || !fest_name.length) { |
| 2808 |
return false; |
| 2809 |
} |
| 2810 |
// make the AJAX request to the controller to add this fest to the DB |
| 2811 |
VBOCore.doAjax( |
| 2812 |
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=add_fest'); ?>", |
| 2813 |
{ |
| 2814 |
tmpl: "component", |
| 2815 |
dt: ymd, |
| 2816 |
type: "custom", |
| 2817 |
name: fest_name, |
| 2818 |
descr: fest_descr |
| 2819 |
}, |
| 2820 |
(res) => { |
| 2821 |
// parse the JSON response that contains the fest object for the passed date |
| 2822 |
try { |
| 2823 |
var stored_fest = typeof res === 'string' ? JSON.parse(res) : res; |
| 2824 |
if (!vboFests.hasOwnProperty(stored_fest['dt'])) { |
| 2825 |
// we need to add the proper class to all cells to show that there is a fest |
| 2826 |
jQuery('th.bluedays[data-ymd="'+stored_fest['dt']+'"]').addClass('vbo-overv-festcell'); |
| 2827 |
jQuery('td.notbusy[data-day="'+stored_fest['dt']+'"]').addClass('vbo-overv-festcell'); |
| 2828 |
jQuery('td.subnotbusy[data-day="'+stored_fest['dt']+'"]').addClass('vbo-overv-festcell'); |
| 2829 |
jQuery('td.busy[data-day="'+stored_fest['dt']+'"]').addClass('vbo-overv-festcell'); |
| 2830 |
jQuery('td.subroom-busy[data-day="'+stored_fest['dt']+'"]').addClass('vbo-overv-festcell'); |
| 2831 |
} |
| 2832 |
vboFests[stored_fest['dt']] = stored_fest; |
| 2833 |
// hide modal |
| 2834 |
VBOCore.emitEvent('vbo-dismiss-modal-overv-mng-fests'); |
| 2835 |
// reset input fields |
| 2836 |
jQuery('#vbo-newfest-name').val(''); |
| 2837 |
jQuery('#vbo-newfest-descr').val(''); |
| 2838 |
} catch (e) { |
| 2839 |
console.log(res); |
| 2840 |
alert('Invalid response'); |
| 2841 |
return false; |
| 2842 |
} |
| 2843 |
}, |
| 2844 |
(err) => { |
| 2845 |
alert('Request failed'); |
| 2846 |
} |
| 2847 |
); |
| 2848 |
} |
| 2849 |
|
| 2850 |
/** |
| 2851 |
* Room-day notes |
| 2852 |
*/ |
| 2853 |
var rdaynote_icn_full = '<?php echo VikBookingIcons::i('sticky-note', 'vbo-roomdaynote-display'); ?>'; |
| 2854 |
var rdaynote_icn_empty = '<?php echo VikBookingIcons::i('far fa-sticky-note', 'vbo-roomdaynote-display'); ?>'; |
| 2855 |
function vboRenderRdayNotes(day, idroom, subunit, readymd) { |
| 2856 |
// compose fests information |
| 2857 |
var notes_html = ''; |
| 2858 |
var keyid = day + '_' + idroom + '_' + subunit; |
| 2859 |
if (vboRdayNotes.hasOwnProperty(keyid) && vboRdayNotes[keyid]['info'] && vboRdayNotes[keyid]['info'].length) { |
| 2860 |
for (var i = 0; i < vboRdayNotes[keyid]['info'].length; i++) { |
| 2861 |
var note_data = vboRdayNotes[keyid]['info'][i]; |
| 2862 |
notes_html += '<div class="vbo-overlay-fest-details vbo-modal-roomdaynotes-note-details">'; |
| 2863 |
notes_html += ' <div class="vbo-fest-info vbo-modal-roomdaynotes-note-info">'; |
| 2864 |
notes_html += ' <div class="vbo-fest-name vbo-modal-roomdaynotes-note-name">' + note_data['name'] + '</div>'; |
| 2865 |
notes_html += ' <div class="vbo-fest-desc vbo-modal-roomdaynotes-note-desc">' + note_data['descr'].replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br />' + '$2') + '</div>'; |
| 2866 |
notes_html += ' </div>'; |
| 2867 |
notes_html += ' <div class="vbo-fest-cmds vbo-modal-roomdaynotes-note-cmds">'; |
| 2868 |
notes_html += ' <button type="button" class="btn btn-danger" onclick="vboRemoveRdayNote(\'' + i + '\', \'' + day + '\', \'' + idroom + '\', \'' + subunit + '\', \'' + note_data['type'] + '\', this);"><?php VikBookingIcons::e('trash-alt', 'no-margin'); ?></button>'; |
| 2869 |
notes_html += ' </div>'; |
| 2870 |
notes_html += '</div>'; |
| 2871 |
} |
| 2872 |
} |
| 2873 |
// update attributes keys for the selected date, useful for adding new notes |
| 2874 |
jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-ymd', day).attr('data-roomid', idroom).attr('data-subroomid', subunit); |
| 2875 |
if (readymd !== null) { |
| 2876 |
jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-readymd', readymd); |
| 2877 |
jQuery('.vbo-newrdnote-dayto-val').text(readymd); |
| 2878 |
} |
| 2879 |
// set content and display modal |
| 2880 |
jQuery('.vbo-modal-roomdaynotes-list').html(notes_html); |
| 2881 |
} |
| 2882 |
|
| 2883 |
function vboAddRoomDayNote(that) { |
| 2884 |
var mainelem = jQuery('.vbo-modal-roomdaynotes-addnew'); |
| 2885 |
var ymd = mainelem.attr('data-ymd'); |
| 2886 |
var roomid = mainelem.attr('data-roomid'); |
| 2887 |
var subroomid = mainelem.attr('data-subroomid'); |
| 2888 |
var note_name = jQuery('#vbo-newrdnote-name').val(); |
| 2889 |
var note_descr = jQuery('#vbo-newrdnote-descr').val(); |
| 2890 |
var note_cdays = jQuery('#vbo-newrdnote-cdays').val(); |
| 2891 |
if (!note_name.length && !note_descr.length) { |
| 2892 |
alert('Missing required fields'); |
| 2893 |
return false; |
| 2894 |
} |
| 2895 |
// make the AJAX request to the controller to add this note to the DB |
| 2896 |
VBOCore.doAjax( |
| 2897 |
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=add_roomdaynote'); ?>", |
| 2898 |
{ |
| 2899 |
tmpl: "component", |
| 2900 |
dt: ymd, |
| 2901 |
idroom: roomid, |
| 2902 |
subunit: subroomid, |
| 2903 |
type: "custom", |
| 2904 |
name: note_name, |
| 2905 |
descr: note_descr, |
| 2906 |
cdays: note_cdays |
| 2907 |
}, |
| 2908 |
(res) => { |
| 2909 |
// parse the JSON response that contains the note object for the passed date |
| 2910 |
try { |
| 2911 |
var stored_notes = typeof res === 'string' ? JSON.parse(res) : res; |
| 2912 |
for (var keyid in stored_notes) { |
| 2913 |
if (!stored_notes.hasOwnProperty(keyid)) { |
| 2914 |
continue; |
| 2915 |
} |
| 2916 |
if (!vboRdayNotes.hasOwnProperty(keyid) && jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').length) { |
| 2917 |
// we need to add the proper class to the cell for this note (if it's visible) |
| 2918 |
jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').parent('td').removeClass('vbo-roomdaynote-empty').addClass('vbo-roomdaynote-full').find('i').attr('class', rdaynote_icn_full); |
| 2919 |
} |
| 2920 |
// update global object with the new notes in any case |
| 2921 |
vboRdayNotes[keyid] = stored_notes[keyid]; |
| 2922 |
} |
| 2923 |
// hide modal |
| 2924 |
VBOCore.emitEvent('vbo-dismiss-modal-overv-mng-rdaynotes'); |
| 2925 |
// reset input fields |
| 2926 |
jQuery('#vbo-newrdnote-name').val(''); |
| 2927 |
jQuery('#vbo-newrdnote-descr').val(''); |
| 2928 |
jQuery('#vbo-newrdnote-cdays').val('0').trigger('change'); |
| 2929 |
} catch (e) { |
| 2930 |
console.log(res); |
| 2931 |
alert('Invalid response'); |
| 2932 |
return false; |
| 2933 |
} |
| 2934 |
}, |
| 2935 |
(err) => { |
| 2936 |
alert('Request failed'); |
| 2937 |
} |
| 2938 |
); |
| 2939 |
} |
| 2940 |
|
| 2941 |
function vboRemoveRdayNote(index, day, idroom, subunit, note_type, that) { |
| 2942 |
if (!confirm('<?php echo addslashes(JText::translate('VBDELCONFIRM')); ?>')) { |
| 2943 |
return false; |
| 2944 |
} |
| 2945 |
var elem = jQuery(that); |
| 2946 |
// make the AJAX request to the controller to remove this note from the DB |
| 2947 |
VBOCore.doAjax( |
| 2948 |
"<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=remove_roomdaynote'); ?>", |
| 2949 |
{ |
| 2950 |
tmpl: "component", |
| 2951 |
dt: day, |
| 2952 |
idroom: idroom, |
| 2953 |
subunit: subunit, |
| 2954 |
ind: index, |
| 2955 |
type: note_type |
| 2956 |
}, |
| 2957 |
(res) => { |
| 2958 |
if (res.indexOf('e4j.ok') >= 0) { |
| 2959 |
var keyid = day + '_' + idroom + '_' + subunit; |
| 2960 |
// delete note also from the json-decode array of objects |
| 2961 |
if (vboRdayNotes[keyid] && vboRdayNotes[keyid]['info']) { |
| 2962 |
// use splice to remove the desired index from array, or delete would not make the length of the array change |
| 2963 |
vboRdayNotes[keyid]['info'].splice(index, 1); |
| 2964 |
// re-build indexes of delete buttons, fundamental for removing the right index at next click |
| 2965 |
vboRenderRdayNotes(day, idroom, subunit, null); |
| 2966 |
if (!vboRdayNotes[keyid]['info'].length) { |
| 2967 |
// delete also this date object from notes |
| 2968 |
delete vboRdayNotes[keyid]; |
| 2969 |
// no more notes, update the proper class attribute for this cell (should be visible) |
| 2970 |
if (jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').length) { |
| 2971 |
jQuery('.vbo-roomdaynote-trigger[data-roomday="' + keyid + '"]').parent('td').removeClass('vbo-roomdaynote-full').addClass('vbo-roomdaynote-empty').find('i').attr('class', rdaynote_icn_empty); |
| 2972 |
} |
| 2973 |
} |
| 2974 |
} |
| 2975 |
elem.closest('.vbo-modal-roomdaynotes-note-details').remove(); |
| 2976 |
} else { |
| 2977 |
console.log(res); |
| 2978 |
alert('Invalid response'); |
| 2979 |
} |
| 2980 |
}, |
| 2981 |
(err) => { |
| 2982 |
alert('Request failed'); |
| 2983 |
} |
| 2984 |
); |
| 2985 |
} |
| 2986 |
|
| 2987 |
function vboRdayNoteCdaysCount() { |
| 2988 |
var cdays = parseInt(jQuery('#vbo-newrdnote-cdays').val()); |
| 2989 |
var defymd = jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-ymd'); |
| 2990 |
var defreadymd = jQuery('.vbo-modal-roomdaynotes-addnew').attr('data-readymd'); |
| 2991 |
defreadymd = !defreadymd || !defreadymd.length ? defymd : defreadymd; |
| 2992 |
if (isNaN(cdays) || cdays < 1) { |
| 2993 |
jQuery('.vbo-newrdnote-dayto-val').text(defreadymd); |
| 2994 |
return; |
| 2995 |
} |
| 2996 |
// calculate target (until) date |
| 2997 |
var targetdate = new Date(defymd); |
| 2998 |
targetdate.setDate(targetdate.getDate() + cdays); |
| 2999 |
var target_y = targetdate.getFullYear(); |
| 3000 |
var target_m = targetdate.getMonth() + 1; |
| 3001 |
target_m = target_m < 10 ? '0' + target_m : target_m; |
| 3002 |
var target_d = targetdate.getDate(); |
| 3003 |
target_d = target_d < 10 ? '0' + target_d : target_d; |
| 3004 |
// display target date |
| 3005 |
var display_target = target_y + '-' + target_m + '-' + target_d; |
| 3006 |
// check if we can get the "read ymd property" |
| 3007 |
if (jQuery('.bluedays[data-ymd="' + display_target + '"]').length) { |
| 3008 |
display_target = jQuery('.bluedays[data-ymd="' + display_target + '"]').attr('data-readymd'); |
| 3009 |
} |
| 3010 |
jQuery('.vbo-newrdnote-dayto-val').text(display_target); |
| 3011 |
} |
| 3012 |
</script> |
| 3013 |
|
| 3014 |
<div class="vbo-orphans-overlay-block"> |
| 3015 |
<a class="vbo-info-overlay-close" href="javascript: void(0);"></a> |
| 3016 |
<div class="vbo-info-overlay-content vbo-info-overlay-content-orphans"> |
| 3017 |
<h3><?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'); ?></h3> |
| 3018 |
<div class="vbo-info-overlay-scroll-content"> |
| 3019 |
<div class="vbo-orphans-info-list"></div> |
| 3020 |
</div> |
| 3021 |
<div class="vbo-orphans-info-cmds"> |
| 3022 |
<div class="vbo-orphans-info-cmd"> |
| 3023 |
<button type="button" class="btn btn-success" onclick="javascript: hideVboDialogOverv(1);"><?php echo JText::translate('VBOBTNKEEPREMIND'); ?></button> |
| 3024 |
</div> |
| 3025 |
<div class="vbo-orphans-info-cmd"> |
| 3026 |
<button type="button" class="btn btn-danger" onclick="javascript: hideVboDialogOverv(-1);"><?php echo JText::translate('VBOBTNDONTREMIND'); ?></button> |
| 3027 |
</div> |
| 3028 |
</div> |
| 3029 |
</div> |
| 3030 |
</div> |
| 3031 |
|
| 3032 |
<div class="vbo-overv-mngfest-block" style="display: none;"> |
| 3033 |
<div class="vbo-overv-mngfest-wrap"> |
| 3034 |
<div class="vbo-overlay-fests-list"></div> |
| 3035 |
<div class="vbo-overlay-fests-addnew" data-ymd=""> |
| 3036 |
<h4><?php echo JText::translate('VBOADDCUSTOMFESTTODAY'); ?></h4> |
| 3037 |
<div class="vbo-overlay-fests-addnew-elem"> |
| 3038 |
<label for="vbo-newfest-name"><?php echo JText::translate('VBPVIEWPLACESONE'); ?></label> |
| 3039 |
<input type="text" id="vbo-newfest-name" value="" /> |
| 3040 |
</div> |
| 3041 |
<div class="vbo-overlay-fests-addnew-elem"> |
| 3042 |
<label for="vbo-newfest-descr"><?php echo JText::translate('VBPLACEDESCR'); ?></label> |
| 3043 |
<textarea id="vbo-newfest-descr"></textarea> |
| 3044 |
</div> |
| 3045 |
</div> |
| 3046 |
</div> |
| 3047 |
</div> |
| 3048 |
|
| 3049 |
<div class="vbo-overv-mngroomdaynotes-block" style="display: none;"> |
| 3050 |
<div class="vbo-overv-mngroomdaynotes-wrap"> |
| 3051 |
<div class="vbo-modal-roomdaynotes-list"></div> |
| 3052 |
<div class="vbo-modal-roomdaynotes-addnew" data-readymd="" data-ymd="" data-roomid="" data-subroomid=""> |
| 3053 |
<h4><?php echo JText::translate('VBOADDCUSTOMFESTTODAY'); ?></h4> |
| 3054 |
<div class="vbo-modal-roomdaynotes-addnew-elem"> |
| 3055 |
<label for="vbo-newrdnote-name"><?php echo JText::translate('VBPVIEWPLACESONE'); ?></label> |
| 3056 |
<input type="text" id="vbo-newrdnote-name" value="" /> |
| 3057 |
</div> |
| 3058 |
<div class="vbo-modal-roomdaynotes-addnew-elem"> |
| 3059 |
<label for="vbo-newrdnote-descr"><?php echo JText::translate('VBPLACEDESCR'); ?></label> |
| 3060 |
<textarea id="vbo-newrdnote-descr"></textarea> |
| 3061 |
</div> |
| 3062 |
<div class="vbo-modal-roomdaynotes-addnew-elem"> |
| 3063 |
<label for="vbo-newrdnote-cdays"><?php echo JText::translate('VBOCONSECUTIVEDAYS'); ?></label> |
| 3064 |
<input type="number" id="vbo-newrdnote-cdays" min="0" max="365" value="0" onchange="vboRdayNoteCdaysCount();" onkeyup="vboRdayNoteCdaysCount();" /> |
| 3065 |
<span class="vbo-newrdnote-dayto"> |
| 3066 |
<span class="vbo-newrdnote-dayto-lbl"><?php echo JText::translate('VBOUNTIL'); ?></span> |
| 3067 |
<span class="vbo-newrdnote-dayto-val"></span> |
| 3068 |
</span> |
| 3069 |
</div> |
| 3070 |
</div> |
| 3071 |
</div> |
| 3072 |
</div> |
| 3073 |
|