diff --git a/src/components/transactions/CSVUpload.tsx b/src/components/transactions/CSVUpload.tsx index d4f3064..193d88d 100644 --- a/src/components/transactions/CSVUpload.tsx +++ b/src/components/transactions/CSVUpload.tsx @@ -1,6 +1,8 @@ import { useState } from "react"; import { Transaction } from "./Transaction"; import { Alert, Button, Form, Modal } from "react-bootstrap"; +import { writeNewTransactionsBatched } from "../../utils/firestore.ts"; +import { auth } from "../../utils/firebase"; export function CSVUpload({ show, setShow }: { show: boolean, setShow: React.Dispatch> }) { const [error, setError] = useState(); @@ -8,37 +10,36 @@ export function CSVUpload({ show, setShow }: { show: boolean, setShow: React.Dis const reader = new FileReader(); - function handleUpload() { + async function handleUpload() { setError(null); setSuccessMsg(null); - + const fileElement = document.getElementById("file") as HTMLInputElement | null; if (!fileElement || fileElement.files?.length === 0) return setError("You haven't uploaded a CSV file"); const file = fileElement.files![0]; if (!file) return setError("You haven't uploaded a CSV file"); - reader.onload = (event) => { + reader.onload = async (event) => { + if (!auth.currentUser) return setError("You are not signed in"); + const csvContent = event.target?.result; if (!csvContent || csvContent instanceof ArrayBuffer) return setError("Unable to read uploaded CSV file"); - const rows = csvContent + const transactionDocuments = csvContent .split("\n") .slice(1) - .map((row) => row.split(",")); - - const transactions = rows + .map((row) => row.split(",")) .filter((row) => row[3] === "Card payment" || row[3] === "Faster payment") // filter by type - .map((row) => new Transaction().fromRow(row)); + .map((row) => new Transaction().fromRow(row)) + .filter((transaction) => transaction.isValid) + .map((transaction) => transaction.toDocument(auth.currentUser!.uid)); - const validTransactions = transactions.filter((transaction) => transaction.isValid); - if (validTransactions.length === 0) return setError("The uploaded CSV file has no valid transactions"); - - // ------------------------------------------------------------------------------------- - // TODO: STORE "validTransactions" IN THE DATABASE - // ------------------------------------------------------------------------------------- + if (transactionDocuments.length === 0) return setError("The uploaded CSV file has no valid transactions"); + + await writeNewTransactionsBatched(auth.currentUser, transactionDocuments); - setSuccessMsg(`${validTransactions.length} valid transactions have been imported out of ${transactions.length} total transactions`); + setSuccessMsg(`${transactionDocuments.length} transactions have been imported`); setTimeout(() => setSuccessMsg(null), 10000); fileElement.value = ""; diff --git a/src/components/transactions/InputTransaction.tsx b/src/components/transactions/InputTransaction.tsx index 473d7ae..f5485e4 100644 --- a/src/components/transactions/InputTransaction.tsx +++ b/src/components/transactions/InputTransaction.tsx @@ -1,6 +1,8 @@ import { useState } from "react"; import { Transaction, emojis, formatDate, formatTime } from "./Transaction"; import { Button, Modal, Form, Alert } from "react-bootstrap"; +import { auth } from "../../utils/firebase"; +import { writeNewTransaction } from "../../utils/firestore.ts"; export function InputTransaction({ show, setShow}: { show: boolean, setShow: React.Dispatch> }) { const [name, setName] = useState(""); @@ -15,10 +17,12 @@ export function InputTransaction({ show, setShow}: { show: boolean, setShow: Rea const [error, setError] = useState(""); const [successMsg, setSuccessMsg] = useState(""); - function addTransaction() { + async function addTransaction() { setError(null); setSuccessMsg(null); + if (!auth.currentUser) return setError("You are not signed in"); + const date = new Date(); const transaction = new Transaction() @@ -39,9 +43,7 @@ export function InputTransaction({ show, setShow}: { show: boolean, setShow: Rea return; } - // ------------------------------------------------------------------------------------- - // TODO: STORE "transaction" IN THE DATABASE - // ------------------------------------------------------------------------------------- + await writeNewTransaction(auth.currentUser, transaction.toDocument(auth.currentUser.uid)); setSuccessMsg("Transaction has been successfully added"); setTimeout(() => setSuccessMsg(null), 10000); diff --git a/src/components/transactions/Transaction.ts b/src/components/transactions/Transaction.ts index f9a6075..d9c1fa5 100644 --- a/src/components/transactions/Transaction.ts +++ b/src/components/transactions/Transaction.ts @@ -1,3 +1,5 @@ +import { Transaction as TransactionDocument } from "../../utils/firestore.ts"; + export const emojis: { [index: string]: string } = { "Income": "💸", "Transfers": "🏦", @@ -148,6 +150,21 @@ export class Transaction { return this; } + toDocument(uid: string): TransactionDocument { + return new TransactionDocument( + this.address as string, + this.amount as number, + this.category as string, + this.currency as string, + new Date((this.date as string) + (this.time as string)).getTime(), + this.description as string, + this.emoji as string, + this.name as string, + this.notes as string, + uid + ); + } + isNotEmpty(val?: string): val is string { return !!val && val.trim() !== ""; } diff --git a/tsconfig.json b/tsconfig.json index 6138ae3..3743d79 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,10 @@ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + + "baseUrl": ".", + "importHelpers": true }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }]