goldenChat base source add

This commit is contained in:
aidev
2026-05-23 15:11:48 +09:00
commit a4ea7762b5
2081 changed files with 1155760 additions and 0 deletions
+154
View File
@@ -0,0 +1,154 @@
/**
* 서비스 진입 스플래시 — 로그인 또는 게스트 모드로 메인 화면 진입
*/
import React, { useState } from 'react';
import { loginUser, type LoginResponse } from '../utils/backendApi';
const DEFAULT_USERNAME = 'admin';
const DEFAULT_PASSWORD = 'admin';
interface Props {
onLoginSuccess: (res: LoginResponse) => void;
onGuest: () => void;
}
const SplashScreen: React.FC<Props> = ({ onLoginSuccess, onGuest }) => {
const [username, setUsername] = useState(DEFAULT_USERNAME);
const [password, setPassword] = useState(DEFAULT_PASSWORD);
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
const submitLogin = async (e: React.FormEvent) => {
e.preventDefault();
setError(null);
setLoading(true);
try {
const res = await loginUser(username.trim(), password);
onLoginSuccess(res);
} catch (err) {
setError(err instanceof Error ? err.message : '로그인에 실패했습니다.');
} finally {
setLoading(false);
}
};
return (
<div className="splash">
<div className="splash-bg" aria-hidden />
<div className="splash-chart-deco" aria-hidden>
<svg className="splash-chart-svg" viewBox="0 0 400 120" preserveAspectRatio="none">
<defs>
<linearGradient id="splashLineGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#2196f3" stopOpacity="0.2" />
<stop offset="50%" stopColor="#42a5f5" stopOpacity="1" />
<stop offset="100%" stopColor="#ffd54f" stopOpacity="0.8" />
</linearGradient>
</defs>
<path
className="splash-line"
d="M0,90 L40,70 L80,75 L120,45 L160,55 L200,25 L240,40 L280,15 L320,30 L360,10 L400,20"
fill="none"
stroke="url(#splashLineGrad)"
strokeWidth="2.5"
/>
<path
className="splash-area"
d="M0,90 L40,70 L80,75 L120,45 L160,55 L200,25 L240,40 L280,15 L320,30 L360,10 L400,20 L400,120 L0,120 Z"
fill="url(#splashLineGrad)"
opacity="0.12"
/>
</svg>
</div>
<div className="splash-inner">
<header className="splash-brand">
<div className="splash-logo">
<svg width="48" height="48" viewBox="0 0 48 48" fill="none">
<rect width="48" height="48" rx="10" fill="#2196f3" />
<polyline
points="8,32 16,22 24,26 32,14 40,18"
stroke="white"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
/>
</svg>
</div>
<h1 className="splash-title">GoldenChart</h1>
<p className="splash-tagline">
· · ·
</p>
</header>
<ul className="splash-features">
<li><span className="splash-feat-icon">📈</span> ·</li>
<li><span className="splash-feat-icon"></span> &amp; </li>
<li><span className="splash-feat-icon">🔔</span> </li>
<li><span className="splash-feat-icon">🛡</span> · ( )</li>
</ul>
<div className="splash-card">
<h2 className="splash-card-title"></h2>
<p className="splash-card-desc">
. .
</p>
<form className="splash-form" onSubmit={submitLogin}>
<div className="splash-form-row">
<label className="splash-field">
<span></span>
<input
type="text"
autoComplete="username"
value={username}
onChange={e => setUsername(e.target.value)}
disabled={loading}
placeholder="admin"
/>
</label>
<label className="splash-field">
<span></span>
<input
type="text"
autoComplete="off"
className="splash-field--visible"
value={password}
onChange={e => setPassword(e.target.value)}
disabled={loading}
placeholder="••••••"
/>
</label>
</div>
{error && <p className="splash-error">{error}</p>}
<div className="splash-actions">
<button
type="submit"
className="splash-btn splash-btn--primary"
disabled={loading}
>
{loading ? '로그인 중…' : '로그인'}
</button>
<button
type="button"
className="splash-btn splash-btn--guest"
onClick={onGuest}
disabled={loading}
>
</button>
</div>
</form>
<p className="splash-footnote">
: <code>admin</code> / <code>admin</code> ·
</p>
</div>
</div>
<footer className="splash-footer">
<span>GoldenChart Trading Platform</span>
</footer>
</div>
);
};
export default SplashScreen;