'use client'; import { ProductDisplay, CityPositionsTable, PositionChart, HistoryDisplay, } from './components'; import { motion } from 'framer-motion'; import { useState, useEffect } from 'react'; import ClientWrapper from './ClientWrapper'; import { ChartDataPoint, CityPosition, HistoryRecord, SearchResponse, } from '@/types'; import { FiBarChart2, FiActivity } from 'react-icons/fi'; // Data persistence removed – no localStorage interaction export default function Home() { // Добавляем состояние для данных const [chartData, setChartData] = useState([]); const [cityPositions, setCityPositions] = useState([]); const [competitorPositions, setCompetitorPositions] = useState([]); const [historyData, setHistoryData] = useState([]); const [isLoading, setIsLoading] = useState(true); const [searchPerformed, setSearchPerformed] = useState(false); const [currentQuery, setCurrentQuery] = useState(''); // Текущий поисковый запрос const [currentArticleId, setCurrentArticleId] = useState(''); // Текущий артикул товара const [currentCompetitorId, setCurrentCompetitorId] = useState(''); // Текущий артикул конкурента const [isComparisonMode, setIsComparisonMode] = useState(false); // Режим сравнения // Helper to reset state when new search starts const resetDataState = () => { setChartData([]); setCityPositions([]); setCompetitorPositions([]); setSearchPerformed(false); setIsComparisonMode(false); }; // Загрузка начальных данных истории (без localStorage) useEffect(() => { fetchHistory(); }, []); // Получение данных истории const fetchHistory = async (queryOverride?: string, articleOverride?: string) => { try { setIsLoading(true); // Параметры запроса для фильтрации истории const params = new URLSearchParams(); // Фильтруем строго по конкретному артикулу и по конкретному запросу const articleId = articleOverride || currentArticleId; const query = queryOverride || currentQuery; if (articleId) { params.append('articleId', articleId); } // Обязательно фильтруем по точному запросу (ключевые слова) if (query) { params.append('query', query); } const queryString = params.toString() ? `?${params.toString()}` : ''; const response = await fetch(`/api/history${queryString}`); if (!response.ok) { throw new Error('Ошибка при загрузке истории'); } const data = await response.json(); setHistoryData(data); // Если есть история, берем последнюю запись для отображения if (data.length > 0) { updateDisplayData(data[0]); } } catch (error) { console.error('Ошибка загрузки истории:', error); } finally { setIsLoading(false); } }; // Обновление данных для отображения const updateDisplayData = (historyItem: HistoryRecord) => { // Обновляем графические данные const chartDataFromHistory = historyItem.positions.map((pos) => ({ city: pos.city, myPosition: pos.pageRank === 1 ? pos.rank : (pos.pageRank - 1) * 100 + pos.rank, // В истории нет данных конкурента, используем заглушку competitorPosition: pos.competitorRank && pos.competitorPageRank ? pos.competitorPageRank === 1 ? pos.competitorRank : (pos.competitorPageRank - 1) * 100 + pos.competitorRank : 0, })); setChartData(chartDataFromHistory); }; // Обработчик завершения поиска (обновлено под новую структуру) const handleSearchComplete = (data: SearchResponse, searchQuery?: string) => { // Сбрасываем предыдущие данные resetDataState(); // Формируем позиции для таблицы - берем позиции основного товара const myArticleId = data.myArticleId; const myPositions = data.positions[myArticleId] || []; setCityPositions(myPositions); // Определяем режим сравнения и данные конкурента const hasCompetitor = !!(data.competitorArticleId && data.positions[data.competitorArticleId]); setIsComparisonMode(hasCompetitor); setCurrentCompetitorId(data.competitorArticleId || ''); if (hasCompetitor) { const competitorPositions = data.positions[data.competitorArticleId!] || []; setCompetitorPositions(competitorPositions); // Создаем chartData для сравнения с конкурентом const chartDataFromResponse: ChartDataPoint[] = myPositions.map(myPos => { const competitorPos = competitorPositions.find(cp => cp.city === myPos.city); return { city: myPos.city, myPosition: myPos.position ?? 0, competitorPosition: competitorPos?.position ?? 0, }; }); setChartData(chartDataFromResponse); // Save to localStorage (removed) } else { // Режим без конкурента - показываем только мои позиции setCompetitorPositions([]); const chartDataFromResponse: ChartDataPoint[] = myPositions.map(myPos => ({ city: myPos.city, myPosition: myPos.position ?? 0, competitorPosition: 0, })); setChartData(chartDataFromResponse); // Save to localStorage (removed) } setSearchPerformed(true); // Сохраняем артикул основного товара для фильтрации истории if (data.products && data.products.length > 0) { const mainProduct = data.products.find(p => p.article === myArticleId); if (mainProduct) { // Если сменился артикул, очищаем историю if (currentArticleId !== mainProduct.article) { setHistoryData([]); } setCurrentArticleId(mainProduct.article); // Save query and article ID (removed) if (searchQuery) setCurrentQuery(searchQuery); } } // Обновляем историю после выполнения поиска, чтобы отобразить новые данные // Устанавливаем небольшую задержку, чтобы данные успели сохраниться в БД setTimeout(() => { fetchHistory(); }, 300); }; // Анимационные варианты const containerVariants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.2, delayChildren: 0.3, }, }, }; const itemVariants = { hidden: { opacity: 0, y: 20 }, visible: { opacity: 1, y: 0, transition: { type: 'spring', stiffness: 80, }, }, }; // Заглушки для пустых состояний const TablePlaceholder = () => (

Таблица позиций

Данные о позициях товаров по городам будут отображаться здесь

); const ChartPlaceholder = () => (

График позиций

Визуализация позиций товаров будет отображаться здесь

); return (
{/* Data Management Controls removed (no persistence) */} {/* Mobile Layout */}
{/* Mobile: Search section */} {/* Mobile: Table section */} {searchPerformed ? ( ) : ( )} {/* Mobile: Chart section */} {searchPerformed ? ( ) : ( )} {/* Mobile: History section */}
{/* Desktop Layout */}
{/* Desktop: Top section with three columns */}
{/* Товары и поиск - 3/12 */} {/* Таблица - 3/12 */} {searchPerformed ? ( ) : ( )} {/* График - 6/12 */} {searchPerformed ? ( ) : ( )}
{/* Desktop: Bottom section - History */}
); }