w-lab-app/src/hooks/video-guides/useVideoGuidePurchase.ts
dev.daminik00 1adac2836b add video
2025-10-28 05:58:51 +01:00

118 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useCallback, useState, useTransition } from "react";
import { useRouter } from "next/navigation";
import { checkVideoGuidePurchase } from "@/entities/dashboard/actions";
import { useSingleCheckout } from "@/hooks/payment/useSingleCheckout";
import { useToast } from "@/providers/toast-provider";
import { ROUTES } from "@/shared/constants/client-routes";
interface UseVideoGuidePurchaseOptions {
videoGuideId: string;
productId: string;
productKey: string;
}
export function useVideoGuidePurchase(options: UseVideoGuidePurchaseOptions) {
const { productId, productKey } = options;
const { addToast } = useToast();
const router = useRouter();
const [isProcessingPurchase, setIsProcessingPurchase] = useState(false);
const [isCheckingPurchase, setIsCheckingPurchase] = useState(false);
const [isPending, startTransition] = useTransition();
const { handleSingleCheckout, isLoading: isCheckoutLoading } = useSingleCheckout({
onSuccess: async () => {
// Показываем toast о успешной покупке
addToast({
variant: "success",
message: "Video guide purchased successfully!",
duration: 3000,
});
// Включаем лоадер на всей карточке
setIsProcessingPurchase(true);
// Ждем 4 секунды
await new Promise(resolve => setTimeout(resolve, 4000));
// Обновляем данные dashboard в transition
// isPending будет true пока данные загружаются
startTransition(() => {
router.refresh();
});
// Убираем наш флаг, но isPending продолжит показывать loader
setIsProcessingPurchase(false);
},
onError: error => {
addToast({
variant: "error",
message: error || "Purchase failed. Please try again.",
duration: 5000,
});
},
returnUrl: new URL(ROUTES.home(), process.env.NEXT_PUBLIC_APP_URL || "").toString(),
});
const handlePurchase = useCallback(async () => {
// Сначала проверяем, не куплен ли уже продукт
setIsCheckingPurchase(true);
try {
const result = await checkVideoGuidePurchase(productKey);
if (result.data && result.data.isPurchased) {
// Продукт уже куплен! Показываем сообщение и обновляем страницу
addToast({
variant: "success",
message: "You already own this video guide!",
duration: 3000,
});
setIsCheckingPurchase(false);
// Включаем лоадер на всей карточке
setIsProcessingPurchase(true);
// Даем небольшую задержку для плавного UX
await new Promise(resolve => setTimeout(resolve, 1000));
// Обновляем данные dashboard в transition
// isPending будет true пока данные загружаются
startTransition(() => {
router.refresh();
});
// Убираем наш флаг, но isPending продолжит показывать loader
setIsProcessingPurchase(false);
return;
}
// Продукт не куплен, продолжаем с checkout
setIsCheckingPurchase(false);
handleSingleCheckout({
productId,
key: productKey,
});
} catch (error) {
console.error("Error checking purchase status:", error);
setIsCheckingPurchase(false);
// Даже если проверка не удалась, продолжаем с checkout
// чтобы не блокировать покупку
handleSingleCheckout({
productId,
key: productKey,
});
}
}, [handleSingleCheckout, productId, productKey, addToast, router]);
return {
handlePurchase,
isCheckoutLoading: isCheckoutLoading || isCheckingPurchase, // Загрузка на кнопке (во время checkout или проверки)
isProcessingPurchase: isProcessingPurchase || isPending, // Загрузка на всей карточке (включая transition)
};
}