mirror of
https://github.com/shawnkim1997/All-in-one-Financial-Analysis.git
synced 2026-08-21 14:48:05 +00:00
Complete migration from Streamlit to Next.js 14 App Router + FastAPI backend. Frontend (Next.js 14): - 10 pages: Overview, Research, Valuation, Technical, Markets, Earnings, News, Portfolio, Filings, Settings - Terminal Noir dark theme with custom Tailwind config - TradingView Lightweight Charts for candlestick/volume - Valuation: DCF, Sensitivity Matrix, Monte Carlo, Tornado, Reverse DCF - Financial Statements table with YoY growth badges and margin rows - SEC EDGAR inline filing viewer with section tabs - News split-view with iframe article embedding - Technical Analysis with RSI, MACD, Bollinger, Fibonacci, Moving Averages - Earnings beat/miss visualization - AI Copilot chat panel with Gemini integration Backend (FastAPI): - 13 routers: market_data, financials, valuation, technical, earnings, insider, edgar, news, portfolio, analysis, chat, estimates, fx - Services: DCF engine, Monte Carlo simulation, sensitivity analysis, risk metrics, SEC parser, technical indicators - yfinance + yahooquery data sources with fallback pattern - SQLite caching layer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
93 lines
3.6 KiB
TypeScript
93 lines
3.6 KiB
TypeScript
"use client";
|
|
import { useState, useEffect } from "react";
|
|
|
|
const KEYS = [
|
|
{ id: "atlas_gemini_key", label: "Gemini API Key", placeholder: "AIza..." },
|
|
{ id: "atlas_openai_key", label: "OpenAI API Key", placeholder: "sk-..." },
|
|
{ id: "atlas_anthropic_key", label: "Anthropic API Key", placeholder: "sk-ant-..." },
|
|
];
|
|
|
|
export default function SettingsPage() {
|
|
const [values, setValues] = useState<Record<string, string>>({});
|
|
const [saved, setSaved] = useState(false);
|
|
const [backendStatus, setBackendStatus] = useState<"checking" | "ok" | "error">("checking");
|
|
|
|
useEffect(() => {
|
|
// Load from localStorage
|
|
const loaded: Record<string, string> = {};
|
|
KEYS.forEach((k) => {
|
|
loaded[k.id] = localStorage.getItem(k.id) || "";
|
|
});
|
|
setValues(loaded);
|
|
|
|
// Check backend health
|
|
fetch("/api/health")
|
|
.then((r) => r.ok ? setBackendStatus("ok") : setBackendStatus("error"))
|
|
.catch(() => setBackendStatus("error"));
|
|
}, []);
|
|
|
|
function handleSave() {
|
|
Object.entries(values).forEach(([key, val]) => {
|
|
if (val) localStorage.setItem(key, val);
|
|
else localStorage.removeItem(key);
|
|
});
|
|
setSaved(true);
|
|
setTimeout(() => setSaved(false), 2000);
|
|
}
|
|
|
|
return (
|
|
<div className="max-w-2xl">
|
|
<h1 className="text-2xl font-bold mb-6">Settings</h1>
|
|
|
|
{/* Backend Status */}
|
|
<div className="bg-bg-card border border-border rounded-lg p-4 mb-6">
|
|
<h3 className="text-text-secondary text-sm font-semibold mb-3">System Status</h3>
|
|
<div className="flex items-center gap-3">
|
|
<div className={`w-3 h-3 rounded-full ${backendStatus === "ok" ? "bg-accent-green" : backendStatus === "error" ? "bg-accent-red" : "bg-accent-yellow animate-pulse"}`} />
|
|
<span className="text-text-primary text-sm">
|
|
Backend API: {backendStatus === "ok" ? "Connected" : backendStatus === "error" ? "Disconnected" : "Checking..."}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* API Keys */}
|
|
<div className="bg-bg-card border border-border rounded-lg p-5 mb-6">
|
|
<h3 className="text-text-secondary text-sm font-semibold mb-4">API Keys</h3>
|
|
<div className="space-y-4">
|
|
{KEYS.map((k) => (
|
|
<div key={k.id}>
|
|
<label className="text-text-muted text-sm mb-1.5 block">{k.label}</label>
|
|
<div className="flex items-center gap-3">
|
|
<input
|
|
type="password"
|
|
value={values[k.id] || ""}
|
|
onChange={(e) => setValues({ ...values, [k.id]: e.target.value })}
|
|
placeholder={k.placeholder}
|
|
className="flex-1 bg-bg-primary border border-border rounded-md px-3 py-2 text-text-primary outline-none focus:border-accent-green transition-colors"
|
|
/>
|
|
<div className={`w-2.5 h-2.5 rounded-full ${values[k.id] ? "bg-accent-green" : "bg-text-muted"}`} />
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<button
|
|
onClick={handleSave}
|
|
className="mt-5 bg-accent-green text-bg-primary px-6 py-2 rounded-md font-semibold hover:opacity-90 transition-opacity"
|
|
>
|
|
{saved ? "Saved!" : "Save Keys"}
|
|
</button>
|
|
</div>
|
|
|
|
{/* Info */}
|
|
<div className="bg-bg-card border border-border rounded-lg p-4">
|
|
<h3 className="text-text-secondary text-sm font-semibold mb-2">About</h3>
|
|
<div className="text-text-muted text-sm space-y-1">
|
|
<p>ATLAS Terminal v2.0 — Advanced Trading & Liquidity Analysis System</p>
|
|
<p>API keys are stored locally in your browser. They are never sent to our servers.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|