whisper-money/resources/js/components/onboarding/step-import-balances.tsx

125 lines
4.9 KiB
TypeScript

import { StepButton } from '@/components/onboarding/step-button';
import { StepHeader } from '@/components/onboarding/step-header';
import { AmountInput } from '@/components/ui/amount-input';
import { Label } from '@/components/ui/label';
import { CreatedAccount } from '@/hooks/use-onboarding-state';
import { __ } from '@/utils/i18n';
import { AlertCircle, TrendingUp, Wallet } from 'lucide-react';
import { useMemo, useState } from 'react';
interface StepImportBalancesProps {
account: CreatedAccount | undefined;
onComplete: () => void;
}
export function StepImportBalances({
account,
onComplete,
}: StepImportBalancesProps) {
const [balanceInCents, setBalanceInCents] = useState(0);
const [isSubmitting, setIsSubmitting] = useState(false);
const [error, setError] = useState<string | null>(null);
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setError(null);
if (balanceInCents === 0) {
setError(__('Please enter a balance'));
return;
}
setIsSubmitting(true);
try {
// TODO: Save balance to backend
onComplete();
} catch (err) {
console.error('Failed to set balance:', err);
setError(__('Failed to set balance. Please try again.'));
setIsSubmitting(false);
}
}
const description = useMemo(() => {
return account
? __(
'This account tracks balance changes over time instead of individual transactions.',
)
: __('Set the current balance for this account to start tracking.');
}, [account]);
return (
<div className="flex animate-in flex-col items-center duration-500 fade-in slide-in-from-bottom-4">
<StepHeader
icon={TrendingUp}
iconContainerClassName="bg-gradient-to-br from-amber-400 to-orange-500"
title={__('Set Account Balance')}
description={description}
/>
<div className="mb-6 w-full max-w-md rounded-xl border bg-card p-6">
<div className="mb-4 flex items-center gap-3">
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-amber-100 dark:bg-amber-900/30">
<Wallet className="h-5 w-5 text-amber-600 dark:text-amber-400" />
</div>
<div>
<h3 className="font-semibold">
{__('Balance Tracking')}
</h3>
<p className="text-sm text-muted-foreground">
{__(
'Perfect for investment portfolios and retirement\n accounts',
)}
</p>
</div>
</div>
<ul className="space-y-2 text-sm text-muted-foreground">
<li className="flex items-center gap-2">
<div className="h-1.5 w-1.5 rounded-full bg-amber-500" />
{__('Update balances periodically to track growth')}
</li>
<li className="flex items-center gap-2">
<div className="h-1.5 w-1.5 rounded-full bg-amber-500" />
{__('Import balance history from CSV files')}
</li>
<li className="flex items-center gap-2">
<div className="h-1.5 w-1.5 rounded-full bg-amber-500" />
{__('View balance evolution over time')}
</li>
</ul>
</div>
<form onSubmit={handleSubmit} className="w-full max-w-md space-y-4">
<div className="space-y-2">
<Label htmlFor="balance">{__('Current Balance')}</Label>
<AmountInput
id="balance"
value={balanceInCents}
onChange={setBalanceInCents}
currencyCode={account?.currencyCode || 'USD'}
disabled={isSubmitting}
required
/>
</div>
{error && (
<div className="flex items-center gap-2 rounded-lg bg-destructive/10 p-3 text-sm text-destructive">
<AlertCircle className="h-4 w-4 shrink-0" />
{error}
</div>
)}
<StepButton
type="submit"
className="w-full sm:w-full"
text={__('Save Balance')}
loading={isSubmitting}
loadingText={__('Saving...')}
/>
</form>
</div>
);
}