'use client'; import { useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import * as z from 'zod'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { Avatar, AvatarFallback } from '@/components/ui/avatar'; import { useUser } from '@/components/user-context'; import { ROLE_LABELS } from '@/lib/constants'; import type { User } from '@/types/database'; import { toast } from 'sonner'; import { getErrorMessage } from '@/lib/error-utils'; import { Plus, Pencil, Trash2, Users, Loader2, Crown, Briefcase, User as UserIcon } from 'lucide-react'; const userSchema = z.object({ name: z.string().min(1, '名称不能为空'), role: z.enum(['owner', 'pm', 'member']), }); type UserFormValues = z.infer; const roleIcons = { owner: Crown, pm: Briefcase, member: UserIcon, }; export default function AdminUsersPage() { const { currentUser, users, refreshUsers } = useUser(); const [isLoading, setIsLoading] = useState(false); const [isDialogOpen, setIsDialogOpen] = useState(false); const [editingUser, setEditingUser] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); const form = useForm({ resolver: zodResolver(userSchema), defaultValues: { name: '', role: 'member', }, }); const onSubmit = async (values: UserFormValues) => { setIsSubmitting(true); try { const url = editingUser ? `/api/users/${editingUser.id}` : '/api/users'; const method = editingUser ? 'PATCH' : 'POST'; const res = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(values), }); if (!res.ok) { const data = await res.json(); throw new Error(data.error || '操作失败'); } toast.success(editingUser ? '用户已更新' : '用户已创建'); setIsDialogOpen(false); setEditingUser(null); form.reset(); refreshUsers(); } catch (error) { toast.error(error instanceof Error ? error.message : '操作失败'); } finally { setIsSubmitting(false); } }; const handleEdit = (user: User) => { setEditingUser(user); form.reset({ name: user.name, role: user.role, }); setIsDialogOpen(true); }; const handleDelete = async (userId: string) => { if (!confirm('确定要删除此用户吗?')) return; try { const res = await fetch(`/api/users/${userId}`, { method: 'DELETE' }); if (!res.ok) throw new Error('删除失败'); toast.success('用户已删除'); refreshUsers(); } catch (error) { toast.error(getErrorMessage(error)); } }; const handleDialogClose = () => { setIsDialogOpen(false); setEditingUser(null); form.reset(); }; if (currentUser?.role !== 'owner') { return (

仅老板可访问此页面

); } return (

用户管理

管理系统用户

{editingUser ? '编辑用户' : '新建用户'}
( 名称 * )} /> ( 角色 * )} />
用户 角色 创建时间 操作 {users.map(user => { const RoleIcon = roleIcons[user.role]; return (
{user.name.charAt(0)} {user.name}
{ROLE_LABELS[user.role]}
{new Date(user.created_at).toLocaleDateString('zh-CN')}
); })}
); }