incr/resources/js/components/Transactions/AddPurchaseForm.tsx
2025-07-13 00:18:45 +02:00

133 lines
No EOL
5.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 } from 'react';
interface PurchaseFormData {
date: string;
shares: string;
price_per_share: string;
total_cost: string;
[key: string]: string;
}
interface AddPurchaseFormProps {
onSuccess?: () => void;
}
export default function AddPurchaseForm({ onSuccess }: AddPurchaseFormProps) {
const { data, setData, post, processing, errors, reset } = useForm<PurchaseFormData>({
date: new Date().toISOString().split('T')[0], // Today's date in YYYY-MM-DD format
shares: '',
price_per_share: '',
total_cost: '',
});
// 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 (
<div className="w-full max-w-md">
<div className="space-y-4">
<form onSubmit={submit} className="space-y-4">
<div>
<Label htmlFor="date" className="text-red-400">Purchase Date</Label>
<Input
id="date"
type="date"
value={data.date}
onChange={(e) => setData('date', e.target.value)}
max={new Date().toISOString().split('T')[0]}
className="bg-black border-red-500/30 text-red-400 focus:border-red-400"
/>
<InputError message={errors.date} />
</div>
<div>
<Label htmlFor="shares" className="text-red-400">Number of Shares</Label>
<Input
id="shares"
type="number"
step="0.000001"
min="0"
placeholder="1.234567"
value={data.shares}
onChange={(e) => setData('shares', e.target.value)}
className="bg-black border-red-500/30 text-red-400 focus:border-red-400 placeholder:text-red-400/30"
/>
<InputError message={errors.shares} />
</div>
<div>
<Label htmlFor="price_per_share" className="text-red-400">Price per Share ()</Label>
<Input
id="price_per_share"
type="number"
step="0.01"
min="0"
placeholder="123.45"
value={data.price_per_share}
onChange={(e) => setData('price_per_share', e.target.value)}
className="bg-black border-red-500/30 text-red-400 focus:border-red-400 placeholder:text-red-400/30"
/>
<InputError message={errors.price_per_share} />
</div>
<div>
<Label htmlFor="total_cost" className="text-red-400">Total Cost ()</Label>
<Input
id="total_cost"
type="number"
step="0.01"
min="0"
placeholder="1234.56"
value={data.total_cost}
onChange={(e) => setData('total_cost', e.target.value)}
className="bg-black border-red-500/30 text-red-400 focus:border-red-400 placeholder:text-red-400/30"
/>
<p className="text-xs text-red-400/60 mt-1">
Auto-calculated from shares × price
</p>
<InputError message={errors.total_cost} />
</div>
<Button
type="submit"
disabled={processing}
className="w-full bg-red-600 hover:bg-red-700 text-white border-red-500"
>
{processing && <LoaderCircle className="mr-2 h-4 w-4 animate-spin" />}
Add Purchase
</Button>
</form>
</div>
</div>
);
}