**chore(storefront): apply consistent code formatting and improve readability**

Refactored multiple files for code styling consistency, using proper indentation and spacing to align with team standards. Improved readability and maintainability across composables, Apollo plugin, and localization files.

Enhancements:
- Standardized import and function indentation across all composables.
- Updated `biome.json` schema to the latest version (v2.4.4) for tool compatibility.
- Organized code blocks in Apollo plugin for better understandability.

No functional changes introduced—this is a non-breaking, code refinement commit.
This commit is contained in:
Alexandr SaVBaD Waltz 2026-02-28 17:41:25 +03:00
parent c36135d78d
commit e65e7b7d73
18 changed files with 600 additions and 576 deletions

View file

@ -31,7 +31,7 @@ export function useRegister() {
password: payload.password, password: payload.password,
confirmPassword: payload.confirmPassword, confirmPassword: payload.confirmPassword,
referrer: payload.referrer, referrer: payload.referrer,
isSubscribed: payload.isSubscribed isSubscribed: payload.isSubscribed,
}); });
if (result?.data?.createUser?.success) { if (result?.data?.createUser?.success) {

View file

@ -1,5 +1,5 @@
import { GET_BRANDS } from '@graphql/queries/standalone/brands'; import { GET_BRANDS } from '@graphql/queries/standalone/brands';
import type { IBrand, IBrandsResponse } from '@types'; import type { IBrand, IBrandsResponse } from '@types';
interface IBrandArgs { interface IBrandArgs {
brandAfter?: string; brandAfter?: string;
@ -32,7 +32,7 @@ export function useBrands(args: IBrandArgs = {}) {
endCursor: string; endCursor: string;
}>({ }>({
hasNextPage: false, hasNextPage: false,
endCursor: '' endCursor: '',
}); });
const error = ref<string | null>(null); const error = ref<string | null>(null);

View file

@ -8,7 +8,8 @@ import {
} from '@graphql/mutations/cart'; } from '@graphql/mutations/cart';
import type { import type {
IAddToOrderResponse, IAddToOrderResponse,
IBulkOrderResponse, IProduct, IBulkOrderResponse,
IProduct,
IRemoveAllFromOrderResponse, IRemoveAllFromOrderResponse,
IRemoveFromOrderResponse, IRemoveFromOrderResponse,
IRemoveKindFromOrderResponse, IRemoveKindFromOrderResponse,
@ -168,17 +169,20 @@ export function useOrderOverwrite() {
switch (args.type) { switch (args.type) {
case 'add': { case 'add': {
const currentCart = cookieCart.value || []; const currentCart = cookieCart.value || [];
const existingItem = currentCart.find( const existingItem = currentCart.find((item) => item.product.uuid === args.product.uuid);
(item) => item.product.uuid === args.product.uuid
);
if (existingItem) { if (existingItem) {
existingItem.quantity += 1; existingItem.quantity += 1;
cookieCart.value = [...currentCart]; cookieCart.value = [
...currentCart,
];
} else { } else {
cookieCart.value = [ cookieCart.value = [
...currentCart, ...currentCart,
{ product: args.product, quantity: 1 } {
product: args.product,
quantity: 1,
},
]; ];
} }
@ -194,18 +198,16 @@ export function useOrderOverwrite() {
case 'remove': { case 'remove': {
const currentCart = cookieCart.value || []; const currentCart = cookieCart.value || [];
const existingItem = currentCart.find( const existingItem = currentCart.find((item) => item.product.uuid === args.product.uuid);
(item) => item.product.uuid === args.product.uuid
);
if (existingItem) { if (existingItem) {
if (existingItem.quantity > 1) { if (existingItem.quantity > 1) {
existingItem.quantity -= 1; existingItem.quantity -= 1;
cookieCart.value = [...currentCart]; cookieCart.value = [
...currentCart,
];
} else { } else {
cookieCart.value = currentCart.filter( cookieCart.value = currentCart.filter((item) => item.product.uuid !== args.product.uuid);
(item) => item.product.uuid !== args.product.uuid
);
} }
useNotification({ useNotification({
@ -220,9 +222,7 @@ export function useOrderOverwrite() {
} }
case 'removeKind': { case 'removeKind': {
cookieCart.value = cookieCart.value.filter( cookieCart.value = cookieCart.value.filter((item) => item.product.uuid !== args.product.uuid);
(item) => item.product.uuid !== args.product.uuid
);
useNotification({ useNotification({
message: t('popup.success.removeFromCart', { message: t('popup.success.removeFromCart', {
@ -247,10 +247,8 @@ export function useOrderOverwrite() {
case 'bulk': { case 'bulk': {
if (args.bulkAction === 'remove' && args.products) { if (args.bulkAction === 'remove' && args.products) {
const uuidsToRemove = args.products.map(p => p.uuid); const uuidsToRemove = args.products.map((p) => p.uuid);
cookieCart.value = cookieCart.value.filter( cookieCart.value = cookieCart.value.filter((item) => !uuidsToRemove.includes(item.product.uuid));
(item) => !uuidsToRemove.includes(item.product.uuid)
);
useNotification({ useNotification({
message: t('popup.success.bulkRemoveOrder'), message: t('popup.success.bulkRemoveOrder'),
@ -260,16 +258,16 @@ export function useOrderOverwrite() {
const currentCart = cookieCart.value || []; const currentCart = cookieCart.value || [];
for (const productRef of args.products) { for (const productRef of args.products) {
const existingItem = currentCart.find( const existingItem = currentCart.find((item) => item.product.uuid === productRef.uuid);
(item) => item.product.uuid === productRef.uuid
);
if (existingItem) { if (existingItem) {
existingItem.quantity += 1; existingItem.quantity += 1;
} }
} }
cookieCart.value = [...currentCart]; cookieCart.value = [
...currentCart,
];
} }
break; break;

View file

@ -1,68 +1,73 @@
import { useOrderOverwrite } from '@composables/orders/useOrderOverwrite'; import { useOrderOverwrite } from '@composables/orders/useOrderOverwrite';
export function useOrderSync() { export function useOrderSync() {
const cartStore = useCartStore(); const cartStore = useCartStore();
const userStore = useUserStore(); const userStore = useUserStore();
const { $appHelpers } = useNuxtApp(); const { $appHelpers } = useNuxtApp();
const { overwriteOrder } = useOrderOverwrite(); const { overwriteOrder } = useOrderOverwrite();
const isAuthenticated = computed(() => userStore.isAuthenticated); const isAuthenticated = computed(() => userStore.isAuthenticated);
const orderUuid = computed(() => cartStore.currentOrder?.uuid); const orderUuid = computed(() => cartStore.currentOrder?.uuid);
const cookieCart = useCookie($appHelpers.COOKIES_CART_KEY, { const cookieCart = useCookie($appHelpers.COOKIES_CART_KEY, {
default: () => [], default: () => [],
path: '/', path: '/',
}); });
async function syncOrder() { async function syncOrder() {
if (!isAuthenticated.value || !orderUuid.value) { if (!isAuthenticated.value || !orderUuid.value) {
return; return;
} }
const cookieCartItems = cookieCart.value || []; const cookieCartItems = cookieCart.value || [];
if (cookieCartItems.length === 0) { if (cookieCartItems.length === 0) {
return; return;
} }
const apiCartProducts = cartStore.currentOrder?.orderProducts?.edges || []; const apiCartProducts = cartStore.currentOrder?.orderProducts?.edges || [];
const apiProductMap = new Map( const apiProductMap = new Map(
apiCartProducts.map(e => [e.node.product.uuid, e.node.quantity]) apiCartProducts.map((e) => [
); e.node.product.uuid,
e.node.quantity,
]),
);
const productsToSync = []; const productsToSync = [];
for (const cartItem of cookieCartItems) { for (const cartItem of cookieCartItems) {
const apiQuantity = apiProductMap.get(cartItem.product.uuid) || 0; const apiQuantity = apiProductMap.get(cartItem.product.uuid) || 0;
const quantityDifference = cartItem.quantity - apiQuantity; const quantityDifference = cartItem.quantity - apiQuantity;
if (quantityDifference > 0) { if (quantityDifference > 0) {
for (let i = 0; i < quantityDifference; i++) { for (let i = 0; i < quantityDifference; i++) {
productsToSync.push({ uuid: cartItem.product.uuid }); productsToSync.push({
} uuid: cartItem.product.uuid,
} });
} }
}
}
if (productsToSync.length === 0) { if (productsToSync.length === 0) {
cookieCart.value = []; cookieCart.value = [];
return; return;
} }
try { try {
await overwriteOrder({ await overwriteOrder({
type: 'bulk', type: 'bulk',
bulkAction: 'add', bulkAction: 'add',
isBulkSync: true, isBulkSync: true,
products: productsToSync products: productsToSync,
}); });
} catch (err) { } catch (err) {
console.error('Failed to sync cart:', err); console.error('Failed to sync cart:', err);
} }
} }
return { return {
syncOrder, syncOrder,
}; };
} }

View file

@ -1,18 +1,18 @@
import {GET_POSTS} from "@graphql/queries/standalone/blog"; import { GET_POSTS } from '@graphql/queries/standalone/blog';
import type {IPostResponse} from '@types'; import type { IPostResponse } from '@types';
export function usePosts() { export function usePosts() {
const { data, error } = useAsyncQuery<IPostResponse>(GET_POSTS); const { data, error } = useAsyncQuery<IPostResponse>(GET_POSTS);
const posts = computed(() => data.value?.posts.edges ?? []); const posts = computed(() => data.value?.posts.edges ?? []);
watch(error, (err) => { watch(error, (err) => {
if (err) { if (err) {
console.error('usePosts error:', err); console.error('usePosts error:', err);
} }
}); });
return { return {
posts, posts,
}; };
} }

View file

@ -17,4 +17,4 @@ export async function usePromocodes() {
}); });
return {}; return {};
} }

View file

@ -4,45 +4,53 @@ import type { Ref } from 'vue';
export function useFilters(filterableAttributes: Ref<IStoreFilters[]>) { export function useFilters(filterableAttributes: Ref<IStoreFilters[]>) {
const selectedMap = reactive<Record<string, Record<string, boolean>>>({}); const selectedMap = reactive<Record<string, Record<string, boolean>>>({});
const selectedAllMap = reactive<Record<string, boolean>>({}); const selectedAllMap = reactive<Record<string, boolean>>({});
const priceRange = ref<[number, number]>([0, 50000]); const priceRange = ref<
[
number,
number,
]
>([
0,
50000,
]);
const collapse = ref<string[]>([]); const collapse = ref<string[]>([]);
watch( watch(
filterableAttributes, filterableAttributes,
(attrs) => { (attrs) => {
attrs?.forEach((attr) => { attrs?.forEach((attr) => {
const key = attr.attributeName; const key = attr.attributeName;
if (!selectedMap[key]) { if (!selectedMap[key]) {
selectedMap[key] = {}; selectedMap[key] = {};
}
if (selectedAllMap[key] === undefined) {
selectedAllMap[key] = false;
}
attr.possibleValues.forEach((v) => {
if (selectedMap[key][v] === undefined) {
selectedMap[key][v] = false;
} }
if (selectedAllMap[key] === undefined) {
selectedAllMap[key] = false;
}
attr.possibleValues.forEach((v) => {
if (selectedMap[key][v] === undefined) {
selectedMap[key][v] = false;
}
});
}); });
}, });
{ },
immediate: true, {
}, immediate: true,
},
); );
watch( watch(
() => filterableAttributes.value?.map((a) => selectedMap[a.attributeName]), () => filterableAttributes.value?.map((a) => selectedMap[a.attributeName]),
(maps) => { (maps) => {
maps?.forEach((values, idx) => { maps?.forEach((values, idx) => {
const key = filterableAttributes.value[idx]?.attributeName; const key = filterableAttributes.value[idx]?.attributeName;
selectedAllMap[key] = Object.values(values).every((v) => v); selectedAllMap[key] = Object.values(values).every((v) => v);
}); });
}, },
{ {
immediate: true, immediate: true,
deep: true, deep: true,
}, },
); );
function toggleAll(attrName: string) { function toggleAll(attrName: string) {
@ -56,10 +64,10 @@ export function useFilters(filterableAttributes: Ref<IStoreFilters[]>) {
function resetFilters() { function resetFilters() {
filterableAttributes.value?.forEach((attr) => { filterableAttributes.value?.forEach((attr) => {
selectedAllMap[attr.attributeName] = false; selectedAllMap[attr.attributeName] = false;
attr.possibleValues.forEach((v) => { attr.possibleValues.forEach((v) => {
selectedMap[attr.attributeName][v] = false; selectedMap[attr.attributeName][v] = false;
}); });
}); });
} }
@ -68,8 +76,8 @@ export function useFilters(filterableAttributes: Ref<IStoreFilters[]>) {
Object.entries(selectedMap).forEach(([attr, values]) => { Object.entries(selectedMap).forEach(([attr, values]) => {
const checked = Object.entries(values) const checked = Object.entries(values)
.filter(([, ok]) => ok) .filter(([, ok]) => ok)
.map(([val]) => val); .map(([val]) => val);
if (checked.length) { if (checked.length) {
picked[attr] = checked; picked[attr] = checked;
} }
@ -80,13 +88,13 @@ export function useFilters(filterableAttributes: Ref<IStoreFilters[]>) {
function buildAttributesString(filters: Record<string, string[]>): string { function buildAttributesString(filters: Record<string, string[]>): string {
return Object.entries(filters) return Object.entries(filters)
.map(([name, vals]) => { .map(([name, vals]) => {
if (name === 'float' && vals.length === 2) { if (name === 'float' && vals.length === 2) {
return `${name}=gte-${vals[0]};${name}=lte-${vals[1]}`; return `${name}=gte-${vals[0]};${name}=lte-${vals[1]}`;
} }
return vals.length === 1 ? `${name}=icontains-${vals[0]}` : `${name}=in-${JSON.stringify(vals)}`; return vals.length === 1 ? `${name}=icontains-${vals[0]}` : `${name}=in-${JSON.stringify(vals)}`;
}) })
.join(';'); .join(';');
} }
function parseAttributesString(str: string): Record<string, string[]> { function parseAttributesString(str: string): Record<string, string[]> {
@ -100,7 +108,10 @@ export function useFilters(filterableAttributes: Ref<IStoreFilters[]>) {
if (expr.startsWith('range-')) { if (expr.startsWith('range-')) {
const parts = expr.slice(6).split('-'); const parts = expr.slice(6).split('-');
if (parts.length >= 2) { if (parts.length >= 2) {
result[name] = [parts.slice(0, parts.length - 1).join('-'), parts[parts.length - 1]]; result[name] = [
parts.slice(0, parts.length - 1).join('-'),
parts[parts.length - 1],
];
} }
} else if (expr.startsWith('in-')) { } else if (expr.startsWith('in-')) {
try { try {

View file

@ -12,14 +12,15 @@ export function useAvatarUpload() {
if (!file) return; if (!file) return;
await mutate( await mutate(
{ {
file, file,
}, },
{ {
context: { context: {
hasUpload: true, hasUpload: true,
},
}, },
}); );
} }
onDone(({ data }) => { onDone(({ data }) => {

View file

@ -1,6 +1,6 @@
import { orderStatuses } from '@appConstants'; import { orderStatuses } from '@appConstants';
import { useOrderSync } from '@composables/orders'; import { useOrderSync } from '@composables/orders';
import {useWishlistSync} from "@composables/wishlist"; import { useWishlistSync } from '@composables/wishlist';
import { getUserBaseData } from '@graphql/queries/combined/userBaseData'; import { getUserBaseData } from '@graphql/queries/combined/userBaseData';
import type { IUserBaseDataResponse } from '@types'; import type { IUserBaseDataResponse } from '@types';

View file

@ -7,7 +7,8 @@ import {
} from '@graphql/mutations/wishlist'; } from '@graphql/mutations/wishlist';
import type { import type {
IAddToWishlistResponse, IAddToWishlistResponse,
IBulkWishlistResponse, IProduct, IBulkWishlistResponse,
IProduct,
IRemoveAllFromWishlistResponse, IRemoveAllFromWishlistResponse,
IRemoveFromWishlistResponse, IRemoveFromWishlistResponse,
} from '@types'; } from '@types';
@ -147,9 +148,7 @@ export function useWishlistOverwrite() {
} else { } else {
switch (args.type) { switch (args.type) {
case 'add': { case 'add': {
const isAlreadyInWishlist = cookieWishlist.value.some( const isAlreadyInWishlist = cookieWishlist.value.some((item) => item.uuid === args.product.uuid);
(item) => item.uuid === args.product.uuid
);
if (isAlreadyInWishlist) { if (isAlreadyInWishlist) {
useNotification({ useNotification({
@ -159,7 +158,10 @@ export function useWishlistOverwrite() {
type: 'warning', type: 'warning',
}); });
} else { } else {
cookieWishlist.value = [...cookieWishlist.value, args.product]; cookieWishlist.value = [
...cookieWishlist.value,
args.product,
];
useNotification({ useNotification({
message: t('popup.success.addToWishlist', { message: t('popup.success.addToWishlist', {
@ -173,9 +175,7 @@ export function useWishlistOverwrite() {
} }
case 'remove': { case 'remove': {
cookieWishlist.value = cookieWishlist.value.filter( cookieWishlist.value = cookieWishlist.value.filter((item) => item.uuid !== args.product.uuid);
(item) => item.uuid !== args.product.uuid
);
useNotification({ useNotification({
message: t('popup.success.removeFromWishlist', { message: t('popup.success.removeFromWishlist', {

View file

@ -1,66 +1,66 @@
import {useWishlistOverwrite} from "@composables/wishlist/useWishlistOverwrite"; import { useWishlistOverwrite } from '@composables/wishlist/useWishlistOverwrite';
export function useWishlistSync() { export function useWishlistSync() {
const wishlistStore = useWishlistStore(); const wishlistStore = useWishlistStore();
const userStore = useUserStore(); const userStore = useUserStore();
const { $appHelpers } = useNuxtApp(); const { $appHelpers } = useNuxtApp();
const { overwriteWishlist } = useWishlistOverwrite(); const { overwriteWishlist } = useWishlistOverwrite();
const isAuthenticated = computed(() => userStore.isAuthenticated); const isAuthenticated = computed(() => userStore.isAuthenticated);
const wishlistUuid = computed(() => wishlistStore.wishlist?.uuid); const wishlistUuid = computed(() => wishlistStore.wishlist?.uuid);
const cookieWishlist = useCookie($appHelpers.COOKIES_WISHLIST_KEY, { const cookieWishlist = useCookie($appHelpers.COOKIES_WISHLIST_KEY, {
default: () => [], default: () => [],
path: '/', path: '/',
}); });
async function syncWishlist() { async function syncWishlist() {
if (!isAuthenticated.value || !wishlistUuid.value) { if (!isAuthenticated.value || !wishlistUuid.value) {
return; return;
} }
const cookieProducts = cookieWishlist.value || []; const cookieProducts = cookieWishlist.value || [];
if (cookieProducts.length === 0) { if (cookieProducts.length === 0) {
return; return;
} }
const apiProductUuids = wishlistStore.wishlist?.products?.edges.map(e => e.node.uuid) || []; const apiProductUuids = wishlistStore.wishlist?.products?.edges.map((e) => e.node.uuid) || [];
const productsToAdd = cookieProducts.filter( const productsToAdd = cookieProducts.filter((product) => !apiProductUuids.includes(product.uuid));
(product) => !apiProductUuids.includes(product.uuid)
);
if (productsToAdd.length === 0) { if (productsToAdd.length === 0) {
cookieWishlist.value = []; cookieWishlist.value = [];
return; return;
} }
try { try {
await overwriteWishlist({ await overwriteWishlist({
type: 'bulk', type: 'bulk',
bulkAction: 'add', bulkAction: 'add',
isBulkSync: true, isBulkSync: true,
products: productsToAdd.map(p => ({ uuid: p.uuid })) products: productsToAdd.map((p) => ({
}) uuid: p.uuid,
})),
});
if (bulkResult?.data?.bulkWishlistAction?.wishlist) { if (bulkResult?.data?.bulkWishlistAction?.wishlist) {
wishlistStore.setWishlist(bulkResult.data.bulkWishlistAction.wishlist); wishlistStore.setWishlist(bulkResult.data.bulkWishlistAction.wishlist);
cookieWishlist.value = []; cookieWishlist.value = [];
} }
} catch (err) { } catch (err) {
console.error('Failed to sync wishlist:', err); console.error('Failed to sync wishlist:', err);
} }
} }
watch(syncError, (err) => { watch(syncError, (err) => {
if (!err) return; if (!err) return;
console.error('useWishlistSync error:', err); console.error('useWishlistSync error:', err);
}); });
return { return {
syncWishlist, syncWishlist,
}; };
} }

View file

@ -1 +1 @@
export const CURRENCY = '$'; export const CURRENCY = '$';

View file

@ -1,8 +1,8 @@
export enum docsSlugs { export enum docsSlugs {
TERMS = 'terms-conditions', TERMS = 'terms-conditions',
POLICY = 'privacy-policy', POLICY = 'privacy-policy',
FAQ = 'faq', FAQ = 'faq',
SHIPPING = 'shipping-information', SHIPPING = 'shipping-information',
RETURN = 'return-policy', RETURN = 'return-policy',
ABOUT = 'about-us' ABOUT = 'about-us',
} }

View file

@ -1,9 +1,8 @@
import { ApolloLink, from } from '@apollo/client/core'; import { ApolloLink, from } from '@apollo/client/core';
import { setContext } from '@apollo/client/link/context'; import { setContext } from '@apollo/client/link/context';
import { onError } from '@apollo/client/link/error'; import { onError } from '@apollo/client/link/error';
import { provideApolloClient } from '@vue/apollo-composable'; import { provideApolloClient } from '@vue/apollo-composable';
import createUploadLink from "apollo-upload-client/createUploadLink.mjs"; import createUploadLink from 'apollo-upload-client/createUploadLink.mjs';
export default defineNuxtPlugin((nuxtApp) => { export default defineNuxtPlugin((nuxtApp) => {
const runtime = useRuntimeConfig(); const runtime = useRuntimeConfig();
@ -22,23 +21,29 @@ export default defineNuxtPlugin((nuxtApp) => {
let locale = 'en-gb'; let locale = 'en-gb';
if (import.meta.client) { if (import.meta.client) {
const clientCookies = document.cookie.split(';').reduce((acc, cookie) => { const clientCookies = document.cookie.split(';').reduce(
const [key, value] = cookie.trim().split('='); (acc, cookie) => {
acc[key] = decodeURIComponent(value); const [key, value] = cookie.trim().split('=');
return acc; acc[key] = decodeURIComponent(value);
}, {} as Record<string, string>); return acc;
},
{} as Record<string, string>,
);
accessToken = clientCookies[$appHelpers.COOKIES_ACCESS_TOKEN_KEY] || ''; accessToken = clientCookies[$appHelpers.COOKIES_ACCESS_TOKEN_KEY] || '';
locale = clientCookies[$appHelpers.COOKIES_LOCALE_KEY] || 'en-gb'; locale = clientCookies[$appHelpers.COOKIES_LOCALE_KEY] || 'en-gb';
} else { } else {
const cookieHeader = nuxtApp.ssrContext?.event?.node?.req?.headers?.cookie || ''; const cookieHeader = nuxtApp.ssrContext?.event?.node?.req?.headers?.cookie || '';
const serverCookies = cookieHeader.split(';').reduce((acc, cookie) => { const serverCookies = cookieHeader.split(';').reduce(
const [key, value] = cookie.trim().split('='); (acc, cookie) => {
if (key && value) { const [key, value] = cookie.trim().split('=');
acc[key] = decodeURIComponent(value); if (key && value) {
} acc[key] = decodeURIComponent(value);
return acc; }
}, {} as Record<string, string>); return acc;
},
{} as Record<string, string>,
);
accessToken = serverCookies[$appHelpers.COOKIES_ACCESS_TOKEN_KEY] || ''; accessToken = serverCookies[$appHelpers.COOKIES_ACCESS_TOKEN_KEY] || '';
locale = serverCookies[$appHelpers.COOKIES_LOCALE_KEY] || 'en-gb'; locale = serverCookies[$appHelpers.COOKIES_LOCALE_KEY] || 'en-gb';
@ -46,14 +51,16 @@ export default defineNuxtPlugin((nuxtApp) => {
const hdrs: Record<string, string> = { const hdrs: Record<string, string> = {
...headers, ...headers,
'Accept-Language': locale 'Accept-Language': locale,
}; };
if (accessToken) { if (accessToken) {
hdrs['X-SCHON-AUTH'] = `Bearer ${accessToken}`; hdrs['X-SCHON-AUTH'] = `Bearer ${accessToken}`;
} }
return { headers: hdrs }; return {
headers: hdrs,
};
}); });
const customLink = new ApolloLink((operation, forward) => { const customLink = new ApolloLink((operation, forward) => {
@ -63,15 +70,17 @@ export default defineNuxtPlugin((nuxtApp) => {
}); });
const httpLink = createUploadLink({ const httpLink = createUploadLink({
uri: `https://api.${runtime.public.schonBaseDomain}/graphql/` uri: `https://api.${runtime.public.schonBaseDomain}/graphql/`,
}); });
$apollo.defaultClient.setLink(from([ $apollo.defaultClient.setLink(
errorLink, from([
authLink, errorLink,
customLink, authLink,
httpLink, customLink,
])); httpLink,
]),
);
provideApolloClient($apollo.defaultClient); provideApolloClient($apollo.defaultClient);
}); });

View file

@ -1,5 +1,5 @@
{ {
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json", "$schema": "https://biomejs.dev/schemas/2.4.4/schema.json",
"vcs": { "vcs": {
"enabled": true, "enabled": true,
"clientKind": "git", "clientKind": "git",

View file

@ -341,4 +341,4 @@
"title": "Shop", "title": "Shop",
"text": "Discover our curated collection of luxury fashion and accessories that define sophisticated style" "text": "Discover our curated collection of luxury fashion and accessories that define sophisticated style"
} }
} }

View file

@ -1 +1 @@
{} {}

View file

@ -1,344 +1,344 @@
{ {
"buttons": { "buttons": {
"login": "Войти", "login": "Войти",
"register": "Регистрация", "register": "Регистрация",
"createAccount": "Создать аккаунт", "createAccount": "Создать аккаунт",
"addToCart": "В корзину", "addToCart": "В корзину",
"removeFromCart": "Удалить из корзины", "removeFromCart": "Удалить из корзины",
"addAllToCart": "Добавить все в корзину", "addAllToCart": "Добавить все в корзину",
"addToWishlist": "В избранное", "addToWishlist": "В избранное",
"removeFromWishlist": "Удалить из избранного", "removeFromWishlist": "Удалить из избранного",
"send": "Отправить", "send": "Отправить",
"goEmail": "Перейти к почте", "goEmail": "Перейти к почте",
"logout": "Выйти", "logout": "Выйти",
"checkout": "Оформить заказ", "checkout": "Оформить заказ",
"save": "Сохранить", "save": "Сохранить",
"sendLink": "Отправить ссылку для сброса", "sendLink": "Отправить ссылку для сброса",
"topUp": "Пополнить", "topUp": "Пополнить",
"shopNow": "КУПИТЬ СЕЙЧАС", "shopNow": "КУПИТЬ СЕЙЧАС",
"shopTheSale": "Купить по акции", "shopTheSale": "Купить по акции",
"readMore": "Читать далее", "readMore": "Читать далее",
"sendMessage": "Отправить сообщение", "sendMessage": "Отправить сообщение",
"saveChanges": "Сохранить изменения", "saveChanges": "Сохранить изменения",
"clearAll": "Очистить всё" "clearAll": "Очистить всё"
}, },
"errors": { "errors": {
"required": "Это поле обязательно!", "required": "Это поле обязательно!",
"mail": "Введите корректный email!", "mail": "Введите корректный email!",
"compare": "Пароли не совпадают!", "compare": "Пароли не совпадают!",
"needLower": "Добавьте строчную букву.", "needLower": "Добавьте строчную букву.",
"needUpper": "Добавьте заглавную букву.", "needUpper": "Добавьте заглавную букву.",
"needNumber": "Добавьте цифру.", "needNumber": "Добавьте цифру.",
"needMin": "Мин. 8 символов", "needMin": "Мин. 8 символов",
"needSpecial": "Добавьте спецсимвол: #.?!$%^&*'()_+=:;\"'/>.<,|\\-", "needSpecial": "Добавьте спецсимвол: #.?!$%^&*'()_+=:;\"'/>.<,|\\-",
"pageNotFound": "Страница не найдена" "pageNotFound": "Страница не найдена"
}, },
"fields": { "fields": {
"search": "Поиск", "search": "Поиск",
"searchOrder": "Поиск заказа", "searchOrder": "Поиск заказа",
"name": "Имя", "name": "Имя",
"firstName": "Имя", "firstName": "Имя",
"lastName": "Фамилия", "lastName": "Фамилия",
"phoneNumber": "Номер телефона", "phoneNumber": "Номер телефона",
"email": "Email", "email": "Email",
"subject": "Тема", "subject": "Тема",
"message": "Ваше сообщение", "message": "Ваше сообщение",
"password": "Пароль", "password": "Пароль",
"newPassword": "Новый пароль", "newPassword": "Новый пароль",
"confirmPassword": "Подтвердите пароль", "confirmPassword": "Подтвердите пароль",
"confirmNewPassword": "Подтвердите новый пароль", "confirmNewPassword": "Подтвердите новый пароль",
"brandsSearch": "Поиск брендов по названию..." "brandsSearch": "Поиск брендов по названию..."
}, },
"checkboxes": { "checkboxes": {
"remember": "Запомнить меня", "remember": "Запомнить меня",
"chooseAll": "Выбрать все", "chooseAll": "Выбрать все",
"agree": "Я согласен с {terms} и {policy}", "agree": "Я согласен с {terms} и {policy}",
"subscribe": "Подписаться на рассылку новостей об эксклюзивных предложениях и обновлениях" "subscribe": "Подписаться на рассылку новостей об эксклюзивных предложениях и обновлениях"
}, },
"popup": { "popup": {
"errors": { "errors": {
"main": "Ошибка!", "main": "Ошибка!",
"defaultError": "Что-то пошло не так...", "defaultError": "Что-то пошло не так...",
"noDataToUpdate": "Нет данных для обновления.", "noDataToUpdate": "Нет данных для обновления.",
"loginFirst": "Войдите, чтобы выполнить это действие!", "loginFirst": "Войдите, чтобы выполнить это действие!",
"alreadyInWishlist": "{product} уже есть в избранном!" "alreadyInWishlist": "{product} уже есть в избранном!"
}, },
"success": { "success": {
"login": "Вход выполнен", "login": "Вход выполнен",
"register": "Аккаунт успешно создан. Пожалуйста, подтвердите ваш Email перед входом!", "register": "Аккаунт успешно создан. Пожалуйста, подтвердите ваш Email перед входом!",
"confirmEmail": "Ссылка для подтверждения E-mail успешно отправлена!", "confirmEmail": "Ссылка для подтверждения E-mail успешно отправлена!",
"reset": "Если указанный email существует в нашей системе, мы отправим на него письмо для восстановления пароля!", "reset": "Если указанный email существует в нашей системе, мы отправим на него письмо для восстановления пароля!",
"newPassword": "Вы успешно изменили пароль!", "newPassword": "Вы успешно изменили пароль!",
"contactUs": "Ваше сообщение успешно отправлено!", "contactUs": "Ваше сообщение успешно отправлено!",
"addToCart": "{product} добавлен в корзину!", "addToCart": "{product} добавлен в корзину!",
"removeFromCart": "{product} удален из корзины!", "removeFromCart": "{product} удален из корзины!",
"removeAllFromCart": "Корзина успешно очищена!", "removeAllFromCart": "Корзина успешно очищена!",
"addToWishlist": "{product} добавлен в избранное!", "addToWishlist": "{product} добавлен в избранное!",
"removeFromWishlist": "{product} удален из избранного!", "removeFromWishlist": "{product} удален из избранного!",
"removeAllFromWishlist": "Список избранного успешно очищен!", "removeAllFromWishlist": "Список избранного успешно очищен!",
"bulkRemoveWishlist": "Выбранные товары удалены из избранного!", "bulkRemoveWishlist": "Выбранные товары удалены из избранного!",
"bulkRemoveOrder": "Выбранные товары удалены из корзины!", "bulkRemoveOrder": "Выбранные товары удалены из корзины!",
"avatarUpload": "Аватар успешно загружен!", "avatarUpload": "Аватар успешно загружен!",
"userUpdate": "Профиль успешно обновлен!", "userUpdate": "Профиль успешно обновлен!",
"emailUpdate": "Проверьте вашу почту для перехода по ссылке подтверждения и завершения обновления email.", "emailUpdate": "Проверьте вашу почту для перехода по ссылке подтверждения и завершения обновления email.",
"referralCopy": "Реферальная ссылка скопирована!", "referralCopy": "Реферальная ссылка скопирована!",
"promocodeCopy": "Промокод скопирован!", "promocodeCopy": "Промокод скопирован!",
"configCopy": "Новая ui конфигурация скопирована!", "configCopy": "Новая ui конфигурация скопирована!",
"addFeedback": "Ваш отзыв сохранен!" "addFeedback": "Ваш отзыв сохранен!"
}, },
"addToCartLimit": "Лимит общего количества составляет {quantity}!", "addToCartLimit": "Лимит общего количества составляет {quantity}!",
"failAdd": "Пожалуйста, войдите, чтобы совершить покупку", "failAdd": "Пожалуйста, войдите, чтобы совершить покупку",
"activationSuccess": "E-mail успешно подтвержден. Пожалуйста, войдите!", "activationSuccess": "E-mail успешно подтвержден. Пожалуйста, войдите!",
"successUpdate": "Профиль успешно обновлен!", "successUpdate": "Профиль успешно обновлен!",
"payment": "Ваш платеж обрабатывается! Пожалуйста, подождите", "payment": "Ваш платеж обрабатывается! Пожалуйста, подождите",
"successCheckout": "Заказ успешно оплачен!" "successCheckout": "Заказ успешно оплачен!"
}, },
"header": { "header": {
"nav": { "nav": {
"shop": "Магазин", "shop": "Магазин",
"catalog": "Каталог", "catalog": "Каталог",
"brands": "Бренды", "brands": "Бренды",
"blog": "Блог", "blog": "Блог",
"contact": "Контакты" "contact": "Контакты"
}, },
"actions": { "actions": {
"wishlist": "Избранное", "wishlist": "Избранное",
"cart": "Корзина", "cart": "Корзина",
"login": "Войти", "login": "Войти",
"profile": "Профиль" "profile": "Профиль"
}, },
"search": { "search": {
"empty": "Ничего не найдено" "empty": "Ничего не найдено"
}, },
"catalog": { "catalog": {
"title": "Каталог" "title": "Каталог"
} }
}, },
"footer": { "footer": {
"address": "Адрес: ", "address": "Адрес: ",
"email": "Email: ", "email": "Email: ",
"phone": "Телефон: ", "phone": "Телефон: ",
"text": "Курируем вневременную роскошную моду для взыскательных личностей", "text": "Курируем вневременную роскошную моду для взыскательных личностей",
"shop": "Магазин", "shop": "Магазин",
"allProducts": "Все товары", "allProducts": "Все товары",
"catalog": "Каталог", "catalog": "Каталог",
"brands": "Бренды", "brands": "Бренды",
"help": "Помощь", "help": "Помощь",
"rights": "Все права защищены." "rights": "Все права защищены."
}, },
"home": { "home": {
"hero": { "hero": {
"title": "Вневременная элегантность", "title": "Вневременная элегантность",
"text": "Откройте для себя нашу кураторскую коллекцию люксовой моды и аксессуаров, определяющих утонченный стиль" "text": "Откройте для себя нашу кураторскую коллекцию люксовой моды и аксессуаров, определяющих утонченный стиль"
}, },
"categories": { "categories": {
"title": "Покупки по категориям" "title": "Покупки по категориям"
}, },
"ad": { "ad": {
"title": "Весенняя коллекция", "title": "Весенняя коллекция",
"text1": "Скидки до 40%", "text1": "Скидки до 40%",
"text2": "Откройте для себя последние тренды в мире люксовой моды" "text2": "Откройте для себя последние тренды в мире люксовой моды"
}, },
"blog": { "blog": {
"title": "Из журнала" "title": "Из журнала"
} }
}, },
"forms": { "forms": {
"login": { "login": {
"title": "С возвращением", "title": "С возвращением",
"subtitle": "Войдите в свой аккаунт, чтобы продолжить", "subtitle": "Войдите в свой аккаунт, чтобы продолжить",
"forgot": "Забыли пароль?", "forgot": "Забыли пароль?",
"or": "или" "or": "или"
}, },
"register": { "register": {
"title": "Создать аккаунт", "title": "Создать аккаунт",
"subtitle": "Зарегистрируйтесь, чтобы начать ваше стильное путешествие", "subtitle": "Зарегистрируйтесь, чтобы начать ваше стильное путешествие",
"login": "Уже есть аккаунт?" "login": "Уже есть аккаунт?"
}, },
"reset": { "reset": {
"title": "Сброс пароля", "title": "Сброс пароля",
"subtitle": "Введите ваш email, и мы отправим ссылку для сброса пароля.", "subtitle": "Введите ваш email, и мы отправим ссылку для сброса пароля.",
"backToLogin": "Назад к входу" "backToLogin": "Назад к входу"
}, },
"newPassword": { "newPassword": {
"title": "Новый пароль" "title": "Новый пароль"
} }
}, },
"cards": { "cards": {
"product": { "product": {
"stock": "В наличии: " "stock": "В наличии: "
} }
}, },
"breadcrumbs": { "breadcrumbs": {
"home": "Главная", "home": "Главная",
"catalog": "Каталог", "catalog": "Каталог",
"contact": "Контакты", "contact": "Контакты",
"orders": "Заказы", "orders": "Заказы",
"wishlist": "Избранное", "wishlist": "Избранное",
"cart": "Корзина", "cart": "Корзина",
"settings": "Настройки", "settings": "Настройки",
"balance": "Баланс", "balance": "Баланс",
"promocodes": "Промокоды", "promocodes": "Промокоды",
"login": "Вход", "login": "Вход",
"register": "Регистрация", "register": "Регистрация",
"resetPassword": "Сброс пароля", "resetPassword": "Сброс пароля",
"newPassword": "Новый пароль", "newPassword": "Новый пароль",
"brands": "Бренды", "brands": "Бренды",
"blog": "Блог", "blog": "Блог",
"search": "Поиск", "search": "Поиск",
"categories": "Категории", "categories": "Категории",
"shop": "Магазин", "shop": "Магазин",
"policy": "Политика конфиденциальности", "policy": "Политика конфиденциальности",
"terms": "Условия использования", "terms": "Условия использования",
"return": "Политика возврата", "return": "Политика возврата",
"faq": "Часто задаваемые вопросы", "faq": "Часто задаваемые вопросы",
"shipping": "Информация о доставке", "shipping": "Информация о доставке",
"about": "О нас" "about": "О нас"
}, },
"contact": { "contact": {
"title": "Свяжитесь с нами", "title": "Свяжитесь с нами",
"text": "Мы будем рады услышать вас. Отправьте нам сообщение, и мы ответим как можно скорее.", "text": "Мы будем рады услышать вас. Отправьте нам сообщение, и мы ответим как можно скорее.",
"block": { "block": {
"title": "Давайте общаться", "title": "Давайте общаться",
"text": "Есть ли у вас вопросы о наших товарах, нужен совет по стилю или вы хотите сотрудничать с нами — мы здесь, чтобы помочь. Наша команда стремится предоставлять исключительный сервис и поддержку.", "text": "Есть ли у вас вопросы о наших товарах, нужен совет по стилю или вы хотите сотрудничать с нами — мы здесь, чтобы помочь. Наша команда стремится предоставлять исключительный сервис и поддержку.",
"email": "Написать нам", "email": "Написать нам",
"call": "Позвонить нам", "call": "Позвонить нам",
"hours": "Часы работы" "hours": "Часы работы"
}, },
"form": { "form": {
"title": "Отправить сообщение" "title": "Отправить сообщение"
} }
}, },
"store": { "store": {
"sorting": "Сортировать по:", "sorting": "Сортировать по:",
"filters": { "filters": {
"title": "Фильтры", "title": "Фильтры",
"apply": "Применить", "apply": "Применить",
"reset": "Сбросить", "reset": "Сбросить",
"all": "Все" "all": "Все"
} }
}, },
"search": { "search": {
"title": "Результаты поиска", "title": "Результаты поиска",
"products": "Товары", "products": "Товары",
"categories": "Категории", "categories": "Категории",
"brands": "Бренды", "brands": "Бренды",
"byRequest": "по запросу" "byRequest": "по запросу"
}, },
"product": { "product": {
"characteristics": "Все характеристики", "characteristics": "Все характеристики",
"similar": "Вам также может понравиться" "similar": "Вам также может понравиться"
}, },
"profile": { "profile": {
"settings": { "settings": {
"title": "Настройки", "title": "Настройки",
"joinData": "Дата регистрации", "joinData": "Дата регистрации",
"accountInfo": "Информация об аккаунте", "accountInfo": "Информация об аккаунте",
"copyReferral": "Скопировать реферальную ссылку", "copyReferral": "Скопировать реферальную ссылку",
"referralTooltip": "Вы получите реферальную ссылку после успешной покупки" "referralTooltip": "Вы получите реферальную ссылку после успешной покупки"
}, },
"orders": { "orders": {
"title": "Заказы", "title": "Заказы",
"chooseStatus": "Выберите статус", "chooseStatus": "Выберите статус",
"id": "№", "id": "№",
"price": "Цена", "price": "Цена",
"total": "Итого", "total": "Итого",
"empty": "Нет заказов по данным параметрам.", "empty": "Нет заказов по данным параметрам.",
"statuses": { "statuses": {
"all": "Все", "all": "Все",
"failed": "Ошибка", "failed": "Ошибка",
"payment": "Ожидает оплаты", "payment": "Ожидает оплаты",
"created": "Создан", "created": "Создан",
"delivering": "Доставляется", "delivering": "Доставляется",
"finished": "Завершен", "finished": "Завершен",
"momental": "Моментальный" "momental": "Моментальный"
}, },
"searchTooltip": "Введите номер заказа или название товара" "searchTooltip": "Введите номер заказа или название товара"
}, },
"wishlist": { "wishlist": {
"title": "Избранное", "title": "Избранное",
"total": "{quantity} товаров на сумму {amount}", "total": "{quantity} товаров на сумму {amount}",
"deleteTooltip": "Удалить всё из избранного", "deleteTooltip": "Удалить всё из избранного",
"empty": "Ваш список избранного пуст." "empty": "Ваш список избранного пуст."
}, },
"cart": { "cart": {
"title": "Корзина", "title": "Корзина",
"quantity": "Количество: ", "quantity": "Количество: ",
"total": "Итого", "total": "Итого",
"empty": "Ваша корзина пуста." "empty": "Ваша корзина пуста."
}, },
"balance": { "balance": {
"title": "Баланс" "title": "Баланс"
}, },
"promocodes": { "promocodes": {
"title": "Промокоды", "title": "Промокоды",
"until": "До", "until": "До",
"empty": "У вас нет промокодов." "empty": "У вас нет промокодов."
}, },
"logout": "Выйти" "logout": "Выйти"
}, },
"demo": { "demo": {
"settings": { "settings": {
"title": "Демо-настройки", "title": "Демо-настройки",
"ui": "Настройки интерфейса" "ui": "Настройки интерфейса"
}, },
"buttons": { "buttons": {
"reset": "Сбросить на умолчания", "reset": "Сбросить на умолчания",
"save": "Сохранить изменения", "save": "Сохранить изменения",
"generateCode": "Сгенерировать код для 'app.config.ts'" "generateCode": "Сгенерировать код для 'app.config.ts'"
}, },
"preview": { "preview": {
"text": "Замените объект UI в 'app.config.ts' на этот код" "text": "Замените объект UI в 'app.config.ts' на этот код"
}, },
"descriptions": { "descriptions": {
"showBreadcrumbs": "Показывать цепочку навигации на страницах.", "showBreadcrumbs": "Показывать цепочку навигации на страницах.",
"showSearchBar": "Показывать строку поиска в шапке сайта." "showSearchBar": "Показывать строку поиска в шапке сайта."
} }
}, },
"docs": { "docs": {
"faq": { "faq": {
"title": "Часто задаваемые вопросы" "title": "Часто задаваемые вопросы"
}, },
"shipping": { "shipping": {
"title": "Информация о доставке" "title": "Информация о доставке"
}, },
"return": { "return": {
"title": "Политика возврата" "title": "Политика возврата"
}, },
"policy": { "policy": {
"title": "Политика конфиденциальности" "title": "Политика конфиденциальности"
}, },
"terms": { "terms": {
"title": "Условия использования" "title": "Условия использования"
}, },
"about": { "about": {
"title": "О нас" "title": "О нас"
} }
}, },
"brands": { "brands": {
"title": "Люксовые бренды", "title": "Люксовые бренды",
"text": "Откройте для себя самые престижные мировые модные дома и люксовые бренды, подобранные для взыскательного вкуса." "text": "Откройте для себя самые престижные мировые модные дома и люксовые бренды, подобранные для взыскательного вкуса."
}, },
"catalog": { "catalog": {
"title": "Разнообразные категории", "title": "Разнообразные категории",
"text": "Откройте для себя самые престижные мировые модные дома и люксовые категории, подобранные для взыскательного вкуса." "text": "Откройте для себя самые престижные мировые модные дома и люксовые категории, подобранные для взыскательного вкуса."
}, },
"blog": { "blog": {
"title": "Модный журнал", "title": "Модный журнал",
"text": "Узнавайте о последних трендах, источниках вдохновения для стиля и модных инсайтах от нашей редакции." "text": "Узнавайте о последних трендах, источниках вдохновения для стиля и модных инсайтах от нашей редакции."
}, },
"cart": { "cart": {
"title": "Моя корзина", "title": "Моя корзина",
"items": "нет товаров | {count} товар | {count} товара | {count} товаров", "items": "нет товаров | {count} товар | {count} товара | {count} товаров",
"empty": "Ваша корзина пуста" "empty": "Ваша корзина пуста"
}, },
"wishlist": { "wishlist": {
"title": "Мои Избранные", "title": "Мои Избранные",
"items": "нет товаров | {count} товар | {count} товара | {count} товаров", "items": "нет товаров | {count} товар | {count} товара | {count} товаров",
"empty": "Список выших избранных пуст" "empty": "Список выших избранных пуст"
}, },
"shop": { "shop": {
"title": "Магазин", "title": "Магазин",
"text": "Откройте для себя нашу кураторскую коллекцию люксовой моды и аксессуаров, определяющих утонченный стиль" "text": "Откройте для себя нашу кураторскую коллекцию люксовой моды и аксессуаров, определяющих утонченный стиль"
} }
} }