'use client' import { useMemo, useState, useEffect } from 'react' import PageLayout from '../../components/PageLayout' import UserDetailModal from '../../components/UserDetailModal' import { MagnifyingGlassIcon, ExclamationTriangleIcon, EyeIcon } from '@heroicons/react/24/outline' import { useAdminUsers } from '../../hooks/useAdminUsers' import { PendingUser } from '../../utils/api' type UserType = 'personal' | 'company' type UserRole = 'user' | 'admin' type VerificationReadyFilter = 'all' | 'ready' | 'not_ready' type StatusFilter = 'all' | 'pending' | 'verifying' | 'active' export default function AdminUserVerifyPage() { const { pendingUsers, loading, error, isAdmin, fetchPendingUsers } = useAdminUsers() const [isClient, setIsClient] = useState(false) // Handle client-side mounting useEffect(() => { setIsClient(true) }, []) const [search, setSearch] = useState('') const [fType, setFType] = useState<'all' | UserType>('all') const [fRole, setFRole] = useState<'all' | UserRole>('all') const [fReady, setFReady] = useState('all') const [fStatus, setFStatus] = useState('all') const [perPage, setPerPage] = useState(10) const [page, setPage] = useState(1) // All computations must be after hooks but before conditional returns const filtered = useMemo(() => { return pendingUsers.filter(u => { const firstName = u.first_name || '' const lastName = u.last_name || '' const companyName = u.company_name || '' const fullName = u.user_type === 'company' ? companyName : `${firstName} ${lastName}` const isReadyToVerify = u.email_verified === 1 && u.profile_completed === 1 && u.documents_uploaded === 1 && u.contract_signed === 1 return ( (fType === 'all' || u.user_type === fType) && (fRole === 'all' || u.role === fRole) && (fStatus === 'all' || u.status === fStatus) && ( fReady === 'all' || (fReady === 'ready' && isReadyToVerify) || (fReady === 'not_ready' && !isReadyToVerify) ) && ( !search.trim() || u.email.toLowerCase().includes(search.toLowerCase()) || fullName.toLowerCase().includes(search.toLowerCase()) ) ) }) }, [pendingUsers, search, fType, fRole, fReady, fStatus]) const totalPages = Math.max(1, Math.ceil(filtered.length / perPage)) const current = filtered.slice((page - 1) * perPage, page * perPage) // Modal state const [isDetailModalOpen, setIsDetailModalOpen] = useState(false) const [selectedUserId, setSelectedUserId] = useState(null) const applyFilters = (e: React.FormEvent) => { e.preventDefault() setPage(1) } const badge = (text: string, color: string) => {text} const typeBadge = (t: UserType) => t === 'personal' ? badge('Personal', 'bg-blue-100 text-blue-700') : badge('Company', 'bg-purple-100 text-purple-700') const roleBadge = (r: UserRole) => r === 'admin' ? badge('Admin', 'bg-indigo-100 text-indigo-700') : badge('User', 'bg-gray-100 text-gray-700') const statusBadge = (s: PendingUser['status']) => { if (s === 'pending') return badge('Pending', 'bg-amber-100 text-amber-700') if (s === 'verifying') return badge('Verifying', 'bg-blue-100 text-blue-700') return badge('Active', 'bg-green-100 text-green-700') } const verificationStatusBadge = (user: PendingUser) => { const steps = [ { name: 'Email', completed: user.email_verified === 1 }, { name: 'Profile', completed: user.profile_completed === 1 }, { name: 'Documents', completed: user.documents_uploaded === 1 }, { name: 'Contract', completed: user.contract_signed === 1 } ] const completedSteps = steps.filter(s => s.completed).length const totalSteps = steps.length if (completedSteps === totalSteps) { return badge('Ready to Verify', 'bg-green-100 text-green-700') } else { return badge(`${completedSteps}/${totalSteps} Steps`, 'bg-gray-100 text-gray-700') } } // Show loading during SSR/initial client render if (!isClient) { return (

Loading...

) } // Access check (only after client-side hydration) if (!isAdmin) { return (

Access Denied

You need admin privileges to access this page.

) } return (
{/* Header */}

User Verification Center

Review and verify all users who need admin approval. Users must complete all steps before verification.

{/* Error Message */} {error && (

Error loading data

{error}

)} {/* Filter Card */}

Search & Filter Pending Users

setSearch(e.target.value)} placeholder="Email, name, company..." className="w-full rounded-lg border border-gray-300 pl-10 pr-3 py-3 text-sm focus:ring-2 focus:ring-blue-900 focus:border-transparent shadow" />
{/* Pending Users Table */}
Users Pending Verification
Showing {current.length} of {filtered.length} users
{loading ? ( ) : current.map(u => { const displayName = u.user_type === 'company' ? u.company_name || 'Unknown Company' : `${u.first_name || 'Unknown'} ${u.last_name || 'User'}` const initials = u.user_type === 'company' ? (u.company_name?.[0] || 'C').toUpperCase() : `${u.first_name?.[0] || 'U'}${u.last_name?.[0] || 'U'}`.toUpperCase() const createdDate = new Date(u.created_at).toLocaleDateString() return ( ) })} {current.length === 0 && !loading && ( )}
User Type Progress Status Role Created Actions
Loading users...
{initials}
{displayName}
{u.email}
{typeBadge(u.user_type)} {verificationStatusBadge(u)} {statusBadge(u.status)} {roleBadge(u.role)} {createdDate}
No unverified users match current filters.
{/* Pagination */}
Page {page} of {totalPages} ({filtered.length} pending users)
{/* User Detail Modal */} { setIsDetailModalOpen(false) setSelectedUserId(null) }} userId={selectedUserId} onUserUpdated={() => { fetchPendingUsers() }} />
) }