import React, { useState, useEffect, useCallback } from 'react'; import { initializeApp } from 'firebase/app'; import { getAuth, signInAnonymously, signInWithCustomToken, onAuthStateChanged } from 'firebase/auth'; import { getFirestore, doc, setDoc, onSnapshot, getDoc } from 'firebase/firestore';// --- Firebase Configuration & Globals --- // Mandatory environment variables provided by the Canvas platform const appId = typeof __app_id !== 'undefined' ? __app_id : 'investor-dashboard-app'; const firebaseConfig = typeof __firebase_config !== 'undefined' ? JSON.parse(__firebase_config) : {}; const initialAuthToken = typeof __initial_auth_token !== 'undefined' ? __initial_auth_token : null;// Utility for currency formatting const formatCurrency = (amount) => { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 2, }).format(amount); };// --- Main Application Component --- const App = () => { const [db, setDb] = useState(null); const [auth, setAuth] = useState(null); const [userId, setUserId] = useState(null); const [isAuthReady, setIsAuthReady] = useState(false); const [investorData, setInvestorData] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null);// 1. Firebase Initialization and Authentication useEffect(() => { try { const app = initializeApp(firebaseConfig); const firestore = getFirestore(app); const authInstance = getAuth(app); setDb(firestore); setAuth(authInstance);// Authentication Listener const unsubscribe = onAuthStateChanged(authInstance, async (user) => { if (user) { setUserId(user.uid); } else { // Sign in anonymously if no token is available (for development/testing) if (initialAuthToken) { await signInWithCustomToken(authInstance, initialAuthToken); } else { await signInAnonymously(authInstance); } } setIsAuthReady(true); });return () => unsubscribe(); } catch (e) { console.error("Firebase Initialization Error:", e); setError("Failed to initialize the application."); setIsAuthReady(true); setIsLoading(false); } }, []);// 2. Real-time Data Listener (onSnapshot) useEffect(() => { if (!isAuthReady || !db || !userId) return;// Path for the private investor profile document // /artifacts/{appId}/users/{userId}/investor_data/profile const investorDocRef = doc(db, 'artifacts', appId, 'users', userId, 'investor_data', 'profile'); // Listen for real-time changes const unsubscribe = onSnapshot(investorDocRef, (docSnap) => { if (docSnap.exists()) { const data = docSnap.data(); setInvestorData(data); } else { setInvestorData(null); // Profile does not exist (needs registration) } setIsLoading(false); setError(null); }, (e) => { console.error("Firestore Snapshot Error:", e); setError("Could not load investor data."); setIsLoading(false); });return () => unsubscribe(); }, [db, userId, isAuthReady]); // Dependencies include initialized state and user ID// --- Components / Views ---const LoadingView = () => (

Connecting to investor network...

);const LoginView = () => { const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [capital, setCapital] = useState(''); const [isSubmitting, setIsSubmitting] = useState(false); const [formError, setFormError] = useState(null);const handleSubmit = async (e) => { e.preventDefault(); setFormError(null); const numericCapital = parseFloat(capital);if (!name || !email || isNaN(numericCapital) || numericCapital <= 0) { setFormError('Please enter a valid name, email, and a positive capital amount.'); return; }if (!db || !userId) { setFormError('Application is still loading. Please try again in a moment.'); return; }setIsSubmitting(true);try { // Path: /artifacts/{appId}/users/{userId}/investor_data/profile const investorDocRef = doc(db, 'artifacts', appId, 'users', userId, 'investor_data', 'profile'); await setDoc(investorDocRef, { name: name.trim(), email: email.trim(), capital: numericCapital, lastUpdated: new Date(), userId: userId, // Store the ID for cross-reference/debugging }, { merge: false }); // Overwrite the document if it exists// The onSnapshot listener will automatically update the UI to DashboardView } catch (error) { console.error("Error submitting profile:", error); setFormError("Failed to save investor profile. Please check your inputs."); } finally { setIsSubmitting(false); } };return (

Investor Registration

Enter your details to create your personalized investment dashboard.

setName(e.target.value)} className="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:ring-indigo-500 focus:border-indigo-500 transition duration-150 ease-in-out" placeholder="John Doe" required />
setEmail(e.target.value)} className="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:ring-indigo-500 focus:border-indigo-500 transition duration-150 ease-in-out" placeholder="john.doe@investor.com" required />
setCapital(e.target.value)} className="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:ring-indigo-500 focus:border-indigo-500 transition duration-150 ease-in-out" placeholder="e.g., 500000" min="1" step="0.01" required />
{formError && (

{formError}

)}

User ID: {userId || 'Authenticating...'}

); };const DashboardView = ({ data }) => { // Mock data for demonstration purposes, as updates aren't implemented in this view const currentReturn = (data.capital * 0.12).toFixed(2); const currentValue = (data.capital + parseFloat(currentReturn)).toFixed(2); const StatCard = ({ title, value, color }) => (

{title}

{value}

);return (

Welcome Back, {data.name}

{data.email}

Investor ID: {userId}

{/* KPI Cards */}
{/* Data Summary Table (Mock) */}

Investment Summary

MetricValue
Capital Registered{formatCurrency(data.capital)}
Annualized Performance12.00%
Last Update {data.lastUpdated ? new Date(data.lastUpdated.seconds * 1000).toLocaleString() : 'N/A'}
); };// --- Render Logic --- let content;if (isLoading || !isAuthReady) { content = ; } else if (error) { content =
{error}
; } else if (investorData) { content = ; } else { content = ; }return (
{content}
); };export default App;