@mframework/layer-commerce 0.0.5 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/app/components/catalog/product/ProductAccordion/ProductAccordion.vue +41 -0
  2. package/app/components/catalog/product/ProductAccordion/__tests__/ProductAccordion.spec.ts +15 -0
  3. package/app/components/catalog/product/ProductAccordion/types.ts +5 -0
  4. package/app/components/catalog/product/ProductProperties/ProductProperties.vue +52 -0
  5. package/app/components/catalog/product/ProductProperties/__tests__/ProductProperties.spec.ts +15 -0
  6. package/app/components/catalog/product/ProductProperties/types.ts +5 -0
  7. package/app/components/catalog/product/ProductSlider/ProductSlider.vue +28 -0
  8. package/app/components/catalog/product/ProductSlider/__tests__/ProductSlider.spec.ts +14 -0
  9. package/app/components/catalog/product/ProductSlider/types.ts +7 -0
  10. package/app/components/catalog/product/RecommendedProducts/RecommendedProducts.vue +12 -0
  11. package/app/components/catalog/product/RecommendedProducts/types.ts +5 -0
  12. package/app/components/catalog/product/RenderContentProductSlider/RenderContentProductSlider.vue +11 -0
  13. package/app/components/catalog/product/add-attribute.vue +54 -0
  14. package/app/components/catalog/product/add-product-type.vue +54 -0
  15. package/app/components/catalog/product/add-product.vue +53 -0
  16. package/app/components/catalog/product/add-showcase.vue +52 -0
  17. package/app/components/catalog/product/add-station.vue +54 -0
  18. package/app/components/catalog/product/bestsellers.vue +69 -0
  19. package/app/components/catalog/product/bidding.vue +93 -0
  20. package/app/components/catalog/product/colorOptions.vue +58 -0
  21. package/app/components/catalog/product/deals.vue +61 -0
  22. package/app/components/catalog/product/exclusives.vue +58 -0
  23. package/app/components/catalog/product/featuredproducts.vue +69 -0
  24. package/app/components/catalog/product/giftCard.vue +63 -0
  25. package/app/components/catalog/product/latestproducts.vue +58 -0
  26. package/app/components/catalog/product/productCard.vue +71 -0
  27. package/app/components/catalog/product/productCompare.vue +60 -0
  28. package/app/components/catalog/product/productCompareTable.vue +441 -0
  29. package/app/components/catalog/product/productDetails.vue +120 -0
  30. package/app/components/catalog/product/productFaqs.vue +17 -0
  31. package/app/components/catalog/product/productGallery.vue +16 -0
  32. package/app/components/catalog/product/productQty.vue +54 -0
  33. package/app/components/catalog/product/productReviews.vue +56 -0
  34. package/app/components/catalog/product/productSpecs.vue +116 -0
  35. package/app/components/catalog/product/radiostation.vue +36 -0
  36. package/app/components/catalog/product/recentlyviewed.vue +43 -0
  37. package/app/components/catalog/product/relatedbrands.vue +54 -0
  38. package/app/components/catalog/product/relatedproducts.vue +58 -0
  39. package/app/components/catalog/product/relatedstations.vue +40 -0
  40. package/app/components/catalog/product/shippingOptions.vue +41 -0
  41. package/app/components/catalog/product/sizeOptions.vue +47 -0
  42. package/app/components/catalog/product/update-attribute-set.vue +209 -0
  43. package/app/components/catalog/product/update-attribute.vue +118 -0
  44. package/app/components/catalog/product/update-product.vue +372 -0
  45. package/app/components/catalog/product/update-showcase.vue +153 -0
  46. package/app/components/catalog/shops/relatedstores.vue +52 -0
  47. package/app/components/catalog/shops/restaurant.vue +66 -0
  48. package/app/components/catalog/shops/stores.vue +44 -0
  49. package/app/components/catalog/vendor/README.md +3 -0
  50. package/app/components/catalog/vendor/blocks/biggestcustomers.vue +33 -0
  51. package/app/components/catalog/vendor/blocks/lowestselling.vue +33 -0
  52. package/app/components/catalog/vendor/blocks/topcategories.vue +33 -0
  53. package/app/components/catalog/vendor/blocks/topproducts.vue +27 -0
  54. package/app/components/catalog/vendor/pages/attributes.vue +43 -0
  55. package/app/components/catalog/vendor/pages/commissions.vue +43 -0
  56. package/app/components/catalog/vendor/pages/crm.vue +67 -0
  57. package/app/components/catalog/vendor/pages/dashboard.vue +46 -0
  58. package/app/components/catalog/vendor/pages/emails.vue +43 -0
  59. package/app/components/catalog/vendor/pages/enquiries.vue +43 -0
  60. package/app/components/catalog/vendor/pages/invoices.vue +43 -0
  61. package/app/components/catalog/vendor/pages/orders.vue +68 -0
  62. package/app/components/catalog/vendor/pages/products.vue +55 -0
  63. package/app/components/catalog/vendor/pages/reviews.vue +48 -0
  64. package/app/components/catalog/vendor/pages/shipments.vue +43 -0
  65. package/app/components/catalog/vendor/pages/stores.vue +43 -0
  66. package/app/components/content/blocks/breadcrumbs.vue +0 -0
  67. package/app/components/content/blocks/currencySwitcher.vue +0 -0
  68. package/app/components/content/blocks/languageSwitcher.vue +0 -0
  69. package/app/components/content/blocks/videoproduct.vue +9 -0
  70. package/app/components/content/pages/checkout.vue +118 -0
  71. package/app/components/content/pages/meeoviGlobal.vue +68 -0
  72. package/app/components/content/pages/pickup-locations.vue +238 -0
  73. package/app/components/content/pages/showcases.vue +90 -0
  74. package/app/components/content/pages/success.vue +60 -0
  75. package/app/components/marketing/add-brand.vue +54 -0
  76. package/app/components/marketing/add-incentive.vue +54 -0
  77. package/app/components/marketing/promotions/giftcards.vue +127 -0
  78. package/app/components/marketing/promotions/subscriptions.vue +134 -0
  79. package/app/components/marketing/update-incentive.vue +326 -0
  80. package/app/components/menus/lowernav.vue +78 -0
  81. package/app/components/partials/LocaleSelector.vue +24 -0
  82. package/app/components/partials/ShoppingCart.vue +128 -0
  83. package/app/components/partials/StripePayment.vue +149 -0
  84. package/app/components/partials/addToCartBtn.vue +40 -0
  85. package/app/components/partials/cartItem.vue +124 -0
  86. package/app/components/partials/checkoutButton.vue +44 -0
  87. package/app/components/partials/compareBtn.vue +68 -0
  88. package/app/components/partials/ratings.vue +13 -0
  89. package/app/components/partials/store/CurrencySelector.vue +133 -0
  90. package/app/components/partials/store/StoreSwitcher.vue +13 -0
  91. package/app/components/related/brandCard.vue +41 -0
  92. package/app/components/related/incentiveCard.vue +44 -0
  93. package/app/components/related/invoiceCard.vue +43 -0
  94. package/app/components/related/orderCard.vue +43 -0
  95. package/app/components/related/relatedproducts.vue +17 -0
  96. package/app/components/sales/CartPageContent/CartPageContent.vue +43 -0
  97. package/app/components/sales/CheckoutAddress/CheckoutAddress.vue +50 -0
  98. package/app/components/sales/CheckoutAddress/__tests__/CheckoutAddress.spec.ts +16 -0
  99. package/app/components/sales/CheckoutAddress/types.ts +16 -0
  100. package/app/components/sales/CheckoutPayment/CheckoutPayment.vue +65 -0
  101. package/app/components/sales/CheckoutPayment/__tests__/CheckoutPayment.spec.ts +14 -0
  102. package/app/components/sales/CheckoutPayment/types.ts +12 -0
  103. package/app/components/sales/OrderSummary/OrderSummary.vue +57 -0
  104. package/app/components/sales/OrderSummary/__tests__/ContactInformation.spec.ts +52 -0
  105. package/app/components/sales/OrderSummary/types.ts +5 -0
  106. package/app/components/sales/incentives.vue +247 -0
  107. package/app/components/sales/invoices.vue +107 -0
  108. package/app/components/sales/orders.vue +378 -0
  109. package/app/components/sales/shipments.vue +65 -0
  110. package/app/components/sales/transactions.vue +109 -0
  111. package/app/components/shop/add-shop.vue +54 -0
  112. package/app/components/shop/cart/cartItem.vue +182 -0
  113. package/app/components/shop/cart/checkout.vue +415 -0
  114. package/app/components/shop/checkout/StripeCardElement.vue +206 -0
  115. package/app/components/shop/checkout/StripeCheckout.vue +49 -0
  116. package/app/components/shop/checkout/addressBilling.vue +263 -0
  117. package/app/components/shop/checkout/addressShipping.vue +175 -0
  118. package/app/components/shop/checkout/cart/ProductItem.vue +56 -0
  119. package/app/components/shop/checkout/cart/PromotionItem.vue +53 -0
  120. package/app/composables/useCustomer/__tests__/useCustomer.spec.ts +1 -1
  121. package/app/composables/useProductReviews/__tests__/useProductReviews.spec.ts +1 -1
  122. package/app/stores/cart.ts +1 -1
  123. package/app/types/Direction.type.ts +1 -1
  124. package/app/types/Global.type.ts +6 -6
  125. package/app/types/Layout.type.ts +1 -1
  126. package/app/types/index.ts +1 -1
  127. package/app/{normalizers → types/normalizers}/Cart.query.ts +1 -1
  128. package/app/{normalizers → types/normalizers}/Cart.type.ts +2 -2
  129. package/app/{normalizers → types/normalizers}/Checkout.query.ts +2 -2
  130. package/app/{normalizers → types/normalizers}/Config.query.ts +1 -1
  131. package/app/{normalizers → types/normalizers}/Config.type.ts +1 -1
  132. package/app/{normalizers → types/normalizers}/ContactForm.query.ts +2 -2
  133. package/app/{normalizers → types/normalizers}/CreditMemo.type.ts +1 -1
  134. package/app/{normalizers → types/normalizers}/GiftCard.type.ts +1 -1
  135. package/app/{normalizers → types/normalizers}/Invoice.type.ts +1 -1
  136. package/app/{normalizers → types/normalizers}/MyAccount.query.ts +1 -1
  137. package/app/{normalizers → types/normalizers}/MyAccount.type.ts +1 -1
  138. package/app/{normalizers → types/normalizers}/NewsletterSubscription.query.ts +1 -1
  139. package/app/{normalizers → types/normalizers}/Order.query.ts +1 -1
  140. package/app/{normalizers → types/normalizers}/Order.type.ts +2 -2
  141. package/app/{normalizers → types/normalizers}/Payment.type.ts +1 -1
  142. package/app/{normalizers → types/normalizers}/ProductCompare.query.ts +1 -1
  143. package/app/{normalizers → types/normalizers}/ProductCompare.type.ts +1 -1
  144. package/app/{normalizers → types/normalizers}/ProductList.query.ts +2 -2
  145. package/app/{normalizers → types/normalizers}/ProductList.type.ts +2 -2
  146. package/app/{normalizers → types/normalizers}/Return.type.ts +1 -1
  147. package/app/{normalizers → types/normalizers}/Review.query.ts +1 -1
  148. package/app/{normalizers → types/normalizers}/Review.type.ts +1 -1
  149. package/app/{normalizers → types/normalizers}/StoreInPickUp.query.ts +1 -1
  150. package/app/{normalizers → types/normalizers}/Subscription.type.ts +1 -1
  151. package/app/{normalizers → types/normalizers}/Transaction.type.ts +1 -1
  152. package/app/{normalizers → types/normalizers}/UrlRewrites.query.ts +1 -1
  153. package/app/{normalizers → types/normalizers}/UrlRewrites.type.ts +1 -1
  154. package/app/{normalizers → types/normalizers}/Wishlist.query.ts +4 -4
  155. package/app/{normalizers → types/normalizers}/Wishlist.type.ts +1 -1
  156. package/app/utils/Address/Address.type.ts +1 -1
  157. package/app/utils/Address/index.ts +5 -5
  158. package/app/utils/Cart/Cart.ts +1 -1
  159. package/app/utils/Currency/Currency.ts +1 -1
  160. package/app/utils/History/History.type.ts +1 -1
  161. package/app/utils/Menu/Menu.ts +1 -1
  162. package/app/utils/Menu/Menu.type.ts +2 -2
  163. package/app/utils/Orders/Orders.ts +1 -1
  164. package/app/utils/Preload/CategoryPreload.ts +2 -2
  165. package/app/utils/Preload/ProductPreload.ts +1 -1
  166. package/app/utils/Preload/index.ts +1 -1
  167. package/app/utils/Price/Price.ts +1 -1
  168. package/app/utils/Product/Extract.ts +1 -1
  169. package/app/utils/Product/Product.ts +1 -1
  170. package/app/utils/Product/Product.type.ts +1 -1
  171. package/app/utils/Product/Transform.ts +1 -1
  172. package/app/utils/Wishlist/Wishlist.ts +1 -1
  173. package/app/utils/client.ts +20 -20
  174. package/package.json +1 -3
  175. package/tsconfig.json +2 -2
  176. package/app/cart/useCart.ts +0 -1
  177. /package/app/{components → composables}/ChevronIcon/ChevronIcon.config.ts +0 -0
  178. /package/app/{components → composables}/DateSelect/DateSelect.config.ts +0 -0
  179. /package/app/{components → composables}/Field/Field.config.ts +0 -0
  180. /package/app/{components → composables}/FieldDate/FieldDate.config.ts +0 -0
  181. /package/app/{components → composables}/Form/Form.type.ts +0 -0
  182. /package/app/{components → composables}/Product/Product.config.ts +0 -0
  183. /package/app/{components → composables}/Product/Stock.config.ts +0 -0
  184. /package/app/{components → composables}/ProductCustomizableOption/ProductCustomizableOption.config.ts +0 -0
  185. /package/app/{components → composables}/ProductGallery/ProductGallery.config.ts +0 -0
  186. /package/app/{components → composables}/ProductReviews/ProductReviews.config.ts +0 -0
  187. /package/app/{normalizers → types/normalizers}/Category.query.ts +0 -0
  188. /package/app/{normalizers → types/normalizers}/Category.type.ts +0 -0
  189. /package/app/{normalizers → types/normalizers}/CheckEmail.query.ts +0 -0
  190. /package/app/{normalizers → types/normalizers}/Checkout.type.ts +0 -0
  191. /package/app/{normalizers → types/normalizers}/CmsBlock.query.ts +0 -0
  192. /package/app/{normalizers → types/normalizers}/CmsBlock.type.ts +0 -0
  193. /package/app/{normalizers → types/normalizers}/CmsPage.query.ts +0 -0
  194. /package/app/{normalizers → types/normalizers}/CmsPage.type.ts +0 -0
  195. /package/app/{normalizers → types/normalizers}/Menu.query.ts +0 -0
  196. /package/app/{normalizers → types/normalizers}/Menu.type.ts +0 -0
  197. /package/app/{normalizers → types/normalizers}/ProductAlerts.query.ts +0 -0
  198. /package/app/{normalizers → types/normalizers}/Region.query.ts +0 -0
  199. /package/app/{normalizers → types/normalizers}/Region.type.ts +0 -0
  200. /package/app/{normalizers → types/normalizers}/Slider.query.ts +0 -0
  201. /package/app/{normalizers → types/normalizers}/Slider.type.ts +0 -0
  202. /package/app/{normalizers → types/normalizers}/StoreInPickUp.type.ts +0 -0
  203. /package/app/{routes → types/routes}/CategoryPage/CategoryPage.config.ts +0 -0
  204. /package/app/{routes → types/routes}/CategoryPage/CategoryPage.type.ts +0 -0
  205. /package/app/{routes → types/routes}/Checkout/Checkout.config.ts +0 -0
  206. /package/app/{routes → types/routes}/Checkout/Checkout.type.ts +0 -0
  207. /package/app/{routes → types/routes}/MyAccount/MyAccount.config.ts +0 -0
  208. /package/app/{routes → types/routes}/SearchPage/SearchPage.config.ts +0 -0
  209. /package/app/{routes → types/routes}/UrlRewrites/UrlRewrites.config.ts +0 -0
@@ -0,0 +1,238 @@
1
+ <template>
2
+ <div class="customerDashboard">
3
+ <v-row>
4
+ <v-toolbar color="transparent">
5
+ <v-toolbar-title>{{ pickupBlocks?.content?.[0]?.name }}</v-toolbar-title>
6
+ </v-toolbar>
7
+
8
+ <!-- Search and Filter Section -->
9
+ <v-col cols="12" class="mb-4">
10
+ <v-card>
11
+ <v-card-text>
12
+ <v-row>
13
+ <v-col cols="4">
14
+ <v-text-field v-model="searchAddress" label="Search by address"
15
+ @keyup.enter="searchByAddress"></v-text-field>
16
+ </v-col>
17
+ <v-col cols="3">
18
+ <v-select v-model="selectedRadius" :items="radiusOptions" label="Search radius"></v-select>
19
+ </v-col>
20
+ <v-col cols="2">
21
+ <v-btn color="primary" @click="searchByAddress">Search</v-btn>
22
+ </v-col>
23
+ </v-row>
24
+ </v-card-text>
25
+ </v-card>
26
+ </v-col>
27
+
28
+ <!-- Locations List -->
29
+ <v-col cols="4">
30
+ <template v-if="pickupLocations.length">
31
+ <v-card class="mx-auto mb-4" prepend-icon="$vuetify" :subtitle="pickupBlocks?.content?.[0]?.url_name"
32
+ width="100%" v-for="location in pickupLocations" :key="location?.id" @click="selectLocation(location)">
33
+ <template v-slot:title>
34
+ <span class="font-weight-black">{{ location?.name }}</span>
35
+ </template>
36
+
37
+ <v-card-text class="bg-surface-light pt-4">
38
+ <div>{{ pickupBlocks?.menus?.[0]?.name }} {{ location?.street }}</div>
39
+ <div>{{ pickupBlocks?.menus?.[1]?.name }} {{ location?.city }}</div>
40
+ <div>{{ pickupBlocks?.menus?.[2]?.name }} {{ location?.postcode }}</div>
41
+ <div>{{ pickupBlocks?.menus?.[3]?.name }} {{ location?.phone }}</div>
42
+ <div>{{ pickupBlocks?.menus?.[4]?.name }} {{ location?.email }}</div>
43
+ <div>{{ pickupBlocks?.menus?.[5]?.name }} {{ location?.region }}</div>
44
+ <div>{{ pickupBlocks?.menus?.[6]?.name }} {{ location?.description }}</div>
45
+ <div v-if="location.distance">Distance: {{ formatDistance(location.distance) }}</div>
46
+ </v-card-text>
47
+ </v-card>
48
+ </template>
49
+ <template v-else>
50
+ <v-card class="mx-auto mb-4" width="100%" elevation="0">
51
+ <v-card-text class="text-center">
52
+ <p class="text-h6" v-dompurify-html="pickupBlocks?.content?.[0]?.content"></p>
53
+ </v-card-text>
54
+ </v-card>
55
+ </template>
56
+ </v-col>
57
+
58
+ <!-- Map Section -->
59
+ <v-col cols="8">
60
+ <client-only>
61
+ <Map style="height: 600px" :zoom="mapZoom" :center="mapCenter" :use-global-leaflet="false">
62
+ <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
63
+ attribution="&copy; 'https://www.openstreetmap.org'; contributors" layer-type="base"
64
+ name="OpenStreetMap" />
65
+ <template v-if="pickupLocations.length">
66
+ <Marker v-for="location in pickupLocations" :key="location.id"
67
+ :lat-lng="[location?.latitude, location?.longitude]" @click="selectLocation(location)">
68
+ <Popup>{{ location?.name }}</Popup>
69
+ </Marker>
70
+ </template>
71
+ </Map>
72
+ </client-only>
73
+ </v-col>
74
+
75
+ <v-col cols="12">
76
+ <latestproducts />
77
+ </v-col>
78
+ </v-row>
79
+ </div>
80
+ </template>
81
+
82
+ <script setup>
83
+ import {
84
+ ref,
85
+ computed,
86
+ onMounted
87
+ } from 'vue';
88
+ import latestproducts from '#commerce/app/components/catalog/product/latestproducts.vue';
89
+
90
+ // State
91
+ const locations = ref([]);
92
+ const selectedLocation = ref(null);
93
+ const searchAddress = ref('');
94
+ const selectedRadius = ref(25);
95
+ const mapZoom = ref(12);
96
+ const loading = ref(false);
97
+ const error = ref(null);
98
+
99
+ // Constants
100
+ const radiusOptions = [{
101
+ title: '10 miles',
102
+ value: 10
103
+ },
104
+ {
105
+ title: '25 miles',
106
+ value: 25
107
+ },
108
+ {
109
+ title: '50 miles',
110
+ value: 50
111
+ },
112
+ {
113
+ title: '100 miles',
114
+ value: 100
115
+ }
116
+ ];
117
+
118
+ // Computed
119
+ const mapCenter = computed(() => {
120
+ if (selectedLocation.value) {
121
+ return [selectedLocation.value.latitude, selectedLocation.value.longitude];
122
+ }
123
+ if (locations.value.length) {
124
+ return [locations.value[0].latitude, locations.value[0].longitude];
125
+ }
126
+ return [47.21322, -1.559482]; // Default center
127
+ });
128
+
129
+ // Methods
130
+ const loadLocations = async () => {
131
+ try {
132
+ loading.value = true;
133
+ const result = await getPickupLocations();
134
+ locations.value = result.items || [];
135
+ } catch (err) {
136
+ error.value = err.message;
137
+ console.error('Error loading locations:', err);
138
+ } finally {
139
+ loading.value = false;
140
+ }
141
+ };
142
+
143
+ const searchByAddress = async () => {
144
+ try {
145
+ loading.value = true;
146
+ error.value = null;
147
+
148
+ // Get coordinates from address using browser's geolocation API
149
+ const coordinates = await getCoordinatesFromAddress(searchAddress.value);
150
+
151
+ const searchParams = {
152
+ searchTerm: searchAddress.value,
153
+ latitude: coordinates.latitude,
154
+ longitude: coordinates.longitude,
155
+ radius: selectedRadius.value
156
+ };
157
+
158
+ const result = await getPickupLocationsByDistance(searchParams);
159
+ locations.value = result.items || [];
160
+
161
+ if (locations.value.length) {
162
+ mapZoom.value = 12;
163
+ selectedLocation.value = locations.value[0];
164
+ }
165
+ } catch (err) {
166
+ error.value = err.message;
167
+ console.error('Error searching locations:', err);
168
+ } finally {
169
+ loading.value = false;
170
+ }
171
+ };
172
+
173
+ const selectLocation = (location) => {
174
+ selectedLocation.value = location;
175
+ mapZoom.value = 15;
176
+ };
177
+
178
+ const formatDistance = (distance) => {
179
+ return `${Math.round(distance * 10) / 10} miles`;
180
+ };
181
+
182
+ // Helper function to get coordinates from address
183
+ const getCoordinatesFromAddress = async (address) => {
184
+ try {
185
+ // You might want to use a geocoding service here
186
+ // For now, returning mock coordinates
187
+ return {
188
+ latitude: 47.21322,
189
+ longitude: -1.559482
190
+ };
191
+ } catch (error) {
192
+ console.error('Error getting coordinates:', error);
193
+ throw new Error('Unable to get coordinates from address');
194
+ }
195
+ };
196
+
197
+ // Directus setup
198
+ const {
199
+ $directus,
200
+ $readItem
201
+ } = useNuxtApp();
202
+
203
+ const {
204
+ data: pickupBlocks
205
+ } = await useAsyncData('pickupBlocks', () => {
206
+ return $directus.request($readItem('page_blocks', '10', {
207
+ fields: ['*', 'media.directus_files_id.filename_disk', 'content.*'],
208
+ }))
209
+ });
210
+
211
+ const {
212
+ data: pickupLocations
213
+ } = await useAsyncData('pickupLocations', () => {
214
+ return $directus.request($readItem('pages', '33', {
215
+ fields: ['*', 'image.*'],
216
+ }))
217
+ });
218
+
219
+ // Initial load
220
+ onMounted(() => {
221
+ loadLocations();
222
+ });
223
+
224
+ // Meta
225
+ definePageMeta({
226
+ layout: 'nolive',
227
+ });
228
+
229
+ useHead({
230
+ title: 'Pickup Locations',
231
+ });
232
+ </script>
233
+
234
+ <style scoped>
235
+ .customerDashboard {
236
+ padding: 20px;
237
+ }
238
+ </style>
@@ -0,0 +1,90 @@
1
+ <template>
2
+ <div>
3
+ <v-card variant="text">
4
+ <v-toolbar
5
+ :style="`background-color: ${showcasePage?.color}; color: ${showcasePage?.colortext} !important`">
6
+ <v-toolbar-title>{{ showcasePage?.name }}</v-toolbar-title>
7
+
8
+ <v-tabs v-model="currentTab" fixed-tabs>
9
+
10
+ <v-tab :value="'create'">
11
+ <createshowcase />
12
+ </v-tab>
13
+ </v-tabs>
14
+ </v-toolbar>
15
+
16
+ <v-tabs-window v-model="currentTab">
17
+ <v-tabs-window-item v-for="(menu, index) in showcaseBar" :key="menu?.value ?? index"
18
+ :value="menu?.value ?? menu">
19
+ <component :is="contentComponents[index] || null" />
20
+ </v-tabs-window-item>
21
+ </v-tabs-window>
22
+ </v-card>
23
+
24
+ <section data-bs-version="5.1" class="features03 flavorm5 cid-uHg490M3EL" id="features03-at">
25
+ <div class="container">
26
+ <div class="row">
27
+ <div class="item features-image col-12 col-lg-6" v-for="(list, index) in lists" :key="index">
28
+ <listShowcases :list="list" />
29
+ </div>
30
+ </div>
31
+ </div>
32
+ </section>
33
+ </div>
34
+ </template>
35
+
36
+ <script setup>
37
+ import createshowcase from '@/components/catalog/product/add-showcase.vue'
38
+ import listShowcases from '#lists/app/components/related/list.vue'
39
+
40
+ const {
41
+ $directus,
42
+ $readItem,
43
+ $readItems
44
+ } = useNuxtApp()
45
+
46
+ // current selected tab value (matches menu.value)
47
+ const currentTab = ref(null);
48
+
49
+ const {
50
+ data: showcasePage
51
+ } = await useAsyncData('showcasePage', () => {
52
+ return $directus.request($readItem('pages', '115', {
53
+ fields: ['*', {
54
+ '*': ['*']
55
+ }]
56
+ }))
57
+ })
58
+
59
+ const {
60
+ data: lists
61
+ } = await useAsyncData('lists', () => {
62
+ return $directus.request($readItems('lists', {
63
+ fields: ['*', {
64
+ '*': ['*']
65
+ }],
66
+ filter: {
67
+ lists_type: {
68
+ lists_type_id: {
69
+ name: {
70
+ _eq: "Showcase"
71
+ }
72
+ }
73
+ },
74
+ status: {
75
+ _eq: "Public"
76
+ }
77
+ }
78
+ }))
79
+ })
80
+
81
+ const {
82
+ data: showcaseBar
83
+ } = await useAsyncData('showcaseBar', () => {
84
+ return $directus.request($readItem('navigation', '54', {
85
+ fields: ['*', {
86
+ '*': ['*']
87
+ }]
88
+ }))
89
+ })
90
+ </script>
@@ -0,0 +1,60 @@
1
+ <template>
2
+ <v-container class="text-center">
3
+ <v-row justify="center">
4
+ <v-col cols="12" md="8">
5
+ <v-card class="pa-6">
6
+ <v-icon color="success" size="64" class="mb-4">mdi-check-circle</v-icon>
7
+ <h1 class="text-h4 mb-4">Thank You for Your Purchase!</h1>
8
+ <p class="text-body-1 mb-4">
9
+ Your order has been successfully placed. We've sent a confirmation email to your registered email address.
10
+ </p>
11
+ <p class="text-body-1 mb-6">
12
+ Order ID: {{ orderId }}
13
+ </p>
14
+ <v-btn
15
+ color="primary"
16
+ @click="router.push('/')"
17
+ class="mr-4"
18
+ >
19
+ Continue Shopping
20
+ </v-btn>
21
+ <v-btn
22
+ color="secondary"
23
+ @click="router.push('/orders')"
24
+ >
25
+ View Orders
26
+ </v-btn>
27
+ </v-card>
28
+ </v-col>
29
+ </v-row>
30
+ </v-container>
31
+ </template>
32
+
33
+ <script setup>
34
+ import { ref, onMounted } from 'vue';
35
+ import { useRoute, useRouter } from 'vue-router';
36
+
37
+ const route = useRoute();
38
+ const router = useRouter();
39
+ const orderId = ref('');
40
+
41
+ onMounted(async () => {
42
+ const sessionId = route.query.session_id;
43
+ if (sessionId) {
44
+ try {
45
+ // Here you would typically fetch the order details from your backend
46
+ // using the session ID
47
+ orderId.value = sessionId;
48
+ } catch (error) {
49
+ console.error('Error fetching order details:', error);
50
+ }
51
+ }
52
+ });
53
+ </script>
54
+
55
+ <style scoped>
56
+ .v-card {
57
+ border-radius: 8px;
58
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
59
+ }
60
+ </style>
@@ -0,0 +1,54 @@
1
+ <template>
2
+ <v-row justify="center">
3
+ <v-dialog v-model="dialog" :scrim="false" transition="dialog-bottom-transition">
4
+ <template v-slot:activator="{ props }">
5
+ <v-btn v-bind="props" class="rightAddBtn">
6
+ <v-icon start icon="fas:fa fa-plus"></v-icon>Create a Brand
7
+ </v-btn>
8
+ </template>
9
+ <v-card class="b-1">
10
+ <v-card-title>
11
+ <h3>Create New Brand</h3>
12
+ </v-card-title>
13
+
14
+ <v-card-text>
15
+ <div v-if="formError" class="error">{{ formError }}</div>
16
+ <div v-else-if="formSuccess" class="success">{{ formSuccess }}</div>
17
+ <form @submit.prevent="submitForm">
18
+ <DirectusFormElement v-for="field in brandFields" :key="field.field" :field="field" v-model="form[field.field]" />
19
+ <v-btn type="submit">Submit</v-btn>
20
+ </form>
21
+ </v-card-text>
22
+ </v-card>
23
+ </v-dialog>
24
+ </v-row>
25
+
26
+ </template>
27
+
28
+ <script setup>
29
+ import { ref } from 'vue'
30
+ import DirectusFormElement from '#shared/app/components/ui/forms/DirectusFormElement.vue'
31
+ import { useDirectusForm } from '#shared/app/composables/globals/useDirectusForm'
32
+
33
+ const dialog = ref(false)
34
+ const { $directus, $readFieldsByCollection } = useNuxtApp()
35
+
36
+ const { data, error } = await useAsyncData('brands', async () => {
37
+ return $directus.request($readFieldsByCollection('brands'))
38
+ })
39
+
40
+ // guard against undefined/null data.value and empty arrays
41
+ if (error.value || data.value == null || (data.value?.length ?? 0) === 0) {
42
+ console.error(error)
43
+ throw createError({
44
+ statusCode: 404,
45
+ statusMessage: 'Brand not found'
46
+ })
47
+ }
48
+
49
+ const brandFields = data
50
+
51
+
52
+ // use composable for form handling (validation, submit, provide context)
53
+ const { form, formError, formSuccess, submitForm } = useDirectusForm('brands', brandFields, { clearOnSuccess: true, closeDialogRef: dialog })
54
+ </script>
@@ -0,0 +1,54 @@
1
+ <template>
2
+ <v-row justify="center">
3
+ <v-dialog v-model="dialog" :scrim="false" transition="dialog-bottom-transition">
4
+ <template v-slot:activator="{ props }">
5
+ <v-btn v-bind="props" class="rightAddBtn">
6
+ <v-icon start icon="fas:fa fa-plus"></v-icon>Create a Coupon
7
+ </v-btn>
8
+ </template>
9
+ <v-card class="b-1">
10
+ <v-card-title>
11
+ <h3>Create New Coupon</h3>
12
+ </v-card-title>
13
+
14
+ <v-card-text>
15
+ <div v-if="formError" class="error">{{ formError }}</div>
16
+ <div v-else-if="formSuccess" class="success">{{ formSuccess }}</div>
17
+ <form @submit.prevent="submitForm">
18
+ <DirectusFormElement v-for="field in couponFields" :key="field.field" :field="field" v-model="form[field.field]" />
19
+ <v-btn type="submit">Submit</v-btn>
20
+ </form>
21
+ </v-card-text>
22
+ </v-card>
23
+ </v-dialog>
24
+ </v-row>
25
+
26
+ </template>
27
+
28
+ <script setup>
29
+ import { ref } from 'vue'
30
+ import DirectusFormElement from '#shared/app/components/ui/forms/DirectusFormElement.vue'
31
+ import { useDirectusForm } from '#shared/app/composables/globals/useDirectusForm'
32
+
33
+ const dialog = ref(false)
34
+ const { $directus, $readFieldsByCollection } = useNuxtApp()
35
+
36
+ const { data, error } = await useAsyncData('incentives', async () => {
37
+ return $directus.request($readFieldsByCollection('incentives'))
38
+ })
39
+
40
+ // guard against undefined/null data.value and empty arrays
41
+ if (error.value || data.value == null || (data.value?.length ?? 0) === 0) {
42
+ console.error(error)
43
+ throw createError({
44
+ statusCode: 404,
45
+ statusMessage: 'Coupon not found'
46
+ })
47
+ }
48
+
49
+ const couponFields = data
50
+
51
+
52
+ // use composable for form handling (validation, submit, provide context)
53
+ const { form, formError, formSuccess, submitForm } = useDirectusForm('incentives', couponFields, { clearOnSuccess: true, closeDialogRef: dialog })
54
+ </script>
@@ -0,0 +1,127 @@
1
+ <template>
2
+ <div>
3
+ <!---->
4
+ <v-row>
5
+ <v-col cols="12">
6
+ <v-sheet class="mx-auto sliderProducts row align-items-stretch items-row justify-content-center">
7
+ <h4 style="left: 15px; position: relative;">{{ callouts?.menus?.[0]?.name }}</h4>
8
+ <v-slide-group v-model="model" class="pa-4" selected-class="bg-success" show-arrows>
9
+ <v-slide-group-item v-slot="{ isSelected, toggle, selectedClass }"
10
+ v-for="products in mycards" :key="products">
11
+ <productCard :product="products" :class="['ma-4', selectedClass]"
12
+ @click="toggle" />
13
+ <div class="d-flex fill-height align-center justify-center">
14
+ <v-scale-transition>
15
+ <v-icon v-if="isSelected" color="white" icon="mdi-close-circle-outline"
16
+ size="48"></v-icon>
17
+ </v-scale-transition>
18
+ </div>
19
+ </v-slide-group-item>
20
+ </v-slide-group>
21
+ </v-sheet>
22
+ </v-col>
23
+
24
+ <v-col cols="12">
25
+ <v-sheet class="mx-auto sliderProducts row align-items-stretch items-row justify-content-center">
26
+ <h4 style="left: 15px; position: relative;">{{ callouts?.menus?.[1]?.name }}</h4>
27
+ <v-slide-group v-model="model" class="pa-4" selected-class="bg-success" show-arrows>
28
+ <v-slide-group-item v-slot="{ isSelected, toggle, selectedClass }"
29
+ v-for="products in cards" :key="products">
30
+ <productCard :product="products" :class="['ma-4', selectedClass]"
31
+ @click="toggle" />
32
+ <div class="d-flex fill-height align-center justify-center">
33
+ <v-scale-transition>
34
+ <v-icon v-if="isSelected" color="white" icon="mdi-close-circle-outline"
35
+ size="48"></v-icon>
36
+ </v-scale-transition>
37
+ </div>
38
+ </v-slide-group-item>
39
+ </v-slide-group>
40
+ </v-sheet>
41
+ </v-col>
42
+ </v-row>
43
+ </div>
44
+ </template>
45
+
46
+ <script setup>
47
+ import productCard from '~/components/catalog/product/productCard.vue'
48
+ import {
49
+ ref,
50
+ onMounted
51
+ } from 'vue';
52
+ import {
53
+ useUserStore
54
+ } from '#auth/app/stores/user'
55
+
56
+ const model = ref(null);
57
+ const userStore = useUserStore()
58
+
59
+ const userDisplayName = computed(() => {
60
+ return userStore.name || userStore.username || 'User'
61
+ })
62
+
63
+ const {
64
+ $directus,
65
+ $readItems,
66
+ $readItem
67
+ } = useNuxtApp()
68
+
69
+ const {
70
+ data: cards
71
+ } = await useAsyncData('cards', () => {
72
+ return $directus.request($readItems('products', {
73
+ fields: ['*',
74
+ 'image.*',
75
+ 'currency.currency_id.*'
76
+ ],
77
+ filter: {
78
+ product_types: {
79
+ product_types_id: {
80
+ name: {
81
+ _eq: "Gift Card"
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }))
87
+ })
88
+
89
+ const {
90
+ data: mycards
91
+ } = await useAsyncData('mycards', () => {
92
+ return $directus.request($readItems('products', {
93
+ fields: ['*',
94
+ 'image.*',
95
+ 'currency.currency_id.*'
96
+ ],
97
+ filter: {
98
+ product_types: {
99
+ product_types_id: {
100
+ name: {
101
+ _eq: "Gift Card"
102
+ }
103
+ }
104
+ },
105
+ user: {
106
+ directus_users: {
107
+ _eq: `${userDisplayName.user.displayName}`
108
+ }
109
+ }
110
+ }
111
+ }))
112
+ })
113
+
114
+ const {
115
+ data: callouts
116
+ } = await useAsyncData('callouts', () => {
117
+ return $directus.request($readItem('callouts', '4'))
118
+ })
119
+
120
+ useHead({
121
+ title: 'Gift Cards',
122
+ })
123
+
124
+ definePageMeta({
125
+ middleware: ['authenticated'],
126
+ })
127
+ </script>