refactor: sihirbaz feature'ı — lib/sihirbaz bölündü, bileşenler taşındı (Faz 6)

- lib/sihirbaz.ts ikiye ayrıldı: sihirbaz-sabitler.ts (şema + doğrulayıcılar +
  event/storage sabitleri + sonucHref/secimOzeti, izomorfik) ve
  sihirbaz-profil.ts (localStorage oku/yaz/sil); 25 tüketicinin importu
  sembol bazında bölünerek güncellendi, localStorage anahtar/event değerleri
  birebir aynı
- sihirbaz-adimlar(+lazy), hero-form, cta-sira-form, il-secim-haritasi ve
  /sonuc'un sihirbaz-modal/sihirbaz-cagri-karti/sira-gerekli bileşenleri
  features/sihirbaz/components/ altına taşındı
- sihirbaz-queries.ts ve async SihirbazBolumu sarmalayıcısı /sonuc sayfa
  dönüşümüyle birlikte Faz 9'da gelecek (o zamana dek ölü kod olurlardı)
- 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:31:32 +03:00
parent baebc1fc80
commit 792e8c7346
36 changed files with 102 additions and 128 deletions

View File

@@ -13,7 +13,7 @@ import { sohbetAkisi } from "@/lib/ai/cagri";
import { listeOzetiCikar } from "@/lib/ai/rapor"; import { listeOzetiCikar } from "@/lib/ai/rapor";
import type { RaporSonuc } from "@/features/rapor/types/rapor"; import type { RaporSonuc } from "@/features/rapor/types/rapor";
import type { RaporParams } from "@/features/rapor/types/rapor"; import type { RaporParams } from "@/features/rapor/types/rapor";
import { secimOzeti } from "@/lib/sihirbaz"; import { secimOzeti } from "@/features/sihirbaz/sihirbaz-sabitler";
import { PUAN_TURLERI } from "@/types/yokatlas"; import { PUAN_TURLERI } from "@/types/yokatlas";
import { ACIK_SATIR } from "@/lib/rapor-maske"; import { ACIK_SATIR } from "@/lib/rapor-maske";

View File

@@ -13,12 +13,8 @@ import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import { listeOlustur } from "@/app/sonuc/actions"; import { listeOlustur } from "@/app/sonuc/actions";
import { olay, siraKovasi } from "@/lib/analitik"; import { olay, siraKovasi } from "@/lib/analitik";
import { import { sonucHref, type TercihProfili } from "@/features/sihirbaz/sihirbaz-sabitler";
sonucHref, import { tercihProfiliOku, tercihProfiliSil } from "@/features/sihirbaz/sihirbaz-profil";
tercihProfiliOku,
tercihProfiliSil,
type TercihProfili,
} from "@/lib/sihirbaz";
const URETIM_MESAJLARI = [ const URETIM_MESAJLARI = [
"Sıralamana uygun programlar taranıyor…", "Sıralamana uygun programlar taranıyor…",

View File

@@ -5,7 +5,7 @@ import { ArrowRight } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { PagePixelDivider } from "@/components/pixel-decor"; import { PagePixelDivider } from "@/components/pixel-decor";
import { useTercihProfili } from "@/components/manuel-liste/profil-kapisi-store"; import { useTercihProfili } from "@/components/manuel-liste/profil-kapisi-store";
import { sonucHref } from "@/lib/sihirbaz"; import { sonucHref } from "@/features/sihirbaz/sihirbaz-sabitler";
/** /**
* /listem boş hâlinin metni + CTA'sı: sıralamasını zaten girmiş adaya * /listem boş hâlinin metni + CTA'sı: sıralamasını zaten girmiş adaya

View File

@@ -4,7 +4,7 @@ import Link from "next/link";
import { ArrowRight } from "lucide-react"; import { ArrowRight } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { useTercihProfili } from "@/components/manuel-liste/profil-kapisi-store"; import { useTercihProfili } from "@/components/manuel-liste/profil-kapisi-store";
import { sonucHref } from "@/lib/sihirbaz"; import { sonucHref } from "@/features/sihirbaz/sihirbaz-sabitler";
/** /**
* Ödeme başarılı ama henüz Yapay Zeka listesi yokken gösterilen CTA: kayıtlı tercih * Ödeme başarılı ama henüz Yapay Zeka listesi yokken gösterilen CTA: kayıtlı tercih

View File

@@ -18,7 +18,7 @@ import { Suspense } from "react";
import { ComparisonCell } from "@/features/pazarlama/components/landing-parcalari"; import { ComparisonCell } from "@/features/pazarlama/components/landing-parcalari";
import { HeroBaslik } from "@/features/pazarlama/components/hero-baslik"; import { HeroBaslik } from "@/features/pazarlama/components/hero-baslik";
import { KapanisCta } from "@/features/pazarlama/components/hero-focus-button"; import { KapanisCta } from "@/features/pazarlama/components/hero-focus-button";
import { HeroForm } from "@/components/hero-form"; import { HeroForm } from "@/features/sihirbaz/components/hero-form";
import { Parallax } from "@/components/parallax"; import { Parallax } from "@/components/parallax";
import { Reveal } from "@/features/pazarlama/components/reveal"; import { Reveal } from "@/features/pazarlama/components/reveal";
import { SosyalKanitBandi } from "@/features/pazarlama/components/sosyal-kanit"; import { SosyalKanitBandi } from "@/features/pazarlama/components/sosyal-kanit";

View File

@@ -1,7 +1,7 @@
import { Suspense } from "react"; import { Suspense } from "react";
import type { Metadata } from "next"; import type { Metadata } from "next";
import { JsonLd, breadcrumbJsonLd } from "@/lib/seo"; import { JsonLd, breadcrumbJsonLd } from "@/lib/seo";
import { CtaSiraForm } from "@/components/cta-sira-form"; import { CtaSiraForm } from "@/features/sihirbaz/components/cta-sira-form";
import { SiteFooter } from "@/components/site-footer"; import { SiteFooter } from "@/components/site-footer";
import { PagePixelDivider } from "@/components/pixel-decor"; import { PagePixelDivider } from "@/components/pixel-decor";
import { import {

View File

@@ -21,7 +21,7 @@ import type {
RaporParams, RaporParams,
RaporSonuc, RaporSonuc,
} from "@/features/rapor/types/rapor"; } from "@/features/rapor/types/rapor";
import { sihirbazDogrula, type SihirbazSecimleri } from "@/lib/sihirbaz"; import { sihirbazDogrula, type SihirbazSecimleri } from "@/features/sihirbaz/sihirbaz-sabitler";
import { raporMaskele } from "@/lib/rapor-maske"; import { raporMaskele } from "@/lib/rapor-maske";

View File

@@ -4,12 +4,12 @@ import { PUAN_TURLERI, type PuanTuruKey } from "@/types/yokatlas";
import { getSession } from "@/lib/session"; import { getSession } from "@/lib/session";
import { kullanicininRaporu } from "@/lib/rapor-kaydi"; import { kullanicininRaporu } from "@/lib/rapor-kaydi";
import { tadimlikSec } from "@/lib/tadimlik-havuzu"; import { tadimlikSec } from "@/lib/tadimlik-havuzu";
import { SihirbazBolumu } from "./sihirbaz-cagri-karti"; import { SihirbazBolumu } from "@/features/sihirbaz/components/sihirbaz-cagri-karti";
import { TadimlikSatiri } from "./tadimlik-satiri"; import { TadimlikSatiri } from "./tadimlik-satiri";
import { ProgramTablosu } from "@/components/program-tablosu"; import { ProgramTablosu } from "@/components/program-tablosu";
import { ManuelHarita } from "@/components/manuel-liste/manuel-harita"; import { ManuelHarita } from "@/components/manuel-liste/manuel-harita";
import { SiteFooter } from "@/components/site-footer"; import { SiteFooter } from "@/components/site-footer";
import { SiraGerekli } from "./sira-gerekli"; import { SiraGerekli } from "@/features/sihirbaz/components/sira-gerekli";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Tercih Listeni Kur", title: "Tercih Listeni Kur",

View File

@@ -25,11 +25,8 @@ import { useGorunumOlayi } from "@/components/use-gorunum-olayi";
import { olay, siraKovasi } from "@/lib/analitik"; import { olay, siraKovasi } from "@/lib/analitik";
import { dilimdenRisk, riskHesapla } from "@/lib/risk"; import { dilimdenRisk, riskHesapla } from "@/lib/risk";
import { turkishSlugify } from "@/lib/slug"; import { turkishSlugify } from "@/lib/slug";
import { import { PROFIL_DEGISTI_EVENT, sonucHref } from "@/features/sihirbaz/sihirbaz-sabitler";
PROFIL_DEGISTI_EVENT, import { tercihProfiliOku } from "@/features/sihirbaz/sihirbaz-profil";
sonucHref,
tercihProfiliOku,
} from "@/lib/sihirbaz";
import type { TadimlikSatir } from "@/lib/tadimlik-havuzu"; import type { TadimlikSatir } from "@/lib/tadimlik-havuzu";
const GENEL = "genel"; const GENEL = "genel";

View File

@@ -10,7 +10,7 @@ import {
} from "lucide-react"; } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { TypingAnimation } from "@/components/ui/typing-animation"; import { TypingAnimation } from "@/components/ui/typing-animation";
import { SIHIRBAZ_AC_EVENT, sonucHref } from "@/lib/sihirbaz"; import { SIHIRBAZ_AC_EVENT, sonucHref } from "@/features/sihirbaz/sihirbaz-sabitler";
import { import {
profilToplamaAc, profilToplamaAc,
useTercihProfili, useTercihProfili,

View File

@@ -12,7 +12,7 @@ import { useRouter } from "next/navigation";
import { Wrench, X } from "lucide-react"; import { Wrench, X } from "lucide-react";
import { toast } from "sonner"; import { toast } from "sonner";
import { authClient } from "@/lib/auth-client"; import { authClient } from "@/lib/auth-client";
import { tercihProfiliSil } from "@/lib/sihirbaz"; import { tercihProfiliSil } from "@/features/sihirbaz/sihirbaz-profil";
import { import {
devAnindaGiris, devAnindaGiris,
devAyarla, devAyarla,

View File

@@ -13,7 +13,7 @@
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { getSession } from "@/lib/session"; import { getSession } from "@/lib/session";
import { appDb, schema } from "@/lib/appdb"; import { appDb, schema } from "@/lib/appdb";
import { tercihProfiliDogrula, type TercihProfili } from "@/lib/sihirbaz"; import { tercihProfiliDogrula, type TercihProfili } from "@/features/sihirbaz/sihirbaz-sabitler";
import { import {
MANUEL_LISTE_MAX, MANUEL_LISTE_MAX,
dogrula, dogrula,

View File

@@ -11,11 +11,8 @@
// - Sonrasında: liste/profil değişimleri ~2 sn debounce ile sunucuya yazılır. // - Sonrasında: liste/profil değişimleri ~2 sn debounce ile sunucuya yazılır.
import { useEffect, useRef } from "react"; import { useEffect, useRef } from "react";
import { import { PROFIL_DEGISTI_EVENT } from "@/features/sihirbaz/sihirbaz-sabitler";
PROFIL_DEGISTI_EVENT, import { tercihProfiliOku, tercihProfiliYaz } from "@/features/sihirbaz/sihirbaz-profil";
tercihProfiliOku,
tercihProfiliYaz,
} from "@/lib/sihirbaz";
import { listeOku, sunucuylaBirlestir, useManuelListe } from "./store"; import { listeOku, sunucuylaBirlestir, useManuelListe } from "./store";
import { oturumDurumuBildir } from "./oturum-sinyali"; import { oturumDurumuBildir } from "./oturum-sinyali";
import { listeSenkronla, listeyiKaydet } from "./kayitli-liste-actions"; import { listeSenkronla, listeyiKaydet } from "./kayitli-liste-actions";

View File

@@ -5,13 +5,8 @@
import { useSyncExternalStore } from "react"; import { useSyncExternalStore } from "react";
import type { Program } from "@/types/yokatlas"; import type { Program } from "@/types/yokatlas";
import { import { PROFIL_DEGISTI_EVENT, sonucHref, type TercihProfili } from "@/features/sihirbaz/sihirbaz-sabitler";
PROFIL_DEGISTI_EVENT, import { tercihProfiliOku, tercihProfiliTamamlandiMi } from "@/features/sihirbaz/sihirbaz-profil";
sonucHref,
tercihProfiliOku,
tercihProfiliTamamlandiMi,
type TercihProfili,
} from "@/lib/sihirbaz";
import { import {
ekle, ekle,
listedeMi, listedeMi,

View File

@@ -13,7 +13,7 @@ import {
} from "lucide-react"; } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { RISK_ETIKET, type RiskSeviyesi } from "@/lib/risk"; import { RISK_ETIKET, type RiskSeviyesi } from "@/lib/risk";
import { sonucHref } from "@/lib/sihirbaz"; import { sonucHref } from "@/features/sihirbaz/sihirbaz-sabitler";
import { import {
tercihDegerlendir, tercihDegerlendir,
tercihListesiOzeti, tercihListesiOzeti,

View File

@@ -8,10 +8,8 @@
import { useSyncExternalStore } from "react"; import { useSyncExternalStore } from "react";
import type { Program } from "@/types/yokatlas"; import type { Program } from "@/types/yokatlas";
import { riskHesapla } from "@/lib/risk"; import { riskHesapla } from "@/lib/risk";
import { import { type TercihProfili } from "@/features/sihirbaz/sihirbaz-sabitler";
tercihProfiliOku, import { tercihProfiliOku } from "@/features/sihirbaz/sihirbaz-profil";
type TercihProfili,
} from "@/lib/sihirbaz";
import { import {
MANUEL_LISTE_MAX, MANUEL_LISTE_MAX,
dogrula, dogrula,

View File

@@ -25,14 +25,11 @@ import {
import { import {
SihirbazAdimlarLazy, SihirbazAdimlarLazy,
preloadSihirbazAdimlar, preloadSihirbazAdimlar,
} from "@/components/sihirbaz-adimlar-lazy"; } from "@/features/sihirbaz/components/sihirbaz-adimlar-lazy";
import type { SihirbazFacetleri } from "@/types/yokatlas"; import type { SihirbazFacetleri } from "@/types/yokatlas";
import { olay, siraKovasi } from "@/lib/analitik"; import { olay, siraKovasi } from "@/lib/analitik";
import { import { type SihirbazSecimleri, type TercihProfili } from "@/features/sihirbaz/sihirbaz-sabitler";
tercihProfiliYaz, import { tercihProfiliYaz } from "@/features/sihirbaz/sihirbaz-profil";
type SihirbazSecimleri,
type TercihProfili,
} from "@/lib/sihirbaz";
import { authClient } from "@/lib/auth-client"; import { authClient } from "@/lib/auth-client";
import { import {
profilKapisiniKapat, profilKapisiniKapat,

View File

@@ -1,7 +1,7 @@
import Link from "next/link"; import Link from "next/link";
import { getAllBolumler, type BolumOzet } from "../katalog-queries"; import { getAllBolumler, type BolumOzet } from "../katalog-queries";
import { KATEGORILER } from "@/lib/kategoriler"; import { KATEGORILER } from "@/lib/kategoriler";
import { CtaSiraForm } from "@/components/cta-sira-form"; import { CtaSiraForm } from "@/features/sihirbaz/components/cta-sira-form";
import { PagePixelDivider } from "@/components/pixel-decor"; import { PagePixelDivider } from "@/components/pixel-decor";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";

View File

@@ -13,7 +13,7 @@ import {
sonucaGitIste, sonucaGitIste,
useTercihProfili, useTercihProfili,
} from "@/components/manuel-liste/profil-kapisi-store"; } from "@/components/manuel-liste/profil-kapisi-store";
import { PUAN_TURU_ETIKET } from "@/lib/sihirbaz"; import { PUAN_TURU_ETIKET } from "@/features/sihirbaz/sihirbaz-sabitler";
import { olay } from "@/lib/analitik"; import { olay } from "@/lib/analitik";
import { import {
ArrowRight, ArrowRight,

View File

@@ -10,7 +10,7 @@ import {
} from "../katalog-queries"; } from "../katalog-queries";
import { trBaslikDuzeni } from "@/lib/slug"; import { trBaslikDuzeni } from "@/lib/slug";
import { JsonLd, breadcrumbJsonLd, SITE_URL } from "@/lib/seo"; import { JsonLd, breadcrumbJsonLd, SITE_URL } from "@/lib/seo";
import { CtaSiraForm } from "@/components/cta-sira-form"; import { CtaSiraForm } from "@/features/sihirbaz/components/cta-sira-form";
import { SiteFooter } from "@/components/site-footer"; import { SiteFooter } from "@/components/site-footer";
import { Sayfalama, SAYFA_BOYU } from "./sayfalama"; import { Sayfalama, SAYFA_BOYU } from "./sayfalama";
import { PagePixelDivider } from "@/components/pixel-decor"; import { PagePixelDivider } from "@/components/pixel-decor";

View File

@@ -1,7 +1,7 @@
import Link from "next/link"; import Link from "next/link";
import { getAllUniversiteler, type UniOzet } from "../katalog-queries"; import { getAllUniversiteler, type UniOzet } from "../katalog-queries";
import { trBaslikDuzeni } from "@/lib/slug"; import { trBaslikDuzeni } from "@/lib/slug";
import { CtaSiraForm } from "@/components/cta-sira-form"; import { CtaSiraForm } from "@/features/sihirbaz/components/cta-sira-form";
import { PagePixelDivider } from "@/components/pixel-decor"; import { PagePixelDivider } from "@/components/pixel-decor";
import { UniLogo } from "@/components/uni-logo"; import { UniLogo } from "@/components/uni-logo";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";

View File

@@ -4,7 +4,7 @@ import Link from "next/link";
import { ArrowRight } from "lucide-react"; import { ArrowRight } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { useTercihProfili } from "@/components/manuel-liste/profil-kapisi-store"; import { useTercihProfili } from "@/components/manuel-liste/profil-kapisi-store";
import { sonucHref } from "@/lib/sihirbaz"; import { sonucHref } from "@/features/sihirbaz/sihirbaz-sabitler";
export function HeroFocusButton() { export function HeroFocusButton() {
function handleClick() { function handleClick() {

View File

@@ -17,7 +17,7 @@ import {
import Link from "next/link"; import Link from "next/link";
import { ArrowRight } from "lucide-react"; import { ArrowRight } from "lucide-react";
import { useTercihProfili } from "@/components/manuel-liste/profil-kapisi-store"; import { useTercihProfili } from "@/components/manuel-liste/profil-kapisi-store";
import { PUAN_TURU_ETIKET, sonucHref } from "@/lib/sihirbaz"; import { PUAN_TURU_ETIKET, sonucHref } from "@/features/sihirbaz/sihirbaz-sabitler";
import type { DilimKey, SihirbazFacetleri } from "@/types/yokatlas"; import type { DilimKey, SihirbazFacetleri } from "@/types/yokatlas";
export type DemoVeri = { export type DemoVeri = {

View File

@@ -3,7 +3,7 @@ import Link from "next/link";
import { notFound } from "next/navigation"; import { notFound } from "next/navigation";
import { getAllRehberler, getAllRehberSlugs, getRehber } from "../rehber-queries"; import { getAllRehberler, getAllRehberSlugs, getRehber } from "../rehber-queries";
import { JsonLd, articleJsonLd, breadcrumbJsonLd } from "@/lib/seo"; import { JsonLd, articleJsonLd, breadcrumbJsonLd } from "@/lib/seo";
import { CtaSiraForm } from "@/components/cta-sira-form"; import { CtaSiraForm } from "@/features/sihirbaz/components/cta-sira-form";
import { ElCizimiSema } from "./el-cizimi-sema"; import { ElCizimiSema } from "./el-cizimi-sema";
import { RehberKapak } from "./rehber-kapak"; import { RehberKapak } from "./rehber-kapak";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";

View File

@@ -24,16 +24,13 @@ import { SectionEyebrow } from "@/components/pixel-decor";
import { import {
SihirbazAdimlarLazy, SihirbazAdimlarLazy,
preloadSihirbazAdimlar, preloadSihirbazAdimlar,
} from "@/components/sihirbaz-adimlar-lazy"; } from "./sihirbaz-adimlar-lazy";
import { authClient } from "@/lib/auth-client"; import { authClient } from "@/lib/auth-client";
import { olay, siraKovasi } from "@/lib/analitik"; import { olay, siraKovasi } from "@/lib/analitik";
import { useTercihProfili } from "@/components/manuel-liste/profil-kapisi-store"; import { useTercihProfili } from "@/components/manuel-liste/profil-kapisi-store";
import type { SihirbazFacetleri } from "@/types/yokatlas"; import type { SihirbazFacetleri } from "@/types/yokatlas";
import { import { sonucHref, type SihirbazSecimleri } from "@/features/sihirbaz/sihirbaz-sabitler";
sonucHref, import { tercihProfiliYaz } from "@/features/sihirbaz/sihirbaz-profil";
tercihProfiliYaz,
type SihirbazSecimleri,
} from "@/lib/sihirbaz";
// lib/db sunucu tarafı; etiketler client bundle'a sızmasın diye burada. // lib/db sunucu tarafı; etiketler client bundle'a sızmasın diye burada.
const PUAN_TURLERI_SECENEK = [ const PUAN_TURLERI_SECENEK = [

View File

@@ -15,7 +15,7 @@ import {
import { import {
SihirbazAdimlarLazy, SihirbazAdimlarLazy,
preloadSihirbazAdimlar, preloadSihirbazAdimlar,
} from "@/components/sihirbaz-adimlar-lazy"; } from "./sihirbaz-adimlar-lazy";
import { authClient } from "@/lib/auth-client"; import { authClient } from "@/lib/auth-client";
import { olay, siraKovasi } from "@/lib/analitik"; import { olay, siraKovasi } from "@/lib/analitik";
import { import {
@@ -23,12 +23,8 @@ import {
useTercihProfili, useTercihProfili,
} from "@/components/manuel-liste/profil-kapisi-store"; } from "@/components/manuel-liste/profil-kapisi-store";
import type { SihirbazFacetleri } from "@/types/yokatlas"; import type { SihirbazFacetleri } from "@/types/yokatlas";
import { import { PUAN_TURU_ETIKET, sonucHref, type SihirbazSecimleri } from "@/features/sihirbaz/sihirbaz-sabitler";
PUAN_TURU_ETIKET, import { tercihProfiliYaz } from "@/features/sihirbaz/sihirbaz-profil";
sonucHref,
tercihProfiliYaz,
type SihirbazSecimleri,
} from "@/lib/sihirbaz";
// lib/db sunucu tarafı; etiketler client bundle'a sızmasın diye burada. // lib/db sunucu tarafı; etiketler client bundle'a sızmasın diye burada.
const PUAN_TURLERI_SECENEK = [ const PUAN_TURLERI_SECENEK = [

View File

@@ -45,7 +45,7 @@ function SihirbazAdimlarSkeleton() {
export const SihirbazAdimlarLazy = dynamic( export const SihirbazAdimlarLazy = dynamic(
() => () =>
import("@/components/sihirbaz-adimlar").then((m) => m.SihirbazAdimlar), import("./sihirbaz-adimlar").then((m) => m.SihirbazAdimlar),
{ {
ssr: false, ssr: false,
loading: () => <SihirbazAdimlarSkeleton />, loading: () => <SihirbazAdimlarSkeleton />,
@@ -54,5 +54,5 @@ export const SihirbazAdimlarLazy = dynamic(
/** Kullanıcı forma dokunduğu anda chunk'ı arka planda indir. */ /** Kullanıcı forma dokunduğu anda chunk'ı arka planda indir. */
export function preloadSihirbazAdimlar() { export function preloadSihirbazAdimlar() {
void import("@/components/sihirbaz-adimlar"); void import("./sihirbaz-adimlar");
} }

View File

@@ -15,17 +15,12 @@ import { toast } from "sonner";
import { cities } from "turkey-map-react/lib/data"; import { cities } from "turkey-map-react/lib/data";
import { TransitionPanel } from "@/components/core/transition-panel"; import { TransitionPanel } from "@/components/core/transition-panel";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { IlSecimHaritasi } from "@/components/il-secim-haritasi"; import { IlSecimHaritasi } from "./il-secim-haritasi";
import { normalizeIlAdi } from "@/lib/harita"; import { normalizeIlAdi } from "@/lib/harita";
import { olay } from "@/lib/analitik"; import { olay } from "@/lib/analitik";
import { trBaslikDuzeni } from "@/lib/slug"; import { trBaslikDuzeni } from "@/lib/slug";
import type { SihirbazFacetleri } from "@/types/yokatlas"; import type { SihirbazFacetleri } from "@/types/yokatlas";
import { import { ONCELIKLER, UNIVERSITE_TIPI_ETIKET, type SihirbazSecimleri, type UniversiteTipi } from "@/features/sihirbaz/sihirbaz-sabitler";
ONCELIKLER,
UNIVERSITE_TIPI_ETIKET,
type SihirbazSecimleri,
type UniversiteTipi,
} from "@/lib/sihirbaz";
export function Cip({ export function Cip({
secili, secili,

View File

@@ -11,13 +11,8 @@ import { PixelField } from "@/components/pixel-decor";
import { useGorunumOlayi } from "@/components/use-gorunum-olayi"; import { useGorunumOlayi } from "@/components/use-gorunum-olayi";
import { olay } from "@/lib/analitik"; import { olay } from "@/lib/analitik";
import type { SihirbazFacetleri } from "@/types/yokatlas"; import type { SihirbazFacetleri } from "@/types/yokatlas";
import { import { SIHIRBAZ_AC_EVENT, SIHIRBAZ_STORAGE_KEY, sihirbazDogrula, type SihirbazSecimleri } from "@/features/sihirbaz/sihirbaz-sabitler";
SIHIRBAZ_AC_EVENT, import { tercihProfiliYaz } from "@/features/sihirbaz/sihirbaz-profil";
SIHIRBAZ_STORAGE_KEY,
sihirbazDogrula,
tercihProfiliYaz,
type SihirbazSecimleri,
} from "@/lib/sihirbaz";
import { SihirbazModal } from "./sihirbaz-modal"; import { SihirbazModal } from "./sihirbaz-modal";
// Üretim /listem'de koşar (bkz. listem/liste-uretici.tsx); sihirbaz // Üretim /listem'de koşar (bkz. listem/liste-uretici.tsx); sihirbaz

View File

@@ -6,9 +6,9 @@ import {
DialogDescription, DialogDescription,
DialogTitle, DialogTitle,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { SihirbazAdimlarLazy } from "@/components/sihirbaz-adimlar-lazy"; import { SihirbazAdimlarLazy } from "./sihirbaz-adimlar-lazy";
import type { SihirbazFacetleri } from "@/types/yokatlas"; import type { SihirbazFacetleri } from "@/types/yokatlas";
import type { SihirbazSecimleri } from "@/lib/sihirbaz"; import type { SihirbazSecimleri } from "@/features/sihirbaz/sihirbaz-sabitler";
/** /**
* Sihirbaz modalı artık yalnızca adımları toplar; üretim, önizleme ve liste * Sihirbaz modalı artık yalnızca adımları toplar; üretim, önizleme ve liste

View File

@@ -9,7 +9,7 @@ import Link from "next/link";
import { ArrowLeft, Trophy } from "lucide-react"; import { ArrowLeft, Trophy } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { PagePixelDivider } from "@/components/pixel-decor"; import { PagePixelDivider } from "@/components/pixel-decor";
import { sonucHref } from "@/lib/sihirbaz"; import { sonucHref } from "@/features/sihirbaz/sihirbaz-sabitler";
import { import {
sonucaGitIste, sonucaGitIste,
useProfilKapisi, useProfilKapisi,

View File

@@ -0,0 +1,49 @@
// Ortak tercih profilinin localStorage katmanı — yalnızca client'ta anlamlı.
// Şema, doğrulama ve sabitler sihirbaz-sabitler.ts'te yaşar.
import {
PROFIL_DEGISTI_EVENT,
SIHIRBAZ_STORAGE_KEY,
tercihProfiliDogrula,
type TercihProfili,
} from "./sihirbaz-sabitler";
function profilDegistiginiYayinla(): void {
window.dispatchEvent(new Event(PROFIL_DEGISTI_EVENT));
}
/** Client'ta SIHIRBAZ_STORAGE_KEY'den doğrulanmış profil okur. */
export function tercihProfiliOku(): TercihProfili | null {
if (typeof window === "undefined") return null;
try {
const ham = localStorage.getItem(SIHIRBAZ_STORAGE_KEY);
if (!ham) return null;
return tercihProfiliDogrula(JSON.parse(ham));
} catch {
return null;
}
}
/** Ortak profili yazar; hero ve Yapay Zeka sihirbazıyla aynı anahtarı kullanır. */
export function tercihProfiliYaz(profil: TercihProfili): void {
if (typeof window === "undefined") return;
const dogru = tercihProfiliDogrula(profil);
if (!dogru) return;
try {
localStorage.setItem(SIHIRBAZ_STORAGE_KEY, JSON.stringify(dogru));
} catch {}
profilDegistiginiYayinla();
}
/** Profili siler (ör. Yapay Zeka listesi üretilip seçimler tüketildiğinde). */
export function tercihProfiliSil(): void {
if (typeof window === "undefined") return;
try {
localStorage.removeItem(SIHIRBAZ_STORAGE_KEY);
} catch {}
profilDegistiginiYayinla();
}
export function tercihProfiliTamamlandiMi(): boolean {
return tercihProfiliOku() !== null;
}

View File

@@ -1,8 +1,10 @@
// Sonuç sayfasındaki sihirbaz modalının seçim şeması, doğrulaması ve prompt özeti. // Sihirbazın seçim şeması, doğrulaması ve prompt özeti — izomorfik katman:
// hem client bileşenleri hem server action'ları/AI motoru buradan okur.
// localStorage'a dokunan profil yardımcıları sihirbaz-profil.ts'te yaşar.
// Kategoriler/iller sıralamaya göre dinamik üretilir (bkz. rankWindowFacets); // Kategoriler/iller sıralamaya göre dinamik üretilir (bkz. rankWindowFacets);
// öncelikler statik kalır (veriye bağlı değil, tercih niyeti). // öncelikler statik kalır (veriye bağlı değil, tercih niyeti).
import { KATEGORILER } from "./kategoriler"; import { KATEGORILER } from "@/lib/kategoriler";
import type { UniturGrubu } from "@/types/yokatlas"; import type { UniturGrubu } from "@/types/yokatlas";
export const ONCELIKLER = [ export const ONCELIKLER = [
@@ -43,10 +45,6 @@ export const PROFIL_DEGISTI_EVENT = "kolaytercih:profil-degisti";
// orkestratörünü (SihirbazBolumu) bu olayla açar. // orkestratörünü (SihirbazBolumu) bu olayla açar.
export const SIHIRBAZ_AC_EVENT = "kolaytercih:sihirbaz-ac"; export const SIHIRBAZ_AC_EVENT = "kolaytercih:sihirbaz-ac";
function profilDegistiginiYayinla(): void {
window.dispatchEvent(new Event(PROFIL_DEGISTI_EVENT));
}
export interface SihirbazSecimleri { export interface SihirbazSecimleri {
kategoriler: string[]; kategoriler: string[];
iller: string[]; iller: string[];
@@ -128,42 +126,6 @@ export function tercihProfiliDogrula(girdi: unknown): TercihProfili | null {
return { sira, tur: p.tur, secimler }; return { sira, tur: p.tur, secimler };
} }
/** Client'ta SIHIRBAZ_STORAGE_KEY'den doğrulanmış profil okur. */
export function tercihProfiliOku(): TercihProfili | null {
if (typeof window === "undefined") return null;
try {
const ham = localStorage.getItem(SIHIRBAZ_STORAGE_KEY);
if (!ham) return null;
return tercihProfiliDogrula(JSON.parse(ham));
} catch {
return null;
}
}
/** Ortak profili yazar; hero ve Yapay Zeka sihirbazıyla aynı anahtarı kullanır. */
export function tercihProfiliYaz(profil: TercihProfili): void {
if (typeof window === "undefined") return;
const dogru = tercihProfiliDogrula(profil);
if (!dogru) return;
try {
localStorage.setItem(SIHIRBAZ_STORAGE_KEY, JSON.stringify(dogru));
} catch {}
profilDegistiginiYayinla();
}
/** Profili siler (ör. Yapay Zeka listesi üretilip seçimler tüketildiğinde). */
export function tercihProfiliSil(): void {
if (typeof window === "undefined") return;
try {
localStorage.removeItem(SIHIRBAZ_STORAGE_KEY);
} catch {}
profilDegistiginiYayinla();
}
export function tercihProfiliTamamlandiMi(): boolean {
return tercihProfiliOku() !== null;
}
/** Profildeki sıra/tur ile sonuç sayfası URL'i — tüm uygulama aynı sorguyu kullanır. */ /** Profildeki sıra/tur ile sonuç sayfası URL'i — tüm uygulama aynı sorguyu kullanır. */
export function sonucHref( export function sonucHref(
profil: Pick<TercihProfili, "sira" | "tur">, profil: Pick<TercihProfili, "sira" | "tur">,

View File

@@ -17,7 +17,7 @@ import {
type Dilim, type Dilim,
type AdayProgram, type AdayProgram,
} from "../rapor-havuzu"; } from "../rapor-havuzu";
import { secimOzeti } from "../sihirbaz"; import { secimOzeti } from "@/features/sihirbaz/sihirbaz-sabitler";
import { RISK_ETIKET, dilimdenRisk, riskHesapla } from "../risk"; import { RISK_ETIKET, dilimdenRisk, riskHesapla } from "../risk";
// Yapay zekâdan istenen küçük şema (kullanıcı kararı, 6 Ağu 2026): riskNotu // Yapay zekâdan istenen küçük şema (kullanıcı kararı, 6 Ağu 2026): riskNotu

View File

@@ -1,6 +1,6 @@
import { kategoriEslesir } from "./kategoriler"; import { kategoriEslesir } from "./kategoriler";
import { riskHesapla, type RiskSeviyesi } from "./risk"; import { riskHesapla, type RiskSeviyesi } from "./risk";
import type { TercihProfili } from "./sihirbaz"; import type { TercihProfili } from "@/features/sihirbaz/sihirbaz-sabitler";
export type DegerlendirilecekProgram = { export type DegerlendirilecekProgram = {
isim: string; isim: string;