Files
kolaytercih/docs/gece-vardiyasi/2026-09-23/09-harita-ve-tur-tasarim.md
bilalgursen a42a1a9920
All checks were successful
Deploy / deploy (push) Successful in 17s
docs(ekip): 22-23 Eylül vardiya raporları, BACKLOG/KARARLAR/PROTOKOL güncellemeleri
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 11:43:11 +03:00

24 KiB
Raw Blame History

09 — Tasarım: /sonuc haritası en üste + üniversite sayfasında tür

Temel: is/0923-harita-ve-tur worktree'si, origin/main (c5769e2). Karşılaştırma için gece/0922-urap dalı git show ile okundu. Tarayıcı/dev sunucusu açılmadı, kod değiştirilmedi. Piksel ve CLS değerleri token/kod okumasından hesaplandı, ölçülmedi — hesap §1.2'de açık. Her iki talimat da "yapılacak" kabul edildi; aşağıdakiler nasıl yapılacağıdır.


Özet — 5 madde

  1. Harita en üste çıkabilir ve CLS bedeli sıfıra inebilir. Tek gereken, listenin sayısını sunucunun hidrasyondan önce bilmesi. Profil zaten kolaytercih.profil çerezi ile sunucuya aynalanıyor (sihirbaz-profil.ts:51-57); aynı desenle kolaytercih.liste-sayi çerezi yazılır, /sonuc bunu okuyup haritaya tam ölçülü yer ayırır. Uygulama yükü: 3 dosya, ~25 satır.
  2. "Boşken hiç gözükmesin" şartı bozulmuyor. Çerez yoksa ya da 0 ise ManuelHarita bugünkü gibi null döner — ilk kez gelen ziyaretçi için DOM'da hiçbir düğüm yoktur, dolayısıyla tadımlığın first:mt-0 kuralı (tadimlik-satiri.tsx:134) da bozulmaz. İlk ziyaretçide sıra değişmiyor — doğrulandı (manuel-harita.tsx:71 return null).
  3. Tadımlığın kaybı kabul edilebilir ve dar. Kayıp yalnız "girişsiz + kayıtlı listesi olan" ziyaretçide var. 375×812'de tadımlığın rozeti, H2'si ve açıklaması harita eklendikten sonra da katlamanın üstünde kalıyor (hesap §1.4); yalnız örnek satır kartı aşağı iniyor. Bu ziyaretçi "bu ürün ne?" aşamasını geçmiş, ekranda önce kendi listesini görmesi doğru.
  4. Üniversite sayfasında tür, ızgaraya değil kimlik satırına gider. Izgara 5 karta çıkamaz: lg:grid-cols-[1fr_1fr_1.35fr] lg:grid-rows-2 şablonunda harita 2 satır kaplıyor, kartlar için tam 4 hücre var (universite-icerik.tsx:291, universite-konum-haritasi.tsx:77). Tür zaten bir metrik değil kategori; sitenin geri kalanında (4 ayrı dosyada) başlığın altındaki meta satırında çip olarak yaşıyor. Aynı çip H1'in altına konur, ızgara 4 sayısal kart kalır.
  5. Yan bulgu: unitur etiketinin 4 farklı sözlüğü var ve ikisi bozuk metin basıyor (universite-icerik.tsx:318 ve bolum-program-listesi.tsx:227 → "Kktc", "Vakıf Myo"). UNITUR_ETIKET (bugün gece/0922-urap'ta, bileşenin içinde) src/lib/'e taşınmalı — tıpkı DILIM_ETIKET'in src/lib/risk.ts'te tek kaynak olması gibi (AGENTS.md).

Talimat 1 — /sonuc'ta harita en üste

1.1 Bugünkü durum (doğrulandı)

Olgu Kanıt
Sıra: tadımlık → tablo → harita src/app/sonuc/page.tsx:118, 124, 131
Liste boşken harita hiç çizilmiyor manuel-harita.tsx:71 (if (liste.length === 0) return null)
Sunucu snapshot'ı her zaman boş liste-store.ts:30, 86 (getServerSnapshot → BOS_LISTE)
Liste yalnız localStorage'ta liste-store.ts:27, 42-46
Profil ise sunucuya çerezle aynalanıyor sihirbaz-profil.ts:51-57, sonuc/page.tsx:65
Store her sayfada hidrasyonda okunuyor layout.tsx:98-102 → ListeCekmecesiLazy/KaydetBannerLazy → useManuelListe

Son satır kritik: liste store'u site genelinde, ilk açılan sayfada yükleniyor. Yani yazılacak çerez, kullanıcı /sonuc'a varmadan önce (ana sayfada) yazılmış oluyor.

1.2 CLS hesabı — "368 px" rakamı masaüstündü

main = max-w-4xl px-4 (sonuc/page.tsx:99). Harita w-full, viewBox 1050×447 (harita.ts:10-13, tercih-haritasi.tsx:46-51), iskelet de aynı oranı rezerve ediyor (tercih-haritasi-lazy.tsx:14).

Ekran İçerik genişliği Harita yüksekliği
375 px (mobil, trafiğin ~%90'ı) 343 px 343 × 447/1050 = 146 px
≥ 928 px (masaüstü) 864 px 864 × 447/1050 = 368 px

Yani sonuc/page.tsx:107'deki "~368 px" masaüstü rakamı; mobilde 146 px (+ bugünkü mt-16 = 64 px). CLS = etki payı × mesafe payı:

Senaryo Etki payı Mesafe payı CLS
Bugün (harita altta), dönüş ziyaretçisi ~0 (kayan içerik ~2,4 ekran aşağıda) — ~0
Harita üstte, yer ayırmadan, 375×812 (812−220)/812 ≈ 0,73 146/812 = 0,18 ~0,13 ("iyileştirilmeli")
Harita üstte, yer ayırmadan, 1280×800 ~0,75 368/800 = 0,46 ~0,35 ("kötü")
Harita üstte + çerezle yer ayrılmış 0 0 0

(Hesap; ölçüm değil. 220 px = bant + başlık + py-12, önceki raporun tahmini.)

1.3 İki alternatif

Alternatif A — liste sayısı çerezi, tek yuva (ÖNERİLEN)

375 px · /sonuc · DÖNÜŞ ziyaretçisi (çerez: liste-sayi=7)
┌───────────────────────────────┐   ← ilk boyada sunucudan gelen HTML
│ [bant] [başlık]               │
│                               │
│  ░░░░░░░░░░░░░░░░░░░░░░░░░░░  │ 146 px · HaritaIskeleti
│  ░░░  harita yer tutucu  ░░░  │ (aspect-[1050/447], tam ölçü)
│  ░░░░░░░░░░░░░░░░░░░░░░░░░░░  │
│                               │
│  ◇ Yapay zekâdan örnek satır  │   chunk inince yer tutucunun
│  Yapay zekâ listendeki her     │   İÇİ dolar; hiçbir şey kaymaz
│  satırı böyle anlatır          │
└───────────────────────────────┘

375 px · /sonuc · İLK KEZ gelen ziyaretçi (çerez yok)
┌───────────────────────────────┐
│ [bant] [başlık]               │
│                               │
│  ◇ Yapay zekâdan örnek satır  │   ← harita DOM'da hiç yok,
│  Yapay zekâ listendeki her     │     tadımlık first:mt-0'ı korur:
│  satırı böyle anlatır          │     BUGÜNKÜ EKRANIN AYNISI
└───────────────────────────────┘
  • CLS: çerez isabetliyse 0. Çerez yoksa ama liste varsa (aşağıdaki dar kaçak) 0,13 (mobil).
  • Çerezin kaçacağı tek durum: dağıtım sonrası ilk sayfa açılışı (kullanıcı başına bir kez; ana sayfada yazıldığı için /sonuc'a client-side geçişte bile kapanır) ve localStorage yazma hatası. Safari ITP kaçağı yok sayılabilir: ITP script'le yazılan çerezi 7 günde siler ama aynı koşulda localStorage'ı da siler — ikisi birlikte ölür, ayrışmaz. Aynı risk zaten kolaytercih.profil çerezinde de var, yeni bir sınıf risk getirmiyor.

Alternatif B — çift yuva (çerez varsa üstte, yoksa altta)

ManuelHarita iki konumda da yazılır; sunucu çereze bakarak hangisinin aktif olacağını seçer.

çerez > 0  →  [HARİTA] → tadımlık → tablo → sihirbaz
çerez yok  →  tadımlık → tablo → [HARİTA] → sihirbaz     (bugünkü davranış)
  • CLS: her durumda ~0. Kaçak senaryoda bile sıfır, çünkü harita eski (güvenli) yerine düşer.
  • Bedeli: aynı bileşen iki DOM konumunda yaşar — AGENTS.md'nin "bir eleman iki yerde görünüyorsa tek kaynaktan" ilkesine biçimsel olarak uymasa da okuma yükü artar; ve kullanıcı bazı ziyaretlerde haritayı üstte, bazılarında altta görür. Tutarsızlık, kazanılan 0,13'lük tek seferlik CLS'ten daha pahalı.

Hüküm: A

B'nin kapattığı tek delik, kullanıcı başına bir kez yaşanan ve "iyileştirilmeli" bandındaki (kırmızı değil) bir kayma. Bunun için haritanın sabit bir yeri olmamasını kabul etmek doğru takas değil.

1.4 Tadımlık ne kaybediyor — hüküm: kabul edilebilir

Ziyaretçi Sıra değişiyor mu? Tadımlık nerede?
İlk kez gelen (liste boş) Hayır — harita hiç render edilmez Bugünkü yerinde, ~220 px
Girişli (tadımlık zaten yok, tadimlik-bolumu.tsx:19) Evet, harita tablonun üstüne çıkar —
Girişsiz + kayıtlı listesi olan Evet ~220 → ~366 px

Üçüncü satır için 375×812 hesabı (koddan çıkarım): tadımlığın SectionEyebrow'u, H2'si ("Yapay zekâ listendeki her satırı böyle anlatır") ve üç satırlık açıklaması katlamanın üstünde kalıyor; aşağı inen şey örnek satır kartının gövdesi ve CTA'sı. 375×667'de (iPhone SE) rozet + H2 görünür, paragraf yarılanır.

Hüküm: kabul edilebilir. Gerekçe kaybın büyüklüğü değil, kime denk geldiği: tadımlık "ödeme öncesi tek gerçek önizleme" argümanı ürünü ilk kez gören kişi içindir ve o kişide sıra hiç değişmiyor. Zaten liste kurmuş ziyaretçi için ekranın ilk işi, kendi kurduğu listeyi göstermektir; tadımlığı onun üstüne koymak "sana hâlâ ürünü tanıtıyorum" demek olurdu.

1.5 Uygulayıcıya tarif (yazılımcı)

Dosya 1 — src/features/liste/liste-store.ts

  1. PROFIL_CEREZ_ADI deseninin eşi olarak sabit ekle: LISTE_SAYI_CEREZ_ADI = "kolaytercih.liste-sayi" (sabitin yeri: bu dosya; sunucu tarafı buradan import eder — liste-store.ts "use client" olduğu için sabiti liste-dogrula.ts'e koymak daha temiz, orası zaten sunucu action'larıyla paylaşılıyor, bkz. :23-25).
  2. sayiCereziniYaz(n: number) — profilCerezineYaz (sihirbaz-profil.ts:51-57) ile birebir aynı öznitelikler: path=/; max-age=31536000; samesite=lax + https'te secure. Değer düz tamsayı.
  3. Üç çağrı yeri (listenin değiştiği her yer):
    • kaydet() içinde (:42-46) — ekle/çıkar/sırala/temizle hepsi buradan geçiyor;
    • yukle() içinde, liste = dogrula(...) satırından sonra (:53) — dağıtım sonrası ilk açılışta çerezi kendiliğinden doğurur;
    • "storage" dinleyicisinde liste atandıktan sonra (:64) — başka sekmedeki değişiklik.

Dosya 2 — src/features/liste/components/manuel-harita.tsx

  1. İmza: export function ManuelHarita({ yerAyir = false }: { yerAyir?: boolean }).
  2. :71 → if (liste.length === 0 && !yerAyir) return null; Boş+yerAyir dalında ayrı bir iskelet dalı yazma: fonksiyon akmaya devam etsin, pinler boş dizi olur, TercihHaritasiLazy monte olur ve chunk inene kadar zaten HaritaIskeleti'ni gösterir (tercih-haritasi-lazy.tsx:10-21). Böylece (a) yer tutucu ile gerçek harita aynı kutudan gelir, yükseklik ayrışamaz; (b) 197 KB'lık chunk hidrasyonu beklemeden inmeye başlar.
  3. :78 <div className="mt-16"> → <div>. Harita artık main'in ilk çocuğu; üst boşluğu main'in py-12'sinden alır (bu, mt-16'nın eklenmesinden önceki durumdu). :73-76'daki yorum tersini anlatıyor, aynı commit'te düzeltilmeli.

Dosya 3 — src/app/sonuc/page.tsx

  1. cookies() zaten okunuyor (:56): const listeSayisi = Number.parseInt(cerezler.get(LISTE_SAYI_CEREZ_ADI)?.value ?? "", 10); → const yerAyir = Number.isFinite(listeSayisi) && listeSayisi > 0;
  2. <ManuelHarita yerAyir={yerAyir} /> satırını :131'den :118'in üstüne taşı. Yeni sıra: harita → tadımlık → tablo → sihirbaz → dipnot.
  3. :100-114'teki yorum bloğu bugünkü kararın tersini belgeliyor; yerine yeni gerekçe (çerezle yer ayırma) yazılmalı — yoksa bir sonraki oturum haritayı yine aşağı alır.
  4. tadimlik-satiri.tsx:127-133'teki yorum ("harita artık tablonun altında, üstte hiçbir kardeş yok") da yalan olur. first:mt-0 kuralı doğru çalışmaya devam eder (harita varken tadımlık ikinci çocuk olur ve mt-16 alır, harita yokken ilk çocuktur ve mt-0 alır) — düzeltilecek olan yalnız yorumun metni.

Kabul kriterleri

  1. Listesi olmayan ziyaretçinin /sonuc HTML'inde harita ile ilgili hiçbir düğüm yok (grep -c "aspect-\[1050/447\]" = 0) ve tadımlık <section>'ı main'in ilk çocuğu.
  2. kolaytercih.liste-sayi=7 çereziyle istenen /sonuc HTML'inde, tadımlık <section>'ından önce aspect-[1050/447] kutusu var.
  3. Listeye ilk +'dan sonra sayfa yenilenince harita en üstte ve yukarı kayma yok.
  4. Listeyi tamamen boşaltıp sayfayı yenileyince harita yok (çerez 0 yazılmış olmalı).

Büyüklük: S (3 dosya, ~25 satır + 3 yorum bloğu).

1.6 Aynı işte kapanması gereken iki küçük delik

# Yer Sorun Düzeltme
H1 tercih-haritasi-lazy.tsx:14 animate-pulse yer tutucu artık katlamanın üstünde ve prefers-reduced-motion okunmuyor (WCAG 2.2.2'nin ruhu; sürekli, durdurulamaz hareket) motion-reduce:animate-none ekle (tek sınıf)
H2 manuel-harita.tsx:84-86 → yurtdisi-haritalar-lazy.tsx:8-11 dynamic(..., { ssr:false }) ama loading yok; chunk inince ~150 px'lik şerit yoktan belirir. Bugün katlamanın altındaydı, yarın üstünde olacak loading: () => <div className="mt-3 h-40" aria-hidden /> ya da eşdeğer sabit yükseklik

Artık kalan (kabul edilen) kayma: listesinde KKTC/yurt dışı program olan kullanıcıda yurt dışı şeridi + "N tercih haritada gösterilemiyor" satırı sunucuda bilinemez; hidrasyonda belirir. H2 uygulanırsa bu ~150 px'lik tek kaymaya iner (mobil CLS ~0,11). Bunu da sıfırlamak çereze ikinci bir alan yazmayı gerektirir — önermiyorum, kazanç bedeli haklı çıkarmıyor.

1.7 Reddedilen seçenekler

  • Her zaman sabit yükseklikli yer tutucu: Bilal'in "liste eklenmezse gözükmesin" şartını doğrudan çiğniyor.
  • Harita üstte ama küçük/sabit, büyümeyen biçim: sorun haritanın boyutu değil, null→görünür geçişi. 60 px'lik bir şerit bile aynı kaymayı üretir, üstelik harita okunmaz hale gelir.
  • Girişli kullanıcıda listeyi DB'den okumak: /sonuc bugün oturum açmıyor; oturum + sorgu eklemek sayfayı yavaşlatır ve girişsiz çoğunluğu (funnel'ın asıl kitlesi) hiç kapsamaz. Çerez ikisini birden çözüyor.

Talimat 2 — Üniversite sayfasında "tür"

2.1 Izgara gerçekte 4 kart değil, 4 hücre

universite-icerik.tsx:291
  grid-cols-2                                  ← mobil
  lg:grid-cols-[1fr_1fr_1.35fr] lg:grid-rows-2 ← masaüstü
universite-konum-haritasi.tsx:77
  col-span-2  lg:col-start-3 lg:row-start-1 lg:row-span-2

Masaüstünde harita 3. sütunu iki satır boyunca kaplıyor; kartlara kalan yer 2 sütun × 2 satır = tam 4 hücre. 5. kart şablonu bozar: ya 3. bir satır açılır (harita yanında boşluk kalır) ya da grid-rows-2 elle 3'e çıkarılır ve haritanın oranı bozulur. Mobilde 5. kart 2 sütunlu ızgarada tek başına bir satıra düşer (yanında boşluk) ve ilk ekrandan ~90 px daha gider.

→ (a) "ızgara 5 karta çıksın mı?" cevabı: hayır. Gerekçe estetik değil, şablonun kendisi.

2.2 Asıl mesele: tür bir metrik değil

Izgaradaki diğer üç kart sayısal ve karşılaştırılabilir (Program, Fakülte/Birim, En iyi sıralama, URAP). "Devlet" bir ölçüm değil, kurumun kimliği. Sitenin geri kalanı bunu zaten böyle işliyor: başlığın altındaki meta satırında küçük bir çip olarak, dört ayrı yerde birebir aynı sınıf setiyle:

shrink-0 rounded px-1 py-px text-[10px] font-medium leading-4
  DEVLET → bg-slate-100 text-slate-600     (kontrast 6,92:1 ✅)
  diğer  → bg-violet-50  text-violet-600   (kontrast 5,19:1 ✅ — hesap: WCAG 2.x, #7C3AED/#F5F3FF)

program-tablosu.tsx:328-336 · rapor-listesi.tsx:225-234 · tadimlik-satiri.tsx:160-166 · bolum-program-listesi.tsx:220-229

Üniversite detay sayfası, bu çipi taşımayan tek yüzey. Eksik olan şey kart değil, çip.

2.3 İki alternatif

Alternatif A — çip, H1'in altındaki meta satırında (ÖNERİLEN)

390 px · /universite/koc-universitesi · ilk ekran

  Ana Sayfa › Üniversiteler › Koç Üniversitesi

  ┌────┐  Koç Üniversitesi
  │logo│  Taban Puanları
  │ 64 │  2026
  └────┘
  [Vakıf] İstanbul                     ← EKLENEN TEK SATIR (mt-3, ~22 px)
                                          çip sınıfı: program-tablosu.tsx:329 ile birebir

  Koç Üniversitesi (İstanbul), vakıf üniversitesi;    ← gece/0922-urap'taki
  2026 YKS yerleştirme sonuçlarına göre …               telafi cümlesi KALIR

  [ Sıralaman Koç tabanlarının neresinde?  →  ]

  ┌─ harita (col-span-2, min-h-44) ──────────┐
  │                                          │
  └──────────────────────────────────────────┘
  ┌───────────────┐┌───────────────┐
  │ PROGRAM       ││ FAKÜLTE/BİRİM │
  │ 78            ││ 12            │
  └───────────────┘└───────────────┘
  ┌───────────────┐┌───────────────┐
  │ URAP TÜRKİYE  ││ EN İYİ SIRALAMA│        ← 4 hücre, hepsi sayısal
  │ 34 / 198      ││ 412            │
  │ 2025-2026     ││                │
  └───────────────┘└───────────────┘
  • Yeni bileşen yok, yeni sınıf yok: çip dört yerde duran sınıf setinin beşinci kopyası (ya da — tercihen — hepsinin çıkarılacağı tek kaynak, bkz. §2.5).
  • Türün kaç kez geçtiği: çip 1 + cümle 1 = 2, biri taranabilir, biri okunabilir. Kart yok.
  • Mobil: H1 bloğu (logo size-16 + text-3xl) 390 px'te zaten ~180 px; çip satırı 22 px ekler, taşma riski yok (flex items-center gap-1.5, çip shrink-0, il truncate).
  • Erişilebilirlik: çip metni okunur ("Vakıf"), renk tek başına anlam taşımıyor — AGENTS.md'nin risk dili kuralının aynı mantığı.
  • Gereken tek yan değişiklik: URAP'ı olmayan 31 sayfada 4. hücre bugün "Tür" kartı olarak dolduruluyor (gece/0922-urap, :394-417). Çip geldiğinde o sayfalarda tür üç kez yazar. 4. hücre oraya "Toplam kontenjan" olur (uni.stats.toplamKontenjan, lib/katalog.ts:380-401). Veri kontrolü: data/yokatlas.db — toplam kontenjanı 0 olan hiçbir üniversite yok (SELECT … GROUP BY universite HAVING SUM(COALESCE(kontenjan2026,0))=0 → 0 satır), yani bu hücrede asla "—" çıkmaz. Precedent var: minSira de hem paragrafta hem kartta geçiyor.

Alternatif B — "Tür" kartı geri gelir, URAP satır olur

  Koç Üniversitesi (İstanbul), vakıf üniversitesi; 2026 YKS …
  URAP Türkiye sıralaması: 34 / 198 (2025-2026)     ← paragrafın altına yeni satır

  ┌ PROGRAM 78 ┐┌ FAKÜLTE 12 ┐
  ┌ TÜR Vakıf  ┐┌ EN İYİ 412 ┐
  • Artısı: diff küçük, gece/0922-urap'ın kart kısmı geri alınır.
  • Eksileri: (a) sayı prozaya gömülür — URAP taranmak için var, "34/198" cümle içinde aranır hale gelir; tasarımın dünkü gerekçesinin tersi. (b) Izgarada kategori/metrik karışımı sürer. (c) Tür yine text-2xl font-bold ile "Vakıf MYO" gibi uzun değerlerde 190 px'lik karta sığmaz. (d) Çip eksikliği kapanmaz: detay sayfası hâlâ sitenin geri kalanından farklı konuşur.

Hüküm: A

Bilal'in "tür olsun" isteği A'da daha güçlü karşılanıyor: tür artık ızgaranın dördüncü kutusunda, ekranın ortasında değil, üniversitenin adının hemen altında — hem ilk bakışta hem her sayfa genişliğinde. Ve site genelindeki çiple aynı dili konuşuyor.

2.4 Uygulayıcıya tarif (yazılımcı)

Taban: gece/0922-urap (orada UNITUR_ETIKET ve telafi cümlesi hazır). Dal bayatsa önce origin/main üstüne yeniden kurulmalı.

  1. UNITUR_ETIKETi (universite-icerik.tsx:54-66) src/lib/unitur.ts'e taşı ve üçüncü alan ekle: { kart, cumle, cip }. cip = çipte görünen kısa metin (Devlet, Vakıf, Vakıf MYO, KKTC, Yurt dışı (kamu), Yurt dışı (vakıf)) — kart ile aynı değerler, ama kart alanı §2.4-3 ile ölüyorsa ikisi birleştirilebilir. Gerekçe: aynı bilginin ekrandaki etiketi tek kaynaktan gelmeli — DILIM_ETIKET'in src/lib/risk.ts'te durması gibi (AGENTS.md).
  2. universite-icerik.tsx, H1 bloğunun (:253-259) hemen altına, ilkSayfa koşulundan bağımsız (sayfalama sayfalarında da üniversite kimliği aynı):
    <p className="mt-3 flex items-center gap-1.5 text-xs text-slate-500"> …çip… {il} </p>
    
    Çipin sınıfı program-tablosu.tsx:329-333'ten kopyalanır, yeni varyant üretilmez. Renk kuralı da aynı: DEVLET → slate, diğer her şey → violet. uni.unitur NULL ise satırın tamamı render edilmez (kopuk boşluk kalmaz).
  3. Izgaradaki 4. hücre (gece/0922-urap, :394-417): uni.urap ? URAP : Tür koşulu → uni.urap ? URAP : Toplam kontenjan. dt: "Toplam kontenjan", dd: sayi(uni.stats.toplamKontenjan).
  4. bolum-program-listesi.tsx:227 trBaslikDuzeni(p.unitur) → UNITUR_ETIKET[p.unitur].cip. Bugün o çip "Kktc" / "Vakıf Myo" / "Yurtdısı Kamu" basıyor (slug.ts:56-64 tr-TR küçültmesi). Aynı commit'e girmeli: tek kaynak taşınırken düzelmeyen tek tüketici kalmasın.

Kabul kriterleri

  1. bogazici-universitesi.html → çipte "Devlet" 1 kez, özet cümlesinde "devlet üniversitesi" 1 kez, ızgarada "Tür" 0 kez.
  2. dogu-akdeniz-universitesi.html (URAP yok) → çipte "KKTC", 4. hücrede "Toplam kontenjan" + sayı, hiçbir hücrede "—" yok.
  3. /bolum/... sayfalarında KKTC programının çipinde "KKTC" yazıyor, "Kktc" değil.
  4. 390 px'te H1 bloğu + çip satırı yatay taşma üretmiyor (uzun üniversite adı: "İstanbul Medeniyet Üniversitesi").
  5. pnpm build temiz; 229 üniversite sayfasının 229'unda çip var.

Büyüklük: S (2 yeni/taşınan dosya + 3 dokunuş, ~50 satır).

2.5 Aynı işte kapanacak tutarlılık borcu

Yer Sorun Kanonik kaynak
program-tablosu.tsx:329 · rapor-listesi.tsx:227 · tadimlik-satiri.tsx:161 · bolum-program-listesi.tsx:222 Aynı çip sınıf seti 4 kez elle kopyalanmış; 5.'si ekleniyor AGENTS.md "ortak elemanlar tek kaynaktan". Öneri: src/components/unitur-cipi.tsx — küçük, tek amaçlı sunum bileşeni. Bu, "yeni bileşen tasarlama" yasağının kapsamına girmez: yeni bir tasarım değil, var olan beş kopyanın tek kaynağa alınmasıdır. Ayrı ve tek amaçlı commit.
app/api/katalog-ara/route.ts:49-56 unitur için beşinci sözlük: "KKTC / Yurt dışı" (arama sonucunda böyle, sayfada "KKTC") Aynı UNITUR_ETIKET. Düşük öncelik; ayrı iş.
program-tablosu.tsx:175 Root <section className="mt-16"> — first:mt-0 yok. Girişli + listesiz kullanıcıda (tadımlık yok, harita yok) tablo main'in ilk çocuğu olur, tepede 64 px ölü alan kalır tadimlik-satiri.tsx:134 deseni (mt-16 first:mt-0). XS, Talimat 1 ile aynı commit'e sığar

Bilal'in gözle kontrol etmesi gerekenler (375–390 px)

  1. /sonuc, listeye 1-2 program ekledikten sonra sayfayı yenile. Harita en üstte mi, açılışta yukarı/aşağı zıplama var mı? (Talimat 1'in tek gerçek testi.)
  2. /sonuc, tarayıcı verisini sildikten sonra ilk kez. Harita hiç yok mu, tadımlık en üstte mi ve üstünde fazladan boşluk var mı? (first:mt-0 kontrolü.)
  3. /sonuc, girişsiz + listeli. Tadımlığın başlığı ("Yapay zekâ listendeki her satırı böyle anlatır") hâlâ katlamanın üstünde mi? Hükmüm buna dayanıyor (§1.4).
  4. Listesinde KKTC/yurt dışı programı olan bir listeyle /sonuc. Türkiye haritasının altındaki yurt dışı şeridi geç belirip içeriği itiyor mu? (§1.6-H2)
  5. /universite/koc-universitesi ve /universite/dogu-akdeniz-universitesi. Üniversite adının altındaki tür çipi ilk bakışta görülüyor mu, yoksa çok mu küçük kalıyor? (A alternatifinin tek öznel riski budur; "daha büyük olsun" dersen o yeni bir çip varyantı demektir ve site genelindeki dört kopyayı da etkiler → [BİLAL] kararı.)

Bilal'den istenen (3 madde)

  1. Talimat 1 için A'yı onayla (liste sayısı çerezi + harita en üstte). Yeni bir işlevsel çerez yazılacak; kişisel veri taşımıyor, kolaytercih.profil ile aynı sınıf. ~2 dk.
  2. Talimat 2 için A'yı onayla: tür = ad altındaki çip, URAP'ı olmayan 31 sayfada 4. kart "Toplam kontenjan" olur. ~2 dk.
  3. §2.5'teki UniturCipi tek-kaynak commit'i ayrı iş olarak backlog'a girsin mi (5 kopya → 1 bileşen)? ~1 dk.