Uname: Linux webm012.cluster130.gra.hosting.ovh.net 5.15.167-ovh-vps-grsec-zfs-classid #1 SMP Tue Sep 17 08:14:20 UTC 2024 x86_64
Software: Apache
PHP version: 8.0.30 [ PHP INFO ] PHP os: Linux
Server Ip: 145.239.37.162
Your Ip: 216.73.216.190
User: dreampi (1009562) | Group: users (100)
Safe Mode: OFF
Disable Function:
_dyuweyrj4,_dyuweyrj4r,dl

name : ConfirmBooking.vue
<template>
  <div
    id="am-confirm-booking"
    class="am-confirmation-booking"
    :class="[dialogClass, ($root.settings.customization.hasOwnProperty('forms') && $root.settings.customization.forms.hasOwnProperty(formType)) ? `am-form-${formType}-${formName}-${bookableType}` : '']"
  >

    <!-- Confirm Booking Form -->
    <div v-show="fetched">

      <!-- Header Error-->
      <div class="am-payment-error">
        <el-alert
          :id="'am-payment-error-' + $root.shortcodeData.counter"
          :title="headerErrorMessage !== '' ? headerErrorMessage : $root.labels.payment_error"
          type="warning"
          v-show="headerErrorShow"
          show-icon
        >
        </el-alert>
      </div>
      <!-- /Header Error-->

      <!-- Confirm Dialog Header -->
      <div class="am-confirmation-booking-header" v-show="fetched" v-if="bookableType === 'appointment' && serviceHeadingVisibility">
        <img :src="pictureLoad(bookable, false)" @error="imageLoadError(bookable, false)" :alt="bookable.name"/>
        <h2 :style="{fontWeight: 500, fontFamily: $root.settings.customization.font}" :class="`am-block-${formType}-${formName}-${bookableType}`">
          {{ bookable.name }}
        </h2>
      </div>
      <!-- /Confirm Dialog Header -->

      <!-- Confirm Dialog Package -->
      <div class="am-confirmation-booking-package-wrapper" v-if="bookableType === 'package' && hasHeader">

        <!-- Package Header -->
        <div class="am-package-header">
          <!-- Package Header Image Data container -->
          <div class="am-package-header-image-data-wrapper">
            <!-- Package Image -->
            <div class="am-package-image">
              <img :src="pictureLoad(bookable, false)" @error="imageLoadError(bookable, false)"/>
              <span :style="{'background-color': bookable.color}">
                <img :src="$root.getUrl + 'public/img/am-package-catalog.svg'">
              </span>
            </div>
            <!-- /Package Image -->

            <!-- Package Data -->
            <div class="am-package-data">

              <!-- Package Name -->
              <div class="am-package-title">
                <h2 :style="{fontWeight: 500, fontFamily: $root.settings.customization.font}">
                  {{ bookable.name }}
                </h2>
              </div>
              <!-- /Package Name -->
            </div>
            <!-- /Package Data -->
          </div>
          <!-- /Package Header Image Data container -->

          <!-- Package Price Container -->
          <div class="am-package-price" v-if="bookable.price">
            <!-- Package Price -->
            <div class="am-package-price__wrapper" :class="{'am-service-price__wrapper-discount': bookable.discount && !bookable.calculatedPrice}">
              {{ getFormattedPrice(bookable.price, !$root.settings.payments.hideCurrencySymbolFrontend) }}
            </div>
            <!-- /Package Price -->

            <!-- Package Discount -->
            <div v-if="bookable.discount && !bookable.calculatedPrice" class="am-package-price__discount">
              <img class="am-package-price__discount-image" :src="$root.getUrl + 'public/img/am-package-catalog.svg'">
              <div class="am-package-price__discount-text">
                {{ $root.labels.package_discount_text + ' ' + bookable.discount + '%' }}
              </div>
            </div>
            <!-- /Package Discount -->
          </div>
          <!-- /Package Price Container -->

        </div>
        <!-- /Package Header -->
      </div>
      <!-- /Confirm Dialog Package -->

      <!-- Confirm Dialog Body -->
      <el-form
        :model="appointment.bookings[0]"
        ref="booking"
        :rules="rules"
        label-position="top"
        @submit.prevent="onSubmit"
        class="am-confirm-booking-form"
      >
        <el-row class="am-confirm-booking-data" :gutter="24">
          <!-- Booking Data -->
          <el-col :sm="24" v-if="bookableType === 'appointment'">
            <confirm-heading-data-form-field
              :bookable-start="bookable.bookingStart"
              :provider="provider"
              :location="location"
              :form-field="formsData[formName][bookableType].itemsStatic"
            ></confirm-heading-data-form-field>
          </el-col>
          <!-- /Booking Data -->

          <el-col :sm="24" v-if="recurringData.length && recurringStringVisibility">
            <recurring-string-form-field
              :recurring-string="recurringString"
              :form-field="formsData[formName][bookableType].itemsStatic"
            ></recurring-string-form-field>
          </el-col>

          <template v-for="(formField, key) in formsData[formName][bookableType].itemsDraggable">
            <component
              :is="key"
              :appointment="appointment"
              :columns-lg="columnsLg"
              :form-valid-options="formValidOptions"
              :errors="errors"
              :phone-populated="!!phonePopulated"
              :class-identifier="($root.settings.customization.hasOwnProperty('forms') && $root.settings.customization.forms.hasOwnProperty(formType)) ? `${formType}-${formName}-${bookableType}` : ''"
              :formField="formField"
              @inputChanges="validateFieldsForPayPal"
            >
            </component>
          </template>

          <!-- Custom Fields -->
          <div class="am-custom-fields">
            <el-row :gutter="24">
              <el-col
                v-for="(customField, key) in customFields"
                v-if="isBookableCustomFieldVisible(customField)"
                :key="customField.id"
                :sm="columnsLg"
                :ref="'customFields.' + customField.id + '.value'"
              >
                <el-form-item
                  :label="(customField.type !== 'content' && customField.type !== 'checkbox' && customField.type !== 'radio') && customField.label ? customField.label : ''"
                  :prop="customField.required === true && customField.type !== 'content' && customField.type !== 'file' ? 'customFields.' + customField.id + '.value' : (customField.required === true && customField.type !== 'file' ? 'inputFile' : null)"
                  :error="errors.files && customField.type === 'file' && customField.required ? errors.files['files' + customField.id] : null"
                  :class="[
                    getCustomFieldClass(customField),
                    ($root.settings.customization.hasOwnProperty('forms') && $root.settings.customization.forms.hasOwnProperty(formType)) ? `am-custom-${formType}-${formName}-${bookableType}` : ''
                  ]"
                >
                  <span
                    v-if="(customField.type === 'checkbox' || customField.type === 'radio') && customField.label" v-html="customField.label ? '<label class=' + '\'el-form-item__label\'>' + customField.label + '</label>' : ''"
                    :class="(customField.type === 'checkbox' || customField.type === 'radio') && customField.required ? 'am-custom-required-as-html' : ''">
                  </span>

                  <!-- Text Field -->
                  <el-input
                    v-if="customField.type === 'text'"
                    placeholder=""
                    v-model="appointment.bookings[0].customFields[customField.id].value"
                    @input="validateFieldsForPayPal()"
                  >
                  </el-input>
                  <!-- /Text Field -->

                  <!-- Address Field -->
                  <div class="el-input" v-if="customField.type === 'address'" :style="{marginBottom: $root.settings.general.gMapApiKey ? '':0}">
                    <vue-google-autocomplete
                      v-if="googleMapsLoaded()"
                      :ref="'amelia-cf-address-'+customField.id"
                      :id="'address-autocomplete-'+customField.id"
                      classname="el-input__inner"
                      @change="setAddressCF($event, customField.id)"
                      placeholder=""
                      types=""
                    >
                    </vue-google-autocomplete>
                    <el-input
                      v-else
                      placeholder=""
                      v-model="appointment.bookings[0].customFields[customField.id].value"
                      @input="validateFieldsForPayPal()"
                    >
                    </el-input>
                  </div>
                  <!-- /Address Field -->

                  <!-- Text Area -->
                  <el-input
                    v-else-if="customField.type === 'text-area'"
                    class="am-front-texarea"
                    placeholder=""
                    v-model="appointment.bookings[0].customFields[customField.id].value"
                    type="textarea"
                    :rows="3"
                    @input="validateFieldsForPayPal()"
                  >
                  </el-input>
                  <!-- /Text Area -->

                  <!-- Text Content -->
                  <div v-else-if="customField.type === 'content'" class="am-text-content">
                    <i class="el-icon-info"></i>
                    <p style='display: inline;' v-html="customField.label"></p>
                  </div>
                  <!-- /Text Content -->

                  <!-- Selectbox -->
                  <el-select
                    v-else-if="customField.type === 'select'"
                    v-model="appointment.bookings[0].customFields[customField.id].value"
                    :popper-class="($root.settings.customization.hasOwnProperty('forms') && $root.settings.customization.forms.hasOwnProperty(formType)) ? `am-dropdown-${formType}-${formName}-${bookableType}` : ''"
                    placeholder=""
                    clearable
                    @change="validateFieldsForPayPal()"
                  >
                    <el-option
                      v-for="(option, index) in getCustomFieldOptions(customField.options)"
                      :key="index"
                      :value="option"
                      :label="option"
                      :style="{'color': appointment.bookings[0].customFields[customField.id].value === option ? bookable.color : ''}"
                    >
                    </el-option>
                  </el-select>
                  <!-- /Selectbox -->

                  <!-- Checkbox -->
                  <el-checkbox-group
                    v-else-if="customField.type === 'checkbox'"
                    v-model="appointment.bookings[0].customFields[customField.id].value"
                    @change="selectedCustomFieldValue"
                  >
                    <el-checkbox
                      v-for="(option, index) in getCustomFieldOptions(customField.options)"
                      :key="index"
                      :label="option"
                    >
                    </el-checkbox>
                  </el-checkbox-group>
                  <!-- /Checkbox -->

                  <!-- Radio Buttons -->
                  <el-radio-group
                    v-else-if="customField.type === 'radio'"
                    v-model="appointment.bookings[0].customFields[customField.id].value"
                    @change="selectedCustomFieldValue"
                  >
                    <el-radio
                      v-for="(option, index) in getCustomFieldOptions(customField.options)"
                      :key="index"
                      :label="option"
                      ref="customFieldsRadioButtons"
                    >
                    </el-radio>
                  </el-radio-group>
                  <!-- /Radio Buttons -->

                  <!-- Upload Files -->
                  <div v-if="customField.type === 'file'">
                    <el-upload
                      :auto-upload="false"
                      action=""
                      drag
                      ref="customFieldsFiles"
                      :accept="$root.fileUploadExtensions.join(',')"
                      :on-change="onSelectFiles"
                      multiple
                    >
                      <i class="el-icon-upload"></i><span>{{$root.labels.file_upload}}</span>
                    </el-upload>
                  </div>
                  <!-- /Upload Files -->

                  <!-- Date picker -->
                  <div v-if="customField.type === 'datepicker'">
                    <v-date-picker
                      v-model="appointment.bookings[0].customFields[customField.id].value"
                      class='am-calendar-picker'
                      @input="validateFieldsForPayPal()"
                      mode='single'
                      popover-visibility="focus"
                      popover-direction="top"
                      :popover-align="screenWidth < 768 ? 'center' : 'left'"
                      :tint-color='"#1A84EE"'
                      :show-day-popover=false
                      :input-props='{class: "el-input__inner"}'
                      input-class="el-input__inner"
                      :is-expanded=false
                      :is-required=true
                      :disabled=false
                      :formats="vCalendarFormats"
                    ></v-date-picker>
                  </div>
                  <!-- /Date picker -->

                </el-form-item>
              </el-col>

              <!-- Recaptcha -->
              <el-col
                :sm="columnsLg"
                :class="$root.settings.general.googleRecaptcha.invisible ? '' : 'am-confirm-booking-recaptcha'"
                v-if="$root.settings.general.googleRecaptcha.enabled"
              >
                <el-form-item :error="errors.recaptcha">
                  <div id="recaptcha">
                    <vue-recaptcha
                      ref="recaptcha"
                      :size="$root.settings.general.googleRecaptcha.invisible ? 'invisible' : null"
                      @verify="onRecaptchaVerify"
                      @expired="onRecaptchaExpired"
                      :loadRecaptchaScript="true"
                      class="am-confirm-booking-recaptcha-block"
                      :sitekey="$root.settings.general.googleRecaptcha.siteKey">
                    </vue-recaptcha>
                  </div>
                </el-form-item>
              </el-col>
              <!-- /Recaptcha -->
            </el-row>
          </div>
          <!-- /Custom Fields -->

        </el-row>

        <!-- Payment Method & Stripe Card -->
        <el-row :gutter="24" class="am-confirm-booking-payment">

          <!-- Payment Method -->
          <el-col
          :span="formsData[formName][bookableType].itemsStatic.paymentMethodFormField.switchPaymentMethodView &&
           formsData[formName][bookableType].itemsStatic.paymentMethodFormField.switchPaymentMethodView === 'Selectbox' ? 12 : 24">
            <payment-method-form-field
              :total-price="getTotalPrice() > 0"
              :bookable-color="bookable.color"
              :payment-options="paymentOptions"
              :appointment="appointment"
              :classIdentifier="($root.settings.customization.hasOwnProperty('forms') && $root.settings.customization.forms.hasOwnProperty(formType)) ? `${formType}-${formName}-${bookableType}` : ''"
              :form-field="formsData[formName][bookableType].itemsStatic"
              @changeItem="validateFieldsForPayPal()"
            ></payment-method-form-field>
          </el-col>
          <!-- /Payment Method -->

          <!-- Stripe Card -->
          <el-col :sm="columnsLg">
            <stripe-card-form-field
              :appointment="appointment"
              :errors="errors"
              :total-price="getTotalPrice() > 0"
              :stripe-payment="stripePayment"
              :class-identifier="($root.settings.customization.hasOwnProperty('forms') && $root.settings.customization.forms.hasOwnProperty(formType)) ? `${formType}-${formName}-${bookableType}` : ''"
              :form-field="formsData[formName][bookableType].itemsStatic"
            ></stripe-card-form-field>
          </el-col>
          <!-- /Stripe Card -->

        </el-row>
        <!-- /Payment Method & Stripe Card -->

        <el-row class="am-confirm-booking-data" :gutter="24">

          <!-- Payment Type -->
          <el-col  :sm="24" :lg="24">
            <payment-type-form-field
              :show="bookable.depositData && bookable.depositData.depositFullPayment && getPaymentGateway() !== 'onSite'"
              :bookable-color="bookable.color"
              :classIdentifier="($root.settings.customization.hasOwnProperty('forms') && $root.settings.customization.forms.hasOwnProperty(formType)) ? `${formType}-${formName}-${bookableType}` : ''"
              :form-field="formsData[formName][bookableType].itemsStatic"
              @changeItem="paymentTypeChanged"
            >
            </payment-type-form-field>
          </el-col>
          <!-- Payment Type -->

        </el-row>

        <!-- Appointment Data -->
        <el-row>
          <el-col :sm="24">

            <!-- Payment Data -->
            <div class="am-confirmation-booking-cost" v-if="!packageData" :style="{paddingTop: '16px'}">

              <!-- Number Of Persons -->
              <el-row :gutter="24" v-if="bookable.maxCapacity > 1">
                <el-col :span="12">
                  <p>{{ priceLabels.total_number_of_persons.value || $root.labels.total_number_of_persons }}</p>
                </el-col>
                <el-col :span="12">
                  <p class="am-semi-strong am-align-right">
                    {{ bookable.ticketsData ? bookable.ticketsData.totalTickets : appointment.bookings[0].persons }}
                  </p>
                </el-col>
              </el-row>
              <!-- /Number Of Persons -->

              <!-- Appointment Price -->
              <el-row :gutter="24" v-for="(item, index) in instantPaymentBasePriceData" :key="index">
                <el-col :span="6">
                  <p :style="{'visibility': index === 0 ? 'visible' : 'hidden'}">
                    {{ priceLabels.base_price_colon.value || $root.labels.base_price_colon }}
                  </p>
                </el-col>
                <el-col :span="18">
                  <p class="am-semi-strong am-align-right">
                    {{ bookable.ticketsData ? getBookingTicketsBasePriceCalculationString(bookable.ticketsData) :
                      getBookingBasePriceCalculationString(item.count, item.price) }}
                  </p>
                </el-col>
              </el-row>
              <!-- /Appointment Price -->

              <!-- Extras Price -->
              <el-row
                class="am-confirmation-extras-cost" :gutter="24"
                v-if="appointment.bookings[0].extras.length > 0 && amountData.instant.total > 0"
              >
                <el-collapse
                  accordion v-if="selectedExtras.length > 0"
                  :class="($root.settings.customization.hasOwnProperty('forms') && $root.settings.customization.forms.hasOwnProperty(formType)) ? `am-block-${formType}-${formName}-${bookableType}`: ''"
                >
                  <el-collapse-item name="1">
                    <template slot="title">
                      <div class="am-extras-title">
                        {{ priceLabels.extras_costs_colon.value || $root.labels.extras_costs_colon }}
                      </div>
                      <div
                        class="am-extras-total-cost am-semi-strong"
                        :style="bookableType === 'event' && !useGlobalCustomization ? getBookableColor(false) : {}"
                      >
                        {{ getFormattedPrice(getExtrasPrice(instantPaymentBookingsCount), !$root.settings.payments.hideCurrencySymbolFrontend) }}
                      </div>
                    </template>
                    <div v-for="extra in selectedExtras">
                      <div class="am-extras-details">{{ extra.name }}</div>
                      <div class="am-extras-cost">{{ getSelectedExtraDetails(extra) }}</div>
                    </div>
                  </el-collapse-item>
                </el-collapse>
                <div v-else>
                  <el-col :span="12">
                    <p>{{ priceLabels.extras_costs_colon.value || $root.labels.extras_costs_colon }}</p>
                  </el-col>
                  <el-col :span="12">
                    <p class="am-semi-strong am-align-right">
                      {{ getFormattedPrice(getExtrasPrice(instantPaymentBookingsCount), !$root.settings.payments.hideCurrencySymbolFrontend) }}
                    </p>
                  </el-col>
                </div>
              </el-row>
              <!-- /Extras Price -->

              <!-- Coupon -->
              <el-row
                :gutter="0" class="am-add-coupon am-flex-row-middle-align"
                v-if="$root.settings.payments.coupons && amountData.instant.total > 0"
              >

                <!-- Coupon Label -->
                <el-col v-if="bookableType === 'appointment'" :sm="10" :xs="10">
                  <img :src="$root.getUrl+'public/img/coupon.svg'" class="svg-amelia" alt="add-coupon">
                  <span>{{ $root.labels.add_coupon }}</span>
                </el-col>
                <el-col v-else :sm="10" :xs="10">
                  <svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg">
                    <desc>Created with Sketch.</desc>
                    <defs></defs>
                    <g id="Icons" stroke="none" stroke-width="1" :style="{'fill':bookable.color}" fill-rule="evenodd">
                      <g id="Group" :fill="bookable.color">
                        <path
                          :style="{'fill':bookable.color}"
                          d="M7.152,12.7704615 C6.29353846,11.5809231 6.26092308,10.8652308 6.23446154,10.2904615 C6.22953846,10.1852308 6.22584615,10.0978462 6.21661538,10.0055385 C6.17415385,9.54953846 5.84676923,8.64738462 5.22769231,7.74461538 C4.37538462,6.49907692 3.79384615,4.63569231 4.95876923,3.48307692 C5.232,3.21230769 5.58523077,3.06953846 5.97907692,3.06953846 C6.952,3.06953846 7.98892308,4.02892308 8.61538462,4.85846154 L8.61538462,3.55261538 L8.61538462,1.23261538 C8.61538462,0.552615385 8.06276923,0 7.38461538,0 L5.53661538,0 C5.36861538,0 5.232,0.134769231 5.22892308,0.302769231 C5.22092308,0.804923077 4.80738462,1.21353846 4.30769231,1.21353846 C3.80738462,1.21353846 3.39446154,0.804923077 3.38646154,0.302769231 C3.38338462,0.134769231 3.24676923,0 3.07876923,0 L1.23076923,0 C0.552,0 0,0.552615385 0,1.23261538 L0,12.3058462 C0,12.9858462 0.552,13.5384615 1.23076923,13.5384615 L3.07692308,13.5384615 C3.24676923,13.5384615 3.38461538,13.4006154 3.38461538,13.2307692 C3.38461538,12.7206154 3.79876923,12.3058462 4.30769231,12.3058462 C4.81661538,12.3058462 5.23076923,12.7206154 5.23076923,13.2307692 C5.23076923,13.4006154 5.36861538,13.5384615 5.53846154,13.5384615 L7.38461538,13.5384615 C7.52430769,13.5384615 7.65907692,13.5101538 7.78707692,13.4646154 C7.56738462,13.2683077 7.352,13.048 7.152,12.7704615"
                          id="Fill-1450"
                        ></path>
                        <path
                          :style="{'fill':bookable.color}"
                          d="M15.9536615,11.8383385 C15.9487385,11.8303385 15.4373538,10.9934154 15.0724308,9.83095385 C14.9881231,9.55956923 14.8816615,9.17741538 14.7604308,8.73987692 C14.1825846,6.66295385 13.6588923,4.89741538 13.0865846,4.32141538 C12.9450462,4.17987692 12.5161231,3.74787692 9.58812308,3.26295385 C9.50135385,3.2488 9.40843077,3.27341538 9.33950769,3.33187692 C9.27058462,3.39033846 9.23058462,3.47587692 9.23058462,3.56633846 L9.23058462,6.03956923 C9.23058462,6.16449231 9.30627692,6.27710769 9.42258462,6.32449231 L10.3192,6.68941538 C10.3782769,6.90172308 10.4908923,7.28572308 10.6016615,7.56572308 C10.5487385,7.65310769 10.5050462,7.75341538 10.4570462,7.86233846 C10.3764308,8.04695385 10.2878154,8.25064615 10.1518154,8.40018462 C9.55489231,8.01741538 8.95181538,6.91895385 8.56781538,5.96264615 C8.26504615,5.20756923 6.93273846,3.69926154 5.97889231,3.69926154 C5.74996923,3.69926154 5.54750769,3.78110769 5.3912,3.93495385 C4.49643077,4.81926154 5.01766154,6.35649231 5.73581538,7.40449231 C6.3272,8.26849231 6.7672,9.29187692 6.82996923,9.95218462 C6.83981538,10.0611077 6.84473846,10.1644923 6.84966154,10.2666462 C6.87489231,10.8100308 6.90073846,11.3724923 7.65089231,12.4112615 C8.04289231,12.9534154 8.50135385,13.2721846 8.98627692,13.6100308 C9.67858462,14.0912615 10.3942769,14.5897231 11.1179692,15.8457231 C11.1727385,15.9411077 11.2742769,16.0001846 11.3844308,16.0001846 C15.0004308,16.0001846 15.9819692,12.1115692 15.9912,12.0721846 C16.0108923,11.9921846 15.9967385,11.9084923 15.9536615,11.8383385"
                          id="Fill-1452"
                        ></path>
                      </g>
                    </g>
                  </svg>
                  <span :style="{'color': bookable.color}">{{ $root.labels.add_coupon }}</span>
                </el-col>
                <!-- /Coupon Label -->

                <!-- Coupon Input -->
                <el-col :sm="14" :xs="14">
                  <el-form
                    :model="appointment.bookings[0].customer"
                    ref="coupon"
                    :rules="rules"
                    label-position="top"
                    @keyup.enter.native="onSubmitCoupon"
                    status-icon
                  >
                    <el-form-item
                      :style="bookableType === 'event' && !useGlobalCustomization ? getBookableColor(false) : {}"
                      :class="($root.settings.customization.hasOwnProperty('forms') && $root.settings.customization.forms.hasOwnProperty(formType)) ? `am-input-${formType}-${formName}-${bookableType}`: ''"
                      :error="errors.coupon"
                      prop="couponCode"
                    >
                      <el-input
                        v-model="coupon.code"
                        @input="validateFieldsForPayPal()"
                        type="text"
                        size="small"
                        class="am-add-coupon-field"
                        :style="bookableType === 'event' && !useGlobalCustomization ? getBookableColor(false) : {}"
                        native-type="submit"
                        @keydown.enter.native="onSubmitCoupon"
                      >
                        <!-- Coupon Button -->
                        <el-button
                          class="am-add-coupon-button"
                          slot="append"
                          size="mini"
                          icon="el-icon-check"
                          @click="checkCoupon"
                          :disabled="coupon.code ? coupon.code.trim() === '' : true"
                          :style="bookableType === 'event' && !useGlobalCustomization ? getBookableColor(true) : {}"
                          native-type="submit"
                        >
                        </el-button>
                        <!-- /Coupon Button -->

                      </el-input>
                    </el-form-item>
                  </el-form>
                </el-col>
                <!-- /Coupon Input -->

              </el-row>
              <!-- /Coupon -->

              <!-- Coupons Used Message -->
              <el-row class="am-coupon-limit" v-show="$root.settings.payments.coupons && recurringData.length && couponLimit < recurringData.length + 1 && (coupon.discount || coupon.deduction)">
                <el-col :sm="2" :xs="4">
                  <div style="display: inline-block;">
                    <img :src="$root.getUrl+'public/img/coupon-limit.svg'" class="svg-amelia" alt="coupon-limit">
                  </div>
                </el-col>

                <el-col :sm="22" :xs="20">
                  <div class="am-coupon-limit-text">
                    <strong>{{ $root.labels.coupons_used }}</strong>
                    <p>{{ $root.labels.coupons_used_description }} {{ couponLimit }}</p>
                  </div>
                </el-col>
              </el-row>
              <!-- /Coupons Used Message -->

              <div
                v-if="amountData.instant.total > 0"
                class="am-confirmation-total"
              >
              <!-- :style="{'color': bookable.color, 'background-color': bookableType === 'event' && !useGlobalCustomization ? '#E8E8E8' : ''}" -->
                <!-- SubTotal Price -->
                <el-row :gutter="24" v-if="amountData.instant.discount > 0 || amountData.instant.tax > 0">
                  <el-col :span="12">
                    <p>
                      {{ priceLabels.subtotal_colon.value || $root.labels.subtotal_colon }}
                    </p>
                  </el-col>
                  <el-col :span="12">
                    <p class="am-semi-strong am-align-right" :style="{'color': bookable.color}">
                      {{ getFormattedPrice(amountData.instant.total, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                    </p>
                  </el-col>
                </el-row>
                <!-- /SubTotal Price -->

                <!-- Discount Amount -->
                <el-row :gutter="24" v-if="amountData.instant.discount > 0">
                  <el-col :span="12">
                    <p>{{ priceLabels.discount_amount_colon.value || $root.labels.discount_amount_colon }}</p>
                  </el-col>
                  <el-col :span="12">
                    <p class="am-semi-strong am-align-right" :style="{'color': bookable.color}">
                      {{ getFormattedPrice(amountData.instant.discount, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                    </p>
                  </el-col>
                </el-row>
                <!-- /Discount Amount -->

                <!-- Tax Amount -->
                <el-row :gutter="24" v-if="amountData.instant.tax > 0">
                  <el-col :span="12">
                    <p>
                      {{ getTaxLabel() }}
                    </p>
                  </el-col>
                  <el-col :span="12">
                    <p class="am-semi-strong am-align-right" :style="{'color': bookable.color}">
                      {{ getFormattedPrice(amountData.instant.tax, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                    </p>
                  </el-col>
                </el-row>
                <!-- /Tax Amount -->

                <!-- Total Price -->
                <el-row :gutter="24" :class="{'am-confirmation-total-bordered': !onlyTotal}">
                  <el-col :span="12">
                    <p>
                      {{ priceLabels.total_cost_colon.value || $root.labels.total_cost_colon }}
                    </p>
                  </el-col>
                  <el-col :span="12">
                    <p class="am-semi-strong am-align-right" :style="{'color': bookable.color}">
                      {{ getFormattedPrice(getTotalPrice(), !$root.settings.payments.hideCurrencySymbolFrontend) }}
                    </p>
                  </el-col>
                </el-row>
                <!-- /Total Price -->

                <!-- Deposit -->
                <el-row
                  class="am-confirmation-deposit" :gutter="24" v-if="withDeposit"
                  :style="{'color': bookable.color}"
                >
                  <el-col :span="12">
                    <p>{{ priceLabels.deposit.value || $root.labels.deposit }} <label class="am-confirmation-deposit-info">{{ priceLabels.pay_now.value || $root.labels.pay_now }}</label></p>
                  </el-col>
                  <el-col :span="12">
                    <p class="am-semi-strong am-align-right" :style="{'color': bookable.color}">
                      {{ getFormattedPrice(amountData.instant.deposit, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                    </p>
                  </el-col>
                </el-row>

                <el-row
                  class="am-confirmation-deposit-price"
                  :gutter="24" v-if="withDeposit"
                  :style="{'color': bookable.color}"
                >
                  <el-col :span="12">
                    <p>{{ priceLabels.pay_later.value || $root.labels.pay_later }}</p>
                  </el-col>
                  <el-col :span="12">
                    <p class="am-semi-strong am-align-right" :style="{'color': bookable.color}">
                      {{ getFormattedPrice(getTotalPrice() - amountData.instant.deposit, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                    </p>
                  </el-col>
                </el-row>
                <!-- /Deposit -->

              </div>

              <!-- Recurring Price -->
              <el-row
                class="am-confirmation-extras-cost" :gutter="24"
                v-if="recurringData.length && amountData.postponed.total > 0"
              >
                <el-collapse
                  accordion
                  :class="($root.settings.customization.hasOwnProperty('forms') && $root.settings.customization.forms.hasOwnProperty(formType)) ? `am-block-${formType}-${formName}-${bookableType}`: ''"
                >
                  <el-collapse-item name="1">
                    <template slot="title">
                      <div class="am-extras-title">{{ priceLabels.recurring_costs_colon.value || $root.labels.recurring_costs_colon }}</div>
                      <div class="am-extras-total-cost am-semi-strong">
                        {{ getFormattedPrice(amountData.postponed.total - amountData.postponed.discount + amountData.postponed.tax, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                      </div>
                    </template>
                    <div v-for="(item, key) in amountData.postponed.totals" :key="key">
                      <div class="am-extras-details" :style="{'visibility': key === 0 ? 'visible' : 'hidden'}">
                        {{ priceLabels.base_price_colon.value || $root.labels.base_price_colon }}
                      </div>
                      <div class="am-extras-cost">
                        {{ item.count + ' ' + (item.count ? $root.labels.appointments.toLowerCase() : $root.labels.appointment.toLowerCase()) + ' x ' + getFormattedPrice(item.total, !$root.settings.payments.hideCurrencySymbolFrontend) + ' = ' + getFormattedPrice(item.count * item.total, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                      </div>
                    </div>
                    <div v-if="amountData.postponed.discount">
                      <div class="am-extras-details"> {{ priceLabels.discount_amount_colon.value || $root.labels.discount_amount_colon }}</div>
                      <div class="am-extras-cost">
                        {{ getFormattedPrice(amountData.postponed.discount, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                      </div>
                    </div>
                    <div v-if="amountData.postponed.tax">
                      <div class="am-extras-details">
                        {{ getTaxLabel() }}
                      </div>
                      <div class="am-extras-cost">{{ getFormattedPrice(amountData.postponed.tax, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                      </div>
                    </div>
                  </el-collapse-item>
                </el-collapse>
              </el-row>
              <!-- /Recurring Price -->

            </div>
            <div
              class="am-confirmation-total am-confirmation-booking-cost"
              v-else-if="bookable.price > 0"
            >
              <!-- SubTotal Price -->
              <el-row :gutter="24" v-if="amountData.instant.tax > 0">
                <el-col :span="12">
                  <p>
                    {{ priceLabels.subtotal_colon.value || $root.labels.subtotal_colon }}
                  </p>
                </el-col>
                <el-col :span="12">
                  <p class="am-semi-strong am-align-right" :style="{'color': bookable.color}">
                    {{ getFormattedPrice(amountData.instant.total, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                  </p>
                </el-col>
              </el-row>
              <!-- /SubTotal Price -->

              <!-- Tax Amount -->
              <el-row :gutter="24" v-if="amountData.instant.tax > 0">
                <el-col :span="12">
                  <p>
                    {{ getTaxLabel() }}
                  </p>
                </el-col>
                <el-col :span="12">
                  <p class="am-semi-strong am-align-right">
                    {{ getFormattedPrice(amountData.instant.tax, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                  </p>
                </el-col>
              </el-row>
              <!-- /Tax Amount -->

              <!-- Total Price -->
              <el-row :gutter="24" v-if="bookable.price > 0" :class="{'am-confirmation-total-bordered': !onlyTotal}">
                <el-col :span="12">
                  <p>
                    {{ priceLabels.total_cost_colon.value || $root.labels.total_cost_colon }}
                  </p>
                </el-col>
                <el-col :span="12">
                  <p class="am-semi-strong am-align-right" :style="{'color': bookable.color}">
                    {{ getFormattedPrice(amountData.instant.total + amountData.instant.tax, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                  </p>
                </el-col>
              </el-row>
              <!-- /Total Price -->

              <!-- Deposit -->
              <el-row class="am-confirmation-deposit" :gutter="24" v-if="withDeposit">
                <el-col :span="12">
                  <p>{{ priceLabels.deposit.value || $root.labels.deposit }} <label class="am-confirmation-deposit-info">{{ priceLabels.pay_now.value || $root.labels.pay_now }}</label></p>
                </el-col>
                <el-col :span="12">
                  <p class="am-semi-strong am-align-right" :style="{'color': bookable.color}">
                    {{ getFormattedPrice(amountData.instant.deposit, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                  </p>
                </el-col>
              </el-row>

              <el-row
                class="am-confirmation-deposit-price"
                :gutter="24"
                v-if="withDeposit">
                <el-col :span="12">
                  <p>{{ priceLabels.pay_later.value || $root.labels.pay_later }}</p>
                </el-col>
                <el-col :span="12">
                  <p class="am-semi-strong am-align-right" :style="{'color': bookable.color}">
                    {{ getFormattedPrice(getTotalPrice() - amountData.instant.deposit, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                  </p>
                </el-col>
              </el-row>
              <!-- /Deposit -->
            </div>
            <!-- /Payment Data -->

          </el-col>
        </el-row>
        <!-- /Appointment Data -->

      </el-form>
      <!-- /Confirm Dialog Body -->

      <!-- Confirm Dialog Footer -->
      <div class="dialog-footer payment-dialog-footer" slot="footer">
        <div
          v-if="hasCancel"
          class="el-button el-button--default"
          :style="bookableType === 'event' ? bookableCancelStyle : ''"
          @mouseleave="setBookableCancelStyle(false)"
          @mouseover="setBookableCancelStyle(true)"
          @click="cancelBooking()"
        >
          <span :style="bookableType === 'event' ? bookableCancelSpanStyle : ''">{{ $root.labels.cancel }}</span>
        </div>

        <div
          v-show="$root.settings.payments.payPal.enabled && appointment.payment.gateway === 'payPal' && getTotalPrice() !== 0"
          class="paypal-button el-button el-button--primary"
          :style="bookableType === 'event' ? bookableConfirmStyle : ''"
          @mouseleave="setBookableConfirmStyle(false)"
          @mouseover="setBookableConfirmStyle(true)"
        >
          <div id="am-paypal-button-container"></div>
          <span>{{ $root.labels.confirm }}</span>
        </div>

        <div
          v-show="showConfirmBookingButton"
          class="el-button el-button--primary"
          :style="bookableType === 'event' ? bookableConfirmStyle : ''"
          @mouseleave="setBookableConfirmStyle(false)"
          @mouseover="setBookableConfirmStyle(true)"
          @click="confirmBooking()"
        >
          <span>{{ $root.labels.confirm }}</span>
        </div>
      </div>
      <!-- /Confirm Dialog Footer -->

    </div>
    <!-- /Confirm Booking Form -->

    <!-- Spinner & Waiting For Payment -->
    <div id="am-spinner" class="am-booking-fetched" v-show="!fetched && !paid">
      <h4
        v-if="appointment.payment.gateway === 'payPal'"
        :style="{color: (bookableType === 'event' && formType === 'eventListForm') ? formsData.globalSettings.formTextColor : formsData[$options.name][bookableType].globalSettings.formTextColor}"
      >
        {{ $root.labels.waiting_for_payment }}
      </h4>
      <h4
        v-else
        :style="{color: (bookableType === 'event' && formType === 'eventListForm') ? formsData.globalSettings.formTextColor : formsData[$options.name][bookableType].globalSettings.formTextColor}"
      >
        {{ $root.labels.please_wait }}
      </h4>
      <div class="am-svg-wrapper">

        <!-- Oval Spinner -->
        <span v-if="bookableType === 'event' && !useGlobalCustomization">
          <svg width="160" height="160" class="am-spin" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg" stroke="#7F8FA4">
            <g fill="none" fill-rule="evenodd">
              <g transform="translate(1 1)" stroke-width="2">
                <path d="M36 18c0-9.94-8.06-18-18-18" :style="{'stroke':bookable.color}" :stroke="bookable.color">
                  <animateTransform
                    attributeName="transform"
                    type="rotate"
                    from="0 18 18"
                    to="360 18 18"
                    dur="1s"
                    repeatCount="indefinite"
                  />
                </path>
              </g>
            </g>
          </svg>

          <!-- HourGlass -->
          <svg width="12px" height="16px" class="am-hourglass" viewBox="0 0 12 16" version="1.1" xmlns="http://www.w3.org/2000/svg">
            <g id="Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-2.000000, 0.000000)">
              <g id="sat" transform="translate(2.000000, 0.000000)" :style="{'fill': bookable.color}">
                <path
                  :style="{'fill': bookable.color, 'stroke': 'none'}"
                  d="M8.37968,4.8 L3.32848,4.8 C3.22074667,4.8 3.12368,4.86506667 3.08208,4.9648 C3.04101333,5.06453333 3.06394667,5.1792 3.14021333,5.25546667 L5.67834667,7.79093333 C5.72794667,7.84106667 5.79621333,7.86933333 5.86661333,7.86933333 C5.95941333,7.8672 6.00634667,7.84106667 6.05594667,7.7904 L8.56901333,5.2544 C8.64474667,5.1776 8.66714667,5.06346667 8.62554667,4.96426667 C8.58448,4.86453333 8.48741333,4.8 8.37968,4.8"
                  id="Fill-694"
                ></path>
                <path
                  :style="{'fill': bookable.color, 'stroke': 'none'}"
                  d="M6.82293333,7.62293333 C6.6144,7.83146667 6.6144,8.16853333 6.82293333,8.37706667 L9.04,10.5941333 C9.74506667,11.2992 10.1333333,12.2368 10.1333333,13.2341333 L10.1333333,14.4 L9.2,14.4 L6.08,10.24 C5.9792,10.1056 5.75413333,10.1056 5.65333333,10.24 L2.53333333,14.4 L1.6,14.4 L1.6,13.2341333 C1.6,12.2368 1.98826667,11.2992 2.69333333,10.5941333 L4.9104,8.37706667 C5.11893333,8.16853333 5.11893333,7.83146667 4.9104,7.62293333 L2.69333333,5.40586667 C1.98826667,4.7008 1.6,3.7632 1.6,2.7664 L1.6,1.6 L10.1333333,1.6 L10.1333333,2.7664 C10.1333333,3.7632 9.74506667,4.7008 9.04,5.40586667 L6.82293333,7.62293333 Z M11.2,2.7664 L11.2,1.45173333 C11.5173333,1.26666667 11.7333333,0.9264 11.7333333,0.533333333 L11.7333333,0.266666667 C11.7333333,0.119466667 11.6138667,0 11.4666667,0 L0.266666667,0 C0.119466667,0 0,0.119466667 0,0.266666667 L0,0.533333333 C0,0.9264 0.216,1.26666667 0.533333333,1.45173333 L0.533333333,2.7664 C0.533333333,4.048 1.03253333,5.25386667 1.9392,6.16 L3.7792,8 L1.9392,9.84 C1.03253333,10.7461333 0.533333333,11.952 0.533333333,13.2341333 L0.533333333,14.5482667 C0.216,14.7333333 0,15.0736 0,15.4666667 L0,15.7333333 C0,15.8805333 0.119466667,16 0.266666667,16 L11.4666667,16 C11.6138667,16 11.7333333,15.8805333 11.7333333,15.7333333 L11.7333333,15.4666667 C11.7333333,15.0736 11.5173333,14.7333333 11.2,14.5482667 L11.2,13.2341333 C11.2,11.952 10.7008,10.7461333 9.79413333,9.84 L7.95413333,8 L9.79413333,6.16 C10.7008,5.25386667 11.2,4.048 11.2,2.7664 L11.2,2.7664 Z"
                    id="Fill-696"
                ></path>
              </g>
            </g>
          </svg>
        </span>

        <span v-else>
          <img class="svg-amelia am-spin" :src="$root.getUrl+'public/img/oval-spinner.svg'"/>
          <img class="svg-amelia am-hourglass" :src="$root.getUrl+'public/img/hourglass.svg'"/>
        </span>
      </div>
    </div>
    <!-- /Spinner & Waiting For Payment -->

  </div>
</template>

<script>
import moment from 'moment'
import taxesMixin from '../../../js/common/mixins/taxesMixin'
import marketingMixin from '../../../js/frontend/mixins/marketingMixin'
import imageMixin from '../../../js/common/mixins/imageMixin'
import dateMixin from '../../../js/common/mixins/dateMixin'
import priceMixin from '../../../js/common/mixins/priceMixin'
import helperMixin from '../../../js/backend/mixins/helperMixin'
import windowMixin from '../../../js/backend/mixins/windowMixin'
import customFieldMixin from '../../../js/common/mixins/customFieldMixin'
import VueRecaptcha from 'vue-recaptcha'
import confirmHeadingDataFormField from './formFields/ConfirmHeadingDataFormField'
import recurringStringFormField from './formFields/RecurringStringFormField'
import firstNameFormField from './formFields/FirstNameFormField'
import lastNameFormField from './formFields/LastNameFormField'
import emailFormField from './formFields/EmailFormField'
import phoneFormField from './formFields/PhoneFormField'
import paymentMethodFormField from './formFields/PaymentMethodFormField'
import paymentTypeFormField from './formFields/PaymentTypeFormField'
import stripeCardFormField from './formFields/StripeCardFormField'
import VueGoogleAutocomplete from 'vue-google-autocomplete'
import formsCustomizationMixin from '../../../js/common/mixins/formsCustomizationMixin'

export default {
  name: 'confirmBookingForm',

  mixins: [
    taxesMixin,
    imageMixin,
    dateMixin,
    priceMixin,
    helperMixin,
    customFieldMixin,
    windowMixin,
    formsCustomizationMixin
  ],

  props: {
    trigger: null,
    passedCategoryId: null,
    couponCode: '',
    paymentGateway: '',
    queryParams: {},
    status: null,
    phonePopulated: null,
    containerId: null,
    recurringString: '',
    useGlobalCustomization: false,
    bookableType: null,
    taxes: {
      default: () => [],
      type: Array
    },
    bookable: {
      default: () => {},
      type: Object
    },
    recurringData: {
      default: () => []
    },
    packageData: null,
    hasCancel: true,
    hasHeader: true,
    appointment: {
      default: () => {},
      type: Object
    },
    marketing: null,
    provider: {
      default: () => {},
      type: Object
    },
    location: {
      default: () => {},
      type: Object
    },
    service: {
      type: Object,
      default: () => {}
    },
    dialogClass: {
      default: '',
      type: String
    },
    customFields: {
      default: () => []
    },
    formType: {
      type: String
    },
    formsData: {
      type: Object,
      default: function () {
        return {}
      }
    }
  },

  data () {
    let validateCoupon = (rule, bookings, callback) => {
      let field = document.getElementsByClassName('am-add-coupon-field')[0].getElementsByClassName('el-input__suffix')[0]

      if (this.coupon.code) {
        this.coupon.code = this.coupon.code.trim()
        this.$http.post(`${this.$root.getAjaxUrl}/coupons/validate`, {
          'code': this.coupon.code,
          'id': this.bookable.id,
          'type': this.bookableType,
          'user': this.appointment.bookings[0]['customer']
        }).then(response => {
          // Customization hook
          if ('afterSuccessCouponValidated' in window) {
            window.afterSuccessCouponValidated(this.appointment, this.bookable, this.provider, this.location)
          }
          this.coupon = response.data.data.coupon
          this.couponLimit = response.data.data.limit
          if (typeof field !== 'undefined') {
            field.style.visibility = 'visible'
          }
          callback()
        }).catch(e => {
          this.coupon.discount = 0
          this.coupon.deduction = 0

          if (e.response.data.data.couponUnknown === true) {
            callback(new Error(this.$root.labels.coupon_unknown))
          } else if (e.response.data.data.couponInvalid === true) {
            callback(new Error(this.$root.labels.coupon_invalid))
          } else if (e.response.data.data.couponExpired === true) {
            callback(new Error(this.$root.labels.coupon_expired))
          } else {
            callback()
          }

          if (typeof field !== 'undefined') {
            field.style.visibility = 'hidden'
          }
        })
      } else {
        if (typeof field !== 'undefined') {
          field.style.visibility = 'hidden'
        }
        callback()
      }
    }

    let validatePhone = (rule, input, callback) => {
      if (input && input !== '' && !input.startsWith('+')) {
        callback(new Error(this.$root.labels.enter_valid_phone_warning))
      } else {
        callback()
      }
    }

    return {
      paymentType: 'depositOnly',
      validRecaptcha: false,
      recaptchaResponse: false,
      customFieldsFiles: [],
      stripePayment: {
        stripe: null,
        cardElement: null
      },
      hoverConfirm: false,
      hoverCancel: false,
      columnsLg: 12,
      couponLimit: 0,
      coupon: {
        code: '',
        discount: 0,
        deduction: 0
      },
      clearValidate: true,
      errors: {
        email: '',
        phone: '',
        coupon: '',
        stripe: '',
        recaptcha: '',
        files: {}
      },
      fetched: true,
      paid: false,
      headerErrorMessage: '',
      headerErrorShow: false,
      payPalActions: null,
      rules: {
        'customer.firstName': [
          {required: true, message: this.$root.labels.enter_first_name_warning, trigger: 'submit'}
        ],
        'customer.lastName': [
          {
            required: this.formsData[this.$options.name][this.bookableType].itemsDraggable.lastNameFormField.required,
            message: this.$root.labels.enter_last_name_warning,
            trigger: 'submit'
          }
        ],
        'customer.email': [
          {
            required: this.formsData[this.$options.name][this.bookableType].itemsDraggable.emailFormField.required,
            message: this.$root.labels.enter_email_warning,
            trigger: 'submit'
          },
          {type: 'email', message: this.$root.labels.enter_valid_email_warning, trigger: 'submit'}
        ],
        'customer.phone': [
          {
            required: this.formsData[this.$options.name][this.bookableType].itemsDraggable.phoneFormField.required,
            message: this.$root.labels.enter_phone_warning,
            trigger: 'submit'
          },
          {validator: validatePhone, trigger: 'submit'}
        ],
        couponCode: [
          {validator: validateCoupon, trigger: 'submit'}
        ]
      },
      formValidOptions: {},
      formName: this.$options.name,
      serviceHeadingVisibility: this.formsData[this.$options.name][this.bookableType].itemsStatic.confirmServiceHeadingFormField ? this.formsData[this.$options.name][this.bookableType].itemsStatic.confirmServiceHeadingFormField.visibility : true,
      recurringStringVisibility: this.formsData[this.$options.name][this.bookableType].itemsStatic.recurringStringFormField ? this.formsData[this.$options.name][this.bookableType].itemsStatic.recurringStringFormField.visibility : true
    }
  },

  created () {
    this.inlineSVG()
    window.addEventListener('resize', this.handleResize)
  },

  mounted () {
    if (this.appointment.bookings[0].customFields) {
      for (const [key, cf] of Object.entries(this.appointment.bookings[0].customFields)) {
        if (cf.type === 'address') {
          if (this.$refs['amelia-cf-address-' + key] !== undefined && this.$refs['amelia-cf-address-' + key].length > 0) {
            this.$refs['amelia-cf-address-' + key][0].update(cf.value)
          }
        }
      }
    }

    this.paymentType = this.bookable.depositData !== null ? 'depositOnly' : 'fullAmount'

    if (marketingMixin.hasAmeliaTracking(this)) {
      marketingMixin.trackAmeliaData(this, this.$root.marketing, this.bookableType, 'InitiateCheckout')
    }

    if (this.status === 'failed') {
      this.headerErrorMessage = this.$root.labels.payment_error

      this.headerErrorShow = true
    }

    this.coupon.code = this.couponCode

    if (this.bookableType === 'event' && !this.useGlobalCustomization) {
      // this.changeElementsColor('.el-upload-dragger', false, true, false)
      // this.changeElementsColor('.el-upload-dragger span', true, true, false)
      // this.changeElementsColor('.el-icon-upload', true, true, false)
      // this.changeElementsColor('.el-input-group__append', false, false, true)
      // this.changeElementsColor('.am-add-coupon-button', false, true, false)
      // this.changeSelectedColor('.el-radio', 'is-checked', '.el-radio__label', true, false)
      // this.changeSelectedColor('.el-radio', 'is-checked', '.el-radio__inner', false, true)
      // this.changeSelectedColor('.el-checkbox', 'is-checked', '.el-checkbox__label', true, false)
      // this.changeSelectedColor('.el-checkbox', 'is-checked', '.el-checkbox__inner', false, true)
    }

    this.setBookableConfirmStyle(false)
    this.setBookableCancelStyle(false)

    this.inlineSVG()

    // Get Default Payment Option
    let paymentOption = this.paymentOptions.find(option => option.value === this.$root.settings.payments.defaultPaymentMethod)

    if (!this.appointment.payment.gateway) {
      this.appointment.payment.gateway = paymentOption
        ? paymentOption.value : this.paymentOptions.length
          ? this.paymentOptions[0].value : this.$root.settings.payments.defaultPaymentMethod
    }

    if (this.bookableType === 'appointment') {
      this.saveStats()
    }

    this.addCustomFieldsValidationRules()
    if (this.$root.settings.payments.payPal.enabled) {
      this.payPalInit()
    }

    // myCred fix for total amount for recurring
    this.appointment.payment.amount = this.getTotalPrice()

    // Customization hook
    if ('beforeConfirmBookingLoaded' in window) {
      window.beforeConfirmBookingLoaded(this.appointment, this.bookable, this.provider, this.location)
    }

    let $this = this

    if (this.bookableType === 'event' && !('ameliaBooking' in window && 'disableScrollView' in window.ameliaBooking && window.ameliaBooking.disableScrollView === true)) {
      setTimeout(() => {
        $this.scrollView('am-confirm-booking', 'start')
      }, 1200)
    }
  },

  updated () {
    if (this.clearValidate === true) {
      this.validateFieldsForPayPal()
      this.clearValidate = false
    }
    this.handleResize()
  },

  methods: {
    setAddressCF (input, cfId) {
      this.appointment.bookings[0].customFields[cfId].value = input
      this.validateFieldsForPayPal()
    },

    googleMapsLoaded () {
      return window.google && this.$root.settings.general.gMapApiKey
    },

    paymentTypeChanged (paymentType) {
      this.paymentType = paymentType.value
    },

    getComponentProps () {
      return {
        phonePopulated: this.phonePopulated ? 1 : 0,
        containerId: this.containerId,
        trigger: 'booking' in this.$root.shortcodeData && 'trigger' in this.$root.shortcodeData.booking ? this.$root.shortcodeData.booking.trigger : '',
        recurringString: this.recurringString,
        useGlobalCustomization: this.useGlobalCustomization ? 1 : 0,
        bookableType: this.bookableType,
        bookable: Object.assign(
          this.bookable,
          {aggregatedPrice: this.bookable.aggregatedPrice ? 1 : 0}
        ),
        recurringData: this.recurringData,
        packageData: this.packageData,
        hasCancel: this.hasCancel ? 1 : 0,
        hasHeader: this.hasHeader ? 1 : 0,
        appointment: Object.assign(
          this.appointment,
          {group: this.appointment.group ? 1 : 0}
        ),
        dialogClass: this.dialogClass,
        couponCode: this.coupon.code,
        passedCategoryId: this.passedCategoryId,
        queryParams: this.queryParams
      }
    },

    onSubmitCoupon (ev) {
      ev.preventDefault()
      return false
    },

    getPackagePrice (pack) {
      return pack.calculatedPrice ? pack.price : pack.price - pack.price / 100 * pack.discount
    },

    isBookableCustomFieldVisible (customField) {
      switch (this.bookableType) {
        case ('appointment'):
          return this.isCustomFieldVisible(customField, 'appointment', this.bookable.id)
        case ('package'):
          let customFieldVisible = false

          for (let i = 0; i < this.packageData.data.length; i++) {
            if (this.isCustomFieldVisible(customField, 'appointment', this.packageData.data[i].serviceId)) {
              customFieldVisible = true

              break
            }
          }

          return customFieldVisible
        case ('event'):
          return this.isCustomFieldVisible(customField, 'event', this.bookable.id)
      }
    },

    getCustomFieldClass (customField) {
      let classData = {
        'is-required': customField.type === 'file' && customField.required,
        'text-content-custom-field': customField.type === 'content'
      }

      classData['am-cf-' + customField.id] = true

      return classData
    },

    onRecaptchaExpired () {
      this.validRecaptcha = false
      this.errors.recaptcha = this.$root.labels.recaptcha_error
      this.validateFieldsForPayPal()
    },

    onRecaptchaVerify (response) {
      this.validRecaptcha = true
      this.errors.recaptcha = ''
      this.recaptchaResponse = response

      if (this.$root.settings.general.googleRecaptcha.invisible) {
        switch (this.appointment.payment.gateway) {
          case ('onSite'):
            this.saveBooking(this.getRequestData(false))

            break
          case ('stripe'):
            this.stripeBooking()

            break
        }

        return false
      }

      this.validateFieldsForPayPal()
    },

    selectedCustomFieldValue () {
      if (this.bookableType === 'event' && !this.useGlobalCustomization) {
        // this.changeSelectedColor('.el-radio', 'is-checked', '.el-radio__label', true, false)
        // this.changeSelectedColor('.el-radio', 'is-checked', '.el-radio__inner', false, true)
        //
        // this.changeSelectedColor('.el-checkbox', 'is-checked', '.el-checkbox__label', true, false)
        // this.changeSelectedColor('.el-checkbox', 'is-checked', '.el-checkbox__inner', false, true)
      }

      this.validateFieldsForPayPal()
    },

    getBookableColor (colorBackground) {
      return colorBackground ? {
        'color': '#ffffff',
        'background-color': this.bookable.color,
        'border-color': '#ffffff'
      } : {
        'color': this.bookable.color,
        'background-color': '',
        'border-color': ''
      }
    },

    changeElementsColor (selector, isColor, isBorderColor, isBackgroundColor) {
      // let elements = document.querySelectorAll(selector)
      //
      // for (let i = 0; i < elements.length; i++) {
      //   if (isColor) {
      //     elements[i].style.color = this.bookable.color
      //   }
      //
      //   if (isBorderColor) {
      //     elements[i].style.borderColor = this.bookable.color
      //   }
      //
      //   if (isBackgroundColor) {
      //     elements[i].style.backgroundColor = this.bookable.color
      //   }
      // }
    },

    changeSelectedColor (selector, filterClass, childSelector, isColor, isBackgroundColor) {
      // let elements = document.querySelectorAll(selector)
      //
      // for (let i = 0; i < elements.length; i++) {
      //   let color = elements[i].classList.contains(filterClass) ? this.bookable.color : 'inherit'
      //
      //   let elementChildren = elements[i].querySelectorAll(childSelector)
      //
      //   if (elementChildren.length) {
      //     if (isColor) {
      //       elementChildren[0].style.color = color
      //     }
      //
      //     if (isBackgroundColor) {
      //       elementChildren[0].style.backgroundColor = color
      //     }
      //   }
      // }
    },

    setBookableConfirmStyle (isHover) {
      if (!this.useGlobalCustomization && this.bookableType === 'event') {
        this.hoverConfirm = isHover
      }
    },

    setBookableCancelStyle (isHover) {
      if (!this.useGlobalCustomization && this.bookableType === 'event') {
        this.hoverCancel = isHover
      }
    },

    saveStats () {
      this.$http.post(`${this.$root.getAjaxUrl}/stats`, {
        'locationId': this.location !== null ? this.location.id : null,
        'providerId': this.provider.id,
        'serviceId': this.bookable.id
      })
    },

    handleServerResponse (response) {
      let $this = this

      if (response.requiresAction) {
        $this.stripePayment.stripe.handleCardAction(
          response.paymentIntentClientSecret
        ).then(function (result) {
          if (result.error) {
            $this.headerErrorShow = true
            $this.headerErrorMessage = $this.$root.labels.payment_error
            $this.fetched = true
          } else {
            let requestData = $this.getRequestData(false, {
              'paymentIntentId': result.paymentIntent.id
            })

            $this.saveBooking(requestData)
          }
        })
      } else {
        if (response) {
          $this.$emit('confirmedBooking', Object.assign(response, {
            color: $this.bookable.color,
            type: $this.bookableType,
            packageId: this.bookableType === 'package' ? this.bookable.id : null
          }, this.$root.settings.general.runInstantPostBookingActions, null))

          this.paid = true
        } else {
          $this.fetched = true
        }
      }
    },

    cancelBooking () {
      this.$emit('cancelBooking')
    },

    onSelectFiles () {
      this.validateFieldsForPayPal()
    },

    validateUploadedFiles () {
      let isValid = true

      let bookings = this.appointment.bookings

      let customFieldFilesIndexes = {}

      let filesIndex = 0

      for (let i = 0; i < this.customFields.length; i++) {
        if (this.customFields[i].type === 'file' && this.isBookableCustomFieldVisible(this.customFields[i])) {
          customFieldFilesIndexes[this.customFields[i].id] = filesIndex
          filesIndex++
        }
      }

      for (let key in bookings[0].customFields) {
        if (!bookings[0].customFields.hasOwnProperty(key)) {
          continue
        }

        let customField = this.customFields.find(field => parseInt(field.id) === parseInt(key))

        if (this.isBookableCustomFieldVisible(customField) && customField.type === 'file' && customField.required) {
          let uploadedFilesIndex = key in customFieldFilesIndexes && customFieldFilesIndexes[key] in this.$refs.customFieldsFiles ? customFieldFilesIndexes[key] : null

          if (uploadedFilesIndex !== null && this.$refs.customFieldsFiles[uploadedFilesIndex].uploadFiles.length === 0) {
            this.errors.files['files' + customField.id] = this.$root.labels.file_upload_error
            isValid = false
          }
        }
      }

      return isValid
    },

    isDefaultOnSitePayment () {
      return this.getTotalPrice() === 0 &&
        (
          this.appointment.payment.gateway === 'payPal' ||
          this.appointment.payment.gateway === 'stripe' ||
          this.appointment.payment.gateway === 'mollie' ||
          this.appointment.payment.gateway === 'square' ||
          this.appointment.payment.gateway === 'razorpay' ||
          (this.appointment.payment.gateway === 'wc' && 'ameliaBooking' in window && 'wc' in window.ameliaBooking && 'bookIfPriceIsZero' in window.ameliaBooking.wc && window.ameliaBooking.wc.bookIfPriceIsZero === true) ||
          (this.appointment.payment.gateway === 'wc' && this.$root.settings.payments.wc.onSiteIfFree)
        )
    },

    getPaymentGateway () {
      return this.isDefaultOnSitePayment() ? 'onSite' : this.appointment.payment.gateway
    },

    confirmBooking () {
      if (!this.fetched) {
        return
      }

      let $this = this

      this.headerErrorShow = false
      this.errors.email = ''
      this.errors.phone = ''
      this.errors.coupon = ''
      this.validateFieldsForPayPal()

      let paymentGateway = this.getPaymentGateway()

      // Validate Form
      this.$refs.booking.validate((valid, validOptions) => {
        this.formValidOptions = {}
        if (this.validateUploadedFiles() && valid && this.errors.stripe === '' && this.errors.coupon === '' && (paymentGateway !== 'onSite' || this.isRequiredAndValidRecaptcha())) {
          // Customization hook
          if ('afterConfirmBooking' in window) {
            window.afterConfirmBooking(this.appointment, this.bookable, this.provider, this.location)
          }

          this.fetched = false
          this.inlineSVG()

          this.appointment.payment.gateway = paymentGateway

          switch (this.appointment.payment.gateway) {
            case 'stripe':
              if (this.$root.settings.general.googleRecaptcha.enabled &&
                this.$root.settings.general.googleRecaptcha.invisible
              ) {
                this.$refs.recaptcha.execute()
              } else {
                this.stripeBooking()
              }
              break
            case 'onSite':
              if (this.$root.settings.general.googleRecaptcha.enabled &&
                  this.$root.settings.general.googleRecaptcha.invisible
              ) {
                this.$refs.recaptcha.execute()
              } else {
                this.saveBooking(this.getRequestData(false))
              }
              break
            case 'wc':
              this.addToWooCommerceCart()
              break
            case 'mollie':
              this.goToMolliePaymentPage()
              break
            case 'square':
              this.goToSquarePaymentPage()
              break
            case 'razorpay':
              this.razorPayCreateOrder()

              break
          }
          this.scrollView('am-spinner', 'start')
        } else {
          this.fetched = true

          if (!valid && (validOptions.hasOwnProperty('customer.firstName') || validOptions.hasOwnProperty('customer.lastName') || validOptions.hasOwnProperty('customer.email') || validOptions.hasOwnProperty('customer.phone'))) {
            this.formValidOptions = JSON.parse(JSON.stringify(validOptions))
            return false
          }

          let initialErrorArray = []
          let fileErrorArray = []
          this.customFields.forEach((item) => {
            if (item.type === 'file' && item.required === true && this.isBookableCustomFieldVisible(item) && this.$refs['customFields.' + item.id + '.value'][0].$el.getElementsByTagName('input')[0].files.length === 0) {
              let fileErrorItem = {}
              fileErrorItem.position = item.position - 1
              fileErrorItem.name = 'customFields.' + item.id + '.value'
              fileErrorArray.push(fileErrorItem)
            }
            initialErrorArray.push('customFields.' + item.id + '.value')
          })

          let initialErrorExtendedArray = []
          Object.keys(validOptions).forEach(item => {
            let index = initialErrorArray.indexOf(item)
            let errorItem = {}
            errorItem.position = index
            errorItem.name = item

            initialErrorExtendedArray.push(errorItem)
          })

          let errorArray = initialErrorExtendedArray.concat(fileErrorArray).sort((a, b) => {
            const positionA = a.position
            const positionB = b.position

            let comparison = 0
            if (positionA > positionB) {
              comparison = 1
            } else if (positionA < positionB) {
              comparison = -1
            }

            return comparison
          })

          if (errorArray.length !== 0) {
            this.$refs[errorArray[0].name][0].$el.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' })
          }

          return false
        }
      })
    },

    buildFormData (formData, data, parentKey) {
      let $this = this

      if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File)) {
        Object.keys(data).forEach(key => {
          $this.buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key)
        })
      } else {
        formData.append(parentKey, data !== null ? data : '')
      }
    },

    book (requestData) {
      this.$http.post(`${this.$root.getAjaxUrl}/bookings`, requestData.data, requestData.options).then(response => {
        if (response.data.data) {
          this.$emit('confirmedBooking', Object.assign(response.data.data, {
            color: this.bookable.color,
            type: this.bookableType,
            packageId: this.bookableType === 'package' ? this.bookable.id : null
          }, this.$root.settings.general.runInstantPostBookingActions, null))

          this.paid = true
        } else {
          this.fetched = true
        }
      }).catch(e => {
        if (this.getPaymentGateway() === 'onSite' && this.$root.settings.general.googleRecaptcha.enabled && this.$root.settings.general.googleRecaptcha.invisible) {
          this.$refs.recaptcha.reset()
        }
        this.handleSaveBookingErrors(e.response.data)
      })
    },

    saveBooking (requestData) {
      if ('ameliaActions' in window && 'beforeBooking' in window.ameliaActions) {
        window.ameliaActions.beforeBooking(
          () => {
            this.book(requestData)
          },
          (message) => {
            this.headerErrorMessage = message
            this.headerErrorShow = true
            this.fetched = true
          },
          this.getRequestData(true).data
        )
      } else {
        this.book(requestData)
      }
    },

    addToWooCommerceCart () {
      let requestData = this.getRequestData(false)

      this.$http.post(`${this.$root.getAjaxUrl}/payment/wc`, requestData.data, requestData.options).then(response => {
        window.location = response.data.data.cartUrl
      }).catch(e => {
        this.handleSaveBookingErrors(e.response.data)
      })
    },

    stripeBooking () {
      this.stripePayment.stripe.createPaymentMethod('card', this.stripePayment.cardElement, {}).then((result) => {
        if (result.error) {
          this.headerErrorShow = true
          this.headerErrorMessage = this.$root.labels.payment_error
          this.fetched = true
        } else {
          let requestData = this.getRequestData(false, {
            'paymentMethodId': result.paymentMethod.id
          })

          this.$http.post(`${this.$root.getAjaxUrl}/bookings`, requestData.data, requestData.options
          ).then(response => {
            if (response.data.data) {
              this.handleServerResponse(response.data.data)
            }
          }).catch(e => {
            this.handleSaveBookingErrors(e.response.data)
          })
        }
      })
    },

    goToMolliePaymentPage () {
      let requestData = this.getRequestData(false)

      this.$http.post(`${this.$root.getAjaxUrl}/payment/mollie`, requestData.data, requestData.options).then(response => {
        window.location = response.data.data.redirectUrl
      }).catch(e => {
        this.handleSaveBookingErrors(e.response.data)
      })
    },

    goToSquarePaymentPage () {
      let requestData = this.getRequestData(false)

      this.$http.post(`${this.$root.getAjaxUrl}/payment/square`, requestData.data, requestData.options).then(response => {
        window.location = response.data.data.redirectUrl
      }).catch(e => {
        this.handleSaveBookingErrors(e.response.data)
      })
    },

    getAppointmentDate () {
      return this.getFrontedFormattedDate(
        moment(this.bookable.bookingStart, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD')
      )
    },

    getAppointmentTime () {
      return this.getFrontedFormattedTime(this.bookable.bookingStart.split(' ')[1])
    },

    getExtrasPrice (bookingsCount) {
      let totalPrice = 0

      for (let i = 0; i < this.selectedExtras.length; i++) {
        totalPrice += bookingsCount * this.selectedExtras[i].price * this.selectedExtras[i].quantity * this.getExtraPriceMultipleValue(this.selectedExtras[i])
      }

      return totalPrice
    },

    getTotalPrice () {
      let totalPrice = this.amountData.instant.total - this.amountData.instant.discount + this.amountData.instant.tax

      return totalPrice > 0 ? totalPrice : 0
    },

    getSelectedExtraDetails (extra) {
      let result = ''

      if (extra.price) {
        if (this.instantPaymentBookingsCount > 1 || (this.recurringData !== null && this.recurringData.length)) {
          result += this.instantPaymentBookingsCount + ' ' + (this.instantPaymentBookingsCount > 1 ? this.$root.labels.appointments.toLowerCase() : this.$root.labels.appointment.toLowerCase()) + ' x '
        }

        if (this.getExtraPriceMultipleValue(extra) > 1) {
          result += this.getExtraPriceMultipleValue(extra) + ' ' + this.$root.labels.persons + ' x '
        }

        result += extra.quantity + ' ' + ' x '

        result += this.getFormattedPrice(extra.price, !this.$root.settings.payments.hideCurrencySymbolFrontend) + ' = '
      }

      result += this.getFormattedPrice(
        this.instantPaymentBookingsCount * extra.price * this.getExtraPriceMultipleValue(extra) * extra.quantity,
        !this.$root.settings.payments.hideCurrencySymbolFrontend
      )

      return result
    },

    getExtraPriceMultipleValue (extra) {
      let aggregatedPrice = extra.aggregatedPrice === null ? this.bookable.aggregatedPrice : extra.aggregatedPrice

      return aggregatedPrice ? this.appointment.bookings[0].persons : 1
    },

    getBasePrice (bookingsCount, bookingBasePrice) {
      return bookingsCount * this.basePriceMultipleValue * bookingBasePrice
    },

    getBookingTicketsBasePriceCalculationString (ticketsData) {
      let ticketsArray = ticketsData.bookingToEventTickets
      let result = ''

      ticketsArray.forEach(ticket => {
        if (ticket.persons !== 0) {
          result += result !== '' ? ' + ' : ''

          result += ticket.name + '(' + this.getFormattedPrice(ticket.price, !this.$root.settings.payments.hideCurrencySymbolFrontend) + ')' +
              (this.bookable.aggregatedPrice ? (' x ' + ticket.persons) : '')
        }
      })
      result += ' = ' + this.getFormattedPrice(ticketsData.totalPrice, !this.$root.settings.payments.hideCurrencySymbolFrontend)
      return result
    },

    getBookingBasePriceCalculationString (bookingsCount, bookingBasePrice) {
      let result = ''

      if (bookingsCount > 1 || (this.recurringData !== null && this.recurringData.length)) {
        result += bookingsCount + ' ' + (bookingsCount > 1 ? this.$root.labels.appointments.toLowerCase() : this.$root.labels.appointment.toLowerCase()) + ' x '
      }

      if (this.basePriceMultipleValue > 1) {
        result += this.basePriceMultipleValue + ' ' + this.$root.labels.persons + ' x '
      }

      let totalPriceFormatted = this.getFormattedPrice(
        this.getBasePrice(bookingsCount, bookingBasePrice),
        !this.$root.settings.payments.hideCurrencySymbolFrontend
      )

      if (result) {
        let bookingBasePriceFormatted = this.getFormattedPrice(
          bookingBasePrice,
          !this.$root.settings.payments.hideCurrencySymbolFrontend
        )

        result += bookingBasePriceFormatted + ' = ' + totalPriceFormatted
      }

      return result !== '' ? result : totalPriceFormatted
    },

    getBookingBasePriceData (type) {
      let result = []

      let paymentData = this.paymentPeriodData[type]

      for (let entityId in paymentData) {
        if (paymentData[entityId].price) {
          result.push({
            count: paymentData[entityId].count,
            price: paymentData[entityId].price
          })
        }
      }

      return result
    },

    checkCoupon (ev) {
      ev.preventDefault()

      this.$refs.coupon.clearValidate()
      this.$refs.coupon.validate()
    },

    getExtras () {
      let extras = JSON.parse(JSON.stringify(this.selectedExtras))

      extras.forEach(function (extItem) {
        extItem.extraId = extItem.id
        extItem.id = null
      })

      return extras
    },

    trimValue (value) {
      return typeof value === 'string' ? value.replace(/^\s+|\s+$/g, '') : value
    },

    getRequestData (mandatoryJson, paymentData) {
      let componentProps = JSON.parse(JSON.stringify(this.getComponentProps()))

      let customFieldFilesIndexes = {}

      let filesIndex = 0

      for (let i = 0; i < this.customFields.length; i++) {
        if (this.customFields[i].type === 'file') {
          let customField = this.customFields.find(field => parseInt(field.id) === parseInt(this.customFields[i].id))

          if (this.isBookableCustomFieldVisible(customField)) {
            customFieldFilesIndexes[this.customFields[i].id] = filesIndex
            filesIndex++
          }
        }
      }

      this.appointment.payment.amount = (this.paymentType !== 'fullAmount') ? this.amountData.instant.deposit.toFixed(2).toString() : this.getTotalPrice().toFixed(2).toString()

      this.appointment.payment.currency = this.$root.settings.payments.currencyCode

      let bookings = JSON.parse(JSON.stringify(this.appointment.bookings))

      let tickets = null

      if (this.bookable.ticketsData) {
        tickets = this.bookable.ticketsData.bookingToEventTickets
      }

      bookings[0].extras = this.getExtras()

      bookings[0].ticketsData = tickets

      let customFields = {}

      for (let key in bookings[0].customFields) {
        if (!bookings[0].customFields.hasOwnProperty(key)) {
          continue
        }

        let customField = this.customFields.find(field => parseInt(field.id) === parseInt(key))

        if (this.isBookableCustomFieldVisible(customField)) {
          let uploadedFilesIndex = key in customFieldFilesIndexes && customFieldFilesIndexes[key] in this.$refs.customFieldsFiles ? customFieldFilesIndexes[key] : null

          if (uploadedFilesIndex !== null) {
            let uploadCustomField = {
              label: bookings[0].customFields[key].label,
              value: []
            }

            for (let i = 0; i < this.$refs.customFieldsFiles[uploadedFilesIndex].uploadFiles.length; i++) {
              uploadCustomField.value.push({
                name: this.$refs.customFieldsFiles[uploadedFilesIndex].uploadFiles[i].name
              })
            }

            customFields[key] = (uploadCustomField)
          } else {
            customFields[key] = (bookings[0].customFields[key])
          }

          customFields[key].type = customField.type

          if (customFields[key].type === 'datepicker') {
            customFields[key].value = customFields[key].value ? this.getStringFromDate(new Date(customFields[key].value)) : null
          }
        }
      }

      bookings[0].customer.email = bookings[0].customer.email ? this.trimValue(bookings[0].customer.email) : bookings[0].customer.email
      bookings[0].customer.phone = bookings[0].customer.phone ? this.trimValue(bookings[0].customer.phone) : bookings[0].customer.phone

      bookings[0].customFields = customFields

      let bookingDateTime = this.bookable.bookingStart
      let recurringData = typeof this.recurringData !== 'undefined' && this.recurringData !== null ? JSON.parse(JSON.stringify(this.recurringData)) : []
      let packageData = typeof this.packageData !== 'undefined' && this.packageData !== null ? JSON.parse(JSON.stringify(this.packageData)) : {id: null, data: []}

      bookings[0].utcOffset = null

      bookings[0].deposit = this.paymentType === 'fullAmount' ? false : this.bookable.depositData !== null

      componentProps.appointment.bookings[0].customFields = customFields

      componentProps.appointment.payment = Object.assign(this.appointment.payment, {data: paymentData})

      componentProps.appointment.payment.amount = this.appointment.payment.amount

      if (this.$root.settings.general.showClientTimeZone) {
        bookingDateTime = moment(bookingDateTime, 'YYYY-MM-DD HH:mm').utc().format('YYYY-MM-DD HH:mm')

        recurringData.forEach((item) => {
          item.bookingStart = moment(item.bookingStart, 'YYYY-MM-DD HH:mm').utc().format('YYYY-MM-DD HH:mm')
          item.utcOffset = this.getClientUtcOffset(item.bookingStart)
        })

        packageData.data.forEach((item) => {
          item.bookingStart = moment(item.bookingStart, 'YYYY-MM-DD HH:mm').utc().format('YYYY-MM-DD HH:mm')
          item.utcOffset = this.getClientUtcOffset(item.bookingStart)
        })

        bookings[0].utcOffset = this.getClientUtcOffset(bookingDateTime)
      }

      packageData.data.forEach((item) => {
        item.notifyParticipants = this.appointment.notifyParticipants ? 1 : 0
      })

      if (componentProps && 'bookable' in componentProps && 'name' in componentProps.bookable) {
        componentProps.bookable.name = componentProps.bookable.name.replace(/"/g, "'")
      }

      let jsonData = {
        'type': this.bookableType,
        'bookings': bookings,
        'payment': Object.assign(this.appointment.payment, {data: paymentData}),
        'recaptcha': this.recaptchaResponse,
        'locale': window.localeLanguage[0],
        'timeZone': Intl.DateTimeFormat().resolvedOptions().timeZone,
        'urlParams': this.getUrlQueryParams(window.location.href),
        'couponCode': this.coupon && this.coupon.code ? this.coupon.code : '',
        'componentProps': componentProps,
        'returnUrl': this.removeURLParameter(location.href, 'ameliaCache')
      }

      switch (this.bookableType) {
        case ('appointment'):
          bookings[0].duration = this.appointment.serviceDuration

          jsonData = Object.assign(jsonData, {
            'bookingStart': bookingDateTime,
            'notifyParticipants': this.appointment.notifyParticipants ? 1 : 0,
            'locationId': this.location !== null ? this.location.id : null,
            'providerId': this.provider ? this.provider.id : null,
            'serviceId': this.bookable.id,
            'recurring': recurringData,
            'package': []
          })

          break

        case ('package'):
          jsonData = Object.assign(jsonData, {
            'package': packageData.data,
            'packageId': packageData.id,
            'packageRules': packageData.rules,
            'utcOffset': this.getClientUtcOffset(null),
            'deposit': this.paymentType === 'fullAmount' ? false : this.bookable.depositData !== null
          })

          break

        case ('event'):
          jsonData = Object.assign(jsonData, {
            'eventId': this.bookable.id
          })
      }

      let bookingData = null
      let requestOptions = null

      let hasUploadedFiles = false

      if (this.$refs.customFieldsFiles) {
        for (let i = 0; i < this.$refs.customFieldsFiles.length; i++) {
          if (this.$refs.customFieldsFiles[i].uploadFiles.length > 0) {
            hasUploadedFiles = true
            break
          }
        }
      }

      if (hasUploadedFiles && !mandatoryJson) {
        bookingData = new FormData()

        this.buildFormData(bookingData, jsonData)

        for (let key in customFieldFilesIndexes) {
          let index = customFieldFilesIndexes[key]

          if (!customFieldFilesIndexes.hasOwnProperty(key) || !(index in this.$refs.customFieldsFiles)) {
            continue
          }

          for (let i = 0; i < this.$refs.customFieldsFiles[index].uploadFiles.length; i++) {
            bookingData.append('files[' + key + '][' + i + ']', this.$refs.customFieldsFiles[index].uploadFiles[i].raw)
          }
        }

        requestOptions = {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        }
      } else {
        bookingData = jsonData

        requestOptions = {}
      }

      return {
        data: bookingData,
        options: requestOptions
      }
    },

    handleSaveBookingErrors (response) {
      if ('data' in response) {
        if ('onSitePayment' in response.data && response.data.onSitePayment) {
          this.appointment.payment.gateway = 'onSite'
          this.saveBooking(this.getRequestData(false))
        } else {
          if ('afterFailedBooking' in window) {
            window.afterFailedBooking(response.data)
          }
        }

        if ('customerAlreadyBooked' in response.data && response.data.customerAlreadyBooked === true) {
          this.headerErrorShow = true
          switch (this.bookableType) {
            case 'appointment':
            case 'package':
              this.headerErrorMessage = this.$root.labels.customer_already_booked_app

              break
            case 'event':
              this.headerErrorMessage = this.$root.labels.customer_already_booked_ev
              break
          }
        }
        if ('timeSlotUnavailable' in response.data && response.data.timeSlotUnavailable === true) {
          this.headerErrorShow = true

          switch (this.bookableType) {
            case 'appointment':
            case 'package':
              this.headerErrorMessage = this.$root.labels.time_slot_unavailable
              break
            case 'event':
              this.headerErrorMessage = this.$root.labels.maximum_capacity_reached
              break
          }
        } else if ('bookingsLimitReached' in response.data && response.data.bookingsLimitReached === true) {
          this.headerErrorShow = true
          this.headerErrorMessage = this.$root.labels.bookings_limit_reached
        } else if ('emailError' in response.data && response.data.emailError === true) {
          this.errors.email = this.$root.labels.email_exist_error
        } else if ('phoneError' in response.data && response.data.phoneError === true) {
          this.errors.phone = this.$root.labels.phone_exist_error
        } else if ('couponUnknown' in response.data && response.data.couponUnknown === true) {
          this.errors.coupon = this.$root.labels.coupon_unknown
        } else if ('couponInvalid' in response.data && response.data.couponInvalid === true) {
          this.errors.coupon = this.$root.labels.coupon_invalid
        } else if ('couponExpired' in response.data && response.data.couponExpired === true) {
          this.errors.coupon = this.$root.labels.coupon_expired
        } else if ('couponMissing' in response.data && response.data.couponMissing === true) {
          this.errors.coupon = this.$root.labels.coupon_missing
        } else if ('paymentSuccessful' in response.data && response.data.paymentSuccessful === false) {
          this.headerErrorShow = true
          this.headerErrorMessage = this.$root.labels.payment_error
        } else if ('bookingAlreadyInWcCart' in response.data && response.data.bookingAlreadyInWcCart === true) {
          this.headerErrorShow = true
          this.headerErrorMessage = this.$root.labels.booking_already_in_wc_cart
        } else if ('wcError' in response.data && response.data.wcError === true) {
          this.headerErrorShow = true
          this.headerErrorMessage = this.$root.labels.wc_error
        } else if ('recaptchaError' in response.data && response.data.recaptchaError === true) {
          this.errors.recaptcha = this.$root.labels.recaptcha_invalid_error
        } else if ('message' in response.data) {
          this.headerErrorShow = true
          this.headerErrorMessage = response.data.message
        }
      }

      this.fetched = true
    },

    isRequiredAndValidRecaptcha () {
      this.errors.recaptcha = ''

      if (this.$root.settings.general.googleRecaptcha.enabled &&
        !this.$root.settings.general.googleRecaptcha.invisible &&
        !this.validRecaptcha
      ) {
        this.errors.recaptcha = this.$root.labels.recaptcha_error
        return false
      }

      return true
    },

    validateFieldsForPayPal () {
      this.clearValidation()

      if (/^\s/.test(this.appointment.bookings[0].customer.firstName)) {
        this.appointment.bookings[0].customer.firstName = this.appointment.bookings[0].customer.firstName.substring(1)
      }

      if (/^\s/.test(this.appointment.bookings[0].customer.lastName)) {
        this.appointment.bookings[0].customer.lastName = this.appointment.bookings[0].customer.lastName.substring(1)
      }

      this.appointment.bookings[0].customer.email = this.trimValue(this.appointment.bookings[0].customer.email)

      if (this.payPalActions === null || this.appointment.payment.gateway !== 'payPal') {
        return
      }

      let validCustomFields = true

      for (let key in this.appointment.bookings[0].customFields) {
        if (!this.appointment.bookings[0].customFields.hasOwnProperty(key)) {
          continue
        }

        let customField = this.customFields.find(field => parseInt(field.id) === parseInt(key))

        if (this.isBookableCustomFieldVisible(customField) && customField.required && customField.type !== 'file' &&
          (
            (Array.isArray(this.appointment.bookings[0].customFields[key].value) && this.appointment.bookings[0].customFields[key].value.length === 0) ||
            (!Array.isArray(this.appointment.bookings[0].customFields[key].value) && (!this.appointment.bookings[0].customFields[key].value || this.trimValue(this.appointment.bookings[0].customFields[key].value) === ''))
          )
        ) {
          validCustomFields = false
        }
      }

      if (this.appointment.bookings[0].customer.firstName === '' ||
        (this.formsData[this.$options.name][this.bookableType].itemsDraggable.lastNameFormField.required && this.appointment.bookings[0].customer.lastName === '') ||
        (this.formsData[this.$options.name][this.bookableType].itemsDraggable.emailFormField.required && this.appointment.bookings[0].customer.email === '') ||
        (this.formsData[this.$options.name][this.bookableType].itemsDraggable.phoneFormField.required && this.appointment.bookings[0].customer.phone === '') ||
        !validCustomFields ||
        !this.validateUploadedFiles()) {
        this.payPalActions.disable()
      } else {
        this.payPalActions.enable()
      }
    },

    razorPayVerify (paymentId, signature, orderId) {
      this.$emit('changeConfirmBookingRazorpay', true)
      this.saveBooking(this.getRequestData(false, {'paymentId': paymentId, 'signature': signature, 'orderId': orderId}))
    },

    razorPayCreateOrder () {
      let $this = this
      let requestData = this.getRequestData(true)
      this.$http.post(`${this.$root.getAjaxUrl}/payment/razorpay`, requestData.data, requestData.options).then(response => {
        let options = response.data.data.data
        options.handler = function (res) {
          $this.razorPayVerify(res.razorpay_payment_id, res.razorpay_signature, options.order_id)
        }

        options.modal = {
          ondismiss: function () {
            $this.fetched = true
            $this.$emit('changeConfirmBookingRazorpay', true)
          }
        }

        var rzp = new Razorpay(options)
        this.$emit('changeConfirmBookingRazorpay', false)
        rzp.open()
      }).catch(e => {
        this.handleSaveBookingErrors(e.response.data)
      })
    },

    payPalInit () {
      let $this = this

      let transactionReference = ''

      window.paypal.Button.render({
        style: {
          size: 'responsive',
          color: 'gold',
          shape: 'rect',
          tagLine: false
        },

        env: $this.$root.settings.payments.payPal.sandboxMode ? 'sandbox' : 'production',

        client: {
          sandbox: $this.$root.settings.payments.payPal.testApiClientId,
          production: $this.$root.settings.payments.payPal.liveApiClientId
        },

        commit: true,

        onClick: function () {
          $this.confirmBooking()
        },

        validate: function (actions) {
          $this.payPalActions = actions
          $this.validateFieldsForPayPal()
        },

        payment: function () {
          let bookings = JSON.parse(JSON.stringify($this.appointment.bookings))

          bookings[0].extras = $this.getExtras()

          return window.paypal.request(
            {
              method: 'post',
              url: $this.$root.getAjaxUrl + '/payment/payPal',
              json: $this.getRequestData(true)['data']
            }
          ).then(
            function (response) {
              transactionReference = response.data.transactionReference
              return response.data.paymentID
            }
          ).catch(
            function (error) {
              $this.parseError(error)
            }
          )
        },

        onAuthorize: function (data, actions) {
          return actions.payment.get().then(function () {
            let requestData = $this.getRequestData(false, {
              'transactionReference': transactionReference,
              'PaymentId': data.paymentID,
              'PayerId': data.payerID
            })

            $this.saveBooking(requestData)
          })
        },

        onCancel: function () {
          $this.fetched = true
          $this.inlineSVG()
        },

        onError: function (error) {
          $this.parseError(error)
        }

      }, '#am-paypal-button-container')
    },

    parseError: function (error) {
      let errorString = error.toString()
      let response = JSON.parse(JSON.stringify(JSON.parse(errorString.substring(errorString.indexOf('{'), errorString.lastIndexOf('}') + 1))))

      if (typeof response === 'object' && response.hasOwnProperty('data')) {
        this.handleSaveBookingErrors(response)
      } else {
        this.headerErrorShow = true
        this.headerErrorMessage = this.$root.labels.payment_error
      }

      this.fetched = true
      this.inlineSVG()
    },

    clearValidation () {
      if (typeof this.$refs.booking !== 'undefined') {
        this.$refs.booking.clearValidate()
      }

      if (typeof this.$refs.coupon !== 'undefined') {
        this.$refs.coupon.clearValidate()
      }

      let $this = this

      Object.keys(this.errors.files).forEach(function (key) {
        $this.errors.files[key] = ''
      })

      this.errors.recaptcha = ''

      if (this.errors.files) {
        let firstName = this.appointment.bookings[0].customer.firstName
        this.appointment.bookings[0].customer.firstName = firstName + '_'
        this.appointment.bookings[0].customer.firstName = firstName
      }
    },

    handleResize () {
      let amContainer = document.getElementById(this.containerId)

      if (!amContainer) {
        return
      }

      let amContainerWidth = amContainer.offsetWidth

      if (amContainerWidth < 670) {
        this.columnsLg = 24
      } else {
        this.columnsLg = 12
      }
    },

    addCustomFieldsValidationRules () {
      for (let i = 0; i < this.customFields.length; i++) {
        if (this.isBookableCustomFieldVisible(this.customFields[i]) && this.customFields[i].required === true) {
          let rules = [
            {required: true, message: this.$root.labels.required_field, trigger: 'submit'}
          ]

          if (this.customFields[i].type === 'text' || this.customFields[i].type === 'text-area' || this.customFields[i].type === 'address') {
            rules = [
              {required: true, message: this.$root.labels.required_field, trigger: 'submit'},
              {validator: this.validateCustomFieldInput, trigger: 'submit'}
            ]
          }

          this.$set(this.rules, 'customFields.' + this.customFields[i].id + '.value', rules)
        }
      }
    },

    validateCustomFieldInput (rule, input, callback) {
      if (!input || this.trimValue(input) === '') {
        callback(new Error(this.$root.labels.required_field))
      } else {
        callback()
      }
    },

    getAppointmentsAmountData () {
      let data = {
        instant: {
          total: 0,
          tax: 0,
          discount: 0,
          base: 0,
          deposit: 0
        },
        postponed: {
          total: 0,
          tax: 0,
          discount: 0,
          base: 0,
          deposit: 0,
          totals: {}
        }
      }

      let coupon = this.coupon && (this.coupon.discount || this.coupon.deduction) ? this.coupon : null

      let couponLimit = this.couponLimit

      let instantPaymentCount = 1

      if (this.service.recurringPayment) {
        instantPaymentCount = this.service.recurringPayment > this.recurringData.length + 1
          ? this.recurringData.length + 1
          : this.service.recurringPayment
      }

      let periodType = 'instant'

      let amounts = [this.bookable.price]

      this.recurringData.forEach((item) => {
        amounts.push(item.price)
      })

      let postponedAppointmentsIndex = 0

      amounts.forEach((serviceAmount, index) => {
        if (coupon && couponLimit > 0) {
          couponLimit--
        } else {
          coupon = null
        }

        let appointmentData = this.getAppointmentPriceAmount(
          Object.assign({}, this.bookable, {price: serviceAmount}),
          this.selectedExtras,
          this.appointment.bookings[0].persons,
          coupon,
          true
        )

        if (index < instantPaymentCount) {
          data[periodType].deposit += this.getDepositAmount(appointmentData.total - appointmentData.discount + appointmentData.tax)
        } else {
          periodType = 'postponed'
        }

        data[periodType].total += appointmentData.total
        data[periodType].discount += appointmentData.discount
        data[periodType].tax += appointmentData.tax

        if (periodType === 'postponed') {
          if (!(appointmentData.total in data[periodType].totals)) {
            data[periodType].totals[appointmentData.total] = {
              index: postponedAppointmentsIndex,
              count: 1,
              total: appointmentData.total
            }

            postponedAppointmentsIndex++
          } else {
            data[periodType].totals[appointmentData.total].count++
          }
        }
      })

      let totals = []

      Object.keys(data.postponed.totals).forEach((total) => {
        totals[data.postponed.totals[total].index] = {
          total: total,
          count: data.postponed.totals[total].count,
        }
      })

      data.postponed.totals = totals

      return data
    },

    getEventAmountData () {
      let price = this.bookable.ticketsData
        ? this.bookable.ticketsData.totalPrice
        : this.basePriceMultipleValue * this.bookable.price

      let eventTax = this.getEntityTax(this.bookable.id, 'event')

      if (this.$root.settings.payments.taxes.enabled && eventTax && !this.$root.settings.payments.taxes.excluded && this.coupon && this.couponLimit) {
        price = this.getBaseAmount(price, eventTax)
      }

      let discount = this.coupon && this.couponLimit ? (price / 100 * this.coupon.discount) + this.coupon.deduction : 0

      let tax = 0

      if (this.$root.settings.payments.taxes.enabled && eventTax && this.$root.settings.payments.taxes.excluded) {
        tax = this.getEntityTaxAmount(eventTax, price - discount)
      } else if (this.$root.settings.payments.taxes.enabled && eventTax && !this.$root.settings.payments.taxes.excluded && discount) {
        price += this.getEntityTaxAmount(eventTax, price - discount)
      }

      return {
        instant: {
          total: price,
          discount: discount,
          tax: tax,
          deposit: this.getDepositAmount(price - discount + tax)
        },
        postponed: {
          total: 0,
          discount: 0,
          tax: 0,
          deposit: 0
        }
      }
    },

    getPackageAmountData () {
      let price = this.basePriceMultipleValue * this.bookable.price

      let packageTax = this.getEntityTax(this.bookable.id, 'package')

      if (this.$root.settings.payments.taxes.enabled && packageTax && !this.$root.settings.payments.taxes.excluded && this.coupon && this.couponLimit) {
        price = this.getBaseAmount(price, packageTax)
      }

      let discount = this.coupon && this.couponLimit ? (price / 100 * this.coupon.discount) + this.coupon.deduction : 0

      let tax = 0

      if (this.$root.settings.payments.taxes.enabled && packageTax && this.$root.settings.payments.taxes.excluded) {
        tax = this.getEntityTaxAmount(packageTax, price - discount)
      } else if (this.$root.settings.payments.taxes.enabled && packageTax && !this.$root.settings.payments.taxes.excluded && discount) {
        price += this.getEntityTaxAmount(packageTax, price - discount)
      }

      return {
        instant: {
          total: price,
          discount: discount,
          tax: tax,
          deposit: this.getDepositAmount(price - discount + tax)
        },
        postponed: {
          total: 0,
          discount: 0,
          tax: 0,
          deposit: 0
        }
      }
    },

    getDepositAmount (totalAmount) {
      let depositAmount = 0

      if (this.bookable.depositData) {
        switch (this.bookable.depositData.depositPayment) {
          case ('fixed'):
            depositAmount = this.bookable.depositData.depositPerPerson
              ? this.appointment.bookings[0].persons * this.bookable.depositData.deposit
              : this.bookable.depositData.deposit

            break

          case ('percentage'):
            depositAmount = this.getPercentage(totalAmount, this.bookable.depositData.deposit)

            break
        }
      }

      return this.getRound(totalAmount > depositAmount ? depositAmount : 0)
    },

    getTaxLabel () {
      let entityTax = this.getEntityTax(this.bookable.id, this.bookableType === 'appointment' ? 'service' : this.bookableType)

      let taxes = {}

      taxes[entityTax.id] = entityTax.name

      this.selectedExtras.forEach((extItem) => {
        let extraTax = this.getEntityTax(extItem.extraId, 'extra')

        if (extraTax) {
          taxes[extraTax.id] = extraTax.name
        }
      })

      let label = 'total_tax_colon' in this.priceLabels
        ? this.priceLabels.total_tax_colon.value || this.$root.labels.total_tax_colon
        : this.$root.labels.total_tax_colon

      return Object.keys(taxes).length === 1 ? Object.values(taxes)[0] : label
    }
  },

  computed: {
    amountData () {
      switch (this.bookableType) {
        case ('appointment'):
          return this.getAppointmentsAmountData()
        case ('event'):
          return this.getEventAmountData()
        case ('package'):
          return this.getPackageAmountData()
      }
    },

    withDeposit () {
      return this.amountData.instant.deposit > 0 && this.getPaymentGateway() !== 'onSite' && this.paymentType === 'depositOnly'
    },

    onlyTotal () {
      return !(this.amountData.instant.tax > 0 || this.amountData.instant.discount > 0)
    },

    instantPaymentBasePriceData () {
      return this.getBookingBasePriceData('instant')
    },

    basePriceMultipleValue () {
      return this.bookable.aggregatedPrice ? this.appointment.bookings[0].persons : 1
    },

    instantPaymentBookingsCount () {
      if (this.recurringData.length === 0) {
        return 1
      }

      return (this.recurringData.length < this.service.recurringPayment ? this.recurringData.length : this.service.recurringPayment) + 1
    },

    // amountData.instant.deposit () {
    //   return this.amountData.instant.deposit
    //
    //   let amountData.instant.deposit = 0
    //
    //   let totalPrice = this.getTotalPrice()
    //
    //   if (this.bookable.depositData) {
    //     switch (this.bookable.depositData.depositPayment) {
    //       case ('fixed'):
    //         if (this.bookable.depositData.depositPerPerson && this.bookable.aggregatedPrice) {
    //           let persons = 'ticketsData' in this.bookable && this.bookable.ticketsData && 'totalTickets' in this.bookable.ticketsData
    //             ? this.bookable.ticketsData.totalTickets : this.appointment.bookings[0].persons
    //
    //           amountData.instant.deposit = persons * this.bookable.depositData.deposit
    //         } else {
    //           amountData.instant.deposit = this.bookable.depositData.deposit
    //         }
    //
    //         if (this.bookableType === 'appointment') {
    //           this.recurringData.forEach((value, index) => {
    //             if (this.instantPaymentBookingsCount - 1 > index) {
    //               amountData.instant.deposit +=
    //                 this.bookable.depositData.depositPerPerson
    //                   ? this.appointment.bookings[0].persons * value.depositData.deposit : value.depositData.deposit
    //             } else if (value.depositData) {
    //               value.depositData = null
    //             }
    //           })
    //         }
    //
    //         break
    //
    //       case 'percentage':
    //         amountData.instant.deposit = totalPrice / 100 * this.bookable.depositData.deposit
    //         console.log(amountData.instant.deposit)
    //
    //         break
    //     }
    //   }
    //
    //   return totalPrice > amountData.instant.deposit ? amountData.instant.deposit : 0
    // },

    paymentPeriodData () {
      let instantPaymentData = {}
      let postponedPaymentData = {}

      switch (this.bookableType) {
        case ('appointment'):
          instantPaymentData[this.bookable.price] = {
            count: 1,
            price: this.bookable.price
          }

          this.recurringData.forEach((value, index) => {
            if (this.instantPaymentBookingsCount - 1 > index) {
              if (!(value.price in instantPaymentData)) {
                instantPaymentData[value.price] = {
                  count: 1,
                  price: value.price
                }
              } else {
                instantPaymentData[value.price].count++
              }
            } else {
              if (!(value.price in postponedPaymentData)) {
                postponedPaymentData[value.price] = {
                  count: 1,
                  price: value.price
                }
              } else {
                postponedPaymentData[value.price].count++
              }
            }
          })

          break

        case ('package'):
          instantPaymentData[this.bookable.price] = {
            count: 1,
            price: this.bookable.price
          }

          break

        case ('event'):
          instantPaymentData[this.bookable.price] = {
            count: 1,
            price: this.bookable.price
          }

          break
      }

      return {
        instant: instantPaymentData,
        postponed: postponedPaymentData
      }
    },

    bookableConfirmStyle () {
      return this.hoverConfirm ? {
        color: this.bookable.color,
        borderColor: this.bookable.color,
        backgroundColor: this.bookable.color,
        opacity: 0.8
      } : {
        color: '#ffffff',
        backgroundColor: this.bookable.color,
        borderColor: this.bookable.color,
        opacity: 1
      }
    },

    bookableCancelStyle () {
      return this.hoverCancel ? {
        color: this.bookable.color,
        borderColor: this.bookable.color,
        backgroundColor: '',
        opacity: 0.7
      } : {
        color: '',
        backgroundColor: '#ffffff',
        borderColor: '',
        opacity: 1
      }
    },

    bookableCancelSpanStyle () {
      return this.hoverCancel ? {
        color: this.bookable.color,
        borderColor: '',
        backgroundColor: '',
        opacity: 0.9
      } : {
        color: '',
        backgroundColor: '',
        borderColor: '',
        opacity: 1
      }
    },

    selectedExtras () {
      return this.appointment.bookings[0].extras.filter(extra => extra.selected === true)
    },

    paymentOptions () {
      let paymentOptions = []

      if (this.$root.settings.payments.onSite === true) {
        paymentOptions.push({
          value: 'onSite',
          label: this.$root.labels.on_site
        })
      }

      if (this.$root.settings.payments.payPal.enabled) {
        paymentOptions.push({
          value: 'payPal',
          label: this.$root.labels.pay_pal
        })
      }

      if (this.$root.settings.payments.stripe.enabled) {
        paymentOptions.push({
          value: 'stripe',
          label: this.$root.labels.credit_card
        })
      }

      if (this.$root.settings.payments.wc.enabled) {
        paymentOptions.push({
          value: 'wc',
          label: this.$root.labels.wc
        })
      }

      if (this.$root.settings.payments.mollie.enabled) {
        paymentOptions.push({
          value: 'mollie',
          label: this.$root.labels.on_line
        })
      }

      if (this.$root.settings.payments.square.enabled) {
        paymentOptions.push({
          value: 'square',
          label: this.$root.labels.square
        })
      }

      if (this.$root.settings.payments.razorpay.enabled) {
        paymentOptions.push({
          value: 'razorpay',
          label: this.$root.labels.razorpay
        })
      }

      return paymentOptions
    },

    showConfirmBookingButton () {
      return this.appointment.payment.gateway === 'onSite' ||
        this.appointment.payment.gateway === 'wc' ||
        this.appointment.payment.gateway === 'mollie' ||
        this.appointment.payment.gateway === 'square' ||
        this.appointment.payment.gateway === 'stripe' ||
        this.appointment.payment.gateway === 'razorpay' ||
        (this.appointment.payment.gateway === 'payPal' && this.getTotalPrice() === 0)
    },

    priceLabels () {
      if (this.formType === 'searchForm') {
        return this.defaultFormsData['stepByStepForm'][this.formName][this.bookableType].itemsStatic.priceFormFiled.labels
      }

      return this.formsData.confirmBookingForm[this.bookableType].itemsStatic.priceFormFiled
        ? this.formsData.confirmBookingForm[this.bookableType].itemsStatic.priceFormFiled.labels
        : this.defaultFormsData[this.formType][this.formName][this.bookableType].itemsStatic.priceFormFiled.labels
    }
  },

  components: {
    moment,
    VueRecaptcha,
    confirmHeadingDataFormField,
    recurringStringFormField,
    firstNameFormField,
    lastNameFormField,
    emailFormField,
    phoneFormField,
    paymentMethodFormField,
    paymentTypeFormField,
    stripeCardFormField,
    VueGoogleAutocomplete
  }
}
</script>
© 2026 GrazzMean-Shell