102 lines
3.9 KiB
TypeScript
102 lines
3.9 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { useParams, useNavigate } from 'react-router-dom';
|
|
import { ArrowLeft, RefreshCw, Shield } from 'lucide-react';
|
|
import { useModuleApi } from '../hooks/useModuleApi';
|
|
import Loader from '../../../../components/custom/CustomLoader';
|
|
import type { ModulePermission, Module } from '../AdminModuleTypes';
|
|
import CustomButton from '../../../../components/custom/CustomButton';
|
|
import { NodeGroupAccessViewer } from '../../../roles/components/NodeGroupAccessViewer';
|
|
import type { RoleAccess } from '../../../roles/RolesTypes';
|
|
|
|
const ModulePermissions = () => {
|
|
const { moduleId } = useParams<{ moduleId: string }>();
|
|
const navigate = useNavigate();
|
|
const { getModule, getPermissions, syncPermissions, loading } = useModuleApi();
|
|
|
|
const [module, setModule] = useState<Module | null>(null);
|
|
const [permissions, setPermissions] = useState<ModulePermission[]>([]);
|
|
const [syncing, setSyncing] = useState(false);
|
|
|
|
const fetchData = async () => {
|
|
if (!moduleId) return;
|
|
|
|
const [moduleData, permsData] = await Promise.all([
|
|
getModule(moduleId),
|
|
getPermissions(moduleId)
|
|
]);
|
|
|
|
if (moduleData) setModule(moduleData);
|
|
if (permsData) setPermissions(permsData);
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchData();
|
|
}, [moduleId]);
|
|
|
|
const handleSync = async () => {
|
|
if (!moduleId) return;
|
|
|
|
setSyncing(true);
|
|
const result = await syncPermissions(moduleId);
|
|
if (result) {
|
|
fetchData();
|
|
}
|
|
setSyncing(false);
|
|
};
|
|
|
|
|
|
|
|
const viewerAccesses: RoleAccess[] = permissions.map(p => ({
|
|
id: p.id,
|
|
access_code: p.access_code,
|
|
name: p.name,
|
|
category: p.category || 'General',
|
|
parent_id: p.parent_id
|
|
}));
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div className="flex items-center gap-4">
|
|
<button
|
|
onClick={() => navigate('/admin/modules')}
|
|
className="p-2 hover:bg-(--background) rounded-lg transition-colors text-(--text-secondary) hover:text-(--text-primary)"
|
|
>
|
|
<ArrowLeft size={20} />
|
|
</button>
|
|
<div className="flex flex-col gap-1">
|
|
<h1 className="text-2xl font-bold text-(--text-primary)">
|
|
{module?.module_name || 'Loading...'} - Permissions
|
|
</h1>
|
|
<p className="text-sm text-(--text-secondary)">View and sync permissions from module</p>
|
|
</div>
|
|
<div className="ml-auto">
|
|
<CustomButton
|
|
onClick={handleSync}
|
|
loading={syncing}
|
|
leftIcon={!syncing && <RefreshCw size={20} />}
|
|
>
|
|
{syncing ? 'Syncing...' : 'Sync Permissions'}
|
|
</CustomButton>
|
|
</div>
|
|
</div>
|
|
|
|
{loading ? (
|
|
<div className=" p-12 flex flex-col items-center justify-center min-h-[300px]">
|
|
<Loader size="md" />
|
|
</div>
|
|
) : permissions.length > 0 ? (
|
|
<div className="bg-(--card-bg) border border-(--card-border) rounded-lg p-6">
|
|
<NodeGroupAccessViewer accesses={viewerAccesses} />
|
|
</div>
|
|
) : (
|
|
<div className="bg-(--card-bg) border border-(--card-border) rounded-lg p-12 text-center">
|
|
<Shield className="w-16 h-16 text-(--text-secondary) mx-auto mb-4" />
|
|
<h3 className="text-lg font-semibold text-(--text-primary) mb-2">No Permissions Synced</h3>
|
|
<p className="text-(--text-secondary) mb-4">Click "Sync Permissions" to fetch from the module</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ModulePermissions; |