File size: 6,939 Bytes
8d3471e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | import React from 'react'
import { useI18n } from '../i18n'
import LanguageToggle from './LanguageToggle'
const LandingPage = ({ onEnter }) => {
const { t } = useI18n()
return (
<div className="landing-container min-h-screen relative overflow-hidden flex flex-col items-center justify-center p-6 text-center">
{/* Animated Background Elements - using Tailwind with some custom CSS in styles.css if needed,
but for simplicity I will use inline styles to match the backend version precisely */}
<style dangerouslySetInnerHTML={{
__html: `
.landing-container {
background-color: #030712;
color: #f9fafb;
font-family: 'Inter', sans-serif;
}
.bg-glow {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
background:
radial-gradient(circle at 20% 30%, rgba(245, 158, 11, 0.05) 0%, transparent 40%),
radial-gradient(circle at 80% 70%, rgba(239, 68, 68, 0.05) 0%, transparent 40%);
}
.blob {
position: absolute;
width: 400px;
height: 400px;
background: linear-gradient(135deg, #f59e0b, #ef4444);
filter: blur(80px);
opacity: 0.15;
border-radius: 50%;
z-index: 0;
animation: move 20s infinite alternate;
}
@keyframes move {
from { transform: translate(-10%, -10%) scale(1); }
to { transform: translate(10%, 10%) scale(1.1); }
}
.landing-content {
position: relative;
z-index: 10;
max-width: 900px;
animation: fadeInUp 0.8s ease-out;
}
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.logo-text {
font-family: 'Orbitron', sans-serif;
font-size: clamp(3rem, 10vw, 5rem);
font-weight: 700;
background: linear-gradient(135deg, #f59e0b, #ef4444);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
letter-spacing: -2px;
margin-bottom: 0.5rem;
}
.btn-premium {
background: linear-gradient(135deg, #f59e0b, #ef4444);
box-shadow: 0 4px 15px rgba(245, 158, 11, 0.4);
}
.btn-premium:hover {
box-shadow: 0 8px 25px rgba(245, 158, 11, 0.6);
transform: translateY(-3px) scale(1.02);
}
.glass-card {
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.08);
backdrop-filter: blur(10px);
transition: all 0.3s ease;
}
.glass-card:hover {
border-color: rgba(245, 158, 11, 0.3);
background: rgba(255, 255, 255, 0.05);
transform: translateY(-5px);
}
`}} />
<div className="bg-glow" />
<div className="blob" style={{ top: '10%', left: '15%' }} />
<div className="blob" style={{ bottom: '10%', right: '15%', animationDelay: '-5s' }} />
<div className="absolute top-6 right-6 z-20">
<LanguageToggle />
</div>
<div className="landing-content">
<header className="mb-12">
<h1 className="logo-text">DS2API</h1>
<p className="text-gray-400 text-xl max-w-2xl mx-auto leading-relaxed">
DeepSeek to OpenAI & Claude Compatible API Interface
</p>
</header>
<div className="flex flex-wrap gap-4 justify-center mb-16">
<button
onClick={onEnter}
className="btn-premium text-white px-8 py-3 rounded-xl font-bold transition-all flex items-center gap-2"
>
<span>ποΈ</span> {t('landing.adminConsole')}
</button>
<a
href="/v1/models"
target="_blank"
className="glass-card text-white px-8 py-3 rounded-xl font-semibold transition-all flex items-center gap-2"
>
<span>π‘</span> {t('landing.apiStatus')}
</a>
<a
href="https://github.com/CJackHwang/ds2api"
target="_blank"
className="glass-card text-white px-8 py-3 rounded-xl font-semibold transition-all flex items-center gap-2"
>
<span>π¦</span> GitHub
</a>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-6 text-left">
{[
{ icon: 'π', title: t('landing.features.compatibility.title'), desc: t('landing.features.compatibility.desc') },
{ icon: 'βοΈ', title: t('landing.features.loadBalancing.title'), desc: t('landing.features.loadBalancing.desc') },
{ icon: 'π§ ', title: t('landing.features.reasoning.title'), desc: t('landing.features.reasoning.desc') },
{ icon: 'π', title: t('landing.features.search.title'), desc: t('landing.features.search.desc') },
].map((feature, idx) => (
<div key={idx} className="glass-card p-6 rounded-2xl">
<span className="text-2xl mb-4 block">{feature.icon}</span>
<h3 className="text-lg font-bold mb-2">{feature.title}</h3>
<p className="text-sm text-gray-400 leading-relaxed">{feature.desc}</p>
</div>
))}
</div>
<footer className="mt-20 opacity-40 text-sm">
<p>© 2026 DS2API Project. Designed for flexibility & performance.</p>
</footer>
</div>
</div>
)
}
export default LandingPage
|