From 62d4903566d8cc29721564a8d699a10d5e0fb846 Mon Sep 17 00:00:00 2001 From: Christian Vidal Wolf Date: Fri, 6 Feb 2026 09:22:24 +0100 Subject: [PATCH] feat: implement bulk search for ASINs/SKUs in DataGrid --- App.tsx | 1 + components/DataGrid.tsx | 105 +++++++++++++++++++++++++++----------- services/dataProcessor.ts | 38 +++++++++++++- types.ts | 1 + 4 files changed, 114 insertions(+), 31 deletions(-) diff --git a/App.tsx b/App.tsx index 3ddc7ec..4656389 100644 --- a/App.tsx +++ b/App.tsx @@ -69,6 +69,7 @@ const App: React.FC = () => { stock: [], vendorStock: [], woc: [], + bulkSearch: '', }); const top50Mode = useMemo(() => { diff --git a/components/DataGrid.tsx b/components/DataGrid.tsx index e32c264..433d9dd 100644 --- a/components/DataGrid.tsx +++ b/components/DataGrid.tsx @@ -249,6 +249,7 @@ const DataGrid: React.FC = ({ data, hasCustomerFilter, adsData, s const [visibleMetrics, setVisibleMetrics] = useState<('sellOut' | 'units')[]>(['sellOut', 'units']); const [showAdsMetrics, setShowAdsMetrics] = useState(true); const [showAttributedSales, setShowAttributedSales] = useState(false); + const [showBulkSearch, setShowBulkSearch] = useState(false); const [showYTD, setShowYTD] = useState(false); const [showOnlyTop50, setShowOnlyTop50] = useState(false); const [showDimensionMenu, setShowDimensionMenu] = useState(false); @@ -413,16 +414,40 @@ const DataGrid: React.FC = ({ data, hasCustomerFilter, adsData, s // 0. Global Search Filter if (searchTerm) { - const term = searchTerm.toLowerCase().trim(); - result = result.filter(row => { - return ( - (row.sku?.toLowerCase().includes(term)) || - (row.asin?.toLowerCase().includes(term)) || - (row.title?.toLowerCase().includes(term)) || - (row.line?.toLowerCase().includes(term)) || - (row.customer?.toLowerCase().includes(term)) - ); - }); + const rawTerm = searchTerm.trim(); + // Check if it looks like a bulk search (contains newlines or commas) + const isBulk = rawTerm.includes('\n') || rawTerm.includes(',') || rawTerm.includes(' '); + + if (isBulk) { + const searchTerms = rawTerm + .split(/[\s,\n]+/) + .map(t => t.trim().toLowerCase()) + .filter(t => t.length > 0); + + if (searchTerms.length > 0) { + result = result.filter(row => { + const rowSku = row.sku?.toLowerCase() || ''; + const rowAsin = row.asin?.toLowerCase() || ''; + const rowTitle = row.title?.toLowerCase() || ''; + return searchTerms.some(term => + rowSku.includes(term) || + rowAsin.includes(term) || + rowTitle.includes(term) + ); + }); + } + } else { + const term = rawTerm.toLowerCase(); + result = result.filter(row => { + return ( + (row.sku?.toLowerCase().includes(term)) || + (row.asin?.toLowerCase().includes(term)) || + (row.title?.toLowerCase().includes(term)) || + (row.line?.toLowerCase().includes(term)) || + (row.customer?.toLowerCase().includes(term)) + ); + }); + } } // 1. Filter @@ -1329,25 +1354,47 @@ const DataGrid: React.FC = ({ data, hasCustomerFilter, adsData, s
{/* Search Bar */} -
- setSearchTerm(e.target.value)} - className="w-full bg-slate-950 border border-white/10 rounded-xl px-4 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-all pl-10" - /> - - - - {searchTerm && ( - - )} +
+
+ {showBulkSearch ? ( +