Skip to content

Commit 41da6a8

Browse files
committed
refactor: extract token item + fix many layout pbs
1 parent 837cb76 commit 41da6a8

File tree

2 files changed

+213
-137
lines changed

2 files changed

+213
-137
lines changed

app/components/tokenListItem.tsx

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
import { IconChevronsRight } from '@tabler/icons-react';
2+
import { Flex } from 'antd';
3+
import Image from 'next/image';
4+
import { useState } from 'react';
5+
import { twMerge } from 'tailwind-merge';
6+
import { Token } from '../hooks/useData';
7+
import { Data, Dataset } from '../utils/types';
8+
import { Privacy } from './privacy';
9+
import { TokenDetails } from './tokenDetails';
10+
11+
const t: Dataset = {
12+
tokenLogo: 'Logo du token',
13+
transfered: 'Investi',
14+
withdrawn: 'Retiré',
15+
gains: 'Gains',
16+
loss: 'Pertes',
17+
};
18+
19+
interface TokenListItemProps {
20+
asset: Token;
21+
index: number;
22+
selectedIndex?: number;
23+
hasLoaded: boolean;
24+
tokens: Token[];
25+
tokenDetails: Data[];
26+
total: number;
27+
onSelectedIndexChange: (index: number | undefined) => void;
28+
}
29+
30+
interface TokenDetailsButtonProps {
31+
index: number;
32+
selectedIndex?: number;
33+
hasLoaded: boolean;
34+
isTokenDetailsOpen: boolean;
35+
tokens: Token[];
36+
tokenDetails: Data[];
37+
total: number;
38+
onSelectedIndexChange: (index: number | undefined) => void;
39+
onTokenDetailsOpenChange: (isOpen: boolean) => void;
40+
}
41+
42+
function TokenDetailsButton({
43+
index,
44+
selectedIndex,
45+
hasLoaded,
46+
isTokenDetailsOpen,
47+
tokens,
48+
tokenDetails,
49+
total,
50+
onSelectedIndexChange,
51+
onTokenDetailsOpenChange,
52+
}: TokenDetailsButtonProps) {
53+
return (
54+
<div className="hidden xs:flex items-center mx-0 xs:mx-2 md:mx-4 w-[50px] h-[50px] justify-center">
55+
<IconChevronsRight
56+
className={twMerge(
57+
'h-8 w-8 text-theme-content-strong dark:text-dark-theme-content-strong',
58+
'transition-all duration-500 group-hover:animate-pulse',
59+
index === selectedIndex ? 'opacity-100' : 'opacity-0 group-hover:opacity-100',
60+
)}
61+
onClick={e => {
62+
e.stopPropagation();
63+
onSelectedIndexChange(index);
64+
onTokenDetailsOpenChange(true);
65+
}}
66+
/>
67+
{hasLoaded ? (
68+
<TokenDetails
69+
isOpen={isTokenDetailsOpen}
70+
onClose={() => onTokenDetailsOpenChange(false)}
71+
tokens={tokens}
72+
data={tokenDetails}
73+
total={total}
74+
selectedIndex={selectedIndex}
75+
onSelectedIndexChange={onSelectedIndexChange}
76+
/>
77+
) : null}
78+
</div>
79+
);
80+
}
81+
82+
export function TokenListLoading() {
83+
return (
84+
<div className="flex w-full animate-pulse py-4">
85+
<div className="bg-theme-border rounded-full w-[50px] h-[50px] hidden 2xs:flex items-center mx-0 xs:mx-2 md:mx-4"></div>
86+
<div className="flex flex-col px-2 md:px-4 flex-1 min-w-0">
87+
<div className="bg-theme-border rounded-md w-24 xs:w-36 md:w-44 h-7 mb-1" />
88+
<div className="bg-theme-border rounded-md w-12 h-5 mb-1" />
89+
</div>
90+
<div className="hidden sm:flex flex-col w-32">
91+
<div className="bg-theme-border rounded-md w-32 h-5 mb-1" />
92+
<div className="bg-theme-border rounded-md w-32 h-5 mb-1" />
93+
</div>
94+
<div className="flex flex-col mx-0 md:mx-2 items-end w-32 md:flex-1">
95+
<div className="bg-theme-border rounded-md w-24 h-5 mb-1" />
96+
<div className="bg-theme-border rounded-md w-16 h-7 mb-1" />
97+
</div>
98+
<div className="bg-theme-border rounded-md hidden xs:flex self-center mx-0 xs:mx-2 md:mx-4 justify-center w-8 h-8"></div>
99+
</div>
100+
);
101+
}
102+
103+
export function TokenListItem({
104+
asset,
105+
index,
106+
selectedIndex,
107+
hasLoaded,
108+
tokens,
109+
tokenDetails,
110+
total,
111+
onSelectedIndexChange,
112+
}: TokenListItemProps) {
113+
const [isTokenDetailsOpen, setIsTokenDetailsOpen] = useState(false);
114+
115+
return (
116+
<div
117+
key={asset.label}
118+
className={twMerge(
119+
'flex w-full border-b-2 last:border-b-0 border-theme-border dark:border-dark-theme-border',
120+
'group cursor-pointer select-none touch-none transition-colors duration-200 py-4',
121+
selectedIndex === index
122+
? 'bg-theme-background-subtle dark:bg-dark-theme-background-subtle'
123+
: 'hover:bg-theme-background-subtle dark:hover:bg-dark-theme-background-subtle [@media(hover:none)]:hover:bg-transparent [@media(hover:none)]:dark:hover:bg-transparent',
124+
)}
125+
onClick={() => onSelectedIndexChange(selectedIndex === index ? undefined : index)}
126+
onContextMenu={e => {
127+
e.preventDefault();
128+
e.stopPropagation();
129+
onSelectedIndexChange(index);
130+
setIsTokenDetailsOpen(true);
131+
}}
132+
>
133+
<Image
134+
className="rounded-full w-[50px] h-[50px] hidden 2xs:flex items-center mx-0 xs:mx-2 md:mx-4"
135+
src={asset.image}
136+
alt={t.tokenLogo}
137+
width={50}
138+
height={50}
139+
/>
140+
<div className="flex flex-col px-2 md:px-4 flex-1 min-w-0">
141+
<div className="text-xl truncate">{asset.label}</div>
142+
<div>{asset.value ? asset.value.toLocaleCurrency() : ''}</div>
143+
</div>
144+
{hasLoaded ? (
145+
<div className={twMerge('hidden sm:flex flex-col w-32', asset.movement ? 'opacity-100' : 'opacity-0')}>
146+
<Flex>
147+
{asset.movement >= 0 ? t.transfered : t.withdrawn}&nbsp;:&nbsp;
148+
<Privacy className="font-bold" amount={asset.movement} />
149+
</Flex>
150+
<Flex>
151+
{asset.profit >= 0 ? t.gains : t.loss}&nbsp;:&nbsp;
152+
<Privacy
153+
className={twMerge('font-bold', asset.profit >= 0 ? 'text-ok' : 'text-error')}
154+
amount={asset.profit}
155+
/>
156+
</Flex>
157+
</div>
158+
) : (
159+
<div className="hidden sm:flex flex-col w-32 animate-pulse">
160+
<div className="bg-theme-border rounded-md w-32 h-5 mb-1" />
161+
<div className="bg-theme-border rounded-md w-32 h-5 mb-1" />
162+
</div>
163+
)}
164+
<div className="flex flex-col mx-0 md:mx-2 items-end w-32 md:flex-1">
165+
<Flex className="gap-1 justify-end">
166+
<Privacy amount={asset.balance.toDecimalPlace(asset.balance.getPrecision(), 'down')} currencyType="none" />
167+
{asset.symbol}
168+
</Flex>
169+
<Privacy className="font-bold text-lg text-right" amount={asset.total} />
170+
</div>
171+
<TokenDetailsButton
172+
index={index}
173+
selectedIndex={selectedIndex}
174+
hasLoaded={hasLoaded}
175+
isTokenDetailsOpen={isTokenDetailsOpen}
176+
tokens={tokens}
177+
tokenDetails={tokenDetails}
178+
total={total}
179+
onSelectedIndexChange={onSelectedIndexChange}
180+
onTokenDetailsOpenChange={setIsTokenDetailsOpen}
181+
/>
182+
</div>
183+
);
184+
}

0 commit comments

Comments
 (0)