category
This commit is contained in:
@@ -26,6 +26,11 @@ import { importSheetProducts, type SheetImportResult, type SheetProductRow } fro
|
||||
import { errorMessage } from '@/api/client';
|
||||
import { SectionHeader } from '@/components/SectionHeader';
|
||||
import { SheetDropzone } from '@/components/SheetDropzone';
|
||||
import {
|
||||
resolveCategory,
|
||||
UNKNOWN_CATEGORY,
|
||||
type CategoryRule,
|
||||
} from './productCategory';
|
||||
import { TablePager } from '@/components/TablePager';
|
||||
import { usePaged } from '@/components/usePaged';
|
||||
import {
|
||||
@@ -34,10 +39,20 @@ import {
|
||||
type ParsedSheet,
|
||||
} from '@/features/nearle-admin/import/parseProductSheet';
|
||||
|
||||
/** How the category was arrived at, in the operator's words. */
|
||||
const RULE_LABEL: Record<CategoryRule, string> = {
|
||||
sheet: 'from your sheet',
|
||||
registry: 'matched by name',
|
||||
lexicon: 'matched as a commodity',
|
||||
unknown: 'could not tell',
|
||||
};
|
||||
|
||||
interface PreviewRow extends Record<string, unknown> {
|
||||
productname: string;
|
||||
productsku: string;
|
||||
categoryid: number;
|
||||
/** Resolved by the category ladder, before anything is created. */
|
||||
category: string;
|
||||
categoryRule: CategoryRule;
|
||||
retailprice: number;
|
||||
productcost: number;
|
||||
quantity: number;
|
||||
@@ -119,11 +134,25 @@ export function TenantSheetImportPanel({ tenantid, locationid }: TenantSheetImpo
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'categoryid',
|
||||
key: 'category',
|
||||
header: 'Category',
|
||||
align: 'end',
|
||||
width: { type: 'pixel', value: 100 },
|
||||
renderCell: (row) => <Text type="body" size="sm" hasTabularNumbers>{row.categoryid}</Text>,
|
||||
width: { type: 'pixel', value: 170 },
|
||||
renderCell: (row) => (
|
||||
<VStack gap={0}>
|
||||
<Text
|
||||
type="body"
|
||||
size="sm"
|
||||
{...(row.category === UNKNOWN_CATEGORY ? { color: 'secondary' as const } : {})}
|
||||
>
|
||||
{row.category}
|
||||
</Text>
|
||||
{/* Which rule answered. An operator trusts their own column and
|
||||
checks an inferred one, and cannot tell them apart otherwise. */}
|
||||
<Text type="body" size="xsm" color="secondary">
|
||||
{RULE_LABEL[row.categoryRule]}
|
||||
</Text>
|
||||
</VStack>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'retailprice',
|
||||
@@ -159,14 +188,35 @@ export function TenantSheetImportPanel({ tenantid, locationid }: TenantSheetImpo
|
||||
/* The whole sheet, paged — it used to be cut at 25 with nothing saying so,
|
||||
unlike the issues list above, which says '…and N more'. A bad row on line
|
||||
300 was unreachable in the one screen meant for checking the parse. */
|
||||
const preview: PreviewRow[] = (parsed?.rows ?? []).map((row: SheetProductRow) => ({
|
||||
productname: row.productname,
|
||||
productsku: row.productsku,
|
||||
categoryid: row.categoryid,
|
||||
retailprice: row.retailprice,
|
||||
productcost: row.productcost,
|
||||
quantity: row.quantity,
|
||||
}));
|
||||
const preview: PreviewRow[] = (parsed?.rows ?? []).map((row: SheetProductRow) => {
|
||||
/*
|
||||
The category comes from the parser, which ran the ladder once; this
|
||||
re-runs it only to recover WHICH RULE answered, so the column can say so.
|
||||
The answer itself is the parser's own file, before a
|
||||
single product is created — the same deterministic ladder the catalogue
|
||||
team runs, so a product filed here and the same product in the global
|
||||
catalogue land in the same place.
|
||||
|
||||
Shown rather than silently applied: the column used to print
|
||||
`categoryid`, which the parser sets to 0 on every row, so it read "0" all
|
||||
the way down and told nobody anything.
|
||||
*/
|
||||
const verdict = resolveCategory({
|
||||
title: row.productname,
|
||||
description: row.productdesc ?? '',
|
||||
sheetValue: row.category ?? '',
|
||||
packSize: [row.unitvalue, row.productunit].filter(Boolean).join(' '),
|
||||
});
|
||||
return {
|
||||
productname: row.productname,
|
||||
productsku: row.productsku,
|
||||
category: verdict.category,
|
||||
categoryRule: verdict.rule,
|
||||
retailprice: row.retailprice,
|
||||
productcost: row.productcost,
|
||||
quantity: row.quantity,
|
||||
};
|
||||
});
|
||||
|
||||
// A new file is a new sheet, so the pager starts over.
|
||||
const previewPaged = usePaged(preview, { resetKey: preview.length });
|
||||
|
||||
Reference in New Issue
Block a user