cloudcommerce 2.5.1 → 2.6.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 (68) hide show
  1. package/.vscode/settings.json +4 -1
  2. package/CHANGELOG.md +27 -0
  3. package/ecomplus-stores/barradoce/.devcontainer/devcontainer.json +10 -4
  4. package/ecomplus-stores/barradoce/.vscode/settings.json +3 -0
  5. package/ecomplus-stores/barradoce/functions/many/package.json +3 -3
  6. package/ecomplus-stores/barradoce/functions/ssr/package.json +6 -6
  7. package/ecomplus-stores/barradoce/functions/ssr/src/components/CartSidebar.vue +29 -9
  8. package/ecomplus-stores/barradoce/functions/ssr/src/components/HeroSlider.vue +1 -3
  9. package/ecomplus-stores/barradoce/functions/ssr/src/components/ProductDetails.vue +30 -12
  10. package/ecomplus-stores/barradoce/functions/ssr/src/components/SearchModal.vue +9 -6
  11. package/ecomplus-stores/barradoce/functions/ssr/src/components/SearchShowcase.vue +19 -17
  12. package/ecomplus-stores/barradoce/functions/ssr/src/components/ShippingCalculator.vue +100 -0
  13. package/ecomplus-stores/barradoce/functions/ssr/src/main/content/Sections.astro +3 -0
  14. package/ecomplus-stores/barradoce/functions/ssr/src/state/midd-search-engine.ts +19 -0
  15. package/ecomplus-stores/barradoce/functions/with-apps/package.json +3 -3
  16. package/ecomplus-stores/barradoce/package.json +2 -2
  17. package/ecomplus-stores/barradoce/tailwind.config.cjs +5 -3
  18. package/package.json +2 -2
  19. package/packages/api/package.json +1 -1
  20. package/packages/apps/affiliate-program/package.json +1 -1
  21. package/packages/apps/correios/package.json +1 -1
  22. package/packages/apps/custom-payment/package.json +1 -1
  23. package/packages/apps/custom-shipping/package.json +1 -1
  24. package/packages/apps/datafrete/package.json +1 -1
  25. package/packages/apps/discounts/package.json +1 -1
  26. package/packages/apps/emails/package.json +1 -1
  27. package/packages/apps/fb-conversions/package.json +1 -1
  28. package/packages/apps/flash-courier/package.json +1 -1
  29. package/packages/apps/frenet/package.json +1 -1
  30. package/packages/apps/galaxpay/package.json +1 -1
  31. package/packages/apps/google-analytics/package.json +1 -1
  32. package/packages/apps/jadlog/package.json +1 -1
  33. package/packages/apps/loyalty-points/package.json +1 -1
  34. package/packages/apps/mandae/package.json +1 -1
  35. package/packages/apps/melhor-envio/package.json +1 -1
  36. package/packages/apps/mercadopago/package.json +1 -1
  37. package/packages/apps/pagarme/package.json +1 -1
  38. package/packages/apps/pagarme-v5/package.json +1 -1
  39. package/packages/apps/paghiper/package.json +1 -1
  40. package/packages/apps/pix/package.json +1 -1
  41. package/packages/apps/tiny-erp/package.json +1 -1
  42. package/packages/apps/webhooks/package.json +1 -1
  43. package/packages/cli/package.json +1 -1
  44. package/packages/config/package.json +1 -1
  45. package/packages/emails/package.json +1 -1
  46. package/packages/eslint/package.json +1 -1
  47. package/packages/eslint/storefront.eslintrc.cjs +1 -0
  48. package/packages/events/package.json +1 -1
  49. package/packages/feeds/package.json +1 -1
  50. package/packages/firebase/package.json +1 -1
  51. package/packages/i18n/package.json +1 -1
  52. package/packages/modules/package.json +1 -1
  53. package/packages/passport/package.json +1 -1
  54. package/packages/ssr/package.json +3 -3
  55. package/packages/storefront/package.json +4 -3
  56. package/packages/storefront/src/__fixtures__/calculate_shipping.json +161 -0
  57. package/packages/storefront/src/helpers/afetch.ts +1 -0
  58. package/packages/storefront/src/lib/components/Spinner.vue +16 -0
  59. package/packages/storefront/src/lib/components/globals/Skeleton.vue +25 -7
  60. package/packages/storefront/src/lib/composables/use-search-modal.ts +3 -1
  61. package/packages/storefront/src/lib/composables/use-search-showcase.ts +2 -1
  62. package/packages/storefront/src/lib/composables/use-shipping-calculator.ts +90 -31
  63. package/packages/storefront/src/lib/layouts/BaseHead.astro +2 -1
  64. package/packages/storefront/src/lib/layouts/use-page-main.ts +9 -5
  65. package/packages/storefront/src/lib/ssr-context.ts +9 -0
  66. package/packages/storefront/src/lib/state/search-engine.ts +21 -11
  67. package/packages/test-base/package.json +1 -1
  68. package/packages/types/package.json +1 -1
@@ -1,4 +1,7 @@
1
1
  {
2
+ "editor.tabSize": 2,
3
+ "files.eol": "\n",
4
+ "files.insertFinalNewline": true,
2
5
  "editor.quickSuggestions": {
3
6
  "strings": true
4
7
  },
@@ -16,7 +19,7 @@
16
19
  "tailwindCSS.experimental.configFile": {
17
20
  "packages/storefront/tailwind.config.cjs": "packages/**",
18
21
  "store/functions/ssr/tailwind.config.cjs": "store/**",
19
- "ecomplus-stores/barra-doce/functions/ssr/tailwind.config.cjs": "ecomplus-stores/barra-doce/**"
22
+ "ecomplus-stores/barradoce/functions/ssr/tailwind.config.cjs": "ecomplus-stores/barradoce/**"
20
23
  },
21
24
  "typescript.tsdk": "node_modules/typescript/lib",
22
25
  "eslint.validate": [
package/CHANGELOG.md CHANGED
@@ -2,6 +2,33 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [2.6.1](https://github.com/ecomplus/cloud-commerce/compare/v2.6.0...v2.6.1) (2024-02-24)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **storefront:** Add `searchEngine` as custom prop of SSR `usePageSections` composable ([74f3078](https://github.com/ecomplus/cloud-commerce/commit/74f307807406d30a891990c5a6da44d125e8e9dc))
11
+ * **storefront:** Better handle search engine middlewares passing search options object ([daf2084](https://github.com/ecomplus/cloud-commerce/commit/daf2084203561402ef72493d7840c7081eabac6e))
12
+ * **storefront:** New optional `searchEngine` on search modal and showcase composables ([65c6e21](https://github.com/ecomplus/cloud-commerce/commit/65c6e21b3503227be2cb11d6c40558d480b0f72e))
13
+ * **storefront:** Only sync middlewares (no promises) for `SearchEngine` fetch ([4fa8965](https://github.com/ecomplus/cloud-commerce/commit/4fa89658c409b90203ac76f8ee54cfbefdca44a3))
14
+ * **storefront:** Properly support `SearchEngine` extendability with new `addMiddleware` method ([0142368](https://github.com/ecomplus/cloud-commerce/commit/01423686f3c915da63a3e476521d7cf275d67dd0))
15
+
16
+ ## [2.6.0](https://github.com/ecomplus/cloud-commerce/compare/v2.5.1...v2.6.0) (2024-02-22)
17
+
18
+
19
+ ### Features
20
+
21
+ * **storefront:** New `<Spinner>` basic component ([b83b594](https://github.com/ecomplus/cloud-commerce/commit/b83b594c133635413829bf4fca15b9177187cf3c))
22
+ * **storefront:** New `getShippingDeadline` and `getShippingPrice` methods on calculator composable ([4dc32e1](https://github.com/ecomplus/cloud-commerce/commit/4dc32e1c2a3d1b235c6d46f91602a263b393d432))
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * **storefront:** Bump Astro to latest v4.4.1 and VueUse v10.8 ([e01fb6d](https://github.com/ecomplus/cloud-commerce/commit/e01fb6d2d307c93fbdf34e413b4b7bad5f939a5c))
28
+ * **storefront:** Exporting `isFetching` state from shipping calculator composable ([9266d0c](https://github.com/ecomplus/cloud-commerce/commit/9266d0c8d4a5c7dd6ffa99b44170988891e7257a))
29
+ * **storefront:** Prevent "=undefined" params on modules (and other internals) fetch ([a4f594e](https://github.com/ecomplus/cloud-commerce/commit/a4f594ea40269c6ef8b22cb166c3298fa877023d))
30
+ * **storefront:** Receiving `zipCode` ref instead of input on shipping calculator composable ([813dcb1](https://github.com/ecomplus/cloud-commerce/commit/813dcb16943f922ac52995778c42840d96195d67))
31
+
5
32
  ### [2.5.1](https://github.com/ecomplus/cloud-commerce/compare/v2.5.0...v2.5.1) (2024-02-19)
6
33
 
7
34
 
@@ -2,13 +2,13 @@
2
2
  "postCreateCommand": "npm i && npm i --prefix=functions/ssr",
3
3
  "waitFor": "postCreateCommand",
4
4
  "portsAttributes": {
5
- "3000": {
5
+ "4321": {
6
6
  "label": "Application",
7
7
  "onAutoForward": "openPreview"
8
8
  }
9
9
  },
10
10
  "forwardPorts": [
11
- 3000
11
+ 4321
12
12
  ],
13
13
  "postAttachCommand": {
14
14
  "Server": "npm run dev"
@@ -16,7 +16,8 @@
16
16
  "customizations": {
17
17
  "codespaces": {
18
18
  "openFiles": [
19
- "functions/ssr/src/main/Home.astro"
19
+ "functions/ssr/src/components/ShopHeader.vue",
20
+ "functions/ssr/src/components/ProductCard.vue"
20
21
  ]
21
22
  },
22
23
  "vscode": {
@@ -24,7 +25,12 @@
24
25
  "astro-build.astro-vscode",
25
26
  "vue.volar",
26
27
  "bradlc.vscode-tailwindcss"
27
- ]
28
+ ],
29
+ "settings": {
30
+ "files.autoSave": "afterDelay",
31
+ "files.autoSaveDelay": 5000,
32
+ "files.autoSaveWhenNoErrors": true
33
+ }
28
34
  }
29
35
  }
30
36
  }
@@ -1,4 +1,7 @@
1
1
  {
2
+ "editor.tabSize": 2,
3
+ "files.eol": "\n",
4
+ "files.insertFinalNewline": true,
2
5
  "editor.quickSuggestions": {
3
6
  "strings": true
4
7
  },
@@ -15,8 +15,8 @@
15
15
  },
16
16
  "main": "index.js",
17
17
  "dependencies": {
18
- "@cloudcommerce/feeds": "^2.5.0",
19
- "@cloudcommerce/firebase": "^2.5.0",
20
- "@cloudcommerce/passport": "^2.5.0"
18
+ "@cloudcommerce/feeds": "^2.6.0",
19
+ "@cloudcommerce/firebase": "^2.6.0",
20
+ "@cloudcommerce/passport": "^2.6.0"
21
21
  }
22
22
  }
@@ -19,16 +19,16 @@
19
19
  },
20
20
  "main": "index.js",
21
21
  "dependencies": {
22
- "@cloudcommerce/api": "^2.5.0",
23
- "@cloudcommerce/firebase": "^2.5.0",
24
- "@cloudcommerce/ssr": "^2.5.0",
22
+ "@cloudcommerce/api": "^2.6.0",
23
+ "@cloudcommerce/firebase": "^2.6.0",
24
+ "@cloudcommerce/ssr": "^2.6.0",
25
25
  "@headlessui/vue": "^1.7.18",
26
26
  "micromark": "^4.0.0"
27
27
  },
28
28
  "devDependencies": {
29
- "@cloudcommerce/i18n": "^2.5.0",
30
- "@cloudcommerce/storefront": "^2.5.0",
31
- "@cloudcommerce/types": "^2.5.0",
29
+ "@cloudcommerce/i18n": "^2.6.0",
30
+ "@cloudcommerce/storefront": "^2.6.0",
31
+ "@cloudcommerce/types": "^2.6.0",
32
32
  "@iconify-json/mingcute": "^1.1.16",
33
33
  "photoswipe": "^5.4.3"
34
34
  }
@@ -2,7 +2,7 @@
2
2
  <aside class="flex h-screen flex-col bg-white">
3
3
  <header class="z-10 flex items-center justify-end gap-3
4
4
  px-6 py-4 shadow ring-1 ring-black/5">
5
- <span class="text-base-600 text-right text-base font-medium">
5
+ <span class="text-right text-base font-medium text-base-600">
6
6
  {{ $t.i19myShoppingCart }}
7
7
  </span>
8
8
  <span class="min-w-[3rem] text-right">
@@ -11,18 +11,18 @@
11
11
  </span>
12
12
  </span>
13
13
  </header>
14
- <article class="bg-base-50 grow overflow-y-auto">
14
+ <article class="grow overflow-y-auto bg-base-50">
15
15
  <div v-if="freeShippingFromValue" class="text-center text-sm">
16
16
  <div
17
17
  v-if="freeShippingFromValue > shoppingCart.subtotal"
18
- class="secondary-subtle p-3"
18
+ class="p-3 secondary-subtle"
19
19
  >
20
20
  {{ $t.i19add$1ToEarn.replace('$1',
21
21
  $money(freeShippingFromValue - shoppingCart.subtotal)) }}
22
22
  <strong class="lowercase">{{ $t.i19freeShipping }}</strong>
23
23
  </div>
24
- <div v-else class="bg-success-50 text-success-800 p-3">
25
- <i class="text-success-900 i-check mr-1"></i>
24
+ <div v-else class="bg-success-50 p-3 text-success-800">
25
+ <i class="mr-1 text-success-900 i-check"></i>
26
26
  {{ $t.i19freeShippingFrom }} {{ $money(freeShippingFromValue) }}
27
27
  </div>
28
28
  </div>
@@ -39,19 +39,37 @@
39
39
  </div>
40
40
  <Prices :price="shoppingCart.subtotal" class="col-span-3 text-lg" />
41
41
  </div>
42
+ <div v-if="!hasShippingCalculator" class="my-2.5 text-right">
43
+ <a
44
+ href="#"
45
+ class="text-base-700 decoration-base-300 ui-link"
46
+ @click.prevent.stop="hasShippingCalculator = true"
47
+ >
48
+ {{ $t.i19calculateShipping }}
49
+ <i class="ml-1 text-base-500 i-truck-line"></i>
50
+ </a>
51
+ </div>
52
+ <Fade slide="down">
53
+ <ShippingCalculator
54
+ v-if="hasShippingCalculator"
55
+ :shipped-items="shoppingCart.items"
56
+ class="my-2.5 flex flex-wrap justify-end"
57
+ can-auto-submit
58
+ />
59
+ </Fade>
42
60
  <CheckoutLink
43
61
  to="checkout"
44
- class="ui-btn-lg ui-btn-primary my-2.5 w-full text-right"
62
+ class="my-2.5 w-full text-right ui-btn-lg ui-btn-primary"
45
63
  >
46
- <i class="i-check mr-2"></i>
64
+ <i class="mr-2 i-check"></i>
47
65
  {{ $t.i19checkout }}
48
66
  </CheckoutLink>
49
67
  <a
50
68
  href="#"
51
69
  @click.prevent="emit('close')"
52
- class="text-base-500 ui-link hover:text-base-700 text-sm"
70
+ class="text-sm text-base-500 ui-link hover:text-base-700"
53
71
  >
54
- <i class="i-arrow-right-line mr-1 rotate-180"></i>
72
+ <i class="mr-1 rotate-180 i-arrow-right-line"></i>
55
73
  {{ $t.i19continueShopping }}
56
74
  </a>
57
75
  </footer>
@@ -64,6 +82,8 @@ import { shoppingCart, totalItems } from '@@sf/state/shopping-cart';
64
82
  import CheckoutLink from '@@sf/components/CheckoutLink.vue';
65
83
  import Prices from '~/components/Prices.vue';
66
84
  import CartItem from '~/components/CartItem.vue';
85
+ import ShippingCalculator from '~/components/ShippingCalculator.vue';
67
86
 
68
87
  const emit = defineEmits(['close']);
88
+ const hasShippingCalculator = ref(false);
69
89
  </script>
@@ -54,7 +54,5 @@ export type Props = {
54
54
 
55
55
  defineProps<Props>();
56
56
  const isMounted = ref(false);
57
- onMounted(() => {
58
- isMounted.value = true;
59
- });
57
+ onMounted(() => { isMounted.value = true; });
60
58
  </script>
@@ -1,14 +1,24 @@
1
1
  <template>
2
- <section class="ui-section relative grid grid-cols-1 items-start
3
- gap-5 md:gap-4 lg:grid-cols-4 2xl:gap-6">
2
+ <section class="relative grid grid-cols-1 items-start gap-x-5
3
+ ui-section lg:grid-cols-4 lg:gap-x-4 2xl:gap-x-6">
4
4
  <div class="w-full lg:col-span-3">
5
5
  <template v-if="product.pictures?.length">
6
- <ImagesGallery :pictures="product.pictures" />
6
+ <ImagesGallery :pictures="product.pictures" class="mb-5" />
7
7
  </template>
8
8
  </div>
9
- <div class="lg:sticky-header:translate-y-24 top-0 py-4
10
- transition-transform lg:sticky">
11
- <h1 class="text-secondary-900 ui-text-brand text-lg">
9
+ <div class="top-0 pt-4 transition-transform
10
+ lg:sticky lg:pb-4 lg:sticky-header:translate-y-24">
11
+ <ul class="flax-wrap mb-3 flex gap-2">
12
+ <li class="flex items-center gap-1 py-1 font-normal ui-badge-pill">
13
+ <i class="m-0 text-secondary-700 i-arrow-path-rounded-square-16-solid"></i>
14
+ <span class="whitespace-nowrap text-sm">devolução grátis</span>
15
+ </li>
16
+ <li class="flex items-center gap-1 py-1 font-normal ui-badge-pill">
17
+ <i class="m-0 text-secondary-700 i-building-storefront-solid"></i>
18
+ <span class="whitespace-nowrap text-sm">desde 1984</span>
19
+ </li>
20
+ </ul>
21
+ <h1 class="text-lg text-base-600 ui-text-brand">
12
22
  {{ title }}
13
23
  </h1>
14
24
  <div v-if="isActive" class="mt-5">
@@ -20,9 +30,9 @@
20
30
  class="my-4"
21
31
  />
22
32
  <Fade slide="down">
23
- <div v-if="hasSkuSelectionAlert" class="ui-alert inline-block">
33
+ <div v-if="hasSkuSelectionAlert" class="inline-block ui-alert">
24
34
  {{ $t.i19selectVariationMsg }}
25
- <i class="i-arrow-right-line ml-1 -rotate-90"></i>
35
+ <i class="ml-1 -rotate-90 i-arrow-right-line"></i>
26
36
  </div>
27
37
  </Fade>
28
38
  <div class="mt-5 flex flex-wrap items-center gap-x-4 gap-y-2
@@ -31,11 +41,11 @@
31
41
  v-model="quantity"
32
42
  :min="product.min_quantity"
33
43
  :max="product.quantity"
34
- class="border-base-100 rounded md:mr-5
44
+ class="rounded border-base-100 md:mr-5
35
45
  lg:mb-2 lg:mr-auto lg:border-2"
36
46
  />
37
47
  <CheckoutLink
38
- class="ui-btn-lg ui-btn-primary grow text-center"
48
+ class="grow text-center ui-btn-lg ui-btn-primary"
39
49
  to="checkout"
40
50
  :cart-item="{
41
51
  product_id: product._id,
@@ -45,17 +55,24 @@
45
55
  :data-tooltip="!isSkuSelected ? $t.i19chooseProductDetailsToBuy : null"
46
56
  @click="checkVariation"
47
57
  >
48
- <i class="i-chevron-double-right mr-1"></i>
58
+ <i class="mr-1 i-chevron-double-right"></i>
49
59
  {{ $t.i19buy }}
50
60
  </CheckoutLink>
51
61
  <button
52
- class="ui-btn-lg ui-btn-contrast grow"
62
+ class="grow ui-btn-lg ui-btn-contrast"
53
63
  @click.prevent="addToCart"
54
64
  :data-tooltip="!isSkuSelected ? $t.i19chooseProductDetailsToBuy : null"
55
65
  >
56
66
  {{ $t.i19addToCart }}
57
67
  </button>
58
68
  </div>
69
+ <div class="mt-6 rounded border-2
70
+ border-base-50 border-t-secondary-100 p-4 lg:mt-4">
71
+ <ShippingCalculator
72
+ :shipped-items="[{ ...product, quantity }]"
73
+ has-label
74
+ />
75
+ </div>
59
76
  </div>
60
77
  </div>
61
78
  <div class="w-full lg:col-span-3">
@@ -74,6 +91,7 @@ import QuantitySelector from '@@sf/components/QuantitySelector.vue';
74
91
  import Prices from '~/components/Prices.vue';
75
92
  import ImagesGallery from '~/components/ImagesGallery.vue';
76
93
  import SkuSelector from '~/components/SkuSelector.vue';
94
+ import ShippingCalculator from '~/components/ShippingCalculator.vue';
77
95
 
78
96
  export interface Props {
79
97
  product?: Products;
@@ -36,21 +36,21 @@
36
36
  <section
37
37
  v-if="!isFetching
38
38
  && (searchHistory.length || productCount > products.length)"
39
- class="bg-base-100/80 grid grid-cols-1 items-center
40
- gap-4 p-4 backdrop-blur-md
39
+ class="grid grid-cols-1 items-center gap-4
40
+ bg-base-100/80 p-4 backdrop-blur-md
41
41
  md:grid-cols-2 md:rounded-b lg:mt-5 lg:grid-cols-3 lg:rounded"
42
42
  >
43
43
  <div class="flex items-center justify-end gap-4 md:order-2">
44
44
  <p
45
45
  v-if="productCount > 1"
46
- class="text-base-900 text-right text-sm lowercase"
46
+ class="text-right text-sm lowercase text-base-900"
47
47
  >
48
48
  <strong>{{ productCount }}</strong> {{ $t.i19itemsFound }}
49
49
  </p>
50
50
  <a
51
51
  v-if="productCount > products.length"
52
52
  :href="getSearchUrl(term)"
53
- class="ui-btn ui-btn-primary w-auto whitespace-nowrap text-center"
53
+ class="w-auto whitespace-nowrap text-center ui-btn ui-btn-primary"
54
54
  >
55
55
  {{ $t.i19seeAll }}
56
56
  </a>
@@ -65,13 +65,13 @@
65
65
  >
66
66
  <a
67
67
  :href="getSearchUrl(term)"
68
- class="text-base-700 ui-link text-sm font-normal"
68
+ class="text-sm font-normal text-base-700 ui-link"
69
69
  >
70
70
  {{ term }}
71
71
  </a>
72
72
  </li>
73
73
  <template #previous>
74
- <i class="i-clock m-0" :aria-label="$t.i19searchAgain"></i>
74
+ <i class="m-0 i-clock" :aria-label="$t.i19searchAgain"></i>
75
75
  </template>
76
76
  </Carousel>
77
77
  </nav>
@@ -88,15 +88,18 @@ import {
88
88
  } from '@@sf/composables/use-search-modal';
89
89
  import { getSearchUrl } from '@@sf/sf-lib';
90
90
  import ProductShelf from '~/components/ProductShelf.vue';
91
+ import middSearchEngine from '~/state/midd-search-engine';
91
92
 
92
93
  export interface Props extends UseSearchModalProps {}
93
94
 
94
95
  const props = defineProps<Props>();
95
96
  const {
96
97
  searchHistory,
98
+ searchEngine,
97
99
  isFetching,
98
100
  products,
99
101
  productCount,
100
102
  linkHits,
101
103
  } = useSearchModal(props);
104
+ middSearchEngine(searchEngine);
102
105
  </script>
@@ -1,17 +1,17 @@
1
1
  <template>
2
2
  <section
3
3
  v-if="searchTerm"
4
- class="text-base-700 ui-section-slim px-6 text-center text-xl lowercase"
4
+ class="px-6 text-center text-xl lowercase text-base-700 ui-section-slim"
5
5
  :class="hasFiltersBar ? 'relative z-[14] -mb-4' : 'mb-0'"
6
6
  >
7
7
  {{ $t.i19searchingFor }}
8
- <h1 class="text-base-800 inline font-bold italic">
8
+ <h1 class="inline font-bold italic text-base-800">
9
9
  {{ searchTerm }}
10
10
  </h1>
11
11
  </section>
12
12
  <div
13
13
  v-if="isFetching && !products.length"
14
- class="ui-section relative min-h-[300px]"
14
+ class="relative min-h-[300px] ui-section"
15
15
  >
16
16
  <Skeleton class="absolute top-0 w-full px-5" is-bold is-large />
17
17
  </div>
@@ -19,13 +19,13 @@
19
19
  <Fade>
20
20
  <section
21
21
  v-if="hasFiltersBar"
22
- class="to-base-100 ui-section-slim sticky-header:translate-y-16
23
- lg:sticky-header:translate-y-24 sticky top-0
24
- z-[12] flex items-center justify-between
25
- rounded-b bg-white/80 px-6 py-4 shadow-sm
26
- backdrop-blur-sm transition-transform"
22
+ class="sticky top-0 z-[12]
23
+ flex items-center justify-between
24
+ rounded-b bg-white/80 to-base-100 px-6
25
+ py-4 shadow-sm backdrop-blur-sm transition-transform ui-section-slim
26
+ sticky-header:translate-y-16 lg:sticky-header:translate-y-24"
27
27
  >
28
- <strong class="text-base-700 font-medium lowercase">
28
+ <strong class="font-medium lowercase text-base-700">
29
29
  <template v-if="resultMeta.count > 1">
30
30
  {{ resultMeta.count }}
31
31
  <span class="hidden lg:inline">{{ $t.i19itemsFound }}</span>
@@ -34,23 +34,23 @@
34
34
  </strong>
35
35
  <div class="flex items-center gap-4">
36
36
  <span class="hidden text-xl leading-none md:block">
37
- <i class="text-base-600 i-adjustments-horizontal m-0"></i>
37
+ <i class="m-0 text-base-600 i-adjustments-horizontal"></i>
38
38
  </span>
39
39
  <button
40
40
  @click="isFiltersOpen = !isFiltersOpen"
41
- class="ui-btn-sm ui-btn-secondary relative"
41
+ class="relative ui-btn-sm ui-btn-secondary"
42
42
  >
43
43
  <span class="hidden md:inline">
44
44
  {{ $t.i19filterProducts }}
45
45
  </span>
46
46
  <span class="md:hidden">
47
- <i class="i-adjustments-horizontal mr-1"></i>
47
+ <i class="mr-1 i-adjustments-horizontal"></i>
48
48
  {{ $t.i19filterOut }}
49
49
  </span>
50
50
  <span
51
51
  v-if="filtersCount"
52
- class="outline-3 outline-secondary/80 ui-badge-pill-sm
53
- absolute -right-1.5 -top-1 outline"
52
+ class="outline-3 absolute -right-1.5
53
+ -top-1 outline outline-secondary/80 ui-badge-pill-sm"
54
54
  >
55
55
  {{ filtersCount }}
56
56
  </span>
@@ -58,14 +58,14 @@
58
58
  <Listbox
59
59
  v-model="sortOption"
60
60
  as="div"
61
- class="text-base-800 relative text-sm"
61
+ class="relative text-sm text-base-800"
62
62
  >
63
63
  <ListboxButton :id="$useId('ss')" class="ui-btn-sm ui-btn-secondary">
64
64
  {{ $t.i19sort }}
65
65
  </ListboxButton>
66
66
  <Fade>
67
- <ListboxOptions class="divide-base-100
68
- absolute right-0 mt-2 divide-y rounded bg-white
67
+ <ListboxOptions class="absolute
68
+ right-0 mt-2 divide-y divide-base-100 rounded bg-white
69
69
  shadow ring-1 ring-black/5 focus:outline-none">
70
70
  <ListboxOption
71
71
  v-for="({ label, value }) in sortOptions"
@@ -139,6 +139,7 @@ import Drawer from '@@sf/components/Drawer.vue';
139
139
  import Pagination from '~/components/Pagination.vue';
140
140
  import ProductShelf from '~/components/ProductShelf.vue';
141
141
  import SearchFilters from '~/components/SearchFilters.vue';
142
+ import middSearchEngine from '~/state/midd-search-engine';
142
143
 
143
144
  export interface Props extends UseSearchShowcaseProps {}
144
145
 
@@ -157,6 +158,7 @@ const {
157
158
  sortOptions,
158
159
  sortOption,
159
160
  } = useSearchShowcase({ ...props, showcase });
161
+ middSearchEngine(searchEngine);
160
162
  if (import.meta.env.SSR) {
161
163
  await fetching;
162
164
  }
@@ -0,0 +1,100 @@
1
+ <template>
2
+ <div class="max-w-sm">
3
+ <form
4
+ class="group"
5
+ @submit.prevent="() => !isFetching && fetchShippingServices()"
6
+ >
7
+ <label
8
+ :for="zipInputId"
9
+ :class="hasLabel
10
+ ? 'lg:text-sm text-base-700 flex flex-wrap gap-x-5 items-center mb-1.5'
11
+ : 'sr-only'"
12
+ >
13
+ <span>{{ $t.i19calculateShipping }}</span>
14
+ <ALink
15
+ v-if="hasLabel && $settings.countryCode === 'BR'"
16
+ href="https://buscacepinter.correios.com.br/app/endereco/index.php"
17
+ class="text-xs font-normal text-base-500 ui-link"
18
+ >
19
+ Não sei meu CEP
20
+ <i class="mr-1 opacity-50 i-arrow-top-right-on-square"></i>
21
+ </ALink>
22
+ </label>
23
+ <div class="relative max-w-52">
24
+ <input
25
+ ref="zipInput"
26
+ :id="zipInputId"
27
+ type="tel"
28
+ :readonly="isFetching"
29
+ v-model.trim="zipCode"
30
+ placeholder="12345-123"
31
+ class="w-full"
32
+ :class="isFetching && 'bg-base-50'"
33
+ />
34
+ <button
35
+ class="absolute inset-y-0 end-0 grid w-12
36
+ place-content-center text-xl
37
+ hover:text-primary group-focus-within:text-primary"
38
+ :class="isMounted && !shippingServices.length && zipCode.length > 1
39
+ ? 'text-primary' : `${hasLabel ? 'text-base-400' : 'text-base-600'}`"
40
+ :aria-label="$t.i19calculateShipping"
41
+ >
42
+ <Spinner v-if="isFetching" class="size-5" />
43
+ <i v-else class="m-0 i-truck-line"></i>
44
+ </button>
45
+ </div>
46
+ </form>
47
+ <Fade slide="down">
48
+ <ul
49
+ v-if="!isFetching && shippingServices.length"
50
+ class="mt-2 grow divide-y divide-base-200
51
+ rounded border border-base-100 bg-base-50/50 px-3 py-1"
52
+ >
53
+ <li
54
+ v-for="({ label, shipping_line: shipping }, i) in shippingServices"
55
+ :key="`${zipCode}-${i}`"
56
+ class="py-2.5 text-base-800 md:text-sm"
57
+ >
58
+ <div class="flex flex-wrap items-center">
59
+ <div class="grow">
60
+ <strong class="mr-2 font-semibold">
61
+ {{ getShippingDeadline(shipping) }}
62
+ </strong>
63
+ <span class="mr-2">{{ getShippingPrice(shipping) }}</span>
64
+ </div>
65
+ <small class="text-base-600">{{ label }}</small>
66
+ </div>
67
+ <small v-if="shipping.delivery_instructions" class="text-base-700">
68
+ {{ shipping.delivery_instructions }}
69
+ </small>
70
+ </li>
71
+ </ul>
72
+ </Fade>
73
+ </div>
74
+ </template>
75
+
76
+ <script setup lang="ts">
77
+ import {
78
+ type Props as UseShippingCalculatorProps,
79
+ useShippingCalculator,
80
+ } from '@@sf/composables/use-shipping-calculator';
81
+ import { useId } from '@@sf/sf-lib';
82
+ import Spinner from '@@sf/components/Spinner.vue';
83
+
84
+ export interface Props extends UseShippingCalculatorProps {
85
+ hasLabel?: boolean;
86
+ }
87
+
88
+ const props = defineProps<Props>();
89
+ const zipCode = ref('');
90
+ const zipInputId = useId('ZipInput');
91
+ const {
92
+ isFetching,
93
+ fetchShippingServices,
94
+ shippingServices,
95
+ getShippingDeadline,
96
+ getShippingPrice,
97
+ } = useShippingCalculator({ ...props, zipCode });
98
+ const isMounted = ref(false);
99
+ onMounted(() => { isMounted.value = true; });
100
+ </script>
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  import { usePageSections } from '@@sf/layouts/use-page-main';
3
+ import { SearchEngine } from '@@sf/state/search-engine';
3
4
  import ContentClearfix from '@@sf/components/ContentClearfix.vue';
4
5
  import BannersGrid from '~/components/BannersGrid.astro';
5
6
  import Breadcrumbs from '~/components/Breadcrumbs.vue';
@@ -11,6 +12,7 @@ import ProductSpecifications from '~/components/ProductSpecifications.vue';
11
12
  import SearchShowcase from '~/components/SearchShowcase.vue';
12
13
  import PageTitle from '~/components/PageTitle.vue';
13
14
  import ContentEntry from '~/components/ContentEntry.vue';
15
+ import middSearchEngine from '~/state/midd-search-engine';
14
16
 
15
17
  const { routeContext } = Astro.locals;
16
18
  const { sections } = await usePageSections({
@@ -19,6 +21,7 @@ const { sections } = await usePageSections({
19
21
  if (type === 'c:foo') return { props: { ...content, foo: 'bar' } };
20
22
  return { props: content };
21
23
  },
24
+ searchEngine: middSearchEngine(new SearchEngine()),
22
25
  });
23
26
  const { cmsContent } = routeContext;
24
27
  /* `apiContext` is surelly set here (from Main.astro)
@@ -0,0 +1,19 @@
1
+ import type { SearchEngineInstance } from '@@sf/state/search-engine';
2
+
3
+ export default (searchEngine: SearchEngineInstance) => {
4
+ searchEngine.addMiddleware((searchOptions) => {
5
+ if (!searchOptions.term) return;
6
+ if (!searchOptions.params) searchOptions.params = {};
7
+ let { sort } = searchOptions.params;
8
+ if (
9
+ (typeof sort === 'string' || typeof sort === 'object')
10
+ && (sort as string[]).includes('-available')
11
+ ) return;
12
+ searchOptions.params.sort = '-available,-in_stock';
13
+ if (sort) {
14
+ if (Array.isArray(sort)) sort = sort.join(',');
15
+ searchOptions.params.sort += `,${sort}`;
16
+ }
17
+ });
18
+ return searchEngine;
19
+ };
@@ -15,8 +15,8 @@
15
15
  },
16
16
  "main": "index.js",
17
17
  "dependencies": {
18
- "@cloudcommerce/events": "^2.5.0",
19
- "@cloudcommerce/firebase": "^2.5.0",
20
- "@cloudcommerce/modules": "^2.5.0"
18
+ "@cloudcommerce/events": "^2.6.0",
19
+ "@cloudcommerce/firebase": "^2.6.0",
20
+ "@cloudcommerce/modules": "^2.6.0"
21
21
  }
22
22
  }
@@ -26,10 +26,10 @@
26
26
  "url": "https://github.com/ecomplus/cloud-commerce/issues"
27
27
  },
28
28
  "dependencies": {
29
- "@cloudcommerce/cli": "^2.5.0"
29
+ "@cloudcommerce/cli": "^2.6.0"
30
30
  },
31
31
  "devDependencies": {
32
- "@cloudcommerce/eslint": "^2.5.0",
32
+ "@cloudcommerce/eslint": "^2.6.0",
33
33
  "husky": "^9.0.10",
34
34
  "lint-staged": "^15.2.2"
35
35
  }