"use client"; import { useState, useEffect, useCallback, useMemo, Suspense } from "react"; import { useSearchParams, useRouter } from "next/navigation"; import { Search, ArrowLeft, Loader2, Grid, List, SlidersHorizontal, RefreshCw, Database, X, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"; import { Product, sortProducts, fetchAllResults } from "@/lib/openFoodFactsApi"; import { ProductCard } from "@/app/components/ProductCard"; import { ProductCardSkeleton } from "@/app/components/ProductCardSkeleton"; import { FilterSidebar } from "@/app/components/FilterSidebar"; import { FilterBadges } from "@/app/components/FilterBadge"; import { SortDropdown } from "@/app/components/SortDropdown"; import { Pagination } from "@/app/components/Pagination"; import { useProductFilters } from "@/hooks/useProductFilters"; import { useSearchCache } from "@/hooks/useSearchCache"; import { detectUserCountry } from "@/lib/geolocation"; import { FilterRecord } from "@/lib/cacheManager"; import { ProductFilters } from "@/lib/types"; import Link from "next/link"; // Função para converter ProductFilters para FilterRecord function convertFiltersToRecord(filters: ProductFilters): FilterRecord { const record: FilterRecord = {}; Object.entries(filters).forEach(([key, value]) => { if (value !== undefined && value !== null) { record[key] = value as FilterRecord[string]; } }); return record; } function ResultadosContent() { const searchParams = useSearchParams(); const router = useRouter(); const query = searchParams.get("q") || ""; const countryParam = searchParams.get("country") || ""; // Estados principais const [allProducts, setAllProducts] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [detectedCountry, setDetectedCountry] = useState(""); const [viewMode, setViewMode] = useState<"grid" | "list">("grid"); const [forceRefresh, setForceRefresh] = useState(false); // Estados de paginação const [currentPage, setCurrentPage] = useState(1); const [itemsPerPage, setItemsPerPage] = useState(20); // Hook de cache const { state: cacheState, getCachedSearch, saveSearch, clearCache, updateProgress, setError: setCacheError, setLoading: setCacheLoading, } = useSearchCache(); // Hook de filtros const { filters, updateFilters, clearFilters, hasActiveFilters, setTotalResults, setIsLoading, } = useProductFilters(); // Detectar país do usuário useEffect(() => { const detectCountry = async () => { try { const country = await detectUserCountry(true); setDetectedCountry(country.code); } catch { setDetectedCountry("br"); } }; detectCountry(); }, []); const loadProducts = useCallback( async (forceRefresh: boolean = false) => { try { setLoading(true); setError(null); setIsLoading(true); setCacheLoading(true); const countryToUse = detectedCountry || countryParam || "br"; // Verificar cache primeiro (se não for refresh forçado) if (!forceRefresh) { const cached = getCachedSearch( query, countryToUse, convertFiltersToRecord(filters) ); if (cached) { console.log("Usando dados do cache"); setAllProducts(cached.products); setTotalResults(cached.totalCount); setLoading(false); setIsLoading(false); setCacheLoading(false); return; } } console.log("Fazendo busca completa na API"); // Fazer busca completa const result = await fetchAllResults( query, countryToUse, 10, // Máximo 10 páginas (500 produtos) (currentPage, totalPages, loadedProducts) => { updateProgress(currentPage, totalPages, loadedProducts, 0); } ); // Salvar no cache const searchId = saveSearch( query, countryToUse, result.products, result.totalCount, convertFiltersToRecord(filters) ); console.log(`Busca salva no cache com ID: ${searchId}`); setAllProducts(result.products); setTotalResults(result.totalCount); setCurrentPage(1); // Voltar para primeira página } catch (err) { const errorMessage = err instanceof Error ? err.message : "Erro ao buscar produtos"; setError(errorMessage); setCacheError(errorMessage); } finally { setLoading(false); setIsLoading(false); setCacheLoading(false); } }, [ query, detectedCountry, countryParam, filters, getCachedSearch, saveSearch, updateProgress, setIsLoading, setTotalResults, setCacheLoading, setCacheError, ] ); useEffect(() => { if (query) { loadProducts(forceRefresh); setForceRefresh(false); } }, [query, countryParam, detectedCountry, loadProducts, forceRefresh]); // Produtos filtrados e ordenados para exibição const filteredAndSortedProducts = useMemo(() => { let filtered = [...allProducts]; // Aplicar filtros aqui (implementar conforme necessário) // Por enquanto, apenas ordenação if (filters.sortBy) { filtered = sortProducts( filtered, filters.sortBy, filters.sortOrder || "asc" ); } return filtered; }, [allProducts, filters.sortBy, filters.sortOrder]); // Produtos da página atual const currentPageProducts = useMemo(() => { const startIndex = (currentPage - 1) * itemsPerPage; const endIndex = startIndex + itemsPerPage; return filteredAndSortedProducts.slice(startIndex, endIndex); }, [filteredAndSortedProducts, currentPage, itemsPerPage]); // Cálculos de paginação const totalPages = Math.ceil(filteredAndSortedProducts.length / itemsPerPage); const totalItems = filteredAndSortedProducts.length; const handleRefresh = useCallback(() => { setForceRefresh(true); }, []); const handleClearCache = useCallback(() => { clearCache( query, detectedCountry || countryParam || "br", convertFiltersToRecord(filters) ); setForceRefresh(true); }, [clearCache, query, detectedCountry, countryParam, filters]); const handleSortChange = useCallback( (sortBy: string) => { updateFilters({ sortBy: sortBy as | "relevance" | "nutrition_grade" | "name" | "brand" | "energy" | "fat" | "sugars" | "completeness" | "with_images" | "with_nutrition" | "eco_score" | "nova_group", }); }, [updateFilters] ); if (!query) { return (

Nenhuma busca realizada

Digite um termo de busca para encontrar produtos

); } return (
{/* Header */}

Resultados para "{query}"

{!loading && totalItems > 0 && (

{totalItems} produto{totalItems !== 1 ? "s" : ""} encontrado {totalItems !== 1 ? "s" : ""} {detectedCountry && ` em ${detectedCountry}`} {cacheState.isCached && ( Cache )}

)}
{/* Controles de visualização - Desktop */}
{/* Botões de controle de cache */}
{cacheState.isCached && ( )}
{/* Filtros Mobile */}
{/* Filtros ativos */} {hasActiveFilters && (
{ if (value) { const currentArray = (filters[key as keyof typeof filters] as string[]) || []; updateFilters({ [key]: currentArray.filter((item) => item !== value), }); } else { updateFilters({ [key]: undefined }); } }} onClearAll={clearFilters} />
)} {/* Layout principal */}
{/* Sidebar de filtros - Desktop */}
{/* Conteúdo principal */}
{/* Loading Inicial */} {loading && (
{/* Indicador de progresso do cache */} {cacheState.progress && (

Carregando todos os resultados...

Página {cacheState.progress.currentPage} de{" "} {cacheState.progress.totalPages} • {cacheState.progress.loadedProducts} produtos carregados

)} {/* Skeleton dos produtos */}
{[...Array(8)].map((_, i) => ( ))}
)} {/* Erro */} {error && !loading && (

Erro ao buscar produtos

{error}

)} {/* Sem Resultados */} {!loading && !error && totalItems === 0 && (

Nenhum produto encontrado

Tente ajustar os filtros ou buscar com outros termos

{hasActiveFilters && ( )}
)} {/* Grid de Produtos */} {!loading && totalItems > 0 && ( <>
{currentPageProducts.map((product, index) => (
))}
{/* Paginação */} {totalPages > 1 && (
)} {/* Informações adicionais */} {cacheState.isCached && (

Dados carregados do cache •

)} )}
); } export default function ResultadosPage() { return (
} > ); }