feat: add filter to Issues column in Pricing view

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Christian Vidal Wolf
2026-04-22 14:39:04 +02:00
co-authored by Claude Sonnet 4.6
parent db25ea793d
commit e7f88c67e6
+38 -3
View File
@@ -82,6 +82,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
const [outerLFilter, setOuterLFilter] = useState<string[]>([]);
const [outerHFilter, setOuterHFilter] = useState<string[]>([]);
const [dynamicColFilters, setDynamicColFilters] = useState<Record<number, string[]>>({});
const [weightIssueFilter, setWeightIssueFilter] = useState<'all' | 'with' | 'without'>('all');
const [editingType, setEditingType] = useState<{ rowIndex: number; value: string } | null>(null);
const [typeSuggestions, setTypeSuggestions] = useState<string[]>([]);
const typeInputRef = useRef<HTMLInputElement>(null);
@@ -345,8 +346,15 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
}
});
// Weight issue filter
if (weightIssueFilter === 'with') {
result = result.filter(r => r.unitErrors.some(e => e.startsWith('NW')));
} else if (weightIssueFilter === 'without') {
result = result.filter(r => !r.unitErrors.some(e => e.startsWith('NW')));
}
return result;
}, [analyzedRows, filterMode, search, nameColFilter, lineMultiFilter, classificationFilter, unitsOuterFilter, outerWFilter, outerLFilter, outerHFilter, dynamicColFilters]);
}, [analyzedRows, filterMode, search, nameColFilter, lineMultiFilter, classificationFilter, unitsOuterFilter, outerWFilter, outerLFilter, outerHFilter, dynamicColFilters, weightIssueFilter]);
// ── Sorted rows ──────────────────────────────────────────────────────────
const sortedRows = useMemo(() => {
@@ -1057,8 +1065,35 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
);
})}
<th style={{ width: 180 }} className="text-left px-3 py-3 text-xs font-semibold text-red-400 uppercase tracking-wider border-b border-slate-700 whitespace-nowrap relative">
Issues
<th style={{ width: 180 }} className="text-left px-3 py-3 text-xs font-semibold text-red-400 uppercase tracking-wider border-b border-slate-700 whitespace-nowrap group relative">
<div className="flex items-center gap-1">
<span>Issues</span>
<button
onClick={() => setOpenFilter(openFilter === 'weightIssue' ? null : 'weightIssue')}
className={cn(
'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0',
weightIssueFilter !== 'all' ? 'text-red-400 bg-red-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
)}
>
<Filter className="w-3 h-3" />
</button>
</div>
{openFilter === 'weightIssue' && (
<div className="absolute top-full left-0 mt-1 w-44 bg-slate-800 border border-slate-700 rounded-lg shadow-2xl z-50 p-1 flex flex-col gap-0.5 animate-in fade-in zoom-in-95 duration-100">
{(['all', 'with', 'without'] as const).map(opt => (
<button
key={opt}
onClick={() => { setWeightIssueFilter(opt); setOpenFilter(null); }}
className={cn(
'w-full text-left px-3 py-1.5 rounded text-xs transition-colors',
weightIssueFilter === opt ? 'bg-red-500/20 text-red-400' : 'text-slate-300 hover:bg-slate-700'
)}
>
{opt === 'all' ? 'All' : opt === 'with' ? 'With weight issue' : 'No weight issue'}
</button>
))}
</div>
)}
</th>
<th style={{ width: columnWidths.check }} className="text-left px-3 py-3 text-xs font-semibold text-blue-400 uppercase tracking-wider group cursor-pointer hover:bg-slate-800/50 transition-colors relative" onClick={() => handleSort(COLUMNS.VALIDATED_CHECK)}>