PluginProbe
Booking Calendar / 11.3
Booking Calendar v11.3
11.9 11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 All 205 releases
booking / includes / page-availability-timeslots / availability_timeslots__page.php

availability_timeslots__page.php in Booking Calendar 11.3, at includes/page-availability-timeslots/availability_timeslots__page.php

807 lines 31.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Time slots availability admin page.
4 *
5 * @package Booking Calendar
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Check whether the reusable Time Slots Availability component is rendered on current admin page.
14 *
15 * @return bool
16 */
17 function wpbc_availability_timeslots__is_component_page() {
18
19 if ( ! is_admin() ) {
20 return false;
21 }
22
23 if ( function_exists( 'wpbc_is_availability_page' ) && wpbc_is_availability_page() ) {
24 return true;
25 }
26
27 if (
28 function_exists( 'wpbc_is_bookings_page' )
29 && wpbc_is_bookings_page()
30 && function_exists( 'wpbc_get_default_saved_view_mode_for_wpbc_page' )
31 ) {
32 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
33 $requested_tab = isset( $_REQUEST['tab'] ) ? sanitize_key( wp_unslash( $_REQUEST['tab'] ) ) : '';
34 if ( '' !== $requested_tab ) {
35 return ( 'vm_booking_listing' === $requested_tab );
36 }
37
38 return ( 'vm_booking_listing' === wpbc_get_default_saved_view_mode_for_wpbc_page() );
39 }
40
41 return false;
42 }
43
44 /**
45 * Enqueue CSS for Time Slots Availability.
46 *
47 * @param string $where_to_load Where assets are loaded.
48 *
49 * @return void
50 */
51 function wpbc_availability_timeslots_enqueue_css_files( $where_to_load ) {
52
53 if ( ( ! is_admin() ) || ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) ) ) {
54 return;
55 }
56
57 if ( ! wpbc_availability_timeslots__is_component_page() ) {
58 return;
59 }
60
61 wp_enqueue_style(
62 'wpbc-availability-timeslots-page',
63 trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/availability_timeslots_page.css',
64 array( 'wpbc-calendar', 'wpbc-all-admin' ),
65 WP_BK_VERSION_NUM
66 );
67 }
68 add_action( 'wpbc_enqueue_css_files', 'wpbc_availability_timeslots_enqueue_css_files', 66 );
69
70 /**
71 * Print the same datepicker support CSS that the Booking Listing filter uses.
72 *
73 * @return void
74 */
75 function wpbc_availability_timeslots_print_datepicker_css() {
76
77 if ( ! wpbc_availability_timeslots__is_component_page() ) {
78 return;
79 }
80
81 if ( function_exists( 'wpbc_is_availability_page' ) && wpbc_is_availability_page() ) {
82 $active_tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
83 if ( 'time_slots_availability' !== $active_tab ) {
84 return;
85 }
86 }
87
88 if ( function_exists( 'wpbc_datepicker_css' ) ) {
89 wpbc_datepicker_css();
90 }
91 }
92 add_action( 'admin_footer', 'wpbc_availability_timeslots_print_datepicker_css', 66 );
93
94 /**
95 * Print tooltip initializer for Time Slots Availability.
96 *
97 * @return void
98 */
99 function wpbc_availability_timeslots_print_tooltip_js() {
100
101 if ( ! wpbc_availability_timeslots__is_component_page() ) {
102 return;
103 }
104
105 if ( function_exists( 'wpbc_is_availability_page' ) && wpbc_is_availability_page() ) {
106 $active_tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
107 if ( 'time_slots_availability' !== $active_tab ) {
108 return;
109 }
110 }
111
112 if ( function_exists( 'wpbc_bs_javascript_tooltips' ) ) {
113 wpbc_bs_javascript_tooltips();
114 }
115 }
116 add_action( 'admin_footer', 'wpbc_availability_timeslots_print_tooltip_js', 67 );
117
118 /**
119 * Enqueue JS for Time Slots Availability.
120 *
121 * @param string $where_to_load Where assets are loaded.
122 *
123 * @return void
124 */
125 function wpbc_availability_timeslots_enqueue_js_files( $where_to_load ) {
126
127 if ( ( ! is_admin() ) || ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) ) ) {
128 return;
129 }
130
131 if ( ! wpbc_availability_timeslots__is_component_page() ) {
132 return;
133 }
134
135 wp_enqueue_script(
136 'wpbc-availability-timeslots-page',
137 trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/availability_timeslots_page.js',
138 array( 'jquery', 'wpbc_all', 'wpbc-datepick' ),
139 WP_BK_VERSION_NUM,
140 array( 'in_footer' => WPBC_JS_IN_FOOTER )
141 );
142
143 wp_localize_script(
144 'wpbc-availability-timeslots-page',
145 'wpbc_availability_timeslots_page',
146 array(
147 'ajax_url' => admin_url( 'admin-ajax.php' ),
148 'nonce' => wp_create_nonce( 'wpbc_availability_timeslots_ajax_nonce' ),
149 'i18n' => array(
150 'select_slots_first' => __( 'Select one or more time ranges first.', 'booking' ),
151 'block_success' => __( 'Selected time ranges have been blocked.', 'booking' ),
152 'unblock_success' => __( 'Selected time ranges have been unblocked.', 'booking' ),
153 'save_error' => __( 'Unable to save time-slot availability.', 'booking' ),
154 'loading' => __( 'Loading', 'booking' ),
155 'open_booking' => __( 'Open booking in Booking Listing', 'booking' ),
156 'open_availability_rule' => __( 'Open availability settings', 'booking' ),
157 'select_one_slot_for_booking' => __( 'Select one time range on one date first.', 'booking' ),
158 'add_booking_modal_missing' => __( 'Add Booking popup is not available on this page.', 'booking' ),
159 'saving' => __( 'Saving', 'booking' ),
160 ),
161 )
162 );
163 }
164 add_action( 'wpbc_enqueue_js_files', 'wpbc_availability_timeslots_enqueue_js_files', 66 );
165
166 /**
167 * Get resource options for the Time Slots Availability component.
168 *
169 * @return array
170 */
171 function wpbc_availability_timeslots__get_resources() {
172
173 $resources = array();
174
175 if ( function_exists( 'wpbc_ajx_get_sorted_booking_resources_arr' ) && function_exists( 'wpbc_ajx_get_all_booking_resources_arr' ) ) {
176 $resource_rows = wpbc_ajx_get_sorted_booking_resources_arr( wpbc_ajx_get_all_booking_resources_arr() );
177 foreach ( $resource_rows as $resource ) {
178 $resources[] = array(
179 'id' => isset( $resource['booking_type_id'] ) ? (int) $resource['booking_type_id'] : 1,
180 'title' => isset( $resource['title'] ) ? $resource['title'] : __( 'Booking resource', 'booking' ),
181 );
182 }
183 }
184
185 if ( empty( $resources ) ) {
186 $resources[] = array(
187 'id' => wpbc_get_default_resource(),
188 'title' => '---', //__( 'Default Resource', 'booking' ),
189 );
190 }
191
192 return $resources;
193 }
194
195 /**
196 * Get initial timeline rows. Real booked and blocked bars are loaded by AJAX.
197 *
198 * @param int $start_ts Start timestamp.
199 * @param int $days_count Number of days.
200 *
201 * @return array
202 */
203 function wpbc_availability_timeslots__get_initial_rows( $start_ts, $days_count = 7 ) {
204
205 $rows = array();
206 $days_count = max( 1, intval( $days_count ) );
207
208 for ( $i = 0; $i < $days_count; $i++ ) {
209 $ts = strtotime( '+' . $i . ' days', $start_ts );
210 $rows[] = array(
211 'date' => wp_date( 'Y-m-d', $ts ),
212 'label' => wp_date( 'D M j', $ts ),
213 );
214 }
215
216 return $rows;
217 }
218
219 /**
220 * Get selectable time options from 00:00 to 24:00.
221 *
222 * @param int $selected_minutes Selected minute value.
223 *
224 * @return string
225 */
226 function wpbc_availability_timeslots__get_time_options( $selected_minutes ) {
227
228 $html = '';
229 for ( $minutes = 0; $minutes <= 1440; $minutes += 60 ) {
230 $hours = (int) floor( $minutes / 60 );
231 $mins = $minutes % 60;
232 $label = sprintf( '%02d:%02d', $hours, $mins );
233 $html .= sprintf(
234 '<option value="%1$d"%2$s>%3$s</option>',
235 (int) $minutes,
236 selected( $selected_minutes, $minutes, false ),
237 esc_html( $label )
238 );
239 }
240
241 return $html;
242 }
243
244 /**
245 * Print slot step options.
246 *
247 * @param int $selected_step Selected step.
248 *
249 * @return void
250 */
251 function wpbc_availability_timeslots__render_slot_step_options( $selected_step = 15 ) {
252
253 $steps = array(
254 5 => __( '5 min', 'booking' ),
255 10 => __( '10 min', 'booking' ),
256 15 => __( '15 min', 'booking' ),
257 30 => __( '30 min', 'booking' ),
258 60 => __( '1 hour', 'booking' ),
259 );
260
261 foreach ( $steps as $step => $label ) {
262 ?>
263 <option value="<?php echo esc_attr( $step ); ?>" <?php selected( (int) $selected_step, (int) $step ); ?>><?php echo esc_html( $label ); ?></option>
264 <?php
265 }
266 }
267
268 /**
269 * Render zoom control.
270 *
271 * @param string $control_id Control ID.
272 * @param int $selected_step Selected step.
273 * @param string $control_name Control name for JS.
274 *
275 * @return void
276 */
277 function wpbc_availability_timeslots__render_zoom_control( $control_id, $selected_step = 15, $control_name = 'zoom' ) {
278
279 $zoom_steps = array( 60, 30, 15, 10, 5 );
280 $zoom_index = array_search( (int) $selected_step, $zoom_steps, true );
281 if ( false === $zoom_index ) {
282 $zoom_index = 2;
283 }
284 ?>
285 <div class="wpbc_ts_zoom">
286 <a href="javascript:void(0)" class="button button-secondary wpbc_ts_zoom_button" data-wpbc-ts-zoom="out" aria-label="<?php esc_attr_e( 'Zoom out', 'booking' ); ?>">-</a>
287 <input id="<?php echo esc_attr( $control_id ); ?>" data-wpbc-ts-control="<?php echo esc_attr( $control_name ); ?>" type="range" min="0" max="<?php echo esc_attr( count( $zoom_steps ) - 1 ); ?>" value="<?php echo esc_attr( $zoom_index ); ?>" />
288 <a href="javascript:void(0)" class="button button-secondary wpbc_ts_zoom_button" data-wpbc-ts-zoom="in" aria-label="<?php esc_attr_e( 'Zoom in', 'booking' ); ?>">+</a>
289 </div>
290 <?php
291 }
292
293 /**
294 * Render Time Slots Availability action buttons.
295 *
296 * @param string $extra_class Additional wrapper CSS class.
297 * @return void
298 */
299 function wpbc_availability_timeslots__render_action_buttons( $extra_class = '' ) {
300
301 $wrapper_class = trim( 'wpbc_ts_action_buttons ' . $extra_class );
302 ?>
303 <div class="<?php echo esc_attr( $wrapper_class ); ?>">
304 <a href="javascript:void(0)" class="button button-secondary wpbc_ts_button_danger wpbc_ts_action_button" data-wpbc-ts-command="block"><span class="wpbc_icn_do_not_disturb_on"></span> <?php esc_html_e( 'Block selected', 'booking' ); ?></a>
305 <a href="javascript:void(0)" class="button button-secondary wpbc_ts_action_button wpbc_ts_unblock" data-wpbc-ts-command="unblock"><span class="wpbc_icn_blur_off"></span> <?php esc_html_e( 'Unblock selected', 'booking' ); ?></a>
306 <a href="javascript:void(0)" class="button button-secondary wpbc_ts_clear_selection"><?php esc_html_e( 'Clear selection', 'booking' ); ?></a>
307 </div>
308 <?php
309 }
310
311 /**
312 * Render the reusable Time Slots Availability timeline component.
313 *
314 * @param array $args Component arguments.
315 *
316 * @return void
317 */
318 function wpbc_availability_timeslots__render_timeline_component( $args = array() ) {
319
320 $defaults = array(
321 'id_prefix' => 'wpbc_ts',
322 'wrap_class' => 'wrap wpbc_ts_page wpdevelop',
323 'resource_id' => wpbc_get_default_resource(),
324 'resources' => null,
325 'start_ts' => strtotime( wp_date( 'Y-m-d 00:00:00' ) ),
326 'days_count' => 7,
327 'visible_start_minutes' => 360,
328 'visible_end_minutes' => 1320,
329 'slot_step' => 15,
330 'show_toolbar' => true,
331 'show_toolbar_actions' => true,
332 'show_hint' => true,
333 'show_legend' => true,
334 'auto_init' => true,
335 );
336 $args = wp_parse_args( $args, $defaults );
337
338 $id_prefix = sanitize_key( $args['id_prefix'] );
339 $resource_id = (int) $args['resource_id'];
340 $resources = is_array( $args['resources'] ) ? $args['resources'] : wpbc_availability_timeslots__get_resources();
341 $start_ts = (int) $args['start_ts'];
342 $days_count = max( 1, intval( $args['days_count'] ) );
343 $end_ts = strtotime( '+' . ( $days_count - 1 ) . ' days', $start_ts );
344 $rows = wpbc_availability_timeslots__get_initial_rows( $start_ts, $days_count );
345 $visible_start_minutes = (int) $args['visible_start_minutes'];
346 $visible_end_minutes = (int) $args['visible_end_minutes'];
347 $slot_step = (int) $args['slot_step'];
348
349 $ids = array(
350 'resource' => $id_prefix . '_resource',
351 'date_range' => $id_prefix . '_date_range',
352 'slot_step' => $id_prefix . '_slot_step',
353 'zoom' => $id_prefix . '_zoom',
354 'day_start' => $id_prefix . '_day_start',
355 'day_end' => $id_prefix . '_day_end',
356 'day_start_slider' => $id_prefix . '_day_start_slider',
357 'day_end_slider' => $id_prefix . '_day_end_slider',
358 );
359
360 ?>
361 <div class="<?php echo esc_attr( $args['wrap_class'] ); ?>" data-wpbc-ts-component="1" data-wpbc-ts-auto-init="<?php echo esc_attr( $args['auto_init'] ? '1' : '0' ); ?>" data-wpbc-ts-id-prefix="<?php echo esc_attr( $id_prefix ); ?>">
362 <?php if ( $args['show_toolbar'] ) : ?>
363 <div class="wpbc_ts_toolbar">
364 <div class="wpbc_ts_control wpbc_ts_control_resource">
365 <label for="<?php echo esc_attr( $ids['resource'] ); ?>"><?php esc_html_e( 'Booking resource', 'booking' ); ?></label>
366 <select id="<?php echo esc_attr( $ids['resource'] ); ?>" data-wpbc-ts-control="resource" class="wpbc_ui_control wpbc_ui_select">
367 <?php foreach ( $resources as $resource ) : ?>
368 <option value="<?php echo esc_attr( $resource['id'] ); ?>" <?php selected( (int) $resource['id'], (int) $resource_id ); ?>>
369 <?php echo esc_html( $resource['title'] ); ?>
370 </option>
371 <?php endforeach; ?>
372 </select>
373 </div>
374
375 <div class="wpbc_ts_control wpbc_ts_control_range">
376 <label for="<?php echo esc_attr( $ids['date_range'] ); ?>"><?php esc_html_e( 'Date range', 'booking' ); ?></label>
377 <div class="wpbc_ts_range_nav">
378 <a href="javascript:void(0)"
379 class="button tooltip_top button-secondary wpbc_button_no_background wpbc_ts_range_nav_button"
380 data-wpbc-ts-range-shift="prev"
381 aria-label="<?php esc_attr_e( 'Previous date range', 'booking' ); ?>"
382 data-original-title="<?php esc_attr_e( 'Previous date range', 'booking' ); ?>"><i class="menu_icon icon-1x wpbc_icn_keyboard_arrow_left"></i><span class="in-button-text"></span></a>
383 <div class="wpbc_ts_input_icon">
384 <span class="wpbc-bi-calendar3-range"></span>
385 <input id="<?php echo esc_attr( $ids['date_range'] ); ?>"
386 data-wpbc-ts-control="date_range"
387 class="wpbc_ui_control wpbc_ui_text wpdevbk-filters-section-calendar"
388 type="text"
389 readonly="readonly"
390 data-wpbc-ts-start="<?php echo esc_attr( wp_date( 'Y-m-d', $start_ts ) ); ?>"
391 data-wpbc-ts-end="<?php echo esc_attr( wp_date( 'Y-m-d', $end_ts ) ); ?>"
392 value="<?php echo esc_attr( wp_date( 'M j, Y', $start_ts ) . ' - ' . wp_date( 'M j, Y', $end_ts ) ); ?>" />
393 </div>
394 <a href="javascript:void(0)"
395 class="button tooltip_top button-secondary wpbc_button_no_background wpbc_ts_range_nav_button"
396 data-wpbc-ts-range-shift="next"
397 aria-label="<?php esc_attr_e( 'Next date range', 'booking' ); ?>"
398 data-original-title="<?php esc_attr_e( 'Next date range', 'booking' ); ?>"><i class="menu_icon icon-1x wpbc_icn_keyboard_arrow_right"></i><span class="in-button-text"></span></a>
399 </div>
400 </div>
401
402 <div class="wpbc_ts_control wpbc_ts_control_precision">
403 <label for="<?php echo esc_attr( $ids['slot_step'] ); ?>"><?php esc_html_e( 'Slot step', 'booking' ); ?></label>
404 <select id="<?php echo esc_attr( $ids['slot_step'] ); ?>" data-wpbc-ts-control="slot_step" class="wpbc_ui_control wpbc_ui_select">
405 <?php wpbc_availability_timeslots__render_slot_step_options( $slot_step ); ?>
406 </select>
407 <?php wpbc_availability_timeslots__render_zoom_control( $ids['zoom'], $slot_step ); ?>
408 </div>
409
410 <div class="wpbc_ts_control wpbc_ts_control_time_range">
411 <label><?php esc_html_e( 'Visible time', 'booking' ); ?></label>
412 <div class="wpbc_ts_time_inputs">
413 <select id="<?php echo esc_attr( $ids['day_start'] ); ?>" data-wpbc-ts-control="day_start" class="wpbc_ui_control wpbc_ui_select" aria-label="<?php esc_attr_e( 'Start time', 'booking' ); ?>">
414 <?php echo wpbc_availability_timeslots__get_time_options( $visible_start_minutes ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
415 </select>
416 <select id="<?php echo esc_attr( $ids['day_end'] ); ?>" data-wpbc-ts-control="day_end" class="wpbc_ui_control wpbc_ui_select" aria-label="<?php esc_attr_e( 'End time', 'booking' ); ?>">
417 <?php echo wpbc_availability_timeslots__get_time_options( $visible_end_minutes ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
418 </select>
419 </div>
420 <div class="wpbc_ts_dual_slider">
421 <input id="<?php echo esc_attr( $ids['day_start_slider'] ); ?>" data-wpbc-ts-control="day_start_slider" type="range" min="0" max="1440" step="60" value="<?php echo esc_attr( $visible_start_minutes ); ?>" aria-label="<?php esc_attr_e( 'Start time', 'booking' ); ?>" />
422 <input id="<?php echo esc_attr( $ids['day_end_slider'] ); ?>" data-wpbc-ts-control="day_end_slider" type="range" min="0" max="1440" step="60" value="<?php echo esc_attr( $visible_end_minutes ); ?>" aria-label="<?php esc_attr_e( 'End time', 'booking' ); ?>" />
423 </div>
424 </div>
425
426 <?php if ( $args['show_toolbar_actions'] ) : ?>
427 <div class="wpbc_ts_toolbar_actions">
428 <?php wpbc_availability_timeslots__render_action_buttons( 'wpbc_ts_action_buttons_inline' ); ?>
429 </div>
430 <?php endif; ?>
431 </div>
432 <?php endif; ?>
433
434 <?php if ( $args['show_hint'] ) : ?>
435 <div class="wpbc_ts_hint">
436 <span class="wpbc_icn_info_outline"></span>
437 <?php esc_html_e( 'Click and drag across the timeline to select slots. Drag selection ends to adjust the time range.', 'booking' ); ?>
438 </div>
439 <?php endif; ?>
440
441 <div class="wpbc_ts_timeline_card">
442 <div class="wpbc_ts_loading_overlay" aria-live="polite" aria-hidden="true">
443 <div class="wpbc_spins_loading_container wpbc_bfb_spins_loading_container">
444 <div class="wpbc_booking_form_spin_loader">
445 <div class="wpbc_spins_loader_wrapper">
446 <div class="wpbc_one_spin_loader_mini2"></div>
447 </div>
448 </div>
449 <span><?php esc_html_e( 'Loading', 'booking' ); ?>...</span>
450 </div>
451 </div>
452 <div class="wpbc_ts_grid"
453 data-wpbc-ts-start="<?php echo esc_attr( $visible_start_minutes ); ?>"
454 data-wpbc-ts-end="<?php echo esc_attr( $visible_end_minutes ); ?>"
455 data-wpbc-ts-step="<?php echo esc_attr( $slot_step ); ?>">
456 <div class="wpbc_ts_header">
457 <div class="wpbc_ts_axis_corner">
458 <div><?php esc_html_e( 'Time', 'booking' ); ?></div>
459 <div><?php esc_html_e( 'Date', 'booking' ); ?></div>
460 </div>
461 <div class="wpbc_ts_time_axis" aria-hidden="true"></div>
462 </div>
463
464 <div class="wpbc_ts_rows">
465 <?php foreach ( $rows as $row_index => $row ) : ?>
466 <div class="wpbc_ts_row" data-wpbc-ts-row="<?php echo esc_attr( $row_index ); ?>" data-wpbc-ts-date="<?php echo esc_attr( $row['date'] ); ?>">
467 <div class="wpbc_ts_row_label">
468 <span class="wpbc_ts_row_label_text"><?php echo esc_html( $row['label'] ); ?></span>
469 <?php // TODO: add later extended row actions menu! ?>
470 <!--a href="javascript:void(0)" class="wpbc_ts_row_menu" aria-label="<?php esc_attr_e( 'Row actions', 'booking' ); ?>">...</a-->
471 </div>
472 <div class="wpbc_ts_lane" tabindex="0">
473 <div class="wpbc_ts_available_rail"></div>
474 <div class="wpbc_ts_selection wpbc_ts_selection_template" hidden="hidden">
475 <span class="wpbc_ts_time_chip wpbc_ts_time_chip_start">00:00</span>
476 <span class="wpbc_ts_time_chip wpbc_ts_time_chip_end">00:00</span>
477 <span class="wpbc_ts_handle wpbc_ts_handle_start"></span>
478 <span class="wpbc_ts_handle wpbc_ts_handle_end"></span>
479 </div>
480 </div>
481 </div>
482 <?php endforeach; ?>
483 </div>
484 </div>
485
486 <?php if ( $args['show_legend'] ) : ?>
487 <div class="wpbc_ts_legend">
488 <span><i class="wpbc_ts_legend_available"></i><?php esc_html_e( 'Available', 'booking' ); ?></span>
489 <span><i class="wpbc_ts_legend_booked"><span class="wpbc_icn_lock"></span></i><?php esc_html_e( 'Booked', 'booking' ); ?></span>
490 <span><i class="wpbc_ts_legend_blocked"><span class="wpbc_icn_do_not_disturb_on"></span></i><?php esc_html_e( 'Blocked', 'booking' ); ?></span>
491 <span><i class="wpbc_ts_legend_unavailable_day"><span class="wpbc_icn_event_busy"></span></i><?php esc_html_e( 'Unavailable day', 'booking' ); ?></span>
492 <span><i class="wpbc_ts_legend_working_time"><span class="wpbc-bi-clock-history"></span></i><?php esc_html_e( 'Outside working time', 'booking' ); ?></span>
493 <span><i class="wpbc_ts_legend_selected"></i><?php esc_html_e( 'Selected pending changes', 'booking' ); ?></span>
494 <span class="wpbc_ts_legend_note"><span class="wpbc_icn_info_outline"></span><?php esc_html_e( 'Booked slots and availability rules cannot be changed here.', 'booking' ); ?></span>
495 </div>
496 <?php endif; ?>
497 </div>
498 </div>
499 <?php
500 }
501
502 /**
503 * Time Slots Availability tab.
504 */
505 class WPBC_Page_TimeSlots_Availability extends WPBC_Page_Structure {
506
507 /**
508 * Menu slug.
509 *
510 * @return string
511 */
512 public function in_page() {
513 return 'wpbc-availability';
514 }
515
516 /**
517 * Register tab.
518 *
519 * @return array
520 */
521 public function tabs() {
522
523 $tabs = array();
524 $tabs['time_slots_availability'] = array(
525 'is_show_top_path' => true,
526 'right_vertical_sidebar__is_show' => true,
527 'right_vertical_sidebar__default_view_mode' => '',
528 'right_vertical_sidebar_compact__is_show' => true,
529 'left_navigation__default_view_mode' => 'compact',
530 'top_path_title' => __( 'Time Slots Availability', 'booking' ),
531 'title' => __( 'Time Slots Availability', 'booking' ). // Title of TAB.
532 '<span class="wpbc_new_label" style="margin-left: auto;">' . esc_html__( 'New', 'booking' ) . '</span>',
533 'hint' => __( 'Flexible blocking time-slot ranges.', 'booking' ),
534 'page_title' => __( 'Time Slots Availability', 'booking' ),
535 'link' => '',
536 'position' => '',
537 'css_classes' => '',
538 'icon' => '',
539 'font_icon' => 'wpbc-bi-clock-history',
540 // 'font_icon_right' => 'wpbc-bi-question-circle', //.
541 'font_icon_right' => '',
542 'default' => false,
543 'disabled' => false,
544 'hided' => false,
545 'subtabs' => array(),
546 'folder_style' => 'order:92;',
547 );
548
549 return $tabs;
550 }
551
552 /**
553 * Right compact sidebar tabs.
554 *
555 * @return void
556 */
557 public function right_sidebar_compact_content() {
558
559 WPBC_UI_Sidebar_Panels::render_rightbar_tabs(
560 array(
561 array(
562 'id' => 'wpbc_tab_ts_summary',
563 'panel_id' => 'wpbc_ts__inspector_summary',
564 'title' => __( 'Selection', 'booking' ),
565 'icon' => 'wpbc-bi-check2-circle',
566 'selected' => true,
567 ),
568 array(
569 'id' => 'wpbc_tab_ts_settings',
570 'panel_id' => 'wpbc_ts__inspector_settings',
571 'title' => __( 'Settings', 'booking' ),
572 'icon' => 'wpbc_icn_tune',
573 ),
574 ),
575 array(
576 'aria_label' => __( 'Time Slots Availability Panels', 'booking' ),
577 'context' => 'time_slots_availability',
578 'class' => 'wpbc_ts_rightbar_tabs',
579 )
580 );
581 }
582
583 /**
584 * Right sidebar panels.
585 *
586 * @return void
587 */
588 public function right_sidebar_content() {
589 ?>
590 <div class="wpbc_bfb__panel--library wpbc_rightbar_palette wpbc_ts_rightbar_panels">
591 <?php
592 WPBC_UI_Sidebar_Panels::render_panel(
593 array(
594 'id' => 'wpbc_ts__inspector_summary',
595 'labelledby' => 'wpbc_tab_ts_summary',
596 'class' => 'wpbc_ts__inspector_summary',
597 ),
598 array( $this, 'right_panel_summary_content' )
599 );
600
601 WPBC_UI_Sidebar_Panels::render_panel(
602 array(
603 'id' => 'wpbc_ts__inspector_settings',
604 'labelledby' => 'wpbc_tab_ts_settings',
605 'class' => 'wpbc_ts__inspector_settings',
606 'hidden' => true,
607 ),
608 array( $this, 'right_panel_settings_content' )
609 );
610 ?>
611 </div>
612 <?php
613 }
614
615 /**
616 * Summary panel content.
617 *
618 * @return void
619 */
620 public function right_panel_summary_content() {
621
622 WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Selection', 'booking' ), __( 'Review selected time slots, then block or unblock them.', 'booking' ) );
623 ?>
624 <div class="wpbc_bfb__inspector__body wpbc_ts_inspector_body">
625 <?php
626 WPBC_UI_Sidebar_Panels::render_collapsible_group(
627 array(
628 'id' => 'wpbc_ts_action_group',
629 'group' => 'time-slots-actions',
630 'title' => __( 'Selected Time Slots', 'booking' ),
631 'open' => true,
632 ),
633 function () {
634 ?>
635 <?php wpbc_availability_timeslots__render_action_buttons(); ?>
636 <div class="wpbc_ts_inspector_row row__bordered">
637 <div class="wpbc_ts_inspector_label"><?php esc_html_e( 'Slots selected', 'booking' ); ?></div>
638 <div class="wpbc_ts_inspector_value"><strong data-wpbc-ts-detail="slots">0</strong></div>
639 <div class="wpbc_ts_inspector_row">
640 <div class="wpbc_ts_inspector_label"><?php esc_html_e( 'Dates', 'booking' ); ?></div>
641 <div class="wpbc_ts_inspector_value" data-wpbc-ts-detail="dates">-</div>
642 </div>
643 <div class="wpbc_ts_inspector_row">
644 <div class="wpbc_ts_inspector_label"><?php esc_html_e( 'Time', 'booking' ); ?></div>
645 <div class="wpbc_ts_inspector_value" data-wpbc-ts-detail="time">-</div>
646 </div>
647 </div>
648 <div class="wpbc_ts_selection_details" data-wpbc-ts-detail="selection_list">
649 <div class="wpbc_ts_selection_details_empty"><?php esc_html_e( 'No time slots selected.', 'booking' ); ?></div>
650 </div>
651 <?php
652 }
653 );
654 ?>
655 </div>
656 <?php
657 }
658
659 /**
660 * Settings panel content.
661 *
662 * @return void
663 */
664 public function right_panel_settings_content() {
665 $visible_start_minutes = 360;
666 $visible_end_minutes = 1320;
667
668 WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Timeline Settings', 'booking' ), __( 'Control the visible time window and selection precision.', 'booking' ) );
669 ?>
670 <div class="wpbc_bfb__inspector__body wpbc_ts_inspector_body">
671 <?php
672 WPBC_UI_Sidebar_Panels::render_collapsible_group(
673 array(
674 'id' => 'wpbc_ts_date_range_group',
675 'group' => 'time-slots-date-range',
676 'title' => __( 'Date Range', 'booking' ),
677 'open' => true,
678 ),
679 function () {
680 ?>
681 <div class="wpbc_ts_inspector_row">
682 <div class="wpbc_ts_inspector_label"><?php esc_html_e( 'Scroll range', 'booking' ); ?></div>
683 <div class="wpbc_ts_inspector_value">
684 <div class="wpbc_ts_range_nav wpbc_ts_range_nav_sidebar">
685 <a href="javascript:void(0)"
686 class="button tooltip_top button-secondary wpbc_button_no_background wpbc_ts_range_nav_button"
687 data-wpbc-ts-range-shift="prev"
688 aria-label="<?php esc_attr_e( 'Previous date range', 'booking' ); ?>"
689 data-original-title="<?php esc_attr_e( 'Previous date range', 'booking' ); ?>"><i class="menu_icon icon-1x wpbc_icn_keyboard_arrow_left"></i><span class="in-button-text"></span></a>
690 <a href="javascript:void(0)"
691 class="button tooltip_top button-secondary wpbc_button_no_background wpbc_ts_range_nav_button"
692 data-wpbc-ts-range-shift="next"
693 aria-label="<?php esc_attr_e( 'Next date range', 'booking' ); ?>"
694 data-original-title="<?php esc_attr_e( 'Next date range', 'booking' ); ?>"><i class="menu_icon icon-1x wpbc_icn_keyboard_arrow_right"></i><span class="in-button-text"></span></a>
695 </div>
696 </div>
697 </div>
698 <?php
699 }
700 );
701
702 WPBC_UI_Sidebar_Panels::render_collapsible_group(
703 array(
704 'id' => 'wpbc_ts_slot_precision_group',
705 'group' => 'time-slots-precision',
706 'title' => __( 'Time Step & Zoom', 'booking' ),
707 'open' => true,
708 ),
709 function () {
710 ?>
711 <div class="wpbc_ts_inspector_row">
712 <label class="wpbc_ts_inspector_label" for="wpbc_ts_side_slot_step"><?php esc_html_e( 'Slot step', 'booking' ); ?></label>
713 <div class="wpbc_ts_inspector_value">
714 <select id="wpbc_ts_side_slot_step" class="wpbc_ts_inspector_select">
715 <?php wpbc_availability_timeslots__render_slot_step_options( 15 ); ?>
716 </select>
717 </div>
718 </div>
719 <div class="wpbc_ts_inspector_row">
720 <div class="wpbc_ts_inspector_label"><?php esc_html_e( 'Zoom', 'booking' ); ?></div>
721 <div class="wpbc_ts_inspector_value">
722 <?php wpbc_availability_timeslots__render_zoom_control( 'wpbc_ts_side_zoom', 15, 'side_zoom' ); ?>
723 </div>
724 </div>
725 <?php
726 }
727 );
728
729 WPBC_UI_Sidebar_Panels::render_collapsible_group(
730 array(
731 'id' => 'wpbc_ts_time_window_group',
732 'group' => 'time-slots-visible-window',
733 'title' => __( 'Visible Time Range', 'booking' ),
734 'open' => true,
735 ),
736 function () use ( $visible_start_minutes, $visible_end_minutes ) {
737 ?>
738 <div class="wpbc_ts_inspector_row">
739 <label class="wpbc_ts_inspector_label" for="wpbc_ts_side_start"><?php esc_html_e( 'Start time', 'booking' ); ?></label>
740 <div class="wpbc_ts_inspector_value">
741 <select id="wpbc_ts_side_start" class="wpbc_ts_inspector_select">
742 <?php echo wpbc_availability_timeslots__get_time_options( $visible_start_minutes ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
743 </select>
744 </div>
745 </div>
746 <div class="wpbc_ts_inspector_row">
747 <label class="wpbc_ts_inspector_label" for="wpbc_ts_side_end"><?php esc_html_e( 'End time', 'booking' ); ?></label>
748 <div class="wpbc_ts_inspector_value">
749 <select id="wpbc_ts_side_end" class="wpbc_ts_inspector_select">
750 <?php echo wpbc_availability_timeslots__get_time_options( $visible_end_minutes ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
751 </select>
752 </div>
753 </div>
754 <div class="wpbc_ts_inspector_row">
755 <div class="wpbc_ts_inspector_label"><?php esc_html_e( 'Visible range', 'booking' ); ?></div>
756 <div class="wpbc_ts_inspector_value">
757 <div class="wpbc_ts_dual_slider">
758 <input id="wpbc_ts_side_start_slider" type="range" min="0" max="1440" step="60" value="<?php echo esc_attr( $visible_start_minutes ); ?>" aria-label="<?php esc_attr_e( 'Start time', 'booking' ); ?>" />
759 <input id="wpbc_ts_side_end_slider" type="range" min="0" max="1440" step="60" value="<?php echo esc_attr( $visible_end_minutes ); ?>" aria-label="<?php esc_attr_e( 'End time', 'booking' ); ?>" />
760 </div>
761 </div>
762 </div>
763 <?php
764 }
765 );
766 // TODO: add later Advanced Options.
767 if ( 0 )
768 WPBC_UI_Sidebar_Panels::render_collapsible_group(
769 array(
770 'id' => 'wpbc_ts_future_group',
771 'group' => 'time-slots-future-settings',
772 'title' => __( 'Advanced Options', 'booking' ),
773 ),
774 function () {
775 ?>
776 <div class="wpbc_ts_inspector_row row__bordered">
777 <div class="wpbc_ts_inspector_label"><?php esc_html_e( 'Extension area', 'booking' ); ?></div>
778 <div class="wpbc_ts_inspector_value"><?php esc_html_e( 'Rules, copy tools, templates, and resource constraints can be added here later.', 'booking' ); ?></div>
779 </div>
780 <?php
781 }
782 );
783 ?>
784 </div>
785 <?php
786 }
787
788 /**
789 * Show page content.
790 *
791 * @return void|false
792 */
793 public function content() {
794
795 do_action( 'wpbc_hook_settings_page_header', 'page_booking_availability_timeslots' );
796
797 if ( ! wpbc_is_mu_user_can_be_here( 'activated_user' ) ) {
798 return false;
799 }
800
801 wpbc_availability_timeslots__render_timeline_component();
802
803 do_action( 'wpbc_hook_settings_page_footer', 'page_booking_availability_timeslots' );
804 }
805 }
806 add_action( 'wpbc_menu_created', array( new WPBC_Page_TimeSlots_Availability(), '__construct' ) );
807