feat: tadımlık havuzuna üniversite tipi boyutu
Tadımlık satırı batch üretildiği için sihirbazdaki devlet/vakıf seçimini bilmiyor, vakıf seçen kullanıcıya devlet örneği gösteriyordu. Havuz anahtarı kova×tür×kategori×tip'e genişledi (migration 0001; mevcut satırlar tip='genel'). Üretim scripti tip varyantlarını uniturGrubu filtresiyle seçer; tadimlikSec tip verildiğinde kategori→genel fallback'i korur ama tip fallback'i YAPMAZ — uygun satır yoksa bileşen gizlenir, yanlış tipte örnek asla gösterilmez. Client profildeki tipi de gönderir ve SSR "genel" satırı tipe uymuyorsa fetch bitene kadar gizler. Not: prod app.db volume'de — `pnpm tadimlik` prod DB'ye karşı ayrıca koşulmalı. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -27,10 +27,17 @@ import { dilimdenRisk, riskHesapla } from "@/lib/risk";
|
||||
import { turkishSlugify } from "@/lib/slug";
|
||||
import { PROFIL_DEGISTI_EVENT, sonucHref } from "@/features/sihirbaz/sihirbaz-sabitler";
|
||||
import { tercihProfiliOku } from "@/features/sihirbaz/sihirbaz-profil";
|
||||
import type { TadimlikSatir } from "@/lib/tadimlik-havuzu";
|
||||
import type { TadimlikSatir, TadimlikTip } from "@/lib/tadimlik-havuzu";
|
||||
|
||||
const GENEL = "genel";
|
||||
|
||||
/** Program tipi ile sihirbaz tercihi eşleşiyor mu (uniturFiltreSql semantiği). */
|
||||
function tipeUyar(program: TadimlikSatir["program"], tip: TadimlikTip): boolean {
|
||||
if (tip === "genel") return true;
|
||||
if (tip === "devlet") return program.unitur === "DEVLET";
|
||||
return program.unitur != null && program.unitur !== "DEVLET";
|
||||
}
|
||||
|
||||
export function TadimlikSatiri({
|
||||
sira,
|
||||
tur,
|
||||
@@ -42,29 +49,46 @@ export function TadimlikSatiri({
|
||||
ilk: TadimlikSatir | null;
|
||||
}) {
|
||||
const [satir, setSatir] = useState<TadimlikSatir | null>(ilk);
|
||||
const yuklenenSlug = useRef(GENEL);
|
||||
const yuklenenAnahtar = useRef(`${GENEL}|${GENEL}`);
|
||||
|
||||
// Sihirbaz kategorisi yalnızca localStorage'da yaşar; mount'ta ve profil
|
||||
// değiştikçe okunur, kategoriye özel satır sunucudan çekilir.
|
||||
// Sihirbaz kategorisi ve devlet/vakıf tercihi yalnızca localStorage'da
|
||||
// yaşar; mount'ta ve profil değiştikçe okunur, seçime özel satır sunucudan
|
||||
// çekilir. Tip tercihi varsa yanlış tipte örnek bir an bile gösterilmez.
|
||||
useEffect(() => {
|
||||
const guncelle = () => {
|
||||
const profil = tercihProfiliOku();
|
||||
const kategori = profil?.secimler.kategoriler[0];
|
||||
const slug = kategori ? turkishSlugify(kategori) : GENEL;
|
||||
if (slug === yuklenenSlug.current) return;
|
||||
yuklenenSlug.current = slug;
|
||||
if (slug === GENEL) {
|
||||
const tipTercihi = profil?.secimler.universiteTipi;
|
||||
const tip: TadimlikTip =
|
||||
tipTercihi === "devlet" || tipTercihi === "vakif"
|
||||
? tipTercihi
|
||||
: GENEL;
|
||||
const anahtar = `${slug}|${tip}`;
|
||||
if (anahtar === yuklenenAnahtar.current) return;
|
||||
yuklenenAnahtar.current = anahtar;
|
||||
if (slug === GENEL && tip === GENEL) {
|
||||
setSatir(ilk);
|
||||
return;
|
||||
}
|
||||
fetch(
|
||||
`/api/tadimlik?sira=${sira}&tur=${encodeURIComponent(tur)}&kategori=${encodeURIComponent(slug)}`,
|
||||
)
|
||||
// SSR "genel" satırı seçilen tipe uymuyorsa fetch bitene kadar gizle
|
||||
setSatir((mevcut) =>
|
||||
mevcut && !tipeUyar(mevcut.program, tip) ? null : mevcut,
|
||||
);
|
||||
const q = new URLSearchParams({ sira: String(sira), tur });
|
||||
if (slug !== GENEL) q.set("kategori", slug);
|
||||
if (tip !== GENEL) q.set("tip", tip);
|
||||
fetch(`/api/tadimlik?${q}`)
|
||||
.then((yanit) => (yanit.ok ? yanit.json() : null))
|
||||
.then((veri: { tadimlik: TadimlikSatir | null } | null) => {
|
||||
// Yarış koruması: bu arada başka kategori yüklendiyse dokunma
|
||||
if (yuklenenSlug.current !== slug) return;
|
||||
if (veri?.tadimlik) setSatir(veri.tadimlik);
|
||||
// Yarış koruması: bu arada başka seçim yüklendiyse dokunma
|
||||
if (yuklenenAnahtar.current !== anahtar) return;
|
||||
if (veri?.tadimlik) {
|
||||
setSatir(veri.tadimlik);
|
||||
} else if (tip !== GENEL) {
|
||||
// Uygun tipte satır yok: yanlış tip göstermektense gizle
|
||||
setSatir(null);
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user