import React, { useState, useEffect, useCallback } from 'react'; import { Card } from '../ui/card'; import { Button } from '../ui/button'; import { Badge } from '../ui/badge'; import { EmptyState } from '../ui/empty-state'; import { BarChart3, Users, Music, CreditCard, FileText, Search, Ban, CheckCircle, Eye, EyeOff, Loader2, Shield, } from 'lucide-react'; import { useToast } from '../../components/feedback/ToastProvider'; import { adminService, PlatformMetrics, AdminUserInfo, AdminContentItem, PaymentOverview, } from '../../services/adminService'; import { logger } from '@/utils/logger'; type PlatformTab = 'metrics' | 'users' | 'content' | 'payments'; export const AdminPlatformView: React.FC = () => { const { addToast } = useToast(); const [activeTab, setActiveTab] = useState('metrics'); const [loading, setLoading] = useState(true); // Metrics const [metrics, setMetrics] = useState(null); // Users const [users, setUsers] = useState([]); const [usersTotal, setUsersTotal] = useState(0); const [userSearch, setUserSearch] = useState(''); const [userRoleFilter, setUserRoleFilter] = useState(''); // Content const [content, setContent] = useState([]); const [contentTotal, setContentTotal] = useState(0); const [contentSearch, setContentSearch] = useState(''); const [contentType, setContentType] = useState('track'); // Payments const [payments, setPayments] = useState(null); const loadMetrics = useCallback(async () => { setLoading(true); try { const data = await adminService.getPlatformMetrics(); setMetrics(data); } catch (e) { logger.error('Error loading platform metrics', { error: e instanceof Error ? e.message : String(e) }); } finally { setLoading(false); } }, []); const loadUsers = useCallback(async () => { setLoading(true); try { const data = await adminService.searchUsers({ q: userSearch || undefined, role: userRoleFilter || undefined }); setUsers(data.users); setUsersTotal(data.total); } catch (e) { logger.error('Error loading users', { error: e instanceof Error ? e.message : String(e) }); } finally { setLoading(false); } }, [userSearch, userRoleFilter]); const loadContent = useCallback(async () => { setLoading(true); try { const data = await adminService.searchContent({ type: contentType, q: contentSearch || undefined }); setContent(data.content); setContentTotal(data.total); } catch (e) { logger.error('Error loading content', { error: e instanceof Error ? e.message : String(e) }); } finally { setLoading(false); } }, [contentType, contentSearch]); const loadPayments = useCallback(async () => { setLoading(true); try { const data = await adminService.getPaymentOverview(); setPayments(data); } catch (e) { logger.error('Error loading payments', { error: e instanceof Error ? e.message : String(e) }); } finally { setLoading(false); } }, []); useEffect(() => { switch (activeTab) { case 'metrics': loadMetrics(); break; case 'users': loadUsers(); break; case 'content': loadContent(); break; case 'payments': loadPayments(); break; } }, [activeTab, loadMetrics, loadUsers, loadContent, loadPayments]); const handleSuspendUser = async (userId: string) => { const reason = prompt('Suspension reason:'); if (!reason) return; try { await adminService.suspendUser(userId, reason); addToast('User suspended', 'success'); loadUsers(); } catch { addToast('Suspension failed', 'error'); } }; const handleUnsuspendUser = async (userId: string) => { try { await adminService.unsuspendUser(userId); addToast('User unsuspended', 'success'); loadUsers(); } catch { addToast('Unsuspension failed', 'error'); } }; const handleHideContent = async (id: string, type: string) => { try { await adminService.hideContent(id, type, 'Admin action'); addToast('Content hidden', 'success'); loadContent(); } catch { addToast('Hide failed', 'error'); } }; const handleRestoreContent = async (id: string, type: string) => { try { await adminService.restoreContent(id, type); addToast('Content restored', 'success'); loadContent(); } catch { addToast('Restore failed', 'error'); } }; const tabs: { key: PlatformTab; label: string; icon: React.ReactNode }[] = [ { key: 'metrics', label: 'Dashboard', icon: }, { key: 'users', label: 'Users', icon: }, { key: 'content', label: 'Content', icon: }, { key: 'payments', label: 'Payments', icon: }, ]; return (

PLATFORM ADMINISTRATION

Metrics, users, content, and payments management.

{/* Tabs */}
{tabs.map((tab) => ( ))}
{loading && (
)} {!loading && activeTab === 'metrics' && metrics && } {!loading && activeTab === 'users' && ( )} {!loading && activeTab === 'content' && ( )} {!loading && activeTab === 'payments' && payments && }
); }; function MetricsPanel({ metrics }: { metrics: PlatformMetrics }) { const cards = [ { label: 'Total Users', value: metrics.total_users.toLocaleString(), color: 'text-blue-400', icon: }, { label: 'Active (30d)', value: metrics.active_users.toLocaleString(), color: 'text-green-400', icon: }, { label: 'New Today', value: metrics.new_users_today.toLocaleString(), color: 'text-cyan-400', icon: }, { label: 'New This Week', value: metrics.new_users_week.toLocaleString(), color: 'text-cyan-400', icon: }, { label: 'Total Tracks', value: metrics.total_tracks.toLocaleString(), color: 'text-purple-400', icon: }, { label: 'Tracks Today', value: metrics.tracks_today.toLocaleString(), color: 'text-purple-400', icon: }, { label: 'Playlists', value: metrics.total_playlists.toLocaleString(), color: 'text-orange-400', icon: }, { label: 'Comments', value: metrics.total_comments.toLocaleString(), color: 'text-orange-400', icon: }, { label: 'Banned Users', value: metrics.banned_users.toLocaleString(), color: 'text-red-400', icon: }, { label: 'Pending Reports', value: metrics.pending_reports.toLocaleString(), color: 'text-red-400', icon: }, { label: 'Storage', value: `${(metrics.storage_used_mb / 1024).toFixed(1)} GB`, color: 'text-yellow-400', icon: }, { label: 'Total Revenue', value: `$${metrics.total_revenue.toFixed(2)}`, color: 'text-green-400', icon: }, ]; return (
{cards.map((card) => (
{card.icon}
{card.label}
{card.value}
))}
); } function UsersPanel({ users, total, search, roleFilter, onSearchChange, onRoleFilterChange, onSearch, onSuspend, onUnsuspend, }: { users: AdminUserInfo[]; total: number; search: string; roleFilter: string; onSearchChange: (v: string) => void; onRoleFilterChange: (v: string) => void; onSearch: () => void; onSuspend: (userId: string) => void; onUnsuspend: (userId: string) => void; }) { return (
onSearchChange(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && onSearch()} className="w-full bg-muted border border-border rounded pl-10 pr-3 py-2 text-sm text-foreground" aria-label="Search users" />
{total} users
{users.length === 0 && ( } title="No users found" description="Try adjusting your search." /> )}
{users.map((user) => (
{user.username} {user.is_banned && BANNED} {user.is_suspended && SUSPENDED} {user.is_admin && ADMIN}
{user.email} {user.track_count} tracks {user.active_strikes} strikes Joined: {new Date(user.created_at).toLocaleDateString()}
{!user.is_banned && !user.is_suspended ? ( ) : ( )}
))}
); } function ContentPanel({ content, total, search, contentType, onSearchChange, onTypeChange, onSearch, onHide, onRestore, }: { content: AdminContentItem[]; total: number; search: string; contentType: string; onSearchChange: (v: string) => void; onTypeChange: (v: string) => void; onSearch: () => void; onHide: (id: string, type: string) => void; onRestore: (id: string, type: string) => void; }) { return (
onSearchChange(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && onSearch()} className="w-full bg-muted border border-border rounded pl-10 pr-3 py-2 text-sm text-foreground" aria-label="Search content" />
{total} items
{content.length === 0 && ( } title="No content found" description="Try adjusting your search." /> )}
{content.map((item) => (
{item.title} {item.status === 'hidden' && HIDDEN} {item.report_count > 0 && ( {item.report_count} reports )}
By: {item.creator_name} | {new Date(item.created_at).toLocaleDateString()}
{item.status === 'active' ? ( ) : ( )}
))}
); } function PaymentsPanel({ payments }: { payments: PaymentOverview }) { const cards = [ { label: 'Total Orders', value: payments.total_orders.toLocaleString(), color: 'text-blue-400' }, { label: 'Completed', value: payments.completed_orders.toLocaleString(), color: 'text-green-400' }, { label: 'Pending', value: payments.pending_orders.toLocaleString(), color: 'text-orange-400' }, { label: 'Refunded', value: payments.refunded_orders.toLocaleString(), color: 'text-red-400' }, { label: 'Total Revenue', value: `$${payments.total_revenue.toFixed(2)}`, color: 'text-green-400' }, { label: 'Platform Fees', value: `$${payments.platform_fees.toFixed(2)}`, color: 'text-purple-400' }, { label: 'Total Refunded', value: `$${payments.total_refunded.toFixed(2)}`, color: 'text-red-400' }, ]; return (
{cards.map((card) => (
{card.label}
{card.value}
))}
); }