'use client'; import axios from 'axios'; import { useRouter } from 'next/navigation'; import React, { useEffect, useMemo, useState } from 'react'; /** ================== Config ================== */ const BACKEND_BASE = process.env.NEXT_PUBLIC_BACKEND_BASEURL || 'https://ebay.backend.data4autos.com'; // Your GET route that lists from tbl_user_products_mapping // Example: GET {BACKEND_BASE}/api/user-products-mapping?userid=...&page=1&pageSize=50&search=... const ENDPOINT_PRODUCTS = `${BACKEND_BASE}/api/motorstate/user-products`; // Optional: where you queue selected products (same as your other page) const ENDPOINT_QUEUE = `${BACKEND_BASE}/api/ebay/withdraw-offer`; /** ================== Types ================== */ type ProductRow = { trand_id: number; user_id: string; id: string | null; // Turn14 item id sku: string | null; imgSrc: string | null; name: string | null; partNumber: string | null; category: string | null; subcategory: string | null; price: number | string | null; // handle either inventory: number | string | null; description: string | null; offer_status: string | null; offer_offerId: string | null; offer_listingId: string | null; offer_categoryId: string | null; offer_url: string | null; offer_error: string | null; created_at: string; updated_at: string; }; type ApiListResp = { code: 'PRODUCT_MAPPING_LIST'; page: number; pageSize: number; total: number; items: ProductRow[]; }; type Filters = { inStockOnly: boolean; priceMin: number; category: string; subcategory: string; offer_status: string; }; /** ================== Helpers ================== */ const toNumber = (val: unknown): number => { if (typeof val === 'number') return Number.isFinite(val) ? val : 0; if (typeof val === 'string') { const cleaned = val.replace(/[^0-9.\-]/g, ''); const n = parseFloat(cleaned); return Number.isFinite(n) ? n : 0; } return 0; }; const quantityToList = (qty: number) => { if (qty <= 1) return 1; if (qty >= 2 && qty <= 8) return qty; return 8; }; /** ================== Component ================== */ const ManageAddedProducts: React.FC = () => { // Session values (only available client-side) const userId = typeof window !== 'undefined' ? sessionStorage.getItem('USERID') : null; const EBAYSTOREID = typeof window !== 'undefined' ? sessionStorage.getItem('EBAYSTOREID') : null; const router = useRouter() // Data state const [items, setItems] = useState([]); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(48); const [total, setTotal] = useState(0); // UI state const [isScrolled, setIsScrolled] = useState(false); const [loading, setLoading] = useState(false); const [toast, setToast] = useState(''); const [toastActive, setToastActive] = useState(false); // Filters / query const [searchText, setSearchText] = useState(''); const [filters, setFilters] = useState({ inStockOnly: false, priceMin: 0, category: '', subcategory: '', offer_status: '', }); // Selection const [selected, setSelected] = useState>({}); const [payment, setPayment] = useState(null); useEffect(() => { const role = localStorage.getItem("user_role"); const sessionId = localStorage.getItem("payment_session"); // ✅ Admins and Partners can access directly (skip payment check) if (role === "admin" || role === "partner") { return; } // 🚫 If no payment session, redirect to pricing if (!sessionId) { router.push("/pricing"); return; } // ✅ Otherwise, check payment details const fetchPaymentDetails = async () => { try { const res: any = await axios.get( "https://ebay.backend.data4autos.com/api/payment/details", { params: { session_id: sessionId } } ); setPayment(res.data.payment); } catch (err) { console.error("Error fetching payment details:", err); } }; fetchPaymentDetails(); }, [router]); /** Scroll shadow effect */ useEffect(() => { const onScroll = () => setIsScrolled(window.scrollY > 10); window.addEventListener('scroll', onScroll); return () => window.removeEventListener('scroll', onScroll); }, []); /** Data loader */ useEffect(() => { if (!userId) return; const load = async () => { setLoading(true); try { const params = new URLSearchParams({ userid: userId, page: String(page), pageSize: String(pageSize), }); if (searchText) params.set('search', searchText); if (filters.category) params.set('category', filters.category); if (filters.subcategory) params.set('subcategory', filters.subcategory); if (filters.offer_status) params.set('offer_status', filters.offer_status); const url = `${ENDPOINT_PRODUCTS}?${params.toString()}`; const res = await fetch(url, { method: 'GET' }); const data: ApiListResp = await res.json(); setItems(data.items || []); setTotal(data.total || 0); setToast(`Loaded ${data.items?.length || 0} items (Total: ${data.total || 0})`); setTimeout(() => setToast(''), 3000); } catch (e) { console.error(e); setToast('Failed to load products'); setTimeout(() => setToast(''), 3000); } finally { setLoading(false); } }; load(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [userId, page, pageSize, searchText, filters.category, filters.subcategory, filters.offer_status]); /** Dropdown options (use Array.from to avoid TS downlevel iteration issue) */ const categoryOptions = useMemo(() => { const s = new Set(); items.forEach((i) => i.category && s.add(i.category)); return [''].concat(Array.from(s).sort()); }, [items]); const subcategoryOptions = useMemo(() => { const s = new Set(); items.forEach((i) => { if (!filters.category || i.category === filters.category) { i.subcategory && s.add(i.subcategory); } }); return [''].concat(Array.from(s).sort()); }, [items, filters.category]); const offerStatusOptions = useMemo(() => { const s = new Set(); items.forEach((i) => i.offer_status && s.add(i.offer_status)); return [''].concat(Array.from(s).sort()); }, [items]); /** Client-side filters (in-stock & price floor + search) */ const filteredItems = useMemo(() => { return items.filter((it) => { const inv = toNumber(it.inventory); const price = toNumber(it.price); if (filters.inStockOnly && inv <= 0) return false; if (price < filters.priceMin) return false; if (searchText) { const hay = `${it.id ?? ''} ${it.sku ?? ''} ${it.name ?? ''} ${it.partNumber ?? ''} ${it.category ?? ''} ${it.subcategory ?? ''}`.toLowerCase(); if (!hay.includes(searchText.toLowerCase())) return false; } return true; }); }, [items, filters.inStockOnly, filters.priceMin, searchText]); /** Selection helpers */ const selectedCount = useMemo(() => Object.keys(selected).length, [selected]); const isSelected = (row: ProductRow) => Boolean(selected[row.trand_id]); const toggleSelect = (row: ProductRow) => { setSelected((prev) => { const copy = { ...prev }; if (copy[row.trand_id]) delete copy[row.trand_id]; else copy[row.trand_id] = row; return copy; }); }; const toggleSelectAllVisible = () => { setSelected((prev) => { const copy = { ...prev }; const allVisibleSelected = filteredItems.length > 0 && filteredItems.every((it) => copy[it.trand_id]); if (allVisibleSelected) { filteredItems.forEach((it) => { if (copy[it.trand_id]) delete copy[it.trand_id]; }); } else { filteredItems.forEach((it) => (copy[it.trand_id] = it)); } return copy; }); }; const clearVisibleSelection = () => { setSelected((prev) => { const copy = { ...prev }; filteredItems.forEach((it) => { if (copy[it.trand_id]) delete copy[it.trand_id]; }); return copy; }); }; /** Queue selected products (mirrors your other page’s payload shape) */ const handleAddSelectedProducts = async () => { const picked = Object.values(selected); const queuePayload = picked.map(x => x.offer_offerId) console.log('Adding products:', queuePayload); setToast(`Queued ${queuePayload.length} product(s)`); try { const res = await fetch(ENDPOINT_QUEUE, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userKey: EBAYSTOREID, products: queuePayload, userId, }), }); const data = await res.json(); console.log('Queue response:', data); setToastActive(true); setTimeout(() => setToastActive(false), 2500); } catch (e) { console.error(e); setToast('Failed to queue products'); } }; const totalPages = Math.max(1, Math.ceil(total / pageSize)); /** ================== Render ================== */ return (
{/* Sticky Header */}

Data4Autos – Your Listed Products

Showing {filteredItems.length} of {items.length} (Total in DB: {total})

Selected: {selectedCount}

{/* Search */}
{ setPage(1); setSearchText(e.target.value); }} placeholder="Search (sku, name, id)…" className="block w-full pl-10 pr-3 py-2.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors" />
{/* In-stock-only pill toggle */}
{/* Global Filters */}
{/* Category */} {/* Subcategory */} {/* Offer Status */} {/* Price Floor */}
Price Floor
setFilters((f) => ({ ...f, priceMin: toNumber(e.target.value) })) } className="w-full" aria-label="Minimum price" /> setFilters((f) => ({ ...f, priceMin: toNumber(e.target.value) })) } className="w-24 px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
Showing items with price ≥ ${filters.priceMin}
{/* Pagination Controls */}
Page {page} of{' '} {Math.max(1, Math.ceil(total / pageSize))}
{/* Grid */}
{loading ? (
Loading products…
) : filteredItems.length === 0 ? (
{/* Icon Circle */}
{/* Text */}

No Products Found

No products match the current filters. Try adjusting your search or filters to find what you need.

{/* Button */} {/* */} {/* Decorative Blur Circle */}
) : ( <>
Showing {filteredItems.length} of{' '} {items.length}
{Object.values(selected).some((r) => filteredItems.find((fi) => fi.trand_id === r.trand_id) ) && ( )}
{filteredItems.map((it) => { const img = it.imgSrc || 'https://cdn.shopify.com/s/files/1/0757/9955/files/no-image_280x@2x.png'; const inv = toNumber(it.inventory); const price = toNumber(it.price); const willList = quantityToList(inv); return (
{/* Select */}
Will list: {willList}
{it.name
{it.name || 'Unnamed Product'}
Part #: {it.partNumber || '-'}
{it.category || '-'} > {it.subcategory || '-'}
Price:{' '} {Number.isFinite(price) && price > 0 ? `$${price.toFixed(2)}` : '-'}
Inventory: {inv}
{it.description && (

{it.description}

)} {/* Offer / URL badges */}
{it.offer_status && ( {it.offer_status} )} {it.offer_url && ( Listing )}
); })}
)}
{/* Toasts */} {toast && (
{toast}
)} {toastActive && (
Products Unlisted successfully!
)} {/* Tiny animation helper */}
); }; export default ManageAddedProducts;