"use client" import { parseCSVAction, saveTransactionsAction } from "@/app/(app)/import/csv/actions" import { FormError } from "@/components/forms/error" import { Button } from "@/components/ui/button" import { Field } from "@prisma/client" import { Loader2, Play, Upload } from "lucide-react" import { useRouter } from "next/navigation" import { startTransition, useActionState, useEffect, useState } from "react" const MAX_PREVIEW_ROWS = 100 export function ImportCSVTable({ fields }: { fields: Field[] }) { const router = useRouter() const [parseState, parseAction, isParsing] = useActionState(parseCSVAction, null) const [saveState, saveAction, isSaving] = useActionState(saveTransactionsAction, null) const [csvSettings, setCSVSettings] = useState({ skipHeader: true, }) const [csvData, setCSVData] = useState([]) const [columnMappings, setColumnMappings] = useState([]) useEffect(() => { if (parseState?.success && parseState.data) { setCSVData(parseState.data) if (parseState.data.length > 0) { setColumnMappings( parseState.data[0].map((value) => { const field = fields.find((field) => field.code === value || field.name === value) return field?.code || "" }) ) } else { setColumnMappings([]) } } }, [parseState]) useEffect(() => { if (saveState?.success) { router.push("/transactions") } }, [saveState, router]) const handleFileChange = async (event: React.ChangeEvent) => { const file = event.target.files?.[0] if (!file) return const formData = new FormData() formData.append("file", file) startTransition(async () => { await parseAction(formData) }) } const handleMappingChange = (columnIndex: number, fieldCode: string) => { setColumnMappings((prev) => { const state = [...prev] state[columnIndex] = fieldCode return state }) } const handleSave = async () => { if (csvData.length === 0) return if (!isAtLeastOneFieldMapped(columnMappings)) { alert("Please map at least one column to a field") return } const startIndex = csvSettings.skipHeader ? 1 : 0 const processedRows = csvData.slice(startIndex).map((row) => { const processedRow: Record = {} columnMappings.forEach((fieldCode, columnIndex) => { if (!fieldCode || !row[columnIndex]) return processedRow[fieldCode] = row[columnIndex] }) return processedRow }) const formData = new FormData() formData.append("rows", JSON.stringify(processedRows)) startTransition(async () => { await saveAction(formData) }) } return ( <> {csvData.length === 0 && (

Upload your CSV file to import transactions

{parseState?.error && {parseState.error}}
)} {csvData.length > 0 && (

Import {csvData.length} items from CSV

{saveState?.error && {saveState.error}}
{csvData[0].map((_, index) => ( ))} {csvData.slice(0, MAX_PREVIEW_ROWS).map((row, rowIndex) => ( {csvData[0].map((_, colIndex) => ( ))} ))}
{(row[colIndex] || "").toString().slice(0, 256)}
{csvData.length > MAX_PREVIEW_ROWS && (

and {csvData.length - MAX_PREVIEW_ROWS} more entries...

)}
)} ) } function isAtLeastOneFieldMapped(columnMappings: string[]) { return columnMappings.some((mapping) => mapping !== "") }