From 87d3b41e05bfb1ebf7bbca9ac9c04651ac07b8ca Mon Sep 17 00:00:00 2001 From: Face <69168154+face-hh@users.noreply.github.com> Date: Tue, 27 May 2025 16:19:57 +0300 Subject: [PATCH] feat: mobile support + more skeletons --- .../src/lib/components/self/AppSidebar.svelte | 2 +- .../lib/components/self/CommentSection.svelte | 10 +- .../src/lib/components/self/DataTable.svelte | 12 +- .../self/skeletons/CoinSkeleton.svelte | 33 ++- .../self/skeletons/HomeSkeleton.svelte | 10 +- .../self/skeletons/LeaderboardSkeleton.svelte | 32 +-- .../self/skeletons/LiveTradeSkeleton.svelte | 47 ++++ .../self/skeletons/PortfolioSkeleton.svelte | 167 ++++++++++++ .../self/skeletons/ProfileSkeleton.svelte | 84 +++--- website/src/routes/+page.svelte | 4 +- .../src/routes/coin/[coinSymbol]/+page.svelte | 100 +++++--- website/src/routes/leaderboard/+page.svelte | 76 +++--- website/src/routes/live/+page.svelte | 139 +++++----- website/src/routes/portfolio/+page.svelte | 240 +++++++++--------- 14 files changed, 589 insertions(+), 367 deletions(-) create mode 100644 website/src/lib/components/self/skeletons/LiveTradeSkeleton.svelte create mode 100644 website/src/lib/components/self/skeletons/PortfolioSkeleton.svelte diff --git a/website/src/lib/components/self/AppSidebar.svelte b/website/src/lib/components/self/AppSidebar.svelte index 6a25cb5..3dd6ff9 100644 --- a/website/src/lib/components/self/AppSidebar.svelte +++ b/website/src/lib/components/self/AppSidebar.svelte @@ -364,7 +364,7 @@ Settings - (showPromoCode = true)}> + { showPromoCode = true; setOpenMobile(false); }}> Promo code diff --git a/website/src/lib/components/self/CommentSection.svelte b/website/src/lib/components/self/CommentSection.svelte index f8272bf..4f3cf99 100644 --- a/website/src/lib/components/self/CommentSection.svelte +++ b/website/src/lib/components/self/CommentSection.svelte @@ -226,7 +226,7 @@
goto(`/user/${comment.userUsername}`)} > {comment.userName} @@ -237,13 +237,13 @@ - + {formatTimeAgo(comment.createdAt)}
diff --git a/website/src/lib/components/self/DataTable.svelte b/website/src/lib/components/self/DataTable.svelte index 53a0b3a..133be81 100644 --- a/website/src/lib/components/self/DataTable.svelte +++ b/website/src/lib/components/self/DataTable.svelte @@ -51,7 +51,7 @@ {#each columns as column} - {column.label} + {column.label} {/each} @@ -114,20 +114,20 @@ #{rendered.number} {:else if rendered.component === 'coin'} -
+
-
-
{rendered.name}
+
+
{rendered.name}
*{rendered.symbol}
{:else if rendered.component === 'link'} - +
-
-
- -
- -
- - +
+
+ +
+ +
+ + +
-
- -
+
+ +
- +
-
+
@@ -44,10 +45,8 @@ -
- {#each Array(6) as _} - - {/each} +
+
diff --git a/website/src/lib/components/self/skeletons/HomeSkeleton.svelte b/website/src/lib/components/self/skeletons/HomeSkeleton.svelte index 30d45c5..1a44589 100644 --- a/website/src/lib/components/self/skeletons/HomeSkeleton.svelte +++ b/website/src/lib/components/self/skeletons/HomeSkeleton.svelte @@ -3,13 +3,7 @@ import { Skeleton } from '$lib/components/ui/skeleton'; -
- -
- - -
- +
{#each Array(6) as _} @@ -18,7 +12,7 @@
- +
diff --git a/website/src/lib/components/self/skeletons/LeaderboardSkeleton.svelte b/website/src/lib/components/self/skeletons/LeaderboardSkeleton.svelte index 62030ab..7682b61 100644 --- a/website/src/lib/components/self/skeletons/LeaderboardSkeleton.svelte +++ b/website/src/lib/components/self/skeletons/LeaderboardSkeleton.svelte @@ -3,30 +3,30 @@ import { Skeleton } from '$lib/components/ui/skeleton'; -
+
{#each Array(4) as _} - - + + - - + + - + - -
+ +
{#each Array(5) as _} -
- - -
- - +
+ + +
+ +
- - + +
{/each}
diff --git a/website/src/lib/components/self/skeletons/LiveTradeSkeleton.svelte b/website/src/lib/components/self/skeletons/LiveTradeSkeleton.svelte new file mode 100644 index 0000000..1d04f7c --- /dev/null +++ b/website/src/lib/components/self/skeletons/LiveTradeSkeleton.svelte @@ -0,0 +1,47 @@ + + + + + +{#each Array(8) as _} +
+
+
+
+ +
+ + +
+ + + +
+ + +
+
+
+
+ +
+ +
+ + + + +
+ + +
+ + +
+
+
+{/each} diff --git a/website/src/lib/components/self/skeletons/PortfolioSkeleton.svelte b/website/src/lib/components/self/skeletons/PortfolioSkeleton.svelte new file mode 100644 index 0000000..d4b92cb --- /dev/null +++ b/website/src/lib/components/self/skeletons/PortfolioSkeleton.svelte @@ -0,0 +1,167 @@ + + +
+ +
+ {#each Array(3) as _} + + + + + + + + + + + + + {/each} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {#each Array(4) as _} + + +
+ +
+ + +
+
+
+ + + + + + + + + + + + + +
+ {/each} +
+
+
+
+ + + + +
+
+ + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + {#each Array(5) as _} + + + + + +
+ +
+ + +
+
+
+ + + + + + + + + + +
+ {/each} +
+
+
+
+
diff --git a/website/src/lib/components/self/skeletons/ProfileSkeleton.svelte b/website/src/lib/components/self/skeletons/ProfileSkeleton.svelte index c69f23c..2612f28 100644 --- a/website/src/lib/components/self/skeletons/ProfileSkeleton.svelte +++ b/website/src/lib/components/self/skeletons/ProfileSkeleton.svelte @@ -9,25 +9,25 @@
- +
- - + +
- +
- +
- +
@@ -40,32 +40,32 @@
- +
- - + +
{/each}
-
+
{#each Array(4) as _}
- +
- - + +
- - + +
@@ -77,22 +77,26 @@ - + - + -
+
{#each Array(3) as _} -
- -
- - +
+ +
+ +
- - - + + +
{/each}
@@ -104,23 +108,27 @@ - + - + -
+
{#each Array(5) as _} -
- - -
- - +
+ + +
+ +
- - - + + +
{/each}
diff --git a/website/src/routes/+page.svelte b/website/src/routes/+page.svelte index 6bcde8f..dff987d 100644 --- a/website/src/routes/+page.svelte +++ b/website/src/routes/+page.svelte @@ -66,13 +66,11 @@ { key: 'marketCap', label: 'Market Cap', - class: 'hidden md:table-cell', render: (value: any) => formatMarketCap(value) }, { key: 'volume24h', label: 'Volume (24h)', - class: 'hidden md:table-cell', render: (value: any) => formatMarketCap(value) } ]; @@ -144,7 +142,7 @@

Market Overview

- + import * as Card from '$lib/components/ui/card'; + import * as Select from '$lib/components/ui/select'; import { Badge } from '$lib/components/ui/badge'; import { Button } from '$lib/components/ui/button'; import * as Avatar from '$lib/components/ui/avatar'; @@ -37,6 +38,15 @@ let selectedTimeframe = $state('1m'); let lastPriceUpdateTime = 0; + const timeframeOptions = [ + { value: '1m', label: '1 minute' }, + { value: '5m', label: '5 minutes' }, + { value: '15m', label: '15 minutes' }, + { value: '1h', label: '1 hour' }, + { value: '4h', label: '4 hours' }, + { value: '1d', label: '1 day' } + ]; + onMount(async () => { await loadCoinData(); await loadUserHolding(); @@ -165,19 +175,10 @@ loading = false; } - function generateVolumeData(candlestickData: any[], volumeData: any[]) { - return candlestickData.map((candle, index) => { - // Find corresponding volume data for this time period - const volumePoint = volumeData.find((v) => v.time === candle.time); - const volume = volumePoint ? volumePoint.volume : 0; + let currentTimeframeLabel = $derived( + timeframeOptions.find((option) => option.value === selectedTimeframe)?.label || '1 minute' + ); - return { - time: candle.time, - value: volume, - color: candle.close >= candle.open ? '#26a69a' : '#ef5350' - }; - }); - } let chartContainer = $state(); let chart: IChartApi | null = null; let candlestickSeries: any = null; @@ -312,6 +313,20 @@ if (num >= 1e3) return `${(num / 1e3).toFixed(2)}K`; return num.toLocaleString(); } + + function generateVolumeData(candlestickData: any[], volumeData: any[]) { + return candlestickData.map((candle, index) => { + // Find corresponding volume data for this time period + const volumePoint = volumeData.find((v) => v.time === candle.time); + const volume = volumePoint ? volumePoint.volume : 0; + + return { + time: candle.time, + value: volume, + color: candle.close >= candle.open ? '#26a69a' : '#ef5350' + }; + }); + } @@ -341,19 +356,19 @@ {:else}
-
-
+
+
-
-

{coin.name}

-
- *{coin.symbol} +
+

{coin.name}

+
+ *{coin.symbol} {#if $isConnectedStore}
-
+
-

+

${formatPrice(coin.currentPrice)}

-
+
{#if coin.change24h >= 0} {:else} {/if} - = 0 ? 'success' : 'destructive'}> + = 0 ? 'success' : 'destructive'} class="text-sm"> {coin.change24h >= 0 ? '+' : ''}{Number(coin.change24h).toFixed(2)}%
@@ -389,7 +404,7 @@ {#if coin.creatorName} -
+
Created by @@ -423,17 +438,26 @@ Price Chart ({selectedTimeframe}) -
- {#each ['1m', '5m', '15m', '1h', '4h', '1d'] as timeframe} - - {/each} +
+ + + {currentTimeframeLabel} + + + + {#each timeframeOptions as option} + + {option.label} + + {/each} + + +
@@ -581,7 +605,9 @@

- {formatSupply(coin.circulatingSupply)} + {formatSupply(coin.circulatingSupply)} of {formatSupply(coin.initialSupply)} total

diff --git a/website/src/routes/leaderboard/+page.svelte b/website/src/routes/leaderboard/+page.svelte index 0fe946e..4b3013d 100644 --- a/website/src/routes/leaderboard/+page.svelte +++ b/website/src/routes/leaderboard/+page.svelte @@ -201,14 +201,14 @@ Leaderboard - Rugplay -
-
-
+
+
+
-

Leaderboard

-

Top performers and market activity

+

Leaderboard

+

Top performers and market activity

- @@ -220,24 +220,24 @@ {:else if !leaderboardData}
-
Failed to load leaderboard
+
Failed to load leaderboard
{:else} -
+
- - - - - Top Rugpullers (24h) + + + + + Top Rugpullers (24h) - + Users who made the most profit from selling coins today - + - - - - - Biggest Losses (24h) + + + + + Biggest Losses (24h) - Users who experienced the largest losses today + Users who experienced the largest losses today - + - - - - - Top Cash Holders + + + + + Top Cash Holders - Users with the highest liquid cash balances + Users with the highest liquid cash balances - + - - - - - Highest Portfolio Values + + + + + Highest Portfolio Values - Users with the largest total portfolio valuations (including illiquid) - +
-

Live Trades

-

Real-time trading activity for all trades

+

Live Trades

+

+ Real-time trading activity for all trades +

- - - Stream + +
+ + Stream +
{#if $allTradesStore.length > 0} - + {$allTradesStore.length} trade{$allTradesStore.length !== 1 ? 's' : ''} {/if}
- {#if $isLoadingTrades} -
- {#each Array(8) as _, i} -
-
-
- - -
- -
-
- - - - - -
- -
-
- -
- - -
-
- {/each} -
- {:else if $allTradesStore.length === 0} -
- -

Waiting for trades...

-

All trades will appear here in real-time.

-
- {:else} -
+
+ {#if $isLoadingTrades} + + {:else if $allTradesStore.length === 0} +
+ +

Waiting for trades...

+

+ All trades will appear here in real-time. +

+
+ {:else} {#each $allTradesStore as trade (trade.timestamp)}
-
-
- {#if trade.type === 'BUY'} -
- -
- BUY - {:else} -
- -
- SELL - {/if} -
- -
-
+
+
+
- + {trade.type === 'BUY' ? 'bought by' : 'sold by'} @@ -131,7 +93,7 @@ onclick={() => handleUserClick(trade.username)} >
- + {trade.username.charAt(0).toUpperCase()} - @{trade.username} + @{trade.username}
@@ -148,20 +112,35 @@
-
- Trade value: {formatValue(trade.totalValue)} -
-
- - {formatRelativeTime(new Date(trade.timestamp))} +
+
+ {#if trade.type === 'BUY'} + + BUY + {:else} + + SELL + {/if} + | + {formatValue(trade.totalValue)} +
+ +
+ + {formatRelativeTime(new Date(trade.timestamp))} +
{/each} -
- {/if} + {/if} +
diff --git a/website/src/routes/portfolio/+page.svelte b/website/src/routes/portfolio/+page.svelte index 017a652..13a013e 100644 --- a/website/src/routes/portfolio/+page.svelte +++ b/website/src/routes/portfolio/+page.svelte @@ -1,9 +1,10 @@ @@ -69,11 +174,7 @@
{#if loading} -
-
-
Loading portfolio...
-
-
+ {:else if !portfolioData}
@@ -160,52 +261,11 @@ Current positions in your portfolio - - - - Coin - Quantity - Price - 24h Change - Value - - - - - {#each portfolioData.coinHoldings as holding} - goto(`/coin/${holding.symbol}`)} - > - -
- - *{holding.symbol} -
-
- - {formatQuantity(holding.quantity)} - - - ${formatPrice(holding.currentPrice)} - - - = 0 ? 'success' : 'destructive'}> - {holding.change24h >= 0 ? '+' : ''}{holding.change24h.toFixed(2)}% - - - - {formatValue(holding.value)} - - -
- {/each} -
-
+ goto(`/coin/${holding.symbol}`)} + />
{/if} @@ -229,74 +289,14 @@
- {#if !hasTransactions} -
-
- -
-

No transactions yet

-

- You haven't made any trades yet. Start by buying or selling coins. -

- -
- {:else} - - - - Type - Coin - Quantity - Price - Total - - - - - {#each transactions as tx} - goto(`/coin/${tx.coin.symbol}`)} - > - -
- {#if tx.type === 'BUY'} - - Buy - {:else} - - Sell - {/if} -
-
- -
- - *{tx.coin.symbol} -
-
- - {formatQuantity(tx.quantity)} - - - ${formatPrice(tx.pricePerCoin)} - - - {formatValue(tx.totalBaseCurrencyAmount)} - - -
- {/each} -
-
- {/if} + goto(`/coin/${tx.coin.symbol}`)} + emptyIcon={Receipt} + emptyTitle="No transactions yet" + emptyDescription="You haven't made any trades yet. Start by buying or selling coins." + />
{/if}