_customer.js
350 lines
| 1 | /* |
| 2 | * Copyright (c) 2023 LatePoint LLC. All rights reserved. |
| 3 | */ |
| 4 | |
| 5 | async function latepoint_init_transaction_payment_form() { |
| 6 | let callbacks_list = []; |
| 7 | let $transaction_payment_form = jQuery('.latepoint-transaction-payment-form'); |
| 8 | let current_step = $transaction_payment_form.find('input[name="current_step"]').val(); |
| 9 | |
| 10 | $transaction_payment_form.on('click keydown', '.lp-option', (e) => { |
| 11 | let $option = jQuery(e.currentTarget); |
| 12 | if(e.type === 'keydown' && e.key !== ' ' && e.key !== 'Enter') return; |
| 13 | $option.closest('.lp-options').find('.lp-option.selected').removeClass('selected'); |
| 14 | $option.addClass('selected'); |
| 15 | $transaction_payment_form.find('input[name="' + $option.data('holder') + '"]').val($option.data('value')); |
| 16 | $transaction_payment_form.trigger('submit'); |
| 17 | return false; |
| 18 | }); |
| 19 | |
| 20 | |
| 21 | switch (current_step) { |
| 22 | case 'methods': |
| 23 | break; |
| 24 | case 'processors': |
| 25 | break; |
| 26 | case 'pay': |
| 27 | $transaction_payment_form.trigger('latepoint:initOrderPaymentMethod', [{ |
| 28 | callbacks_list: callbacks_list, |
| 29 | payment_method: $transaction_payment_form.find('input[name="payment_method"]').val(), |
| 30 | payment_processor: $transaction_payment_form.find('input[name="payment_processor"]').val(), |
| 31 | }]); |
| 32 | $transaction_payment_form.addClass('os-loading'); |
| 33 | |
| 34 | try { |
| 35 | for (const callback of callbacks_list) { |
| 36 | await callback.action(); |
| 37 | } |
| 38 | $transaction_payment_form.removeClass('os-loading'); |
| 39 | } catch (error) { |
| 40 | latepoint_show_error_and_stop_loading_booking_form(error, $transaction_payment_form); |
| 41 | } |
| 42 | break; |
| 43 | case 'confirmation': |
| 44 | break; |
| 45 | } |
| 46 | |
| 47 | $transaction_payment_form.on('submit', async function (e) { |
| 48 | e.preventDefault(); |
| 49 | await latepoint_submit_transaction_payment_form(jQuery(e.target)); |
| 50 | }); |
| 51 | } |
| 52 | |
| 53 | async function latepoint_submit_transaction_payment_form($transaction_payment_form) { |
| 54 | |
| 55 | if($transaction_payment_form.hasClass('os-loading')) return false; |
| 56 | let callbacks_list = []; |
| 57 | |
| 58 | $transaction_payment_form.find('.latepoint-message').remove(); |
| 59 | $transaction_payment_form.addClass('os-loading'); |
| 60 | $transaction_payment_form.find('.latepoint-btn').addClass('os-loading'); |
| 61 | |
| 62 | $transaction_payment_form.trigger('latepoint:submitTransactionPaymentForm', [{ |
| 63 | callbacks_list: callbacks_list, |
| 64 | payment_method: $transaction_payment_form.find('input[name="payment_method"]').val(), |
| 65 | payment_processor: $transaction_payment_form.find('input[name="payment_processor"]').val(), |
| 66 | current_step: $transaction_payment_form.find('input[name="current_step"]').val(), |
| 67 | }]); |
| 68 | |
| 69 | try { |
| 70 | for (const callback of callbacks_list) { |
| 71 | await callback.action(); |
| 72 | } |
| 73 | } catch (error) { |
| 74 | $transaction_payment_form.removeClass('os-loading').find('.os-loading').removeClass('os-loading'); |
| 75 | latepoint_show_message_inside_element(error.message, $transaction_payment_form.find('.lp-payment-method-content'), 'error'); |
| 76 | return false; |
| 77 | } |
| 78 | |
| 79 | |
| 80 | try { |
| 81 | let response = await jQuery.ajax({ |
| 82 | type: "post", |
| 83 | dataType: "json", |
| 84 | processData: false, |
| 85 | contentType: false, |
| 86 | url: latepoint_timestamped_ajaxurl(), |
| 87 | data: latepoint_create_form_data($transaction_payment_form, latepoint_helper.invoices_payment_form_route) |
| 88 | }); |
| 89 | |
| 90 | $transaction_payment_form.removeClass('os-loading').find('.os-loading').removeClass('os-loading'); |
| 91 | |
| 92 | if (response.status === 'success') { |
| 93 | $transaction_payment_form.html(response.message); |
| 94 | return await latepoint_init_transaction_payment_form(); |
| 95 | |
| 96 | } else { |
| 97 | latepoint_show_message_inside_element(response.message, $transaction_payment_form.find('.lp-payment-method-content'), 'error'); |
| 98 | return false; |
| 99 | } |
| 100 | } catch (e) { |
| 101 | |
| 102 | $transaction_payment_form.removeClass('os-loading').find('.os-loading').removeClass('os-loading'); |
| 103 | console.log(e); |
| 104 | alert('Error:' + e); |
| 105 | } |
| 106 | |
| 107 | } |
| 108 | |
| 109 | function latepoint_hide_reschedule_button() { |
| 110 | jQuery('.reschedule-confirmation-button-wrapper').hide(); |
| 111 | } |
| 112 | |
| 113 | function latepoint_show_reschedule_button() { |
| 114 | jQuery('.reschedule-confirmation-button-wrapper').show(); |
| 115 | } |
| 116 | |
| 117 | function latepoint_customer_cabinet_reload_booking_tile($booking_tile) { |
| 118 | $booking_tile.addClass('os-loading'); |
| 119 | let params = { |
| 120 | booking_id: $booking_tile.data('id'), |
| 121 | } |
| 122 | let data = { |
| 123 | action: latepoint_helper.route_action, |
| 124 | route_name: $booking_tile.data('route-name'), |
| 125 | params: params, |
| 126 | layout: 'none', |
| 127 | return_format: 'json' |
| 128 | }; |
| 129 | jQuery.ajax({ |
| 130 | type: "post", |
| 131 | dataType: "json", |
| 132 | url: latepoint_timestamped_ajaxurl(), |
| 133 | data: data, |
| 134 | success: function (data) { |
| 135 | $booking_tile.removeClass('os-loading') |
| 136 | if (data.status === "success") { |
| 137 | $booking_tile.replaceWith(data.message); |
| 138 | } else { |
| 139 | alert(data.message); |
| 140 | } |
| 141 | } |
| 142 | }); |
| 143 | } |
| 144 | |
| 145 | |
| 146 | function latepoint_init_reschedule() { |
| 147 | |
| 148 | jQuery('.reschedule-calendar-wrapper').on('click', '.latepoint-request-reschedule-trigger', function () { |
| 149 | let $trigger = jQuery(this) |
| 150 | let $wrapper = $trigger.closest('.reschedule-calendar-wrapper') |
| 151 | let booking_id = $wrapper.find('input[type="hidden"].latepoint_booking_id').val() |
| 152 | |
| 153 | $trigger.addClass('os-loading') |
| 154 | let params = { |
| 155 | booking_id: booking_id, |
| 156 | key: $wrapper.find('input[type="hidden"].latepoint_manage_booking_key').val(), |
| 157 | start_date: $wrapper.find('input[type="hidden"].latepoint_start_date').val(), |
| 158 | start_time: $wrapper.find('input[type="hidden"].latepoint_start_time').val(), |
| 159 | } |
| 160 | let data = { |
| 161 | action: latepoint_helper.route_action, |
| 162 | route_name: $trigger.data('route-name'), |
| 163 | params: params, |
| 164 | layout: 'none', |
| 165 | return_format: 'json' |
| 166 | }; |
| 167 | jQuery.ajax({ |
| 168 | type: "post", |
| 169 | dataType: "json", |
| 170 | url: latepoint_timestamped_ajaxurl(), |
| 171 | data: data, |
| 172 | success: function (data) { |
| 173 | $trigger.removeClass('os-loading') |
| 174 | if (data.status === "success") { |
| 175 | jQuery('.latepoint-lightbox-content').html(data.message); |
| 176 | jQuery('.latepoint-lightbox-footer, .latepoint-lightbox-heading').remove(); |
| 177 | if (jQuery('.customer-bookings-tiles').length) { |
| 178 | // called from customer cabinet |
| 179 | latepoint_customer_cabinet_reload_booking_tile(jQuery('.customer-bookings-tiles .customer-booking[data-id="' + booking_id + '"]')); |
| 180 | } else { |
| 181 | // called from manage by key |
| 182 | latepoint_manage_by_key_reload_booking(); |
| 183 | } |
| 184 | } else { |
| 185 | latepoint_show_message_inside_element(data.message, jQuery('.latepoint-lightbox-content'), 'error'); |
| 186 | jQuery('.latepoint-lightbox-content').animate({scrollTop: 0}, 300); |
| 187 | } |
| 188 | } |
| 189 | }); |
| 190 | return false; |
| 191 | }); |
| 192 | |
| 193 | jQuery('.reschedule-calendar-wrapper').on('click keydown', '.dp-timepicker-trigger', function (event) { |
| 194 | if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return; |
| 195 | var $reschedule_form_element = jQuery(this).closest('.reschedule-calendar-wrapper'); |
| 196 | if (jQuery(this).hasClass('is-booked') || jQuery(this).hasClass('is-off')) { |
| 197 | // Show error message that you cant select a booked period |
| 198 | } else { |
| 199 | if (jQuery(this).hasClass('selected')) { |
| 200 | jQuery(this).removeClass('selected'); |
| 201 | jQuery(this).find('.dp-success-label').remove(); |
| 202 | $reschedule_form_element.find('.latepoint_start_time').val(''); |
| 203 | latepoint_hide_reschedule_button(); |
| 204 | } else { |
| 205 | $reschedule_form_element.find('.dp-timepicker-trigger.selected').removeClass('selected').find('.dp-success-label').remove(); |
| 206 | var selected_timeslot_time = jQuery(this).find('.dp-label-time').html(); |
| 207 | jQuery(this).addClass('selected').find('.dp-label').prepend('<span class="dp-success-label">' + latepoint_helper.datepicker_timeslot_selected_label + '</span>'); |
| 208 | |
| 209 | var minutes = parseInt(jQuery(this).data('minutes')); |
| 210 | var timeshift_minutes = parseInt($reschedule_form_element.find('.latepoint_timeshift_minutes').val()); |
| 211 | // we substract timeshift minutes because its timeshift minutes that the business is running in, in opposite of what we do when we generate a calendar for a client |
| 212 | if (timeshift_minutes) minutes = minutes - timeshift_minutes; |
| 213 | var start_date = new Date($reschedule_form_element.find('.os-day.selected').data('date')); |
| 214 | if (minutes < 0) { |
| 215 | // business minutes are in previous day |
| 216 | minutes = 24 * 60 + minutes; |
| 217 | // move start date back 1 day |
| 218 | start_date.setDate(start_date.getDate() - 1); |
| 219 | } else if (minutes >= 24 * 60) { |
| 220 | // business minutes are in next day |
| 221 | minutes = minutes - 24 * 60; |
| 222 | start_date.setDate(start_date.getDate() + 1); |
| 223 | } |
| 224 | $reschedule_form_element.find('.latepoint_start_date').val(start_date.toISOString().split('T')[0]) |
| 225 | $reschedule_form_element.find('.latepoint_start_time').val(minutes); |
| 226 | latepoint_show_reschedule_button(); |
| 227 | } |
| 228 | } |
| 229 | return false; |
| 230 | }); |
| 231 | |
| 232 | |
| 233 | jQuery('.reschedule-calendar-wrapper').on('click', '.os-month-next-btn', function () { |
| 234 | var $reschedule_form_element = jQuery(this).closest('.reschedule-calendar-wrapper'); |
| 235 | var next_month_route_name = jQuery(this).data('route'); |
| 236 | if ($reschedule_form_element.find('.os-monthly-calendar-days-w.active + .os-monthly-calendar-days-w').length) { |
| 237 | $reschedule_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').next('.os-monthly-calendar-days-w').addClass('active'); |
| 238 | latepoint_calendar_set_month_label($reschedule_form_element); |
| 239 | } else { |
| 240 | // TODO add condition to check maximum number months to call into the future |
| 241 | if (true) { |
| 242 | var $btn = jQuery(this); |
| 243 | $btn.addClass('os-loading'); |
| 244 | var $calendar_element = $reschedule_form_element.find('.os-monthly-calendar-days-w').last(); |
| 245 | var calendar_year = $calendar_element.data('calendar-year'); |
| 246 | var calendar_month = $calendar_element.data('calendar-month'); |
| 247 | if (calendar_month == 12) { |
| 248 | calendar_year = calendar_year + 1; |
| 249 | calendar_month = 1; |
| 250 | } else { |
| 251 | calendar_month = calendar_month + 1; |
| 252 | } |
| 253 | var data = { |
| 254 | action: latepoint_helper.route_action, |
| 255 | route_name: next_month_route_name, |
| 256 | params: { |
| 257 | timezone_name: $reschedule_form_element.find('input[type="hidden"].latepoint_timezone_name').val(), |
| 258 | key: $reschedule_form_element.find('input[type="hidden"].latepoint_manage_booking_key').val(), |
| 259 | target_date_string: `${calendar_year}-${calendar_month}-1`, |
| 260 | booking: { |
| 261 | id: $reschedule_form_element.find('input[type="hidden"].latepoint_booking_id').val() |
| 262 | } |
| 263 | }, |
| 264 | layout: 'none', |
| 265 | return_format: 'json' |
| 266 | } |
| 267 | jQuery.ajax({ |
| 268 | type: "post", |
| 269 | dataType: "json", |
| 270 | url: latepoint_timestamped_ajaxurl(), |
| 271 | data: data, |
| 272 | success: function (data) { |
| 273 | $btn.removeClass('os-loading'); |
| 274 | if (data.status === "success") { |
| 275 | $reschedule_form_element.find('.os-months').append(data.message); |
| 276 | $reschedule_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').next('.os-monthly-calendar-days-w').addClass('active'); |
| 277 | latepoint_calendar_set_month_label($reschedule_form_element); |
| 278 | } else { |
| 279 | // console.log(data.message); |
| 280 | } |
| 281 | } |
| 282 | }); |
| 283 | } |
| 284 | } |
| 285 | latepoint_calendar_show_or_hide_prev_next_buttons($reschedule_form_element); |
| 286 | return false; |
| 287 | }); |
| 288 | |
| 289 | jQuery('.reschedule-calendar-wrapper').on('click', '.os-month-prev-btn', function () { |
| 290 | var $reschedule_form_element = jQuery(this).closest('.reschedule-calendar-wrapper'); |
| 291 | if ($reschedule_form_element.find('.os-monthly-calendar-days-w.active').prev('.os-monthly-calendar-days-w').length) { |
| 292 | $reschedule_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').prev('.os-monthly-calendar-days-w').addClass('active'); |
| 293 | latepoint_calendar_set_month_label($reschedule_form_element); |
| 294 | } |
| 295 | latepoint_calendar_show_or_hide_prev_next_buttons($reschedule_form_element); |
| 296 | return false; |
| 297 | }); |
| 298 | |
| 299 | jQuery('.reschedule-calendar-wrapper .os-months').on('click', '.os-day', function () { |
| 300 | if (jQuery(this).hasClass('os-day-passed')) return false; |
| 301 | if (jQuery(this).hasClass('os-not-in-allowed-period')) return false; |
| 302 | var $reschedule_form_element = jQuery(this).closest('.reschedule-calendar-wrapper'); |
| 303 | if (jQuery(this).closest('.os-monthly-calendar-days-w').hasClass('hide-if-single-slot')) { |
| 304 | |
| 305 | // HIDE TIMESLOT IF ONLY ONE TIMEPOINT |
| 306 | if (jQuery(this).hasClass('os-not-available')) { |
| 307 | // clicked on a day that has no available timeslots |
| 308 | // do nothing |
| 309 | } else { |
| 310 | $reschedule_form_element.find('.os-day.selected').removeClass('selected'); |
| 311 | jQuery(this).addClass('selected'); |
| 312 | // set date |
| 313 | $reschedule_form_element.find('.latepoint_start_date').val(jQuery(this).data('date')); |
| 314 | if (jQuery(this).hasClass('os-one-slot-only')) { |
| 315 | // clicked on a day that has only one slot available |
| 316 | var bookable_minutes = jQuery(this).data('bookable-minutes').toString().split(':')[0]; |
| 317 | var selected_timeslot_time = latepoint_format_minutes_to_time(Number(bookable_minutes), Number(jQuery(this).data('service-duration'))); |
| 318 | $reschedule_form_element.find('.latepoint_start_time').val(jQuery(this).data('bookable-minutes')); |
| 319 | $reschedule_form_element.find('.time-selector-w').slideUp(200); |
| 320 | latepoint_show_reschedule_button() |
| 321 | } else { |
| 322 | // regular day with more than 1 timeslots available |
| 323 | // build timeslots |
| 324 | day_timeslots(jQuery(this), $reschedule_form_element, $reschedule_form_element.find('.latepoint-lightbox-content')); |
| 325 | // initialize timeslots events |
| 326 | // clear time and hide next btn |
| 327 | $reschedule_form_element.find('.latepoint_start_time').val(''); |
| 328 | } |
| 329 | } |
| 330 | } else { |
| 331 | |
| 332 | // SHOW TIMESLOTS EVEN IF ONLY ONE TIMEPOINT |
| 333 | $reschedule_form_element.find('.latepoint_start_date').val(jQuery(this).data('date')); |
| 334 | $reschedule_form_element.find('.os-day.selected').removeClass('selected'); |
| 335 | jQuery(this).addClass('selected'); |
| 336 | |
| 337 | // build timeslots |
| 338 | day_timeslots(jQuery(this), $reschedule_form_element, $reschedule_form_element.find('.latepoint-lightbox-content')); |
| 339 | // initialize timeslots events |
| 340 | // clear time and hide next btn |
| 341 | let $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element'); |
| 342 | if ($booking_form_element.length) latepoint_reload_summary($booking_form_element); |
| 343 | $reschedule_form_element.find('.latepoint_start_time').val(''); |
| 344 | latepoint_hide_next_btn($reschedule_form_element); |
| 345 | } |
| 346 | |
| 347 | return false; |
| 348 | }); |
| 349 | } |
| 350 |