From 221a0f879dc28f06aef62625c950463256d163b7 Mon Sep 17 00:00:00 2001 From: myrmidex Date: Sat, 2 May 2026 20:43:41 +0200 Subject: [PATCH] 42 - Extract todayISO() to utils, delete dead AddPurchaseForm --- .../js/components/Pricing/UpdatePriceForm.tsx | 5 +- .../components/Transactions/AddEntryForm.tsx | 7 +- .../Transactions/AddPurchaseForm.tsx | 178 ------------------ resources/js/lib/utils.ts | 2 + 4 files changed, 9 insertions(+), 183 deletions(-) delete mode 100644 resources/js/components/Transactions/AddPurchaseForm.tsx diff --git a/resources/js/components/Pricing/UpdatePriceForm.tsx b/resources/js/components/Pricing/UpdatePriceForm.tsx index 8a99c2b..b88c882 100644 --- a/resources/js/components/Pricing/UpdatePriceForm.tsx +++ b/resources/js/components/Pricing/UpdatePriceForm.tsx @@ -3,6 +3,7 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import InputError from '@/components/InputError'; import { useForm } from '@inertiajs/react'; +import { todayISO } from '@/lib/utils'; import { LoaderCircle } from 'lucide-react'; import { FormEventHandler } from 'react'; import ComponentTitle from '@/components/ui/ComponentTitle'; @@ -22,7 +23,7 @@ interface UpdatePriceFormProps { export default function UpdatePriceForm({ currentPrice, className, onSuccess, onCancel }: UpdatePriceFormProps) { const { data, setData, post, processing, errors } = useForm({ - date: new Date().toISOString().split('T')[0], // Today's date in YYYY-MM-DD format + date: todayISO(), // Today's date in YYYY-MM-DD format price: currentPrice?.toString() || '100.00', }); @@ -60,7 +61,7 @@ export default function UpdatePriceForm({ currentPrice, className, onSuccess, on type="date" value={data.date} onChange={(e) => setData('date', e.target.value)} - max={new Date().toISOString().split('T')[0]} + max={todayISO()} 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 transition-all glow-red" /> diff --git a/resources/js/components/Transactions/AddEntryForm.tsx b/resources/js/components/Transactions/AddEntryForm.tsx index fee5885..3dbb106 100644 --- a/resources/js/components/Transactions/AddEntryForm.tsx +++ b/resources/js/components/Transactions/AddEntryForm.tsx @@ -3,6 +3,7 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import InputError from '@/components/InputError'; import { useForm } from '@inertiajs/react'; +import { todayISO } from '@/lib/utils'; import { LoaderCircle } from 'lucide-react'; import { FormEventHandler, useEffect, useState } from 'react'; import ComponentTitle from '@/components/ui/ComponentTitle'; @@ -30,7 +31,7 @@ interface EntrySummary { export default function AddEntryForm({ unit = 'units', priceTrackingEnabled = false, onSuccess, onCancel }: AddEntryFormProps) { const { data, setData, post, processing, errors, reset } = useForm({ - date: new Date().toISOString().split('T')[0], + date: todayISO(), quantity: '', unit_price: '', total_cost: '', @@ -72,7 +73,7 @@ export default function AddEntryForm({ unit = 'units', priceTrackingEnabled = fa post(route('entries.store'), { onSuccess: () => { reset(); - setData('date', new Date().toISOString().split('T')[0]); + setData('date', todayISO()); if (onSuccess) onSuccess(); }, }); @@ -96,7 +97,7 @@ export default function AddEntryForm({ unit = 'units', priceTrackingEnabled = fa type="date" value={data.date} onChange={(e) => setData('date', e.target.value)} - max={new Date().toISOString().split('T')[0]} + max={todayISO()} 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 transition-all glow-red" /> diff --git a/resources/js/components/Transactions/AddPurchaseForm.tsx b/resources/js/components/Transactions/AddPurchaseForm.tsx deleted file mode 100644 index 94c254b..0000000 --- a/resources/js/components/Transactions/AddPurchaseForm.tsx +++ /dev/null @@ -1,178 +0,0 @@ -import { Button } from '@/components/ui/button'; -import { Input } from '@/components/ui/input'; -import { Label } from '@/components/ui/label'; -import InputError from '@/components/InputError'; -import { useForm } from '@inertiajs/react'; -import { LoaderCircle } from 'lucide-react'; -import { FormEventHandler, useEffect, useState } from 'react'; -import ComponentTitle from '@/components/ui/ComponentTitle'; - -interface PurchaseFormData { - date: string; - shares: string; - price_per_share: string; - total_cost: string; - [key: string]: string; -} - -interface AddPurchaseFormProps { - onSuccess?: () => void; - onCancel?: () => void; -} - -interface PurchaseSummary { - total_shares: number; - total_investment: number; - average_cost_per_share: number; -} - -export default function AddPurchaseForm({ onSuccess, onCancel }: AddPurchaseFormProps) { - const { data, setData, post, processing, errors, reset } = useForm({ - date: new Date().toISOString().split('T')[0], // Today's date in YYYY-MM-DD format - shares: '', - price_per_share: '', - total_cost: '', - }); - - const [currentHoldings, setCurrentHoldings] = useState(null); - - // Load existing holdings data on mount - useEffect(() => { - const fetchCurrentHoldings = async () => { - try { - const response = await fetch('/purchases/summary'); - if (response.ok) { - const summary = await response.json(); - setCurrentHoldings(summary); - } - } catch (error) { - console.error('Failed to fetch current holdings:', error); - } - }; - - fetchCurrentHoldings(); - }, []); - - // Auto-calculate total cost when shares or price changes - useEffect(() => { - if (data.shares && data.price_per_share) { - const shares = parseFloat(data.shares); - const pricePerShare = parseFloat(data.price_per_share); - - if (!isNaN(shares) && !isNaN(pricePerShare)) { - const totalCost = (shares * pricePerShare).toFixed(2); - setData('total_cost', totalCost); - } - } - }, [data.shares, data.price_per_share, setData]); - - const submit: FormEventHandler = (e) => { - e.preventDefault(); - - post(route('purchases.store'), { - onSuccess: () => { - reset(); - setData('date', new Date().toISOString().split('T')[0]); - if (onSuccess) { - onSuccess(); - } - }, - }); - }; - - return ( -
-
- ADD PURCHASE - {currentHoldings && currentHoldings.total_shares > 0 && ( -

- [CURRENT] {currentHoldings.total_shares.toFixed(6)} shares • €{currentHoldings.total_investment.toFixed(2)} invested -

- )} -
-
- - setData('date', e.target.value)} - max={new Date().toISOString().split('T')[0]} - 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 transition-all glow-red" - /> - -
- -
- - setData('shares', 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('price_per_share', 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] shares × price -

- -
- -
- - {onCancel && ( - - )} -
-
-
-
- ); -} diff --git a/resources/js/lib/utils.ts b/resources/js/lib/utils.ts index dd53ea8..f04a0b2 100644 --- a/resources/js/lib/utils.ts +++ b/resources/js/lib/utils.ts @@ -4,3 +4,5 @@ import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } + +export const todayISO = (): string => new Date().toISOString().split('T')[0];