feat(web): vehicle detail — empty-categories state, equipment show-more, mobile header

- Render a composed "no categories found" panel when the category tree
  resolves to an empty array, so vehicles without a catalog stop showing
  a silent void under "Yedek Parça Kategorileri".
- Collapse the equipment list to the first 8 codes by default with a
  "Tümünü göster (N)" toggle instead of a sub-scrollarea — friendlier
  on mobile, no card-in-card scroll.
- Loosen the header flex layout: the title block gets `min-w-0 flex-1`
  with break-words and a truncated VIN line so long brand+model strings
  no longer crush the layout on narrow screens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-31 21:29:49 +03:00
parent a6ce215c47
commit 74f32b82e5

View File

@@ -193,21 +193,20 @@ function VehicleDetailPage() {
onClick={handleBack}
title="Geri dön"
aria-label="Geri dön"
className="shrink-0"
data-faro-user-action-name="vehicle-back"
>
<ArrowLeft className="h-4 w-4" />
</Button>
<div className="flex items-center gap-3">
{vehicle?.brandName && (
<CarBrandLogo brandName={vehicle.brandName} size={32} className="shrink-0" />
)}
<div>
<h2 className="text-2xl font-bold">
{vehicle?.brandName} {cleanModelName(vehicle?.model)}{" "}
{vehicle?.year && `(${vehicle.year})`}
</h2>
<p className="font-mono text-sm text-muted-foreground">{vehicle?.vin}</p>
</div>
{vehicle?.brandName && (
<CarBrandLogo brandName={vehicle.brandName} size={32} className="shrink-0" />
)}
<div className="min-w-0 flex-1">
<h2 className="break-words text-2xl font-bold leading-tight">
{vehicle?.brandName} {cleanModelName(vehicle?.model)}{" "}
{vehicle?.year && `(${vehicle.year})`}
</h2>
<p className="truncate font-mono text-sm text-muted-foreground">{vehicle?.vin}</p>
</div>
</div>
@@ -253,12 +252,22 @@ function VehicleDetailPage() {
<Skeleton key={__k} className="h-8 w-full" />
))}
</div>
) : !categoryTree || categoryTree.length === 0 ? (
<div className="rounded-lg border border-dashed border-border bg-muted/30 px-6 py-10 text-center">
<p className="text-sm font-medium text-foreground">
Bu araç için kategori bulunamadı
</p>
<p className="mx-auto mt-1 max-w-md text-xs text-muted-foreground">
Araç decode edildi ama parça kataloğu henüz hazırlanmamış olabilir. Destek
ekibimize bildirirseniz katalog hızlandırılır.
</p>
</div>
) : viewMode === "grid" ? (
<CategoryGrid categories={categoryTree || []} vehicleId={id} hideFilter />
<CategoryGrid categories={categoryTree} vehicleId={id} hideFilter />
) : viewMode === "tree" ? (
<CategoryTree categories={categoryTree || []} vehicleId={id} />
<CategoryTree categories={categoryTree} vehicleId={id} />
) : (
<CategoryColumns categories={categoryTree || []} vehicleId={id} />
<CategoryColumns categories={categoryTree} vehicleId={id} />
))}
</CardContent>
</Card>
@@ -525,17 +534,22 @@ function getEquipment(vehicle: any): Equipment[] {
}
/** Full decoded equipment / PR-code list, shown inside the expanded card. */
const EQUIPMENT_PREVIEW = 8;
function VehicleEquipment({ vehicle }: { vehicle: any }) {
const items = getEquipment(vehicle);
const [expanded, setExpanded] = useState(false);
if (items.length === 0) return null;
const hasMore = items.length > EQUIPMENT_PREVIEW;
const visible = expanded || !hasMore ? items : items.slice(0, EQUIPMENT_PREVIEW);
return (
<div className="mt-6 border-t border-border pt-4">
<p className="mb-3 text-xs font-semibold text-muted-foreground">
Donanım kodları ({items.length})
</p>
<ul className="grid max-h-80 grid-cols-1 gap-x-6 gap-y-2 overflow-y-auto pr-1 sm:grid-cols-2">
{items.map((it, i) => (
<ul className="grid grid-cols-1 gap-x-6 gap-y-2 sm:grid-cols-2">
{visible.map((it, i) => (
<li key={`${it.code}-${i}`} className="flex items-baseline gap-2">
{it.code && (
<span className="shrink-0 rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] leading-tight text-muted-foreground">
@@ -546,6 +560,17 @@ function VehicleEquipment({ vehicle }: { vehicle: any }) {
</li>
))}
</ul>
{hasMore && (
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => setExpanded((v) => !v)}
className="mt-3 h-8 px-2 text-xs text-muted-foreground hover:text-foreground"
>
{expanded ? "Daha az göster" : `Tümünü göster (${items.length})`}
</Button>
)}
</div>
);
}