Merge pull request #4772 from Infisical/fix/made-upgrade-license-modal-intrusive

[ENG-3937] fix: makes upgrade license modal intrusive
This commit is contained in:
Piyush Gupta
2025-10-31 20:11:32 +05:30
committed by GitHub
3 changed files with 46 additions and 19 deletions
+16 -10
View File
@@ -14,6 +14,7 @@ export type ModalContentProps = Omit<DialogPrimitive.DialogContentProps, "title"
bodyClassName?: string; bodyClassName?: string;
onClose?: () => void; onClose?: () => void;
overlayClassName?: string; overlayClassName?: string;
showCloseButton?: boolean;
}; };
export const ModalContent = forwardRef<HTMLDivElement, ModalContentProps>( export const ModalContent = forwardRef<HTMLDivElement, ModalContentProps>(
@@ -27,6 +28,7 @@ export const ModalContent = forwardRef<HTMLDivElement, ModalContentProps>(
footerContent, footerContent,
bodyClassName, bodyClassName,
onClose, onClose,
showCloseButton = true,
...props ...props
}, },
forwardedRef forwardedRef
@@ -57,15 +59,17 @@ export const ModalContent = forwardRef<HTMLDivElement, ModalContentProps>(
{children} {children}
</CardBody> </CardBody>
{footerContent && <CardFooter>{footerContent}</CardFooter>} {footerContent && <CardFooter>{footerContent}</CardFooter>}
<DialogPrimitive.Close aria-label="Close" asChild onClick={onClose}> {showCloseButton && (
<IconButton <DialogPrimitive.Close aria-label="Close" asChild onClick={onClose}>
variant="plain" <IconButton
ariaLabel="close" variant="plain"
className="absolute top-4 right-6 rounded-sm text-bunker-400 hover:text-bunker-50" ariaLabel="close"
> className="absolute top-4 right-6 rounded-sm text-bunker-400 hover:text-bunker-50"
<FontAwesomeIcon icon={faTimes} size="lg" className="cursor-pointer" /> >
</IconButton> <FontAwesomeIcon icon={faTimes} size="lg" className="cursor-pointer" />
</DialogPrimitive.Close> </IconButton>
</DialogPrimitive.Close>
)}
</Card> </Card>
</DialogPrimitive.Content> </DialogPrimitive.Content>
</DialogPrimitive.Portal> </DialogPrimitive.Portal>
@@ -74,7 +78,9 @@ export const ModalContent = forwardRef<HTMLDivElement, ModalContentProps>(
ModalContent.displayName = "ModalContent"; ModalContent.displayName = "ModalContent";
export type ModalProps = Omit<DialogPrimitive.DialogProps, "open"> & { isOpen?: boolean }; export type ModalProps = Omit<DialogPrimitive.DialogProps, "open"> & {
isOpen?: boolean;
};
export const Modal = ({ isOpen, ...props }: ModalProps) => ( export const Modal = ({ isOpen, ...props }: ModalProps) => (
<DialogPrimitive.Root open={isOpen} {...props} /> <DialogPrimitive.Root open={isOpen} {...props} />
); );
@@ -59,6 +59,7 @@ export type SubscriptionPlan = {
enterpriseAppConnections: boolean; enterpriseAppConnections: boolean;
cardDeclined?: boolean; cardDeclined?: boolean;
cardDeclinedReason?: string; cardDeclinedReason?: string;
cardDeclinedDays?: number;
machineIdentityAuthTemplates: boolean; machineIdentityAuthTemplates: boolean;
pam: boolean; pam: boolean;
}; };
@@ -141,12 +141,10 @@ export const Navbar = () => {
enabled: Boolean(subscription.subOrganization) enabled: Boolean(subscription.subOrganization)
}); });
useEffect(() => { const isCardDeclined = Boolean(subscription?.cardDeclined);
if (subscription?.cardDeclined && !sessionStorage.getItem("paymentFailed")) { const isCardDeclinedMoreThan30Days = Boolean(
sessionStorage.setItem("paymentFailed", "true"); isCardDeclined && subscription?.cardDeclinedDays && subscription?.cardDeclinedDays >= 30
setShowCardDeclinedModal(true); );
}
}, [subscription]);
const { data: orgs } = useGetOrganizations(); const { data: orgs } = useGetOrganizations();
const navigate = useNavigate(); const navigate = useNavigate();
@@ -158,6 +156,23 @@ export const Navbar = () => {
const [isOrgSelectOpen, setIsOrgSelectOpen] = useState(false); const [isOrgSelectOpen, setIsOrgSelectOpen] = useState(false);
const location = useLocation(); const location = useLocation();
const isBillingPage = location.pathname === "/organization/billing";
const isModalIntrusive = Boolean(!isBillingPage && isCardDeclinedMoreThan30Days);
useEffect(() => {
if (isModalIntrusive) {
setShowCardDeclinedModal(true);
sessionStorage.setItem("paymentFailed", "true");
return;
}
if (isCardDeclined && !sessionStorage.getItem("paymentFailed")) {
sessionStorage.setItem("paymentFailed", "true");
setShowCardDeclinedModal(true);
}
}, [subscription, isBillingPage, isModalIntrusive]);
const matches = useRouterState({ select: (s) => s.matches.at(-1)?.context }); const matches = useRouterState({ select: (s) => s.matches.at(-1)?.context });
const breadcrumbs = matches && "breadcrumbs" in matches ? matches.breadcrumbs : undefined; const breadcrumbs = matches && "breadcrumbs" in matches ? matches.breadcrumbs : undefined;
@@ -689,7 +704,10 @@ export const Navbar = () => {
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
<Modal isOpen={showCardDeclinedModal} onOpenChange={setShowCardDeclinedModal}> <Modal
isOpen={showCardDeclinedModal}
onOpenChange={() => !isModalIntrusive && setShowCardDeclinedModal(false)}
>
<ModalContent <ModalContent
title={ title={
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@@ -697,6 +715,7 @@ export const Navbar = () => {
Your payment could not be processed. Your payment could not be processed.
</div> </div>
} }
showCloseButton={!isModalIntrusive}
> >
<div> <div>
<div> <div>
@@ -717,15 +736,16 @@ export const Navbar = () => {
> >
Update Payment Method Update Payment Method
</Button> </Button>
</Link>
{!isModalIntrusive && (
<Button <Button
colorSchema="secondary" colorSchema="secondary"
variant="outline" variant="outline"
className="ml-2"
onClick={() => setShowCardDeclinedModal(false)} onClick={() => setShowCardDeclinedModal(false)}
> >
Dismiss Dismiss
</Button> </Button>
</Link> )}
</div> </div>
</div> </div>
</div> </div>