import { useState, useEffect, useCallback } from 'react'; import { Activity, Zap, Database, Server, Workflow, Globe, CheckCircle, AlertTriangle, XCircle, RefreshCw, TrendingUp, Clock, Cpu, HardDrive, MemoryStick } from 'lucide-react'; import PageMeta from '../../components/common/PageMeta'; import DebugSiteSelector from '../../components/common/DebugSiteSelector'; import { fetchAPI } from '../../services/api'; import { useSiteStore } from '../../store/siteStore'; // Types interface SystemMetrics { cpu: { usage_percent: number; cores: number; status: string }; memory: { total_gb: number; used_gb: number; usage_percent: number; status: string }; disk: { total_gb: number; used_gb: number; usage_percent: number; status: string }; } interface ServiceHealth { database: { status: string; connected: boolean }; redis: { status: string; connected: boolean }; celery: { status: string; worker_count: number }; } interface ApiGroupHealth { name: string; total: number; healthy: number; warning: number; error: number; percentage: number; status: 'healthy' | 'warning' | 'error'; } interface WorkflowHealth { name: string; steps: { name: string; status: 'healthy' | 'warning' | 'error'; message?: string }[]; overall: 'healthy' | 'warning' | 'error'; } interface IntegrationHealth { platform: string; connected: boolean; last_sync: string | null; sync_enabled: boolean; plugin_active: boolean; status: 'healthy' | 'warning' | 'error'; } export default function MasterStatus() { const { activeSite } = useSiteStore(); const [loading, setLoading] = useState(true); const [lastUpdate, setLastUpdate] = useState(new Date()); // System metrics const [systemMetrics, setSystemMetrics] = useState(null); const [serviceHealth, setServiceHealth] = useState(null); // API health const [apiHealth, setApiHealth] = useState([]); // Workflow health (keywords → clusters → ideas → tasks → content → publish) const [workflowHealth, setWorkflowHealth] = useState([]); // Integration health const [integrationHealth, setIntegrationHealth] = useState(null); // Fetch system metrics const fetchSystemMetrics = useCallback(async () => { try { const data = await fetchAPI('/v1/system/status/'); setSystemMetrics(data.system); setServiceHealth({ database: data.database, redis: data.redis, celery: data.celery, }); } catch (error) { console.error('Failed to fetch system metrics:', error); } }, []); // Fetch API health (aggregated from API monitor) const fetchApiHealth = useCallback(async () => { const groups = [ { name: 'Auth & User', endpoints: ['/v1/auth/me/', '/v1/auth/sites/', '/v1/auth/accounts/'] }, { name: 'Planner', endpoints: ['/v1/planner/keywords/', '/v1/planner/clusters/', '/v1/planner/ideas/'] }, { name: 'Writer', endpoints: ['/v1/writer/tasks/', '/v1/writer/content/', '/v1/writer/images/'] }, { name: 'Integration', endpoints: ['/v1/integration/integrations/'] }, ]; const healthChecks: ApiGroupHealth[] = []; for (const group of groups) { let healthy = 0; let warning = 0; let error = 0; for (const endpoint of group.endpoints) { try { const startTime = Date.now(); await fetchAPI(endpoint + (activeSite ? `?site=${activeSite.id}` : '')); const responseTime = Date.now() - startTime; if (responseTime < 1000) healthy++; else if (responseTime < 3000) warning++; else error++; } catch (e) { error++; } } const total = group.endpoints.length; const percentage = Math.round((healthy / total) * 100); healthChecks.push({ name: group.name, total, healthy, warning, error, percentage, status: error > 0 ? 'error' : warning > 0 ? 'warning' : 'healthy', }); } setApiHealth(healthChecks); }, [activeSite]); // Check workflow health (end-to-end pipeline) const checkWorkflowHealth = useCallback(async () => { if (!activeSite) { setWorkflowHealth([]); return; } const workflows: WorkflowHealth[] = []; // Content Generation Workflow try { const steps = []; // Step 1: Keywords exist const keywords = await fetchAPI(`/v1/planner/keywords/?site=${activeSite.id}`); steps.push({ name: 'Keywords Imported', status: keywords.count > 0 ? 'healthy' : 'warning' as const, message: `${keywords.count} keywords`, }); // Step 2: Clusters exist const clusters = await fetchAPI(`/v1/planner/clusters/?site=${activeSite.id}`); steps.push({ name: 'Content Clusters', status: clusters.count > 0 ? 'healthy' : 'warning' as const, message: `${clusters.count} clusters`, }); // Step 3: Ideas generated const ideas = await fetchAPI(`/v1/planner/ideas/?site=${activeSite.id}`); steps.push({ name: 'Content Ideas', status: ideas.count > 0 ? 'healthy' : 'warning' as const, message: `${ideas.count} ideas`, }); // Step 4: Tasks created const tasks = await fetchAPI(`/v1/writer/tasks/?site=${activeSite.id}`); steps.push({ name: 'Writer Tasks', status: tasks.count > 0 ? 'healthy' : 'warning' as const, message: `${tasks.count} tasks`, }); // Step 5: Content generated const content = await fetchAPI(`/v1/writer/content/?site=${activeSite.id}`); steps.push({ name: 'Content Generated', status: content.count > 0 ? 'healthy' : 'warning' as const, message: `${content.count} articles`, }); const hasErrors = steps.some(s => s.status === 'error'); const hasWarnings = steps.some(s => s.status === 'warning'); workflows.push({ name: 'Content Generation Pipeline', steps, overall: hasErrors ? 'error' : hasWarnings ? 'warning' : 'healthy', }); } catch (error) { workflows.push({ name: 'Content Generation Pipeline', steps: [{ name: 'Pipeline Check', status: 'error', message: 'Failed to check workflow' }], overall: 'error', }); } setWorkflowHealth(workflows); }, [activeSite]); // Check integration health const checkIntegrationHealth = useCallback(async () => { if (!activeSite) { setIntegrationHealth(null); return; } try { const integrations = await fetchAPI(`/v1/integration/integrations/?site_id=${activeSite.id}`); if (integrations.results && integrations.results.length > 0) { const wpIntegration = integrations.results.find((i: any) => i.platform === 'wordpress'); if (wpIntegration) { const health = await fetchAPI(`/v1/integration/integrations/${wpIntegration.id}/debug-status/`); setIntegrationHealth({ platform: 'WordPress', connected: wpIntegration.is_active, last_sync: wpIntegration.last_sync_at, sync_enabled: wpIntegration.sync_enabled, plugin_active: health.health?.plugin_active || false, status: wpIntegration.is_active && health.health?.plugin_active ? 'healthy' : 'warning', }); } else { setIntegrationHealth(null); } } else { setIntegrationHealth(null); } } catch (error) { console.error('Failed to check integration:', error); setIntegrationHealth(null); } }, [activeSite]); // Refresh all data const refreshAll = useCallback(async () => { setLoading(true); await Promise.all([ fetchSystemMetrics(), fetchApiHealth(), checkWorkflowHealth(), checkIntegrationHealth(), ]); setLastUpdate(new Date()); setLoading(false); }, [fetchSystemMetrics, fetchApiHealth, checkWorkflowHealth, checkIntegrationHealth]); // Initial load and auto-refresh (pause when page not visible) useEffect(() => { let interval: NodeJS.Timeout; const handleVisibilityChange = () => { if (document.hidden) { // Page not visible - clear interval if (interval) clearInterval(interval); } else { // Page visible - refresh and restart interval refreshAll(); interval = setInterval(refreshAll, 30000); } }; // Initial setup refreshAll(); interval = setInterval(refreshAll, 30000); // Listen for visibility changes document.addEventListener('visibilitychange', handleVisibilityChange); return () => { clearInterval(interval); document.removeEventListener('visibilitychange', handleVisibilityChange); }; }, [refreshAll]); // Status badge component const StatusBadge = ({ status }: { status: string }) => { const colors = { healthy: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400', warning: 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400', error: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400', }; const icons = { healthy: CheckCircle, warning: AlertTriangle, error: XCircle, }; const Icon = icons[status as keyof typeof icons] || AlertTriangle; return (
{status.charAt(0).toUpperCase() + status.slice(1)}
); }; // Progress bar component const ProgressBar = ({ value, status }: { value: number; status: string }) => { const colors = { healthy: 'bg-green-500', warning: 'bg-yellow-500', error: 'bg-red-500', }; return (
); }; return ( <>
{/* Header */}

System Status

Master dashboard showing all system health metrics

Last updated: {lastUpdate.toLocaleTimeString()}
{/* System Resources & Services Health */}

System Resources

{/* Compact System Metrics (70% width) */}
{/* CPU */}
CPU
{systemMetrics?.cpu.usage_percent.toFixed(1)}%

{systemMetrics?.cpu.cores} cores

{/* Memory */}
Memory
{systemMetrics?.memory.usage_percent.toFixed(1)}%

{systemMetrics?.memory.used_gb.toFixed(1)}/{systemMetrics?.memory.total_gb.toFixed(1)} GB

{/* Disk */}
Disk
{systemMetrics?.disk.usage_percent.toFixed(1)}%

{systemMetrics?.disk.used_gb.toFixed(1)}/{systemMetrics?.disk.total_gb.toFixed(1)} GB

{/* Services Stack (30% width) */}
PostgreSQL
Redis
Celery
{serviceHealth?.celery.worker_count || 0}w
{/* Site Selector */}
{/* API Health by Module */}

API Module Health

{apiHealth.map((group) => (
{group.name}
{group.percentage}%
{group.healthy}/{group.total} healthy
))}
{/* Content Workflow Health */}

Content Pipeline Status

{workflowHealth.length === 0 ? (

Select a site to view workflow health

) : (
{workflowHealth.map((workflow) => (

{workflow.name}

{workflow.steps.map((step, idx) => (
{step.name} {step.status === 'healthy' ? ( ) : step.status === 'warning' ? ( ) : ( )}
{step.message && (

{step.message}

)} {idx < workflow.steps.length - 1 && (
)}
))}
))}
)}
{/* WordPress Integration */} {integrationHealth && (

WordPress Integration

Connection
Plugin Status
Sync Enabled
Last Sync {integrationHealth.last_sync ? new Date(integrationHealth.last_sync).toLocaleString() : 'Never'}
)}
); }