Skip to content

Commit c33a76a

Browse files
feat: mobile UI and support for multiple contracts
1 parent 7ce2668 commit c33a76a

15 files changed

+358
-114
lines changed

app/page.tsx

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import { useState, useEffect } from 'react';
3+
import { useState, useEffect, useRef } from 'react';
44
import { useWallet } from '@/contexts/WalletContext';
55
import { useHathor } from '@/contexts/HathorContext';
66
import { useUnifiedWallet } from '@/contexts/UnifiedWalletContext';
@@ -25,7 +25,7 @@ import { toast } from '@/lib/toast';
2525
import { APP_VERSION } from '@/lib/version';
2626

2727
export default function Home() {
28-
const { connected, balance, address, claimBalance, refreshBalance, contractBalance, setContractBalance, balanceVerified, isLoadingBalance } = useWallet();
28+
const { connected, balance, address, claimBalance, refreshBalance, contractBalance, setContractBalance, setBalance, balanceVerified, isLoadingBalance } = useWallet();
2929
const { network, getContractStateForToken, getContractIdForToken, switchNetwork, isConnected, coreAPI, disconnectWallet } = useHathor();
3030
const { walletType } = useUnifiedWallet();
3131
const [selectedToken, setSelectedToken] = useState('HTR');
@@ -50,6 +50,15 @@ export default function Home() {
5050
}
5151
}, []);
5252

53+
// Listen for openStatistics event from mobile UI
54+
useEffect(() => {
55+
const handleOpenStatistics = () => {
56+
handleModeChange('classic');
57+
};
58+
window.addEventListener('openStatistics', handleOpenStatistics);
59+
return () => window.removeEventListener('openStatistics', handleOpenStatistics);
60+
}, []);
61+
5362
const handleModeChange = (mode: UIMode) => {
5463
setUIMode(mode);
5564
localStorage.setItem('ui_mode', mode);
@@ -91,6 +100,26 @@ export default function Home() {
91100
fetchClaimableBalance();
92101
}, [isConnected, address, selectedToken, getContractIdForToken, coreAPI, setContractBalance]);
93102

103+
// Handle token change - clear balance and fetch new one
104+
const handleTokenChange = (newToken: string) => {
105+
// Clear current balance when switching tokens
106+
setBalance(0n);
107+
setSelectedToken(newToken);
108+
};
109+
110+
// Track previous token to only refresh when it actually changes
111+
const prevTokenRef = useRef(selectedToken);
112+
113+
// Refresh wallet balance when token changes (not on initial connection)
114+
useEffect(() => {
115+
// Only refresh if token actually changed, not on initial connection
116+
if (prevTokenRef.current !== selectedToken && isConnected && address) {
117+
const tokenUid = getContractStateForToken(selectedToken)?.token_uid || '00';
118+
refreshBalance(tokenUid);
119+
}
120+
prevTokenRef.current = selectedToken;
121+
}, [selectedToken, isConnected, address]);
122+
94123
const handleWithdrawClick = () => {
95124
setShowWithdrawModal(true);
96125
setWithdrawAmount('');
@@ -147,7 +176,8 @@ export default function Home() {
147176
const handleRefreshWalletBalance = async () => {
148177
setIsRefreshingWallet(true);
149178
try {
150-
await refreshBalance();
179+
const tokenUid = getContractStateForToken(selectedToken)?.token_uid || '00';
180+
await refreshBalance(tokenUid);
151181
toast.success('Wallet balance refreshed');
152182
} catch (error: any) {
153183
toast.error('Failed to refresh wallet balance');
@@ -196,8 +226,9 @@ export default function Home() {
196226
{showIntro && (
197227
<IntroVideo onComplete={() => setShowIntro(false)} />
198228
)}
199-
{/* Wallet Controls - Top Right */}
200-
<div className="fixed top-4 right-4 z-40 flex items-center gap-3">
229+
{/* Wallet Controls - Top Right on desktop, hidden on mobile (shown in FortuneTigerBetCard) */}
230+
<div className="hidden md:flex fixed top-4 right-4 z-40 items-center gap-2">
231+
<TokenSelector selectedToken={selectedToken} onTokenChange={handleTokenChange} />
201232
<NetworkSelector
202233
value={network}
203234
onChange={switchNetwork}
@@ -207,7 +238,7 @@ export default function Home() {
207238
<div className="relative">
208239
<button
209240
onClick={() => setShowDisconnectMenu(!showDisconnectMenu)}
210-
className="flex items-center gap-2 px-4 py-2 bg-slate-800 rounded-lg border border-slate-700 hover:bg-slate-700 transition-colors"
241+
className="flex items-center gap-2 px-3 py-2 bg-slate-800 rounded-lg border border-slate-700 hover:bg-slate-700 transition-colors whitespace-nowrap"
211242
>
212243
<span className="w-2 h-2 bg-green-500 rounded-full"></span>
213244
<span className="text-sm text-slate-300">{formatAddress(address || '')}</span>
@@ -232,14 +263,27 @@ export default function Home() {
232263
) : (
233264
<button
234265
onClick={() => setShowWalletModal(true)}
235-
className="px-6 py-2 rounded-lg font-bold bg-gradient-to-b from-yellow-400 via-yellow-500 to-yellow-600 text-yellow-900 hover:brightness-110 transition-all"
266+
className="px-4 py-2 rounded-lg font-bold bg-gradient-to-b from-yellow-400 via-yellow-500 to-yellow-600 text-yellow-900 hover:brightness-110 transition-all whitespace-nowrap"
236267
>
237268
Connect Wallet
238269
</button>
239270
)}
240271
</div>
241272

242-
<FortuneTigerBetCard selectedToken={selectedToken} />
273+
<FortuneTigerBetCard
274+
selectedToken={selectedToken}
275+
onTokenChange={handleTokenChange}
276+
network={network}
277+
onNetworkChange={switchNetwork}
278+
onConnectWallet={() => setShowWalletModal(true)}
279+
onDisconnectWallet={disconnectWallet}
280+
formattedBalance={formattedBalance}
281+
onLoadBalance={() => {
282+
const tokenUid = getContractStateForToken(selectedToken)?.token_uid || '00';
283+
refreshBalance(tokenUid);
284+
}}
285+
walletType={walletType}
286+
/>
243287
<UIModeSwitcher
244288
currentMode={uiMode}
245289
onModeChange={handleModeChange}
@@ -261,24 +305,21 @@ export default function Home() {
261305

262306
return (
263307
<div className="min-h-screen bg-slate-900">
264-
<Header />
308+
<Header selectedToken={selectedToken} onTokenChange={handleTokenChange} />
265309

266310
<main className="container mx-auto px-6 py-8">
267311
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
268312
<div className="lg:col-span-2 space-y-6">
269313
{connected && <BalanceCard selectedToken={selectedToken} />}
270-
<ProfitLossCard />
271-
<RecentBetsTable />
314+
<ProfitLossCard selectedToken={selectedToken} />
315+
<RecentBetsTable selectedToken={selectedToken} />
272316
<RecentOperationsTable selectedToken={selectedToken} />
273317
</div>
274318

275319
<div className="space-y-6">
276320
{/* Place Bet - Right Panel */}
277321
<div className="bg-slate-800 rounded-xl border border-slate-700 p-6">
278-
<div className="flex items-center justify-between mb-4">
279-
<h2 className="text-lg font-bold text-white">PLACE BET</h2>
280-
<TokenSelector selectedToken={selectedToken} onTokenChange={setSelectedToken} />
281-
</div>
322+
<h2 className="text-lg font-bold text-white mb-4">PLACE BET</h2>
282323

283324
{isConnected && (
284325
<div className="mb-4 p-4 bg-slate-700/50 rounded-lg border border-slate-600 space-y-3">
@@ -300,7 +341,8 @@ export default function Home() {
300341
if (walletType !== 'metamask') {
301342
toast.info('⏳ Please confirm the operation in your wallet...');
302343
}
303-
refreshBalance();
344+
const tokenUid = getContractStateForToken(selectedToken)?.token_uid || '00';
345+
refreshBalance(tokenUid);
304346
}}
305347
className="px-3 py-1 font-medium rounded transition-colors hover:opacity-90"
306348
style={{ background: 'linear-gradient(244deg, rgb(255, 166, 0) 0%, rgb(255, 115, 0) 100%)', color: '#1e293b' }}

components/ContractInfoPanel.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import { formatTokenAmount, formatNumber } from '@/lib/utils';
77
interface ContractInfoPanelProps {
88
contractState: ContractState | null;
99
loading?: boolean;
10+
token?: string;
1011
}
1112

12-
export function ContractInfoPanel({ contractState, loading }: ContractInfoPanelProps) {
13+
export function ContractInfoPanel({ contractState, loading, token = 'HTR' }: ContractInfoPanelProps) {
1314
if (loading) {
1415
return (
1516
<Card>
@@ -57,15 +58,15 @@ export function ContractInfoPanel({ contractState, loading }: ContractInfoPanelP
5758
</div>
5859
<div>
5960
<p className="text-sm text-slate-400">Max Bet</p>
60-
<p className="text-lg font-semibold">{formatTokenAmount(contractState.max_bet_amount)} HTR</p>
61+
<p className="text-lg font-semibold">{formatTokenAmount(contractState.max_bet_amount)} {token}</p>
6162
</div>
6263
<div>
6364
<p className="text-sm text-slate-400">Available Liquidity</p>
64-
<p className="text-lg font-semibold">{formatTokenAmount(contractState.available_tokens)} HTR</p>
65+
<p className="text-lg font-semibold">{formatTokenAmount(contractState.available_tokens)} {token}</p>
6566
</div>
6667
<div>
6768
<p className="text-sm text-slate-400">Total Liquidity</p>
68-
<p className="text-lg font-semibold">{formatTokenAmount(contractState.total_liquidity_provided)} HTR</p>
69+
<p className="text-lg font-semibold">{formatTokenAmount(contractState.total_liquidity_provided)} {token}</p>
6970
</div>
7071
<div>
7172
<p className="text-sm text-slate-400">Random Bits</p>

0 commit comments

Comments
 (0)