Files
stock-scanner/src/App.js

130 lines
6.1 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from "react";
import { BrowserRouter as Router, Routes, Route, useNavigate } from "react-router-dom";
import axios from "axios";
import Chart from "./components/Chart";
import Scanner from "./components/Scanner";
import Ribbon from "./components/Ribbon";
import SmartMoney from "./components/SmartMoney";
import Popup from "./components/Popup";
import AboutScanner from "./components/AboutScanner";
import MarketIntel from "./components/MarketIntel";
import TrendScanner from "./components/TrendScanner";
import WatchlistManager from "./components/WatchlistManager";
import Login from "./components/Login";
import Signup from "./components/Signup";
import ProtectedRoute from "./components/ProtectedRoute";
import Profile from "./components/Profile";
import MainDashboard from "./components/MainDashboard";
import "./index.css";
function Dashboard() {
const [selectedStock, setSelectedStock] = useState("NSE:RELIANCE");
const [signal, setSignal] = useState(null);
const [view, setView] = useState("dashboard");
const [userProfile, setUserProfile] = useState(null);
const [dropdownOpen, setDropdownOpen] = useState(false);
const [scannerLoaded, setScannerLoaded] = useState(false);
const navigate = useNavigate();
const fetchProfile = () => {
axios.get("/api/auth/me")
.then(res => setUserProfile(res.data))
.catch(err => {
if (err.response?.status === 401) handleLogout();
});
};
useEffect(() => {
fetchProfile();
}, []);
const handleLogout = () => {
localStorage.removeItem("token");
navigate("/login");
};
return (
<div className="app-container">
{/* HEADER */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '2rem', position: 'relative' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
<span style={{ fontSize: '2.5rem' }}>📊</span>
<h1 style={{ margin: 0 }}>Stock Scanner Pro</h1>
</div>
{userProfile && (
<div style={{ position: 'relative' }}>
<div
style={{ display: 'flex', alignItems: 'center', gap: '12px', cursor: 'pointer', background: 'var(--glass-bg)', padding: '8px 16px', borderRadius: '30px', border: '1px solid var(--border-color)', backdropFilter: 'blur(10px)' }}
onClick={() => setDropdownOpen(!dropdownOpen)}
>
<div style={{ width: '35px', height: '35px', borderRadius: '50%', background: 'linear-gradient(135deg, var(--accent-blue), var(--accent-green))', display: 'flex', justifyContent: 'center', alignItems: 'center', fontWeight: 'bold', fontSize: '1.2rem', color: 'white' }}>
{userProfile.display_name ? userProfile.display_name.charAt(0).toUpperCase() : '?'}
</div>
<span style={{ fontWeight: 600 }}>{userProfile.display_name || userProfile.username}</span>
<span style={{ fontSize: '0.8rem', color: 'var(--text-secondary)' }}></span>
</div>
{dropdownOpen && (
<div className="glass-card animate-fade-in" style={{ position: 'absolute', top: '55px', right: '0', width: '220px', zIndex: 100, padding: '10px' }}>
<button className="nav-btn" style={{ width: '100%', marginBottom: '8px', border: 'none', whiteSpace: 'nowrap' }} onClick={() => { setView('profile'); setDropdownOpen(false); }}>
Profile Settings
</button>
<button className="nav-btn" style={{ width: '100%', border: 'none', background: 'var(--accent-red-bg)', color: 'var(--accent-red)', whiteSpace: 'nowrap' }} onClick={handleLogout}>
🚪 Logout
</button>
</div>
)}
</div>
)}
</div>
<div className="nav-container">
<button className={`nav-btn ${view === "dashboard" ? "active" : ""}`} onClick={() => setView("dashboard")} title="Dashboard" style={{ padding: '8px 12px' }}>🏠</button>
<button className={`nav-btn ${view === "scanner" ? "active" : ""}`} onClick={() => setView("scanner")}>📊 Scanner</button>
<button className={`nav-btn ${view === "ribbon" ? "active" : ""}`} onClick={() => setView("ribbon")}>📈 Ribbon Strategy</button>
<button className={`nav-btn ${view === "smartmoney" ? "active" : ""}`} onClick={() => setView("smartmoney")}>🏦 Smart Money</button>
<button className={`nav-btn ${view === "trend" ? "active" : ""}`} onClick={() => setView("trend")}> Trend Analysis</button>
<button className={`nav-btn ${view === "marketintel" ? "active" : ""}`} onClick={() => setView("marketintel")}>📰 Market Intel</button>
<button className={`nav-btn ${view === "watchlists" ? "active" : ""}`} onClick={() => setView("watchlists")}>📋 Watchlists</button>
</div>
<div className="animate-fade-in">
{view === "scanner" && (
<>
<Scanner
onSelectStock={setSelectedStock}
onSignal={setSignal}
/>
<div className="glass-card" style={{ marginTop: "20px" }}>
<h2>TradingView Chart</h2>
<Chart symbol={selectedStock} />
</div>
{signal && <Popup signal={signal} />}
</>
)}
{view === "dashboard" && <MainDashboard userProfile={userProfile} />}
{view === "ribbon" && <Ribbon />}
{view === "smartmoney" && <SmartMoney />}
{view === "marketintel" && <MarketIntel />}
{view === "trend" && <TrendScanner />}
{view === "watchlists" && <WatchlistManager userProfile={userProfile} onProfileUpdated={fetchProfile} />}
{view === "profile" && <Profile userProfile={userProfile} onProfileUpdated={fetchProfile} />}
</div>
</div>
);
}
function App() {
return (
<Router>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
<Route path="/" element={<ProtectedRoute><Dashboard /></ProtectedRoute>} />
</Routes>
</Router>
);
}
export default App;