refactor(payment): centralize route lifecycle

This commit is contained in:
2026-07-15 18:47:01 +08:00
parent 7dce1b5d4c
commit 590dee417b
9 changed files with 203 additions and 144 deletions
+83
View File
@@ -0,0 +1,83 @@
"use client";
import { type Dispatch, useEffect, useRef } from "react";
import type { PayChannel } from "@/data/dto/payment";
import type { PendingPaymentSubscriptionType } from "@/lib/payment/pending_payment_order";
import {
usePaymentDispatch,
usePaymentState,
type PaymentContextState,
} from "@/stores/payment/payment-context";
import type { PaymentEvent } from "@/stores/payment/payment-events";
import type { PaymentPlanCatalog } from "@/stores/payment/payment-state";
import { usePendingPaymentOrderLifecycle } from "./use-pending-payment-order-lifecycle";
export interface UsePaymentRouteFlowInput {
catalog?: PaymentPlanCatalog;
initialPayChannel: PayChannel;
paymentType: PendingPaymentSubscriptionType;
shouldResumePendingOrder: boolean;
}
export interface PaymentRouteFlow {
payment: PaymentContextState;
paymentDispatch: Dispatch<PaymentEvent>;
}
/**
* Owns the lifecycle shared by payment entry routes:
* initialize the requested catalog and restore or clean up redirect orders.
*/
export function usePaymentRouteFlow({
catalog = "default",
initialPayChannel,
paymentType,
shouldResumePendingOrder,
}: UsePaymentRouteFlowInput): PaymentRouteFlow {
const payment = usePaymentState();
const paymentDispatch = usePaymentDispatch();
const initialPayChannelAppliedRef = useRef(false);
usePendingPaymentOrderLifecycle({
payment,
paymentDispatch,
paymentType,
shouldResumePendingOrder,
});
useEffect(() => {
if (payment.status === "idle") {
initialPayChannelAppliedRef.current = true;
paymentDispatch({
type: "PaymentInit",
catalog,
payChannel: initialPayChannel,
});
return;
}
if (
initialPayChannelAppliedRef.current ||
payment.status !== "ready"
) {
return;
}
initialPayChannelAppliedRef.current = true;
if (payment.payChannel === initialPayChannel) return;
paymentDispatch({
type: "PaymentPayChannelChanged",
payChannel: initialPayChannel,
});
}, [
catalog,
initialPayChannel,
payment.payChannel,
payment.status,
paymentDispatch,
]);
return { payment, paymentDispatch };
}