add auto refill
This commit is contained in:
parent
07c7588d19
commit
47fea81380
@ -4,6 +4,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|||||||
|
|
||||||
import { fetchChatMessages } from "@/entities/chats/actions";
|
import { fetchChatMessages } from "@/entities/chats/actions";
|
||||||
import type { IChatMessage } from "@/entities/chats/types";
|
import type { IChatMessage } from "@/entities/chats/types";
|
||||||
|
import { useSingleCheckout } from "@/hooks/payment/useSingleCheckout";
|
||||||
import { useSocketEvent } from "@/hooks/socket/useSocketEvent";
|
import { useSocketEvent } from "@/hooks/socket/useSocketEvent";
|
||||||
import { useChatStore } from "@/providers/chat-store-provider";
|
import { useChatStore } from "@/providers/chat-store-provider";
|
||||||
import {
|
import {
|
||||||
@ -112,6 +113,20 @@ export const useChatSocket = (
|
|||||||
emit("fetch_balance", { chatId });
|
emit("fetch_balance", { chatId });
|
||||||
}, [emit, 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 balancePollId = useRef<NodeJS.Timeout | null>(null);
|
||||||
|
|
||||||
const startBalancePolling = useCallback(() => {
|
const startBalancePolling = useCallback(() => {
|
||||||
@ -177,13 +192,32 @@ export const useChatSocket = (
|
|||||||
options.onNewMessage(data[0]);
|
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 => {
|
useSocketEvent("balance_updated", b => {
|
||||||
setBalance(prev => (prev ? { ...prev, balance: b.data.balance } : null));
|
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_started", s => setSession(s.data));
|
||||||
useSocketEvent("session_ended", () => setSession(null));
|
useSocketEvent("session_ended", () => setSession(null));
|
||||||
useSocketEvent("show_refill_modals", r => setRefillModals(r.data));
|
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(() => {
|
useEffect(() => {
|
||||||
if (!session?.maxFinishedAt) return;
|
if (!session?.maxFinishedAt) return;
|
||||||
|
|||||||
@ -44,6 +44,12 @@ export interface IRefillModals {
|
|||||||
products?: IRefillModalsProduct[];
|
products?: IRefillModalsProduct[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IAutoTopUpRequest {
|
||||||
|
productId: string;
|
||||||
|
key: string;
|
||||||
|
isAutoTopUp?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IUnreadMessagesCount {
|
export interface IUnreadMessagesCount {
|
||||||
unreadCount: number;
|
unreadCount: number;
|
||||||
}
|
}
|
||||||
@ -81,6 +87,9 @@ export interface ServerToClientEvents {
|
|||||||
show_refill_modals: (
|
show_refill_modals: (
|
||||||
data: ServerToClientEventsBaseData<IRefillModals>
|
data: ServerToClientEventsBaseData<IRefillModals>
|
||||||
) => void;
|
) => void;
|
||||||
|
auto_topup_request: (
|
||||||
|
data: ServerToClientEventsBaseData<IAutoTopUpRequest>
|
||||||
|
) => void;
|
||||||
chats_updated: (data: IGetChatsListResponse) => void;
|
chats_updated: (data: IGetChatsListResponse) => void;
|
||||||
unread_messages_count: (data: IUnreadMessagesCount) => void;
|
unread_messages_count: (data: IUnreadMessagesCount) => void;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user