feat: update app.db and BACKLOG.md with new decisions and adjustments
All checks were successful
Deploy / deploy (push) Successful in 7m45s
All checks were successful
Deploy / deploy (push) Successful in 7m45s
- Updated the app.db file to reflect recent changes in the application state. - Modified BACKLOG.md to include new entries regarding the removal of certain wizard steps, adjustments to priority chips, and the introduction of special quota conditions for candidates. - Added details on the decision to link priority chips to data sources and clarified the implications for user experience and data handling.
This commit is contained in:
@@ -22,33 +22,42 @@ import { olay } from "@/lib/analitik";
|
||||
import { trBaslikDuzeni } from "@/lib/slug";
|
||||
import type { SihirbazFacetleri } from "@/types/yokatlas";
|
||||
import { ONCELIKLER, UNIVERSITE_TIPI_ETIKET, type SihirbazSecimleri, type UniversiteTipi } from "@/features/sihirbaz/sihirbaz-sabitler";
|
||||
import { OZEL_DURUMLAR, OZEL_DURUM_ETIKET, type OzelDurum } from "@/lib/ozel-durum";
|
||||
|
||||
export function Cip({
|
||||
secili,
|
||||
onClick,
|
||||
children,
|
||||
kucuk = false,
|
||||
ton = "notr",
|
||||
className = "",
|
||||
}: {
|
||||
secili: boolean;
|
||||
onClick: () => void;
|
||||
children: React.ReactNode;
|
||||
kucuk?: boolean;
|
||||
/**
|
||||
* bilgi: özel kontenjan durumu çipi (DESIGN.md §4.21) — pasif hâli bilgi
|
||||
* mavisi tonunda (§2 `primary` rolü), seçili hâli nötr çiple aynı.
|
||||
*/
|
||||
ton?: "notr" | "bilgi";
|
||||
className?: string;
|
||||
}) {
|
||||
// Şişko ve sade (DESIGN.md §1.1): çip 44 px dokunma hedefi; il
|
||||
// çipleri (kucuk) çok sayıda olduğu için 40 px. Hover §2.1 tek turuncu.
|
||||
const boyut = kucuk ? "h-10 px-3.5 text-sm" : "h-11 px-4 text-sm";
|
||||
const temel = `inline-flex cursor-pointer items-center rounded-full border font-semibold transition-[background-color,border-color,color,transform] duration-150 active:scale-[0.97] ${boyut} ${className}`;
|
||||
const pasif =
|
||||
ton === "bilgi"
|
||||
? "border-primary/30 bg-primary/10 text-primary hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500"
|
||||
: "border-slate-200 bg-card text-slate-700 hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500";
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
aria-pressed={secili}
|
||||
className={
|
||||
secili
|
||||
? `${temel} border-primary bg-primary text-white`
|
||||
: `${temel} border-slate-200 bg-card text-slate-700 hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500`
|
||||
secili ? `${temel} border-primary bg-primary text-white` : `${temel} ${pasif}`
|
||||
}
|
||||
>
|
||||
{children}
|
||||
@@ -91,6 +100,10 @@ export function SihirbazAdimlar({
|
||||
const [oncelikler, setOncelikler] = useState<string[]>(
|
||||
baslangicSecimler?.oncelikler ?? [],
|
||||
);
|
||||
// Özel kontenjan durumu: isteğe bağlı, havuzu daraltmaz (lib/ozel-durum.ts)
|
||||
const [ozelDurum, setOzelDurum] = useState<OzelDurum[]>(
|
||||
baslangicSecimler?.ozelDurum ?? [],
|
||||
);
|
||||
|
||||
// Kademeli facet'ler: kategoriler daima ilk yükten gelir; il ve üniversite
|
||||
// tipi sayıları adıma girerken o anki seçimlerle tazelenir. Fetch başarısız
|
||||
@@ -533,8 +546,42 @@ export function SihirbazAdimlar({
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-slate-500">
|
||||
Öncelikler yapay zekânın gerekçelerine ve program seçimine yön
|
||||
verir; listeyi daraltmaz.
|
||||
Listeyi daraltmaz; programların sırasını ve gerekçelerini
|
||||
yönlendirir (istihdam ve kazanç TÜİK 2025, araştırma sırası URAP,
|
||||
kadro YÖK Atlas).
|
||||
</p>
|
||||
</div>
|
||||
{/* Özel kontenjan durumu (DESIGN.md §4.21): düz ayraç, bilgi tonlu
|
||||
çipler. Cinsiyet ya da sağlık sorulmaz; "34 yaş üstü kadın" ÖSYM
|
||||
kontenjan hakkının beyanıdır. Değer analitiğe gitmez. */}
|
||||
<div className="border-t border-slate-100 pt-4">
|
||||
<p className="mb-2 text-sm font-semibold text-slate-700">
|
||||
Özel kontenjan durumun{" "}
|
||||
<span className="font-normal text-slate-500">(isteğe bağlı)</span>
|
||||
</p>
|
||||
<div className="grid grid-cols-2 gap-2 sm:flex sm:flex-wrap">
|
||||
{OZEL_DURUMLAR.map((d) => (
|
||||
<Cip
|
||||
key={d}
|
||||
ton="bilgi"
|
||||
className="h-auto min-h-11 justify-center px-3 py-1.5 text-center leading-tight sm:h-11 sm:px-4 sm:py-0"
|
||||
secili={ozelDurum.includes(d)}
|
||||
onClick={() =>
|
||||
setOzelDurum(
|
||||
ozelDurum.includes(d)
|
||||
? ozelDurum.filter((x) => x !== d)
|
||||
: OZEL_DURUMLAR.filter((x) => x === d || ozelDurum.includes(x)),
|
||||
)
|
||||
}
|
||||
>
|
||||
{OZEL_DURUM_ETIKET[d]}
|
||||
</Cip>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-slate-500">
|
||||
ÖSYM bu durumlar için ayrı kontenjan ayırır. İşaretlersen o
|
||||
kontenjanı olan programlar listende öne çıkar ve danışman bunu
|
||||
bilir. Cinsiyet ya da sağlık bilgisi sorulmaz.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -571,7 +618,8 @@ export function SihirbazAdimlar({
|
||||
uni_tipi: universiteTipi,
|
||||
oncelik_sayisi: oncelikler.length,
|
||||
});
|
||||
onTamamla({ kategoriler, iller, universiteTipi, oncelikler });
|
||||
// ozelDurum olaya YAZILMAZ: profil değeri analitiğe gitmez (gizlilik)
|
||||
onTamamla({ kategoriler, iller, universiteTipi, oncelikler, ozelDurum });
|
||||
}}
|
||||
disabled={kategoriler.length === 0}
|
||||
className="h-11 cursor-pointer bg-orange-500 px-5 text-white transition-[background-color,transform] duration-200 hover:bg-orange-600 active:scale-[0.97]"
|
||||
|
||||
@@ -2,21 +2,33 @@
|
||||
// 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);
|
||||
// öncelikler statik kalır (veriye bağlı değil, tercih niyeti).
|
||||
// öncelikler statik kalır ama her biri bir veriye bağlıdır (lib/uyum-puani.ts).
|
||||
|
||||
import { KATEGORILER } from "@/lib/kategoriler";
|
||||
import { ozelDurumDogrula, ozelDurumOzeti, type OzelDurum } from "@/lib/ozel-durum";
|
||||
import type { UniturGrubu } from "@/types/yokatlas";
|
||||
|
||||
/**
|
||||
* "Senin için önemli olan" çipleri — her biri uyum puanında bir veriye bağlı
|
||||
* (6 Eki 2026 kararı): İş bulma → TÜİK kayıtlı istihdam; Yüksek maaş → TÜİK
|
||||
* kazanç grubu; Akademik kariyer → program kadrosu + URAP; Prestij → URAP;
|
||||
* Kolay yerleşme → liste iskeleti (güvenli dilim payı). "Sevdiğim işi yapmak"
|
||||
* ve "Yurtdışı imkânı" veri bulunana kadar kaldırıldı (BACKLOG); eski
|
||||
* kayıtlardaki değerleri `oncelikNormalize` düşürür.
|
||||
*/
|
||||
export const ONCELIKLER = [
|
||||
"İş bulma kolaylığı",
|
||||
"Yüksek maaş potansiyeli",
|
||||
"Sevdiğim işi yapmak",
|
||||
"Akademik kariyer",
|
||||
"Yurtdışı imkânı",
|
||||
"Prestijli üniversite",
|
||||
"Kolay yerleşme",
|
||||
] as const;
|
||||
|
||||
export type Oncelik = (typeof ONCELIKLER)[number];
|
||||
|
||||
/** Kaldırılan çipler: eski kayıtlarda görülürse sessizce düşer (fark sayılmaz). */
|
||||
const KALKAN_ONCELIKLER: readonly string[] = ["Sevdiğim işi yapmak", "Yurtdışı imkânı"];
|
||||
|
||||
export const UNIVERSITE_TIPI_ETIKET: Record<UniturGrubu | "farketmez", string> = {
|
||||
devlet: "Devlet",
|
||||
vakif: "Vakıf (burslu olursa)",
|
||||
@@ -56,6 +68,11 @@ export interface SihirbazSecimleri {
|
||||
iller: string[];
|
||||
universiteTipi: UniversiteTipi;
|
||||
oncelikler: string[];
|
||||
/**
|
||||
* Özel kontenjan durumu (isteğe bağlı; lib/ozel-durum.ts). Havuzu
|
||||
* daraltmaz, o kontenjanı olan programları öne alır. Eski kayıtlarda yok.
|
||||
*/
|
||||
ozelDurum: OzelDurum[];
|
||||
}
|
||||
|
||||
export interface TercihProfili {
|
||||
@@ -121,16 +138,22 @@ export function sihirbazDogrula(girdi: unknown): SihirbazSecimleri | null {
|
||||
]
|
||||
: [];
|
||||
|
||||
return { kategoriler, iller, universiteTipi, oncelikler };
|
||||
const ozelDurum = ozelDurumDogrula(p.ozelDurum);
|
||||
|
||||
return { kategoriler, iller, universiteTipi, oncelikler, ozelDurum };
|
||||
}
|
||||
|
||||
/**
|
||||
* Eski çip adı "İş garantisi" → "İş bulma kolaylığı". Kayıtlı profil ve eski
|
||||
* rapor parametreleri eski adı taşıyabilir; karşılaştırma/gösterim öncesi
|
||||
* yeni ada eşlenir ki ad değişikliği "tercihlerin değişmiş" diye okunmasın.
|
||||
* Eski çip adı "İş garantisi" → "İş bulma kolaylığı"; kaldırılan çipler
|
||||
* ("Sevdiğim işi yapmak", "Yurtdışı imkânı") → undefined. Kayıtlı profil ve
|
||||
* eski rapor parametreleri eski adı taşıyabilir; karşılaştırma/gösterim
|
||||
* öncesi normalize edilir ki ad değişikliği ya da kalkan çip "tercihlerin
|
||||
* değişmiş" diye okunmasın (tercih-farki.ts).
|
||||
*/
|
||||
export function oncelikNormalize<T>(x: T): T | string {
|
||||
return x === "İş garantisi" ? "İş bulma kolaylığı" : x;
|
||||
export function oncelikNormalize<T>(x: T): T | string | undefined {
|
||||
if (x === "İş garantisi") return "İş bulma kolaylığı";
|
||||
if (typeof x === "string" && KALKAN_ONCELIKLER.includes(x)) return undefined;
|
||||
return x;
|
||||
}
|
||||
|
||||
/** localStorage'taki ortak sıra + sihirbaz profilini güvenle doğrular. */
|
||||
@@ -196,5 +219,8 @@ export function secimOzeti(secimler: SihirbazSecimleri): string {
|
||||
if (secimler.oncelikler.length > 0) {
|
||||
satirlar.push(`- Öncelikleri: ${secimler.oncelikler.join(", ")}`);
|
||||
}
|
||||
if (secimler.ozelDurum.length > 0) {
|
||||
satirlar.push(`- Özel kontenjan durumu: ${ozelDurumOzeti(secimler.ozelDurum)}`);
|
||||
}
|
||||
return satirlar.join("\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user