cloudcommerce 0.32.0 → 0.33.1

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 (179) hide show
  1. package/.github/workflows/test-apps.yml +3 -3
  2. package/CHANGELOG.md +44 -0
  3. package/action.yml +2 -2
  4. package/ecomplus-stores/barra-doce/.github/workflows/build-and-deploy.yml +1 -1
  5. package/ecomplus-stores/barra-doce/.github/workflows/calibreapp-image-actions.yml +1 -1
  6. package/ecomplus-stores/barra-doce/.vscode/settings.json +3 -0
  7. package/ecomplus-stores/barra-doce/functions/many/package.json +3 -3
  8. package/ecomplus-stores/barra-doce/functions/ssr/content/extra-pages/terms.json +1 -1
  9. package/ecomplus-stores/barra-doce/functions/ssr/content/pages/home.json +20 -0
  10. package/ecomplus-stores/barra-doce/functions/ssr/content/pages/products.json +2 -1
  11. package/ecomplus-stores/barra-doce/functions/ssr/content/settings.json +4 -1
  12. package/ecomplus-stores/barra-doce/functions/ssr/package.json +10 -8
  13. package/ecomplus-stores/barra-doce/functions/ssr/public/robots.txt +1 -1
  14. package/ecomplus-stores/barra-doce/functions/ssr/src/assets/style.css +15 -4
  15. package/ecomplus-stores/barra-doce/functions/ssr/src/components/AccountMenu.vue +5 -3
  16. package/ecomplus-stores/barra-doce/functions/ssr/src/components/AccountPage.vue +62 -0
  17. package/ecomplus-stores/barra-doce/functions/ssr/src/components/Banner.vue +6 -3
  18. package/ecomplus-stores/barra-doce/functions/ssr/src/components/Breadcrumbs.astro +44 -0
  19. package/ecomplus-stores/barra-doce/functions/ssr/src/components/CartItem.vue +11 -11
  20. package/ecomplus-stores/barra-doce/functions/ssr/src/components/CartSidebar.vue +16 -13
  21. package/ecomplus-stores/barra-doce/functions/ssr/src/components/CheckoutPage.vue +33 -0
  22. package/ecomplus-stores/barra-doce/functions/ssr/src/components/Collapse.vue +19 -0
  23. package/ecomplus-stores/barra-doce/functions/ssr/src/components/DocDescription.vue +28 -0
  24. package/ecomplus-stores/barra-doce/functions/ssr/src/components/FooterStamps.vue +62 -0
  25. package/ecomplus-stores/barra-doce/functions/ssr/src/components/HeroSlider.vue +14 -9
  26. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ImagesGallery.vue +151 -0
  27. package/ecomplus-stores/barra-doce/functions/ssr/src/components/LoginForm.vue +107 -0
  28. package/ecomplus-stores/barra-doce/functions/ssr/src/components/PitchBar.vue +6 -8
  29. package/ecomplus-stores/barra-doce/functions/ssr/src/components/Prices.vue +3 -3
  30. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ProductCard.vue +22 -22
  31. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ProductDetails.vue +122 -0
  32. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ProductShelf.vue +10 -12
  33. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ProductSpecifications.vue +42 -0
  34. package/ecomplus-stores/barra-doce/functions/ssr/src/components/SearchModal.vue +1 -1
  35. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ShopFooter.vue +7 -58
  36. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ShopHeader.vue +33 -34
  37. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ShopHeaderMenu.vue +5 -5
  38. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ShopHeaderSubmenu.vue +19 -11
  39. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ShopSidenav.vue +10 -11
  40. package/ecomplus-stores/barra-doce/functions/ssr/src/components/ShopSidenavCategory.vue +9 -10
  41. package/ecomplus-stores/barra-doce/functions/ssr/src/components/SkuSelector.vue +58 -0
  42. package/ecomplus-stores/barra-doce/functions/ssr/src/layouts/PageFooter.astro +3 -1
  43. package/ecomplus-stores/barra-doce/functions/ssr/src/layouts/PageHeader.astro +1 -2
  44. package/ecomplus-stores/barra-doce/functions/ssr/src/main/Home.astro +1 -2
  45. package/ecomplus-stores/barra-doce/functions/ssr/src/main/Sections.astro +25 -2
  46. package/ecomplus-stores/barra-doce/functions/ssr/src/main/Wildcard.astro +12 -12
  47. package/ecomplus-stores/barra-doce/functions/ssr/src/pages/[...slug].astro +2 -0
  48. package/ecomplus-stores/barra-doce/functions/ssr/src/pages/_vue.ts +17 -1
  49. package/ecomplus-stores/barra-doce/functions/ssr/src/pages/app/account.astro +34 -0
  50. package/ecomplus-stores/barra-doce/functions/ssr/src/pages/app/index.astro +62 -0
  51. package/ecomplus-stores/barra-doce/functions/ssr/src/pages/index.astro +0 -5
  52. package/ecomplus-stores/barra-doce/functions/ssr/src/pages/~fallback.astro +0 -2
  53. package/ecomplus-stores/barra-doce/functions/ssr/tailwind.config.cjs +0 -1
  54. package/ecomplus-stores/barra-doce/functions/with-apps/package.json +3 -3
  55. package/ecomplus-stores/barra-doce/package.json +2 -2
  56. package/ecomplus-stores/monocard/.editorconfig +13 -0
  57. package/ecomplus-stores/monocard/.eslintrc.cjs +1 -1
  58. package/ecomplus-stores/monocard/.vscode/settings.json +5 -1
  59. package/ecomplus-stores/monocard/functions/many/package.json +3 -3
  60. package/ecomplus-stores/monocard/functions/ssr/content/extra-pages/terms.json +1 -1
  61. package/ecomplus-stores/monocard/functions/ssr/content/pages/home.json +1 -44
  62. package/ecomplus-stores/monocard/functions/ssr/content/pages/products.json +2 -1
  63. package/ecomplus-stores/monocard/functions/ssr/content/settings.json +4 -1
  64. package/ecomplus-stores/monocard/functions/ssr/package.json +9 -7
  65. package/ecomplus-stores/monocard/functions/ssr/public/robots.txt +2 -4
  66. package/ecomplus-stores/monocard/functions/ssr/src/assets/style.css +7 -2
  67. package/ecomplus-stores/monocard/functions/ssr/src/components/AccountMenu.vue +16 -14
  68. package/ecomplus-stores/monocard/functions/ssr/src/components/AccountPage.vue +62 -0
  69. package/ecomplus-stores/monocard/functions/ssr/src/components/Banner.vue +3 -3
  70. package/ecomplus-stores/monocard/functions/ssr/src/components/Breadcrumbs.astro +1 -1
  71. package/ecomplus-stores/monocard/functions/ssr/src/components/CartItem.vue +11 -11
  72. package/ecomplus-stores/monocard/functions/ssr/src/components/CartSidebar.vue +16 -13
  73. package/ecomplus-stores/monocard/functions/ssr/src/components/CheckoutPage.vue +33 -0
  74. package/ecomplus-stores/monocard/functions/ssr/src/components/Collapse.vue +19 -0
  75. package/ecomplus-stores/monocard/functions/ssr/src/components/DemoVideo.vue +1 -1
  76. package/ecomplus-stores/monocard/functions/ssr/src/components/DocDescription.vue +3 -8
  77. package/ecomplus-stores/monocard/functions/ssr/src/components/FeatureTabs.vue +73 -79
  78. package/ecomplus-stores/monocard/functions/ssr/src/components/FooterStamps.vue +63 -0
  79. package/ecomplus-stores/monocard/functions/ssr/src/components/ImagesGallery.vue +154 -0
  80. package/ecomplus-stores/monocard/functions/ssr/src/components/LoginForm.vue +107 -0
  81. package/ecomplus-stores/monocard/functions/ssr/src/components/LottiePhoneNFC.vue +1 -3
  82. package/ecomplus-stores/monocard/functions/ssr/src/components/MonocardCustomizer.vue +21 -22
  83. package/ecomplus-stores/monocard/functions/ssr/src/components/PitchBar.vue +7 -7
  84. package/ecomplus-stores/monocard/functions/ssr/src/components/Prices.vue +3 -3
  85. package/ecomplus-stores/monocard/functions/ssr/src/components/ProductCard.vue +24 -24
  86. package/ecomplus-stores/monocard/functions/ssr/src/components/ProductDetails.vue +122 -0
  87. package/ecomplus-stores/monocard/functions/ssr/src/components/ProductShelf.vue +11 -11
  88. package/ecomplus-stores/monocard/functions/ssr/src/components/ProductSpecifications.vue +42 -0
  89. package/ecomplus-stores/monocard/functions/ssr/src/components/SearchModal.vue +1 -1
  90. package/ecomplus-stores/monocard/functions/ssr/src/components/ShopFooter.vue +10 -62
  91. package/ecomplus-stores/monocard/functions/ssr/src/components/ShopHeader.vue +25 -31
  92. package/ecomplus-stores/monocard/functions/ssr/src/components/ShopHeaderMenu.vue +8 -8
  93. package/ecomplus-stores/monocard/functions/ssr/src/components/ShopSidenav.vue +10 -11
  94. package/ecomplus-stores/monocard/functions/ssr/src/components/ShopSidenavCategory.vue +9 -10
  95. package/ecomplus-stores/monocard/functions/ssr/src/components/SkuSelector.vue +58 -0
  96. package/ecomplus-stores/monocard/functions/ssr/src/layouts/PageFooter.astro +4 -3
  97. package/ecomplus-stores/monocard/functions/ssr/src/layouts/PageHeader.astro +1 -1
  98. package/ecomplus-stores/monocard/functions/ssr/src/main/Home.astro +2 -1
  99. package/ecomplus-stores/monocard/functions/ssr/src/main/Sections.astro +18 -4
  100. package/ecomplus-stores/monocard/functions/ssr/src/main/Wildcard.astro +10 -1
  101. package/ecomplus-stores/monocard/functions/ssr/src/pages/app/account.astro +34 -0
  102. package/ecomplus-stores/monocard/functions/ssr/src/pages/app/index.astro +62 -0
  103. package/ecomplus-stores/monocard/functions/ssr/src/pages/index.astro +0 -5
  104. package/ecomplus-stores/monocard/functions/ssr/src/pages/~fallback.astro +0 -2
  105. package/ecomplus-stores/monocard/functions/ssr/tailwind.config.cjs +0 -1
  106. package/ecomplus-stores/monocard/functions/with-apps/package.json +3 -3
  107. package/ecomplus-stores/monocard/package.json +2 -2
  108. package/ecomplus-stores/tia-sonia/functions/ssr/package.json +2 -1
  109. package/package.json +6 -6
  110. package/packages/api/package.json +1 -1
  111. package/packages/apps/affilate-program/package.json +1 -1
  112. package/packages/apps/correios/package.json +3 -3
  113. package/packages/apps/custom-payment/package.json +1 -1
  114. package/packages/apps/custom-shipping/package.json +1 -1
  115. package/packages/apps/datafrete/package.json +2 -2
  116. package/packages/apps/discounts/package.json +1 -1
  117. package/packages/apps/emails/package.json +1 -1
  118. package/packages/apps/fb-conversions/package.json +3 -3
  119. package/packages/apps/flash-courier/package.json +2 -2
  120. package/packages/apps/frenet/package.json +2 -2
  121. package/packages/apps/galaxpay/package.json +2 -2
  122. package/packages/apps/google-analytics/package.json +2 -2
  123. package/packages/apps/jadlog/package.json +2 -2
  124. package/packages/apps/loyalty-points/package.json +1 -1
  125. package/packages/apps/mandae/package.json +2 -2
  126. package/packages/apps/melhor-envio/package.json +2 -2
  127. package/packages/apps/mercadopago/package.json +2 -2
  128. package/packages/apps/pagarme/package.json +2 -2
  129. package/packages/apps/pagarme-v5/package.json +3 -3
  130. package/packages/apps/paghiper/package.json +2 -2
  131. package/packages/apps/pix/package.json +2 -2
  132. package/packages/apps/tiny-erp/package.json +2 -2
  133. package/packages/apps/webhooks/package.json +2 -2
  134. package/packages/cli/package.json +1 -1
  135. package/packages/config/package.json +1 -1
  136. package/packages/emails/package.json +4 -4
  137. package/packages/eslint/package.json +3 -3
  138. package/packages/events/package.json +1 -1
  139. package/packages/feeds/package.json +1 -1
  140. package/packages/firebase/package.json +2 -2
  141. package/packages/i18n/package.json +1 -1
  142. package/packages/modules/lib/firebase.js +2 -2
  143. package/packages/modules/lib/firebase.js.map +1 -1
  144. package/packages/modules/package.json +2 -2
  145. package/packages/modules/src/firebase.ts +2 -2
  146. package/packages/passport/lib/firebase.js +13 -2
  147. package/packages/passport/lib/firebase.js.map +1 -1
  148. package/packages/passport/package.json +1 -1
  149. package/packages/passport/src/firebase.ts +16 -2
  150. package/packages/ssr/package.json +2 -3
  151. package/packages/storefront/client.d.ts +3 -0
  152. package/packages/storefront/config/astro/context-directive.mjs +2 -2
  153. package/packages/storefront/package.json +5 -5
  154. package/packages/storefront/src/analytics/event-to-fbq.ts +15 -0
  155. package/packages/storefront/src/helpers/afetch.ts +20 -8
  156. package/packages/storefront/src/lib/assets/base.css +5 -4
  157. package/packages/storefront/src/lib/assets/tooltip.css +1 -1
  158. package/packages/storefront/src/lib/components/Carousel.vue +19 -14
  159. package/packages/storefront/src/lib/composables/use-product-card.ts +11 -0
  160. package/packages/storefront/src/lib/layouts/Base.astro +1 -0
  161. package/packages/storefront/src/lib/layouts/BaseHead.astro +9 -2
  162. package/packages/storefront/src/lib/scripts/push-analytics-events.ts +82 -0
  163. package/packages/storefront/src/lib/scripts/session-utm.ts +16 -6
  164. package/packages/storefront/src/lib/scripts/vbeta-app.ts +5 -1
  165. package/packages/storefront/src/lib/ssr-context.ts +2 -2
  166. package/packages/storefront/src/lib/state/use-analytics.ts +242 -0
  167. package/packages/test-base/package.json +1 -1
  168. package/packages/types/package.json +1 -1
  169. package/ecomplus-stores/barra-doce/functions/ssr/public/img/uploads/banner2.webp +0 -0
  170. package/ecomplus-stores/barra-doce/functions/ssr/public/img/uploads/headphone.webp +0 -0
  171. package/ecomplus-stores/barra-doce/functions/ssr/public/img/uploads/logo.png +0 -0
  172. package/ecomplus-stores/barra-doce/functions/ssr/public/img/uploads/passion.webp +0 -0
  173. package/ecomplus-stores/barra-doce/functions/ssr/public/img/uploads/rect8589.png +0 -0
  174. package/ecomplus-stores/barra-doce/functions/ssr/public/img/uploads/rect859.png +0 -0
  175. package/ecomplus-stores/barra-doce/functions/ssr/public/img/uploads/rect89.webp +0 -0
  176. package/ecomplus-stores/monocard/functions/ssr/content/extra-pages/contato.json +0 -11
  177. package/ecomplus-stores/monocard/functions/ssr/public/img/uploads/fluxo.png +0 -0
  178. package/ecomplus-stores/monocard/functions/ssr/src/layouts/Checkout.astro +0 -0
  179. /package/{ecomplus-stores/barra-doce/functions/ssr/src/layouts/Checkout.astro → packages/storefront/src/analytics/event-to-ttq.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <section class="ui-section">
3
- <div v-if="title" class="max-w-prose mx-auto text-center mb-2">
3
+ <div v-if="title" class="mx-auto mb-2 max-w-prose text-center">
4
4
  <h2 class="ui-text-brand text-3xl">
5
5
  <ALink :href="titleLink" :class="titleLink ? 'ui-link' : 'text-base-700'">
6
6
  {{ title }}
@@ -11,22 +11,22 @@
11
11
  <li
12
12
  v-for="product in products"
13
13
  :key="product._id"
14
- class="basis-1/2 md:basis-1/3 lg:basis-1/4 shrink-0"
14
+ class="shrink-0 basis-1/2 md:basis-1/3 lg:basis-1/4"
15
15
  >
16
16
  <ProductCard :product="product" />
17
17
  </li>
18
18
  <template #controls>
19
19
  <div
20
20
  v-show="products.length > 2"
21
- class="text-3xl lg:text-2xl leading-none text-primary
22
- lg:opacity-0 group-hover/shelf:opacity-90 transition-opacity"
21
+ class="text-primary text-3xl leading-none transition-opacity
22
+ group-hover/shelf:opacity-90 lg:text-2xl lg:opacity-0"
23
23
  >
24
- <CarouselControl class="!top-1/2 !lg:top-1/3 !-left-4 w-12 h-12
25
- bg-transparent lg:bg-white/80 lg:hover:bg-primary-300/60 rounded
26
- lg:shadow-sm lg:ring-1 ring-black/5" is-prev />
27
- <CarouselControl class="!top-1/2 !lg:top-1/3 !-right-4 w-12 h-12
28
- bg-transparent lg:bg-white/80 lg:hover:bg-primary-300/60 rounded
29
- lg:shadow-sm lg:ring-1 ring-black/5" />
24
+ <CarouselControl class="!lg:top-1/3 lg:hover:bg-primary-300/60 !-left-4 !top-1/2 h-12
25
+ w-12 rounded bg-transparent ring-black/5
26
+ lg:bg-white/80 lg:shadow-sm lg:ring-1" is-prev />
27
+ <CarouselControl class="!lg:top-1/3 lg:hover:bg-primary-300/60 !-right-4 !top-1/2 h-12
28
+ w-12 rounded bg-transparent ring-black/5
29
+ lg:bg-white/80 lg:shadow-sm lg:ring-1" />
30
30
  </div>
31
31
  </template>
32
32
  </Carousel>
@@ -38,8 +38,6 @@ import {
38
38
  type Props as UseProductShelfProps,
39
39
  useProductShelf,
40
40
  } from '@@sf/composables/use-product-shelf';
41
- import Carousel from '@@sf/components/Carousel.vue';
42
- import CarouselControl from '@@sf/components/CarouselControl.vue';
43
41
  import ProductCard from '~/components/ProductCard.vue';
44
42
 
45
43
  export interface Props extends UseProductShelfProps {}
@@ -0,0 +1,42 @@
1
+ <template>
2
+ <section v-if="hasSpecs" class="ui-section">
3
+ <Collapse :title="title || $t.i19specifications">
4
+ <ul>
5
+ <li
6
+ v-for="(grid, gridId) in specifications"
7
+ :key="gridId"
8
+ class="border-base-200 grid grid-cols-2
9
+ border-dashed py-2 sm:grid-cols-3 [&:not(:last-child)]:border-b"
10
+ >
11
+ <span class="text-base-700">
12
+ {{ getGridTitle(`${gridId}`, grids) }}
13
+ </span>
14
+ <strong class="font-semibold sm:col-span-2">
15
+ {{ getSpecTextValue(product, `${gridId}`, grids) }}
16
+ </strong>
17
+ </li>
18
+ </ul>
19
+ </Collapse>
20
+ </section>
21
+ </template>
22
+
23
+ <script setup lang="ts">
24
+ import type { Products } from '@cloudcommerce/api/types';
25
+ import {
26
+ gridTitle as getGridTitle,
27
+ specTextValue as getSpecTextValue,
28
+ } from '@ecomplus/utils';
29
+ import Collapse from '~/components/Collapse.vue';
30
+
31
+ export interface Props {
32
+ product?: Products;
33
+ title?: string;
34
+ }
35
+
36
+ const props = withDefaults(defineProps<Props>(), {
37
+ product: () => globalThis.$storefront.apiContext?.doc as Products,
38
+ });
39
+ const specifications = computed(() => props.product.specifications || {});
40
+ const hasSpecs = computed(() => Object.keys(specifications.value).length);
41
+ const { grids } = globalThis.$storefront.data;
42
+ </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="w-full h-40 bg-base-300"></div>
2
+ <div class="bg-base-300 h-40 w-full"></div>
3
3
  </template>
4
4
 
5
5
  <script setup lang="ts">
@@ -19,10 +19,7 @@
19
19
  </SocialNetworkLink>
20
20
  </span>
21
21
  </div>
22
- <div v-if="$settings.address || $settings.phone" class="text-base-700 mt-3">
23
- <address v-if="$settings.address" class="mr-4 inline-block">
24
- {{ $settings.address }}
25
- </address>
22
+ <div v-if="$settings.phone" class="text-base-700 mt-3">
26
23
  <ALink
27
24
  v-if="$settings.phone"
28
25
  :href="`tel:${$settings.phone.replace(/\D/g, '')}`"
@@ -43,14 +40,14 @@
43
40
  ? 'grid md:grid-cols-2 gap-x-5 gap-y-1.5' : 'space-y-1.5'"
44
41
  >
45
42
  <li v-for="({ name, slug }, i) in categories" :key="`c-${i}`">
46
- <ALink :href="`/${slug}`" class="ui-link text-base-600">
43
+ <a :href="`/${slug}`" class="ui-link text-base-600">
47
44
  {{ name }}
48
- </ALink>
45
+ </a>
49
46
  </li>
50
47
  <li>
51
- <ALink href="/s" class="ui-link text-base-900">
48
+ <a href="/s" class="ui-link text-base-900">
52
49
  {{ $t.i19allProducts }}
53
- </ALink>
50
+ </a>
54
51
  </li>
55
52
  </ul>
56
53
  </div>
@@ -72,55 +69,7 @@
72
69
  </div>
73
70
  </div>
74
71
  </div>
75
- <div class="ui-section">
76
- <div class="flex flex-wrap items-start justify-between gap-5 lg:flex-nowrap">
77
- <ul class="mx-auto flex items-center gap-x-6 gap-y-3
78
- overflow-x-auto md:mx-0 md:flex-wrap md:overflow-hidden lg:gap-x-8">
79
- <li v-for="(stamp, i) in stamps" :key="i">
80
- <ALink :href="stamp.href?.replace('{domain}', $settings.domain || '')">
81
- <slot :name="`picture-${i}`" />
82
- <span v-if="!stamp.img" class="flex items-center">
83
- <span
84
- v-if="stamp.icon"
85
- class="[&>*]:from-secondary-300 [&>*]:to-secondary-600
86
- mr-2 text-4xl [&>*]:bg-gradient-to-br"
87
- >
88
- <i v-if="stamp.icon === 'lock'" class="i-lock-closed"></i>
89
- <i v-else-if="stamp.icon === 'check'" class="i-check-badge"></i>
90
- <i v-else class="i-arrow-path-rounded-square"></i>
91
- </span>
92
- <span class="text-base-600 max-w-[140px] text-sm font-medium">
93
- {{ stamp.alt }}
94
- <i
95
- v-if="stamp.href && stamp.href.charAt(0) !== '/'"
96
- class="bg-base-400 i-arrow-top-right-on-square ml-0.5"
97
- ></i>
98
- </span>
99
- </span>
100
- </ALink>
101
- </li>
102
- </ul>
103
- <div class="mx-auto flex flex-wrap items-center justify-end
104
- gap-4 overflow-x-auto text-2xl md:mx-0 md:flex-nowrap md:overflow-hidden">
105
- <PaymentMethodFlag
106
- v-for="paymentMethod in $settings.paymentMethods"
107
- :key="paymentMethod"
108
- :flag="paymentMethod"
109
- />
110
- </div>
111
- </div>
112
- <div class="mt-7 justify-between gap-4 text-center
113
- text-xs md:flex md:text-left">
114
- <div class="mb-3 md:mb-0">
115
- @ {{ new Date().getFullYear() }} {{ $settings.corporateName }}
116
- {{ $settings.address ? `/ ${$settings.address}` : '' }}
117
- / {{ $settings.docNumber }}
118
- </div>
119
- <ALink href="https://www.ecomplus.io/" class="italic text-[#37003c]">
120
- powered by <b>E-Com Plus</b>
121
- </ALink>
122
- </div>
123
- </div>
72
+ <FooterStamps :stamps="stamps" />
124
73
  </footer>
125
74
  </template>
126
75
 
@@ -129,7 +78,7 @@ import type { Categories } from '@cloudcommerce/api/types';
129
78
  import type { LayoutContent } from '@@sf/content';
130
79
  import { socialNetworks } from '@@sf/sf-lib';
131
80
  import SocialNetworkLink from '@@sf/components/SocialNetworkLink.vue';
132
- import PaymentMethodFlag from '@@sf/components/PaymentMethodFlag.vue';
81
+ import FooterStamps from '~/components/FooterStamps.vue';
133
82
 
134
83
  export interface Props {
135
84
  stamps?: LayoutContent['footer']['stamps'];
@@ -4,35 +4,38 @@
4
4
  class="relative top-0 z-50 transition-colors"
5
5
  :class="[
6
6
  isSticky && !isSidenavOpen ? 'bg-white/80' : 'bg-white',
7
- isSticky ? 'backdrop-blur-md shadow py-2 md:py-3' : 'py-3 sm:py-4 md:py-5',
7
+ isSticky ? 'py-2 shadow backdrop-blur-md md:py-3' : 'py-3 sm:py-4 md:py-5',
8
8
  ]"
9
9
  >
10
- <div class="w-screen lg:w-[calc(100vw-1rem)] xl:max-w-[82rem] 2xl:max-w-[85rem]
11
- mx-auto px-1 sm:pl-2 sm:pr-2.5 lg:px-1">
12
- <div class="flex justify-between items-center">
10
+ <div class="mx-auto w-screen px-1 sm:pl-2
11
+ sm:pr-2.5 lg:w-[calc(100vw-1rem)] lg:px-1 xl:max-w-[82rem] 2xl:max-w-[85rem]">
12
+ <div class="flex items-center justify-between">
13
13
  <div
14
- class="basis-1/4 lg:basis-auto lg:me-5"
14
+ class="basis-1/4 lg:me-5 lg:basis-auto"
15
15
  :class="!isSticky ? 'lg:hidden' : null"
16
16
  >
17
17
  <button
18
- class="px-2 my-1"
18
+ class="my-1 px-2"
19
19
  :aria-label="$t.i19toggleMenu"
20
20
  @click="isSidenavOpen = !isSidenavOpen"
21
21
  >
22
22
  <i
23
- class="text-base-600 text-3xl"
24
- :class="isSidenavOpen ? 'i-close' : 'i-menu-line'"
23
+ class="text-3xl transition-colors"
24
+ :class="[
25
+ isSidenavOpen ? 'i-close' : 'i-menu-line',
26
+ isMounted ? 'text-base-600' : 'text-base-400 animate-pulse',
27
+ ]"
25
28
  ></i>
26
29
  </button>
27
30
  </div>
28
31
  <div class="lg:grow" :class="isSticky ? '[&_img]:max-w-[170px]' : null">
29
32
  <slot name="logo" />
30
33
  </div>
31
- <div class="basis-1/4 px-2 flex justify-end items-center gap-3 lg:gap-4">
34
+ <div class="flex basis-1/4 items-center justify-end gap-3 px-2 lg:gap-4">
32
35
  <form
33
- action="/search"
36
+ action="/s"
34
37
  method="get"
35
- class="hidden lg:block w-[400px] relative mb-1"
38
+ class="relative mb-1 hidden w-[400px] lg:block"
36
39
  @submit.prevent="searchTerm
37
40
  ? (isSearchOpen = !isSearchOpen)
38
41
  : searchInput?.focus()"
@@ -47,14 +50,14 @@
47
50
  name="term"
48
51
  v-model="searchTerm"
49
52
  :placeholder="$t.i19searchProducts"
50
- class="w-full rounded-md py-2.5 pe-10 sm:text-sm
51
- bg-gradient-to-br from-secondary-50/10 to-secondary-50/80
52
- border-secondary-200 shadow-sm"
53
+ class="from-secondary-50/10 to-secondary-50/80 border-secondary-200 w-full rounded-md
54
+ bg-gradient-to-br py-2.5 pe-10
55
+ shadow-sm sm:text-sm"
53
56
  />
54
- <span class="absolute inset-y-0 end-0 px-1 grid place-content-center">
57
+ <span class="absolute inset-y-0 end-0 grid place-content-center px-1">
55
58
  <button
56
59
  type="submit"
57
- class="p-1 text-2xl text-secondary-600 hover:text-primary"
60
+ class="text-secondary-600 hover:text-primary p-1 text-2xl"
58
61
  >
59
62
  <span class="sr-only">{{ $t.i19search }}</span>
60
63
  <i class="i-search-3-line"></i>
@@ -66,38 +69,40 @@
66
69
  @click="isSearchOpen = !isSearchOpen"
67
70
  class="lg:hidden"
68
71
  >
69
- <i class="i-search-3-line w-7 h-7
70
- text-base-700 hover:text-primary hover:scale-110 active:scale-125"></i>
72
+ <i class="i-search-3-line text-base-700 hover:text-primary
73
+ h-7 w-7 hover:scale-110 active:scale-125"></i>
71
74
  </button>
72
75
  <AccountMenu class="hidden sm:block">
73
76
  <template #button="{ open }">
74
77
  <i
75
- class="i-user-2-line w-7 h-7
76
- text-base-600 hover:text-primary hover:scale-110 active:scale-125"
78
+ class="i-user-2-line text-base-600 hover:text-primary
79
+ h-7 w-7 hover:scale-110 active:scale-125"
77
80
  :class="open ? 'text-base-800 scale-110' : null"
78
81
  ></i>
79
82
  </template>
80
83
  </AccountMenu>
81
- <button
84
+ <a
85
+ :href="$settings.cartUrl || '/app/'"
82
86
  :aria-label="$t.i19openCart"
83
- @click="isCartOpen = !isCartOpen"
84
- class="relative group text-primary-500"
87
+ @click.prevent="isCartOpen = !isCartOpen"
88
+ class="text-primary-500 group relative"
89
+ role="button"
85
90
  >
86
- <i class="i-shopping-bag-3-fill w-7 h-7 group-hover:text-primary
91
+ <i class="i-shopping-bag-3-fill group-hover:text-primary h-7 w-7
87
92
  group-hover:scale-110 group-active:scale-125"></i>
88
93
  <span
89
94
  v-if="delayedTotalItems"
90
- class="ui-badge-pill-sm absolute -top-1 -right-1.5"
95
+ class="ui-badge-pill-sm absolute -right-1.5 -top-1"
91
96
  >
92
97
  {{ delayedTotalItems }}
93
98
  </span>
94
- </button>
99
+ </a>
95
100
  </div>
96
101
  </div>
97
102
  <ShopHeaderMenu
98
103
  v-show="!isSticky"
99
104
  v-bind="{ inlineMenuTrees }"
100
- class="hidden lg:block px-3 2xl:px-8 mt-3"
105
+ class="mt-3 hidden px-3 lg:block 2xl:px-8"
101
106
  />
102
107
  </div>
103
108
  <Drawer
@@ -135,7 +140,7 @@
135
140
  <Suspense>
136
141
  <CartSidebar v-if="isCartOpenOnce" @close="isCartOpen = false" />
137
142
  <template #fallback>
138
- <Skeleton class="pt-16 px-6" is-bold />
143
+ <Skeleton class="px-6 pt-16" is-bold />
139
144
  </template>
140
145
  </Suspense>
141
146
  </Drawer>
@@ -144,12 +149,6 @@
144
149
  </template>
145
150
 
146
151
  <script setup lang="ts">
147
- import {
148
- ref,
149
- watch,
150
- onMounted,
151
- defineAsyncComponent,
152
- } from 'vue';
153
152
  import { watchOnce } from '@vueuse/core';
154
153
  import { totalItems } from '@@sf/state/shopping-cart';
155
154
  import {
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <nav>
3
3
  <ul
4
- class="flex justify-between gap-1.5 text-base-700"
4
+ class="text-base-700 flex justify-between gap-1.5"
5
5
  :class="inlineMenuTrees.length < 7 ? 'text-base' : 'text-sm'"
6
6
  >
7
7
  <li v-for="(categoryTree, i) in inlineMenuTrees" :key="i">
@@ -9,13 +9,13 @@
9
9
  v-if="categoryTree.subcategories.length"
10
10
  :category-tree="categoryTree"
11
11
  :class="[
12
- i < 4 ? '[&_.Popover]:translate-x-0 [&_.Popover]:-left-2' : null,
13
- i > 3 ? '[&_.Popover]:text-right [&_.Popover]:-right-2' : null,
12
+ i < 4 ? '[&_.Popover]:-left-2 [&_.Popover]:translate-x-0' : null,
13
+ i > 3 ? '[&_.Popover]:-right-2 [&_.Popover]:text-right' : null,
14
14
  ]"
15
15
  >
16
16
  <template #button="{ open }">
17
17
  <span class="hover:text-primary group">
18
- <span class="hidden lg:inline text-secondary-500">
18
+ <span class="text-secondary-500 hidden lg:inline">
19
19
  <i v-if="categoryTree.slug.includes('confeitar')"
20
20
  class="i-cupcake-line me-1"></i>
21
21
  <i v-else-if="categoryTree.slug.includes('cortadores')"
@@ -30,7 +30,7 @@
30
30
  class="i-drop-line me-1"></i>
31
31
  </span>
32
32
  <h3
33
- class="group-hover:underline inline tracking-tight"
33
+ class="inline tracking-tight group-hover:underline"
34
34
  :class="[
35
35
  inlineMenuTrees.length < 7 ? 'decoration-2' : null,
36
36
  open ? 'underline' : null,
@@ -1,25 +1,28 @@
1
1
  <template>
2
2
  <Popover v-slot="{ open }">
3
- <PopoverButton class="outline-none">
4
- <slot name="button" v-bind="{ open }" />
5
- </PopoverButton>
6
- <div class="relative">
3
+ <a :href="`/${categoryTree.slug}`" role="button">
4
+ <PopoverButton class="outline-none">
5
+ <slot name="button" v-bind="{ open }" />
6
+ </PopoverButton>
7
+ </a>
8
+ <div class="relative" ref="panel">
7
9
  <Fade>
8
10
  <PopoverPanel
9
- class="Popover absolute z-20 top-3 !transform
10
- px-7 py-5 rounded backdrop-blur-md shadow bg-white/80
11
- text-base text-base-700"
11
+ v-slot="{ close }"
12
+ class="Popover text-base-700 absolute top-3 z-20
13
+ !transform rounded bg-white/80 px-7 py-5 text-base
14
+ shadow backdrop-blur-md"
12
15
  :class="countMenuCols === 1 ? 'w-auto'
13
16
  : countMenuCols === 2 ? `w-screen ${(categoryPicture ? 'max-w-lg' : 'max-w-sm')}`
14
17
  : countMenuCols === 3 ? `w-screen ${(categoryPicture ? 'max-w-xl' : 'max-w-md')}`
15
18
  : countMenuCols < 6 ? 'w-screen max-w-3xl' : 'w-screen max-w-5xl'"
16
19
  >
17
- <div class="flex gap-6 w-full">
20
+ <div class="flex w-full gap-6">
18
21
  <ul v-if="subcategoryLinks.length" class="flex-1">
19
22
  <li
20
23
  v-for="(subcategory, i) in subcategoryLinks"
21
24
  :key="`link-${i}`"
22
- class="text-sm mb-2"
25
+ class="mb-2 text-sm"
23
26
  >
24
27
  <a :href="`/${subcategory.slug}`" class="hover:text-primary">
25
28
  <h3 :class="countMenuCols === 1 ? 'whitespace-nowrap' : null">
@@ -36,7 +39,7 @@
36
39
  <a :href="`/${subcategory.slug}`" class="hover:text-primary">
37
40
  <h3>{{ subcategory.name }}</h3>
38
41
  </a>
39
- <ul class="text-sm text-base-600 mt-1 mb-1.5">
42
+ <ul class="text-base-600 mb-1.5 mt-1 text-sm">
40
43
  <li
41
44
  v-for="(nestedSubcategory, ii) in subcategory.subcategories"
42
45
  :key="`${i}-${ii}`"
@@ -61,10 +64,11 @@
61
64
  </div>
62
65
  <a
63
66
  :href="`/${categoryTree.slug}`"
64
- class="block mt-1 text-xs text-base-600 leading-snug underline"
67
+ class="text-base-600 mt-1 block text-xs leading-snug underline"
65
68
  >
66
69
  {{ $t.i19seeAll$1Category.replace('$1', categoryTree.name) }}
67
70
  </a>
71
+ <button ref="close" @click.stop="close" class="hidden"></button>
68
72
  </PopoverPanel>
69
73
  </Fade>
70
74
  </div>
@@ -72,6 +76,7 @@
72
76
  </template>
73
77
 
74
78
  <script setup lang="ts">
79
+ import { onClickOutside } from '@vueuse/core';
75
80
  import { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue';
76
81
  import {
77
82
  type Props as UseShopHeaderSubmenuProps,
@@ -87,4 +92,7 @@ const {
87
92
  subcategoryCols,
88
93
  countMenuCols,
89
94
  } = useShopHeaderSubmenu(props);
95
+ const panel = ref(null);
96
+ const close = ref<HTMLElement | null>(null);
97
+ onClickOutside(panel, () => close.value?.click());
90
98
  </script>
@@ -1,6 +1,6 @@
1
1
  <template>
2
- <aside class="flex flex-col h-full">
3
- <nav class="py-4 grow">
2
+ <aside class="flex h-full flex-col">
3
+ <nav class="grow py-4">
4
4
  <ul class="relative h-full">
5
5
  <ShopSidenavCategory
6
6
  v-for="(categoryTree, i) in categoryTrees"
@@ -10,12 +10,12 @@
10
10
  </ul>
11
11
  </nav>
12
12
  <footer class="text-base">
13
- <div class="flex items-center px-2 py-4 bg-base-100">
14
- <AccountLink class="p-2 grow flex items-center gap-3">
15
- <i class="i-user-2-line text-4xl text-base-500 m-0"></i>
13
+ <div class="bg-base-100 flex items-center px-2 py-4">
14
+ <AccountLink class="flex grow items-center gap-3 p-2">
15
+ <i class="i-user-2-line text-base-500 m-0 text-4xl"></i>
16
16
  <span class="leading-tight">
17
17
  {{ `${$t.i19hello} ${customerName || $t.i19visitor}` }}
18
- <small class="block lowercase font-semibold text-primary">
18
+ <small class="text-primary block font-semibold lowercase">
19
19
  {{ $t.i19myOrders }}, {{ $t.i19myAccount }}
20
20
  </small>
21
21
  </span>
@@ -23,15 +23,15 @@
23
23
  <button
24
24
  v-if="isLogged"
25
25
  @click="logout"
26
- class="p-2 text-right text-base-800"
26
+ class="text-base-800 p-2 text-right"
27
27
  >
28
28
  <span class="text-base-600">{{ $t.i19logout }}</span>
29
- <i class="i-align-arrow-left-fill text-lg ml-1"></i>
29
+ <i class="i-align-arrow-left-fill ml-1 text-lg"></i>
30
30
  </button>
31
31
  </div>
32
- <ul class="flex gap-3 p-4 bg-base-200 text-xl text-base-700">
32
+ <ul class="bg-base-200 text-base-700 flex gap-3 p-4 text-xl">
33
33
  <li v-for="(href, network) in socialNetworks" :key="network">
34
- <SocialNetworkLink :network="network" class="p-1 active:text-primary" />
34
+ <SocialNetworkLink :network="network" class="active:text-primary p-1" />
35
35
  </li>
36
36
  </ul>
37
37
  </footer>
@@ -40,7 +40,6 @@
40
40
 
41
41
  <script setup lang="ts">
42
42
  import type { CategoryTree } from '@@sf/composables/use-shop-header';
43
- import { onMounted } from 'vue';
44
43
  import { socialNetworks } from '@@sf/sf-lib';
45
44
  import {
46
45
  customerName,
@@ -1,23 +1,23 @@
1
1
  <template>
2
- <li class="text-lg text-base-800">
2
+ <li class="text-base-800 text-lg">
3
3
  <details
4
4
  v-if="categoryTree.subcategories.length"
5
- class="bg-white overflow-y-auto overflow-x-hidden z-10
6
- open:absolute open:top-0 open:left-0 open:w-full open:h-full"
5
+ class="z-10 overflow-y-auto overflow-x-hidden bg-white
6
+ open:absolute open:left-0 open:top-0 open:h-full open:w-full"
7
7
  @toggle="isOpen = !isOpen"
8
8
  >
9
9
  <summary
10
- class="cursor-pointer list-none px-6 py-3 active:bg-base-100 transition-colors"
10
+ class="active:bg-base-100 cursor-pointer list-none px-6 py-3 transition-colors"
11
11
  :class="isOpen ? 'bg-base-100' : null"
12
12
  >
13
13
  <i :class="!isOpen
14
14
  ? 'i-arrow-right-line float-right mb-0 mt-1 text-xl text-base-500'
15
- : 'i-arrow-left-line text-lg'"></i>
15
+ : 'i-arrow-right-line rotate-180 text-lg'"></i>
16
16
  <AImg
17
17
  v-if="!isOpen && categoryTree.icon"
18
18
  :picture="categoryTree.icon"
19
19
  :alt="categoryTree.name"
20
- class="w-auto h-5 inline mr-3"
20
+ class="mr-3 inline h-5 w-auto"
21
21
  />
22
22
  <h3 class="inline" :class="isOpen ? 'ml-4 text-base' : null">
23
23
  {{ categoryTree.name }}
@@ -36,7 +36,7 @@
36
36
  <li>
37
37
  <a
38
38
  :href="`/${categoryTree.slug}`"
39
- class="block px-6 py-3 text-base underline active:bg-base-200"
39
+ class="active:bg-base-200 block px-6 py-3 text-base underline"
40
40
  >
41
41
  {{ $t.i19seeAll$1Category.replace('$1', categoryTree.name) }}
42
42
  </a>
@@ -46,13 +46,13 @@
46
46
  <a
47
47
  v-else
48
48
  :href="`/${categoryTree.slug}`"
49
- class="block px-6 py-3 active:bg-base-200"
49
+ class="active:bg-base-200 block px-6 py-3"
50
50
  >
51
51
  <AImg
52
52
  v-if="!isOpen && categoryTree.icon"
53
53
  :picture="categoryTree.icon"
54
54
  :alt="categoryTree.name"
55
- class="w-auto h-5 inline mr-3"
55
+ class="mr-3 inline h-5 w-auto"
56
56
  />
57
57
  <h3 class="inline">{{ categoryTree.name }}</h3>
58
58
  </a>
@@ -61,7 +61,6 @@
61
61
 
62
62
  <script setup lang="ts">
63
63
  import type { CategoryTree, SubcategoryTree } from '@@sf/composables/use-shop-header';
64
- import { ref, watch } from 'vue';
65
64
 
66
65
  export interface Props {
67
66
  categoryTree: CategoryTree | SubcategoryTree;
@@ -0,0 +1,58 @@
1
+ <template>
2
+ <div>
3
+ <div v-for="(options, gridId) in variationsGrids" :key="gridId">
4
+ <span class="text-base-700 text-sm font-medium">
5
+ {{ getGridTitle(gridId) }}:
6
+ <strong v-if="selectedOptions[gridId]" class="text-base-800">
7
+ {{ selectedOptions[gridId] }}
8
+ </strong>
9
+ </span>
10
+ <ul v-if="options.length < 7" class="mt-2 flex gap-2">
11
+ <li v-for="(optionText, i) in options" :key="`${gridId}-${i}`">
12
+ <button
13
+ class="ring-secondary/60 rounded border"
14
+ :class="[
15
+ selectedOptions[gridId] === optionText
16
+ ? 'border-secondary ring-2'
17
+ : null,
18
+ gridId === 'colors'
19
+ ? 'h-9 w-9 text-[0]'
20
+ : 'px-2 py-1',
21
+ activeVariationsGrids[gridId].includes(optionText)
22
+ ? 'text-base-800 bg-base-100 border-base-400'
23
+ : 'text-base-500 bg-base-200 border-base-300'
24
+ ]"
25
+ :style="gridId === 'colors' ? getColorOptionBg(optionText) : undefined"
26
+ @click="selectOption({ optionText, gridId, gridIndex: i })"
27
+ >
28
+ {{ optionText }}
29
+ </button>
30
+ </li>
31
+ </ul>
32
+ </div>
33
+ </div>
34
+ </template>
35
+
36
+ <script setup lang="ts">
37
+ import {
38
+ type Props as UseSkuSelector,
39
+ useSkuSelector,
40
+ } from '@@sf/composables/use-sku-selector';
41
+
42
+ export interface Props extends UseSkuSelector {}
43
+
44
+ const props = defineProps<Props>();
45
+ const emit = defineEmits(['update:variationId']);
46
+ const {
47
+ variationsGrids,
48
+ activeVariationsGrids,
49
+ selectOption,
50
+ selectedOptions,
51
+ variationId,
52
+ getGridTitle,
53
+ getColorOptionBg,
54
+ } = useSkuSelector(props);
55
+ watch(variationId, (_id) => {
56
+ emit('update:variationId', _id);
57
+ });
58
+ </script>
@@ -26,7 +26,9 @@ if (categoriesList?.isActive) {
26
26
  } else {
27
27
  // Will wait and reuse categories loaded from <PageHeader>
28
28
  const { value: categories } = await useSharedData({ field: 'categories' });
29
- mainCategories = filterMainCategories(categories);
29
+ if (categories) {
30
+ mainCategories = filterMainCategories(categories);
31
+ }
30
32
  }
31
33
  }
32
34
  if (pagesList?.isActive) {
@@ -23,12 +23,11 @@ const { inlineClientJS } = await useSharedData({
23
23
  {pitchBar.slides.length === 1 && <PitchBar {...pitchBar} />}
24
24
  </slot>
25
25
  <script is:inline set:html={inlineClientJS} />
26
- <ShopHeader {...shopHeader} client:load>
26
+ <ShopHeader {...shopHeader} client:context>
27
27
  <Fragment slot="logo">
28
28
  <a href="/" class="inline-block">
29
29
  <LogoHeading class="inline-block">
30
30
  <Picture
31
- slot="logo-picture"
32
31
  src={settings.logo}
33
32
  alt={settings.name}
34
33
  widths={[280, 400]}