Skip to content

Commit cb4eec0

Browse files
committed
Add Personal Finance Dashboard project (Issue #93)
1 parent ede837f commit cb4eec0

File tree

4 files changed

+144
-0
lines changed

4 files changed

+144
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Personal Finance Dashboard
2+
3+
A simple personal finance dashboard to track expenses, set budgets, and visualize spending habits.
4+
5+
## Features
6+
- Add and view expenses
7+
- Set and display budget
8+
- Visualize expenses with Chart.js
9+
10+
## Usage
11+
1. Install dependencies:
12+
```bash
13+
pip install flask
14+
```
15+
2. Run the Flask app:
16+
```bash
17+
python app.py
18+
```
19+
3. Open your browser at `http://localhost:5000`.
20+
21+
## Requirements
22+
- Python 3.x
23+
- Flask
24+
25+
## License
26+
MIT

Personal_Finance_Dashboard/app.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
Personal Finance Dashboard (Issue #93)
3+
Minimal Flask backend + HTML/JS frontend with Chart.js
4+
"""
5+
from flask import Flask, request, jsonify, send_from_directory
6+
import os
7+
8+
app = Flask(__name__)
9+
10+
DATA = {
11+
"expenses": [],
12+
"budget": 0
13+
}
14+
15+
@app.route("/api/expenses", methods=["GET", "POST"])
16+
def expenses():
17+
if request.method == "POST":
18+
expense = request.json
19+
DATA["expenses"].append(expense)
20+
return jsonify({"status": "added"}), 201
21+
return jsonify(DATA["expenses"])
22+
23+
@app.route("/api/budget", methods=["GET", "POST"])
24+
def budget():
25+
if request.method == "POST":
26+
DATA["budget"] = request.json.get("budget", 0)
27+
return jsonify({"status": "set"}), 201
28+
return jsonify({"budget": DATA["budget"]})
29+
30+
@app.route("/")
31+
def index():
32+
return send_from_directory(".", "dashboard.html")
33+
34+
if __name__ == "__main__":
35+
app.run(debug=True)
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Personal Finance Dashboard</title>
6+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
7+
<style>
8+
body { font-family: Arial, sans-serif; margin: 40px; }
9+
.container { max-width: 600px; margin: auto; }
10+
input, button { margin: 5px; }
11+
</style>
12+
</head>
13+
<body>
14+
<div class="container">
15+
<h2>Personal Finance Dashboard</h2>
16+
<div>
17+
<label>Set Budget: </label>
18+
<input type="number" id="budgetInput" />
19+
<button onclick="setBudget()">Set</button>
20+
<span id="budgetDisplay"></span>
21+
</div>
22+
<div>
23+
<label>Add Expense: </label>
24+
<input type="text" id="expenseName" placeholder="Name" />
25+
<input type="number" id="expenseAmount" placeholder="Amount" />
26+
<button onclick="addExpense()">Add</button>
27+
</div>
28+
<canvas id="expenseChart" width="400" height="200"></canvas>
29+
</div>
30+
<script>
31+
let expenses = [];
32+
let budget = 0;
33+
const chartCtx = document.getElementById('expenseChart').getContext('2d');
34+
let chart;
35+
36+
function fetchBudget() {
37+
fetch('/api/budget').then(r => r.json()).then(data => {
38+
budget = data.budget;
39+
document.getElementById('budgetDisplay').innerText = `Budget: $${budget}`;
40+
});
41+
}
42+
function setBudget() {
43+
const val = Number(document.getElementById('budgetInput').value);
44+
fetch('/api/budget', {
45+
method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({budget: val})
46+
}).then(fetchBudget);
47+
}
48+
function fetchExpenses() {
49+
fetch('/api/expenses').then(r => r.json()).then(data => {
50+
expenses = data;
51+
updateChart();
52+
});
53+
}
54+
function addExpense() {
55+
const name = document.getElementById('expenseName').value;
56+
const amount = Number(document.getElementById('expenseAmount').value);
57+
fetch('/api/expenses', {
58+
method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({name, amount})
59+
}).then(fetchExpenses);
60+
}
61+
function updateChart() {
62+
const labels = expenses.map(e => e.name);
63+
const data = expenses.map(e => e.amount);
64+
if (chart) chart.destroy();
65+
chart = new Chart(chartCtx, {
66+
type: 'bar',
67+
data: {
68+
labels: labels,
69+
datasets: [{ label: 'Expenses', data: data, backgroundColor: '#4caf50' }]
70+
},
71+
options: {
72+
plugins: {
73+
title: { display: true, text: `Budget: $${budget} | Total Spent: $${data.reduce((a,b)=>a+b,0)}` }
74+
}
75+
}
76+
});
77+
}
78+
fetchBudget();
79+
fetchExpenses();
80+
</script>
81+
</body>
82+
</html>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
flask

0 commit comments

Comments
 (0)