Merge pull request #7 from jejolare-dev/dev
feature: render token images
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 136 KiB |
BIN
public/tokens/token.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
26
src/components/UI/ImgWithFallback/index.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import Image, { ImageProps } from 'next/image';
|
||||
|
||||
type ImgWithFallbackProps = ImageProps & {
|
||||
fallbackSrc?: string;
|
||||
alt: string;
|
||||
};
|
||||
|
||||
const ImgWithFallback = ({
|
||||
src,
|
||||
alt,
|
||||
fallbackSrc = '/tokens/token.png',
|
||||
...rest
|
||||
}: ImgWithFallbackProps) => {
|
||||
const [imgSrc, setImgSrc] = useState(src);
|
||||
|
||||
useEffect(() => {
|
||||
setImgSrc(src);
|
||||
}, [src]);
|
||||
|
||||
return <Image {...rest} alt={alt} src={imgSrc} onError={() => setImgSrc(fallbackSrc)} />;
|
||||
};
|
||||
|
||||
export default ImgWithFallback;
|
||||
|
|
@ -5,6 +5,7 @@ import { ReactComponent as ArrowRight } from '@/assets/images/UI/arrow_right.svg
|
|||
import { Store } from '@/store/store-reducer';
|
||||
import PairData from '@/interfaces/common/PairData';
|
||||
import { notationToString, roundTo, tradingKnownCurrencies } from '@/utils/utils';
|
||||
import ImgWithFallback from '@/components/UI/ImgWithFallback';
|
||||
import styles from './PairsCard.module.scss';
|
||||
|
||||
interface IProps {
|
||||
|
|
@ -51,10 +52,10 @@ export default function PairsCard({ pair }: IProps) {
|
|||
return (
|
||||
<div className={styles.card}>
|
||||
<div className={styles.card__header}>
|
||||
<Image
|
||||
<ImgWithFallback
|
||||
width={18}
|
||||
height={18}
|
||||
src={`/currencies/trade_${code}.svg`}
|
||||
src={`/tokens/${firstCurrency.asset_id}.png`}
|
||||
alt="currency"
|
||||
/>
|
||||
<div className={styles.currency_name}>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// PairsTable.tsx
|
||||
import { memo, useContext, useMemo } from 'react';
|
||||
import { ColumnDef, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
||||
import { useRouter } from 'next/router';
|
||||
|
|
@ -7,29 +8,9 @@ import { Store } from '@/store/store-reducer';
|
|||
import PairData from '@/interfaces/common/PairData';
|
||||
import { ContextState } from '@/interfaces/common/ContextValue';
|
||||
import { tradingKnownCurrencies, roundTo, notationToString } from '@/utils/utils';
|
||||
import ImgWithFallback from '@/components/UI/ImgWithFallback';
|
||||
import styles from './PairsTable.module.scss';
|
||||
|
||||
type Currency = {
|
||||
code: string;
|
||||
name: string;
|
||||
whitelisted?: boolean;
|
||||
featured?: boolean;
|
||||
};
|
||||
|
||||
type Row = {
|
||||
id: string;
|
||||
pair: {
|
||||
base: Currency;
|
||||
quote: Currency;
|
||||
};
|
||||
price: number;
|
||||
priceUSD: string;
|
||||
change: number;
|
||||
volume: number;
|
||||
volumeUSD: string;
|
||||
featured: boolean;
|
||||
code: string;
|
||||
};
|
||||
import { Row } from './types';
|
||||
|
||||
function transformPairsToRows(pairs: PairData[], state: ContextState): Row[] {
|
||||
return pairs.map((pair) => {
|
||||
|
|
@ -38,17 +19,18 @@ function transformPairsToRows(pairs: PairData[], state: ContextState): Row[] {
|
|||
const price = Number(roundTo(notationToString(pair.rate ?? 0)));
|
||||
const currentPriceUSD = secondAssetUsdPrice ? price : 0;
|
||||
const priceUSD = currentPriceUSD
|
||||
? String(`$${(secondAssetUsdPrice * price).toFixed(2)}`)
|
||||
: String(`$${(secondAssetUsdPrice * price).toFixed(0)}`);
|
||||
? `$${(secondAssetUsdPrice * price).toFixed(2)}`
|
||||
: `$${(secondAssetUsdPrice * price).toFixed(0)}`;
|
||||
|
||||
const volume = Number(roundTo(notationToString(pair.volume ?? 0)));
|
||||
const currentVolumeUSD = secondAssetUsdPrice ? volume : 0;
|
||||
const volumeUSD = currentVolumeUSD
|
||||
? String(`$${(secondAssetUsdPrice * volume).toFixed(2)}`)
|
||||
: String(`$${(secondAssetUsdPrice * volume).toFixed(0)}`);
|
||||
? `$${(secondAssetUsdPrice * volume).toFixed(2)}`
|
||||
: `$${(secondAssetUsdPrice * volume).toFixed(0)}`;
|
||||
|
||||
return {
|
||||
id: pair.id,
|
||||
assetId: pair.first_currency.asset_id,
|
||||
pair: {
|
||||
base: pair.first_currency,
|
||||
quote: pair.second_currency,
|
||||
|
|
@ -74,6 +56,10 @@ function PairsTable({ data }: IProps) {
|
|||
const router = useRouter();
|
||||
const { state } = useContext(Store);
|
||||
|
||||
const rows = useMemo(() => {
|
||||
return transformPairsToRows(data, state);
|
||||
}, [data, state.assetsRates]);
|
||||
|
||||
const columns = useMemo<ColumnDef<Row>[]>(
|
||||
() => [
|
||||
{
|
||||
|
|
@ -82,15 +68,15 @@ function PairsTable({ data }: IProps) {
|
|||
cell: ({ row }) => {
|
||||
const {
|
||||
pair: { base, quote },
|
||||
code,
|
||||
featured,
|
||||
assetId,
|
||||
} = row.original;
|
||||
return (
|
||||
<div className={styles.pair_cell}>
|
||||
<Image
|
||||
<ImgWithFallback
|
||||
width={18}
|
||||
height={18}
|
||||
src={`/currencies/trade_${code}.svg`}
|
||||
src={`/tokens/${assetId}.png`}
|
||||
alt="currency"
|
||||
/>
|
||||
<div className={styles.currency_name}>
|
||||
|
|
@ -114,9 +100,8 @@ function PairsTable({ data }: IProps) {
|
|||
{
|
||||
accessorKey: 'price',
|
||||
header: ({ table }) => {
|
||||
const row = table.options.data[0] as Row;
|
||||
const name = row?.pair.quote.name;
|
||||
|
||||
const row0 = table.options.data[0] as Row | undefined;
|
||||
const name = row0?.pair.quote.name;
|
||||
return `Price ${name ? `(${name})` : ''}`;
|
||||
},
|
||||
cell: ({ row }) => (
|
||||
|
|
@ -186,13 +171,14 @@ function PairsTable({ data }: IProps) {
|
|||
),
|
||||
},
|
||||
],
|
||||
[],
|
||||
[router],
|
||||
);
|
||||
|
||||
const table = useReactTable({
|
||||
data: transformPairsToRows(data, state),
|
||||
data: rows,
|
||||
columns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getRowId: (r) => r.id,
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
|
|||
22
src/pages/dex/pairs/PairsTable/types.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
type Currency = {
|
||||
code: string;
|
||||
name: string;
|
||||
whitelisted?: boolean;
|
||||
featured?: boolean;
|
||||
};
|
||||
|
||||
export type Row = {
|
||||
id: string;
|
||||
assetId: string | undefined | null;
|
||||
pair: {
|
||||
base: Currency;
|
||||
quote: Currency;
|
||||
};
|
||||
price: number;
|
||||
priceUSD: string;
|
||||
change: number;
|
||||
volume: number;
|
||||
volumeUSD: string;
|
||||
featured: boolean;
|
||||
code: string;
|
||||
};
|
||||
|
|
@ -56,6 +56,7 @@ import LightningImg from '@/assets/images/UI/lightning.png';
|
|||
import RocketImg from '@/assets/images/UI/rocket.png';
|
||||
import { ReactComponent as ConnectionIcon } from '@/assets/images/UI/connection.svg';
|
||||
import Image from 'next/image';
|
||||
import ImgWithFallback from '@/components/UI/ImgWithFallback';
|
||||
import CandleChart from './CandleChart/CandleChart';
|
||||
import OrdersBuySellSwitch from './OrdersBuySellSwitch/OrdersBuySellSwitch';
|
||||
import InputPanelItem from './InputPanelItem/InputPanelItem';
|
||||
|
|
@ -1054,10 +1055,10 @@ function Trading() {
|
|||
<div className={styles.trading__currency__wrapper}>
|
||||
<div className={styles.trading__currency__wrapper_top}>
|
||||
<div>
|
||||
<Image
|
||||
<ImgWithFallback
|
||||
width={50}
|
||||
height={50}
|
||||
src={`/currencies/trade_${imgCode}.svg`}
|
||||
src={`/tokens/${pairData?.first_currency.asset_id}.png`}
|
||||
alt="currency"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||