refactor: pazarlama feature'ı — landing + meraklısına taşındı (Faz 5)

- landing/{sosyal-kanit,sosyal-kanit-govde,reveal} + hero-baslik +
  hero-focus-button + turkey-pixel-map features/pazarlama/components/ altına
- app/page.tsx'teki inline ComparisonCell landing-parcalari.tsx'e çıkarıldı
- /meraklisina içeriği MeraklisinaIcerik'e (okumayı pazarlama-queries'in
  meraklisinaDemoVerisi'nden alıyor); sayfa senkron + Suspense; demo.tsx →
  meraklisina-demo.tsx, huni-semasi.tsx feature'a taşındı
- AGENTS.md'deki huni-semasi ve anlatım metni yol referansları aynı commit'te
  güncellendi; SEMA içeriği değişmedi
- Davranış değişikliği yok

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-08-08 01:27:53 +03:00
parent 8b5aa8c8a6
commit baebc1fc80
15 changed files with 228 additions and 185 deletions

View File

@@ -25,5 +25,5 @@ Funnel CTA butonlarında ("Listemi oluştur", "Tercihlerimi belirle", giriş/öd
# Meraklısına'daki mermaid şeması mimariyle senkron kalmalı # Meraklısına'daki mermaid şeması mimariyle senkron kalmalı
`/meraklisina` sayfasındaki sihirbaz akış şeması (`src/app/meraklisina/huni-semasi.tsx` içindeki `SEMA` sabiti) ürünün gerçek davranışının belgesidir, dekor değildir. Sihirbaz/listeleme mimarisinde davranış değiştiren her değişiklikte bu şema da aynı PR/commit içinde güncellenmeli: sihirbaz adımlarının sayısı-sırası-içeriği (alan → il → devlet/vakıf), aday havuzu kuralları, 24'lük liste iskeleti (hayal/dengeli/garanti dağılımı), havuz 24'ün altına düşünce filtre gevşetme sırası ve yapay zekânın havuz-dışına-çıkamama kuralı. Şemayı güncellerken çevresindeki unsurları da eşitle: bölümdeki anlatım metni (`src/app/meraklisina/page.tsx`, 4. bölüm), kabın `aria-label`'ı ve figcaption. Şema öğrenci diliyle kalmalı (SQL/prompt/teknik detay yok) ve ürünün risk renk dilini korumalı — kırmızı/sarı/yeşil her zaman metin etiketiyle birlikte, renk tek başına anlam taşımaz. `/meraklisina` sayfasındaki sihirbaz akış şeması (`src/features/pazarlama/components/huni-semasi.tsx` içindeki `SEMA` sabiti) ürünün gerçek davranışının belgesidir, dekor değildir. Sihirbaz/listeleme mimarisinde davranış değiştiren her değişiklikte bu şema da aynı PR/commit içinde güncellenmeli: sihirbaz adımlarının sayısı-sırası-içeriği (alan → il → devlet/vakıf), aday havuzu kuralları, 24'lük liste iskeleti (hayal/dengeli/garanti dağılımı), havuz 24'ün altına düşünce filtre gevşetme sırası ve yapay zekânın havuz-dışına-çıkamama kuralı. Şemayı güncellerken çevresindeki unsurları da eşitle: bölümdeki anlatım metni (`src/features/pazarlama/components/meraklisina-icerik.tsx`, 4. bölüm), kabın `aria-label`'ı ve figcaption. Şema öğrenci diliyle kalmalı (SQL/prompt/teknik detay yok) ve ürünün risk renk dilini korumalı — kırmızı/sarı/yeşil her zaman metin etiketiyle birlikte, renk tek başına anlam taşımaz.
<!-- END:nextjs-agent-rules --> <!-- END:nextjs-agent-rules -->

View File

@@ -2,7 +2,7 @@ import { NextResponse } from "next/server";
import { sosyalKanitVerisi } from "@/lib/sosyal-kanit"; import { sosyalKanitVerisi } from "@/lib/sosyal-kanit";
// Fiyat bölümündeki şeridin canlı sayıyı tazelemek için yokladığı uç. // Fiyat bölümündeki şeridin canlı sayıyı tazelemek için yokladığı uç.
// İlk değer sunucudan HTML ile geliyor (bkz. components/landing/sosyal-kanit.tsx); // İlk değer sunucudan HTML ile geliyor (bkz. features/pazarlama/components/sosyal-kanit.tsx);
// burası yalnızca sayfa açık kaldıkça gelen güncellemeler için. // burası yalnızca sayfa açık kaldıkça gelen güncellemeler için.
// Sayılar sosyal kanıt, gizli veri değil — kimlik doğrulaması yok. // Sayılar sosyal kanıt, gizli veri değil — kimlik doğrulaması yok.
// Yük: sosyalKanitVerisi kendi içinde TTL önbelleğine sahip, yoklama // Yük: sosyalKanitVerisi kendi içinde TTL önbelleğine sahip, yoklama

View File

@@ -1,17 +1,12 @@
import { Suspense } from "react";
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Parallax } from "@/components/parallax"; import { Parallax } from "@/components/parallax";
import { PagePixelDivider, SectionEyebrow } from "@/components/pixel-decor"; import { PagePixelDivider, SectionEyebrow } from "@/components/pixel-decor";
import { SiteFooter } from "@/components/site-footer"; import { SiteFooter } from "@/components/site-footer";
import { dilimAra, rankWindowFacets } from "@/lib/db";
import type { DilimKey } from "@/types/yokatlas";
import { import {
DemoKapanisCta, MeraklisinaIcerik,
DemoKumanda, MeraklisinaIcerikSkeleton,
DilimSeridiCanli, } from "@/features/pazarlama/components/meraklisina-icerik";
SiralamaDemo,
type DemoVeri,
} from "./demo";
import { HuniSemasi } from "./huni-semasi";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Meraklısına: KolayTercih nasıl çalışır?", title: "Meraklısına: KolayTercih nasıl çalışır?",
@@ -20,33 +15,7 @@ export const metadata: Metadata = {
"Sıralamanı girdiğinde arka planda ne oluyor? Dilimler, risk renkleri ve sihirbazın adım adım daralan filtreleri — öğrenci diliyle, sıralamana göre hesaplanan canlı görsellerle.", "Sıralamanı girdiğinde arka planda ne oluyor? Dilimler, risk renkleri ve sihirbazın adım adım daralan filtreleri — öğrenci diliyle, sıralamana göre hesaplanan canlı görsellerle.",
}; };
/**
* Algoritmanın öğrenci diline çevrilmiş anlatımı. Teknik detay (SQL, çarpan
* mutfağı) bilerek verilmez; amaç güven: veri gerçek, kurallar şeffaf.
* Dilim şeridi canlıdır: kullanıcının kayıtlı tercih profilindeki sıralama
* okunur, şerit o sıralamanın gerçek sayılarıyla güncellenir (bkz. demo.tsx);
* profil yoksa örnek sıralama gösterilir. Sihirbaz hunisi ise statik
* bir mermaid şemasıyla anlatılır (bkz. huni-semasi.tsx).
* Diyagramlar ürünün risk renk dilini kullanır (yeşil/sarı/kırmızı) ve her
* bölge metinle de etiketlenir — renk tek başına anlam taşımaz.
*/
// Profili olmayan ziyaretçi bu örnek sıralamayı görür; SSR'da gerçek veriyle
// render edilir ki profil olmadan da sayfa anlamlı olsun.
const VARSAYILAN_SIRA = 100_000;
export default function MeraklisinaPage() { export default function MeraklisinaPage() {
const dilimToplam = Object.fromEntries(
(["hayal", "dengeli", "garanti"] as DilimKey[]).map((d) => [
d,
dilimAra(VARSAYILAN_SIRA, "say", d, { limit: 0 }).toplam,
]),
) as Record<DilimKey, number>;
const baslangicVeri: DemoVeri = {
facetler: rankWindowFacets(VARSAYILAN_SIRA, "say"),
dilimToplam,
};
return ( return (
<> <>
<main className="mx-auto w-full max-w-2xl px-4 py-16"> <main className="mx-auto w-full max-w-2xl px-4 py-16">
@@ -65,117 +34,9 @@ export default function MeraklisinaPage() {
<PagePixelDivider seed={73} className="mt-6" /> <PagePixelDivider seed={73} className="mt-6" />
<SiralamaDemo <Suspense fallback={<MeraklisinaIcerikSkeleton />}>
baslangicSira={VARSAYILAN_SIRA} <MeraklisinaIcerik />
baslangicVeri={baslangicVeri} </Suspense>
>
<Parallax
fromStart
strength={4}
className="mt-8 space-y-10 text-sm leading-7 text-slate-700"
>
<section>
<h2 className="font-heading text-lg font-bold text-slate-900">
1. Her şey taban sıralamasıyla başlar
</h2>
<p className="mt-2">
Bir bölümün <strong>taban sıralaması</strong>, geçen yıl o bölüme
yerleşen <em>son</em>{" "}
öğrencinin Türkiye sıralamasıdır. Senin sıralaman bu sayıdan
küçükse (yani daha iyiysen), geçen yılın koşullarında o bölüme
yerleşebilirdin demektir. Sistemde her programın en güncel taban
sıralaması kayıtlıdır; bir bölümün 2025 verisi henüz oluşmamışsa
bir önceki yılınki kullanılır.
</p>
</section>
<DemoKumanda />
<section>
<h2 className="font-heading text-lg font-bold text-slate-900">
2. Programlar üç dilime ayrılır
</h2>
<p className="mt-2">
Sıralamanı girdiğinde tüm programlar senin konumuna göre üç kümeye
ayrılır: tabanı senden <strong>daha iyi</strong> olanlar{" "}
<span className="font-semibold text-red-600">Hayal</span> (şansını
denediğin satırlar), tabanı sıralamana{" "}
<strong>yakın</strong> olanlar{" "}
<span className="font-semibold text-amber-600">Dengeli</span>{" "}
(listenin bel kemiği sıralamanın yaklaşık yüzde kırk fazlasına
kadar pay bırakılır), tabanı{" "}
<strong>belirgin şekilde altında</strong> kalan her şey ise{" "}
<span className="font-semibold text-emerald-600">Garanti</span>{" "}
dilimidir.
</p>
<DilimSeridiCanli />
<p className="mt-4">
Garanti diliminin bir sonu yok: 87. sıradaki bir adayın da 500
bininci sıradaki bir adayın da ulaşabildiği <em>bütün</em>{" "}
programlar listededir. Liste sana en yakın tabandan başlar; aşağı
indikçe ve &ldquo;Daha fazla göster&rdquo;e bastıkça senden
uzaklaşan seçenekler gelir. Böylece ilk gördüklerin her zaman en
isabetli adaylardır ama hiçbir seçenek senden saklanmaz.
</p>
</section>
<section>
<h2 className="font-heading text-lg font-bold text-slate-900">
3. Risk renkleri her yerde aynı dili konuşur
</h2>
<p className="mt-2">
Tabloda, haritada ve yapay zekâ listesinde gördüğün nokta ve
renkler tek bir kurala bağlıdır:{" "}
<span className="font-semibold text-emerald-600">yeşil</span>{" "}
tabanı sıralamanın belirgin altında (güvenli),{" "}
<span className="font-semibold text-amber-600">sarı</span>{" "}
sıralamana yakın (az riskli),{" "}
<span className="font-semibold text-red-600">kırmızı</span>{" "}
tabanı senden iyi (riskli). Renk hangi sayfada olursa olsun aynı
hesaptan çıkar; bir satır sekme değiştirdi diye renk değiştirmez.
</p>
</section>
<section>
<h2 className="font-heading text-lg font-bold text-slate-900">
4. Sihirbaz süzer, yapay zekâ kurar
</h2>
<p className="mt-2">
&ldquo;Yapay Zeka listemi kur&rdquo; sihirbazındaki üç adım birbirinden
bağımsız değildir. İlk adımda yalnızca{" "}
<strong>sıralamanla ulaşabildiğin</strong>{" "}
alanlar listelenir; ikinci adımdaki iller, seçtiğin alanlardaki
program sayısına göre yeniden hesaplanır; üçüncü adımdaki
devlet/vakıf sayıları da hem alan hem il seçimini hesaba katar.
Adımlar bitince elde kalan gerçek programlar bir{" "}
<strong>aday havuzu</strong>{" "}
olur ve yapay zekâya öyle gider: ona boş bir sayfa değil, bu havuz
verilir. Aşağıdaki şema akışın tamamını gösterir havuz
24&apos;ün altına düşerse filtrelerin nasıl gevşetildiği, yine de
yetmezse listenin eldeki programlarla, sana ıkça belirtilerek
nasıl kurulduğu da dahil.
</p>
<HuniSemasi />
</section>
<section>
<h2 className="font-heading text-lg font-bold text-slate-900">
5. Dürüst olalım: bu bir tahmin aracıdır
</h2>
<p className="mt-2">
Tüm bu hesaplar <strong>geçen yılların</strong>{" "}
yerleştirme sonuçlarına dayanır. Kontenjanlar, tercih davranışları
ve puanlar her yıl değişir; geçen yıl &ldquo;garanti&rdquo;
görünen bir bölüm bu yıl dolabilir. Bu yüzden satırlarda son beş
yılın taban seyrini de gösteririz çizgi yukarı tırmanıyorsa
bölüm zorlaşıyor demektir. KolayTercih karar <em>destek</em>{" "}
aracıdır; listenin son hâli ve sorumluluğu her zaman sana aittir.
</p>
</section>
<DemoKapanisCta />
</Parallax>
</SiralamaDemo>
</main> </main>
<SiteFooter /> <SiteFooter />
</> </>

View File

@@ -2,7 +2,6 @@ import {
ArrowRight, ArrowRight,
ArrowUpRight, ArrowUpRight,
BarChart3, BarChart3,
CheckCircle2,
Coins, Coins,
Compass, Compass,
FileText, FileText,
@@ -12,18 +11,18 @@ import {
ShieldCheck, ShieldCheck,
TrendingUp, TrendingUp,
Wallet, Wallet,
X,
} from "lucide-react"; } from "lucide-react";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import { Suspense } from "react"; import { Suspense } from "react";
import { HeroBaslik } from "@/components/hero-baslik"; import { ComparisonCell } from "@/features/pazarlama/components/landing-parcalari";
import { KapanisCta } from "@/components/hero-focus-button"; import { HeroBaslik } from "@/features/pazarlama/components/hero-baslik";
import { KapanisCta } from "@/features/pazarlama/components/hero-focus-button";
import { HeroForm } from "@/components/hero-form"; import { HeroForm } from "@/components/hero-form";
import { Parallax } from "@/components/parallax"; import { Parallax } from "@/components/parallax";
import { Reveal } from "@/components/landing/reveal"; import { Reveal } from "@/features/pazarlama/components/reveal";
import { SosyalKanitBandi } from "@/components/landing/sosyal-kanit"; import { SosyalKanitBandi } from "@/features/pazarlama/components/sosyal-kanit";
import { TurkeyPixelMap } from "@/components/turkey-pixel-map"; import { TurkeyPixelMap } from "@/features/pazarlama/components/turkey-pixel-map";
import { import {
PixelCorner, PixelCorner,
PixelDivider, PixelDivider,
@@ -188,17 +187,6 @@ const paketOzellikleri = [
}, },
] as const; ] as const;
function ComparisonCell({ value }: { value: boolean | string }) {
if (typeof value === "string") {
return <span className="text-sm font-medium">{value}</span>;
}
return value ? (
<CheckCircle2 className="mx-auto size-5 text-primary" aria-label="Var" />
) : (
<X className="mx-auto size-5 text-muted-foreground/50" aria-label="Yok" />
);
}
export default function Home() { export default function Home() {
return ( return (
<div <div

View File

@@ -0,0 +1,14 @@
import { CheckCircle2, X } from "lucide-react";
// Ana sayfadaki karşılaştırma tablosunun hücresi: metin değeri düz yazılır,
// boolean değer Var/Yok ikonuna çevrilir.
export function ComparisonCell({ value }: { value: boolean | string }) {
if (typeof value === "string") {
return <span className="text-sm font-medium">{value}</span>;
}
return value ? (
<CheckCircle2 className="mx-auto size-5 text-primary" aria-label="Var" />
) : (
<X className="mx-auto size-5 text-muted-foreground/50" aria-label="Yok" />
);
}

View File

@@ -0,0 +1,158 @@
import { Parallax } from "@/components/parallax";
import { Skeleton } from "@/components/ui/skeleton";
import { meraklisinaDemoVerisi } from "../pazarlama-queries";
import {
DemoKapanisCta,
DemoKumanda,
DilimSeridiCanli,
SiralamaDemo,
} from "./meraklisina-demo";
import { HuniSemasi } from "./huni-semasi";
/**
* Algoritmanın öğrenci diline çevrilmiş anlatımı. Teknik detay (SQL, çarpan
* mutfağı) bilerek verilmez; amaç güven: veri gerçek, kurallar şeffaf.
* Dilim şeridi canlıdır: kullanıcının kayıtlı tercih profilindeki sıralama
* okunur, şerit o sıralamanın gerçek sayılarıyla güncellenir (bkz.
* meraklisina-demo.tsx); profil yoksa örnek sıralama gösterilir. Sihirbaz
* hunisi ise statik bir mermaid şemasıyla anlatılır (bkz. huni-semasi.tsx).
* Diyagramlar ürünün risk renk dilini kullanır (yeşil/sarı/kırmızı) ve her
* bölge metinle de etiketlenir — renk tek başına anlam taşımaz.
*/
// Profili olmayan ziyaretçi bu örnek sıralamayı görür; SSR'da gerçek veriyle
// render edilir ki profil olmadan da sayfa anlamlı olsun.
const VARSAYILAN_SIRA = 100_000;
export function MeraklisinaIcerik() {
const baslangicVeri = meraklisinaDemoVerisi(VARSAYILAN_SIRA);
return (
<SiralamaDemo
baslangicSira={VARSAYILAN_SIRA}
baslangicVeri={baslangicVeri}
>
<Parallax
fromStart
strength={4}
className="mt-8 space-y-10 text-sm leading-7 text-slate-700"
>
<section>
<h2 className="font-heading text-lg font-bold text-slate-900">
1. Her şey taban sıralamasıyla başlar
</h2>
<p className="mt-2">
Bir bölümün <strong>taban sıralaması</strong>, geçen yıl o bölüme
yerleşen <em>son</em>{" "}
öğrencinin Türkiye sıralamasıdır. Senin sıralaman bu sayıdan
küçükse (yani daha iyiysen), geçen yılın koşullarında o bölüme
yerleşebilirdin demektir. Sistemde her programın en güncel taban
sıralaması kayıtlıdır; bir bölümün 2025 verisi henüz oluşmamışsa
bir önceki yılınki kullanılır.
</p>
</section>
<DemoKumanda />
<section>
<h2 className="font-heading text-lg font-bold text-slate-900">
2. Programlar üç dilime ayrılır
</h2>
<p className="mt-2">
Sıralamanı girdiğinde tüm programlar senin konumuna göre üç kümeye
ayrılır: tabanı senden <strong>daha iyi</strong> olanlar{" "}
<span className="font-semibold text-red-600">Hayal</span> (şansını
denediğin satırlar), tabanı sıralamana{" "}
<strong>yakın</strong> olanlar{" "}
<span className="font-semibold text-amber-600">Dengeli</span>{" "}
(listenin bel kemiği sıralamanın yaklaşık yüzde kırk fazlasına
kadar pay bırakılır), tabanı{" "}
<strong>belirgin şekilde altında</strong> kalan her şey ise{" "}
<span className="font-semibold text-emerald-600">Garanti</span>{" "}
dilimidir.
</p>
<DilimSeridiCanli />
<p className="mt-4">
Garanti diliminin bir sonu yok: 87. sıradaki bir adayın da 500
bininci sıradaki bir adayın da ulaşabildiği <em>bütün</em>{" "}
programlar listededir. Liste sana en yakın tabandan başlar; aşağı
indikçe ve &ldquo;Daha fazla göster&rdquo;e bastıkça senden
uzaklaşan seçenekler gelir. Böylece ilk gördüklerin her zaman en
isabetli adaylardır ama hiçbir seçenek senden saklanmaz.
</p>
</section>
<section>
<h2 className="font-heading text-lg font-bold text-slate-900">
3. Risk renkleri her yerde aynı dili konuşur
</h2>
<p className="mt-2">
Tabloda, haritada ve yapay zekâ listesinde gördüğün nokta ve
renkler tek bir kurala bağlıdır:{" "}
<span className="font-semibold text-emerald-600">yeşil</span>{" "}
tabanı sıralamanın belirgin altında (güvenli),{" "}
<span className="font-semibold text-amber-600">sarı</span>{" "}
sıralamana yakın (az riskli),{" "}
<span className="font-semibold text-red-600">kırmızı</span>{" "}
tabanı senden iyi (riskli). Renk hangi sayfada olursa olsun aynı
hesaptan çıkar; bir satır sekme değiştirdi diye renk değiştirmez.
</p>
</section>
<section>
<h2 className="font-heading text-lg font-bold text-slate-900">
4. Sihirbaz süzer, yapay zekâ kurar
</h2>
<p className="mt-2">
&ldquo;Yapay Zeka listemi kur&rdquo; sihirbazındaki üç adım birbirinden
bağımsız değildir. İlk adımda yalnızca{" "}
<strong>sıralamanla ulaşabildiğin</strong>{" "}
alanlar listelenir; ikinci adımdaki iller, seçtiğin alanlardaki
program sayısına göre yeniden hesaplanır; üçüncü adımdaki
devlet/vakıf sayıları da hem alan hem il seçimini hesaba katar.
Adımlar bitince elde kalan gerçek programlar bir{" "}
<strong>aday havuzu</strong>{" "}
olur ve yapay zekâya öyle gider: ona boş bir sayfa değil, bu havuz
verilir. Aşağıdaki şema akışın tamamını gösterir havuz
24&apos;ün altına düşerse filtrelerin nasıl gevşetildiği, yine de
yetmezse listenin eldeki programlarla, sana ıkça belirtilerek
nasıl kurulduğu da dahil.
</p>
<HuniSemasi />
</section>
<section>
<h2 className="font-heading text-lg font-bold text-slate-900">
5. Dürüst olalım: bu bir tahmin aracıdır
</h2>
<p className="mt-2">
Tüm bu hesaplar <strong>geçen yılların</strong>{" "}
yerleştirme sonuçlarına dayanır. Kontenjanlar, tercih davranışları
ve puanlar her yıl değişir; geçen yıl &ldquo;garanti&rdquo;
görünen bir bölüm bu yıl dolabilir. Bu yüzden satırlarda son beş
yılın taban seyrini de gösteririz çizgi yukarı tırmanıyorsa
bölüm zorlaşıyor demektir. KolayTercih karar <em>destek</em>{" "}
aracıdır; listenin son hâli ve sorumluluğu her zaman sana aittir.
</p>
</section>
<DemoKapanisCta />
</Parallax>
</SiralamaDemo>
);
}
export function MeraklisinaIcerikSkeleton() {
return (
<div className="mt-8 space-y-10">
{Array.from({ length: 3 }, (_, i) => (
<div key={i}>
<Skeleton className="h-6 w-72" />
<Skeleton className="mt-3 h-4 w-full" />
<Skeleton className="mt-1.5 h-4 w-full" />
<Skeleton className="mt-1.5 h-4 w-2/3" />
</div>
))}
</div>
);
}

View File

@@ -1,6 +1,6 @@
import { SosyalKanitGovde } from "@/components/landing/sosyal-kanit-govde"; import { SosyalKanitGovde } from "./sosyal-kanit-govde";
import { LISTE_ESIGI, esikGecti } from "@/lib/sosyal-kanit-sabitler"; import { LISTE_ESIGI, esikGecti } from "@/lib/sosyal-kanit-sabitler";
import { sosyalKanitVerisi } from "@/lib/sosyal-kanit"; import { sosyalKanitVerisi } from "../pazarlama-queries";
/** /**
* Fiyat bölümünün üstündeki sosyal kanıt şeridi: kaç öğrenci listesini * Fiyat bölümünün üstündeki sosyal kanıt şeridi: kaç öğrenci listesini

View File

@@ -0,0 +1,22 @@
import "server-only";
import { dilimAra, rankWindowFacets } from "@/lib/db";
import type { DilimKey } from "@/types/yokatlas";
import type { DemoVeri } from "./components/meraklisina-demo";
// Fiyat bölümü üstündeki sosyal kanıt şeridinin okuma kapısı.
export { sosyalKanitVerisi } from "@/lib/sosyal-kanit";
// /meraklisina'nın SSR başlangıç verisi: örnek sıralamanın gerçek dilim
// sayıları ve facetleri (puan türü anlatı gereği hep "say").
export function meraklisinaDemoVerisi(sira: number): DemoVeri {
const dilimToplam = Object.fromEntries(
(["hayal", "dengeli", "garanti"] as DilimKey[]).map((d) => [
d,
dilimAra(sira, "say", d, { limit: 0 }).toplam,
]),
) as Record<DilimKey, number>;
return {
facetler: rankWindowFacets(sira, "say"),
dilimToplam,
};
}