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 : Category.vue
<template>
  <div class="am-wrap" ref="categoryContainer">

    <div id="am-category" v-if="!empty">

      <!-- Services -->
      <transition name="fade" v-if="category">
        <div v-show="fetchedCategory && showCategory && !loadingCacheCategoryData">
          <!-- Back button & Category Name -->
          <div class="am-category-headline">
            <span
              v-if="$root.shortcodeData.enabled === false || $root.shortcodeData.hasCategoryShortcode.length === 0"
              :style="{color: globalCustomization.globalColors.primaryColor}"
              @click="backToCatalog" class="am-back"
            >
              <i class="el-icon-arrow-left"></i> {{ formLabels.back.value || $root.labels.back }}
            </span>
            <h3 :style="{color: globalCustomization.globalColors.primaryColor, fontWeight: 500}">
              {{ category.name }}
            </h3>
          </div>

          <!-- Service Item -->
          <el-row :gutter="24" v-if="options.entities.services" type="flex" class="am-category-service-wrapper">
            <el-col
              v-for="(service, index) in getListedItems()"
              v-if="('type' in service) || getServiceProviders(service.id).length > 0"
              :key="index"
              :lg="columnsLg"
              :md="12"
              :sm="12"
              class="am-category-service-inner"
            >
              <!-- Service -->
              <div class="am-category-service">
                <!-- View More -->
                <div
                  class="am-category-service-hover"
                  :style="{backgroundColor: colorTransparency(globalCustomization.globalColors.primaryColor, 0.7)}"
                  @click="showNext(service)"
                >
                  <span class="am-category-service-title">{{ service.name }}</span>
                  <el-button>{{ formLabels.view_more.value || $root.labels.view_more }}</el-button>
                </div>

                <!-- Service Background Image -->
                <div
                  class="am-category-service-image"
                  :style="(service.pictureFullPath) ? {'background-image': 'url(' + service.pictureFullPath + ')'} : null"
                >
                </div>

                <!-- Service Info -->
                <div class="am-category-service-info" :style="{backgroundColor: formColors.formBackgroundColor}">

                  <!-- Service Initials -->
                  <div v-if="!('type' in service) && formParts.service_badge.visibility" class="am-category-color-wrapper">
                    <div class="am-category-service-color" :style="{'background-color': service.color}">
                      {{ getNameInitials(service.name) }}
                    </div>
                  </div>

                  <div v-if="('type' in service) && formParts.package_badge.visibility" class="am-category-color-wrapper">
                    <div class="am-category-service-color am-category-package-color" :style="{'background-color': service.color}">
                      <img :src="$root.getUrl + 'public/img/am-package-catalog.svg'">
                    </div>
                    <div class="am-category-item-type" :style="{'background-color': service.color}">
                      {{ formLabels.package.value || $root.labels.package }}
                    </div>
                  </div>

                  <div
                    :class="'type' in service ? 'am-category-package-title-price' : 'am-category-service-title-price'"
                    :style="{color: formColors.formTextColor}"
                  >
                    <!-- Service Name -->
                    <div class="am-category-service-title" :style="{color: formColors.formTextColor}">
                      {{ service.name }}
                    </div>

                    <!-- Service Price -->
                    <span
                      v-if="!('type' in service) && formParts.service_price.visibility"
                      :style="{visibility: ((getServicePrice(service)['min'] || getServicePrice(service)['max']) ? '' : 'hidden'), color: formColors.formTextColor, opacity: 0.7}"
                    >
                      {{ formLabels.price_colon.value || $root.labels.price_colon }} {{ getServicePrice(service)['price'] }}
                    </span>
                    <span
                      v-if="('type' in service) && formParts.package_price.visibility"
                      :style="{visibility: service.price ? '' : 'hidden', color: formColors.formTextColor}"
                      class="am-category-package-price"
                    >
                      {{ getFormattedPrice(service.calculatedPrice ? service.price : service.price - service.price / 100 * service.discount, !$root.settings.payments.hideCurrencySymbolFrontend) }}
                      <span
                        v-if="service.discount && !service.calculatedPrice"
                        :style="{color: formColors.formTextColor, opacity: 0.7}"
                      >
                        {{ `${ formLabels.package_discount_text.value || $root.labels.package_discount_text} ${service.discount}%` }}
                      </span>
                    </span>
                  </div>

                  <div v-if="('type' in service) && formParts.package_services_list.visibility">
                    <div :style="{color: formColors.formTextColor}">
                      {{ formLabels.services.value || $root.labels.services }}
                    </div>
                    <span
                      v-for="item in service.bookable"
                      class="am-category-package-service-item"
                      :style="{color: formColors.formTextColor, opacity: 0.7}"
                    >
                      {{ item.service.name }}
                    </span>
                  </div>

                  <!-- Service Employees -->
                  <div class="am-category-services-thumbs" v-show="!('type' in service) && formParts.service_employees_list.visibility">
                    <img
                      v-for="(employee, index) in getServiceProviders(service.id)"
                      v-if="index < 6"
                      :key="employee.id"
                      :style="{borderColor: formColors.formBackgroundColor}"
                      :src="pictureLoad(employee, true)"
                      @error="imageLoadError(employee, true)"
                    >
                    <span v-if="getServiceProviders(service.id).length > 6">
                  +{{ getInvisibleEmployeesCount(service) }}
                </span>
                  </div>

                </div>

              </div>
            </el-col>
          </el-row>

        </div>
      </transition>

      <!-- Service -->
      <service
        v-if="showService"
        :forms-data="dataObj"
        :customize="globalCustomization.globalColors"
        :passed-category="category"
        :passed-service="category.serviceList.find(service => service.id === serviceId)"
        :passed-entities="options.entities"
        :passed-entities-relations="options.entitiesRelations"
        :addToCalendarProperty="addToCalendarProperty"
        @showAllServices="showAllServices"
      >
      </service>

      <!-- Package -->
      <package
        v-if="showPackage"
        :forms-data="dataObj"
        :customize="globalCustomization.globalColors"
        :passed-category="category"
        :passed-package="getPackageById(packageId)"
        :passed-entities="responseEntities"
        :passed-entities-relations="options.entitiesRelations"
        :addToCalendarProperty="addToCalendarProperty"
        @showAllServices="showAllServices"
      >
      </package>

      <!-- Spinner -->
      <div class="am-spinner am-section c2" v-show="(!fetchedCategory && $root.shortcodeData.enabled === true) || loadingCacheCategoryData">
        <img class="svg-category am-spin" :src="$root.getUrl + 'public/img/oval-spinner.svg'">
        <img class="svg-category am-hourglass" :src="$root.getUrl + 'public/img/hourglass.svg'">
      </div>

    </div>

    <div v-else class="am-no-services">
      <img :src="$root.getUrl+'public/img/am-empty-booking.svg'" style="margin-top: 10px;">
      <h1>{{$root.labels.oops}}</h1>
      <h3>{{$root.labels.no_services_employees}}</h3>
      <p>{{$root.labels.add_services_employees}}</p>
      <a href="https://wpamelia.com/services-and-categories/" rel="nofollow">
        {{$root.labels.add_services_url}}
      </a>
      <span style="font-size:14px">{{$root.labels.and}}</span>
      <a href="https://wpamelia.com/employees/" rel="nofollow">
        {{$root.labels.add_employees_url}}
      </a>
    </div>

    <div v-if="showCategory && $root.licence.isLite && $root.settings.general.backLink.enabled" class="am-lite-footer">
      <a
        rel="nofollow"
        class="am-lite-footer-link"
        :href="$root.settings.general.backLink.url"
        target="_blank"
      >
        {{ $root.settings.general.backLink.label }}
      </a>
    </div>

  </div>
</template>

<script>
  import imageMixin from '../../../js/common/mixins/imageMixin'
  import priceMixin from '../../../js/common/mixins/priceMixin'
  import catalogMixin from '../../../js/frontend/mixins/catalogMixin'
  import entitiesMixin from '../../../js/common/mixins/entitiesMixin'
  import cacheMixin from '../../../js/frontend/mixins/cacheMixin'
  import formsCustomizationMixin from '../../../js/common/mixins/formsCustomizationMixin'
  import cssColorManipulationMixin from '../../../js/common/mixins/cssColorManipulationMixin'
  import marketingMixin from '../../../js/frontend/mixins/marketingMixin'
  import Service from '../catalog/Service'
  import Package from '../catalog/Package'

  export default {

    mixins: [cacheMixin, imageMixin, priceMixin, catalogMixin, entitiesMixin, formsCustomizationMixin, cssColorManipulationMixin],

    props: {
      formsData: {
        type: Object,
        default: () => {
          return {}
        }
      },
      passedCategory: {
        default: () => {},
        type: Object
      },
      passedResponseEntities: {
        default: () => {},
        type: Object
      },
      passedEntities: {
        default: () => {},
        type: Object
      },
      passedEntitiesRelations: {
        default: () => {},
        type: Object
      }
    },

    data () {
      return {
        empty: false,
        addToCalendarProperty: {
          visible: true
        },
        category: {
          serviceList: []
        },
        marketing: {
          service: null,
          employee: null,
          location: null,
          category: null,
          package: null,
          payment: null
        },
        categoryId: '',
        fetchedCategory: false,
        responseEntities: {
          taxes: [],
          categories: [],
          employees: [],
          locations: [],
          customFields: []
        },
        options: {
          availableEntitiesIds: {
            categories: [],
            employees: [],
            locations: [],
            services: []
          },
          entitiesRelations: {},
          entities: {
            packages: [],
            employees: [],
            locations: []
          }
        },
        packageId: '',
        serviceId: '',
        showCategory: true,
        showService: false,
        showPackage: false,
        columnsLg: 8,
        globalCustomization: this.$root.settings.customization,
        dataObj: Object.keys(this.formsData).length ? this.formsData : {},
        formColors: Object.keys(this.formsData).length ? (this.$root.settings.customization.useGlobalColors.catalogForm ? this.$root.settings.customization.globalColors : this.formsData.categoryListForm.globalSettings) : {},
        formLabels: Object.keys(this.formsData).length ? this.formsData.categoryListForm.labels : {},
        formParts: Object.keys(this.formsData).length ? this.formsData.categoryListForm.parts : {}
      }
    },

    created () {
      if (!Object.keys(this.formsData).length) {
        let customizedData = this.getTranslatedForms('catalogForm').catalogForm
        this.dataObj = customizedData
        this.formColors = this.$root.settings.customization.useGlobalColors.catalogForm ? this.$root.settings.customization.globalColors : customizedData.categoryListForm.globalSettings
        this.formLabels = customizedData.categoryListForm.labels
        this.formParts = customizedData.categoryListForm.parts
      }
      this.categoryId = 'category' in this.$root.shortcodeData.booking ? this.$root.shortcodeData.booking.category : null
      window.addEventListener('resize', this.handleResize)
    },

    mounted () {
      this.setCacheData('amelia-app-booking' + this.$root.shortcodeData.counter, false)

      if (!this.$root.shortcodeData.hasCategoryShortcode) {
        this.inlineCategorySVG()
      }

      if (this.passedCategory) {
        this.options.isFrontEnd = true
        this.options.entitiesRelations = Object.assign({}, this.passedEntitiesRelations)
        this.responseEntities = this.passedResponseEntities

        let shortCodeEntitiesIds = this.getShortCodeEntityIds()

        this.filterEntities(this.passedEntities, {
          categoryId: this.passedCategory.id,
          serviceId: shortCodeEntitiesIds.serviceId,
          employeeId: shortCodeEntitiesIds.employeeId,
          locationId: shortCodeEntitiesIds.locationId
        })

        this.category = JSON.parse(JSON.stringify(this.passedCategory))
        this.fetchedCategory = true

        this.cacheDataProcessing()

        this.options.entities.packages.sort((a, b) => a.position - b.position)
      } else {
        let $this = this

        this.fetchEntities(function (success) {
          if (success) {
            $this.fetchedEntities(success)
          }
        }, {
          types: ['locations', 'employees', 'categories', 'custom_fields', 'packages', 'taxes'],
          isFrontEnd: true,
          isPanel: false
        })
      }

      // Customization hook
      if ('beforeCatalogCategoryLoaded' in window) {
        window.beforeCatalogCategoryLoaded(this.category)
      }
    },

    updated () {
      this.handleResize()
    },

    methods: {
      cacheDataProcessing () {
        if (this.loadingCacheBookingData) {
          let entity = null

          switch (this.cacheData.request.bookableType) {
            case ('appointment'):
              entity = this.getServiceById(this.cacheData.request.bookable.id)

              break

            case ('package'):
              entity = this.getPackageById(this.cacheData.request.bookable.id)

              break
          }

          this.showNext(entity)

          this.loadingCacheCategoryData = false
        }
      },

      showNext (entity) {
        this.$nextTick(() => {
          if (this.$refs && this.$refs.categoryContainer) {
            this.$refs.categoryContainer.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' })
          }
        })

        !('type' in entity) ? this.selectService(entity.id) : this.selectPackage(entity.id)
      },

      getListedItems () {
        let shortCodeEntitiesIds = this.getShortCodeEntityIds()

        if (shortCodeEntitiesIds.show === 'packages') {
          return this.options.entities.packages
        } else if (shortCodeEntitiesIds.show === 'services') {
          return this.options.entities.services
        } else {
          return this.options.entities.packages.concat(this.options.entities.services)
        }
      },

      fetchedEntities () {
        if (this.options.entities.services.length === 0 || this.options.entities.employees.length === 0) this.empty = true
        let category = this.options.entities.categories.find(category => category.id === this.categoryId)

        this.category = typeof category !== 'undefined' ? category : null

        this.fetchedCategory = true

        this.cacheDataProcessing()
      },

      backToCatalog () {
        this.$emit('showAllCategories')
      },

      getInvisibleEmployeesCount (service) {
        let serviceProviders = this.getServiceProviders(service.id)

        return serviceProviders.length > 6 ? serviceProviders.length - 6 : ''
      },

      selectService (serviceId) {
        this.serviceId = serviceId

        // Customization hook
        if ('afterSelectCatalogService' in window) {
          window.afterSelectCatalogService(this.category, this.category.serviceList.find(service => service.id === serviceId))
        }

        if (marketingMixin.hasAmeliaTracking(this.$root.marketing, this.serviceId)) {
          this.marketing.service = this.getServiceById(this.serviceId)

          marketingMixin.trackAmeliaData(this, this.$root.marketing, 'appointment', 'SelectService')
        }

        this.showCategory = false
        this.showService = true
      },

      selectPackage (packageId) {
        this.packageId = packageId

        // Customization hook
        if ('afterSelectCatalogPackage' in window) {
          window.afterSelectCatalogService(this.options.entities.packages.find(pack => pack.id === packageId))
        }

        if (marketingMixin.hasAmeliaTracking(this.$root.marketing, this.packageId)) {
          this.marketing.package = this.getPackageById(this.packageId)

          marketingMixin.trackAmeliaData(this, this.$root.marketing, 'package', 'SelectPackage')
        }

        this.showCategory = false
        this.showPackage = true
      },

      showAllServices () {
        this.serviceId = ''
        this.showCategory = true
        this.showService = false
        this.showPackage = false
        this.addToCalendarProperty.visible = false
      },

      handleResize () {
        let amContainer = document.getElementById('amelia-app-booking' + this.$root.shortcodeData.counter)
        let amContainerWidth = amContainer.offsetWidth
        if (amContainerWidth < 670) {
          this.columnsLg = 12
        }

        if (amContainerWidth >= 670) {
          this.columnsLg = 8
        }
      },

      inlineCategorySVG () {
        let inlineSVG = require('inline-svg')
        inlineSVG.init({
          svgSelector: 'img.svg-category',
          initClass: 'js-inlinesvg'
        })
      }
    },

    components: {
      Service,
      Package
    }

  }
</script>
© 2026 GrazzMean-Shell