(null);
- const veriAnahtari = `${adaySira}-${tur}`;
+ const veriAnahtari = `${adaySira}-${tur}-${iller.join(",")}-${filtreTip ?? ""}`;
const [oncekiAnahtar, setOncekiAnahtar] = useState(veriAnahtari);
if (veriAnahtari !== oncekiAnahtar) {
setOncekiAnahtar(veriAnahtari);
@@ -129,9 +154,15 @@ export function ProgramTablosu({
async function dahaFazlaYukle(dilim: DilimKey, offset: number) {
setYuklenen(dilim);
try {
- const res = await fetch(
- `/api/programlar?sira=${adaySira}&tur=${tur}&dilim=${dilim}&offset=${offset}`,
- );
+ const q = new URLSearchParams({
+ sira: String(adaySira),
+ tur,
+ dilim,
+ offset: String(offset),
+ });
+ for (const il of iller) q.append("il", il);
+ if (filtreTip) q.set("tip", filtreTip);
+ const res = await fetch(`/api/programlar?${q}`);
if (!res.ok) return;
const veri = (await res.json()) as { programlar: ProgramListeSatiri[] };
// Aynı sayfanın iki kez istenmesine karşı id bazında tekilleştir
@@ -162,6 +193,39 @@ export function ProgramTablosu({
onPointerEnter={preloadTercihHaritasi}
onFocusCapture={preloadTercihHaritasi}
>
+ {/* Sihirbaz seçimlerinden gelen aktif filtreler — görünür ve tek tek
+ kaldırılabilir; sayılar neden azaldı sorusunu burada yanıtlar. */}
+ {iller.length > 0 || filtreTip ? (
+
+
+ Filtreler:
+
+ {filtreTip ? (
+
+ ) : null}
+ {iller.map((il) => (
+
+ ))}
+
+ ) : null}
+
setAktifDilim(v as DilimKey)}
diff --git a/src/features/liste/components/sonuc-program-tablosu.tsx b/src/features/liste/components/sonuc-program-tablosu.tsx
index dae1317..b34ca89 100644
--- a/src/features/liste/components/sonuc-program-tablosu.tsx
+++ b/src/features/liste/components/sonuc-program-tablosu.tsx
@@ -1,19 +1,31 @@
import { siraylaProgramAra } from "../liste-queries";
import { ProgramTablosu } from "./program-tablosu";
import { Skeleton } from "@/components/ui/skeleton";
-import type { PuanTuruKey } from "@/types/yokatlas";
+import type { PuanTuruKey, UniturGrubu } from "@/types/yokatlas";
// /sonuc'un ham tablosunun sunucu sarmalayıcısı: okuma burada yaşar, sayfa
// yalnızca kompoze eder.
export function SonucProgramTablosu({
sira,
tur,
+ iller,
+ uniturGrubu,
}: {
sira: number;
tur: PuanTuruKey;
+ iller?: string[];
+ uniturGrubu?: UniturGrubu;
}) {
- const sonuclar = siraylaProgramAra(sira, tur);
- return ;
+ const sonuclar = siraylaProgramAra(sira, tur, { iller, uniturGrubu });
+ return (
+
+ );
}
export function SonucProgramTablosuSkeleton() {
diff --git a/src/features/liste/liste-queries.ts b/src/features/liste/liste-queries.ts
index 597344b..569f366 100644
--- a/src/features/liste/liste-queries.ts
+++ b/src/features/liste/liste-queries.ts
@@ -5,6 +5,7 @@ import type {
ProgramListeSatiri,
PuanTuruKey,
RankResultsListe,
+ UniturGrubu,
} from "@/types/yokatlas";
// Tabloda kullanılmayan alanlar (fakulte, puan2025) client'a serileşmesin.
@@ -29,13 +30,22 @@ export function programOzetle(p: Program): ProgramListeSatiri {
};
}
-// /sonuc'un ham tablosu: yalnızca sıralamayla ulaşılabilen programlar,
-// hayal/dengeli/garanti dilimli, dilim başına ilk 20 satır.
+// /sonuc'un ham tablosu: sıralamayla ulaşılabilen programlar,
+// hayal/dengeli/garanti dilimli, dilim başına ilk 20 satır. Sihirbaz
+// seçimlerinden il + üniversite tipi URL üzerinden buraya taşınır ve SQL'de
+// filtrelenir; kategori bilinçli olarak uygulanmaz (DB'de kategori kolonu
+// yok, JS filtresi offset/toplam semantiğini bozar — kategori AI listesi ve
+// tadımlıkta uygulanır).
export function siraylaProgramAra(
sira: number,
tur: PuanTuruKey,
+ opts: { iller?: string[]; uniturGrubu?: UniturGrubu } = {},
): RankResultsListe {
- const ham = searchByRank(sira, tur, { limitPerBucket: 20 });
+ const ham = searchByRank(sira, tur, {
+ limitPerBucket: 20,
+ iller: opts.iller,
+ uniturGrubu: opts.uniturGrubu,
+ });
return {
hayal: ham.hayal.map(programOzetle),
dengeli: ham.dengeli.map(programOzetle),
diff --git a/src/features/sihirbaz/sihirbaz-sabitler.ts b/src/features/sihirbaz/sihirbaz-sabitler.ts
index 1e6a948..f923335 100644
--- a/src/features/sihirbaz/sihirbaz-sabitler.ts
+++ b/src/features/sihirbaz/sihirbaz-sabitler.ts
@@ -126,16 +126,29 @@ export function tercihProfiliDogrula(girdi: unknown): TercihProfili | null {
return { sira, tur: p.tur, secimler };
}
-/** 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. Profilde sihirbaz seçimleri varsa il + üniversite tipi de URL'e
+ * yazılır: /sonuc'un ham tablosu SSR'da bu paramlarla filtrelenir (tek
+ * doğruluk kaynağı URL; localStorage profili yalnızca URL'i üretir).
+ */
export function sonucHref(
- profil: Pick,
+ profil: Pick & {
+ secimler?: SihirbazSecimleri;
+ },
ekstra?: Record,
): string {
const q = new URLSearchParams({
sira: String(profil.sira),
tur: profil.tur,
- ...ekstra,
});
+ if (profil.secimler) {
+ for (const il of profil.secimler.iller) q.append("il", il);
+ if (profil.secimler.universiteTipi !== "farketmez") {
+ q.set("tip", profil.secimler.universiteTipi);
+ }
+ }
+ for (const [k, v] of Object.entries(ekstra ?? {})) q.set(k, v);
return `/sonuc?${q}`;
}