Files
TaxHacker_s23/components/transactions/create.tsx
Vasily Zubarev 0b98a2c307 (squash) init
feat: filters, settings, backups

fix: ts compile errors

feat: new dashboard, webp previews and settings

feat: use webp for pdfs

feat: use webp

fix: analyze resets old data

fix: switch to corsproxy

fix: switch to free cors

fix: max upload limit

fix: currency conversion

feat: transaction export

fix: currency conversion

feat: refactor settings actions

feat: new loader

feat: README + LICENSE

doc: update readme

doc: update readme

doc: update readme

doc: update screenshots

ci: bump prisma
2025-03-16 21:29:20 +01:00

130 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client"
import { createTransactionAction } from "@/app/transactions/actions"
import { FormSelectCategory } from "@/components/forms/select-category"
import { FormSelectCurrency } from "@/components/forms/select-currency"
import { FormSelectProject } from "@/components/forms/select-project"
import { FormSelectType } from "@/components/forms/select-type"
import { FormInput, FormTextarea } from "@/components/forms/simple"
import { Button } from "@/components/ui/button"
import { Category, Currency, Project } from "@prisma/client"
import { format } from "date-fns"
import { Loader2 } from "lucide-react"
import { useRouter } from "next/navigation"
import { useActionState, useEffect, useState } from "react"
export default function TransactionCreateForm({
categories,
projects,
currencies,
settings,
}: {
categories: Category[]
projects: Project[]
currencies: Currency[]
settings: Record<string, string>
}) {
const router = useRouter()
const [createState, createAction, isCreating] = useActionState(createTransactionAction, null)
const [formData, setFormData] = useState({
name: "",
merchant: "",
description: "",
total: 0.0,
convertedTotal: 0.0,
currencyCode: settings.default_currency,
convertedCurrencyCode: settings.default_currency,
type: settings.default_type,
categoryCode: settings.default_category,
projectCode: settings.default_project,
issuedAt: format(new Date(), "yyyy-MM-dd"),
note: "",
})
useEffect(() => {
if (createState?.success) {
router.push(`/transactions/${createState.transactionId}`)
}
}, [createState, router])
return (
<form action={createAction} className="space-y-4">
<FormInput title="Name" name="name" defaultValue={formData.name} />
<FormInput title="Merchant" name="merchant" defaultValue={formData.merchant} />
<FormInput title="Description" name="description" defaultValue={formData.description} />
<div className="flex flex-row gap-4">
<FormInput title="Total" type="number" step="0.01" name="total" defaultValue={formData.total.toFixed(2)} />
<FormSelectCurrency
title="Currency"
name="currencyCode"
currencies={currencies}
placeholder="Select Currency"
value={formData.currencyCode}
onValueChange={(value) => {
setFormData({ ...formData, currencyCode: value })
}}
/>
<FormSelectType title="Type" name="type" defaultValue={formData.type} />
</div>
{formData.currencyCode !== settings.default_currency ? (
<div className="flex flex-row gap-4">
<FormInput
title={`Converted to ${settings.default_currency}`}
type="number"
step="0.01"
name="convertedTotal"
defaultValue={formData.convertedTotal.toFixed(2)}
/>
</div>
) : (
<></>
)}
<div className="flex flex-row flex-grow gap-4">
<FormInput title="Issued At" type="date" name="issuedAt" defaultValue={formData.issuedAt} />
</div>
<div className="flex flex-row gap-4">
<FormSelectCategory
title="Category"
categories={categories}
name="categoryCode"
defaultValue={formData.categoryCode}
placeholder="Select Category"
/>
<FormSelectProject
title="Project"
projects={projects}
name="projectCode"
defaultValue={formData.projectCode}
placeholder="Select Project"
/>
</div>
<FormTextarea title="Note" name="note" defaultValue={formData.note} />
<div className="flex justify-end space-x-4 pt-6">
<Button type="submit" disabled={isCreating}>
{isCreating ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Creating...
</>
) : (
"Create and Add Files"
)}
</Button>
{createState?.error && <span className="text-red-500"> {createState.error}</span>}
</div>
</form>
)
}