feat(storefront): refactor i18n and cart/wishlist handling for improved user experience
Refactored i18n configuration, replacing `DEFAULT_LOCALE` with `DEFAULT_LOCALE_FALLBACK` and enhancing environment-based locale validation. Improved cookie persistence for cart and wishlist, ensuring fallback handling for unauthenticated users. Enhancements: - Added `createProjectKey` utility for consistent project key generation. - Reworked cart and wishlist composables (`useOrderOverwrite`, `useWishlistOverwrite`) to decouple product identifier and handle cookies robustly. - Centralized `DEFAULT_LOCALE` logic for better maintainability. - Refined `useOrderSync` and `useWishlistSync` for clean synchronization across auth states. - Updated SCSS in hero and header styles for alignment corrections. Breaking Changes: `DEFAULT_LOCALE` constant removed; replaced with runtime config and fallback logic. Consumers must adapt to `DEFAULT_LOCALE_FALLBACK` and `$appHelpers.DEFAULT_LOCALE`.
This commit is contained in:
parent
a14be696e7
commit
2ea18eb8a6
24 changed files with 391 additions and 194 deletions
|
|
@ -1,9 +1,8 @@
|
|||
import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from '@appConstants';
|
||||
import { SUPPORTED_LOCALES } from '@appConstants';
|
||||
|
||||
export default defineAppConfig({
|
||||
i18n: {
|
||||
supportedLocales: SUPPORTED_LOCALES,
|
||||
defaultLocale: DEFAULT_LOCALE,
|
||||
},
|
||||
ui: {
|
||||
showBreadcrumbs: true,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {DEFAULT_LOCALE} from '@appConstants';
|
||||
import {useRefresh} from '@composables/auth';
|
||||
import {useLanguages, useLocaleRedirect} from '@composables/languages';
|
||||
import {useCompanyInfo} from '@composables/company';
|
||||
|
|
@ -49,11 +48,11 @@ const { locale } = useI18n();
|
|||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
const { $appHelpers } = useNuxtApp();
|
||||
|
||||
const { isDemoMode, uiConfig } = useProjectConfig();
|
||||
const toaster = { position: uiConfig.value.toastPosition };
|
||||
const switchLocalePath = useSwitchLocalePath();
|
||||
const { $appHelpers } = useNuxtApp();
|
||||
|
||||
const showBreadcrumbs = computed(() => {
|
||||
const name = typeof route.name === 'string' ? route.name : '';
|
||||
|
|
@ -77,7 +76,7 @@ const activeState = computed(() => appStore.activeAuthState);
|
|||
const cookieLocale = useCookie(
|
||||
$appHelpers.COOKIES_LOCALE_KEY,
|
||||
{
|
||||
default: () => DEFAULT_LOCALE,
|
||||
default: () => $appHelpers.DEFAULT_LOCALE,
|
||||
path: '/'
|
||||
}
|
||||
);
|
||||
|
|
@ -116,7 +115,7 @@ watch(locale, () => {
|
|||
let stopWatcher: VoidFunction = () => {};
|
||||
|
||||
if (!cookieLocale.value) {
|
||||
cookieLocale.value = DEFAULT_LOCALE;
|
||||
cookieLocale.value = $appHelpers.DEFAULT_LOCALE;
|
||||
await router.push({path: switchLocalePath(cookieLocale.value)});
|
||||
}
|
||||
|
||||
|
|
@ -127,10 +126,10 @@ if (locale.value !== cookieLocale.value) {
|
|||
query: route.query
|
||||
});
|
||||
} else {
|
||||
cookieLocale.value = DEFAULT_LOCALE
|
||||
cookieLocale.value = $appHelpers.DEFAULT_LOCALE;
|
||||
|
||||
await router.push({
|
||||
path: switchLocalePath(DEFAULT_LOCALE),
|
||||
path: switchLocalePath($appHelpers.DEFAULT_LOCALE),
|
||||
query: route.query
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,6 +130,11 @@ const cookieWishlist = useCookie($appHelpers.COOKIES_WISHLIST_KEY, {
|
|||
default: () => [],
|
||||
path: '/',
|
||||
});
|
||||
const cookieCart = useCookie($appHelpers.COOKIES_CART_KEY, {
|
||||
default: () => [],
|
||||
path: '/',
|
||||
});
|
||||
console.log(cookieCart.value)
|
||||
|
||||
const productsInCartQuantity = computed(() => {
|
||||
if (isAuthenticated.value) {
|
||||
|
|
@ -166,7 +171,7 @@ const redirectTo = (to) => {
|
|||
<style lang="scss" scoped>
|
||||
.header {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
z-index: 5;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
class="card__wishlist"
|
||||
@click="overwriteWishlist({
|
||||
type: (isProductInWishlist ? 'remove' : 'add'),
|
||||
product: product,
|
||||
productUuid: product.uuid,
|
||||
productName: product.name,
|
||||
})"
|
||||
>
|
||||
<icon style="color: #dc2626;" name="mdi:cards-heart" size="16" v-if="isProductInWishlist" />
|
||||
|
|
@ -128,22 +129,56 @@ const props = defineProps<{
|
|||
const {t} = useI18n();
|
||||
const wishlistStore = useWishlistStore();
|
||||
const cartStore = useCartStore();
|
||||
const userStore = useUserStore();
|
||||
const { $appHelpers } = useNuxtApp();
|
||||
|
||||
const { overwriteWishlist } = useWishlistOverwrite();
|
||||
const { addLoading, removeLoading, overwriteOrder } = useOrderOverwrite();
|
||||
|
||||
const cookieWishlist = useCookie($appHelpers.COOKIES_WISHLIST_KEY, {
|
||||
default: () => [],
|
||||
path: '/',
|
||||
});
|
||||
const cookieCart = useCookie($appHelpers.COOKIES_CART_KEY, {
|
||||
default: () => [],
|
||||
path: '/',
|
||||
});
|
||||
|
||||
const isAuthenticated = computed(() => userStore.isAuthenticated);
|
||||
|
||||
const isProductInWishlist = computed(() => {
|
||||
const el = wishlistStore.wishlist?.products?.edges.find(
|
||||
if (isAuthenticated.value) {
|
||||
return !!wishlistStore.wishlist?.products?.edges.find(
|
||||
(el) => el?.node?.uuid === props.product.uuid
|
||||
);
|
||||
|
||||
return !!el;
|
||||
} else {
|
||||
return (cookieWishlist.value ?? []).includes(props.product.uuid);
|
||||
}
|
||||
});
|
||||
const isProductInCart = computed(() => {
|
||||
return cartStore.currentOrder?.orderProducts?.edges.find((prod) => prod.node.product.uuid === props.product?.uuid);
|
||||
if (isAuthenticated.value) {
|
||||
return !!cartStore.currentOrder?.orderProducts?.edges.find(
|
||||
(prod) => prod.node.product.uuid === props.product?.uuid
|
||||
);
|
||||
} else {
|
||||
return (cookieCart.value ?? []).some(
|
||||
(item) => item.product === props.product?.uuid
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const productInCartQuantity = computed(() => {
|
||||
return cartStore.currentOrder?.orderProducts?.edges.filter((prod) => prod.node.product.uuid === props.product.uuid)[0].node.quantity;
|
||||
if (isAuthenticated.value) {
|
||||
const productEdge = cartStore.currentOrder?.orderProducts?.edges.find(
|
||||
(prod) => prod.node.product.uuid === props.product.uuid
|
||||
);
|
||||
return productEdge?.node.quantity ?? 0;
|
||||
} else {
|
||||
const cartItem = (cookieCart.value ?? []).find(
|
||||
(item) => item.product === props.product.uuid
|
||||
);
|
||||
return cartItem?.quantity ?? 0;
|
||||
}
|
||||
});
|
||||
|
||||
const rating = computed(() => {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ const {t} = useI18n();
|
|||
|
||||
&__title {
|
||||
color: $white;
|
||||
text-align: center;
|
||||
font-family: "Playfair Display", sans-serif;
|
||||
font-size: 60px;
|
||||
font-weight: 700;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { DEFAULT_LOCALE } from '@appConstants';
|
||||
import { useLocaleRedirect } from '@composables/languages';
|
||||
import { useNotification } from '@composables/notification';
|
||||
import { useUserBaseData } from '@composables/user';
|
||||
|
|
@ -22,7 +21,7 @@ export function useLogin() {
|
|||
path: '/',
|
||||
});
|
||||
const cookieLocale = useCookie($appHelpers.COOKIES_LOCALE_KEY, {
|
||||
default: () => DEFAULT_LOCALE,
|
||||
default: () => $appHelpers.DEFAULT_LOCALE,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
|
|
@ -43,8 +42,6 @@ export function useLogin() {
|
|||
userStore.setUser(authData.user);
|
||||
cookieAccess.value = authData.accessToken;
|
||||
|
||||
await nextTick();
|
||||
|
||||
navigateTo(localePath('/'));
|
||||
|
||||
useNotification({
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { DEFAULT_LOCALE } from '@appConstants';
|
||||
import { useLogout } from '@composables/auth';
|
||||
import { useLocaleRedirect } from '@composables/languages';
|
||||
import { useNotification } from '@composables/notification';
|
||||
|
|
@ -40,7 +39,7 @@ export function useRefresh() {
|
|||
path: '/',
|
||||
});
|
||||
const cookieLocale = useCookie($appHelpers.COOKIES_LOCALE_KEY, {
|
||||
default: () => DEFAULT_LOCALE,
|
||||
default: () => $appHelpers.DEFAULT_LOCALE,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from '@appConstants';
|
||||
import { SUPPORTED_LOCALES } from '@appConstants';
|
||||
import { GET_LANGUAGES } from '@graphql/queries/standalone/languages.js';
|
||||
import type { ILanguage, ILanguagesResponse } from '@types';
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ export async function useLanguages() {
|
|||
const { $appHelpers } = useNuxtApp();
|
||||
|
||||
const cookieLocale = useCookie($appHelpers.COOKIES_LOCALE_KEY, {
|
||||
default: () => DEFAULT_LOCALE,
|
||||
default: () => $appHelpers.DEFAULT_LOCALE,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { DEFAULT_LOCALE } from '@appConstants';
|
||||
import { SWITCH_LANGUAGE } from '@graphql/mutations/languages.js';
|
||||
import type { IUserResponse, LocaleDefinition } from '@types';
|
||||
|
||||
|
|
@ -11,7 +10,7 @@ export function useLanguageSwitch() {
|
|||
const switchLocalePath = useSwitchLocalePath();
|
||||
|
||||
const cookieLocale = useCookie($appHelpers.COOKIES_LOCALE_KEY, {
|
||||
default: () => DEFAULT_LOCALE,
|
||||
default: () => $appHelpers.DEFAULT_LOCALE,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from '@appConstants';
|
||||
import { SUPPORTED_LOCALES } from '@appConstants';
|
||||
import type { SupportedLocale } from '@types';
|
||||
|
||||
export function useLocaleRedirect() {
|
||||
|
|
@ -9,7 +9,7 @@ export function useLocaleRedirect() {
|
|||
const switchLocalePath = useSwitchLocalePath();
|
||||
|
||||
const cookieLocale = useCookie($appHelpers.COOKIES_LOCALE_KEY, {
|
||||
default: () => DEFAULT_LOCALE,
|
||||
default: () => $appHelpers.DEFAULT_LOCALE,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ export function useLocaleRedirect() {
|
|||
}
|
||||
|
||||
async function checkAndRedirect(userLocale: string) {
|
||||
const targetLocale = isSupportedLocale(userLocale) ? userLocale : DEFAULT_LOCALE;
|
||||
const targetLocale = isSupportedLocale(userLocale) ? userLocale : $appHelpers.DEFAULT_LOCALE;
|
||||
|
||||
if (targetLocale !== locale.value) {
|
||||
cookieLocale.value = targetLocale;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import {
|
|||
import type {
|
||||
IAddToOrderResponse,
|
||||
IBulkOrderResponse,
|
||||
IProduct,
|
||||
IRemoveAllFromOrderResponse,
|
||||
IRemoveFromOrderResponse,
|
||||
IRemoveKindFromOrderResponse,
|
||||
|
|
@ -17,7 +16,8 @@ import type {
|
|||
|
||||
interface IOverwriteOrderArguments {
|
||||
type: string;
|
||||
product: IProduct;
|
||||
productUuid: string;
|
||||
productName: string;
|
||||
bulkAction?: string;
|
||||
isBulkSync?: boolean;
|
||||
products?: {
|
||||
|
|
@ -29,6 +29,7 @@ export function useOrderOverwrite() {
|
|||
const { t } = useI18n();
|
||||
const cartStore = useCartStore();
|
||||
const userStore = useUserStore();
|
||||
const { $appHelpers } = useNuxtApp();
|
||||
|
||||
const isAuthenticated = computed(() => userStore.isAuthenticated);
|
||||
const orderUuid = computed(() => cartStore.currentOrder?.uuid);
|
||||
|
|
@ -36,6 +37,7 @@ export function useOrderOverwrite() {
|
|||
const cookieCart = useCookie($appHelpers.COOKIES_CART_KEY, {
|
||||
default: () => [],
|
||||
path: '/',
|
||||
watch: true,
|
||||
});
|
||||
|
||||
const {
|
||||
|
|
@ -70,7 +72,7 @@ export function useOrderOverwrite() {
|
|||
case 'add': {
|
||||
const addResult = await addMutate({
|
||||
orderUuid: orderUuid.value,
|
||||
productUuid: args.product.uuid,
|
||||
productUuid: args.productUuid,
|
||||
});
|
||||
|
||||
if (addResult?.data?.addOrderProduct?.order) {
|
||||
|
|
@ -78,7 +80,7 @@ export function useOrderOverwrite() {
|
|||
|
||||
useNotification({
|
||||
message: t('popup.success.addToCart', {
|
||||
product: args.product.name,
|
||||
product: args.productName,
|
||||
}),
|
||||
type: 'success',
|
||||
});
|
||||
|
|
@ -90,7 +92,7 @@ export function useOrderOverwrite() {
|
|||
case 'remove': {
|
||||
const removeResult = await removeMutate({
|
||||
orderUuid: orderUuid.value,
|
||||
productUuid: args.product.uuid,
|
||||
productUuid: args.productUuid,
|
||||
});
|
||||
|
||||
if (removeResult?.data?.removeOrderProduct?.order) {
|
||||
|
|
@ -98,7 +100,7 @@ export function useOrderOverwrite() {
|
|||
|
||||
useNotification({
|
||||
message: t('popup.success.removeFromCart', {
|
||||
product: args.product.name,
|
||||
product: args.productName,
|
||||
}),
|
||||
type: 'success',
|
||||
});
|
||||
|
|
@ -110,7 +112,7 @@ export function useOrderOverwrite() {
|
|||
case 'removeKind': {
|
||||
const removeKindResult = await removeKindMutate({
|
||||
orderUuid: orderUuid.value,
|
||||
productUuid: args.product.uuid,
|
||||
productUuid: args.productUuid,
|
||||
});
|
||||
|
||||
if (removeKindResult?.data?.removeOrderProductsOfAKind?.order) {
|
||||
|
|
@ -118,7 +120,7 @@ export function useOrderOverwrite() {
|
|||
|
||||
useNotification({
|
||||
message: t('popup.success.removeFromCart', {
|
||||
product: args.product.name,
|
||||
product: args.productName,
|
||||
}),
|
||||
type: 'success',
|
||||
});
|
||||
|
|
@ -168,27 +170,29 @@ export function useOrderOverwrite() {
|
|||
} else {
|
||||
switch (args.type) {
|
||||
case 'add': {
|
||||
const currentCart = cookieCart.value || [];
|
||||
const existingItem = currentCart.find((item) => item.product.uuid === args.product.uuid);
|
||||
const current = Array.isArray(cookieCart.value) ? [...cookieCart.value] : [];
|
||||
|
||||
if (existingItem) {
|
||||
existingItem.quantity += 1;
|
||||
cookieCart.value = [
|
||||
...currentCart,
|
||||
];
|
||||
const index = current.findIndex(
|
||||
(item) => item.product === args.productUuid
|
||||
);
|
||||
|
||||
if (index !== -1) {
|
||||
current[index] = {
|
||||
...current[index],
|
||||
quantity: current[index].quantity + 1,
|
||||
};
|
||||
} else {
|
||||
cookieCart.value = [
|
||||
...currentCart,
|
||||
{
|
||||
product: args.product,
|
||||
current.push({
|
||||
product: args.productUuid,
|
||||
quantity: 1,
|
||||
},
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
cookieCart.value = current;
|
||||
|
||||
useNotification({
|
||||
message: t('popup.success.addToCart', {
|
||||
product: args.product.name,
|
||||
product: args.productName,
|
||||
}),
|
||||
type: 'success',
|
||||
});
|
||||
|
|
@ -197,22 +201,29 @@ export function useOrderOverwrite() {
|
|||
}
|
||||
|
||||
case 'remove': {
|
||||
const currentCart = cookieCart.value || [];
|
||||
const existingItem = currentCart.find((item) => item.product.uuid === args.product.uuid);
|
||||
const current = Array.isArray(cookieCart.value)
|
||||
? [...cookieCart.value]
|
||||
: [];
|
||||
|
||||
if (existingItem) {
|
||||
if (existingItem.quantity > 1) {
|
||||
existingItem.quantity -= 1;
|
||||
cookieCart.value = [
|
||||
...currentCart,
|
||||
];
|
||||
const index = current.findIndex(
|
||||
(item) => item.product === args.productUuid
|
||||
);
|
||||
|
||||
if (index !== -1) {
|
||||
if (current[index].quantity > 1) {
|
||||
current[index] = {
|
||||
...current[index],
|
||||
quantity: current[index].quantity - 1,
|
||||
};
|
||||
} else {
|
||||
cookieCart.value = currentCart.filter((item) => item.product.uuid !== args.product.uuid);
|
||||
current.splice(index, 1);
|
||||
}
|
||||
|
||||
cookieCart.value = current;
|
||||
|
||||
useNotification({
|
||||
message: t('popup.success.removeFromCart', {
|
||||
product: args.product.name,
|
||||
product: args.productName,
|
||||
}),
|
||||
type: 'success',
|
||||
});
|
||||
|
|
@ -222,11 +233,13 @@ export function useOrderOverwrite() {
|
|||
}
|
||||
|
||||
case 'removeKind': {
|
||||
cookieCart.value = cookieCart.value.filter((item) => item.product.uuid !== args.product.uuid);
|
||||
cookieCart.value = (cookieCart.value ?? []).filter(
|
||||
(item) => item.product.uuid !== args.productUuid
|
||||
);
|
||||
|
||||
useNotification({
|
||||
message: t('popup.success.removeFromCart', {
|
||||
product: args.product.name,
|
||||
product: args.productName,
|
||||
}),
|
||||
type: 'success',
|
||||
});
|
||||
|
|
@ -246,28 +259,18 @@ export function useOrderOverwrite() {
|
|||
}
|
||||
|
||||
case 'bulk': {
|
||||
if (args.bulkAction === 'remove' && args.products) {
|
||||
const uuidsToRemove = args.products.map((p) => p.uuid);
|
||||
cookieCart.value = cookieCart.value.filter((item) => !uuidsToRemove.includes(item.product.uuid));
|
||||
const bulkResult = await bulkMutate({
|
||||
orderUuid: orderUuid.value,
|
||||
action: args.bulkAction,
|
||||
products: args.products,
|
||||
});
|
||||
|
||||
if (bulkResult?.data?.bulkOrderAction?.order) {
|
||||
cartStore.setCurrentOrders(bulkResult.data.bulkOrderAction.order);
|
||||
useNotification({
|
||||
message: t('popup.success.bulkRemoveOrder'),
|
||||
type: 'success',
|
||||
});
|
||||
} else if (args.bulkAction === 'add' && args.products) {
|
||||
const currentCart = cookieCart.value || [];
|
||||
|
||||
for (const productRef of args.products) {
|
||||
const existingItem = currentCart.find((item) => item.product.uuid === productRef.uuid);
|
||||
|
||||
if (existingItem) {
|
||||
existingItem.quantity += 1;
|
||||
}
|
||||
}
|
||||
|
||||
cookieCart.value = [
|
||||
...currentCart,
|
||||
];
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -279,21 +282,29 @@ export function useOrderOverwrite() {
|
|||
}
|
||||
}
|
||||
|
||||
watch(addError || removedError || removedKindError || removedAllError || bulkError, (err) => {
|
||||
watch(
|
||||
[addError, removedError, removedKindError, removedAllError, bulkError],
|
||||
(errors) => {
|
||||
const err = errors.find(Boolean);
|
||||
if (!err) return;
|
||||
|
||||
console.error('useOrderOverwrite error:', err);
|
||||
|
||||
let message = t('popup.errors.defaultError');
|
||||
|
||||
if (isGraphQLError(err)) {
|
||||
message = err.graphQLErrors?.[0]?.message || message;
|
||||
} else {
|
||||
message = err.message;
|
||||
}
|
||||
|
||||
useNotification({
|
||||
message,
|
||||
type: 'error',
|
||||
title: t('popup.errors.main'),
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
addLoading,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { DEFAULT_LOCALE } from '@appConstants';
|
||||
import { useLogout } from '@composables/auth';
|
||||
import { useLocaleRedirect } from '@composables/languages';
|
||||
import { useNotification } from '@composables/notification';
|
||||
|
|
@ -16,7 +15,7 @@ export function useUserUpdating() {
|
|||
const { logout } = useLogout();
|
||||
|
||||
const cookieLocale = useCookie($appHelpers.COOKIES_LOCALE_KEY, {
|
||||
default: () => DEFAULT_LOCALE,
|
||||
default: () => $appHelpers.DEFAULT_LOCALE,
|
||||
path: '/',
|
||||
});
|
||||
const userUuid = computed(() => userStore.user?.uuid);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useNotification } from '@composables/notification';
|
||||
import {useNotification} from '@composables/notification';
|
||||
import {
|
||||
ADD_TO_WISHLIST,
|
||||
BULK_WISHLIST,
|
||||
|
|
@ -8,14 +8,14 @@ import {
|
|||
import type {
|
||||
IAddToWishlistResponse,
|
||||
IBulkWishlistResponse,
|
||||
IProduct,
|
||||
IRemoveAllFromWishlistResponse,
|
||||
IRemoveFromWishlistResponse,
|
||||
} from '@types';
|
||||
|
||||
interface IOverwriteWishlistArguments {
|
||||
type: string;
|
||||
product: IProduct;
|
||||
productUuid: string;
|
||||
productName: string;
|
||||
bulkAction?: string;
|
||||
isBulkSync?: boolean;
|
||||
products?: {
|
||||
|
|
@ -35,6 +35,7 @@ export function useWishlistOverwrite() {
|
|||
const cookieWishlist = useCookie($appHelpers.COOKIES_WISHLIST_KEY, {
|
||||
default: () => [],
|
||||
path: '/',
|
||||
watch: true,
|
||||
});
|
||||
|
||||
const {
|
||||
|
|
@ -64,7 +65,7 @@ export function useWishlistOverwrite() {
|
|||
case 'add': {
|
||||
const addResult = await addMutate({
|
||||
wishlistUuid: wishlistUuid.value,
|
||||
productUuid: args.product.uuid,
|
||||
productUuid: args.productUuid,
|
||||
});
|
||||
|
||||
if (addResult?.data?.addWishlistProduct?.wishlist) {
|
||||
|
|
@ -72,7 +73,7 @@ export function useWishlistOverwrite() {
|
|||
|
||||
useNotification({
|
||||
message: t('popup.success.addToWishlist', {
|
||||
product: args.product.name,
|
||||
product: args.productName,
|
||||
}),
|
||||
type: 'success',
|
||||
});
|
||||
|
|
@ -84,7 +85,7 @@ export function useWishlistOverwrite() {
|
|||
case 'remove': {
|
||||
const removeResult = await removeMutate({
|
||||
wishlistUuid: wishlistUuid.value,
|
||||
productUuid: args.product.uuid,
|
||||
productUuid: args.productUuid,
|
||||
});
|
||||
|
||||
if (removeResult?.data?.removeWishlistProduct?.wishlist) {
|
||||
|
|
@ -92,7 +93,7 @@ export function useWishlistOverwrite() {
|
|||
|
||||
useNotification({
|
||||
message: t('popup.success.removeFromWishlist', {
|
||||
product: args.product.name,
|
||||
product: args.productName,
|
||||
}),
|
||||
type: 'success',
|
||||
});
|
||||
|
|
@ -104,7 +105,7 @@ export function useWishlistOverwrite() {
|
|||
case 'removeAll': {
|
||||
const removeAllResult = await removeAllMutate({
|
||||
wishlistUuid: wishlistUuid.value,
|
||||
productUuid: args.product.uuid,
|
||||
productUuid: args.productUuid,
|
||||
});
|
||||
|
||||
if (removeAllResult?.data?.removeAllWishlistProducts?.wishlist) {
|
||||
|
|
@ -148,38 +149,43 @@ export function useWishlistOverwrite() {
|
|||
} else {
|
||||
switch (args.type) {
|
||||
case 'add': {
|
||||
const isAlreadyInWishlist = cookieWishlist.value.some((item) => item.uuid === args.product.uuid);
|
||||
const current = Array.isArray(cookieWishlist.value)
|
||||
? [...cookieWishlist.value]
|
||||
: [];
|
||||
|
||||
if (isAlreadyInWishlist) {
|
||||
if (current.includes(args.productUuid)) {
|
||||
useNotification({
|
||||
message: t('popup.errors.alreadyInWishlist', {
|
||||
product: args.product.name,
|
||||
product: args.productName,
|
||||
}),
|
||||
type: 'warning',
|
||||
});
|
||||
} else {
|
||||
cookieWishlist.value = [
|
||||
...cookieWishlist.value,
|
||||
args.product,
|
||||
];
|
||||
return;
|
||||
}
|
||||
|
||||
current.push(args.productUuid);
|
||||
cookieWishlist.value = current;
|
||||
|
||||
useNotification({
|
||||
message: t('popup.success.addToWishlist', {
|
||||
product: args.product.name,
|
||||
product: args.productName,
|
||||
}),
|
||||
type: 'success',
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'remove': {
|
||||
cookieWishlist.value = cookieWishlist.value.filter((item) => item.uuid !== args.product.uuid);
|
||||
cookieWishlist.value = Array.isArray(cookieWishlist.value)
|
||||
? cookieWishlist.value.filter(
|
||||
(uuid) => uuid !== args.productUuid
|
||||
)
|
||||
: [];
|
||||
|
||||
useNotification({
|
||||
message: t('popup.success.removeFromWishlist', {
|
||||
product: args.product.name,
|
||||
product: args.productName,
|
||||
}),
|
||||
type: 'success',
|
||||
});
|
||||
|
|
@ -227,7 +233,10 @@ export function useWishlistOverwrite() {
|
|||
}
|
||||
}
|
||||
|
||||
watch(addError || removedError || removeAllError || bulkError, (err) => {
|
||||
watch(
|
||||
[addError, removedError, removeAllError, bulkError],
|
||||
(errors) => {
|
||||
const err = errors.find(Boolean);
|
||||
if (!err) return;
|
||||
console.error('useWishlistOverwrite error:', err);
|
||||
let message = t('popup.errors.defaultError');
|
||||
|
|
@ -241,7 +250,8 @@ export function useWishlistOverwrite() {
|
|||
type: 'error',
|
||||
title: t('popup.errors.main'),
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
addLoading,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export function useWishlistSync() {
|
|||
|
||||
const apiProductUuids = wishlistStore.wishlist?.products?.edges.map((e) => e.node.uuid) || [];
|
||||
|
||||
const productsToAdd = cookieProducts.filter((product) => !apiProductUuids.includes(product.uuid));
|
||||
const productsToAdd = cookieProducts.filter((product) => !apiProductUuids.includes(product));
|
||||
|
||||
if (productsToAdd.length === 0) {
|
||||
cookieWishlist.value = [];
|
||||
|
|
@ -41,7 +41,7 @@ export function useWishlistSync() {
|
|||
bulkAction: 'add',
|
||||
isBulkSync: true,
|
||||
products: productsToAdd.map((p) => ({
|
||||
uuid: p.uuid,
|
||||
uuid: p,
|
||||
})),
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ import type { LocaleDefinition } from '@types';
|
|||
export const SUPPORTED_LOCALES: LocaleDefinition[] = [
|
||||
{
|
||||
code: 'en-gb',
|
||||
file: 'en-gb.json',
|
||||
default: true,
|
||||
file: 'en-gb.json'
|
||||
},
|
||||
// {
|
||||
// code: 'ar-ar',
|
||||
|
|
@ -73,8 +72,7 @@ export const SUPPORTED_LOCALES: LocaleDefinition[] = [
|
|||
// },
|
||||
{
|
||||
code: 'ru-ru',
|
||||
file: 'ru-ru.json',
|
||||
default: false,
|
||||
file: 'ru-ru.json'
|
||||
},
|
||||
// {
|
||||
// code: 'zh-hans',
|
||||
|
|
@ -83,4 +81,4 @@ export const SUPPORTED_LOCALES: LocaleDefinition[] = [
|
|||
// },
|
||||
];
|
||||
|
||||
export const DEFAULT_LOCALE = SUPPORTED_LOCALES.find((locale) => locale.default)?.code || 'en-gb';
|
||||
export const DEFAULT_LOCALE_FALLBACK = 'en-gb';
|
||||
|
|
@ -79,7 +79,8 @@
|
|||
class="product__main-button"
|
||||
@click="overwriteWishlist({
|
||||
type: (isProductInWishlist ? 'remove' : 'add'),
|
||||
product: product
|
||||
productUuid: product.uuid,
|
||||
productName: product.name,
|
||||
})"
|
||||
:type="'button'"
|
||||
:style="'secondary'"
|
||||
|
|
@ -165,6 +166,7 @@ const route = useRoute();
|
|||
const {t, locale} = useI18n();
|
||||
const wishlistStore = useWishlistStore();
|
||||
const cartStore = useCartStore();
|
||||
const userStore = useUserStore();
|
||||
const { $appHelpers } = useNuxtApp();
|
||||
|
||||
const { setPageTitle } = usePageTitle();
|
||||
|
|
@ -176,6 +178,13 @@ const { overwriteWishlist } = useWishlistOverwrite();
|
|||
const { addLoading, removeLoading, overwriteOrder } = useOrderOverwrite();
|
||||
const { product, seoMeta } = await useProductBySlug(slug.value);
|
||||
|
||||
const cookieWishlist = useCookie($appHelpers.COOKIES_WISHLIST_KEY, {
|
||||
default: () => [],
|
||||
path: '/',
|
||||
});
|
||||
|
||||
const isAuthenticated = computed(() => userStore.isAuthenticated);
|
||||
|
||||
const meta = useDefaultSeo(seoMeta.value || null);
|
||||
|
||||
if (meta) {
|
||||
|
|
@ -211,18 +220,39 @@ if (meta) {
|
|||
const { products } = useProducts({ categoriesSlugs: product.value?.category.slug });
|
||||
|
||||
const isProductInWishlist = computed(() => {
|
||||
const el = wishlistStore.wishlist?.products?.edges.find(
|
||||
(el) => el?.node?.uuid === product.value?.uuid
|
||||
if (isAuthenticated.value) {
|
||||
return !!wishlistStore.wishlist?.products?.edges.find(
|
||||
(el) => el?.node?.uuid === product.value.uuid
|
||||
);
|
||||
|
||||
return !!el;
|
||||
} else {
|
||||
return (cookieWishlist.value ?? []).includes(product.value.uuid);
|
||||
}
|
||||
});
|
||||
|
||||
const isProductInCart = computed(() => {
|
||||
return cartStore.currentOrder?.orderProducts?.edges.find((prod) => prod.node.product.uuid === product.value?.uuid);
|
||||
if (isAuthenticated.value) {
|
||||
return !!cartStore.currentOrder?.orderProducts?.edges.find(
|
||||
(prod) => prod.node.product.uuid === product.value?.uuid
|
||||
);
|
||||
} else {
|
||||
return (cookieCart.value ?? []).some(
|
||||
(item) => item.product.uuid === product.value?.uuid
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const productInCartQuantity = computed(() => {
|
||||
return cartStore.currentOrder?.orderProducts?.edges.filter((prod) => prod.node.product.uuid === product.value.uuid)[0].node.quantity;
|
||||
if (isAuthenticated.value) {
|
||||
const productEdge = cartStore.currentOrder?.orderProducts?.edges.find(
|
||||
(prod) => prod.node.product.uuid === product.value.uuid
|
||||
);
|
||||
return productEdge?.node.quantity ?? 0;
|
||||
} else {
|
||||
const cartItem = (cookieCart.value ?? []).find(
|
||||
(item) => item.product === product.value.uuid
|
||||
);
|
||||
return cartItem?.quantity ?? 0;
|
||||
}
|
||||
});
|
||||
|
||||
const images = computed<string[]>(() =>
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@
|
|||
<script setup lang="ts">
|
||||
import {usePageTitle} from '@composables/utils';
|
||||
import { useDate } from '@composables/date';
|
||||
import {DEFAULT_LOCALE} from '@appConstants';
|
||||
import {useAvatarUpload} from '@composables/user';
|
||||
import {useNotification} from '@composables/notification';
|
||||
|
||||
|
|
@ -62,7 +61,7 @@ const { uploadAvatar } = useAvatarUpload();
|
|||
const cookieLocale = useCookie(
|
||||
$appHelpers. COOKIES_LOCALE_KEY,
|
||||
{
|
||||
default: () => DEFAULT_LOCALE,
|
||||
default: () => $appHelpers.DEFAULT_LOCALE,
|
||||
path: '/'
|
||||
}
|
||||
);
|
||||
|
|
@ -77,9 +76,9 @@ const joinData = computed(() => {
|
|||
|
||||
const referralLink = computed(() => {
|
||||
if (finishedOrdersQuantity.value > 0) {
|
||||
return `https://${$appHelpers.APP_DOMAIN}/${DEFAULT_LOCALE}/?referrer=` + user.value?.uuid;
|
||||
return `https://${$appHelpers.APP_DOMAIN}/${$appHelpers.DEFAULT_LOCALE}/?referrer=` + user.value?.uuid;
|
||||
} else {
|
||||
return `https://${$appHelpers.APP_DOMAIN}/${DEFAULT_LOCALE}/`;
|
||||
return `https://${$appHelpers.APP_DOMAIN}/${$appHelpers.DEFAULT_LOCALE}/`;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
import {usePageTitle} from '@composables/utils';
|
||||
|
||||
const { t, locale } = useI18n();
|
||||
const { $appHelpers } = useNuxtApp();
|
||||
|
||||
const { setPageTitle } = usePageTitle();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
import { COOKIE_KEY_TEMPLATES } from '~/constants';
|
||||
import { COOKIE_KEY_TEMPLATES, DEFAULT_LOCALE_FALLBACK, SUPPORTED_LOCALES } from '~/constants';
|
||||
import { createProjectKey } from "~/utils/transliterator";
|
||||
|
||||
export default defineNuxtPlugin(() => {
|
||||
const runtimeConfig = useRuntimeConfig();
|
||||
const APP_NAME = runtimeConfig.public.schonProjectName as string;
|
||||
const APP_NAME_KEY = APP_NAME.toLowerCase().replace(/\s+/g, '-');
|
||||
const APP_NAME_KEY = createProjectKey(APP_NAME);
|
||||
|
||||
const envLocale = runtimeConfig.public.schonLanguageCode as string;
|
||||
const isValid = SUPPORTED_LOCALES.some(locale => locale.code === envLocale);
|
||||
const DEFAULT_LOCALE = isValid ? envLocale : DEFAULT_LOCALE_FALLBACK;
|
||||
|
||||
return {
|
||||
provide: {
|
||||
|
|
@ -11,6 +16,7 @@ export default defineNuxtPlugin(() => {
|
|||
APP_DOMAIN: runtimeConfig.public.schonBaseDomain,
|
||||
APP_NAME,
|
||||
APP_NAME_KEY,
|
||||
DEFAULT_LOCALE,
|
||||
COOKIES_LOCALE_KEY: COOKIE_KEY_TEMPLATES.LOCALE(APP_NAME_KEY),
|
||||
COOKIES_REFRESH_TOKEN_KEY: COOKIE_KEY_TEMPLATES.REFRESH_TOKEN(APP_NAME_KEY),
|
||||
COOKIES_ACCESS_TOKEN_KEY: COOKIE_KEY_TEMPLATES.ACCESS_TOKEN(APP_NAME_KEY),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
import { DEFAULT_LOCALE } from '@appConstants';
|
||||
import type { ILanguage } from '@types';
|
||||
|
||||
export const useLanguageStore = defineStore('language', () => {
|
||||
const { $appHelpers } = useNuxtApp();
|
||||
|
||||
const cookieLocale = useCookie($appHelpers.COOKIES_LOCALE_KEY, {
|
||||
default: () => DEFAULT_LOCALE,
|
||||
default: () => $appHelpers.DEFAULT_LOCALE,
|
||||
path: '/',
|
||||
});
|
||||
|
||||
|
|
|
|||
99
storefront/app/utils/transliterator.ts
Normal file
99
storefront/app/utils/transliterator.ts
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
|
||||
export function transliterate(str: string | undefined): string {
|
||||
if (!str) return '';
|
||||
|
||||
const map = {
|
||||
// Russian/Ukrainian/Belarusian Cyrillic
|
||||
'А': 'A', 'Б': 'B', 'В': 'V', 'Г': 'G', 'Д': 'D', 'Е': 'E', 'Ё': 'Yo', 'Ж': 'Zh',
|
||||
'З': 'Z', 'И': 'I', 'Й': 'Y', 'К': 'K', 'Л': 'L', 'М': 'M', 'Н': 'N', 'О': 'O',
|
||||
'П': 'P', 'Р': 'R', 'С': 'S', 'Т': 'T', 'У': 'U', 'Ф': 'F', 'Х': 'Kh', 'Ц': 'Ts',
|
||||
'Ч': 'Ch', 'Ш': 'Sh', 'Щ': 'Shch', 'Ъ': '', 'Ы': 'Y', 'Ь': '', 'Э': 'E', 'Ю': 'Yu',
|
||||
'Я': 'Ya',
|
||||
'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo', 'ж': 'zh',
|
||||
'з': 'z', 'и': 'i', 'й': 'y', 'к': 'k', 'л': 'l', 'м': 'm', 'н': 'n', 'о': 'o',
|
||||
'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u', 'ф': 'f', 'х': 'kh', 'ц': 'ts',
|
||||
'ч': 'ch', 'ш': 'sh', 'щ': 'shch', 'ъ': '', 'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu',
|
||||
'я': 'ya',
|
||||
|
||||
// Ukrainian extras
|
||||
'Ґ': 'G', 'ґ': 'g', 'Є': 'Ye', 'є': 'ye', 'І': 'I', 'і': 'i', 'Ї': 'Yi', 'ї': 'yi',
|
||||
|
||||
// Serbian/Macedonian Cyrillic extras
|
||||
'Ђ': 'Dj', 'ђ': 'dj', 'Ј': 'J', 'ј': 'j', 'Љ': 'Lj', 'љ': 'lj', 'Њ': 'Nj', 'њ': 'nj',
|
||||
'Ћ': 'C', 'ћ': 'c', 'Џ': 'Dz', 'џ': 'dz', 'Ѓ': 'Gj', 'ѓ': 'gj', 'Ѕ': 'Dz', 'ѕ': 'dz',
|
||||
'Ќ': 'Kj', 'ќ': 'kj',
|
||||
|
||||
// Belarusian extras
|
||||
'Ў': 'U', 'ў': 'u',
|
||||
|
||||
// Bulgarian extras (mostly covered above, but ъ is different)
|
||||
// In Bulgarian context ъ = 'a', but we keep '' as default for Russian
|
||||
|
||||
// Greek
|
||||
'Α': 'A', 'Β': 'V', 'Γ': 'G', 'Δ': 'D', 'Ε': 'E', 'Ζ': 'Z', 'Η': 'I', 'Θ': 'Th',
|
||||
'Ι': 'I', 'Κ': 'K', 'Λ': 'L', 'Μ': 'M', 'Ν': 'N', 'Ξ': 'X', 'Ο': 'O', 'Π': 'P',
|
||||
'Ρ': 'R', 'Σ': 'S', 'Τ': 'T', 'Υ': 'Y', 'Φ': 'F', 'Χ': 'Ch', 'Ψ': 'Ps', 'Ω': 'O',
|
||||
'α': 'a', 'β': 'v', 'γ': 'g', 'δ': 'd', 'ε': 'e', 'ζ': 'z', 'η': 'i', 'θ': 'th',
|
||||
'ι': 'i', 'κ': 'k', 'λ': 'l', 'μ': 'm', 'ν': 'n', 'ξ': 'x', 'ο': 'o', 'π': 'p',
|
||||
'ρ': 'r', 'σ': 's', 'ς': 's', 'τ': 't', 'υ': 'y', 'φ': 'f', 'χ': 'ch', 'ψ': 'ps', 'ω': 'o',
|
||||
|
||||
// Arabic
|
||||
'ا': 'a', 'ب': 'b', 'ت': 't', 'ث': 'th', 'ج': 'j', 'ح': 'h', 'خ': 'kh', 'د': 'd',
|
||||
'ذ': 'dh', 'ر': 'r', 'ز': 'z', 'س': 's', 'ش': 'sh', 'ص': 's', 'ض': 'd', 'ط': 't',
|
||||
'ظ': 'z', 'ع': 'a', 'غ': 'gh', 'ف': 'f', 'ق': 'q', 'ك': 'k', 'ل': 'l', 'م': 'm',
|
||||
'ن': 'n', 'ه': 'h', 'و': 'w', 'ي': 'y', 'ة': 'h', 'ء': '\'', 'آ': 'aa',
|
||||
|
||||
// German/Nordic/Central European diacritics
|
||||
'Ä': 'Ae', 'ä': 'ae', 'Ö': 'Oe', 'ö': 'oe', 'Ü': 'Ue', 'ü': 'ue', 'ß': 'ss',
|
||||
'Å': 'A', 'å': 'a', 'Æ': 'Ae', 'æ': 'ae', 'Ø': 'O', 'ø': 'o',
|
||||
'Ð': 'D', 'ð': 'd', 'Þ': 'Th', 'þ': 'th',
|
||||
|
||||
// Czech/Slovak/Polish/Hungarian/Romanian/Turkish
|
||||
'Č': 'C', 'č': 'c', 'Ď': 'D', 'ď': 'd', 'Ě': 'E', 'ě': 'e', 'Ň': 'N', 'ň': 'n',
|
||||
'Ř': 'R', 'ř': 'r', 'Š': 'S', 'š': 's', 'Ť': 'T', 'ť': 't', 'Ů': 'U', 'ů': 'u',
|
||||
'Ž': 'Z', 'ž': 'z', 'Ľ': 'L', 'ľ': 'l', 'Ĺ': 'L', 'ĺ': 'l', 'Ŕ': 'R', 'ŕ': 'r',
|
||||
'Ą': 'A', 'ą': 'a', 'Ć': 'C', 'ć': 'c', 'Ę': 'E', 'ę': 'e', 'Ł': 'L', 'ł': 'l',
|
||||
'Ń': 'N', 'ń': 'n', 'Ś': 'S', 'ś': 's', 'Ź': 'Z', 'ź': 'z', 'Ż': 'Z', 'ż': 'z',
|
||||
'Á': 'A', 'á': 'a', 'É': 'E', 'é': 'e', 'Í': 'I', 'í': 'i', 'Ó': 'O', 'ó': 'o',
|
||||
'Ú': 'U', 'ú': 'u', 'Ý': 'Y', 'ý': 'y',
|
||||
'Ő': 'O', 'ő': 'o', 'Ű': 'U', 'ű': 'u',
|
||||
'Ă': 'A', 'ă': 'a', 'Â': 'A', 'â': 'a', 'Î': 'I', 'î': 'i', 'Ș': 'S', 'ș': 's', 'Ț': 'T', 'ț': 't',
|
||||
'Ç': 'C', 'ç': 'c', 'Ğ': 'G', 'ğ': 'g', 'İ': 'I', 'ı': 'i', 'Ş': 'S', 'ş': 's',
|
||||
|
||||
// Vietnamese (basic - stripped of tone marks conceptually)
|
||||
'Đ': 'D', 'đ': 'd',
|
||||
|
||||
// Spanish/Portuguese/French
|
||||
'Ñ': 'N', 'ñ': 'n',
|
||||
'À': 'A', 'à': 'a', 'È': 'E', 'è': 'e', 'Ì': 'I', 'ì': 'i', 'Ò': 'O', 'ò': 'o',
|
||||
'Ù': 'U', 'ù': 'u', 'Ë': 'E', 'ë': 'e', 'Ï': 'I', 'ï': 'i',
|
||||
'Ê': 'E', 'ê': 'e', 'Ô': 'O', 'ô': 'o', 'Û': 'U', 'û': 'u',
|
||||
'Ã': 'A', 'ã': 'a', 'Õ': 'O', 'õ': 'o',
|
||||
};
|
||||
|
||||
return str.split('').map(ch => {
|
||||
if (ch in map) return map[ch];
|
||||
|
||||
const normalized = ch
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '');
|
||||
|
||||
if (normalized !== ch && /^[\x20-\x7E]+$/.test(normalized)) {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
return ch;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
export function createProjectKey(str: string | undefined): string {
|
||||
if (!str) return 'default-project';
|
||||
|
||||
return transliterate(str)
|
||||
.toLowerCase()
|
||||
.replace(/['"]/g, '')
|
||||
.replace(/[^a-z0-9\s-]/g, '')
|
||||
.trim()
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/-+/g, '-');
|
||||
}
|
||||
|
|
@ -1,8 +1,16 @@
|
|||
import type { NuxtI18nOptions } from '@nuxtjs/i18n';
|
||||
import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from '../app/constants';
|
||||
import { SUPPORTED_LOCALES } from '../app/constants';
|
||||
import { createProjectKey } from "../app/utils/transliterator";
|
||||
|
||||
export const i18nConfig: NuxtI18nOptions = {
|
||||
defaultLocale: DEFAULT_LOCALE,
|
||||
export function createI18nConfig(defaultLocaleCode?: string, projectName: string): NuxtI18nOptions {
|
||||
const defaultLocale = defaultLocaleCode && SUPPORTED_LOCALES.some(l => l.code === defaultLocaleCode)
|
||||
? defaultLocaleCode
|
||||
: 'en-gb';
|
||||
|
||||
const cookieKey = `${createProjectKey(projectName)}-locale`;
|
||||
|
||||
return {
|
||||
defaultLocale,
|
||||
locales: SUPPORTED_LOCALES.map((locale) => ({
|
||||
code: locale.code,
|
||||
file: locale.file,
|
||||
|
|
@ -12,7 +20,8 @@ export const i18nConfig: NuxtI18nOptions = {
|
|||
detectBrowserLanguage: {
|
||||
alwaysRedirect: true,
|
||||
redirectOn: 'root',
|
||||
fallbackLocale: DEFAULT_LOCALE,
|
||||
cookieKey: 'schon-locale',
|
||||
fallbackLocale: defaultLocale,
|
||||
cookieKey,
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
1
storefront/nuxt-app.d.ts
vendored
1
storefront/nuxt-app.d.ts
vendored
|
|
@ -7,6 +7,7 @@ declare module '#app' {
|
|||
APP_DOMAIN: string;
|
||||
APP_NAME: string;
|
||||
APP_NAME_KEY: string;
|
||||
DEFAULT_LOCALE: string;
|
||||
COOKIES_LOCALE_KEY: string;
|
||||
COOKIES_REFRESH_TOKEN_KEY: string;
|
||||
COOKIES_ACCESS_TOKEN_KEY: string;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { resolve } from 'node:path';
|
||||
import { fileURLToPath, URL } from 'node:url';
|
||||
import { i18nConfig } from './i18n/i18.config';
|
||||
import { createProjectKey } from './app/utils/transliterator';
|
||||
import { createI18nConfig } from './i18n/i18.config';
|
||||
|
||||
export default defineNuxtConfig({
|
||||
compatibilityDate: '2025-07-15',
|
||||
|
|
@ -22,7 +23,7 @@ export default defineNuxtConfig({
|
|||
'@nuxt/hints',
|
||||
'@nuxt/image',
|
||||
],
|
||||
i18n: i18nConfig,
|
||||
i18n: createI18nConfig(process.env.SCHON_LANGUAGE_CODE),
|
||||
apollo: {
|
||||
autoImports: true,
|
||||
clients: {
|
||||
|
|
@ -32,7 +33,7 @@ export default defineNuxtConfig({
|
|||
authType: 'Bearer',
|
||||
authHeader: 'X-SCHON-AUTH',
|
||||
tokenStorage: 'cookie',
|
||||
tokenName: `${process.env.SCHON_PROJECT_NAME?.toLowerCase().replace(/\s+/g, '-')}-access`,
|
||||
tokenName: `${createProjectKey(process.env.SCHON_PROJECT_NAME)}-access`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -40,6 +41,7 @@ export default defineNuxtConfig({
|
|||
public: {
|
||||
schonProjectName: process.env.SCHON_PROJECT_NAME,
|
||||
schonBaseDomain: process.env.SCHON_BASE_DOMAIN,
|
||||
schonLanguageCode: process.env.SCHON_LANGUAGE_CODE,
|
||||
},
|
||||
},
|
||||
app: {
|
||||
|
|
@ -75,6 +77,7 @@ export default defineNuxtConfig({
|
|||
'@appConstants': fileURLToPath(new URL('./app/constants', import.meta.url)),
|
||||
'@composables': fileURLToPath(new URL('./app/composables', import.meta.url)),
|
||||
'@types': fileURLToPath(new URL('./types', import.meta.url)),
|
||||
'@utils': fileURLToPath(new URL('./app/utils', import.meta.url)),
|
||||
},
|
||||
vite: {
|
||||
envDir: '../',
|
||||
|
|
|
|||
Loading…
Reference in a new issue