Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/XLabs/wormscan-ui
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinoConti committed Jan 14, 2025
2 parents 8cbcafb + d81da18 commit d49bf1e
Show file tree
Hide file tree
Showing 22 changed files with 445 additions and 633 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "wormscan-ui",
"version": "2.0.11",
"version": "2.0.12",
"private": true,
"source": "src/index.html",
"@parcel/resolver-default": {
Expand Down Expand Up @@ -35,7 +35,7 @@
"@playwright/test": "^1.38.1",
"@types/node": "^18.13.0",
"@types/react": "^18.0.27",
"@types/react-datepicker": "^6.2.0",
"@types/react-datepicker": "7.0.0",
"@types/react-dom": "^18.0.10",
"@types/react-dropzone": "^5.1.0",
"@types/react-table": "^7.7.20",
Expand Down Expand Up @@ -80,7 +80,7 @@
"immutable": "3.8.2",
"react": "18.2.0",
"react-apexcharts": "^1.4.1",
"react-datepicker": "^6.9.0",
"react-datepicker": "7.6.0",
"react-dom": "18.2.0",
"react-draggable": "4.4.5",
"react-dropzone": "^14.2.3",
Expand Down
30 changes: 21 additions & 9 deletions src/api/native-token-transfer/NttApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,16 @@ export class NttApi {

const tokenListWithFallback = await Promise.all(
tokenListResponse.map(async item => {
if (item.circulating_supply === "0" || item.market_cap === "0") {
if (!item?.total_value_transferred) {
try {
const summary = await this.getNttTVT({ coingecko_id: item.coingecko_id });
item.total_value_transferred = summary.totalValueTokenTransferred || "0";
} catch (error) {
console.log("Failed to get total value transferred for token", item.symbol);
}
}

if (item.circulating_supply === "0") {
const symbol = item.symbol.toUpperCase();

const coinMarketCapTokenInfo = await getCoinMarketCapTokenInfo(symbol);
Expand All @@ -68,14 +77,6 @@ export class NttApi {
coinMarketCapTokenInfo?.data[symbol]?.[0]?.circulating_supply ||
coinMarketCapTokenInfo?.data[symbol]?.[0]?.self_reported_circulating_supply ||
0;

item.market_cap =
coinMarketCapTokenInfo?.data[symbol]?.[0]?.market_cap ||
coinMarketCapTokenInfo?.data[symbol]?.[0]?.self_reported_market_cap ||
coinMarketCapTokenInfo?.data[symbol]?.[0]?.quote?.USD?.market_cap ||
0;

return item;
}

return item;
Expand All @@ -85,6 +86,17 @@ export class NttApi {
return tokenListWithFallback;
}

async getNttTVT({ coingecko_id }: GetSummary): Promise<{ totalValueTokenTransferred: string }> {
const summaryResponse = await this._client.doGet<GetSummaryResult>(
"/native-token-transfer/summary",
{
coingecko_id,
},
);

return { totalValueTokenTransferred: summaryResponse.totalValueTokenTransferred };
}

async getNttSummary({ coingecko_id }: GetSummary): Promise<GetSummaryResult> {
const summaryResponse = await this._client.doGet<GetSummaryResult>(
"/native-token-transfer/summary",
Expand Down
1 change: 1 addition & 0 deletions src/api/native-token-transfer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export type GetListResult = {
price_change_percentage_24h: string;
volume_24h: string;
total_value_locked: string;
total_value_transferred: string;
market_cap: string;
circulating_supply: string;
image: {
Expand Down
3 changes: 2 additions & 1 deletion src/components/molecules/Calendar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ const Calendar = ({
}`}
>
<ReactDatePicker
{...({ swapRange: true } as any)}
swapRange
selected={startDate}
onChange={(dates: [Date | null, Date | null]) => {
const [start, end] = dates;
Expand Down Expand Up @@ -166,6 +166,7 @@ const Calendar = ({
monthsShown={isDesktop ? 2 : 1}
showMonthDropdown
showYearDropdown
focusSelectedMonth
/>

<div className="calendar-custom-box-date-calendar-btns">
Expand Down
168 changes: 152 additions & 16 deletions src/components/organisms/Table/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CSSProperties, useEffect } from "react";
import { CSSProperties, Fragment, useEffect, useState } from "react";
import {
useTable,
Column,
Expand All @@ -8,22 +8,24 @@ import {
UseSortByOptions,
TableInstance,
} from "react-table";
import { SortByIcon } from "src/icons/generic";
import "./styles.scss";
import { CrossIcon, FilterListIcon, SortByIcon } from "src/icons/generic";
import analytics from "src/analytics";
import { useEnvironment } from "src/context/EnvironmentContext";
import { Select } from "src/components/atoms";
import { useLockBodyScroll, useWindowSize } from "src/utils/hooks";
import { BREAKPOINTS } from "src/consts";
import "./styles.scss";

type Props<T extends object> = {
className?: string;
columns: Column<T>[];
data: T[];
defaultSortBy?: { id: string; desc: boolean };
emptyMessage?: string | JSX.Element;
hasSort?: boolean;
isLoading?: boolean;
numberOfColumns?: number;
numberOfRows?: number;
onRowClick?: (row: any) => void;
sortBy?: { id: string; desc: boolean }[];
trackTxsSortBy?: boolean;
};

Expand All @@ -35,16 +37,19 @@ const Table = <T extends object>({
className,
columns,
data,
defaultSortBy,
emptyMessage = "No items found.",
hasSort = false,
isLoading = false,
numberOfColumns = 7,
numberOfRows = 50,
onRowClick,
sortBy = [],
trackTxsSortBy = false,
}: Props<T>) => {
const { environment } = useEnvironment();
const [openSortBy, setOpenSortBy] = useState(false);
const [currentSortBy, setCurrentSortBy] = useState(defaultSortBy);
const { width } = useWindowSize();
const isDesktop = width >= BREAKPOINTS.desktop;

const {
getTableProps,
Expand All @@ -57,23 +62,155 @@ const Table = <T extends object>({
{
columns,
data,
initialState: { sortBy } as Partial<TableState<T>>,
initialState: { sortBy: defaultSortBy ? [defaultSortBy] : [] } as Partial<TableState<T>>,
disableSortRemove: true,
} as UseTableOptions<T> & UseSortByOptions<T>,
useSortBy,
);

useEffect(() => {
if (sortBy.length > 0) {
setSortBy(sortBy);
const sortedColumn = headerGroups.flatMap(group =>
// @ts-expect-error Property 'isSorted' exists at runtime but TypeScript doesn't know about it
group.headers.filter(col => col.isSorted),
)[0];

if (sortedColumn) {
setCurrentSortBy({
id: sortedColumn.id,
// @ts-expect-error Property 'isSortedDesc' exists at runtime but TypeScript doesn't know about it
desc: sortedColumn.isSortedDesc || false,
});
}
}, [sortBy, setSortBy, environment.network]);
}, [headerGroups]);

const handleReset = () => {
setSortBy([defaultSortBy]);
setCurrentSortBy(defaultSortBy);
setOpenSortBy(false);
};

useLockBodyScroll({ isLocked: !isDesktop && openSortBy });

return (
<>
{defaultSortBy && (
<>
<div
className={`table-mobile-filters-overlay ${openSortBy ? "open" : ""}`}
onClick={() => setOpenSortBy(false)}
/>

<button
aria-expanded={openSortBy}
aria-label="Sort by"
className="table-sort-by-btn"
onClick={() => setOpenSortBy(!openSortBy)}
>
<FilterListIcon width={24} />
</button>

<div className={`table-mobile-filters ${openSortBy ? "open" : ""}`}>
<div className="table-mobile-filters-top">
<h4>Sort by</h4>
<button
className="table-mobile-filters-top-btn"
onClick={() => setOpenSortBy(false)}
aria-label="Close sort options"
>
<CrossIcon width={24} />
</button>
</div>

{headerGroups.map((headerGroup, index) => {
return (
<Fragment key={index}>
<Select
ariaLabel="Sort column"
className="table-mobile-filters-select"
items={headerGroup.headers
.filter(
(column: any) => column.render("Header").toString() !== "View Details",
)
.map((column: any) => ({
value: column.id,
label: column.render("Header").toString(),
}))}
menuFixed
menuListStyles={{ maxHeight: "unset" }}
name="Sort column"
onValueChange={selected => {
const selectedColumn = headerGroup.headers.find(
(col: any) => col.id === selected.value,
);

if (selectedColumn) {
setCurrentSortBy(prev => ({
id: selected.value,
desc: prev.desc,
}));
// @ts-expect-error Property 'toggleSortBy' exists at runtime but TypeScript doesn't know about it
selectedColumn.toggleSortBy(currentSortBy.desc);
}
}}
optionStyles={{ padding: 16 }}
value={{
value: currentSortBy.id,
label:
headerGroup.headers
.find((column: any) => column.id === currentSortBy.id)
?.render("Header") || "Sort",
}}
/>

<Select
ariaLabel="Sort order"
className="table-mobile-filters-select"
items={[
{ value: false, label: "Low to High" },
{ value: true, label: "High to Low" },
]}
menuFixed
menuListStyles={{ maxHeight: "unset" }}
name="Sort order"
onValueChange={selected => {
setCurrentSortBy(prev => ({ ...prev, desc: selected.value }));

const column = headerGroup.headers.find(
(col: any) => col.id === currentSortBy.id,
);
if (column) {
// @ts-expect-error Property 'toggleSortBy' exists at runtime but TypeScript doesn't know about it
column.toggleSortBy(selected.value);
}
}}
optionStyles={{ padding: 16 }}
value={{
value: currentSortBy.desc,
label: currentSortBy.desc ? "High to Low" : "Low to High",
}}
/>
</Fragment>
);
})}

<div className="table-mobile-filters-btns">
<button
className="table-mobile-filters-btns-apply"
onClick={() => setOpenSortBy(false)}
>
Apply
</button>
<button className="table-mobile-filters-btns-reset" onClick={handleReset}>
Reset
</button>
</div>
</div>
</>
)}

<table
{...getTableProps()}
className={`table ${hasSort ? "table-sortable" : ""} ${
className={`table ${defaultSortBy ? "table-sortable" : ""} ${
onRowClick ? "table-clickable" : ""
} ${className}`}
>
Expand All @@ -86,7 +223,6 @@ const Table = <T extends object>({
if (trackTxsSortBy) {
setTimeout(() => {
const sortedColumn = headerGroup.headers.find((header: any) => header.isSorted);

analytics.track("txsSortBy", {
network: environment.network,
selected: sortedColumn?.id,
Expand All @@ -99,7 +235,7 @@ const Table = <T extends object>({
>
{headerGroup.headers.map((column: any, index) => {
const style: CSSProperties = column.style as CSSProperties;
const sortIcon = hasSort && (
const sortIcon = defaultSortBy && (
<span className="table-head-th-container-arrow">
<SortByIcon
sortBy={column.isSorted ? (column.isSortedDesc ? "DSC" : "ASC") : null}
Expand All @@ -110,14 +246,14 @@ const Table = <T extends object>({
return (
<th
key={index}
{...column.getHeaderProps(hasSort ? column.getSortByToggleProps() : {})}
{...column.getHeaderProps(defaultSortBy ? column.getSortByToggleProps() : {})}
style={{
...style,
color: column.isSorted ? "var(--color-white)" : "var(--color-gray-400)",
}}
>
<div className="table-head-th-container">
{column.render("Header")}
{column.render("Header")} {column?.Tooltip && column.Tooltip}
{sortIcon}
</div>
</th>
Expand Down
Loading

0 comments on commit d49bf1e

Please sign in to comment.