Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | 22x 22x 22x 22x 22x 350x 350x 350x 350x 350x 350x 350x 350x 4x 1x | import { useState } from "react";
import { Box } from "@mui/material";
import { InfoIcon, XIcon } from "@phosphor-icons/react";
import GiveAlert from "@shared/GiveAlert/GiveAlert";
import GiveIconButton from "@shared/IconButton/GiveIconButton";
import { checkPortals } from "@utils/routing";
import { useMerchantSidePanelContext } from "../../Provider/MerchantSidePanelProvider";
const ATTENTION_LABEL = "Attention";
// QA PAH006 (DEV): the new PAH had to re-onboard their identity. Once they
// finish, the acquirer is prompted to review the now-updated merchant details.
const PAH_CHANGED_REVIEW_DESCRIPTION =
"The primary account holder for this merchant has been changed. Please review the updated information.";
// QA PAH006 (STG) / bug 4: the new PAH was already approved for another
// merchant, so no further approval is required — purely informational.
const PAH_PREVIOUSLY_APPROVED_DESCRIPTION =
"The merchant's Primary Account Holder has been updated and was previously approved for another merchant; therefore, no additional approval is required.";
const REVIEW_BANNER_TEST_ID = "pah-changed-review-banner";
const PREVIOUSLY_APPROVED_BANNER_TEST_ID = "pah-previously-approved-banner";
/**
* First-side-panel banner shown to the acquirer/provider when a merchant's
* Primary Account Holder has been reassigned. Renders above the merchant title
* (see SidePanelBody) per the PAH006 mockups. Two mutually-exclusive variants:
*
* - identity-only re-onboarding finished → "review the updated information"
* - new PAH already approved elsewhere → "no additional approval is required"
*/
export default function PahReassignmentBanner() {
const { data, isProvider } = useMerchantSidePanelContext();
const { isAcquirerPortal, isEnterprisePortal } = checkPortals();
const [isDismissed, setIsDismissed] = useState(false);
// Merchants-first rollout: providers stay on the old owner-change flow, so the
// new-flow banner only renders for acquirer/enterprise sessions on a merchant.
const isEligible =
!isProvider && (isAcquirerPortal || isEnterprisePortal);
// Gate the "review the updated information" banner on an ACTUAL reassignment
// the new PAH has engaged with — it appears once they have accepted and
// submitted identity (state === "ready_for_approval"), which is when there is
// genuinely updated info for the acquirer to review. Do NOT gate on the raw
// `isPahReassignmentIdentityOnly` flag: the BE derives it merchant-wide from
// "onboarding completed && open PAH-identity task" with no reassignment
// awareness, so it is true for any merchant sitting in underwriting/KYB — even
// one whose PAH was never changed (`pendingChangeRequest` null). That caused
// the banner to show on merchants with no reassignment (PAH006 regression).
const isIdentityOnlyReview =
data?.pahReassignment?.state === "ready_for_approval";
const isPreviouslyApproved =
data?.pahReassignment?.state === "pending_reassignment" &&
data?.pahReassignment?.newPahStatusName === "approved";
const banner = isIdentityOnlyReview
? {
description: PAH_CHANGED_REVIEW_DESCRIPTION,
testId: REVIEW_BANNER_TEST_ID,
}
: isPreviouslyApproved
? {
description: PAH_PREVIOUSLY_APPROVED_DESCRIPTION,
testId: PREVIOUSLY_APPROVED_BANNER_TEST_ID,
}
: null;
if (!isEligible || isDismissed || !banner) return null;
return (
<Box sx={{ position: "relative" }}>
{/* Neutral (gray) styling with an info icon, per the PAH006 mockups. */}
<GiveAlert
type="default"
variant="alert"
withBorder
Icon={<InfoIcon />}
label={ATTENTION_LABEL}
description={banner.description}
dataTestId={banner.testId}
textContainerSx={{ paddingRight: "28px" }}
/>
<GiveIconButton
Icon={XIcon}
variant="ghost"
size="small"
onClick={() => setIsDismissed(true)}
data-testid={`${banner.testId}-close`}
sx={{ position: "absolute", top: 8, right: 8 }}
/>
</Box>
);
}
|