refactor: replace window.location with useNavigate for routing in auth components (#1470)

Co-authored-by: Dean <afei.wuhao@gmail.com>
This commit is contained in:
deanokk
2026-04-13 23:44:14 +08:00
committed by GitHub
parent eef78b7987
commit e1b5a5d833
22 changed files with 1930 additions and 1273 deletions

View File

@@ -1,5 +1,6 @@
import { useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { useNavigate } from 'react-router-dom'
import useSWR from 'swr'
import {
TrendingUp,
@@ -15,7 +16,7 @@ import {
Activity,
Terminal,
Cpu,
Database
Database,
} from 'lucide-react'
import { useLanguage } from '../contexts/LanguageContext'
import { useAuth } from '../contexts/AuthContext'
@@ -39,14 +40,24 @@ interface PublicStrategy {
updated_at: string
}
const strategyStyles: Record<string, { color: string; border: string; glow: string; shadow: string; icon: any; bg: string }> = {
const strategyStyles: Record<
string,
{
color: string
border: string
glow: string
shadow: string
icon: any
bg: string
}
> = {
scalper: {
color: 'text-[#F0B90B]',
border: 'border-[#F0B90B]/30',
glow: 'shadow-[0_0_20px_rgba(240,185,11,0.15)]',
shadow: 'hover:shadow-[0_0_30px_rgba(240,185,11,0.25)]',
bg: 'bg-[#F0B90B]/5',
icon: Zap
icon: Zap,
},
swing: {
color: 'text-cyan-400',
@@ -54,7 +65,7 @@ const strategyStyles: Record<string, { color: string; border: string; glow: stri
glow: 'shadow-[0_0_20px_rgba(34,211,238,0.15)]',
shadow: 'hover:shadow-[0_0_30px_rgba(34,211,238,0.25)]',
bg: 'bg-cyan-400/5',
icon: TrendingUp
icon: TrendingUp,
},
arbitrage: {
color: 'text-purple-400',
@@ -62,7 +73,7 @@ const strategyStyles: Record<string, { color: string; border: string; glow: stri
glow: 'shadow-[0_0_20px_rgba(192,132,252,0.15)]',
shadow: 'hover:shadow-[0_0_30px_rgba(192,132,252,0.25)]',
bg: 'bg-purple-400/5',
icon: Layers
icon: Layers,
},
conservative: {
color: 'text-emerald-400',
@@ -70,7 +81,7 @@ const strategyStyles: Record<string, { color: string; border: string; glow: stri
glow: 'shadow-[0_0_20px_rgba(52,211,153,0.15)]',
shadow: 'hover:shadow-[0_0_30px_rgba(52,211,153,0.25)]',
bg: 'bg-emerald-400/5',
icon: Shield
icon: Shield,
},
aggressive: {
color: 'text-red-500',
@@ -78,7 +89,7 @@ const strategyStyles: Record<string, { color: string; border: string; glow: stri
glow: 'shadow-[0_0_20px_rgba(239,68,68,0.15)]',
shadow: 'hover:shadow-[0_0_30px_rgba(239,68,68,0.25)]',
bg: 'bg-red-500/5',
icon: Target
icon: Target,
},
default: {
color: 'text-zinc-400',
@@ -86,8 +97,8 @@ const strategyStyles: Record<string, { color: string; border: string; glow: stri
glow: '',
shadow: 'hover:shadow-[0_0_20px_rgba(255,255,255,0.05)]',
bg: 'bg-zinc-800/20',
icon: Activity
}
icon: Activity,
},
}
function getStrategyStyle(name: string) {
@@ -95,12 +106,15 @@ function getStrategyStyle(name: string) {
if (lowerName.includes('scalp')) return strategyStyles.scalper
if (lowerName.includes('swing')) return strategyStyles.swing
if (lowerName.includes('arb')) return strategyStyles.arbitrage
if (lowerName.includes('safe') || lowerName.includes('conserv')) return strategyStyles.conservative
if (lowerName.includes('aggress') || lowerName.includes('high')) return strategyStyles.aggressive
if (lowerName.includes('safe') || lowerName.includes('conserv'))
return strategyStyles.conservative
if (lowerName.includes('aggress') || lowerName.includes('high'))
return strategyStyles.aggressive
return strategyStyles.default
}
export function StrategyMarketPage() {
const navigate = useNavigate()
const { language } = useLanguage()
const { token, user } = useAuth()
const [searchQuery, setSearchQuery] = useState('')
@@ -120,23 +134,28 @@ export function StrategyMarketPage() {
},
{
refreshInterval: 60000,
revalidateOnFocus: false
revalidateOnFocus: false,
}
)
const filteredStrategies = strategies?.filter(s => {
if (searchQuery) {
const query = searchQuery.toLowerCase()
return s.name.toLowerCase().includes(query) ||
s.description?.toLowerCase().includes(query)
}
return true
}) || []
const filteredStrategies =
strategies?.filter((s) => {
if (searchQuery) {
const query = searchQuery.toLowerCase()
return (
s.name.toLowerCase().includes(query) ||
s.description?.toLowerCase().includes(query)
)
}
return true
}) || []
const handleCopyConfig = async (strategy: PublicStrategy) => {
if (!strategy.config) return
try {
await navigator.clipboard.writeText(JSON.stringify(strategy.config, null, 2))
await navigator.clipboard.writeText(
JSON.stringify(strategy.config, null, 2)
)
setCopiedId(strategy.id)
toast.success(tr('copied'))
setTimeout(() => setCopiedId(null), 2000)
@@ -147,14 +166,16 @@ export function StrategyMarketPage() {
const formatDate = (dateStr: string) => {
const date = new Date(dateStr)
return date.toLocaleDateString('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false
}).replace(',', '')
return date
.toLocaleDateString('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false,
})
.replace(',', '')
}
const getIndicatorList = (config: any) => {
@@ -174,15 +195,15 @@ export function StrategyMarketPage() {
return (
<DeepVoidBackground className="min-h-screen text-white font-mono py-12">
<div className="w-full px-4 md:px-8 space-y-8">
<div className="w-full relative z-10">
{/* Header Section */}
<div className="mb-12 border-b border-zinc-800 pb-8 relative">
<div className="absolute top-0 right-0 p-2 border border-zinc-800 rounded bg-black/50 text-xs text-zinc-500 font-mono hidden md:block">
SYSTEM_STATUS: <span className="text-emerald-500 animate-pulse">ONLINE</span>
SYSTEM_STATUS:{' '}
<span className="text-emerald-500 animate-pulse">ONLINE</span>
<br />
MARKET_UPLINK: <span className="text-emerald-500">ESTABLISHED</span>
MARKET_UPLINK:{' '}
<span className="text-emerald-500">ESTABLISHED</span>
</div>
<div className="flex items-center gap-4 mb-4">
@@ -191,11 +212,15 @@ export function StrategyMarketPage() {
<Database className="w-8 h-8 text-nofx-gold relative z-10" />
</div>
<div>
<h1 className="text-4xl font-bold tracking-tighter text-white uppercase glitch-text" data-text={tr('title')}>
<h1
className="text-4xl font-bold tracking-tighter text-white uppercase glitch-text"
data-text={tr('title')}
>
{tr('title')}
</h1>
<p className="text-xs text-nofx-gold tracking-[0.3em] font-bold mt-1">
// {tr('subtitle')}
{'// '}
{tr('subtitle')}
</p>
</div>
</div>
@@ -232,16 +257,21 @@ export function StrategyMarketPage() {
<button
key={cat}
onClick={() => setSelectedCategory(cat)}
className={`px-4 py-2 text-xs font-mono uppercase tracking-wider transition-all relative overflow-hidden ${selectedCategory === cat
? 'text-black font-bold'
: 'text-zinc-500 hover:text-white'
}`}
className={`px-4 py-2 text-xs font-mono uppercase tracking-wider transition-all relative overflow-hidden ${
selectedCategory === cat
? 'text-black font-bold'
: 'text-zinc-500 hover:text-white'
}`}
>
{selectedCategory === cat && (
<motion.div
layoutId="filter-highlight"
className="absolute inset-0 bg-nofx-gold"
transition={{ type: "spring", bounce: 0.2, duration: 0.6 }}
transition={{
type: 'spring',
bounce: 0.2,
duration: 0.6,
}}
/>
)}
<span className="relative z-10">{tr(cat)}</span>
@@ -260,11 +290,22 @@ export function StrategyMarketPage() {
<Cpu size={24} className="text-nofx-gold/50" />
</div>
</div>
<p className="text-nofx-gold text-xs tracking-widest animate-pulse">{tr('loading')}</p>
<p className="text-nofx-gold text-xs tracking-widest animate-pulse">
{tr('loading')}
</p>
<div className="flex gap-1">
<div className="w-1 h-1 bg-nofx-gold rounded-full animate-bounce" style={{ animationDelay: '0s' }}></div>
<div className="w-1 h-1 bg-nofx-gold rounded-full animate-bounce" style={{ animationDelay: '0.2s' }}></div>
<div className="w-1 h-1 bg-nofx-gold rounded-full animate-bounce" style={{ animationDelay: '0.4s' }}></div>
<div
className="w-1 h-1 bg-nofx-gold rounded-full animate-bounce"
style={{ animationDelay: '0s' }}
></div>
<div
className="w-1 h-1 bg-nofx-gold rounded-full animate-bounce"
style={{ animationDelay: '0.2s' }}
></div>
<div
className="w-1 h-1 bg-nofx-gold rounded-full animate-bounce"
style={{ animationDelay: '0.4s' }}
></div>
</div>
</div>
)}
@@ -279,7 +320,9 @@ export function StrategyMarketPage() {
<h3 className="text-xl font-bold text-zinc-300 font-mono tracking-tight mb-2">
[{tr('noStrategies')}]
</h3>
<p className="text-zinc-600 text-xs tracking-wide uppercase">{tr('noStrategiesDesc')}</p>
<p className="text-zinc-600 text-xs tracking-wide uppercase">
{tr('noStrategiesDesc')}
</p>
</div>
)}
@@ -290,9 +333,10 @@ export function StrategyMarketPage() {
{filteredStrategies.map((strategy, i) => {
const style = getStrategyStyle(strategy.name)
const Icon = style.icon
const indicators = strategy.config_visible && strategy.config
? getIndicatorList(strategy.config)
: []
const indicators =
strategy.config_visible && strategy.config
? getIndicatorList(strategy.config)
: []
return (
<motion.div
@@ -304,16 +348,24 @@ export function StrategyMarketPage() {
className={`group relative bg-black border border-zinc-800 hover:border-zinc-600 transition-all duration-300 ${style.shadow}`}
>
{/* Holographic Border Highlight */}
<div className={`absolute top-0 left-0 w-full h-[1px] bg-gradient-to-r from-transparent via-${style.color.split('-')[1]}-500 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500`}></div>
<div className={`absolute bottom-0 right-0 w-full h-[1px] bg-gradient-to-r from-transparent via-${style.color.split('-')[1]}-500 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500`}></div>
<div
className={`absolute top-0 left-0 w-full h-[1px] bg-gradient-to-r from-transparent via-${style.color.split('-')[1]}-500 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500`}
></div>
<div
className={`absolute bottom-0 right-0 w-full h-[1px] bg-gradient-to-r from-transparent via-${style.color.split('-')[1]}-500 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500`}
></div>
{/* Category Side Strip */}
<div className={`absolute left-0 top-0 bottom-0 w-[2px] ${style.bg.replace('/5', '/50')}`}></div>
<div
className={`absolute left-0 top-0 bottom-0 w-[2px] ${style.bg.replace('/5', '/50')}`}
></div>
<div className="p-6 relative">
{/* Header */}
<div className="flex justify-between items-start mb-6">
<div className={`p-2 rounded-none border ${style.border} ${style.bg}`}>
<div
className={`p-2 rounded-none border ${style.border} ${style.bg}`}
>
<Icon className={`w-5 h-5 ${style.color}`} />
</div>
<div className="text-[10px] font-mono">
@@ -332,7 +384,9 @@ export function StrategyMarketPage() {
</div>
{/* Name and Description */}
<h3 className={`text-lg font-bold mb-2 tracking-tight group-hover:${style.color} transition-colors uppercase truncate relative`}>
<h3
className={`text-lg font-bold mb-2 tracking-tight group-hover:${style.color} transition-colors uppercase truncate relative`}
>
{strategy.name}
<span className="absolute -bottom-1 left-0 w-8 h-[2px] bg-zinc-800 group-hover:bg-nofx-gold transition-colors"></span>
</h3>
@@ -343,12 +397,22 @@ export function StrategyMarketPage() {
{/* Meta Data */}
<div className="grid grid-cols-2 gap-y-2 mb-6 text-[10px] font-mono text-zinc-600">
<div className="flex flex-col">
<span className="text-zinc-700 uppercase">{tr('author')}</span>
<span className="text-zinc-400 group-hover:text-white transition-colors">@{strategy.author_email?.split('@')[0] || 'UNKNOWN'}</span>
<span className="text-zinc-700 uppercase">
{tr('author')}
</span>
<span className="text-zinc-400 group-hover:text-white transition-colors">
@
{strategy.author_email?.split('@')[0] ||
'UNKNOWN'}
</span>
</div>
<div className="flex flex-col text-right">
<span className="text-zinc-700 uppercase">{tr('createdAt')}</span>
<span className="text-zinc-400">{formatDate(strategy.created_at)}</span>
<span className="text-zinc-700 uppercase">
{tr('createdAt')}
</span>
<span className="text-zinc-400">
{formatDate(strategy.created_at)}
</span>
</div>
</div>
@@ -358,14 +422,20 @@ export function StrategyMarketPage() {
<div className="space-y-3">
{/* Indicators */}
<div className="flex items-center gap-2 overflow-x-auto scrollbar-hide pb-1">
{indicators.length > 0 ? indicators.map((ind) => (
<span
key={ind}
className="px-1.5 py-0.5 border border-zinc-700 bg-zinc-800 text-[9px] text-zinc-300 font-mono whitespace-nowrap"
>
{ind}
{indicators.length > 0 ? (
indicators.map((ind) => (
<span
key={ind}
className="px-1.5 py-0.5 border border-zinc-700 bg-zinc-800 text-[9px] text-zinc-300 font-mono whitespace-nowrap"
>
{ind}
</span>
))
) : (
<span className="text-[9px] text-zinc-600">
NO_INDICATORS
</span>
)) : <span className="text-[9px] text-zinc-600">NO_INDICATORS</span>}
)}
</div>
{/* Risk Control */}
@@ -373,22 +443,38 @@ export function StrategyMarketPage() {
<div className="flex justify-between items-center text-[10px]">
<div className="flex gap-3">
<div className="flex flex-col">
<span className="text-zinc-600 scale-90 origin-left">LEV</span>
<span className="text-zinc-300 font-bold">{strategy.config.risk_control.btc_eth_max_leverage || '-'}x</span>
<span className="text-zinc-600 scale-90 origin-left">
LEV
</span>
<span className="text-zinc-300 font-bold">
{strategy.config.risk_control
.btc_eth_max_leverage || '-'}
x
</span>
</div>
<div className="flex flex-col">
<span className="text-zinc-600 scale-90 origin-left">POS</span>
<span className="text-zinc-300 font-bold">{strategy.config.risk_control.max_positions || '-'}</span>
<span className="text-zinc-600 scale-90 origin-left">
POS
</span>
<span className="text-zinc-300 font-bold">
{strategy.config.risk_control
.max_positions || '-'}
</span>
</div>
</div>
<Activity size={12} className="text-zinc-700" />
<Activity
size={12}
className="text-zinc-700"
/>
</div>
)}
</div>
) : (
<div className="flex flex-col items-center justify-center h-full text-zinc-600">
<EyeOff size={16} className="mb-1 opacity-50" />
<span className="text-[9px] uppercase tracking-widest">{tr('configHiddenDesc')}</span>
<span className="text-[9px] uppercase tracking-widest">
{tr('configHiddenDesc')}
</span>
</div>
)}
</div>
@@ -403,7 +489,9 @@ export function StrategyMarketPage() {
{copiedId === strategy.id ? (
<>
<Check className="w-3 h-3 text-emerald-500" />
<span className="text-emerald-500">{tr('copied')}</span>
<span className="text-emerald-500">
{tr('copied')}
</span>
</>
) : (
<>
@@ -413,13 +501,15 @@ export function StrategyMarketPage() {
)}
</button>
) : (
<button disabled className="w-full py-2.5 text-[10px] font-bold font-mono uppercase tracking-widest border border-zinc-800 bg-black text-zinc-700 cursor-not-allowed flex items-center justify-center gap-2">
<button
disabled
className="w-full py-2.5 text-[10px] font-bold font-mono uppercase tracking-widest border border-zinc-800 bg-black text-zinc-700 cursor-not-allowed flex items-center justify-center gap-2"
>
<Shield size={12} />
{tr('hideConfig')}
</button>
)}
</div>
</div>
</motion.div>
)
@@ -436,13 +526,23 @@ export function StrategyMarketPage() {
transition={{ delay: 0.3 }}
className="mt-16 mb-20 flex justify-center"
>
<div className="relative group cursor-pointer" onClick={() => window.location.href = '/strategy'}>
<div
className="relative group cursor-pointer"
onClick={() => navigate('/strategy')}
>
<div className="absolute -inset-1 bg-gradient-to-r from-nofx-gold to-yellow-600 rounded blur opacity-25 group-hover:opacity-75 transition duration-1000 group-hover:duration-200"></div>
<div className="relative px-8 py-4 bg-black border border-zinc-800 hover:border-nofx-gold/50 flex items-center gap-4 transition-all">
<Hexagon className="text-nofx-gold animate-spin-slow" size={24} />
<Hexagon
className="text-nofx-gold animate-spin-slow"
size={24}
/>
<div className="text-left">
<div className="text-sm font-bold text-white uppercase tracking-wider group-hover:text-nofx-gold transition-colors">{tr('shareYours')}</div>
<div className="text-[10px] text-zinc-500 font-mono">CONTRIBUTE TO THE GLOBAL DATABASE</div>
<div className="text-sm font-bold text-white uppercase tracking-wider group-hover:text-nofx-gold transition-colors">
{tr('shareYours')}
</div>
<div className="text-[10px] text-zinc-500 font-mono">
CONTRIBUTE TO THE GLOBAL DATABASE
</div>
</div>
<div className="w-[1px] h-8 bg-zinc-800 mx-2"></div>
<div className="text-xs font-mono text-zinc-400 group-hover:translate-x-1 transition-transform">
@@ -452,7 +552,6 @@ export function StrategyMarketPage() {
</div>
</motion.div>
)}
</div>
</div>
</DeepVoidBackground>