Implemented rbac
This commit is contained in:
@@ -40,6 +40,7 @@ import { HelpTooltip } from '../components/ui/HelpTooltip';
|
||||
import { ExportButton } from '../components/ui/ExportButton';
|
||||
import { ExportColumn } from '../utils/exportUtils';
|
||||
import { useTableSort, SortableTh } from '../utils/tableSort';
|
||||
import { useRbac } from '../auth/rbac';
|
||||
import { ApprovalStatusBadge } from '../components/ui/StatusBadge';
|
||||
import { Beneficiary, ComplianceItem, Outcome, ApprovalStatus } from '../types';
|
||||
import { getApprovalStatusBadge, formatDate, APPROVAL_STATUS_OPTIONS } from '../lib/formatters';
|
||||
@@ -70,6 +71,7 @@ type OutcomeFormValues = z.infer<typeof outcomeSchema>;
|
||||
export const BeneficiariesPage: React.FC = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { success, error: toastError } = useToast();
|
||||
const { canAdd, canApprove, canExport } = useRbac();
|
||||
|
||||
const [selectedProjectId, setSelectedProjectId] = useState<string>('all');
|
||||
const [activeTab, setActiveTab] = useState<'beneficiaries' | 'compliance'>('beneficiaries');
|
||||
@@ -574,23 +576,26 @@ export const BeneficiariesPage: React.FC = () => {
|
||||
</button>
|
||||
|
||||
<ExportButton
|
||||
claim="beneficiaries"
|
||||
data={sortedBens}
|
||||
columns={benExportColumns}
|
||||
filename={`project_beneficiaries_${new Date().toISOString().split('T')[0]}`}
|
||||
title="Beneficiaries Register"
|
||||
/>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
setEditingBen(null);
|
||||
benForm.reset({ name: '', category: 'Youth & Skills', location: 'National', targetCount: 100, reachedCount: 0 });
|
||||
setIsBenModalOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-1.5 px-3.5 py-1.5 rounded-xl text-xs font-semibold bg-gradient-to-r from-blue-600 to-indigo-600 text-white hover:from-blue-500 hover:to-indigo-500 shadow-md shadow-blue-600/25 transition cursor-pointer"
|
||||
>
|
||||
<Plus className="w-3.5 h-3.5" />
|
||||
<span>Register Beneficiary</span>
|
||||
</button>
|
||||
{canAdd('beneficiaries') && (
|
||||
<button
|
||||
onClick={() => {
|
||||
setEditingBen(null);
|
||||
benForm.reset({ name: '', category: 'Youth & Skills', location: 'National', targetCount: 100, reachedCount: 0 });
|
||||
setIsBenModalOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-1.5 px-3.5 py-1.5 rounded-xl text-xs font-semibold bg-gradient-to-r from-blue-600 to-indigo-600 text-white hover:from-blue-500 hover:to-indigo-500 shadow-md shadow-blue-600/25 transition cursor-pointer"
|
||||
>
|
||||
<Plus className="w-3.5 h-3.5" />
|
||||
<span>Register Beneficiary</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-[#0f1523]/80 rounded-2xl border border-slate-800/80 shadow-lg backdrop-blur-sm overflow-hidden">
|
||||
@@ -759,24 +764,27 @@ export const BeneficiariesPage: React.FC = () => {
|
||||
</button>
|
||||
|
||||
<ExportButton
|
||||
claim="beneficiaries"
|
||||
data={sortedComps}
|
||||
columns={compExportColumns}
|
||||
filename={`compliance_requirements_${new Date().toISOString().split('T')[0]}`}
|
||||
title="Compliance Requirements"
|
||||
/>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
setEditingComp(null);
|
||||
setCompTargetProjectId(selectedProjectId !== 'all' ? selectedProjectId : projects[0]?.id ? String(projects[0].id) : '');
|
||||
compForm.reset({ title: '', requirements: '', status: ApprovalStatus.Pending });
|
||||
setIsCompModalOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-1.5 px-3.5 py-1.5 rounded-xl text-xs font-semibold bg-slate-800 text-white hover:bg-slate-700 border border-slate-700 shadow-md transition cursor-pointer"
|
||||
>
|
||||
<CheckSquare className="w-3.5 h-3.5 text-emerald-400" />
|
||||
<span>Add Compliance Item</span>
|
||||
</button>
|
||||
{canAdd('beneficiaries') && (
|
||||
<button
|
||||
onClick={() => {
|
||||
setEditingComp(null);
|
||||
setCompTargetProjectId(selectedProjectId !== 'all' ? selectedProjectId : projects[0]?.id ? String(projects[0].id) : '');
|
||||
compForm.reset({ title: '', requirements: '', status: ApprovalStatus.Pending });
|
||||
setIsCompModalOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-1.5 px-3.5 py-1.5 rounded-xl text-xs font-semibold bg-slate-800 text-white hover:bg-slate-700 border border-slate-700 shadow-md transition cursor-pointer"
|
||||
>
|
||||
<CheckSquare className="w-3.5 h-3.5 text-emerald-400" />
|
||||
<span>Add Compliance Item</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1017,8 +1025,13 @@ export const BeneficiariesPage: React.FC = () => {
|
||||
className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white focus:outline-none focus:border-blue-500"
|
||||
>
|
||||
{APPROVAL_STATUS_OPTIONS.map((opt) => (
|
||||
<option key={opt.value} value={opt.value}>
|
||||
<option
|
||||
key={opt.value}
|
||||
value={opt.value}
|
||||
disabled={opt.value === ApprovalStatus.Approved && !canApprove('beneficiaries')}
|
||||
>
|
||||
{opt.label}
|
||||
{opt.value === ApprovalStatus.Approved && !canApprove('beneficiaries') ? ' (Requires Update Permission)' : ''}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
Reference in New Issue
Block a user