feat(catalog): part-count signposting + drill hint for deep category trees
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
pcat/emex vehicles decode into a tree whose top level is ~100% folders with zero parts (6746/9458 root nodes are parents, 0 direct leaves across 477 vehicles). Users — serkan filazi among them — saw an opaque wall of identical folder cards, assumed the parts feature was missing, and bounced without ever drilling (his session: 3 view-mode toggles, 0 category clicks; his data was 2-3 clicks deep and fully reachable). Two changes, no upstream/proxy cost: - getCategoryTree now rolls up a subtree partCount per node (one grouped parts read + JS post-order sum). The grid already renders "N parça", so folders now read "Fren sistemi · 142 parça" and steer drilling toward the branches that actually contain parts; empty branches stay quiet. Counts reflect drilled data and grow as branches are visited. - A one-line drill hint on a "cold" tree (nothing drilled yet → no counts) so first-visit users know parts live inside the subcategories instead of reading the folder wall as a broken/empty catalog. Drops away once any branch is hit. Verified: subtree roll-up unit test + existing suite (10/10), tsc + biome clean across api/web/shared. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -26,7 +26,7 @@ import { Skeleton } from "@sase/ui";
|
||||
import { Button } from "@sase/ui";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { createFileRoute, useCanGoBack, useNavigate, useRouter } from "@tanstack/react-router";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import { ArrowLeft, Info } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { KEYS_8 } from "@/lib/keys";
|
||||
@@ -92,6 +92,15 @@ function VehicleDetailPage() {
|
||||
enabled: !!id && idValid,
|
||||
});
|
||||
|
||||
// A "cold" tree has nothing drilled yet — no part counts anywhere. This is the
|
||||
// normal first-visit state for pcat/emex vehicles, whose top level is entirely
|
||||
// folders with zero parts. Without a nudge users read that folder wall as
|
||||
// "parts feature missing" and bounce (serkan's exact misread), instead of
|
||||
// drilling in. Once any branch is visited the counts light up and the hint
|
||||
// drops away on its own.
|
||||
const treeCold =
|
||||
!!categoryTree && categoryTree.length > 0 && categoryTree.every((c) => !c.partCount);
|
||||
|
||||
const vehicleLabel: string = vehicle?.brandName
|
||||
? `${vehicle.brandName}${cleanModelName(vehicle.model) ? ` ${cleanModelName(vehicle.model)}` : ""}`
|
||||
: t("vehicle.title");
|
||||
@@ -305,6 +314,12 @@ function VehicleDetailPage() {
|
||||
if (active) capture("catalog_search_opened", { vehicle_id: id });
|
||||
}}
|
||||
/>
|
||||
{!searchActive && !categoriesLoading && treeCold && (
|
||||
<div className="mt-3 flex items-start gap-2 rounded-lg border border-border bg-muted/40 px-3 py-2.5 text-xs text-muted-foreground">
|
||||
<Info className="mt-0.5 h-4 w-4 shrink-0 text-primary" />
|
||||
<span>{t("vehicle.drillHint")}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!searchActive &&
|
||||
(categoriesLoading ? (
|
||||
|
||||
Reference in New Issue
Block a user