Skip to content

Commit 1dfe312

Browse files
Orv2 2862 bvt bug special authorization tab visible with no special authorizations (#1817)
1 parent 7731031 commit 1dfe312

File tree

4 files changed

+221
-196
lines changed

4 files changed

+221
-196
lines changed

frontend/src/features/manageProfile/components/dashboard/ManageProfilesDashboard.tsx

+17-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { AxiosError } from "axios";
44
import React, { useContext, useState } from "react";
55
import { useLocation, useNavigate } from "react-router";
66
import { Navigate } from "react-router-dom";
7-
7+
import { useFetchLOAs } from "../../../settings/hooks/LOA";
88
import OnRouteBCContext from "../../../../common/authentication/OnRouteBCContext";
99
import { CLAIMS } from "../../../../common/authentication/types";
1010
import { DoesUserHaveClaim } from "../../../../common/authentication/util";
@@ -78,7 +78,17 @@ export const ManageProfilesDashboard = React.memo(() => {
7878

7979
const { data: specialAuthorizations, isPending: isSpecialAuthAPILoading } =
8080
useFetchSpecialAuthorizations(companyId as number, true);
81-
81+
const activeLOAsQuery = useFetchLOAs(companyId, false);
82+
const expiredLOAsQuery = useFetchLOAs(companyId, true);
83+
const activeLOAs = getDefaultRequiredVal([], activeLOAsQuery.data);
84+
const expiredLOAs = getDefaultRequiredVal([], expiredLOAsQuery.data);
85+
const canWriteLOA = usePermissionMatrix({
86+
featureFlag: "LOA",
87+
permissionMatrixKeys: {
88+
permissionMatrixFeatureKey: "MANAGE_SETTINGS",
89+
permissionMatrixFunctionKey: "EDIT_AN_LOA",
90+
},
91+
});
8292
const showSpecialAuth = usePermissionMatrix({
8393
additionalConditionToCheck: () =>
8494
!isStaffActingAsCompany &&
@@ -87,7 +97,11 @@ export const ManageProfilesDashboard = React.memo(() => {
8797
featureFlags?.["LCV"] === "ENABLED") &&
8898
!isSpecialAuthAPILoading &&
8999
Boolean(
90-
specialAuthorizations?.isLcvAllowed || specialAuthorizations?.noFeeType,
100+
specialAuthorizations?.isLcvAllowed ||
101+
specialAuthorizations?.noFeeType ||
102+
activeLOAs.length > 0 ||
103+
expiredLOAs.length > 0 ||
104+
canWriteLOA,
91105
),
92106
permissionMatrixKeys: {
93107
permissionMatrixFeatureKey: "MANAGE_PROFILE",

frontend/src/features/settings/components/SpecialAuthorizations/LCV/LCVSection.tsx

+2-4
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@ export const LCVSection = ({
1212
onUpdateLCV: (enable: boolean) => void;
1313
isEditable?: boolean;
1414
}) => {
15-
return (isEditable || enableLCV) ? (
15+
return isEditable || enableLCV ? (
1616
<div className={`lcv-section ${isEditable ? "" : "lcv-section--readonly"}`}>
1717
<div className="lcv-section__header">
18-
<div className="lcv-section__title">
19-
Long Combination Vehicle (LCV)
20-
</div>
18+
<div className="lcv-section__title">Long Combination Vehicle (LCV)</div>
2119

2220
{isEditable ? (
2321
<Switch
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
2+
import { faPlus } from "@fortawesome/free-solid-svg-icons";
3+
import { Button } from "@mui/material";
4+
import { CustomActionLink } from "../../../../../common/components/links/CustomActionLink";
5+
import { LOAList } from "./list/LOAList";
6+
import { getDefaultRequiredVal } from "../../../../../common/helpers/util";
7+
import { useFetchLOAs, useRemoveLOAMutation } from "../../../hooks/LOA";
8+
import { usePermissionMatrix } from "../../../../../common/authentication/PermissionMatrix";
9+
import { useState } from "react";
10+
import { RequiredOrNull } from "../../../../../common/types/common";
11+
import { downloadLOA } from "../../../apiManager/loa";
12+
import { LOASteps } from "../../../pages/SpecialAuthorizations/LOA/LOASteps";
13+
import { ExpiredLOAModal } from "./expired/ExpiredLOAModal";
14+
import { DeleteConfirmationDialog } from "../../../../../common/components/dialog/DeleteConfirmationDialog";
15+
16+
export const LOASection = ({
17+
canReadLOA,
18+
companyId,
19+
}: {
20+
canReadLOA: boolean;
21+
companyId: number;
22+
}) => {
23+
const [showExpiredLOAs, setShowExpiredLOAs] = useState<boolean>(false);
24+
const [loaToDelete, setLoaToDelete] = useState<RequiredOrNull<number>>(null);
25+
const [showLOASteps, setShowLOASteps] = useState<boolean>(false);
26+
const [loaToEdit, setLoaToEdit] = useState<RequiredOrNull<number>>(null);
27+
const activeLOAsQuery = useFetchLOAs(companyId, false);
28+
const expiredLOAsQuery = useFetchLOAs(companyId, true);
29+
const activeLOAs = getDefaultRequiredVal([], activeLOAsQuery.data);
30+
const expiredLOAs = getDefaultRequiredVal([], expiredLOAsQuery.data);
31+
const showExpiredLOAsLink = canReadLOA && expiredLOAs.length > 0;
32+
const showActiveLOAsList = canReadLOA && activeLOAs.length > 0;
33+
const showExpiredLOAsModal = canReadLOA && showExpiredLOAs;
34+
const removeLOAMutation = useRemoveLOAMutation();
35+
36+
const canWriteLOA = usePermissionMatrix({
37+
featureFlag: "LOA",
38+
permissionMatrixKeys: {
39+
permissionMatrixFeatureKey: "MANAGE_SETTINGS",
40+
permissionMatrixFunctionKey: "EDIT_AN_LOA",
41+
},
42+
});
43+
44+
const showDeleteDialog = canWriteLOA && loaToDelete;
45+
46+
const handleOpenDeleteModal = (loaId: number) => {
47+
if (!canWriteLOA) return;
48+
setLoaToDelete(loaId);
49+
};
50+
51+
const handleCloseDeleteModal = () => {
52+
setLoaToDelete(null);
53+
};
54+
55+
const handleDeleteLOA = async (loaId: number) => {
56+
try {
57+
if (canWriteLOA) {
58+
await removeLOAMutation.mutateAsync({
59+
companyId,
60+
loaId,
61+
});
62+
63+
activeLOAsQuery.refetch();
64+
}
65+
} catch (e) {
66+
console.error(e);
67+
} finally {
68+
setLoaToDelete(null);
69+
}
70+
};
71+
72+
const handleDownloadLOA = async (loaId: number) => {
73+
if (loaId && canReadLOA) {
74+
try {
75+
const { blobObj: blobObjWithoutType } = await downloadLOA(
76+
loaId,
77+
companyId,
78+
);
79+
80+
const objUrl = URL.createObjectURL(
81+
new Blob([blobObjWithoutType], { type: "application/pdf" }),
82+
);
83+
window.open(objUrl, "_blank");
84+
} catch (err) {
85+
console.error(err);
86+
}
87+
}
88+
};
89+
90+
const handleShowExpiredLOA = () => {
91+
setShowExpiredLOAs(true);
92+
};
93+
const handleAddLOA = () => {
94+
if (!canWriteLOA) return;
95+
setShowLOASteps(true);
96+
setLoaToEdit(null);
97+
};
98+
99+
const handleEditLOA = (loaId: number) => {
100+
if (!canWriteLOA) return;
101+
setShowLOASteps(true);
102+
setLoaToEdit(loaId);
103+
};
104+
105+
const handleExitLOASteps = () => {
106+
setShowLOASteps(false);
107+
setLoaToEdit(null);
108+
activeLOAsQuery.refetch();
109+
expiredLOAsQuery.refetch();
110+
};
111+
112+
if (showLOASteps) {
113+
return canWriteLOA ? (
114+
<LOASteps
115+
loaId={loaToEdit}
116+
companyId={companyId}
117+
onExit={handleExitLOASteps}
118+
/>
119+
) : null;
120+
}
121+
122+
return activeLOAs.length > 0 || expiredLOAs.length > 0 || canWriteLOA ? (
123+
<div className="special-authorizations__loa">
124+
<div className="special-authorizations__section-header">
125+
<div className="special-authorizations__header-title">
126+
Letter of Authorization (LOA)
127+
</div>
128+
129+
{showExpiredLOAsLink ? (
130+
<CustomActionLink
131+
className="special-authorizations__link"
132+
onClick={handleShowExpiredLOA}
133+
>
134+
Expired LOA(s)
135+
</CustomActionLink>
136+
) : null}
137+
</div>
138+
139+
{canWriteLOA ? (
140+
<Button
141+
className="add-loa-btn"
142+
key="add-loa-button"
143+
aria-label="Add LOA"
144+
variant="contained"
145+
color="tertiary"
146+
onClick={handleAddLOA}
147+
>
148+
<FontAwesomeIcon className="add-loa-btn__icon" icon={faPlus} />
149+
Add an LOA
150+
</Button>
151+
) : (
152+
<div className="loa-info">
153+
Download the letter to see the specific travel terms of the LOA.
154+
</div>
155+
)}
156+
157+
{showActiveLOAsList ? (
158+
<div className="active-loas">
159+
<div className="active-loas__header">Active LOA(s)</div>
160+
161+
<LOAList
162+
loas={activeLOAs}
163+
isActive={true}
164+
allowEditLOA={canWriteLOA}
165+
onDelete={handleOpenDeleteModal}
166+
onEdit={handleEditLOA}
167+
onDownload={handleDownloadLOA}
168+
/>
169+
</div>
170+
) : null}
171+
{showExpiredLOAsModal ? (
172+
<ExpiredLOAModal
173+
allowEditLOA={canWriteLOA}
174+
showModal={showExpiredLOAs}
175+
handleCancel={() => setShowExpiredLOAs(false)}
176+
expiredLOAs={expiredLOAs}
177+
handleEdit={(loaId) => {
178+
setShowExpiredLOAs(false);
179+
handleEditLOA(loaId);
180+
}}
181+
handleDownload={handleDownloadLOA}
182+
/>
183+
) : null}
184+
185+
{showDeleteDialog ? (
186+
<DeleteConfirmationDialog
187+
showDialog={Boolean(loaToDelete)}
188+
onCancel={handleCloseDeleteModal}
189+
onDelete={() => handleDeleteLOA(loaToDelete)}
190+
itemToDelete="item"
191+
confirmationMsg={"Are you sure you want to delete this?"}
192+
/>
193+
) : null}
194+
</div>
195+
) : null;
196+
};
197+
198+
export default LOASection;

0 commit comments

Comments
 (0)