feat: migrate and redesign dashboard to modern React

- Full rewrite of legacy vanilla JS UI into React SPA
- Implement modern design system using Tailwind CSS and shadcn/ui primitives
- Create typed API modules and hooks for voice, media, and moderation
- Add new features: separated Music and Screen Share panels, Image Grid
- Implement unified WebSocket hook for real-time state and PCM audio
- Improve visualizer with smooth CSS transitions and live state sync
- Add __dirname polyfill for ES module compatibility
- Ensure responsive layout for mobile and desktop

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
MythEclipse
2026-05-16 19:17:34 +07:00
parent 3c7d722973
commit 82025a19b2
51 changed files with 2865 additions and 1204 deletions

View File

@@ -0,0 +1,45 @@
import { MonitorUp } from "lucide-react";
import { useState } from "react";
import { Button } from "../ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card";
import { Input } from "../ui/input";
interface ScreenShareProps {
loading: boolean;
onStart: (source: string) => void;
onSkip: () => void;
onStop: () => void;
}
export function ScreenShare({ loading, onStart, onSkip, onStop }: ScreenShareProps) {
const [source, setSource] = useState("");
const submit = () => {
const trimmed = source.trim();
if (!trimmed) return;
onStart(trimmed);
setSource("");
};
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2"><MonitorUp className="h-5 w-5" /> Screen Share</CardTitle>
<CardDescription>Start screen-share playback from a URL or local file path.</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<Input
value={source}
onChange={(event) => setSource(event.target.value)}
onKeyDown={(event) => event.key === "Enter" && submit()}
placeholder="Screen share URL or local file path"
/>
<div className="flex flex-wrap gap-2">
<Button disabled={loading || !source.trim()} onClick={submit}>Start Screen Share</Button>
<Button variant="secondary" disabled={loading} onClick={onSkip}>Skip</Button>
<Button variant="destructive" disabled={loading} onClick={onStop}>Stop</Button>
</div>
</CardContent>
</Card>
);
}