add auto refill

This commit is contained in:
dev.daminik00 2025-08-24 01:41:12 +02:00
parent 07c7588d19
commit 47fea81380
2 changed files with 44 additions and 1 deletions

View File

@ -4,6 +4,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { fetchChatMessages } from "@/entities/chats/actions";
import type { IChatMessage } from "@/entities/chats/types";
import { useSingleCheckout } from "@/hooks/payment/useSingleCheckout";
import { useSocketEvent } from "@/hooks/socket/useSocketEvent";
import { useChatStore } from "@/providers/chat-store-provider";
import {
@ -112,6 +113,20 @@ export const useChatSocket = (
emit("fetch_balance", { chatId });
}, [emit, chatId]);
// Auto top-up: use existing single checkout flow
const { handleSingleCheckout, isLoading: isAutoTopUpLoading } = useSingleCheckout({
onSuccess: fetchBalance,
onError: () => {
// eslint-disable-next-line no-console
console.error("Auto top-up payment failed");
// Release in-flight lock on error so a future event can retry
autoTopUpInProgressRef.current = false;
},
});
// Auto top-up: silent flow (no UI prompt)
const autoTopUpInProgressRef = useRef(false);
const balancePollId = useRef<NodeJS.Timeout | null>(null);
const startBalancePolling = useCallback(() => {
@ -177,13 +192,32 @@ export const useChatSocket = (
options.onNewMessage(data[0]);
}
});
useSocketEvent("current_balance", b => setBalance(b.data));
useSocketEvent("current_balance", b => {
setBalance(b.data);
// If auto top-up was in-flight, release the lock only after balance became positive
if (autoTopUpInProgressRef.current && b?.data?.balance > 0) {
autoTopUpInProgressRef.current = false;
}
});
useSocketEvent("balance_updated", b => {
setBalance(prev => (prev ? { ...prev, balance: b.data.balance } : null));
if (autoTopUpInProgressRef.current && b?.data?.balance > 0) {
autoTopUpInProgressRef.current = false;
}
});
useSocketEvent("session_started", s => setSession(s.data));
useSocketEvent("session_ended", () => setSession(null));
useSocketEvent("show_refill_modals", r => setRefillModals(r.data));
useSocketEvent("auto_topup_request", r => {
if (!r?.data) return;
if (isAutoTopUpLoading) return;
// Prevent concurrent or rapid duplicate attempts
if (autoTopUpInProgressRef.current) return;
autoTopUpInProgressRef.current = true;
// Trigger checkout silently
handleSingleCheckout(r.data);
});
useEffect(() => {
if (!session?.maxFinishedAt) return;

View File

@ -44,6 +44,12 @@ export interface IRefillModals {
products?: IRefillModalsProduct[];
}
export interface IAutoTopUpRequest {
productId: string;
key: string;
isAutoTopUp?: boolean;
}
export interface IUnreadMessagesCount {
unreadCount: number;
}
@ -81,6 +87,9 @@ export interface ServerToClientEvents {
show_refill_modals: (
data: ServerToClientEventsBaseData<IRefillModals>
) => void;
auto_topup_request: (
data: ServerToClientEventsBaseData<IAutoTopUpRequest>
) => void;
chats_updated: (data: IGetChatsListResponse) => void;
unread_messages_count: (data: IUnreadMessagesCount) => void;
}