resolve confilict

This commit is contained in:
marshal
2026-06-05 14:07:26 +03:00
40 changed files with 3823 additions and 768 deletions

View File

@@ -13,7 +13,11 @@ import {
} from "lucide-react";
import type { AuthUser } from "@/auth/types";
import { FREIGHT_PERMS, hasPermission } from "@/lib/permissions";
import {
FREIGHT_PERMS,
hasPermission,
isFreightApprovalAdmin,
} from "@/lib/permissions";
import type {
BookingApprovalStep,
BookingDetail,
@@ -71,18 +75,7 @@ function approvalActions(
const next = getNextPendingApprovalStep(steps);
if (!next) return [];
return [
{
id: "approve",
label: `Approve (${next.requiredRole})`,
shortLabel: "Approve",
description: `Complete step ${next.stepOrder} as ${next.requiredRole}`,
confirmTitle: `Approve as ${next.requiredRole}?`,
confirmDescription:
"This records your approval and advances the booking to the next step in the chain.",
variant: "default",
icon: Check,
primary: true,
},
buildApproveActionForStep(next),
{
id: "rejectApproval",
label: "Reject approval",
@@ -219,6 +212,37 @@ const approvePermissionForRole = (role: string): string | undefined => {
return undefined;
};
/** True when this step is the current pending step and the user may approve it. */
export function canActOnApprovalStep(
user: AuthUser | null | undefined,
step: BookingApprovalStep,
steps?: BookingApprovalStep[] | null,
): boolean {
if (step.status !== "PENDING") return false;
const next = getNextPendingApprovalStep(steps);
if (!next || next.id !== step.id) return false;
if (isFreightApprovalAdmin(user)) return true;
const perm = approvePermissionForRole(step.requiredRole);
return perm ? hasPermission(user, perm) : false;
}
export function buildApproveActionForStep(
step: BookingApprovalStep,
): BookingActionDef {
return {
id: "approve",
label: `Approve (${step.requiredRole})`,
shortLabel: "Approve",
description: `Complete step ${step.stepOrder} as ${step.requiredRole}`,
confirmTitle: `Approve as ${step.requiredRole}?`,
confirmDescription:
"This records your approval and advances the booking to the next step in the chain.",
variant: "default",
icon: Check,
primary: true,
};
}
function filterActionsByUser(
actions: BookingActionDef[],
user: AuthUser | null | undefined,
@@ -228,8 +252,7 @@ function filterActionsByUser(
const next = getNextPendingApprovalStep(approvalSteps);
return actions.filter((action) => {
if (action.id === "approve" && next) {
const perm = approvePermissionForRole(next.requiredRole);
return perm ? hasPermission(user, perm) : false;
return canActOnApprovalStep(user, next, approvalSteps);
}
const perm = ACTION_PERMISSION[action.id];
return perm ? hasPermission(user, perm) : true;