fix(sonuc,liste): tadımlık listesi olanda tablonun altına iner, çekmecede risk etiketi metinle
- /sonuc: kayıtlı listesi olan ziyaretçide harita ile ekleme tablosu arasına tadımlık CTA'sı girmez, tablonun altına iner (karar sunucudaki liste sayısı çerezinden, hidrasyonda zıplamaz) - Liste çekmecesi: risk noktası tek başına değil RISK_ETIKET metniyle - Sıralama formu: kompakt başlık düzeni
This commit is contained in:
@@ -106,14 +106,19 @@ export default function SonucPage({
|
||||
);
|
||||
}
|
||||
|
||||
const tadimlik = <TadimlikBolumu sira={sira} tur={turKey} />;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-slate-50 text-slate-900">
|
||||
<main className="mx-auto max-w-4xl px-4 py-12">
|
||||
{/* Sayfa hiyerarşisi: manuel listenin haritası → tadımlık → ham
|
||||
tablo. İki farklı ziyaretçi, iki farklı ilk ekran:
|
||||
{/* Sayfa hiyerarşisi: manuel listenin haritası → ham tablo →
|
||||
tadımlık (listesi yoksa tadımlık → tablo). İki farklı
|
||||
ziyaretçi, iki farklı ilk ekran:
|
||||
|
||||
• Listesi OLAN ziyaretçi ekranda önce kendi kurduğu listeyi
|
||||
görür — o kişi "bu ürün ne?" aşamasını geçmiştir.
|
||||
görür — o kişi "bu ürün ne?" aşamasını geçmiştir. Haritanın
|
||||
hemen altında ekleme alanı (tablo) durur; tadımlık CTA'sı
|
||||
ikisinin arasına girmez, tablonun altına iner.
|
||||
• Listesi OLMAYAN ziyaretçide harita DOM'a hiç girmez
|
||||
(manuel-harita.tsx), sıra bugünküyle birebir aynı kalır:
|
||||
tadımlık → tablo. Tadımlık, ödeme öncesi gösterebildiğimiz
|
||||
@@ -131,8 +136,12 @@ export default function SonucPage({
|
||||
<ManuelHarita yerAyir={haritayaYerAyir} />
|
||||
|
||||
{/* Girişsiz tadımlık: gerçek rapor satırı formatında tek örnek.
|
||||
Havuzda içerik yoksa bileşen hiç render edilmez. */}
|
||||
<TadimlikBolumu sira={sira} tur={turKey} />
|
||||
Havuzda içerik yoksa bileşen hiç render edilmez. Listesi
|
||||
OLAN ziyaretçide harita ile tablo (+ ile ekleme alanı)
|
||||
arasına CTA girmesin diye tadımlık tablonun altına iner;
|
||||
karar sunucudaki liste sayısı çerezinden verilir, böylece
|
||||
hidrasyonda yer değiştirip zıplamaz. */}
|
||||
{haritayaYerAyir ? null : tadimlik}
|
||||
|
||||
{/* Yapay Zeka'dan bağımsız ham tablo — sayfanın ana gövdesi;
|
||||
puan türü navbar'daki sıralama rozetinden değiştirilir.
|
||||
@@ -145,6 +154,8 @@ export default function SonucPage({
|
||||
uniturGrubu={uniturGrubu}
|
||||
/>
|
||||
|
||||
{haritayaYerAyir ? tadimlik : null}
|
||||
|
||||
{/* Sihirbaz akışı (CTA + modal) — üretim ve liste /listem'de
|
||||
yaşar, burada yalnızca funnel kartları render edilir */}
|
||||
<SonucSihirbazi
|
||||
|
||||
@@ -422,10 +422,13 @@ function CekmeceSatiri({
|
||||
</span>
|
||||
) : null}
|
||||
{tercih.risk ? (
|
||||
<span className="inline-flex shrink-0 items-center gap-1.5 text-xs font-medium">
|
||||
<span
|
||||
className={`size-2.5 shrink-0 rounded-full ${RISK_NOKTA[tercih.risk]}`}
|
||||
aria-label={RISK_ETIKET[tercih.risk]}
|
||||
aria-hidden
|
||||
/>
|
||||
{RISK_ETIKET[tercih.risk]}
|
||||
</span>
|
||||
) : null}
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -120,11 +120,11 @@ export function TadimlikSatiri({
|
||||
const girisUrl = `/giris?callback=${encodeURIComponent(listemUretHref("tadimlik"))}`;
|
||||
|
||||
return (
|
||||
// first:mt-0 — /sonuc'ta harita bu <section>'ın ÜSTÜNDE durur ama yalnızca
|
||||
// kayıtlı listesi olan ziyaretçide DOM'a girer (manuel-harita.tsx). Liste
|
||||
// yoksa tadımlık main'in ilk DOM çocuğudur (JSX yorumları düğüm üretmez) ve
|
||||
// main'in py-12'si tek başına yeterli üst boşluğu verir; harita varsa
|
||||
// tadımlık ikinci çocuk olur ve bölüm ritmini veren mt-16'yı alır.
|
||||
// first:mt-0 — kayıtlı listesi olan ziyaretçide /sonuc tadımlığı haritanın
|
||||
// ve tablonun ALTINA koyar (sonuc/page.tsx), orada bölüm ritmini veren
|
||||
// mt-16'yı alır. Liste yoksa tadımlık main'in ilk DOM çocuğudur (JSX
|
||||
// yorumları düğüm üretmez) ve 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.
|
||||
<section ref={gorunumRef} className="mt-16 min-w-0 first:mt-0">
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
DrawerDescription,
|
||||
DrawerTitle,
|
||||
} from "@/components/ui/drawer";
|
||||
import { SectionEyebrow } from "@/components/pixel-decor";
|
||||
import { PagePixelDivider, SectionEyebrow } from "@/components/pixel-decor";
|
||||
import { useGorunumOlayi } from "@/components/use-gorunum-olayi";
|
||||
import {
|
||||
SihirbazAdimlarLazy,
|
||||
@@ -51,6 +51,31 @@ const KANITLAR = [
|
||||
{ ikon: Database, etiket: "YÖK Atlas verisi" },
|
||||
] as const;
|
||||
|
||||
// Kayıtlı profilli CTA'lar /listem boş durumunun dilini taşır (bkz.
|
||||
// listem-bos-cta.tsx): büyük turuncu buton, piksel ayraç. Sınıf seti tek yerde.
|
||||
const PROFILLI_CTA_SINIF =
|
||||
"h-12 cursor-pointer bg-orange-500 px-6 text-white transition-colors duration-200 hover:bg-orange-600";
|
||||
|
||||
function turEtiketi(tur: string) {
|
||||
return PUAN_TURLERI_SECENEK.find((t) => t.deger === tur)?.etiket ?? tur.toUpperCase();
|
||||
}
|
||||
|
||||
/** "Sayısal · 100.000. sıra" — kayıtlı profilin kısa özeti. */
|
||||
function KayitliSira({ sira, tur }: { sira: number; tur: string }) {
|
||||
return (
|
||||
<span className="inline-flex items-center gap-1.5 text-sm text-slate-600">
|
||||
<Trophy className="size-4 shrink-0 text-primary" aria-hidden />
|
||||
<span>
|
||||
Sıralaman kayıtlı:{" "}
|
||||
<strong className="font-semibold tabular-nums text-slate-900">
|
||||
{sira.toLocaleString("tr-TR")}.
|
||||
</strong>{" "}
|
||||
sıra · {turEtiketi(tur)}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Programatik SEO sayfalarındaki funnel girişi. Statik/SSR çıktı her zaman
|
||||
* profilsiz hâldir (sayfalar prerender edilmeye devam eder); hydration
|
||||
@@ -344,42 +369,53 @@ export function CtaSiraForm({
|
||||
if (kompakt) {
|
||||
// CLS: kayıtlı profil hydration SONRASI bulunur. Satır tablonun üstünde
|
||||
// olduğundan yüksekliği o anda değişmemeli — form yerinde (görünmez ve
|
||||
// inert) kalır, profilli kısayol aynı ızgara hücresine bindirilir; hücrenin
|
||||
// yüksekliğini her iki durumda da form belirler.
|
||||
// inert) kalır, profilli kısayol (başlığıyla birlikte) aynı ızgara hücresine
|
||||
// bindirilir; hücrenin yüksekliğini her iki durumda da başlık + form belirler.
|
||||
// Profilli içerik bu yüksekliği aşmayacak kadar kısa tutulmalı.
|
||||
const kompaktBaslik = baslik ?? "Sıralaman bu tabanların neresinde?";
|
||||
return (
|
||||
<section
|
||||
aria-labelledby={baslikId}
|
||||
className="rounded-2xl border border-slate-200 bg-white p-4 sm:p-5"
|
||||
className={cn(
|
||||
"rounded-2xl border p-4 transition-colors duration-200 sm:p-5",
|
||||
profil ? "border-primary/20 bg-primary/5" : "border-slate-200 bg-white",
|
||||
)}
|
||||
>
|
||||
<p className="text-sm leading-6 text-slate-600">
|
||||
<strong
|
||||
id={baslikId}
|
||||
className="font-heading text-base font-bold text-slate-900"
|
||||
>
|
||||
{baslik ?? "Sıralaman bu tabanların neresinde?"}
|
||||
</strong>{" "}
|
||||
Ücretsiz, üyelik gerekmez.
|
||||
</p>
|
||||
<div className="mt-3 grid">
|
||||
<div className="grid">
|
||||
<div
|
||||
ref={profil ? undefined : formRef}
|
||||
inert={profil ? true : undefined}
|
||||
className={cn("col-start-1 row-start-1", profil && "invisible")}
|
||||
>
|
||||
{siraFormu}
|
||||
<p className="text-sm leading-6 text-slate-600">
|
||||
<strong
|
||||
id={profil ? undefined : baslikId}
|
||||
className="font-heading text-base font-bold text-slate-900"
|
||||
>
|
||||
{kompaktBaslik}
|
||||
</strong>{" "}
|
||||
Ücretsiz, üyelik gerekmez.
|
||||
</p>
|
||||
<div className="mt-3">{siraFormu}</div>
|
||||
</div>
|
||||
{profil ? (
|
||||
<div className="col-start-1 row-start-1 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||
<p className="text-sm leading-6 text-slate-600">
|
||||
Sıralaman kayıtlı ({profil.sira.toLocaleString("tr-TR")}. sıra).
|
||||
</p>
|
||||
<Link
|
||||
href={sonucHref()}
|
||||
className="inline-flex h-11 items-center justify-center gap-2 rounded-full bg-orange-500 px-6 text-sm font-semibold text-white transition-colors duration-200 hover:bg-orange-600"
|
||||
<div className="col-start-1 row-start-1 flex flex-col items-center justify-center gap-3 text-center sm:flex-row sm:justify-between sm:gap-6 sm:text-left">
|
||||
<div className="flex min-w-0 flex-col items-center gap-1 sm:items-start">
|
||||
<p
|
||||
id={baslikId}
|
||||
className="font-heading text-base font-bold leading-6 text-slate-900"
|
||||
>
|
||||
{kompaktBaslik}
|
||||
</p>
|
||||
<KayitliSira sira={profil.sira} tur={profil.tur} />
|
||||
</div>
|
||||
<PagePixelDivider seed={67} className="w-24 sm:hidden" />
|
||||
<Button asChild size="lg" className={cn(PROFILLI_CTA_SINIF, "w-full sm:w-auto")}>
|
||||
<Link href={sonucHref()}>
|
||||
Sıralamana uygun programları gör
|
||||
<ArrowRight className="size-4" aria-hidden />
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -390,22 +426,24 @@ export function CtaSiraForm({
|
||||
|
||||
if (profil) {
|
||||
return (
|
||||
<section className="rounded-2xl border border-primary/20 bg-primary/5 p-6 sm:p-8">
|
||||
<h2 className="font-heading text-xl font-bold text-slate-900">
|
||||
<section className="flex flex-col items-center rounded-2xl border border-primary/20 bg-primary/5 px-6 py-8 text-center sm:px-10 sm:py-10">
|
||||
<h2 className="font-heading text-xl font-bold text-balance text-slate-900 sm:text-2xl">
|
||||
{baslik ?? "Sıralamana yakın programlar hangileri? Saniyede gör."}
|
||||
</h2>
|
||||
<p className="mt-2 text-sm leading-6 text-slate-600">
|
||||
Sıralaman kayıtlı ({profil.sira.toLocaleString("tr-TR")}. sıra) —
|
||||
gerçek YÖK Atlas verisiyle hayal, dengeli ve güvenli dilimlerindeki
|
||||
<div className="mt-3">
|
||||
<KayitliSira sira={profil.sira} tur={profil.tur} />
|
||||
</div>
|
||||
<p className="mt-2 max-w-xl text-sm leading-6 text-slate-600">
|
||||
Gerçek YÖK Atlas verisiyle hayal, dengeli ve güvenli dilimlerindeki
|
||||
programların hazır.
|
||||
</p>
|
||||
<Link
|
||||
href={sonucHref()}
|
||||
className="mt-4 inline-flex h-12 items-center justify-center gap-2 rounded-full bg-orange-500 px-7 text-sm font-semibold text-white transition-colors duration-200 hover:bg-orange-600"
|
||||
>
|
||||
<PagePixelDivider seed={67} className="mt-6" />
|
||||
<Button asChild size="lg" className={cn(PROFILLI_CTA_SINIF, "mt-6")}>
|
||||
<Link href={sonucHref()}>
|
||||
Sıralamana uygun programları gör
|
||||
<ArrowRight className="size-4" aria-hidden />
|
||||
</Link>
|
||||
</Button>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user