Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 38 additions & 19 deletions apps/payments/web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,23 @@ import { DashboardView } from './views/DashboardView';
import { EmissionsView } from './views/EmissionsView';
import { DiemRewardsView } from './views/DiemRewardsView';
import { ChannelsView } from './components/ChannelsView';
import { SettingsView } from './views/SettingsView';
import { AuthorizedWalletProvider } from './context/AuthorizedWalletContext';
import { useAuthorizedWallet } from './context/AuthorizedWalletContext';
import { AuthorizeWalletAlert } from './layout/AuthorizeWalletAlert';

export type OverlayPhase = 'deposit' | 'success' | null;

const VALID_TABS = new Set<TabId>(['dashboard', 'channels', 'emissions', 'diem-rewards']);
const VALID_TABS = new Set<TabId>(['overview', 'rewards', 'diem-rewards', 'activity', 'settings']);

function parseTabFromUrl(): TabId {
const raw = new URLSearchParams(window.location.search).get('tab');
if (!raw) return 'dashboard';
if (!raw) return 'overview';
// Legacy compat: the old deposits tab no longer exists; fall through to dashboard.
if (raw === 'deposit' || raw === 'deposits') return 'dashboard';
return VALID_TABS.has(raw as TabId) ? (raw as TabId) : 'dashboard';
if (raw === 'deposit' || raw === 'deposits' || raw === 'dashboard') return 'overview';
if (raw === 'channels') return 'activity';
if (raw === 'emissions') return 'rewards';
return VALID_TABS.has(raw as TabId) ? (raw as TabId) : 'overview';
}

function shouldOpenDepositFromUrl(): boolean {
Expand Down Expand Up @@ -187,6 +191,7 @@ function AppShell({
}: AppShellProps) {
const [justDeposited, setJustDeposited] = useState(false);
const [depositPromptDismissed, setDepositPromptDismissed] = useState(false);
const authorizedWallet = useAuthorizedWallet();

const isLoading = !balanceLoaded;
const isEmptyBuyer =
Expand Down Expand Up @@ -216,34 +221,48 @@ function AppShell({
<Sidebar
activeTab={activeTab}
onSelect={onSelectTab}
isDark={isDark}
onToggleTheme={onToggleTheme}
/>
<div className="dash-main">
<TopBar
activeTab={activeTab}
balance={balance}
buyerEvmAddress={buyerEvmAddress}
atRisk={authorizedWallet.operatorSet === false && Number(balance?.total ?? 0) > 0}
isDark={isDark}
onToggleTheme={onToggleTheme}
onOpenWallet={onOpenWalletDrawer}
onOpenDeposit={onOpenDeposit}
/>
<AuthorizeWalletAlert />
<main className="dash-content">
{activeTab === 'dashboard' && <DashboardView config={config} />}
{activeTab === 'channels' && <ChannelsView config={config} />}
{activeTab === 'emissions' && <EmissionsView config={config} />}
{activeTab === 'overview' && (
<DashboardView
config={config}
balance={balance}
onOpenDeposit={onOpenDeposit}
onOpenWithdraw={onOpenWithdraw}
onOpenRewards={() => onSelectTab('rewards')}
onOpenDiemRewards={() => onSelectTab('diem-rewards')}
onOpenActivity={() => onSelectTab('activity')}
/>
)}
{activeTab === 'rewards' && <EmissionsView config={config} />}
{activeTab === 'diem-rewards' && <DiemRewardsView config={config} />}
{activeTab === 'activity' && <ChannelsView config={config} />}
{activeTab === 'settings' && (
<SettingsView
config={config}
/>
)}
</main>
</div>
<WalletDrawer
isOpen={walletDrawerOpen}
onClose={onCloseWalletDrawer}
balance={balance}
config={config}
buyerEvmAddress={buyerEvmAddress}
onOpenDeposit={onOpenDeposit}
onOpenWithdraw={onOpenWithdraw}
/>
</div>
<WalletDrawer
isOpen={walletDrawerOpen}
onClose={onCloseWalletDrawer}
balance={balance}
config={config}
buyerEvmAddress={buyerEvmAddress}
/>
<LoaderOverlay isVisible={isLoading} />
<EmptyStateOverlay
phase={overlayPhase}
Expand Down
15 changes: 8 additions & 7 deletions apps/payments/web/src/components/AuthorizeWalletModal.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { useAccount } from 'wagmi';
import { ConnectButton } from '@rainbow-me/rainbowkit';
import { ActionModal } from '../layout/ActionModal';
import { useSetOperator } from '../hooks/useSetOperator';
import type { PaymentConfig } from '../types';
import { Button } from './Button';
import { ConnectWalletAction } from './ConnectWalletAction';

interface AuthorizeWalletModalProps {
isOpen: boolean;
Expand All @@ -23,6 +23,7 @@ export function AuthorizeWalletModal({
onAuthorized,
}: AuthorizeWalletModalProps) {
const { address, isConnected } = useAccount();
const walletConnected = isConnected && Boolean(address);
const { run, running, success, error, reset } = useSetOperator(config);

const whyRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -91,20 +92,20 @@ export function AuthorizeWalletModal({
document.body,
)}

{!isConnected ? (
{!walletConnected ? (
<div className="authorize-wallet-connect">
<div className="authorize-wallet-step-label">Step 1 — Connect a wallet</div>
<ConnectButton.Custom>
{({ openConnectModal, mounted }) => (
<ConnectWalletAction>
{({ openConnectModal, ready, connected }) => connected ? null : (
<Button
fullWidth
onClick={openConnectModal}
disabled={!mounted}
disabled={!ready}
>
Connect wallet
</Button>
)}
</ConnectButton.Custom>
</ConnectWalletAction>
</div>
) : (
<div className="authorize-wallet-connect">
Expand All @@ -117,7 +118,7 @@ export function AuthorizeWalletModal({
<Button
fullWidth
onClick={() => void run()}
disabled={!isConnected || running || !config}
disabled={!walletConnected || running || !config}
>
{running ? 'Authorizing…' : 'Authorize this wallet'}
</Button>
Expand Down
51 changes: 1 addition & 50 deletions apps/payments/web/src/components/ChannelsView.scss
Original file line number Diff line number Diff line change
@@ -1,32 +1,3 @@
.channels-section-head-row {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 16px;

.dashboard-section-head {
flex: 1 1 auto;
min-width: 0;
}
}

.dashboard-kpi-sub {
margin-top: 4px;
font-size: 11px;
font-weight: 600;
color: var(--text-muted);
letter-spacing: 0.02em;
font-variant-numeric: tabular-nums;
}

.channels-table-caption {
font-size: 11px;
font-weight: 600;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.08em;
}

.channels-table-wrap {
overflow-x: auto;
margin: 0 -24px;
Expand Down Expand Up @@ -73,10 +44,6 @@
border-bottom: none;
}

tbody tr:hover td {
background: var(--card-hover, rgba(148, 163, 184, 0.05));
}

.channels-table-num {
text-align: right;
color: var(--text-primary);
Expand All @@ -86,7 +53,7 @@
.channels-table-cell-seller {
color: var(--text-primary);
font-weight: 600;
letter-spacing: -0.01em;
letter-spacing: 0;
}

.channels-table-cell-id {
Expand Down Expand Up @@ -194,22 +161,6 @@
}
}

.channels-section-head-row .channels-refresh-btn {
width: auto;
padding: 6px 14px;
font-size: 12px;
flex-shrink: 0;
margin-top: 14px;
align-self: flex-start;
}

.channels-view-empty {
text-align: center;
padding: 40px 16px;
color: var(--text-muted);
font-size: 13px;
}

.status-pill {
display: inline-block;
padding: 3px 10px;
Expand Down
Loading