feat: add amazon seller filter to product list and result parsing

This commit is contained in:
Victor Noguera
2026-04-14 18:43:35 -04:00
parent b52cdc7f2b
commit d25cf5d5ec
2 changed files with 47 additions and 3 deletions

View File

@@ -150,6 +150,7 @@ function parseResultFilters(
const sellabilityStatus = filters.get("sellabilityStatus")?.trim(); const sellabilityStatus = filters.get("sellabilityStatus")?.trim();
const minConfidence = filters.get("minConfidence")?.trim(); const minConfidence = filters.get("minConfidence")?.trim();
const maxConfidence = filters.get("maxConfidence")?.trim(); const maxConfidence = filters.get("maxConfidence")?.trim();
const amazonIsSeller = filters.get("amazonIsSeller")?.trim();
const conditions: string[] = ["run_id = ?"]; const conditions: string[] = ["run_id = ?"];
const params: Array<string | number> = [runId]; const params: Array<string | number> = [runId];
@@ -174,6 +175,12 @@ function parseResultFilters(
params.push(Number(maxConfidence)); params.push(Number(maxConfidence));
} }
if (amazonIsSeller === "yes") {
conditions.push("amazon_is_seller = 1");
} else if (amazonIsSeller === "no") {
conditions.push("amazon_is_seller = 0");
}
if (q) { if (q) {
const wildcard = `%${q}%`; const wildcard = `%${q}%`;
if (processType === "lead_analysis") { if (processType === "lead_analysis") {
@@ -310,6 +317,7 @@ function getRuns(filters: URLSearchParams) {
function getProductList(filters: URLSearchParams) { function getProductList(filters: URLSearchParams) {
const q = filters.get("q")?.trim() || ""; const q = filters.get("q")?.trim() || "";
const verdict = filters.get("verdict")?.trim(); const verdict = filters.get("verdict")?.trim();
const amazonIsSeller = filters.get("amazonIsSeller")?.trim();
const page = parseIntParam(filters.get("page"), 1); const page = parseIntParam(filters.get("page"), 1);
const pageSize = Math.min( const pageSize = Math.min(
parseIntParam(filters.get("pageSize"), DEFAULT_PAGE_SIZE), parseIntParam(filters.get("pageSize"), DEFAULT_PAGE_SIZE),
@@ -325,6 +333,12 @@ function getProductList(filters: URLSearchParams) {
params.push(verdict); params.push(verdict);
} }
if (amazonIsSeller === "yes") {
conditions.push("amazon_is_seller = 1");
} else if (amazonIsSeller === "no") {
conditions.push("amazon_is_seller = 0");
}
if (q) { if (q) {
const wildcard = `%${q}%`; const wildcard = `%${q}%`;
conditions.push( conditions.push(

View File

@@ -78,6 +78,7 @@ type ResultsResponse = {
}; };
type VerdictFilter = "" | "FBA" | "FBM" | "SKIP"; type VerdictFilter = "" | "FBA" | "FBM" | "SKIP";
type AmazonSellerFilter = "" | "yes" | "no";
type ProductListItem = { type ProductListItem = {
processType: ProcessType; processType: ProcessType;
@@ -429,6 +430,8 @@ function RunDetails({
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
const [verdict, setVerdict] = useState(""); const [verdict, setVerdict] = useState("");
const [sellabilityStatus, setSellabilityStatus] = useState(""); const [sellabilityStatus, setSellabilityStatus] = useState("");
const [amazonSellerFilter, setAmazonSellerFilter] =
useState<AmazonSellerFilter>("");
const [minConfidence, setMinConfidence] = useState(""); const [minConfidence, setMinConfidence] = useState("");
const [maxConfidence, setMaxConfidence] = useState(""); const [maxConfidence, setMaxConfidence] = useState("");
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
@@ -469,6 +472,7 @@ function RunDetails({
if (search) params.set("q", search); if (search) params.set("q", search);
if (verdict) params.set("verdict", verdict); if (verdict) params.set("verdict", verdict);
if (sellabilityStatus) params.set("sellabilityStatus", sellabilityStatus); if (sellabilityStatus) params.set("sellabilityStatus", sellabilityStatus);
if (amazonSellerFilter) params.set("amazonIsSeller", amazonSellerFilter);
if (minConfidence) params.set("minConfidence", minConfidence); if (minConfidence) params.set("minConfidence", minConfidence);
if (maxConfidence) params.set("maxConfidence", maxConfidence); if (maxConfidence) params.set("maxConfidence", maxConfidence);
@@ -484,7 +488,7 @@ function RunDetails({
return () => { return () => {
cancelled = true; cancelled = true;
}; };
}, [processType, runId, search, verdict, sellabilityStatus, minConfidence, maxConfidence, page, pageSize, sort, refreshTick]); }, [processType, runId, search, verdict, sellabilityStatus, amazonSellerFilter, minConfidence, maxConfidence, page, pageSize, sort, refreshTick]);
useEffect(() => { useEffect(() => {
const interval = window.setInterval(() => { const interval = window.setInterval(() => {
@@ -555,6 +559,17 @@ function RunDetails({
<option value="not_available">not_available</option> <option value="not_available">not_available</option>
<option value="unknown">unknown</option> <option value="unknown">unknown</option>
</select> </select>
<select
value={amazonSellerFilter}
onChange={(e) => {
setPage(1);
setAmazonSellerFilter(e.target.value as AmazonSellerFilter);
}}
>
<option value="">Amazon seller: all</option>
<option value="yes">Amazon seller: yes</option>
<option value="no">Amazon seller: no</option>
</select>
<input value={minConfidence} onChange={(e) => { setPage(1); setMinConfidence(e.target.value); }} placeholder="Min confidence" /> <input value={minConfidence} onChange={(e) => { setPage(1); setMinConfidence(e.target.value); }} placeholder="Min confidence" />
<input value={maxConfidence} onChange={(e) => { setPage(1); setMaxConfidence(e.target.value); }} placeholder="Max confidence" /> <input value={maxConfidence} onChange={(e) => { setPage(1); setMaxConfidence(e.target.value); }} placeholder="Max confidence" />
<select value={String(pageSize)} onChange={(e) => { setPage(1); setPageSize(Number(e.target.value)); }}> <select value={String(pageSize)} onChange={(e) => { setPage(1); setPageSize(Number(e.target.value)); }}>
@@ -565,7 +580,7 @@ function RunDetails({
</div> </div>
<div style={{ marginTop: 10 }}> <div style={{ marginTop: 10 }}>
<a <a
href={`/api/runs/${processType}/${runId}/export.csv?q=${encodeURIComponent(search)}&verdict=${encodeURIComponent(verdict)}&sellabilityStatus=${encodeURIComponent(sellabilityStatus)}&minConfidence=${encodeURIComponent(minConfidence)}&maxConfidence=${encodeURIComponent(maxConfidence)}&sort=${encodeURIComponent(buildSortValue(sort))}`} href={`/api/runs/${processType}/${runId}/export.csv?q=${encodeURIComponent(search)}&verdict=${encodeURIComponent(verdict)}&sellabilityStatus=${encodeURIComponent(sellabilityStatus)}&amazonIsSeller=${encodeURIComponent(amazonSellerFilter)}&minConfidence=${encodeURIComponent(minConfidence)}&maxConfidence=${encodeURIComponent(maxConfidence)}&sort=${encodeURIComponent(buildSortValue(sort))}`}
> >
<button>Export filtered CSV</button> <button>Export filtered CSV</button>
</a> </a>
@@ -665,6 +680,8 @@ function ProductList({ verdict, onBack }: { verdict: VerdictFilter; onBack: () =
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
const [activeVerdict, setActiveVerdict] = useState<VerdictFilter>(verdict); const [activeVerdict, setActiveVerdict] = useState<VerdictFilter>(verdict);
const [amazonSellerFilter, setAmazonSellerFilter] =
useState<AmazonSellerFilter>("");
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(25); const [pageSize, setPageSize] = useState(25);
const [sort, setSort] = useState<SortState>({ field: "monthly_sold", direction: "DESC" }); const [sort, setSort] = useState<SortState>({ field: "monthly_sold", direction: "DESC" });
@@ -683,6 +700,7 @@ function ProductList({ verdict, onBack }: { verdict: VerdictFilter; onBack: () =
params.set("sort", buildSortValue(sort)); params.set("sort", buildSortValue(sort));
if (search) params.set("q", search); if (search) params.set("q", search);
if (activeVerdict) params.set("verdict", activeVerdict); if (activeVerdict) params.set("verdict", activeVerdict);
if (amazonSellerFilter) params.set("amazonIsSeller", amazonSellerFilter);
const res = await fetch(`/api/products?${params.toString()}`); const res = await fetch(`/api/products?${params.toString()}`);
const payload = (await res.json()) as ProductListResponse; const payload = (await res.json()) as ProductListResponse;
if (!cancelled) { if (!cancelled) {
@@ -695,7 +713,7 @@ function ProductList({ verdict, onBack }: { verdict: VerdictFilter; onBack: () =
return () => { return () => {
cancelled = true; cancelled = true;
}; };
}, [search, activeVerdict, page, pageSize, sort]); }, [search, activeVerdict, amazonSellerFilter, page, pageSize, sort]);
async function reanalyzeAsin(item: ProductListItem) { async function reanalyzeAsin(item: ProductListItem) {
const key = `${item.processType}:${item.runId}:${item.asin}`; const key = `${item.processType}:${item.runId}:${item.asin}`;
@@ -715,6 +733,7 @@ function ProductList({ verdict, onBack }: { verdict: VerdictFilter; onBack: () =
params.set("sort", buildSortValue(sort)); params.set("sort", buildSortValue(sort));
if (search) params.set("q", search); if (search) params.set("q", search);
if (activeVerdict) params.set("verdict", activeVerdict); if (activeVerdict) params.set("verdict", activeVerdict);
if (amazonSellerFilter) params.set("amazonIsSeller", amazonSellerFilter);
const res = await fetch(`/api/products?${params.toString()}`); const res = await fetch(`/api/products?${params.toString()}`);
const payload = (await res.json()) as ProductListResponse; const payload = (await res.json()) as ProductListResponse;
setItems(payload); setItems(payload);
@@ -740,6 +759,17 @@ function ProductList({ verdict, onBack }: { verdict: VerdictFilter; onBack: () =
<option value="FBM">FBM</option> <option value="FBM">FBM</option>
<option value="SKIP">SKIP</option> <option value="SKIP">SKIP</option>
</select> </select>
<select
value={amazonSellerFilter}
onChange={(e) => {
setPage(1);
setAmazonSellerFilter(e.target.value as AmazonSellerFilter);
}}
>
<option value="">Amazon seller: all</option>
<option value="yes">Amazon seller: yes</option>
<option value="no">Amazon seller: no</option>
</select>
<select value={String(pageSize)} onChange={(e) => { setPage(1); setPageSize(Number(e.target.value)); }}> <select value={String(pageSize)} onChange={(e) => { setPage(1); setPageSize(Number(e.target.value)); }}>
<option value="25">25 / page</option> <option value="25">25 / page</option>
<option value="50">50 / page</option> <option value="50">50 / page</option>