PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.7
VikBooking Hotel Booking Engine & PMS v1.8.7
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
vikbooking / site / layouts / taskmanager / calendar / month.php

month.php in VikBooking Hotel Booking Engine & PMS 1.8.7, at site/layouts/taskmanager/calendar/month.php

379 lines 14.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2025 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 /**
15 * Obtain vars from arguments received in the layout file.
16 *
17 * @var string $tool The operator tool identifier calling this layout file.
18 * @var array $operator The operator record accessing the tool.
19 * @var object $permissions The operator-tool permissions registry.
20 * @var string $tool_uri The base URI for rendering this tool.
21 * @var array $data The data for rendering the tasks of a given month within a calendar.
22 * @var int $no_tasks True for just displaying the month with no tasks, can be undefined.
23 */
24 extract($displayData);
25
26 if (!$operator || empty($operator['id'])) {
27 throw new Exception('Missing operator details', 400);
28 }
29
30 // check no-loading flag
31 $no_loading = (bool) ($no_tasks ?? 0);
32
33 // access the task manager object
34 $taskManager = VBOFactory::getTaskManager();
35
36 // get the filters for rendering the calendar tasks
37 $filters = (array) ($data['filters'] ?? []);
38
39 // get the current operator permissions
40 $accept_tasks = (bool) ($permissions ? $permissions->get('accept_tasks', 0) : 0);
41
42 // determine the month to load
43 $fromYmd = $filters['calendar_month'] ?? date('Y-m-01');
44 $toYmd = date('Y-m-t', strtotime($fromYmd));
45 if (($filters['dates'] ?? null) && !($filters['calendar_month'] ?? null)) {
46 // when no calendar month filter set, use the current dates filter
47 list($fromDt, $toDt) = VBOTaskModelTask::getInstance()->getFilterDatesInterval((string) $filters['dates'], $local = true, $sql = false);
48 if ($fromDt && $toDt) {
49 $fromYmd = date('Y-m-01', strtotime($fromDt));
50 $toYmd = date('Y-m-t', strtotime($toDt));
51 }
52 }
53
54 // build the pool of month tasks
55 $monthTasks = [];
56
57 if (!$no_loading) {
58 // save current filters in the user state
59 JFactory::getApplication()->setUserState('vbo.tm.filters', $filters);
60
61 // check from the permissions whether tasks can be accepted by the operator,
62 // hence null assigness should be included - use a different filter otherwise
63 $operatorTasksFilterName = $accept_tasks ? 'operator' : 'assignee';
64
65 // build filter options for fetching the tasks
66 $fetchOptions = array_merge($filters, [
67 $operatorTasksFilterName => $operator['id'],
68 'dates' => $fromYmd . ':' . $toYmd,
69 ]);
70
71 // load tasks according to filters, by always forcing/injecting the dates and the assignee/operator filter
72 foreach (VBOTaskModelTask::getInstance()->filterItems($fetchOptions, 0, 0) as $taskRecord) {
73 // wrap task record into a registry
74 $task = VBOTaskTaskregistry::getInstance((array) $taskRecord);
75
76 // get task due date in Y-m-d format
77 $due_date_key = $task->getDueDate($local = true, $format = 'Y-m-d');
78
79 if ($due_date_key) {
80 // start a container for this date
81 $monthTasks[$due_date_key] = $monthTasks[$due_date_key] ?? [];
82
83 // push task registry for this day
84 $monthTasks[$due_date_key][] = $task;
85 }
86 }
87 }
88
89 // obtain the current month information
90 $monthDate = getdate(strtotime($fromYmd));
91 $monthIter = $monthDate;
92
93 // get navigation dates
94 $todayYmd = date('Y-m-d');
95 $monthBack = date('Y-m-01', strtotime('-1 month', $monthDate[0]));
96 $monthNext = date('Y-m-01', strtotime('+1 month', $monthDate[0]));
97 $monthToday = date('Y-m-01');
98
99 // build week-day indexes
100 $firstwday = (int) VikBooking::getFirstWeekDay();
101 $days_indexes = [];
102 $wday_labels = [
103 JText::translate('VBSUN'),
104 JText::translate('VBMON'),
105 JText::translate('VBTUE'),
106 JText::translate('VBWED'),
107 JText::translate('VBTHU'),
108 JText::translate('VBFRI'),
109 JText::translate('VBSAT'),
110 ];
111
112 for ($d = 0; $d < 7; $d++) {
113 $days_indexes[$d] = (6-($firstwday-$d)+1)%7;
114 }
115
116 ?>
117
118 <div class="vbo-tm-calendar-wrap">
119 <div class="vbo-tm-calendar-head">
120 <div class="vbo-tm-calendar-info">
121 <span class="vbo-tm-calendar-month-name"><?php echo VikBooking::sayMonth($monthDate['mon']); ?></span>
122 <span class="vbo-tm-calendar-month-year"><?php echo $monthDate['year']; ?></span>
123 </div>
124
125 <div class="vbo-tm-calendar-nav">
126 <div class="vbo-tm-calendar-nav-btns">
127 <span class="vbo-tm-calendar-nav-btn vbo-tm-calendar-nav-back" data-month="<?php echo $monthBack; ?>"><?php VikBookingIcons::e('chevron-left'); ?></span>
128 <span class="vbo-tm-calendar-nav-btn vbo-tm-calendar-nav-today" data-month="<?php echo $monthToday; ?>"><?php echo JText::translate('VBTODAY'); ?></span>
129 <span class="vbo-tm-calendar-nav-btn vbo-tm-calendar-nav-next" data-month="<?php echo $monthNext; ?>"><?php VikBookingIcons::e('chevron-right'); ?></span>
130 </div>
131 </div>
132 </div>
133
134 <div class="vbo-tm-calendar-month-container">
135
136 <div class="vbo-tm-calendar-month-row vbo-tm-calendar-month-weekdays">
137 <?php
138 // display days of week
139 for ($d = 0; $d < 7; $d++) {
140 $d_ind = ($d + $firstwday) < 7 ? ($d + $firstwday) : ($d + $firstwday - 7);
141 ?>
142 <div class="vbo-tm-calendar-month-day vbo-tm-calendar-month-weekday">
143 <span><?php echo $wday_labels[$d_ind]; ?></span>
144 </div>
145 <?php
146 }
147 ?>
148 </div>
149
150 <div class="vbo-tm-calendar-month-row">
151 <?php
152 // start month-day counter
153 $d_count = 0;
154
155 // display the initial empty week-days, if any
156 for ($i = 0, $n = $days_indexes[$monthDate['wday']]; $i < $n; $i++, $d_count++) {
157 ?>
158 <div class="vbo-tm-calendar-month-day vbo-tm-calendar-month-day-empty"></div>
159 <?php
160 }
161
162 // loop through all dates of the current month
163 while ($monthIter['mon'] == $monthDate['mon']) {
164 if ($d_count > 6) {
165 // week is over, reset counter and start a new row
166 $d_count = 0;
167 echo '</div>' . "\n" . '<div class="vbo-tm-calendar-month-row">' . "\n";
168 }
169
170 // build date key
171 $date_key = date('Y-m-d', $monthIter[0]);
172
173 ?>
174 <div class="vbo-tm-calendar-month-day<?php echo $date_key == $todayYmd ? ' vbo-tm-calendar-month-today' : ''; ?>" data-date="<?php echo $date_key; ?>">
175 <span class="vbo-tm-calendar-mday"><?php echo $monthIter['mday']; ?></span>
176 <?php
177 if ($monthTasks[$date_key] ?? []) {
178 ?>
179 <div class="vbo-tm-calendar-month-day-tasks">
180 <?php
181 foreach ($monthTasks[$date_key] as $taskIndex => $task) {
182 // get task status
183 $statusColor = '';
184 $statusName = '';
185 if ($taskManager->statusTypeExists($task->getStatus())) {
186 $status = $taskManager->getStatusTypeInstance($task->getStatus());
187 $statusColor = $status->getColor();
188 $statusName = $status->getName();
189 }
190
191 // get task assignee details
192 $assignees = $task->getAssigneeDetails();
193 ?>
194 <div class="vbo-tm-calendar-month-day-task vbo-tm-color <?php echo $statusColor ?: 'gray'; ?> <?php echo $statusName ? 'vbo-tooltip vbo-tooltip-top' : ''; ?>" data-task-id="<?php echo $task->getID(); ?>" data-area-id="<?php echo $task->getAreaID(); ?>" data-tooltiptext="<?php echo JHtml::fetch('esc_attr', $statusName); ?>">
195 <div class="vbo-tm-calendar-month-day-task-wrap">
196 <div class="vbo-tm-calendar-task-title">
197 <?php echo $task->getTitle(); ?>
198
199 <?php if ($task->get('hasUnreadMessages', false)): ?>
200 <span class="unread-message-dot">
201 <?php VikBookingIcons::e('comment'); ?>
202 </span>
203 <?php endif; ?>
204 </div>
205 <?php
206 if ($assignees) {
207 ?>
208 <span class="vbo-tm-calendar-task-assignees">
209 <?php
210 foreach ($assignees as $operator) {
211 ?>
212 <span class="vbo-tm-calendar-task-assignee vbo-tm-task-assignee">
213 <span class="vbo-tm-calendar-task-assignee-avatar vbo-tm-task-assignee-avatar" title="<?php echo JHtml::fetch('esc_attr', $operator['name']); ?>">
214 <?php
215 if (!empty($operator['img_uri'])) {
216 ?>
217 <img src="<?php echo $operator['img_uri']; ?>" alt="<?php echo JHtml::fetch('esc_attr', $operator['initials']); ?>" decoding="async" loading="lazy" />
218 <?php
219 } else {
220 ?>
221 <span><?php echo $operator['initials']; ?></span>
222 <?php
223 }
224 ?>
225 </span>
226 </span>
227 <?php
228 }
229 ?>
230 </span>
231 <?php
232 }
233 ?>
234 </div>
235 </div>
236 <?php
237 if ($taskIndex > 1 && $exceeding = (count($monthTasks[$date_key]) - ++$taskIndex)) {
238 // we display at most 3 tasks per day
239 ?>
240 <div class="vbo-tm-calendar-month-day-task vbo-tm-calendar-month-day-more" data-date="<?php echo $date_key; ?>">
241 <span><?php echo sprintf('+%d %s', $exceeding, strtolower($exceeding > 1 ? JText::translate('VBO_TASKS') : JText::translate('VBO_TASK'))); ?></span>
242 </div>
243 <?php
244
245 // break the execution of the tasks for this day
246 break;
247 }
248 }
249 ?>
250 </div>
251 <?php
252 }
253 ?>
254 </div>
255 <?php
256 // increase month-day counter
257 $d_count++;
258
259 // go to next day
260 $monthIter = getdate(mktime(0, 0, 0, $monthIter['mon'], $monthIter['mday'] + 1, $monthIter['year']));
261 }
262
263 // display the ending empty week-days, if any
264 for ($i = $d_count; $i <= 6; $i++) {
265 ?>
266 <div class="vbo-tm-calendar-month-day vbo-tm-calendar-month-day-empty"></div>
267 <?php
268 }
269 ?>
270 </div>
271
272 </div>
273 </div>
274
275 <script type="text/javascript">
276 jQuery(function($) {
277
278 /**
279 * Register listeners for month navigation buttons.
280 */
281 document
282 .querySelectorAll('.vbo-tm-calendar-nav-btn')
283 .forEach((nav) => {
284 // get the navigation month
285 const month = nav.getAttribute('data-month');
286
287 nav.addEventListener('click', () => {
288 VBOCore.emitEvent('vbo-tm-apply-filters', {
289 filters: {
290 calendar_month: month,
291 },
292 });
293 });
294 });
295
296 /**
297 * Register listeners for day calendar type.
298 */
299 document
300 .querySelectorAll('.vbo-tm-calendar-month-day[data-date]')
301 .forEach((day) => {
302 // get the navigation month
303 const ymd = day.getAttribute('data-date');
304
305 day
306 .querySelector('.vbo-tm-calendar-mday')
307 .addEventListener('click', (event) => {
308 event.preventDefault();
309 event.stopPropagation();
310
311 VBOCore.emitEvent('vbo-tm-apply-filters', {
312 filters: {
313 calendar_type: 'day',
314 calendar_day: ymd,
315 },
316 });
317 });
318 });
319
320 /**
321 * Register listeners for viewing an existing task.
322 */
323 document
324 .querySelectorAll('.vbo-tm-calendar-month-day-task')
325 .forEach((taskElement) => {
326 if (taskElement.clickListener) {
327 // listener added already
328 return;
329 }
330
331 // get the clicked task and area IDs
332 const taskId = taskElement.getAttribute('data-task-id');
333 const areaId = taskElement.getAttribute('data-area-id');
334 const date = taskElement.getAttribute('data-date');
335
336 if ((!taskId || !areaId) && !date) {
337 // missing task details
338 return;
339 }
340
341 if (!taskId && !areaId && date) {
342 // see more day tasks
343 taskElement.addEventListener('click', (event) => {
344 event.preventDefault();
345 event.stopPropagation();
346
347 VBOCore.emitEvent('vbo-tm-apply-filters', {
348 filters: {
349 calendar_type: 'day',
350 calendar_day: date,
351 },
352 });
353 });
354
355 // abort
356 return;
357 }
358
359 taskElement.addEventListener('click', (event) => {
360 event.preventDefault();
361 event.stopPropagation();
362
363 VBOCore.emitEvent('vbo-tm-apply-filters', {
364 filters: {
365 calendar_back_type: 'month',
366 calendar_month: '<?php echo $fromYmd; ?>',
367 calendar_type: 'taskdetails',
368 task_id: taskId,
369 },
370 });
371 });
372
373 // turn flag on for listener set
374 taskElement.clickListener = true;
375 });
376
377 });
378 </script>
379