Skip to content

Commit

Permalink
Create Strategy Table List
Browse files Browse the repository at this point in the history
  • Loading branch information
GrandSchtroumpf committed Dec 13, 2024
1 parent 27bb2d7 commit b94a610
Show file tree
Hide file tree
Showing 20 changed files with 331 additions and 45 deletions.
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 @@ -16,7 +16,7 @@ export const PairLogoName: FC<Props> = ({
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 @@ -26,7 +26,7 @@ export const PairLogoName: FC<Props> = ({
{quoteToken.isSuspicious && (
<WarningWithTooltip tooltipContent={suspiciousTokenTooltipMsg} />
)}
</p>
</span>
</>
);
};
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>
);
};
43 changes: 43 additions & 0 deletions src/components/strategies/StrategySelectLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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';

const urls = {
explorer: '/explore/$type/$slug/' as const,
myStrategy: '/my-strategy-layout/' as const,
};
interface Props {
from: keyof typeof urls;
}
export const StrategySelectLayout: FC<Props> = ({ from }) => {
const { layout } = useSearch({ from: urls[from] });
const nav = useNavigate({ from: urls[from] });
const set = (layout: 'list' | 'table') => {
nav({ search: (s) => ({ ...s, layout }) });
};
return (
<RadioGroup
aria-label="Select strategy list layout"
className="border-2 border-white/10"
>
<Radio
name="layout"
checked={layout !== 'table'}
onChange={() => set('list')}
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: 47 additions & 0 deletions src/components/strategies/overview/StrategyContent.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,50 @@
/* content-visibility: auto; */ /* to prevent no tooltips when scrolling down */
contain-intrinsic-size: auto 410px;
}
.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 tbody td {
animation: open 100ms ease-out;
}
.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);
}
}
18 changes: 11 additions & 7 deletions src/components/strategies/overview/StrategyContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@ import { StrategyBlockCreate } from 'components/strategies/overview/strategyBloc
import { CarbonLogoLoading } from 'components/common/CarbonLogoLoading';
import { cn } from 'utils/helpers';
import styles from './StrategyContent.module.css';
import { StrategyTable } from './StrategyTable';

type Props = {
strategies: StrategyWithFiat[];
isPending: boolean;
emptyElement: ReactElement;
isExplorer?: boolean;
layout?: 'list' | 'table';
};

export const _StrategyContent: FC<Props> = ({
strategies,
isExplorer,
isPending,
emptyElement,
layout = 'list',
}) => {
if (isPending) {
return (
Expand All @@ -38,22 +41,23 @@ export const _StrategyContent: FC<Props> = ({

if (!strategies?.length) return emptyElement;

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

return (
<ul
data-testid="strategy-list"
className={cn('xl:gap-25 grid gap-20 lg:gap-10', styles.strategyList)}
>
{strategies.map((s) => (
<StrategyBlock key={s.id} strategy={s} isExplorer={isExplorer} />
<StrategyBlock key={s.id} strategy={s} />
))}
{!isExplorer && <StrategyBlockCreate />}
</ul>
);
};

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);
});
Loading

0 comments on commit b94a610

Please sign in to comment.