@shopbite-de/storefront 1.18.1 → 1.18.3

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 (31) hide show
  1. package/app/app.vue +3 -9
  2. package/app/components/Cart/Item.vue +5 -5
  3. package/app/components/Category/Listing.vue +141 -92
  4. package/app/components/Checkout/DeliveryTimeSelect.vue +8 -6
  5. package/app/components/Checkout/PaymentAndDelivery.vue +31 -33
  6. package/app/components/Checkout/PaymentMethod.vue +1 -1
  7. package/app/components/Checkout/ShippingMethod.vue +1 -1
  8. package/app/components/Checkout/Summary.vue +37 -48
  9. package/app/components/Header/Right.vue +3 -3
  10. package/app/components/Header/Title.vue +7 -14
  11. package/app/components/Header.vue +2 -2
  12. package/app/components/ImageGallery.vue +26 -13
  13. package/app/components/Product/Card.vue +13 -11
  14. package/app/components/Product/CardSkeleton.vue +26 -0
  15. package/app/components/Product/{Detail2.vue → Detail.vue} +1 -1
  16. package/app/components/User/Detail.vue +2 -2
  17. package/app/composables/useShopBiteConfig.ts +5 -20
  18. package/app/pages/bestellung/bestaetigen.vue +14 -0
  19. package/app/pages/bestellung/warenkorb.vue +49 -0
  20. package/app/pages/bestellung/zahlung-versand.vue +23 -0
  21. package/app/pages/bestellung.vue +36 -84
  22. package/app/pages/index.vue +1 -1
  23. package/app/pages/kontakt.vue +1 -1
  24. package/app/pages/speisekarte/[...all].vue +1 -0
  25. package/app/stores/checkout.ts +22 -0
  26. package/nuxt.config.ts +5 -0
  27. package/package.json +3 -1
  28. package/test/e2e/simple-checkout-as-recurring-customer.test.ts +8 -8
  29. package/test/nuxt/useShopBiteConfig.test.ts +16 -20
  30. package/test/nuxt/HeaderTitle.test.ts +0 -42
  31. /package/app/components/Product/{Configurator2.vue → Configurator.vue} +0 -0
package/app/app.vue CHANGED
@@ -7,11 +7,11 @@ const TOAST_CONFIG = {
7
7
  title: "Wir haben geöffnet!",
8
8
  color: "primary" as const,
9
9
  progress: false,
10
- duration: 0,
10
+ duration: 5000,
11
11
  icon: "i-lucide-party-popper",
12
12
  actions: [
13
13
  {
14
- icon: "i-lucide-pizza",
14
+ icon: "i-lucide-utensils-crossed",
15
15
  label: "Zur Speisekarte",
16
16
  color: "neutral" as const,
17
17
  variant: "outline" as const,
@@ -89,14 +89,8 @@ if (import.meta.client) {
89
89
  }
90
90
  }
91
91
 
92
- const { refresh: refreshToppings } = useShopBiteConfig();
93
-
94
92
  onMounted(async () => {
95
- await Promise.all([
96
- refreshHolidays(),
97
- refreshBusinessHours(),
98
- refreshToppings(),
99
- ]);
93
+ await Promise.all([refreshHolidays(), refreshBusinessHours()]);
100
94
  refreshCart();
101
95
  displayStoreStatus();
102
96
  });
@@ -64,7 +64,7 @@ const handleRemoveItem = () => {
64
64
  ? cartItem?.children?.[0]?.payload?.options
65
65
  : cartItem?.payload?.options"
66
66
  :key="option.group + option.option"
67
- class="text-sm text-pretty text-toned mt-1"
67
+ class="text-sm text-pretty text-muted mt-1"
68
68
  >
69
69
  {{ option.group }}: {{ option.option }}
70
70
  </p>
@@ -84,14 +84,14 @@ const handleRemoveItem = () => {
84
84
  :min="1"
85
85
  :max="100"
86
86
  class="max-w-46"
87
- aria-label="Item quantity"
87
+ aria-label="Menge"
88
88
  />
89
89
  <UButton
90
90
  v-if="withDeleteButton"
91
91
  icon="i-lucide-trash"
92
92
  variant="soft"
93
93
  color="neutral"
94
- aria-label="Remove item from cart"
94
+ aria-label="Artikel entfernen"
95
95
  @click="handleRemoveItem"
96
96
  />
97
97
  </div>
@@ -101,14 +101,14 @@ const handleRemoveItem = () => {
101
101
  icon="i-lucide-trash"
102
102
  variant="outline"
103
103
  color="error"
104
- aria-label="Remove item from cart"
104
+ aria-label="Artikel entfernen"
105
105
  @click="handleRemoveItem"
106
106
  />
107
107
  </div>
108
108
 
109
109
  <!-- Empty state -->
110
110
  <div v-else class="text-center py-4">
111
- <p class="text-toned">Warenkorb ist leer...</p>
111
+ <p class="text-muted">Warenkorb ist leer...</p>
112
112
  </div>
113
113
  </div>
114
114
  </template>
@@ -46,12 +46,14 @@ const {
46
46
  loading,
47
47
  search,
48
48
  getElements,
49
+ getCurrentListing,
49
50
  getCurrentSortingOrder,
50
51
  getSortingOrders,
51
52
  changeCurrentSortingOrder,
52
53
  getAvailableFilters,
53
54
  getCurrentFilters,
54
55
  setCurrentFilters,
56
+ setInitialListing,
55
57
  } = useListing({
56
58
  listingType: "categoryListing",
57
59
  categoryId: props.id,
@@ -85,9 +87,27 @@ const selectedListingFilters = computed<ShortcutFilterParam[]>(() => {
85
87
  ];
86
88
  });
87
89
 
88
- await useAsyncData(`listing${categoryId.value}`, async () => {
89
- await search(searchCriteria);
90
- });
90
+ const nuxtApp = useNuxtApp();
91
+ const { data: listingPayload, pending } = await useAsyncData(
92
+ `listing${categoryId.value}`,
93
+ async () => {
94
+ await search(searchCriteria);
95
+ // Return the result so it gets serialized into the SSR payload.
96
+ // On the client, useAsyncData will restore this without re-running search().
97
+ return getCurrentListing.value;
98
+ },
99
+ );
100
+
101
+ // Populate useListing state from the SSR payload on the client.
102
+ // useListing uses plain refs (not useState), so its state is not automatically
103
+ // hydrated — we restore it via setInitialListing.
104
+ if (listingPayload.value) {
105
+ await setInitialListing(listingPayload.value);
106
+ }
107
+
108
+ // During SSR hydration, pending may briefly be true before the payload cache is applied.
109
+ // Suppress the skeleton in that window to prevent a hydration mismatch.
110
+ const showSkeleton = computed(() => pending.value && !nuxtApp.isHydrating);
91
111
 
92
112
  watch(selectedListingFilters, (newFilters, oldFilters) => {
93
113
  if (newFilters[0]?.value === oldFilters?.[0]?.value) {
@@ -139,66 +159,77 @@ const moreThanOneFilterAndOption = computed<boolean>(
139
159
  :items="getSortingOrders"
140
160
  placeholder="Sortierung"
141
161
  />
142
- <UDrawer
143
- v-if="moreThanOneFilterAndOption"
144
- class="lg:hidden"
145
- title="Filter"
146
- direction="right"
147
- >
148
- <UButton
149
- label="Filter"
150
- icon="i-lucide-sliders-horizontal"
151
- color="neutral"
152
- variant="subtle"
153
- />
162
+ <ClientOnly v-if="moreThanOneFilterAndOption">
163
+ <UDrawer class="lg:hidden" title="Filter" direction="right">
164
+ <UButton
165
+ label="Filter"
166
+ icon="i-lucide-sliders-horizontal"
167
+ color="neutral"
168
+ variant="subtle"
169
+ />
154
170
 
155
- <template #body>
156
- <div class="flex flex-col gap-4">
157
- <div
158
- v-for="filter in propertyFilters"
159
- :key="filter.id"
160
- class="flex flex-col gap-4"
161
- >
162
- <UCollapsible
163
- class="flex flex-col gap-2 w-48"
164
- :default-open="true"
171
+ <template #body>
172
+ <div class="flex flex-col gap-4">
173
+ <div
174
+ v-for="filter in propertyFilters"
175
+ :key="filter.id"
176
+ class="flex flex-col gap-4"
165
177
  >
166
- <UButton
167
- :label="filter.translated.name"
168
- color="neutral"
169
- variant="subtle"
170
- trailing-icon="i-lucide-chevron-down"
171
- block
172
- :ui="{
173
- trailingIcon:
174
- 'group-data-[state=open]:rotate-180 transition-transform duration-200',
175
- }"
176
- />
177
-
178
- <template #content>
179
- <UCheckboxGroup
180
- v-model="selectedPropertyFilters"
181
- :items="filter.options"
182
- value-key="id"
183
- label-key="translated.name"
178
+ <UCollapsible
179
+ class="flex flex-col gap-2 w-48"
180
+ :default-open="true"
181
+ >
182
+ <UButton
183
+ :label="filter.translated.name"
184
+ color="neutral"
185
+ variant="subtle"
186
+ trailing-icon="i-lucide-chevron-down"
187
+ block
188
+ :ui="{
189
+ trailingIcon:
190
+ 'group-data-[state=open]:rotate-180 transition-transform duration-200',
191
+ }"
184
192
  />
185
- </template>
186
- </UCollapsible>
193
+
194
+ <template #content>
195
+ <UCheckboxGroup
196
+ v-model="selectedPropertyFilters"
197
+ :items="filter.options"
198
+ value-key="id"
199
+ label-key="translated.name"
200
+ />
201
+ </template>
202
+ </UCollapsible>
203
+ </div>
204
+ <UButton
205
+ label="Zurücksetzen"
206
+ variant="outline"
207
+ block
208
+ @click="handleFilterRest"
209
+ />
187
210
  </div>
188
- <UButton
189
- label="Zurücksetzten"
190
- variant="outline"
191
- block
192
- @click="handleFilterRest"
193
- />
194
- </div>
211
+ </template>
212
+ </UDrawer>
213
+ <template #fallback>
214
+ <USkeleton class="h-8 w-20 lg:hidden" />
195
215
  </template>
196
- </UDrawer>
216
+ </ClientOnly>
197
217
  </div>
198
218
 
199
- <Loading v-if="loading" text="Produkte werden geladen..." size="lg" />
219
+ <div
220
+ v-if="showSkeleton"
221
+ class="flex flex-col gap-4"
222
+ aria-busy="true"
223
+ aria-label="Produkte werden geladen"
224
+ >
225
+ <LazyProductCardSkeleton v-for="i in 6" :key="i" />
226
+ </div>
200
227
 
201
- <div v-else class="flex flex-col gap-4">
228
+ <div
229
+ v-else
230
+ class="flex flex-col gap-4 transition-opacity duration-200"
231
+ :class="{ 'opacity-40 pointer-events-none': loading }"
232
+ >
202
233
  <ProductCard
203
234
  v-for="product in getElements"
204
235
  :key="product.id"
@@ -212,46 +243,64 @@ const moreThanOneFilterAndOption = computed<boolean>(
212
243
 
213
244
  <template #right>
214
245
  <UPageAside>
215
- <div v-if="moreThanOneFilterAndOption" class="flex flex-col gap-4">
216
- <h2 class="text-3xl md:text-4xl mb-3 pb-2">Filter</h2>
217
- <div
218
- v-for="filter in propertyFilters"
219
- :key="filter.id"
220
- class="flex flex-col gap-4"
221
- >
222
- <UCollapsible
223
- class="flex flex-col gap-2 w-48"
224
- :default-open="true"
246
+ <ClientOnly v-if="moreThanOneFilterAndOption">
247
+ <div class="flex flex-col gap-4">
248
+ <h2 class="text-3xl md:text-4xl mb-3 pb-2">Filter</h2>
249
+ <div
250
+ v-for="filter in propertyFilters"
251
+ :key="filter.id"
252
+ class="flex flex-col gap-4"
225
253
  >
226
- <UButton
227
- :label="filter.translated.name"
228
- color="neutral"
229
- variant="subtle"
230
- trailing-icon="i-lucide-chevron-down"
231
- block
232
- :ui="{
233
- trailingIcon:
234
- 'group-data-[state=open]:rotate-180 transition-transform duration-200',
235
- }"
236
- />
237
-
238
- <template #content>
239
- <UCheckboxGroup
240
- v-model="selectedPropertyFilters"
241
- :items="filter.options"
242
- value-key="id"
243
- label-key="translated.name"
254
+ <UCollapsible
255
+ class="flex flex-col gap-2 w-48"
256
+ :default-open="true"
257
+ >
258
+ <UButton
259
+ :label="filter.translated.name"
260
+ color="neutral"
261
+ variant="subtle"
262
+ trailing-icon="i-lucide-chevron-down"
263
+ block
264
+ :ui="{
265
+ trailingIcon:
266
+ 'group-data-[state=open]:rotate-180 transition-transform duration-200',
267
+ }"
244
268
  />
245
- </template>
246
- </UCollapsible>
269
+
270
+ <template #content>
271
+ <UCheckboxGroup
272
+ v-model="selectedPropertyFilters"
273
+ :items="filter.options"
274
+ value-key="id"
275
+ label-key="translated.name"
276
+ />
277
+ </template>
278
+ </UCollapsible>
279
+ </div>
280
+ <UButton
281
+ label="Zurücksetzen"
282
+ variant="outline"
283
+ block
284
+ @click="handleFilterRest"
285
+ />
247
286
  </div>
248
- <UButton
249
- label="Zurücksetzten"
250
- variant="outline"
251
- block
252
- @click="handleFilterRest"
253
- />
254
- </div>
287
+ <template #fallback>
288
+ <div class="flex flex-col gap-4">
289
+ <USkeleton class="h-9 w-20" />
290
+ <div class="flex flex-col gap-2">
291
+ <USkeleton class="h-8 w-48" />
292
+ <USkeleton class="h-4 w-36" />
293
+ <USkeleton class="h-4 w-32" />
294
+ <USkeleton class="h-4 w-40" />
295
+ </div>
296
+ <div class="flex flex-col gap-2">
297
+ <USkeleton class="h-8 w-48" />
298
+ <USkeleton class="h-4 w-36" />
299
+ <USkeleton class="h-4 w-32" />
300
+ </div>
301
+ </div>
302
+ </template>
303
+ </ClientOnly>
255
304
  </UPageAside>
256
305
  </template>
257
306
  </UPage>
@@ -136,24 +136,26 @@ function handleTimeInput(event: Event): void {
136
136
  <template>
137
137
  <div v-if="isClosedHoliday(now) === false" class="flex flex-col gap-2 mt-4">
138
138
  <div class="flex flex-row items-center justify-between gap-4">
139
- <div>Wunschlieferung- oder Abholzeit ab:</div>
139
+ <label for="delivery-time" class="flex-1">
140
+ Wunschlieferung- oder Abholzeit ab:
141
+ </label>
140
142
  <client-only>
141
- <input
143
+ <UInput
144
+ id="delivery-time"
142
145
  type="time"
143
146
  :min="minTime ?? undefined"
144
147
  :max="maxTime ?? undefined"
145
148
  :disabled="isClosedToday || isClosedHoliday(now) === true"
146
- :value="selected"
149
+ :model-value="selected"
147
150
  step="300"
148
- class="border rounded px-2 py-1"
149
151
  @input="handleTimeInput"
150
152
  />
151
153
  </client-only>
152
154
  </div>
153
- <p v-if="validationError" class="text-sm text-red-600">
155
+ <p v-if="validationError" class="text-sm text-error">
154
156
  {{ validationError }}
155
157
  </p>
156
- <p v-else class="text-sm text-gray-500">{{ helperText }}</p>
158
+ <p v-else class="text-sm text-muted">{{ helperText }}</p>
157
159
  <UBadge
158
160
  :label="deliveryTimeInfo"
159
161
  icon="i-lucide-clock"
@@ -82,42 +82,40 @@ watch(
82
82
  </script>
83
83
 
84
84
  <template>
85
- <UContainer>
86
- <div class="flex flex-col md:flex-row justify-between gap-4">
87
- <div class="basis-1/2">
88
- <div class="flex flex-row items-center gap-4">
89
- <UIcon name="i-lucide-badge-euro" class="size-8" />
90
- <h2 class="text-2xl text-blackish my-8">Zahlungsarten</h2>
91
- <UButton
92
- to="/zahlung-und-versand"
93
- size="md"
94
- variant="ghost"
95
- icon="i-lucide-circle-question-mark"
96
- />
97
- </div>
98
- <URadioGroup
99
- v-model="selectedPaymentMethodId"
100
- :items="selectablePaymentMethods"
101
- variant="card"
85
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
86
+ <div class="flex flex-col gap-4">
87
+ <div class="flex items-center gap-2">
88
+ <UIcon name="i-lucide-badge-euro" class="size-5 text-muted" />
89
+ <h2 class="text-lg font-semibold">Zahlungsarten</h2>
90
+ <UButton
91
+ to="/zahlung-und-versand"
92
+ size="sm"
93
+ variant="ghost"
94
+ icon="i-lucide-circle-help"
102
95
  />
103
96
  </div>
104
- <div class="basis-1/2">
105
- <div class="flex flex-row items-center gap-4">
106
- <UIcon name="i-lucide-car" class="size-8" />
107
- <h2 class="text-2xl text-blackish my-8">Versandarten</h2>
108
- <UButton
109
- to="/zahlung-und-versand"
110
- size="md"
111
- variant="ghost"
112
- icon="i-lucide-circle-question-mark"
113
- />
114
- </div>
115
- <URadioGroup
116
- v-model="selectedShippingMethodId"
117
- :items="selectableShippingMethods"
118
- variant="card"
97
+ <URadioGroup
98
+ v-model="selectedPaymentMethodId"
99
+ :items="selectablePaymentMethods"
100
+ variant="card"
101
+ />
102
+ </div>
103
+ <div class="flex flex-col gap-4">
104
+ <div class="flex items-center gap-2">
105
+ <UIcon name="i-lucide-car" class="size-5 text-muted" />
106
+ <h2 class="text-lg font-semibold">Versandarten</h2>
107
+ <UButton
108
+ to="/zahlung-und-versand"
109
+ size="sm"
110
+ variant="ghost"
111
+ icon="i-lucide-circle-help"
119
112
  />
120
113
  </div>
114
+ <URadioGroup
115
+ v-model="selectedShippingMethodId"
116
+ :items="selectableShippingMethods"
117
+ variant="card"
118
+ />
121
119
  </div>
122
- </UContainer>
120
+ </div>
123
121
  </template>
@@ -22,7 +22,7 @@ const { paymentMethod } = toRefs(props);
22
22
  <h3 class="text-base text-pretty font-semibold text-highlighted">
23
23
  Zahlart
24
24
  </h3>
25
- <p class="text-[15px] text-pretty text-toned mt-1">
25
+ <p class="text-[15px] text-pretty text-muted mt-1">
26
26
  {{ paymentMethod.distinguishableName }}
27
27
  </p>
28
28
  </div>
@@ -22,7 +22,7 @@ const { shippingMethod } = toRefs(props);
22
22
  <h3 class="text-base text-pretty font-semibold text-highlighted">
23
23
  Versandart
24
24
  </h3>
25
- <p class="text-[15px] text-pretty text-toned mt-1">
25
+ <p class="text-[15px] text-pretty text-muted mt-1">
26
26
  {{ shippingMethod.name }}
27
27
  </p>
28
28
  </div>
@@ -23,8 +23,6 @@ onMounted(() => {
23
23
  });
24
24
  });
25
25
 
26
- watch(isCheckoutEnabled, () => console.log(isCheckoutEnabled.value));
27
-
28
26
  useIntervalFn(refresh, 10000);
29
27
 
30
28
  async function handleCreateOrder() {
@@ -63,10 +61,6 @@ const isValidToProceed = computed(
63
61
  const selectedDeliveryTime = ref("");
64
62
  const isValidTime = ref(true);
65
63
 
66
- watch(selectedDeliveryTime, (newValue) => {
67
- console.log(newValue);
68
- });
69
-
70
64
  const checkoutButtonLabel = computed<string>(() => {
71
65
  if (!customerDataAvailable.value) {
72
66
  return "Bitte einloggen oder Kundendaten erfassen";
@@ -85,52 +79,47 @@ const checkoutButtonLabel = computed<string>(() => {
85
79
  </script>
86
80
 
87
81
  <template>
88
- <UContainer class="my-16">
89
- <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
82
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-8 py-8">
83
+ <div class="flex flex-col gap-6">
90
84
  <div class="flex flex-col gap-4">
91
- <h3 class="text-xl font-bold">Kundendaten</h3>
85
+ <h3 class="text-lg font-semibold">Kundendaten</h3>
92
86
  <UserDetail v-if="customerDataAvailable" />
93
- <div v-else>Bitte vorher einloggen oder Kundendaten erfassen</div>
94
- <div class="flex flex-col gap-4">
95
- <h3 class="text-xl font-bold">Versand- und Zahlung</h3>
96
- <CheckoutPaymentMethod :payment-method="selectedPaymentMethod" />
97
- <CheckoutShippingMethod :shipping-method="selectedShippingMethod" />
98
- <CheckoutDeliveryTimeSelect
99
- v-model:valid="isValidTime"
100
- v-model="selectedDeliveryTime"
101
- />
102
- </div>
87
+ <p v-else class="text-muted">
88
+ Bitte vorher einloggen oder Kundendaten erfassen
89
+ </p>
103
90
  </div>
104
91
  <div class="flex flex-col gap-4">
105
- <h3 class="text-xl font-bold">Warenkorb</h3>
106
- <div class="rounded-lg flex flex-col gap-4">
107
- <QuickView
108
- :with-quantity-input="false"
109
- :with-delete-button="false"
110
- class="p-6 bg-elevated"
111
- />
112
- <CheckoutVoucherInput />
113
- <UButton
114
- :icon="
115
- isValidToProceed ? 'i-lucide-shopping-cart' : 'i-lucide-lock'
116
- "
117
- :disabled="!isValidToProceed"
118
- :label="checkoutButtonLabel"
119
- size="xl"
120
- block
121
- @click="handleCreateOrder"
122
- />
123
- <p class="font-light text-muted">
124
- Mit Klick auf den Button "Jetzt bestellen!" erklärst du dich mit
125
- unseren
126
- <ULink to="/agb" class="text-primary font-medium">AGB</ULink> und
127
- <ULink to="/datenschutz" class="text-primary font-medium"
128
- >Datenschutzbestimmungen</ULink
129
- >
130
- einverstanden.
131
- </p>
132
- </div>
92
+ <h3 class="text-lg font-semibold">Versand & Zahlung</h3>
93
+ <CheckoutPaymentMethod :payment-method="selectedPaymentMethod" />
94
+ <CheckoutShippingMethod :shipping-method="selectedShippingMethod" />
95
+ <CheckoutDeliveryTimeSelect
96
+ v-model:valid="isValidTime"
97
+ v-model="selectedDeliveryTime"
98
+ />
133
99
  </div>
134
100
  </div>
135
- </UContainer>
101
+ <div class="flex flex-col gap-4">
102
+ <h3 class="text-lg font-semibold">Warenkorb</h3>
103
+ <UCard>
104
+ <QuickView :with-quantity-input="false" :with-delete-button="false" />
105
+ </UCard>
106
+ <CheckoutVoucherInput />
107
+ <UButton
108
+ :icon="isValidToProceed ? 'i-lucide-shopping-cart' : 'i-lucide-lock'"
109
+ :disabled="!isValidToProceed"
110
+ :label="checkoutButtonLabel"
111
+ size="xl"
112
+ block
113
+ @click="handleCreateOrder"
114
+ />
115
+ <p class="text-sm text-muted">
116
+ Mit Klick auf "Jetzt bestellen!" erklärst du dich mit unseren
117
+ <ULink to="/agb" class="text-primary font-medium">AGB</ULink> und
118
+ <ULink to="/datenschutz" class="text-primary font-medium"
119
+ >Datenschutzbestimmungen</ULink
120
+ >
121
+ einverstanden.
122
+ </p>
123
+ </div>
124
+ </div>
136
125
  </template>
@@ -110,7 +110,7 @@ const dropDownMenu = computed<DropdownMenuItem[][]>(() => {
110
110
  />
111
111
  </UChip>
112
112
  </div>
113
- <UDrawer
113
+ <LazyUDrawer
114
114
  v-if="isCheckoutEnabled"
115
115
  v-model:open="cartQuickViewOpen"
116
116
  title="Warenkorb"
@@ -134,11 +134,11 @@ const dropDownMenu = computed<DropdownMenuItem[][]>(() => {
134
134
  </div>
135
135
  </template>
136
136
  <template #body>
137
- <CartQuickView
137
+ <LazyCartQuickView
138
138
  :with-to-cart-button="true"
139
139
  class="md:min-w-90"
140
140
  @go-to-cart="cartQuickViewOpen = false"
141
141
  />
142
142
  </template>
143
- </UDrawer>
143
+ </LazyUDrawer>
144
144
  </template>
@@ -1,16 +1,9 @@
1
- <script setup lang="ts">
2
- const config = useRuntimeConfig();
3
- const siteName = computed(() => config.public.site.name);
4
- </script>
5
-
1
+ <script setup lang="ts"></script>
6
2
  <template>
7
- <NuxtLink to="/" class="-m-1.5 p-1.5">
8
- <span class="sr-only">{{ siteName }}</span>
9
- <UColorModeImage
10
- alt="Logo"
11
- light="/light/Logo.png"
12
- dark="/dark/Logo.png"
13
- class="h-12 w-auto"
14
- />
15
- </NuxtLink>
3
+ <UColorModeImage
4
+ alt="Logo"
5
+ light="/light/Logo.png"
6
+ dark="/dark/Logo.png"
7
+ width="150"
8
+ />
16
9
  </template>
@@ -17,7 +17,7 @@ const loginSlide = ref(false);
17
17
  </template>
18
18
 
19
19
  <template #body>
20
- <HeaderBody />
20
+ <LazyHeaderBody />
21
21
  </template>
22
22
  </UHeader>
23
23
 
@@ -28,7 +28,7 @@ const loginSlide = ref(false);
28
28
  >
29
29
  <template #body>
30
30
  <div class="h-full m-4">
31
- <UserLoginForm />
31
+ <LazyUserLoginForm />
32
32
  </div>
33
33
  </template>
34
34
  </USlideover>