feat(catalog): kök-seviye canonical fallback + araç sayfası "Birleşik" toggle
Backend: groupCategoriesByCanonical'a requireParts opsiyonu; her iki serving metodu artık parça-içeren yaprak yoksa (taze/drill-edilmemiş araç) kök kategorileri kovalayarak boş dönmüyor. Frontend: araç sayfasına "Katalog | Birleşik" toggle'ı; Birleşik seçilince CanonicalView aracın kataloğunu 18 kanonik başlık altında gösterir, her kova CategoryGrid ile normal drill'e bağlanır. canonical_view_opened event'i. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import {
|
||||
ReportCatalogIssueButton,
|
||||
useReportCatalogDegradation,
|
||||
} from "@/components/catalog/report-catalog-issue";
|
||||
import { CanonicalView } from "@/components/categories/canonical-view";
|
||||
import { CatalogSearch } from "@/components/categories/catalog-search";
|
||||
import { CategoryBreadcrumb } from "@/components/categories/category-breadcrumb";
|
||||
import { CategoryColumns } from "@/components/categories/category-columns";
|
||||
@@ -56,6 +57,9 @@ function VehicleDetailPage() {
|
||||
// When a cross-tree catalog search is active, the normal browse (and its view
|
||||
// toggle) are hidden in favour of the search results.
|
||||
const [searchActive, setSearchActive] = useState(false);
|
||||
// "source" = the raw per-brand OEM tree (default); "canonical" = the same
|
||||
// catalog folded into the unified 18-bucket taxonomy.
|
||||
const [browseMode, setBrowseMode] = useState<"source" | "canonical">("source");
|
||||
|
||||
const changeViewMode = (mode: "grid" | "tree" | "columns") => {
|
||||
setViewMode(mode);
|
||||
@@ -308,9 +312,34 @@ function VehicleDetailPage() {
|
||||
|
||||
{/* Categories */}
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between">
|
||||
<CardHeader className="flex flex-row items-center justify-between gap-3">
|
||||
<CardTitle className="text-base">{t("vehicle.categories")}</CardTitle>
|
||||
{!searchActive && <CategoryViewToggle value={viewMode} onChange={changeViewMode} />}
|
||||
{!searchActive && (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="inline-flex rounded-md border border-border p-0.5">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setBrowseMode("source")}
|
||||
className={`rounded px-2.5 py-1 text-xs font-medium transition-colors ${browseMode === "source" ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground"}`}
|
||||
>
|
||||
Katalog
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setBrowseMode("canonical");
|
||||
capture("canonical_view_opened", { vehicle_id: id });
|
||||
}}
|
||||
className={`rounded px-2.5 py-1 text-xs font-medium transition-colors ${browseMode === "canonical" ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground"}`}
|
||||
>
|
||||
Birleşik
|
||||
</button>
|
||||
</div>
|
||||
{browseMode === "source" && (
|
||||
<CategoryViewToggle value={viewMode} onChange={changeViewMode} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CardHeader>
|
||||
<CardContent
|
||||
className={
|
||||
@@ -335,7 +364,9 @@ function VehicleDetailPage() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!searchActive && browseMode === "canonical" ? <CanonicalView vehicleId={id} /> : null}
|
||||
{!searchActive &&
|
||||
browseMode === "source" &&
|
||||
(categoriesLoading ? (
|
||||
viewMode === "grid" ? (
|
||||
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
|
||||
|
||||
Reference in New Issue
Block a user