From 93b79df7e725e5cdee790290285edbe2c18479a5 Mon Sep 17 00:00:00 2001 From: charles Date: Fri, 29 May 2026 16:07:21 +0100 Subject: [PATCH] Add accessible creator list and fee copy --- src/components/common/CreatorCard.tsx | 6 ++-- src/components/common/TradeDialog.tsx | 14 ++++++++ src/constants/fees.ts | 5 +++ src/pages/LandingPage.tsx | 50 ++++++++++++++++++++++++--- src/utils/transactionFee.utils.ts | 31 +++++++++++++++++ 5 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 src/utils/transactionFee.utils.ts diff --git a/src/components/common/CreatorCard.tsx b/src/components/common/CreatorCard.tsx index ad810fa..73e4e90 100644 --- a/src/components/common/CreatorCard.tsx +++ b/src/components/common/CreatorCard.tsx @@ -162,7 +162,7 @@ const CreatorCard: React.FC = ({ return (
@@ -218,9 +218,9 @@ const CreatorCard: React.FC = ({ name={creator.title} creatorId={creator.id} imageSrc={creator.thumbnail} - imageClassName="transition-transform duration-500 md:group-hover:scale-[1.03]" + imageClassName="transition-transform duration-500 motion-reduce:transition-none motion-safe:md:group-hover:scale-[1.03] motion-reduce:md:group-hover:scale-100" /> -
+
{creator.volume24h !== undefined && ( // #313: the .creator-card-overlay-text class swaps this // pill to system high-contrast tokens (Canvas / CanvasText diff --git a/src/components/common/TradeDialog.tsx b/src/components/common/TradeDialog.tsx index 6e0d5bd..65be12f 100644 --- a/src/components/common/TradeDialog.tsx +++ b/src/components/common/TradeDialog.tsx @@ -12,6 +12,9 @@ import { import { cn } from '@/lib/utils'; import { formatNumber } from '@/utils/numberFormat.utils'; import PercentageBadge from '@/components/common/PercentageBadge'; +import NetworkFeeHint from '@/components/common/NetworkFeeHint'; +import { TRADE_FEE_ESTIMATE } from '@/constants/fees'; +import { formatTransactionFeeDisplay } from '@/utils/transactionFee.utils'; export type TradeSide = 'buy' | 'sell'; @@ -54,6 +57,10 @@ const TradeDialog: React.FC = ({ const title = side === 'buy' ? 'Buy keys' : 'Sell keys'; const confirmLabel = side === 'buy' ? 'Confirm buy' : 'Confirm sell'; + const estimatedNetworkFee = formatTransactionFeeDisplay( + TRADE_FEE_ESTIMATE.DEFAULT_NETWORK_FEE, + { unit: TRADE_FEE_ESTIMATE.UNIT } + ); return ( = ({ /> )}
+ {side === 'buy' && ( + + )} {side === 'sell' && parsedAmount > availableHoldings && (
You can’t sell more than your current holdings. diff --git a/src/constants/fees.ts b/src/constants/fees.ts index 7243979..4c01482 100644 --- a/src/constants/fees.ts +++ b/src/constants/fees.ts @@ -11,3 +11,8 @@ export const KEY_PRICE_BOUNDS = { MIN_PRICE: 0.001, MAX_PRICE: 100, } as const; + +export const TRADE_FEE_ESTIMATE = { + DEFAULT_NETWORK_FEE: 0.0001, + UNIT: 'ETH', +} as const; diff --git a/src/pages/LandingPage.tsx b/src/pages/LandingPage.tsx index 86e0ca4..6b9061a 100644 --- a/src/pages/LandingPage.tsx +++ b/src/pages/LandingPage.tsx @@ -43,7 +43,7 @@ import { CREATOR_CARD_ENTRY_CLASS, creatorCardEntryStyle, } from '@/utils/cardEntryAnimation.utils'; -import { AlertCircle, RefreshCw } from 'lucide-react'; +import { AlertCircle, ChevronDown, RefreshCw } from 'lucide-react'; import ClearedFiltersEmptyState from '@/components/common/ClearedFiltersEmptyState'; import CreatorListPagination from '@/components/common/CreatorListPagination'; @@ -55,6 +55,29 @@ const FEATURED_CREATOR_FACTS = [ ]; const FEATURED_CREATOR_FOLLOWER_COUNT: number | null = null; +const FEATURED_CREATOR_KEY_HOLDER_COUNT = 0; + +const getFeaturedCreatorKeyHolderCopy = (count: number | null) => { + if (count == null) { + return { + value: 'Key holders unavailable', + explanation: 'Key holder data is not available yet.', + }; + } + + if (count === 0) { + return { + value: 'No key holders yet', + explanation: + 'This creator has not unlocked any key holders yet. Be the first to buy a key and start the collector base.', + }; + } + + return { + value: `${formatCompactNumber(count)} key holders`, + explanation: 'Number of wallets that currently hold at least one key.', + }; +}; // Fallback demo data in case API fails const DEMO_CREATORS: Course[] = [ @@ -411,6 +434,9 @@ function LandingPage() { const start = safePage * PAGE_SIZE; return filteredCreators.slice(start, start + PAGE_SIZE); }, [filteredCreators, safePage]); + const featuredCreatorKeyHolderCopy = getFeaturedCreatorKeyHolderCopy( + FEATURED_CREATOR_KEY_HOLDER_COUNT + ); useEffect(() => { if (pendingScrollRestoreRef.current == null) return; @@ -652,8 +678,22 @@ function LandingPage() { onPageChange={handlePageChange} className="mt-8" /> - {safePage >= totalPages - 1 && ( -

+ +

+ )} + {safePage >= totalPages - 1 && ( +