From e4c06f54d9d9e590894196ecbe99f4272dde7649 Mon Sep 17 00:00:00 2001 From: bilalgursen Date: Wed, 7 Oct 2026 23:26:58 +0300 Subject: [PATCH] =?UTF-8?q?chore(entegrasyon):=20revizyonAcik=20prop'u,=20?= =?UTF-8?q?varyant=20metin=20say=C4=B1lar=C4=B1,=20DESIGN=20notlar=C4=B1,?= =?UTF-8?q?=20worktree=20lint=20ignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beş paket (A sohbet sunucusu, B ilk-N garantisi, C program varyantı, D1 sohbet UI, D2 program ayrıntı) v2'ye alındıktan sonraki dikişler: sohbet-client'ta revizyonHakki sayısı yerine revizyonAcik bayrağı; rapor.ts üst sayı kümesine varyant metni; DESIGN §4.15/§4.20/§4.33 notları; .claude/worktrees lint dışı. Co-Authored-By: Claude Fable 5.1 --- docs/tasarim/DESIGN.md | 10 ++++++++++ eslint.config.mjs | 2 ++ src/features/rapor/components/listem-govde.tsx | 3 +-- src/features/rapor/components/sohbet-client.tsx | 10 +++++----- src/lib/ai/rapor.ts | 4 ++-- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/docs/tasarim/DESIGN.md b/docs/tasarim/DESIGN.md index b3e4df4..b8be510 100644 --- a/docs/tasarim/DESIGN.md +++ b/docs/tasarim/DESIGN.md @@ -485,6 +485,10 @@ elle yazılmaz. Başka yerde tekrarlanmaz — SectionEyebrow kuralının tek ist Sınıf dizileri tek dosyada (`SATIR_AD`, `SATIR_META`, `SATIR_CIP`, `SATIR_MOBIL_SAYI`, `SATIR_BUTON_KABI`…); üniversite, bölüm ve `/sonuc` tabloları oradan okur. Yeni bir liste tablosu bu sabitleri kullanır, sınıfı elle yazmaz. +- **Varyant çipi** (7 Eki 2026): burs / öğretim dili / öğretim türü etiketi (`Program.varyant`, + `src/lib/program-varyant.ts`, ör. "Burslu · İngilizce", "%50 İndirimli", "Açık Öğretim") tür + çipinin hemen ardından `SATIR_CIP` ile; null ise çizilmez. Aynı üniversite + aynı bölüm adı + taşıyan kayıtlar (Başkent Tıp ×6 gibi) ancak bu çiple ayırt edilir; tekilleştirme yapılmaz. - Risk sütunu (`/sonuc`) sm'den itibaren ayrı sütun; telefonda adın altındaki sayı satırına iner. Etiket §4.5: `size-2` nokta + `text-xs font-semibold text-{renk}-600` + `RISK_ETIKET`. - Veride BÜYÜK HARF gelen üniversite adı ekranda `trBaslikDuzeni` ile yazılır. @@ -661,6 +665,9 @@ sihirbaz modalı içindir; yeni bir ayrıntı için `Dialog` açılmaz. solma (§6). Akademik göstergeler çekmecesi (§4.9) aynı bileşenin kartlı modunu kullanır. ### 4.20 Danışman sohbeti — `sohbet-client.tsx`, `arac-pilleri.tsx` +- **Soru formu hazırlanırken** (7 Eki 2026): `soru_sor` aracı tamamlanana dek cevap iskeleti değil + `TextShimmerLoader` "Soruları hazırlıyorum…" (`role=status`); danışman araç çalıştırırken avatar + header logosuyla aynı `"rota"` koreografisini oynatır (`AnimasyonluMark`), farklı bir animasyon yazılmaz. Sohbet kabuğu **prompt-kit** bileşenleridir (`src/components/ui/`: `prompt-input`, `message`, `chat-container` + `scroll-button`, `prompt-suggestion`, `loader`, `markdown`); yeni bir sohbet parçası gerekince önce prompt-kit'e bakılır (`shadcn add https://prompt-kit.com/c/.json`). @@ -941,6 +948,9 @@ alanı §4.6 hapı (`h-11 rounded-full`). Düğmeler sitenin `Button`'u (`sm`): font-medium text-red-600`. Kapanmış form tek satır: "Formu cevapladın." (yeşil tik) ya da "Form kapandı; isteğini yazarak söyleyebilirsin." Yeni bir anket/soru akışı gerekince bu bileşen kullanılır; radio/checkbox'lı yeni form tasarlanmaz. +Sorular arası geçiş **sihirbaz adım geçişiyle birebir aynı** (7 Eki 2026): yay ve varyantlar tek +kaynak `src/lib/adim-gecisi.ts` (`adimGecisiVaryantlari`, `adimGecisi`); yön index'ten türer. Pasif +sorular DOM'da kalır (mutlak/saydam/`inert`) ki FormData toplanmaya devam etsin. ## 5. Yerleşim diff --git a/eslint.config.mjs b/eslint.config.mjs index 05e726d..00a7342 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -12,6 +12,8 @@ const eslintConfig = defineConfig([ "out/**", "build/**", "next-env.d.ts", + // Paralel ajan worktree'leri (typegen çıktıları lint'e girmesin). + ".claude/worktrees/**", ]), ]); diff --git a/src/features/rapor/components/listem-govde.tsx b/src/features/rapor/components/listem-govde.tsx index 3943711..ce72b6c 100644 --- a/src/features/rapor/components/listem-govde.tsx +++ b/src/features/rapor/components/listem-govde.tsx @@ -443,8 +443,7 @@ export function ListemGovde({ bildikleri={danismaninBildikleri} genis={sohbetGenis} onGenisDegistir={sohbetGenisligiAyarla} - // 0/1 bayrak; prop adı entegrasyonda revizyonAcik olur - revizyonHakki={hasPaket ? 1 : 0} + revizyonAcik={hasPaket} /> ) : ( diff --git a/src/features/rapor/components/sohbet-client.tsx b/src/features/rapor/components/sohbet-client.tsx index e0be39b..3c6ecbe 100644 --- a/src/features/rapor/components/sohbet-client.tsx +++ b/src/features/rapor/components/sohbet-client.tsx @@ -350,7 +350,7 @@ export function SohbetClient({ genis: genisProp, onGenisDegistir, genisYukseklik = GENIS_YUKSEKLIK, - revizyonHakki = 0, + revizyonAcik = false, }: { baslangicKredi: number; /** Sunucu tarafında çekilmiş danışman profili; verilirse mount fetch'i atlanır */ @@ -382,8 +382,8 @@ export function SohbetClient({ /** Genişletilmiş panelin yüksekliği; verilmezse ekrana göre hesaplanır * (üst 7rem sticky hizası, alt 7rem progressive blur payı). */ genisYukseklik?: string; - /** Kalan liste revizyonu hakkı (paketli); 0 ise revizyon örneği gösterilmez. */ - revizyonHakki?: number; + /** Liste revizyonu açık mı (paketli aday); kapalıysa revizyon örneği ve ipucu gösterilmez. */ + revizyonAcik?: boolean; }) { const [girdi, setGirdi] = useState(""); const [yuklendi, setYuklendi] = useState(initialMesajlar != null); @@ -942,7 +942,7 @@ export function SohbetClient({ !ozet && "justify-center", )} > - {[...(revizyonHakki > 0 ? [REVIZYON_ORNEGI] : []), ...ORNEK_SORULAR].map((s) => ( + {[...(revizyonAcik ? [REVIZYON_ORNEGI] : []), ...ORNEK_SORULAR].map((s) => ( 0 + revizyonAcik ? "Sorunu yaz ya da listende ne değişsin söyle… (1 kredi)" : "Sorunu yaz… (1 kredi)" } diff --git a/src/lib/ai/rapor.ts b/src/lib/ai/rapor.ts index a68b78b..0307387 100644 --- a/src/lib/ai/rapor.ts +++ b/src/lib/ai/rapor.ts @@ -689,7 +689,7 @@ export async function raporUretAyrintili( let kaynak: RaporTani["kaynak"] = "model"; if (!enIyi || enIyi.onarim.modelSecimi === 0) { // Revizyonda kodla kurulan liste adayın isteğini yok sayar ve bir - // revizyon hakkını yakardı: hata fırlar (çağıran krediyi/hakkı iade eder). + // sohbet kredisini yakardı: hata fırlar (çağıran krediyi iade eder). if (!zamanAsimi || revizyonNotu || !ZAMAN_ASIMINDA_KODLA_KUR) { // Zaman aşımı hatası olduğu gibi fırlar: çağıran "çok uzun sürdü, // kredin iade edildi" mesajını bu hatadan tanıyor. @@ -797,7 +797,7 @@ export async function raporUretAyrintili( p.kontenjanSon, p.yerlesenSon, params.sira, - ...metindekiSayilar(p.isim, p.universite), + ...metindekiSayilar(p.isim, p.universite, p.varyant ?? ""), // Koddan gelen "öne çıkan" cümlelerdeki sayılar meşrudur (TÜİK %, URAP sırası, km…) ...metindekiSayilar(...(p.oneCikan ?? [])), ...profilSayilari,