polish(web): oy kartı header'a — OEM kodunun sağ simetriğine, araç+parça bağlamıyla

Topluluk oyu kartının koyu dolgusu kalktı (sayfa arkaplanıyla aynı, yalnız
çerçeve); desktop'ta başlıkta OEM kodunun sağına yerleşti, mobilde kodun
altına iner. Katalogdan gelişte araç etiketi + parça adı search-param'la
taşınır (v/p/vid) ve kartta butonların üstünde "araç · parça" satırı olarak
gösterilir — neyle neyin uyumlu olduğu tek alanda. vid oy kaydına analitik
bağlam olarak geri eklendi; doğrudan ziyarette genel soru metnine düşülür.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 00:47:06 +03:00
parent 6575c611e8
commit 24e668ea01
5 changed files with 138 additions and 68 deletions

View File

@@ -116,11 +116,22 @@ function PartThumb({ src, alt }: { src: string | null; alt: string }) {
// ─── Route ───────────────────────────────────────────────────────────────────
export const Route = createFileRoute("/dashboard/oem/$code")({
// Katalogdan gelişte taşınan görüntü bağlamı: v = araç etiketi, p = parça
// adı (oy kartında "neyle neyin uyumlu olduğu" satırı), vid = vehicleId
// (oy kaydına analitik bağlam). Doğrudan ziyarette üçü de boş.
validateSearch: (
search: Record<string, unknown>,
): { v?: string; p?: string; vid?: string } => ({
v: typeof search.v === "string" && search.v ? search.v : undefined,
p: typeof search.p === "string" && search.p ? search.p : undefined,
vid: typeof search.vid === "string" && search.vid ? search.vid : undefined,
}),
component: OemDetailPage,
});
function OemDetailPage() {
const { code } = Route.useParams();
const { v: vehicleLabel, p: partName, vid: vehicleId } = Route.useSearch();
const { data, isLoading, error } = useQuery({
queryKey: ["p-oem", code],
@@ -171,33 +182,40 @@ function OemDetailPage() {
return (
<div className="mx-auto max-w-4xl space-y-6">
{/* ─── Header ─────────────────────────────────────────────────────── */}
<header className="flex items-start gap-4">
<Button asChild variant="ghost" size="icon" className="mt-0.5 shrink-0">
<Link to="/dashboard/search" aria-label="Geri">
<ArrowLeft className="size-5" />
</Link>
</Button>
<div className="min-w-0 flex-1">
<p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
OEM kodu
</p>
<div className="mt-1 flex flex-wrap items-center gap-3">
<h1 className="font-mono text-2xl font-bold tracking-tight break-all">{code}</h1>
<CopyCode
code={code}
className="rounded-md border border-border px-2 py-1 hover:bg-accent"
/>
{/* ─── Header: solda OEM kodu, desktop'ta sağ simetriğinde topluluk
oyu kartı; mobilde kart kodun altına iner ─────────────────────── */}
<header className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
<div className="flex min-w-0 flex-1 items-start gap-4">
<Button asChild variant="ghost" size="icon" className="mt-0.5 shrink-0">
<Link to="/dashboard/search" aria-label="Geri">
<ArrowLeft className="size-5" />
</Link>
</Button>
<div className="min-w-0 flex-1">
<p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
OEM kodu
</p>
<div className="mt-1 flex flex-wrap items-center gap-3">
<h1 className="font-mono text-2xl font-bold tracking-tight break-all">{code}</h1>
<CopyCode
code={code}
className="rounded-md border border-border px-2 py-1 hover:bg-accent"
/>
</div>
<p className="mt-1 text-sm text-muted-foreground">
Uyumlu parça kodları ve muadil numaralar
</p>
</div>
<p className="mt-1 text-sm text-muted-foreground">
Uyumlu parça kodları ve muadil numaralar
</p>
</div>
<OemVoteCard
oemCode={code}
vehicleLabel={vehicleLabel}
partName={partName}
vehicleId={vehicleId}
className="w-full lg:w-96 lg:shrink-0"
/>
</header>
{/* ─── Topluluk uyumluluk oyu (P eşleşmesinden bağımsız) ───────────── */}
<OemVoteCard oemCode={code} />
{/* ─── Loading ────────────────────────────────────────────────────── */}
{isLoading && (
<div className="space-y-4">