Skip to content
This repository was archived by the owner on Apr 10, 2025. It is now read-only.

Commit 2aa4070

Browse files
authored
fix: #265: route book styles (#270)
* refactor: #265: split route book into multiple files and improve styles * feat: improve text styles for route book
1 parent a1c04fd commit 2aa4070

File tree

9 files changed

+265
-271
lines changed

9 files changed

+265
-271
lines changed

src/pages/trade/ui/route-book.tsx

Lines changed: 0 additions & 175 deletions
This file was deleted.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React from 'react';
2+
import { observer } from 'mobx-react-lite';
3+
import { BlockchainError } from '@/shared/ui/blockchain-error';
4+
import { usePathSymbols } from '../../model/use-path';
5+
import { useBook } from '../../api/book';
6+
import { calculateRelativeSizes } from './utils';
7+
import { RouteBookLoadingRow } from './loading-row';
8+
import { TradeRow } from './trade-row';
9+
import { SpreadRow } from './spread-row';
10+
import { RouteBookHeader } from './header-row';
11+
12+
export const RouteBook = observer(() => {
13+
const { data, isLoading, error: bookErr } = useBook();
14+
15+
const multiHops = data?.multiHops;
16+
const pair = usePathSymbols();
17+
18+
const sellRelativeSizes = calculateRelativeSizes(multiHops?.sell ?? []);
19+
const buyRelativeSizes = calculateRelativeSizes(multiHops?.buy ?? []);
20+
21+
if (bookErr) {
22+
return (
23+
<div className='flex items-center justify-center p-4 min-h-[600px]'>
24+
<BlockchainError
25+
message='An error occurred while loading data from the blockchain'
26+
direction='column'
27+
/>
28+
</div>
29+
);
30+
}
31+
32+
if (isLoading || !multiHops) {
33+
return (
34+
<div className='mt-2 w-full grid grid-cols-[1fr_1fr_1fr_1fr] gap-x-2 auto-rows-[32px]'>
35+
<RouteBookHeader quote={pair.quoteSymbol} base={pair.baseSymbol} />
36+
{Array(17)
37+
.fill(1)
38+
.map((_, i) => (
39+
<RouteBookLoadingRow isSpread={i === 8} key={i} />
40+
))}
41+
</div>
42+
);
43+
}
44+
45+
return (
46+
<div className='mt-2 w-full grid grid-cols-[1fr_1fr_1fr_1fr] gap-x-2 auto-rows-[32px] items-center'>
47+
<RouteBookHeader quote={pair.quoteSymbol} base={pair.baseSymbol} />
48+
49+
{multiHops.sell.map((trace, idx) => (
50+
<TradeRow
51+
key={`${trace.price}-${trace.total}-${idx}`}
52+
trace={trace}
53+
isSell={true}
54+
relativeSize={sellRelativeSizes.get(trace.total) ?? 0}
55+
/>
56+
))}
57+
58+
<SpreadRow sellOrders={multiHops.sell} buyOrders={multiHops.buy} />
59+
60+
{multiHops.buy.map((trace, idx) => (
61+
<TradeRow
62+
key={`${trace.price}-${trace.total}-${idx}`}
63+
trace={trace}
64+
isSell={false}
65+
relativeSize={buyRelativeSizes.get(trace.total) ?? 0}
66+
/>
67+
))}
68+
</div>
69+
);
70+
});
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Text } from '@penumbra-zone/ui/Text';
2+
3+
export interface OrderBookHeaderProps {
4+
base: string;
5+
quote: string;
6+
}
7+
8+
export const RouteBookHeader = ({ base, quote }: OrderBookHeaderProps) => {
9+
return (
10+
<div className='grid grid-cols-subgrid col-span-4 text-xs text-text-secondary px-4 border-b border-b-other-tonalStroke'>
11+
<div className='py-2 text-left'>
12+
<Text tableItemSmall>Price({quote})</Text>
13+
</div>
14+
<div className='py-2 text-right'>
15+
<Text tableItemSmall>Amount({base})</Text>
16+
</div>
17+
<div className='py-2 text-right'>
18+
<Text tableItemSmall>Total</Text>
19+
</div>
20+
<div className='py-2 text-right'>
21+
<Text tableItemSmall>Route</Text>
22+
</div>
23+
</div>
24+
);
25+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { RouteBook } from './book';
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Skeleton } from '@/shared/ui/skeleton';
2+
3+
export interface RouteBookLoadingRowProps {
4+
isSpread: boolean;
5+
}
6+
7+
export const RouteBookLoadingRow = ({ isSpread }: RouteBookLoadingRowProps) =>
8+
isSpread ? (
9+
<div className='col-span-4 flex items-center justify-center gap-2 px-3 py-3 text-xs border-b border-b-other-tonalStroke'>
10+
<div className='w-[78px] h-[16px]'>
11+
<Skeleton />
12+
</div>
13+
<div className='w-[54px] h-[16px]'>
14+
<Skeleton />
15+
</div>
16+
<div className='w-[69px] h-[16px]'>
17+
<Skeleton />
18+
</div>
19+
<div className='w-[39px] h-[16px]'>
20+
<Skeleton />
21+
</div>
22+
</div>
23+
) : (
24+
<div className='grid grid-cols-subgrid col-span-4 items-center group relative border-b border-b-other-tonalStroke px-4'>
25+
<div className='w-[56px] h-[16px]'>
26+
<Skeleton />
27+
</div>
28+
<div className='w-[56px] h-[16px] ml-auto'>
29+
<Skeleton />
30+
</div>
31+
<div className='w-[56px] h-[16px] ml-auto'>
32+
<Skeleton />
33+
</div>
34+
<div className='w-[24px] h-[16px] ml-auto'>
35+
<Skeleton />
36+
</div>
37+
</div>
38+
);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Text } from '@penumbra-zone/ui/Text';
2+
import type { Trace } from '@/shared/api/server/book/types';
3+
import { calculateSpread } from '../../model/trace';
4+
import { usePathSymbols } from '../../model/use-path';
5+
import { formatNumber } from './utils';
6+
7+
export const SpreadRow = ({
8+
sellOrders,
9+
buyOrders,
10+
}: {
11+
sellOrders: Trace[];
12+
buyOrders: Trace[];
13+
}) => {
14+
const spreadInfo = calculateSpread(sellOrders, buyOrders);
15+
const pair = usePathSymbols();
16+
17+
if (!spreadInfo) {
18+
return null;
19+
}
20+
21+
return (
22+
<div className='col-span-4 flex items-center h-full justify-center gap-2 px-3 py-3 text-xs border-b border-b-other-tonalStroke'>
23+
<Text detailTechnical color='success.light'>
24+
{formatNumber(spreadInfo.midPrice, 7)}
25+
</Text>
26+
<Text detailTechnical color='text.secondary'>
27+
Spread:
28+
</Text>
29+
<Text detailTechnical color='text.primary'>
30+
{formatNumber(spreadInfo.amount, 6)} {pair.quoteSymbol}
31+
</Text>
32+
<Text detailTechnical color='text.secondary'>
33+
({parseFloat(spreadInfo.percentage).toFixed(2)}%)
34+
</Text>
35+
</div>
36+
);
37+
};

0 commit comments

Comments
 (0)