'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 { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { Skeleton } from '@/components/ui/skeleton' import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert' import { toast } from 'sonner' import { TagInput } from '@/components/shared/tag-input' import { ArrowLeft, Save, Mail, User, Shield, Loader2, CheckCircle, AlertCircle, } from 'lucide-react' export default function UserEditPage() { 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() const [name, setName] = useState('') const [role, setRole] = useState<'JURY_MEMBER' | 'OBSERVER' | 'PROGRAM_ADMIN'>('JURY_MEMBER') const [status, setStatus] = useState<'INVITED' | 'ACTIVE' | 'SUSPENDED'>('INVITED') const [expertiseTags, setExpertiseTags] = useState([]) const [maxAssignments, setMaxAssignments] = useState('') // Populate form when user data loads useEffect(() => { if (user) { setName(user.name || '') setRole(user.role as 'JURY_MEMBER' | 'OBSERVER' | 'PROGRAM_ADMIN') setStatus(user.status as 'INVITED' | 'ACTIVE' | 'SUSPENDED') setExpertiseTags(user.expertiseTags || []) setMaxAssignments(user.maxAssignments?.toString() || '') } }, [user]) const handleSave = async () => { try { await updateUser.mutateAsync({ id: userId, name: name || null, role, status, expertiseTags, maxAssignments: maxAssignments ? parseInt(maxAssignments) : null, }) toast.success('User updated successfully') router.push('/admin/users') } catch (error) { toast.error(error instanceof Error ? error.message : 'Failed to update user') } } 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 (
User not found The user you're looking for does not exist.
) } return (
{/* Header */}

Edit User

{user.email}

{user.status === 'INVITED' && ( )}
{/* Basic Info */} Basic Information Update the user's profile information

Email cannot be changed

setName(e.target.value)} placeholder="Enter name" />
{/* Assignment Settings */} Assignment Settings Configure expertise tags and assignment limits
setMaxAssignments(e.target.value)} placeholder="Unlimited" />

Maximum number of projects this user can be assigned

{user._count && (

Statistics

Total Assignments

{user._count.assignments}

Last Login

{user.lastLoginAt ? new Date(user.lastLoginAt).toLocaleDateString() : 'Never'}

)}
{/* Status Alert */} {user.status === 'INVITED' && ( Invitation Pending This user hasn't accepted their invitation yet. You can resend the invitation email using the button above. )} {/* Save Button */}
) }