From 309fb73a34ca79d0b1b44e3c2b27a689c5de7795 Mon Sep 17 00:00:00 2001 From: bilalgursen Date: Thu, 24 Sep 2026 00:57:27 +0300 Subject: [PATCH] =?UTF-8?q?feat(tasarim):=20rapor=20listesi=20ve=20tad?= =?UTF-8?q?=C4=B1ml=C4=B1k=20sat=C4=B1r=C4=B1=20"=C5=9Fi=C5=9Fko=20ve=20sa?= =?UTF-8?q?de"=20dile=20g=C3=B6re?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- docs/tasarim/DESIGN.md | 7 +- src/components/risk-etiketi.tsx | 32 +++ .../liste/components/liste-cekmecesi.tsx | 27 +-- .../liste/components/program-tablosu.tsx | 40 +--- .../rapor/components/listem-govde.tsx | 2 +- .../rapor/components/rapor-listesi.tsx | 216 ++++++++++-------- .../rapor/components/rapor-yazdir.tsx | 2 +- .../rapor/components/tadimlik-satiri.tsx | 44 ++-- .../components/tercih-degisti-modali.tsx | 2 +- 9 files changed, 186 insertions(+), 186 deletions(-) create mode 100644 src/components/risk-etiketi.tsx diff --git a/docs/tasarim/DESIGN.md b/docs/tasarim/DESIGN.md index e77bd02..ec8c9e5 100644 --- a/docs/tasarim/DESIGN.md +++ b/docs/tasarim/DESIGN.md @@ -213,7 +213,8 @@ Alt sayfada (`Drawer`) aynı sınıf seti `DrawerClose` üstünde kullanılır ( - İkon kutusu: `flex size-11 items-center justify-center rounded-xl bg-primary/10` içinde `size-5 text-primary` ikon. Kart içinde sayının yanında küçük hâli: `size-8 … sm:size-10` + `size-4 sm:size-5` ikon (§4.8). - Gölge: `shadow-sm` varsayılan; hover'da `shadow-lg shadow-orange-500/5`. Başka gölge yok. -### 4.5 Risk çipi / etiketi +### 4.5 Risk çipi / etiketi — `RiskEtiketi`, `src/components/risk-etiketi.tsx` +Tablolar, çekmece ve rapor listesi `` kullanır; elle yazılmaz. Nokta + metin: `` yanında `text-xs font-semibold text-emerald-600`; metin `RISK_ETIKET`'ten. Renk tek başına asla. ### 4.6 Form @@ -360,6 +361,10 @@ tablosu bu sabitleri kullanır, sınıfı elle yazmaz. iki buton alt alta durur (`inline-flex flex-col items-center gap-2 sm:flex-row`, sütun `w-14 sm:w-28`): yan yana 96 px yiyip adı 157 px'e sıkıştırıyordu, alt alta 273 px kalıyor (24 Eyl 2026 ölçümü). +- Rapor listesinde (`rapor-listesi.tsx`) telefonda logo gizlenir (`hidden sm:block`): solda + sıra numarası zaten satırı çapalıyor, logo adı üç satıra sıkıştırıyordu (satır 214 → + 152 px). Açılan ayrıntı iç kutuları `rounded-xl`, etiket `text-sm font-semibold + text-slate-900`, metin `text-base`. - Satırda logo varsa (bölüm sayfası) `UniLogo boy="sm"` adın solunda, `items-start`. - Program varyantı ("… (İngilizce) (Burslu)") adın altında ayrı satır `mt-0.5 block text-sm leading-snug text-slate-600`; tür çipine yapıştırılıp kesilmez. diff --git a/src/components/risk-etiketi.tsx b/src/components/risk-etiketi.tsx new file mode 100644 index 0000000..0398422 --- /dev/null +++ b/src/components/risk-etiketi.tsx @@ -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 = { + guvenli: "bg-emerald-500", + "az-riskli": "bg-amber-500", + riskli: "bg-red-500", +}; + +const RISK_METIN: Record = { + guvenli: "text-emerald-600", + "az-riskli": "text-amber-600", + riskli: "text-red-600", +}; + +export function RiskEtiketi({ risk }: { risk: RiskSeviyesi }) { + return ( + + + {RISK_ETIKET[risk]} + + ); +} diff --git a/src/features/liste/components/liste-cekmecesi.tsx b/src/features/liste/components/liste-cekmecesi.tsx index 7f22d20..83240b6 100644 --- a/src/features/liste/components/liste-cekmecesi.tsx +++ b/src/features/liste/components/liste-cekmecesi.tsx @@ -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 = { - 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 = { - 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({ {tercih.risk || tercih.efektifSira != null ? ( - {tercih.risk ? ( - - - {RISK_ETIKET[tercih.risk]} - - ) : null} + {tercih.risk ? : null} {tercih.efektifSira != null ? ( Taban sıra diff --git a/src/features/liste/components/program-tablosu.tsx b/src/features/liste/components/program-tablosu.tsx index 73b90e0..3dc2fd0 100644 --- a/src/features/liste/components/program-tablosu.tsx +++ b/src/features/liste/components/program-tablosu.tsx @@ -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 = { - guvenli: "bg-emerald-500", - "az-riskli": "bg-amber-500", - riskli: "bg-red-500", -}; - const BOS_EKSTRA: Record = { 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 = { - guvenli: "text-emerald-600", - "az-riskli": "text-amber-600", - riskli: "text-red-600", -}; - -function RiskEtiketi({ risk }: { risk: RiskSeviyesi }) { - return ( - - - {RISK_ETIKET[risk]} - - ); -} - function ProgramSatiri({ program: p, adaySira, @@ -381,7 +347,7 @@ function ProgramSatiri({ {risk ? : null} - + diff --git a/src/features/rapor/components/listem-govde.tsx b/src/features/rapor/components/listem-govde.tsx index 28feb08..e5b7de8 100644 --- a/src/features/rapor/components/listem-govde.tsx +++ b/src/features/rapor/components/listem-govde.tsx @@ -372,7 +372,7 @@ export function ListemGovde({ -
+
iyzico güvenli ödeme diff --git a/src/features/rapor/components/rapor-listesi.tsx b/src/features/rapor/components/rapor-listesi.tsx index 16db174..9e23d2e 100644 --- a/src/features/rapor/components/rapor-listesi.tsx +++ b/src/features/rapor/components/rapor-listesi.tsx @@ -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 = { - 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 = { + 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 ( <> -
- - +
+ + {DILIM_ETIKET[dilim as Dilim] ?? dilim} {farkliRisk ? ` · ${farkliRisk}` : null} - {unitur ? · {unitur} : null} + {unitur ? ( + · {UNITUR_ETIKET[unitur]?.cip ?? unitur} + ) : null}
-
-
-
+
+
+
Neden listede?
-
{gerekce}
+
{gerekce}
-
-
+
+
Risk ve Yapay Zeka yorumu
-
+
{riskNotu} {trendOzeti}
@@ -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 ? ( + + + Pakette + + ) : ( + + ); return ( @@ -197,84 +219,77 @@ export function RaporListesi({ onClick={() => tiklandi(t.sira)} className="kt-cv-satir cursor-pointer" > - - + + {t.sira} - - - {p?.universite ? : null} + + + {/* 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 ? ( + + + + ) : null} {p ? ( e.stopPropagation()} > {p.isim} ) : ( - - {t.programId} - + {t.programId} )} - - {p?.unitur ? ( - + e.stopPropagation()} > - {devlet ? "Devlet" : "Vakıf"} - + {trBaslikDuzeni(p.universite)} + + + ) : null} + + {p?.unitur ? ( + {devlet ? "Devlet" : "Vakıf"} ) : null} - - {p?.universite ? ( - e.stopPropagation()} - > - {p.universite} - - ) : null} - {p?.il ? ` · ${p.il.toLocaleLowerCase("tr-TR")}` : ""} + {p?.il ? ( + {trBaslikDuzeni(p.il)} + ) : null} + + + {riskHucresi} + + Taban sıra + + {tabanMetni} + + - + - - {analizKilitli ? ( - - - Pakette - - ) : ( - - - {RISK_ETIKET[risk]} - - )} - - - + {riskHucresi} + + - {taban != null ? `~${taban.toLocaleString("tr-TR")}.` : "—"} + {tabanMetni} - + ) : null} @@ -349,13 +365,13 @@ export function RaporListesi({ return (
{kilitIdx < rapor.tercihler.length ? ( -

+

Programlar ve ham veriler ücretsiz

) : null} {rapor.kapsam?.uyarlandi ? ( -

+

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 ? ( -

+

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.

) : null} -
+
- - # - Program - + + + # + + Program + Son {yilSayisi} yıl - - Yapay Zeka Risk + + Yapay Zeka riski - Taban sıra - + + Taban sıra + + Yapay Zeka değerlendirmesi diff --git a/src/features/rapor/components/rapor-yazdir.tsx b/src/features/rapor/components/rapor-yazdir.tsx index 10fc8c0..df81b29 100644 --- a/src/features/rapor/components/rapor-yazdir.tsx +++ b/src/features/rapor/components/rapor-yazdir.tsx @@ -122,7 +122,7 @@ export async function RaporYazdir() {
-
+

Bu rapor KolayTercih tarafından resmî YÖK Atlas verisi ({veriAraligi}{" "} taban sıralamaları, kontenjan ve yerleşme istatistikleri) kullanılarak diff --git a/src/features/rapor/components/tadimlik-satiri.tsx b/src/features/rapor/components/tadimlik-satiri.tsx index 1f7e8cf..3e0d7a7 100644 --- a/src/features/rapor/components/tadimlik-satiri.tsx +++ b/src/features/rapor/components/tadimlik-satiri.tsx @@ -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({

-
+ {/* Rapor listesinin satırıyla aynı düzen (§4.15): ad sarar, + üniversite adı altında, taban sıra sağda iri. */} +
- - {p.isim} + {p.isim} + + {trBaslikDuzeni(p.universite)} - + {p.unitur ? ( - - {devlet ? "Devlet" : "Vakıf"} - + {devlet ? "Devlet" : "Vakıf"} + ) : null} + {p.il ? ( + {trBaslikDuzeni(p.il)} ) : null} - - {p.universite} - {p.il ? ` · ${p.il.toLocaleLowerCase("tr-TR")}` : ""} - - + - + {taban != null ? `~${taban.toLocaleString("tr-TR")}.` : "—"}
-
+