diff --git a/src/app/sonuc/page.tsx b/src/app/sonuc/page.tsx index e41766d..b30fe24 100644 --- a/src/app/sonuc/page.tsx +++ b/src/app/sonuc/page.tsx @@ -97,15 +97,30 @@ export default function SonucPage({ return (
- {/* Sayfa hiyerarşisi: önce Türkiye haritası, sonra liste. Manuel - liste store'una abone olduğundan tablodan "+" ile eklenenler - buraya canlı yansır. */} - + {/* Sayfa hiyerarşisi: tadımlık → ham tablo → manuel listenin + haritası. Tadımlık, ödeme öncesi gösterebildiğimiz TEK gerçek + önizleme olduğu için ilk ekranda durur. - {/* Yapay Zeka'dan bağımsız ham tablo — haritanın hemen altında, - sayfanın ana gövdesi; puan türü navbar'daki sıralama - rozetinden değiştirilir. Sihirbaz seçimleri (il, devlet/ - vakıf) profil çerezinden tabloya uygulanır. */} + Harita neden TABLONUN ALTINDA: liste store'unun sunucu + snapshot'ı her zaman boş liste döner (liste-store.ts), kayıtlı + liste ancak hidrasyondan sonra okunur. Harita yukarıda olsaydı + dönüş ziyaretçisinde sayfa açıldıktan saniyeler sonra ~368 px + yüksekliğinde belirip tadımlığı ve tabloyu aşağı itecekti + (impact fraction ~1, CLS eşiğinin çok üstü). Aşağıda belirince + yalnızca sihirbaz ile dipnotu iter, ikisi de katlanın altında. + Bilgi mimarisi olarak da doğru sıra: harita, tablodan kurulan + listenin görselleştirmesidir. Liste boşken hiç render edilmez + (bkz. manuel-harita.tsx); store'a abone olduğu için tablodan + "+" ile eklenenler buraya canlı yansır. */} + + {/* Girişsiz tadımlık: gerçek rapor satırı formatında tek örnek. + Havuzda içerik yoksa bileşen hiç render edilmez. */} + + + {/* Yapay Zeka'dan bağımsız ham tablo — sayfanın ana gövdesi; + puan türü navbar'daki sıralama rozetinden değiştirilir. + Sihirbaz seçimleri (il, devlet/vakıf) profil çerezinden + tabloya uygulanır. */} - {/* Girişsiz tadımlık: gerçek rapor satırı formatında tek örnek. - Havuzda içerik yoksa bileşen hiç render edilmez. */} - + {/* Sihirbaz akışı (CTA + modal) — üretim ve liste /listem'de yaşar, burada yalnızca funnel kartları render edilir */} diff --git a/src/features/liste/components/manuel-harita.tsx b/src/features/liste/components/manuel-harita.tsx index 4ab7fb8..392d1d5 100644 --- a/src/features/liste/components/manuel-harita.tsx +++ b/src/features/liste/components/manuel-harita.tsx @@ -64,23 +64,18 @@ export function ManuelHarita() { }; }, [liste]); - // Liste boşken 197 KB'lık il geometrisi hiç inmesin: aynı oranlı - // placeholder alanı rezerve eder, ilk eklemede lazy harita yerine oturur. - if (liste.length === 0) { - return ( -
-
-

- Tablodan + ile ekledikçe üniversiteler - haritada belirir. -

-
-
- ); - } + // Liste boşken hiç yer tutulmaz: boş harita /sonuc'un ilk ekranını işgal + // ediyordu, oysa ödeme öncesi ilk ekranda durması gereken şey tadımlık. + // İlk "+" ile liste dolunca harita kendiliğinden belirir; 197 KB'lık il + // geometrisi yine ancak o anda iner (TercihHaritasiLazy zaten `dynamic`). + if (liste.length === 0) return null; + // mt-16: /sonuc'ta harita artık tablonun ALTINDA duruyor (bkz. sonuc/page.tsx) + // ve sayfanın bölüm ritmini paylaşıyor — tablo
'ı ve sihirbaz + // kartları da mt-16 kullanır. Eskiden main'in ilk çocuğu olduğu için üst + // boşluğu main'in py-12'sinden alıyordu, kendi margin'i yoktu. return ( -
+
window.removeEventListener(PROFIL_DEGISTI_EVENT, guncelle); }, [sira, tur, ilk]); + // SERİ KIRILMASI (22 Eyl 2026): bu olay bu değişiklikten önce /sonuc'un + // ~2.200 px altında, tablonun arkasında yaşıyordu; artık tadımlık ilk + // ekranda. Adet bir gecede 0'dan yukarı fırlayacak — kırık ölçüm değil, + // kazanılan payda. Öncesi ve sonrası KARŞILAŞTIRILAMAZ; anlamlı ölçüt + // bundan sonra "tadımlık CTA tıklaması / tadımlık görüntülenmesi" oranıdır. + // (Not analitik.ts'e değil buraya yazıldı: o dosya aynı gece başka bir + // dalın altında — CTO şartnamesi, çakışma kararı #1.) const gorunumRef = useGorunumOlayi("tadimlik_goruntulendi", { kova: siraKovasi(sira), }); @@ -108,18 +115,32 @@ export function TadimlikSatiri({ const seri = raporSiraSerisi(p.siraGecmisi, p.ilkYil); const taban = p.efektifSira ?? programEtkinSira(seri); const devlet = p.unitur === "DEVLET"; - const girisUrl = `/giris?callback=${encodeURIComponent(sonucHref())}`; + // Giriş dönüşü kullanıcıyı /sonuc'a geri bırakmaz: callback doğrudan + // üretimin koştuğu /listem'e iner, liste ek tık olmadan orada başlar. + const girisUrl = `/giris?callback=${encodeURIComponent(listemUretHref("tadimlik"))}`; return ( -
+ // first:mt-0 — /sonuc'ta bu
main'in ilk DOM çocuğudur (harita + // artık tablonun altında, üstte hiçbir kardeş yok; JSX yorumları düğüm + // üretmez): main'in py-12'si tek başına yeterli üst boşluğu verir. + // Tadımlığın render edilmediği durumlarda (girişli kullanıcı, boş havuz) + // bu bileşen hiç dönmediği için kural ilk gerçek bölüme geçer. +
Yapay zekâdan örnek satır

Yapay zekâ listendeki her satırı böyle anlatır

+ {/* "ilk üçü" = rapor-maske.ts içindeki ACIK_SATIR (3). O dosya + `server-only`, bu dosya "use client" — sabit buraya import + edilemiyor, sayı elle yazıldı. ACIK_SATIR değişirse bu cümle de + aynı commit'te değişmeli. Cümle kasten "her satır bu formatta + kurulur"u sınırlıyor: maske girişsiz/paketsiz kullanıcıya 3 satır + açıyor, kalan 21'in gerekçe/risk/trend metni maskeli geliyor. */}

Sıralamana uygun bir programın gerekçesi, yerleşme riski ve taban - trendi — 24 tercihlik listenin her satırı bu formatta kurulur. + trendi — 24 tercihlik listenin her satırı bu formatta kurulur, ilk + üçü hemen açılır.

@@ -172,7 +193,8 @@ export function TadimlikSatiri({

Bu, 24 satırlık Yapay Zeka listenden yalnızca bir örnek. - Kredi kartı gerekmez · Google ya da e-posta ile 30 saniyede + Kredi kartı gerekmez · Google ya da e-posta ile 30 saniyede · + Giriş sonrası liste hemen üretilir

diff --git a/src/features/rapor/components/uretim-basladi-olayi.tsx b/src/features/rapor/components/uretim-basladi-olayi.tsx index 9215dfb..f0ff05c 100644 --- a/src/features/rapor/components/uretim-basladi-olayi.tsx +++ b/src/features/rapor/components/uretim-basladi-olayi.tsx @@ -29,6 +29,8 @@ const IZINLI_KAYNAKLAR = new Set([ "giris_donusu", "bos_durum", "odeme_sonrasi", + // /sonuc'taki girişsiz tadımlık CTA'sı (tadimlik-satiri.tsx). + "tadimlik", // /sonuc'ta ?sihirbaz=1 ile otomatik başlayan üretimin gerçek yüzeyleri. // Eskiden hepsi "giris_donusu" sayılıyordu (güvenlik denetimi G3). "hero", diff --git a/src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx b/src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx index 43837b8..5777d3c 100644 --- a/src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx +++ b/src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx @@ -11,20 +11,14 @@ import { PixelField } from "@/components/pixel-decor"; import { useGorunumOlayi } from "@/components/use-gorunum-olayi"; import { olay, olayBirKez, siraKovasi } from "@/lib/analitik"; import type { SihirbazFacetleri } from "@/types/yokatlas"; -import { SIHIRBAZ_AC_EVENT, SIHIRBAZ_STORAGE_KEY, sihirbazDogrula, type SihirbazSecimleri } from "@/features/sihirbaz/sihirbaz-sabitler"; +import { listemUretHref, SIHIRBAZ_AC_EVENT, SIHIRBAZ_STORAGE_KEY, sihirbazDogrula, type SihirbazSecimleri } from "@/features/sihirbaz/sihirbaz-sabitler"; import { tercihProfiliYaz } from "@/features/sihirbaz/sihirbaz-profil"; import { SihirbazModal } from "./sihirbaz-modal"; // Üretim /listem'de koşar (bkz. listem/liste-uretici.tsx); sihirbaz // tamamlanınca seçimler storage'a yazılıp kullanıcı buraya yönlendirilir. -// `kaynak` denemenin hangi yüzeyden başladığını ölçer (bkz. -// rapor/components/uretim-basladi-olayi.tsx — izinli değerler orada). -// `uret=1` HER ZAMAN ilk parametre kalmalı: giris-karti.tsx:31 funnel -// metnini `callbackURL.startsWith("/listem?uret=1")` ile seçiyor, sıra -// bozulursa girişteki "Seçimlerin hazır" metni kaybolur. -function listemUretHref(kaynak: string) { - return `/listem?uret=1&kaynak=${kaynak}`; -} +// Hedef URL'i `listemUretHref` kurar (sihirbaz-sabitler.ts) — `uret=1` +// parametre sırası sözleşmesi ve izinli `kaynak` değerleri orada yazılı. // SSR'da false, client'ta true — storage'a ancak mount sonrası dokunuruz const bosAbone = () => () => {}; diff --git a/src/features/sihirbaz/sihirbaz-sabitler.ts b/src/features/sihirbaz/sihirbaz-sabitler.ts index 2b9ac6a..896a850 100644 --- a/src/features/sihirbaz/sihirbaz-sabitler.ts +++ b/src/features/sihirbaz/sihirbaz-sabitler.ts @@ -168,6 +168,20 @@ export function sonucHref(ekstra?: Record): string { return `/sonuc?${new URLSearchParams(girdiler)}`; } +/** + * Üretimin koştuğu /listem URL'i. `kaynak` denemenin hangi yüzeyden + * başladığını ölçer (izinli değerler: + * rapor/components/uretim-basladi-olayi.tsx — yeni yüzeyi önce oraya ekle). + * + * `uret=1` HER ZAMAN ilk parametre kalmalı: giris-karti.tsx funnel metnini + * `callbackURL.startsWith("/listem?uret=1")` ile seçiyor, sıra bozulursa + * girişteki "Seçimlerin hazır" metni sessizce kaybolur. Bu sözleşmenin + * literal kopyası çoğalmasın diye tek kaynak burası. + */ +export function listemUretHref(kaynak: string): string { + return `/listem?uret=1&kaynak=${kaynak}`; +} + /** Prompt'a enjekte edilecek Türkçe özet. */ export function secimOzeti(secimler: SihirbazSecimleri): string { const satirlar = [