212 lines
6.6 KiB
TypeScript
212 lines
6.6 KiB
TypeScript
'use client';
|
|
import { useEffect } from 'react';
|
|
import { useForm, Controller } from 'react-hook-form';
|
|
import { useOrgStore } from '../store';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Input } from '@/components/ui/input';
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from '@/components/ui/select';
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from '@/components/ui/table';
|
|
import {
|
|
Drawer,
|
|
DrawerContent,
|
|
DrawerHeader,
|
|
DrawerTitle,
|
|
DrawerClose,
|
|
} from '@/components/ui/drawer';
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from '@/components/ui/dialog';
|
|
import { Plus, Trash2, X } from 'lucide-react';
|
|
|
|
interface UserDrawerProps {
|
|
open: boolean;
|
|
onOpenChange: (open: boolean) => void;
|
|
}
|
|
|
|
export const UserDrawer = ({ open, onOpenChange }: UserDrawerProps) => {
|
|
const {
|
|
orgId,
|
|
users,
|
|
getOrg,
|
|
addUser,
|
|
removeUser,
|
|
setUserFormData: setUserFormData,
|
|
userFormData,
|
|
showUserEdit,
|
|
setShowUserEdit,
|
|
} = useOrgStore();
|
|
|
|
const {
|
|
handleSubmit,
|
|
formState: { errors },
|
|
reset,
|
|
register,
|
|
control,
|
|
} = useForm();
|
|
|
|
useEffect(() => {
|
|
if (open && orgId) {
|
|
getOrg();
|
|
}
|
|
}, [open, orgId, getOrg]);
|
|
|
|
useEffect(() => {
|
|
if (!showUserEdit) return;
|
|
// 确保 userFormData 已更新后再重置表单
|
|
console.log('Resetting form with userFormData:', userFormData);
|
|
if (userFormData?.id) {
|
|
reset({ id: userFormData.id, username: userFormData.username, role: userFormData.role || 'member' });
|
|
} else {
|
|
reset({ id: '', username: '', role: 'member' });
|
|
}
|
|
}, [showUserEdit, userFormData, reset]);
|
|
|
|
const handleAddUser = async (data: any) => {
|
|
const res = await addUser({ ...data, action: 'add' });
|
|
if (res.code === 200) {
|
|
setShowUserEdit(false);
|
|
setUserFormData({});
|
|
}
|
|
};
|
|
|
|
const handleRemoveUser = async (uid: string) => {
|
|
await removeUser(uid);
|
|
};
|
|
|
|
const handleEditUser = (user: any) => {
|
|
console.log('Editing user:', user);
|
|
setUserFormData(user);
|
|
// 使用 setTimeout 确保 userFormData 更新后再打开弹窗
|
|
setShowUserEdit(true);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Drawer open={open} onOpenChange={onOpenChange} direction="right">
|
|
<DrawerContent className="h-full !max-w-xl ml-auto">
|
|
<DrawerHeader className="flex flex-row items-center justify-between">
|
|
<DrawerTitle>用户管理</DrawerTitle>
|
|
<DrawerClose>
|
|
<Button variant="ghost" size="icon-sm">
|
|
<X className="w-4 h-4" />
|
|
</Button>
|
|
</DrawerClose>
|
|
</DrawerHeader>
|
|
|
|
<div className="flex gap-2 mb-4 px-4">
|
|
<Button
|
|
size="sm"
|
|
onClick={() => {
|
|
setUserFormData({});
|
|
setShowUserEdit(true);
|
|
}}>
|
|
<Plus className="w-4 h-4 mr-1" />
|
|
添加用户
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="flex-1 overflow-auto px-4">
|
|
<Table>
|
|
<TableHeader>
|
|
<TableRow>
|
|
<TableHead>用户ID</TableHead>
|
|
<TableHead>用户名</TableHead>
|
|
<TableHead>角色</TableHead>
|
|
<TableHead>操作</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{users.map((user) => (
|
|
<TableRow key={user.id}>
|
|
<TableCell>{user.id}</TableCell>
|
|
<TableCell>{user.username}</TableCell>
|
|
<TableCell>{user.role || 'member'}</TableCell>
|
|
<TableCell className="flex gap-2">
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={() => handleEditUser(user)}>
|
|
编辑
|
|
</Button>
|
|
<Button
|
|
variant="destructive"
|
|
size="sm"
|
|
onClick={() => handleRemoveUser(user.id)}>
|
|
<Trash2 className="w-4 h-4" />
|
|
</Button>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
</DrawerContent>
|
|
</Drawer>
|
|
|
|
<Dialog open={showUserEdit} onOpenChange={setShowUserEdit}>
|
|
<DialogContent className='px-4 overflow-hidden'>
|
|
<DialogHeader>
|
|
<DialogTitle>{userFormData?.id ? '编辑用户' : '添加用户'}</DialogTitle>
|
|
</DialogHeader>
|
|
<div className="p-4 ">
|
|
<form className="w-full flex flex-col gap-4" onSubmit={handleSubmit(handleAddUser)}>
|
|
<div className="flex flex-col gap-2">
|
|
<label className="text-sm font-medium">用户ID</label>
|
|
<Input
|
|
{...register('id', { required: '请输入用户ID' })}
|
|
placeholder="请输入用户ID"
|
|
className={errors.id ? "border-red-500" : ""}
|
|
/>
|
|
{errors.id && <span className="text-xs text-red-500">{errors.id.message as string}</span>}
|
|
</div>
|
|
<div>{userFormData?.username}</div>
|
|
<Controller
|
|
control={control}
|
|
name="role"
|
|
defaultValue={userFormData?.role || 'member'}
|
|
render={({ field }) => (
|
|
<div className="flex flex-col gap-2">
|
|
<label className="text-sm font-medium">角色</label>
|
|
<Select value={field.value} onValueChange={field.onChange}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="请选择角色" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="owner">owner</SelectItem>
|
|
<SelectItem value="admin">admin</SelectItem>
|
|
<SelectItem value="member">member</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
)}
|
|
/>
|
|
<div className="flex gap-2 justify-end">
|
|
<Button type="button" variant="outline" onClick={() => setShowUserEdit(false)}>
|
|
取消
|
|
</Button>
|
|
<Button type="submit">提交</Button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</>
|
|
);
|
|
};
|