diff --git a/components/WeeklyGrid.tsx b/components/WeeklyGrid.tsx index 867e10b..31f39ca 100644 --- a/components/WeeklyGrid.tsx +++ b/components/WeeklyGrid.tsx @@ -19,6 +19,8 @@ const WeeklyGrid: React.FC = ({ data }) => { const [searchTerm, setSearchTerm] = useState(''); const [currentPage, setCurrentPage] = useState(1); + const [growthFilterMode, setGrowthFilterMode] = useState<'all' | 'up' | 'down' | 'stable'>('all'); + const [growthThreshold, setGrowthThreshold] = useState(10); // Default sort: most recent week, descending, units const [sortConfig, setSortConfig] = useState(() => { @@ -46,15 +48,50 @@ const WeeklyGrid: React.FC = ({ data }) => { // 1. Filter by search term const filteredRows = useMemo(() => { - if (!searchTerm) return rows; - const lowSearch = searchTerm.toLowerCase(); - return rows.filter(r => - r.sku.toLowerCase().includes(lowSearch) || - r.asin.toLowerCase().includes(lowSearch) || - r.title.toLowerCase().includes(lowSearch) || - r.line.toLowerCase().includes(lowSearch) - ); - }, [rows, searchTerm]); + let result = rows; + + // 1. Search Filter + if (searchTerm) { + const lowSearch = searchTerm.toLowerCase(); + result = result.filter(r => + r.sku.toLowerCase().includes(lowSearch) || + r.asin.toLowerCase().includes(lowSearch) || + r.title.toLowerCase().includes(lowSearch) || + r.line.toLowerCase().includes(lowSearch) + ); + } + + // 2. Growth Filter (if active) + if (growthFilterMode !== 'all' && sortConfig) { + const currentWeek = sortConfig.key; + const currentWeekIdx = weeks.indexOf(currentWeek); + const prevWeek = weeks[currentWeekIdx + 1]; + + if (prevWeek) { + result = result.filter(r => { + const currentUnits = r.unitsByWeek[currentWeek] || 0; + const prevUnits = r.unitsByWeek[prevWeek] || 0; + + // Handle edge case: units were 0 in previous week + if (prevUnits === 0) { + if (currentUnits === 0) return growthFilterMode === 'stable'; + return growthFilterMode === 'up'; // Gained from 0 + } + + // Calculate percentage growth + const growth = ((currentUnits - prevUnits) / prevUnits) * 100; + + // For 'down', we use the absolute threshold to check if it dropped BY at least that amount + if (growthFilterMode === 'up') return growth >= growthThreshold; + if (growthFilterMode === 'down') return growth <= -Math.abs(growthThreshold); + if (growthFilterMode === 'stable') return Math.abs(growth) < growthThreshold; + return true; + }); + } + } + + return result; + }, [rows, searchTerm, growthFilterMode, growthThreshold, sortConfig, weeks]); // 2. Sort results const sortedRows = useMemo(() => { @@ -109,41 +146,71 @@ const WeeklyGrid: React.FC = ({ data }) => { return (
{/* Toolbar: Search & Pagination */} -
-
- setSearchTerm(e.target.value)} - className="w-full bg-slate-950 border border-white/10 rounded-lg px-4 py-2 text-base text-white focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-all pl-10" - /> - - - +
+
+ {/* Search Input */} +
+ setSearchTerm(e.target.value)} + className="w-full bg-slate-950 border border-white/10 rounded-lg px-4 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-all pl-10" + /> + + + +
+ + {/* Growth Filter */} +
+ Growth Filter + + {growthFilterMode !== 'all' && ( +
+ Thresh: + setGrowthThreshold(Number(e.target.value))} + className="w-12 bg-slate-900 border border-white/10 rounded px-1.5 py-1 text-xs text-white text-center focus:outline-none focus:ring-1 focus:ring-indigo-500" + /> + % +
+ )} +
- - Showing {Math.min(sortedRows.length, (currentPage - 1) * ROWS_PER_PAGE + 1)}-{Math.min(sortedRows.length, currentPage * ROWS_PER_PAGE)} of {sortedRows.length} + + Showing {Math.min(filteredRows.length, (currentPage - 1) * ROWS_PER_PAGE + 1)}-{Math.min(filteredRows.length, currentPage * ROWS_PER_PAGE)} of {filteredRows.length}
- + {currentPage} / {Math.max(1, totalPages)}