Files
ayrisdevandClaude Sonnet 5 7d504d1938 feat: panel UI'ını Tailwind v4 + shadcn/ui ile yeniden tasarla (Faz 4)
Elle yazılmış tek-dosya CSS (sabit koyu tema, ham table/button, window.confirm
ile silme onayı) yerine tutarlı bir bileşen sistemi: Card/Table/Badge/Button/
Input/Switch/AlertDialog primitifleri, Hanken Grotesk + JetBrains Mono
tipografi çifti, "broadcast/monitör" temalı özel bir renk paleti (camgöbeği
accent, ok/warn/err/live durum rengi sözlüğü). Tüm sayfalar (dashboard, kanal
detay, segmentler, ayarlar, istatistik, kullanıcılar, login) aynı oturumda
taşındı — silme onayları artık gerçek AlertDialog, native confirm() değil.

Veri akışı/server action'lar değişmedi, tamamen görsel katman.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 14:33:24 +03:00

43 lines
1.2 KiB
TypeScript

"use client";
import { useEffect, useRef, useState } from "react";
export function LiveLogViewer({ sessionId }: { sessionId: string }) {
const [lines, setLines] = useState<string[]>([]);
const boxRef = useRef<HTMLPreElement>(null);
useEffect(() => {
let cancelled = false;
async function poll() {
try {
const res = await fetch(`/api/debug/capture/${sessionId}`, { cache: "no-store" });
const data = (await res.json()) as { lines: string[] };
if (!cancelled) setLines(data.lines);
} catch {
// transient fetch failures are fine to just skip — next tick retries
}
}
poll();
const timer = setInterval(poll, 4000);
return () => {
cancelled = true;
clearInterval(timer);
};
}, [sessionId]);
useEffect(() => {
if (boxRef.current) boxRef.current.scrollTop = boxRef.current.scrollHeight;
}, [lines]);
return (
<pre
ref={boxRef}
className="font-mono-num mt-3 max-h-56 overflow-y-auto rounded-md border border-border bg-background/60 p-3 text-[0.7rem] leading-relaxed whitespace-pre-wrap text-muted-foreground"
>
{lines.length > 0 ? lines.join("\n") : "Log bekleniyor…"}
</pre>
);
}