'use client' import { useEffect, useState } from 'react' import { useParams, useRouter } from 'next/navigation' import Link from 'next/link' import { trpc } from '@/lib/trpc/client' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { Skeleton } from '@/components/ui/skeleton' import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { toast } from 'sonner' import { TagInput } from '@/components/shared/tag-input' import { UserActivityLog } from '@/components/shared/user-activity-log' import { ArrowLeft, Save, Mail, User, Shield, Loader2, AlertCircle, } from 'lucide-react' export default function MemberDetailPage() { const params = useParams() const router = useRouter() const userId = params.id as string const { data: user, isLoading, refetch } = trpc.user.get.useQuery({ id: userId }) const updateUser = trpc.user.update.useMutation() const sendInvitation = trpc.user.sendInvitation.useMutation() // Mentor assignments (only fetched for mentors) const { data: mentorAssignments } = trpc.mentor.listAssignments.useQuery( { mentorId: userId, page: 1, perPage: 50 }, { enabled: user?.role === 'MENTOR' } ) const [name, setName] = useState('') const [role, setRole] = useState('JURY_MEMBER') const [status, setStatus] = useState('INVITED') const [expertiseTags, setExpertiseTags] = useState([]) const [maxAssignments, setMaxAssignments] = useState('') useEffect(() => { if (user) { setName(user.name || '') setRole(user.role) setStatus(user.status) setExpertiseTags(user.expertiseTags || []) setMaxAssignments(user.maxAssignments?.toString() || '') } }, [user]) const handleSave = async () => { try { await updateUser.mutateAsync({ id: userId, name: name || null, role: role as 'JURY_MEMBER' | 'MENTOR' | 'OBSERVER' | 'PROGRAM_ADMIN', status: status as 'INVITED' | 'ACTIVE' | 'SUSPENDED', expertiseTags, maxAssignments: maxAssignments ? parseInt(maxAssignments) : null, }) toast.success('Member updated successfully') router.push('/admin/members') } catch (error) { toast.error(error instanceof Error ? error.message : 'Failed to update member') } } const handleSendInvitation = async () => { try { await sendInvitation.mutateAsync({ userId }) toast.success('Invitation email sent successfully') refetch() } catch (error) { toast.error(error instanceof Error ? error.message : 'Failed to send invitation') } } if (isLoading) { return (
) } if (!user) { return (
Member not found The member you're looking for does not exist.
) } return (
{/* Header */}

{user.name || 'Unnamed Member'}

{user.email}

{user.status}
{user.status === 'INVITED' && ( )}
{/* Basic Info */} Basic Information
setName(e.target.value)} placeholder="Enter name" />
{/* Expertise & Capacity */} Expertise & Capacity
setMaxAssignments(e.target.value)} placeholder="Unlimited" />
{user._count && (

Statistics

Jury Assignments

{user._count.assignments}

Mentor Assignments

{user._count.mentorAssignments}

)}
{/* Mentor Assignments Section */} {user.role === 'MENTOR' && mentorAssignments && mentorAssignments.assignments.length > 0 && ( Mentored Projects Projects this mentor is assigned to Project Category Status Assigned {mentorAssignments.assignments.map((assignment) => ( {assignment.project.title} {assignment.project.teamName && (

{assignment.project.teamName}

)}
{assignment.project.competitionCategory ? ( {assignment.project.competitionCategory.replace('_', ' ')} ) : ( '-' )} {assignment.project.roundProjects?.[0]?.status ?? 'SUBMITTED'} {new Date(assignment.assignedAt).toLocaleDateString()}
))}
)} {/* Activity Log */} {/* Status Alert */} {user.status === 'INVITED' && ( Invitation Pending This member hasn't accepted their invitation yet. You can resend the invitation email using the button above. )} {/* Save Button */}
) }