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:
k
2026-04-25 16:04:57 +08:00
parent 83e5892ddf
commit 040e1df685
28 changed files with 4133 additions and 690 deletions
+26 -20
View File
@@ -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>
)}