From 4dfb24bb134d10faf89f2569de3c58e5b088800e Mon Sep 17 00:00:00 2001 From: bilalgursen Date: Mon, 21 Sep 2026 09:22:59 +0300 Subject: [PATCH 1/2] =?UTF-8?q?feat(seo):=20derin=20katalog=20sayfalar?= =?UTF-8?q?=C4=B1nda=20ba=C5=9Fl=C4=B1k/a=C3=A7=C4=B1klama/H1'i=20sayfan?= =?UTF-8?q?=C4=B1n=20i=C3=A7eri=C4=9Fiyle=20ayr=C4=B1=C5=9Ft=C4=B1r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /bolum/*/sayfa/N: title + description + H1 o sayfanın taban sırası aralığını taşır (dilimdeki min–max efektif sıra; veri yoksa "taban verisi olmayan programlar"). Görünür breadcrumb üniversite sayfasındaki desenle eşitlendi (üst bölüm linki + "Sayfa N"). /universite/*/sayfa/N: description + giriş paragrafı o sayfadaki birim adlarını sayar (ilk 2 + "ve N birim daha"); dilim tek birimden ibaretse birim içi taban sırası aralığı eklenir. uzunluk nedeniyle değişmedi. Dilim hesabı tek yardımcıda (sayfaDilimi); metadata ve gövde aynı hesabı kullanır. Canonical, robots, sitemap, rota dosyaları ve 1. sayfaların başlık/açıklaması değişmedi. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --- .../katalog/components/bolum-icerik.tsx | 129 ++++++++++++++++-- src/features/katalog/components/sayfalama.tsx | 8 ++ .../katalog/components/universite-icerik.tsx | 69 ++++++++-- 3 files changed, 182 insertions(+), 24 deletions(-) diff --git a/src/features/katalog/components/bolum-icerik.tsx b/src/features/katalog/components/bolum-icerik.tsx index e1fd6d9..c676d43 100644 --- a/src/features/katalog/components/bolum-icerik.tsx +++ b/src/features/katalog/components/bolum-icerik.tsx @@ -14,7 +14,7 @@ import { sayfaMetadata, ustSegmentOgGorseli, } from "@/lib/seo"; -import { SAYFA_BOYU } from "./sayfalama"; +import { SAYFA_BOYU, sayfaDilimi } from "./sayfalama"; import { BolumProgramListesi } from "./bolum-program-listesi"; import { VeriKaynagi } from "./veri-kaynagi"; import { SiteFooter } from "@/components/site-footer"; @@ -42,14 +42,77 @@ export function bolumSayfaStaticParams(): { slug: string; no: string }[] { }); } +type BolumDetay = NonNullable<ReturnType<typeof getBolumBySlug>>; + +/** + * Sayfanın satır dilimi + o dilimin taban sırası aralığı. Liste efektif sıraya + * göre dizili (lisans, sonra önlisans) olduğundan her derin sayfa belirli bir + * sıralama aralığını kapsar. Metadata ve gövde aynı hesabı buradan alır; ikisi + * ayrı ayrı dilimlerse başlık ile tablo birbirinden kayabilir. + */ +function bolumSayfaDilimi(bolum: BolumDetay, sayfa: number) { + const tumProgramlar = [ + ...bolum.lisansProgramlari, + ...bolum.onlisansProgramlari, + ]; + const dilim = sayfaDilimi(tumProgramlar, sayfa); + let minSira: number | null = null; + let maxSira: number | null = null; + let verisiz = 0; + for (const p of dilim) { + const efektif = p.sira2025 ?? p.sira2024; + if (efektif == null) { + verisiz += 1; + continue; + } + if (minSira == null || efektif < minSira) minSira = efektif; + if (maxSira == null || efektif > maxSira) maxSira = efektif; + } + return { tumProgramlar, dilim, minSira, maxSira, verisiz }; +} + +/** + * Dilimin okunur özeti ("taban sırası 95.000–180.000 arası programlar"). + * Dilim boşsa null (çağıran sayfa numaralı eski metne düşer); dilimde hiç + * taban verisi yoksa aralık yerine bunu söyler. + */ +function siraAraligiMetni({ + dilim, + minSira, + maxSira, + verisiz, +}: ReturnType<typeof bolumSayfaDilimi>): string | null { + if (dilim.length === 0) return null; + if (minSira == null || maxSira == null) { + return "taban verisi olmayan programlar"; + } + const aralik = + minSira === maxSira + ? `taban sırası ${sayi(minSira)} olan programlar` + : `taban sırası ${sayi(minSira)}–${sayi(maxSira)} arası programlar`; + return verisiz > 0 ? `${aralik} ile taban verisi olmayanlar` : aralik; +} + export function bolumSayfaMetadata(slug: string, sayfa: number): Metadata { const bolum = getBolumBySlug(slug); if (!bolum) return {}; const { stats } = bolum; if (sayfa > 1) { + const sayfaDilim = bolumSayfaDilimi(bolum, sayfa); + const aralik = siraAraligiMetni(sayfaDilim); + const { minSira, maxSira } = sayfaDilim; + // <title> kısa kalsın: aralığın yalnız rakamları; açıklama tam cümleyi taşır. + const baslikEki = + minSira != null && maxSira != null + ? minSira === maxSira + ? `Sıra ${sayi(minSira)}, Sayfa ${sayfa}` + : `Sıra ${sayi(minSira)}–${sayi(maxSira)}, Sayfa ${sayfa}` + : `Sayfa ${sayfa}`; return sayfaMetadata({ - title: `${bolum.ad} Taban Puanları 2026 (Sayfa ${sayfa})`, - description: `${bolum.ad} taban puanları ve başarı sıralamaları tablosunun ${sayfa}. sayfası — toplam ${stats.toplam} programın 2025 yerleştirme verileri.`, + title: `${bolum.ad} Taban Puanları 2026 (${baslikEki})`, + description: aralik + ? `${bolum.ad} taban puanları, sayfa ${sayfa}: ${aralik}. Toplam ${stats.toplam} programın 2025 yerleştirme verileri — taban puanı, başarı sıralaması ve kontenjan.` + : `${bolum.ad} taban puanları ve başarı sıralamaları tablosunun ${sayfa}. sayfası — toplam ${stats.toplam} programın 2025 yerleştirme verileri.`, path: `/bolum/${slug}/sayfa/${sayfa}`, openGraph: { images: ustSegmentOgGorseli( @@ -74,13 +137,12 @@ export function BolumIcerik({ slug, sayfa }: { slug: string; sayfa: number }) { const bolum = getBolumBySlug(slug); if (!bolum) notFound(); - const tumProgramlar = [ - ...bolum.lisansProgramlari, - ...bolum.onlisansProgramlari, - ]; + const sayfaDilim = bolumSayfaDilimi(bolum, sayfa); + const { tumProgramlar } = sayfaDilim; const toplamSayfa = bolumToplamSayfa(tumProgramlar.length); if (sayfa < 1 || sayfa > toplamSayfa) notFound(); const ilkSayfa = sayfa === 1; + const aralik = siraAraligiMetni(sayfaDilim); const buYol = ilkSayfa ? `/bolum/${slug}` : `/bolum/${slug}/sayfa/${sayfa}`; return ( @@ -113,20 +175,57 @@ export function BolumIcerik({ slug, sayfa }: { slug: string; sayfa: number }) { Bölümler </Link> <ChevronRight className="size-3.5" aria-hidden /> - <span className="text-foreground"> - {ilkSayfa ? bolum.ad : `Sayfa ${sayfa}`} - </span> + {ilkSayfa ? ( + <span className="text-foreground">{bolum.ad}</span> + ) : ( + <> + <Link + href={`/bolum/${slug}`} + className="transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring" + > + {bolum.ad} + </Link> + <ChevronRight className="size-3.5" aria-hidden /> + <span className="text-foreground">Sayfa {sayfa}</span> + </> + )} </nav> <header className="border-b pb-7 sm:pb-9"> <h1 className="max-w-3xl font-heading text-3xl font-bold tracking-tight text-foreground sm:text-5xl"> {bolum.ad} + {ilkSayfa ? "" : ` — Sayfa ${sayfa}`} + {!ilkSayfa && aralik ? ( + <> + {" "} + <span className="mt-2 block text-lg font-semibold tracking-normal text-muted-foreground sm:text-2xl"> + {aralik.charAt(0).toLocaleUpperCase("tr-TR") + aralik.slice(1)} + </span> + </> + ) : null} </h1> - <p className="mt-3 max-w-2xl text-sm leading-6 text-muted-foreground sm:text-base"> - {sayi(tumProgramlar.length)} üniversite programının 2025 taban - puanlarını, başarı sıralamalarını ve kontenjanlarını incele - {!ilkSayfa ? ` — sayfa ${sayfa}` : ""}. - </p> + {ilkSayfa ? ( + <p className="mt-3 max-w-2xl text-sm leading-6 text-muted-foreground sm:text-base"> + {sayi(tumProgramlar.length)} üniversite programının 2025 taban + puanlarını, başarı sıralamalarını ve kontenjanlarını incele. + </p> + ) : ( + <p className="mt-3 max-w-2xl text-sm leading-6 text-muted-foreground sm:text-base"> + {bolum.ad} taban puanları tablosunun {sayfa}. sayfası ( + {sayi(tumProgramlar.length)} programın{" "} + {sayi((sayfa - 1) * SAYFA_BOYU + 1)}– + {sayi(Math.min(sayfa * SAYFA_BOYU, tumProgramlar.length))}. + satırları, taban sırasına göre) + {aralik ? `: ${aralik}` : ""}. Listenin başı{" "} + <Link + href={`/bolum/${slug}`} + className="font-medium text-primary hover:underline" + > + ilk sayfada + </Link> + . + </p> + )} </header> <section aria-labelledby="universite-programlari" className="mt-8"> diff --git a/src/features/katalog/components/sayfalama.tsx b/src/features/katalog/components/sayfalama.tsx index 4802634..5cd3c52 100644 --- a/src/features/katalog/components/sayfalama.tsx +++ b/src/features/katalog/components/sayfalama.tsx @@ -5,6 +5,14 @@ import { ChevronLeft, ChevronRight } from "lucide-react"; /** Programatik tablo sayfaları için satır dilimi boyutu. */ export const SAYFA_BOYU = 50; +/** + * Düz listenin `sayfa` numaralı dilimi. Metadata (title/description) ile sayfa + * gövdesi aynı satırları anlatsın diye dilim hesabı tek yerde durur. + */ +export function sayfaDilimi<T>(liste: readonly T[], sayfa: number): T[] { + return liste.slice((sayfa - 1) * SAYFA_BOYU, sayfa * SAYFA_BOYU); +} + /** * Statik path tabanlı sayfalama navigasyonu. 1. sayfa taban URL'in * kendisidir (/bolum/x), sonrakiler /bolum/x/sayfa/2 ... — hepsi gerçek diff --git a/src/features/katalog/components/universite-icerik.tsx b/src/features/katalog/components/universite-icerik.tsx index 1b47c40..c473a84 100644 --- a/src/features/katalog/components/universite-icerik.tsx +++ b/src/features/katalog/components/universite-icerik.tsx @@ -18,7 +18,7 @@ import { } from "@/lib/seo"; import { CtaSiraForm } from "@/features/sihirbaz/components/cta-sira-form"; import { SiteFooter } from "@/components/site-footer"; -import { Sayfalama, SAYFA_BOYU } from "./sayfalama"; +import { Sayfalama, SAYFA_BOYU, sayfaDilimi } from "./sayfalama"; import { PagePixelDivider } from "@/components/pixel-decor"; import { UniversiteKonumHaritasi } from "./universite-konum-haritasi"; import { uniUlkeKonum } from "@/lib/harita-ulkeler"; @@ -51,13 +51,65 @@ export function uniSayfaStaticParams(): { slug: string; no: string }[] { }); } +type UniDetay = NonNullable<ReturnType<typeof getUniversiteBySlug>>; + +/** + * Sayfanın satır dilimi + o dilimde geçen fakülte/birim adları (tablo + * sırasıyla, tekrarsız). Liste fakülteye göre dizili olduğundan her derin + * sayfa belirli birimleri kapsar. Metadata ve gövde aynı hesabı buradan alır. + * Fakültesi boş satırlar tabloda "Diğer" grubuna düşer; ad listesine girmez. + */ +function uniSayfaDilimi(uni: UniDetay, sayfa: number) { + // Sayfalama fakülte sıralı düz liste üzerinden; dilim içi yeniden gruplanır + const tumProgramlar = uni.fakulteler.flatMap((f) => f.programlar); + const dilim = sayfaDilimi(tumProgramlar, sayfa); + const fakulteAdlari: string[] = []; + for (const p of dilim) { + if (p.fakulte && !fakulteAdlari.includes(p.fakulte)) { + fakulteAdlari.push(p.fakulte); + } + } + return { tumProgramlar, dilim, fakulteAdlari }; +} + +/** + * İlk 2 ad + "ve N birim daha"; ad yoksa null (çağıran eski metne düşer). + * Dilim tek birimden ibaretse (50'den çok programlı MYO'lar art arda iki + * sayfayı doldurabiliyor) sayfalar ayırt edilsin diye birim içi taban sırası + * aralığı eklenir — birim içinde satırlar zaten taban sırasına göre dizili. + */ +function fakulteOzeti({ + dilim, + fakulteAdlari: adlar, +}: ReturnType<typeof uniSayfaDilimi>): string | null { + if (adlar.length === 0) return null; + if (adlar.length === 1) { + const siralar = dilim + .map((p) => p.sira2025 ?? p.sira2024) + .filter((n): n is number => n != null); + if (siralar.length === 0) return adlar[0]; + const min = Math.min(...siralar); + const max = Math.max(...siralar); + return min === max + ? `${adlar[0]} (taban sırası ${sayi(min)})` + : `${adlar[0]} (taban sırası ${sayi(min)}–${sayi(max)} arası)`; + } + if (adlar.length === 2) return `${adlar[0]} ve ${adlar[1]}`; + return `${adlar[0]}, ${adlar[1]} ve ${adlar.length - 2} birim daha`; +} + export function uniSayfaMetadata(slug: string, sayfa: number): Metadata { const uni = getUniversiteBySlug(slug); if (!uni) return {}; if (sayfa > 1) { + // Üniversite adları uzun: <title> sayfa numarasıyla kalır (~60 karakter), + // farklılaştırıcı (o sayfadaki birimler) açıklamaya ve gövdeye gider. + const birimler = fakulteOzeti(uniSayfaDilimi(uni, sayfa)); return sayfaMetadata({ title: `${uni.ad} Taban Puanları 2026 (Sayfa ${sayfa})`, - description: `${uni.ad} taban puanları ve başarı sıralamaları tablosunun ${sayfa}. sayfası — toplam ${uni.programSayisi} programın 2025 yerleştirme verileri.`, + description: birimler + ? `${uni.ad} taban puanları, sayfa ${sayfa}: ${birimler}. Toplam ${uni.programSayisi} programın 2025 yerleştirme verileri — taban puanı, başarı sıralaması ve kontenjan.` + : `${uni.ad} taban puanları ve başarı sıralamaları tablosunun ${sayfa}. sayfası — toplam ${uni.programSayisi} programın 2025 yerleştirme verileri.`, path: `/universite/${slug}/sayfa/${sayfa}`, openGraph: { images: ustSegmentOgGorseli( @@ -84,14 +136,11 @@ export function UniversiteIcerik({ const uni = getUniversiteBySlug(slug); if (!uni) notFound(); - // Sayfalama fakülte sıralı düz liste üzerinden; dilim içi yeniden gruplanır - const tumProgramlar = uni.fakulteler.flatMap((f) => f.programlar); + const sayfaDilim = uniSayfaDilimi(uni, sayfa); + const { tumProgramlar, dilim } = sayfaDilim; const toplamSayfa = uniToplamSayfa(tumProgramlar.length); if (sayfa < 1 || sayfa > toplamSayfa) notFound(); - const dilim = tumProgramlar.slice( - (sayfa - 1) * SAYFA_BOYU, - sayfa * SAYFA_BOYU, - ); + const birimler = fakulteOzeti(sayfaDilim); const gruplar: { fakulte: string; programlar: (Program & { bolumSlug: string | null })[]; @@ -263,7 +312,9 @@ export function UniversiteIcerik({ {sayi(tumProgramlar.length)} programın{" "} {sayi((sayfa - 1) * SAYFA_BOYU + 1)}– {sayi(Math.min(sayfa * SAYFA_BOYU, tumProgramlar.length))}. - satırları, fakülte sırasıyla). Üniversite özeti ve istatistikler{" "} + satırları, fakülte sırasıyla). + {birimler ? ` Bu sayfadaki birimler: ${birimler}.` : ""} Üniversite + özeti ve istatistikler{" "} <Link href={`/universite/${slug}`} className="font-medium text-primary hover:underline" From f1abedcceee54fba0c1a765e07ea229720a64e0f Mon Sep 17 00:00:00 2001 From: bilalgursen <bilalgursen777@gmail.com> Date: Mon, 21 Sep 2026 09:24:32 +0300 Subject: [PATCH 2/2] =?UTF-8?q?feat(katalog):=20CTA=20kart=C4=B1nda=20vaat?= =?UTF-8?q?siz=20ba=C5=9Fl=C4=B1k=20+=20k=C3=B6pr=C3=BC=20c=C3=BCmlesi,=20?= =?UTF-8?q?/bolum=20sayfas=C4=B1na=20CTA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CtaSiraForm'a isteğe bağlı `aciklama` prop'u (yalnız profilsiz karttaki paragrafın yerine geçer; varsayılan paragraflar aynen kaldı). "Sıralamanla nereye yerleşirsin?" / "…programlarına yerleşir misin?" başlıkları kalktı: varsayılan "Sıralamana yakın programlar hangileri?", katalogda "Sıralaman {ad} tabanlarının neresinde?". Üniversite ve bölüm sayfaları aynı köprü cümlesini tek sabitten (KATALOG_CTA_ACIKLAMA) alır; kart /bolum/[slug] sayfasına üniversite sayfasıyla aynı konumda (liste + sayfalama altı, mt-10) eklendi. cta_form_goruntulendi ölçümü ve buton deseni değişmedi. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --- .../katalog/components/bolum-icerik.tsx | 11 +++++++- src/features/katalog/components/sayfalama.tsx | 11 ++++++++ .../katalog/components/universite-icerik.tsx | 10 +++++-- .../sihirbaz/components/cta-sira-form.tsx | 26 +++++++++++++------ 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/features/katalog/components/bolum-icerik.tsx b/src/features/katalog/components/bolum-icerik.tsx index c676d43..d9b5bbf 100644 --- a/src/features/katalog/components/bolum-icerik.tsx +++ b/src/features/katalog/components/bolum-icerik.tsx @@ -14,9 +14,10 @@ import { sayfaMetadata, ustSegmentOgGorseli, } from "@/lib/seo"; -import { SAYFA_BOYU, sayfaDilimi } from "./sayfalama"; +import { KATALOG_CTA_ACIKLAMA, SAYFA_BOYU, sayfaDilimi } from "./sayfalama"; import { BolumProgramListesi } from "./bolum-program-listesi"; import { VeriKaynagi } from "./veri-kaynagi"; +import { CtaSiraForm } from "@/features/sihirbaz/components/cta-sira-form"; import { SiteFooter } from "@/components/site-footer"; import { Skeleton } from "@/components/ui/skeleton"; @@ -252,6 +253,14 @@ export function BolumIcerik({ slug, sayfa }: { slug: string; sayfa: number }) { /> <VeriKaynagi className="mt-6" /> </section> + + {/* Üniversite sayfasıyla aynı konum ve aynı kart: liste + sayfalama altı */} + <div className="mt-10"> + <CtaSiraForm + baslik={`Sıralaman ${bolum.ad} tabanlarının neresinde?`} + aciklama={KATALOG_CTA_ACIKLAMA} + /> + </div> </main> <SiteFooter /> </> diff --git a/src/features/katalog/components/sayfalama.tsx b/src/features/katalog/components/sayfalama.tsx index 5cd3c52..f86685f 100644 --- a/src/features/katalog/components/sayfalama.tsx +++ b/src/features/katalog/components/sayfalama.tsx @@ -13,6 +13,17 @@ export function sayfaDilimi<T>(liste: readonly T[], sayfa: number): T[] { return liste.slice((sayfa - 1) * SAYFA_BOYU, sayfa * SAYFA_BOYU); } +/** + * Üniversite ve bölüm tablo sayfalarının altındaki CtaSiraForm kartının köprü + * cümlesi — iki sayfa birebir aynı metni kullansın diye tek kaynak. Sunucu + * bileşenlerinden okunduğu için "use client" olan cta-sira-form.tsx'te + * duramaz (istemci modülünün sabitleri sunucuda değer olarak okunamaz). + * Vaat içermez: tablo geçmiş veridir, ürün sıralamaya yakın programları + * risk seviyesine göre ayırıp listeler. + */ +export const KATALOG_CTA_ACIKLAMA = + "Bu tablodaki tabanlar geçmiş yerleştirmelerin sonucu; bu yıl değişebilir. Sıralamanı gir, tabanı sıralamana yakın programları risk seviyesine göre ayrılmış hâlde listeleyelim. Ücretsiz, üyelik gerekmez."; + /** * Statik path tabanlı sayfalama navigasyonu. 1. sayfa taban URL'in * kendisidir (/bolum/x), sonrakiler /bolum/x/sayfa/2 ... — hepsi gerçek diff --git a/src/features/katalog/components/universite-icerik.tsx b/src/features/katalog/components/universite-icerik.tsx index c473a84..207f9b7 100644 --- a/src/features/katalog/components/universite-icerik.tsx +++ b/src/features/katalog/components/universite-icerik.tsx @@ -18,7 +18,12 @@ import { } from "@/lib/seo"; import { CtaSiraForm } from "@/features/sihirbaz/components/cta-sira-form"; import { SiteFooter } from "@/components/site-footer"; -import { Sayfalama, SAYFA_BOYU, sayfaDilimi } from "./sayfalama"; +import { + KATALOG_CTA_ACIKLAMA, + Sayfalama, + SAYFA_BOYU, + sayfaDilimi, +} from "./sayfalama"; import { PagePixelDivider } from "@/components/pixel-decor"; import { UniversiteKonumHaritasi } from "./universite-konum-haritasi"; import { uniUlkeKonum } from "@/lib/harita-ulkeler"; @@ -351,7 +356,8 @@ export function UniversiteIcerik({ <div className="mt-10"> <CtaSiraForm - baslik={`Sıralamanla ${uni.ad} programlarına yerleşir misin?`} + baslik={`Sıralaman ${uni.ad} tabanlarının neresinde?`} + aciklama={KATALOG_CTA_ACIKLAMA} /> </div> </main> diff --git a/src/features/sihirbaz/components/cta-sira-form.tsx b/src/features/sihirbaz/components/cta-sira-form.tsx index 6003c8f..5044d41 100644 --- a/src/features/sihirbaz/components/cta-sira-form.tsx +++ b/src/features/sihirbaz/components/cta-sira-form.tsx @@ -60,8 +60,19 @@ const KANITLAR = [ * Profilsiz CTA adayı ana sayfaya göndermez: buton alttan bir çekmece açar, * sıralama girişi ve sihirbaz adayın bulunduğu sayfanın bağlamında akar. * Tasarım gerekçesi için bkz. docs/tasarim/cta-cekmece-tasarimi.md. + * + * `baslik` iki kartın (profilli/profilsiz) başlığını, `aciklama` yalnız + * profilsiz karttaki paragrafı değiştirir — katalog sayfaları kartı üstündeki + * tabloya bağlayan köprü cümlesini buradan verir. Başlık ve açıklamalar + * yerleşme vaadi içermez: ürün sıralamaya yakın programları listeler. */ -export function CtaSiraForm({ baslik }: { baslik?: string }) { +export function CtaSiraForm({ + baslik, + aciklama, +}: { + baslik?: string; + aciklama?: string; +}) { const profil = useTercihProfili(); const router = useRouter(); @@ -146,7 +157,7 @@ export function CtaSiraForm({ baslik }: { baslik?: string }) { 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"> - {baslik ?? "Sıralamanla nereye yerleşirsin? Saniyede gör."} + {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) — @@ -170,12 +181,11 @@ export function CtaSiraForm({ baslik }: { baslik?: string }) { 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"> - {baslik ?? "Sıralamanla nereye yerleşirsin? Saniyede gör."} + {baslik ?? "Sıralamana yakın programlar hangileri? Saniyede gör."} </h2> <p className="mt-2 text-sm leading-6 text-slate-600"> - YKS başarı sıralamanı gir; gerçek YÖK Atlas verisiyle sıralamana uygun - hayal, dengeli ve garanti dilimlerindeki programları anında listele. - Ücretsiz, üyelik gerekmez. + {aciklama ?? + "YKS başarı sıralamanı gir; gerçek YÖK Atlas verisiyle sıralamana uygun hayal, dengeli ve garanti dilimlerindeki programları anında listele. Ücretsiz, üyelik gerekmez."} </p> <Button type="button" @@ -195,7 +205,7 @@ export function CtaSiraForm({ baslik }: { baslik?: string }) { > {/* Görünür başlıklar adıma göre değişir; erişilebilir ad sabit kalır. */} <DrawerTitle className="sr-only"> - Sıralamanla nereye yerleşirsin? + Sıralamana yakın programlar hangileri? </DrawerTitle> <DrawerDescription className="sr-only"> YKS başarı sıralamanı gir; sıralamana uygun programları bu sayfadan @@ -215,7 +225,7 @@ export function CtaSiraForm({ baslik }: { baslik?: string }) { <div> <SectionEyebrow>Saniyede gör</SectionEyebrow> <h2 className="mt-3 font-heading text-2xl font-bold text-slate-900"> - Sıralamanla nereye yerleşirsin? + Sıralamana yakın programlar hangileri? </h2> <p className="mt-2 max-w-xl text-sm leading-6 text-slate-600"> Puan türünü seç, başarı sıralamanı yaz; hayal, dengeli ve