"use client" import { useState, useEffect } from "react" import { ProtectedRoute } from "@/components/protected-route" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { Badge } from "@/components/ui/badge" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" import { Alert, AlertDescription } from "@/components/ui/alert" import { Plus, Edit, Trash2, ArrowLeft, Eye, EyeOff, ChevronLeft, ChevronRight } from "lucide-react" import Link from "next/link" import { useAuth, type User } from "@/lib/hooks/use-auth" export default function UsersManagementPage() { return ( ) } function UsersManagementContent() { const { user: currentUser } = useAuth() const [users, setUsers] = useState<(User & { password?: string })[]>([]) const [isAddDialogOpen, setIsAddDialogOpen] = useState(false) const [editingUser, setEditingUser] = useState(null) const [deletingUser, setDeletingUser] = useState(null) const [showPassword, setShowPassword] = useState(false) const [newUser, setNewUser] = useState({ name: "", email: "", password: "", department: "", role: "user" as "user" | "admin", }) const [error, setError] = useState("") // 分頁相關狀態 const [currentPage, setCurrentPage] = useState(1) const [totalPages, setTotalPages] = useState(1) const [totalUsers, setTotalUsers] = useState(0) const [adminCount, setAdminCount] = useState(0) const [userCount, setUserCount] = useState(0) const usersPerPage = 5 const departments = ["人力資源部", "資訊技術部", "財務部", "行銷部", "業務部", "研發部", "客服部", "其他"] useEffect(() => { loadUsers() }, []) const loadUsers = async (page: number = 1) => { try { const response = await fetch(`/api/admin/users?page=${page}&limit=${usersPerPage}`) const data = await response.json() if (data.success) { setUsers(data.data.users) setTotalPages(data.data.totalPages) setTotalUsers(data.data.totalUsers) setCurrentPage(page) // 更新統計數據 setAdminCount(data.data.adminCount) setUserCount(data.data.userCount) } else { setError(data.error || '載入用戶列表失敗') } } catch (err) { console.error('載入用戶列表錯誤:', err) setError('載入用戶列表時發生錯誤') } } const handleAddUser = async () => { setError("") if (!newUser.name || !newUser.email || !newUser.password || !newUser.department) { setError("請填寫所有必填欄位") return } try { const response = await fetch('/api/admin/users', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(newUser), }) const data = await response.json() if (data.success) { // 重新載入用戶列表 await loadUsers(currentPage) setNewUser({ name: "", email: "", password: "", department: "", role: "user", }) setIsAddDialogOpen(false) } else { setError(data.error || '創建用戶失敗') } } catch (err) { console.error('創建用戶錯誤:', err) setError('創建用戶時發生錯誤') } } const handleEditUser = (user: User) => { setEditingUser(user) setNewUser({ name: user.name, email: user.email, password: "", department: user.department, role: user.role, }) } const handleUpdateUser = async () => { if (!editingUser) return setError("") if (!newUser.name || !newUser.email || !newUser.department) { setError("請填寫所有必填欄位") return } try { const updateData: any = { id: editingUser.id, name: newUser.name, email: newUser.email, department: newUser.department, role: newUser.role, } const response = await fetch('/api/admin/users', { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(updateData), }) const data = await response.json() if (data.success) { // 重新載入用戶列表 await loadUsers(currentPage) setEditingUser(null) setNewUser({ name: "", email: "", password: "", department: "", role: "user", }) } else { setError(data.error || '更新用戶失敗') } } catch (err) { console.error('更新用戶錯誤:', err) setError('更新用戶時發生錯誤') } } const handleDeleteUser = (user: User) => { if (user.id === currentUser?.id) { setError("無法刪除自己的帳戶") return } setDeletingUser(user) } const confirmDeleteUser = async () => { if (!deletingUser) return try { const response = await fetch(`/api/admin/users?id=${deletingUser.id}`, { method: 'DELETE', }) const data = await response.json() if (data.success) { // 重新載入用戶列表 await loadUsers(currentPage) setDeletingUser(null) } else { setError(data.error || '刪除用戶失敗') } } catch (err) { console.error('刪除用戶錯誤:', err) setError('刪除用戶時發生錯誤') } } // 分頁控制函數 const handlePageChange = (page: number) => { if (page >= 1 && page <= totalPages) { loadUsers(page) } } const handlePreviousPage = () => { if (currentPage > 1) { handlePageChange(currentPage - 1) } } const handleNextPage = () => { if (currentPage < totalPages) { handlePageChange(currentPage + 1) } } return ( {/* Header */} 返回儀表板 用戶管理 管理系統用戶和權限 {/* Stats */} 總用戶數 {totalUsers} 管理員 {adminCount} 一般用戶 {userCount} {/* Users Table */} 用戶列表 管理系統中的所有用戶 新增用戶 新增用戶 建立新的系統用戶帳戶 姓名 setNewUser({ ...newUser, name: e.target.value })} placeholder="請輸入姓名" /> 電子郵件 setNewUser({ ...newUser, email: e.target.value })} placeholder="請輸入電子郵件" /> 密碼 setNewUser({ ...newUser, password: e.target.value })} placeholder="請輸入密碼或使用預設密碼" className="pr-10" /> setShowPassword(!showPassword)} className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent" > {showPassword ? ( ) : ( )} setNewUser({ ...newUser, password: "password123" })} className="whitespace-nowrap" > 使用預設密碼 預設密碼:password123(建議用戶首次登入後修改) 部門 setNewUser({ ...newUser, department: value })} > {departments.map((dept) => ( {dept} ))} 角色 setNewUser({ ...newUser, role: value })} > 一般用戶 管理員 {error && ( {error} )} 新增用戶 setIsAddDialogOpen(false)} className="flex-1"> 取消 姓名 電子郵件 部門 角色 建立時間 操作 {users.map((user) => ( {user.name} {user.email} {user.department} {user.role === "admin" ? "管理員" : "一般用戶"} {new Date(user.createdAt).toLocaleDateString("zh-TW")} handleEditUser(user)}> {user.id !== currentUser?.id && ( handleDeleteUser(user)}> )} ))} {/* Pagination */} {totalPages > 1 && ( 顯示第 {((currentPage - 1) * usersPerPage) + 1} - {Math.min(currentPage * usersPerPage, totalUsers)} 筆,共 {totalUsers} 筆 {/* Desktop Pagination */} 上一頁 {Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => ( handlePageChange(page)} className="w-8 h-8 p-0" > {page} ))} 下一頁 {/* Mobile Pagination */} 上一頁 {(() => { const maxVisiblePages = 3 const startPage = Math.max(1, currentPage - 1) const endPage = Math.min(totalPages, startPage + maxVisiblePages - 1) const pages = [] // 如果不在第一頁,顯示第一頁和省略號 if (startPage > 1) { pages.push( handlePageChange(1)} className="w-8 h-8 p-0" > 1 ) if (startPage > 2) { pages.push( ... ) } } // 顯示當前頁附近的頁碼 for (let i = startPage; i <= endPage; i++) { pages.push( handlePageChange(i)} className="w-8 h-8 p-0" > {i} ) } // 如果不在最後一頁,顯示省略號和最後一頁 if (endPage < totalPages) { if (endPage < totalPages - 1) { pages.push( ... ) } pages.push( handlePageChange(totalPages)} className="w-8 h-8 p-0" > {totalPages} ) } return pages })()} 下一頁 )} {/* Edit User Dialog */} setEditingUser(null)}> 編輯用戶 修改用戶資訊和權限 姓名 setNewUser({ ...newUser, name: e.target.value })} placeholder="請輸入姓名" /> 電子郵件 setNewUser({ ...newUser, email: e.target.value })} placeholder="請輸入電子郵件" /> 部門 setNewUser({ ...newUser, department: value })} > {departments.map((dept) => ( {dept} ))} 角色 setNewUser({ ...newUser, role: value })} > 一般用戶 管理員 {error && ( {error} )} 更新用戶 setEditingUser(null)} className="flex-1"> 取消 {/* Delete Confirmation Dialog */} setDeletingUser(null)}> 確認刪除用戶 此操作無法復原。您確定要刪除以下用戶嗎? {deletingUser && ( 姓名: {deletingUser.name} 電子郵件: {deletingUser.email} 部門: {deletingUser.department} 角色: {deletingUser.role === "admin" ? "管理員" : "一般用戶"} 警告 刪除用戶後,該用戶的所有測試記錄和相關資料也將被永久刪除。 )} setDeletingUser(null)} className="flex-1" > 取消 確認刪除 ) }
管理系統用戶和權限
預設密碼:password123(建議用戶首次登入後修改)
警告
刪除用戶後,該用戶的所有測試記錄和相關資料也將被永久刪除。