frontend: kanal detay sayfası (canlı durum + poll hatası + yayın geçmişi)

/channels/[id] rotası eklendi: dashboard'daki kanal adı artık oraya
link veriyor. Sayfa api-daemon'un /status'undan canlı durum ve son
poll hatasını (lastPollError, DB'de değil sadece bellekte tutuluyordu)
çekiyor, Prisma'dan da o kanala ait tüm StreamSession/RawSegment/
CandidateSegment geçmişini transkript önizlemesiyle listeliyor.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-30 17:34:15 +03:00
co-authored by Claude Sonnet 5
parent b62d6a7e5f
commit 19fe430549
4 changed files with 181 additions and 10 deletions
+24 -10
View File
@@ -1,19 +1,24 @@
import Link from "next/link";
import { prisma } from "@streamclipper/db";
import { addChannel } from "./actions";
import { fetchChannelStatuses } from "../lib/apiDaemon";
export const dynamic = "force-dynamic";
export default async function DashboardPage() {
const channels = await prisma.channel.findMany({
orderBy: { name: "asc" },
include: {
sessions: {
where: { endedAt: null },
orderBy: { startedAt: "desc" },
take: 1,
const [channels, statuses] = await Promise.all([
prisma.channel.findMany({
orderBy: { name: "asc" },
include: {
sessions: {
where: { endedAt: null },
orderBy: { startedAt: "desc" },
take: 1,
},
},
},
});
}),
fetchChannelStatuses(),
]);
return (
<>
@@ -41,9 +46,13 @@ export default async function DashboardPage() {
<tbody>
{channels.map((c) => {
const recording = c.sessions.length > 0;
const status = statuses.get(c.id);
return (
<tr key={c.id}>
<td>{c.name} <span className="mono">{c.youtubeHandle}</span></td>
<td>
<Link href={`/channels/${c.id}`}>{c.name}</Link>{" "}
<span className="mono">{c.youtubeHandle}</span>
</td>
<td>
<span className={`badge ${c.isActive ? "ok" : "muted"}`}>
{c.isActive ? "Aktif" : "Pasif"}
@@ -53,6 +62,11 @@ export default async function DashboardPage() {
<span className={`badge ${recording ? "warn" : "muted"}`}>
{recording ? "🔴 Kayıtta" : "—"}
</span>
{status?.lastPollError && (
<span className="badge err" style={{ marginLeft: "0.4rem" }}>
hata
</span>
)}
</td>
<td className="mono">
{c.lastCheckedAt ? new Date(c.lastCheckedAt).toLocaleString("tr-TR") : "—"}