import LedDisplay from '@/components/Display/LedDisplay'; import InlineForm from '@/components/Display/InlineForm'; import ProgressBar from '@/components/Display/ProgressBar'; import StatsBox from '@/components/Display/StatsBox'; import OnboardingFlow from '@/components/Onboarding/OnboardingFlow'; import TerminalSpinner from '@/components/ui/TerminalSpinner'; import { Head } from '@inertiajs/react'; import { useCallback, useEffect, useState } from 'react'; import type { Milestone, Tracker, TrackerAsset } from '@/types/domain'; interface PurchaseSummary { total_shares: number; total_investment: number; average_cost_per_share: number; } interface CurrentPrice { current_price: number | null; } export default function Dashboard() { const [purchaseData, setPurchaseData] = useState({ total_shares: 0, total_investment: 0, average_cost_per_share: 0, }); const [priceData, setPriceData] = useState({ current_price: null, }); const [milestones, setMilestones] = useState([]); const [selectedMilestoneIndex, setSelectedMilestoneIndex] = useState(0); const [showProgressBar, setShowProgressBar] = useState(false); const [showStatsBox, setShowStatsBox] = useState(false); const [activeForm, setActiveForm] = useState<'purchase' | 'milestone' | 'price' | null>(null); const [loading, setLoading] = useState(true); const [needsOnboarding, setNeedsOnboarding] = useState(false); const [tracker, setTracker] = useState(null); const [currentAsset, setCurrentAsset] = useState(null); const [priceTrackingEnabled, setPriceTrackingEnabled] = useState(false); // Fetch entry summary, current price, milestones, and check onboarding useEffect(() => { const fetchData = async () => { try { const [entriesResponse, priceResponse, milestonesResponse, trackerResponse] = await Promise.all([ fetch('/entries/summary'), fetch('/pricing/current'), fetch('/milestones'), fetch('/tracker'), ]); let totalQuantity = 0; let milestonesCount = 0; if (entriesResponse.ok) { const entries = await entriesResponse.json(); setPurchaseData({ total_shares: entries.total_quantity, total_investment: entries.total_cost, average_cost_per_share: entries.average_cost_per_unit, }); totalQuantity = entries.total_quantity; } if (priceResponse.ok) { const price = await priceResponse.json(); setPriceData(price); } if (milestonesResponse.ok) { const milestonesData = await milestonesResponse.json(); setMilestones(milestonesData); milestonesCount = milestonesData.length; } if (trackerResponse.ok) { const trackerData = await trackerResponse.json(); setTracker(trackerData); setCurrentAsset(trackerData?.asset ?? null); setPriceTrackingEnabled(trackerData?.price_tracking_enabled ?? false); } setNeedsOnboarding(totalQuantity === 0 || milestonesCount === 0); } catch (error) { console.error('Failed to fetch data:', error); } finally { setLoading(false); } }; fetchData(); }, []); // Refresh data after successful entry const handlePurchaseSuccess = async () => { try { const entriesResponse = await fetch('/entries/summary'); if (entriesResponse.ok) { const entries = await entriesResponse.json(); setPurchaseData({ total_shares: entries.total_quantity, total_investment: entries.total_cost, average_cost_per_share: entries.average_cost_per_unit, }); } } catch (error) { console.error('Failed to refresh entry data:', error); } }; // Refresh milestones after successful creation const handleMilestoneSuccess = async () => { try { const milestonesResponse = await fetch('/milestones'); if (milestonesResponse.ok) { const milestonesData = await milestonesResponse.json(); setMilestones(milestonesData); // Reset to first milestone when milestones change setSelectedMilestoneIndex(0); } } catch (error) { console.error('Failed to refresh milestone data:', error); } }; // Handle milestone selection const handleMilestoneSelect = (index: number) => { setSelectedMilestoneIndex(index); }; // Refresh price data after successful update const handlePriceSuccess = async () => { try { const priceResponse = await fetch('/pricing/current'); if (priceResponse.ok) { const price = await priceResponse.json(); setPriceData(price); } } catch (error) { console.error('Failed to refresh price data:', error); } }; // Calculate portfolio stats const currentValue = priceData.current_price ? purchaseData.total_shares * priceData.current_price : undefined; const profitLoss = currentValue ? currentValue - purchaseData.total_investment : undefined; const profitLossPercentage = profitLoss && purchaseData.total_investment > 0 ? (profitLoss / purchaseData.total_investment) * 100 : undefined; const statsData = { totalShares: purchaseData.total_shares, totalInvestment: purchaseData.total_investment, averageCostPerShare: purchaseData.average_cost_per_share, currentPrice: priceData.current_price || undefined, currentValue, profitLoss, profitLossPercentage, }; if (loading) { return ( <> ); } // Toggle handlers with cascading behavior const handleLedClick = () => { const newShowProgressBar = !showProgressBar; setShowProgressBar(newShowProgressBar); if (!newShowProgressBar) { // If hiding progress bar, also hide stats box setShowStatsBox(false); } }; const handleProgressClick = () => { setShowStatsBox(!showStatsBox); setActiveForm(null) }; // Handle onboarding completion const handleOnboardingComplete = useCallback(async () => { const [entriesResponse, priceResponse, milestonesResponse, trackerResponse] = await Promise.all([ fetch('/entries/summary'), fetch('/pricing/current'), fetch('/milestones'), fetch('/tracker'), ]); let totalQuantity = 0; let milestonesCount = 0; if (entriesResponse.ok) { const entries = await entriesResponse.json(); setPurchaseData({ total_shares: entries.total_quantity, total_investment: entries.total_cost, average_cost_per_share: entries.average_cost_per_unit, }); totalQuantity = entries.total_quantity; } if (priceResponse.ok) { const price = await priceResponse.json(); setPriceData(price); } if (milestonesResponse.ok) { const milestonesData = await milestonesResponse.json(); setMilestones(milestonesData); milestonesCount = milestonesData.length; } if (trackerResponse.ok) { const tracker = await trackerResponse.json(); setCurrentAsset(tracker?.asset ?? null); setPriceTrackingEnabled(tracker?.price_tracking_enabled ?? false); } setNeedsOnboarding(totalQuantity === 0 || milestonesCount === 0); }, []); // Show onboarding if needed if (needsOnboarding) { return ( <> ); } return ( <> {/* Stacked Layout */}
{/* Box 1: LED Number Display - Fixed position from top */}
{/* Box 2: Progress Bar (toggleable) */}
{/* Box 3: Stats Box (toggleable) */}
setActiveForm('purchase')} onAddMilestone={() => setActiveForm('milestone')} onUpdatePrice={() => setActiveForm('price')} assetSymbol={currentAsset?.symbol} priceTrackingEnabled={priceTrackingEnabled} />
{/* Box 4: Forms (only when active form is set) */}
setActiveForm(null)} onSuccess={(type) => { if (type === 'purchase') handlePurchaseSuccess(); else if (type === 'milestone') handleMilestoneSuccess(); else if (type === 'price') handlePriceSuccess(); }} />
); }