Files
SimpleFinanceDash/frontend/src/components/BudgetSetup.tsx
Jean-Luc Makiola 7dfd04f31b feat(06-02): replace BudgetSetup with template-based month picker
- Rewrite BudgetSetup to use month picker + currency + Generate button
- Remove manual form fields (name, dates, carryover, copy-from select)
- Handle 409 conflict gracefully by calling onCreated() to refresh list
- Remove copyFrom method from budgets API (TMPL-06)
- Update BudgetSetup test to reflect new month-picker UI
- Remove copyFrom from DashboardPage test mock
- Add budget.generate, budget.month, budget.generating i18n keys (EN/DE)
- Remove budget.copyFrom and budget.setup i18n keys
2026-03-12 13:08:46 +01:00

62 lines
2.2 KiB
TypeScript

import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Card, CardContent, CardHeader, CardTitle, CardFooter } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Spinner } from '@/components/ui/spinner'
import { budgets as budgetsApi, type Budget, ApiError } from '@/lib/api'
interface Props {
existingBudgets: Budget[]
onCreated: () => void
onCancel: () => void
}
export function BudgetSetup({ existingBudgets: _existingBudgets, onCreated, onCancel }: Props) {
const { t } = useTranslation()
const [month, setMonth] = useState('')
const [currency, setCurrency] = useState('EUR')
const [saving, setSaving] = useState(false)
const handleGenerate = async () => {
setSaving(true)
try {
await budgetsApi.generate({ month, currency })
onCreated()
} catch (err) {
if (err instanceof ApiError && err.status === 409) {
// Budget already exists for this month — navigate to it by refreshing the list
onCreated()
} else {
throw err
}
} finally {
setSaving(false)
}
}
return (
<Card>
<CardHeader className="bg-gradient-to-r from-violet-50 to-purple-50">
<CardTitle>{t('budget.generate')}</CardTitle>
</CardHeader>
<CardContent className="flex flex-col gap-4 pt-4">
<div className="flex flex-col gap-2">
<label className="text-sm font-medium">{t('budget.month')}</label>
<Input type="month" value={month} onChange={(e) => setMonth(e.target.value)} />
</div>
<div className="flex flex-col gap-2">
<label className="text-sm font-medium">{t('budget.currency')}</label>
<Input value={currency} onChange={(e) => setCurrency(e.target.value)} />
</div>
</CardContent>
<CardFooter className="flex gap-2 justify-end">
<Button variant="outline" onClick={onCancel}>{t('common.cancel')}</Button>
<Button onClick={handleGenerate} disabled={saving || !month} className="min-w-[160px]">
{saving ? <Spinner /> : t('budget.generate')}
</Button>
</CardFooter>
</Card>
)
}