summaryrefslogtreecommitdiff
path: root/components/permissions/role-permission-manager.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-09-26 09:57:24 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-09-26 09:57:24 +0000
commit8b23b471638a155fd1bfa3a8c853b26d9315b272 (patch)
tree47353e9dd342011cb2f1dcd24b09661707a8421b /components/permissions/role-permission-manager.tsx
parentd62368d2b68d73da895977e60a18f9b1286b0545 (diff)
(대표님) 권한관리, 문서업로드, rfq첨부, SWP문서룰 등
(최겸) 입찰
Diffstat (limited to 'components/permissions/role-permission-manager.tsx')
-rw-r--r--components/permissions/role-permission-manager.tsx178
1 files changed, 178 insertions, 0 deletions
diff --git a/components/permissions/role-permission-manager.tsx b/components/permissions/role-permission-manager.tsx
new file mode 100644
index 00000000..b229ec57
--- /dev/null
+++ b/components/permissions/role-permission-manager.tsx
@@ -0,0 +1,178 @@
+// components/permissions/role-permission-manager.tsx
+
+"use client";
+
+import { useState, useEffect } from "react";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+import { Button } from "@/components/ui/button";
+import { Checkbox } from "@/components/ui/checkbox";
+import { Badge } from "@/components/ui/badge";
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+import { toast } from "sonner";
+import { assignPermissionsToRole, getRolePermissions } from "@/lib/permissions/service";
+
+export function RolePermissionManager() {
+ const [selectedRole, setSelectedRole] = useState<string>("");
+ const [permissions, setPermissions] = useState<any[]>([]);
+ const [selectedPermissions, setSelectedPermissions] = useState<Set<number>>(new Set());
+ const [loading, setLoading] = useState(false);
+
+ useEffect(() => {
+ if (selectedRole) {
+ loadRolePermissions(selectedRole);
+ }
+ }, [selectedRole]);
+
+ const loadRolePermissions = async (roleId: string) => {
+ try {
+ const data = await getRolePermissions(parseInt(roleId));
+ setPermissions(data.permissions);
+ setSelectedPermissions(new Set(data.assignedPermissionIds));
+ } catch (error) {
+ toast.error("권한 목록을 불러오는데 실패했습니다.");
+ }
+ };
+
+ const handleSave = async () => {
+ if (!selectedRole) {
+ toast.error("역할을 선택해주세요.");
+ return;
+ }
+
+ try {
+ setLoading(true);
+ await assignPermissionsToRole(
+ parseInt(selectedRole),
+ Array.from(selectedPermissions)
+ );
+ toast.success("권한이 성공적으로 저장되었습니다.");
+ } catch (error) {
+ toast.error("권한 저장에 실패했습니다.");
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const togglePermission = (permissionId: number) => {
+ const newSet = new Set(selectedPermissions);
+ if (newSet.has(permissionId)) {
+ newSet.delete(permissionId);
+ } else {
+ newSet.add(permissionId);
+ }
+ setSelectedPermissions(newSet);
+ };
+
+ // 권한 그룹별로 정리
+ const groupedPermissions = permissions.reduce((acc, perm) => {
+ const group = perm.menuPath || "기타";
+ if (!acc[group]) acc[group] = [];
+ acc[group].push(perm);
+ return acc;
+ }, {} as Record<string, any[]>);
+
+ return (
+ <Card>
+ <CardHeader>
+ <CardTitle>역할별 권한 설정</CardTitle>
+ <CardDescription>
+ 역할을 선택하고 해당 역할에 부여할 권한을 선택하세요.
+ </CardDescription>
+ </CardHeader>
+ <CardContent>
+ <div className="space-y-6">
+ {/* 역할 선택 */}
+ <div className="flex items-center gap-4">
+ <Select value={selectedRole} onValueChange={setSelectedRole}>
+ <SelectTrigger className="w-[300px]">
+ <SelectValue placeholder="역할 선택..." />
+ </SelectTrigger>
+ <SelectContent>
+ <SelectItem value="1">EVCP Admin</SelectItem>
+ <SelectItem value="2">EVCP Manager</SelectItem>
+ <SelectItem value="3">EVCP User</SelectItem>
+ <SelectItem value="4">Partner Admin</SelectItem>
+ <SelectItem value="5">Partner User</SelectItem>
+ </SelectContent>
+ </Select>
+
+ <Button
+ onClick={handleSave}
+ disabled={!selectedRole || loading}
+ >
+ 권한 저장
+ </Button>
+ </div>
+
+ {/* 권한 목록 */}
+ {selectedRole && (
+ <div className="border rounded-lg">
+ <Table>
+ <TableHeader>
+ <TableRow>
+ <TableHead className="w-[50px]">선택</TableHead>
+ <TableHead>메뉴/그룹</TableHead>
+ <TableHead>권한명</TableHead>
+ <TableHead>타입</TableHead>
+ <TableHead>범위</TableHead>
+ <TableHead>설명</TableHead>
+ </TableRow>
+ </TableHeader>
+ <TableBody>
+ {Object.entries(groupedPermissions).map(([group, perms]) => (
+ <>
+ <TableRow key={group} className="bg-muted/50">
+ <TableCell colSpan={6} className="font-medium">
+ {group}
+ </TableCell>
+ </TableRow>
+ {perms.map((permission) => (
+ <TableRow key={permission.id}>
+ <TableCell>
+ <Checkbox
+ checked={selectedPermissions.has(permission.id)}
+ onCheckedChange={() => togglePermission(permission.id)}
+ />
+ </TableCell>
+ <TableCell>
+ <Badge variant="outline">{permission.resource}</Badge>
+ </TableCell>
+ <TableCell className="font-medium">
+ {permission.name}
+ </TableCell>
+ <TableCell>
+ <Badge>{permission.permissionType}</Badge>
+ </TableCell>
+ <TableCell>
+ <Badge variant="secondary">{permission.scope}</Badge>
+ </TableCell>
+ <TableCell className="text-sm text-muted-foreground">
+ {permission.description}
+ </TableCell>
+ </TableRow>
+ ))}
+ </>
+ ))}
+ </TableBody>
+ </Table>
+ </div>
+ )}
+ </div>
+ </CardContent>
+ </Card>
+ );
+} \ No newline at end of file