diff --git a/resources/js/components/Display/InlineForm.tsx b/resources/js/components/Display/InlineForm.tsx index 1536d83..777a09d 100644 --- a/resources/js/components/Display/InlineForm.tsx +++ b/resources/js/components/Display/InlineForm.tsx @@ -1,14 +1,12 @@ import AddEntryForm from '@/components/Transactions/AddEntryForm'; import AddMilestoneForm from '@/components/Milestones/AddMilestoneForm'; -import UpdatePriceForm from '@/components/Pricing/UpdatePriceForm'; import { cn } from '@/lib/utils'; -type FormType = 'purchase' | 'milestone' | 'price'; +type FormType = 'purchase' | 'milestone'; interface InlineFormProps { type: FormType | null; unit?: string; - priceTrackingEnabled?: boolean; onClose: () => void; onSuccess?: (type: FormType) => void; className?: string; @@ -17,7 +15,6 @@ interface InlineFormProps { export default function InlineForm({ type, unit = 'units', - priceTrackingEnabled = false, onClose, onSuccess, className, @@ -42,17 +39,11 @@ export default function InlineForm({ {type === 'purchase' ? ( - ) : type === 'milestone' ? ( - ) : ( - diff --git a/resources/js/components/Display/StatsBox.tsx b/resources/js/components/Display/StatsBox.tsx index db34199..bcc19af 100644 --- a/resources/js/components/Display/StatsBox.tsx +++ b/resources/js/components/Display/StatsBox.tsx @@ -7,12 +7,6 @@ import type { Milestone } from '@/types/domain'; interface StatsBoxProps { stats: { totalShares: number; - totalInvestment: number; - averageCostPerShare: number; - currentPrice?: number; - currentValue?: number; - profitLoss?: number; - profitLossPercentage?: number; }; unit?: string; milestones?: Milestone[]; @@ -21,9 +15,6 @@ interface StatsBoxProps { className?: string; onAddPurchase?: () => void; onAddMilestone?: () => void; - onUpdatePrice?: () => void; - assetSymbol?: string; - priceTrackingEnabled?: boolean; } export default function StatsBox({ @@ -35,9 +26,6 @@ export default function StatsBox({ className, onAddPurchase, onAddMilestone, - onUpdatePrice, - assetSymbol, - priceTrackingEnabled = false, }: StatsBoxProps) { const [isDropdownOpen, setIsDropdownOpen] = useState(false); @@ -46,22 +34,6 @@ export default function StatsBox({ const nextIndex = (selectedMilestoneIndex + 1) % milestones.length; onMilestoneSelect(nextIndex); }; - const formatCurrency = (amount: number) => { - return new Intl.NumberFormat('de-DE', { - style: 'currency', - currency: 'EUR', - minimumFractionDigits: 2, - maximumFractionDigits: 2, - }).format(amount); - }; - - const formatCurrencyDetailed = (amount: number) => { - return new Intl.NumberFormat('de-DE', { - style: 'currency', - currency: 'EUR', - minimumFractionDigits: 4, - }).format(amount); - }; return (
- {/* STATS Title and Current Price */}
Stats
- {priceTrackingEnabled && stats.currentPrice && ( -
- {assetSymbol ?? 'PRICE'}: {formatCurrencyDetailed(stats.currentPrice)} -
- )} - {/* Action Dropdown */}
- {/* Dropdown Menu */} {isDropdownOpen && (
{onAddPurchase && ( @@ -113,22 +77,11 @@ export default function StatsBox({ onAddMilestone(); setIsDropdownOpen(false); }} - className="w-full text-left px-4 py-2 text-red-400 hover:bg-red-600/20 hover:text-red-300 transition-colors transition-colors text-sm font-mono border-b border-red-500/20 last:border-b-0" + className="w-full text-left px-4 py-2 text-red-400 hover:bg-red-600/20 hover:text-red-300 transition-colors text-sm font-mono border-b border-red-500/20 last:border-b-0" > ADD MILESTONE )} - {priceTrackingEnabled && onUpdatePrice && ( - - )}
)}
@@ -146,78 +99,45 @@ export default function StatsBox({
- {/* Milestone Table */} -
-
MILESTONES
-
- - - - - - {priceTrackingEnabled && } - {priceTrackingEnabled && } - - - - {/* Current position row */} - - - - {priceTrackingEnabled && ( - - )} - {priceTrackingEnabled && ( + {/* Milestone Table */} +
+
MILESTONES
+
+
DESCRIPTION{unit.toUpperCase()}SWR 3%SWR 4%
CURRENT - {Math.floor(stats.totalShares).toLocaleString()} - - {stats.currentPrice ? formatCurrency(stats.totalShares * stats.currentPrice * 0.03) : 'N/A'} -
+ + + + + + + + + - )} - + - {/* Render milestones after current */} - {milestones.map((milestone, index) => { - const swr3 = stats.currentPrice ? milestone.target * stats.currentPrice * 0.03 : 0; - const swr4 = stats.currentPrice ? milestone.target * stats.currentPrice * 0.04 : 0; - - const isSelectedMilestone = index === selectedMilestoneIndex; - - return ( + {milestones.map((milestone, index) => ( - - + - {priceTrackingEnabled && ( - - )} - {priceTrackingEnabled && ( - - )} - ); - })} - -
DESCRIPTION{unit.toUpperCase()}
CURRENT - {stats.currentPrice ? formatCurrency(stats.totalShares * stats.currentPrice * 0.04) : 'N/A'} + {Math.floor(stats.totalShares).toLocaleString()}
- {milestone.description} - + {milestone.description} {Math.floor(milestone.target).toLocaleString()} - {stats.currentPrice ? formatCurrency(swr3) : 'N/A'} - - {stats.currentPrice ? formatCurrency(swr4) : 'N/A'} -
+ ))} + + +
-
); } diff --git a/resources/js/components/Onboarding/CreateTrackerStep.tsx b/resources/js/components/Onboarding/CreateTrackerStep.tsx index 2669d19..90491e8 100644 --- a/resources/js/components/Onboarding/CreateTrackerStep.tsx +++ b/resources/js/components/Onboarding/CreateTrackerStep.tsx @@ -7,26 +7,15 @@ import { FormEventHandler, useState } from 'react'; import ComponentTitle from '@/components/ui/ComponentTitle'; interface CreateTrackerStepProps { - onSuccess: (priceTrackingEnabled: boolean) => void; + onSuccess: () => void; } export default function CreateTrackerStep({ onSuccess }: CreateTrackerStepProps) { const [label, setLabel] = useState(''); const [unit, setUnit] = useState(''); - const [priceTracking, setPriceTracking] = useState(false); - const [symbol, setSymbol] = useState(''); - const [fullName, setFullName] = useState(''); const [processing, setProcessing] = useState(false); const [errors, setErrors] = useState>({}); - const togglePriceTracking = (enabled: boolean) => { - setPriceTracking(enabled); - if (!enabled) { - setSymbol(''); - setFullName(''); - } - }; - const submit: FormEventHandler = async (e) => { e.preventDefault(); setProcessing(true); @@ -43,14 +32,12 @@ export default function CreateTrackerStep({ onSuccess }: CreateTrackerStepProps) body: JSON.stringify({ label, unit, - price_tracking_enabled: priceTracking ? 1 : 0, - symbol: priceTracking ? symbol : null, - full_name: priceTracking ? fullName : null, + price_tracking_enabled: 0, }), }); if (response.ok || response.status === 201 || response.status === 409) { - onSuccess(priceTracking); + onSuccess(); } else { const data = await response.json(); if (data.errors) { @@ -111,59 +98,9 @@ export default function CreateTrackerStep({ onSuccess }: CreateTrackerStepProps) -
- -

- Track market price, portfolio value, and P&L. Requires an asset symbol. -

- - {priceTracking && ( -
-
- - setSymbol(e.target.value.toUpperCase())} - className="bg-black border-red-500 text-red-400 focus:border-red-300 font-mono text-sm rounded-none border-2 focus:ring-0 focus:outline-none focus:shadow-[0_0_10px_rgba(239,68,68,0.5)] placeholder:text-red-400/40 transition-all" - /> - -
-
- - setFullName(e.target.value)} - className="bg-black border-red-500 text-red-400 focus:border-red-300 font-mono text-sm rounded-none border-2 focus:ring-0 focus:outline-none focus:shadow-[0_0_10px_rgba(239,68,68,0.5)] placeholder:text-red-400/40 transition-all" - /> - -
-
- )} -
- - )} - - ); -} - interface OnboardingStep { id: string; title: string; @@ -51,13 +11,7 @@ interface OnboardingStep { required: boolean; } -const ASSET_STEPS: OnboardingStep[] = [ - { id: 'entries', title: 'ADD ENTRIES', description: 'Enter your current holdings', completed: false, required: true }, - { id: 'milestones', title: 'SET MILESTONES', description: 'Define your goals', completed: false, required: true }, - { id: 'price', title: 'CURRENT PRICE', description: 'Set current asset price (optional)', completed: false, required: false }, -]; - -const SIMPLE_STEPS: OnboardingStep[] = [ +const STEPS: OnboardingStep[] = [ { id: 'entries', title: 'STARTING AMOUNT', description: 'Enter your starting amount', completed: false, required: true }, { id: 'milestones', title: 'SET MILESTONES', description: 'Define your goals', completed: false, required: true }, ]; @@ -68,7 +22,6 @@ interface OnboardingFlowProps { export default function OnboardingFlow({ onComplete }: OnboardingFlowProps) { const [trackerCreated, setTrackerCreated] = useState(false); - const [priceTracking, setPriceTracking] = useState(false); const [currentStep, setCurrentStep] = useState(0); const [steps, setSteps] = useState([]); @@ -78,7 +31,6 @@ export default function OnboardingFlow({ onComplete }: OnboardingFlowProps) { .then(r => r.ok ? r.json() : null) .then(data => { if (data?.tracker) { - setPriceTracking(data.tracker.price_tracking_enabled ?? false); setTrackerCreated(true); } }) @@ -87,22 +39,19 @@ export default function OnboardingFlow({ onComplete }: OnboardingFlowProps) { const checkOnboardingStatus = useCallback(async (currentSteps: OnboardingStep[]) => { try { - const [entriesData, milestonesData, priceData] = await Promise.all([ + const [entriesData, milestonesData] = await Promise.all([ fetch('/entries/summary').then(r => r.json()), fetch('/milestones').then(r => r.json()), - fetch('/pricing/current').then(r => r.json()), ]); const hasEntries = entriesData.total_quantity > 0; const hasMilestones = milestonesData.length > 0; - const hasPrice = !!priceData.current_price; const freshSteps = currentSteps.map(step => ({ ...step, completed: (step.id === 'entries' && hasEntries) || - (step.id === 'milestones' && hasMilestones) || - (step.id === 'price' && hasPrice), + (step.id === 'milestones' && hasMilestones), })); setSteps(freshSteps); @@ -122,14 +71,12 @@ export default function OnboardingFlow({ onComplete }: OnboardingFlowProps) { useEffect(() => { if (!trackerCreated) return; - const initialSteps = priceTracking ? ASSET_STEPS : SIMPLE_STEPS; - setSteps(initialSteps); + setSteps(STEPS); setCurrentStep(0); - checkOnboardingStatus(initialSteps); - }, [trackerCreated, priceTracking, checkOnboardingStatus]); + checkOnboardingStatus(STEPS); + }, [trackerCreated, checkOnboardingStatus]); - const handleTrackerCreated = (withPriceTracking: boolean) => { - setPriceTracking(withPriceTracking); + const handleTrackerCreated = () => { setTrackerCreated(true); }; @@ -151,11 +98,9 @@ export default function OnboardingFlow({ onComplete }: OnboardingFlowProps) { switch (step.id) { case 'entries': - return ; + return ; case 'milestones': return ; - case 'price': - return {})} />; default: return null; } @@ -194,7 +139,7 @@ export default function OnboardingFlow({ onComplete }: OnboardingFlowProps) { : 'bg-black text-red-400/60 hover:text-red-400 hover:border-red-400' } ${index > 0 ? 'ml-2' : ''}`} > - {step.completed ? '[✓]' : step.required ? '[REQ]' : '[OPT]'} {step.title} + {step.completed ? '[✓]' : '[REQ]'} {step.title} ))} @@ -219,7 +164,7 @@ export default function OnboardingFlow({ onComplete }: OnboardingFlowProps) { [STATUS] {steps.filter(s => s.completed).length}/{steps.length} STEPS COMPLETE

- {steps.filter(s => s.required && !s.completed).length} REQUIRED REMAINING + {steps.filter(s => !s.completed).length} REQUIRED REMAINING

diff --git a/resources/js/components/Transactions/AddEntryForm.tsx b/resources/js/components/Transactions/AddEntryForm.tsx index 3dbb106..ec75cbc 100644 --- a/resources/js/components/Transactions/AddEntryForm.tsx +++ b/resources/js/components/Transactions/AddEntryForm.tsx @@ -11,30 +11,23 @@ import ComponentTitle from '@/components/ui/ComponentTitle'; interface EntryFormData { date: string; quantity: string; - unit_price: string; - total_cost: string; [key: string]: string; } interface AddEntryFormProps { unit?: string; - priceTrackingEnabled?: boolean; onSuccess?: () => void; onCancel?: () => void; } interface EntrySummary { total_quantity: number; - total_cost: number; - average_cost_per_unit: number; } -export default function AddEntryForm({ unit = 'units', priceTrackingEnabled = false, onSuccess, onCancel }: AddEntryFormProps) { +export default function AddEntryForm({ unit = 'units', onSuccess, onCancel }: AddEntryFormProps) { const { data, setData, post, processing, errors, reset } = useForm({ date: todayISO(), quantity: '', - unit_price: '', - total_cost: '', }); const [currentHoldings, setCurrentHoldings] = useState(null); @@ -55,18 +48,6 @@ export default function AddEntryForm({ unit = 'units', priceTrackingEnabled = fa fetchSummary(); }, []); - // Auto-calculate total cost when quantity or unit_price changes - useEffect(() => { - if (data.quantity && data.unit_price) { - const quantity = parseFloat(data.quantity); - const unitPrice = parseFloat(data.unit_price); - - if (!isNaN(quantity) && !isNaN(unitPrice)) { - setData('total_cost', (quantity * unitPrice).toFixed(2)); - } - } - }, [data.quantity, data.unit_price, setData]); - const submit: FormEventHandler = (e) => { e.preventDefault(); @@ -86,7 +67,6 @@ export default function AddEntryForm({ unit = 'units', priceTrackingEnabled = fa {currentHoldings && currentHoldings.total_quantity > 0 && (

[CURRENT] {currentHoldings.total_quantity.toFixed(6)} {unit} - {priceTrackingEnabled && ` • €${currentHoldings.total_cost.toFixed(2)} spent`}

)}
@@ -120,41 +100,6 @@ export default function AddEntryForm({ unit = 'units', priceTrackingEnabled = fa - {priceTrackingEnabled && ( - <> -
- - setData('unit_price', e.target.value)} - className="bg-black border-red-500 text-red-400 focus:border-red-300 font-mono text-sm rounded-none border-2 focus:ring-0 focus:outline-none placeholder:text-red-400/40 transition-all glow-red" - /> - -
- -
- - setData('total_cost', e.target.value)} - className="bg-black border-red-500 text-red-400 focus:border-red-300 font-mono text-sm rounded-none border-2 focus:ring-0 focus:outline-none placeholder:text-red-400/40 transition-all glow-red" - /> -

[AUTO-CALC] quantity × price

- -
- - )} -