Files
kolaytercih/src/features/katalog/components/universite-program-tablosu.tsx
bilalgursen 7c48f64ff3 feat(liste): varyant çipi — sonuç tablosu, kendi listem çekmecesi, katalog tabloları
Satır altı meta satırında tür çipinin hemen ardından SATIR_CIP sınıfıyla
"Burslu · İngilizce" çipi (DESIGN.md §4.15); null ise hiçbir şey çizilmez.
Çekmecede üniversite adından sonra "· %50 İndirimli". Manuel liste kaydı
varyantı opsiyonel taşır (eski localStorage kayıtları geçer); + butonu ve
programEkleIste etiketi kopyalar, programOzetle client'a serileştirir.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-07 23:12:15 +03:00

166 lines
6.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import Link from "next/link";
import type { Program } from "@/types/yokatlas";
import { SON_YIL, VERI_YIL_SAYISI } from "@/lib/veri-yillari";
import {
ProgramSiraGecmisi,
ProgramTabanTrendi,
programEtkinSira,
} from "@/components/program-liste-verileri";
import {
SATIR_AD,
SATIR_AD_DUZ,
SATIR_AD_HUCRE,
SATIR_BASLIK,
SATIR_BUTON_BASLIK,
SATIR_BUTON_HUCRE,
SATIR_BUTON_KABI,
SATIR_CIP,
SATIR_GRUP,
SATIR_META,
SATIR_MOBIL_SAYI,
} from "@/components/liste-satiri";
import { ProgramEkleButonu } from "@/features/liste/components/program-ekle-butonu";
import { ProgramAyrintiButonu } from "./program-ayrinti";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
const sayi = (n: number) => n.toLocaleString("tr-TR");
const TUR_ETIKET: Record<string, string> = {
SAYISAL: "SAY",
"EŞİT AĞIRLIK": "EA",
SÖZEL: "SÖZ",
DİL: "DİL",
TYT: "TYT",
};
export type UniProgramSatiri = Program & { bolumSlug: string | null };
export function UniversiteProgramTablosu({
gruplar,
}: {
gruplar: { fakulte: string; programlar: UniProgramSatiri[] }[];
}) {
// Şişko ve sade: program adı kesilmez (sarar), sıra ve butonlar iri.
// 375 px'te yalnız ad + butonlar sütun olarak kalır; taban sıra adın
// altındaki satıra iner, böylece ad bütün genişliği kullanır.
return (
<>
{gruplar.map(({ fakulte, programlar }, i) => (
<section key={`${fakulte}-${i}`} className="mt-10">
<h2 className="mb-4 text-center font-heading text-xl font-bold text-slate-900 sm:text-2xl lg:text-left">
{fakulte}
</h2>
<div className="overflow-hidden rounded-2xl border border-slate-200 bg-card">
<Table>
<TableHeader>
<TableRow className="hover:bg-transparent">
<TableHead className={`${SATIR_BASLIK} pl-4 sm:pl-5`}>
Program
</TableHead>
<TableHead className={`hidden text-right lg:table-cell ${SATIR_BASLIK}`}>
Son {VERI_YIL_SAYISI} yıl
</TableHead>
<TableHead className={`hidden text-right lg:table-cell ${SATIR_BASLIK}`}>
{SON_YIL} puan
</TableHead>
<TableHead className={`hidden text-right md:table-cell ${SATIR_BASLIK}`}>
Kontenjan
</TableHead>
<TableHead className={`hidden text-right sm:table-cell ${SATIR_BASLIK}`}>
Taban sıra
</TableHead>
<TableHead className={SATIR_BUTON_BASLIK}>
<span className="sr-only">Ayrıntı ve listeye ekle</span>
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{programlar.map((p) => {
const taban = programEtkinSira(p);
const tabanMetni = taban != null ? `~${sayi(taban)}.` : "—";
return (
<TableRow key={p.id} className="kt-cv-satir">
<TableCell className={SATIR_AD_HUCRE}>
<span className={SATIR_GRUP}>
{p.bolumSlug ? (
<Link
href={`/bolum/${p.bolumSlug}`}
className={SATIR_AD}
>
{p.isim.trim()}
</Link>
) : (
<span className={SATIR_AD_DUZ}>
{p.isim.trim()}
</span>
)}
<span className={SATIR_META}>
<span className={SATIR_CIP}>
{TUR_ETIKET[p.tur] ?? p.tur}
</span>
{/* Burs/dil/öğretim türü: aynı adlı satırları ayırt eder (§4.15 çip) */}
{p.varyant ? (
<span className={SATIR_CIP}>{p.varyant}</span>
) : null}
{p.sure ? (
<span className="shrink-0">{p.sure} yıl</span>
) : null}
</span>
</span>
<span className={SATIR_MOBIL_SAYI}>
Taban sıra
<span className="font-semibold tabular-nums text-slate-900">
{tabanMetni}
</span>
<ProgramTabanTrendi program={p} />
</span>
</TableCell>
<TableCell className="hidden text-right text-sm lg:table-cell">
<ProgramSiraGecmisi program={p} />
</TableCell>
<TableCell className="hidden text-right text-sm tabular-nums text-slate-600 lg:table-cell">
{p.puanSon != null
? p.puanSon.toFixed(2).replace(".", ",")
: "—"}
</TableCell>
<TableCell className="hidden text-right text-sm tabular-nums text-slate-600 md:table-cell">
{p.kontenjanSon != null
? `${sayi(p.kontenjanSon)} kişi`
: "—"}
</TableCell>
<TableCell className="hidden text-right text-base font-semibold tabular-nums text-slate-900 sm:table-cell">
<span className="inline-flex items-center gap-1.5">
<ProgramTabanTrendi program={p} />
{tabanMetni}
</span>
</TableCell>
<TableCell className={SATIR_BUTON_HUCRE}>
<span className={SATIR_BUTON_KABI}>
<ProgramAyrintiButonu
programId={p.id}
isim={p.isim.trim()}
/>
<ProgramEkleButonu program={p} kaynak="universite" />
</span>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>
</section>
))}
</>
);
}