'use client'; import { useState, useEffect, useMemo, useCallback } from 'react'; import Link from 'next/link'; import Image from 'next/image'; import { useRouter, useSearchParams } from 'next/navigation'; import { catalogService, CategoryResponse, CategoryParentHierarchyResponse, HierarchyBrandItem, HierarchySeriesItem, HierarchyModelItem, ProductResponse, } from '@/services/api/catalogService'; import { BrandSelector } from './BrandSelector'; import { SeriesSelector } from './SeriesSelector'; import { ModelSelector } from './ModelSelector'; import { StandardCatalog } from './StandardCatalog'; import { formatCurrency, getCatalogPriceInfo, getImageUrl } from '@/lib/utils'; import { ShoppingCart, Heart, ArrowLeftRight, Search, RotateCcw } from 'lucide-react'; import { useCartStore } from '@/store/cartStore'; import { mapProductCardToProductResponse } from '@/utils/productMapper'; import { addToCompareAndNavigate } from '@/lib/compare'; import BlurHashImage from '@/components/ui/BlurHashImage'; interface ParentFeatureCatalogProps { category: CategoryResponse; } export function ParentFeatureCatalog({ category }: ParentFeatureCatalogProps) { const router = useRouter(); const searchParams = useSearchParams(); // Hierarchy Data state fetched once const [hierarchy, setHierarchy] = useState(null); const [isHierarchyLoading, setIsHierarchyLoading] = useState(true); // Model search input state const [modelSearchQuery, setModelSearchQuery] = useState(''); // Selection states derived from / synced with URL search params const brandParam = searchParams.get('brand'); const seriesParam = searchParams.get('series'); const modelParam = searchParams.get('model'); // Filtered Products state const [products, setProducts] = useState([]); const [totalProducts, setTotalProducts] = useState(0); const [isProductsLoading, setIsProductsLoading] = useState(true); const addToCart = useCartStore((state) => state.addToCart); const toggleWishlist = useCartStore((state) => state.toggleWishlist); const wishlist = useCartStore((state) => state.wishlist); const compareList = useCartStore((state) => state.compareList); // Fetch Parent Hierarchy Data ONCE for this category useEffect(() => { setIsHierarchyLoading(true); catalogService .getParentHierarchy(category.category_id) .then((data) => { setHierarchy(data); }) .catch(() => { setHierarchy(null); }) .finally(() => { setIsHierarchyLoading(false); }); }, [category.category_id]); // Derived Active Brands list const brands: HierarchyBrandItem[] = useMemo(() => { return hierarchy?.brands || []; }, [hierarchy]); // Find currently selected Brand object from URL param or ID/slug const selectedBrandObj = useMemo(() => { if (!brandParam || brands.length === 0) return null; return ( brands.find( (b) => b.brand_id === brandParam || b.slug.toLowerCase() === brandParam.toLowerCase() ) || null ); }, [brands, brandParam]); // Derived Series list for the selected Brand const seriesList: HierarchySeriesItem[] = useMemo(() => { return selectedBrandObj?.series || []; }, [selectedBrandObj]); // Find currently selected Series object const selectedSeriesObj = useMemo(() => { if (!seriesParam || seriesList.length === 0) return null; return ( seriesList.find( (s) => s.series_id === seriesParam || s.slug.toLowerCase() === seriesParam.toLowerCase() ) || null ); }, [seriesList, seriesParam]); // Derived Models list for selected Series or all Series under Brand const rawModelsList: HierarchyModelItem[] = useMemo(() => { if (selectedSeriesObj) { return selectedSeriesObj.models; } if (selectedBrandObj) { return selectedBrandObj.series.flatMap((s) => s.models); } return []; }, [selectedBrandObj, selectedSeriesObj]); // Filter models live by search query input const modelsList: HierarchyModelItem[] = useMemo(() => { if (!modelSearchQuery.trim()) return rawModelsList; const q = modelSearchQuery.toLowerCase(); return rawModelsList.filter((m) => m.name.toLowerCase().includes(q)); }, [rawModelsList, modelSearchQuery]); // Find currently selected Model object const selectedModelObj = useMemo(() => { if (!modelParam || rawModelsList.length === 0) return null; return ( rawModelsList.find( (m) => m.model_id === modelParam || m.slug.toLowerCase() === modelParam.toLowerCase() ) || null ); }, [rawModelsList, modelParam]); // URL State Updater Helper - Preserves category while updating selection const updateUrlParams = useCallback( (brandId: string | null, seriesId: string | null, modelId: string | null) => { const params = new URLSearchParams(); params.set('category', category.slug || category.category_id); if (brandId) params.set('brand', brandId); if (seriesId) params.set('series', seriesId); if (modelId) params.set('model', modelId); router.push(`/products?${params.toString()}`, { scroll: false }); }, [category, router] ); // Normalize invalid URL params safely useEffect(() => { if (isHierarchyLoading || !hierarchy) return; let shouldNormalize = false; let validBrand = brandParam; let validSeries = seriesParam; let validModel = modelParam; if (brandParam && !selectedBrandObj) { validBrand = null; validSeries = null; validModel = null; shouldNormalize = true; } else if (seriesParam && !selectedSeriesObj) { validSeries = null; validModel = null; shouldNormalize = true; } else if (modelParam && !selectedModelObj) { validModel = null; shouldNormalize = true; } if (shouldNormalize) { updateUrlParams(validBrand, validSeries, validModel); } }, [ isHierarchyLoading, hierarchy, brandParam, seriesParam, modelParam, selectedBrandObj, selectedSeriesObj, selectedModelObj, updateUrlParams, ]); // Handle Brand Selection const handleSelectBrand = (brandId: string | null) => { updateUrlParams(brandId, null, null); }; // Handle Series Selection const handleSelectSeries = (seriesId: string | null) => { const brandId = selectedBrandObj?.brand_id || null; updateUrlParams(brandId, seriesId, null); }; // Handle Model Selection const handleSelectModel = (modelId: string | null) => { const brandId = selectedBrandObj?.brand_id || null; const seriesId = selectedSeriesObj?.series_id || null; updateUrlParams(brandId, seriesId, modelId); }; // Fetch Products based on selected filters useEffect(() => { setIsProductsLoading(true); const params: Record = { category: category.category_id, page: 1, limit: 36, }; if (selectedBrandObj) { params.brand = selectedBrandObj.brand_id; } if (selectedSeriesObj) { params.series = selectedSeriesObj.series_id; } if (selectedModelObj) { params.model = selectedModelObj.model_id; } catalogService .getProductsPaginated(params) .then((res) => { const mapped: ProductResponse[] = res.products.map((p) => mapProductCardToProductResponse({ ...p, category_id: p.category_id || category.category_id, brand_id: selectedBrandObj?.brand_id || '', device_series_id: selectedSeriesObj?.series_id || '', device_model_id: selectedModelObj?.model_id || '', }) ); setProducts(mapped); setTotalProducts(res.total); }) .catch(() => { setProducts([]); setTotalProducts(0); }) .finally(() => { setIsProductsLoading(false); }); }, [category.category_id, selectedBrandObj, selectedSeriesObj, selectedModelObj]); // Fallback to StandardCatalog if hierarchy has no brands if (!isHierarchyLoading && (!hierarchy || brands.length === 0)) { return ; } return (
{/* Top tools bar */}
{/* Top-left Brand Logo & Title */}
iFix Kart
{category.name}
{/* Quick Search Model Input Box */}
setModelSearchQuery(e.target.value)} className="w-full pl-9 pr-4 py-2 bg-gray-50 border border-gray-200 rounded-xl text-xs text-gray-800 focus:outline-none focus:border-gray-400 focus:bg-white transition-all placeholder:text-gray-400" />
{/* Level 1: Select Brand Cards (Image 3) */} {/* Level 2: Select Series Pills (Image 2) */} {selectedBrandObj && seriesList.length > 0 && ( )} {/* Level 3: Select Model Cards (Image 2) */} {selectedBrandObj && modelsList.length > 0 && ( )} {/* Filtered Products Section */}

{selectedModelObj ? `${selectedModelObj.name} Products` : selectedSeriesObj ? `${selectedSeriesObj.name} Products` : selectedBrandObj ? `${selectedBrandObj.name} Products` : `All ${category.name} Products`}

Showing {products.length} of {totalProducts} items

{(selectedBrandObj || selectedSeriesObj || selectedModelObj) && ( )}
{/* Products Grid */} {isProductsLoading ? (
{[...Array(8)].map((_, i) => (
))}
) : products.length === 0 ? (

No products available for this selection.

) : (
{products.map((p) => { const firstVariant = p.variants?.[0]; const { price, oldPrice: comparePrice } = getCatalogPriceInfo(p); const primaryImage = getImageUrl(p.images?.[0]?.image_url); const isWishlisted = wishlist.some((item) => item.product_id === p.product_id); const isCompared = compareList.some((item) => item.product_id === p.product_id); return (
{p.badge && ( {p.badge} )}

{p.name}

{formatCurrency(price)}
{comparePrice && comparePrice > price && (
{formatCurrency(comparePrice)}
)}
); })}
)}
); }