RBAC Improvements
Caching improvements Maker-Checker Implementation
This commit is contained in:
@@ -99,7 +99,7 @@ type DisbursementFormValues = z.infer<typeof disbursementSchema>;
|
||||
export const GrantsPage: React.FC = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { success, error: toastError } = useToast();
|
||||
const { canAdd, canApprove, canExport } = useRbac();
|
||||
const { canAdd, canApprove, canExport, canApproveRecord, isMaker } = useRbac();
|
||||
|
||||
const [activeTab, setActiveTab] = useState<'awards' | 'budgets' | 'disbursements'>('awards');
|
||||
|
||||
@@ -1002,7 +1002,7 @@ export const GrantsPage: React.FC = () => {
|
||||
<Edit2 className="w-3 h-3" />
|
||||
<span>Update</span>
|
||||
</button>
|
||||
{b.status !== ApprovalStatus.Approved && canApprove('grant_financials') && (
|
||||
{b.status !== ApprovalStatus.Approved && canApproveRecord('grant_financials', b.createdBy) && (
|
||||
<button
|
||||
type="button"
|
||||
disabled={updateBudgetMutation.isPending}
|
||||
@@ -1019,6 +1019,11 @@ export const GrantsPage: React.FC = () => {
|
||||
<span>Approve</span>
|
||||
</button>
|
||||
)}
|
||||
{b.status !== ApprovalStatus.Approved && canApprove('grant_financials') && isMaker(b.createdBy) && (
|
||||
<span className="text-[10px] text-amber-400 font-mono italic px-1.5 py-0.5 bg-amber-500/10 border border-amber-500/20 rounded">
|
||||
Maker-Checker
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -1159,7 +1164,7 @@ export const GrantsPage: React.FC = () => {
|
||||
>
|
||||
<Edit2 className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
{canApprove('grant_financials') && (
|
||||
{canApproveRecord('grant_financials', d.createdBy) && (
|
||||
<button
|
||||
onClick={() => approveMutation.mutate(d.id)}
|
||||
disabled={approveMutation.isPending}
|
||||
@@ -1169,6 +1174,11 @@ export const GrantsPage: React.FC = () => {
|
||||
Approve Payment
|
||||
</button>
|
||||
)}
|
||||
{canApprove('grant_financials') && isMaker(d.createdBy) && (
|
||||
<span className="text-[10px] text-amber-400 font-mono italic px-1.5 py-0.5 bg-amber-500/10 border border-amber-500/20 rounded">
|
||||
Maker-Checker (Creator)
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@@ -1562,9 +1572,21 @@ export const GrantsPage: React.FC = () => {
|
||||
onChange={(e) => setSelectedBudgetStatus(Number(e.target.value) as ApprovalStatus)}
|
||||
className="w-full px-3 py-2 text-xs bg-slate-900/80 border border-slate-700/80 rounded-xl text-white focus:outline-none focus:ring-2 focus:ring-blue-500/50 focus:border-blue-500 font-medium [&>option]:bg-slate-900 [&>option]:text-white"
|
||||
>
|
||||
<option value={ApprovalStatus.Approved} disabled={!canApprove('grant_financials')}>
|
||||
Approved {!canApprove('grant_financials') ? '(Requires Update Permission)' : ''}
|
||||
</option>
|
||||
{(() => {
|
||||
const canApproveBudget = canApproveRecord('grant_financials', editingBudget?.createdBy);
|
||||
const isSelf = isMaker(editingBudget?.createdBy);
|
||||
let reason = '';
|
||||
if (!canApprove('grant_financials')) {
|
||||
reason = ' (Requires Update Permission)';
|
||||
} else if (isSelf) {
|
||||
reason = ' (Maker-Checker: Cannot approve own record)';
|
||||
}
|
||||
return (
|
||||
<option value={ApprovalStatus.Approved} disabled={!canApproveBudget}>
|
||||
Approved {reason}
|
||||
</option>
|
||||
);
|
||||
})()}
|
||||
<option value={ApprovalStatus.Pending}>Pending Review</option>
|
||||
<option value={ApprovalStatus.Rejected}>Rejected / Blocked</option>
|
||||
</select>
|
||||
|
||||
Reference in New Issue
Block a user