UX/CRO denetimi uygulandı: değer-önce funnel, güven sayfaları, dev paneli

Kritik (K1-K6) sonrası kalan tüm maddeler:
- Değer önce: girişsiz kullanıcı sihirbaz bitince /giris yerine /sonuc'taki
  ücretsiz tabloya gider (?hazir=1); AI CTA'sı "5 deneme kredinle listeni
  kur — giriş yap" paneli + sabit alt karttan verilir, girişte otomatik üretim
- Ö1-Ö10: paywall kopyası, aranabilir il seçimi, "Seçtiklerim" adlandırması,
  gizlilik/koşullar/iletişim sayfaları, danışman özeti + uyarılar, revizyon
  kutusu, dilim özeti + tek şehir uyarısı, eksik veri rozetleri, magic link
  yeniden gönder, mobil sohbet kısayolu
- G1-G5: binlik ayraçlı input + inline hata, adım göstergesi, route-level
  loading/error/not-found, dürüst konumlandırma kartı, dürüst buton etiketleri
- Seçtiklerim butonu liste boşken gizli; ilk eklemede belirir
- Dev süperadmin paneli (yalnızca development): hızlı giriş, kredi/paket/rapor
  senaryoları, sahte ödeme dönüşü

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-07-26 15:10:57 +03:00
parent d93cf742ff
commit 7288c926d0
40 changed files with 1666 additions and 162 deletions

View File

@@ -40,8 +40,12 @@ type BekleyenSecim = {
* - Sayfa ortasındaki büyük CTA + sabit alt çağrı kartı (rapor yokken)
* - Adımları toplayan modal
* - Üretim/önizleme/liste paneli (sayfa gövdesinde)
* Akış: adımlar → (girişsizse /giris) → kredi ile üretim → paketsizse
* progressive-blur önizleme, paketliyse tam liste.
* Akış: adımlar → kredi ile üretim → paketsizse progressive-blur önizleme,
* paketliyse tam liste. Girişsiz kullanıcı hero'dan seçimleri tamamlanmış
* gelirse önce ücretsiz tabloyu görür; giriş CTA'sı "hazır seçimlerin
* kaydedilmesi" olarak panelde sunulur, girişten dönüşte üretim otomatik
* başlar. Modal içinden ilerleyen girişsiz kullanıcı ise butonun söylediği
* gibi doğrudan girişe gider.
*/
export function SihirbazBolumu({
sira,
@@ -53,6 +57,7 @@ export function SihirbazBolumu({
mevcutRapor,
otomatikAc,
acilis,
secimlerHazir,
}: {
sira: number;
tur: string;
@@ -65,6 +70,10 @@ export function SihirbazBolumu({
otomatikAc?: boolean;
/** ?acildi=1 (ödeme dönüşü): blur çözülme animasyonuyla aç */
acilis?: boolean;
/** ?hazir=1 (hero sihirbazından girişsiz geliş): seçimler storage'da,
panel giriş CTA'sına döner. URL'den gelir ki SSR'da doğru panel
render edilsin — mount sonrası anahtar değişimi animasyonu donduruyor. */
secimlerHazir?: boolean;
}) {
const router = useRouter();
const monteEdildi = useMonteEdildi();
@@ -280,8 +289,25 @@ export function SihirbazBolumu({
}
const panelde = Boolean(rapor) || durum !== "bos";
// Değer önce: sihirbazı bitirmiş ama girişsiz kullanıcı ücretsiz tabloyu
// zaten görüyor; giriş burada bariyer değil, hazır seçimlerin (ödülün)
// kaydedilmesi olarak sunulur. Girişten dönüşte otomatik üretim başlar.
// Sinyal URL'den (?hazir=1) gelir; storage'a bakılsaydı panel anahtarı
// mount sonrası değişir ve AnimatePresence geçişi donardı.
const girisBekliyor = Boolean(!girisliMi && secimlerHazir && !rapor);
const girisUrl = `/giris?callback=${encodeURIComponent(
`/sonuc?sira=${sira}&tur=${tur}&sihirbaz=1`,
)}`;
const panelAnahtari =
durum !== "bos" ? durum : rapor ? "rapor-hazir" : "sihirbaz-cta";
durum !== "bos"
? durum
: rapor
? "rapor-hazir"
: girisBekliyor
? "giris-cta"
: "sihirbaz-cta";
return (
<>
@@ -370,6 +396,31 @@ export function SihirbazBolumu({
<Link href="/listem">Listeni gör</Link>
</Button>
</section>
) : girisBekliyor ? (
<section className="mt-16 rounded-2xl bg-primary p-8 text-center text-white sm:p-12">
<h2 className="font-heading text-2xl font-bold sm:text-3xl">
Seçimlerin hazır AI listen bir adım uzakta
</h2>
<p className="mx-auto mt-3 max-w-xl text-white/90">
Yukarıdaki tablo her zaman ücretsiz. 5 deneme kredinle 24
tercihlik AI listeni de kurabilirsin: ücretsiz giriş yap,
seçimlerin kayıtlı listen otomatik kurulsun (üretim 3
kredi, kalan 2 kredinle danışmana soru sorarsın).
</p>
<Button
asChild
size="lg"
className="mt-6 h-12 cursor-pointer bg-orange-500 px-8 text-white transition-colors duration-200 hover:bg-orange-600"
>
<Link href={girisUrl}>
<Sparkles className="size-4" aria-hidden />5 deneme kredinle
AI listeni kur giriş yap
</Link>
</Button>
<p className="mt-3 text-xs text-white/70">
Kredi kartı gerekmez · Google ya da e-posta ile 30 saniyede
</p>
</section>
) : (
<section className="mt-16 rounded-2xl bg-primary p-8 text-center text-white sm:p-12">
<h2 className="font-heading text-2xl font-bold sm:text-3xl">
@@ -400,19 +451,33 @@ export function SihirbazBolumu({
<div className="pointer-events-auto mx-auto flex max-w-xl items-center gap-4 rounded-2xl border border-slate-200 bg-white p-4 shadow-xl">
<div className="flex-1">
<p className="font-heading text-sm font-bold text-slate-900">
3 adımda 24 tercihlik listen
{girisBekliyor
? "Seçimlerin kayıtlı — AI listen hazır bekliyor"
: "3 adımda 24 tercihlik listen"}
</p>
<p className="text-xs text-slate-500">
Sıralamana uygun bölümleri seç, yapay zekâ listeni kursun.
{girisBekliyor
? "Ücretsiz giriş yap, 5 deneme kredinle listen otomatik kurulsun."
: "Sıralamana uygun bölümleri seç, yapay zekâ listeni kursun."}
</p>
</div>
<Button
size="sm"
onClick={() => acikDegisti(true)}
className="cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600"
>
Başla
</Button>
{girisBekliyor ? (
<Button
asChild
size="sm"
className="cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600"
>
<Link href={girisUrl}>Giriş yap</Link>
</Button>
) : (
<Button
size="sm"
onClick={() => acikDegisti(true)}
className="cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600"
>
Başla
</Button>
)}
<button
type="button"
aria-label="Kapat"
@@ -441,7 +506,7 @@ export function SihirbazBolumu({
sonSecimler ?? (bekleyen?.eslesir ? bekleyen.secimler : null)
}
sonButonEtiketi={
girisliMi ? "Listemi oluştur (3 kredi)" : "Listemi gör"
girisliMi ? "Listemi oluştur (3 kredi)" : "Giriş yap ve listeni gör"
}
onTamamla={ilerle}
/>