161 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // File: frontend/app/(protected)/admin/users/page.jsx
 | |
| 'use client';
 | |
| 
 | |
| import { useState, useEffect } from 'react';
 | |
| import { PlusCircle, MoreHorizontal } from 'lucide-react';
 | |
| import api from '@/lib/api';
 | |
| import { Button } from '@/components/ui/button';
 | |
| import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
 | |
| import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
 | |
| import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
 | |
| import { Badge } from '@/components/ui/badge';
 | |
| 
 | |
| // Import components ที่เราเพิ่งสร้าง
 | |
| import { UserFormDialog } from '../_components/user-form-dialog';
 | |
| import { ConfirmDeleteDialog } from '../_components/confirm-delete-dialog';
 | |
| 
 | |
| 
 | |
| export default function UsersPage() {
 | |
|   const [users, setUsers] = useState([]);
 | |
|   const [loading, setLoading] = useState(true);
 | |
|   
 | |
|   // State สำหรับควบคุม Dialog ทั้งหมด
 | |
|   const [isFormOpen, setIsFormOpen] = useState(false);
 | |
|   const [isDeleteOpen, setIsDeleteOpen] = useState(false);
 | |
|   const [selectedUser, setSelectedUser] = useState(null);
 | |
|   const [isSubmitting, setIsSubmitting] = useState(false);
 | |
| 
 | |
|   // Function สำหรับดึงข้อมูลใหม่
 | |
|   const fetchUsers = async () => {
 | |
|     try {
 | |
|       setLoading(true);
 | |
|       const res = await api.get('/users');
 | |
|       setUsers(res.data);
 | |
|     } catch (error) {
 | |
|       console.error("Failed to fetch users", error);
 | |
|     } finally {
 | |
|       setLoading(false);
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   useEffect(() => {
 | |
|     fetchUsers();
 | |
|   }, []);
 | |
| 
 | |
|   // Handlers สำหรับเปิด Dialog
 | |
|   const handleCreate = () => {
 | |
|     setSelectedUser(null);
 | |
|     setIsFormOpen(true);
 | |
|   };
 | |
| 
 | |
|   const handleEdit = (user) => {
 | |
|     setSelectedUser(user);
 | |
|     setIsFormOpen(true);
 | |
|   };
 | |
|   
 | |
|   const handleDelete = (user) => {
 | |
|     setSelectedUser(user);
 | |
|     setIsDeleteOpen(true);
 | |
|   };
 | |
| 
 | |
|   // Function ที่จะทำงานเมื่อยืนยันการลบ
 | |
|   const confirmDeactivate = async () => {
 | |
|     if (!selectedUser) return;
 | |
|     setIsSubmitting(true);
 | |
|     try {
 | |
|         await api.delete(`/users/${selectedUser.id}`);
 | |
|         fetchUsers(); // Refresh ข้อมูล
 | |
|         setIsDeleteOpen(false);
 | |
|     } catch (error) {
 | |
|         console.error("Failed to deactivate user", error);
 | |
|         // ควรมี Alert แจ้งเตือน
 | |
|     } finally {
 | |
|         setIsSubmitting(false);
 | |
|     }
 | |
|   };
 | |
| 
 | |
| 
 | |
|   return (
 | |
|     <>
 | |
|       <Card>
 | |
|         <CardHeader>
 | |
|           <div className="flex items-center justify-between">
 | |
|             <div>
 | |
|               <CardTitle>User Accounts</CardTitle>
 | |
|               <CardDescription>Manage all user accounts and their roles.</CardDescription>
 | |
|             </div>
 | |
|             <Button onClick={handleCreate}>
 | |
|               <PlusCircle className="w-4 h-4 mr-2" /> Add User
 | |
|             </Button>
 | |
|           </div>
 | |
|         </CardHeader>
 | |
|         <CardContent>
 | |
|           <Table>
 | |
|             <TableHeader>
 | |
|               <TableRow>
 | |
|                 <TableHead>Username</TableHead>
 | |
|                 <TableHead>Email</TableHead>
 | |
|                 <TableHead>Roles</TableHead>
 | |
|                 <TableHead>Status</TableHead>
 | |
|                 <TableHead><span className="sr-only">Actions</span></TableHead>
 | |
|               </TableRow>
 | |
|             </TableHeader>
 | |
|             <TableBody>
 | |
|               {loading ? (
 | |
|                 <TableRow><TableCell colSpan={5} className="text-center">Loading...</TableCell></TableRow>
 | |
|               ) : (
 | |
|                 users.map((user) => (
 | |
|                   <TableRow key={user.id}>
 | |
|                     <TableCell className="font-medium">{user.username}</TableCell>
 | |
|                     <TableCell>{user.email}</TableCell>
 | |
|                     <TableCell>
 | |
|                       <div className="flex flex-wrap gap-1">
 | |
|                         {user.Roles?.map(role => <Badge key={role.id} variant="secondary">{role.name}</Badge>)}
 | |
|                       </div>
 | |
|                     </TableCell>
 | |
|                     <TableCell>
 | |
|                       <Badge variant={user.is_active ? 'default' : 'destructive'}>
 | |
|                         {user.is_active ? 'Active' : 'Inactive'}
 | |
|                       </Badge>
 | |
|                     </TableCell>
 | |
|                     <TableCell>
 | |
|                       <DropdownMenu>
 | |
|                         <DropdownMenuTrigger asChild>
 | |
|                           <Button variant="ghost" className="w-8 h-8 p-0"><MoreHorizontal className="w-4 h-4" /></Button>
 | |
|                         </DropdownMenuTrigger>
 | |
|                         <DropdownMenuContent align="end">
 | |
|                           <DropdownMenuLabel>Actions</DropdownMenuLabel>
 | |
|                           <DropdownMenuItem onClick={() => handleEdit(user)}>Edit</DropdownMenuItem>
 | |
|                           <DropdownMenuItem onClick={() => handleDelete(user)} className="text-red-500">
 | |
|                             Deactivate
 | |
|                           </DropdownMenuItem>
 | |
|                         </DropdownMenuContent>
 | |
|                       </DropdownMenu>
 | |
|                     </TableCell>
 | |
|                   </TableRow>
 | |
|                 ))
 | |
|               )}
 | |
|             </TableBody>
 | |
|           </Table>
 | |
|         </CardContent>
 | |
|       </Card>
 | |
| 
 | |
|       {/* Render Dialogs ที่นี่ (มันจะไม่แสดงผลจนกว่า state จะเป็น true) */}
 | |
|       <UserFormDialog 
 | |
|         user={selectedUser}
 | |
|         isOpen={isFormOpen}
 | |
|         setIsOpen={setIsFormOpen}
 | |
|         onSuccess={fetchUsers}
 | |
|       />
 | |
|       
 | |
|       <ConfirmDeleteDialog
 | |
|         isOpen={isDeleteOpen}
 | |
|         setIsOpen={setIsDeleteOpen}
 | |
|         isLoading={isSubmitting}
 | |
|         title="Are you sure?"
 | |
|         description={`This will deactivate the user "${selectedUser?.username}". They will no longer be able to log in.`}
 | |
|         onConfirm={confirmDeactivate}
 | |
|       />
 | |
|     </>
 | |
|   );
 | |
| } | 
