cloudcommerce 0.4.1 → 0.6.0
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/.github/renovate.json +1 -1
- package/CHANGELOG.md +52 -0
- package/action.yml +1 -2
- package/package.json +7 -7
- package/packages/api/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/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/infinitepay/package.json +1 -1
- package/packages/apps/jadlog/package.json +1 -1
- package/packages/apps/loyalty-points/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 +2 -2
- 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 +3 -3
- package/packages/cli/package.json +1 -1
- package/packages/config/package.json +1 -1
- package/packages/emails/package.json +1 -1
- package/packages/events/package.json +1 -1
- package/packages/firebase/package.json +1 -1
- package/packages/i18n/package.json +1 -1
- package/packages/modules/lib/firebase/checkout.js +4 -1
- package/packages/modules/lib/firebase/checkout.js.map +1 -1
- package/packages/modules/package.json +1 -1
- package/packages/modules/src/firebase/checkout.ts +4 -1
- package/packages/passport/package.json +1 -1
- package/packages/ssr/package.json +3 -3
- package/packages/storefront/client.d.ts +23 -3
- package/packages/storefront/config/storefront.cms.cjs +31 -5
- package/packages/storefront/config/storefront.cms.mjs +31 -5
- package/packages/storefront/dist/client/_astro/PitchBar.457658a3.js +1 -0
- package/packages/storefront/dist/client/_astro/Prices.a1302bf9.js +1 -0
- package/packages/storefront/dist/client/_astro/ProductCard.1a45764a.js +1 -0
- package/packages/storefront/dist/client/_astro/ShopHeader.0a6766ac.js +1 -0
- package/packages/storefront/dist/client/_astro/_...slug_.6721f699.css +1 -0
- package/packages/storefront/dist/client/_astro/_plugin-vue_export-helper.6da04e63.js +1 -0
- package/packages/storefront/dist/client/_astro/client.b854166f.js +1 -0
- package/packages/storefront/dist/client/_astro/firebase-app.7ce2ebb1.js +1426 -0
- package/packages/storefront/dist/client/_astro/format-money.6f464cee.js +1 -0
- package/packages/storefront/dist/client/_astro/hoisted.721ad75d.js +1 -0
- package/packages/storefront/dist/client/_astro/idle-callback.889bf0ea.js +1 -0
- package/packages/storefront/dist/client/_astro/index.a500792d.js +1 -0
- package/packages/storefront/dist/client/_astro/modules-info.80ae4e30.js +1 -0
- package/packages/storefront/dist/client/_astro/preload-helper.101896b7.js +1 -0
- package/packages/storefront/dist/client/_astro/runtime-dom.esm-bundler.acde10ec.js +1 -0
- package/packages/storefront/dist/client/fallback/index.html +8 -8
- package/packages/storefront/dist/client/sw.js +1 -1
- package/packages/storefront/dist/server/chunks/{astro.0f5b754a.mjs → astro.7d9d5f6e.mjs} +100 -38
- package/packages/storefront/dist/server/chunks/pages/{all.671e6bc1.mjs → all.e0f284c9.mjs} +980 -660
- package/packages/storefront/dist/server/chunks/{prerender.fd8cdc24.mjs → prerender.9f6cbb00.mjs} +0 -0
- package/packages/storefront/dist/server/entry.mjs +100 -48
- package/packages/storefront/package.json +8 -8
- package/packages/storefront/server.d.ts +34 -0
- package/packages/storefront/src/env.d.ts +1 -0
- package/packages/storefront/src/helpers/afetch.ts +3 -1
- package/packages/storefront/src/helpers/idle-callback.ts +9 -0
- package/packages/storefront/src/lib/assets/base.css +6 -0
- package/packages/storefront/src/lib/browser-env.ts +22 -0
- package/packages/storefront/src/lib/cms.d.ts +25 -0
- package/packages/storefront/src/lib/components/Drawer.vue +1 -1
- package/packages/storefront/src/lib/components/LoginForm.vue +13 -9
- package/packages/storefront/src/lib/components/SocialNetworkIcon.vue +29 -0
- package/packages/storefront/src/lib/components/SocialNetworkLink.vue +37 -0
- package/packages/storefront/src/lib/components/globals/ALink.vue +2 -2
- package/packages/storefront/src/lib/composables/use-shop-header.ts +79 -0
- package/packages/storefront/src/lib/layouts/Base.astro +4 -5
- package/packages/storefront/src/lib/layouts/BaseHead.astro +7 -7
- package/packages/storefront/src/lib/layouts/BaseStateJson.astro +1 -1
- package/packages/storefront/src/lib/layouts/PagesHeader.astro +5 -23
- package/packages/storefront/src/lib/scripts/firebase-app.ts +16 -3
- package/packages/storefront/src/lib/server-data.ts +25 -0
- package/packages/storefront/src/lib/ssr-context.ts +11 -10
- package/packages/storefront/src/lib/state/customer-session.ts +51 -30
- package/packages/storefront/src/lib/state/modules-info.ts +3 -6
- package/packages/storefront/tailwind.config.cjs +1 -4
- package/packages/types/index.ts +7 -0
- package/packages/types/package.json +1 -1
- package/pnpm-workspace.yaml +3 -3
- package/packages/storefront/dist/client/_astro/PitchBar.004b6ea4.js +0 -1
- package/packages/storefront/dist/client/_astro/Prices.f311909a.js +0 -1
- package/packages/storefront/dist/client/_astro/Prices.vue_vue_type_script_setup_true_lang.ef47de70.js +0 -1
- package/packages/storefront/dist/client/_astro/ProductCard.34de5097.js +0 -1
- package/packages/storefront/dist/client/_astro/ShopHeader.cbfee289.js +0 -1
- package/packages/storefront/dist/client/_astro/_...slug_.bcc33d9d.css +0 -1
- package/packages/storefront/dist/client/_astro/client.56d86c9b.js +0 -1
- package/packages/storefront/dist/client/_astro/ecom-utils.92f137f6.js +0 -1
- package/packages/storefront/dist/client/_astro/hoisted.6edd7364.js +0 -1
- package/packages/storefront/dist/client/_astro/index.2d12be6c.js +0 -1
- package/packages/storefront/dist/client/_astro/modules-info.0debb0b0.js +0 -1
- package/packages/storefront/dist/client/_astro/runtime-core.esm-bundler.a0432a8e.js +0 -1
- package/packages/storefront/dist/client/_astro/runtime-dom.esm-bundler.0e5774ce.js +0 -1
- package/packages/storefront/src/lib/components/ADrawer.vue +0 -110
- package/packages/storefront/src/lib/components/LoginDrawer.vue +0 -82
- package/packages/storefront/src/lib/components/ShopHeader.vue +0 -111
- package/packages/storefront/src/lib/components/ShopSidenav.vue +0 -26
- package/packages/storefront/src/lib/types/cms-code.d.ts +0 -5
- package/packages/storefront/src/lib/types/cms-contacts.d.ts +0 -5
- package/packages/storefront/src/lib/types/cms-header.d.ts +0 -5
- package/packages/storefront/src/lib/types/cms-settings.d.ts +0 -8
- package/packages/storefront/src/lib/types/cms-social.d.ts +0 -5
|
@@ -4,12 +4,10 @@ import {
|
|
|
4
4
|
i19accessMyAccount,
|
|
5
5
|
i19createAnAccount,
|
|
6
6
|
i19enterWithPassword,
|
|
7
|
-
i19hello,
|
|
8
7
|
i19iForgotMyPassword,
|
|
9
8
|
i19password,
|
|
10
9
|
i19sendLoginCodeByEmail,
|
|
11
10
|
i19signUp,
|
|
12
|
-
i19visitor,
|
|
13
11
|
} from '@@i18n';
|
|
14
12
|
import {
|
|
15
13
|
getAuth,
|
|
@@ -22,9 +20,20 @@ import {
|
|
|
22
20
|
isLogged,
|
|
23
21
|
} from '@@sf/state/customer-session';
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
// eslint-disable-next-line no-spaced-func, func-call-spacing
|
|
24
|
+
const emit = defineEmits<{
|
|
25
|
+
(e: 'set:is-logged', value: boolean): void
|
|
26
|
+
(e: 'set:email', value: string): void
|
|
27
|
+
(e: 'set:customer-name', value: string): void
|
|
28
|
+
}>();
|
|
26
29
|
watch(isLogged, (_isLogged) => {
|
|
27
|
-
emit(
|
|
30
|
+
emit('set:is-logged', _isLogged);
|
|
31
|
+
emit('set:customer-name', customerName.value);
|
|
32
|
+
}, {
|
|
33
|
+
immediate: true,
|
|
34
|
+
});
|
|
35
|
+
watch(email, (_email) => {
|
|
36
|
+
emit('set:email', _email);
|
|
28
37
|
}, {
|
|
29
38
|
immediate: true,
|
|
30
39
|
});
|
|
@@ -58,11 +67,6 @@ const submitLogin = async () => {
|
|
|
58
67
|
</script>
|
|
59
68
|
|
|
60
69
|
<template>
|
|
61
|
-
<slot name="greetings" v-bind="{ customerName }">
|
|
62
|
-
<div class="text-xl font-medium mb-5">
|
|
63
|
-
{{ `${i19hello} ${customerName || i19visitor}` }}
|
|
64
|
-
</div>
|
|
65
|
-
</slot>
|
|
66
70
|
<form
|
|
67
71
|
class="login-form text-base"
|
|
68
72
|
@submit.prevent="submitLogin"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { NetworkName } from '@@sf/server-data';
|
|
3
|
+
import { computed } from 'vue';
|
|
4
|
+
|
|
5
|
+
export interface Props {
|
|
6
|
+
as?: string;
|
|
7
|
+
network: NetworkName;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
11
|
+
as: 'i',
|
|
12
|
+
});
|
|
13
|
+
const iconClassName = computed(() => {
|
|
14
|
+
switch (props.network) {
|
|
15
|
+
case 'facebook': return 'i-facebook';
|
|
16
|
+
case 'instagram': return 'i-instagram';
|
|
17
|
+
case 'whatsapp': return 'i-whatsapp';
|
|
18
|
+
case 'youtube': return 'i-youtube';
|
|
19
|
+
case 'pinterest': return 'i-pinterest';
|
|
20
|
+
case 'tiktok': return 'i-tiktok';
|
|
21
|
+
case 'twitter': return 'i-twitter';
|
|
22
|
+
default: return '';
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<component :is="as" :class="iconClassName" />
|
|
29
|
+
</template>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { NetworkName } from '@@sf/server-data';
|
|
3
|
+
import { computed } from 'vue';
|
|
4
|
+
import { isMobile } from '@@sf/browser-env';
|
|
5
|
+
import { socialNetworks } from '@@sf/server-data';
|
|
6
|
+
import SocialNetworkIcon from '@@sf/components/SocialNetworkIcon.vue';
|
|
7
|
+
|
|
8
|
+
export interface Props {
|
|
9
|
+
network: NetworkName;
|
|
10
|
+
href?: string;
|
|
11
|
+
message?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const props = defineProps<Props>();
|
|
15
|
+
const fixedHref = computed(() => {
|
|
16
|
+
let href = props.href || socialNetworks[props.network];
|
|
17
|
+
if (props.network === 'whatsapp') {
|
|
18
|
+
const tel = href.replace(/[^+\d]/g, '');
|
|
19
|
+
// eslint-disable-next-line prefer-template
|
|
20
|
+
href = `https://${(isMobile ? 'api' : 'web')}.whatsapp.com/send?phone=`
|
|
21
|
+
+ encodeURIComponent(tel.charAt(0) === '+' ? tel : `+55${tel}`);
|
|
22
|
+
if (props.message) {
|
|
23
|
+
href += `&text=${encodeURIComponent(props.message)}`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return href;
|
|
27
|
+
});
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<template>
|
|
31
|
+
<ALink :href="fixedHref">
|
|
32
|
+
<slot>
|
|
33
|
+
<SocialNetworkIcon :network="network" />
|
|
34
|
+
<slot name="append"></slot>
|
|
35
|
+
</slot>
|
|
36
|
+
</ALink>
|
|
37
|
+
</template>
|
|
@@ -9,11 +9,11 @@ export interface Props {
|
|
|
9
9
|
const props = defineProps<Props>();
|
|
10
10
|
const linkTarget = computed(() => {
|
|
11
11
|
if (props.target) return props.target;
|
|
12
|
-
if (props.href.startsWith('http')
|
|
12
|
+
if (props.href.startsWith('http')) {
|
|
13
13
|
const domain = globalThis.storefront.settings.domain || window.location.host;
|
|
14
14
|
if (props.href.startsWith(`https://${domain}`)) return null;
|
|
15
15
|
}
|
|
16
|
-
return
|
|
16
|
+
return '_blank';
|
|
17
17
|
});
|
|
18
18
|
</script>
|
|
19
19
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
import type { CategoriesList } from '@cloudcommerce/api/types';
|
|
3
|
+
import { ref, computed } from 'vue';
|
|
4
|
+
import useStickyHeader from '@@sf/composables/use-sticky-header';
|
|
5
|
+
|
|
6
|
+
export interface Props {
|
|
7
|
+
header: Ref<HTMLElement>;
|
|
8
|
+
categories: CategoriesList;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type CategoryTree = CategoriesList[0] & {
|
|
12
|
+
subcategories: Array<CategoryTree>,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const filterMainCategories = (categories: CategoriesList) => {
|
|
16
|
+
return categories.filter(({ slug, parent }) => {
|
|
17
|
+
return slug && !parent;
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const filterSubcategories = (
|
|
22
|
+
categories: CategoriesList,
|
|
23
|
+
parentCategory: CategoriesList[0],
|
|
24
|
+
) => {
|
|
25
|
+
return categories.filter(({ slug, parent }) => {
|
|
26
|
+
if (slug && parent) {
|
|
27
|
+
return parent._id === parentCategory._id
|
|
28
|
+
|| (parent.slug && parent.slug === parentCategory.slug);
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const useShopHeader = (props: Props) => {
|
|
35
|
+
const { header } = props;
|
|
36
|
+
const {
|
|
37
|
+
isSticky,
|
|
38
|
+
staticHeight,
|
|
39
|
+
staticY,
|
|
40
|
+
} = useStickyHeader({ header });
|
|
41
|
+
const positionY = computed(() => {
|
|
42
|
+
return isSticky.value ? header.value.offsetHeight : staticY.value;
|
|
43
|
+
});
|
|
44
|
+
const mainCategories = filterMainCategories(props.categories);
|
|
45
|
+
const getSubcategories = (parentCategory: CategoriesList[0]) => {
|
|
46
|
+
return filterSubcategories(props.categories, parentCategory);
|
|
47
|
+
};
|
|
48
|
+
const getCategoryTree = (parentCategory: CategoriesList[0]): CategoryTree => {
|
|
49
|
+
return {
|
|
50
|
+
...parentCategory,
|
|
51
|
+
subcategories: getSubcategories(parentCategory).map((subcategory) => {
|
|
52
|
+
return getCategoryTree(subcategory);
|
|
53
|
+
}),
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
const categoryTrees = mainCategories.map(getCategoryTree);
|
|
57
|
+
const isSidenavOpen = ref(false);
|
|
58
|
+
return {
|
|
59
|
+
isSticky,
|
|
60
|
+
staticHeight,
|
|
61
|
+
staticY,
|
|
62
|
+
positionY,
|
|
63
|
+
mainCategories,
|
|
64
|
+
getSubcategories,
|
|
65
|
+
getCategoryTree,
|
|
66
|
+
categoryTrees,
|
|
67
|
+
isSidenavOpen,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export default useShopHeader;
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
useShopHeader,
|
|
75
|
+
filterMainCategories,
|
|
76
|
+
filterSubcategories,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export type { CategoryTree };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
---
|
|
2
|
-
import type CmsCode from '@@sf/types/cms-code';
|
|
3
2
|
import type { PageContext } from '@@sf/ssr-context';
|
|
4
3
|
import BaseHead from '@@sf/layouts/BaseHead.astro';
|
|
5
4
|
import BaseStateJson from '@@sf/layouts/BaseStateJson.astro';
|
|
@@ -12,14 +11,14 @@ export interface Props {
|
|
|
12
11
|
|
|
13
12
|
const { pageContext, title } = Astro.props as Props;
|
|
14
13
|
const { cms } = pageContext;
|
|
15
|
-
const cmsCustomCode = cms('code')
|
|
14
|
+
const cmsCustomCode = await cms('code');
|
|
16
15
|
---
|
|
17
16
|
|
|
18
17
|
<head>
|
|
19
18
|
<BaseHead pageContext={pageContext} title={title} />
|
|
20
19
|
<BaseStateJson pageContext={pageContext} />
|
|
21
|
-
{cmsCustomCode
|
|
22
|
-
{cmsCustomCode
|
|
20
|
+
{cmsCustomCode?.css && <style>{cmsCustomCode.css}</style>}
|
|
21
|
+
{cmsCustomCode?.html_head && <Fragment set:html={cmsCustomCode.html_head} />}
|
|
23
22
|
<slot name="base-head-scripts">
|
|
24
23
|
<script src="../scripts/modules-info-preset"></script>
|
|
25
24
|
</slot>
|
|
@@ -27,7 +26,7 @@ const cmsCustomCode = cms('code') as CmsCode;
|
|
|
27
26
|
</head>
|
|
28
27
|
<BaseBody pageContext={pageContext}>
|
|
29
28
|
<slot />
|
|
30
|
-
{cmsCustomCode
|
|
29
|
+
{cmsCustomCode?.html_body && <Fragment set:html={cmsCustomCode.html_body} />}
|
|
31
30
|
<slot name="base-body-scripts">
|
|
32
31
|
<script src="../scripts/session-utm"></script>
|
|
33
32
|
</slot>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
---
|
|
2
|
-
import type CmsSocial from '@@sf/types/cms-social';
|
|
3
2
|
import type { PageContext } from '@@sf/ssr-context';
|
|
4
3
|
import { pwaInfo } from 'virtual:pwa-info';
|
|
5
4
|
import { img as getImg } from '@ecomplus/utils';
|
|
@@ -33,7 +32,7 @@ const favicon = settings.icon
|
|
|
33
32
|
})).src
|
|
34
33
|
: '/favicon.ico';
|
|
35
34
|
const canonicalUrl = new URL(Astro.url.pathname, Astro.site || `https://${domain}`);
|
|
36
|
-
const
|
|
35
|
+
const cmsMetatags = await cms('metatags');
|
|
37
36
|
const ogLocale = lang.length === 2 ? lang : lang.substring(0, 2) + lang.slice(3).toUpperCase();
|
|
38
37
|
let ogImage: string | undefined;
|
|
39
38
|
if (apiDoc) {
|
|
@@ -41,9 +40,9 @@ if (apiDoc) {
|
|
|
41
40
|
ogImage = picture && picture.url;
|
|
42
41
|
}
|
|
43
42
|
if (!ogImage) {
|
|
44
|
-
if (
|
|
45
|
-
ogImage =
|
|
46
|
-
? `https://${domain}${
|
|
43
|
+
if (cmsMetatags?.og_image) {
|
|
44
|
+
ogImage = cmsMetatags.og_image.charAt(0) === '/'
|
|
45
|
+
? `https://${domain}${cmsMetatags.og_image}` : cmsMetatags.og_image;
|
|
47
46
|
}
|
|
48
47
|
} else {
|
|
49
48
|
ogImage = ogImage.replace(/(\w+\.)?(ecoms\d)\.com/i, '$2-nyc3.nyc3.cdn.digitaloceanspaces.com');
|
|
@@ -69,9 +68,10 @@ if (!ogImage) {
|
|
|
69
68
|
<meta property="og:type" content="website">
|
|
70
69
|
<meta property="og:locale" content={ogLocale}>
|
|
71
70
|
{ogImage && <meta property="og:image" content={ogImage} />}
|
|
72
|
-
{
|
|
71
|
+
{cmsMetatags?.fb_app_id && <meta property="fb:app_id" content={cmsMetatags.fb_app_id} />}
|
|
73
72
|
<meta name="twitter:card" content="summary">
|
|
74
|
-
{
|
|
73
|
+
{cmsMetatags?.twitter_username &&
|
|
74
|
+
<meta name="twitter:site" content={cmsMetatags.twitter_username} />}
|
|
75
75
|
<meta name="ecom-store-id" content={String(storeId)}>
|
|
76
76
|
{pwaInfo && <Fragment set:html={pwaInfo.webManifest.linkTag} />}
|
|
77
77
|
<script>
|
|
@@ -32,7 +32,7 @@ if (apiDoc) {
|
|
|
32
32
|
apiDoc.price = getPrice(apiDoc);
|
|
33
33
|
}
|
|
34
34
|
const slimDocRegex = globalThis.storefront_slim_doc_regex
|
|
35
|
-
|| /
|
|
35
|
+
|| /body_|meta_|metafields|_records|i18n/;
|
|
36
36
|
const minifyApiDoc = (nestedDoc: any) => {
|
|
37
37
|
if (typeof nestedDoc === 'object' && nestedDoc) {
|
|
38
38
|
if (Array.isArray(nestedDoc)) {
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
import type CmsHeader from '@@sf/types/cms-header';
|
|
3
2
|
import type { PageContext } from '@@sf/ssr-context';
|
|
4
|
-
import Picture from '@@sf/ssr/Picture.astro';
|
|
5
3
|
import PitchBar, { type Props as PitchBarProps } from '~/components/PitchBar.vue';
|
|
6
|
-
import ShopHeader, { type Props as ShopHeaderProps } from '
|
|
4
|
+
import ShopHeader, { type Props as ShopHeaderProps } from '~/components/ShopHeader.vue';
|
|
7
5
|
|
|
8
6
|
export interface Props {
|
|
9
7
|
pageContext: PageContext;
|
|
@@ -14,20 +12,13 @@ const {
|
|
|
14
12
|
pageContext: {
|
|
15
13
|
isHomepage,
|
|
16
14
|
apiState,
|
|
17
|
-
settings,
|
|
18
15
|
cms,
|
|
19
16
|
},
|
|
20
17
|
} = Astro.props as Props;
|
|
21
|
-
const
|
|
22
|
-
{ marketing_stripe?: { text: string, link: string }, logo?: string };
|
|
18
|
+
const cmsHeader = await cms('header');
|
|
23
19
|
const pitchBar: PitchBarProps = { slides: [] };
|
|
24
|
-
if (
|
|
25
|
-
pitchBar.slides =
|
|
26
|
-
} else if (header.marketing_stripe) {
|
|
27
|
-
pitchBar.slides = [{
|
|
28
|
-
href: header.marketing_stripe.link,
|
|
29
|
-
html: header.marketing_stripe.text,
|
|
30
|
-
}];
|
|
20
|
+
if (cmsHeader?.pitch_bar) {
|
|
21
|
+
pitchBar.slides = cmsHeader.pitch_bar;
|
|
31
22
|
}
|
|
32
23
|
const shopHeader: ShopHeaderProps = {
|
|
33
24
|
categories: apiState.categories,
|
|
@@ -46,16 +37,7 @@ const LogoHeading = Astro.props.logoHeading || (isHomepage ? 'h1' : 'h2');
|
|
|
46
37
|
<slot name="logo">
|
|
47
38
|
<a href="/">
|
|
48
39
|
<LogoHeading>
|
|
49
|
-
<slot name="logo-picture"
|
|
50
|
-
<Picture
|
|
51
|
-
src={header.logo || settings.logo}
|
|
52
|
-
alt={settings.name}
|
|
53
|
-
widths={[300]}
|
|
54
|
-
sizes="150px"
|
|
55
|
-
fetchpriority="high"
|
|
56
|
-
class="hover:drop-shadow-sm"
|
|
57
|
-
/>
|
|
58
|
-
</slot>
|
|
40
|
+
<slot name="logo-picture" />
|
|
59
41
|
</LogoHeading>
|
|
60
42
|
</a>
|
|
61
43
|
</slot>
|
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import { initializeApp } from 'firebase/app';
|
|
2
|
+
import {
|
|
3
|
+
getAuth,
|
|
4
|
+
onAuthStateChanged,
|
|
5
|
+
isSignInWithEmailLink,
|
|
6
|
+
signInWithEmailLink,
|
|
7
|
+
// updateProfile,
|
|
8
|
+
} from 'firebase/auth';
|
|
2
9
|
|
|
3
|
-
const
|
|
10
|
+
const firebaseApp = initializeApp(window.firebaseConfig);
|
|
4
11
|
|
|
5
|
-
export default
|
|
12
|
+
export default firebaseApp;
|
|
6
13
|
|
|
7
|
-
export
|
|
14
|
+
export {
|
|
15
|
+
firebaseApp,
|
|
16
|
+
getAuth,
|
|
17
|
+
onAuthStateChanged,
|
|
18
|
+
isSignInWithEmailLink,
|
|
19
|
+
signInWithEmailLink,
|
|
20
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const {
|
|
2
|
+
settings,
|
|
3
|
+
context: apiContext,
|
|
4
|
+
} = globalThis.storefront;
|
|
5
|
+
|
|
6
|
+
const networkNames = [
|
|
7
|
+
'whatsapp',
|
|
8
|
+
'instagram',
|
|
9
|
+
'facebook',
|
|
10
|
+
'twitter',
|
|
11
|
+
'youtube',
|
|
12
|
+
'tiktok',
|
|
13
|
+
'pinterest',
|
|
14
|
+
] as const;
|
|
15
|
+
type NetworkName = typeof networkNames[number];
|
|
16
|
+
const socialNetworks: Partial<Record<NetworkName, string>> = {};
|
|
17
|
+
networkNames.forEach((network: NetworkName) => {
|
|
18
|
+
if (settings[network]) {
|
|
19
|
+
socialNetworks[network] = settings[network];
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export { settings, apiContext, socialNetworks };
|
|
24
|
+
|
|
25
|
+
export type { NetworkName };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AstroGlobal } from 'astro';
|
|
2
2
|
import type { BaseConfig } from '@cloudcommerce/config';
|
|
3
3
|
import type { CategoriesList, BrandsList } from '@cloudcommerce/api/types';
|
|
4
|
-
import type CmsSettings from './
|
|
4
|
+
import type { CMS, CmsSettings } from './cms';
|
|
5
5
|
import { EventEmitter } from 'node:events';
|
|
6
6
|
import api, { ApiError, ApiEndpoint } from '@cloudcommerce/api';
|
|
7
7
|
import _getConfig from '../../storefront.config.mjs';
|
|
@@ -18,8 +18,7 @@ type StorefrontConfig = {
|
|
|
18
18
|
settings: CmsSettings,
|
|
19
19
|
dirContent: string,
|
|
20
20
|
// eslint-disable-next-line no-unused-vars
|
|
21
|
-
cms:
|
|
22
|
-
? Array<string> : Record<string, any>,
|
|
21
|
+
cms: CMS,
|
|
23
22
|
};
|
|
24
23
|
|
|
25
24
|
const emitter = new EventEmitter();
|
|
@@ -28,11 +27,6 @@ const getConfig: () => StorefrontConfig = _getConfig;
|
|
|
28
27
|
declare global {
|
|
29
28
|
// eslint-disable-next-line
|
|
30
29
|
var api_prefetch_endpoints: ApiEndpoint[];
|
|
31
|
-
// eslint-disable-next-line
|
|
32
|
-
var storefront: {
|
|
33
|
-
settings: Partial<CmsSettings>,
|
|
34
|
-
onLoad: (callback: (...args: any[]) => void) => void,
|
|
35
|
-
};
|
|
36
30
|
}
|
|
37
31
|
if (!globalThis.api_prefetch_endpoints) {
|
|
38
32
|
globalThis.api_prefetch_endpoints = ['categories'];
|
|
@@ -71,7 +65,7 @@ const loadPageContext = async (Astro: AstroGlobal, {
|
|
|
71
65
|
const config = getConfig();
|
|
72
66
|
globalThis.storefront.settings = config.settings;
|
|
73
67
|
let cmsContent: Record<string, any> | undefined;
|
|
74
|
-
let apiResource:
|
|
68
|
+
let apiResource: 'products' | 'categories' | 'brands' | 'collections' | undefined;
|
|
75
69
|
let apiDoc: Record<string, any> | undefined;
|
|
76
70
|
const apiState: {
|
|
77
71
|
categories?: CategoriesList,
|
|
@@ -88,7 +82,7 @@ const loadPageContext = async (Astro: AstroGlobal, {
|
|
|
88
82
|
];
|
|
89
83
|
if (slug) {
|
|
90
84
|
if (cmsCollection) {
|
|
91
|
-
cmsContent = config.cms(`${cmsCollection}/${slug}`);
|
|
85
|
+
cmsContent = await config.cms(`${cmsCollection}/${slug}`);
|
|
92
86
|
} else {
|
|
93
87
|
apiFetchings[0] = api.get(`slugs/${slug}`, apiOptions);
|
|
94
88
|
}
|
|
@@ -134,6 +128,13 @@ const loadPageContext = async (Astro: AstroGlobal, {
|
|
|
134
128
|
} else {
|
|
135
129
|
setResponseCache(Astro, 120, 300);
|
|
136
130
|
}
|
|
131
|
+
if (apiDoc) {
|
|
132
|
+
globalThis.storefront.context = {
|
|
133
|
+
resource: apiResource,
|
|
134
|
+
doc: apiDoc as any,
|
|
135
|
+
timestamp: Date.now(),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
137
138
|
const pageContext = {
|
|
138
139
|
...config,
|
|
139
140
|
isHomepage,
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import type { Customers } from '@cloudcommerce/api/types';
|
|
2
|
+
import type { Auth } from 'firebase/auth';
|
|
2
3
|
import api from '@cloudcommerce/api';
|
|
3
4
|
import { nickname as getNickname } from '@ecomplus/utils';
|
|
4
5
|
import { computed } from 'vue';
|
|
5
|
-
import
|
|
6
|
-
getAuth,
|
|
7
|
-
onAuthStateChanged,
|
|
8
|
-
isSignInWithEmailLink,
|
|
9
|
-
signInWithEmailLink,
|
|
10
|
-
// updateProfile,
|
|
11
|
-
} from 'firebase/auth';
|
|
6
|
+
import requestIdleCallback from '../../helpers/idle-callback';
|
|
12
7
|
import useStorage from './use-storage';
|
|
13
|
-
import '../scripts/firebase-app';
|
|
14
8
|
|
|
15
9
|
const storageKey = 'SESSION';
|
|
16
10
|
const emptySession = {
|
|
@@ -44,18 +38,9 @@ const customerEmail = computed({
|
|
|
44
38
|
},
|
|
45
39
|
});
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
if (isSignInWithEmailLink(firebaseAuth, window.location.href)) {
|
|
49
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
50
|
-
const email = urlParams.get('email');
|
|
51
|
-
if (email) {
|
|
52
|
-
signInWithEmailLink(firebaseAuth, email, window.location.href)
|
|
53
|
-
.catch(console.error);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
41
|
+
let firebaseAuth: Auth;
|
|
57
42
|
const isLogged = computed(() => {
|
|
58
|
-
return isAuthenticated.value || !!firebaseAuth
|
|
43
|
+
return isAuthenticated.value || !!firebaseAuth?.currentUser?.emailVerified;
|
|
59
44
|
});
|
|
60
45
|
const logout = () => {
|
|
61
46
|
session.auth = emptySession.auth;
|
|
@@ -97,21 +82,56 @@ const fetchCustomer = async () => {
|
|
|
97
82
|
return data;
|
|
98
83
|
};
|
|
99
84
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
85
|
+
let isAuthInitialized = false;
|
|
86
|
+
const initializeFirebaseAuth = (canWaitIdle = !window.location.pathname.startsWith('/app/')) => {
|
|
87
|
+
if (import.meta.env.SSR || isAuthInitialized) return;
|
|
88
|
+
isAuthInitialized = true;
|
|
89
|
+
const runImport = () => import('../scripts/firebase-app')
|
|
90
|
+
.then(({
|
|
91
|
+
getAuth,
|
|
92
|
+
onAuthStateChanged,
|
|
93
|
+
isSignInWithEmailLink,
|
|
94
|
+
signInWithEmailLink,
|
|
95
|
+
}) => {
|
|
96
|
+
firebaseAuth = getAuth();
|
|
97
|
+
onAuthStateChanged(firebaseAuth, async (user) => {
|
|
98
|
+
if (user) {
|
|
99
|
+
if (user.displayName && !customerName.value) {
|
|
100
|
+
session.customer.display_name = user.displayName;
|
|
101
|
+
}
|
|
102
|
+
if (user.email && (!customerEmail.value || user.emailVerified)) {
|
|
103
|
+
session.customer.main_email = user.email;
|
|
104
|
+
}
|
|
105
|
+
if (user.emailVerified) {
|
|
106
|
+
const isEmailChanged = user.email !== customerEmail.value;
|
|
107
|
+
if (isEmailChanged || !isAuthenticated.value) {
|
|
108
|
+
await authenticate();
|
|
109
|
+
if (isEmailChanged || !customerName.value) {
|
|
110
|
+
await fetchCustomer();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
logout();
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
if (isSignInWithEmailLink(firebaseAuth, window.location.href)) {
|
|
119
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
120
|
+
const email = urlParams.get('email');
|
|
121
|
+
if (email) {
|
|
122
|
+
signInWithEmailLink(firebaseAuth, email, window.location.href)
|
|
123
|
+
.then(() => window.localStorage.removeItem('emailForSignIn'))
|
|
124
|
+
.catch(console.error);
|
|
108
125
|
}
|
|
109
126
|
}
|
|
110
|
-
}
|
|
127
|
+
})
|
|
128
|
+
.catch(console.error);
|
|
129
|
+
if (canWaitIdle) {
|
|
130
|
+
requestIdleCallback(runImport);
|
|
111
131
|
} else {
|
|
112
|
-
|
|
132
|
+
runImport();
|
|
113
133
|
}
|
|
114
|
-
}
|
|
134
|
+
};
|
|
115
135
|
|
|
116
136
|
export default session;
|
|
117
137
|
|
|
@@ -126,4 +146,5 @@ export {
|
|
|
126
146
|
authenticate,
|
|
127
147
|
getAccessToken,
|
|
128
148
|
fetchCustomer,
|
|
149
|
+
initializeFirebaseAuth,
|
|
129
150
|
};
|
|
@@ -8,6 +8,7 @@ import { formatMoney } from '@ecomplus/utils';
|
|
|
8
8
|
import loadingGlobalInfoPreset from '@@sf/scripts/modules-info-preset';
|
|
9
9
|
import utm from '@@sf/scripts/session-utm';
|
|
10
10
|
import afetch from '../../helpers/afetch';
|
|
11
|
+
import requestIdleCallback from '../../helpers/idle-callback';
|
|
11
12
|
|
|
12
13
|
const emptyInfo = {
|
|
13
14
|
list_payments: {},
|
|
@@ -140,11 +141,7 @@ if (!import.meta.env.SSR) {
|
|
|
140
141
|
.catch(console.error);
|
|
141
142
|
});
|
|
142
143
|
};
|
|
143
|
-
|
|
144
|
-
window.requestIdleCallback(fetchInfo);
|
|
145
|
-
} else {
|
|
146
|
-
setTimeout(fetchInfo, 300);
|
|
147
|
-
}
|
|
144
|
+
requestIdleCallback(fetchInfo);
|
|
148
145
|
}
|
|
149
146
|
|
|
150
147
|
export default modulesInfo;
|
|
@@ -156,7 +153,7 @@ const parsePhrase = <T extends keyof typeof modulesInfo>(
|
|
|
156
153
|
formatValue: (x: any) => string = formatMoney,
|
|
157
154
|
) => {
|
|
158
155
|
return computed(() => {
|
|
159
|
-
const searchString = `{
|
|
156
|
+
const searchString = `{${varName}}`;
|
|
160
157
|
const index = phrase.indexOf(searchString);
|
|
161
158
|
if (index > -1) {
|
|
162
159
|
const fieldValue = modulesInfo[modName][varName];
|
|
@@ -40,14 +40,11 @@ let defaultThemeOptions = {
|
|
|
40
40
|
iconAliases: {
|
|
41
41
|
'shopping-cart': 'shopping-bag',
|
|
42
42
|
cashback: 'arrow-uturn-left',
|
|
43
|
-
'chevron-right': 'chevron-right',
|
|
44
|
-
'chevron-left': 'chevron-left',
|
|
45
|
-
'chevron-up': 'chevron-up',
|
|
46
|
-
'chevron-down': 'chevron-down',
|
|
47
43
|
menu: 'bars-3-bottom-left',
|
|
48
44
|
search: 'magnifying-glass',
|
|
49
45
|
account: 'user-circle',
|
|
50
46
|
close: 'x-mark',
|
|
47
|
+
logout: 'arrow-right-on-rectangle',
|
|
51
48
|
},
|
|
52
49
|
};
|
|
53
50
|
if (globalThis.storefront_theme_options) {
|
package/packages/types/index.ts
CHANGED
|
@@ -97,6 +97,13 @@ type CmsSettings = {
|
|
|
97
97
|
currency: string,
|
|
98
98
|
currency_symbol: string,
|
|
99
99
|
country_code: string,
|
|
100
|
+
whatsapp?: string,
|
|
101
|
+
instagram?: string,
|
|
102
|
+
facebook?: string,
|
|
103
|
+
twitter?: string,
|
|
104
|
+
youtube?: string,
|
|
105
|
+
tiktok?: string,
|
|
106
|
+
pinterest?: string,
|
|
100
107
|
modules?: {
|
|
101
108
|
list_payments?: {
|
|
102
109
|
installments_option?: Partial<ListPaymentsResponse['installments_option']>,
|
package/pnpm-workspace.yaml
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{v as O}from"./runtime-dom.esm-bundler.0e5774ce.js";import{p as U}from"./modules-info.0debb0b0.js";import{c as w,d as L,o as r,a as f,l as h,e as k,n as R,u as i,m as G,i as u,p as y,q as N,s as J,v as Q,x as X,y as Y,j as H,w as p,k as M,z as Z,A as ee,g as x,B as te,F as ae,C as se,b as oe}from"./runtime-core.esm-bundler.a0432a8e.js";import{u as ne,a as le,b as re}from"./index.2d12be6c.js";/* empty css */import"./session-utm.72684b84.js";import"./ecom-utils.92f137f6.js";const ue=s=>{const l=w(()=>s.slides.map(({html:t})=>U(t).value)),o=w(()=>l.value.filter(t=>t).length);return{parsedContents:l,countValidSlides:o}},D=Symbol("carousel"),ie=["aria-label","data-carousel-control"],_=L({__name:"CarouselControl",props:{direction:{default:1}},setup(s){const{changeSlide:l}=G(D);return(o,t)=>(r(),f("button",{type:"button","aria-label":s.direction>0?"Próximo":"Anterior",onClick:t[0]||(t[0]=n=>i(l)(s.direction)),"data-carousel-control":s.direction>0?"next":"previous"},[h(o.$slots,"default",{},()=>[k("i",{class:R(["m-0",s.direction>0?"i-chevron-right":"i-chevron-left"])},null,2)])],8,ie))}}),ce=L({__name:"Carousel",props:{as:{default:"ul"},modelValue:{default:1},autoplay:null},emits:["update:modelValue"],setup(s,{emit:l}){const o=s,t=u(o.modelValue-1);y(N(o,"modelValue"),e=>{t.value=e-1}),y(t,(e,a)=>{e!==a&&l("update:modelValue",e+1)});const n=u(null),{x:V,isScrolling:c,arrivedState:d}=ne(n),C=w(()=>d.left),S=w(()=>d.right),b=u([]),W=u(0),P=u(0),B=u(0),F=()=>{W.value=n.value.scrollWidth,P.value=n.value.offsetWidth},j=()=>{const e=[...n.value.children];b.value=e.map(a=>({offsetLeft:a.offsetLeft,width:a.offsetWidth}))},q=e=>{const a=e>0?t.value:t.value+e,E=b.value[a]?.width||0;return E?E*e:0},T=()=>{const e=b.value.findIndex(a=>Math.abs(a.offsetLeft-V.value)<=5);e>-1&&(t.value=e||0)},$=()=>{const e=W.value-P.value;B.value=b.value.findIndex(({offsetLeft:a})=>a>=e-5)};let v=null;const g=()=>{o.autoplay&&(clearTimeout(v),v=setTimeout(()=>{m(1)},o.autoplay))},m=e=>{if(e<0){if(C.value){$(),t.value=B.value-1,m(1);return}}else if(S.value){t.value=1,m(-1);return}const a=q(e);a&&(n.value.scrollBy({left:a,behavior:"smooth"}),g())};y(c,e=>{e?clearTimeout(v):(T(),g())});const I=u(null),K=le(I);y(K,e=>{e?clearTimeout(v):g()});const z=()=>{n.value&&(F(),j(),T(),$())},A=re(z,400);return J(()=>{z(),Q(()=>{[...n.value.children].forEach(e=>{e.setAttribute("tabindex","0")})}),g(),window.addEventListener("resize",A)}),X(()=>{window.removeEventListener("resize",A),clearTimeout(v)}),Y(D,{autoplay:N(o,"autoplay"),changeSlide:m,isBoundLeft:C,isBoundRight:S}),(e,a)=>(r(),f("div",{ref_key:"carousel",ref:I,"data-carousel":""},[(r(),H(M(s.as),{ref_key:"wrapper",ref:n,"data-carousel-wrapper":""},{default:p(()=>[h(e.$slots,"default")]),_:3},512)),h(e.$slots,"controls",Z(ee({changeSlide:m,isBoundLeft:i(C),isBoundRight:i(S),currentPage:t.value+1,pageCount:B.value+1})),()=>[x(_,{direction:-1},{default:p(()=>[h(e.$slots,"previous")]),_:3}),x(_,null,{default:p(()=>[h(e.$slots,"next")]),_:3})])],512))}}),de={class:"bg-base-100 relative z-1"},fe={class:"container md:w-2/3 mx-auto px-3 py-1"},pe=["innerHTML"],ve={class:"text-xl leading-none text-base-400"},_e=L({__name:"PitchBar",props:{slides:null},setup(s){const l=s,{parsedContents:o,countValidSlides:t}=ue(l);return(n,V)=>(r(),f("div",de,[k("div",fe,[x(ce,{autoplay:i(t)>1?7e3:null},{controls:p(()=>[te(k("div",ve,[x(_,{direction:-1,class:"pr-2 bg-base-100 hover:text-base-700"}),x(_,{class:"pl-2 bg-base-100 hover:text-base-700"})],512),[[O,i(t)>1]])]),default:p(()=>[(r(!0),f(ae,null,se(s.slides,(c,d)=>(r(),f("li",{key:d},[(r(),H(M(c.href?"ALink":"span"),{href:c.href,target:c.target,class:R(["inline-block px-8",c.href?"hover:underline":null])},{default:p(()=>[i(o)[d]?(r(),f("span",{key:0,innerHTML:i(o)[d],class:"prose text-sm text-base-800"},null,8,pe)):oe("",!0)]),_:2},1032,["href","target","class"]))]))),128))]),_:1},8,["autoplay"])])]))}});export{_e as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{_ as o}from"./Prices.vue_vue_type_script_setup_true_lang.ef47de70.js";/* empty css */import"./modules-info.0debb0b0.js";import"./session-utm.72684b84.js";import"./runtime-core.esm-bundler.a0432a8e.js";import"./ecom-utils.92f137f6.js";export{o as default};
|