common
5 days ago
BringingAnyone.vue
5 days ago
CartStep.vue
5 days ago
Congratulations.vue
5 days ago
DateTimeStep.vue
5 days ago
EmployeeStep.vue
5 days ago
Extras.vue
5 days ago
InfoStep.vue
5 days ago
InitStep.vue
5 days ago
LocationStep.vue
5 days ago
PackageAppointmentsListStep.vue
5 days ago
PackageAppointmentsStep.vue
5 days ago
PackageInfoStep.vue
5 days ago
PackageStep.vue
5 days ago
PaymentStep.vue
5 days ago
RecurringStep.vue
5 days ago
RecurringSummary.vue
5 days ago
ServiceStep.vue
5 days ago
LocationStep.vue
261 lines
| 1 | <template> |
| 2 | <StepCardLayout |
| 3 | ref="stepCardLayoutReference" |
| 4 | :custom-class="[props.class, 'am-fs-location-step']" |
| 5 | :card-selected="selectedLocation !== null || anyLocation" |
| 6 | > |
| 7 | <!-- Any Location --> |
| 8 | <div |
| 9 | v-if="!amCustomize[pageRenderKey].locationStep.options.location.required" |
| 10 | class="am-fs__init-item" |
| 11 | :class="{ |
| 12 | 'am--selected': anyLocation, |
| 13 | }" |
| 14 | tabindex="0" |
| 15 | @click=" |
| 16 | () => { |
| 17 | selectedLocation = null |
| 18 | anyLocation = true |
| 19 | } |
| 20 | " |
| 21 | > |
| 22 | <div class="am-fs__init-item__img am-item-any"> |
| 23 | <span class="am-icon-locations" /> |
| 24 | </div> |
| 25 | <div class="am-fs__init-item__content am-item-any"> |
| 26 | <div class="am-fs__init-item__heading" :class="responsiveClass"> |
| 27 | <div class="am-fs__init-item__name" :class="responsiveClass"> |
| 28 | {{ labelsDisplay('any_location') }} |
| 29 | </div> |
| 30 | </div> |
| 31 | </div> |
| 32 | </div> |
| 33 | <!-- /Any Location --> |
| 34 | |
| 35 | <!-- Card --> |
| 36 | <StepCard |
| 37 | v-for="location in locationOptions" |
| 38 | :key="location.id" |
| 39 | :item="location" |
| 40 | :item-name="location.name" |
| 41 | :selected="selectedLocation?.id === location.id" |
| 42 | :disabled="false" |
| 43 | :is-person="false" |
| 44 | :labels="amLabels" |
| 45 | :info-items=" |
| 46 | location.address && amCustomize[pageRenderKey].locationStep.options.address.visibility |
| 47 | ? [ |
| 48 | { |
| 49 | icon: 'locations', |
| 50 | name: location.address, |
| 51 | isLink: true, |
| 52 | }, |
| 53 | ] |
| 54 | : [] |
| 55 | " |
| 56 | :parent-width="componentWidth" |
| 57 | :info-btn-visibility=" |
| 58 | !!location.description && amCustomize[pageRenderKey].locationStep.options.moreBtn.visibility |
| 59 | " |
| 60 | @select-item=" |
| 61 | () => { |
| 62 | selectedLocation = location |
| 63 | anyLocation = false |
| 64 | } |
| 65 | " |
| 66 | @trigger-info-popup=" |
| 67 | () => { |
| 68 | moreInfoVisibility = true |
| 69 | selectedLocation = location |
| 70 | } |
| 71 | " |
| 72 | /> |
| 73 | <!-- /Card --> |
| 74 | </StepCardLayout> |
| 75 | |
| 76 | <!-- More Info --> |
| 77 | <MoreInfoPopup |
| 78 | v-if="moreInfoVisibility" |
| 79 | v-model:visibility="moreInfoVisibility" |
| 80 | :heading="labelsDisplay('location_information')" |
| 81 | :item="selectedLocation" |
| 82 | :item-name="selectedLocation.name" |
| 83 | :is-person="false" |
| 84 | /> |
| 85 | <!-- /More Info --> |
| 86 | </template> |
| 87 | |
| 88 | <script setup> |
| 89 | import StepCardLayout from './common/StepCardLayout.vue' |
| 90 | import StepCard from './common/StepCard.vue' |
| 91 | import MoreInfoPopup from '../../../../public/StepForm/common/MoreInfoPopup.vue' |
| 92 | |
| 93 | // * Import from Vue |
| 94 | import { computed, inject, ref } from 'vue' |
| 95 | |
| 96 | // * Composables |
| 97 | import { useResponsiveClass } from '../../../../../assets/js/common/responsive' |
| 98 | import { useElementSize } from '@vueuse/core' |
| 99 | |
| 100 | // * Props |
| 101 | const props = defineProps({ |
| 102 | class: { |
| 103 | type: String, |
| 104 | default: '', |
| 105 | }, |
| 106 | }) |
| 107 | |
| 108 | // * Lang key |
| 109 | let langKey = inject('langKey') |
| 110 | |
| 111 | // * Labels |
| 112 | let amLabels = inject('labels') |
| 113 | |
| 114 | let stepName = inject('stepName') |
| 115 | let pageRenderKey = inject('pageRenderKey') |
| 116 | let amCustomize = inject('customize') |
| 117 | |
| 118 | // * Component References |
| 119 | const stepCardLayoutReference = ref(null) |
| 120 | const stepCardLayoutDom = computed(() => stepCardLayoutReference.value?.stepCardLayoutRef || null) |
| 121 | |
| 122 | // * Component width |
| 123 | const { width: componentWidth } = useElementSize(stepCardLayoutDom) |
| 124 | |
| 125 | // * Responsive Class |
| 126 | let responsiveClass = computed(() => { |
| 127 | return useResponsiveClass(componentWidth.value) |
| 128 | }) |
| 129 | |
| 130 | function labelsDisplay(label) { |
| 131 | return computed(() => { |
| 132 | return ( |
| 133 | amCustomize.value[pageRenderKey.value]?.[stepName.value]?.translations?.[label]?.[ |
| 134 | langKey.value |
| 135 | ] || amLabels[label] |
| 136 | ) |
| 137 | }).value |
| 138 | } |
| 139 | |
| 140 | // * Any Employee |
| 141 | let anyLocation = ref(true) |
| 142 | |
| 143 | let selectedLocation = ref(null) |
| 144 | |
| 145 | // * Set Location Options from entities |
| 146 | let locationOptions = ref([ |
| 147 | { |
| 148 | id: 1, |
| 149 | name: 'Nail Lounge', |
| 150 | address: '123 Beauty Street, Downtown, NY 10001', |
| 151 | description: |
| 152 | 'Premium nail salon offering luxury manicures, pedicures, and nail art services in a relaxing spa-like environment.', |
| 153 | }, |
| 154 | { |
| 155 | id: 2, |
| 156 | name: 'Medical Center', |
| 157 | address: '456 Health Ave, Medical District, NY 10002', |
| 158 | description: |
| 159 | 'Full-service medical facility providing comprehensive healthcare services with state-of-the-art equipment and experienced medical professionals.', |
| 160 | }, |
| 161 | { |
| 162 | id: 3, |
| 163 | name: 'Fitness Gym', |
| 164 | address: '789 Workout Blvd, Sports Complex, NY 10003', |
| 165 | description: |
| 166 | 'Modern fitness center with cutting-edge equipment, personal training services, and group fitness classes for all fitness levels.', |
| 167 | }, |
| 168 | { |
| 169 | id: 4, |
| 170 | name: 'Downtown Salon', |
| 171 | address: '321 Style Street, Fashion District, NY 10004', |
| 172 | description: |
| 173 | 'Trendy hair salon specializing in cuts, coloring, styling, and treatments using premium products and latest techniques.', |
| 174 | }, |
| 175 | { |
| 176 | id: 5, |
| 177 | name: 'Wellness Center', |
| 178 | address: '654 Serenity Lane, Wellness Quarter, NY 10005', |
| 179 | description: |
| 180 | 'Holistic wellness facility offering massage therapy, meditation classes, yoga sessions, and various healing treatments.', |
| 181 | }, |
| 182 | { |
| 183 | id: 6, |
| 184 | name: 'Beauty Spa', |
| 185 | address: '987 Pamper Plaza, Luxury District, NY 10006', |
| 186 | description: |
| 187 | 'Luxurious spa retreat providing facial treatments, body therapies, and rejuvenating services in an elegant setting.', |
| 188 | }, |
| 189 | { |
| 190 | id: 7, |
| 191 | name: 'Beauty Studio', |
| 192 | address: '147 Glamour Street, Beauty Row, NY 10007', |
| 193 | description: |
| 194 | 'Contemporary beauty studio offering makeup services, eyebrow shaping, eyelash extensions, and skincare treatments.', |
| 195 | }, |
| 196 | { |
| 197 | id: 8, |
| 198 | name: 'Color Studio', |
| 199 | address: '258 Artistic Ave, Creative Quarter, NY 10008', |
| 200 | description: |
| 201 | 'Specialized color studio focusing on hair coloring, balayage, highlights, and creative color transformations.', |
| 202 | }, |
| 203 | ]) |
| 204 | |
| 205 | // * Location - More Info |
| 206 | let moreInfoVisibility = ref(false) |
| 207 | </script> |
| 208 | |
| 209 | <script> |
| 210 | export default { |
| 211 | name: 'LocationStep', |
| 212 | key: 'locationStep', |
| 213 | sidebarData: { |
| 214 | label: 'location_selection', |
| 215 | icon: 'locations', |
| 216 | stepSelectedData: [], |
| 217 | finished: false, |
| 218 | selected: false, |
| 219 | }, |
| 220 | } |
| 221 | </script> |
| 222 | |
| 223 | <style lang="scss"> |
| 224 | #amelia-app-backend-new #amelia-container { |
| 225 | .am-fs-location-step { |
| 226 | .am-fs__init { |
| 227 | &-item { |
| 228 | // Card content |
| 229 | &__content { |
| 230 | &.am-item-any { |
| 231 | justify-content: center; |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | // Card heading |
| 236 | &__heading { |
| 237 | &.am-rw-370 { |
| 238 | flex-wrap: nowrap; |
| 239 | justify-content: unset; |
| 240 | margin-bottom: 8px; |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | // Card name |
| 245 | &__name { |
| 246 | &.am-rw-370 { |
| 247 | display: block; |
| 248 | white-space: nowrap; |
| 249 | overflow: hidden; |
| 250 | text-overflow: ellipsis; |
| 251 | width: auto; |
| 252 | order: unset; |
| 253 | justify-self: flex-start; |
| 254 | } |
| 255 | } |
| 256 | } |
| 257 | } |
| 258 | } |
| 259 | } |
| 260 | </style> |
| 261 |