PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.6
Booking for Appointments and Events Calendar – Amelia v2.4.6
2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / v3 / src / views / admin / customize / steps / StepForm / EmployeeStep.vue
ameliabooking / v3 / src / views / admin / customize / steps / StepForm Last commit date
common 1 month ago BringingAnyone.vue 1 month ago CartStep.vue 1 month ago Congratulations.vue 1 month ago DateTimeStep.vue 1 month ago EmployeeStep.vue 1 month ago Extras.vue 1 month ago InfoStep.vue 1 month ago InitStep.vue 1 month ago LocationStep.vue 1 month ago PackageAppointmentsListStep.vue 1 month ago PackageAppointmentsStep.vue 1 month ago PackageInfoStep.vue 1 month ago PackageStep.vue 1 month ago PaymentStep.vue 1 month ago RecurringStep.vue 1 month ago RecurringSummary.vue 1 month ago ServiceStep.vue 1 month ago
EmployeeStep.vue
263 lines
1 <template>
2 <StepCardLayout
3 ref="stepCardLayoutReference"
4 :custom-class="[props.class, 'am-fs-employee-step']"
5 :card-selected="selectedEmployee !== null || anyEmployee"
6 >
7 <!-- Any Employee -->
8 <div
9 v-if="!amCustomize[pageRenderKey].employeeStep.options.employee.required"
10 class="am-fs__init-item"
11 :class="{
12 'am--selected': anyEmployee,
13 }"
14 tabindex="0"
15 @click="
16 () => {
17 selectedEmployee = null
18 anyEmployee = true
19 }
20 "
21 >
22 <div class="am-fs__init-item__img am-item-any">
23 <span class="am-icon-user" />
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_employee') }}
29 </div>
30 </div>
31 </div>
32 </div>
33 <!-- /Any Employee -->
34
35 <StepCard
36 v-for="employee in employeeOptions"
37 :key="employee.id"
38 :item="employee"
39 :item-name="`${employee.firstName} ${employee.lastName}`"
40 :selected="selectedEmployee?.id === employee.id"
41 :disabled="false"
42 :is-person="true"
43 :price="employee.price"
44 :price-visibility="amCustomize[pageRenderKey].employeeStep.options.price.visibility"
45 :labels="amLabels"
46 :parent-width="componentWidth"
47 :info-btn-visibility="
48 !!employee.description && amCustomize[pageRenderKey].employeeStep.options.moreBtn.visibility
49 "
50 @select-item="
51 () => {
52 selectedEmployee = employee
53 anyEmployee = false
54 }
55 "
56 @trigger-info-popup="
57 () => {
58 moreInfoVisibility = true
59 selectedEmployee = employee
60 }
61 "
62 />
63 </StepCardLayout>
64
65 <!-- More Info -->
66 <MoreInfoPopup
67 v-if="moreInfoVisibility"
68 v-model:visibility="moreInfoVisibility"
69 :heading="labelsDisplay('employee_information')"
70 :item="selectedEmployee"
71 :item-name="`${selectedEmployee.firstName} ${selectedEmployee.lastName}`"
72 :is-person="true"
73 />
74 <!-- /More Info -->
75 </template>
76
77 <script setup>
78 // * Import from Vue
79 import { ref, computed, inject } from 'vue'
80
81 // * Dedicated components
82 import StepCardLayout from './common/StepCardLayout.vue'
83 import StepCard from './common/StepCard.vue'
84 import MoreInfoPopup from '../../../../public/StepForm/common/MoreInfoPopup.vue'
85
86 // * Composables
87 import { useElementSize } from '@vueuse/core'
88 import { useResponsiveClass } from '../../../../../assets/js/common/responsive'
89
90 // * Props
91 const props = defineProps({
92 class: {
93 type: [String, Array],
94 default: '',
95 },
96 })
97
98 // * Lang key
99 let langKey = inject('langKey')
100
101 // * Labels
102 let amLabels = inject('labels')
103
104 let stepName = inject('stepName')
105 let pageRenderKey = inject('pageRenderKey')
106 let amCustomize = inject('customize')
107
108 // * Component reference
109 const stepCardLayoutReference = ref(null)
110 const stepCardLayoutDom = computed(() => stepCardLayoutReference.value?.stepCardLayoutRef || null)
111
112 // * Component width
113 const { width: componentWidth } = useElementSize(stepCardLayoutDom)
114
115 let responsiveClass = computed(() => {
116 return useResponsiveClass(componentWidth.value)
117 })
118
119 function labelsDisplay(label) {
120 return computed(() => {
121 return (
122 amCustomize.value[pageRenderKey.value]?.[stepName.value]?.translations?.[label]?.[
123 langKey.value
124 ] || amLabels[label]
125 )
126 }).value
127 }
128
129 let anyEmployee = ref(true)
130
131 let selectedEmployee = ref(null)
132
133 let employeeOptions = ref([
134 {
135 id: 1,
136 firstName: 'Sarah',
137 lastName: 'Johnson',
138 description:
139 'Senior nail technician with 8 years of experience specializing in gel manicures and nail art. Sarah is known for her attention to detail and creative designs.',
140 price: '$45',
141 },
142 {
143 id: 2,
144 firstName: 'Michael',
145 lastName: 'Davis',
146 description:
147 'Licensed massage therapist specializing in deep tissue and Swedish massage. Michael has extensive training in sports massage and injury recovery.',
148 price: '',
149 },
150 {
151 id: 3,
152 firstName: 'Emma',
153 lastName: 'Wilson',
154 description:
155 'Professional hairstylist and colorist with expertise in balayage, highlights, and modern cuts. Emma stays current with the latest trends and techniques.',
156 price: '',
157 },
158 {
159 id: 4,
160 firstName: 'James',
161 lastName: 'Rodriguez',
162 description:
163 'Certified personal trainer with specialization in strength training and weight loss. James creates personalized workout plans for all fitness levels.',
164 price: '$55',
165 },
166 {
167 id: 5,
168 firstName: 'Lisa',
169 lastName: 'Chen',
170 description:
171 'Licensed esthetician specializing in facials, chemical peels, and anti-aging treatments. Lisa provides personalized skincare consultations.',
172 price: '$75',
173 },
174 {
175 id: 6,
176 firstName: 'David',
177 lastName: 'Thompson',
178 description:
179 "Master barber with traditional and modern cutting techniques. David offers classic shaves, beard trimming, and contemporary men's styling.",
180 price: '$40',
181 },
182 {
183 id: 7,
184 firstName: 'Amanda',
185 lastName: 'Brown',
186 description:
187 'Yoga instructor certified in Hatha, Vinyasa, and Restorative yoga. Amanda focuses on mindfulness and proper alignment for all skill levels.',
188 price: '',
189 },
190 {
191 id: 8,
192 firstName: 'Robert',
193 lastName: 'Martinez',
194 description:
195 'Licensed physiotherapist specializing in injury rehabilitation and pain management. Robert uses evidence-based treatments for optimal recovery.',
196 price: '',
197 },
198 ])
199
200 // * Service - More Info
201 let moreInfoVisibility = ref(false)
202 </script>
203
204 <script>
205 export default {
206 name: 'EmployeeStep',
207 key: 'employeeStep',
208 sidebarData: {
209 label: 'employee_selection',
210 icon: 'employee',
211 stepSelectedData: [],
212 finished: false,
213 selected: false,
214 },
215 }
216 </script>
217
218 <style lang="scss">
219 #amelia-app-backend-new #amelia-container {
220 .am-fs-employee-step {
221 .am-fs__init {
222 &-item {
223 // Card content
224 &__content {
225 justify-content: space-between;
226 &.am-item-any {
227 justify-content: center;
228 }
229 }
230
231 // Card heading
232 &__heading {
233 &.am-rw-370 {
234 flex-wrap: nowrap;
235 justify-content: unset;
236 }
237 }
238
239 // Card name
240 &__name {
241 &.am-rw-370 {
242 display: block;
243 white-space: nowrap;
244 overflow: hidden;
245 text-overflow: ellipsis;
246 width: auto;
247 order: unset;
248 justify-self: flex-start;
249 }
250 }
251
252 // Card cost
253 &__cost {
254 &.am-rw-370 {
255 flex: 0 0 auto;
256 }
257 }
258 }
259 }
260 }
261 }
262 </style>
263