fixing
This commit is contained in:
@ -110,6 +110,7 @@ model Organization {
|
|||||||
supplySuppliers SupplySupplier[] @relation("SupplySuppliers")
|
supplySuppliers SupplySupplier[] @relation("SupplySuppliers")
|
||||||
externalAds ExternalAd[] @relation("ExternalAds")
|
externalAds ExternalAd[] @relation("ExternalAds")
|
||||||
wbWarehouseCaches WBWarehouseCache[] @relation("WBWarehouseCaches")
|
wbWarehouseCaches WBWarehouseCache[] @relation("WBWarehouseCaches")
|
||||||
|
sellerStatsCaches SellerStatsCache[] @relation("SellerStatsCaches")
|
||||||
|
|
||||||
@@map("organizations")
|
@@map("organizations")
|
||||||
}
|
}
|
||||||
@ -546,3 +547,35 @@ model WBWarehouseCache {
|
|||||||
@@index([organizationId, cacheDate])
|
@@index([organizationId, cacheDate])
|
||||||
@@map("wb_warehouse_caches")
|
@@map("wb_warehouse_caches")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model SellerStatsCache {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
organizationId String // ID организации
|
||||||
|
cacheDate DateTime // Дата кеширования (только дата, без времени)
|
||||||
|
period String // Период статистики (week, month, quarter, custom)
|
||||||
|
dateFrom DateTime? // Дата начала периода (для custom)
|
||||||
|
dateTo DateTime? // Дата окончания периода (для custom)
|
||||||
|
|
||||||
|
// Данные товаров
|
||||||
|
productsData Json? // Кешированные данные товаров
|
||||||
|
productsTotalSales Decimal? @db.Decimal(15, 2) // Общая сумма продаж товаров
|
||||||
|
productsTotalOrders Int? // Общее количество заказов товаров
|
||||||
|
productsCount Int? // Количество товаров
|
||||||
|
|
||||||
|
// Данные рекламы
|
||||||
|
advertisingData Json? // Кешированные данные рекламы
|
||||||
|
advertisingTotalCost Decimal? @db.Decimal(15, 2) // Общие расходы на рекламу
|
||||||
|
advertisingTotalViews Int? // Общие показы рекламы
|
||||||
|
advertisingTotalClicks Int? // Общие клики рекламы
|
||||||
|
|
||||||
|
// Метаданные
|
||||||
|
expiresAt DateTime // Время истечения кеша (24 часа)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
organization Organization @relation("SellerStatsCaches", fields: [organizationId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@unique([organizationId, cacheDate, period, dateFrom, dateTo])
|
||||||
|
@@index([organizationId, cacheDate])
|
||||||
|
@@index([expiresAt])
|
||||||
|
@@map("seller_stats_caches")
|
||||||
|
}
|
||||||
|
@ -95,6 +95,11 @@ interface CampaignStatsProps {
|
|||||||
useCustomDates: boolean
|
useCustomDates: boolean
|
||||||
startDate: string
|
startDate: string
|
||||||
endDate: string
|
endDate: string
|
||||||
|
// Новые пропсы для работы с кэшем
|
||||||
|
getCachedData?: () => any
|
||||||
|
setCachedData?: (data: any) => void
|
||||||
|
isLoadingData?: boolean
|
||||||
|
setIsLoadingData?: (loading: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
// Интерфейсы для API данных
|
// Интерфейсы для API данных
|
||||||
@ -455,7 +460,16 @@ const CompactCampaignSelector = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AdvertisingTab({ selectedPeriod, useCustomDates, startDate, endDate }: CampaignStatsProps) {
|
export function AdvertisingTab({
|
||||||
|
selectedPeriod,
|
||||||
|
useCustomDates,
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
getCachedData,
|
||||||
|
setCachedData,
|
||||||
|
isLoadingData,
|
||||||
|
setIsLoadingData
|
||||||
|
}: CampaignStatsProps) {
|
||||||
const { user } = useAuth()
|
const { user } = useAuth()
|
||||||
|
|
||||||
// Состояния для раскрытия строк
|
// Состояния для раскрытия строк
|
||||||
@ -481,6 +495,19 @@ export function AdvertisingTab({ selectedPeriod, useCustomDates, startDate, endD
|
|||||||
const [generatedLinksData, setGeneratedLinksData] = useState<Record<string, GeneratedLink[]>>({})
|
const [generatedLinksData, setGeneratedLinksData] = useState<Record<string, GeneratedLink[]>>({})
|
||||||
const prevCampaignStats = useRef<CampaignStats[]>([])
|
const prevCampaignStats = useRef<CampaignStats[]>([])
|
||||||
|
|
||||||
|
// Проверяем кэш при изменении периода
|
||||||
|
useEffect(() => {
|
||||||
|
if (getCachedData) {
|
||||||
|
const cachedData = getCachedData()
|
||||||
|
if (cachedData) {
|
||||||
|
setDailyData(cachedData.dailyData || [])
|
||||||
|
setCampaignStats(cachedData.campaignStats || [])
|
||||||
|
console.log('Advertising: Using cached data')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [selectedPeriod, useCustomDates, startDate, endDate, getCachedData])
|
||||||
|
|
||||||
// Вычисляем диапазон дат для запроса внешней рекламы
|
// Вычисляем диапазон дат для запроса внешней рекламы
|
||||||
const getDateRange = () => {
|
const getDateRange = () => {
|
||||||
if (useCustomDates && startDate && endDate) {
|
if (useCustomDates && startDate && endDate) {
|
||||||
@ -949,9 +976,24 @@ export function AdvertisingTab({ selectedPeriod, useCustomDates, startDate, endD
|
|||||||
const newDailyData = convertCampaignDataToDailyData(campaignStats)
|
const newDailyData = convertCampaignDataToDailyData(campaignStats)
|
||||||
setDailyData(newDailyData)
|
setDailyData(newDailyData)
|
||||||
prevCampaignStats.current = campaignStats
|
prevCampaignStats.current = campaignStats
|
||||||
|
|
||||||
|
// Сохраняем данные в кэш
|
||||||
|
if (setCachedData) {
|
||||||
|
const cacheData = {
|
||||||
|
dailyData: newDailyData,
|
||||||
|
campaignStats: campaignStats,
|
||||||
|
totalCost: newDailyData.reduce((sum, day) => sum + day.totalSum, 0),
|
||||||
|
totalViews: newDailyData.reduce((sum, day) =>
|
||||||
|
sum + day.products.reduce((daySum, product) => daySum + product.totalViews, 0), 0),
|
||||||
|
totalClicks: newDailyData.reduce((sum, day) =>
|
||||||
|
sum + day.products.reduce((daySum, product) => daySum + product.totalClicks, 0), 0),
|
||||||
|
}
|
||||||
|
setCachedData(cacheData)
|
||||||
|
console.log('Advertising: Data cached successfully')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [campaignStats, externalAdsData]) // Добавляем externalAdsData в зависимости
|
}, [campaignStats, externalAdsData, setCachedData]) // Добавляем externalAdsData и setCachedData в зависимости
|
||||||
|
|
||||||
const handleCampaignsSelected = (ids: number[]) => {
|
const handleCampaignsSelected = (ids: number[]) => {
|
||||||
if (ids.length === 0) return
|
if (ids.length === 0) return
|
||||||
|
@ -58,6 +58,11 @@ interface SalesTabProps {
|
|||||||
endDate?: string
|
endDate?: string
|
||||||
onPeriodChange?: (period: string) => void
|
onPeriodChange?: (period: string) => void
|
||||||
onUseCustomDatesChange?: (useCustom: boolean) => void
|
onUseCustomDatesChange?: (useCustom: boolean) => void
|
||||||
|
// Новые пропсы для работы с кэшем
|
||||||
|
getCachedData?: () => any
|
||||||
|
setCachedData?: (data: any) => void
|
||||||
|
isLoadingData?: boolean
|
||||||
|
setIsLoadingData?: (loading: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mock данные для графиков
|
// Mock данные для графиков
|
||||||
@ -169,7 +174,18 @@ const mockTableData = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export function SalesTab({ selectedPeriod, useCustomDates, startDate, endDate, onPeriodChange, onUseCustomDatesChange }: SalesTabProps) {
|
export function SalesTab({
|
||||||
|
selectedPeriod,
|
||||||
|
useCustomDates,
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
onPeriodChange,
|
||||||
|
onUseCustomDatesChange,
|
||||||
|
getCachedData,
|
||||||
|
setCachedData,
|
||||||
|
isLoadingData,
|
||||||
|
setIsLoadingData
|
||||||
|
}: SalesTabProps) {
|
||||||
// Состояния для чекбоксов фильтрации
|
// Состояния для чекбоксов фильтрации
|
||||||
const [visibleMetrics, setVisibleMetrics] = useState({
|
const [visibleMetrics, setVisibleMetrics] = useState({
|
||||||
sales: true,
|
sales: true,
|
||||||
@ -179,18 +195,55 @@ export function SalesTab({ selectedPeriod, useCustomDates, startDate, endDate, o
|
|||||||
returns: true,
|
returns: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Получаем данные из WB API
|
// Данные для графика и таблицы
|
||||||
const { data: wbData, loading, error } = useQuery(GET_WILDBERRIES_STATISTICS, {
|
const [chartData, setChartData] = useState<typeof mockChartData>([])
|
||||||
|
const [tableData, setTableData] = useState<typeof mockTableData>([])
|
||||||
|
|
||||||
|
// Получаем данные из WB API только если нет в кэше
|
||||||
|
const { data: wbData, loading, error, refetch } = useQuery(GET_WILDBERRIES_STATISTICS, {
|
||||||
variables: useCustomDates
|
variables: useCustomDates
|
||||||
? { startDate, endDate }
|
? { startDate, endDate }
|
||||||
: { period: selectedPeriod },
|
: { period: selectedPeriod },
|
||||||
errorPolicy: 'all',
|
errorPolicy: 'all',
|
||||||
skip: useCustomDates && (!startDate || !endDate) // Не запрашиваем пока не выбраны обе даты
|
skip: true, // Изначально пропускаем запрос, будем запускать вручную
|
||||||
})
|
})
|
||||||
|
|
||||||
// Данные для графика и таблицы
|
// Эффект для проверки кэша и загрузки данных
|
||||||
const [chartData, setChartData] = useState<typeof mockChartData>([])
|
useEffect(() => {
|
||||||
const [tableData, setTableData] = useState<typeof mockTableData>([])
|
const loadData = async () => {
|
||||||
|
// Сначала проверяем локальный кэш
|
||||||
|
if (getCachedData) {
|
||||||
|
const cachedData = getCachedData()
|
||||||
|
if (cachedData) {
|
||||||
|
setChartData(cachedData.chartData || mockChartData)
|
||||||
|
setTableData(cachedData.tableData || mockTableData)
|
||||||
|
console.log('Sales: Using cached data')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если нет кэша, запрашиваем данные
|
||||||
|
if (setIsLoadingData) setIsLoadingData(true)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await refetch()
|
||||||
|
if (result.data?.getWildberriesStatistics?.success) {
|
||||||
|
console.log('Sales: Loading fresh data from API')
|
||||||
|
// Обрабатываем данные в существующем useEffect
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Sales: Error loading data:', error)
|
||||||
|
} finally {
|
||||||
|
if (setIsLoadingData) setIsLoadingData(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Загружаем данные только если не пропускаем загрузку
|
||||||
|
const shouldSkip = useCustomDates && (!startDate || !endDate)
|
||||||
|
if (!shouldSkip) {
|
||||||
|
loadData()
|
||||||
|
}
|
||||||
|
}, [selectedPeriod, useCustomDates, startDate, endDate, getCachedData, refetch, setIsLoadingData])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (wbData?.getWildberriesStatistics?.success && wbData.getWildberriesStatistics.data) {
|
if (wbData?.getWildberriesStatistics?.success && wbData.getWildberriesStatistics.data) {
|
||||||
@ -311,8 +364,21 @@ export function SalesTab({ selectedPeriod, useCustomDates, startDate, endDate, o
|
|||||||
|
|
||||||
setChartData(newChartData.reverse()) // Для графика - старые даты слева
|
setChartData(newChartData.reverse()) // Для графика - старые даты слева
|
||||||
setTableData(newTableData) // Для таблицы - новые даты сверху
|
setTableData(newTableData) // Для таблицы - новые даты сверху
|
||||||
|
|
||||||
|
// Сохраняем данные в кэш
|
||||||
|
if (setCachedData) {
|
||||||
|
const cacheData = {
|
||||||
|
chartData: newChartData,
|
||||||
|
tableData: newTableData,
|
||||||
|
totalSales: newTableData.reduce((sum, item) => sum + item.sales, 0),
|
||||||
|
totalOrders: newTableData.reduce((sum, item) => sum + item.orders, 0),
|
||||||
|
productsCount: newTableData.length,
|
||||||
|
}
|
||||||
|
setCachedData(cacheData)
|
||||||
|
console.log('Sales: Data cached successfully')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [wbData])
|
}, [wbData, setCachedData])
|
||||||
|
|
||||||
// Функция для переключения видимости метрики
|
// Функция для переключения видимости метрики
|
||||||
const toggleMetric = (metric: keyof typeof visibleMetrics) => {
|
const toggleMetric = (metric: keyof typeof visibleMetrics) => {
|
||||||
@ -323,7 +389,7 @@ export function SalesTab({ selectedPeriod, useCustomDates, startDate, endDate, o
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем состояние загрузки и данных
|
// Проверяем состояние загрузки и данных
|
||||||
const isLoading = loading || (useCustomDates && (!startDate || !endDate))
|
const isLoading = (isLoadingData !== undefined ? isLoadingData : loading) || (useCustomDates && (!startDate || !endDate))
|
||||||
const hasData = tableData.length > 0
|
const hasData = tableData.length > 0
|
||||||
|
|
||||||
// Состояние для сортировки
|
// Состояние для сортировки
|
||||||
|
@ -1,21 +1,127 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useState } from 'react'
|
import { useState, useEffect, useRef } from 'react'
|
||||||
|
import { useQuery, useMutation } from '@apollo/client'
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||||
import { Card } from '@/components/ui/card'
|
import { Card } from '@/components/ui/card'
|
||||||
import { Sidebar } from '@/components/dashboard/sidebar'
|
import { Sidebar } from '@/components/dashboard/sidebar'
|
||||||
import { useSidebar } from '@/hooks/useSidebar'
|
import { useSidebar } from '@/hooks/useSidebar'
|
||||||
|
import { useAuth } from '@/hooks/useAuth'
|
||||||
import { SalesTab } from '@/components/seller-statistics/sales-tab'
|
import { SalesTab } from '@/components/seller-statistics/sales-tab'
|
||||||
import { AdvertisingTab } from '@/components/seller-statistics/advertising-tab'
|
import { AdvertisingTab } from '@/components/seller-statistics/advertising-tab'
|
||||||
import { DateRangePicker } from '@/components/ui/date-picker'
|
import { DateRangePicker } from '@/components/ui/date-picker'
|
||||||
|
import { GET_SELLER_STATS_CACHE } from '@/graphql/queries'
|
||||||
|
import { SAVE_SELLER_STATS_CACHE } from '@/graphql/mutations'
|
||||||
import { BarChart3, PieChart, TrendingUp, Calendar } from 'lucide-react'
|
import { BarChart3, PieChart, TrendingUp, Calendar } from 'lucide-react'
|
||||||
|
|
||||||
export function SellerStatisticsDashboard() {
|
export function SellerStatisticsDashboard() {
|
||||||
const { getSidebarMargin } = useSidebar()
|
const { getSidebarMargin } = useSidebar()
|
||||||
|
const { user } = useAuth()
|
||||||
const [selectedPeriod, setSelectedPeriod] = useState('week')
|
const [selectedPeriod, setSelectedPeriod] = useState('week')
|
||||||
const [useCustomDates, setUseCustomDates] = useState(false)
|
const [useCustomDates, setUseCustomDates] = useState(false)
|
||||||
const [startDate, setStartDate] = useState('')
|
const [startDate, setStartDate] = useState('')
|
||||||
const [endDate, setEndDate] = useState('')
|
const [endDate, setEndDate] = useState('')
|
||||||
|
const [activeTab, setActiveTab] = useState('sales')
|
||||||
|
|
||||||
|
// Кэш для данных разных периодов и табов
|
||||||
|
const [salesCache, setSalesCache] = useState<Map<string, any>>(new Map())
|
||||||
|
const [advertisingCache, setAdvertisingCache] = useState<Map<string, any>>(new Map())
|
||||||
|
const [isLoadingData, setIsLoadingData] = useState(false)
|
||||||
|
|
||||||
|
// Мутация для сохранения кэша
|
||||||
|
const [saveCache] = useMutation(SAVE_SELLER_STATS_CACHE)
|
||||||
|
|
||||||
|
// Создаём ключ для кэша на основе периода и дат
|
||||||
|
const getCacheKey = () => {
|
||||||
|
if (useCustomDates && startDate && endDate) {
|
||||||
|
return `custom_${startDate}_${endDate}`
|
||||||
|
}
|
||||||
|
return selectedPeriod
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем есть ли данные в локальном кэше
|
||||||
|
const getCachedData = (type: 'sales' | 'advertising') => {
|
||||||
|
const cache = type === 'sales' ? salesCache : advertisingCache
|
||||||
|
const cacheKey = getCacheKey()
|
||||||
|
return cache.get(cacheKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сохраняем данные в локальный кэш
|
||||||
|
const setCachedData = (type: 'sales' | 'advertising', data: any) => {
|
||||||
|
const cacheKey = getCacheKey()
|
||||||
|
if (type === 'sales') {
|
||||||
|
setSalesCache(new Map(salesCache.set(cacheKey, data)))
|
||||||
|
} else {
|
||||||
|
setAdvertisingCache(new Map(advertisingCache.set(cacheKey, data)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запрос кэша из БД
|
||||||
|
const { data: cacheData, refetch: refetchCache } = useQuery(GET_SELLER_STATS_CACHE, {
|
||||||
|
variables: {
|
||||||
|
period: useCustomDates ? 'custom' : selectedPeriod,
|
||||||
|
dateFrom: useCustomDates ? startDate : undefined,
|
||||||
|
dateTo: useCustomDates ? endDate : undefined,
|
||||||
|
},
|
||||||
|
skip: !user?.organization,
|
||||||
|
fetchPolicy: 'cache-first',
|
||||||
|
errorPolicy: 'ignore',
|
||||||
|
})
|
||||||
|
|
||||||
|
// Загружаем данные из кэша БД при изменении периода
|
||||||
|
useEffect(() => {
|
||||||
|
if (cacheData?.getSellerStatsCache?.success && cacheData.getSellerStatsCache.cache) {
|
||||||
|
const cache = cacheData.getSellerStatsCache.cache
|
||||||
|
const cacheKey = getCacheKey()
|
||||||
|
|
||||||
|
// Проверяем не истёк ли кэш (24 часа)
|
||||||
|
const expiresAt = new Date(cache.expiresAt)
|
||||||
|
const now = new Date()
|
||||||
|
|
||||||
|
if (expiresAt > now) {
|
||||||
|
// Кэш актуален, загружаем данные
|
||||||
|
if (cache.productsData) {
|
||||||
|
setSalesCache(new Map(salesCache.set(cacheKey, JSON.parse(cache.productsData))))
|
||||||
|
}
|
||||||
|
if (cache.advertisingData) {
|
||||||
|
setAdvertisingCache(new Map(advertisingCache.set(cacheKey, JSON.parse(cache.advertisingData))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [cacheData, selectedPeriod, useCustomDates, startDate, endDate])
|
||||||
|
|
||||||
|
// Сохраняем данные в БД кэш
|
||||||
|
const saveToCacheDB = async (type: 'sales' | 'advertising', data: any) => {
|
||||||
|
try {
|
||||||
|
const cacheKey = getCacheKey()
|
||||||
|
const expiresAt = new Date()
|
||||||
|
expiresAt.setHours(expiresAt.getHours() + 24) // 24 часа
|
||||||
|
|
||||||
|
const input: any = {
|
||||||
|
period: useCustomDates ? 'custom' : selectedPeriod,
|
||||||
|
dateFrom: useCustomDates ? startDate : null,
|
||||||
|
dateTo: useCustomDates ? endDate : null,
|
||||||
|
expiresAt: expiresAt.toISOString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'sales') {
|
||||||
|
input.productsData = JSON.stringify(data)
|
||||||
|
input.productsTotalSales = data.totalSales || 0
|
||||||
|
input.productsTotalOrders = data.totalOrders || 0
|
||||||
|
input.productsCount = data.productsCount || 0
|
||||||
|
} else {
|
||||||
|
input.advertisingData = JSON.stringify(data)
|
||||||
|
input.advertisingTotalCost = data.totalCost || 0
|
||||||
|
input.advertisingTotalViews = data.totalViews || 0
|
||||||
|
input.advertisingTotalClicks = data.totalClicks || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
await saveCache({ variables: { input } })
|
||||||
|
console.log(`Cached ${type} data saved to DB for period ${cacheKey}`)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error saving ${type} cache:`, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen flex overflow-hidden">
|
<div className="h-screen flex overflow-hidden">
|
||||||
@ -25,7 +131,7 @@ export function SellerStatisticsDashboard() {
|
|||||||
|
|
||||||
{/* Основной контент с табами */}
|
{/* Основной контент с табами */}
|
||||||
<div className="flex-1 overflow-hidden">
|
<div className="flex-1 overflow-hidden">
|
||||||
<Tabs defaultValue="sales" className="h-full flex flex-col">
|
<Tabs value={activeTab} onValueChange={setActiveTab} className="h-full flex flex-col">
|
||||||
<TabsList className="grid w-full grid-cols-3 bg-white/5 backdrop-blur border border-white/10 rounded-xl flex-shrink-0 h-11">
|
<TabsList className="grid w-full grid-cols-3 bg-white/5 backdrop-blur border border-white/10 rounded-xl flex-shrink-0 h-11">
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="sales"
|
value="sales"
|
||||||
@ -60,6 +166,14 @@ export function SellerStatisticsDashboard() {
|
|||||||
endDate={endDate}
|
endDate={endDate}
|
||||||
onPeriodChange={setSelectedPeriod}
|
onPeriodChange={setSelectedPeriod}
|
||||||
onUseCustomDatesChange={setUseCustomDates}
|
onUseCustomDatesChange={setUseCustomDates}
|
||||||
|
// Передаём функции для работы с кэшем
|
||||||
|
getCachedData={() => getCachedData('sales')}
|
||||||
|
setCachedData={(data) => {
|
||||||
|
setCachedData('sales', data)
|
||||||
|
saveToCacheDB('sales', data)
|
||||||
|
}}
|
||||||
|
isLoadingData={isLoadingData}
|
||||||
|
setIsLoadingData={setIsLoadingData}
|
||||||
/>
|
/>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
@ -69,6 +183,14 @@ export function SellerStatisticsDashboard() {
|
|||||||
useCustomDates={useCustomDates}
|
useCustomDates={useCustomDates}
|
||||||
startDate={startDate}
|
startDate={startDate}
|
||||||
endDate={endDate}
|
endDate={endDate}
|
||||||
|
// Передаём функции для работы с кэшем
|
||||||
|
getCachedData={() => getCachedData('advertising')}
|
||||||
|
setCachedData={(data) => {
|
||||||
|
setCachedData('advertising', data)
|
||||||
|
saveToCacheDB('advertising', data)
|
||||||
|
}}
|
||||||
|
isLoadingData={isLoadingData}
|
||||||
|
setIsLoadingData={setIsLoadingData}
|
||||||
/>
|
/>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
@ -1334,3 +1334,32 @@ export const SAVE_WB_WAREHOUSE_CACHE = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
// Мутации для кеша статистики продаж
|
||||||
|
export const SAVE_SELLER_STATS_CACHE = gql`
|
||||||
|
mutation SaveSellerStatsCache($input: SellerStatsCacheInput!) {
|
||||||
|
saveSellerStatsCache(input: $input) {
|
||||||
|
success
|
||||||
|
message
|
||||||
|
cache {
|
||||||
|
id
|
||||||
|
organizationId
|
||||||
|
cacheDate
|
||||||
|
period
|
||||||
|
dateFrom
|
||||||
|
dateTo
|
||||||
|
productsData
|
||||||
|
productsTotalSales
|
||||||
|
productsTotalOrders
|
||||||
|
productsCount
|
||||||
|
advertisingData
|
||||||
|
advertisingTotalCost
|
||||||
|
advertisingTotalViews
|
||||||
|
advertisingTotalClicks
|
||||||
|
expiresAt
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
@ -977,3 +977,41 @@ export const GET_WB_WAREHOUSE_DATA = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
// Запросы для кеша статистики продаж
|
||||||
|
export const GET_SELLER_STATS_CACHE = gql`
|
||||||
|
query GetSellerStatsCache(
|
||||||
|
$period: String!
|
||||||
|
$dateFrom: String
|
||||||
|
$dateTo: String
|
||||||
|
) {
|
||||||
|
getSellerStatsCache(
|
||||||
|
period: $period
|
||||||
|
dateFrom: $dateFrom
|
||||||
|
dateTo: $dateTo
|
||||||
|
) {
|
||||||
|
success
|
||||||
|
message
|
||||||
|
fromCache
|
||||||
|
cache {
|
||||||
|
id
|
||||||
|
organizationId
|
||||||
|
cacheDate
|
||||||
|
period
|
||||||
|
dateFrom
|
||||||
|
dateTo
|
||||||
|
productsData
|
||||||
|
productsTotalSales
|
||||||
|
productsTotalOrders
|
||||||
|
productsCount
|
||||||
|
advertisingData
|
||||||
|
advertisingTotalCost
|
||||||
|
advertisingTotalViews
|
||||||
|
advertisingTotalClicks
|
||||||
|
expiresAt
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
Reference in New Issue
Block a user