Skip to content

Commit 7bf4e85

Browse files
committed
refactor: refine wallet transaction list layout
1 parent daf2f81 commit 7bf4e85

File tree

1 file changed

+55
-28
lines changed

1 file changed

+55
-28
lines changed

frontend/src/components/console/nav/nav-balance.tsx

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Spinner } from "@/components/ui/spinner";
99
import { Switch } from "@/components/ui/switch";
1010
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
1111
import { ConstsTransactionKind, type DomainInvitationItem, type DomainTransactionLog } from "@/api/Api";
12-
import { Item, ItemContent, ItemGroup, ItemTitle } from "@/components/ui/item";
12+
import { Item, ItemContent, ItemGroup, ItemSeparator, ItemTitle } from "@/components/ui/item";
1313
import dayjs from "dayjs";
1414
import { cn } from "@/lib/utils";
1515
import {
@@ -57,6 +57,7 @@ export default function NavBalance({ variant = "sidebar" }: NavBalanceProps) {
5757
const [hasNextPage, setHasNextPage] = useState(false);
5858
const [isLoadingMore, setIsLoadingMore] = useState(false);
5959
const loadMoreRef = useRef<HTMLDivElement>(null);
60+
const contentScrollRef = useRef<HTMLDivElement>(null);
6061
const { balance, dailyBalance, loadingSubscription, reloadSubscription, reloadWallet, subscription, user } = useCommonData();
6162

6263
const positiveKinds = new Set<string>([
@@ -172,7 +173,7 @@ export default function NavBalance({ variant = "sidebar" }: NavBalanceProps) {
172173
const fetchTranscations = useCallback(async (pageToLoad: number, replace = false) => {
173174
setIsLoadingMore(true);
174175
await apiRequest('v1UsersWalletTransactionList', {
175-
size: 10,
176+
size: 20,
176177
page: pageToLoad,
177178
}, [], (resp) => {
178179
if (resp.code === 0) {
@@ -285,26 +286,36 @@ export default function NavBalance({ variant = "sidebar" }: NavBalanceProps) {
285286
}
286287

287288
useEffect(() => {
289+
if (!dialogOpen || activeSection !== "usage") {
290+
return;
291+
}
292+
293+
const currentRef = loadMoreRef.current;
294+
const rootRef = contentScrollRef.current;
295+
if (!currentRef || !rootRef) {
296+
return;
297+
}
298+
288299
const observer = new IntersectionObserver(
289300
(entries) => {
290301
if (entries[0].isIntersecting) {
291302
loadMore();
292303
}
293304
},
294-
{ threshold: 0.1 }
305+
{
306+
root: rootRef,
307+
threshold: 0,
308+
rootMargin: "0px 0px 120px 0px",
309+
}
295310
);
296311

297-
const currentRef = loadMoreRef.current;
298-
if (currentRef) {
299-
observer.observe(currentRef);
300-
}
312+
observer.observe(currentRef);
301313

302314
return () => {
303-
if (currentRef) {
304-
observer.unobserve(currentRef);
305-
}
315+
observer.unobserve(currentRef);
316+
observer.disconnect();
306317
};
307-
}, [loadMore]);
318+
}, [activeSection, dialogOpen, hasNextPage, loadMore, transcations.length]);
308319

309320
const openDialog = useCallback((section: BalanceSectionId = "balance") => {
310321
setActiveSection(section)
@@ -651,23 +662,39 @@ export default function NavBalance({ variant = "sidebar" }: NavBalanceProps) {
651662
)
652663

653664
const usageContent = (
654-
<ItemGroup className="flex max-h-full flex-col gap-2 overflow-y-auto">
665+
<ItemGroup className="flex flex-col">
655666
{transcations.map((transaction, index) => (
656-
<Item key={`${transaction.created_at || 0}-${transaction.kind || "unknown"}-${index}`} variant="outline" size="sm">
657-
<ItemContent>
658-
<ItemTitle className="flex flex-row w-full">
659-
<div className={cn("flex flex-1 flex-row items-center", positiveKinds.has(transaction.kind || ConstsTransactionKind.TransactionKindVMConsumption) ? "text-primary" : "")}>
660-
{formatSignedAmount(transaction.amount || ((transaction.amount_balance || 0) + (transaction.amount_daily || 0)), transaction.kind)}
661-
</div>
662-
<div className="flex flex-row items-center gap-1 text-muted-foreground text-xs font-normal">
663-
{transaction.remark || getTransactionLabel(transaction.kind)}
664-
</div>
665-
<div className="text-muted-foreground text-xs ml-4">
666-
{dayjs((transaction.created_at || 0) * 1000).format("YYYY-MM-DD HH:mm:ss")}
667-
</div>
668-
</ItemTitle>
669-
</ItemContent>
670-
</Item>
667+
<div key={`${transaction.created_at || 0}-${transaction.kind || "unknown"}-${index}`}>
668+
<Item
669+
variant="default"
670+
size="sm"
671+
className="px-2 py-2"
672+
>
673+
<ItemContent>
674+
<ItemTitle className="grid w-full grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
675+
<div className="min-w-0">
676+
<div className="truncate text-sm text-foreground font-normal">
677+
{transaction.remark || getTransactionLabel(transaction.kind)}
678+
</div>
679+
<div className="mt-0.5 text-xs text-muted-foreground">
680+
{dayjs((transaction.created_at || 0) * 1000).format("YYYY-MM-DD HH:mm:ss")}
681+
</div>
682+
</div>
683+
<div
684+
className={cn(
685+
"text-right tabular-nums",
686+
positiveKinds.has(transaction.kind || ConstsTransactionKind.TransactionKindVMConsumption)
687+
? "text-green-600"
688+
: "text-red-600",
689+
)}
690+
>
691+
{formatSignedAmount(transaction.amount || ((transaction.amount_balance || 0) + (transaction.amount_daily || 0)), transaction.kind)}
692+
</div>
693+
</ItemTitle>
694+
</ItemContent>
695+
</Item>
696+
{index < transcations.length - 1 && <ItemSeparator />}
697+
</div>
671698
))}
672699
{hasNextPage && (
673700
<div ref={loadMoreRef} className="flex justify-center py-2">
@@ -735,7 +762,7 @@ export default function NavBalance({ variant = "sidebar" }: NavBalanceProps) {
735762
<div className="text-sm font-medium">{sectionMeta.title}</div>
736763
<div className="mt-1 text-xs text-muted-foreground">{sectionMeta.description}</div>
737764
</div>
738-
<div className="flex min-h-0 flex-1 flex-col overflow-y-auto p-4">
765+
<div ref={contentScrollRef} className="flex min-h-0 flex-1 flex-col overflow-y-auto p-4">
739766
{activeSection === "balance"
740767
? balanceContent
741768
: activeSection === "earn"

0 commit comments

Comments
 (0)