"use client"; import { Wallet } from "lucide-react"; import Image from "next/image"; import { useCallback, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { getWalletBalance, getWalletLogs } from "@/api/wallet"; import { Button } from "@/components/ui/button"; import { Skeleton } from "@/components/ui/skeleton"; import { PlayerPanel } from "@/components/layout/player-panel"; import { TransferInDialog, TransferOutDialog, } from "@/features/wallet/wallet-transfer-dialogs"; import { WalletLogsBlock } from "@/features/wallet/wallet-logs-block"; import { dispatchWalletLogsRefresh } from "@/hooks/use-pending-wallet-reconcile"; import { useActivePlayerCurrency } from "@/hooks/use-active-player-currency"; import { formatMinorAsCurrency } from "@/lib/money"; import { PLAYER_CURRENCY_CHANGE_EVENT } from "@/lib/player-currency-preference"; import { formatWalletClientError } from "@/lib/wallet-api-error"; import type { WalletBalanceData } from "@/types/api/wallet-balance"; import { getWalletLogsLastPage, type WalletLogsData } from "@/types/api/wallet-logs"; const WALLET_LOGS_PAGE_SIZE = 10; export function WalletScreen() { const { activeCurrency: currency } = useActivePlayerCurrency(); const { t } = useTranslation("player"); const [balance, setBalance] = useState(null); const [logs, setLogs] = useState(null); const [filter, setFilter] = useState(""); const [loading, setLoading] = useState(true); const [logsLoading, setLogsLoading] = useState(false); const [loadingMore, setLoadingMore] = useState(false); const [error, setError] = useState(null); const loadMoreRef = useRef(null); const fetchPassRef = useRef(true); const loadLogs = useCallback(async (targetPage = 1, append = false) => { const nextLogs = await getWalletLogs({ page: targetPage, size: WALLET_LOGS_PAGE_SIZE, type: filter || undefined, currency, }); setLogs((current) => append && current ? { ...nextLogs, items: [...current.items, ...nextLogs.items] } : nextLogs, ); dispatchWalletLogsRefresh(nextLogs.pending_reconcile ?? []); return nextLogs; }, [currency, filter]); useEffect(() => { let cancelled = false; void (async () => { setError(null); if (fetchPassRef.current) { setLoading(true); fetchPassRef.current = false; } else { setLogsLoading(true); } try { const b = await getWalletBalance({ currency }); if (cancelled) return; setBalance(b); const nextLogs = await loadLogs(1, false); if (cancelled) return; setLogs(nextLogs); } catch (e) { if (!cancelled) { setError(formatWalletClientError(e, t)); } } finally { if (!cancelled) { setLoading(false); setLogsLoading(false); } } })(); return () => { cancelled = true; }; }, [currency, loadLogs, t]); const refreshAll = useCallback(async () => { setError(null); setLogsLoading(true); try { const b = await getWalletBalance({ currency }); setBalance(b); await loadLogs(1, false); } catch (e) { setError(formatWalletClientError(e, t)); } finally { setLogsLoading(false); setLoading(false); } }, [currency, loadLogs, t]); useEffect(() => { const onCurrencyChange = () => void refreshAll(); window.addEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onCurrencyChange); return () => window.removeEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onCurrencyChange); }, [refreshAll]); const hasMore = logs ? logs.page < getWalletLogsLastPage(logs) : false; const loadMore = useCallback(() => { if (!logs || !hasMore || loadingMore) return; setError(null); setLoadingMore(true); void loadLogs(logs.page + 1, true) .catch((e) => { setError(formatWalletClientError(e, t)); }) .finally(() => { setLoadingMore(false); }); }, [hasMore, loadLogs, loadingMore, logs, t]); useEffect(() => { const target = loadMoreRef.current; if (!target || loading || logsLoading || loadingMore || !hasMore) return; const observer = new IntersectionObserver( ([entry]) => { if (entry?.isIntersecting) { loadMore(); } }, { rootMargin: "160px" }, ); observer.observe(target); return () => observer.disconnect(); }, [hasMore, loadMore, loading, loadingMore, logsLoading]); return (
{error ? (

{error}

) : null}

{t("wallet.balance")}

{loading ? ( ) : (

{formatMinorAsCurrency(balance?.balance ?? 0, currency)}

)}

{t("wallet.available", { amount: formatMinorAsCurrency(balance?.available_balance ?? 0, currency), })}

); }