feat: 优化注单与钱包流水分页加载体验
- 注单列表与钱包流水支持 10 条分页、滚动触底自动加载和手动加载更多 - 新增钱包流水无更多数据提示与分页末页计算工具 - 精简钱包首页快捷入口与页面标题眉标展示 - 将下注表格草稿合计文案调整为投注金额并同步多语言翻译
This commit is contained in:
@@ -9,7 +9,9 @@ import { PlayerPanel } from "@/components/layout/player-panel";
|
||||
import { WalletLogsBlock } from "@/features/wallet/wallet-logs-block";
|
||||
import { formatWalletClientError } from "@/lib/wallet-api-error";
|
||||
import { usePlayerSessionStore } from "@/stores/player-session-store";
|
||||
import type { WalletLogsData } from "@/types/api/wallet-logs";
|
||||
import { getWalletLogsLastPage, type WalletLogsData } from "@/types/api/wallet-logs";
|
||||
|
||||
const WALLET_LOGS_PAGE_SIZE = 10;
|
||||
|
||||
export function WalletLogsScreen() {
|
||||
const profile = usePlayerSessionStore((s) => s.profile);
|
||||
@@ -18,7 +20,9 @@ export function WalletLogsScreen() {
|
||||
const [filter, setFilter] = useState("");
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [logsLoading, setLogsLoading] = useState(false);
|
||||
const [loadingMore, setLoadingMore] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const loadMoreRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const currency = useMemo(
|
||||
() => (profile?.default_currency ?? "NPR").toUpperCase(),
|
||||
@@ -27,35 +31,69 @@ export function WalletLogsScreen() {
|
||||
|
||||
const fetchPassRef = useRef(true);
|
||||
|
||||
const load = useCallback(async () => {
|
||||
const load = useCallback(async (targetPage = 1, append = false) => {
|
||||
setError(null);
|
||||
if (fetchPassRef.current) {
|
||||
if (append) {
|
||||
setLoadingMore(true);
|
||||
} else if (fetchPassRef.current) {
|
||||
setLoading(true);
|
||||
fetchPassRef.current = false;
|
||||
} else {
|
||||
setLogsLoading(true);
|
||||
}
|
||||
try {
|
||||
const L = await getWalletLogs({
|
||||
page: 1,
|
||||
size: 50,
|
||||
const nextLogs = await getWalletLogs({
|
||||
page: targetPage,
|
||||
size: WALLET_LOGS_PAGE_SIZE,
|
||||
type: filter || undefined,
|
||||
});
|
||||
setLogs(L);
|
||||
setLogs((current) =>
|
||||
append && current
|
||||
? { ...nextLogs, items: [...current.items, ...nextLogs.items] }
|
||||
: nextLogs,
|
||||
);
|
||||
} catch (e) {
|
||||
setError(formatWalletClientError(e, t));
|
||||
if (!append) {
|
||||
setLogs(null);
|
||||
}
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setLogsLoading(false);
|
||||
setLoadingMore(false);
|
||||
}
|
||||
}, [filter, t]);
|
||||
|
||||
useEffect(() => {
|
||||
queueMicrotask(() => {
|
||||
void load();
|
||||
void load(1, false);
|
||||
});
|
||||
}, [load]);
|
||||
|
||||
const hasMore = logs ? logs.page < getWalletLogsLastPage(logs) : false;
|
||||
|
||||
const loadMore = useCallback(() => {
|
||||
if (!logs || !hasMore || loadingMore) return;
|
||||
void load(logs.page + 1, true);
|
||||
}, [hasMore, load, loadingMore, logs]);
|
||||
|
||||
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 (
|
||||
<PlayerPanel
|
||||
title={t("wallet.logsTitle")}
|
||||
@@ -81,6 +119,10 @@ export function WalletLogsScreen() {
|
||||
<WalletLogsBlock
|
||||
logs={logs}
|
||||
logsLoading={loading || logsLoading}
|
||||
loadingMore={loadingMore}
|
||||
hasMore={hasMore}
|
||||
onLoadMore={loadMore}
|
||||
loadMoreRef={loadMoreRef}
|
||||
filter={filter}
|
||||
onFilterChange={setFilter}
|
||||
currency={currency}
|
||||
|
||||
Reference in New Issue
Block a user