feat: Complete Fiscal Clone deployment package
- SEC filings extraction (10-K, 10-Q, 8-K) - Portfolio analytics with real-time prices - Watchlist management - NextAuth.js authentication - OpenClaw AI integration - PostgreSQL database with auto P&L calculations - Elysia.js backend (Bun runtime) - Next.js 14 frontend (TailwindCSS + Recharts) - Production-ready Docker configurations
This commit is contained in:
110
frontend/app/page.tsx
Normal file
110
frontend/app/page.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
'use client';
|
||||
|
||||
import { useSession } from 'next-auth/react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function Home() {
|
||||
const { data: session, status } = useSession();
|
||||
const router = useRouter();
|
||||
const [stats, setStats] = useState({ filings: 0, portfolioValue: 0, watchlist: 0 });
|
||||
|
||||
useEffect(() => {
|
||||
if (status === 'unauthenticated') {
|
||||
router.push('/auth/signin');
|
||||
return;
|
||||
}
|
||||
|
||||
if (session?.user) {
|
||||
fetchStats(session.user.id);
|
||||
}
|
||||
}, [session, status, router]);
|
||||
|
||||
const fetchStats = async (userId: string) => {
|
||||
try {
|
||||
const [portfolioRes, watchlistRes, filingsRes] = await Promise.all([
|
||||
fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/portfolio/${userId}/summary`),
|
||||
fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/watchlist/${userId}`),
|
||||
fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/filings`)
|
||||
]);
|
||||
|
||||
const portfolioData = await portfolioRes.json();
|
||||
const watchlistData = await watchlistRes.json();
|
||||
const filingsData = await filingsRes.json();
|
||||
|
||||
setStats({
|
||||
filings: filingsData.length || 0,
|
||||
portfolioValue: portfolioData.total_value || 0,
|
||||
watchlist: watchlistData.length || 0
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching stats:', error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-900 to-slate-800 text-white">
|
||||
<nav className="border-b border-slate-700 bg-slate-900/50 backdrop-blur">
|
||||
<div className="container mx-auto px-4 py-4 flex justify-between items-center">
|
||||
<Link href="/" className="text-2xl font-bold bg-gradient-to-r from-blue-400 to-purple-500 bg-clip-text text-transparent">
|
||||
Fiscal Clone
|
||||
</Link>
|
||||
<div className="flex gap-4">
|
||||
<Link href="/filings" className="hover:text-blue-400 transition">
|
||||
Filings
|
||||
</Link>
|
||||
<Link href="/portfolio" className="hover:text-blue-400 transition">
|
||||
Portfolio
|
||||
</Link>
|
||||
<Link href="/watchlist" className="hover:text-blue-400 transition">
|
||||
Watchlist
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main className="container mx-auto px-4 py-8">
|
||||
<div className="mb-6">
|
||||
<h1 className="text-3xl font-bold">Dashboard</h1>
|
||||
<p className="text-slate-400">Welcome back, {session?.user?.name}</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
|
||||
<div className="bg-slate-800/50 rounded-lg p-6 border border-slate-700">
|
||||
<h3 className="text-slate-400 mb-2">Total Filings</h3>
|
||||
<p className="text-4xl font-bold text-blue-400">{stats.filings}</p>
|
||||
</div>
|
||||
<div className="bg-slate-800/50 rounded-lg p-6 border border-slate-700">
|
||||
<h3 className="text-slate-400 mb-2">Portfolio Value</h3>
|
||||
<p className="text-4xl font-bold text-green-400">
|
||||
${stats.portfolioValue.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-slate-800/50 rounded-lg p-6 border border-slate-700">
|
||||
<h3 className="text-slate-400 mb-2">Watchlist</h3>
|
||||
<p className="text-4xl font-bold text-purple-400">{stats.watchlist}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-slate-800/50 rounded-lg p-6 border border-slate-700">
|
||||
<h2 className="text-xl font-semibold mb-4">Quick Actions</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<Link href="/watchlist/add" className="bg-blue-600 hover:bg-blue-700 text-white px-6 py-3 rounded-lg text-center transition">
|
||||
Add to Watchlist
|
||||
</Link>
|
||||
<Link href="/portfolio" className="bg-green-600 hover:bg-green-700 text-white px-6 py-3 rounded-lg text-center transition">
|
||||
Add to Portfolio
|
||||
</Link>
|
||||
<Link href="/filings" className="bg-slate-700 hover:bg-slate-600 text-white px-6 py-3 rounded-lg text-center transition">
|
||||
Search SEC Filings
|
||||
</Link>
|
||||
<Link href="/portfolio" className="bg-purple-600 hover:bg-purple-700 text-white px-6 py-3 rounded-lg text-center transition">
|
||||
View Portfolio
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user