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 : BookingStepForm.vue
<template>
  <template v-if="!amFonts.customFontSelected">
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      rel="stylesheet"
      type="text/css"
      :href="`${baseUrls.wpAmeliaPluginURL}v3/src/assets/scss/common/fonts/font.css`"
      media="all"
    />
  </template>
  <div
    v-if="!empty && formDialogVisibility"
    id="amelia-container"
    ref="ameliaContainer"
    class="am-fs__wrapper"
    :class="{ 'am-collapsed': sidebarCollapsed }"
    :style="cssVars"
  >
    <SideBar
      v-if="containerWidth > 560 && sidebarVisibility"
      class="am-fs-sb"
      :class="[{ 'am-collapsed': sidebarCollapsed }, {'am-rtl': isRtl}]"
      :style="{
        width: !sidebarCollapsed ? '240px' : '72px',
        paddingBottom: `${sidebarFooterHeight + 16}px`,
      }"
    >
      <template #step-list>
        <div class="am-fs-sb__step-wrapper" tabindex="0">
          <template
            v-if="
              ready &&
              (stepsArray[stepIndex] !== congratulationsStep ||
                !amSettings.general.addToCalendar ||
                (booked && booked.data.length === 0))
            "
          >
            <div
              v-for="step in sidebarSteps"
              :key="step.key"
              class="am-fs-sb__step"
            >
              <div class="am-fs-sb__step-inner">
                <div class="am-fs-sb__step-icon">
                  <span :class="`am-icon-${step.icon}`"></span>
                  <span
                    v-if="
                      step.key === 'cartStep' && useCartHasItems(store) !== 0
                    "
                    class="am-fs-sb__step-icon__number"
                    :class="[{'am-rtl': isRtl} ,sidebarCollapseItemsClass]"
                  >
                    {{ useCartHasItems(store) }}
                  </span>
                </div>
                <transition name="fade">
                  <p
                    v-if="!sidebarCollapsed"
                    class="am-fs-sb__step-heading"
                    :class="sidebarCollapseItemsClass"
                  >
                    {{ step.label }}
                  </p>
                </transition>
                <div
                  class="am-fs-sb__step-checker"
                  :class="[
                    { 'am-fs-sb__step-checker-selected': step.selected },
                    { 'am-rtl': isRtl },
                    sidebarCollapseItemsClass,
                  ]"
                >
                  <transition name="fade">
                    <span v-if="step.finished" class="am-icon-check"></span>
                  </transition>
                </div>
              </div>
              <TransitionGroup
                tag="span"
                name="fade"
                appear
                class="am-fs-sb__step-selection__wrapper"
                :class="{
                  'am-fs-sb__step-selection-packages':
                    step.key === packageAppointmentsStep.key &&
                    step.stepSelectedData.length > 3,
                }"
              >
                <template
                  v-if="
                    !sidebarCollapsed &&
                    (useCart(store).length === 1 || step.key === 'cartStep')
                  "
                >
                  <p
                    v-for="(itemSelected, index) in step.stepSelectedData"
                    :key="itemSelected.position"
                    class="am-fs-sb__step-selection"
                  >
                    <span
                      v-if="
                        step.key !== packageAppointmentsStep.key || index < 3
                      "
                    >
                      {{ itemSelected.value }}
                    </span>
                    <span v-else>
                      {{ amLabels.plus_more }}
                    </span>
                  </p>
                </template>
              </TransitionGroup>
            </div>
          </template>
          <template v-else-if="ready">
            <div>
              <transition name="fade">
                <AddToCalendar v-if="!sidebarCollapsed"></AddToCalendar>
              </transition>
              <div v-if="sidebarCollapsed" class="am-fs-sb__step">
                <div class="am-fs-sb__step-inner">
                  <div class="am-fs-sb__step-icon">
                    <span
                      :class="`am-icon-${stepsArray[stepIndex].sidebarData.icon}`"
                    ></span>
                  </div>
                  <div
                    class="am-fs-sb__step-checker"
                    :class="[
                      {
                        'am-fs-sb__step-checker-selected':
                          stepsArray[stepIndex].sidebarData.selected,
                      },
                      sidebarCollapseItemsClass,
                    ]"
                  >
                    <transition name="fade">
                      <span
                        v-if="stepsArray[stepIndex].sidebarData.finished"
                        class="am-icon-check"
                      ></span>
                    </transition>
                  </div>
                </div>
              </div>
            </div>
          </template>
          <template v-else>
            <!-- Skeleton -->
            <el-skeleton animated>
              <template #template>
                <div v-for="item in new Array(3)" :key="item">
                  <div class="el-skeleton-item-wrapper">
                    <el-skeleton-item variant="text" />
                  </div>
                </div>
              </template>
            </el-skeleton>
            <!-- /Skeleton -->
          </template>
        </div>
      </template>
      <template #support-info>
        <div ref="sidebarFooterRef" class="am-fs-sb__footer">
          <div
            v-if="
              (amSettings.company.email || amSettings.company.phone) &&
              (footerCustomizeOptions.heading ||
                footerCustomizeOptions.phone ||
                footerCustomizeOptions.email)
            "
            class="am-fs-sb__support"
          >
            <transition name="fade">
              <div
                v-if="!sidebarCollapsed && footerCustomizeOptions.heading"
                class="am-fs-sb__support-heading"
                :class="sidebarCollapseItemsClass"
              >
                {{ amLabels.get_in_touch }}
              </div>
            </transition>
            <a
              v-if="amSettings.company.phone && footerCustomizeOptions.phone"
              class="am-fs-sb__support-email"
              :aria-label="`Company phone: ${amSettings.company.phone}`"
              :href="`tel:${amSettings.company.phone}`"
            >
              <template v-if="!sidebarCollapsed">
                {{ amSettings.company.phone }}
              </template>
              <template v-else>
                <span class="am-icon-phone"></span>
              </template>
            </a>
            <a
              v-if="amSettings.company.email && footerCustomizeOptions.email"
              class="am-fs-sb__support-email"
              :aria-label="`Company email: ${amSettings.company.email}`"
              :href="`mailto:${amSettings.company.email}`"
            >
              <template v-if="!sidebarCollapsed">
                {{ amSettings.company.email }}
              </template>
              <template v-else>
                <span class="am-icon-email"></span>
              </template>
            </a>
          </div>
          <div
            class="am-fs-sb__menu"
            :class="sidebarCollapseItemsClass"
            @click="sidebarCollapsed = !sidebarCollapsed"
          >
            <Transition name="fade">
              <span v-if="!sidebarCollapsed" class="am-fs-sb__menu-text">
                {{ amLabels.collapse_menu }}
              </span>
            </Transition>
            <span
              :class="`am-icon-arrow-circle-${
                sidebarCollapsed ? 'left' : 'right'
              }`"
            ></span>
          </div>
        </div>
      </template>
    </SideBar>
    <MainContent>
      <template v-if="stepsArray[stepIndex] !== congratulationsStep" #header>
        <MainContentHeader
          :sidebar-visible="sidebarVisibility"
          :ready="ready"
        ></MainContentHeader>
      </template>
      <template #step>
        <component
          :is="stepsArray[stepIndex]"
          global-class="am-fs__main-content"
        ></component>
      </template>
      <template #footer>
        <MainContentFooter
          :second-button-show="
            stepsArray[stepIndex] === congratulationsStep &&
            amSettings.roles.customerCabinet.enabled &&
            amSettings.roles.customerCabinet.pageUrl !== null
          "
          :add-to-cart-button-show="
            useCartStep(store) && stepsArray[stepIndex] === cartStep
          "
          :back-to-cart-button-show="
            useCartStep(store) &&
            cart.length > 1 &&
            stepsArray[stepIndex] !== cartStep &&
            stepsArray[stepIndex] !== infoStep &&
            stepsArray[stepIndex] !== paymentStep &&
            stepsArray[stepIndex] !== congratulationsStep
          "
          :booked="booked"
          :loading="loading"
          :payment-gateway="paymentGateway"
          :customized-labels="footerLabels"
          :primary-footer-button-type="primFooterBtnType"
          :secondary-footer-button-type="secFooterBtnType"
          :add-to-cart-button-type="addToCartBtnType"
          :back-to-cart-button-type="backToCartBtnType"
          :back-to-cart-label="dedicatedStepLabel('cancel', 'cartStep')"
          :ready="ready"
          @add-to-cart="addToCart"
          @back-to-cart="backToCart"
        ></MainContentFooter>
      </template>
    </MainContent>
  </div>
  <template v-else>
    <div
      v-if="shortcodeData.show !== 'packages' && !shortcodeData.package"
      ref="ameliaContainer"
      class="am-no-services"
    >
      <img
        :src="
          baseUrls.wpAmeliaPluginURL + '/v3/src/assets/img/am-empty-booking.svg'
        "
        style="margin-top: 10px"
        :alt="amLabels.no_services_employees"
      />
      <div class="am-no-services-oops">{{ amLabels.oops }}</div>
      <div class="am-no-services-text">
        {{ amLabels.no_services_employees }}
      </div>
      <div class="am-no-services-text-2">
        <p>{{ amLabels.add_services_employees }}</p>
        <a href="https://wpamelia.com/services-and-categories/" rel="nofollow">
          {{ amLabels.add_services_url }}&nbsp;
        </a>
        <span style="font-size: 14px">{{ amLabels.and }}&nbsp;</span>
        <a href="https://wpamelia.com/employees/" rel="nofollow">
          {{ amLabels.add_employees_url }}
        </a>
      </div>
    </div>
    <div
      v-else
      ref="ameliaContainer"
      class="am-no-services"
      style="height: 100%"
    >
      <img
        :src="
          baseUrls.wpAmeliaPluginURL + '/v3/src/assets/img/am-empty-booking.svg'
        "
        style="margin-top: 10px"
        :alt="amLabels.no_package_services"
      />
      <div>{{ amLabels.oops }}</div>
      <div>{{ amLabels.no_package_services }}</div>
      <a href="https://wpamelia.com/services-and-categories/" rel="nofollow">
        {{ amLabels.add_services_url }}&nbsp;
      </a>
    </div>
  </template>
  <BackLink />
</template>

<script setup>
// * Form construction
import MainContent from '../../common/SbsFormConstruction/MainContent/MainContent.vue'
import MainContentHeader from '../../common/SbsFormConstruction/MainContent/parts/MainContentHeader.vue'
import MainContentFooter from '../../common/SbsFormConstruction/MainContent/parts/MainContentFooter'
import SideBar from '../../common/SbsFormConstruction/SideBar/SideBar.vue'
import BackLink from '../Parts/BackLink'

// * Step components
import InitStep from './InitStep/InitStep.vue'
import BringingAnyone from './BringingAnyone/BringingAnyone'
import Extras from './Extras/Extras.vue'
import PackageInfo from './PakagesStep/PackageInfoStep'
import DateTimeStep from './DateTimeStep/DateTimeStep.vue'
import PackageAppointmentsStep from './PakagesStep/PackageAppointmentsStep.vue'
import PackageAppointmentsListStep from './PakagesStep/PackageAppointmentsListStep.vue'
import CartStep from './CartStep/CartStep.vue'
import InfoStep from './InfoStep/InfoStep.vue'
import Congratulations from './Congratulations/Congratulations.vue'
import AddToCalendar from './Congratulations/AddToCalendar.vue'
import PaymentStep from './PaymentStep/PaymentStep.vue'
import PackagesStep from './PakagesStep/PackageStep'
import RecurringStep from './RecurringStep/RecurringStep'
import RecurringSummary from './RecurringStep/RecurringSummary'

// * import from Vue
import {
  ref,
  reactive,
  watch,
  provide,
  inject,
  markRaw,
  computed,
  onMounted,
  watchEffect,
  nextTick,
} from 'vue'
// * import from Vuex
import { useStore } from 'vuex'
// * import composable
import useRestore from '../../../assets/js/public/restore'
import { useBuildPackage } from '../../../assets/js/public/package.js'
import { defaultCustomizeSettings } from '../../../assets/js/common/defaultCustomize.js'
import useAction from '../../../assets/js/public/actions'
import { useRenderAction } from '../../../assets/js/public/renderActions.js'
import { useColorTransparency } from '../../../assets/js/common/colorManipulation'
import {
  usePrepaidPrice,
  useCapacity,
  useCheckingIfAllNotFree,
} from '../../../assets/js/common/appointments'
import {
  useCart,
  useCartStep,
  useInitCartItem,
  useCartHasItems,
  useInitSelection,
  useAddToCart,
  useGoToCartStep,
} from '../../../assets/js/public/cart'

let formDialogVisibility = inject('formDialogVisibility', ref(true))

// * Plugin Licence
let licence = inject('licence')

// * Component reference
let ameliaContainer = ref(null)
// * Plugin wrapper width
let containerWidth = ref()
provide('containerWidth', containerWidth)

let empty = ref(false)

// * window resize listener
window.addEventListener('resize', resize)
// * resize function
function resize() {
  if (ameliaContainer.value) {
    containerWidth.value = ameliaContainer.value.offsetWidth
  }
}

onMounted(() => {
  store.commit('shortcodeParams/setForm', 'stepForm')

  document
    .getElementById('amelia-v2-booking-' + shortcodeData.value.counter)
    .classList.add(
      'amelia-v2-booking-' + shortcodeData.value.counter + '-loaded'
    )

  useAction(store, {}, 'ViewContent', 'appointment', null, null)

  nextTick(() => {
    containerWidth.value = ameliaContainer.value.offsetWidth
  })

  useAction(
    store,
    { containerWidth },
    'ContainerWidth',
    'appointment',
    null,
    null
  )
})

// * Root Settings
const amSettings = inject('settings')

// * Customize
const amCustomize = (amSettings.customizedData && amSettings.customizedData.sbsNew)
  ? amSettings.customizedData.sbsNew
  : defaultCustomizeSettings.sbsNew
if (amCustomize) {
  provide('amCustomize', amCustomize)
}

let footerCustomizeOptions = computed(() => {
  let obj = {
    heading: true,
    phone: true,
    email: true,
  }

  if ('supportHeading' in amCustomize.sidebar.options) {
    obj.heading = amCustomize.sidebar.options.supportHeading.visibility
  }

  if ('companyPhone' in amCustomize.sidebar.options) {
    obj.phone = amCustomize.sidebar.options.companyPhone.visibility
  }

  if ('companyEmail' in amCustomize.sidebar.options) {
    obj.email = amCustomize.sidebar.options.companyEmail.visibility
  }

  return obj
})

// * Fonts
const amFonts = ref(
  amSettings.customizedData
    ? amSettings.customizedData.fonts
    : defaultCustomizeSettings.fonts
)
provide('amFonts', amFonts)

// * Dialog width
let dialogWrapperWidth = inject('dialogWrapperWidth', ref(''))

// * Form Sidebar Collapse
let sidebarCollapsed = ref(false)
provide('sidebarCollapsed', sidebarCollapsed)

let sidebarCollapseItemsClass = ref('')

watch(sidebarCollapsed, (current) => {
  if (current) {
    setTimeout(() => {
      sidebarCollapseItemsClass.value = 'am-collapsed'
      dialogWrapperWidth.value = '592px'
    }, 1000)
  } else {
    sidebarCollapseItemsClass.value = ''
    dialogWrapperWidth.value = '760px'
  }
})

let sidebarFooterRef = ref(null)
let sidebarFooterHeight = ref(0)

// * Form Sidebar Visibility
let sidebarVisibility = ref(
  amCustomize.sidebar ? amCustomize.sidebar.options.self.visibility : true
)

// * Root Urls
const baseUrls = inject('baseUrls')

// * Define store
const store = useStore()

let isRtl = computed(() => store.getters['getIsRtl'])

let ready = computed(() => store.getters['entities/getReady'])

let isRestored = ref(false)

watch(ready, (current) => {
  if (current) {
    nextTick(() => {
      if (sidebarFooterRef.value) {
        setTimeout(() => {
          sidebarFooterHeight.value = sidebarFooterRef.value.offsetHeight
        }, 200)
      }
    })

    setShortcodeParams()

    let preselected = store.getters['entities/getPreselected']
    empty.value =
      store.getters['entities/getServices'].length === 0 ||
      store.getters['entities/getEmployees'].length === 0 ||
      (store.getters['entities/getPackages'].length === 0 &&
        (shortcodeData.value.show === 'packages' ||
          preselected.package.length > 0))

    let restore = useRestore(store, shortcodeData.value)

    if (restore) {
      stepsArray.value.splice(0, stepsArray.value.length)

      sidebarSteps.value.splice(0, sidebarSteps.value.length)

      stepIndex.value = 0

      restore.steps.forEach((key) => {
        switch (key) {
          case 'packageStep':
            stepsArray.value.push(packagesStep)
            break

          case 'bringingAnyone':
            stepsArray.value.push(bringingAnyone)
            break

          case 'initStep':
            stepsArray.value.push(initStep)
            break

          case 'packageInfoStep':
            stepsArray.value.push(packageInfoStep)
            break

          case 'packageAppointmentsStep':
            stepsArray.value.push(packageAppointmentsStep)
            break

          case 'packageAppointmentsListStep':
            stepsArray.value.push(packageAppointmentsListStep)
            break

          case 'extrasStep':
            stepsArray.value.push(extras)
            break

          case 'dateTimeStep':
            stepsArray.value.push(dateTimeStep)
            break

          case 'recurringStep':
            stepsArray.value.push(recurringStep)
            break

          case 'recurringSummary':
            stepsArray.value.push(recurringSummary)
            break

          case 'cartStep':
            stepsArray.value.push(cartStep)
            break

          case 'infoStep':
            stepsArray.value.push(infoStep)
            break

          case 'paymentStep':
            stepsArray.value.push(paymentStep)
            break

          case 'congratulations':
            stepsArray.value.push(congratulationsStep)
            break
        }

        let sideBarItem = restore.sidebar.find((i) => i.key === key)

        sidebarDataUpdate()

        if (typeof sideBarItem !== 'undefined') {
          if (sideBarItem.data) {
            sideBarItem.data.forEach((i) => {
              sidebarDataCollector({
                reference: i.reference,
                position: i.position,
                value: i.value,
              })
            })
          }
        }

        stepIndex.value++
      })

      store.commit('booking/setLoading', false)

      let index = -1

      if (restore.result === 'success') {
        index = stepsArray.value.length - 1
      } else if (restore.result === 'error' || restore.result === 'canceled') {
        index = stepsArray.value.length - 2
      }

      for (let i = 0; i <= index; i++) {
        stepsArray.value[i].finished = true
      }

      for (let i = 0; i <= index - 1; i++) {
        sidebarSteps.value[i].finished = true
        sidebarSteps.value[i].selected = false
      }
      if (restore.result === 'error' || restore.result === 'canceled') {
        sidebarSteps.value[index].finished = false
        sidebarSteps.value[index].selected = true
      }

      isRestored.value = true
      stepIndex.value = index
    }
  }
})

const shortcodeData = inject('shortcodeData')

store.commit('entities/setPreselected', shortcodeData.value)

// * Get Entities from server
store.dispatch(
  'entities/getEntities',
  {
    types: [
      'employees',
      'categories',
      'locations',
      'packages',
      'entitiesRelations',
      'customFields',
      'taxes',
    ],
    licence: licence,
    loadEntities: shortcodeData.value.hasApiCall || shortcodeData.value.in_dialog,
    showHidden: false,
    isPanel: false,
  }
)

// * Form Component Collection
const initStep = markRaw(InitStep)
const extras = markRaw(Extras)
const packageInfoStep = markRaw(PackageInfo)
const recurringStep = markRaw(RecurringStep)
const recurringSummary = markRaw(RecurringSummary)
const dateTimeStep = markRaw(DateTimeStep)
const packageAppointmentsStep = markRaw(PackageAppointmentsStep)
const packageAppointmentsListStep = markRaw(PackageAppointmentsListStep)
const congratulationsStep = markRaw(Congratulations)
const cartStep = markRaw(CartStep)
const infoStep = markRaw(InfoStep)
const paymentStep = markRaw(PaymentStep)
const packagesStep = markRaw(PackagesStep)
const bringingAnyone = markRaw(BringingAnyone)

// * Array of step components
const stepsArray = ref(
  useCartStep(store)
    ? [initStep, dateTimeStep, cartStep, infoStep, congratulationsStep]
    : [initStep, dateTimeStep, infoStep, congratulationsStep]
)

provide('stepsArray', stepsArray)

// * labels
const labels = inject('labels')

// * local language short code
const localLanguage = inject('localLanguage')

// * if local lang is in settings lang
let langDetection = computed(() =>
  amSettings.general.usedLanguages.includes(localLanguage.value)
)

let cart = useCart(store)

// * Computed labels
let amLabels = computed(() => {
  let computedLabels = reactive({ ...labels })

  if (amSettings.customizedData && amSettings.customizedData.sbsNew) {
    Object.keys(amSettings.customizedData.sbsNew).forEach((stepKey) => {
      if (
        stepKey !== 'colors' &&
        amSettings.customizedData.sbsNew[stepKey].translations
      ) {
        let customizedLabels =
          amSettings.customizedData.sbsNew[stepKey].translations
        Object.keys(customizedLabels).forEach((labelKey) => {
          if (
            customizedLabels[labelKey][localLanguage.value] &&
            langDetection.value
          ) {
            computedLabels[labelKey] =
              customizedLabels[labelKey][localLanguage.value]
          } else if (customizedLabels[labelKey].default) {
            computedLabels[labelKey] = customizedLabels[labelKey].default
          }
        })
      }
    })
  }
  return computedLabels
})

provide('amLabels', amLabels)

let footerLabels = computed(() => {
  let customLabels = {}
  if (amSettings.customizedData && amSettings.customizedData.sbsNew) {
    let customizedLabels = amSettings.customizedData.sbsNew[
      stepsArray.value[stepIndex.value].key
    ]
      ? amSettings.customizedData.sbsNew[stepsArray.value[stepIndex.value].key]
          .translations
      : null
    if (amSettings.customizedData && customizedLabels) {
      Object.keys(customizedLabels).forEach((labelKey) => {
        if (
          customizedLabels[labelKey][localLanguage.value] &&
          langDetection.value
        ) {
          customLabels[labelKey] =
            customizedLabels[labelKey][localLanguage.value]
        } else if (customizedLabels[labelKey].default) {
          customLabels[labelKey] = customizedLabels[labelKey].default
        }
      })
    }
  }

  return Object.keys(customLabels).length ? customLabels : labels
})

let primFooterBtnType = computed(() => {
  let btnType = 'filled'
  if (
    amSettings.customizedData &&
    amSettings.customizedData.sbsNew &&
    amSettings.customizedData.sbsNew[stepsArray.value[stepIndex.value].key]
  ) {
    btnType =
      amSettings.customizedData.sbsNew[stepsArray.value[stepIndex.value].key]
        .options.primaryFooterButton.buttonType
  }

  return btnType
})

provide('primFooterBtnType', primFooterBtnType)

provide('primDescBtnType', primFooterBtnType)

let secFooterBtnType = computed(() => {
  let btnType = 'text'
  if (
    amSettings.customizedData &&
    amSettings.customizedData.sbsNew &&
    amSettings.customizedData.sbsNew[stepsArray.value[stepIndex.value].key] &&
    amSettings.customizedData.sbsNew[stepsArray.value[stepIndex.value].key]
      .options.secondaryFooterButton
  ) {
    btnType =
      amSettings.customizedData.sbsNew[stepsArray.value[stepIndex.value].key]
        .options.secondaryFooterButton.buttonType
  }

  return btnType
})

let addToCartBtnType = computed(() => {
  if (
    amSettings.customizedData &&
    amSettings.customizedData.sbsNew &&
    amSettings.customizedData.sbsNew['cartStep']
  ) {
    return amSettings.customizedData.sbsNew['cartStep'].options['addToCart']
      .buttonType
  }

  return 'text'
})

let backToCartBtnType = computed(() => {
  if (
    amSettings.customizedData &&
    amSettings.customizedData.sbsNew &&
    amSettings.customizedData.sbsNew['cartStep']
  ) {
    return amSettings.customizedData.sbsNew['cartStep'].options['backToCart']
      .buttonType
  }

  return 'text'
})

function dedicatedStepLabel(labelKey, stepKey) {
  let customLabel = ''
  if (amSettings.customizedData && amSettings.customizedData.sbsNew) {
    let customizedLabels = amSettings.customizedData.sbsNew[stepKey]
      ? amSettings.customizedData.sbsNew[stepKey].translations
      : null
    if (
      amSettings.customizedData &&
      customizedLabels &&
      customizedLabels[labelKey]
    ) {
      if (
        customLabel === '' &&
        customizedLabels[labelKey][localLanguage.value] &&
        langDetection.value
      ) {
        customLabel = customizedLabels[labelKey][localLanguage.value]
      } else if (customLabel === '' && customizedLabels[labelKey].default) {
        customLabel = customizedLabels[labelKey].default
      }
    }
  }

  return customLabel ? customLabel : labels[labelKey]
}

let bringingAnyoneOptions = computed(() => {
  return useCapacity(
    store.getters['entities/getEmployeeServices'](
      store.getters['booking/getSelection']
    )
  )
})

function setShortcodeParams() {
  let preselected = store.getters['entities/getPreselected']
  if (preselected.category.length === 1) {
    store.commit('booking/setCategoryId', parseInt(preselected.category[0]))
  }
  if (preselected.service.length === 1) {
    store.commit('booking/setServiceId', parseInt(preselected.service[0]))
    let service = store.getters['entities/getService'](
      parseInt(preselected.service[0])
    )
    store.commit(
      'booking/setCategoryId',
      service ? parseInt(service.categoryId) : null
    )
  }
  if (preselected.employee.length === 1) {
    store.commit('booking/setEmployeeId', parseInt(preselected.employee[0]))
  }
  if (preselected.location.length === 1) {
    store.commit('booking/setLocationId', parseInt(preselected.location[0]))
  }
  if (preselected.package.length === 1) {
    store.commit('booking/setPackageId', parseInt(preselected.package[0]))
  }

  if (preselected.package.length === 1) {
    stepsArray.value.splice(0, 1, packageInfoStep)
    sidebarSteps.value.splice(0, 1)
    sidebarDataUpdate()
    let selectedPackage = store.getters['entities/filteredPackages'](
      store.getters['booking/getSelection']
    )[0]
    if (selectedPackage) {
      goToPackageStep(selectedPackage, false)
    }
  } else if (
    preselected.show === 'packages' ||
    preselected.package.length > 1
  ) {
    stepsArray.value.splice(0, 1, packagesStep)
    sidebarSteps.value.splice(0, 1)
    store.commit('booking/setBookableType', 'package')
    sidebarDataUpdate()
  } else {
    changeInitStepDataService()
    store.commit('booking/setBookableType', 'appointment')
    let employeeOptions =
      store.getters['entities/filteredEmployees'](
        store.getters['booking/getSelection']
      ).length <= 1
    let employeeVisibility = !amCustomize.initStep.options.employee.visibility
    let locationOptions =
      store.getters['entities/filteredLocations'](
        store.getters['booking/getSelection']
      ).length <= 1
    let locationVisibility = !amCustomize.initStep.options.location.visibility

    if (
      preselected.service.length === 1 &&
      (preselected.employee.length === 1 ||
        employeeOptions ||
        employeeVisibility) &&
      (preselected.location.length === 1 ||
        locationOptions ||
        locationVisibility)
    ) {
      if (bringingAnyoneOptions.value.availability) {
        stepsArray.value.splice(0, 1, bringingAnyone)
        sidebarSteps.value.splice(0, 1)
      } else {
        stepsArray.value.splice(0, 1)
        sidebarSteps.value.splice(0, 1)
      }
      sidebarDataUpdate()
    }
  }
}

function stepChanger(steps, stepsNamesToRemove, stepsToAdd, startIndex) {
  let removeIndexes = steps.value
    .map((item, index) =>
      stepsNamesToRemove.includes(item.name) ? index : null
    )
    .filter((item) => item !== null)
    .reverse()

  removeIndexes.forEach((item) => {
    steps.value.splice(item, 1)
  })

  stepsToAdd.forEach((item) => {
    if (steps.value.indexOf(item) === -1) {
      steps.value.splice(startIndex + 1, 0, item)
    }
  })
}

provide('goToPackageStep', { goToPackageStep })

function goToPackageStep(pack, goToNextStep = true) {
  store.commit('booking/setPackageId', pack.id)
  store.commit('booking/setBookableType', 'package')
  store.commit('booking/setMultipleAppointments', useBuildPackage(0, pack))
  store.commit('booking/setMultipleAppointmentsIndex', 0)

  let bookingCount = pack.bookable.reduce(
    (partialSum, book) => partialSum + book.maximumScheduled,
    0
  )

  let removeSteps = []
  let addSteps = []

  if (stepsArray.value[0] !== extras) {
    removeSteps.push('ExtrasStep')
  }

  if (stepsArray.value[0] !== dateTimeStep) {
    removeSteps.push('DateTimeStep')
  }

  if (stepsArray.value[0] !== cartStep) {
    removeSteps.push('CartStep')
  }

  if (bookingCount > 0) {
    addSteps = addSteps.concat([
      packageAppointmentsListStep,
      packageAppointmentsStep,
      packageInfoStep,
    ])
  } else {
    addSteps.push(packageInfoStep)
  }

  stepChanger(stepsArray, removeSteps, addSteps, stepIndex.value)

  stepChanger(sidebarSteps, removeSteps, [], stepIndex.value)

  sidebarDataUpdate()

  if (goToNextStep) {
    nextStep()
  }
}

function removePackageStep() {
  store.commit('booking/setBookableType', 'appointment')

  store.commit('booking/setMultipleAppointments', [
    {
      packageId: null,
      serviceId: null,
      index: 0,
      services: {},
    },
  ])

  store.commit('booking/setPackageId', null)

  store.commit('booking/setMultipleAppointmentsIndex', 0)

  useInitCartItem(store)

  let addSteps = []

  if (stepsArray.value[0] !== dateTimeStep) {
    if (useCartStep(store)) {
      addSteps.push(cartStep)
    }

    addSteps.push(dateTimeStep)
  }

  if (
    stepsArray.value[0] !== extras &&
    selectedServiceExtras.value &&
    selectedServiceExtras.value.length
  ) {
    addSteps.push(extras)
  }

  stepChanger(
    stepsArray,
    [
      'PackageInfoStep',
      'PackageAppointmentsStep',
      'PackageAppointmentsListStep',
    ],
    addSteps,
    stepIndex.value - 1
  )

  stepChanger(
    sidebarSteps,
    [
      'PackageInfoStep',
      'PackageAppointmentsStep',
      'PackageAppointmentsListStep',
    ],
    [],
    stepIndex.value
  )

  sidebarDataUpdate()
}

provide('goToRecurringStep', { goToRecurringStep })

provide('removeRecurringStep', { removeRecurringStep })

function goToRecurringStep() {
  if (useCartStep(store)) {
    removeCartStep()
  }

  let startIndex = 0

  for (let i = 0; i < stepsArray.value.length; i++) {
    if (stepsArray.value[i].name === 'DateTimeStep') {
      startIndex = i

      break
    }
  }

  stepsArray.value.splice(startIndex + 1, 0, recurringStep)
  stepsArray.value.splice(startIndex + 2, 0, recurringSummary)

  sidebarDataUpdate()

  nextStep()
}

function removeRecurringStep() {
  for (let i = stepsArray.value.length - 1; i >= 0; i--) {
    if (
      stepsArray.value[i].name === 'RecurringStep' ||
      stepsArray.value[i].name === 'RecurringSummary'
    ) {
      stepsArray.value.splice(i + 1, 1)
    }
  }

  if (useCartStep(store)) {
    addCartStep(stepIndex.value)
  }

  sidebarDataUpdate()
}

provide('addPaymentsStep', { addPaymentsStep })

provide('removePaymentsStep', { removePaymentsStep })

function addPaymentsStep() {
  stepsArray.value.splice(stepsArray.value.length - 1, 0, paymentStep)

  sidebarDataUpdate()
}

function removePaymentsStep() {
  let removeSteps = ['PaymentStep']

  stepChanger(stepsArray, removeSteps, [], stepIndex.value)

  stepChanger(sidebarSteps, removeSteps, [], stepIndex.value)
}

function addCartStep(index) {
  stepChanger(stepsArray, [], [cartStep], index)

  stepChanger(sidebarSteps, [], [], index)
}

function removeCartStep() {
  stepChanger(stepsArray, ['CartStep'], [], stepIndex.value)

  stepChanger(sidebarSteps, ['CartStep'], [], stepIndex.value)
}

/**
 * Detect if Selected Service has Extras
 * @type {any}
 */
let selectedServiceExtras = computed(() => {
  let service = store.getters['entities/getService'](
    store.getters['booking/getServiceId']
  )

  return service ? service.extras : []
})

/**
 * Add or Remove steps from Steps Array
 */
function changeInitStepDataService() {
  if (
    selectedServiceExtras.value.length &&
    !stepsArray.value.find((step) => step.name === 'ExtrasStep')
  ) {
    stepsArray.value.splice(stepIndex.value + 1, 0, extras)

    sidebarDataUpdate()
  }

  if (
    sidebarSteps.value.find((step) => step.name === 'ExtrasStep') &&
    !Object.keys(selectedServiceExtras.value).length
  ) {
    stepsArray.value.splice(1, 1)
    sidebarSteps.value.splice(1, 1)
  }

  useInitCartItem(store)
}

provide('initDataChanges', {
  changeInitStepDataService,
})

// * Step index
const stepIndex = ref(0)
// * StepIndex provide
provide('stepIndex', stepIndex)

// * Monitoring step index for step selection
watch(stepIndex, (currStepIndex, prevStepIndex) => {
  if (currStepIndex < sidebarSteps.value.length) {
    sidebarSteps.value[prevStepIndex].selected = false
    sidebarSteps.value[currStepIndex].selected = true
  }

  if (currStepIndex === sidebarSteps.value.length) {
    sidebarSteps.value[prevStepIndex].selected = false
  }
})

let goBackToPackageBooking = ref(false)
provide('goBackToPackageBooking', goBackToPackageBooking)

/**
 * Move to previous Form Step
 */
function previousStep() {
  footerBtnDisabledUpdater(false)

  if (!navigateInsideStep.value) {
    if (stepsArray.value[stepIndex.value].name === packageInfoStep.name) {
      removePackageStep()
    }

    if (stepsArray.value[stepIndex.value].name === recurringStep.name) {
      stepsArray.value.splice(stepIndex.value, 2)
      sidebarSteps.value.splice(stepIndex.value, 2)

      if (useCartStep(store)) {
        stepsArray.value.splice(stepIndex.value, 0, cartStep)

        stepChanger(sidebarSteps, [], [], stepIndex.value)

        sidebarDataUpdate()
      }
    }

    if (
      stepsArray.value[stepIndex.value].name ===
      packageAppointmentsListStep.name
    ) {
      goBackToPackageBooking.value = true
    }

    stepIndex.value = stepIndex.value - 1
  }

  headerButtonPreviousClicked.value = !headerButtonPreviousClicked.value
}

/**
 * Move to next Form Step
 */
function nextStep() {
  if (!navigateInsideStep.value) {
    sidebarSteps.value[stepIndex.value].finished = true
    stepIndex.value = stepIndex.value + 1
  }
}

// * Footer states
let loading = computed(() => store.getters['booking/getLoading'])
let booked = computed(() => store.getters['booking/getBooked'])
let paymentGateway = computed(() => store.getters['booking/getPaymentGateway'])

// * Footer btn flag
let footerButtonClicked = ref(false)
let footerBtnDisabled = ref(false)

let headerButtonPreviousClicked = ref(false)

/**
 * Footer btn clicked
 */
function footerButtonClick() {
  footerButtonClicked.value = true
}

/**
 * Footer btn reset
 */
function footerButtonReset() {
  footerButtonClicked.value = false
}

/**
 * Header btn previous clicked
 */
function headerButtonPreviousClick() {
  headerButtonPreviousClicked.value = true
}

/**
 * Header btn previous reset
 */
function headerButtonPreviousReset() {
  headerButtonPreviousClicked.value = false
}

function footerBtnDisabledUpdater(data) {
  footerBtnDisabled.value = data
}

function secondButtonClick() {
  if (booked.value) {
    if (booked.value.customerCabinetUrl) {
      window.location.href = booked.value.customerCabinetUrl
    } else {
      window.location.href = amSettings.roles.customerCabinet.pageUrl
    }
  }
}

provide('secondButton', {
  secondButtonClick,
})

let navigateInsideStep = ref(false)

provide('changingStepsFunctions', {
  nextStep,
  previousStep,
  footerButtonClick,
  footerButtonReset,
  footerBtnDisabledUpdater,
  headerButtonPreviousClick,
  headerButtonPreviousReset,
  footerBtnDisabled,
  footerButtonClicked,
  headerButtonPreviousClicked,
  navigateInsideStep,
})

// * Array of Sidebar steps
const sidebarSteps = ref([])
provide('sidebarSteps', sidebarSteps)

let keepPaymentStep = computed(() =>
  useCart(store).length ? usePrepaidPrice(store) !== 0 : useCheckingIfAllNotFree(store)
)

watchEffect(() => {
  if (!isRestored.value && !keepPaymentStep.value) {
    removePaymentsStep()
  } else if (!isRestored.value) {
    if (stepsArray.value.indexOf(paymentStep) === -1) {
      addPaymentsStep()
    }
  }
})

/**
 * Collecting and rearranging selected data in form sidebar based on item position in form
 * @param data
 */
function sidebarDataCollector(data) {
  // Determines are selected data already exists
  if (
    sidebarSteps.value[stepIndex.value].stepSelectedData.filter(
      (item) => item.reference === data.reference
    ).length
  ) {
    sidebarSteps.value[stepIndex.value].stepSelectedData.forEach(
      (item, index, array) => {
        // Handles changing value of existing data
        if (
          item.reference === data.reference &&
          data.value &&
          data.value !== item.value
        ) {
          item.value = data.value
        }

        // Removes un-selected form data from sidebar array
        if (item.reference === data.reference && !data.value) {
          array.splice(index, 1)
        }
      }
    )
  } else {
    if (data.value) {
      sidebarSteps.value[stepIndex.value].stepSelectedData.push(data)
    }
  }

  // Rearranges data in sidebar based on item position in the form
  sidebarSteps.value[stepIndex.value].stepSelectedData.sort((a, b) => {
    return a.position - b.position
  })
}

/**
 * Function that update SideBar Data Array when some component are dynamically added
 */
function sidebarDataUpdate() {
  stepsArray.value.forEach((item, index) => {
    if (item.name === 'CongratulationsStep') {
      return
    }
    if (
      !sidebarSteps.value.find(
        (block) => block.labelKey === item.sidebarData.label
      )
    ) {
      let labelKey = item.sidebarData.label
      let step = {
        name: item.name,
        key: item.key,
        label: amLabels.value[labelKey],
        labelKey: labelKey,
        icon: item.sidebarData.icon,
        stepSelectedData: [],
        finished: false,
        selected: index === stepIndex.value,
      }
      sidebarSteps.value.splice(index, 0, step)
    }
  })
}
provide('sidebarStepsFunctions', {
  sidebarDataCollector,
})

// * Cart
function addToCart() {
  sidebarSteps.value.forEach((item) => {
    item.finished = false
    item.selected = false
  })

  stepsArray.value.forEach((item) => {
    item.finished = false
    item.selected = false
  })

  stepIndex.value = 0

  useInitSelection(store, true)

  useAddToCart(store)

  useInitCartItem(store)
}

function backToCart() {
  let currentCartItem = store.getters['booking/getCurrentCartItem']

  let items = store.getters['booking/getAllMultipleAppointments']

  if (currentCartItem) {
    store.commit('booking/setCartItem', currentCartItem)

    store.commit('booking/setCartItemIndex', items.length - 1)

    store.commit('booking/setCurrentCartItem', null)
  } else {
    items.pop()

    store.commit('booking/setCartItemIndex', items.length - 1)

    store.commit('booking/setServiceId', items[items.length - 1].serviceId)

    store.commit(
      'booking/setEmployeeId',
      items[items.length - 1].services[items[items.length - 1].serviceId]
        .providerId
    )

    store.commit(
      'booking/setLocationId',
      items[items.length - 1].services[items[items.length - 1].serviceId]
        .locationId
    )
  }

  useGoToCartStep(stepsArray, stepIndex)
}

// * Colors block
let amColors = computed(() => {
  return (amSettings.customizedData && amSettings.customizedData.sbsNew)
    ? amSettings.customizedData.sbsNew.colors
    : defaultCustomizeSettings.sbsNew.colors
})
provide('amColors', amColors)

let cssVars = computed(() => {
  return {
    '--am-c-primary': amColors.value.colorPrimary,
    '--am-c-success': amColors.value.colorSuccess,
    '--am-c-error': amColors.value.colorError,
    '--am-c-warning': amColors.value.colorWarning,
    '--am-c-main-bgr': amColors.value.colorMainBgr,
    '--am-c-main-heading-text': amColors.value.colorMainHeadingText,
    '--am-c-main-text': amColors.value.colorMainText,
    '--am-c-sb-bgr': amColors.value.colorSbBgr,
    '--am-c-sb-text': amColors.value.colorSbText,
    '--am-c-inp-bgr': amColors.value.colorInpBgr,
    '--am-c-inp-border': amColors.value.colorInpBorder,
    '--am-c-inp-text': amColors.value.colorInpText,
    '--am-c-inp-placeholder': amColors.value.colorInpPlaceHolder,
    '--am-c-drop-bgr': amColors.value.colorDropBgr,
    '--am-c-drop-text': amColors.value.colorDropText,
    '--am-c-btn-prim': amColors.value.colorBtnPrim,
    '--am-c-btn-prim-text': amColors.value.colorBtnPrimText,
    '--am-c-btn-sec': amColors.value.colorBtnSec,
    '--am-c-btn-sec-text': amColors.value.colorBtnSecText,
    '--am-c-skeleton-op20': useColorTransparency(
      amColors.value.colorMainText,
      0.2
    ),
    '--am-c-skeleton-op60': useColorTransparency(
      amColors.value.colorMainText,
      0.6
    ),
    '--am-c-skeleton-sb-op20': useColorTransparency(
      amColors.value.colorSbText,
      0.2
    ),
    '--am-c-skeleton-sb-op60': useColorTransparency(
      amColors.value.colorSbText,
      0.6
    ),
    '--am-font-family': amFonts.value.fontFamily,

    // css properties
    // -mw- max width
    // -brad- border-radius
    '--am-mw-main': sidebarVisibility.value
      ? sidebarCollapsed.value
        ? '592px'
        : '760px'
      : '520px',
    '--am-brad-main': sidebarVisibility.value ? (isRtl.value ? '0.5rem 0 0 0.5rem' : '0 0.5rem 0.5rem 0') : '0.5rem',
  }
})

function activateCustomFontStyles() {
  let head = document.head || document.getElementsByTagName('head')[0]
  if (head.querySelector('#amCustomFont')) {
    head.querySelector('#amCustomFont').remove()
  }

  let css = `@font-face {font-family: '${amFonts.value.fontFamily}'; src: url(${amFonts.value.fontUrl});}`
  let style = document.createElement('style')
  head.appendChild(style)
  style.setAttribute('type', 'text/css')
  style.setAttribute('id', 'amCustomFont')
  style.appendChild(document.createTextNode(css))
}

if (amFonts.value.customFontSelected) activateCustomFontStyles()

// * Design Properties
let amDesignProperties = computed(() => {
  return {
    colorInputBorderRadius: '6px',
  }
})
provide('amDesignProperties', amDesignProperties)

onMounted(() => {
  useRenderAction('renderForm', {
    ameliaContainer,
    containerWidth,
    empty,
    amCustomize,
    amFonts,
    sidebarCollapsed,
    sidebarCollapseItemsClass,
    sidebarFooterRef,
    sidebarFooterHeight,
    sidebarVisibility,
  })
})
</script>

<style lang="scss">
@import '../../../assets/scss/public/overides/overides';
@import '../../../assets/scss/common/reset/reset';
@import '../../../assets/scss/common/icon-fonts/style';
@import '../../../assets/scss/common/skeleton/skeleton.scss';

:root {
  // Colors
  // shortcuts
  // -c-    color
  // -bgr-  background
  // -prim- primary
  // -sec-  secondary
  // primitive colors
  --am-c-primary: #{$blue-1000};
  --am-c-success: #{$green-1000};
  --am-c-error: #{$red-900};
  --am-c-warning: #{$yellow-1000};
  // main container colors - right part of the form
  --am-c-main-bgr: #{$am-white};
  --am-c-main-heading-text: #{$shade-800};
  --am-c-main-text: #{$shade-900};
  // sidebar container colors - left part of the form
  --am-c-sb-bgr: #17295a;
  --am-c-sb-text: #{$am-white};
  // input global colors - usage input, textarea, checkbox, radio button, select input, adv select input
  --am-c-inp-bgr: #{$am-white};
  --am-c-inp-border: #{$shade-250};
  --am-c-inp-text: #{$shade-900};
  --am-c-inp-placeholder: #{$shade-500};
  // dropdown global colors - usage select dropdown, adv select dropdown
  --am-c-drop-bgr: #{$am-white};
  --am-c-drop-text: #{$shade-1000};
  // button global colors
  --am-c-btn-prim: #{$blue-900};
  --am-c-btn-prim-text: #{$am-white};
  --am-c-btn-sec: #{$am-white};
  --am-c-btn-sec-text: #{$shade-900};

  // Properties
  // shortcuts
  // -h- height
  // -fs- font size
  // -rad- border radius
  --am-h-inp: 40px;
  --am-fs-inp: 15px;
  --am-rad-inp: 6px;
  --am-fs-label: 15px;
  --am-fs-btn: 15px;

  // Font
  --am-font-family: 'Amelia Roboto', sans-serif;
}

// am -- amelia
// fs -- form steps
// sb -- sidebar
.amelia-v2-booking {
  background-color: transparent;

  #amelia-container {
    background-color: transparent;
    * {
      font-family: var(--am-font-family);
      font-style: initial;
      box-sizing: border-box;
      word-break: break-word;
    }

    &.am-fs {
      // Container Wrapper
      &__wrapper {
        display: flex;
        justify-content: center;
        max-width: var(--am-mw-main);
        width: 100%;
        height: 560px;
        margin: 100px auto;
        border-radius: 8px;
        box-shadow: 0 30px 40px rgba(0, 0, 0, 0.12);
        transition: max-width 0.3s ease-in-out;

        &.am-collapsed {
          transition-delay: 1s;
        }

        .el-form {
          &-item {
            display: block;
            font-family: var(--am-font-family);
            font-size: var(--am-fs-label);
            margin-bottom: 24px;

            &__label {
              flex: 0 0 auto;
              text-align: left;
              font-size: var(--am-fs-label);
              line-height: 1.3;
              color: var(--am-c-main-text);
              box-sizing: border-box;
              margin: 0;

              &:before {
                color: var(--am-c-error);
              }
            }

            &__content {
              display: flex;
              flex-wrap: wrap;
              align-items: center;
              flex: 1;
              position: relative;
              font-size: var(--am-fs-inp);
              min-width: 0;
              color: var(--am-c-main-text);
            }

            &__error {
              font-size: 12px;
              color: var(--am-c-error);
              padding-top: 4px;
            }
          }
        }

        * {
          font-family: var(--am-font-family);
          box-sizing: border-box;
        }
      }
    }
  }

  .am-no-services {
    box-shadow: 0 30px 40px rgba(0, 0, 0, 0.12);
    margin: 100px auto;
    text-align: center;
    padding: 56px;
    max-width: 760px;
    height: 460px;
    width: 100%;

    p {
      margin-bottom: 8px;
      padding: 0;
    }

    &-oops {
      font-size: 24px;
      line-height: 1.5;
      font-weight: 400;
      color: #354052;
      margin: 0;
    }

    &-text {
      font-size: 16px;
      line-height: 1.5;
      font-weight: 400;
      color: #354052;
      &-2 {
        color: #354052;
        font-size: 14px;
      }
    }

    a {
      font-size: 14px;
    }

    * {
      font-family: 'Amelia Roboto', sans-serif;
      box-sizing: border-box;
    }
  }
}
</style>
© 2026 GrazzMean-Shell