mirror of
https://github.com/christianvidalwolf-prog/Craze-Data-check.git
synced 2026-08-03 15:15:24 +02:00
Add column filters for Units/Outer and Outer W/L/H in Pricing tab
Add dropdown filters to filter by specific values in Units/Outer, Outer W, Outer L, Outer H columns
This commit is contained in:
+130
-10
@@ -55,7 +55,15 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
|
||||
const [lineMultiFilter, setLineMultiFilter] = useState<string[]>([]);
|
||||
const [classificationFilter, setClassificationFilter] = useState<string[]>([]);
|
||||
const [nameColFilter, setNameColFilter] = useState('');
|
||||
const [openFilter, setOpenFilter] = useState<'name' | 'line' | 'classification' | null>(null);
|
||||
const [openFilter, setOpenFilter] = useState<'name' | 'line' | 'classification' | 'unitsOuter' | 'outerW' | 'outerL' | 'outerH' | 'srp' | 'container' | null>(null);
|
||||
const [unitsOuterFilter, setUnitsOuterFilter] = useState<string[]>([]);
|
||||
const [outerWFilter, setOuterWFilter] = useState<string[]>([]);
|
||||
const [outerLFilter, setOuterLFilter] = useState<string[]>([]);
|
||||
const [outerHFilter, setOuterHFilter] = useState<string[]>([]);
|
||||
const [srpFilter, setSrpFilter] = useState<string[]>([]);
|
||||
const [containerFilter, setContainerFilter] = useState<string[]>([]);
|
||||
const [srpColFilter, setSrpColFilter] = useState<string[]>([]);
|
||||
const [containerColFilter, setContainerColFilter] = useState<string[]>([]);
|
||||
|
||||
// ── Dynamic column detection ──────────────────────────────────────────────
|
||||
const { uvpIdx, srpCols, containerCols } = useMemo(() => {
|
||||
@@ -146,6 +154,22 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
|
||||
Array.from(new Set(data.map(r => String(r[COLUMNS.CLASSIFICATION] || '')))).sort(),
|
||||
[data]);
|
||||
|
||||
const uniqueUnitsOuter = useMemo(() =>
|
||||
Array.from(new Set(data.map(r => String(r[COLUMNS.UNITS_OUTER] || '')))).filter(v => v).sort(),
|
||||
[data]);
|
||||
|
||||
const uniqueOuterW = useMemo(() =>
|
||||
Array.from(new Set(data.map(r => String(r[COLUMNS.OUTER_W] || '')))).filter(v => v).sort((a, b) => Number(a) - Number(b)),
|
||||
[data]);
|
||||
|
||||
const uniqueOuterL = useMemo(() =>
|
||||
Array.from(new Set(data.map(r => String(r[COLUMNS.OUTER_L] || '')))).filter(v => v).sort((a, b) => Number(a) - Number(b)),
|
||||
[data]);
|
||||
|
||||
const uniqueOuterH = useMemo(() =>
|
||||
Array.from(new Set(data.map(r => String(r[COLUMNS.OUTER_H] || '')))).filter(v => v).sort((a, b) => Number(a) - Number(b)),
|
||||
[data]);
|
||||
|
||||
// ── Filtered rows ─────────────────────────────────────────────────────────
|
||||
const filteredRows = useMemo(() => {
|
||||
let result = analyzedRows;
|
||||
@@ -177,9 +201,21 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
|
||||
if (classificationFilter.length > 0) {
|
||||
result = result.filter(r => classificationFilter.includes(String(r.row[COLUMNS.CLASSIFICATION] || '')));
|
||||
}
|
||||
if (unitsOuterFilter.length > 0) {
|
||||
result = result.filter(r => unitsOuterFilter.includes(String(r.row[COLUMNS.UNITS_OUTER] || '')));
|
||||
}
|
||||
if (outerWFilter.length > 0) {
|
||||
result = result.filter(r => outerWFilter.includes(String(r.row[COLUMNS.OUTER_W] || '')));
|
||||
}
|
||||
if (outerLFilter.length > 0) {
|
||||
result = result.filter(r => outerLFilter.includes(String(r.row[COLUMNS.OUTER_L] || '')));
|
||||
}
|
||||
if (outerHFilter.length > 0) {
|
||||
result = result.filter(r => outerHFilter.includes(String(r.row[COLUMNS.OUTER_H] || '')));
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [analyzedRows, filterMode, search, nameColFilter, lineMultiFilter, classificationFilter]);
|
||||
}, [analyzedRows, filterMode, search, nameColFilter, lineMultiFilter, classificationFilter, unitsOuterFilter, outerWFilter, outerLFilter, outerHFilter]);
|
||||
|
||||
// ── Inline edit helpers ───────────────────────────────────────────────────
|
||||
const startEdit = (rowIndex: number, colIndex: number, currentValue: string) => {
|
||||
@@ -441,23 +477,107 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
|
||||
))}
|
||||
|
||||
{/* Units/Outer */}
|
||||
<th className="text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider border-b border-slate-700 whitespace-nowrap">
|
||||
Units/Outer
|
||||
<th className="text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider border-b border-slate-700 whitespace-nowrap group relative">
|
||||
<div className="flex items-center gap-1">
|
||||
<span>Units/Outer</span>
|
||||
<button
|
||||
onClick={() => setOpenFilter(openFilter === 'unitsOuter' ? null : 'unitsOuter')}
|
||||
className={cn(
|
||||
'p-0.5 rounded hover:bg-slate-700 transition-colors',
|
||||
unitsOuterFilter.length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
|
||||
)}
|
||||
>
|
||||
<Filter className="w-3 h-3" />
|
||||
</button>
|
||||
</div>
|
||||
{openFilter === 'unitsOuter' && (
|
||||
<ColumnFilterPopover
|
||||
uniqueValues={uniqueUnitsOuter}
|
||||
selectedValues={unitsOuterFilter}
|
||||
onToggle={val => setUnitsOuterFilter(prev => prev.includes(val) ? prev.filter(v => v !== val) : [...prev, val])}
|
||||
onSelectAll={vals => setUnitsOuterFilter(vals)}
|
||||
onClear={() => { setUnitsOuterFilter([]); setOpenFilter(null); }}
|
||||
onClose={() => setOpenFilter(null)}
|
||||
/>
|
||||
)}
|
||||
</th>
|
||||
|
||||
{/* Outer W */}
|
||||
<th className="text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider border-b border-slate-700 whitespace-nowrap">
|
||||
Outer W
|
||||
<th className="text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider border-b border-slate-700 whitespace-nowrap group relative">
|
||||
<div className="flex items-center gap-1">
|
||||
<span>Outer W</span>
|
||||
<button
|
||||
onClick={() => setOpenFilter(openFilter === 'outerW' ? null : 'outerW')}
|
||||
className={cn(
|
||||
'p-0.5 rounded hover:bg-slate-700 transition-colors',
|
||||
outerWFilter.length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
|
||||
)}
|
||||
>
|
||||
<Filter className="w-3 h-3" />
|
||||
</button>
|
||||
</div>
|
||||
{openFilter === 'outerW' && (
|
||||
<ColumnFilterPopover
|
||||
uniqueValues={uniqueOuterW}
|
||||
selectedValues={outerWFilter}
|
||||
onToggle={val => setOuterWFilter(prev => prev.includes(val) ? prev.filter(v => v !== val) : [...prev, val])}
|
||||
onSelectAll={vals => setOuterWFilter(vals)}
|
||||
onClear={() => { setOuterWFilter([]); setOpenFilter(null); }}
|
||||
onClose={() => setOpenFilter(null)}
|
||||
/>
|
||||
)}
|
||||
</th>
|
||||
|
||||
{/* Outer L */}
|
||||
<th className="text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider border-b border-slate-700 whitespace-nowrap">
|
||||
Outer L
|
||||
<th className="text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider border-b border-slate-700 whitespace-nowrap group relative">
|
||||
<div className="flex items-center gap-1">
|
||||
<span>Outer L</span>
|
||||
<button
|
||||
onClick={() => setOpenFilter(openFilter === 'outerL' ? null : 'outerL')}
|
||||
className={cn(
|
||||
'p-0.5 rounded hover:bg-slate-700 transition-colors',
|
||||
outerLFilter.length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
|
||||
)}
|
||||
>
|
||||
<Filter className="w-3 h-3" />
|
||||
</button>
|
||||
</div>
|
||||
{openFilter === 'outerL' && (
|
||||
<ColumnFilterPopover
|
||||
uniqueValues={uniqueOuterL}
|
||||
selectedValues={outerLFilter}
|
||||
onToggle={val => setOuterLFilter(prev => prev.includes(val) ? prev.filter(v => v !== val) : [...prev, val])}
|
||||
onSelectAll={vals => setOuterLFilter(vals)}
|
||||
onClear={() => { setOuterLFilter([]); setOpenFilter(null); }}
|
||||
onClose={() => setOpenFilter(null)}
|
||||
/>
|
||||
)}
|
||||
</th>
|
||||
|
||||
{/* Outer H */}
|
||||
<th className="text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider border-b border-slate-700 whitespace-nowrap">
|
||||
Outer H
|
||||
<th className="text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider border-b border-slate-700 whitespace-nowrap group relative">
|
||||
<div className="flex items-center gap-1">
|
||||
<span>Outer H</span>
|
||||
<button
|
||||
onClick={() => setOpenFilter(openFilter === 'outerH' ? null : 'outerH')}
|
||||
className={cn(
|
||||
'p-0.5 rounded hover:bg-slate-700 transition-colors',
|
||||
outerHFilter.length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
|
||||
)}
|
||||
>
|
||||
<Filter className="w-3 h-3" />
|
||||
</button>
|
||||
</div>
|
||||
{openFilter === 'outerH' && (
|
||||
<ColumnFilterPopover
|
||||
uniqueValues={uniqueOuterH}
|
||||
selectedValues={outerHFilter}
|
||||
onToggle={val => setOuterHFilter(prev => prev.includes(val) ? prev.filter(v => v !== val) : [...prev, val])}
|
||||
onSelectAll={vals => setOuterHFilter(vals)}
|
||||
onClear={() => { setOuterHFilter([]); setOpenFilter(null); }}
|
||||
onClose={() => setOpenFilter(null)}
|
||||
/>
|
||||
)}
|
||||
</th>
|
||||
|
||||
{/* Container columns */}
|
||||
|
||||
Reference in New Issue
Block a user