Files
kolaytercih/src/features/rapor/components/revizyon-kutusu.tsx
bilalgursen 5853b7d091 feat(etiket): görünen "Garanti" dilim adı site genelinde "Güvenli"
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 <noreply@anthropic.com>
2026-09-21 16:03:22 +03:00

101 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
// Paketlinin geri bildirime dayalı liste revizyonu (/listem üzerinde).
// listeRevize sunucu aksiyonunu çağırır; başarıda sayfayı yeniler ki
// sunucuda güncellenen rapor ve kredi bakiyesi ekrana yansısın.
import { useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { RefreshCcw } from "lucide-react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { listeRevize } from "@/features/rapor/rapor-actions";
import { olay } from "@/lib/analitik";
export function RevizyonKutusu({ kalanHak }: { kalanHak: number }) {
const [feedback, setFeedback] = useState("");
const [pending, setPending] = useState(false);
const router = useRouter();
// Aynı deneme için sabit requestId: cevap kaybolan network hatasında retry
// çifte harcamaz. Sunucudan cevap gelince sıfırlanır (harcama ya tamamlandı
// ya iade edildi; sonraki deneme taze id ile başlamalı — bkz. sonuc/actions.ts).
const requestIdRef = useRef<string | null>(null);
if (kalanHak <= 0) {
return (
<section
id="revizyon"
className="scroll-mt-24 rounded-2xl border border-slate-200 bg-white p-5"
>
<p className="text-sm text-slate-500">
Revizyon hakların doldu. Danışman sohbetinden listen hakkında soru
sormaya devam edebilirsin.
</p>
</section>
);
}
async function revizeEt() {
setPending(true);
try {
if (!requestIdRef.current) requestIdRef.current = crypto.randomUUID();
const sonuc = await listeRevize({
feedback: feedback.trim(),
requestId: requestIdRef.current,
});
requestIdRef.current = null;
if (sonuc.ok) {
olay("liste_revize", { sayfa: "listem" });
toast.success("Listen yeniden kuruldu.");
setFeedback("");
router.refresh();
} else {
toast.error(sonuc.error);
}
} catch {
toast.error("Beklenmeyen bir hata oluştu, tekrar dener misin?");
} finally {
setPending(false);
}
}
return (
<section
id="revizyon"
className="scroll-mt-24 rounded-2xl border border-slate-200 bg-white p-5"
>
<h2 className="font-heading text-base font-bold">
Listede değişiklik mi istiyorsun?
</h2>
<p className="mb-3 mt-1 text-sm text-slate-600">
Ne değişsin istediğini yaz; liste aynı gerçek veriyle yeniden kurulsun
(3 kredi).
</p>
<textarea
value={feedback}
onChange={(e) => setFeedback(e.target.value)}
rows={2}
maxLength={1000}
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"
/>
<div className="mt-3 flex items-center gap-3">
<Button
type="button"
variant="outline"
disabled={pending || feedback.trim().length < 5}
onClick={revizeEt}
className="cursor-pointer"
>
<RefreshCcw className="size-4" aria-hidden />
{pending ? "Yeniden kuruluyor…" : "Revize et (3 kredi)"}
</Button>
<span className="text-xs text-slate-500">
Kalan hak: <span className="font-semibold">{kalanHak}</span>
</span>
</div>
</section>
);
}