diff --git a/src/pages/WalletPage.tsx b/src/pages/WalletPage.tsx index 17d9d8a..21142ad 100644 --- a/src/pages/WalletPage.tsx +++ b/src/pages/WalletPage.tsx @@ -1,10 +1,8 @@ +import { useState } from 'react'; import { useSeoMeta } from '@unhead/react'; import { Layout } from '@/components/Layout'; import { WalletModal } from '@/components/WalletModal'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; -import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { useWallet } from '@/hooks/useWallet'; import { useNWC } from '@/hooks/useNWCContext'; import { useCurrentUser } from '@/hooks/useCurrentUser'; @@ -12,296 +10,116 @@ import { useCashu } from '@/hooks/wallet/useCashu'; import { useSatsToUsd } from '@/hooks/useExchangeRate'; import { LoginArea } from '@/components/auth/LoginArea'; import { CashuWalletCard } from '@/components/wallet/CashuWalletCard'; -import { LightningPrivacyTips } from '@/components/wallet/LightningPrivacyTips'; -import { WalletComparisonGuide } from '@/components/wallet/WalletComparisonGuide'; +import { cn } from '@/lib/utils'; import { - Wallet, Zap, Settings, CheckCircle, XCircle, - ExternalLink, Globe, WalletMinimal, - Info, Nut, ChevronRight, + ExternalLink, + ChevronDown, + ChevronUp, + Wallet, Bitcoin, } from 'lucide-react'; -// ─── Wallet Status Card ─────────────────────────────────────────────────────── - -function WalletStatusCard() { - const { webln } = useWallet(); - const { connections } = useNWC(); - const { totalBalance: cashuBalance, isInitialized: hasCashu } = useCashu(); - const cashuUsd = useSatsToUsd(cashuBalance); - const hasNWC = connections.length > 0 && connections.some(c => c.isConnected); - const isReady = webln || hasNWC || hasCashu; - - return ( - - -
- - - Wallet Status - - - {isReady ? '✓ Ready' : 'Not Connected'} - -
- - {isReady - ? 'Your wallet is connected and ready to send zaps!' - : 'Connect a wallet to enable Lightning zaps'} - -
- - {/* Cashu */} -
-
-
- -
-
-

Cashu Wallet

-

- {hasCashu && cashuBalance > 0 - ? `${cashuBalance.toLocaleString()} sats${cashuUsd ? ` · $${cashuUsd.toFixed(2)}` : ''}` - : 'Built-in ecash wallet'} -

-
-
- {hasCashu - ? - : } -
- - {/* WebLN */} -
-
-
- -
-
-

WebLN

-

Browser extension wallet

-
-
- {webln - ? - : } -
- - {/* NWC */} -
-
-
- -
-
-

Nostr Wallet Connect

-

- {connections.length > 0 - ? `${connections.length} wallet${connections.length !== 1 ? 's' : ''} connected` - : 'Remote wallet connection'} -

-
-
- {hasNWC - ? - : } -
- - - - -
-
- ); -} - -// ─── Zaps Info Card ─────────────────────────────────────────────────────────── - -function ZapsInfoCard() { - const items = [ - { emoji: '⚡', title: 'Instant', desc: 'Payments settle in seconds over Lightning' }, - { emoji: '🔐', title: 'Flexible custody', desc: 'Use your own wallet or a custodial service' }, - { emoji: '🥜', title: 'NutZaps for privacy', desc: "Cashu ecash — mints can't see who pays whom" }, - { emoji: '💜', title: 'Value for value', desc: 'Support creators directly' }, - ]; - - return ( - - - - - What are Zaps? - - - -

- Zaps are Lightning micropayments — send sats instantly to any skater, spot creator, or coach. No middleman, no platform cut. -

-
- {items.map((item) => ( -
- {item.emoji} -
-

{item.title}

-

{item.desc}

-
-
- ))} -
-
-
- ); -} - -// ─── Recommended Wallets ────────────────────────────────────────────────────── - -function WalletResourcesCard() { - const wallets = [ - { name: 'Alby', desc: 'Browser extension · WebLN + NWC', url: 'https://getalby.com', type: 'WebLN', color: 'text-yellow-400' }, - { name: 'Minibits', desc: 'Mobile Cashu wallet · NWC', url: 'https://www.minibits.cash', type: 'NWC', color: 'text-orange-400' }, - { name: 'Zeus', desc: 'Self-custodial mobile Lightning', url: 'https://zeusln.com', type: 'NWC', color: 'text-blue-400' }, - { name: 'Coinos', desc: 'Web-based · works everywhere', url: 'https://coinos.io', type: 'NWC', color: 'text-green-400' }, - ]; - - return ( - - - - - Recommended Wallets - - Get started with one of these Lightning wallets - - - {wallets.map((w) => ( - -
-
- -
-
-
- {w.name} - {w.type} -
-

{w.desc}

-
-
- -
- ))} - - - Learn more at Plan B Academy - -
-
- ); -} - -// ─── Not Logged In ──────────────────────────────────────────────────────────── - -function NotLoggedInCard() { - return ( - - -
- -
-

Login Required

-

- Log in with your Nostr account to connect your Lightning wallet and start zapping. -

- -
-
- ); -} - -// ─── Balance Hero Banner ────────────────────────────────────────────────────── +// ─── Balance Hero ───────────────────────────────────────────────────────────── function BalanceHero() { const { totalBalance: cashuBalance, isInitialized: hasCashu } = useCashu(); const cashuUsd = useSatsToUsd(cashuBalance); const { webln } = useWallet(); const { connections } = useNWC(); - const hasNWC = connections.length > 0 && connections.some(c => c.isConnected); + const hasNWC = connections.length > 0 && connections.some((c) => c.isConnected); + const isReady = webln || hasNWC || hasCashu; return ( -
- {/* Background glow */} -
-
+
+ {/* Background glows */} +
+
-
-
-
- - Cashu Balance +
+ {/* Balance */} +
+

Cashu Balance

+
+ + {hasCashu ? cashuBalance.toLocaleString() : '0'} + + sats
-
- {hasCashu ? cashuBalance.toLocaleString() : '—'} - sats -
- {cashuUsd !== null && cashuBalance > 0 && ( -
+ {cashuUsd !== null && cashuBalance > 0 ? ( +

≈ ${cashuUsd.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} -

+

+ ) : ( +

no balance yet

)} - {/* Wallet status pills */} -
- {hasCashu && ( - - Cashu - - )} - {webln && ( - - WebLN - - )} - {hasNWC && ( - - NWC - - )} - {!hasCashu && !webln && !hasNWC && ( - - No wallet connected - - )} -
- {/* Manage button */} + {/* Wallet status — compact icon row */} +
+ + + +
+ + {/* Primary action buttons — scroll down to Cashu card to act */} +
+ + +
+ + {/* Manage wallets */} -
@@ -309,6 +127,167 @@ function BalanceHero() { ); } +function WalletStatusPill({ + icon: Icon, + label, + active, + color, + activeBg, +}: { + icon: React.ComponentType<{ className?: string }>; + label: string; + active: boolean; + color: string; + activeBg: string; +}) { + return ( +
+ + {label} + {active + ? + : + } +
+ ); +} + +// ─── Recommended Wallets (collapsible) ─────────────────────────────────────── + +function RecommendedWallets() { + const [open, setOpen] = useState(false); + + const wallets = [ + { name: 'Minibits', desc: 'Mobile Cashu · NWC', url: 'https://www.minibits.cash', color: 'text-orange-400' }, + { name: 'Alby', desc: 'Browser extension · WebLN + NWC', url: 'https://getalby.com', color: 'text-yellow-400' }, + { name: 'Zeus', desc: 'Self-custodial Lightning', url: 'https://zeusln.com', color: 'text-blue-400' }, + { name: 'Coinos', desc: 'Web-based · works everywhere', url: 'https://coinos.io', color: 'text-green-400' }, + ]; + + return ( +
+ + + {open && ( + + )} +
+ ); +} + +// ─── Zaps explainer (collapsible, hidden once wallet connected) ─────────────── + +function WhatAreZaps({ walletConnected }: { walletConnected: boolean }) { + const [open, setOpen] = useState(!walletConnected); + + if (walletConnected && !open) { + return ( + + ); + } + + return ( +
+ + + {open && ( +
+

+ Zaps are instant Bitcoin Lightning payments. Send sats to any skater, spot creator, or coach — no middleman, no platform cut. +

+
+ {[ + { emoji: '⚡', title: 'Instant', desc: 'Settles in seconds' }, + { emoji: '🔐', title: 'Flexible', desc: 'Your wallet, your keys' }, + { emoji: '🥜', title: 'Private', desc: 'Cashu hides who pays' }, + { emoji: '💜', title: 'Direct', desc: 'Value goes to creator' }, + ].map((item) => ( +
+ {item.emoji} +
+

{item.title}

+

{item.desc}

+
+
+ ))} +
+
+ )} +
+ ); +} + +// ─── Not logged in ──────────────────────────────────────────────────────────── + +function NotLoggedIn() { + return ( +
+
+ +
+

Login Required

+

+ Log in with your Nostr account to connect your Lightning wallet and start zapping. +

+ +
+ ); +} + // ─── Page ───────────────────────────────────────────────────────────────────── export default function WalletPage() { @@ -318,67 +297,42 @@ export default function WalletPage() { }); const { user } = useCurrentUser(); + const { webln } = useWallet(); + const { connections } = useNWC(); + const { isInitialized: hasCashu } = useCashu(); + const hasNWC = connections.length > 0 && connections.some((c) => c.isConnected); + const walletConnected = !!(webln || hasNWC || hasCashu); return ( -
+
+ {/* Header */} -
-

- - Wallet +
+

+ WALLET

-

- Bitcoin Lightning payments & zaps -

+

Bitcoin Lightning + Cashu

{user ? (
- {/* Balance hero — always at top for logged-in users */} + {/* 1. Balance hero — always first */} - {/* Quick Guide — collapsed by default */} - + {/* 2. Cashu wallet card — the main interactive section */} +
+ +
- - {/* Tab pills — full width, thumb-friendly height */} - - - - Cashu - - - - Lightning - - + {/* 3. Get a wallet — collapsed by default */} + - {/* Cashu tab */} - - - - - {/* Lightning tab */} - - - - - - - + {/* 4. Zaps explainer — auto-collapsed once wallet is connected */} +
) : ( -
- - -
+ )}