w-funnel/src/hooks/payment/usePaymentPlacement.ts
2025-10-07 00:48:23 +02:00

69 lines
1.8 KiB
TypeScript

"use client";
import { useEffect, useMemo, useState } from "react";
import type { FunnelDefinition } from "@/lib/funnel/types";
import { loadFunnelPaymentById } from "@/entities/session/funnel/loaders";
import type { IFunnelPaymentPlacement } from "@/entities/session/funnel/types";
interface UsePaymentPlacementArgs {
funnel: FunnelDefinition;
paymentId: string;
}
interface UsePaymentPlacementResult {
placement: IFunnelPaymentPlacement | null;
isLoading: boolean;
error: string | null;
}
export function usePaymentPlacement({
funnel,
paymentId,
}: UsePaymentPlacementArgs): UsePaymentPlacementResult {
const [placement, setPlacement] = useState<IFunnelPaymentPlacement | null>(
null
);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const funnelKey = useMemo(() => funnel?.meta?.id ?? "", [funnel]);
useEffect(() => {
let isMounted = true;
if (!funnelKey || !paymentId) return;
(async () => {
try {
setIsLoading(true);
setError(null);
const data = await loadFunnelPaymentById(
{ funnel: funnelKey },
paymentId
);
// Normalize union: record value can be IFunnelPaymentPlacement or IFunnelPaymentPlacement[] or null
const normalized: IFunnelPaymentPlacement | null = Array.isArray(data)
? data[0] ?? null
: data ?? null;
if (!isMounted) return;
setPlacement(normalized);
} catch (e) {
if (!isMounted) return;
const message =
e instanceof Error ? e.message : "Failed to load payment placement";
setError(message);
} finally {
if (isMounted) setIsLoading(false);
}
})();
return () => {
isMounted = false;
};
}, [funnelKey, paymentId]);
return { placement, isLoading, error };
}