Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strategy Table List #1601

Merged
merged 17 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/assets/icons/grid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/assets/icons/table.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions src/components/activity/ActivityTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export const ActivityId: FC<ActivityIdProps> = ({ activity, size }) => {
};

interface ActivityIconProps {
activity: Activity;
activity: { action: ActivityAction };
size: number;
className?: string;
}
Expand Down Expand Up @@ -317,15 +317,15 @@ interface ActionIconProps {
action: ActivityAction;
size: string | number;
}
const iconColor = (action: ActivityAction) => {
export const iconColor = (action: ActivityAction) => {
if (action === 'buy') return `bg-buy/10 text-buy`;
if (action === 'sell') return `bg-sell/10 text-sell`;
if (action === 'create') return `bg-success/10 text-success`;
if (action === 'delete') return `bg-error/10 text-error`;
return `bg-white/10 text-white`;
};

const ActionIcon: FC<ActionIconProps> = ({ action, size }) => {
export const ActionIcon: FC<ActionIconProps> = ({ action, size }) => {
const className = `size-${size}`;
if (action === 'create') return <IconCheck className={className} />;
if (action === 'transfer') return <IconTransfer className={className} />;
Expand Down
23 changes: 23 additions & 0 deletions src/components/common/FiatPrice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useFiatCurrency } from 'hooks/useFiatCurrency';
import { useGetTokenPrice } from 'libs/queries';
import { SafeDecimal } from 'libs/safedecimal';
import { Token } from 'libs/tokens';
import { FC } from 'react';
import { cn, getFiatDisplayValue } from 'utils/helpers';

interface Props {
token?: Token;
amount: SafeDecimal | string | number;
className?: string;
}
export const FiatPrice: FC<Props> = ({ token, amount, className }) => {
const query = useGetTokenPrice(token?.address);
const { selectedFiatCurrency: currentCurrency } = useFiatCurrency();
const loading = !token || query.isPending;
const value = new SafeDecimal(query.data?.[currentCurrency] || 0).mul(amount);
return (
<span className={cn(className, { invisible: loading })}>
{getFiatDisplayValue(value, currentCurrency)}
</span>
);
};
4 changes: 2 additions & 2 deletions src/components/common/PairLogoName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const _PairLogoName: FC<PairProps> = ({ pair: { baseToken, quoteToken } }) => {
return (
<>
<TokensOverlap tokens={[baseToken, quoteToken]} size={30} />
<p className="font-weight-500 flex items-center gap-4">
<span className="font-weight-500 inline-flex items-center gap-4">
{baseToken.symbol}
{baseToken.isSuspicious && (
<WarningWithTooltip tooltipContent={suspiciousTokenTooltipMsg} />
Expand All @@ -44,7 +44,7 @@ const _PairLogoName: FC<PairProps> = ({ pair: { baseToken, quoteToken } }) => {
{quoteToken.isSuspicious && (
<WarningWithTooltip tooltipContent={suspiciousTokenTooltipMsg} />
)}
</p>
</span>
</>
);
};
Expand Down
4 changes: 3 additions & 1 deletion src/components/common/radio/RadioGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const RadioGroup: FC<RadioGroupProps> = ({ children, ...props }) => {
role="group"
{...props}
className={cn(
'text-14 relative flex items-center rounded-full bg-black p-2',
'text-14 relative flex items-center rounded-full bg-black px-6 py-4',
props.className
)}
>
Expand All @@ -30,6 +30,7 @@ interface RadioProps {
onChange?: (value?: string) => any;
className?: string;
'data-testid'?: string;
'aria-label'?: string;
}

export const Radio: FC<RadioProps> = (props) => {
Expand All @@ -45,6 +46,7 @@ export const Radio: FC<RadioProps> = (props) => {
onChange={() => props.onChange?.(props.value)}
className={style.radio}
data-testid={props['data-testid']}
aria-label={props['aria-label']}
/>
<label
htmlFor={id}
Expand Down
2 changes: 2 additions & 0 deletions src/components/explorer/ExplorerTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ReactComponent as IconPieChart } from 'assets/icons/piechart.svg';
import { ReactComponent as IconActivity } from 'assets/icons/activity.svg';
import { StrategyFilterSort } from 'components/strategies/overview/StrategyFilterSort';
import { useStrategyCtx } from 'hooks/useStrategies';
import { StrategySelectLayout } from 'components/strategies/StrategySelectLayout';

export const ExplorerTabs = () => {
const { filteredStrategies } = useStrategyCtx();
Expand Down Expand Up @@ -51,6 +52,7 @@ export const ExplorerTabs = () => {
<div className="flex items-center justify-between gap-16">
<StrategyPageTabs currentPathname={pathname} tabs={tabs} />
{isOverview && <StrategyFilterSort />}
{isOverview && <StrategySelectLayout from="explorer" />}
</div>
);
};
48 changes: 48 additions & 0 deletions src/components/strategies/StrategySelectLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { useNavigate, useSearch } from '@tanstack/react-router';
import { Radio, RadioGroup } from 'components/common/radio/RadioGroup';
import { ReactComponent as IconGrid } from 'assets/icons/grid.svg';
import { ReactComponent as IconTable } from 'assets/icons/table.svg';
import { FC } from 'react';
import { lsService } from 'services/localeStorage';

export type StrategyLayout = 'grid' | 'table';

const urls = {
explorer: '/explore/$type/$slug/' as const,
myStrategy: '/my-strategy-layout/' as const,
GrandSchtroumpf marked this conversation as resolved.
Show resolved Hide resolved
};
interface Props {
from: keyof typeof urls;
}
export const StrategySelectLayout: FC<Props> = ({ from }) => {
const config = { from: urls[from] };
const { layout = lsService.getItem('strategyLayout') } = useSearch(config);
const nav = useNavigate(config);
const set = (layout: StrategyLayout) => {
lsService.setItem('strategyLayout', layout);
nav({ search: (s) => ({ ...s, layout }) });
};
return (
<RadioGroup
aria-label="Select strategy list layout"
className="hidden border-2 border-white/10 xl:flex"
>
<Radio
name="layout"
checked={layout !== 'table'}
onChange={() => set('grid')}
aria-label="List"
>
<IconGrid className="size-20" />
</Radio>
<Radio
name="layout"
checked={layout === 'table'}
onChange={() => set('table')}
aria-label="Table"
>
<IconTable className="size-20" />
</Radio>
</RadioGroup>
);
};
47 changes: 46 additions & 1 deletion src/components/strategies/overview/StrategyContent.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,55 @@
}
@media (prefers-reduced-motion: no-preference) {
.animate-item {
animation: open 200ms var(--delay, 0ms) backwards;
animation: open-item 200ms var(--delay, 0ms) backwards;
}
}
.strategy-table {
@apply bg-background-900 text-14;
border-radius: 8px;
animation: open 300ms ease-out;
}
.strategy-table th {
font-weight: 400;
color: rgba(255 255 255 / .6);
padding: 16px;
border-bottom: solid 1px rgba(255 255 255 / .4);
text-align: start;
text-wrap: nowrap;
}
.strategy-table td {
padding: 8px 16px;
}
.strategy-table td:first-child {
padding-left: 24px;
}
.strategy-table td:last-child {
padding-right: 24px;
}
.strategy-table th:first-child {
border-top-left-radius: 8px;
}
.strategy-table th:last-child {
border-top-right-radius: 8px;
}
.strategy-table tr:not(:last-child) td {
border-bottom: solid 1px rgba(255 255 255 / .4);
}
.strategy-table tr:last-child td:first-child {
border-bottom-left-radius: 8px;
}
.strategy-table tr:last-child td:last-child {
border-bottom-right-radius: 8px;
}

@keyframes open {
from {
opacity: 0;
transform: translateY(10px);
}
}

@keyframes open-item {
from {
opacity: 0;
transform: scale(0.9);
Expand Down
23 changes: 17 additions & 6 deletions src/components/strategies/overview/StrategyContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,29 @@ import { StrategyBlock } from 'components/strategies/overview/strategyBlock';
import { StrategyBlockCreate } from 'components/strategies/overview/strategyBlock';
import { CarbonLogoLoading } from 'components/common/CarbonLogoLoading';
import { cn } from 'utils/helpers';
import { StrategyTable } from './StrategyTable';
import { StrategyLayout } from '../StrategySelectLayout';
import { lsService } from 'services/localeStorage';
import styles from './StrategyContent.module.css';
import { useBreakpoints } from 'hooks/useBreakpoints';

type Props = {
strategies: StrategyWithFiat[];
isPending: boolean;
emptyElement: ReactElement;
isExplorer?: boolean;
layout?: StrategyLayout;
};

export const _StrategyContent: FC<Props> = ({
strategies,
isExplorer,
isPending,
emptyElement,
layout = lsService.getItem('strategyLayout') || 'grid',
}) => {
const { belowBreakpoint } = useBreakpoints();

if (isPending) {
return (
<div key="loading" className="flex flex-grow items-center justify-center">
Expand All @@ -31,6 +39,10 @@ export const _StrategyContent: FC<Props> = ({

if (!strategies?.length) return emptyElement;

if (layout === 'table' && !belowBreakpoint('xl')) {
return <StrategyTable strategies={strategies} />;
}

return (
<ul
data-testid="strategy-list"
Expand All @@ -57,9 +69,8 @@ export const _StrategyContent: FC<Props> = ({
);
};

export const StrategyContent = memo(
_StrategyContent,
(prev, next) =>
prev.isPending === next.isPending &&
JSON.stringify(prev.strategies) === JSON.stringify(next.strategies)
);
export const StrategyContent = memo(_StrategyContent, (prev, next) => {
if (prev.isPending && next.isPending) return true;
if (prev.layout !== next.layout) return false;
return JSON.stringify(prev.strategies) === JSON.stringify(next.strategies);
});
2 changes: 1 addition & 1 deletion src/components/strategies/overview/StrategyFilterSort.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const strategySort = {
pairAsc: 'Pair (A->Z)',
pairDesc: 'Pair (Z->A)',
totalBudgetDesc: 'Total Budget',
trades: 'Trade Count',
trades: 'Trades',
};

export type StrategySort = keyof typeof strategySort;
Expand Down
Loading