1- 'use client' ;
2-
1+ import React , { useState , useEffect } from 'react' ;
32import { Table , TableHead , TableRow } from '@mui/material' ;
43import * as S from '@/styles/table' ;
54import { motion } from 'framer-motion' ;
6- import type { RichListTableProps } from './types' ;
75import Link from 'next/link' ;
8- import * as React from 'react' ;
9-
10- import * as Switch from '@radix-ui/react-switch' ;
116import clsx from 'clsx' ;
7+ import type { RichListTableProps } from './types' ;
8+
129const MotionTableRow = motion ( TableRow ) ;
1310
1411interface DataItem {
15- rank : number ;
12+ rank : number ;
1613 account : string ;
1714 amount : number ;
18- url ?: string ;
19- }
20-
21- interface ValidatorsTableProps {
22- liquidData : DataItem [ ] ;
23- stakedData : DataItem [ ] ;
2415}
2516
2617export default function RichListTable ( { data, data2 } : RichListTableProps ) {
2718 const numberFormat = new Intl . NumberFormat ( 'en-US' , { style : 'decimal' } ) ;
19+ const [ selectedTab , setSelectedTab ] = useState ( 'balance' ) ;
20+
21+ const calculateTotalData = ( ) => {
22+ const combinedData = [ ...data , ...data2 ] ;
23+ const accountMap = new Map ( ) ;
24+
25+ combinedData . forEach ( ( item ) => {
26+ if ( accountMap . has ( item . account ) ) {
27+ const existing = accountMap . get ( item . account ) ;
28+ accountMap . set ( item . account , { ...item , amount : existing . amount + item . amount } ) ;
29+ } else {
30+ accountMap . set ( item . account , item ) ;
31+ }
32+ } ) ;
33+
34+ return Array . from ( accountMap . values ( ) ) . sort ( ( a , b ) => b . amount - a . amount ) ;
35+ } ;
2836
29- const [ showLiquid , setShowLiquid ] = React . useState ( false ) ; // if (true) default:topstakers
30- const toggleDataView = ( ) => setShowLiquid ( ! showLiquid ) ;
31- const dataToDisplay = showLiquid ? data : data2 ;
37+ const [ totalData , setTotalData ] = useState < DataItem [ ] > ( calculateTotalData ( ) ) ;
3238
39+ useEffect ( ( ) => {
40+ setTotalData ( calculateTotalData ( ) ) ;
41+ } , [ data , data2 , selectedTab ] ) ;
42+
43+ const dataToDisplay = selectedTab === 'holders' ? data : selectedTab === 'stakers' ? data2 : totalData ;
3344
3445 return (
3546 < >
3647 < div className = 'flex items-center mb-6 justify-center' >
37- < div
38- className = { clsx ( 'text-base font-medium leading-none transition' , {
39- 'text-shade-400' : showLiquid ,
40- 'text-black' : ! showLiquid ,
41- } ) }
42- >
43- Top Holders
44- </ div >
45- < Switch . Root
46- checked = { showLiquid }
47- onCheckedChange = { toggleDataView }
48- className = 'relative mx-4 w-16 rounded-full bg-shade-100 py-1.5 outline-none border'
49- style = { { WebkitTapHighlightColor : 'rgba(0, 0, 0, 0)' } }
50- >
51- < Switch . Thumb className = 'block h-6 w-6 translate-x-1.5 rounded-full bg-indigo-500 transition will-change-transform data-[state=checked]:translate-x-[34px]' />
52- </ Switch . Root >
53- < div className = 'relative' >
54- < div
55- className = { clsx ( 'text-base font-medium leading-none transition' , {
56- 'text-shade-400' : ! showLiquid ,
57- 'text-black' : showLiquid ,
58- } ) }
59- >
60- Top Stakers
61- </ div >
48+ < div className = "flex gap-4" >
49+ < button onClick = { ( ) => setSelectedTab ( 'balance' ) } className = { clsx ( 'px-4 py-2 rounded' , { 'bg-indigo-500 text-white' : selectedTab === 'balance' , 'bg-shade-100 text-shade-400' : selectedTab !== 'balance' } ) } > Top Balance</ button >
50+ < button onClick = { ( ) => setSelectedTab ( 'holders' ) } className = { clsx ( 'px-4 py-2 rounded' , { 'bg-indigo-500 text-white' : selectedTab === 'holders' , 'bg-shade-100 text-shade-400' : selectedTab !== 'holders' } ) } > Top Holders</ button >
51+ < button onClick = { ( ) => setSelectedTab ( 'stakers' ) } className = { clsx ( 'px-4 py-2 rounded' , { 'bg-indigo-500 text-white' : selectedTab === 'stakers' , 'bg-shade-100 text-shade-400' : selectedTab !== 'stakers' } ) } > Top Stakers</ button >
6252 </ div >
6353 </ div >
6454
65-
6655 < div className = 'w-full overflow-x-auto rounded-md border border-shade-200 bg-white' >
67- < Table aria-label = 'Validators Table' >
56+ < Table aria-label = 'Rich List Table' >
6857 < TableHead >
6958 < S . StyledTableRow >
70- < S . StyledTableHeadCell size = 'medium' > RANK</ S . StyledTableHeadCell >
71- < S . StyledTableHeadCell size = 'medium' >
72- ACCOUNT
73- </ S . StyledTableHeadCell >
74- < S . StyledTableHeadCell size = 'medium' >
75- TOTAL
76- </ S . StyledTableHeadCell >
77-
59+ < S . StyledTableHeadCell > RANK</ S . StyledTableHeadCell >
60+ < S . StyledTableHeadCell > ACCOUNT</ S . StyledTableHeadCell >
61+ < S . StyledTableHeadCell > TOTAL</ S . StyledTableHeadCell >
7862 </ S . StyledTableRow >
7963 </ TableHead >
8064 < S . StyledTableBody >
8165 { dataToDisplay . map ( ( item , index ) => (
8266 < MotionTableRow
8367 key = { index }
84- initial = { { height : 0 , opacity : 0 } }
85- animate = { {
86- height : 'auto' ,
87- display : 'table-row' ,
88- opacity : 1 ,
89- transition : {
90- duration : 0.6 ,
91- } ,
92- } }
93- exit = { {
94- height : 0 ,
95- opacity : 0 ,
96- display : 'none' ,
97- transition : {
98- duration : 0.2 ,
99- } ,
100- } }
68+ initial = { { opacity : 0 } }
69+ animate = { { opacity : 1 , transition : { duration : 0.5 } } }
70+ exit = { { opacity : 0 , transition : { duration : 0.3 } } }
10171 >
102- < S . StyledTableCell size = 'medium' >
103- < span className = 'text-primary' > { index + 1 } </ span >
104- </ S . StyledTableCell >
105- < S . StyledTableCell size = 'medium' >
106- < Link
107- href = { `/address/${ item . account } ` }
108- className = 'inline-block max-w-full truncate align-middle hover:underline'
109- >
110- < span className = '' > { item . account } </ span >
72+ < S . StyledTableCell > { index + 1 } </ S . StyledTableCell >
73+ < S . StyledTableCell >
74+ < Link href = { `/address/${ item . account } ` } >
75+ { item . account }
11176 </ Link >
11277 </ S . StyledTableCell >
113- < S . StyledTableCell size = 'medium' >
114- < span className = '' > { numberFormat . format ( item . amount ) } </ span >
115- </ S . StyledTableCell >
116-
117-
118- < S . StyledTableCell size = 'medium' >
119- < a
120- href = "{row.url}"
121- target = '_blank'
122- className = 'text-primary hover:underline'
123- >
124-
125- </ a >
78+ < S . StyledTableCell >
79+ { numberFormat . format ( item . amount ) }
12680 </ S . StyledTableCell >
12781 </ MotionTableRow >
12882 ) ) }
@@ -131,4 +85,4 @@ export default function RichListTable({ data, data2 }: RichListTableProps) {
13185 </ div >
13286 </ >
13387 ) ;
134- }
88+ }
0 commit comments