import React from 'react'; import { Box, Typography, Paper, Stack, Button, Chip, CircularProgress, ToggleButtonGroup, ToggleButton } from '@mui/material'; import { apiClient } from '../api/client'; import { useUser } from '@clerk/clerk-react'; type Approval = { id: number; status: string; decision?: string | null; action_id: string; action_type: string; agent_type?: string | null; target_resource?: string | null; risk_level: number; payload?: any; created_at?: string | null; }; export default function ApprovalsPage() { const { user } = useUser(); const [loading, setLoading] = React.useState(false); const [approvals, setApprovals] = React.useState([]); const [error, setError] = React.useState(null); const [detailTier, setDetailTier] = React.useState<'summary' | 'detailed'>('summary'); const canUseDetailed = React.useMemo(() => { const role = String(user?.publicMetadata?.role || '').toLowerCase().trim(); const featureFlags = user?.publicMetadata?.feature_flags as Record | string[] | undefined; const hasFeatureFlag = Array.isArray(featureFlags) ? featureFlags.map((flag) => String(flag).toLowerCase()).includes('agent_activity_detailed') : Boolean(featureFlags && (featureFlags['agent_activity_detailed'] || featureFlags['agents_activity_detailed'])); return role === 'admin' || role === 'internal' || hasFeatureFlag; }, [user]); const loadApprovals = React.useCallback(async () => { setLoading(true); setError(null); try { const tier = canUseDetailed ? detailTier : 'summary'; const resp = await apiClient.get('/api/agents/approvals', { params: { status: 'pending', limit: 50, detail_tier: tier } }); const items = resp?.data?.data?.approvals || []; setApprovals(items); } catch (e: any) { setError(e?.message || 'Failed to load approvals'); } finally { setLoading(false); } }, [canUseDetailed, detailTier]); React.useEffect(() => { loadApprovals(); }, [loadApprovals]); const decide = async (approvalId: number, decision: 'approved' | 'rejected') => { setLoading(true); setError(null); try { await apiClient.post(`/api/agents/approvals/${approvalId}/decision`, { decision }); await loadApprovals(); } catch (e: any) { setError(e?.message || 'Failed to submit decision'); } finally { setLoading(false); } }; return ( Agent Approvals { if (value) { setDetailTier(value); } }} > Basic Detailed {error && ( {error} )} {loading && approvals.length === 0 && ( )} {approvals.length === 0 && !loading && ( No pending approvals. )} {approvals.map((a) => ( = 0.8 ? 'error' : a.risk_level >= 0.6 ? 'warning' : 'default'} /> {a.action_type} {a.target_resource && ( {a.target_resource} )} {detailTier === 'detailed' && a.payload && ( Detailed payload {JSON.stringify(a.payload, null, 2)} )} ))} ); }