"use client"; /** * 订阅 checkout 触发按钮 * * 包装 `SubscriptionCtaButton` —— 通过 payment 状态机创建后端订单并拉起支付。 */ import { usePaymentLaunchFlow } from "@/app/_hooks/use-payment-launch-flow"; import { usePaymentDispatch, usePaymentState, } from "@/stores/payment/payment-context"; import { Logger } from "@/utils"; import { StripePaymentDialog } from "./stripe-payment-dialog"; import dialogStyles from "./stripe-payment-dialog.module.css"; import { SubscriptionCtaButton } from "./subscription-cta-button"; const log = new Logger("SubscriptionCheckoutButton"); export interface SubscriptionCheckoutButtonProps { /** 是否可用(未选套餐 / 未勾选协议 → false) */ disabled?: boolean; subscriptionType: "vip" | "topup"; returnTo?: "chat" | null; } export function SubscriptionCheckoutButton({ disabled = false, subscriptionType, returnTo = null, }: SubscriptionCheckoutButtonProps) { const payment = usePaymentState(); const paymentDispatch = usePaymentDispatch(); const paymentLaunch = usePaymentLaunchFlow({ log, logScope: "subscription-checkout", payment, paymentDispatch, returnTo: returnTo ?? undefined, subscriptionType, }); const isLoading = payment.isCreatingOrder || payment.isPollingOrder; const readyLabel = subscriptionType === "topup" ? "Pay and Top Up" : "Pay and Activiate"; const agreementLabel = subscriptionType === "topup" ? "Confirm the agreement and Top Up" : "Confirm the agreement and Activate"; const label = payment.isPollingOrder ? "Processing payment..." : payment.isCreatingOrder ? "Creating order..." : payment.agreed ? readyLabel : agreementLabel; const handleClick = () => { if (disabled || isLoading) return; paymentLaunch.resetLaunchState(); paymentDispatch({ type: "PaymentCreateOrderSubmitted" }); }; return ( <> {label} {payment.errorMessage ? (

{payment.errorMessage}

) : null} {paymentLaunch.shouldShowEzpayConfirmDialog ? ( ) : null} {paymentLaunch.shouldShowStripeDialog && paymentLaunch.stripeClientSecret ? ( ) : null} ); } interface EzpayRedirectConfirmDialogProps { orderId: string; isConfirming: boolean; onCancel: () => void; onConfirm: () => void; } function EzpayRedirectConfirmDialog({ orderId, isConfirming, onCancel, onConfirm, }: EzpayRedirectConfirmDialogProps) { return (

Continue to GCash?

Your order has been created. Continue to GCash to finish the payment.

Order No. {orderId}

); }