diff --git a/src/app/admin/matrix-management/page.tsx b/src/app/admin/matrix-management/page.tsx new file mode 100644 index 0000000..7c6c955 --- /dev/null +++ b/src/app/admin/matrix-management/page.tsx @@ -0,0 +1,306 @@ +'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' + +type Matrix = { + id: string + name: string + status: 'active' | 'inactive' + usersCount: number + createdAt: string + topNodeEmail: string +} + +export default function MatrixManagementPage() { + // Auth guard + const router = useRouter() + const user = useAuthStore(s => s.user) + 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([ + { + id: 'm1', + name: 'Gold Matrix', + status: 'active', + usersCount: 128, + createdAt: new Date(Date.now() - 5 * 24 * 3600 * 1000).toISOString(), + topNodeEmail: 'alice@example.com', + }, + { + id: 'm2', + name: 'Silver Matrix', + status: 'inactive', + usersCount: 64, + createdAt: new Date(Date.now() - 15 * 24 * 3600 * 1000).toISOString(), + topNodeEmail: 'bob@example.com', + }, + { + id: 'm3', + name: 'Bronze Matrix', + status: 'active', + usersCount: 42, + createdAt: new Date(Date.now() - 40 * 24 * 3600 * 1000).toISOString(), + topNodeEmail: 'charlie@example.com', + }, + ]) + + const [createOpen, setCreateOpen] = useState(false) + const [createName, setCreateName] = useState('') + const [createEmail, setCreateEmail] = useState('') + const [formError, setFormError] = useState('') + + const stats = useMemo(() => { + const total = matrices.length + const active = matrices.filter(m => m.status === 'active').length + const totalUsers = matrices.reduce((acc, m) => acc + (m.usersCount || 0), 0) + return { total, active, totalUsers } + }, [matrices]) + + const resetForm = () => { + setCreateName('') + setCreateEmail('') + setFormError('') + } + + const validateEmail = (email: string) => + /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim()) + + const handleCreate = (e: React.FormEvent) => { + e.preventDefault() + const name = createName.trim() + const email = createEmail.trim() + + if (!name) { + setFormError('Please provide a matrix name.') + return + } + if (!email || !validateEmail(email)) { + setFormError('Please provide a valid top-node email.') + return + } + + const newMatrix: Matrix = { + id: `m-${Date.now()}`, + name, + status: 'active', + usersCount: 0, + createdAt: new Date().toISOString(), + topNodeEmail: email, + } + setMatrices(prev => [newMatrix, ...prev]) + setCreateOpen(false) + resetForm() + } + + const toggleStatus = (id: string) => { + setMatrices(prev => + prev.map(m => (m.id === id ? { ...m, status: m.status === 'active' ? 'inactive' : 'active' } : m)) + ) + } + + 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.

+
+ +
+ + {/* Stats */} +
+ + + +
+ + {/* Matrix cards */} +
+ {matrices.map(m => ( +
+
+
+

{m.name}

+ +
+ +
+
+ + {m.usersCount} + users +
+
+ + + {new Date(m.createdAt).toLocaleDateString()} + +
+
+ + {m.topNodeEmail} +
+
+ +
+ + +
+
+
+ ))} +
+
+ + {/* Create Matrix Modal */} + {createOpen && ( +
+
setCreateOpen(false)} /> +
+
+
+

Create New Matrix

+ +
+
+
+ + setCreateName(e.target.value)} + className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent" + placeholder="e.g., Platinum Matrix" + /> +
+
+ + setCreateEmail(e.target.value)} + className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-500 focus:border-transparent" + placeholder="owner@example.com" + /> +
+ {formError && ( +
+ {formError} +
+ )} +
+ + +
+
+
+
+
+ )} +
+ + ) +} diff --git a/src/app/components/nav/Header.tsx b/src/app/components/nav/Header.tsx index 6279fe5..87420d7 100644 --- a/src/app/components/nav/Header.tsx +++ b/src/app/components/nav/Header.tsx @@ -411,6 +411,13 @@ export default function Header() { > User Verify + {/* NEW: Matrix Management link */} +
diff --git a/src/app/quickaction-dashboard/page.tsx b/src/app/quickaction-dashboard/page.tsx index a18b6a4..5590b6f 100644 --- a/src/app/quickaction-dashboard/page.tsx +++ b/src/app/quickaction-dashboard/page.tsx @@ -124,52 +124,20 @@ export default function QuickActionDashboardPage() { return ( -
- {/* Background Pattern */} - - {/* Colored Blur Effect */} -