feat: revamp dashboard, trades, and add landing/legal pages
- Major UI updates across dashboard, analytics, posts, trades, settings - New landing page, robots/sitemap, contact/privacy/terms pages - Updated globals.css with extensive styling and new landing.css - Refactor signedRequest, realtime data hook, and dashboard store Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+26
-20
@@ -4,7 +4,6 @@ import { useState, useEffect } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { useAccount, useConnect, useDisconnect } from 'wagmi'
|
||||
import { injected } from 'wagmi/connectors'
|
||||
|
||||
function BrandMark() {
|
||||
return <span className="brand-mark">α</span>
|
||||
@@ -46,10 +45,12 @@ function ThemeToggle() {
|
||||
export default function Navbar() {
|
||||
const pathname = usePathname()
|
||||
const { address, isConnected } = useAccount()
|
||||
const { connect } = useConnect()
|
||||
const { connect, connectors } = useConnect()
|
||||
const { disconnect } = useDisconnect()
|
||||
const [mounted, setMounted] = useState(false)
|
||||
const [walletMenuOpen, setWalletMenuOpen] = useState(false)
|
||||
useEffect(() => { setMounted(true) }, [])
|
||||
useEffect(() => { setWalletMenuOpen(false) }, [pathname, address])
|
||||
|
||||
const locale = pathname.split('/')[1] || 'en'
|
||||
const path = '/' + pathname.split('/').slice(2).join('/')
|
||||
@@ -98,45 +99,50 @@ export default function Navbar() {
|
||||
<div className="wallet-menu-wrap" style={{ position: 'relative' }}>
|
||||
<button
|
||||
className="wallet-chip"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
const menu = (e.currentTarget.nextElementSibling as HTMLElement | null)
|
||||
if (menu) menu.style.display = menu.style.display === 'block' ? 'none' : 'block'
|
||||
}}
|
||||
onClick={() => setWalletMenuOpen(open => !open)}
|
||||
onBlur={(e) => {
|
||||
const menu = e.currentTarget.nextElementSibling as HTMLElement | null
|
||||
setTimeout(() => { if (menu) menu.style.display = 'none' }, 150)
|
||||
if (!e.currentTarget.parentElement?.contains(e.relatedTarget as Node | null)) {
|
||||
setWalletMenuOpen(false)
|
||||
}
|
||||
}}
|
||||
aria-expanded={walletMenuOpen}
|
||||
aria-haspopup="menu"
|
||||
>
|
||||
<span className="ava" />
|
||||
<span className="mono">{shortAddr}</span>
|
||||
</button>
|
||||
<div
|
||||
style={{
|
||||
display: 'none', position: 'absolute', right: 0, top: 'calc(100% + 6px)',
|
||||
background: 'var(--bg-elev)', border: '1px solid var(--line)', borderRadius: 'var(--r-sm)',
|
||||
minWidth: 180, padding: 6, zIndex: 1000, boxShadow: '0 4px 16px rgba(0,0,0,0.12)',
|
||||
}}
|
||||
>
|
||||
<div className={`wallet-menu ${walletMenuOpen ? 'open' : ''}`} role="menu">
|
||||
<button
|
||||
role="menuitem"
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault()
|
||||
if (address) navigator.clipboard?.writeText(address)
|
||||
setWalletMenuOpen(false)
|
||||
}}
|
||||
style={{ width: '100%', padding: '8px 10px', fontSize: 13, textAlign: 'left', borderRadius: 6, color: 'var(--ink)' }}
|
||||
>
|
||||
Copy address
|
||||
</button>
|
||||
<button
|
||||
onMouseDown={(e) => { e.preventDefault(); disconnect() }}
|
||||
style={{ width: '100%', padding: '8px 10px', fontSize: 13, textAlign: 'left', borderRadius: 6, color: 'var(--down)' }}
|
||||
role="menuitem"
|
||||
className="danger"
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault()
|
||||
disconnect()
|
||||
setWalletMenuOpen(false)
|
||||
}}
|
||||
>
|
||||
Disconnect
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<button className="connect-btn lg" onClick={() => connect({ connector: injected() })}>
|
||||
<button
|
||||
className="connect-btn lg"
|
||||
onClick={() => {
|
||||
const connector = connectors[0]
|
||||
if (connector) connect({ connector })
|
||||
}}
|
||||
>
|
||||
Connect wallet
|
||||
</button>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user