diff --git a/apps/trading/client-pages/referrals/referral-statistics.tsx b/apps/trading/client-pages/referrals/referral-statistics.tsx index 5730abf3e..7d6dfb2d9 100644 --- a/apps/trading/client-pages/referrals/referral-statistics.tsx +++ b/apps/trading/client-pages/referrals/referral-statistics.tsx @@ -14,7 +14,7 @@ import { useUpdateReferees, } from './hooks/use-referral'; import classNames from 'classnames'; -import { Table } from './table'; +import { Table } from '../../components/table'; import { addDecimalsFormatNumber, getDateFormat, diff --git a/apps/trading/client-pages/referrals/tiers.tsx b/apps/trading/client-pages/referrals/tiers.tsx index 803ae9e7b..300043cc3 100644 --- a/apps/trading/client-pages/referrals/tiers.tsx +++ b/apps/trading/client-pages/referrals/tiers.tsx @@ -3,11 +3,12 @@ import { getDateTimeFormat, } from '@vegaprotocol/utils'; import { useReferralProgram } from './hooks/use-referral-program'; -import { Table } from './table'; +import { Table } from '../../components/table'; import classNames from 'classnames'; import { BORDER_COLOR, GRADIENT } from './constants'; -import { Tag } from './tag'; -import type { ComponentProps, ReactNode } from 'react'; +import { Tag } from '../../components/helpers/tag'; +import { getTierColor, getTierGradient } from '../../components/helpers/tiers'; +import type { ReactNode } from 'react'; import { ExternalLink, truncateMiddle } from '@vegaprotocol/ui-toolkit'; import { DApp, @@ -19,25 +20,6 @@ import { import { useT, ns } from '../../lib/use-t'; import { Trans } from 'react-i18next'; -// rainbow-ish order -const TIER_COLORS: Array['color']> = [ - 'pink', - 'orange', - 'yellow', - 'green', - 'blue', - 'purple', -]; - -const getTierColor = (tier: number) => { - const tiers = Object.keys(TIER_COLORS).length; - let index = Math.abs(tier - 1); - if (tier >= tiers) { - index = index % tiers; - } - return TIER_COLORS[index]; -}; - const Loading = ({ variant }: { variant: 'large' | 'inline' }) => (
{ const t = useT(); const minimum = addDecimalsFormatNumber(minimumStakedTokens, 18); @@ -97,7 +81,7 @@ const StakingTier = ({ )} >
- + {t('Multiplier')} {referralRewardMultiplier}x

@@ -159,7 +143,9 @@ export const TiersContainer = () => { return ( <> -

{t('Current program details')}

+

+ {t('Current program details')} +

{details?.id && (

@@ -333,22 +320,7 @@ const TiersTable = ({ className="bg-white dark:bg-vega-cdark-900" data={data.map((d) => ({ ...d, - className: classNames({ - 'from-vega-yellow-400 dark:from-vega-yellow-600 to-20% bg-highlight': - 'yellow' === getTierColor(d.tier), - 'from-vega-green-400 dark:from-vega-green-600 to-20% bg-highlight': - 'green' === getTierColor(d.tier), - 'from-vega-blue-400 dark:from-vega-blue-600 to-20% bg-highlight': - 'blue' === getTierColor(d.tier), - 'from-vega-purple-400 dark:from-vega-purple-600 to-20% bg-highlight': - 'purple' === getTierColor(d.tier), - 'from-vega-pink-400 dark:from-vega-pink-600 to-20% bg-highlight': - 'pink' === getTierColor(d.tier), - 'from-vega-orange-400 dark:from-vega-orange-600 to-20% bg-highlight': - 'orange' === getTierColor(d.tier), - 'from-vega-clight-200 dark:from-vega-cdark-200 to-20% bg-highlight': - 'none' === getTierColor(d.tier), - }), + className: classNames(getTierGradient(d.tier, data.length)), }))} /> ); diff --git a/apps/trading/components/card/card.tsx b/apps/trading/components/card/card.tsx index 68999fe69..6ed2cd98e 100644 --- a/apps/trading/components/card/card.tsx +++ b/apps/trading/components/card/card.tsx @@ -9,6 +9,7 @@ export const Card = ({ loading = false, highlight = false, testId, + noBackgroundOnMobile = false, }: { children: ReactNode; title: string; @@ -16,20 +17,33 @@ export const Card = ({ loading?: boolean; highlight?: boolean; testId?: string; + noBackgroundOnMobile?: boolean; }) => { return (

-
+

{title}

{loading ? : children}
diff --git a/apps/trading/components/fees-container/fees-container.tsx b/apps/trading/components/fees-container/fees-container.tsx index f4b117ee3..a9381050c 100644 --- a/apps/trading/components/fees-container/fees-container.tsx +++ b/apps/trading/components/fees-container/fees-container.tsx @@ -13,7 +13,7 @@ import { MarketFees } from './market-fees'; import { useVolumeStats } from './use-volume-stats'; import { useReferralStats } from './use-referral-stats'; import { formatPercentage, getAdjustedFee } from './utils'; -import { Table, Td, Th, THead, Tr } from './table'; +import { Table as SimpleTable } from '../../components/table'; import BigNumber from 'bignumber.js'; import { Links } from '../../lib/links'; import { Link } from 'react-router-dom'; @@ -24,6 +24,8 @@ import { truncateMiddle, } from '@vegaprotocol/ui-toolkit'; import { useT } from '../../lib/use-t'; +import classNames from 'classnames'; +import { getTierGradient } from '../helpers/tiers'; export const FeesContainer = () => { const t = useT(); @@ -166,6 +168,7 @@ export const FeesContainer = () => { className="lg:col-span-full xl:col-span-2" loading={loading} data-testid="volume-discount-card" + noBackgroundOnMobile={true} > { className="lg:col-span-full xl:col-span-2" loading={loading} data-testid="referral-discount-card" + noBackgroundOnMobile={true} > { className="lg:col-span-full" loading={marketsLoading} data-testid="fees-by-market-card" + noBackgroundOnMobile={true} > - + { + const isUserTier = tierIndex === i; + const indicator = isUserTier ? : null; + const tierIndicator = ( +
+ {i + 1} + {indicator} +
+ ); + return { + tier: tierIndicator, + discount: ( + <>{formatPercentage(Number(tier.volumeDiscountFactor))}% + ), + minTradingVolume: ( + <>{formatNumber(tier.minimumRunningNotionalTakerVolume)} + ), + myVolume: isUserTier ? ( + formatNumber(lastEpochVolume) + ) : ( + - + ), + indicator: indicator, + className: classNames( + getTierGradient(i + 1, tiers.length), + 'text-xs' + ), + }; + })} + /> + {/*
@@ -514,7 +567,7 @@ const VolumeTiers = ({ ); })} -
{t('Tier')}
+ */}
); }; @@ -524,6 +577,7 @@ const ReferralTiers = ({ tierIndex, epochsInSet, referralVolumeInWindow, + referralDiscountWindowLength, }: { tiers: Array<{ referralDiscountFactor: string; @@ -533,6 +587,7 @@ const ReferralTiers = ({ tierIndex: number; epochsInSet: number; referralVolumeInWindow: number; + referralDiscountWindowLength: number; }) => { const t = useT(); @@ -544,7 +599,75 @@ const ReferralTiers = ({ return (
- + { + const isUserTier = tierIndex === i; + const requiredVolume = Number(tier.minimumRunningNotionalTakerVolume); + + const indicator = isUserTier ? ( + + ) : referralVolumeInWindow >= requiredVolume && + epochsInSet < tier.minimumEpochs ? ( + + Unlocks in {tier.minimumEpochs - epochsInSet} epochs + + ) : null; + + const tierIndicator = ( +
+ {i + 1} + {indicator} +
+ ); + + return { + tier: tierIndicator, + discount: ( + <>{formatPercentage(Number(tier.referralDiscountFactor))}% + ), + volume: formatNumber(tier.minimumRunningNotionalTakerVolume), + epochs: tier.minimumEpochs, + indicator, + className: classNames( + getTierGradient(i + 1, tiers.length), + 'text-xs' + ), + }; + })} + /> + {/*
@@ -597,7 +720,7 @@ const ReferralTiers = ({ ); })} -
{t('Tier')}
+ */}
); }; @@ -611,7 +734,7 @@ const YourTier = ({ testId }: YourTierProps) => { return ( {t('Your tier')} diff --git a/apps/trading/components/fees-container/market-fees.tsx b/apps/trading/components/fees-container/market-fees.tsx index 47d307300..350e804e8 100644 --- a/apps/trading/components/fees-container/market-fees.tsx +++ b/apps/trading/components/fees-container/market-fees.tsx @@ -8,35 +8,41 @@ import { useNavigateWithMeta } from '../../lib/hooks/use-market-click-handler'; import { Links } from '../../lib/links'; import { useT } from '../../lib/use-t'; import { useMemo } from 'react'; +import { type ColDef } from 'ag-grid-community/dist/lib/entities/colDef'; -const useFeesTableColumnDefs = () => { +const useFeesTableColumnDefs = (): ColDef[] => { const t = useT(); return useMemo( - () => [ - { field: 'code', cellRenderer: 'MarketCodeCell' }, - { - field: 'feeAfterDiscount', - headerName: t('Total fee after discount'), - valueFormatter: ({ value }: { value: number }) => value + '%', - }, - { - field: 'infraFee', - valueFormatter: ({ value }: { value: number }) => value + '%', - }, - { - field: 'makerFee', - valueFormatter: ({ value }: { value: number }) => value + '%', - }, - { - field: 'liquidityFee', - valueFormatter: ({ value }: { value: number }) => value + '%', - }, - { - field: 'totalFee', - headerName: t('Total fee before discount'), - valueFormatter: ({ value }: { value: number }) => value + '%', - }, - ], + () => + [ + { + field: 'code', + cellRenderer: 'MarketCodeCell', + pinned: 'left', + }, + { + field: 'liquidityFee', + valueFormatter: ({ value }: { value: number }) => value + '%', + }, + { + field: 'feeAfterDiscount', + headerName: t('Total fee after discount'), + valueFormatter: ({ value }: { value: number }) => value + '%', + }, + { + field: 'totalFee', + headerName: t('Total fee before discount'), + valueFormatter: ({ value }: { value: number }) => value + '%', + }, + { + field: 'infraFee', + valueFormatter: ({ value }: { value: number }) => value + '%', + }, + { + field: 'makerFee', + valueFormatter: ({ value }: { value: number }) => value + '%', + }, + ] as ColDef[], [t] ); }; @@ -45,6 +51,8 @@ const feesTableDefaultColDef = { flex: 1, resizable: true, sortable: true, + suppressMovable: true, + pinned: false, }; const components = { @@ -62,6 +70,8 @@ export const MarketFees = ({ }) => { const navigateWithMeta = useNavigateWithMeta(); + const colDef = useFeesTableColumnDefs(); + const rows = compact(markets || []).map((m) => { const infraFee = new BigNumber(m.fees.factors.infrastructureFee); const makerFee = new BigNumber(m.fees.factors.makerFee); @@ -88,9 +98,9 @@ export const MarketFees = ({ }); return ( -
+
data.id} defaultColDef={feesTableDefaultColDef} diff --git a/apps/trading/client-pages/referrals/tag.tsx b/apps/trading/components/helpers/tag.tsx similarity index 90% rename from apps/trading/client-pages/referrals/tag.tsx rename to apps/trading/components/helpers/tag.tsx index 91cc4c120..1ea56849f 100644 --- a/apps/trading/client-pages/referrals/tag.tsx +++ b/apps/trading/components/helpers/tag.tsx @@ -2,7 +2,15 @@ import type { HTMLAttributes } from 'react'; import classNames from 'classnames'; type TagProps = { - color?: 'yellow' | 'green' | 'blue' | 'purple' | 'pink' | 'orange' | 'none'; + color?: + | 'yellow' + | 'green' + | 'blue' + | 'purple' + | 'pink' + | 'orange' + | 'red' + | 'none'; }; export const Tag = ({ color = 'none', diff --git a/apps/trading/components/helpers/tiers.tsx b/apps/trading/components/helpers/tiers.tsx new file mode 100644 index 000000000..9ac62cf20 --- /dev/null +++ b/apps/trading/components/helpers/tiers.tsx @@ -0,0 +1,48 @@ +import type { ComponentProps } from 'react'; +import type { Tag } from './tag'; +import classNames from 'classnames'; + +// rainbow-ish order +export const TIER_COLORS: Array['color']> = [ + 'none', // worst tier if 8 tiers, otherwise relative to the best tier + 'red', + 'pink', + 'orange', + 'yellow', + 'green', + 'blue', + 'purple', // best tier +]; + +export const getTierColor = (tier: number, max = TIER_COLORS.length) => { + const available = + max < TIER_COLORS.length + ? TIER_COLORS.slice(TIER_COLORS.length - max) + : TIER_COLORS; + const tiers = Object.keys(available).length; + let index = Math.abs(tier - 1); + if (tier >= tiers) { + index = index % tiers; + } + return available[index]; +}; + +export const getTierGradient = (tier: number, max = TIER_COLORS.length) => + classNames({ + 'from-vega-yellow-400 dark:from-vega-yellow-600 to-20% bg-highlight': + 'yellow' === getTierColor(tier, max), + 'from-vega-green-400 dark:from-vega-green-600 to-20% bg-highlight': + 'green' === getTierColor(tier, max), + 'from-vega-blue-400 dark:from-vega-blue-600 to-20% bg-highlight': + 'blue' === getTierColor(tier, max), + 'from-vega-purple-400 dark:from-vega-purple-600 to-20% bg-highlight': + 'purple' === getTierColor(tier, max), + 'from-vega-pink-400 dark:from-vega-pink-600 to-20% bg-highlight': + 'pink' === getTierColor(tier, max), + 'from-vega-orange-400 dark:from-vega-orange-600 to-20% bg-highlight': + 'orange' === getTierColor(tier, max), + 'from-vega-red-400 dark:from-vega-red-600 to-20% bg-highlight': + 'red' === getTierColor(tier, max), + 'from-vega-clight-600 dark:from-vega-cdark-600 to-20% bg-highlight': + 'none' === getTierColor(tier, max), + }); diff --git a/apps/trading/components/rewards-container/rewards-container.tsx b/apps/trading/components/rewards-container/rewards-container.tsx index cf305a358..ae44a3639 100644 --- a/apps/trading/components/rewards-container/rewards-container.tsx +++ b/apps/trading/components/rewards-container/rewards-container.tsx @@ -231,6 +231,7 @@ export const RewardsContainer = () => { title={t('Rewards history')} className="lg:col-span-full" loading={rewardsLoading} + noBackgroundOnMobile={true} > ; }, sort: 'desc', + pinned: 'left', }, { field: 'infrastructureFees', @@ -257,7 +258,7 @@ export const RewardHistoryTable = ({ return (
-
+

- +
+ +
); }; diff --git a/apps/trading/components/table/index.ts b/apps/trading/components/table/index.ts new file mode 100644 index 000000000..01643f0f5 --- /dev/null +++ b/apps/trading/components/table/index.ts @@ -0,0 +1 @@ +export * from './table'; diff --git a/apps/trading/client-pages/referrals/table.tsx b/apps/trading/components/table/table.tsx similarity index 92% rename from apps/trading/client-pages/referrals/table.tsx rename to apps/trading/components/table/table.tsx index df5637fbe..c3022af4f 100644 --- a/apps/trading/client-pages/referrals/table.tsx +++ b/apps/trading/components/table/table.tsx @@ -1,7 +1,10 @@ import { Tooltip, VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit'; import classNames from 'classnames'; import { forwardRef, type ReactNode, type HTMLAttributes } from 'react'; -import { BORDER_COLOR, GRADIENT } from './constants'; + +export const BORDER_COLOR = 'border-vega-clight-500 dark:border-vega-cdark-500'; +export const GRADIENT = + 'bg-gradient-to-b from-vega-clight-800 dark:from-vega-cdark-800 to-transparent'; type TableColumnDefinition = { displayName?: ReactNode; @@ -42,7 +45,7 @@ export const Table = forwardRef< key={name} col-id={name} className={classNames( - 'px-5 py-3 text-sm text-vega-clight-100 dark:text-vega-cdark-100 font-normal', + 'px-5 py-3 text-xs text-vega-clight-100 dark:text-vega-cdark-100 font-normal', INNER_BORDER_STYLE )} > @@ -85,7 +88,7 @@ export const Table = forwardRef< {columns.map(({ name, displayName, className }, j) => (