Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ORV2-2571, 2572, 2573 Credit Account - API split integration #1522

Merged
merged 14 commits into from
Aug 1, 2024
Merged
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export const SnackBarContext = createContext({
});

const App = () => {
const queryClient = new QueryClient();
const [queryClient] = useState(() => new QueryClient());
zgong-gov marked this conversation as resolved.
Show resolved Hide resolved

// Globally used SnackBar component
const [snackBar, setSnackBar] = useState<SnackBarOptions>({
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/common/authentication/PermissionMatrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ const MANAGE_PROFILE = {
* Company Information tab
*/
VIEW_COMPANY_INFORMATION: {
allowedBCeIDAuthGroups: [CA],
allowedBCeIDAuthGroups: ALL_BCeID_GROUPS,
allowedIDIRAuthGroups: [PC, SA, FIN, CTPO, HQA],
},
EDIT_COMPANY_INFORMATION: {
Expand Down Expand Up @@ -508,6 +508,7 @@ export const usePermissionMatrix = ({
isAllowed = Boolean(
currentUserAuthGroup &&
allowedIDIRAuthGroups?.includes(currentUserAuthGroup),

);
} else {
currentUserAuthGroup = userDetails?.userAuthGroup;
Expand Down
72 changes: 41 additions & 31 deletions frontend/src/common/components/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,20 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBars } from "@fortawesome/free-solid-svg-icons";

import "./Header.scss";
import { DoesUserHaveRoleWithContext } from "../../authentication/util";
import { Brand } from "./components/Brand";
import { UserSection } from "./components/UserSection";
import { getLoginUsernameFromSession } from "../../apiManager/httpRequestHandler";
import { SearchButton } from "./components/SearchButton";
import { SearchFilter } from "./components/SearchFilter";
import { IDPS } from "../../types/idp";
import OnRouteBCContext from "../../authentication/OnRouteBCContext";
import { ROLES, UserRolesType } from "../../authentication/types";
import { Nullable } from "../../types/common";
import { canViewSettingsTab } from "../../../features/settings/helpers/permissions";
import {
APPLICATIONS_ROUTES,
PROFILE_ROUTES,
SETTINGS_ROUTES,
VEHICLES_ROUTES,
} from "../../../routes/constants";
import { RenderIf } from "../reusable/RenderIf";

const getEnv = () => {
const env =
Expand All @@ -46,11 +43,9 @@ const getEnv = () => {
const Navbar = ({
isAuthenticated,
isMobile = false,
userRoles,
}: {
isAuthenticated: boolean;
isMobile?: boolean;
userRoles?: Nullable<UserRolesType[]>;
}) => {
const navbarClassName = isMobile ? "mobile" : "normal";
return (
Expand All @@ -59,28 +54,44 @@ const Navbar = ({
<ul>
{isAuthenticated && (
<>
{DoesUserHaveRoleWithContext(ROLES.WRITE_PERMIT) && (
<li>
<NavLink to={APPLICATIONS_ROUTES.BASE}>Permits</NavLink>
</li>
)}
{DoesUserHaveRoleWithContext(ROLES.READ_VEHICLE) && (
<li>
<NavLink to={VEHICLES_ROUTES.MANAGE}>
Vehicle Inventory
</NavLink>
</li>
)}
{DoesUserHaveRoleWithContext(ROLES.READ_ORG) && (
<li>
<NavLink to={PROFILE_ROUTES.MANAGE}>Profile</NavLink>
</li>
)}
{canViewSettingsTab(userRoles) && (
<li>
<NavLink to={SETTINGS_ROUTES.MANAGE}>Settings</NavLink>
</li>
)}
<RenderIf
component={
<li>
<NavLink to={APPLICATIONS_ROUTES.BASE}>Permits</NavLink>
</li>
}
permissionMatrixFeatureKey="MANAGE_PERMITS"
permissionMatrixFunctionKey="VIEW_PERMITS_SCREEN"
/>
<RenderIf
component={
<li>
<NavLink to={VEHICLES_ROUTES.MANAGE}>
Vehicle Inventory
</NavLink>
</li>
}
permissionMatrixFeatureKey="MANAGE_VEHICLE_INVENTORY"
permissionMatrixFunctionKey="VIEW_VEHICLE_INVENTORY_SCREEN"
/>
<RenderIf
component={
<li>
<NavLink to={PROFILE_ROUTES.MANAGE}>Profile</NavLink>
</li>
}
permissionMatrixFeatureKey="MANAGE_PROFILE"
permissionMatrixFunctionKey="VIEW_COMPANY_INFORMATION"
/>
<RenderIf
component={
<li>
<NavLink to={SETTINGS_ROUTES.MANAGE}>Settings</NavLink>
</li>
}
permissionMatrixFeatureKey="MANAGE_SETTINGS"
permissionMatrixFunctionKey="VIEW_SPECIAL_AUTHORIZATIONS"
/>
</>
)}
</ul>
Expand Down Expand Up @@ -118,7 +129,7 @@ export const Header = () => {
const [menuOpen, setMenuOpen] = useState(false);
const [filterOpen, setFilterOpen] = useState(false);
const { isAuthenticated, user } = useAuth();
const { companyId, userRoles } = useContext(OnRouteBCContext);
const { companyId } = useContext(OnRouteBCContext);

const username = getLoginUsernameFromSession();
const isIdir = user?.profile?.identity_provider === IDPS.IDIR;
Expand Down Expand Up @@ -154,13 +165,12 @@ export const Header = () => {
</div>
</header>
{shouldDisplayNavBar && (
<Navbar isAuthenticated={isAuthenticated} userRoles={userRoles} />
<Navbar isAuthenticated={isAuthenticated} />
)}
{shouldDisplayNavBar && menuOpen ? (
<Navbar
isAuthenticated={isAuthenticated}
isMobile={true}
userRoles={userRoles}
/>
) : null}
{filterOpen ? <SearchFilter closeFilter={toggleFilter} /> : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ import { BCEID_PROFILE_TABS } from "../../types/manageProfile.d";
import { ERROR_ROUTES, PROFILE_ROUTES } from "../../../../routes/constants";
import { getDefaultRequiredVal } from "../../../../common/helpers/util";
import { SpecialAuthorizations } from "../../../settings/pages/SpecialAuthorizations/SpecialAuthorizations";
import { CreditAccount } from "../../../settings/pages/CreditAccount";
import { useGetCreditAccountQuery } from "../../../settings/hooks/creditAccount";
import { ViewCreditAccount } from "../../../settings/pages/ViewCreditAccount";
import { useGetCreditAccountMetadataQuery } from "../../../settings/hooks/creditAccount";
import { useFeatureFlagsQuery } from "../../../../common/hooks/hooks";
import { CREDIT_ACCOUNT_USER_TYPE } from "../../../settings/types/creditAccount";
import {
canViewSpecialAuthorizations,
canViewCreditAccountTab,
} from "../../../settings/helpers/permissions";
CREDIT_ACCOUNT_USER_TYPE,
CreditAccountMetadata,
} from "../../../settings/types/creditAccount";
import { canViewSpecialAuthorizations } from "../../../settings/helpers/permissions";
import { usePermissionMatrix } from "../../../../common/authentication/PermissionMatrix";

interface ProfileDashboardTab {
label: string;
Expand Down Expand Up @@ -66,31 +67,29 @@ export const ManageProfilesDashboard = React.memo(() => {
idirUserDetails,
userDetails,
} = useContext(OnRouteBCContext);

const companyId = getDefaultRequiredVal(0, companyIdFromContext);
const { data: creditAccount } = useGetCreditAccountQuery(companyId);
const { data: creditAccountMetadata } =
useGetCreditAccountMetadataQuery(companyId);
const { data: featureFlags } = useFeatureFlagsQuery();
const populatedUserRoles = getDefaultRequiredVal([], userRoles);
const isStaffActingAsCompany = Boolean(idirUserDetails?.userAuthGroup);
const isBCeIDAdmin = isBCeIDOrgAdmin(populatedUserRoles);
const shouldAllowUserManagement = isBCeIDAdmin || isStaffActingAsCompany;
const showSpecialAuth = !isStaffActingAsCompany && canViewSpecialAuthorizations(
userRoles,
userDetails?.userAuthGroup,
) && featureFlags?.["LOA"] === "ENABLED";

const creditAccountHolder = creditAccount?.creditAccountUsers.find(
(user) => user.userType === CREDIT_ACCOUNT_USER_TYPE.HOLDER,
);
const isCreditAccountHolder = companyId === creditAccountHolder?.companyId;

const showCreditAccountTab = Boolean(
canViewCreditAccountTab(userRoles) &&
creditAccount &&
companyId &&
isCreditAccountHolder &&
featureFlags?.["CREDIT-ACCOUNT"] === "ENABLED",
);
const showSpecialAuth =
!isStaffActingAsCompany &&
canViewSpecialAuthorizations(userRoles, userDetails?.userAuthGroup) &&
featureFlags?.["LOA"] === "ENABLED";

const isCreditAccountHolder =
creditAccountMetadata?.userType === CREDIT_ACCOUNT_USER_TYPE.HOLDER;

const showCreditAccountTab = usePermissionMatrix({
featureFlag: "CREDIT-ACCOUNT",
permissionMatrixFeatureKey: "MANAGE_SETTINGS",
permissionMatrixFunctionKey: "VIEW_CREDIT_ACCOUNT_TAB",
additionalConditionToCheck: () => isCreditAccountHolder,
});

const { state: stateFromNavigation } = useLocation();

Expand All @@ -100,31 +99,42 @@ export const ManageProfilesDashboard = React.memo(() => {
component: <CompanyInfo companyInfoData={companyInfoData} />,
componentKey: BCEID_PROFILE_TABS.COMPANY_INFORMATION,
},
!isStaffActingAsCompany ? {
label: "My Information",
component: <MyInfo />,
componentKey: BCEID_PROFILE_TABS.MY_INFORMATION,
} : null,
shouldAllowUserManagement ? {
label: "Add / Manage Users",
component: <UserManagement />,
componentKey: BCEID_PROFILE_TABS.USER_MANAGEMENT,
} : null,
showSpecialAuth && companyId ? {
label: "Special Authorizations",
component: (
<SpecialAuthorizations
companyId={companyId}
/>
),
componentKey: BCEID_PROFILE_TABS.SPECIAL_AUTH,
} : null,
showCreditAccountTab ? {
label: "Credit Account",
component: <CreditAccount companyId={companyId} />,
componentKey: BCEID_PROFILE_TABS.CREDIT_ACCOUNT,
} : null,
].filter(tab => Boolean(tab)) as ProfileDashboardTab[];
!isStaffActingAsCompany
? {
label: "My Information",
component: <MyInfo />,
componentKey: BCEID_PROFILE_TABS.MY_INFORMATION,
}
: null,
shouldAllowUserManagement
? {
label: "Add / Manage Users",
component: <UserManagement />,
componentKey: BCEID_PROFILE_TABS.USER_MANAGEMENT,
}
: null,
showSpecialAuth && companyId
? {
label: "Special Authorizations",
component: <SpecialAuthorizations companyId={companyId} />,
componentKey: BCEID_PROFILE_TABS.SPECIAL_AUTH,
}
: null,
showCreditAccountTab
? {
label: "Credit Account",
component: (
<ViewCreditAccount
companyId={companyId}
creditAccountMetadata={
creditAccountMetadata as CreditAccountMetadata
}
/>
),
componentKey: BCEID_PROFILE_TABS.CREDIT_ACCOUNT,
}
: null,
].filter((tab) => Boolean(tab)) as ProfileDashboardTab[];

const getSelectedTabFromNavigation = (): number => {
const tabIndex = tabs.findIndex(
Expand Down Expand Up @@ -160,7 +170,8 @@ export const ManageProfilesDashboard = React.memo(() => {
}

if (isError) {
const isUnauthorized = error instanceof AxiosError && error.response?.status == 401;
const isUnauthorized =
error instanceof AxiosError && error.response?.status == 401;
return isUnauthorized ? (
<Navigate to={ERROR_ROUTES.UNAUTHORIZED} />
) : (
Expand Down
63 changes: 62 additions & 1 deletion frontend/src/features/settings/apiManager/creditAccount.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import {
CreditAccountData,
CreditAccountLimitData,
CreditAccountLimitType,
CreditAccountMetadata,
CreditAccountStatusType,
CreditAccountUser,
} from "../types/creditAccount";
import { CREDIT_ACCOUNT_API_ROUTES } from "../apiManager/endpoints/endpoints";
import {
Expand All @@ -28,15 +31,29 @@ export const createCreditAccount = async (data: {
);
};

/**
* Get credit account information for related to the given company ID
* @returns Credit account information for the company
*/
export const getCreditAccountMetadata = async (
companyId: number,
): Promise<CreditAccountMetadata> => {
const response = await httpGETRequest(
CREDIT_ACCOUNT_API_ROUTES.GET_CREDIT_ACCOUNT_META_DATA(companyId),
);
return response.data;
};

/**
* Get credit account information for related to the given company ID
* @returns Credit account information for the company
*/
export const getCreditAccount = async (
companyId: number,
creditAccountId: number,
): Promise<CreditAccountData> => {
const response = await httpGETRequest(
CREDIT_ACCOUNT_API_ROUTES.GET_CREDIT_ACCOUNT(companyId),
CREDIT_ACCOUNT_API_ROUTES.GET_CREDIT_ACCOUNT(companyId, creditAccountId),
);
return response.data;
};
Expand All @@ -58,9 +75,53 @@ export const getCreditAccountUsers = async (data: {
creditAccountId,
),
);
return response.data as CreditAccountUser[];
};

/**
* Get credit account users for the given credit account ID
* @param companyId Identifier of the company with which the credit Account is associated
* @param creditAccountId Identifier of the credit account to retrieve
* @returns List of credit account users for the credit account
*/
export const getCreditAccountHistory = async ({
companyId,
creditAccountId,
}: {
companyId: number;
creditAccountId: number;
}) => {
const response = await httpGETRequest(
CREDIT_ACCOUNT_API_ROUTES.GET_CREDIT_ACCOUNT_HISTORY(
companyId,
creditAccountId,
),
);
return response.data;
};

/**
* Get credit account users for the given credit account ID
* @param companyId Identifier of the company with which the credit Account is associated
* @param creditAccountId Identifier of the credit account to retrieve
* @returns List of credit account users for the credit account
*/
export const getCreditAccountLimits = async ({
companyId,
creditAccountId,
}: {
companyId: number;
creditAccountId: number;
}) => {
const response = await httpGETRequest(
CREDIT_ACCOUNT_API_ROUTES.GET_CREDIT_ACCOUNT_LIMITS(
companyId,
creditAccountId,
),
);
return response.data as CreditAccountLimitData;
};

/**
* Add a user to credit account
* @param companyId Identifier of the company with which the credit Account is associated
Expand Down
Loading