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
Extras.vue
278 lines
| 1 | <template> |
| 2 | <div class="am-fs__extras" :style="cssVars"> |
| 3 | <div class="am-fs__extras-heading"> |
| 4 | <span v-if="extrasOptions.heading.visibility" class="am-fs__extras-heading-main"> |
| 5 | {{ labelsDisplay('extras_available') }} |
| 6 | </span> |
| 7 | <span class="am-fs__extras-heading-required am-error-text"> |
| 8 | {{ `${labelsDisplay('min_req_extras_colon')} 2` }} |
| 9 | </span> |
| 10 | </div> |
| 11 | <div class="am-fs__extras-main"> |
| 12 | <AmCollapse> |
| 13 | <AmCollapseItem |
| 14 | v-for="extra in extrasArray" |
| 15 | :key="extra.id" |
| 16 | :button-closed="labelsDisplay('extras_card_open')" |
| 17 | :button-opened="labelsDisplay('extras_card_close')" |
| 18 | > |
| 19 | <template #heading> |
| 20 | <div class="am-fs__extras-card__header"> |
| 21 | <span class="am-fs__extras-card__header-left"> |
| 22 | {{ extra.name }} |
| 23 | </span> |
| 24 | <span class="am-fs__extras-card__header-right"> |
| 25 | <span class="card-text"> |
| 26 | {{ useFormattedPrice(extra.price) }} |
| 27 | </span> |
| 28 | <AmInputNumber |
| 29 | v-model="extra.quantity" |
| 30 | :max="extra.maxQuantity" |
| 31 | :min="0" |
| 32 | size="small" |
| 33 | /> |
| 34 | </span> |
| 35 | </div> |
| 36 | </template> |
| 37 | <template #default> |
| 38 | <div |
| 39 | v-if="extrasOptions.description.visibility || extrasOptions.duration.visibility" |
| 40 | class="am-fs__extras-card__content" |
| 41 | :style="cssVars" |
| 42 | > |
| 43 | <div |
| 44 | v-if="extra.description && extrasOptions.description.visibility" |
| 45 | class="am-fs__extras-card__content-main" |
| 46 | > |
| 47 | {{ extra.description }} |
| 48 | </div> |
| 49 | <div v-if="extrasOptions.duration.visibility" class="am-fs__extras-card__content-sub"> |
| 50 | {{ `${labelsDisplay('duration_colon')} 60 min` }} |
| 51 | </div> |
| 52 | </div> |
| 53 | </template> |
| 54 | </AmCollapseItem> |
| 55 | </AmCollapse> |
| 56 | </div> |
| 57 | </div> |
| 58 | </template> |
| 59 | |
| 60 | <script setup> |
| 61 | // * Components |
| 62 | import AmCollapse from '../../../../_components/collapse/AmCollapse.vue' |
| 63 | import AmCollapseItem from '../../../../_components/collapse/AmCollapseItem.vue' |
| 64 | import AmInputNumber from '../../../../_components/input-number/AmInputNumber.vue' |
| 65 | // * Import from Vue |
| 66 | import { ref, inject, computed } from 'vue' |
| 67 | // * Composables |
| 68 | import { useColorTransparency } from '../../../../../assets/js/common/colorManipulation.js' |
| 69 | import { useFormattedPrice } from '../../../../../assets/js/common/formatting' |
| 70 | import { useReactiveCustomize } from '../../../../../assets/js/admin/useReactiveCustomize.js' |
| 71 | |
| 72 | let langKey = inject('langKey') |
| 73 | let amLabels = inject('labels') |
| 74 | |
| 75 | let pageRenderKey = inject('pageRenderKey') |
| 76 | const { amCustomize } = useReactiveCustomize() |
| 77 | |
| 78 | function labelsDisplay(label) { |
| 79 | let computedLabel = computed(() => { |
| 80 | let translations = amCustomize.value[pageRenderKey.value].extrasStep.translations |
| 81 | return translations && translations[label] && translations[label][langKey.value] |
| 82 | ? translations[label][langKey.value] |
| 83 | : amLabels[label] |
| 84 | }) |
| 85 | |
| 86 | return computedLabel.value |
| 87 | } |
| 88 | |
| 89 | let extrasOptions = computed(() => { |
| 90 | return amCustomize.value[pageRenderKey.value].extrasStep.options |
| 91 | }) |
| 92 | |
| 93 | let extrasArray = ref([ |
| 94 | { |
| 95 | name: 'Extra 1', |
| 96 | price: '5', |
| 97 | quantity: 0, |
| 98 | maxQuantity: 5, |
| 99 | description: |
| 100 | "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.", |
| 101 | }, |
| 102 | { |
| 103 | name: 'Extra 2', |
| 104 | price: '3', |
| 105 | quantity: 0, |
| 106 | maxQuantity: 5, |
| 107 | description: |
| 108 | "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.", |
| 109 | }, |
| 110 | { |
| 111 | name: 'Extra 3', |
| 112 | price: '7', |
| 113 | quantity: 0, |
| 114 | maxQuantity: 5, |
| 115 | description: |
| 116 | "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.", |
| 117 | }, |
| 118 | ]) |
| 119 | |
| 120 | // * Colors |
| 121 | let amColors = inject('amColors') |
| 122 | let cssVars = computed(() => { |
| 123 | return { |
| 124 | '--am-c-extras-text': amColors.value.colorMainText, |
| 125 | '--am-c-extras-text-op80': useColorTransparency(amColors.value.colorMainText, 0.8), |
| 126 | } |
| 127 | }) |
| 128 | </script> |
| 129 | |
| 130 | <script> |
| 131 | export default { |
| 132 | name: 'ExtrasStep', |
| 133 | key: 'extrasStep', |
| 134 | sidebarData: { |
| 135 | label: 'extras', |
| 136 | icon: 'border-plus', |
| 137 | stepSelectedData: [], |
| 138 | finished: false, |
| 139 | selected: false, |
| 140 | }, |
| 141 | } |
| 142 | </script> |
| 143 | |
| 144 | <style lang="scss"> |
| 145 | #amelia-app-backend-new { |
| 146 | #amelia-container { |
| 147 | .am-fs__extras { |
| 148 | --am-c-extras-text: var(--am-c-main-text); |
| 149 | |
| 150 | * { |
| 151 | font-family: var(--am-font-family); |
| 152 | box-sizing: border-box; |
| 153 | } |
| 154 | |
| 155 | &-heading { |
| 156 | display: flex; |
| 157 | flex-direction: column; |
| 158 | margin-bottom: 4px; |
| 159 | |
| 160 | & > * { |
| 161 | $count: 3; |
| 162 | @for $i from 0 through $count { |
| 163 | &:nth-child(#{$i + 1}) { |
| 164 | animation: 600ms cubic-bezier(0.45, 1, 0.4, 1.2) #{$i * 100}ms am-animation-slide-up; |
| 165 | animation-fill-mode: both; |
| 166 | } |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | &-main { |
| 171 | display: block; |
| 172 | font-size: var(--am-fs-label); |
| 173 | font-weight: 500; |
| 174 | line-height: 1.6; |
| 175 | color: var(--am-c-extras-text); |
| 176 | margin-bottom: 4px; |
| 177 | } |
| 178 | |
| 179 | &-sub { |
| 180 | display: block; |
| 181 | font-size: 13px; |
| 182 | font-weight: 400; |
| 183 | line-height: 1.3846; |
| 184 | color: var(--am-c-extras-text-op80); |
| 185 | margin-bottom: 4px; |
| 186 | } |
| 187 | |
| 188 | &-required { |
| 189 | display: block; |
| 190 | font-size: 13px; |
| 191 | font-weight: 400; |
| 192 | line-height: 1.3846; |
| 193 | color: var(--am-c-extras-text); |
| 194 | margin-bottom: 4px; |
| 195 | |
| 196 | &.am-error-text { |
| 197 | color: var(--am-c-error); |
| 198 | } |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | &-main { |
| 203 | .am-collapse-item { |
| 204 | $count: 3; |
| 205 | @for $i from 0 through $count { |
| 206 | &:nth-child(#{$i + 1}) { |
| 207 | animation: 600ms cubic-bezier(0.45, 1, 0.4, 1.2) #{$i * 100}ms am-animation-slide-up; |
| 208 | animation-fill-mode: both; |
| 209 | } |
| 210 | } |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | &-card { |
| 215 | &__header { |
| 216 | width: 100%; |
| 217 | display: flex; |
| 218 | align-items: center; |
| 219 | justify-content: space-between; |
| 220 | font-size: var(--am-fs-label); |
| 221 | line-height: 1.6; |
| 222 | |
| 223 | &-left { |
| 224 | display: flex; |
| 225 | align-items: center; |
| 226 | justify-content: left; |
| 227 | font-size: var(--am-fs-label); |
| 228 | line-height: 1.6; |
| 229 | color: var(--am-c-extras-text); |
| 230 | } |
| 231 | |
| 232 | &-right { |
| 233 | display: flex; |
| 234 | align-items: center; |
| 235 | justify-content: right; |
| 236 | font-size: var(--am-fs-label); |
| 237 | line-height: 1.6; |
| 238 | |
| 239 | .card-text { |
| 240 | font-size: var(--am-fs-label); |
| 241 | font-weight: 500; |
| 242 | line-height: 1.6; |
| 243 | color: var(--am-c-primary); |
| 244 | margin-right: 16px; |
| 245 | } |
| 246 | } |
| 247 | |
| 248 | .am-input-number { |
| 249 | max-width: 100px; |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | &__content { |
| 254 | font-size: 14px; |
| 255 | font-weight: 400; |
| 256 | line-height: 1.4285; |
| 257 | |
| 258 | &-main { |
| 259 | font-size: 14px; |
| 260 | font-weight: 400; |
| 261 | line-height: 1.4285; |
| 262 | margin-bottom: 16px; |
| 263 | color: var(--am-c-extras-text-op80); |
| 264 | } |
| 265 | |
| 266 | &-sub { |
| 267 | font-size: 14px; |
| 268 | font-weight: 400; |
| 269 | line-height: 1.4285; |
| 270 | color: var(--am-c-extras-text-op80); |
| 271 | } |
| 272 | } |
| 273 | } |
| 274 | } |
| 275 | } |
| 276 | } |
| 277 | </style> |
| 278 |