show all cosmetic items by cpnp filter

This commit is contained in:
Christian Vidal Wolf
2026-05-20 15:02:48 +02:00
parent 39a3588078
commit 1d5f918a0a
+31 -7
View File
@@ -27,12 +27,12 @@ export function CosmeticItemsView({ data, headers, onSaveRow, onCaptureState, ro
const [search, setSearch] = usePersistentState('cosmeticItems-search', ''); const [search, setSearch] = usePersistentState('cosmeticItems-search', '');
const [sortCol, setSortCol] = usePersistentState<number | null>('cosmeticItems-sortCol', null); const [sortCol, setSortCol] = usePersistentState<number | null>('cosmeticItems-sortCol', null);
const [sortDesc, setSortDesc] = usePersistentState('cosmeticItems-sortDesc', false); const [sortDesc, setSortDesc] = usePersistentState('cosmeticItems-sortDesc', false);
const [cpnpFilter, setCpnpFilter] = usePersistentState<'all' | 'present' | 'missing'>('cosmeticItems-cpnpFilter', 'all');
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [columnFilters, setColumnFilters] = usePersistentState<Record<number, string[]>>('cosmeticItems-columnFilters', {}); const [columnFilters, setColumnFilters] = usePersistentState<Record<number, string[]>>('cosmeticItems-columnFilters', {});
const [openFilter, setOpenFilter] = useState<number | null>(null); const [openFilter, setOpenFilter] = useState<number | null>(null);
const [editingCpnp, setEditingCpnp] = useState<{ rowIndex: number; value: string } | null>(null); const [editingCpnp, setEditingCpnp] = useState<{ rowIndex: number; value: string } | null>(null);
const [savingCpnp, setSavingCpnp] = useState<number | null>(null); const [savingCpnp, setSavingCpnp] = useState<number | null>(null);
const [dashboardFocus, setDashboardFocus] = useState<'present' | 'missing' | null>(null);
const cpnpInputRef = useRef<HTMLInputElement>(null); const cpnpInputRef = useRef<HTMLInputElement>(null);
useEffect(() => { useEffect(() => {
@@ -43,12 +43,12 @@ export function CosmeticItemsView({ data, headers, onSaveRow, onCaptureState, ro
if (!dashboardDrilldown || dashboardDrilldown.tabId !== 'cosmetic_items') return; if (!dashboardDrilldown || dashboardDrilldown.tabId !== 'cosmetic_items') return;
const focus = dashboardDrilldown.focus === 'missing' ? 'missing' : 'present'; const focus = dashboardDrilldown.focus === 'missing' ? 'missing' : 'present';
setDashboardFocus(focus); setCpnpFilter(focus);
setSearch(''); setSearch('');
setColumnFilters({}); setColumnFilters({});
setPage(1); setPage(1);
onDashboardDrilldownApplied?.(); onDashboardDrilldownApplied?.();
}, [dashboardDrilldown?.id, dashboardDrilldown?.tabId, dashboardDrilldown?.focus, onDashboardDrilldownApplied, setSearch, setColumnFilters]); }, [dashboardDrilldown?.id, dashboardDrilldown?.tabId, dashboardDrilldown?.focus, onDashboardDrilldownApplied, setSearch, setColumnFilters, setCpnpFilter]);
const pageSize = 100; const pageSize = 100;
@@ -92,10 +92,10 @@ export function CosmeticItemsView({ data, headers, onSaveRow, onCaptureState, ro
return COSMETIC_LINES.some(l => lineVal === l); return COSMETIC_LINES.some(l => lineVal === l);
}); });
if (dashboardFocus) { if (cpnpFilter !== 'all') {
result = result.filter(({ row }) => { result = result.filter(({ row }) => {
const cpnp = String(row[COLUMNS.CPNP_NO] ?? '').trim(); const cpnp = String(row[COLUMNS.CPNP_NO] ?? '').trim();
return dashboardFocus === 'present' ? cpnp !== '' : cpnp === ''; return cpnpFilter === 'present' ? cpnp !== '' : cpnp === '';
}); });
} }
@@ -136,7 +136,7 @@ export function CosmeticItemsView({ data, headers, onSaveRow, onCaptureState, ro
} }
return result; return result;
}, [data, search, sortCol, sortDesc, columnFilters, COLUMNS, columnUniqueValues, dashboardFocus]); }, [data, search, sortCol, sortDesc, columnFilters, COLUMNS, columnUniqueValues, cpnpFilter]);
const paginatedData = useMemo(() => { const paginatedData = useMemo(() => {
const start = (page - 1) * pageSize; const start = (page - 1) * pageSize;
@@ -219,6 +219,26 @@ export function CosmeticItemsView({ data, headers, onSaveRow, onCaptureState, ro
<span className="text-slate-600">·</span> <span className="text-slate-600">·</span>
<span>Lines: {COSMETIC_LINES.join(', ')}</span> <span>Lines: {COSMETIC_LINES.join(', ')}</span>
</div> </div>
<div className="flex items-center gap-2">
{[
{ id: 'all', label: 'All' },
{ id: 'present', label: 'With CPNP' },
{ id: 'missing', label: 'Missing CPNP' },
].map(option => (
<button
key={option.id}
onClick={() => { setCpnpFilter(option.id as 'all' | 'present' | 'missing'); setPage(1); }}
className={cn(
"rounded-md border px-3 py-2 text-xs font-medium transition-colors",
cpnpFilter === option.id
? "border-indigo-500 bg-indigo-500/15 text-indigo-200"
: "border-slate-700 bg-slate-900/50 text-slate-400 hover:border-slate-600 hover:text-slate-200"
)}
>
{option.label}
</button>
))}
</div>
</div> </div>
<div className="flex-1 bg-slate-800 rounded-xl border border-slate-700 shadow-xl overflow-hidden flex flex-col"> <div className="flex-1 bg-slate-800 rounded-xl border border-slate-700 shadow-xl overflow-hidden flex flex-col">
@@ -385,7 +405,11 @@ export function CosmeticItemsView({ data, headers, onSaveRow, onCaptureState, ro
{paginatedData.length === 0 && ( {paginatedData.length === 0 && (
<tr> <tr>
<td colSpan={columns.length} className="px-4 py-8 text-center text-slate-500"> <td colSpan={columns.length} className="px-4 py-8 text-center text-slate-500">
No cosmetic items pending CPNP registration. {cpnpFilter === 'all'
? 'No cosmetic items found.'
: cpnpFilter === 'present'
? 'No cosmetic items with CPNP No. found.'
: 'No cosmetic items missing CPNP No. found.'}
</td> </td>
</tr> </tr>
)} )}