"use client"; // /meraklisina'nın canlı anlatım katmanı: kullanıcının kayıtlı tercih // profilindeki sıralama + puan türü okunur, dilim şeridi o sıralamanın GERÇEK // sayılarıyla güncellenir. Profil yoksa sayfa SSR'daki örnek sıralamayla kalır. // Provider sayfadaki metin bölümlerini (RSC children) sarar; görseller // context'ten okur. (Sihirbaz hunisi statik bir şemayla anlatılır — bkz. // huni-semasi.tsx.) import { createContext, useContext, useEffect, useState, type ReactNode, } from "react"; import Link from "next/link"; import { ArrowRight } from "lucide-react"; import { useTercihProfili } from "@/features/liste/hooks/use-tercih-profili"; import { PUAN_TURU_ETIKET, sonucHref } from "@/features/sihirbaz/sihirbaz-sabitler"; import type { DilimKey, SihirbazFacetleri } from "@/types/yokatlas"; import { onbellekliJsonGetir } from "@/lib/istek-cache"; export type DemoVeri = { facetler: SihirbazFacetleri; dilimToplam: Record; }; type DemoDurum = { sira: number; tur: string; veri: DemoVeri; yukleniyor: boolean; profilVar: boolean; }; const DemoContext = createContext(null); function useDemo(): DemoDurum { const ctx = useContext(DemoContext); if (!ctx) throw new Error("Demo bileşenleri SiralamaDemo içinde kullanılmalı"); return ctx; } async function facetGetir( sira: number, tur: string, signal: AbortSignal, ): Promise<{ facetler: SihirbazFacetleri; dilimToplam?: Record } | null> { const params = new URLSearchParams({ sira: String(sira), tur, dilimler: "1" }); try { // Demo slider'ı aynı sıraya dönünce cache'ten okur (dedup+TTL) return await onbellekliJsonGetir<{ facetler: SihirbazFacetleri; dilimToplam?: Record; }>(`/api/facetler?${params}`, { signal }); } catch { return null; } } export function SiralamaDemo({ baslangicSira, baslangicVeri, children, }: { baslangicSira: number; baslangicVeri: DemoVeri; children: ReactNode; }) { const profil = useTercihProfili(); const sira = profil?.sira ?? baslangicSira; const tur = profil?.tur ?? "say"; const [veri, setVeri] = useState(baslangicVeri); const [yukleniyor, setYukleniyor] = useState(false); // Profil yüklendi ve SSR örneğinden farklı → ana veriyi tazele useEffect(() => { if (sira === baslangicSira && tur === "say") return; const ctrl = new AbortController(); // eslint-disable-next-line react-hooks/set-state-in-effect -- fetch başlangıç işareti setYukleniyor(true); facetGetir(sira, tur, ctrl.signal) .then((cevap) => { if (!cevap?.dilimToplam) return; setVeri({ facetler: cevap.facetler, dilimToplam: cevap.dilimToplam }); }) .finally(() => setYukleniyor(false)); return () => ctrl.abort(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [sira, tur]); const durum: DemoDurum = { sira, tur, veri, yukleniyor, profilVar: profil !== null, }; return {children}; } /** Görsellerin hangi sıralamayla hesaplandığını söyleyen bilgi kartı. */ export function DemoKumanda() { const { sira, tur, yukleniyor, profilVar } = useDemo(); const turEtiket = PUAN_TURU_ETIKET[tur] ?? tur; return (

{profilVar ? "Görseller senin sıralamana göre hesaplandı" : "Görseller örnek bir sıralamayla gösteriliyor"}

{yukleniyor ? ( "Hesaplanıyor…" ) : ( <> {sira.toLocaleString("tr-TR")}. {" "} sıra · {turEtiket} — aşağıdaki tüm sayılar bu aday için gerçek YÖK Atlas verisidir. {!profilVar && " Ana sayfadan kendi sıralamanı girersen bu sayfa sana göre güncellenir."} )}

); } /** Sıralama ekseni: adayın sırasına göre dilim sınırları ve gerçek adetler. */ export function DilimSeridiCanli() { const { sira, veri, yukleniyor } = useDemo(); const t = veri.dilimToplam; const dengeliUst = Math.round(sira * 1.4); const fmt = (n: number) => n.toLocaleString("tr-TR"); return (
{/* eksen */} 1. sıra (en iyi) taban sıralaması büyüdükçe → {/* hayal */} Hayal {fmt(t.hayal)} program tabanı senden iyi {/* aday işareti */} SEN · {fmt(sira)}. {/* dengeli */} Dengeli {fmt(t.dengeli)} program {fmt(sira)}. – {fmt(dengeliUst)}. arası taban {/* garanti */} Garanti {fmt(t.garanti)} program {fmt(dengeliUst + 1)}. sonrası — sonu yok, sayfaladıkça uzar
Liste her dilimde{" "} sana en yakın tabandan uzağa doğru {" "} sıralanır; “Daha fazla göster” dedikçe uzaktakiler gelir.
); } /** * Sayfanın kapanış kartı: profili olmayan ziyaretçiyi ana sayfadaki sıralama * formuna, sıralamasını zaten girmiş adayı ise doğrudan sonuç sayfasına * gönderir — "sıralamanı gir" CTA'sı profil varken gösterilmez. */ export function DemoKapanisCta() { const profil = useTercihProfili(); return (

{profil ? "Kuralları öğrendin — sayılar zaten senin sıralamanla hesaplandı." : "Kuralları öğrendin — şimdi kendi sıralamanla dene."}

{profil ? "Sıralamana uygun programları gör" : "Sıralamanı gir"}
); }