mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
enhance permission filtering for sidebar items and improve risk assignment logic in clearance components
This commit is contained in:
@@ -474,7 +474,8 @@ const isClearanceItem = (item: SidebarItem): boolean =>
|
||||
/**
|
||||
* Keep only items the user is permitted to see; drop now-empty sections.
|
||||
*
|
||||
* Position-scoped visibility (super_admin bypasses all of this):
|
||||
* Position-scoped visibility (super_admin sees everything):
|
||||
* - Super Admin → sees all items (all permissions pass, all tabs visible)
|
||||
* - Ethiopian GL → sees ONLY the ET document-clearance page.
|
||||
* - Djibouti GL → sees ONLY the DJ clearance page.
|
||||
* - Everyone else → sees everything they have permission for, EXCEPT the two
|
||||
@@ -484,9 +485,11 @@ const filterSidebarByPermission = (
|
||||
sections: SidebarSection[],
|
||||
user: ReturnType<typeof useAuth>["user"],
|
||||
): SidebarSection[] => {
|
||||
const superAdmin = isSuperAdmin(user);
|
||||
const etGl = !superAdmin && isEthiopianGl(user);
|
||||
const djGl = !superAdmin && isDjiboutiGl(user);
|
||||
// Superadmin sees every section and item — no permission filtering.
|
||||
if (isSuperAdmin(user)) return sections;
|
||||
|
||||
const etGl = isEthiopianGl(user);
|
||||
const djGl = isDjiboutiGl(user);
|
||||
|
||||
const permissionAllowed = (item: SidebarItem): boolean => {
|
||||
if (!item.permission) return true;
|
||||
@@ -497,8 +500,6 @@ const filterSidebarByPermission = (
|
||||
};
|
||||
|
||||
const itemAllowed = (item: SidebarItem): boolean => {
|
||||
if (superAdmin) return true;
|
||||
|
||||
// GL positions are locked to their single clearance page.
|
||||
if (etGl) return isEtClearanceItem(item);
|
||||
if (djGl) return isDjClearanceItem(item);
|
||||
|
||||
@@ -122,7 +122,14 @@ function computeImportActiveStep(
|
||||
if (!clearance.gatepassGranted) return 8;
|
||||
if (!t1Uploaded && !clearance.t1?.closed) return 9;
|
||||
if (!clearance.t1?.closed) return 10;
|
||||
if (!isBookingMilestoneDone(bookingMilestones, "RISK_ASSIGNED")) return 11;
|
||||
// Risk is "assigned" when the booking milestone says so OR the clearance view
|
||||
// already carries a riskLevel. The ET page derives its bookingMilestones from a
|
||||
// separately-fetched booking id that can lag or mismatch the booking carrying
|
||||
// the milestone — `clearance.riskLevel` is server truth and matches the badge.
|
||||
const riskAssigned =
|
||||
Boolean(clearance.riskLevel) ||
|
||||
isBookingMilestoneDone(bookingMilestones, "RISK_ASSIGNED");
|
||||
if (!riskAssigned) return 11;
|
||||
// Additional duty round is optional — resolved once skipped or paid.
|
||||
const secondDutyResolved =
|
||||
clearance.secondDuty?.skipped ||
|
||||
@@ -229,6 +236,13 @@ export function PhasedClearanceActionPanel({
|
||||
const actionBookingId =
|
||||
clearance.t1?.bookingId ?? clearance.linkedBookingId ?? bookingId ?? null;
|
||||
const t1Uploaded = t1FilesFromWorkflow(workflowFiles).length > 0;
|
||||
// Risk is assigned when the clearance view carries a riskLevel (server truth,
|
||||
// drives the badge) OR the fetched booking milestone confirms it. Kept in sync
|
||||
// with computeImportActiveStep so the stepper never freezes on a page whose
|
||||
// bookingMilestones lag/mismatch the booking that holds the milestone.
|
||||
const riskAssigned =
|
||||
Boolean(clearance.riskLevel) ||
|
||||
isBookingMilestoneDone(bookingMilestones, "RISK_ASSIGNED");
|
||||
const activeStep = useMemo(
|
||||
() =>
|
||||
isImport
|
||||
@@ -595,7 +609,7 @@ export function PhasedClearanceActionPanel({
|
||||
label="Customs risk"
|
||||
description="GL Ethiopia assigns Green / Yellow / Red"
|
||||
icon={
|
||||
isBookingMilestoneDone(bookingMilestones, "RISK_ASSIGNED") ? (
|
||||
riskAssigned ? (
|
||||
<CheckCircle2 size={14} />
|
||||
) : (
|
||||
<ShieldAlert size={14} />
|
||||
@@ -606,7 +620,7 @@ export function PhasedClearanceActionPanel({
|
||||
bookingId={actionBookingId}
|
||||
clearance={clearance}
|
||||
canAct={showEt && canEt}
|
||||
done={isBookingMilestoneDone(bookingMilestones, "RISK_ASSIGNED")}
|
||||
done={riskAssigned}
|
||||
onChanged={onChanged}
|
||||
/>
|
||||
</Stepper.Step>
|
||||
@@ -620,7 +634,7 @@ export function PhasedClearanceActionPanel({
|
||||
bookingId={actionBookingId}
|
||||
clearance={clearance}
|
||||
canAct={showEt && canEt}
|
||||
riskAssigned={isBookingMilestoneDone(bookingMilestones, "RISK_ASSIGNED")}
|
||||
riskAssigned={riskAssigned}
|
||||
onChanged={onChanged}
|
||||
onViewFile={onViewFile}
|
||||
onDownloadFile={onDownloadFile}
|
||||
|
||||
@@ -44,7 +44,7 @@ export default function ContractClearanceDetailPage() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const { view, viewer } = useFileViewer();
|
||||
|
||||
const { data: contract } = useContractDetail(id);
|
||||
const { data: contract, refetch: refetchContract } = useContractDetail(id);
|
||||
const {
|
||||
data: clearance,
|
||||
isLoading,
|
||||
@@ -250,6 +250,7 @@ export default function ContractClearanceDetailPage() {
|
||||
phasedCustoms={phasedCustoms}
|
||||
onChanged={() => {
|
||||
void refetch();
|
||||
void refetchContract();
|
||||
void refetchBookingMilestones();
|
||||
}}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user