fix(tasarim): netler paneli alt sayfa + §4.15 tablo; ok düğmesinde gölge ve hover rengi yok
All checks were successful
Deploy / deploy (push) Successful in 5m3s
All checks were successful
Deploy / deploy (push) Successful in 5m3s
- "Son yerleşenin netleri" ortada açılan Dialog ve text-xs hücreli tabloydu; şimdi Drawer (kap/çarpı cta-sira-form çekmecesiyle birebir), ortalı başlık + bağlam cümlesi, SATIR_BASLIK başlıklar, text-sm hücreler, en yeni yıl koyu, "Yerleşme puanı" satırı ayrılmış (DESIGN.md §4.10, §4.15, yeni §4.19). - Denetim: tablo-minik-yazi (hata) — TableCell/TableHead içinde text-xs yasak; §9.5 bitirmeden listesine ayrıntı paneli/tablo/buton kontrolü eklendi. - Kayıtlı-sıra ok düğmesi: shadow-lg kaldırıldı (§6), hover'da renk değişmiyor (orange-600 iri yüzeyde kırmızımsı okunuyordu); hover scale + ok kayması. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -509,6 +509,20 @@ telefonda tam genişlik), "Şehre göre" çipleri (sayfa içi `#sehir-…` çapa
|
|||||||
- `/universiteler` dizinindeki "Devlet Üniversiteleri" / "Vakıf Üniversiteleri" başlıkları da
|
- `/universiteler` dizinindeki "Devlet Üniversiteleri" / "Vakıf Üniversiteleri" başlıkları da
|
||||||
tür sayfasına link.
|
tür sayfasına link.
|
||||||
|
|
||||||
|
### 4.19 Netler paneli — `program-netleri.tsx` ("Son yerleşenin netleri")
|
||||||
|
Bilal (24 Eyl 2026): "bu kısımlar design md'ye uygun yap, belirt ki bir daha bu hata olmasın".
|
||||||
|
Panel ortada açılan `Dialog` ve `text-xs` hücreli bir tabloydu; iki kural birden çiğnenmişti.
|
||||||
|
**Kural:** program satırından açılan her ayrıntı (netler, akademik göstergeler, ileride
|
||||||
|
kontenjan geçmişi) §4.10 **alt sayfadır** — `Drawer handleOnly`, kap ve çarpı `cta-sira-form.tsx`
|
||||||
|
çekmecesiyle birebir, başlık `px-10 text-center font-heading text-2xl font-bold`, altında tek
|
||||||
|
cümle bağlam `text-sm text-slate-500`. İçindeki tablo §4.15'tir: başlık `SATIR_BASLIK`, hücre
|
||||||
|
`text-sm` (gövde `text-xs`'e inmez, §3), sayılar `font-sans tabular-nums`, **en yeni yıl** koyu
|
||||||
|
(`font-semibold text-slate-800/900`), eski yıllar `text-slate-500`; toplam satırı ("Yerleşme
|
||||||
|
puanı") `border-t border-slate-200` + `font-semibold text-slate-900`; ilk sütun `pl-0`. Boş ve
|
||||||
|
hata durumu `text-base text-slate-500`. Denetim: `tablo-minik-yazi` (hata) — `TableCell`/
|
||||||
|
`TableHead` içinde `text-xs` yazılamaz. `Dialog` yalnız arama penceresi (`katalog-arama`) ve
|
||||||
|
sihirbaz modalı içindir; yeni bir ayrıntı için `Dialog` açılmaz.
|
||||||
|
|
||||||
## 5. Yerleşim
|
## 5. Yerleşim
|
||||||
|
|
||||||
### 5.1 Genel
|
### 5.1 Genel
|
||||||
@@ -669,6 +683,8 @@ Bir ekranı dönüştüren ajan o ekrandaki uyarıları sıfırlar ya da neden k
|
|||||||
### 9.5 Bitirmeden
|
### 9.5 Bitirmeden
|
||||||
`pnpm tasarim:denetim` sıfır hata (uyarılar raporda listelenir) + 375 px'te tek bakış (taşma,
|
`pnpm tasarim:denetim` sıfır hata (uyarılar raporda listelenir) + 375 px'te tek bakış (taşma,
|
||||||
üst üste binme, dokunma hedefi, çekmece tek ekran) + §9.2 ölçümleri.
|
üst üste binme, dokunma hedefi, çekmece tek ekran) + §9.2 ölçümleri.
|
||||||
|
- Yeni ayrıntı paneli mi? `Dialog` değil `Drawer` (§4.10, §4.19). İçinde tablo mu? §4.15
|
||||||
|
sınıfları, hücre `text-sm`, `text-xs` yok. Buton mu? Gölge yok, hover tek turuncu (§2.1, §6).
|
||||||
|
|
||||||
## 10. Samimi ton, ilerleme ve kutlama (öğrenci ekranları)
|
## 10. Samimi ton, ilerleme ve kutlama (öğrenci ekranları)
|
||||||
|
|
||||||
@@ -838,9 +854,12 @@ tabular-nums yok, §3) ve
|
|||||||
altında `text-sm font-semibold text-white/80` "sıra · Sayısal"; başlık `font-heading text-xl
|
altında `text-sm font-semibold text-white/80` "sıra · Sayısal"; başlık `font-heading text-xl
|
||||||
font-bold leading-tight text-balance sm:text-2xl`. **Buton yazısız** (Bilal, 24 Eyl 2026: "buton
|
font-bold leading-tight text-balance sm:text-2xl`. **Buton yazısız** (Bilal, 24 Eyl 2026: "buton
|
||||||
cılız kaldı, yazılı bir buton olmasın" — §4.1'in "metin + sondaki ok" kuralının bilinçli
|
cılız kaldı, yazılı bir buton olmasın" — §4.1'in "metin + sondaki ok" kuralının bilinçli
|
||||||
istisnası): `flex size-14 items-center justify-center rounded-full bg-orange-500 text-white
|
istisnası): `flex size-14 items-center justify-center rounded-full bg-orange-500 text-white` +
|
||||||
shadow-lg shadow-orange-500/30` + `ArrowRight size-7`, hover `bg-orange-600` ve ok 2 px kayar,
|
`ArrowRight size-7`. **Gölge yok** (§6: derinlik gölgeyle verilmez; ilk sürümdeki
|
||||||
basınca `scale-[0.95]`; `aria-label` + `title` "Sıralamana uygun programları gör". Bandın
|
`shadow-lg shadow-orange-500/30` kaldırıldı) ve **hover'da renk değişmez** — iri dolu turuncu
|
||||||
|
yüzeyde `orange-600` kırmızımsı okunuyor (Bilal, 24 Eyl 2026); tepki `hover:scale-[1.04]` + ok
|
||||||
|
2 px kayar, basınca `scale-[0.95]`. Metinli CTA butonlarında `hover:bg-orange-600` kanonik kalır
|
||||||
|
(§2.1); `aria-label` + `title` "Sıralamana uygun programları gör". Bandın
|
||||||
tamamı gerilmiş linkle (`after:absolute after:inset-0`, §4.8) tıklanabilir. **Telefonda iki
|
tamamı gerilmiş linkle (`after:absolute after:inset-0`, §4.8) tıklanabilir. **Telefonda iki
|
||||||
satır:** başlık (`text-lg`) üstte, altında kupa+sayı ile ok **yan yana** (`flex justify-center
|
satır:** başlık (`text-lg`) üstte, altında kupa+sayı ile ok **yan yana** (`flex justify-center
|
||||||
gap-5`; kupa kutusu ve ok telefonda 48 px, sm'den 56 px); lg'de tek satır (sayı · başlık · ok).
|
gap-5`; kupa kutusu ve ok telefonda 48 px, sm'den 56 px); lg'de tek satır (sayı · başlık · ok).
|
||||||
|
|||||||
@@ -212,6 +212,13 @@ const KURALLAR: Kural[] = [
|
|||||||
muaf: /src\/features\/rehber\/components\/rehber-kapak\.tsx$/,
|
muaf: /src\/features\/rehber\/components\/rehber-kapak\.tsx$/,
|
||||||
bul: regexKurali(/\[#[0-9a-fA-F]{3,8}\]/),
|
bul: regexKurali(/\[#[0-9a-fA-F]{3,8}\]/),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ad: "tablo-minik-yazi",
|
||||||
|
seviye: "hata",
|
||||||
|
mesaj:
|
||||||
|
"Tablo hücresi/başlığında text-xs yok: hücre text-sm, başlık SATIR_BASLIK (DESIGN.md §4.15, §4.19, §3). 24 Eyl 2026 netler panelinde yaşandı",
|
||||||
|
bul: regexKurali(/<Table(?:Cell|Head)\b[^>]*\btext-xs\b/),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ad: "minik-yazi",
|
ad: "minik-yazi",
|
||||||
seviye: "uyari",
|
seviye: "uyari",
|
||||||
|
|||||||
@@ -2,23 +2,25 @@
|
|||||||
|
|
||||||
// Program satırındaki "netler" butonu: YÖK Atlas'ın "yerleşen son kişinin
|
// Program satırındaki "netler" butonu: YÖK Atlas'ın "yerleşen son kişinin
|
||||||
// netleri" verisini (data/yokatlas.db → netler tablosu, /api/netler) yıl
|
// netleri" verisini (data/yokatlas.db → netler tablosu, /api/netler) yıl
|
||||||
// sütunlu kompakt bir modalde gösterir. Kadın-erkek dağılımı bilinçli olarak
|
// sütunlu tabloyla alttan açılan sayfada gösterir (DESIGN.md §4.10: ayrıntı
|
||||||
// yok: YÖK Atlas 2026 SPA'sına geçerken cinsiyet panelini yayından kaldırdı
|
// her zaman Drawer, ortada modal değil; §4.19 netler paneli). Kadın-erkek
|
||||||
// (bkz. scripts/detay.ts).
|
// dağılımı bilinçli olarak yok: YÖK Atlas 2026 SPA'sına geçerken cinsiyet
|
||||||
|
// panelini yayından kaldırdı (bkz. scripts/detay.ts).
|
||||||
|
|
||||||
import { SATIR_DUGME_BOYU } from "@/components/liste-satiri";
|
import { SATIR_BASLIK, SATIR_DUGME_BOYU } from "@/components/liste-satiri";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { ListChecks } from "lucide-react";
|
import { ListChecks, X } from "lucide-react";
|
||||||
import type { ProgramNetSatiri } from "@/types/yokatlas";
|
import type { ProgramNetSatiri } from "@/types/yokatlas";
|
||||||
import { olay } from "@/lib/analitik";
|
import { olay } from "@/lib/analitik";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Drawer,
|
||||||
DialogContent,
|
DrawerClose,
|
||||||
DialogDescription,
|
DrawerContent,
|
||||||
DialogHeader,
|
DrawerDescription,
|
||||||
DialogTitle,
|
DrawerTitle,
|
||||||
DialogTrigger,
|
DrawerTrigger,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/drawer";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@@ -91,8 +93,8 @@ export function ProgramNetleriButonu({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog onOpenChange={acildi}>
|
<Drawer onOpenChange={acildi} handleOnly>
|
||||||
<DialogTrigger asChild>
|
<DrawerTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
title="Son yerleşenin netleri"
|
title="Son yerleşenin netleri"
|
||||||
@@ -102,22 +104,31 @@ export function ProgramNetleriButonu({
|
|||||||
<ListChecks className="size-4" aria-hidden />
|
<ListChecks className="size-4" aria-hidden />
|
||||||
<span className="sr-only">{isim} — son yerleşenin netleri</span>
|
<span className="sr-only">{isim} — son yerleşenin netleri</span>
|
||||||
</button>
|
</button>
|
||||||
</DialogTrigger>
|
</DrawerTrigger>
|
||||||
<DialogContent
|
{/* Çekmece kabı ve çarpı cta-sira-form.tsx'teki çekmeceyle birebir (§4.10, §4.3) */}
|
||||||
className="sm:max-w-md"
|
<DrawerContent
|
||||||
|
className="max-h-[92dvh] bg-white sm:mx-auto sm:max-w-2xl sm:border-x sm:border-slate-200 sm:shadow-2xl"
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<DialogHeader>
|
<DrawerClose className="absolute top-3 right-3 z-10 flex size-9 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-popover text-slate-500 transition-[background-color,transform] duration-150 hover:bg-slate-100 hover:text-slate-800 active:scale-[0.96]">
|
||||||
<DialogTitle className="pr-10">Son yerleşenin netleri</DialogTitle>
|
<X className="size-4" aria-hidden />
|
||||||
<DialogDescription>
|
<span className="sr-only">Kapat</span>
|
||||||
|
</DrawerClose>
|
||||||
|
<div className="min-h-0 flex-1 overflow-y-auto px-4 pt-5 pb-[max(1.25rem,env(safe-area-inset-bottom))] sm:px-6">
|
||||||
|
<DrawerTitle className="px-10 text-center font-heading text-2xl font-bold text-slate-900">
|
||||||
|
Son yerleşenin netleri
|
||||||
|
</DrawerTitle>
|
||||||
|
<DrawerDescription className="mx-auto mt-1 max-w-md px-4 text-center text-sm text-slate-500">
|
||||||
{isim}
|
{isim}
|
||||||
{universite ? ` · ${universite}` : ""} — bölüme en düşük puanla
|
{universite ? ` · ${universite}` : ""} — bölüme en düşük puanla
|
||||||
yerleşen adayın sınav netleri (YÖK Atlas).
|
yerleşen adayın sınav netleri (YÖK Atlas).
|
||||||
</DialogDescription>
|
</DrawerDescription>
|
||||||
</DialogHeader>
|
<div className="mt-5">
|
||||||
<NetlerIcerik durum={durum} netler={netler} />
|
<NetlerIcerik durum={durum} netler={netler} />
|
||||||
</DialogContent>
|
</div>
|
||||||
</Dialog>
|
</div>
|
||||||
|
</DrawerContent>
|
||||||
|
</Drawer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,21 +143,21 @@ function NetlerIcerik({
|
|||||||
return (
|
return (
|
||||||
<div className="space-y-2" aria-hidden>
|
<div className="space-y-2" aria-hidden>
|
||||||
{[0, 1, 2, 3, 4].map((i) => (
|
{[0, 1, 2, 3, 4].map((i) => (
|
||||||
<div key={i} className="h-6 animate-pulse rounded-md bg-slate-100" />
|
<div key={i} className="h-10 animate-pulse rounded-lg bg-slate-100" />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (durum === "hata") {
|
if (durum === "hata") {
|
||||||
return (
|
return (
|
||||||
<p className="py-4 text-center text-sm text-slate-500">
|
<p className="py-4 text-center text-base text-slate-500">
|
||||||
Netler yüklenemedi. Modalı kapatıp yeniden açmayı dene.
|
Netler yüklenemedi. Paneli kapatıp yeniden açmayı dene.
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (netler.length === 0) {
|
if (netler.length === 0) {
|
||||||
return (
|
return (
|
||||||
<p className="py-4 text-center text-sm text-slate-500">
|
<p className="py-4 text-center text-base text-slate-500">
|
||||||
Bu program için YÖK Atlas'ta net verisi yayınlanmamış.
|
Bu program için YÖK Atlas'ta net verisi yayınlanmamış.
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
@@ -155,68 +166,76 @@ function NetlerIcerik({
|
|||||||
const dersler = DERSLER.filter((d) =>
|
const dersler = DERSLER.filter((d) =>
|
||||||
netler.some((y) => y[d.alan] != null),
|
netler.some((y) => y[d.alan] != null),
|
||||||
);
|
);
|
||||||
|
// En yeni yıl vurgulu (§1.1 "sık bakılan önde"); eski yıllar bağlam.
|
||||||
|
const sonYil = Math.max(...netler.map((y) => y.yil));
|
||||||
|
const hucre = (yil: number, vurgu = false) =>
|
||||||
|
cn(
|
||||||
|
"py-2.5 text-right text-sm tabular-nums",
|
||||||
|
yil === sonYil
|
||||||
|
? vurgu
|
||||||
|
? "font-semibold text-slate-900"
|
||||||
|
: "font-semibold text-slate-800"
|
||||||
|
: "text-slate-500",
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="-mx-1 overflow-x-auto">
|
<Table>
|
||||||
<Table>
|
<TableHeader>
|
||||||
<TableHeader>
|
<TableRow>
|
||||||
<TableRow>
|
<TableHead className={cn(SATIR_BASLIK, "pl-0")}>Ders</TableHead>
|
||||||
<TableHead className="h-9">Ders</TableHead>
|
{netler.map((y) => (
|
||||||
{netler.map((y) => (
|
<TableHead
|
||||||
<TableHead key={y.yil} className="h-9 text-right tabular-nums">
|
key={y.yil}
|
||||||
{y.yil}
|
className={cn(
|
||||||
</TableHead>
|
SATIR_BASLIK,
|
||||||
))}
|
"text-right tabular-nums",
|
||||||
</TableRow>
|
y.yil === sonYil && "text-slate-900",
|
||||||
</TableHeader>
|
)}
|
||||||
<TableBody>
|
>
|
||||||
{dersler.map((d) => (
|
{y.yil}
|
||||||
<TableRow key={d.alan}>
|
</TableHead>
|
||||||
<TableCell className="py-2 text-xs text-slate-600">
|
|
||||||
{d.etiket}
|
|
||||||
<span className="text-slate-400"> / {d.max}</span>
|
|
||||||
</TableCell>
|
|
||||||
{netler.map((y) => {
|
|
||||||
const deger = y[d.alan];
|
|
||||||
return (
|
|
||||||
<TableCell
|
|
||||||
key={y.yil}
|
|
||||||
className="py-2 text-right text-xs tabular-nums"
|
|
||||||
>
|
|
||||||
{deger != null ? net(deger) : "—"}
|
|
||||||
</TableCell>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</TableRow>
|
|
||||||
))}
|
))}
|
||||||
<TableRow>
|
</TableRow>
|
||||||
<TableCell className="py-2 text-xs font-medium text-slate-600">
|
</TableHeader>
|
||||||
OBP
|
<TableBody>
|
||||||
|
{dersler.map((d) => (
|
||||||
|
<TableRow key={d.alan}>
|
||||||
|
<TableCell className="py-2.5 pl-0 text-sm text-slate-700">
|
||||||
|
{d.etiket}
|
||||||
|
<span className="text-slate-400"> / {d.max}</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{netler.map((y) => (
|
{netler.map((y) => {
|
||||||
<TableCell
|
const deger = y[d.alan];
|
||||||
key={y.yil}
|
return (
|
||||||
className="py-2 text-right text-xs tabular-nums text-slate-500"
|
<TableCell key={y.yil} className={hucre(y.yil)}>
|
||||||
>
|
{deger != null ? net(deger) : "—"}
|
||||||
{y.obp != null ? net(y.obp) : "—"}
|
</TableCell>
|
||||||
</TableCell>
|
);
|
||||||
))}
|
})}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
))}
|
||||||
<TableCell className="py-2 text-xs font-semibold text-slate-700">
|
<TableRow>
|
||||||
Yerleşme puanı
|
<TableCell className="py-2.5 pl-0 text-sm text-slate-500">OBP</TableCell>
|
||||||
|
{netler.map((y) => (
|
||||||
|
<TableCell
|
||||||
|
key={y.yil}
|
||||||
|
className="py-2.5 text-right text-sm tabular-nums text-slate-500"
|
||||||
|
>
|
||||||
|
{y.obp != null ? net(y.obp) : "—"}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{netler.map((y) => (
|
))}
|
||||||
<TableCell
|
</TableRow>
|
||||||
key={y.yil}
|
<TableRow className="border-t border-slate-200">
|
||||||
className="py-2 text-right text-xs font-semibold tabular-nums text-slate-700"
|
<TableCell className="py-3 pl-0 text-sm font-semibold text-slate-900">
|
||||||
>
|
Yerleşme puanı
|
||||||
{y.tabanPuan != null ? net(y.tabanPuan) : "—"}
|
</TableCell>
|
||||||
</TableCell>
|
{netler.map((y) => (
|
||||||
))}
|
<TableCell key={y.yil} className={hucre(y.yil, true)}>
|
||||||
</TableRow>
|
{y.tabanPuan != null ? net(y.tabanPuan) : "—"}
|
||||||
</TableBody>
|
</TableCell>
|
||||||
</Table>
|
))}
|
||||||
</div>
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -442,7 +442,10 @@ export function CtaSiraForm({
|
|||||||
href={sonucHref()}
|
href={sonucHref()}
|
||||||
aria-label="Sıralamana uygun programları gör"
|
aria-label="Sıralamana uygun programları gör"
|
||||||
title="Sıralamana uygun programları gör"
|
title="Sıralamana uygun programları gör"
|
||||||
className="group flex size-12 shrink-0 items-center justify-center rounded-full bg-orange-500 text-white shadow-lg shadow-orange-500/30 transition-[background-color,transform,box-shadow] duration-200 after:absolute after:inset-0 hover:bg-orange-600 hover:shadow-orange-500/40 active:scale-[0.95] sm:size-14 lg:order-3"
|
// Gölge yok (§6: derinlik gölgeyle verilmez), hover'da renk
|
||||||
|
// değişmez (iri dolu yüzeyde orange-600 kırmızımsı okunuyor —
|
||||||
|
// Bilal, 24 Eyl 2026); tepki: ok kayar, basınca küçülür.
|
||||||
|
className="group flex size-12 shrink-0 items-center justify-center rounded-full bg-orange-500 text-white transition-transform duration-200 after:absolute after:inset-0 hover:scale-[1.04] active:scale-[0.95] sm:size-14 lg:order-3"
|
||||||
>
|
>
|
||||||
<ArrowRight
|
<ArrowRight
|
||||||
className="size-6 transition-transform duration-200 group-hover:translate-x-0.5 sm:size-7"
|
className="size-6 transition-transform duration-200 group-hover:translate-x-0.5 sm:size-7"
|
||||||
|
|||||||
Reference in New Issue
Block a user