diff --git a/src/App.tsx b/src/App.tsx index eb25ab2..eac919b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -548,6 +548,7 @@ export default function App() { {activeModule === 'article_details' && ( setEditingRowIndex(index)} rowStatuses={rowStatuses} /> diff --git a/src/components/ArticleDetails.tsx b/src/components/ArticleDetails.tsx index 267c364..e34b44a 100644 --- a/src/components/ArticleDetails.tsx +++ b/src/components/ArticleDetails.tsx @@ -6,13 +6,23 @@ import { ColumnFilterPopover } from './ColumnFilterPopover'; interface ArticleDetailsProps { data: ExcelRow[]; + headers: string[]; onEdit: (index: number) => void; rowStatuses: Record; } -type TabType = 'all' | 'missingDetailsDE' | 'missingDetailsEN' | 'missingAnyDetails' | 'lowStock'; +type TabType = 'all' | 'missingDetailsDE' | 'missingDetailsEN' | 'missingAnyDetails' | 'lowStock' | 'missingClassOrLaunch'; -export function ArticleDetails({ data, onEdit, rowStatuses }: ArticleDetailsProps) { +function isEmptyLaunchDate(val: any): boolean { + if (val === null || val === undefined || val === '') return true; + const s = String(val).trim(); + if (s === '' || s === '0' || s === '1') return true; + // "00/01/1900" or "01/01/1900" variants + if (s.endsWith('/1900')) return true; + return false; +} + +export function ArticleDetails({ data, headers, onEdit, rowStatuses }: ArticleDetailsProps) { const [activeTab, setActiveTab] = useState('all'); const [search, setSearch] = useState(''); const [lineFilter, setLineFilter] = useState(''); @@ -22,6 +32,12 @@ export function ArticleDetails({ data, onEdit, rowStatuses }: ArticleDetailsProp const [page, setPage] = useState(1); const [columnFilters, setColumnFilters] = useState>({}); const [openFilterCol, setOpenFilterCol] = useState(null); + + const launchDateCol = useMemo(() => + headers.findIndex(h => h.toLowerCase().includes('launch')), [headers]); + const readyToOrderCol = useMemo(() => + headers.findIndex(h => h.toLowerCase().includes('ready')), [headers]); + const [columnWidths, setColumnWidths] = useState>({ [COLUMNS.ARTICLE_NO]: 100, [COLUMNS.ARTICLE_NAME]: 200, @@ -41,6 +57,11 @@ export function ArticleDetails({ data, onEdit, rowStatuses }: ArticleDetailsProp 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 === 'missingClassOrLaunch') result = result.filter(r => { + const missingClass = !r.row[COLUMNS.CLASSIFICATION] || String(r.row[COLUMNS.CLASSIFICATION]).trim() === ''; + const missingLaunch = launchDateCol >= 0 ? isEmptyLaunchDate(r.row[launchDateCol]) : false; + return missingClass || missingLaunch; + }); // Search filter if (search) { @@ -156,6 +177,7 @@ export function ArticleDetails({ data, onEdit, rowStatuses }: ArticleDetailsProp { id: 'missingDetailsEN', label: 'No Details EN' }, { id: 'missingAnyDetails', label: 'Missing Details' }, { id: 'lowStock', label: 'Out of Stock' }, + { id: 'missingClassOrLaunch', label: 'Missing Class / Launch' }, ]; return ( @@ -226,10 +248,15 @@ export function ArticleDetails({ data, onEdit, rowStatuses }: ArticleDetailsProp {[ { col: COLUMNS.ARTICLE_NO, label: 'SKU' }, { col: COLUMNS.ARTICLE_NAME, label: 'Name' }, - { col: COLUMNS.CLASSIFICATION, label: 'Class' }, - { col: COLUMNS.ITEM_AVAILABLE, label: 'Stock' }, - { col: COLUMNS.DETAILS_DE, label: 'Details DE' }, - { col: COLUMNS.DETAILS_EN, label: 'Details EN' }, + { col: COLUMNS.CLASSIFICATION, label: 'Classification' }, + ...(activeTab === 'missingClassOrLaunch' ? [ + ...(launchDateCol >= 0 ? [{ col: launchDateCol, label: headers[launchDateCol] || 'Launch Date' }] : []), + ...(readyToOrderCol >= 0 ? [{ col: readyToOrderCol, label: headers[readyToOrderCol] || 'Ready to Order' }] : []), + ] : [ + { col: COLUMNS.ITEM_AVAILABLE, label: 'Stock' }, + { col: COLUMNS.DETAILS_DE, label: 'Details DE' }, + { col: COLUMNS.DETAILS_EN, label: 'Details EN' }, + ]), ].map(({ col, label }) => ( - - {row[COLUMNS.CLASSIFICATION] || '—'} - - - - - {row[COLUMNS.ITEM_AVAILABLE] || 0} - - - - {row[COLUMNS.DETAILS_DE] ? ( -
{row[COLUMNS.DETAILS_DE]}
- ) : getBadge(null)} - - - {row[COLUMNS.DETAILS_EN] ? ( -
{row[COLUMNS.DETAILS_EN]}
+ {row[COLUMNS.CLASSIFICATION] ? ( + + {row[COLUMNS.CLASSIFICATION]} + ) : getBadge(null)} + {activeTab === 'missingClassOrLaunch' ? ( + <> + {launchDateCol >= 0 && ( + + {isEmptyLaunchDate(row[launchDateCol]) ? getBadge(null) : ( + {String(row[launchDateCol])} + )} + + )} + {readyToOrderCol >= 0 && ( + + {row[readyToOrderCol] !== null && row[readyToOrderCol] !== undefined && row[readyToOrderCol] !== '' ? ( + {String(row[readyToOrderCol])} + ) : getBadge(null)} + + )} + + ) : ( + <> + + + {row[COLUMNS.ITEM_AVAILABLE] || 0} + + + + {row[COLUMNS.DETAILS_DE] ? ( +
{row[COLUMNS.DETAILS_DE]}
+ ) : getBadge(null)} + + + {row[COLUMNS.DETAILS_EN] ? ( +
{row[COLUMNS.DETAILS_EN]}
+ ) : getBadge(null)} + + + )}