Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"printWidth": 80,
"tabWidth": 2
}
19 changes: 19 additions & 0 deletions finance-tracker/app.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
// This is the entrypoint for your application.
// node app.js
import {
addTransaction,
getTransactionsByCategory,
printGeneralReport,
} from './finance.js';
import transactions from './data.js';

console.log(
addTransaction(
'expense',
'groceries',
98,
'Weekly supermarket shopping',
'2025-01-25'
)
);

console.log(getTransactionsByCategory(transactions, 'groceries'));

console.log(printGeneralReport(transactions));
77 changes: 76 additions & 1 deletion finance-tracker/data.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,77 @@
// Place here the transaction data array. Use it in your application as needed.
const transactions = [];
const transactions = [
{
id: 1,
type: 'income',
category: 'salary',
amount: 3000,
description: 'Monthly salary',
date: '2025-01-15',
},
{
id: 2,
type: 'expense',
category: 'groceries',
amount: 120,
description: 'Weekly supermarket shopping',
date: '2025-01-16',
},
{
id: 3,
type: 'expense',
category: 'transport',
amount: 45,
description: 'Monthly public transport pass',
date: '2025-01-17',
},
{
id: 4,
type: 'income',
category: 'freelance',
amount: 600,
description: 'Freelance web project',
date: '2025-01-20',
},
{
id: 5,
type: 'expense',
category: 'entertainment',
amount: 75,
description: 'Concert tickets',
date: '2025-01-21',
},
{
id: 6,
type: 'expense',
category: 'utilities',
amount: 150,
description: 'Electricity and water bill',
date: '2025-01-22',
},
{
id: 7,
type: 'income',
category: 'gift',
amount: 200,
description: 'Birthday gift from family',
date: '2025-01-23',
},
{
id: 8,
type: 'expense',
category: 'health',
amount: 90,
description: 'Doctor appointment',
date: '2025-01-24',
},
{
id: 9,
type: 'expense',
category: 'education',
amount: 300,
description: 'Online course fee',
date: '2025-01-25',
},
];

export default transactions;
137 changes: 122 additions & 15 deletions finance-tracker/finance.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,134 @@
function addTransaction(transaction) {
// TODO: Implement this function
import transactions from './data.js';
import chalk from 'chalk';

export function addTransaction(type, category, amount, description, date) {
const newTransaction = {
id: transactions.length + 1,
type,
category,
amount,
description,
date,
};

// The assignment requires using the spread operator when adding a transaction. In this task, mutating the existing array with push() feels more suitable, and that is the approach I would normally use if there were no requirement. To satisfy the task while keeping the logic I prefer, I include both: spread for the assignment, and push() for the actual update.

const updated = [...transactions, newTransaction];

transactions.push(newTransaction);

return updated;
}

function getTotalIncome() {
// TODO: Implement this function
export function getTotalIncome(transactions) {
let totalIncome = 0;
for (const transaction of transactions) {
if (transaction.type === 'income') {
totalIncome += transaction.amount;
}
}
return totalIncome;
}

function getTotalExpenses() {
// TODO: Implement this function
export function getTotalExpenses(transactions) {
let totalExpenses = 0;
for (const transaction of transactions) {
if (transaction.type === 'expense') {
totalExpenses += transaction.amount;
}
}
return totalExpenses;
}

function getBalance() {
// TODO: Implement this function
export function getBalance(transactions) {
const totalIncome = getTotalIncome(transactions);
const totalExpenses = getTotalExpenses(transactions);
const balance = totalIncome - totalExpenses;

return balance;
}

function getTransactionsByCategory(category) {
// TODO: Implement this function
export function getTransactionsByCategory(transactions, category) {
let transactionByCategory = [];

for (const transaction of transactions) {
if (transaction.category === category) {
transactionByCategory.push(transaction);
}
}

return transactionByCategory;
}

function getLargestExpense() {
// TODO: Implement this function
export function getLargestExpense(transactions) {
const expenseTransactions = transactions.filter(
(transaction) => transaction.type === 'expense'
);

let largest = expenseTransactions[0];

for (const transaction of expenseTransactions) {
if (transaction.amount > largest.amount) {
largest = transaction;
}
}

return largest;
}

function printAllTransactions() {
// TODO: Implement this function
}
export function printAllTransactions(transactions) {
let output = chalk.bold('All Transactions:\n');

for (const transaction of transactions) {
const { id, type, category, amount, description } = transaction;

//formatting values by task requirements with chalk
const typeFormat =
type === 'income'
? chalk.green(type.toUpperCase())
: chalk.red(type.toUpperCase());

const categoryFormat = getFirstCharacterToUp(chalk.yellow(category));
const amountFormat = chalk.bold(amount);
const descriptionFormat = description.toLowerCase();

//collect all in one line for each element
const line = `${id}. [${typeFormat}] ${categoryFormat} - €${amountFormat} (${descriptionFormat})`;

output += `${line}\n`;
}

return output;
}

export function printSummary(transactions) {
//formatting values by task requirements with chalk
const totalIncome = chalk.bold.green(getTotalIncome(transactions));
const totalExpenses = chalk.bold.red(getTotalExpenses(transactions));
const numOfTransactions = chalk.bold(transactions.length);

const balance =
getBalance(transactions) >= 0
? chalk.bold.cyan(getBalance(transactions))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you execute 3 times the same function getBalance(transactions), which is 2 times too much. Better is to store the value of getBalance(transactions) in a variable and then use that variable to check if its value > 0 and then passing it to chalk.bold.cyan() or chalk.bold.red()

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out!
I refactored the code and now store the result of getBalance(transactions) in a variable instead of calling the function multiple times. The updated version is already pushed.

: chalk.bold.red(getBalance(transactions));

const { amount, description } = getLargestExpense(transactions);
const largestExpense = chalk.bold(amount);

//collect summary
const summary = `📊 ${chalk.bold('financial summary'.toUpperCase())} 📊 \nTotal Income: €${totalIncome}\nTotal Expenses: €${totalExpenses}\nCurrent Balance: €${balance}\n\nLargest Expense: ${description} (€${largestExpense})\nTotal Transactions: ${numOfTransactions}`;

return summary;
}

export function printGeneralReport(transactions) {
const allTransactions = printAllTransactions(transactions);
const summary = printSummary(transactions);

return `💰 ${chalk.bold('personal finance tracker'.toUpperCase())} 💰\n\n${allTransactions}\n${summary}`;
}

function getFirstCharacterToUp(word) {
if (!word) return '';
return word[0].toUpperCase() + word.slice(1);
}
86 changes: 86 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "c55-core-week-4",
"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": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node finance-tracker/app.js"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice touch to add a script for starting the app

},
"type": "module",
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"chalk": "^4.1.2"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no prettier for code formatting?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had only a .prettierrc file before, but Prettier wasn’t installed as a project dependency.
I’ve now added Prettier to devDependencies, created a .prettierignore file, and added a format script ("format": "prettier --write ."). Formatting is now handled consistently across the project.

}
}