fix(erisilebilirlik): risk göstergesinin adı satırda yazılı dursun

/sonuc program tablosunda risk yalnız renkli bir noktaydı (aria-hidden,
görünür metin yok); /listem'de etiket vardı ama sm altında sr-only idi.
Trafiğin büyük kısmı mobil olduğu için gerçek kullanıcı yalnız rengi
görüyordu. AGENTS.md: "kırmızı/sarı/yeşil her zaman metin etiketiyle
birlikte, renk tek başına anlam taşımaz."

- program-tablosu: nokta + RISK_ETIKET[risk] kalıbı rapor-listesi'nden
  birebir kopyalandı; boş kalan ilk sütun başlığı "Risk" oldu.
- rapor-listesi: risk etiketindeki sr-only sm:not-sr-only kaldırıldı.

Yeni bileşen/sabit/olay yok; etiket metninin tek kaynağı src/lib/risk.ts
içindeki RISK_ETIKET ve o dosyaya dokunulmadı.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-23 00:16:06 +03:00
parent 9bd448bd16
commit 2dbc8b5039
3 changed files with 89 additions and 12 deletions

View File

@@ -0,0 +1,68 @@
# 07 — P1: Riskin adı satırda yazsın
Dal: `gece/0922-risk-etiketi` · Ajan: `yazilimci` · Kapsam: CEO kararları §3 / P1
---
## Özet (5 madde)
1. `/sonuc` program tablosunda risk göstergesi artık **renkli nokta + yazılı ad**. Etiketin kaynağı `RISK_ETIKET` (`src/lib/risk.ts`); `risk.ts`'e dokunulmadı.
2. `/listem` (rapor listesi) risk etiketindeki `sr-only sm:not-sr-only` kaldırıldı — etiket artık 390px dahil her genişlikte görünüyor.
3. Yeni bileşen, yeni sabit, yeni olay yok. İki dosya değişti, toplam +21/−12 satır.
4. `/sonuc` tablosunda **boş olan ilk sütun başlığına "Risk" yazıldı** — şartnamede açıkça yazmıyordu, sapma olarak aşağıda gerekçelendirildi.
5. `next typegen` + `tsc --noEmit` + `lint` temiz (çalıştırılarak doğrulandı). Build alınmadı (iş tanımı istemiyordu), tarayıcıda doğrulama yapılmadı (AGENTS.md).
---
## Ne değişti
### `src/features/liste/components/program-tablosu.tsx`
- `RISK_ETIKET` import'a eklendi.
- Satırın ilk hücresi (`ProgramSatiri`, eski 306-314): `block size-2.5 … aria-hidden` olan tek nokta yerine,
`rapor-listesi.tsx:262-270` kalıbının birebir aynısı: `inline-flex items-center gap-1.5` kabında
`size-2.5 shrink-0 rounded-full` nokta (`aria-hidden`) + yanında `{RISK_ETIKET[risk]}`.
Hücreye `text-xs font-medium` verildi — rapor listesindeki risk hücresiyle aynı tipografi.
- Tablo başlığı: `<TableHead className="w-8" />` → `<TableHead className="w-8 pl-4 pr-0">Risk</TableHead>`.
- `RISK_NOKTA`'nın üstüne renk dili yorumu eklendi (rapor-listesi'ndeki yorumun eşi).
### `src/features/rapor/components/rapor-listesi.tsx`
- `:267` `<span className="sr-only sm:not-sr-only">` → `<span>`; etiket her zaman görünür.
- `RISK_STIL` üstündeki yorumdaki "dar ekranda sr-only olarak kalır" cümlesi gerçeğe göre düzeltildi.
Başka dosyaya dokunulmadı. `src/lib/risk.ts` değişmedi.
---
## Kabul kriterleri
| # | Kriter | Durum | Nasıl doğrulandı |
|---|---|---|---|
| 1 | `/sonuc` ve `/listem` satırlarında risk **yazıyla** görünür, kaynak `RISK_ETIKET` | ✔ | Koddan: `program-tablosu.tsx` risk hücresi `{RISK_ETIKET[risk]}` basıyor; `rapor-listesi.tsx`'te etiketi gizleyen tek sınıf (`sr-only`) kalktı. `grep -n "sr-only" ` ile risk hücresinde kalıntı yok |
| 2 | 390px'te etiket kesilmez, satır taşmaz | ✔ (koddan çıkarım — tarayıcıda bakılmadı) | `TableCell` varsayılanı zaten `whitespace-nowrap`, yani etiket kesilmez/sarmalanmaz. Program hücresi `max-w-0 w-full` + `truncate` olduğu için artan genişliği o sütun yutar, tablo yatay taşmaz. Genişlik bedeli aşağıda |
| 3 | `RISK_NOKTA` rengi korunur ama tek başına anlam taşımaz | ✔ | `RISK_NOKTA` haritası aynen duruyor; nokta `aria-hidden` kaldı, anlamı taşıyan artık yanındaki metin |
| 4 | `tsc` + `lint` temiz | ✔ | `pnpm exec next typegen` → "Types generated successfully"; `pnpm exec tsc --noEmit` → çıkış 0, hiç çıktı yok; `pnpm lint` → hiç çıktı yok |
---
## Şartnameden sapmalar (2 adet, ikisi de küçük)
1. **`/sonuc` tablosunun ilk sütun başlığına "Risk" yazıldı.** Şartname yalnız satırdan söz ediyordu. Gerekçe: o sütun artık ikonik değil metinsel içerik taşıyor; başlığı boş bırakmak hem `rapor-listesi.tsx`'teki eşdeğer sütunla (orada başlık "Risk") çelişirdi hem de başlıksız metin sütunu bırakırdı. Genişlik bedeli yok — başlık ("Risk", ~30px) hücre içeriğinden dar, sütunu genişletmiyor. Başlığa `pl-4 pr-0` verildi ki hücrelerle hizalansın (yine `rapor-listesi.tsx:380`'deki `#` başlığının deseni).
2. **Tablonun yer darlığı için icat yapılmadı**, şartnamedeki yol izlendi: mevcut sütun yapısı korundu, etiket noktanın yanına `text-xs` (rapor listesiyle aynı punto) ile kondu. Daha küçük punto (`text-[10px]`) denenmedi çünkü kazancı ~5px, bedeli ise AGENTS.md'nin "aynı eleman iki yerde birebir aynı olsun" kuralından sapmak olurdu.
---
## Bilal'in gözle bakması gereken (tek madde)
**`/sonuc` tablosu 390px'te.** Risk sütunu artık ~86px yer kaplıyor (16px sol boşluk + 10px nokta + 6px boşluk + en uzun etiket "Az riskli" ≈ 55px). Bu genişliği program adı sütunu veriyor; o sütun `truncate` olduğu için satır taşmıyor ama **program adı daha erken kısalıyor** (kabaca 150px'ten ~85px'e; üniversite logosu da aynı hücrede). Kesilme yok, kısalma var. Tarayıcıda doğrulanmadı (AGENTS.md gereği açmadım) — telefonda bir bakış yeterli. Dar gelirse iki ucuz seçenek var, ikisi de ayrı karar: (a) etiketi `text-[10px]`e düşür, (b) `Kontenjan` sütununun `sm` eşiğini yükselt.
---
## Merge sonrası doğrulanması gerekenler
- `/sonuc` üç dilim sekmesinde de (hayal/dengeli/güvenli) etiket doğru kelimeyi yazıyor mu; taban verisi olmayan satırda (risk `null`) hücre boş kalıyor mu.
- `/listem` mobilde risk sütunu: kilitli satırlarda hücre içeriği hâlâ yalnız asma kilit ikonu (aşağıdaki nota bakın).
## Kapsam dışı bıraktıklarım (dokunmadım, sahibi ben değilim / şartname dışı)
- **`rapor-listesi.tsx:264` "Pakette" etiketi hâlâ `sr-only sm:not-sr-only`.** Yani mobilde kilitli satırın risk hücresinde yalnız asma kilit ikonu görünüyor. Bu bir renk ihlali değil (ikon, renk değil) ve şartname yalnız `:267`'yi kapsıyordu, o yüzden dokunmadım. Ama artık aynı sütunda bir satır "Az riskli" yazarken diğerinin sadece ikon göstermesi tutarsız duruyor; sütun genişliği zaten risk etiketine göre belirlendiği için bunu görünür yapmanın **ek genişlik maliyeti yok**. Tek satırlık iş, ayrı karar.
- **`liste-cekmecesi.tsx:426`** — çekmecedeki tercih satırlarında risk yalnız renkli nokta (`aria-label` var, görünür metin yok). Aynı çekmecenin başlığında renk dilini açıklayan yazılı bir açıklama listesi (`:172-184`) olduğu için tam ihlal sayılmaz; yine de bu, risk renginin metinsiz göründüğü **üçüncü** yüzey. Şartnamede yok, dosya sahibi değilim — backlog adayı.

View File

@@ -20,7 +20,12 @@ import type {
PuanTuruKey, PuanTuruKey,
RankResultsListe, RankResultsListe,
} from "@/types/yokatlas"; } from "@/types/yokatlas";
import { DILIM_ETIKET, riskHesapla, type RiskSeviyesi } from "@/lib/risk"; import {
DILIM_ETIKET,
RISK_ETIKET,
riskHesapla,
type RiskSeviyesi,
} from "@/lib/risk";
import { bolumSayfaSlug, uniSayfaSlug } from "@/lib/slug"; import { bolumSayfaSlug, uniSayfaSlug } from "@/lib/slug";
import { VERI_YIL_SAYISI } from "@/lib/veri-yillari"; import { VERI_YIL_SAYISI } from "@/lib/veri-yillari";
import { import {
@@ -73,6 +78,9 @@ 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> = { const RISK_NOKTA: Record<RiskSeviyesi, string> = {
guvenli: "bg-emerald-500", guvenli: "bg-emerald-500",
"az-riskli": "bg-amber-500", "az-riskli": "bg-amber-500",
@@ -237,7 +245,7 @@ export function ProgramTablosu({
<Table> <Table>
<TableHeader> <TableHeader>
<TableRow> <TableRow>
<TableHead className="w-8" /> <TableHead className="w-8 pl-4 pr-0">Risk</TableHead>
<TableHead>Program</TableHead> <TableHead>Program</TableHead>
<TableHead className="hidden text-right md:table-cell"> <TableHead className="hidden text-right md:table-cell">
Son {VERI_YIL_SAYISI} yıl Son {VERI_YIL_SAYISI} yıl
@@ -304,12 +312,15 @@ function ProgramSatiri({
return ( return (
<TableRow className="kt-cv-satir"> <TableRow className="kt-cv-satir">
<TableCell className="pl-4 pr-0"> <TableCell className="pl-4 pr-0 text-xs font-medium">
{risk ? ( {risk ? (
<span <span className="inline-flex items-center gap-1.5">
className={`block size-2.5 rounded-full ${RISK_NOKTA[risk]}`} <span
aria-hidden className={`size-2.5 shrink-0 rounded-full ${RISK_NOKTA[risk]}`}
/> aria-hidden
/>
{RISK_ETIKET[risk]}
</span>
) : null} ) : null}
</TableCell> </TableCell>
<TableCell className="max-w-0 w-full"> <TableCell className="max-w-0 w-full">

View File

@@ -40,8 +40,8 @@ import {
import type { Dilim } from "@/lib/rapor-havuzu"; import type { Dilim } from "@/lib/rapor-havuzu";
// Risk renk dili: yeşil = güvenli, sarı = az riskli, kırmızı = riskli. // 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 dar ekranda sr-only // Nokta hiçbir yerde tek başına durmaz; yanındaki etiket her ekran
// olarak kalır (renk tek başına anlam taşımaz). // genişliğinde yazılı durur (renk tek başına anlam taşımaz).
const RISK_STIL: Record<RiskSeviyesi, { nokta: string; icon: typeof Rocket }> = { const RISK_STIL: Record<RiskSeviyesi, { nokta: string; icon: typeof Rocket }> = {
riskli: { nokta: "bg-red-500", icon: Rocket }, riskli: { nokta: "bg-red-500", icon: Rocket },
"az-riskli": { nokta: "bg-amber-500", icon: Scale }, "az-riskli": { nokta: "bg-amber-500", icon: Scale },
@@ -264,9 +264,7 @@ export function RaporListesi({
className={`size-2.5 shrink-0 rounded-full ${stil.nokta}`} className={`size-2.5 shrink-0 rounded-full ${stil.nokta}`}
aria-hidden aria-hidden
/> />
<span className="sr-only sm:not-sr-only"> <span>{RISK_ETIKET[risk]}</span>
{RISK_ETIKET[risk]}
</span>
</span> </span>
)} )}
</TableCell> </TableCell>