cloudcommerce 2.0.0 → 2.0.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.
- package/CHANGELOG.md +8 -0
- package/ecomplus-stores/barra-doce/conf/firebase.json +7 -0
- package/ecomplus-stores/barra-doce/functions/many/package.json +3 -3
- package/ecomplus-stores/barra-doce/functions/ssr/astro.config.mjs +18 -3
- package/ecomplus-stores/barra-doce/functions/ssr/content/blog/3.md +24 -0
- package/ecomplus-stores/barra-doce/functions/ssr/content/blog/4.md +24 -0
- package/ecomplus-stores/barra-doce/functions/ssr/content/blog/5.md +24 -0
- package/ecomplus-stores/barra-doce/functions/ssr/content/blog/dos.md +24 -0
- package/ecomplus-stores/barra-doce/functions/ssr/content/blog/uno.md +24 -0
- package/ecomplus-stores/barra-doce/functions/ssr/content/extra-pages/contato.md +9 -0
- package/ecomplus-stores/barra-doce/functions/ssr/content/extra-pages/terms.md +20 -0
- package/ecomplus-stores/barra-doce/functions/ssr/content/extra-pages/trocas.md +9 -0
- package/ecomplus-stores/barra-doce/functions/ssr/content/pages/brands.json +16 -0
- package/ecomplus-stores/barra-doce/functions/ssr/content/pages/categories.json +16 -0
- package/ecomplus-stores/barra-doce/functions/ssr/content/pages/collections.json +16 -0
- package/ecomplus-stores/barra-doce/functions/ssr/content/pages/search.json +7 -0
- package/ecomplus-stores/barra-doce/functions/ssr/package.json +10 -9
- package/ecomplus-stores/barra-doce/functions/ssr/src/assets/style.css +23 -9
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/BannersGrid.astro +1 -1
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/BlogPosts.vue +88 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/Breadcrumbs.vue +49 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/CartSidebar.vue +2 -2
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/CheckoutPage.vue +14 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/Collapse.vue +4 -4
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/ContentEntry.vue +23 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/DocBanners.vue +26 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/FooterStamps.vue +1 -1
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/HeroSlider.vue +1 -1
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/ImagesGallery.vue +5 -4
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/LoginForm.vue +2 -2
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/PageTitle.vue +43 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/Pagination.vue +67 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/Prices.vue +1 -1
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/ProductCard.vue +3 -4
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/ProductDetails.vue +4 -3
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/ProductShelf.vue +34 -18
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/ProductSpecifications.vue +1 -1
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/SearchFilters.vue +122 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/SearchModal.vue +97 -1
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/SearchShowcase.vue +169 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/ShopFooter.vue +10 -6
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/ShopHeader.vue +61 -63
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/ShopHeaderSubmenu.vue +1 -1
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/ShopSidenav.vue +1 -1
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/SkuSelector.vue +7 -7
- package/ecomplus-stores/barra-doce/functions/ssr/src/env.d.ts +4 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/layouts/PageFooter.astro +4 -1
- package/ecomplus-stores/barra-doce/functions/ssr/src/layouts/PageHeader.astro +2 -2
- package/ecomplus-stores/barra-doce/functions/ssr/src/main/Fallback.astro +28 -5
- package/ecomplus-stores/barra-doce/functions/ssr/src/main/Main.astro +26 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/main/content/Hero.astro +33 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/main/{Sections.astro → content/Sections.astro} +27 -4
- package/ecomplus-stores/barra-doce/functions/ssr/src/pages/[...slug].astro +35 -8
- package/ecomplus-stores/barra-doce/functions/ssr/src/pages/app/account.astro +6 -2
- package/ecomplus-stores/barra-doce/functions/ssr/src/pages/app/index.astro +24 -4
- package/ecomplus-stores/barra-doce/functions/ssr/src/pages/blog/[page].astro +71 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/pages/blog/_blog-pages.ts +9 -0
- package/ecomplus-stores/barra-doce/functions/ssr/src/pages/~fallback.astro +9 -2
- package/ecomplus-stores/barra-doce/functions/with-apps/package.json +3 -3
- package/ecomplus-stores/barra-doce/package.json +2 -2
- package/package.json +2 -2
- package/packages/api/package.json +1 -1
- package/packages/apps/affiliate-program/package.json +1 -1
- package/packages/apps/correios/package.json +1 -1
- package/packages/apps/custom-payment/package.json +1 -1
- package/packages/apps/custom-shipping/package.json +1 -1
- package/packages/apps/datafrete/package.json +1 -1
- package/packages/apps/discounts/package.json +1 -1
- package/packages/apps/emails/package.json +1 -1
- package/packages/apps/fb-conversions/package.json +1 -1
- package/packages/apps/flash-courier/package.json +1 -1
- package/packages/apps/frenet/package.json +1 -1
- package/packages/apps/galaxpay/package.json +1 -1
- package/packages/apps/google-analytics/package.json +1 -1
- package/packages/apps/jadlog/package.json +1 -1
- package/packages/apps/loyalty-points/package.json +1 -1
- package/packages/apps/mandae/package.json +1 -1
- package/packages/apps/melhor-envio/package.json +1 -1
- package/packages/apps/mercadopago/package.json +1 -1
- package/packages/apps/pagarme/package.json +1 -1
- package/packages/apps/pagarme-v5/package.json +1 -1
- package/packages/apps/paghiper/package.json +1 -1
- package/packages/apps/pix/package.json +1 -1
- package/packages/apps/tiny-erp/package.json +1 -1
- package/packages/apps/webhooks/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/config/package.json +1 -1
- package/packages/emails/package.json +1 -1
- package/packages/eslint/package.json +1 -1
- package/packages/events/package.json +1 -1
- package/packages/feeds/package.json +1 -1
- package/packages/firebase/package.json +1 -1
- package/packages/i18n/package.json +1 -1
- package/packages/modules/package.json +1 -1
- package/packages/passport/package.json +1 -1
- package/packages/ssr/package.json +1 -1
- package/packages/storefront/config/astro/context-directive.mjs +16 -2
- package/packages/storefront/config/astro/index.d.ts +3 -1
- package/packages/storefront/package.json +1 -1
- package/packages/storefront/src/lib/components/SharedData.astro +1 -1
- package/packages/storefront/src/lib/composables/use-shared-data.ts +2 -1
- package/packages/test-base/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/ecomplus-stores/barra-doce/functions/ssr/content/blog/.gitkeep +0 -0
- package/ecomplus-stores/barra-doce/functions/ssr/content/extra-pages/contato.json +0 -11
- package/ecomplus-stores/barra-doce/functions/ssr/content/extra-pages/terms.json +0 -11
- package/ecomplus-stores/barra-doce/functions/ssr/content/extra-pages/trocas.json +0 -11
- package/ecomplus-stores/barra-doce/functions/ssr/src/components/Breadcrumbs.astro +0 -44
- package/ecomplus-stores/barra-doce/functions/ssr/src/main/Home.astro +0 -37
- package/ecomplus-stores/barra-doce/functions/ssr/src/main/Wildcard.astro +0 -18
- package/ecomplus-stores/barra-doce/functions/ssr/src/pages/index.astro +0 -32
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section
|
|
3
|
+
v-if="searchTerm"
|
|
4
|
+
class="ui-section-slim text-base-700 px-6 text-center text-xl lowercase"
|
|
5
|
+
:class="hasFiltersBar ? 'relative z-[14] -mb-4' : 'mb-0'"
|
|
6
|
+
>
|
|
7
|
+
{{ $t.i19searchingFor }}
|
|
8
|
+
<h1 class="text-base-800 inline font-bold italic">
|
|
9
|
+
{{ searchTerm }}
|
|
10
|
+
</h1>
|
|
11
|
+
</section>
|
|
12
|
+
<div
|
|
13
|
+
v-if="isFetching && !products.length"
|
|
14
|
+
class="ui-section relative min-h-[300px]"
|
|
15
|
+
>
|
|
16
|
+
<Skeleton class="absolute top-0 w-full px-5" is-bold is-large />
|
|
17
|
+
</div>
|
|
18
|
+
<article ref="showcase" class="relative">
|
|
19
|
+
<Fade>
|
|
20
|
+
<section
|
|
21
|
+
v-if="hasFiltersBar"
|
|
22
|
+
class="ui-section-slim
|
|
23
|
+
sticky-header:translate-y-16 lg:sticky-header:translate-y-14
|
|
24
|
+
to-base-100 sticky top-0 z-[12] flex items-center justify-between
|
|
25
|
+
rounded-b bg-white/80 px-6 py-4 shadow-sm backdrop-blur-sm
|
|
26
|
+
transition-transform"
|
|
27
|
+
>
|
|
28
|
+
<strong class="text-base-700 font-medium lowercase">
|
|
29
|
+
<template v-if="resultMeta.count > 1">
|
|
30
|
+
{{ resultMeta.count }}
|
|
31
|
+
<span class="hidden lg:inline">{{ $t.i19itemsFound }}</span>
|
|
32
|
+
<span class="lg:hidden">{{ $t.i19products }}</span>
|
|
33
|
+
</template>
|
|
34
|
+
</strong>
|
|
35
|
+
<div class="flex items-center gap-4">
|
|
36
|
+
<span class="hidden text-xl leading-none md:block">
|
|
37
|
+
<i class="i-adjustments-horizontal text-base-600 m-0"></i>
|
|
38
|
+
</span>
|
|
39
|
+
<button
|
|
40
|
+
@click="isFiltersOpen = !isFiltersOpen"
|
|
41
|
+
class="ui-btn-sm ui-btn-secondary relative"
|
|
42
|
+
>
|
|
43
|
+
<span class="hidden md:inline">
|
|
44
|
+
{{ $t.i19filterProducts }}
|
|
45
|
+
</span>
|
|
46
|
+
<span class="md:hidden">
|
|
47
|
+
<i class="i-adjustments-horizontal mr-1"></i>
|
|
48
|
+
{{ $t.i19filterOut }}
|
|
49
|
+
</span>
|
|
50
|
+
<span
|
|
51
|
+
v-if="filtersCount"
|
|
52
|
+
class="ui-badge-pill-sm outline-secondary/80 outline-3
|
|
53
|
+
absolute -right-1.5 -top-1 outline"
|
|
54
|
+
>
|
|
55
|
+
{{ filtersCount }}
|
|
56
|
+
</span>
|
|
57
|
+
</button>
|
|
58
|
+
<Listbox
|
|
59
|
+
v-model="sortOption"
|
|
60
|
+
as="div"
|
|
61
|
+
class="text-base-800 relative text-sm"
|
|
62
|
+
>
|
|
63
|
+
<ListboxButton class="ui-btn-sm ui-btn-secondary">
|
|
64
|
+
{{ $t.i19sort }}
|
|
65
|
+
</ListboxButton>
|
|
66
|
+
<Fade>
|
|
67
|
+
<ListboxOptions class="divide-base-100
|
|
68
|
+
absolute right-0 mt-2 divide-y rounded bg-white
|
|
69
|
+
shadow ring-1 ring-black/5 focus:outline-none">
|
|
70
|
+
<ListboxOption
|
|
71
|
+
v-for="({ label, value }) in sortOptions"
|
|
72
|
+
:key="value || 'sort'"
|
|
73
|
+
:value="value"
|
|
74
|
+
as="template"
|
|
75
|
+
v-slot="{ selected, active }"
|
|
76
|
+
>
|
|
77
|
+
<li>
|
|
78
|
+
<component
|
|
79
|
+
:is="selected ? 'div' : 'button'"
|
|
80
|
+
class="flex w-full py-2 pl-3 pr-6"
|
|
81
|
+
:class="!selected && active
|
|
82
|
+
&& 'bg-secondary-100 text-secondary'"
|
|
83
|
+
>
|
|
84
|
+
<div class="w-5">
|
|
85
|
+
<i v-show="selected" class="i-check"></i>
|
|
86
|
+
</div>
|
|
87
|
+
{{ label }}
|
|
88
|
+
</component>
|
|
89
|
+
</li>
|
|
90
|
+
</ListboxOption>
|
|
91
|
+
</ListboxOptions>
|
|
92
|
+
</Fade>
|
|
93
|
+
</Listbox>
|
|
94
|
+
</div>
|
|
95
|
+
</section>
|
|
96
|
+
</Fade>
|
|
97
|
+
<ProductShelf :products="products" is-grid>
|
|
98
|
+
<template #append>
|
|
99
|
+
<Fade slide="down">
|
|
100
|
+
<nav v-if="!isFetching && totalPages > 1" class="mt-3 lg:mt-4">
|
|
101
|
+
<Pagination
|
|
102
|
+
v-model:page="searchEngine.pageNumber.value"
|
|
103
|
+
:total-pages="totalPages"
|
|
104
|
+
/>
|
|
105
|
+
</nav>
|
|
106
|
+
</Fade>
|
|
107
|
+
</template>
|
|
108
|
+
</ProductShelf>
|
|
109
|
+
<Fade>
|
|
110
|
+
<div
|
|
111
|
+
v-if="isFetching"
|
|
112
|
+
class="absolute left-0 top-0 z-[14] h-full w-full bg-white/40"
|
|
113
|
+
></div>
|
|
114
|
+
</Fade>
|
|
115
|
+
</article>
|
|
116
|
+
<Drawer
|
|
117
|
+
v-model="isFiltersOpen"
|
|
118
|
+
placement="end"
|
|
119
|
+
:backdrop-target="null"
|
|
120
|
+
:can-lock-scroll="false"
|
|
121
|
+
class="!z-[80] bg-white shadow [&_[data-drawer-close]]:bg-white/80"
|
|
122
|
+
>
|
|
123
|
+
<SearchFilters :search-engine="searchEngine" />
|
|
124
|
+
</Drawer>
|
|
125
|
+
</template>
|
|
126
|
+
|
|
127
|
+
<script setup lang="ts">
|
|
128
|
+
import {
|
|
129
|
+
useSearchShowcase,
|
|
130
|
+
type Props as UseSearchShowcaseProps,
|
|
131
|
+
} from '@@sf/composables/use-search-showcase';
|
|
132
|
+
import {
|
|
133
|
+
Listbox,
|
|
134
|
+
ListboxButton,
|
|
135
|
+
ListboxOptions,
|
|
136
|
+
ListboxOption,
|
|
137
|
+
} from '@headlessui/vue';
|
|
138
|
+
import Drawer from '@@sf/components/Drawer.vue';
|
|
139
|
+
import Pagination from '~/components/Pagination.vue';
|
|
140
|
+
import ProductShelf from '~/components/ProductShelf.vue';
|
|
141
|
+
import SearchFilters from '~/components/SearchFilters.vue';
|
|
142
|
+
|
|
143
|
+
export interface Props extends UseSearchShowcaseProps {}
|
|
144
|
+
|
|
145
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
146
|
+
canUseUrlParams: true,
|
|
147
|
+
});
|
|
148
|
+
const showcase = ref<HTMLElement | null>(null);
|
|
149
|
+
const {
|
|
150
|
+
searchEngine,
|
|
151
|
+
fetching,
|
|
152
|
+
isFetching,
|
|
153
|
+
products,
|
|
154
|
+
resultMeta,
|
|
155
|
+
totalPages,
|
|
156
|
+
filtersCount,
|
|
157
|
+
sortOptions,
|
|
158
|
+
sortOption,
|
|
159
|
+
} = useSearchShowcase({ ...props, showcase });
|
|
160
|
+
if (import.meta.env.SSR) {
|
|
161
|
+
await fetching;
|
|
162
|
+
}
|
|
163
|
+
const wasFetched = computed(() => searchEngine.wasFetched.value);
|
|
164
|
+
const searchTerm = computed(() => searchEngine.term.value);
|
|
165
|
+
const hasFiltersBar = computed(() => {
|
|
166
|
+
return wasFetched && !!(resultMeta.value.count > 4 || filtersCount.value);
|
|
167
|
+
});
|
|
168
|
+
const isFiltersOpen = ref(false);
|
|
169
|
+
</script>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<footer class="bg-base-50 border-base-100 w-screen border-t py-2">
|
|
2
|
+
<footer class="bg-base-50 border-base-100 mt-auto w-screen border-t py-2">
|
|
3
3
|
<div class="ui-section">
|
|
4
|
-
<div class="border-base-200 flex flex-wrap
|
|
5
|
-
|
|
4
|
+
<div class="border-base-200 flex flex-wrap justify-between
|
|
5
|
+
gap-y-5 border-b pb-7 sm:gap-x-10 lg:flex-nowrap">
|
|
6
6
|
<div class="shrink">
|
|
7
7
|
<slot name="logo" />
|
|
8
8
|
<div v-if="$settings.description" class="prose">
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
</ALink>
|
|
31
31
|
</div>
|
|
32
32
|
</div>
|
|
33
|
-
<div v-if="categories?.length" class="basis-1/2 sm:basis-auto">
|
|
33
|
+
<div v-if="categories?.length" class="basis-1/2 pr-2 sm:basis-auto sm:pr-0">
|
|
34
34
|
<div class="mb-2.5 text-lg font-medium">
|
|
35
35
|
{{ categoriesColTitle || $t.i19categories }}
|
|
36
36
|
</div>
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
</li>
|
|
52
52
|
</ul>
|
|
53
53
|
</div>
|
|
54
|
-
<div v-if="pageLinks?.length" class="basis-1/2 sm:basis-auto">
|
|
54
|
+
<div v-if="pageLinks?.length" class="basis-1/2 pl-2 sm:basis-auto sm:pl-0">
|
|
55
55
|
<div class="mb-2.5 text-lg font-medium">
|
|
56
56
|
{{ pagesColTitle || $t.i19institutional }}
|
|
57
57
|
</div>
|
|
@@ -61,7 +61,11 @@
|
|
|
61
61
|
? 'grid md:grid-cols-2 gap-x-5 gap-y-1.5' : 'space-y-1.5'"
|
|
62
62
|
>
|
|
63
63
|
<li v-for="({ title, href }, i) in pageLinks" :key="`p-${i}`">
|
|
64
|
-
<ALink
|
|
64
|
+
<ALink
|
|
65
|
+
:href="href"
|
|
66
|
+
class="ui-link"
|
|
67
|
+
:class="title === 'Blog' ? 'text-base-900' : 'text-base-600'"
|
|
68
|
+
>
|
|
65
69
|
{{ title }}
|
|
66
70
|
</ALink>
|
|
67
71
|
</li>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
sm:pr-2.5 lg:w-[calc(100vw-1rem)] lg:px-1 xl:max-w-[82rem] 2xl:max-w-[85rem]">
|
|
12
12
|
<div class="flex items-center justify-between">
|
|
13
13
|
<div
|
|
14
|
-
class="basis-1/4 lg:
|
|
14
|
+
class="basis-1/4 lg:mr-5 lg:basis-auto"
|
|
15
15
|
:class="!isSticky ? 'lg:hidden' : null"
|
|
16
16
|
>
|
|
17
17
|
<button
|
|
@@ -31,47 +31,49 @@
|
|
|
31
31
|
<div class="lg:grow" :class="isSticky ? '[&_img]:max-w-[170px]' : null">
|
|
32
32
|
<slot name="logo" />
|
|
33
33
|
</div>
|
|
34
|
-
<div class="flex basis-1/4
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
method="get"
|
|
38
|
-
class="relative mb-1 hidden w-[400px] lg:block"
|
|
39
|
-
@submit.prevent="searchTerm
|
|
40
|
-
? (isSearchOpen = !isSearchOpen)
|
|
41
|
-
: searchInput?.focus()"
|
|
42
|
-
>
|
|
34
|
+
<div class="text-base-800 flex basis-1/4
|
|
35
|
+
items-center justify-end gap-3 px-2 lg:gap-4">
|
|
36
|
+
<form action="/s" method="get" class="relative h-12">
|
|
43
37
|
<label for="HeaderSearch" class="sr-only">
|
|
44
38
|
{{ $t.i19searchProducts }}
|
|
45
39
|
</label>
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
40
|
+
<div
|
|
41
|
+
class="absolute -top-0.5 right-0 items-stretch
|
|
42
|
+
opacity-0 transition-opacity lg:z-auto lg:flex lg:opacity-100"
|
|
43
|
+
:class="isSearchOpen ? 'flex opacity-100' : '-z-10'"
|
|
44
|
+
>
|
|
45
|
+
<div class="hidden w-12 bg-gradient-to-r from-transparent
|
|
46
|
+
to-white sm:block"></div>
|
|
47
|
+
<input
|
|
48
|
+
ref="searchInput"
|
|
49
|
+
type="search"
|
|
50
|
+
id="HeaderSearch"
|
|
51
|
+
name="q"
|
|
52
|
+
v-model.trim="searchTerm"
|
|
53
|
+
:placeholder="$t.i19searchProducts"
|
|
54
|
+
class="from-secondary-50/10 to-secondary-50/80
|
|
55
|
+
border-secondary-200 placeholder:text-secondary-700/60
|
|
56
|
+
text-secondary-700 h-12 w-72 rounded-md bg-gradient-to-br
|
|
57
|
+
py-2.5 pl-4 pr-10 shadow-sm lg:w-[400px]"
|
|
58
|
+
@focusin="isSearchOpen = true"
|
|
59
|
+
/>
|
|
60
|
+
</div>
|
|
61
|
+
<span class="absolute -top-0.5 right-0 grid">
|
|
58
62
|
<button
|
|
59
63
|
type="submit"
|
|
60
|
-
|
|
64
|
+
:aria-label="$t.i19searchProducts"
|
|
65
|
+
class="hover:text-primary flex h-12
|
|
66
|
+
flex-col justify-center lg:px-2.5"
|
|
67
|
+
:class="isSearchOpen
|
|
68
|
+
? 'text-primary px-2.5'
|
|
69
|
+
: 'text-secondary-600'"
|
|
70
|
+
@click="toggleSearch"
|
|
61
71
|
>
|
|
62
72
|
<span class="sr-only">{{ $t.i19search }}</span>
|
|
63
|
-
<i class="i-search-3-line"></i>
|
|
73
|
+
<i class="i-search-3-line mb-0 h-7 w-7"></i>
|
|
64
74
|
</button>
|
|
65
75
|
</span>
|
|
66
76
|
</form>
|
|
67
|
-
<button
|
|
68
|
-
:aria-label="$t.i19searchProducts"
|
|
69
|
-
@click="isSearchOpen = !isSearchOpen"
|
|
70
|
-
class="lg:hidden"
|
|
71
|
-
>
|
|
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>
|
|
74
|
-
</button>
|
|
75
77
|
<AccountMenu class="hidden sm:block">
|
|
76
78
|
<template #button="{ open }">
|
|
77
79
|
<i
|
|
@@ -91,10 +93,10 @@
|
|
|
91
93
|
<i class="i-shopping-bag-3-fill group-hover:text-primary h-7 w-7
|
|
92
94
|
group-hover:scale-110 group-active:scale-125"></i>
|
|
93
95
|
<span
|
|
94
|
-
v-if="
|
|
96
|
+
v-if="cartTotalItems"
|
|
95
97
|
class="ui-badge-pill-sm absolute -right-1.5 -top-1"
|
|
96
98
|
>
|
|
97
|
-
{{
|
|
99
|
+
{{ cartTotalItems }}
|
|
98
100
|
</span>
|
|
99
101
|
</a>
|
|
100
102
|
</div>
|
|
@@ -119,14 +121,21 @@
|
|
|
119
121
|
</Drawer>
|
|
120
122
|
<Drawer
|
|
121
123
|
v-model="isSearchOpen"
|
|
124
|
+
:is-hidden="!quickSearchTerm"
|
|
122
125
|
:has-close-button="false"
|
|
126
|
+
:anchor-el="searchInput?.parentElement"
|
|
127
|
+
position="absolute"
|
|
123
128
|
placement="top"
|
|
129
|
+
animation="scale"
|
|
130
|
+
max-width="55rem"
|
|
131
|
+
class="bg-transparent lg:mt-10"
|
|
132
|
+
:class="isSticky ? 'mt-2 md:mt-3' : 'mt-3 sm:mt-4 md:mt-5'"
|
|
124
133
|
>
|
|
125
134
|
<Suspense>
|
|
126
|
-
<SearchModal v-if="isSearchOpenOnce" />
|
|
135
|
+
<SearchModal v-if="isSearchOpenOnce" :term="quickSearchTerm" />
|
|
127
136
|
<template #fallback>
|
|
128
137
|
<div class="container mx-auto">
|
|
129
|
-
<Skeleton class="p-6" is-large />
|
|
138
|
+
<Skeleton class="p-6" is-large is-bold />
|
|
130
139
|
</div>
|
|
131
140
|
</template>
|
|
132
141
|
</Suspense>
|
|
@@ -136,11 +145,14 @@
|
|
|
136
145
|
v-model="isCartOpen"
|
|
137
146
|
placement="end"
|
|
138
147
|
backdrop-target="#teleported-overlap"
|
|
148
|
+
class="shadow"
|
|
139
149
|
>
|
|
140
150
|
<Suspense>
|
|
141
151
|
<CartSidebar v-if="isCartOpenOnce" @close="isCartOpen = false" />
|
|
142
152
|
<template #fallback>
|
|
143
|
-
<
|
|
153
|
+
<div class="h-full bg-white">
|
|
154
|
+
<Skeleton class="px-6 pt-16" is-bold />
|
|
155
|
+
</div>
|
|
144
156
|
</template>
|
|
145
157
|
</Suspense>
|
|
146
158
|
</Drawer>
|
|
@@ -149,8 +161,6 @@
|
|
|
149
161
|
</template>
|
|
150
162
|
|
|
151
163
|
<script setup lang="ts">
|
|
152
|
-
import { watchOnce } from '@vueuse/core';
|
|
153
|
-
import { totalItems } from '@@sf/state/shopping-cart';
|
|
154
164
|
import {
|
|
155
165
|
type Props as UseShopHeaderProps,
|
|
156
166
|
useShopHeader,
|
|
@@ -166,38 +176,26 @@ const SearchModal = defineAsyncComponent(() => import('~/components/SearchModal.
|
|
|
166
176
|
const CartSidebar = defineAsyncComponent(() => import('~/components/CartSidebar.vue'));
|
|
167
177
|
const props = defineProps<Props>();
|
|
168
178
|
const header = ref<HTMLElement | null>(null);
|
|
179
|
+
const searchInput = ref<HTMLInputElement | null>(null);
|
|
169
180
|
const {
|
|
170
181
|
isSticky,
|
|
171
182
|
positionY,
|
|
172
183
|
categoryTrees,
|
|
173
184
|
inlineMenuTrees,
|
|
174
|
-
|
|
185
|
+
isSearchOpen,
|
|
186
|
+
isSearchOpenOnce,
|
|
187
|
+
searchTerm,
|
|
188
|
+
quickSearchTerm,
|
|
189
|
+
toggleSearch,
|
|
190
|
+
isCartOpen,
|
|
191
|
+
isCartOpenOnce,
|
|
192
|
+
cartTotalItems,
|
|
193
|
+
handleOnMounted,
|
|
194
|
+
} = useShopHeader({ ...props, header, searchInput });
|
|
175
195
|
const isSidenavOpen = ref(false);
|
|
176
|
-
const isSearchOpen = ref(false);
|
|
177
|
-
const isSearchOpenOnce = ref(false);
|
|
178
|
-
watchOnce(isSearchOpen, () => {
|
|
179
|
-
isSearchOpenOnce.value = true;
|
|
180
|
-
});
|
|
181
|
-
const isCartOpen = ref(false);
|
|
182
|
-
const isCartOpenOnce = ref(false);
|
|
183
|
-
watchOnce(isCartOpen, () => {
|
|
184
|
-
isCartOpenOnce.value = true;
|
|
185
|
-
});
|
|
186
196
|
const isMounted = ref(false);
|
|
187
|
-
const delayedTotalItems = ref(0);
|
|
188
197
|
onMounted(() => {
|
|
189
198
|
isMounted.value = true;
|
|
190
|
-
|
|
191
|
-
if (typeof prevTotalItems === 'number') {
|
|
192
|
-
if (prevTotalItems < newTotalItems) {
|
|
193
|
-
isCartOpen.value = true;
|
|
194
|
-
} else if (prevTotalItems && !newTotalItems) {
|
|
195
|
-
isCartOpen.value = false;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
delayedTotalItems.value = newTotalItems;
|
|
199
|
-
}, { immediate: true });
|
|
199
|
+
handleOnMounted();
|
|
200
200
|
});
|
|
201
|
-
const searchTerm = ref('');
|
|
202
|
-
const searchInput = ref<HTMLElement | null>(null);
|
|
203
201
|
</script>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<Fade>
|
|
10
10
|
<PopoverPanel
|
|
11
11
|
v-slot="{ close }"
|
|
12
|
-
class="Popover text-base-700 absolute top-3 z-
|
|
12
|
+
class="Popover text-base-700 absolute top-3 z-50
|
|
13
13
|
!transform rounded bg-white/80 px-7 py-5 text-base
|
|
14
14
|
shadow backdrop-blur-md"
|
|
15
15
|
:class="countMenuCols === 1 ? 'w-auto'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<div v-for="(options, gridId) in variationsGrids" :key="gridId">
|
|
3
|
+
<div v-for="(options, gridId) in variationsGrids" :key="gridId" class="mt-3">
|
|
4
4
|
<span class="text-base-700 text-sm font-medium">
|
|
5
5
|
{{ getGridTitle(gridId) }}:
|
|
6
6
|
<strong v-if="selectedOptions[gridId]" class="text-base-800">
|
|
@@ -10,17 +10,17 @@
|
|
|
10
10
|
<ul v-if="options.length < 7" class="mt-2 flex gap-2">
|
|
11
11
|
<li v-for="(optionText, i) in options" :key="`${gridId}-${i}`">
|
|
12
12
|
<button
|
|
13
|
-
class="ring-
|
|
13
|
+
class="ring-primary/60 rounded border"
|
|
14
14
|
:class="[
|
|
15
15
|
selectedOptions[gridId] === optionText
|
|
16
|
-
? 'border-
|
|
16
|
+
? 'border-primary ring-2'
|
|
17
17
|
: null,
|
|
18
18
|
gridId === 'colors'
|
|
19
|
-
? 'h-9 w-9 text-[
|
|
20
|
-
: 'px-2 py-
|
|
19
|
+
? 'h-9 w-9 text-[0px]'
|
|
20
|
+
: 'px-2.5 py-2 leading-none',
|
|
21
21
|
activeVariationsGrids[gridId].includes(optionText)
|
|
22
|
-
? 'text-
|
|
23
|
-
: 'text-
|
|
22
|
+
? 'text-primary-950 bg-primary-100 border-primary-400'
|
|
23
|
+
: 'text-primary-600 bg-primary-200 border-primary-300'
|
|
24
24
|
]"
|
|
25
25
|
:style="gridId === 'colors' ? getColorOptionBg(optionText) : undefined"
|
|
26
26
|
@click="selectOption({ optionText, gridId, gridIndex: i })"
|
|
@@ -38,11 +38,14 @@ if (pagesList?.isActive) {
|
|
|
38
38
|
pageLinks = [];
|
|
39
39
|
const pageSlugs = await getContent('extra-pages/');
|
|
40
40
|
for (let i = 0; i < pageSlugs.length; i++) {
|
|
41
|
-
const { title } = await getContent(`extra-pages/${pageSlugs[i]}`);
|
|
41
|
+
const { title } = await getContent(`extra-pages/${pageSlugs[i]}`) || {};
|
|
42
42
|
if (title) {
|
|
43
43
|
pageLinks.push({ title, href: `/p/${pageSlugs[i]}` });
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
+
if ((await getContent('blog/')).length) {
|
|
47
|
+
pageLinks.push({ title: 'Blog', href: '/blog/1/' });
|
|
48
|
+
}
|
|
46
49
|
}
|
|
47
50
|
}
|
|
48
51
|
---
|
|
@@ -19,8 +19,8 @@ const { getInlineClientJS } = await useSharedData({ field: 'categories' });
|
|
|
19
19
|
{pitchBar.slides.length > 1 && <PitchBar {...pitchBar} client:idle />}
|
|
20
20
|
{pitchBar.slides.length === 1 && <PitchBar {...pitchBar} />}
|
|
21
21
|
</slot>
|
|
22
|
-
<script is:inline set:html={getInlineClientJS()} />
|
|
23
|
-
<ShopHeader {...shopHeader} client:context>
|
|
22
|
+
<script async is:inline set:html={getInlineClientJS()} />
|
|
23
|
+
<ShopHeader {...shopHeader} client:context="data:categories">
|
|
24
24
|
<Fragment slot="logo">
|
|
25
25
|
<a href="/" class="inline-block">
|
|
26
26
|
<LogoHeading class="inline-block">
|
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
---
|
|
2
|
+
import {
|
|
3
|
+
i19home,
|
|
4
|
+
i19error,
|
|
5
|
+
i19errorMsg,
|
|
6
|
+
i19notFound,
|
|
7
|
+
} from '@@i18n';
|
|
2
8
|
---
|
|
3
9
|
|
|
4
10
|
<main>
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
<article class="prose mx-auto px-8 pt-20 pb-32">
|
|
12
|
+
<h1>{i19error} :/</h1>
|
|
13
|
+
<p class="hidden text-xl" id="errorMsg">
|
|
14
|
+
{i19errorMsg}
|
|
15
|
+
</p>
|
|
16
|
+
<p class="hidden text-xl" id="404Msg">
|
|
17
|
+
{i19notFound} (404)
|
|
18
|
+
</p>
|
|
19
|
+
<p class="text-xl" id="loadingMsg">
|
|
20
|
+
... ... ...
|
|
21
|
+
</p>
|
|
22
|
+
<a href="/" class="text-2xl">
|
|
23
|
+
<i class="i-arrow-right rotate-180 mr-1"></i>
|
|
24
|
+
{i19home}
|
|
25
|
+
</a>
|
|
26
|
+
</article>
|
|
27
|
+
<script>
|
|
28
|
+
const msgId = window.location.search.includes('status=404')
|
|
29
|
+
? '404Msg' : '5xxMsg'
|
|
30
|
+
document.getElementById(msgId)!.style.display = 'block';
|
|
31
|
+
document.getElementById('loadingMsg')!.style.display = 'none';
|
|
32
|
+
</script>
|
|
10
33
|
</main>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
import api from '@cloudcommerce/api';
|
|
3
|
+
import SharedData from '@@sf/components/SharedData.astro';
|
|
4
|
+
import Hero from '~/main/content/Hero.astro';
|
|
5
|
+
import Sections from '~/main/content/Sections.astro';
|
|
6
|
+
|
|
7
|
+
const { routeContext } = Astro.locals;
|
|
8
|
+
const { fetchingApiContext } = routeContext;
|
|
9
|
+
const sharedData: Record<string, any> = {};
|
|
10
|
+
if (fetchingApiContext) {
|
|
11
|
+
const [
|
|
12
|
+
{ data: { result: grids } },
|
|
13
|
+
] = await Promise.all([
|
|
14
|
+
api.get('grids'),
|
|
15
|
+
fetchingApiContext,
|
|
16
|
+
]);
|
|
17
|
+
sharedData.grids = grids;
|
|
18
|
+
}
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
<main>
|
|
22
|
+
{Object.entries(sharedData).map(([field, value]) =>
|
|
23
|
+
<SharedData field={field} value={value} />)}
|
|
24
|
+
<Hero />
|
|
25
|
+
<Sections />
|
|
26
|
+
</main>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { usePageHero } from '@@sf/layouts/use-page-main';
|
|
3
|
+
import BannerPictures from '@@sf/components/BannerPictures.astro';
|
|
4
|
+
import HeroSlider from '~/components/HeroSlider.vue';
|
|
5
|
+
|
|
6
|
+
const { routeContext } = Astro.locals;
|
|
7
|
+
const { heroSlider } = await usePageHero({ routeContext });
|
|
8
|
+
const heroSlides = heroSlider.slides;
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
{heroSlider.slides.length > 0 &&
|
|
12
|
+
<HeroSlider {...heroSlider} client:idle>
|
|
13
|
+
{heroSlides[0] && <BannerPictures
|
|
14
|
+
slot="picture-0" {...heroSlides[0]} index={0}
|
|
15
|
+
widths={[640, 856, 1024, 1536]} class="max-w-screen-sm sm:max-w-screen-lg" />}
|
|
16
|
+
{heroSlides[1] && <BannerPictures
|
|
17
|
+
slot="picture-1" {...heroSlides[1]} index={1}
|
|
18
|
+
widths={[856, 1024, 1536]} class="max-w-screen-sm sm:max-w-screen-lg" />}
|
|
19
|
+
{heroSlides[2] && <BannerPictures
|
|
20
|
+
slot="picture-2" {...heroSlides[2]} index={2}
|
|
21
|
+
widths={[856, 1024, 1536]} class="max-w-screen-sm sm:max-w-screen-lg" />}
|
|
22
|
+
{heroSlides[3] && <BannerPictures
|
|
23
|
+
slot="picture-3" {...heroSlides[3]} index={3}
|
|
24
|
+
widths={[856, 1024, 1536]} class="max-w-screen-sm sm:max-w-screen-lg" />}
|
|
25
|
+
{heroSlides[4] && <BannerPictures
|
|
26
|
+
slot="picture-4" {...heroSlides[4]} index={4}
|
|
27
|
+
widths={[856, 1024, 1536]} class="max-w-screen-sm sm:max-w-screen-lg" />}
|
|
28
|
+
{heroSlides[5] && <BannerPictures
|
|
29
|
+
slot="picture-5" {...heroSlides[5]} index={5}
|
|
30
|
+
widths={[856, 1024, 1536]} class="max-w-screen-sm sm:max-w-screen-lg" />}
|
|
31
|
+
<!-- https://github.com/withastro/astro/issues/5066#issuecomment-1277998365 -->
|
|
32
|
+
</HeroSlider>
|
|
33
|
+
}
|