refactor(fe): align dashboard with backend & gateway data flow
- API/WS clients: same-origin by default, drop dead imphnen hardcode
- chatbot history: map BE rows {user_message,bot_response,created_at}
- message_deleted WS payload: object {id,deleted_at}, not bare string
- dashboard: wire top-channels chart + live mod queue from /api/review,
add Users & Channels tabs consuming /api/dashboard/users|channels
- recordings: live WS sync via voice_recording_uploaded; duration_bytes optional
- remove dead widgets with no BE data source (trend chart, heatmap)
This commit is contained in:
@@ -2,8 +2,9 @@
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { GlassCard } from "@/components/glass/card";
|
||||
import { useWebSocket } from "@/lib/ws/context";
|
||||
import type { MessageRecord } from "@/lib/types";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useWebSocket } from "@/lib/ws/context";
|
||||
|
||||
interface LiveMessage {
|
||||
id: string;
|
||||
@@ -20,12 +21,23 @@ export function LiveStream() {
|
||||
const ws = useWebSocket();
|
||||
|
||||
useEffect(() => {
|
||||
const unsub = ws.on("message_created", (data: any) => {
|
||||
const unsub = ws.on("message_created", (data: MessageRecord) => {
|
||||
// channel name lives inside the metadata JSON (channel.channelName)
|
||||
let channelName: string | undefined;
|
||||
try {
|
||||
const meta =
|
||||
typeof data.metadata === "string"
|
||||
? JSON.parse(data.metadata)
|
||||
: data.metadata;
|
||||
channelName = meta?.channel?.channelName;
|
||||
} catch {
|
||||
channelName = undefined;
|
||||
}
|
||||
const msg: LiveMessage = {
|
||||
id: data.id,
|
||||
content: data.content || "(attachment)",
|
||||
username: data.username || "unknown",
|
||||
channelName: data.channelName,
|
||||
channelName,
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
flagged: data.ai_status === "flagged" || data.ai_status === "warn",
|
||||
};
|
||||
@@ -34,12 +46,6 @@ export function LiveStream() {
|
||||
return () => unsub();
|
||||
}, [ws]);
|
||||
|
||||
useEffect(() => {
|
||||
if (scrollRef.current) {
|
||||
scrollRef.current.scrollTop = 0;
|
||||
}
|
||||
}, [messages]);
|
||||
|
||||
return (
|
||||
<GlassCard variant="base" className="p-0 overflow-hidden">
|
||||
<div className="flex items-center gap-2 px-4 py-2.5 border-b border-glass-border">
|
||||
@@ -51,7 +57,10 @@ export function LiveStream() {
|
||||
Live Stream
|
||||
</span>
|
||||
</div>
|
||||
<div ref={scrollRef} className="overflow-y-auto max-h-[320px] space-y-0.5 p-2">
|
||||
<div
|
||||
ref={scrollRef}
|
||||
className="overflow-y-auto max-h-[320px] space-y-0.5 p-2"
|
||||
>
|
||||
{messages.length === 0 ? (
|
||||
<div className="flex items-center justify-center py-8 text-text-secondary/40 text-xs">
|
||||
Waiting for messages...
|
||||
|
||||
Reference in New Issue
Block a user