| 1 |
<?php |
| 2 |
/** |
| 3 |
* Reusable Days Off and date-availability editor. |
| 4 |
* |
| 5 |
* @package Booking Calendar |
| 6 |
* @var array<string,mixed> $template_context Authorized step context. |
| 7 |
*/ |
| 8 |
|
| 9 |
if ( ! defined( 'ABSPATH' ) ) { |
| 10 |
exit; |
| 11 |
} |
| 12 |
|
| 13 |
$step_data = isset( $template_context['step_data'] ) && is_array( $template_context['step_data'] ) ? $template_context['step_data'] : array(); |
| 14 |
$can_manage = ! empty( $step_data['can_manage'] ); |
| 15 |
$has_resources = ! empty( $step_data['has_resources'] ); |
| 16 |
$resources = isset( $step_data['resources'] ) && is_array( $step_data['resources'] ) ? $step_data['resources'] : array(); |
| 17 |
$apply_options = isset( $step_data['apply_options'] ) && is_array( $step_data['apply_options'] ) ? $step_data['apply_options'] : array(); |
| 18 |
$ranges = isset( $step_data['ranges'] ) && is_array( $step_data['ranges'] ) ? $step_data['ranges'] : array(); |
| 19 |
$first_date = isset( $step_data['default_first_date'] ) ? (string) $step_data['default_first_date'] : ''; |
| 20 |
$last_date = isset( $step_data['default_last_date'] ) ? (string) $step_data['default_last_date'] : ''; |
| 21 |
$initial_state = wp_json_encode( $step_data, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT ); |
| 22 |
$initial_state = false === $initial_state ? '{}' : $initial_state; |
| 23 |
$staged_values = isset( $template_context['values']['days_off'] ) && is_array( $template_context['values']['days_off'] ) |
| 24 |
? $template_context['values']['days_off'] |
| 25 |
: array( |
| 26 |
'revision' => isset( $step_data['revision'] ) ? (string) $step_data['revision'] : '', |
| 27 |
'unavailable_dates' => isset( $step_data['unavailable_dates'] ) && is_array( $step_data['unavailable_dates'] ) ? $step_data['unavailable_dates'] : array(), |
| 28 |
); |
| 29 |
$staged_json = wp_json_encode( $staged_values ); |
| 30 |
$staged_json = false === $staged_json ? '{"revision":"","unavailable_dates":{}}' : $staged_json; |
| 31 |
$is_aggregate_scope = ! empty( $step_data['is_aggregate_scope'] ); |
| 32 |
$aggregate_legend_html = ''; |
| 33 |
$resource_legend_html = ''; |
| 34 |
if ( function_exists( 'wpbc_get_calendar_legend__content_html' ) && ! empty( $resources ) ) { |
| 35 |
$aggregate_legend_html = wpbc_get_calendar_legend__content_html( |
| 36 |
array( |
| 37 |
'is_vertical' => false, |
| 38 |
'text_for_day_cell' => gmdate( 'd' ), |
| 39 |
'items' => array( 'available', 'resource_unavailable', 'resources_partially_unavailable', 'resources_have_bookings' ), |
| 40 |
'unavailable_day_cell_tag' => 'a', |
| 41 |
'resource_id' => absint( $resources[0]['id'] ), |
| 42 |
'titles' => array( |
| 43 |
'available' => __( 'Available', 'booking' ), |
| 44 |
'resource_unavailable' => __( 'Unavailable', 'booking' ), |
| 45 |
'resources_partially_unavailable' => __( 'Some booking items unavailable', 'booking' ), |
| 46 |
'resources_have_bookings' => __( 'Bookings exist for one or more booking items', 'booking' ), |
| 47 |
), |
| 48 |
) |
| 49 |
); |
| 50 |
$resource_legend_html = wpbc_get_calendar_legend__content_html( |
| 51 |
array( |
| 52 |
'is_vertical' => false, |
| 53 |
'text_for_day_cell' => gmdate( 'd' ), |
| 54 |
'items' => array( 'available', 'resource_unavailable', 'approved', 'pending', 'partially' ), |
| 55 |
'unavailable_day_cell_tag' => 'a', |
| 56 |
'resource_id' => absint( $resources[0]['id'] ), |
| 57 |
'titles' => array( |
| 58 |
'available' => __( 'Available', 'booking' ), |
| 59 |
'resource_unavailable' => __( 'Unavailable', 'booking' ), |
| 60 |
'approved' => __( 'Approved booking', 'booking' ), |
| 61 |
'pending' => __( 'Pending booking', 'booking' ), |
| 62 |
'partially' => __( 'Partially booked', 'booking' ), |
| 63 |
), |
| 64 |
) |
| 65 |
); |
| 66 |
} |
| 67 |
?> |
| 68 |
<section class="wpbc_setup_wizard__step-content wpbc_setup_wizard__days-off-step" aria-labelledby="wpbc-setup-wizard-step-title" data-wpbc-days-off-editor> |
| 69 |
<header class="wpbc_setup_wizard__step-heading"> |
| 70 |
<h1 id="wpbc-setup-wizard-step-title"><?php esc_html_e( 'Set days off and date availability', 'booking' ); ?></h1> |
| 71 |
<p class="wpbc_setup_wizard__lead"><?php esc_html_e( 'Add the dates when your business is closed.', 'booking' ); ?></p> |
| 72 |
</header> |
| 73 |
<?php |
| 74 |
$template_context['templates']->render( |
| 75 |
'settings-hint', |
| 76 |
array( 'settings_hint' => $template_context['settings_hint'] ) |
| 77 |
); |
| 78 |
?> |
| 79 |
|
| 80 |
<form class="wpbc_setup_wizard__content-panel wpbc_setup_wizard__days-off-panel" id="wpbc-setup-wizard-step-form" novalidate> |
| 81 |
<input type="hidden" name="days_off" value="<?php echo esc_attr( $staged_json ); ?>" data-wpbc-setup-wizard-field data-wpbc-days-off-value> |
| 82 |
<?php if ( $can_manage && $has_resources ) : ?> |
| 83 |
<div class="wpbc_setup_wizard__days-off-fields"> |
| 84 |
<div class="wpbc_setup_wizard__field"> |
| 85 |
<label for="wpbc-setup-wizard-days-off-first-date"><?php esc_html_e( 'First date', 'booking' ); ?></label> |
| 86 |
<output id="wpbc-setup-wizard-days-off-first-date" class="wpbc_setup_wizard__days-off-date-output" data-wpbc-days-off-first-date aria-live="polite"><?php echo esc_html( $first_date ); ?></output> |
| 87 |
</div> |
| 88 |
<div class="wpbc_setup_wizard__field"> |
| 89 |
<label for="wpbc-setup-wizard-days-off-last-date"><?php esc_html_e( 'Last date', 'booking' ); ?></label> |
| 90 |
<output id="wpbc-setup-wizard-days-off-last-date" class="wpbc_setup_wizard__days-off-date-output" data-wpbc-days-off-last-date aria-live="polite"><?php echo esc_html( $last_date ); ?></output> |
| 91 |
</div> |
| 92 |
<div class="wpbc_setup_wizard__field"> |
| 93 |
<label for="wpbc-setup-wizard-days-off-scope"><?php esc_html_e( 'Apply to', 'booking' ); ?></label> |
| 94 |
<select id="wpbc-setup-wizard-days-off-scope" data-wpbc-days-off-scope aria-describedby="wpbc-setup-wizard-days-off-error"> |
| 95 |
<?php foreach ( $apply_options as $apply_option ) : ?> |
| 96 |
<option value="<?php echo esc_attr( (string) $apply_option['value'] ); ?>"><?php echo esc_html( (string) $apply_option['label'] ); ?></option> |
| 97 |
<?php endforeach; ?> |
| 98 |
</select> |
| 99 |
</div> |
| 100 |
</div> |
| 101 |
|
| 102 |
<div class="wpbc_setup_wizard__days-off-native-availability wpbc_ajx_availability_container"> |
| 103 |
<div class="wpbc_setup_wizard__days-off-picker-layout"> |
| 104 |
<div class="wpbc_setup_wizard__days-off-calendar-column" data-wpbc-days-off-calendar-column> |
| 105 |
<div class="wpbc_cal_container bk_calendar_frame months_num_in_row_2 cal_month_num_2" style="width:100%;max-width:1023px;"> |
| 106 |
<div id="wpbc-setup-wizard-days-off-calendar" class="wpbc_setup_wizard__days-off-calendar wpbc_calendar_id_0" data-wpbc-days-off-calendar aria-label="<?php esc_attr_e( 'Select the first and last unavailable date', 'booking' ); ?>"></div> |
| 107 |
</div> |
| 108 |
</div> |
| 109 |
<aside class="wpbc_setup_wizard__days-off-summary" aria-labelledby="wpbc-setup-wizard-days-off-summary-title"> |
| 110 |
<strong id="wpbc-setup-wizard-days-off-summary-title" data-wpbc-days-off-summary-range></strong> |
| 111 |
<span data-wpbc-days-off-summary-count></span> |
| 112 |
<button type="button" class="button button-primary wpbc_setup_wizard__days-off-add" data-wpbc-days-off-add><?php esc_html_e( 'Add range', 'booking' ); ?></button> |
| 113 |
<button type="button" class="button-link wpbc_setup_wizard__days-off-clear" data-wpbc-days-off-clear><?php esc_html_e( 'Clear selection', 'booking' ); ?></button> |
| 114 |
</aside> |
| 115 |
</div> |
| 116 |
|
| 117 |
<?php if ( '' !== $aggregate_legend_html || '' !== $resource_legend_html ) : ?> |
| 118 |
<div class="wpbc_setup_wizard__days-off-legend" data-wpbc-days-off-aggregate-legend aria-label="<?php esc_attr_e( 'All booking items calendar legend', 'booking' ); ?>"<?php if ( ! $is_aggregate_scope ) : ?> hidden<?php endif; ?>> |
| 119 |
<?php echo $aggregate_legend_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Generated by the core allow-listed Booking Calendar legend renderer. ?> |
| 120 |
</div> |
| 121 |
<div class="wpbc_setup_wizard__days-off-legend" data-wpbc-days-off-resource-legend aria-label="<?php esc_attr_e( 'Booking item calendar legend', 'booking' ); ?>"<?php if ( $is_aggregate_scope ) : ?> hidden<?php endif; ?>> |
| 122 |
<?php echo $resource_legend_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Generated by the core allow-listed Booking Calendar legend renderer. ?> |
| 123 |
</div> |
| 124 |
<?php endif; ?> |
| 125 |
</div> |
| 126 |
|
| 127 |
<div class="wpbc_setup_wizard__field-error wpbc_setup_wizard__days-off-error" id="wpbc-setup-wizard-days-off-error" data-wpbc-days-off-error role="alert"></div> |
| 128 |
|
| 129 |
<section class="wpbc_setup_wizard__days-off-upcoming" aria-labelledby="wpbc-setup-wizard-days-off-upcoming-title"> |
| 130 |
<h2 id="wpbc-setup-wizard-days-off-upcoming-title"><?php esc_html_e( 'Upcoming unavailable dates', 'booking' ); ?></h2> |
| 131 |
<p class="wpbc_setup_wizard__days-off-empty" data-wpbc-days-off-empty<?php if ( ! empty( $ranges ) ) : ?> hidden<?php endif; ?>><?php esc_html_e( 'No upcoming unavailable dates.', 'booking' ); ?></p> |
| 132 |
<ul class="wpbc_setup_wizard__days-off-ranges" data-wpbc-days-off-ranges> |
| 133 |
<?php foreach ( $ranges as $range ) : ?> |
| 134 |
<li> |
| 135 |
<span><?php echo esc_html( (string) $range['label'] ); ?></span> |
| 136 |
<span><?php echo esc_html( (string) $range['scope_label'] ); ?></span> |
| 137 |
<button type="button" class="wpbc_setup_wizard__days-off-remove" data-wpbc-days-off-remove data-first-date="<?php echo esc_attr( (string) $range['first_date'] ); ?>" data-last-date="<?php echo esc_attr( (string) $range['last_date'] ); ?>" data-scope="<?php echo esc_attr( (string) $range['scope'] ); ?>" aria-label="<?php esc_attr_e( 'Remove unavailable date range', 'booking' ); ?>"> |
| 138 |
<i class="menu_icon icon-1x wpbc_icn_delete_outline" aria-hidden="true"></i> |
| 139 |
</button> |
| 140 |
</li> |
| 141 |
<?php endforeach; ?> |
| 142 |
</ul> |
| 143 |
</section> |
| 144 |
<?php else : ?> |
| 145 |
<div class="wpbc_setup_wizard__days-off-permission wpbc_setup_wizard__message wpbc_setup_wizard__message--warning"> |
| 146 |
<?php if ( $can_manage ) : ?> |
| 147 |
<p><?php esc_html_e( 'No booking items are available for date availability yet. You can continue and configure days off later.', 'booking' ); ?></p> |
| 148 |
<?php else : ?> |
| 149 |
<p><?php esc_html_e( 'Your account can continue the Setup Wizard, but it cannot change Days Availability. Ask an administrator with Availability permission to configure days off.', 'booking' ); ?></p> |
| 150 |
<?php endif; ?> |
| 151 |
</div> |
| 152 |
<?php endif; ?> |
| 153 |
</form> |
| 154 |
|
| 155 |
<script type="application/json" data-wpbc-days-off-state><?php echo $initial_state; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON is hex-escaped above. ?></script> |
| 156 |
</section> |
| 157 |
|