diff --git a/app/client/src/components/AccountForm.tsx b/app/client/src/components/AccountForm.tsx index 02c6c75..7ee8513 100644 --- a/app/client/src/components/AccountForm.tsx +++ b/app/client/src/components/AccountForm.tsx @@ -203,7 +203,7 @@ export default function PopupForm({ name="type" className="formSelect" onChange={(event) => - setAccountType(event.target.value as typeofAccount) + {setAccountType(event.target.value as typeofAccount); setFormInput({ ...formInput, ["subType"]: "" })} } > @@ -229,7 +229,7 @@ export default function PopupForm({ />

- {accountType === accountCategory.SAVING ? ( + {accountType === "SAVINGS" ? ( <>

- {account.type + " " + (account.subtype ? " " + account.subtype : "")} + {accountCategory[account.type as keyof typeof accountCategory] + + " " + + (account.subtype ? " " + account.subtype : "")}

{Number(account.balance).toFixed(2)}

diff --git a/app/client/src/components/SelectAccount.tsx b/app/client/src/components/SelectAccount.tsx index f2efbbf..b542d4a 100644 --- a/app/client/src/components/SelectAccount.tsx +++ b/app/client/src/components/SelectAccount.tsx @@ -1,5 +1,6 @@ import type { Account } from "@/types/AccountType"; import React from "react"; +import { accountCategory } from "@/enum/AccountCategory.ts"; interface selectProp { accounts: Account[]; @@ -26,7 +27,13 @@ export default function SelectAccount({ {accounts && accounts.map((account) => ( ))} diff --git a/app/client/src/enum/AccountCategory.ts b/app/client/src/enum/AccountCategory.ts index b35f4ec..33c4cc2 100644 --- a/app/client/src/enum/AccountCategory.ts +++ b/app/client/src/enum/AccountCategory.ts @@ -1,5 +1,5 @@ export const accountCategory = { - SAVING: "Savings", + SAVINGS: "Savings", CHEQUING: "Chequing", INVESTMENT: "Investment", CREDIT_CARD:"Credit Card", diff --git a/app/client/src/pages/ProjectionPage.tsx b/app/client/src/pages/ProjectionPage.tsx index b520687..1a63e8e 100644 --- a/app/client/src/pages/ProjectionPage.tsx +++ b/app/client/src/pages/ProjectionPage.tsx @@ -24,7 +24,11 @@ import { import ProjectionGraph from "@/components/ProjectionGraph"; import { TbGraph } from "react-icons/tb"; import NoItemState from "@/components/NoItemState"; -import { handleCurrencyChange, handleCurrencyBlur } from "@/utils/handleInput"; +import { + handleCurrencyChange, + handleCurrencyBlur, + handleNumberChange, +} from "@/utils/handleInput"; import type { projectionDebtRequest, projectionSavingRequest, @@ -106,7 +110,7 @@ function ProjectionPage({ session }: ProjectionProp) { category: accountCategory.CREDIT_CARD, remainingAmount: inputAmount, minimumPayment: inputMinPay, - interestRate: inputInterest / 100, + interestRate: inputInterest, nextDueDate: nextDueDate, period: inputPeriod, }; @@ -163,7 +167,7 @@ function ProjectionPage({ session }: ProjectionProp) { financial_account_id: selectedAccount, balance: inputAmount, monthly_deposit: inputMinPay, - annual_interest_rate: inputInterest / 100, + annual_interest_rate: inputInterest, time_frame: inputPeriod, }; @@ -233,7 +237,7 @@ function ProjectionPage({ session }: ProjectionProp) { if (savingRequest) { //Assigns the fields to what the projection of the saving account used setSelectedAccount(savingRequest.financial_account_id); - setAmount(savingRequest.balance.toFixed(2)); + setAmount((savingRequest.balance * 100).toFixed(2)); setInterest(savingRequest.annual_interest_rate.toString()); setMinPay(savingRequest.monthly_deposit.toFixed(2)); setPeriod(savingRequest.time_frame.toString()); @@ -270,36 +274,6 @@ function ProjectionPage({ session }: ProjectionProp) { } }; - //Handles on change of percentage - const handleNumberChange = ( - event: React.ChangeEvent, - setNumber: React.Dispatch>, - min: number, - max: number, - ) => { - let input = event.target.value; - let changeInterest; - const pattern = /^\d*\.?\d{0,2}$/; - - console.log(input); - console.log(pattern.test(input)); - - //Determine if the input follows the format/pattern - if (pattern.test(input) || input === "") { - input = input.replace(/^0+(?=\d)/, ""); - changeInterest = Number(input); - - if (changeInterest > max) { - changeInterest = max; - } - - if (changeInterest < min) { - changeInterest = min; - } - console.log(changeInterest); - setNumber(changeInterest.toString()); - } - }; //Get the saving accounts useEffect(() => { if (selectedType === "Saving") { diff --git a/app/client/src/utils/handleInput.ts b/app/client/src/utils/handleInput.ts index 7d05c0b..0b0a071 100644 --- a/app/client/src/utils/handleInput.ts +++ b/app/client/src/utils/handleInput.ts @@ -26,3 +26,34 @@ export const handleCurrencyBlur = ( setCurrency(parseFloat(currency).toFixed(2)); } }; + +//Handles on change of whole numbers +export const handleNumberChange = ( + event: React.ChangeEvent, + setNumber: React.Dispatch>, + min: number, + max: number, +) => { + let input = event.target.value; + let changeNumber; + const pattern = /^\d*\.?\d{0,2}$/; + + console.log(input); + console.log(pattern.test(input)); + + //Determine if the input follows the format/pattern + if (pattern.test(input) || input === "") { + input = input.replace(/^0+(?=\d)/, ""); + changeNumber = Number(input); + + if (changeNumber > max) { + changeNumber = max; + } + + if (changeNumber < min) { + changeNumber = min; + } + console.log(changeNumber); + setNumber(changeNumber.toString()); + } +}; diff --git a/app/client/test/handleInput.test.ts b/app/client/test/handleInput.test.ts index 5a59393..9fe8da4 100644 --- a/app/client/test/handleInput.test.ts +++ b/app/client/test/handleInput.test.ts @@ -2,6 +2,7 @@ import { describe, it, expect, vi } from "vitest"; import { handleCurrencyChange, handleCurrencyBlur, + handleNumberChange, } from "../src/utils/handleInput"; //tests for handleCurrencyChange and handleCurrencyBlur functions function mockEvent(value: string) { @@ -135,3 +136,68 @@ it("does not strip zeros inside the number", () => { expect(setCurrency).toHaveBeenCalledWith("101"); }); + +describe("handleNumberChange", () => { + it("accepts valid number input", () => { + const setNumber = vi.fn(); + const event = mockEvent("12"); + + handleNumberChange(event, setNumber, 0, 100); + + expect(setNumber).toHaveBeenCalledWith("12"); + }); + + it("Doesn't accept decimals", () => { + const setNumber = vi.fn(); + const event = mockEvent("12."); + + handleNumberChange(event, setNumber, 0, 100); + + expect(setNumber).not.toHaveBeenCalledWith(); + }); + + it("Empty string", () => { + const setNumber = vi.fn(); + const event = mockEvent(""); + + handleNumberChange(event, setNumber, 0, 100); + + expect(setNumber).toHaveBeenCalledWith(""); + }); + + it("strip leading 0s", () => { + const setNumber = vi.fn(); + const event = mockEvent("0000123"); + + handleNumberChange(event, setNumber, 0, 100); + + expect(setNumber).toHaveBeenCalledWith("123"); + }); + + it("rejects letters in input", () => { + const setNumber = vi.fn(); + const event = mockEvent("12A"); + + handleNumberChange(event, setNumber, 0, 100); + + expect(setNumber).not.toHaveBeenCalledWith(); + }); + + it("Sets the value to the maximum", () => { + const setNumber = vi.fn(); + const event = mockEvent("120"); + + handleNumberChange(event, setNumber, 0, 100); + + expect(setNumber).not.toHaveBeenCalledWith("100"); + }); + + it("Sets value to the minimum", () => { + const setNumber = vi.fn(); + const event = mockEvent("1"); + + handleNumberChange(event, setNumber, 10, 100); + + expect(setNumber).not.toHaveBeenCalledWith("10"); + }); +}); diff --git a/app/server/services/ts/user/src/index.ts b/app/server/services/ts/user/src/index.ts index 5017b71..451824c 100644 --- a/app/server/services/ts/user/src/index.ts +++ b/app/server/services/ts/user/src/index.ts @@ -58,6 +58,7 @@ process.on("SIGTERM", () => cleanup); app.get("/charts/expenses", async (req, res) => { process.on("SIGTERM", () => server.close()); +}) app.get( "/charts/expenses", diff --git a/app/server/services/ts/user/src/queries/debt.ts b/app/server/services/ts/user/src/queries/debt.ts index e9fb460..f331795 100644 --- a/app/server/services/ts/user/src/queries/debt.ts +++ b/app/server/services/ts/user/src/queries/debt.ts @@ -13,7 +13,7 @@ export async function findDebtsBy(db: Pool, userId: string) : Promise