/ src / app / wallets / page.tsx
page.tsx
  1  'use client'
  2  
  3  import { useEffect, useState } from 'react'
  4  import { useAppStore } from '@/stores/use-app-store'
  5  import { WalletList } from '@/components/wallets/wallet-list'
  6  import { api } from '@/lib/app/api-client'
  7  import type { SafeWallet } from '@/types'
  8  
  9  export default function WalletsPage() {
 10    const agents = useAppStore((s) => s.agents)
 11    const loadAgents = useAppStore((s) => s.loadAgents)
 12    const loadWallets = useAppStore((s) => s.loadWallets)
 13    const [generating, setGenerating] = useState(false)
 14    const [showPicker, setShowPicker] = useState(false)
 15    const [error, setError] = useState<string | null>(null)
 16  
 17    useEffect(() => {
 18      loadAgents()
 19      loadWallets()
 20    }, [loadAgents, loadWallets])
 21  
 22    const agentList = Object.values(agents)
 23  
 24    const handleGenerate = async (agentId?: string) => {
 25      const targetId = agentId || agentList[0]?.id
 26      if (!targetId) {
 27        setError('Create an agent first')
 28        setTimeout(() => setError(null), 3000)
 29        return
 30      }
 31      setGenerating(true)
 32      setShowPicker(false)
 33      setError(null)
 34      try {
 35        await api<SafeWallet>('POST', '/wallets/generate', { agentId: targetId })
 36        loadWallets()
 37      } catch (err) {
 38        setError(err instanceof Error ? err.message : 'Failed to generate wallet')
 39        setTimeout(() => setError(null), 4000)
 40      } finally {
 41        setGenerating(false)
 42      }
 43    }
 44  
 45    return (
 46      <div className="flex-1 flex flex-col h-full">
 47        <div className="flex items-center px-6 pt-5 pb-3 shrink-0">
 48          <h2 className="font-display text-[14px] font-600 text-text-2 tracking-[-0.01em] capitalize flex-1">
 49            Wallets
 50          </h2>
 51          <div className="relative">
 52            <button
 53              onClick={() => {
 54                if (agentList.length <= 1) {
 55                  handleGenerate()
 56                } else {
 57                  setShowPicker(!showPicker)
 58                }
 59              }}
 60              disabled={generating}
 61              className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-[8px] text-[11px] font-600 text-accent-bright bg-accent-soft hover:bg-accent-bright/15 transition-all cursor-pointer disabled:opacity-50"
 62              style={{ fontFamily: 'inherit' }}
 63            >
 64              {generating ? (
 65                <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" className="animate-spin">
 66                  <path d="M21 12a9 9 0 1 1-6.219-8.56" />
 67                </svg>
 68              ) : (
 69                <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
 70                  <line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" />
 71                </svg>
 72              )}
 73              {generating ? 'Generating...' : 'Generate Wallet'}
 74            </button>
 75  
 76            {/* Agent picker dropdown */}
 77            {showPicker && (
 78              <>
 79                <div className="fixed inset-0 z-40" onClick={() => setShowPicker(false)} />
 80                <div className="absolute right-0 top-full mt-1 z-50 w-56 rounded-[12px] bg-surface border border-white/[0.08] shadow-xl overflow-hidden">
 81                  <div className="px-3 py-2 border-b border-white/[0.06]">
 82                    <span className="text-[11px] font-600 text-text-3">Select Agent</span>
 83                  </div>
 84                  <div className="max-h-48 overflow-y-auto py-1">
 85                    {agentList.map((agent) => (
 86                      <button
 87                        key={agent.id}
 88                        onClick={() => handleGenerate(agent.id)}
 89                        className="w-full text-left px-3 py-2 flex items-center gap-2 hover:bg-white/[0.04] transition-colors cursor-pointer"
 90                        style={{ fontFamily: 'inherit' }}
 91                      >
 92                        <span className="text-[14px]">{agent.emoji || '🤖'}</span>
 93                        <span className="text-[12px] font-600 text-text truncate">{agent.name}</span>
 94                      </button>
 95                    ))}
 96                  </div>
 97                </div>
 98              </>
 99            )}
100          </div>
101        </div>
102  
103        {error && (
104          <div className="mx-6 mb-2 px-3 py-2 rounded-[10px] bg-red-500/10 border border-red-500/20 text-[12px] text-red-400 font-600">
105            {error}
106          </div>
107        )}
108  
109        <WalletList />
110      </div>
111    )
112  }