feat: add Classification column and Excel-style column filters to Pricing & Units tab

- Added Classification column next to Line with color-coded badges (Core=blue, OOC=amber)
- Added Excel-style filter icons on Article Name (text search), Line, and Classification headers
- Filter icons appear on hover; turn blue when active
- Multi-select popover for Line and Classification; free-text popover for Article Name
- Filters work additively alongside the existing global search bar
- ArticleDetails: removed Tariff/Barcode/Origin columns and tab to simplify the view

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Christian Vidal Wolf
2026-04-08 16:37:40 +02:00
co-authored by Claude Sonnet 4.6
parent 04d198ea59
commit 71af4e1915
2 changed files with 192 additions and 21 deletions
+4 -13
View File
@@ -8,7 +8,7 @@ interface ArticleDetailsProps {
onEdit: (index: number) => void;
}
type TabType = 'all' | 'missingDetailsDE' | 'missingDetailsEN' | 'missingAnyDetails' | 'lowStock' | 'missingTariff';
type TabType = 'all' | 'missingDetailsDE' | 'missingDetailsEN' | 'missingAnyDetails' | 'lowStock';
export function ArticleDetails({ data, onEdit }: ArticleDetailsProps) {
const [activeTab, setActiveTab] = useState<TabType>('all');
@@ -29,15 +29,13 @@ export function ArticleDetails({ data, onEdit }: ArticleDetailsProps) {
if (activeTab === 'missingDetailsEN') result = result.filter(r => !r.row[COLUMNS.DETAILS_EN]);
if (activeTab === 'missingAnyDetails') result = result.filter(r => !r.row[COLUMNS.DETAILS_DE] || !r.row[COLUMNS.DETAILS_EN]);
if (activeTab === 'lowStock') result = result.filter(r => Number(r.row[COLUMNS.ITEM_AVAILABLE] || 0) <= 0);
if (activeTab === 'missingTariff') result = result.filter(r => !r.row[COLUMNS.TARIFF_CODE]);
// Search filter
if (search) {
const s = search.toLowerCase();
result = result.filter(r =>
String(r.row[COLUMNS.ARTICLE_NO] || '').toLowerCase().includes(s) ||
String(r.row[COLUMNS.ARTICLE_NAME] || '').toLowerCase().includes(s) ||
String(r.row[COLUMNS.BARCODE] || '').toLowerCase().includes(s)
String(r.row[COLUMNS.ARTICLE_NAME] || '').toLowerCase().includes(s)
);
}
@@ -98,7 +96,6 @@ export function ArticleDetails({ data, onEdit }: ArticleDetailsProps) {
{ id: 'missingDetailsEN', label: 'No Details EN' },
{ id: 'missingAnyDetails', label: 'Missing Details' },
{ id: 'lowStock', label: 'Out of Stock' },
{ id: 'missingTariff', label: 'No Tariff Code' },
];
return (
@@ -125,7 +122,7 @@ export function ArticleDetails({ data, onEdit }: ArticleDetailsProps) {
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-500" />
<input
type="text"
placeholder="Search SKU, Name, Barcode..."
placeholder="Search SKU or Name..."
value={search}
onChange={e => { setSearch(e.target.value); setPage(1); }}
className="w-full pl-9 pr-4 py-2 bg-slate-900/50 border border-slate-700 rounded-md text-sm text-white focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
@@ -149,9 +146,6 @@ export function ArticleDetails({ data, onEdit }: ArticleDetailsProps) {
{[
{ col: COLUMNS.ARTICLE_NO, label: 'SKU' },
{ col: COLUMNS.ARTICLE_NAME, label: 'Name' },
{ col: COLUMNS.BARCODE, label: 'Barcode' },
{ col: COLUMNS.TARIFF_CODE, label: 'Tariff' },
{ col: COLUMNS.COUNTRY_ORIGIN, label: 'Origin' },
{ col: COLUMNS.CLASSIFICATION, label: 'Class' },
{ col: COLUMNS.ITEM_AVAILABLE, label: 'Stock' },
{ col: COLUMNS.DETAILS_DE, label: 'Details DE' },
@@ -180,9 +174,6 @@ export function ArticleDetails({ data, onEdit }: ArticleDetailsProps) {
<td className="px-3 py-2 font-medium text-slate-200 max-w-[150px] truncate" title={row[COLUMNS.ARTICLE_NAME]}>
{row[COLUMNS.ARTICLE_NAME]}
</td>
<td className="px-3 py-2 text-slate-400">{row[COLUMNS.BARCODE] || '—'}</td>
<td className="px-3 py-2 text-slate-400">{row[COLUMNS.TARIFF_CODE] || '—'}</td>
<td className="px-3 py-2 text-slate-400">{row[COLUMNS.COUNTRY_ORIGIN] || '—'}</td>
<td className="px-3 py-2">
<span className={cn(
"px-1.5 py-0.5 rounded-[4px] text-[10px] font-bold border",
@@ -221,7 +212,7 @@ export function ArticleDetails({ data, onEdit }: ArticleDetailsProps) {
))}
{paginatedData.length === 0 && (
<tr>
<td colSpan={10} className="px-4 py-8 text-center text-slate-500">
<td colSpan={7} className="px-4 py-8 text-center text-slate-500">
No articles found.
</td>
</tr>