From 3c4d9a7c8a93cbd9aa74445920af2440a17bd935 Mon Sep 17 00:00:00 2001 From: sriram Date: Tue, 6 Oct 2026 12:02:47 +0530 Subject: [PATCH] frontend changes on UI --- src/pages/BrandDiscoveryPanel.jsx | 90 ++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/src/pages/BrandDiscoveryPanel.jsx b/src/pages/BrandDiscoveryPanel.jsx index 16ce78a..52f1497 100644 --- a/src/pages/BrandDiscoveryPanel.jsx +++ b/src/pages/BrandDiscoveryPanel.jsx @@ -33,6 +33,12 @@ import { api } from '../api/client'; * the brand and states a pack size. That search takes minutes, so it runs as a * job: Discover starts it, this panel polls it, then asks for the preview. * + * A PRODUCT NAME WORKS TOO. "Lizol" resolves to Reckitt Benckiser and searches + * only Lizol listings; "Lizol Floor Cleaner" narrows to that line. The result + * is shown grouped - product line, then each variant (Citrus, Floral...), then + * the pack sizes real listings name - above the row-by-row table, and a size + * chip ticks or unticks the rows behind it. + * * There is no progress UI here on purpose. Ingest returns a BatchOut, and * AdminPage hands it to BatchCatalogPanel through the `adoptBatch` prop it * already has - which draws the eleven stages, and owns Resume and Cancel. @@ -72,6 +78,66 @@ function evidenceBadge(product) { return null; } +// "Lizol" typed, "reckitt benckiser" resolved: say so, and say where rows go. +function resolvedNote(result) { + const typed = (result.brand || '').trim().toLowerCase(); + const parent = (result.parent_brand || '').trim().toLowerCase(); + if (!parent || typed === parent) return null; + const maker = result.parent_brand.split(' ').map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' '); + return `"${result.brand}" is a product of ${maker} - only its own listings were searched.`; +} + +// Product line -> variant -> pack sizes. A size chip stands for the preview +// rows behind it (`rows`), and clicking it ticks or unticks all of them. +function Families({ families, selected, onToggleRows }) { + if (!families?.length) return null; + return ( +
+ {families.map((family) => ( +
+
{family.product_line}
+
+ {family.variants.map((variant) => ( +
+ + {variant.variant || 'Regular'} + + {variant.sizes.map((size) => { + const rows = size.rows || []; + const on = rows.length > 0 && rows.every((i) => selected.has(i)); + const shops = size.retailer_count + ? `${size.retailer_count} shop${size.retailer_count === 1 ? '' : 's'}` + : ''; + return ( + + ); + })} +
+ ))} +
+
+ ))} +
+ ); +} + function Toggle({ checked, onChange, label, hint }) { return (