feat(tasarim): rapor listesi ve tadımlık satırı "şişko ve sade" dile göre

- Risk etiketi src/components/risk-etiketi.tsx'e çıkarıldı; /sonuc,
  çekmece ve rapor listesi oradan kullanıyor
- Rapor satırı §4.15: ad sarar, üniversite adı ayrı satırda, telefonda
  risk + taban sıra adın altında, logo gizli (satır 214 → 152 px),
  aç/kapa düğmesi 44 px, hover tek turuncu
- Açılan ayrıntı: 16 px metin, 14 px koyu etiket, rounded-xl iç kutular
- Tadımlık satırı aynı satır düzenine geçti
- Tercih değişti penceresi, liste gövdesi ve yazdırma sayfasında
  10-11 px / büyük harfli etiketler kalktı

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-24 00:57:27 +03:00
parent 73943b0954
commit 309fb73a34
9 changed files with 186 additions and 186 deletions

View File

@@ -0,0 +1,32 @@
import { RISK_ETIKET, type RiskSeviyesi } from "@/lib/risk";
/**
* Risk etiketi (DESIGN.md §4.5) — tek kaynak: renkli nokta + aynı renkte
* metin. Renk hiçbir yerde tek başına durmaz; metin RISK_ETIKET'ten gelir.
* /sonuc tablosu, liste çekmecesi ve rapor listesi buradan kullanır.
*/
export const RISK_NOKTA: Record<RiskSeviyesi, string> = {
guvenli: "bg-emerald-500",
"az-riskli": "bg-amber-500",
riskli: "bg-red-500",
};
const RISK_METIN: Record<RiskSeviyesi, string> = {
guvenli: "text-emerald-600",
"az-riskli": "text-amber-600",
riskli: "text-red-600",
};
export function RiskEtiketi({ risk }: { risk: RiskSeviyesi }) {
return (
<span
className={`inline-flex items-center gap-1.5 text-xs font-semibold ${RISK_METIN[risk]}`}
>
<span
className={`size-2 shrink-0 rounded-full ${RISK_NOKTA[risk]}`}
aria-hidden
/>
{RISK_ETIKET[risk]}
</span>
);
}

View File

@@ -16,6 +16,7 @@ import Link from "next/link";
import { useRouter } from "next/navigation";
import { PixelField } from "@/components/pixel-decor";
import { UniLogo } from "@/components/uni-logo";
import { RiskEtiketi } from "@/components/risk-etiketi";
import { Button } from "@/components/ui/button";
import {
Drawer,
@@ -42,7 +43,6 @@ import {
useTransform,
type PanInfo,
} from "motion/react";
import { RISK_ETIKET, type RiskSeviyesi } from "@/lib/risk";
import { bolumBazAdi, trBaslikDuzeni, turkishSlugify } from "@/lib/slug";
import { SATIR_AD, SATIR_IKINCIL_LINK } from "@/components/liste-satiri";
import { olay } from "@/lib/analitik";
@@ -78,19 +78,6 @@ function uniHref(ad: string): string {
return `/universite/${turkishSlugify(ad.replace(/\s*\([^)]*\)\s*$/, "").trim())}`;
}
// Risk renk dili ürünün geri kalanıyla birebir aynı (bkz. rapor-listesi)
const RISK_NOKTA: Record<RiskSeviyesi, string> = {
guvenli: "bg-emerald-500",
"az-riskli": "bg-amber-500",
riskli: "bg-red-500",
};
// §4.5: nokta + renkli metin; renk tek başına anlam taşımaz
const RISK_METIN: Record<RiskSeviyesi, string> = {
guvenli: "text-emerald-600",
"az-riskli": "text-amber-600",
riskli: "text-red-600",
};
export function ListeCekmecesi() {
const router = useRouter();
const acik = useCekmeceAcik();
@@ -407,17 +394,7 @@ function CekmeceSatiri({
</span>
{tercih.risk || tercih.efektifSira != null ? (
<span className="mt-1.5 flex flex-wrap items-center gap-x-3 gap-y-1 text-sm text-slate-500">
{tercih.risk ? (
<span
className={`inline-flex items-center gap-1.5 text-xs font-semibold ${RISK_METIN[tercih.risk]}`}
>
<span
className={`size-2 shrink-0 rounded-full ${RISK_NOKTA[tercih.risk]}`}
aria-hidden
/>
{RISK_ETIKET[tercih.risk]}
</span>
) : null}
{tercih.risk ? <RiskEtiketi risk={tercih.risk} /> : null}
{tercih.efektifSira != null ? (
<span className="inline-flex items-center gap-1.5">
Taban sıra

View File

@@ -20,12 +20,7 @@ import type {
PuanTuruKey,
RankResultsListe,
} from "@/types/yokatlas";
import {
DILIM_ETIKET,
RISK_ETIKET,
riskHesapla,
type RiskSeviyesi,
} from "@/lib/risk";
import { DILIM_ETIKET, riskHesapla } from "@/lib/risk";
import { bolumSayfaSlug, trBaslikDuzeni, uniSayfaSlug } from "@/lib/slug";
import { VERI_YIL_SAYISI } from "@/lib/veri-yillari";
import {
@@ -46,6 +41,7 @@ import { ProgramEkleButonu } from "@/features/liste/components/program-ekle-buto
import { preloadTercihHaritasi } from "@/features/liste/components/tercih-haritasi-lazy";
import { ProgramNetleriButonu } from "@/features/katalog/components/program-netleri";
import { UniLogo } from "@/components/uni-logo";
import { RiskEtiketi } from "@/components/risk-etiketi";
import { Button } from "@/components/ui/button";
import {
SATIR_AD,
@@ -92,15 +88,6 @@ const DILIMLER: {
},
];
// Risk renk dili: yeşil = güvenli, sarı = az riskli, kırmızı = riskli. Nokta
// hiçbir yerde tek başına durmaz; yanında RISK_ETIKET'ten gelen ad her ekran
// genişliğinde yazılı durur (renk tek başına anlam taşımaz).
const RISK_NOKTA: Record<RiskSeviyesi, string> = {
guvenli: "bg-emerald-500",
"az-riskli": "bg-amber-500",
riskli: "bg-red-500",
};
const BOS_EKSTRA: Record<DilimKey, ProgramListeSatiri[]> = {
hayal: [],
dengeli: [],
@@ -334,27 +321,6 @@ export function ProgramTablosu({
);
}
// Risk etiketinin metin rengi (§4.5): nokta + renkli metin, renk tek başına değil.
const RISK_METIN: Record<RiskSeviyesi, string> = {
guvenli: "text-emerald-600",
"az-riskli": "text-amber-600",
riskli: "text-red-600",
};
function RiskEtiketi({ risk }: { risk: RiskSeviyesi }) {
return (
<span
className={`inline-flex items-center gap-1.5 text-xs font-semibold ${RISK_METIN[risk]}`}
>
<span
className={`size-2 shrink-0 rounded-full ${RISK_NOKTA[risk]}`}
aria-hidden
/>
{RISK_ETIKET[risk]}
</span>
);
}
function ProgramSatiri({
program: p,
adaySira,
@@ -381,7 +347,7 @@ function ProgramSatiri({
<TableCell className="hidden pl-4 pr-0 sm:table-cell sm:pl-5">
{risk ? <RiskEtiketi risk={risk} /> : null}
</TableCell>
<TableCell className={`${SATIR_AD_HUCRE} sm:pl-4`}>
<TableCell className={SATIR_AD_HUCRE}>
<span className="flex items-start gap-3">
<UniLogo ad={p.universite} boy="sm" />
<span className="min-w-0 flex-1">

View File

@@ -372,7 +372,7 @@ export function ListemGovde({
</Link>
</Button>
<div className="mt-4 flex items-center justify-center gap-4 text-[11px] text-slate-500">
<div className="mt-4 flex flex-wrap items-center justify-center gap-x-4 gap-y-1 text-xs text-slate-500">
<span className="inline-flex items-center gap-1">
<ShieldCheck className="size-3.5" aria-hidden />
iyzico güvenli ödeme

View File

@@ -26,12 +26,26 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table";
import { bolumSayfaSlug, uniSayfaSlug } from "@/lib/slug";
import { bolumSayfaSlug, trBaslikDuzeni, uniSayfaSlug } from "@/lib/slug";
import { UNITUR_ETIKET } from "@/lib/unitur";
import { RiskEtiketi } from "@/components/risk-etiketi";
import {
SATIR_AD,
SATIR_AD_DUZ,
SATIR_AD_HUCRE,
SATIR_ALT_AD,
SATIR_BASLIK,
SATIR_BUTON_BASLIK,
SATIR_BUTON_HUCRE,
SATIR_CIP,
SATIR_IKINCIL_LINK,
SATIR_META,
SATIR_MOBIL_SAYI,
} from "@/components/liste-satiri";
import { VERI_YIL_SAYISI } from "@/lib/veri-yillari";
import type { RaporSonuc } from "@/features/rapor/types/rapor";
import {
DILIM_ETIKET,
RISK_ETIKET,
dilimdenFarkliRiskEtiketi,
dilimdenRisk,
riskHesapla,
@@ -39,13 +53,11 @@ import {
} from "@/lib/risk";
import type { Dilim } from "@/lib/rapor-havuzu";
// Risk renk dili: yeşil = güvenli, sarı = az riskli, kırmızı = riskli.
// Nokta hiçbir yerde tek başına durmaz; yanındaki etiket her ekran
// genişliğinde yazılı durur (renk tek başına anlam taşımaz).
const RISK_STIL: Record<RiskSeviyesi, { nokta: string; icon: typeof Rocket }> = {
riskli: { nokta: "bg-red-500", icon: Rocket },
"az-riskli": { nokta: "bg-amber-500", icon: Scale },
guvenli: { nokta: "bg-emerald-500", icon: ShieldCheck },
// Detay başlığındaki dilim ikonu; risk etiketi RiskEtiketi'nden (§4.5).
const RISK_STIL: Record<RiskSeviyesi, { icon: typeof Rocket }> = {
riskli: { icon: Rocket },
"az-riskli": { icon: Scale },
guvenli: { icon: ShieldCheck },
};
// Sütun sayısı: # · Program · Son N yıl · Risk · Taban sıra · detay oku
@@ -78,26 +90,28 @@ export function RaporSatirDetayi({
const farkliRisk = dilimdenFarkliRiskEtiketi(dilim, risk);
return (
<>
<div className="mb-2 flex flex-wrap items-center gap-2 text-xs text-slate-500">
<stil.icon className="size-3.5" aria-hidden />
<span className="font-medium">
<div className="mb-3 flex flex-wrap items-center gap-2 text-sm text-slate-500">
<stil.icon className="size-4" aria-hidden />
<span className="font-semibold text-slate-700">
{DILIM_ETIKET[dilim as Dilim] ?? dilim}
{farkliRisk ? ` · ${farkliRisk}` : null}
</span>
{unitur ? <span>· {unitur}</span> : null}
{unitur ? (
<span>· {UNITUR_ETIKET[unitur]?.cip ?? unitur}</span>
) : null}
</div>
<dl className="grid gap-2 text-sm sm:grid-cols-2">
<div className="rounded-lg border border-slate-200 bg-white p-3">
<dt className="text-xs font-semibold text-slate-500">
<dl className="grid gap-3 text-base leading-relaxed sm:grid-cols-2">
<div className="rounded-xl border border-slate-200 bg-white p-4">
<dt className="text-sm font-semibold text-slate-900">
Neden listede?
</dt>
<dd className="mt-1 text-slate-700">{gerekce}</dd>
<dd className="mt-1 text-slate-600">{gerekce}</dd>
</div>
<div className="rounded-lg border border-slate-200 bg-white p-3">
<dt className="text-xs font-semibold text-slate-500">
<div className="rounded-xl border border-slate-200 bg-white p-4">
<dt className="text-sm font-semibold text-slate-900">
Risk ve Yapay Zeka yorumu
</dt>
<dd className="mt-1 text-slate-700">
<dd className="mt-1 text-slate-600">
{riskNotu} {trendOzeti}
</dd>
</div>
@@ -181,11 +195,19 @@ export function RaporListesi({
const risk =
(adaySira != null ? riskHesapla(p?.efektifSira, adaySira) : null) ??
dilimdenRisk(t.dilim);
const stil = RISK_STIL[risk];
const seri = raporSiraSerisi(p?.siraGecmisi, p?.ilkYil);
const taban = p?.efektifSira ?? programEtkinSira(seri);
const acikMi = acik.has(t.sira);
const devlet = p?.unitur === "DEVLET";
const tabanMetni = taban != null ? `~${taban.toLocaleString("tr-TR")}.` : "—";
const riskHucresi = analizKilitli ? (
<span className="inline-flex items-center gap-1.5 text-xs font-semibold text-slate-500">
<Lock className="size-3.5 shrink-0 text-slate-400" aria-hidden />
Pakette
</span>
) : (
<RiskEtiketi risk={risk} />
);
return (
<Fragment key={t.sira}>
@@ -197,84 +219,77 @@ export function RaporListesi({
onClick={() => tiklandi(t.sira)}
className="kt-cv-satir cursor-pointer"
>
<TableCell className="pl-4 pr-0">
<span className="flex size-7 items-center justify-center rounded-full bg-slate-100 font-heading text-xs font-bold">
<TableCell className="pl-4 pr-0 align-top sm:pl-5">
<span className="mt-4 flex size-8 items-center justify-center rounded-full bg-slate-100 font-heading text-sm font-bold text-slate-900">
{t.sira}
</span>
</TableCell>
<TableCell className="max-w-0 w-full">
<span className="flex min-w-0 items-center gap-2.5">
{p?.universite ? <UniLogo ad={p.universite} boy="sm" /> : null}
<TableCell className={SATIR_AD_HUCRE}>
<span className="flex items-start gap-3">
{/* Telefonda logo yok: sıra numarası satırı zaten çapalıyor,
logo adı üç satıra sıkıştırıyordu (375 px ölçümü). */}
{p?.universite ? (
<span className="hidden sm:block">
<UniLogo ad={p.universite} boy="sm" />
</span>
) : null}
<span className="min-w-0 flex-1">
{p ? (
<Link
href={`/bolum/${bolumSayfaSlug(p.isim)}`}
className="block truncate text-sm font-semibold hover:text-primary hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
className={SATIR_AD}
title={`${p.isim} bölüm sayfası`}
onClick={(e) => e.stopPropagation()}
>
{p.isim}
</Link>
) : (
<span className="block truncate text-sm font-semibold">
{t.programId}
</span>
<span className={SATIR_AD_DUZ}>{t.programId}</span>
)}
<span className="mt-0.5 flex items-center gap-1.5 text-xs text-slate-500">
{p?.unitur ? (
<span
className={`shrink-0 rounded px-1 py-px text-[10px] font-medium leading-4 ${
devlet
? "bg-slate-100 text-slate-600"
: "bg-violet-50 text-violet-600"
}`}
{p?.universite ? (
<span className={SATIR_ALT_AD}>
<Link
href={`/universite/${uniSayfaSlug(p.universite)}`}
className={SATIR_IKINCIL_LINK}
title={`${p.universite} taban puanları sayfası`}
onClick={(e) => e.stopPropagation()}
>
{devlet ? "Devlet" : "Vakıf"}
</span>
{trBaslikDuzeni(p.universite)}
</Link>
</span>
) : null}
<span className={SATIR_META}>
{p?.unitur ? (
<span className={SATIR_CIP}>{devlet ? "Devlet" : "Vakıf"}</span>
) : null}
<span className="truncate">
{p?.universite ? (
<Link
href={`/universite/${uniSayfaSlug(p.universite)}`}
className="hover:text-primary hover:underline"
title={`${p.universite} taban puanları sayfası`}
onClick={(e) => e.stopPropagation()}
>
{p.universite}
</Link>
) : null}
{p?.il ? ` · ${p.il.toLocaleLowerCase("tr-TR")}` : ""}
{p?.il ? (
<span className="shrink-0">{trBaslikDuzeni(p.il)}</span>
) : null}
</span>
<span className={SATIR_MOBIL_SAYI}>
{riskHucresi}
<span className="inline-flex items-center gap-1.5">
Taban sıra
<span className="font-semibold tabular-nums text-slate-900">
{tabanMetni}
</span>
<ProgramTabanTrendi program={seri} />
</span>
</span>
</span>
</span>
</TableCell>
<TableCell className="hidden text-right text-xs md:table-cell">
<TableCell className="hidden text-right text-sm lg:table-cell">
<ProgramSiraGecmisi program={seri} />
</TableCell>
<TableCell className="text-xs font-medium">
{analizKilitli ? (
<span className="inline-flex items-center gap-1.5 text-slate-500">
<Lock className="size-3.5 shrink-0 text-slate-400" aria-hidden />
<span className="sr-only sm:not-sr-only">Pakette</span>
</span>
) : (
<span className="inline-flex items-center gap-1.5">
<span
className={`size-2.5 shrink-0 rounded-full ${stil.nokta}`}
aria-hidden
/>
<span>{RISK_ETIKET[risk]}</span>
</span>
)}
</TableCell>
<TableCell className="text-right text-xs tabular-nums text-slate-500">
<span className="inline-flex items-center gap-1">
<TableCell className="hidden sm:table-cell">{riskHucresi}</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={seri} />
{taban != null ? `~${taban.toLocaleString("tr-TR")}.` : "—"}
{tabanMetni}
</span>
</TableCell>
<TableCell className="pr-4 text-right">
<TableCell className={SATIR_BUTON_HUCRE}>
<button
type="button"
aria-expanded={acikMi}
@@ -282,7 +297,7 @@ export function RaporListesi({
e.stopPropagation();
tiklandi(t.sira);
}}
className="inline-flex size-8 min-h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-white text-slate-500 transition-[background-color,border-color,color,transform] duration-150 hover:border-primary hover:bg-primary/5 hover:text-primary active:scale-[0.92] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
className="inline-flex size-11 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-white text-slate-500 transition-[background-color,border-color,color,transform] duration-150 hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500 active:scale-[0.92] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
>
<ChevronDown
className={`size-4 transition-transform duration-200 ${acikMi ? "rotate-180" : ""}`}
@@ -299,21 +314,22 @@ export function RaporListesi({
<TableRow className="hover:bg-transparent">
<TableCell
colSpan={SUTUN_SAYISI}
className="whitespace-normal bg-slate-50/60 px-4 py-4"
className="whitespace-normal bg-slate-50 px-4 py-5 sm:px-5"
>
{analizKilitli ? (
<>
<div className="mb-2 flex flex-wrap items-center gap-2 text-xs text-slate-500">
<Lock className="size-3.5" aria-hidden />
<span className="font-medium">Kişisel analiz pakette</span>
{p?.unitur ? <span>· {p.unitur}</span> : null}
<div className="mb-3 flex flex-wrap items-center gap-2 text-sm text-slate-500">
<Lock className="size-4" aria-hidden />
<span className="font-semibold text-slate-700">
Kişisel analiz pakette
</span>
</div>
<div className="rounded-lg border border-dashed border-slate-300 bg-white p-3">
<p className="flex items-center gap-1.5 text-xs font-semibold text-slate-700">
<Lock className="size-3.5" aria-hidden />
<div className="rounded-xl border border-dashed border-slate-300 bg-white p-4">
<p className="flex items-center gap-1.5 text-sm font-semibold text-slate-900">
<Lock className="size-4" aria-hidden />
Yapay Zeka karar desteği
</p>
<p className="mt-1 text-sm text-slate-600">
<p className="mt-1 text-base leading-relaxed text-slate-600">
Bu bölümün neden listende olduğunu ve sıralamana özel
yerleşme riskini paketle gör.
</p>
@@ -333,9 +349,9 @@ export function RaporListesi({
<button
type="button"
onClick={() => onHaritadaGor(p.il, t.sira)}
className="mt-3 inline-flex cursor-pointer items-center gap-1.5 text-xs font-medium text-primary transition-colors duration-200 hover:text-primary/80"
className="mt-2 inline-flex min-h-11 cursor-pointer items-center gap-1.5 text-sm font-semibold text-primary transition-colors duration-150 hover:text-orange-500"
>
<MapPin className="size-3.5" aria-hidden />
<MapPin className="size-4" aria-hidden />
Haritada gör
</button>
) : null}
@@ -349,13 +365,13 @@ export function RaporListesi({
return (
<div>
{kilitIdx < rapor.tercihler.length ? (
<p className="text-right text-xs font-medium text-emerald-700">
<p className="text-center text-sm font-semibold text-emerald-700 sm:text-right">
Programlar ve ham veriler ücretsiz
</p>
) : null}
{rapor.kapsam?.uyarlandi ? (
<p className="mt-3 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-900">
<p className="mt-3 rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm leading-relaxed text-amber-900">
Tercihlerine göre {rapor.kapsam.toplam} uygun program bulundu; listen{" "}
{rapor.kapsam.dagilim.hayal} hayal · {rapor.kapsam.dagilim.dengeli}{" "}
dengeli · {rapor.kapsam.dagilim.garanti} güvenli olarak kuruldu. Daha
@@ -364,27 +380,31 @@ export function RaporListesi({
) : null}
{tekIl ? (
<p className="mt-3 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-900">
<p className="mt-3 rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm leading-relaxed text-amber-900">
Listenin {rapor.tercihler.length} tercihi de tek şehirde (
{tekIl.toLocaleLowerCase("tr-TR")}). Boşta kalma riskini azaltmak için
{trBaslikDuzeni(tekIl)}). Boşta kalma riskini azaltmak için
birkaç farklı şehir eklemeyi düşünebilirsin.
</p>
) : null}
<div className="mt-3 overflow-hidden rounded-2xl border border-slate-200 bg-white">
<div className="mt-4 overflow-hidden rounded-2xl border border-slate-200 bg-white">
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-8 pl-4 pr-0">#</TableHead>
<TableHead>Program</TableHead>
<TableHead className="hidden text-right md:table-cell">
<TableRow className="hover:bg-transparent">
<TableHead className={`w-12 pl-4 pr-0 sm:pl-5 ${SATIR_BASLIK}`}>
#
</TableHead>
<TableHead className={`pl-4 ${SATIR_BASLIK}`}>Program</TableHead>
<TableHead className={`hidden text-right lg:table-cell ${SATIR_BASLIK}`}>
Son {yilSayisi} yıl
</TableHead>
<TableHead>
<span className="hidden sm:inline">Yapay Zeka </span>Risk
<TableHead className={`hidden sm:table-cell ${SATIR_BASLIK}`}>
Yapay Zeka riski
</TableHead>
<TableHead className="text-right">Taban sıra</TableHead>
<TableHead className="w-12 pr-4 text-right">
<TableHead className={`hidden text-right sm:table-cell ${SATIR_BASLIK}`}>
Taban sıra
</TableHead>
<TableHead className={SATIR_BUTON_BASLIK}>
<span className="sr-only">Yapay Zeka değerlendirmesi</span>
</TableHead>
</TableRow>

View File

@@ -122,7 +122,7 @@ export async function RaporYazdir() {
</tbody>
</table>
<footer className="mt-6 border-t border-slate-300 pt-3 text-[10px] leading-relaxed text-slate-500">
<footer className="mt-6 border-t border-slate-300 pt-3 text-xs leading-relaxed text-slate-500">
<p>
Bu rapor KolayTercih tarafından resmî YÖK Atlas verisi ({veriAraligi}{" "}
taban sıralamaları, kontenjan ve yerleşme istatistikleri) kullanılarak

View File

@@ -24,7 +24,13 @@ import {
import { useGorunumOlayi } from "@/components/use-gorunum-olayi";
import { olay, siraKovasi } from "@/lib/analitik";
import { dilimdenRisk, riskHesapla } from "@/lib/risk";
import { turkishSlugify } from "@/lib/slug";
import { trBaslikDuzeni, turkishSlugify } from "@/lib/slug";
import {
SATIR_ALT_AD,
SATIR_AD_DUZ,
SATIR_CIP,
SATIR_META,
} from "@/components/liste-satiri";
import { listemUretHref, PROFIL_DEGISTI_EVENT } from "@/features/sihirbaz/sihirbaz-sabitler";
import { tercihProfiliOku } from "@/features/sihirbaz/sihirbaz-profil";
import type { TadimlikSatir, TadimlikTip } from "@/lib/tadimlik-havuzu";
@@ -147,40 +153,34 @@ export function TadimlikSatiri({
</div>
<div className="mt-6 rounded-2xl border border-slate-200 bg-white p-4 shadow-sm sm:p-6">
<div className="flex min-w-0 flex-wrap items-center gap-2.5">
{/* Rapor listesinin satırıyla aynı düzen (§4.15): ad sarar,
üniversite adı altında, taban sıra sağda iri. */}
<div className="flex items-start gap-3">
<UniLogo ad={p.universite} boy="sm" />
<span className="min-w-0 flex-1">
<span className="block truncate text-sm font-semibold">
{p.isim}
<span className={SATIR_AD_DUZ}>{p.isim}</span>
<span className={SATIR_ALT_AD}>
{trBaslikDuzeni(p.universite)}
</span>
<span className="mt-0.5 flex items-center gap-1.5 text-xs text-slate-500">
<span className={SATIR_META}>
{p.unitur ? (
<span
className={`shrink-0 rounded px-1 py-px text-[10px] font-medium leading-4 ${
devlet
? "bg-slate-100 text-slate-600"
: "bg-violet-50 text-violet-600"
}`}
>
{devlet ? "Devlet" : "Vakıf"}
</span>
<span className={SATIR_CIP}>{devlet ? "Devlet" : "Vakıf"}</span>
) : null}
{p.il ? (
<span className="shrink-0">{trBaslikDuzeni(p.il)}</span>
) : null}
<span className="truncate">
{p.universite}
{p.il ? ` · ${p.il.toLocaleLowerCase("tr-TR")}` : ""}
</span>
</span>
</span>
<span className="hidden text-right text-xs md:inline-flex">
<span className="hidden text-right md:inline-flex">
<ProgramSiraGecmisi program={seri} />
</span>
<span className="inline-flex items-center gap-1 text-xs tabular-nums text-slate-500">
<span className="inline-flex shrink-0 items-center gap-1.5 text-base font-semibold tabular-nums text-slate-900">
<ProgramTabanTrendi program={seri} />
{taban != null ? `~${taban.toLocaleString("tr-TR")}.` : "—"}
</span>
</div>
<div className="mt-4 rounded-lg bg-slate-50/60 px-4 py-4">
<div className="mt-4 rounded-xl bg-slate-50 px-4 py-5">
<RaporSatirDetayi
dilim={satir.dilim}
risk={risk}
@@ -201,7 +201,7 @@ export function TadimlikSatiri({
</p>
<Button
asChild
className="h-11 w-full shrink-0 cursor-pointer bg-orange-500 text-white transition-[background-color,transform] duration-200 active:scale-[0.97] hover:bg-orange-600 sm:w-auto"
className="h-12 w-full shrink-0 cursor-pointer bg-orange-500 text-white transition-[background-color,transform] duration-200 active:scale-[0.97] hover:bg-orange-600 sm:w-auto"
>
<Link
href={girisUrl}

View File

@@ -215,7 +215,7 @@ export function TercihDegistiModali({
key={satir.alan}
className={i > 0 ? "border-t border-slate-200" : undefined}
>
<dt className="bg-slate-50 px-3 py-1.5 text-[11px] font-semibold uppercase tracking-wide text-slate-500">
<dt className="bg-slate-50 px-3 py-2 text-sm font-semibold text-slate-700">
{satir.etiket}
</dt>
<dd className="grid grid-cols-2 divide-x divide-slate-200">