From 5853b7d0915ad7c5a0a1cfa6beeb03aabfc0bb7d Mon Sep 17 00:00:00 2001 From: bilalgursen Date: Mon, 21 Sep 2026 16:03:22 +0300 Subject: [PATCH 1/2] =?UTF-8?q?feat(etiket):=20g=C3=B6r=C3=BCnen=20"Garant?= =?UTF-8?q?i"=20dilim=20ad=C4=B1=20site=20genelinde=20"G=C3=BCvenli"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yalnız kullanıcıya görünen etiket değişir; iç anahtar, tip, DB değeri, API parametresi, mermaid classDef ve analitik değeri `garanti` olarak kalır (veri göçü yok). - risk.ts: tek kaynak DILIM_ETIKET + dilimdenFarkliRiskEtiketi; rapor listesi, yazdır tablosu, /sonuc sekmeleri, seçimlerim paneli ve meraklısına şeridi buradan okur - "Güvenli · Güvenli" / "Güvenli (Güvenli)": satır detayında risk etiketi yalnız dilimin varsayılanından farklıysa, yazdır ve seçimlerimde yalnız kelime farklıysa yazılır - LLM prompt'ları: `garanti` teknik anahtar, adaya "güvenli" denir sözlüğü (rapor, soru, tadımlık); liste özeti modele görünen dilim adıyla gider - meraklısına şeması (SEMA düğümü, aria-label), 2. bölüm anlatımı ve AGENTS.md şema kuralı görünen adla eşitlendi - "yerleşme garantisi vermez" türü vaat reddi cümleleri aynen kaldı Co-Authored-By: Claude Fable 5.1 --- AGENTS.md | 2 +- scripts/tadimlik-uret.ts | 2 ++ src/app/api/soru/route.ts | 3 +++ src/app/page.tsx | 4 +-- .../liste/components/program-tablosu.tsx | 8 +++--- .../liste/components/secimlerim-paneli.tsx | 15 +++++++---- .../pazarlama/components/huni-semasi.tsx | 6 +++-- .../pazarlama/components/meraklisina-demo.tsx | 9 ++++--- .../components/meraklisina-icerik.tsx | 6 ++--- .../rapor/components/rapor-listesi.tsx | 17 +++++++------ .../rapor/components/rapor-yazdir.tsx | 19 ++++++++------ .../rapor/components/revizyon-kutusu.tsx | 2 +- .../sihirbaz/components/cta-sira-form.tsx | 6 ++--- .../components/sihirbaz-cagri-karti.tsx | 2 +- src/lib/ai/rapor.ts | 17 ++++++++++--- src/lib/risk.ts | 25 +++++++++++++++++++ src/lib/tercih-degerlendirme.ts | 11 ++++---- 17 files changed, 103 insertions(+), 51 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index c203da0..e5dcc88 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,5 +25,5 @@ Funnel CTA butonlarında ("Listemi oluştur", "Tercihlerimi belirle", giriş/öd # Meraklısına'daki mermaid şeması mimariyle senkron kalmalı -`/meraklisina` sayfasındaki sihirbaz akış şeması (`src/features/pazarlama/components/huni-semasi.tsx` içindeki `SEMA` sabiti) ürünün gerçek davranışının belgesidir, dekor değildir. Sihirbaz/listeleme mimarisinde davranış değiştiren her değişiklikte bu şema da aynı PR/commit içinde güncellenmeli: sihirbaz adımlarının sayısı-sırası-içeriği (alan → il → devlet/vakıf), aday havuzu kuralları, 24'lük liste iskeleti (hayal/dengeli/garanti dağılımı), havuz 24'ün altına düşünce filtre gevşetme sırası ve yapay zekânın havuz-dışına-çıkamama kuralı. Şemayı güncellerken çevresindeki unsurları da eşitle: bölümdeki anlatım metni (`src/features/pazarlama/components/meraklisina-icerik.tsx`, 4. bölüm), kabın `aria-label`'ı ve figcaption. Şema öğrenci diliyle kalmalı (SQL/prompt/teknik detay yok) ve ürünün risk renk dilini korumalı — kırmızı/sarı/yeşil her zaman metin etiketiyle birlikte, renk tek başına anlam taşımaz. +`/meraklisina` sayfasındaki sihirbaz akış şeması (`src/features/pazarlama/components/huni-semasi.tsx` içindeki `SEMA` sabiti) ürünün gerçek davranışının belgesidir, dekor değildir. Sihirbaz/listeleme mimarisinde davranış değiştiren her değişiklikte bu şema da aynı PR/commit içinde güncellenmeli: sihirbaz adımlarının sayısı-sırası-içeriği (alan → il → devlet/vakıf), aday havuzu kuralları, 24'lük liste iskeleti (hayal/dengeli/güvenli dağılımı — üçüncü dilimin kullanıcıya görünen adı "Güvenli"dir; iç anahtar, tip, DB değeri, mermaid `classDef` ve analitik değeri `garanti` olarak kalır, görünen etiketin tek kaynağı `src/lib/risk.ts` içindeki `DILIM_ETIKET`), havuz 24'ün altına düşünce filtre gevşetme sırası ve yapay zekânın havuz-dışına-çıkamama kuralı. Şemayı güncellerken çevresindeki unsurları da eşitle: bölümdeki anlatım metni (`src/features/pazarlama/components/meraklisina-icerik.tsx`, 4. bölüm), kabın `aria-label`'ı ve figcaption. Şema öğrenci diliyle kalmalı (SQL/prompt/teknik detay yok) ve ürünün risk renk dilini korumalı — kırmızı/sarı/yeşil her zaman metin etiketiyle birlikte, renk tek başına anlam taşımaz. diff --git a/scripts/tadimlik-uret.ts b/scripts/tadimlik-uret.ts index 4e2c351..697c6dd 100644 --- a/scripts/tadimlik-uret.ts +++ b/scripts/tadimlik-uret.ts @@ -70,6 +70,8 @@ KURALLAR (kesin): - riskNotu: geçmiş taban verisine dayalı risk değerlendirmesi (TEK kısa cümle). ASLA garanti/kesin/yüzde/olasılık/ihtimal deme; "güvenli / az riskli / riskli" etiketleriyle konuş. +- Programın "dilim" alanındaki "garanti" değeri teknik anahtardır; adaya dönük + hiçbir metinde bu kelimeyi kullanma, o dilimi "güvenli" diye an. - trendOzeti: son 5 yılın taban sıralaması hareketi, TEK cümle (ör. "2022'den beri taban 45B'den 38B'ye indi, bölüm zorlaşıyor"). - Adayın sıralaması yaklaşıktır; kesin sıra telaffuz etme, banda göre konuş.`; diff --git a/src/app/api/soru/route.ts b/src/app/api/soru/route.ts index 01c0cfc..6d86900 100644 --- a/src/app/api/soru/route.ts +++ b/src/app/api/soru/route.ts @@ -41,6 +41,9 @@ iş imkânları, tercih sırası) net ve dürüst yanıtlamak. KURALLAR: - Cevaplarını adayın 24'lük listesi ve seçimleri bağlamında ver; listedeki programlara referans verebilirsin. +- Dilimlerin adı Hayal, Dengeli ve Güvenli'dir. Üçüncü dilime her zaman + "Güvenli" de; "garanti dilimi", "garanti tercih" gibi ifadeler KULLANMA + (aday ya da eski mesajlar böyle dese bile sen "güvenli" diye düzelt). - Listedeki her satırda dilim ve risk etiketi var: Güvenli (yeşil) = taban sıralaması adayın belirgin altında, Az riskli (sarı) = adayın sıralaması civarında, Riskli (kırmızı) = geçen yıl adayın sıralamasının üzerinde diff --git a/src/app/page.tsx b/src/app/page.tsx index d2e9544..8a3a48a 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -112,7 +112,7 @@ const steps = [ step: "3", title: "Dengeli 24'lük listeni al", description: - "Hayal, dengeli ve garanti dilimlerine dağıtılmış, her satırı gerekçeli tercih listeni indir; aklına takılanı listen üzerinden yapay zekâya sor.", + "Hayal, dengeli ve güvenli dilimlerine dağıtılmış, her satırı gerekçeli tercih listeni indir; aklına takılanı listen üzerinden yapay zekâya sor.", }, ]; @@ -129,7 +129,7 @@ const faqs = [ { question: "Yerleşme garantisi veriyor musunuz?", answer: - "Hayır — ve verdiğini iddia eden herkesten uzak dur. Taban sıralamaları her yıl adayların davranışına göre değişir; kimse garanti veremez. Biz riski şeffaf gösterir, listeyi hayal/dengeli/garanti dilimleriyle kurarak boşta kalma ihtimalini en aza indiririz. Tercih listenin son hali ve ÖSYM başvurusu her zaman senin sorumluluğundadır.", + "Hayır — ve verdiğini iddia eden herkesten uzak dur. Taban sıralamaları her yıl adayların davranışına göre değişir; kimse garanti veremez. Biz riski şeffaf gösterir, listeyi hayal/dengeli/güvenli dilimleriyle kurarak boşta kalma ihtimalini en aza indiririz. Tercih listenin son hali ve ÖSYM başvurusu her zaman senin sorumluluğundadır.", }, { question: "Fiyatlandırma nasıl çalışıyor?", diff --git a/src/features/liste/components/program-tablosu.tsx b/src/features/liste/components/program-tablosu.tsx index 5f35ec2..e71c009 100644 --- a/src/features/liste/components/program-tablosu.tsx +++ b/src/features/liste/components/program-tablosu.tsx @@ -20,7 +20,7 @@ import type { PuanTuruKey, RankResultsListe, } from "@/types/yokatlas"; -import { riskHesapla, type RiskSeviyesi } from "@/lib/risk"; +import { DILIM_ETIKET, riskHesapla, type RiskSeviyesi } from "@/lib/risk"; import { bolumSayfaSlug, uniSayfaSlug } from "@/lib/slug"; import { ProgramSiraGecmisi, @@ -51,21 +51,21 @@ const DILIMLER: { }[] = [ { key: "hayal", - etiket: "Hayal", + etiket: DILIM_ETIKET.hayal, icon: Rocket, renk: "text-red-500", renkAktif: "text-red-400", }, { key: "dengeli", - etiket: "Dengeli", + etiket: DILIM_ETIKET.dengeli, icon: Scale, renk: "text-amber-500", renkAktif: "text-amber-400", }, { key: "garanti", - etiket: "Garanti", + etiket: DILIM_ETIKET.garanti, icon: ShieldCheck, renk: "text-emerald-600", renkAktif: "text-emerald-400", diff --git a/src/features/liste/components/secimlerim-paneli.tsx b/src/features/liste/components/secimlerim-paneli.tsx index 1cc08c8..d49d218 100644 --- a/src/features/liste/components/secimlerim-paneli.tsx +++ b/src/features/liste/components/secimlerim-paneli.tsx @@ -13,7 +13,7 @@ import { X, } from "lucide-react"; import { Button } from "@/components/ui/button"; -import { RISK_ETIKET, type RiskSeviyesi } from "@/lib/risk"; +import { DILIM_ETIKET, RISK_ETIKET, type RiskSeviyesi } from "@/lib/risk"; import { sonucHref } from "@/features/sihirbaz/sihirbaz-sabitler"; import { tercihDegerlendir, @@ -156,9 +156,12 @@ export function SecimlerimPaneli() { {ozet ? (
- - - + + +
) : null} @@ -272,7 +275,9 @@ const SecimSatiri = memo(function SecimSatiri({ /> ) : null} {degerlendirme.riskEtiketi} - {risk ? ( + {/* Dilim adı ile risk etiketi aynı kelimeyse ("Güvenli") + parantez yazılmaz — "Güvenli (Güvenli)" olmasın. */} + {risk && RISK_ETIKET[risk] !== degerlendirme.riskEtiketi ? ( ({RISK_ETIKET[risk]}) diff --git a/src/features/pazarlama/components/huni-semasi.tsx b/src/features/pazarlama/components/huni-semasi.tsx index 85557c5..2224b19 100644 --- a/src/features/pazarlama/components/huni-semasi.tsx +++ b/src/features/pazarlama/components/huni-semasi.tsx @@ -6,6 +6,8 @@ import { ElCizimiSema } from "@/features/rehber/components/el-cizimi-sema"; // Renkler ürünün risk dilinden (kırmızı/sarı/yeşil) ve slate paletinden; // renk tek başına anlam taşımaz, her düğüm metinle etiketlidir. +// Üçüncü dilimin görünen adı "güvenli"dir; `classDef garanti` yalnızca iç +// renk sınıfıdır (render edilmez), iç anahtarla aynı kalır. const SEMA = `--- config: look: handDrawn @@ -25,7 +27,7 @@ flowchart TD R --> L("En fazla 24 tercihlik liste") L --> L1("üstte hayal — hedef 5, havuz elverdiğince") L --> L2("ortada dengeli — hedef 13, havuz elverdiğince") - L --> L3("sonda garanti — hedef 6, havuz elverdiğince") + L --> L3("sonda güvenli — hedef 6, havuz elverdiğince") classDef havuz fill:#eff6ff,stroke:#3b82f6,color:#1e3a8a classDef uyari fill:#fffbeb,stroke:#f59e0b,color:#92400e @@ -42,7 +44,7 @@ export function HuniSemasi() { return ( Her adım havuzu biraz daha daraltır; yapay zekâ listeyi bu havuzun{" "} diff --git a/src/features/pazarlama/components/meraklisina-demo.tsx b/src/features/pazarlama/components/meraklisina-demo.tsx index 03a9476..d34ff55 100644 --- a/src/features/pazarlama/components/meraklisina-demo.tsx +++ b/src/features/pazarlama/components/meraklisina-demo.tsx @@ -20,6 +20,7 @@ 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"; +import { DILIM_ETIKET } from "@/lib/risk"; export type DemoVeri = { facetler: SihirbazFacetleri; @@ -146,7 +147,7 @@ export function DilimSeridiCanli() { {/* eksen */} @@ -174,7 +175,7 @@ export function DilimSeridiCanli() { {/* hayal */} - Hayal + {DILIM_ETIKET.hayal} {fmt(t.hayal)} program @@ -192,7 +193,7 @@ export function DilimSeridiCanli() { {/* dengeli */} - Dengeli + {DILIM_ETIKET.dengeli} {fmt(t.dengeli)} program @@ -204,7 +205,7 @@ export function DilimSeridiCanli() { {/* garanti */} - Garanti + {DILIM_ETIKET.garanti} {fmt(t.garanti)} program diff --git a/src/features/pazarlama/components/meraklisina-icerik.tsx b/src/features/pazarlama/components/meraklisina-icerik.tsx index eecd75c..12815f5 100644 --- a/src/features/pazarlama/components/meraklisina-icerik.tsx +++ b/src/features/pazarlama/components/meraklisina-icerik.tsx @@ -68,12 +68,12 @@ export function MeraklisinaIcerik() { (listenin bel kemiği — sıralamanın yaklaşık yüzde kırk fazlasına kadar pay bırakılır), tabanı{" "} belirgin şekilde altında kalan her şey ise{" "} - Garanti{" "} + Güvenli{" "} dilimidir.

- Garanti diliminin bir sonu yok: 87. sıradaki bir adayın da 500 + Güvenli diliminin bir sonu yok: 87. sıradaki bir adayın da 500 bininci sıradaki bir adayın da ulaşabildiği bütün{" "} programlar listededir. Liste sana en yakın tabandan başlar; aşağı indikçe ve “Daha fazla göster”e bastıkça senden @@ -131,7 +131,7 @@ export function MeraklisinaIcerik() {

Tüm bu hesaplar geçen yılların{" "} yerleştirme sonuçlarına dayanır. Kontenjanlar, tercih davranışları - ve puanlar her yıl değişir; geçen yıl “garanti” + ve puanlar her yıl değişir; geçen yıl “güvenli” görünen bir bölüm bu yıl dolabilir. Bu yüzden satırlarda son beş yılın taban seyrini de gösteririz — çizgi yukarı tırmanıyorsa bölüm zorlaşıyor demektir. KolayTercih karar destek{" "} diff --git a/src/features/rapor/components/rapor-listesi.tsx b/src/features/rapor/components/rapor-listesi.tsx index 52ca845..b8af439 100644 --- a/src/features/rapor/components/rapor-listesi.tsx +++ b/src/features/rapor/components/rapor-listesi.tsx @@ -29,17 +29,14 @@ import { import { bolumSayfaSlug, uniSayfaSlug } from "@/lib/slug"; import type { RaporSonuc } from "@/features/rapor/types/rapor"; import { + DILIM_ETIKET, RISK_ETIKET, + dilimdenFarkliRiskEtiketi, dilimdenRisk, riskHesapla, type RiskSeviyesi, } from "@/lib/risk"; - -export const DILIM_ETIKET: Record = { - hayal: "Hayal", - dengeli: "Dengeli", - garanti: "Garanti", -}; +import type { Dilim } from "@/lib/rapor-havuzu"; // Risk renk dili: yeşil = güvenli, sarı = az riskli, kırmızı = riskli. // Nokta hiçbir yerde tek başına durmaz; yanındaki etiket dar ekranda sr-only @@ -75,12 +72,16 @@ export function RaporSatirDetayi({ trendOzeti: string; }) { const stil = RISK_STIL[risk]; + // Risk etiketi yalnızca dilimin varsayılanından farklıysa yazılır; yoksa + // üçüncü dilimde başlık "Güvenli · Güvenli" olurdu (bkz. risk.ts). + const farkliRisk = dilimdenFarkliRiskEtiketi(dilim, risk); return ( <>

- {DILIM_ETIKET[dilim]} · {RISK_ETIKET[risk]} + {DILIM_ETIKET[dilim as Dilim] ?? dilim} + {farkliRisk ? ` · ${farkliRisk}` : null} {unitur ? · {unitur} : null}
@@ -345,7 +346,7 @@ export function RaporListesi({

Tercihlerine göre {rapor.kapsam.toplam} uygun program bulundu; listen{" "} {rapor.kapsam.dagilim.hayal} hayal · {rapor.kapsam.dagilim.dengeli}{" "} - dengeli · {rapor.kapsam.dagilim.garanti} garanti olarak kuruldu. Daha + dengeli · {rapor.kapsam.dagilim.garanti} güvenli olarak kuruldu. Daha fazla seçenek için alan veya il filtreni genişletebilirsin.

) : null} diff --git a/src/features/rapor/components/rapor-yazdir.tsx b/src/features/rapor/components/rapor-yazdir.tsx index 18b93ea..20cf054 100644 --- a/src/features/rapor/components/rapor-yazdir.tsx +++ b/src/features/rapor/components/rapor-yazdir.tsx @@ -2,16 +2,19 @@ import Image from "next/image"; import { redirect } from "next/navigation"; import { verifySession, getCurrentUser } from "@/lib/session"; import { kullanicininRaporu } from "../rapor-queries"; -import { PUAN_TURLERI } from "@/types/yokatlas"; +import { PUAN_TURLERI, type DilimKey } from "@/types/yokatlas"; +import { DILIM_ETIKET, RISK_ETIKET, dilimdenRisk } from "@/lib/risk"; import type { RaporParams, RaporSonuc } from "../types/rapor"; import { Skeleton } from "@/components/ui/skeleton"; import { YazdirButonu } from "./yazdir-butonu"; -const DILIM_LABEL: Record = { - hayal: "Hayal (Riskli)", - dengeli: "Dengeli (Az riskli)", - garanti: "Garanti (Güvenli)", -}; +// Dilim sütunu: dilim adı + varsayılan riski. Üçüncü dilimde ikisi aynı +// kelime ("Güvenli") olduğu için parantez düşer — "Güvenli (Güvenli)" yazmaz. +function dilimLabel(dilim: DilimKey): string { + const ad = DILIM_ETIKET[dilim] ?? dilim; + const risk = RISK_ETIKET[dilimdenRisk(dilim)]; + return ad === risk ? ad : `${ad} (${risk})`; +} export async function RaporYazdir() { const session = await verifySession("/rapor/yazdir"); @@ -50,7 +53,7 @@ export async function RaporYazdir() { Not: Tercihlerine göre {rapor.kapsam.toplam} uygun program bulundu; liste {rapor.kapsam.dagilim.hayal} hayal ·{" "} {rapor.kapsam.dagilim.dengeli} dengeli ·{" "} - {rapor.kapsam.dagilim.garanti} garanti olarak kuruldu. + {rapor.kapsam.dagilim.garanti} güvenli olarak kuruldu.

) : null} @@ -91,7 +94,7 @@ export async function RaporYazdir() { {p?.universite} · {p?.il ?? "—"} - {DILIM_LABEL[t.dilim]} + {dilimLabel(t.dilim)} {t.gerekce} {t.riskNotu} {t.trendOzeti} diff --git a/src/features/rapor/components/revizyon-kutusu.tsx b/src/features/rapor/components/revizyon-kutusu.tsx index ba1a554..adfe0fc 100644 --- a/src/features/rapor/components/revizyon-kutusu.tsx +++ b/src/features/rapor/components/revizyon-kutusu.tsx @@ -76,7 +76,7 @@ export function RevizyonKutusu({ kalanHak }: { kalanHak: number }) { onChange={(e) => setFeedback(e.target.value)} rows={2} maxLength={1000} - placeholder="ör. İlk 5 tercihte daha fazla İstanbul olsun, garanti dilimini genişlet…" + placeholder="ör. İlk 5 tercihte daha fazla İstanbul olsun, güvenli dilimi genişlet…" disabled={pending} className="w-full rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm shadow-xs outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" /> diff --git a/src/features/sihirbaz/components/cta-sira-form.tsx b/src/features/sihirbaz/components/cta-sira-form.tsx index 8b3be95..26bb9ec 100644 --- a/src/features/sihirbaz/components/cta-sira-form.tsx +++ b/src/features/sihirbaz/components/cta-sira-form.tsx @@ -150,7 +150,7 @@ export function CtaSiraForm({ baslik }: { baslik?: string }) {

Sıralaman kayıtlı ({profil.sira.toLocaleString("tr-TR")}. sıra) — - gerçek YÖK Atlas verisiyle hayal, dengeli ve garanti dilimlerindeki + gerçek YÖK Atlas verisiyle hayal, dengeli ve güvenli dilimlerindeki programların hazır.

YKS başarı sıralamanı gir; gerçek YÖK Atlas verisiyle sıralamana uygun - hayal, dengeli ve garanti dilimlerindeki programları anında listele. + hayal, dengeli ve güvenli dilimlerindeki programları anında listele. Ücretsiz, üyelik gerekmez.