diff --git a/components/admin/admin-panel.tsx b/components/admin/admin-panel.tsx index 0352738..a0808d2 100644 --- a/components/admin/admin-panel.tsx +++ b/components/admin/admin-panel.tsx @@ -15,7 +15,7 @@ export function AdminPanel() { const renderPage = () => { switch (currentPage) { case "dashboard": - return + return case "users": return case "apps": @@ -27,7 +27,7 @@ export function AdminPanel() { case "settings": return default: - return + return } } diff --git a/components/admin/dashboard.tsx b/components/admin/dashboard.tsx index fac3bdd..3705c35 100644 --- a/components/admin/dashboard.tsx +++ b/components/admin/dashboard.tsx @@ -20,9 +20,19 @@ const recentActivities: any[] = [] const topApps: any[] = [] -export function AdminDashboard() { +interface AdminDashboardProps { + onPageChange?: (page: string) => void +} + +export function AdminDashboard({ onPageChange }: AdminDashboardProps) { const { competitions } = useCompetition() + const handleManageUsers = () => { + if (onPageChange) { + onPageChange("users") + } + } + return (
{/* Welcome Section */} @@ -150,7 +160,7 @@ export function AdminDashboard() {
- diff --git a/components/admin/user-management.tsx b/components/admin/user-management.tsx index 4dc9640..dea6bbf 100644 --- a/components/admin/user-management.tsx +++ b/components/admin/user-management.tsx @@ -13,6 +13,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu" import { Label } from "@/components/ui/label" import { Alert, AlertDescription } from "@/components/ui/alert" +import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from "@/components/ui/pagination" import { Search, MoreHorizontal, @@ -67,6 +68,12 @@ export function UserManagement() { totalApps: 0, totalReviews: 0 }) + + // Pagination state + const [currentPage, setCurrentPage] = useState(1) + const [totalPages, setTotalPages] = useState(1) + const [totalUsers, setTotalUsers] = useState(0) + const [itemsPerPage] = useState(10) // Default to 10 items per page // 載入用戶資料 useEffect(() => { @@ -74,8 +81,8 @@ export function UserManagement() { try { setIsLoading(true) - // 獲取用戶列表 - const usersResponse = await fetch('/api/users', { + // 獲取用戶列表 with pagination + const usersResponse = await fetch(`/api/users?page=${currentPage}&limit=${itemsPerPage}`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } @@ -84,6 +91,8 @@ export function UserManagement() { if (usersResponse.ok) { const usersData = await usersResponse.json() setUsers(usersData.users || []) + setTotalPages(usersData.pagination?.totalPages || 1) + setTotalUsers(usersData.pagination?.total || 0) } else { const errorData = await usersResponse.json().catch(() => ({})) console.error('獲取用戶列表失敗:', errorData.error || usersResponse.statusText) @@ -105,14 +114,15 @@ export function UserManagement() { console.error('獲取統計資料失敗:', errorData.error || statsResponse.statusText) } } catch (error) { - console.error('載入資料失敗:', error) + console.error('載入用戶資料失敗:', error) + setError('載入用戶資料失敗') } finally { setIsLoading(false) } } fetchUsers() - }, []) + }, [currentPage, itemsPerPage]) // Re-fetch when page changes // 重新獲取統計數據的函數 const refreshStats = async () => { @@ -734,8 +744,11 @@ export function UserManagement() { {/* Users Table */} - 用戶列表 ({filteredUsers.length}) - 管理所有平台用戶 + 用戶列表 ({totalUsers} 總用戶) + + 管理所有平台用戶 - 第 {currentPage} 頁,共 {totalPages} 頁 + {totalPages > 1 && ` (每頁 ${itemsPerPage} 筆)`} + {isLoading ? ( @@ -859,6 +872,66 @@ export function UserManagement() { + {/* Pagination */} + {totalPages > 1 && ( +
+ + + + { + e.preventDefault() + if (currentPage > 1) setCurrentPage(currentPage - 1) + }} + className={currentPage === 1 ? "pointer-events-none opacity-50" : ""} + /> + + + {/* Page numbers */} + {Array.from({ length: Math.min(5, totalPages) }, (_, i) => { + let pageNum + if (totalPages <= 5) { + pageNum = i + 1 + } else if (currentPage <= 3) { + pageNum = i + 1 + } else if (currentPage >= totalPages - 2) { + pageNum = totalPages - 4 + i + } else { + pageNum = currentPage - 2 + i + } + + return ( + + { + e.preventDefault() + setCurrentPage(pageNum) + }} + isActive={currentPage === pageNum} + > + {pageNum} + + + ) + })} + + + { + e.preventDefault() + if (currentPage < totalPages) setCurrentPage(currentPage + 1) + }} + className={currentPage === totalPages ? "pointer-events-none opacity-50" : ""} + /> + + + +
+ )} + {/* Invite User Dialog - 包含角色選擇 */}