"use client" import { useNotification } from "@/app/(app)/context" import { analyzeFileAction, deleteUnsortedFileAction, saveFileAsTransactionAction } from "@/app/(app)/unsorted/actions" import { FormConvertCurrency } from "@/components/forms/convert-currency" import { FormError } from "@/components/forms/error" 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, Field, File, Project } from "@/prisma/client" import { format } from "date-fns" import { Brain, Loader2 } from "lucide-react" import { startTransition, useActionState, useMemo, useState } from "react" import AgentWindow from "../agents/agent-window" export default function AnalyzeForm({ file, categories, projects, currencies, fields, settings, }: { file: File categories: Category[] projects: Project[] currencies: Currency[] fields: Field[] settings: Record }) { const { showNotification } = useNotification() const [isAnalyzing, setIsAnalyzing] = useState(false) const [analyzeStep, setAnalyzeStep] = useState("") const [analyzeError, setAnalyzeError] = useState("") const [deleteState, deleteAction, isDeleting] = useActionState(deleteUnsortedFileAction, null) const [isSaving, setIsSaving] = useState(false) const [saveError, setSaveError] = useState("") const fieldMap = useMemo(() => { return fields.reduce( (acc, field) => { acc[field.code] = field return acc }, {} as Record ) }, [fields]) const extraFields = useMemo(() => fields.filter((field) => field.isExtra), [fields]) const initialFormState = useMemo( () => ({ name: file.filename, merchant: "", description: "", type: settings.default_type, total: 0.0, currencyCode: settings.default_currency, convertedTotal: 0.0, convertedCurrencyCode: settings.default_currency, categoryCode: settings.default_category, projectCode: settings.default_project, issuedAt: "", note: "", text: "", ...extraFields.reduce( (acc, field) => { acc[field.code] = "" return acc }, {} as Record ), }), [file.filename, settings, extraFields] ) const [formData, setFormData] = useState(initialFormState) async function saveAsTransaction(formData: FormData) { setSaveError("") setIsSaving(true) startTransition(async () => { const result = await saveFileAsTransactionAction(null, formData) setIsSaving(false) if (result.success) { showNotification({ code: "sidebar.transactions", message: "new" }) setTimeout(() => showNotification({ code: "sidebar.transactions", message: "" }), 3000) } else { setSaveError(result.error ? result.error : "Something went wrong...") } }) } const startAnalyze = async () => { setIsAnalyzing(true) setAnalyzeError("") try { setAnalyzeStep("Analyzing...") const results = await analyzeFileAction(file, settings, fields, categories, projects) console.log("Analysis results:", results) if (!results.success) { setAnalyzeError(results.error ? results.error : "Something went wrong...") } else { const nonEmptyFields = Object.fromEntries( Object.entries(results.data?.output || {}).filter( ([_, value]) => value !== null && value !== undefined && value !== "" ) ) setFormData({ ...formData, ...nonEmptyFields }) } } catch (error) { console.error("Analysis failed:", error) setAnalyzeError(error instanceof Error ? error.message : "Analysis failed") } finally { setIsAnalyzing(false) setAnalyzeStep("") } } return ( <> {analyzeError && ⚠️ {analyzeError}}
setFormData((prev) => ({ ...prev, name: e.target.value }))} required={true} /> setFormData((prev) => ({ ...prev, merchant: e.target.value }))} hideIfEmpty={!fieldMap.merchant.isVisibleInAnalysis} /> setFormData((prev) => ({ ...prev, description: e.target.value }))} hideIfEmpty={!fieldMap.description.isVisibleInAnalysis} />
{ const newValue = parseFloat(e.target.value || "0") !isNaN(newValue) && setFormData((prev) => ({ ...prev, total: newValue })) }} className="w-32" required={true} /> setFormData((prev) => ({ ...prev, currencyCode: value }))} hideIfEmpty={!fieldMap.currencyCode.isVisibleInAnalysis} /> setFormData((prev) => ({ ...prev, type: value }))} hideIfEmpty={!fieldMap.type.isVisibleInAnalysis} />
{formData.total != 0 && formData.currencyCode && formData.currencyCode !== settings.default_currency && ( setFormData((prev) => ({ ...prev, convertedTotal: value }))} /> )}
setFormData((prev) => ({ ...prev, issuedAt: e.target.value }))} hideIfEmpty={!fieldMap.issuedAt.isVisibleInAnalysis} />
setFormData((prev) => ({ ...prev, categoryCode: value }))} placeholder="Select Category" hideIfEmpty={!fieldMap.categoryCode.isVisibleInAnalysis} /> {projects.length > 0 && ( setFormData((prev) => ({ ...prev, projectCode: value }))} placeholder="Select Project" hideIfEmpty={!fieldMap.projectCode.isVisibleInAnalysis} /> )}
setFormData((prev) => ({ ...prev, note: e.target.value }))} hideIfEmpty={!fieldMap.note.isVisibleInAnalysis} /> {extraFields.map((field) => ( setFormData((prev) => ({ ...prev, [field.code]: e.target.value }))} hideIfEmpty={!field.isVisibleInAnalysis} /> ))}
setFormData((prev) => ({ ...prev, text: e.target.value }))} hideIfEmpty={!fieldMap.text.isVisibleInAnalysis} />
{deleteState?.error && ⚠️ {deleteState.error}} {saveError && ⚠️ {saveError}}
) }