From 254e454d1c334b8622bfc1160afd9d3497a183fe Mon Sep 17 00:00:00 2001 From: Tis5813 Date: Thu, 5 Feb 2026 21:31:22 +0100 Subject: [PATCH] Completed assignment --- .gitignore => finance-tracker/.gitignore | 0 finance-tracker/.prettierrc | 7 ++ finance-tracker/app.js | 16 ++- finance-tracker/data.js | 44 +++++++- finance-tracker/finance.js | 123 ++++++++++++++++++++--- finance-tracker/package-lock.json | 47 +++++++++ finance-tracker/package.json | 27 +++++ 7 files changed, 245 insertions(+), 19 deletions(-) rename .gitignore => finance-tracker/.gitignore (100%) create mode 100644 finance-tracker/.prettierrc create mode 100644 finance-tracker/package-lock.json create mode 100644 finance-tracker/package.json diff --git a/.gitignore b/finance-tracker/.gitignore similarity index 100% rename from .gitignore rename to finance-tracker/.gitignore diff --git a/finance-tracker/.prettierrc b/finance-tracker/.prettierrc new file mode 100644 index 0000000..787be31 --- /dev/null +++ b/finance-tracker/.prettierrc @@ -0,0 +1,7 @@ +{ + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "es5", + "printWidth": 80 +} \ No newline at end of file diff --git a/finance-tracker/app.js b/finance-tracker/app.js index 7cfcd07..553200d 100644 --- a/finance-tracker/app.js +++ b/finance-tracker/app.js @@ -1,3 +1,15 @@ -// This is the entrypoint for your application. -// node app.js +import { transactions } from './data.js'; +import { addTransaction, printSummary } from './finance.js'; +const initFn = (transactions) => { + addTransaction(transactions, { + id: 6, + type: 'income', + category: 'salary', + amount: 3000, + description: 'Monthly salary', + date: '2025-02-15', + }); + return printSummary(transactions); +}; +console.log(initFn(transactions)); diff --git a/finance-tracker/data.js b/finance-tracker/data.js index d7863ff..9241aa3 100644 --- a/finance-tracker/data.js +++ b/finance-tracker/data.js @@ -1,2 +1,42 @@ -// Place here the transaction data array. Use it in your application as needed. -const transactions = []; \ No newline at end of file +export const transactions = [ + { + id: 1, + type: 'income', + category: 'salary', + amount: 3000, + description: 'Monthly salary', + date: '2025-01-15', + }, + { + id: 2, + type: 'expense', + category: 'housing', + amount: 1200, + description: 'Rent', + date: '2025-01-15', + }, + { + id: 3, + type: 'expense', + category: 'food', + amount: 300, + description: 'Groceries', + date: '2025-01-15', + }, + { + id: 4, + type: 'income', + category: 'side-income', + amount: 500, + description: 'Freelance', + date: '2025-01-15', + }, + { + id: 5, + type: 'expense', + category: 'bills', + amount: 150, + description: 'Utilities', + date: '2025-01-15', + }, +]; diff --git a/finance-tracker/finance.js b/finance-tracker/finance.js index ac2118f..e3b37d8 100644 --- a/finance-tracker/finance.js +++ b/finance-tracker/finance.js @@ -1,27 +1,120 @@ -function addTransaction(transaction) { - // TODO: Implement this function +import chalk from 'chalk'; + +// Return a new array to avoid mutating the original transactions list +function addTransaction(transactions, transaction) { + return [...transactions, transaction]; +} + +function getTotalIncome(transactions) { + let total = 0; + for (const transaction of transactions) { + const { type, amount } = transaction; + if (type === 'income') { + total += amount; + } + } + return total; +} + +function getTotalExpenses(transactions) { + let total = 0; + for (const transaction of transactions) { + const { type, amount } = transaction; + if (type === 'expense') { + total += amount; + } + } + return total; +} + +function getBalance(transactions) { + const totalIncome = getTotalIncome(transactions); + const totalExpenses = getTotalExpenses(transactions); + return totalIncome - totalExpenses; } -function getTotalIncome() { - // TODO: Implement this function +function getTransactionsByCategory(transactions, category) { + const result = []; + for (const transaction of transactions) { + if (transaction.category === category) { + result.push(transaction); + } + } + return result; } -function getTotalExpenses() { - // TODO: Implement this function +function getLargestExpense(transactions) { + let largestExpense = 0; + for (const transaction of transactions) { + const { type, amount } = transaction; + if (type === 'expense' && amount > largestExpense) { + largestExpense = amount; + } + } + return largestExpense; } -function getBalance() { - // TODO: Implement this function +// Uses getLargestExpense, so the array is iterated more than once +function getLargestExpenseDescription(transactions) { + let largestExpenseDescription = ''; + for (const transaction of transactions) { + const { type, amount, description } = transaction; + if (type === 'expense' && amount === getLargestExpense(transactions)) { + largestExpenseDescription = description; + } + } + return largestExpenseDescription; } -function getTransactionsByCategory(category) { - // TODO: Implement this function +function printAllTransactions(transactions) { + let result = ''; + for (const transaction of transactions) { + const { id, type, category, amount, description } = transaction; + const coloredCategory = chalk.yellow(category); + const coloredAmount = + type === 'income' ? chalk.green(amount) : chalk.red(amount); + result += `${id}. [${type.toUpperCase()}] ${coloredCategory[0].toUpperCase() + coloredCategory.slice(1)} - €${coloredAmount} (${description.toLowerCase()}) +`; + } + return result; } -function getLargestExpense() { - // TODO: Implement this function +// Calculations are delegated to helper functions; this function handles formatting only +function printSummary(transactions) { + const totalIncome = chalk.bold.green(getTotalIncome(transactions)); + const totalExpenses = chalk.bold.red(getTotalExpenses(transactions)); + const balance = + getBalance(transactions) >= 0 + ? chalk.bold.cyan(getBalance(transactions)) + : chalk.bold.red(getBalance(transactions)); + const largestExpense = chalk.red(getLargestExpense(transactions)); + const largestExpenseDescription = getLargestExpenseDescription(transactions); + const AllTransactions = printAllTransactions(transactions); + const transactionCount = transactions.length; + return ` +💰 PERSONAL FINANCE TRACKER 💰 + +All Transactions: +${AllTransactions} + +📊 FINANCIAL SUMMARY 📊 +Total Income: €${totalIncome} +Total Expenses: €${totalExpenses} +Current Balance: €${balance} + +Largest Expense: ${largestExpenseDescription} (${largestExpense}) +Total Transactions: ${transactionCount} +`; } -function printAllTransactions() { - // TODO: Implement this function -} \ No newline at end of file +export { + addTransaction, + getTotalIncome, + getTotalExpenses, + getBalance, + getTransactionsByCategory, + getLargestExpense, + getLargestExpenseDescription, + printAllTransactions, + printSummary, +}; diff --git a/finance-tracker/package-lock.json b/finance-tracker/package-lock.json new file mode 100644 index 0000000..0ef2646 --- /dev/null +++ b/finance-tracker/package-lock.json @@ -0,0 +1,47 @@ +{ + "name": "finance-tracker", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "finance-tracker", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "chalk": "^5.6.2" + }, + "devDependencies": { + "prettier": "^3.8.1" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + } + } +} diff --git a/finance-tracker/package.json b/finance-tracker/package.json new file mode 100644 index 0000000..2442ff4 --- /dev/null +++ b/finance-tracker/package.json @@ -0,0 +1,27 @@ +{ + "name": "finance-tracker", + "version": "1.0.0", + "description": "The week 4 assignment for the HackYourFuture Core program can be found at the following link: https://hub.hackyourfuture.nl/core-program-week-4-assignment", + "main": "app.js", + "scripts": { + "start": "node app.js", + "format": "prettier --write ." + }, + "repository": { + "type": "git", + "url": "git+https://github.com/pavel-tisner/c55-core-week-4.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/pavel-tisner/c55-core-week-4/issues" + }, + "homepage": "https://github.com/pavel-tisner/c55-core-week-4#readme", + "dependencies": { + "chalk": "^5.6.2" + }, + "devDependencies": { + "prettier": "^3.8.1" + }, + "type": "module" +}