diff --git a/resources/js/components/Display/ProgressBar.tsx b/resources/js/components/Display/ProgressBar.tsx index 45c8fcf..05fdf7e 100644 --- a/resources/js/components/Display/ProgressBar.tsx +++ b/resources/js/components/Display/ProgressBar.tsx @@ -9,6 +9,7 @@ interface Milestone { interface ProgressBarProps { currentShares: number; milestones: Milestone[]; + selectedMilestoneIndex?: number; className?: string; onClick?: () => void; } @@ -16,15 +17,18 @@ interface ProgressBarProps { export default function ProgressBar({ currentShares, milestones, + selectedMilestoneIndex = 0, className, onClick }: ProgressBarProps) { - // Get the first milestone (lowest target) for progress calculation - const firstMilestone = milestones.length > 0 ? milestones[0] : null; + // Get the selected milestone for progress calculation + const selectedMilestone = milestones.length > 0 && selectedMilestoneIndex < milestones.length + ? milestones[selectedMilestoneIndex] + : null; // Calculate progress percentage - const progressPercentage = firstMilestone - ? Math.min((currentShares / firstMilestone.target) * 100, 100) + const progressPercentage = selectedMilestone + ? Math.min((currentShares / selectedMilestone.target) * 100, 100) : 0; return (
{/* Text overlay */} - {firstMilestone && ( + {selectedMilestone && (
{/* Base text (red on black background) */}
diff --git a/resources/js/components/Display/StatsBox.tsx b/resources/js/components/Display/StatsBox.tsx index 4d11085..ef690a5 100644 --- a/resources/js/components/Display/StatsBox.tsx +++ b/resources/js/components/Display/StatsBox.tsx @@ -1,5 +1,5 @@ import { cn } from '@/lib/utils'; -import { Plus } from 'lucide-react'; +import { Plus, ChevronRight } from 'lucide-react'; import { useState } from 'react'; interface Milestone { @@ -19,21 +19,31 @@ interface StatsBoxProps { profitLossPercentage?: number; }; milestones?: Milestone[]; + selectedMilestoneIndex?: number; + onMilestoneSelect?: (index: number) => void; className?: string; onAddPurchase?: () => void; onAddMilestone?: () => void; onUpdatePrice?: () => void; } -export default function StatsBox({ - stats, +export default function StatsBox({ + stats, milestones = [], + selectedMilestoneIndex = 0, + onMilestoneSelect, className, onAddPurchase, onAddMilestone, onUpdatePrice }: StatsBoxProps) { const [isDropdownOpen, setIsDropdownOpen] = useState(false); + + const handleCycleMilestone = () => { + if (milestones.length === 0 || !onMilestoneSelect) return; + const nextIndex = (selectedMilestoneIndex + 1) % milestones.length; + onMilestoneSelect(nextIndex); + }; const formatCurrency = (amount: number) => { return new Intl.NumberFormat('de-DE', { style: 'currency', @@ -52,7 +62,7 @@ export default function StatsBox({ }; return ( -
STATS -
+
{stats.currentPrice && (
VWCE: {formatCurrencyDetailed(stats.currentPrice)}
)} - + {/* Action Dropdown */}
- + {/* Dropdown Menu */} {isDropdownOpen && (
@@ -121,6 +131,17 @@ export default function StatsBox({
)}
+ + {/* Milestone Cycle Button */} + {milestones.length > 1 && ( + + )}
@@ -141,28 +162,35 @@ export default function StatsBox({ {/* Create combined array with current position and milestones, sorted by target */} {[ ...milestones.map(m => ({ ...m, isCurrent: false })), - { - target: stats.totalShares, - description: 'CURRENT', - created_at: '', - isCurrent: true + { + target: stats.totalShares, + description: 'CURRENT', + created_at: '', + isCurrent: true } ] .sort((a, b) => a.target - b.target) .map((item, index) => { const swr3 = stats.currentPrice ? item.target * stats.currentPrice * 0.03 : 0; const swr4 = stats.currentPrice ? item.target * stats.currentPrice * 0.04 : 0; - + + // Check if this milestone is the selected one for progress bar + const isSelectedMilestone = !item.isCurrent && milestones.findIndex(m => + m.target === item.target && m.description === item.description + ) === selectedMilestoneIndex; + return ( - = item.target - ? "text-green-400/80" - : "text-red-400/70" + item.isCurrent + ? "bg-red-500/10 text-red-300" + : isSelectedMilestone + ? "bg-blue-500/10 text-blue-300 border-blue-500/30" + : stats.totalShares >= item.target + ? "text-green-400/80" + : "text-red-400/70" )} > @@ -191,4 +219,4 @@ export default function StatsBox({
); -} \ No newline at end of file +} diff --git a/resources/js/pages/dashboard.tsx b/resources/js/pages/dashboard.tsx index 1727698..6753014 100644 --- a/resources/js/pages/dashboard.tsx +++ b/resources/js/pages/dashboard.tsx @@ -33,6 +33,7 @@ export default function Dashboard() { }); 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); @@ -92,12 +93,19 @@ export default function Dashboard() { 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 { @@ -182,6 +190,7 @@ export default function Dashboard() {
@@ -191,6 +200,8 @@ export default function Dashboard() { setActiveForm('purchase')} onAddMilestone={() => setActiveForm('milestone')} onUpdatePrice={() => setActiveForm('price')}