'use client' import React, { useMemo, useState, useEffect } from 'react' import { ChartBarIcon, CheckCircleIcon, UsersIcon, PlusIcon, EnvelopeIcon, CalendarDaysIcon, } from '@heroicons/react/24/outline' import PageLayout from '../../components/PageLayout' import { useRouter } from 'next/navigation' import useAuthStore from '../../store/authStore' import { createMatrix } from './hooks/createMatrix' import { getMatrixStats } from './hooks/getMatrixStats' import { deactivateMatrix, activateMatrix } from './hooks/changeMatrixState' // NEW type Matrix = { id: string name: string status: 'active' | 'inactive' usersCount: number createdAt: string topNodeEmail: string rootUserId: number // added policyMaxDepth?: number | null // NEW } export default function MatrixManagementPage() { const router = useRouter() const user = useAuthStore(s => s.user) const token = useAuthStore(s => s.accessToken) const isAdmin = !!user && ( (user as any)?.role === 'admin' || (user as any)?.userType === 'admin' || (user as any)?.isAdmin === true || ((user as any)?.roles?.includes?.('admin')) ) useEffect(() => { if (user === null) { router.push('/login') } else if (user && !isAdmin) { router.push('/') } }, [user, isAdmin, router]) const [matrices, setMatrices] = useState([]) const [stats, setStats] = useState({ total: 0, active: 0, totalUsers: 0 }) const [statsLoading, setStatsLoading] = useState(false) const [statsError, setStatsError] = useState('') const [createOpen, setCreateOpen] = useState(false) const [createName, setCreateName] = useState('') const [createEmail, setCreateEmail] = useState('') const [formError, setFormError] = useState('') const [createLoading, setCreateLoading] = useState(false) const [forcePrompt, setForcePrompt] = useState<{ name: string; email: string } | null>(null) const [createSuccess, setCreateSuccess] = useState<{ name: string; email: string } | null>(null) const [policyFilter, setPolicyFilter] = useState<'unlimited'|'five'>('unlimited') // NEW const [sortByUsers, setSortByUsers] = useState<'asc'|'desc'>('desc') // NEW const [mutatingId, setMutatingId] = useState(null) // NEW const loadStats = async () => { if (!token) return setStatsLoading(true) setStatsError('') try { const res = await getMatrixStats({ token }) console.log('📊 MatrixManagement: GET /matrix/stats ->', res.status, res.body) if (res.ok) { const payload = res.body?.data || res.body || {} const apiMatrices: any[] = Array.isArray(payload.matrices) ? payload.matrices : [] const mapped: Matrix[] = apiMatrices.map((m: any, idx: number) => { const isActive = !!m?.isActive const createdAt = m?.createdAt || m?.ego_activated_at || m?.activatedAt || new Date().toISOString() const topNodeEmail = m?.topNodeEmail || m?.masterTopUserEmail || m?.email || '' const rootUserId = Number(m?.rootUserId ?? m?.root_user_id ?? 0) const matrixId = m?.matrixId ?? m?.id // prefer matrixId for routing const maxDepth = (m?.maxDepth ?? m?.policyMaxDepth) // backend optional return { id: String(matrixId ?? `m-${idx}`), name: String(m?.name ?? 'Unnamed Matrix'), status: isActive ? 'active' : 'inactive', usersCount: Number(m?.usersCount ?? 0), createdAt: String(createdAt), topNodeEmail: String(topNodeEmail), rootUserId, policyMaxDepth: typeof maxDepth === 'number' ? maxDepth : null // NEW } }) setMatrices(mapped) const activeMatrices = Number(payload.activeMatrices ?? mapped.filter(m => m.status === 'active').length) const totalMatrices = Number(payload.totalMatrices ?? mapped.length) const totalUsersSubscribed = Number(payload.totalUsersSubscribed ?? 0) setStats({ total: totalMatrices, active: activeMatrices, totalUsers: totalUsersSubscribed }) console.log('✅ MatrixManagement: mapped stats:', { total: totalMatrices, active: activeMatrices, totalUsers: totalUsersSubscribed }) console.log('✅ MatrixManagement: mapped matrices sample:', mapped.slice(0, 3)) } else { setStatsError(res.message || 'Failed to load matrix stats.') } } catch (e) { console.error('❌ MatrixManagement: stats load error', e) setStatsError('Network error while loading matrix stats.') } finally { setStatsLoading(false) } } useEffect(() => { loadStats() }, [token]) const resetForm = () => { setCreateName('') setCreateEmail('') setFormError('') setForcePrompt(null) setCreateSuccess(null) } const validateEmail = (email: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim()) const handleCreate = async (e: React.FormEvent) => { e.preventDefault() const name = createName.trim() const email = createEmail.trim() setFormError('') setCreateSuccess(null) setForcePrompt(null) if (!name) { setFormError('Please provide a matrix name.') return } if (!email || !validateEmail(email)) { setFormError('Please provide a valid top-node email.') return } if (!token) { setFormError('Not authenticated. Please log in again.') return } setCreateLoading(true) try { const res = await createMatrix({ token, name, email }) console.log('🧱 MatrixManagement: create result ->', res.status, res.body) if (res.ok && res.body?.success) { const createdName = res.body?.data?.name || name const createdEmail = res.body?.data?.masterTopUserEmail || email setCreateSuccess({ name: createdName, email: createdEmail }) await loadStats() setCreateName('') setCreateEmail('') } else if (res.status === 409) { setForcePrompt({ name, email }) } else { setFormError(res.message || 'Failed to create matrix.') } } catch (err) { setFormError('Network error while creating the matrix.') } finally { setCreateLoading(false) } } const confirmForce = async () => { if (!forcePrompt || !token) return setFormError('') setCreateLoading(true) try { const res = await createMatrix({ token, name: forcePrompt.name, email: forcePrompt.email, force: true }) console.log('🧱 MatrixManagement: force-create result ->', res.status, res.body) if (res.ok && res.body?.success) { const createdName = res.body?.data?.name || forcePrompt.name const createdEmail = res.body?.data?.masterTopUserEmail || forcePrompt.email setCreateSuccess({ name: createdName, email: createdEmail }) setForcePrompt(null) setCreateName('') setCreateEmail('') await loadStats() } else { setFormError(res.message || 'Failed to create matrix (force).') } } catch { setFormError('Network error while forcing the matrix creation.') } finally { setCreateLoading(false) } } const toggleStatus = async (id: string) => { try { const target = matrices.find(m => m.id === id) if (!target) return setStatsError('') setMutatingId(id) if (target.status === 'active') { await deactivateMatrix(id) } else { await activateMatrix(id) } await loadStats() } catch (e: any) { setStatsError(e?.message || 'Failed to change matrix state.') } finally { setMutatingId(null) } } // derived list with filter/sort (always apply selected filter) const matricesView = useMemo(() => { let list = [...matrices] list = list.filter(m => { const unlimited = !m.policyMaxDepth || m.policyMaxDepth <= 0 return policyFilter === 'unlimited' ? unlimited : (!unlimited && m.policyMaxDepth === 5) }) list.sort((a,b) => sortByUsers === 'asc' ? (a.usersCount - b.usersCount) : (b.usersCount - a.usersCount)) return list }, [matrices, policyFilter, sortByUsers]) const StatCard = ({ icon: Icon, label, value, color, }: { icon: any label: string value: number color: string }) => (

{label}

{value}
) const StatusBadge = ({ status }: { status: Matrix['status'] }) => ( {status.charAt(0).toUpperCase() + status.slice(1)} ) return (
{/* Header + Create */}

Matrix Management

Manage matrices, see stats, and create new ones.

{/* Error banner for stats */} {statsError && (
{statsError}
)} {/* Stats */}
{/* Matrix cards */}
{statsLoading ? ( Array.from({ length: 3 }).map((_, i) => (
)) ) : matricesView.length === 0 ? (
No matrices found.
) : ( matricesView.map(m => (

{m.name}

Max depth: {(!m.policyMaxDepth || m.policyMaxDepth <= 0) ? 'Unlimited' : m.policyMaxDepth}
{m.usersCount} users
{new Date(m.createdAt).toLocaleDateString()}
{m.topNodeEmail}
)) )}
{/* Create Matrix Modal */} {createOpen && (
{ setCreateOpen(false); resetForm() }} />

Create Matrix

{/* Success banner */} {createSuccess && (
Matrix created successfully.
Name: {createSuccess.name}{' '} Top node: {createSuccess.email}
)} {/* 409 force prompt */} {forcePrompt && (
A matrix configuration already exists for this selection.
)} {/* Form fields */}
setCreateName(e.target.value)} disabled={createLoading} className="w-full rounded-lg border border-gray-300 px-4 py-3 text-sm focus:ring-2 focus:ring-blue-900 focus:border-transparent disabled:bg-gray-100" placeholder="e.g., Platinum Matrix" />
setCreateEmail(e.target.value)} disabled={createLoading} className="w-full rounded-lg border border-gray-300 px-4 py-3 text-sm focus:ring-2 focus:ring-blue-900 focus:border-transparent disabled:bg-gray-100" placeholder="owner@example.com" />
{formError && (
{formError}
)}
)}
) }