105 lines
3.4 KiB
JavaScript
Executable File
105 lines
3.4 KiB
JavaScript
Executable File
// File: frontend/app/(protected)/admin/roles/page.jsx
|
|
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import { api } from '@/lib/api';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { ShieldCheck, PlusCircle } from 'lucide-react';
|
|
|
|
// Import Dialog component ที่เราเพิ่งสร้าง
|
|
import { RoleFormDialog } from '../_components/role-form-dialog';
|
|
|
|
export default function RolesPage() {
|
|
const [roles, setRoles] = useState([]);
|
|
const [allPermissions, setAllPermissions] = useState([]);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
// State สำหรับควบคุม Dialog
|
|
const [isFormOpen, setIsFormOpen] = useState(false);
|
|
const [selectedRole, setSelectedRole] = useState(null);
|
|
|
|
const fetchData = async () => {
|
|
try {
|
|
setLoading(true);
|
|
const [rolesRes, permsRes] = await Promise.all([
|
|
api.get('/rbac/roles'),
|
|
api.get('/rbac/permissions'),
|
|
]);
|
|
setRoles(rolesRes.data);
|
|
setAllPermissions(permsRes.data);
|
|
} catch (error) {
|
|
console.error("Failed to fetch RBAC data", error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchData();
|
|
}, []);
|
|
|
|
const handleCreate = () => {
|
|
setSelectedRole(null); // ไม่มี Role ที่เลือก = สร้างใหม่
|
|
setIsFormOpen(true);
|
|
};
|
|
|
|
const handleEdit = (role) => {
|
|
setSelectedRole(role);
|
|
setIsFormOpen(true);
|
|
};
|
|
|
|
if (loading) return <div>Loading role settings...</div>;
|
|
|
|
return (
|
|
<>
|
|
<div className="space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<h2 className="text-2xl font-semibold">Roles & Permissions</h2>
|
|
<Button onClick={handleCreate}>
|
|
<PlusCircle className="w-4 h-4 mr-2" /> Add Role
|
|
</Button>
|
|
</div>
|
|
{roles.map(role => (
|
|
<Card key={role.id}>
|
|
<CardHeader>
|
|
<div className="flex items-start justify-between">
|
|
<div>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<ShieldCheck className="text-primary" />
|
|
{role.name}
|
|
</CardTitle>
|
|
<CardDescription>{role.description || 'No description'}</CardDescription>
|
|
</div>
|
|
<Button variant="outline" size="sm" onClick={() => handleEdit(role)}>
|
|
Edit Permissions
|
|
</Button>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="mb-2 text-sm font-medium">Assigned Permissions:</p>
|
|
<div className="flex flex-wrap gap-2">
|
|
{role.Permissions.length > 0 ? (
|
|
role.Permissions.map(perm => (
|
|
<Badge key={perm.id} variant="secondary">{perm.name}</Badge>
|
|
))
|
|
) : (
|
|
<p className="text-sm text-muted-foreground">No permissions assigned.</p>
|
|
)}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
|
|
<RoleFormDialog
|
|
isOpen={isFormOpen}
|
|
setIsOpen={setIsFormOpen}
|
|
role={selectedRole}
|
|
allPermissions={allPermissions}
|
|
onSuccess={fetchData}
|
|
/>
|
|
</>
|
|
);
|
|
} |