cloudcommerce 2.0.0 → 2.0.2
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 +17 -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/home.json +3 -3
- 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 +24 -10
- 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 +64 -64
- 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/Base.astro +1 -1
- 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} +29 -6
- 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 +9 -9
- package/packages/api/package.json +1 -1
- package/packages/apps/affiliate-program/package.json +1 -1
- package/packages/apps/correios/package.json +2 -2
- package/packages/apps/custom-payment/package.json +1 -1
- package/packages/apps/custom-shipping/package.json +1 -1
- package/packages/apps/datafrete/package.json +2 -2
- 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 +3 -3
- package/packages/apps/frenet/package.json +2 -2
- package/packages/apps/galaxpay/package.json +2 -2
- package/packages/apps/google-analytics/package.json +2 -2
- package/packages/apps/jadlog/package.json +2 -2
- package/packages/apps/loyalty-points/package.json +1 -1
- package/packages/apps/mandae/package.json +3 -3
- package/packages/apps/melhor-envio/package.json +2 -2
- package/packages/apps/mercadopago/package.json +2 -2
- package/packages/apps/pagarme/package.json +2 -2
- package/packages/apps/pagarme-v5/package.json +2 -2
- package/packages/apps/paghiper/package.json +2 -2
- package/packages/apps/pix/package.json +2 -2
- package/packages/apps/tiny-erp/package.json +2 -2
- package/packages/apps/webhooks/package.json +2 -2
- package/packages/cli/package.json +1 -1
- package/packages/config/package.json +1 -1
- package/packages/emails/package.json +2 -2
- package/packages/eslint/package.json +3 -3
- 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 +2 -2
- package/packages/passport/package.json +1 -1
- package/packages/ssr/package.json +3 -3
- 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 +6 -6
- package/packages/storefront/src/lib/components/SharedData.astro +1 -1
- package/packages/storefront/src/lib/composables/use-shared-data.ts +2 -1
- package/packages/storefront/src/lib/composables/use-sku-selector.ts +11 -7
- 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,48 +31,50 @@
|
|
|
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
|
-
<
|
|
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
|
-
<AccountMenu class="hidden sm:block">
|
|
77
|
+
<AccountMenu v-if="!isMobile" class="hidden sm:block">
|
|
76
78
|
<template #button="{ open }">
|
|
77
79
|
<i
|
|
78
80
|
class="i-user-2-line text-base-600 hover:text-primary
|
|
@@ -91,15 +93,16 @@
|
|
|
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>
|
|
101
103
|
</div>
|
|
102
104
|
<ShopHeaderMenu
|
|
105
|
+
v-if="!isMobile"
|
|
103
106
|
v-show="!isSticky"
|
|
104
107
|
v-bind="{ inlineMenuTrees }"
|
|
105
108
|
class="mt-3 hidden px-3 lg:block 2xl:px-8"
|
|
@@ -119,14 +122,21 @@
|
|
|
119
122
|
</Drawer>
|
|
120
123
|
<Drawer
|
|
121
124
|
v-model="isSearchOpen"
|
|
125
|
+
:is-hidden="!quickSearchTerm"
|
|
122
126
|
:has-close-button="false"
|
|
127
|
+
:anchor-el="searchInput?.parentElement"
|
|
128
|
+
position="absolute"
|
|
123
129
|
placement="top"
|
|
130
|
+
animation="scale"
|
|
131
|
+
max-width="55rem"
|
|
132
|
+
class="bg-transparent lg:mt-10"
|
|
133
|
+
:class="isSticky ? 'mt-2 md:mt-3' : 'mt-3 sm:mt-4 md:mt-5'"
|
|
124
134
|
>
|
|
125
135
|
<Suspense>
|
|
126
|
-
<SearchModal v-if="isSearchOpenOnce" />
|
|
136
|
+
<SearchModal v-if="isSearchOpenOnce" :term="quickSearchTerm" />
|
|
127
137
|
<template #fallback>
|
|
128
138
|
<div class="container mx-auto">
|
|
129
|
-
<Skeleton class="p-6" is-large />
|
|
139
|
+
<Skeleton class="p-6" is-large is-bold />
|
|
130
140
|
</div>
|
|
131
141
|
</template>
|
|
132
142
|
</Suspense>
|
|
@@ -136,11 +146,14 @@
|
|
|
136
146
|
v-model="isCartOpen"
|
|
137
147
|
placement="end"
|
|
138
148
|
backdrop-target="#teleported-overlap"
|
|
149
|
+
class="shadow"
|
|
139
150
|
>
|
|
140
151
|
<Suspense>
|
|
141
152
|
<CartSidebar v-if="isCartOpenOnce" @close="isCartOpen = false" />
|
|
142
153
|
<template #fallback>
|
|
143
|
-
<
|
|
154
|
+
<div class="h-full bg-white">
|
|
155
|
+
<Skeleton class="px-6 pt-16" is-bold />
|
|
156
|
+
</div>
|
|
144
157
|
</template>
|
|
145
158
|
</Suspense>
|
|
146
159
|
</Drawer>
|
|
@@ -149,12 +162,11 @@
|
|
|
149
162
|
</template>
|
|
150
163
|
|
|
151
164
|
<script setup lang="ts">
|
|
152
|
-
import { watchOnce } from '@vueuse/core';
|
|
153
|
-
import { totalItems } from '@@sf/state/shopping-cart';
|
|
154
165
|
import {
|
|
155
166
|
type Props as UseShopHeaderProps,
|
|
156
167
|
useShopHeader,
|
|
157
168
|
} from '@@sf/composables/use-shop-header';
|
|
169
|
+
import { isMobile } from '@@sf/sf-lib';
|
|
158
170
|
import Drawer from '@@sf/components/Drawer.vue';
|
|
159
171
|
import ShopSidenav from '~/components/ShopSidenav.vue';
|
|
160
172
|
import ShopHeaderMenu from '~/components/ShopHeaderMenu.vue';
|
|
@@ -166,38 +178,26 @@ const SearchModal = defineAsyncComponent(() => import('~/components/SearchModal.
|
|
|
166
178
|
const CartSidebar = defineAsyncComponent(() => import('~/components/CartSidebar.vue'));
|
|
167
179
|
const props = defineProps<Props>();
|
|
168
180
|
const header = ref<HTMLElement | null>(null);
|
|
181
|
+
const searchInput = ref<HTMLInputElement | null>(null);
|
|
169
182
|
const {
|
|
170
183
|
isSticky,
|
|
171
184
|
positionY,
|
|
172
185
|
categoryTrees,
|
|
173
186
|
inlineMenuTrees,
|
|
174
|
-
|
|
187
|
+
isSearchOpen,
|
|
188
|
+
isSearchOpenOnce,
|
|
189
|
+
searchTerm,
|
|
190
|
+
quickSearchTerm,
|
|
191
|
+
toggleSearch,
|
|
192
|
+
isCartOpen,
|
|
193
|
+
isCartOpenOnce,
|
|
194
|
+
cartTotalItems,
|
|
195
|
+
handleOnMounted,
|
|
196
|
+
} = useShopHeader({ ...props, header, searchInput });
|
|
175
197
|
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
198
|
const isMounted = ref(false);
|
|
187
|
-
const delayedTotalItems = ref(0);
|
|
188
199
|
onMounted(() => {
|
|
189
200
|
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 });
|
|
201
|
+
handleOnMounted();
|
|
200
202
|
});
|
|
201
|
-
const searchTerm = ref('');
|
|
202
|
-
const searchInput = ref<HTMLElement | null>(null);
|
|
203
203
|
</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 })"
|
|
@@ -3,7 +3,7 @@ import SfBase from '@@sf/layouts/Base.astro';
|
|
|
3
3
|
import InlineScripts from '~/scripts/InlineScripts.astro';
|
|
4
4
|
import '~/assets/style.css';
|
|
5
5
|
import 'uno.css';
|
|
6
|
-
import '@fontsource/
|
|
6
|
+
import '@fontsource/league-spartan/700.css';
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
<SfBase>
|
|
@@ -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 { isSearchPage, fetchingApiContext } = routeContext;
|
|
9
|
+
const sharedData: Record<string, any> = {};
|
|
10
|
+
if (isSearchPage || 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
|
+
}
|