import { Head, Link, router } from '@inertiajs/react'; import { Ban, KeyRound, Lock, Radio, Shield, StopCircle, Undo2, Unlock, UserCheck, Users, UserX, } from 'lucide-react'; import type { LucideIcon } from 'lucide-react'; import { useState } from 'react'; import { updateDefault as updateChannelCreationDefault, updateUser as updateUserCreatorAccess, } from '@/actions/App/Http/Controllers/AdminChannelCreationController'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { dashboard as adminDashboard } from '@/routes/admin'; import { stop as stopBroadcast } from '@/routes/admin/broadcasts'; import { restore, suspend } from '@/routes/admin/channels'; import { show as showChannel } from '@/routes/channels'; type LiveBroadcast = { id: number; title: string; started_at: string | null; channel: { id: number; slug: string; display_name: string; thumbnail_url: string | null; owner: string; }; }; type AdminChannel = { id: number; slug: string; display_name: string; avatar_url: string | null; thumbnail_url: string | null; is_live: boolean; suspended_at: string | null; owner: { id: number; name: string; }; }; type AdminUser = { id: number; name: string; email: string; is_admin: boolean; can_create_channel: boolean; suspended_at: string | null; created_at: string | null; channel: { id: number; slug: string; display_name: string; } | null; }; type Props = { stats: { users: number; channels: number; live_channels: number; vods: number; creator_access_grants: number; }; channelCreationPolicy: { channel_creation_open: boolean; }; liveBroadcasts: LiveBroadcast[]; channels: AdminChannel[]; users: AdminUser[]; }; type ModerationAction = | { kind: 'stop'; broadcast: LiveBroadcast } | { kind: 'suspend'; channel: AdminChannel } | { kind: 'restore'; channel: AdminChannel } | null; export default function AdminDashboard({ stats, channelCreationPolicy, liveBroadcasts, channels, users, }: Props) { const [action, setAction] = useState(null); function setChannelCreationDefault(channelCreationOpen: boolean) { router.patch( updateChannelCreationDefault(), { channel_creation_open: channelCreationOpen, }, { preserveScroll: true, }, ); } function setUserCreatorAccess(user: AdminUser, canCreateChannel: boolean) { router.patch( updateUserCreatorAccess(user.id), { can_create_channel: canCreateChannel, }, { preserveScroll: true, }, ); } function confirmAction() { if (!action) { return; } if (action.kind === 'stop') { router.post(stopBroadcast(action.broadcast.id), undefined, { onFinish: () => setAction(null), }); return; } router.post( action.kind === 'suspend' ? suspend(action.channel.slug) : restore(action.channel.slug), undefined, { onFinish: () => setAction(null) }, ); } return ( <>

Moderation console

Review live streams, suspended states, users, and recordings.

{liveBroadcasts.length} active broadcasts

Channel creation access

Control who can create a creator channel.

{users.map((user) => ( setUserCreatorAccess(user, canCreateChannel) } /> ))} {users.length === 0 && ( )}

Live broadcasts

{liveBroadcasts.length} rows
{liveBroadcasts.map((broadcast) => (
{broadcast.title}
{broadcast.channel.display_name} by{' '} {broadcast.channel.owner}
LIVE
))} {liveBroadcasts.length === 0 && ( )}

Recent channels

{channels.length} rows
{channels.map((channel) => (
{channel.display_name}
@{channel.slug} owned by{' '} {channel.owner.name}
{channel.is_live && ( LIVE )} {channel.suspended_at && ( SUSPENDED )}
{channel.suspended_at ? ( ) : ( )}
))}
!open && setAction(null)} > {dialogTitle(action)} {dialogDescription(action)} ); } AdminDashboard.layout = { breadcrumbs: [ { title: 'Admin', href: adminDashboard(), }, ], }; function Stat({ icon: Icon, label, value, live = false, }: { icon: LucideIcon; label: string; value: number; live?: boolean; }) { return (
{label}
{value}
); } function CreatorAccessRow({ user, defaultOpen, onChange, }: { user: AdminUser; defaultOpen: boolean; onChange: (canCreateChannel: boolean) => void; }) { const effectiveAccess = defaultOpen || user.can_create_channel; return (
{user.name} {user.is_admin && ( ADMIN )} {user.suspended_at && ( SUSPENDED )} {effectiveAccess ? 'CAN CREATE' : 'NEEDS APPROVAL'} {defaultOpen && !user.can_create_channel && ( DEFAULT )}
{user.email} {user.channel && ( <> {' - '} {user.channel.display_name} )}
); } function Thumb({ url }: { url: string | null }) { return (
{url ? ( ) : (
)}
); } function Avatar({ channel }: { channel: AdminChannel }) { return (
{channel.avatar_url ? ( ) : ( )}
); } function EmptyState({ text }: { text: string }) { return (
{text}
); } function dialogTitle(action: ModerationAction): string { if (action?.kind === 'stop') { return 'Stop live broadcast?'; } if (action?.kind === 'restore') { return 'Restore channel?'; } return 'Suspend channel?'; } function dialogDescription(action: ModerationAction): string { if (action?.kind === 'stop') { return 'The live session will end immediately and the channel will move offline.'; } if (action?.kind === 'restore') { return 'The channel will be visible again if the owning account is active.'; } return 'The channel will be hidden from public browsing and watch pages.'; }