first commit

This commit is contained in:
Bivekich
2025-06-26 06:59:59 +03:00
commit d44874775c
450 changed files with 76635 additions and 0 deletions

105
src/lib/apollo.ts Normal file
View File

@ -0,0 +1,105 @@
import { ApolloClient, InMemoryCache, createHttpLink, FetchPolicy } from '@apollo/client'
import { setContext } from '@apollo/client/link/context'
const graphqlUri = process.env.NEXT_PUBLIC_CMS_GRAPHQL_URL || 'http://localhost:3000/api/graphql';
console.log('Apollo Client: используется GraphQL URI:', graphqlUri);
const httpLink = createHttpLink({
uri: graphqlUri,
})
const authLink = setContext((_, { headers }) => {
// Получаем данные пользователя из localStorage только на клиенте
let token = null;
if (typeof window !== 'undefined') {
const userData = localStorage.getItem('userData');
console.log('Apollo Client: проверяем localStorage userData:', userData);
if (userData) {
try {
const user = JSON.parse(userData);
// Создаем токен в формате, который ожидает CMS
token = `client_${user.id}`;
console.log('Apollo Client: создан токен:', token);
console.log('Apollo Client: user data:', user);
console.log('Apollo Client: заголовки:', { authorization: `Bearer ${token}` });
} catch (error) {
console.error('Apollo Client: ошибка парсинга userData:', error);
localStorage.removeItem('userData');
localStorage.removeItem('authToken');
}
} else {
console.log('Apollo Client: userData не найден в localStorage');
}
}
return {
headers: {
...headers,
...(token && { authorization: `Bearer ${token}` }),
}
}
});
// Создаём кэш с правильными настройками
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
// Кэшируем изображения по artId
partsAPIMainImage: {
keyArgs: ['artId'],
},
// Кэшируем статьи по параметрам категории
partsAPIArticles: {
keyArgs: ['strId', 'carId', 'carType'],
},
// Кэшируем избранное
favorites: {
merge(existing = [], incoming: any[]) {
return incoming;
}
}
},
},
Mutation: {
fields: {
addToFavorites: {
merge: false,
},
removeFromFavorites: {
merge: false,
},
clearFavorites: {
merge: false,
}
}
}
},
});
export const apolloClient = new ApolloClient({
link: authLink.concat(httpLink),
cache,
defaultOptions: {
watchQuery: {
errorPolicy: 'all',
fetchPolicy: 'cache-first', // Сначала ищем в кэше
},
query: {
errorPolicy: 'all',
fetchPolicy: 'cache-first', // Сначала ищем в кэше
},
},
})
// Очищаем кэш только в режиме разработки при первой загрузке
if (typeof window !== 'undefined' && process.env.NODE_ENV === 'development') {
// Очищаем кэш только один раз при первой загрузке страницы
const cacheCleared = sessionStorage.getItem('apollo-cache-cleared');
if (!cacheCleared) {
apolloClient.clearStore().catch(console.error);
sessionStorage.setItem('apollo-cache-cleared', 'true');
console.log('Apollo Client: очистка кэша в режиме разработки');
}
}

View File

@ -0,0 +1,49 @@
import { gql } from '@apollo/client'
export const GET_FAVORITES = gql`
query GetFavorites {
favorites {
id
clientId
productId
offerKey
name
brand
article
price
currency
image
createdAt
}
}
`
export const ADD_TO_FAVORITES = gql`
mutation AddToFavorites($input: FavoriteInput!) {
addToFavorites(input: $input) {
id
clientId
productId
offerKey
name
brand
article
price
currency
image
createdAt
}
}
`
export const REMOVE_FROM_FAVORITES = gql`
mutation RemoveFromFavorites($id: ID!) {
removeFromFavorites(id: $id)
}
`
export const CLEAR_FAVORITES = gql`
mutation ClearFavorites {
clearFavorites
}
`

1544
src/lib/graphql.ts Normal file
View File

@ -0,0 +1,1544 @@
import { gql } from '@apollo/client'
export const CHECK_CLIENT_BY_PHONE = gql`
mutation CheckClientByPhone($phone: String!) {
checkClientByPhone(phone: $phone) {
exists
client {
id
clientNumber
name
phone
email
}
sessionId
}
}
`
export const SEND_SMS_CODE = gql`
mutation SendSMSCode($phone: String!, $sessionId: String) {
sendSMSCode(phone: $phone, sessionId: $sessionId) {
success
sessionId
code
}
}
`
export const VERIFY_CODE = gql`
mutation VerifyCode($phone: String!, $code: String!, $sessionId: String!) {
verifyCode(phone: $phone, code: $code, sessionId: $sessionId) {
success
client {
id
clientNumber
name
phone
email
}
token
}
}
`
export const REGISTER_NEW_CLIENT = gql`
mutation RegisterNewClient($phone: String!, $name: String!, $sessionId: String!) {
registerNewClient(phone: $phone, name: $name, sessionId: $sessionId) {
success
client {
id
clientNumber
name
phone
email
}
token
}
}
`
// Запросы для профиля пользователя
export const GET_CLIENT_ME = gql`
query GetClientMe {
clientMe {
id
name
email
phone
emailNotifications
smsNotifications
pushNotifications
legalEntities {
id
shortName
fullName
form
legalAddress
actualAddress
taxSystem
responsiblePhone
responsiblePosition
responsibleName
accountant
signatory
registrationReasonCode
ogrn
inn
vatPercent
bankDetails {
id
legalEntityId
name
accountNumber
bankName
bik
correspondentAccount
legalEntity {
id
shortName
inn
}
}
}
contracts {
id
contractNumber
contractDate
name
ourLegalEntity
clientLegalEntity
balance
currency
isActive
isDefault
contractType
relationship
paymentDelay
creditLimit
delayDays
fileUrl
createdAt
updatedAt
}
}
}
`
export const UPDATE_CLIENT_PERSONAL_DATA = gql`
mutation UpdateClientMe($input: ClientInput!) {
updateClientMe(input: $input) {
id
name
email
phone
emailNotifications
smsNotifications
pushNotifications
}
}
`
export const CREATE_CLIENT_LEGAL_ENTITY = gql`
mutation CreateClientLegalEntityMe($input: ClientLegalEntityInput!) {
createClientLegalEntityMe(input: $input) {
id
shortName
fullName
form
legalAddress
actualAddress
taxSystem
responsiblePhone
responsiblePosition
responsibleName
accountant
signatory
registrationReasonCode
ogrn
inn
vatPercent
bankDetails {
id
legalEntityId
name
accountNumber
bankName
bik
correspondentAccount
legalEntity {
id
shortName
inn
}
}
}
}
`
export const UPDATE_CLIENT_LEGAL_ENTITY = gql`
mutation UpdateClientLegalEntity($id: ID!, $input: ClientLegalEntityInput!) {
updateClientLegalEntity(id: $id, input: $input) {
id
shortName
fullName
form
legalAddress
actualAddress
taxSystem
responsiblePhone
responsiblePosition
responsibleName
accountant
signatory
registrationReasonCode
ogrn
inn
vatPercent
bankDetails {
id
legalEntityId
name
accountNumber
bankName
bik
correspondentAccount
legalEntity {
id
shortName
inn
}
}
}
}
`
export const DELETE_CLIENT_LEGAL_ENTITY = gql`
mutation DeleteClientLegalEntity($id: ID!) {
deleteClientLegalEntity(id: $id)
}
`
// Банковские реквизиты
export const CREATE_CLIENT_BANK_DETAILS = gql`
mutation CreateClientBankDetails($legalEntityId: ID!, $input: ClientBankDetailsInput!) {
createClientBankDetails(legalEntityId: $legalEntityId, input: $input) {
id
legalEntityId
name
accountNumber
bankName
bik
correspondentAccount
legalEntity {
id
shortName
inn
}
}
}
`
export const UPDATE_CLIENT_BANK_DETAILS = gql`
mutation UpdateClientBankDetails($id: ID!, $input: ClientBankDetailsInput!, $legalEntityId: ID) {
updateClientBankDetails(id: $id, input: $input, legalEntityId: $legalEntityId) {
id
legalEntityId
name
accountNumber
bankName
bik
correspondentAccount
legalEntity {
id
shortName
inn
}
}
}
`
export const DELETE_CLIENT_BANK_DETAILS = gql`
mutation DeleteClientBankDetails($id: ID!) {
deleteClientBankDetails(id: $id)
}
`
// Мутации для заказов и платежей
export const CREATE_ORDER = gql`
mutation CreateOrder($input: CreateOrderInput!) {
createOrder(input: $input) {
id
orderNumber
clientId
client {
id
name
email
phone
}
clientEmail
clientPhone
clientName
status
totalAmount
discountAmount
finalAmount
currency
items {
id
productId
product {
id
name
article
}
externalId
name
article
brand
price
quantity
totalPrice
}
deliveryAddress
comment
createdAt
updatedAt
}
}
`
export const CREATE_PAYMENT = gql`
mutation CreatePayment($input: CreatePaymentInput!) {
createPayment(input: $input) {
payment {
id
orderId
yookassaPaymentId
status
amount
currency
description
confirmationUrl
createdAt
}
confirmationUrl
}
}
`
export const GET_ORDERS = gql`
query GetOrders($clientId: String, $status: OrderStatus, $search: String, $limit: Int, $offset: Int) {
orders(clientId: $clientId, status: $status, search: $search, limit: $limit, offset: $offset) {
orders {
id
orderNumber
clientId
client {
id
name
email
phone
}
clientEmail
clientPhone
clientName
status
totalAmount
discountAmount
finalAmount
currency
items {
id
productId
product {
id
name
article
}
externalId
name
article
brand
price
quantity
totalPrice
}
deliveryAddress
comment
createdAt
updatedAt
payments {
id
yookassaPaymentId
status
amount
currency
description
confirmationUrl
createdAt
updatedAt
}
}
total
hasMore
}
}
`
// Laximo интеграция
export const GET_LAXIMO_BRANDS = gql`
query GetLaximoBrands {
laximoBrands {
brand
code
icon
name
supportdetailapplicability
supportparameteridentification2
supportquickgroups
supportvinsearch
supportframesearch
vinexample
frameexample
features {
name
example
}
extensions {
operations {
description
kind
name
fields {
description
example
name
pattern
}
}
}
}
}
`
// Новые запросы для поиска автомобилей
export const GET_LAXIMO_CATALOG_INFO = gql`
query GetLaximoCatalogInfo($catalogCode: String!) {
laximoCatalogInfo(catalogCode: $catalogCode) {
brand
code
icon
name
supportdetailapplicability
supportparameteridentification2
supportquickgroups
supportvinsearch
vinexample
features {
name
example
}
permissions
}
}
`
export const GET_LAXIMO_WIZARD2 = gql`
query GetLaximoWizard2($catalogCode: String!, $ssd: String) {
laximoWizard2(catalogCode: $catalogCode, ssd: $ssd) {
allowlistvehicles
automatic
conditionid
determined
name
type
options {
key
value
}
}
}
`
export const FIND_LAXIMO_VEHICLE = gql`
query FindLaximoVehicle($catalogCode: String!, $vin: String!) {
laximoFindVehicle(catalogCode: $catalogCode, vin: $vin) {
vehicleid
name
brand
catalog
model
modification
year
bodytype
engine
notes
ssd
transmission
date
manufactured
framecolor
trimcolor
engine_info
engineno
market
prodRange
prodPeriod
destinationregion
creationregion
datefrom
dateto
modelyearfrom
modelyearto
options
description
grade
}
}
`;
export const FIND_LAXIMO_VEHICLE_GLOBAL = gql`
query FindLaximoVehicleGlobal($vin: String!) {
laximoFindVehicleGlobal(vin: $vin) {
vehicleid
name
brand
catalog
model
modification
year
bodytype
engine
notes
ssd
transmission
date
manufactured
framecolor
trimcolor
engine_info
engineno
market
prodRange
prodPeriod
destinationregion
creationregion
datefrom
dateto
modelyearfrom
modelyearto
options
description
grade
}
}
`;
export const FIND_LAXIMO_VEHICLE_BY_WIZARD = gql`
query FindLaximoVehicleByWizard($catalogCode: String!, $ssd: String!) {
laximoFindVehicleByWizard(catalogCode: $catalogCode, ssd: $ssd) {
vehicleid
brand
model
modification
year
bodytype
engine
notes
ssd
}
}
`;
export const FIND_LAXIMO_VEHICLE_BY_PLATE = gql`
query FindLaximoVehicleByPlate($catalogCode: String!, $plateNumber: String!) {
laximoFindVehicleByPlate(catalogCode: $catalogCode, plateNumber: $plateNumber) {
vehicleid
name
brand
catalog
model
modification
year
bodytype
engine
notes
ssd
transmission
date
manufactured
framecolor
trimcolor
engine_info
engineno
market
prodRange
prodPeriod
destinationregion
creationregion
datefrom
dateto
modelyearfrom
modelyearto
options
description
grade
}
}
`;
export const FIND_LAXIMO_VEHICLE_BY_PLATE_GLOBAL = gql`
query FindLaximoVehicleByPlateGlobal($plateNumber: String!) {
laximoFindVehicleByPlateGlobal(plateNumber: $plateNumber) {
vehicleid
name
brand
catalog
model
modification
year
bodytype
engine
notes
ssd
transmission
date
manufactured
framecolor
trimcolor
engine_info
engineno
market
prodRange
prodPeriod
destinationregion
creationregion
datefrom
dateto
modelyearfrom
modelyearto
options
description
grade
}
}
`;
export const FIND_LAXIMO_PART_REFERENCES = gql`
query FindLaximoPartReferences($partNumber: String!) {
laximoFindPartReferences(partNumber: $partNumber)
}
`;
export const FIND_LAXIMO_APPLICABLE_VEHICLES = gql`
query FindLaximoApplicableVehicles($catalogCode: String!, $partNumber: String!) {
laximoFindApplicableVehicles(catalogCode: $catalogCode, partNumber: $partNumber) {
vehicleid
name
brand
catalog
model
modification
year
bodytype
engine
notes
ssd
transmission
date
manufactured
framecolor
trimcolor
engine_info
engineno
market
prodRange
prodPeriod
destinationregion
creationregion
datefrom
dateto
modelyearfrom
modelyearto
options
description
grade
}
}
`;
export const FIND_LAXIMO_VEHICLES_BY_PART_NUMBER = gql`
query FindLaximoVehiclesByPartNumber($partNumber: String!) {
laximoFindVehiclesByPartNumber(partNumber: $partNumber) {
partNumber
totalVehicles
catalogs {
catalogCode
catalogName
brand
vehicleCount
vehicles {
vehicleid
name
brand
catalog
model
modification
year
bodytype
engine
notes
ssd
}
}
}
}
`;
export const GET_LAXIMO_VEHICLE_INFO = gql`
query GetLaximoVehicleInfo($catalogCode: String!, $vehicleId: String!, $ssd: String, $localized: Boolean!) {
laximoVehicleInfo(catalogCode: $catalogCode, vehicleId: $vehicleId, ssd: $ssd, localized: $localized) {
vehicleid
name
ssd
brand
catalog
attributes {
key
name
value
}
}
}
`
export const GET_LAXIMO_QUICK_GROUPS = gql`
query GetLaximoQuickGroups($catalogCode: String!, $vehicleId: String!, $ssd: String) {
laximoQuickGroups(catalogCode: $catalogCode, vehicleId: $vehicleId, ssd: $ssd) {
quickgroupid
name
link
children {
quickgroupid
name
link
children {
quickgroupid
name
link
}
}
}
}
`
export const GET_LAXIMO_QUICK_GROUPS_WITH_XML = gql`
query GetLaximoQuickGroupsWithXML($catalogCode: String!, $vehicleId: String!, $ssd: String) {
laximoQuickGroupsWithXML(catalogCode: $catalogCode, vehicleId: $vehicleId, ssd: $ssd) {
groups {
quickgroupid
name
link
code
imageurl
largeimageurl
children {
quickgroupid
name
link
code
imageurl
largeimageurl
children {
quickgroupid
name
link
code
imageurl
largeimageurl
}
}
}
rawXML
}
}
`
export const GET_LAXIMO_CATEGORIES = gql`
query GetLaximoCategories($catalogCode: String!, $vehicleId: String, $ssd: String) {
laximoCategories(catalogCode: $catalogCode, vehicleId: $vehicleId, ssd: $ssd) {
quickgroupid
name
link
children {
quickgroupid
name
link
children {
quickgroupid
name
link
}
}
}
}
`
export const GET_LAXIMO_UNITS = gql`
query GetLaximoUnits($catalogCode: String!, $vehicleId: String, $ssd: String, $categoryId: String) {
laximoUnits(catalogCode: $catalogCode, vehicleId: $vehicleId, ssd: $ssd, categoryId: $categoryId) {
quickgroupid
name
link
code
imageurl
largeimageurl
children {
quickgroupid
name
link
code
imageurl
largeimageurl
children {
quickgroupid
name
link
code
imageurl
largeimageurl
}
}
}
}
`
export const GET_LAXIMO_QUICK_DETAIL = gql`
query GetLaximoQuickDetail($catalogCode: String!, $vehicleId: String!, $quickGroupId: String!, $ssd: String!) {
laximoQuickDetail(catalogCode: $catalogCode, vehicleId: $vehicleId, quickGroupId: $quickGroupId, ssd: $ssd) {
quickgroupid
name
units {
unitid
name
code
description
imageurl
largeimageurl
details {
detailid
name
oem
brand
description
applicablemodels
note
attributes {
key
name
value
}
}
}
}
}
`
export const SEARCH_LAXIMO_OEM = gql`
query SearchLaximoOEM($catalogCode: String!, $vehicleId: String!, $oemNumber: String!, $ssd: String!) {
laximoOEMSearch(catalogCode: $catalogCode, vehicleId: $vehicleId, oemNumber: $oemNumber, ssd: $ssd) {
oemNumber
categories {
categoryid
name
units {
unitid
name
code
imageurl
details {
detailid
name
oem
brand
amount
range
attributes {
key
name
value
}
}
}
}
}
}
`
export const SEARCH_LAXIMO_FULLTEXT = gql`
query SearchLaximoFulltext($catalogCode: String!, $vehicleId: String!, $searchQuery: String!, $ssd: String!) {
laximoFulltextSearch(catalogCode: $catalogCode, vehicleId: $vehicleId, searchQuery: $searchQuery, ssd: $ssd) {
searchQuery
details {
oem
name
brand
description
}
}
}
`
export const TEST_LAXIMO_OEM = gql`
query TestLaximoOEM($catalogCode: String!, $vehicleId: String!, $oemNumber: String!, $ssd: String!) {
laximoOEMSearch(catalogCode: $catalogCode, vehicleId: $vehicleId, oemNumber: $oemNumber, ssd: $ssd) {
oemNumber
}
}
`
export const DOC_FIND_OEM = gql`
query DocFindOEM($oemNumber: String!, $brand: String, $replacementTypes: String) {
laximoDocFindOEM(oemNumber: $oemNumber, brand: $brand, replacementTypes: $replacementTypes) {
details {
detailid
formattedoem
manufacturer
manufacturerid
name
oem
volume
weight
replacements {
type
way
replacementid
rate
detail {
detailid
formattedoem
manufacturer
manufacturerid
name
oem
weight
icon
}
}
}
}
}
`
// Запросы для работы с деталями узлов
export const GET_LAXIMO_UNIT_INFO = gql`
query GetLaximoUnitInfo($catalogCode: String!, $vehicleId: String!, $unitId: String!, $ssd: String!) {
laximoUnitInfo(catalogCode: $catalogCode, vehicleId: $vehicleId, unitId: $unitId, ssd: $ssd) {
unitid
name
code
description
imageurl
largeimageurl
attributes {
key
name
value
}
}
}
`
export const GET_LAXIMO_UNIT_DETAILS = gql`
query GetLaximoUnitDetails($catalogCode: String!, $vehicleId: String!, $unitId: String!, $ssd: String!) {
laximoUnitDetails(catalogCode: $catalogCode, vehicleId: $vehicleId, unitId: $unitId, ssd: $ssd) {
detailid
name
oem
brand
codeonimage
code
note
filter
price
availability
description
applicablemodels
attributes {
key
name
value
}
}
}
`
export const GET_LAXIMO_UNIT_IMAGE_MAP = gql`
query GetLaximoUnitImageMap($catalogCode: String!, $vehicleId: String!, $unitId: String!, $ssd: String!) {
laximoUnitImageMap(catalogCode: $catalogCode, vehicleId: $vehicleId, unitId: $unitId, ssd: $ssd) {
unitid
imageurl
largeimageurl
coordinates {
detailid
codeonimage
x
y
width
height
shape
}
}
}
`
export const SEARCH_PRODUCT_OFFERS = gql`
query SearchProductOffers($articleNumber: String!, $brand: String!) {
searchProductOffers(articleNumber: $articleNumber, brand: $brand) {
articleNumber
brand
name
description
hasInternalStock
totalOffers
images {
id
url
alt
order
}
characteristics {
id
value
characteristic {
id
name
}
}
partsIndexImages {
url
alt
order
source
}
partsIndexCharacteristics {
name
value
source
}
internalOffers {
id
productId
price
quantity
warehouse
deliveryDays
available
rating
supplier
}
externalOffers {
offerKey
brand
code
name
price
currency
deliveryTime
deliveryTimeMax
quantity
warehouse
supplier
comment
weight
volume
canPurchase
}
analogs {
brand
articleNumber
name
type
}
}
}
`
export const GET_ANALOG_OFFERS = gql`
query GetAnalogOffers($analogs: [AnalogOfferInput!]!) {
getAnalogOffers(analogs: $analogs) {
brand
articleNumber
name
type
internalOffers {
id
productId
price
quantity
warehouse
deliveryDays
available
rating
supplier
}
externalOffers {
offerKey
brand
code
name
price
currency
deliveryTime
deliveryTimeMax
quantity
warehouse
warehouseName
rejects
supplier
canPurchase
}
}
}
`
export const PARTS_INDEX_SEARCH_BY_ARTICLE = gql`
query PartsIndexSearchByArticle($articleNumber: String!, $brandName: String!, $lang: String) {
partsIndexSearchByArticle(articleNumber: $articleNumber, brandName: $brandName, lang: $lang) {
id
catalog {
id
name
}
name {
id
name
}
originalName
code
barcodes
brand {
id
name
}
description
parameters {
id
name
params {
id
code
title
type
values {
id
value
}
}
}
images
links {
partId
code
brand {
id
name
}
parameters {
id
name
unit
value
}
}
}
}
`
// PartsAPI категории
export const GET_PARTSAPI_CATEGORIES = gql`
query GetPartsAPICategories($carId: Int!, $carType: CarType) {
partsAPICategories(carId: $carId, carType: $carType) {
id
name
level
parentId
children {
id
name
level
parentId
children {
id
name
level
parentId
}
}
}
}
`
export const GET_PARTSAPI_TOP_LEVEL_CATEGORIES = gql`
query GetPartsAPITopLevelCategories($carId: Int!, $carType: CarType) {
partsAPITopLevelCategories(carId: $carId, carType: $carType) {
id
name
level
parentId
}
}
`
export const GET_PARTSAPI_ARTICLES = gql`
query GetPartsAPIArticles($strId: Int!, $carId: Int!, $carType: CarType) {
partsAPIArticles(strId: $strId, carId: $carId, carType: $carType) {
supBrand
supId
productGroup
ptId
artSupBrand
artArticleNr
artId
}
}
`
export const GET_PARTSAPI_MEDIA = gql`
query GetPartsAPIMedia($artId: String!, $lang: Int) {
partsAPIMedia(artId: $artId, lang: $lang) {
artMediaType
artMediaSource
artMediaSupId
artMediaKind
imageUrl
}
}
`;
export const GET_PARTSAPI_MAIN_IMAGE = gql`
query GetPartsAPIMainImage($artId: String!) {
partsAPIMainImage(artId: $artId)
}
`
// PartsIndex категории автотоваров
export const GET_PARTSINDEX_CATEGORIES = gql`
query GetPartsIndexCategories($lang: String) {
partsIndexCategoriesWithGroups(lang: $lang) {
id
name
image
groups {
id
name
image
subgroups {
id
name
image
entityNames {
id
name
}
}
entityNames {
id
name
}
}
}
}
`;
// Новый запрос для получения товаров каталога PartsIndex
export const GET_PARTSINDEX_CATALOG_ENTITIES = gql`
query GetPartsIndexCatalogEntities(
$catalogId: String!
$groupId: String!
$lang: String
$limit: Int
$page: Int
$q: String
$engineId: String
$generationId: String
$params: String
) {
partsIndexCatalogEntities(
catalogId: $catalogId
groupId: $groupId
lang: $lang
limit: $limit
page: $page
q: $q
engineId: $engineId
generationId: $generationId
params: $params
) {
pagination {
limit
page {
prev
current
next
}
}
list {
id
name {
id
name
}
originalName
code
brand {
id
name
}
parameters {
id
code
title
type
values {
id
value
}
}
images
}
catalog {
id
name
image
}
subgroup {
id
name
}
}
}
`;
// Запрос для получения параметров фильтрации PartsIndex
export const GET_PARTSINDEX_CATALOG_PARAMS = gql`
query GetPartsIndexCatalogParams(
$catalogId: String!
$groupId: String!
$lang: String
$engineId: String
$generationId: String
$params: String
$q: String
) {
partsIndexCatalogParams(
catalogId: $catalogId
groupId: $groupId
lang: $lang
engineId: $engineId
generationId: $generationId
params: $params
q: $q
) {
list {
id
code
name
isGeneral
type
values {
value
title
available
selected
}
}
paramsQuery
}
}
`;
// Query для получения истории поиска запчастей
export const GET_PARTS_SEARCH_HISTORY = gql`
query GetPartsSearchHistory {
partsSearchHistory {
id
searchQuery
searchType
brand
articleNumber
vehicleInfo {
brand
model
year
}
createdAt
}
}
`;
// Мутации для адресов доставки
export const CREATE_CLIENT_DELIVERY_ADDRESS = gql`
mutation CreateClientDeliveryAddress($input: ClientDeliveryAddressInput!) {
createClientDeliveryAddressMe(input: $input) {
id
name
address
deliveryType
comment
entrance
floor
apartment
intercom
deliveryTime
contactPhone
createdAt
updatedAt
}
}
`
export const UPDATE_CLIENT_DELIVERY_ADDRESS = gql`
mutation UpdateClientDeliveryAddress($id: ID!, $input: ClientDeliveryAddressInput!) {
updateClientDeliveryAddressMe(id: $id, input: $input) {
id
name
address
deliveryType
comment
entrance
floor
apartment
intercom
deliveryTime
contactPhone
createdAt
updatedAt
}
}
`
export const DELETE_CLIENT_DELIVERY_ADDRESS = gql`
mutation DeleteClientDeliveryAddress($id: ID!) {
deleteClientDeliveryAddressMe(id: $id)
}
`
// Запросы для адресов доставки
export const GET_CLIENT_DELIVERY_ADDRESSES = gql`
query GetClientDeliveryAddresses {
clientMe {
id
deliveryAddresses {
id
name
address
deliveryType
comment
entrance
floor
apartment
intercom
deliveryTime
contactPhone
createdAt
updatedAt
}
}
}
`
// Автокомплит адресов
export const GET_ADDRESS_SUGGESTIONS = gql`
query GetAddressSuggestions($query: String!) {
addressSuggestions(query: $query)
}
`
export const UPDATE_CONTRACT_BALANCE = gql`
mutation UpdateContractBalance($contractId: ID!, $amount: Float!, $comment: String) {
updateContractBalance(contractId: $contractId, amount: $amount, comment: $comment) {
id
balance
updatedAt
}
}
`
export const CREATE_BALANCE_INVOICE = gql`
mutation CreateBalanceInvoice($contractId: String!, $amount: Float!) {
createBalanceInvoice(contractId: $contractId, amount: $amount) {
id
invoiceNumber
amount
status
createdAt
}
}
`
export const GET_INVOICE_PDF = gql`
mutation GetInvoicePDF($invoiceId: String!) {
getInvoicePDF(invoiceId: $invoiceId) {
success
pdfBase64
filename
error
}
}
`
// Мутация для получения офферов доставки
export const GET_DELIVERY_OFFERS = gql`
mutation GetDeliveryOffers($input: DeliveryOffersInput!) {
getDeliveryOffers(input: $input) {
success
message
error
offers {
id
name
deliveryDate
deliveryTime
cost
description
type
expiresAt
}
}
}
`
export const GET_BRANDS_BY_CODE = gql`
query GetBrandsByCode($code: String!) {
getBrandsByCode(code: $code) {
success
error
brands {
brand
code
name
}
}
}
`
// Новый запрос для получения рекомендуемых товаров из категории с AutoEuro предложениями
export const GET_CATEGORY_PRODUCTS_WITH_OFFERS = gql`
query GetCategoryProductsWithOffers($categoryName: String!, $excludeArticle: String!, $excludeBrand: String!, $limit: Int) {
getCategoryProductsWithOffers(categoryName: $categoryName, excludeArticle: $excludeArticle, excludeBrand: $excludeBrand, limit: $limit) {
articleNumber
brand
name
artId
minPrice
hasOffers
}
}
`

186
src/lib/graphql/garage.ts Normal file
View File

@ -0,0 +1,186 @@
import { gql } from '@apollo/client';
// Queries
export const GET_USER_VEHICLES = gql`
query GetUserVehicles {
userVehicles {
id
name
vin
frame
licensePlate
brand
model
modification
year
mileage
comment
createdAt
updatedAt
}
}
`;
export const GET_VEHICLE_SEARCH_HISTORY = gql`
query GetVehicleSearchHistory {
vehicleSearchHistory {
id
vin
brand
model
searchDate
searchQuery
}
}
`;
export const SEARCH_VEHICLE_BY_VIN = gql`
query SearchVehicleByVin($vin: String!) {
searchVehicleByVin(vin: $vin) {
vin
brand
model
modification
year
bodyType
engine
transmission
drive
fuel
}
}
`;
// Mutations
export const CREATE_USER_VEHICLE = gql`
mutation CreateUserVehicle($input: UserVehicleInput!) {
createUserVehicle(input: $input) {
id
name
vin
frame
licensePlate
brand
model
modification
year
mileage
comment
createdAt
}
}
`;
export const UPDATE_USER_VEHICLE = gql`
mutation UpdateUserVehicle($id: ID!, $input: UserVehicleInput!) {
updateUserVehicle(id: $id, input: $input) {
id
name
vin
frame
licensePlate
brand
model
modification
year
mileage
comment
updatedAt
}
}
`;
export const DELETE_USER_VEHICLE = gql`
mutation DeleteUserVehicle($id: ID!) {
deleteUserVehicle(id: $id)
}
`;
export const ADD_VEHICLE_FROM_SEARCH = gql`
mutation AddVehicleFromSearch($vin: String!, $comment: String) {
addVehicleFromSearch(vin: $vin, comment: $comment) {
id
name
vin
brand
model
comment
createdAt
}
}
`;
export const DELETE_SEARCH_HISTORY_ITEM = gql`
mutation DeleteSearchHistoryItem($id: ID!) {
deleteSearchHistoryItem(id: $id)
}
`;
export const CREATE_VEHICLE_FROM_VIN = gql`
mutation CreateVehicleFromVin($vin: String!, $comment: String) {
createVehicleFromVin(vin: $vin, comment: $comment) {
id
name
vin
brand
model
modification
year
mileage
comment
createdAt
}
}
`;
// Types
export interface UserVehicle {
id: string;
name: string;
vin?: string;
frame?: string;
licensePlate?: string;
brand?: string;
model?: string;
modification?: string;
year?: number;
mileage?: number;
comment?: string;
createdAt: string;
updatedAt?: string;
}
export interface UserVehicleInput {
name: string;
vin?: string;
frame?: string;
licensePlate?: string;
brand?: string;
model?: string;
modification?: string;
year?: number;
mileage?: number;
comment?: string;
}
export interface VehicleSearchHistory {
id: string;
vin: string;
brand?: string;
model?: string;
searchDate: string;
searchQuery?: string;
}
export interface VehicleSearchResult {
vin: string;
brand?: string;
model?: string;
modification?: string;
year?: number;
bodyType?: string;
engine?: string;
transmission?: string;
drive?: string;
fuel?: string;
}

219
src/lib/graphql/laximo.ts Normal file
View File

@ -0,0 +1,219 @@
import { gql } from '@apollo/client';
// Запросы для поиска автомобиля
export const GET_LAXIMO_BRANDS = gql`
query GetLaximoBrands {
laximoBrands {
code
name
brand
icon
supportdetailapplicability
supportparameteridentification2
supportquickgroups
supportvinsearch
supportframesearch
vinexample
frameexample
features {
name
example
}
}
}
`;
export const GET_LAXIMO_CATALOG_INFO = gql`
query GetLaximoCatalogInfo($catalogCode: String!) {
laximoCatalogInfo(catalogCode: $catalogCode) {
code
brand
name
features {
name
example
}
}
}
`;
export const GET_LAXIMO_VEHICLE_INFO = gql`
query GetLaximoVehicleInfo($catalogCode: String!, $vehicleId: String!, $ssd: String) {
laximoVehicleInfo(catalogCode: $catalogCode, vehicleId: $vehicleId, ssd: $ssd) {
vehicleid
name
ssd
brand
catalog
attributes {
key
name
value
}
}
}
`;
// Запросы для поиска запчастей
export const GET_LAXIMO_CATEGORIES = gql`
query GetLaximoCategories($catalogCode: String!, $vehicleId: String, $ssd: String) {
laximoCategories(catalogCode: $catalogCode, vehicleId: $vehicleId, ssd: $ssd) {
quickgroupid
name
link
children {
quickgroupid
name
link
children {
quickgroupid
name
link
}
}
}
}
`;
export const GET_LAXIMO_UNITS = gql`
query GetLaximoUnits($catalogCode: String!, $vehicleId: String, $ssd: String, $categoryId: String) {
laximoUnits(catalogCode: $catalogCode, vehicleId: $vehicleId, ssd: $ssd, categoryId: $categoryId) {
quickgroupid
name
link
code
imageurl
largeimageurl
children {
quickgroupid
name
link
code
imageurl
largeimageurl
children {
quickgroupid
name
link
code
imageurl
largeimageurl
}
}
}
}
`;
export const GET_LAXIMO_QUICK_GROUPS = gql`
query GetLaximoQuickGroups($catalogCode: String!, $vehicleId: String!, $ssd: String) {
laximoQuickGroups(catalogCode: $catalogCode, vehicleId: $vehicleId, ssd: $ssd) {
quickgroupid
name
link
children {
quickgroupid
name
link
children {
quickgroupid
name
link
}
}
}
}
`;
export const GET_LAXIMO_QUICK_DETAIL = gql`
query GetLaximoQuickDetail($catalogCode: String!, $vehicleId: String!, $quickGroupId: String!, $ssd: String!) {
laximoQuickDetail(catalogCode: $catalogCode, vehicleId: $vehicleId, quickGroupId: $quickGroupId, ssd: $ssd) {
quickgroupid
name
units {
unitid
name
code
imageurl
largeimageurl
details {
detailid
name
oem
formattedoem
parttype
filter
note
attributes {
key
name
value
}
}
}
}
}
`;
// Поиск по OEM и тексту
export const SEARCH_LAXIMO_OEM = gql`
query SearchLaximoOEM($catalogCode: String!, $vehicleId: String!, $oemNumber: String!, $ssd: String!) {
laximoOEMSearch(catalogCode: $catalogCode, vehicleId: $vehicleId, oemNumber: $oemNumber, ssd: $ssd) {
categories {
categoryid
name
units {
unitid
name
details {
codeonimage
code
name
note
filter
oem
price
availability
}
}
}
}
}
`;
export const SEARCH_LAXIMO_FULLTEXT = gql`
query SearchLaximoFulltext($catalogCode: String!, $vehicleId: String!, $searchText: String!, $ssd: String!) {
laximoFulltextSearch(catalogCode: $catalogCode, vehicleId: $vehicleId, searchText: $searchText, ssd: $ssd) {
details {
codeonimage
code
name
note
filter
oem
price
availability
}
}
}
`;
export const GET_LAXIMO_FULLTEXT_SEARCH = gql`
query GetLaximoFulltextSearch($catalogCode: String!, $vehicleId: String!, $searchQuery: String!, $ssd: String!) {
laximoFulltextSearch(catalogCode: $catalogCode, vehicleId: $vehicleId, searchQuery: $searchQuery, ssd: $ssd) {
details {
detailid
name
oem
formattedoem
parttype
filter
note
attributes {
key
name
value
}
}
}
}
`;

View File

@ -0,0 +1,78 @@
import { gql } from '@apollo/client';
// Запросы для истории поиска запчастей
export const GET_PARTS_SEARCH_HISTORY = gql`
query GetPartsSearchHistory($limit: Int, $offset: Int) {
partsSearchHistory(limit: $limit, offset: $offset) {
items {
id
searchQuery
searchType
brand
articleNumber
vehicleInfo {
brand
model
year
}
resultCount
createdAt
}
total
hasMore
}
}
`;
export const DELETE_SEARCH_HISTORY_ITEM = gql`
mutation DeletePartsSearchHistoryItem($id: ID!) {
deletePartsSearchHistoryItem(id: $id)
}
`;
export const CLEAR_SEARCH_HISTORY = gql`
mutation ClearPartsSearchHistory {
clearPartsSearchHistory
}
`;
export const CREATE_SEARCH_HISTORY_ITEM = gql`
mutation CreatePartsSearchHistoryItem($input: PartsSearchHistoryInput!) {
createPartsSearchHistoryItem(input: $input) {
id
searchQuery
searchType
brand
articleNumber
vehicleInfo {
brand
model
year
}
resultCount
createdAt
}
}
`;
// Типы для TypeScript
export interface PartsSearchHistoryItem {
id: string;
searchQuery: string;
searchType: 'TEXT' | 'ARTICLE' | 'OEM' | 'VIN' | 'PLATE' | 'WIZARD' | 'PART_VEHICLES';
brand?: string;
articleNumber?: string;
vehicleInfo?: {
brand?: string;
model?: string;
year?: number;
};
resultCount: number;
createdAt: string;
}
export interface PartsSearchHistoryResponse {
items: PartsSearchHistoryItem[];
total: number;
hasMore: boolean;
}

View File

@ -0,0 +1,168 @@
import { gql } from '@apollo/client';
// Фрагмент для ПВЗ
export const YANDEX_PICKUP_POINT_FRAGMENT = gql`
fragment YandexPickupPointFragment on YandexPickupPoint {
id
name
address {
fullAddress
locality
street
house
building
apartment
postalCode
comment
}
contact {
phone
email
firstName
lastName
}
position {
latitude
longitude
}
schedule {
restrictions {
days
timeFrom {
hours
minutes
}
timeTo {
hours
minutes
}
}
timeZone
}
type
paymentMethods
instruction
isDarkStore
isMarketPartner
isPostOffice
isYandexBranded
formattedSchedule
typeLabel
}
`;
// Запрос для определения местоположения
export const YANDEX_DETECT_LOCATION = gql`
query YandexDetectLocation($location: String!) {
yandexDetectLocation(location: $location) {
address
geoId
}
}
`;
// Запрос для получения всех ПВЗ с фильтрами
export const YANDEX_PICKUP_POINTS = gql`
${YANDEX_PICKUP_POINT_FRAGMENT}
query YandexPickupPoints($filters: YandexPickupPointFilters) {
yandexPickupPoints(filters: $filters) {
...YandexPickupPointFragment
}
}
`;
// Запрос для получения ПВЗ по городу
export const YANDEX_PICKUP_POINTS_BY_CITY = gql`
${YANDEX_PICKUP_POINT_FRAGMENT}
query YandexPickupPointsByCity($cityName: String!) {
yandexPickupPointsByCity(cityName: $cityName) {
...YandexPickupPointFragment
}
}
`;
// Запрос для получения ПВЗ по координатам
export const YANDEX_PICKUP_POINTS_BY_COORDINATES = gql`
${YANDEX_PICKUP_POINT_FRAGMENT}
query YandexPickupPointsByCoordinates($latitude: Float!, $longitude: Float!, $radiusKm: Float) {
yandexPickupPointsByCoordinates(latitude: $latitude, longitude: $longitude, radiusKm: $radiusKm) {
...YandexPickupPointFragment
}
}
`;
// Типы для TypeScript
export interface YandexLocationVariant {
address: string;
geoId: number;
}
export interface YandexPickupPointAddress {
fullAddress: string;
locality?: string;
street?: string;
house?: string;
building?: string;
apartment?: string;
postalCode?: string;
comment?: string;
}
export interface YandexPickupPointContact {
phone: string;
email?: string;
firstName?: string;
lastName?: string;
}
export interface YandexPickupPointPosition {
latitude: number;
longitude: number;
}
export interface YandexPickupPointScheduleTime {
hours: number;
minutes: number;
}
export interface YandexPickupPointScheduleRestriction {
days: number[];
timeFrom: YandexPickupPointScheduleTime;
timeTo: YandexPickupPointScheduleTime;
}
export interface YandexPickupPointSchedule {
restrictions: YandexPickupPointScheduleRestriction[];
timeZone: number;
}
export type YandexPickupPointType = 'pickup_point' | 'terminal' | 'post_office' | 'sorting_center';
export type YandexPaymentMethod = 'already_paid' | 'card_on_receipt';
export interface YandexPickupPoint {
id: string;
name: string;
address: YandexPickupPointAddress;
contact: YandexPickupPointContact;
position: YandexPickupPointPosition;
schedule: YandexPickupPointSchedule;
type: YandexPickupPointType;
paymentMethods: YandexPaymentMethod[];
instruction?: string;
isDarkStore: boolean;
isMarketPartner: boolean;
isPostOffice: boolean;
isYandexBranded: boolean;
formattedSchedule: string;
typeLabel: string;
}
export interface YandexPickupPointFilters {
geoId?: number;
latitude?: number;
longitude?: number;
radiusKm?: number;
isYandexBranded?: boolean;
isPostOffice?: boolean;
type?: YandexPickupPointType;
}

View File

@ -0,0 +1,162 @@
import { LaximoQuickGroup } from '@/types/laximo';
// Предопределенные категории, аналогичные демо Laximo
export const PREDEFINED_CATEGORIES: LaximoQuickGroup[] = [
{
quickgroupid: 'to',
name: 'Детали для ТО',
link: true,
children: []
},
{
quickgroupid: 'engine',
name: 'Двигатель',
link: true,
children: []
},
{
quickgroupid: 'fuel',
name: 'Топливная система',
link: true,
children: []
},
{
quickgroupid: 'cooling',
name: 'Система охлаждения',
link: true,
children: []
},
{
quickgroupid: 'exhaust',
name: 'Система выпуска',
link: true,
children: []
},
{
quickgroupid: 'transmission',
name: 'Трансмиссия',
link: true,
children: []
},
{
quickgroupid: 'chassis',
name: 'Ходовая часть',
link: true,
children: []
},
{
quickgroupid: 'steering',
name: 'Рулевое управление',
link: true,
children: []
},
{
quickgroupid: 'brakes',
name: 'Тормозная система',
link: true,
children: []
},
{
quickgroupid: 'electrical',
name: 'Электрооборудование',
link: true,
children: []
},
{
quickgroupid: 'climate',
name: 'Отопление / кондиционирование',
link: true,
children: []
},
{
quickgroupid: 'interior',
name: 'Детали салона',
link: true,
children: []
},
{
quickgroupid: 'body',
name: 'Детали кузова',
link: true,
children: []
},
{
quickgroupid: 'accessories',
name: 'Дополнительное оборудование',
link: true,
children: []
}
];
// Соответствие между предопределенными категориями и реальными категориями Laximo
export const CATEGORY_MAPPING: Record<string, string[]> = {
'to': ['10119', '10698', '10697'], // Детали для ТО
'engine': ['10101', '10102', '10103', '10104', '10105', '10107'], // Двигатель
'fuel': ['10109'], // Топливная система
'cooling': ['10117'], // Система охлаждения
'exhaust': ['10115'], // Система выпуска
'transmission': ['10114', '10500', '10515', '10171'], // Трансмиссия
'chassis': ['10111', '10113', '10306', '10307', '10310', '10311', '10312', '10313'], // Ходовая часть
'steering': ['10112', '10297', '10298', '10299', '10301', '10302'], // Рулевое управление
'brakes': ['10106', '10127', '10130', '10132', '10135', '10136', '10125', '10126'], // Тормозная система
'electrical': ['10110', '10141', '10142', '10143', '10108'], // Электрооборудование
'climate': ['10341', '10343'], // Отопление / кондиционирование
'interior': ['10441', '10833'], // Детали салона
'body': ['10785', '10517'], // Детали кузова
'accessories': ['10443', '10118', '10435', '13199'] // Дополнительное оборудование
};
/**
* Группирует категории Laximo по предопределенным категориям
*/
export function mapToStandardCategories(laximoCategories: LaximoQuickGroup[]): LaximoQuickGroup[] {
console.log('🗂️ Начинаем сопоставление категорий Laximo с предопределенными');
console.log('📋 Входные категории Laximo:', laximoCategories.length);
console.log('📋 Первые 5 категорий:', laximoCategories.slice(0, 5));
// Создаем копию предопределенных категорий
const standardCategories = JSON.parse(JSON.stringify(PREDEFINED_CATEGORIES)) as LaximoQuickGroup[];
console.log('📋 Предопределенные категории:', standardCategories.length);
// Проходим по всем категориям Laximo
laximoCategories.forEach(category => {
console.log(`🔍 Обрабатываем категорию: ${category.name} (ID: ${category.quickgroupid})`);
// Ищем, к какой предопределенной категории относится текущая
for (const [predefinedId, mappedIds] of Object.entries(CATEGORY_MAPPING)) {
if (mappedIds.includes(category.quickgroupid)) {
console.log(`✅ Найдено соответствие: ${category.quickgroupid} -> ${predefinedId}`);
// Находим соответствующую предопределенную категорию
const predefinedCategory = standardCategories.find(c => c.quickgroupid === predefinedId);
if (predefinedCategory) {
// Добавляем текущую категорию как дочернюю к предопределенной
if (!predefinedCategory.children) {
predefinedCategory.children = [];
}
predefinedCategory.children.push(category);
console.log(`📂 Добавлена подкатегория "${category.name}" в "${predefinedCategory.name}"`);
break;
}
}
}
});
// Возвращаем только категории, у которых есть дочерние элементы
const result = standardCategories.filter(category => category.children && category.children.length > 0);
console.log('🎯 Результат сопоставления:', result.length, 'категорий с подкатегориями');
result.forEach(cat => {
console.log(`📂 ${cat.name}: ${cat.children?.length || 0} подкатегорий`);
});
return result;
}
/**
* Использует статические категории, если API вернуло ошибку
*/
export function getStaticCategories(): LaximoQuickGroup[] {
return PREDEFINED_CATEGORIES;
}

View File

@ -0,0 +1,59 @@
import { PartsIndexCatalogsResponse, PartsIndexGroup } from '@/types/partsindex';
const PARTS_INDEX_API_BASE = 'https://api.parts-index.com';
const API_KEY = 'PI-E1C0ADB7-E4A8-4960-94A0-4D9C0A074DAE';
class PartsIndexService {
/**
* Получить список каталогов
*/
async getCatalogs(lang: string = 'ru'): Promise<PartsIndexCatalogsResponse> {
try {
const response = await fetch(
`${PARTS_INDEX_API_BASE}/v1/catalogs?lang=${lang}`,
{
headers: {
'Accept': 'application/json',
},
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Ошибка получения каталогов Parts Index:', error);
throw error;
}
}
/**
* Получить группы каталога
*/
async getCatalogGroups(catalogId: string, lang: string = 'ru'): Promise<PartsIndexGroup> {
try {
const response = await fetch(
`${PARTS_INDEX_API_BASE}/v1/catalogs/${catalogId}/groups?lang=${lang}`,
{
headers: {
'Accept': 'application/json',
'Authorization': API_KEY,
},
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error(`Ошибка получения групп каталога ${catalogId}:`, error);
throw error;
}
}
}
export const partsIndexService = new PartsIndexService();

View File

@ -0,0 +1,15 @@
import { useEffect, useLayoutEffect, useState } from 'react';
// Хук для избежания проблем с SSR
export const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
// Хук для проверки клиентского рендеринга
export const useIsClient = () => {
const [isClient, setIsClient] = useState(false);
useEffect(() => {
setIsClient(true);
}, []);
return isClient;
};

95
src/lib/utils.ts Normal file
View File

@ -0,0 +1,95 @@
// Утилиты для проекта
// Простая утилита для дебага запросов
let requestCounter = 0;
export const debugQuery = (queryName: string, variables?: any) => {
requestCounter++;
if (process.env.NODE_ENV === 'development') {
console.log(`🔍 GraphQL Query #${requestCounter}: ${queryName}`, variables);
}
return requestCounter;
};
// Утилита для дебага рендеров компонентов
export const debugRender = (componentName: string, props?: any) => {
if (process.env.NODE_ENV === 'development') {
console.log(`🎨 Render: ${componentName}`, props);
}
};
// Утилита для отслеживания производительности
export const measurePerformance = (label: string, fn: () => void) => {
if (process.env.NODE_ENV === 'development') {
console.time(label);
fn();
console.timeEnd(label);
} else {
fn();
}
};
// Debounce функция для оптимизации запросов
export const debounce = <T extends (...args: any[]) => any>(
func: T,
wait: number
): ((...args: Parameters<T>) => void) => {
let timeout: NodeJS.Timeout;
return function executedFunction(...args: Parameters<T>) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
// Throttle функция для ограничения частоты выполнения
export const throttle = <T extends (...args: any[]) => any>(
func: T,
limit: number
): ((...args: Parameters<T>) => void) => {
let inThrottle: boolean;
return function executedFunction(...args: Parameters<T>) {
if (!inThrottle) {
func(...args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
};
// Кэш для мемоизации результатов
const memoCache = new Map<string, any>();
// Простая мемоизация функций
export const memoize = <T extends (...args: any[]) => any>(
func: T,
keyGenerator?: (...args: Parameters<T>) => string
): T => {
return ((...args: Parameters<T>) => {
const key = keyGenerator ? keyGenerator(...args) : JSON.stringify(args);
if (memoCache.has(key)) {
return memoCache.get(key);
}
const result = func(...args);
memoCache.set(key, result);
// Ограничиваем размер кэша
if (memoCache.size > 1000) {
const firstKey = memoCache.keys().next().value;
if (firstKey !== undefined) {
memoCache.delete(firstKey);
}
}
return result;
}) as T;
};
// Очистка кэша мемоизации
export const clearMemoCache = () => {
memoCache.clear();
};