Conversation
There was a problem hiding this comment.
Pull request overview
Adds a Rust-based CLI “Expense Tracker” submission under submissions/week-2/day-5, including the core data model, tracker logic, and a sample saved output file.
Changes:
- Introduces a CLI menu to add/view/update/delete expenses and save them to a text file on exit.
- Implements an
ExpenseTrackerbacked by aHashMapplusExpense/TransactionTypetypes. - Adds Rust project scaffolding (
Cargo.toml,Cargo.lock,.gitignore) and a samplestephen_expences.txt.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 19 comments.
Show a summary per file
| File | Description |
|---|---|
| submissions/week-2/day-5/Stephen-Ngozi-Merkle-Tree/src/main.rs | CLI menu, input parsing, and calling tracker operations + save-on-quit |
| submissions/week-2/day-5/Stephen-Ngozi-Merkle-Tree/src/tracker.rs | Core CRUD logic and file persistence |
| submissions/week-2/day-5/Stephen-Ngozi-Merkle-Tree/src/expense.rs | Expense and transaction type definitions |
| submissions/week-2/day-5/Stephen-Ngozi-Merkle-Tree/Cargo.toml | Rust package configuration |
| submissions/week-2/day-5/Stephen-Ngozi-Merkle-Tree/Cargo.lock | Cargo lockfile |
| submissions/week-2/day-5/Stephen-Ngozi-Merkle-Tree/.gitignore | Ignores /target |
| submissions/week-2/day-5/Stephen-Ngozi-Merkle-Tree/stephen_expences.txt | Sample persisted expense output |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| tracker.save_to_file("stephen_expences.txt"); | ||
| println!("Data saved to stephen_expences.txt"); |
There was a problem hiding this comment.
The filename "stephen_expences.txt" contains a spelling error ("expences"). Consider renaming to "stephen_expenses.txt" (and updating the checked-in file name) to avoid confusion.
| tracker.save_to_file("stephen_expences.txt"); | |
| println!("Data saved to stephen_expences.txt"); | |
| tracker.save_to_file("stephen_expenses.txt"); | |
| println!("Data saved to stephen_expenses.txt"); |
| println!("ID: {} | Name: {} | Amount: Naria{:.2} | Type: {:?}", | ||
| expense.id, expense.name, expense.amount, expense.tx_type); | ||
| } |
There was a problem hiding this comment.
"Naria" appears to be a misspelling of the currency name "Naira". Fixing the string will make output clearer.
| println!("Enter the ID of the Expence"); | ||
|
|
There was a problem hiding this comment.
Prompt text uses "Expence" instead of "Expense".
| pub struct ExpenseTracker { | ||
| pub values: HashMap<u8, Expense>, | ||
| pub next_id: u8, | ||
| } |
There was a problem hiding this comment.
Using u8 for IDs means next_id will overflow after 255 expenses (panic in debug builds, wrap in release), which can lead to duplicate IDs and lost data. Use a larger type (e.g., u32/u64/usize) and/or handle overflow explicitly.
| [package] | ||
| name = "Stephen-Ngozi-Merkle-Tree" | ||
| version = "0.1.0" | ||
| edition = "2024" |
There was a problem hiding this comment.
The submission is described as an Expense Tracker, but the crate/package name is "Stephen-Ngozi-Merkle-Tree", which is confusing and suggests a different project. Consider renaming the package (and folder) to match the task (e.g., expense_tracker) to avoid confusion when building/running multiple submissions.
| let mut tx_input = String::new(); | ||
| io::stdin().read_line(&mut tx_input).expect("Failed to read input"); | ||
| let tx_input = tx_input.trim(); | ||
|
|
||
| let tx_type = if tx_input == "c" { | ||
| TransactionType::Credit | ||
| } else { | ||
| TransactionType::Debit |
There was a problem hiding this comment.
In the update flow, any transaction type input other than "c" becomes Debit, which can record the wrong transaction type. Add validation/re-prompt for "c" or "d" (case-insensitive).
| let mut tx_input = String::new(); | |
| io::stdin().read_line(&mut tx_input).expect("Failed to read input"); | |
| let tx_input = tx_input.trim(); | |
| let tx_type = if tx_input == "c" { | |
| TransactionType::Credit | |
| } else { | |
| TransactionType::Debit | |
| let tx_type = loop { | |
| let mut tx_input = String::new(); | |
| io::stdin().read_line(&mut tx_input).expect("Failed to read input"); | |
| let tx_input = tx_input.trim().to_lowercase(); | |
| match tx_input.as_str() { | |
| "c" => break TransactionType::Credit, | |
| "d" => break TransactionType::Debit, | |
| _ => { | |
| println!("Invalid transaction type. Please enter 'c' for Credit or 'd' for Debit:"); | |
| } | |
| } |
| let id: u8 = id_input.trim().parse().expect("Please enter a valid ID"); | ||
|
|
||
| if tracker.delete(id){ | ||
| println!(" Your Expence is Deleted "); |
There was a problem hiding this comment.
Delete confirmation message uses "Expence" instead of "Expense".
| println!(" Your Expence is Deleted "); | |
| println!(" Your Expense is Deleted "); |
| pub struct ExpenseTracker { | ||
| pub values: HashMap<u8, Expense>, | ||
| pub next_id: u8, | ||
| } |
There was a problem hiding this comment.
values and next_id are public, which exposes internal state (and allows callers to mutate/replace entries without invariants). Prefer keeping fields private and providing methods like get(id)/iter() for read access.
| if tracker.update(id, amount, tx_type){ | ||
| println!("Expense Updated Successfu"); | ||
|
|
||
| if let Some(expense) = tracker.values.get(&id) { | ||
| println!("ID: {}, Name: {}, Amount: Naria{:.2}, Type: {:?}", |
There was a problem hiding this comment.
If tracker.update(...) returns false (ID not found), the program prints nothing and returns to the menu. Add an else branch to inform the user that the ID was not found.
| @@ -0,0 +1,84 @@ | |||
| use std::{collections::HashMap,fs::File,io::Write}; | |||
There was a problem hiding this comment.
The import list is missing standard spacing after commas (HashMap,fs::File,io::Write), which will fail rustfmt/linting if enabled. Run cargo fmt or fix spacing.
| use std::{collections::HashMap,fs::File,io::Write}; | |
| use std::{collections::HashMap, fs::File, io::Write}; |
Task Submission PR
Student Info:
Task Details:
Checklist Before Submitting:
Additional Comments:
If any, mention here.