88 lines
3.8 KiB
JavaScript
88 lines
3.8 KiB
JavaScript
import React from "react";
|
|
import { showToast } from "../../../toast/toastUtils";
|
|
import { usePermissions } from "../hooks/usePermissionManagement";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
function PermissionOverview({ refreshTrigger, onRefresh }) {
|
|
const { permissions, loading, error, reload } = usePermissions();
|
|
const { t } = useTranslation('permission_management');
|
|
|
|
React.useEffect(() => {
|
|
reload();
|
|
}, [refreshTrigger, reload]);
|
|
|
|
React.useEffect(() => {
|
|
if (!loading && !error) {
|
|
showToast({ type: "success", message: t('messages.loadSuccess') });
|
|
}
|
|
if (error) {
|
|
showToast({ type: "error", message: error });
|
|
}
|
|
}, [loading, error]);
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="bg-white rounded-lg shadow-md p-6">
|
|
<div className="flex items-center justify-center py-8">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
|
|
<span className="ml-3 text-gray-600">{t('headings.loading')}</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="bg-white rounded-lg shadow-md p-6">
|
|
<div className="flex items-center justify-between mb-6">
|
|
<h2 className="text-xl font-semibold text-gray-900">{t('headings.currentPermissions')}</h2>
|
|
<div className="text-sm text-gray-500">
|
|
{t('table.total', { count: permissions.length })}
|
|
</div>
|
|
</div>
|
|
{permissions.length === 0 ? (
|
|
<div className="text-center py-8">
|
|
<svg className="mx-auto h-12 w-12 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.031 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
|
</svg>
|
|
<h3 className="mt-2 text-sm font-medium text-gray-900">{t('headings.noPermissionsTitle')}</h3>
|
|
<p className="mt-1 text-sm text-gray-500">{t('headings.noPermissionsDesc')}</p>
|
|
</div>
|
|
) : (
|
|
<div className="overflow-x-auto">
|
|
<table className="min-w-full divide-y divide-gray-200">
|
|
<thead className="bg-gray-50">
|
|
<tr>
|
|
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{t('table.name')}</th>
|
|
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{t('table.description')}</th>
|
|
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{t('table.status')}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="bg-white divide-y divide-gray-200">
|
|
{permissions.map(p => (
|
|
<tr key={p.id} className="hover:bg-gray-50">
|
|
<td className="px-6 py-4 whitespace-nowrap">
|
|
<div className="text-sm font-medium text-gray-900">{p.name}</div>
|
|
</td>
|
|
<td className="px-6 py-4">
|
|
<div className="text-sm text-gray-600 max-w-xs">
|
|
{p.description || t('table.noDescription')}
|
|
</div>
|
|
</td>
|
|
<td className="px-6 py-4 whitespace-nowrap">
|
|
<span className={`inline-flex px-2 py-1 text-xs font-semibold rounded-full ${
|
|
p.is_active ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'
|
|
}`}>
|
|
{p.is_active ? t('status.active') : t('status.inactive')}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default PermissionOverview; |