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 = () => (
);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 (
);
};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 }) => (
);return ({/* KPI Cards */}
{/* Data Summary Table (Mock) */}
);
};// --- Render Logic ---
let content;if (isLoading || !isAuthReady) {
content = ;
} else if (error) {
content = ;
} else {
content = ;
}return (
Connecting to investor network...
Investor Registration
Enter your details to create your personalized investment dashboard.
{title}
{value}
Welcome Back, {data.name}
{data.email}
Investor ID: {userId}
Investment Summary
| Metric | Value |
|---|---|
| Capital Registered | {formatCurrency(data.capital)} |
| Annualized Performance | 12.00% |
| Last Update | {data.lastUpdated ? new Date(data.lastUpdated.seconds * 1000).toLocaleString() : 'N/A'} |
{error}
;
} else if (investorData) {
content =
{content}
);
};export default App;
