From 089871af3e0091877410efcf19c82876a7b5e5fd Mon Sep 17 00:00:00 2001 From: chenhang Date: Mon, 29 Jun 2026 20:04:10 +0800 Subject: [PATCH] fix(subscription): remove animations affecting stripe dialog --- .../stripe-payment-dialog.module.css | 19 +- .../subscription-checkout-button.tsx | 38 +++- .../components/subscription-screen.module.css | 28 --- src/app/subscription/subscription-screen.tsx | 200 +++++++----------- 4 files changed, 121 insertions(+), 164 deletions(-) diff --git a/src/app/subscription/components/stripe-payment-dialog.module.css b/src/app/subscription/components/stripe-payment-dialog.module.css index bf09a585..2cd64a18 100644 --- a/src/app/subscription/components/stripe-payment-dialog.module.css +++ b/src/app/subscription/components/stripe-payment-dialog.module.css @@ -2,26 +2,17 @@ position: fixed; inset: 0; z-index: 70; - display: block; - height: 100dvh; - padding: - max(24px, env(safe-area-inset-top)) - 20px - max(20px, env(safe-area-inset-bottom)); - overflow-y: auto; + display: flex; + align-items: center; + justify-content: center; + padding: 20px; background: rgba(0, 0, 0, 0.5); - overscroll-behavior: contain; } .dialog { width: 100%; max-width: 420px; - max-height: calc( - 100dvh - - max(48px, env(safe-area-inset-top)) - - max(20px, env(safe-area-inset-bottom)) - ); - margin: clamp(0px, 6dvh, 48px) auto 0; + max-height: calc(100vh - 40px); overflow-y: auto; border-radius: 32px; background: var(--color-page-background, #ffffff); diff --git a/src/app/subscription/components/subscription-checkout-button.tsx b/src/app/subscription/components/subscription-checkout-button.tsx index 9995260c..b71d3c27 100644 --- a/src/app/subscription/components/subscription-checkout-button.tsx +++ b/src/app/subscription/components/subscription-checkout-button.tsx @@ -13,6 +13,7 @@ import { } from "@/stores/payment/payment-context"; import { AppEnvUtil, Logger, Result } from "@/utils"; +import { StripePaymentDialog } from "./stripe-payment-dialog"; import dialogStyles from "./stripe-payment-dialog.module.css"; import { SubscriptionCtaButton } from "./subscription-cta-button"; import styles from "./subscription-cta-button.module.css"; @@ -34,6 +35,9 @@ export function SubscriptionCheckoutButton({ const payment = usePaymentState(); const paymentDispatch = usePaymentDispatch(); const launchedNonceRef = useRef(0); + const [hiddenStripeClientSecret, setHiddenStripeClientSecret] = useState< + string | null + >(null); const [isConfirmingEzpay, setIsConfirmingEzpay] = useState(false); useEffect(() => { @@ -94,7 +98,7 @@ export function SubscriptionCheckoutButton({ payment.isCreatingOrder || payment.isPollingOrder; const readyLabel = - subscriptionType === "topup" ? "Pay and Top Up" : "Pay and Activate"; + subscriptionType === "topup" ? "Pay and Top Up" : "Pay and Activiate"; const agreementLabel = subscriptionType === "topup" ? "Confirm the agreement and Top Up" @@ -110,9 +114,32 @@ export function SubscriptionCheckoutButton({ const handleClick = () => { if (disabled || isLoading) return; setIsConfirmingEzpay(false); + setHiddenStripeClientSecret(null); paymentDispatch({ type: "PaymentCreateOrderSubmitted" }); }; + const handleStripeClose = () => { + if (stripeClientSecret) { + setHiddenStripeClientSecret(stripeClientSecret); + } + if (payment.orderStatus !== "paid") { + paymentDispatch({ type: "PaymentReset" }); + } + }; + + const handleStripeConfirmed = () => { + if (stripeClientSecret) { + setHiddenStripeClientSecret(stripeClientSecret); + } + }; + + const stripeClientSecret = payment.payParams + ? getStripeClientSecret(payment.payParams) + : null; + const shouldShowStripeDialog = + stripeClientSecret !== null && + stripeClientSecret !== hiddenStripeClientSecret && + !payment.isPaid; const ezpayPaymentUrl = payment.payParams ? getPaymentUrl(payment.payParams) : null; @@ -181,6 +208,13 @@ export function SubscriptionCheckoutButton({ onConfirm={handleEzpayConfirm} /> ) : null} + {shouldShowStripeDialog ? ( + + ) : null} ); } @@ -332,7 +366,7 @@ function EzpayRedirectConfirmDialog({ ); } -export function getStripeClientSecret( +function getStripeClientSecret( payParams: Record, ): string | null { const provider = payParams.provider; diff --git a/src/app/subscription/components/subscription-screen.module.css b/src/app/subscription/components/subscription-screen.module.css index 80cd6087..e2f3cae5 100644 --- a/src/app/subscription/components/subscription-screen.module.css +++ b/src/app/subscription/components/subscription-screen.module.css @@ -6,7 +6,6 @@ radial-gradient(circle at 8% 4%, rgba(255, 255, 255, 0.95) 0 90px, transparent 160px), linear-gradient(180deg, #fff9fb 0%, #fcf3f4 52%, #fffefe 100%); padding: 18px 20px 10px; - animation: pageEnter 360ms ease-out both; } .header { @@ -24,7 +23,6 @@ flex-direction: column; gap: 18px; margin-top: 14px; - animation: stackEnter 420ms ease-out 80ms both; } .userSlot { @@ -70,12 +68,10 @@ .paymentMethodSlot { margin-top: 22px; - animation: stackEnter 420ms ease-out 150ms both; } .ctaSlot { margin-top: 22px; - animation: stackEnter 420ms ease-out 190ms both; } .agreementSlot { @@ -96,27 +92,3 @@ .agreementLink:hover { text-decoration: underline; } - -@keyframes pageEnter { - from { - opacity: 0; - transform: translateY(8px); - } - - to { - opacity: 1; - transform: translateY(0); - } -} - -@keyframes stackEnter { - from { - opacity: 0; - transform: translateY(14px); - } - - to { - opacity: 1; - transform: translateY(0); - } -} diff --git a/src/app/subscription/subscription-screen.tsx b/src/app/subscription/subscription-screen.tsx index ef77f69a..ca9ef45f 100644 --- a/src/app/subscription/subscription-screen.tsx +++ b/src/app/subscription/subscription-screen.tsx @@ -13,14 +13,12 @@ import { useUserDispatch } from "@/stores/user/user-context"; import { ROUTES } from "@/router/routes"; import { - getStripeClientSecret, SubscriptionBackLink, SubscriptionCheckoutButton, SubscriptionCoinsOfferSection, SubscriptionPaymentMethod, SubscriptionPaymentSuccessDialog, SubscriptionVipOfferSection, - StripePaymentDialog, } from "./components"; import styles from "./components/subscription-screen.module.css"; import { @@ -51,9 +49,6 @@ export function SubscriptionScreen({ const refreshedPaidOrderRef = useRef(null); const resumedPendingOrderRef = useRef(null); const successDialogShownOrderRef = useRef(null); - const [hiddenStripeDialogKey, setHiddenStripeDialogKey] = useState< - string | null - >(null); const [showPaymentSuccessDialog, setShowPaymentSuccessDialog] = useState(false); const canSubscribeVip = subscriptionType === "vip"; @@ -161,16 +156,6 @@ export function SubscriptionScreen({ payment.isPollingOrder; const canActivate = selectedPlan !== null && payment.agreed && !isPaymentBusy; - const stripeClientSecret = payment.payParams - ? getStripeClientSecret(payment.payParams) - : null; - const stripeDialogKey = stripeClientSecret - ? `${payment.launchNonce}:${stripeClientSecret}` - : null; - const shouldShowStripeDialog = - stripeClientSecret !== null && - stripeDialogKey !== hiddenStripeDialogKey && - !payment.isPaid; const finishPaymentSuccessClose = () => { setShowPaymentSuccessDialog(false); @@ -184,21 +169,6 @@ export function SubscriptionScreen({ finishPaymentSuccessClose(); }; - const handleStripeClose = () => { - if (stripeDialogKey) { - setHiddenStripeDialogKey(stripeDialogKey); - } - if (payment.orderStatus !== "paid") { - paymentDispatch({ type: "PaymentReset" }); - } - }; - - const handleStripeConfirmed = () => { - if (stripeDialogKey) { - setHiddenStripeDialogKey(stripeDialogKey); - } - }; - useEffect(() => { if (canSubscribeVip) { const firstVipPlanId = vipOfferPlans[0]?.id ?? ""; @@ -242,28 +212,16 @@ export function SubscriptionScreen({ ]); return ( - <> - -
-
- -
+ +
+
+ +
-
- {canSubscribeVip ? ( - - paymentDispatch({ - type: "PaymentPlanSelected", - planId, - }) - } - /> - ) : null} - + {canSubscribeVip ? ( + paymentDispatch({ @@ -272,78 +230,80 @@ export function SubscriptionScreen({ }) } /> -
- -
- - paymentDispatch({ - type: "PaymentPayChannelChanged", - payChannel, - }) - } - /> -
- -
- -
- -
- - paymentDispatch({ - type: "PaymentAgreementChanged", - agreed, - }) - } - label={ - - I agree to the{" "} - - VIP Membership Benefits Agreement - {" "} - and{" "} - - Automatic renewal Agreement - - - } - /> -
- - + paymentDispatch({ + type: "PaymentPlanSelected", + planId, + }) + } />
-
- {shouldShowStripeDialog ? ( - + + paymentDispatch({ + type: "PaymentPayChannelChanged", + payChannel, + }) + } + /> + + +
+ +
+ +
+ + paymentDispatch({ + type: "PaymentAgreementChanged", + agreed, + }) + } + label={ + + I agree to the{" "} + + VIP Membership Benefits Agreement + {" "} + and{" "} + + Automatic renewal Agreement + + + } + /> +
+ + - ) : null} - +
+
); }