feat(web): make vehicle info card readable instead of raw VIN codes
The Araç Bilgileri card showed only raw PL24 VIN-decoded codes (Satış tipi 1J10E4, Donanım 82, Motor kodu BCB…) and fully suppressed the friendlier DB fields. Now it leads with the readable engine description + body type, then the decoded codes; drops the Model/Model-yılı rows that duplicate the h2 header; maps the known mojibake labels to clean Turkish; drops the uppercase transform (which corrupted the Turkish dotted/dotless i); and lays out 2 cols on mobile with long values spanning the full row. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -142,7 +142,20 @@ function VehicleDetailPage() {
|
||||
);
|
||||
}
|
||||
|
||||
/** Extract vinfoBasic records from rawData, filtering out VIN. */
|
||||
/** Known PL24 raw labels (missing Turkish chars) → clean Turkish. Unknown
|
||||
* labels pass through unchanged. */
|
||||
const LABEL_OVERRIDES: Record<string, string> = {
|
||||
"Satis tipi": "Satış tipi",
|
||||
Donanim: "Donanım",
|
||||
"Aks tahrigi tanimi": "Aks tahriki tanımı",
|
||||
"Dis rengi / Boya numarasi": "Dış renk / boya kodu",
|
||||
"Model yili": "Model yılı",
|
||||
};
|
||||
|
||||
/** Labels already shown in the page header — dropped to avoid duplication. */
|
||||
const HEADER_LABELS = new Set(["model", "model yili", "model yılı"]);
|
||||
|
||||
/** Extract vinfoBasic records from rawData, dropping VIN and header dupes. */
|
||||
function getVehicleAttributes(vehicle: any): Array<{ label: string; value: string }> {
|
||||
const records = vehicle?.rawData?.raw?.segments?.vinfoBasic?.records;
|
||||
if (!Array.isArray(records)) return [];
|
||||
@@ -156,12 +169,28 @@ function getVehicleAttributes(vehicle: any): Array<{ label: string; value: strin
|
||||
}))
|
||||
.filter(
|
||||
(attr: { label: string; value: string }) =>
|
||||
attr.label && attr.value && attr.value.toLowerCase() !== vinLower,
|
||||
);
|
||||
attr.label &&
|
||||
attr.value &&
|
||||
attr.value.toLowerCase() !== vinLower &&
|
||||
!HEADER_LABELS.has(attr.label.toLowerCase()),
|
||||
)
|
||||
.map((attr: { label: string; value: string }) => ({
|
||||
label: LABEL_OVERRIDES[attr.label] ?? attr.label,
|
||||
value: attr.value,
|
||||
}));
|
||||
}
|
||||
|
||||
function VehicleAttributes({ vehicle }: { vehicle: any }) {
|
||||
const richAttrs = getVehicleAttributes(vehicle);
|
||||
|
||||
// Human-readable fields the VIN-code records don't carry (a decoded engine
|
||||
// description, body type). Prepended so the legible info leads and the raw
|
||||
// decoded codes follow — instead of the codes hiding the readable data.
|
||||
const readableExtras = [
|
||||
{ label: "Motor", value: vehicle?.engine },
|
||||
{ label: "Kasa", value: vehicle?.bodyType },
|
||||
].filter((a): a is { label: string; value: string } => Boolean(a.value));
|
||||
|
||||
const fallbackAttrs = [
|
||||
{ label: "Marka", value: vehicle?.brandName },
|
||||
{ label: "Model", value: vehicle?.model },
|
||||
@@ -171,26 +200,32 @@ function VehicleAttributes({ vehicle }: { vehicle: any }) {
|
||||
{ label: "Kasa", value: vehicle?.bodyType },
|
||||
].filter((a): a is { label: string; value: string } => Boolean(a.value));
|
||||
|
||||
// Prefer the rich VIN-decoded attributes when available; otherwise show DB
|
||||
// fallback fields. Single layout for both — keeps semantics consistent.
|
||||
const attrs = richAttrs.length > 0 ? richAttrs : fallbackAttrs;
|
||||
// With VIN-decoded detail: lead with readable fields, then the decoded codes.
|
||||
// Without it: plain DB fields.
|
||||
const attrs = richAttrs.length > 0 ? [...readableExtras, ...richAttrs] : fallbackAttrs;
|
||||
|
||||
if (attrs.length === 0) {
|
||||
return (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Bu araç için ayrıntı bilgisi bulunamadı.
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">Bu araç için ayrıntı bilgisi bulunamadı.</p>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<dl className="grid grid-cols-1 gap-x-6 gap-y-3 text-sm sm:grid-cols-2 md:grid-cols-3">
|
||||
{attrs.map((attr) => (
|
||||
<div key={attr.label} className="flex flex-col">
|
||||
<dt className="text-xs uppercase tracking-wide text-muted-foreground">{attr.label}</dt>
|
||||
<dd className="font-medium tabular-nums">{attr.value}</dd>
|
||||
</div>
|
||||
))}
|
||||
<dl className="grid grid-cols-2 gap-x-6 gap-y-3 text-sm md:grid-cols-3">
|
||||
{attrs.map((attr, i) => {
|
||||
// Long values (e.g. the engine description) get the full row width so
|
||||
// they stay readable instead of cramping a single grid cell.
|
||||
const wide = attr.value.length > 40;
|
||||
return (
|
||||
<div
|
||||
key={`${attr.label}-${i}`}
|
||||
className={`flex flex-col ${wide ? "col-span-2 md:col-span-3" : ""}`}
|
||||
>
|
||||
<dt className="text-xs text-muted-foreground">{attr.label}</dt>
|
||||
<dd className="font-medium tabular-nums">{attr.value}</dd>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</dl>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user