diff --git a/CLAUDE.md b/CLAUDE.md
index 54f2344..7136156 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -33,6 +33,6 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- `controllers/` - Route handlers
- `routes/` - Express route definitions
- `middlewares/` - Custom middleware functions
-- `views/` - EJS templates
+- `views/` - EJS templatesa
When working in this Express.js application, follow the existing patterns in controllers, models, and routes folders. Handle all form validation with express-validator and use the error handling middleware for consistent error responses.
diff --git a/app.js b/app.js
index e54a0fb..9c07003 100644
--- a/app.js
+++ b/app.js
@@ -20,6 +20,9 @@ const { pool } = require('./config/database');
const indexRoutes = require('./routes/index');
const authRoutes = require('./routes/auth');
const userRoutes = require('./routes/user');
+// New routes
+const budgetRouter = require('./routes/budget');
+const transactionRouter = require('./routes/transaction');
// Import custom middleware
const { setLocals } = require('./middlewares/locals');
@@ -27,6 +30,8 @@ const { handleErrors } = require('./middlewares/error-handler');
// Initialize Express app
const app = express();
+// Tell Express it's behind a proxy (Render/Cloudflare), so secure cookies work
+app.set('trust proxy', 1);
// Test database connection on startup
if (process.env.DATABASE_URL) {
@@ -43,8 +48,11 @@ if (process.env.DATABASE_URL) {
// Configure Express
app.use(express.json());
-app.use(express.urlencoded({ extended: true }));
+// data parsed as simple key-value pairs
+app.use(express.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
+app.use(express.static('public'));
+
// Set up EJS view engine
app.set('view engine', 'ejs');
@@ -110,6 +118,9 @@ app.use(setLocals);
app.use('/', indexRoutes);
app.use('/auth', authRoutes);
app.use('/user', userRoutes);
+// new routes
+app.use('/', budgetRouter);
+app.use('/', transactionRouter);
// Error handling middleware
app.use(handleErrors);
diff --git a/models/Category.js b/models/Category.js
new file mode 100644
index 0000000..e358a96
--- /dev/null
+++ b/models/Category.js
@@ -0,0 +1,51 @@
+const { pool } = require('../config/database');
+
+// Get all categories for a user
+async function getCategoriesForUser(userId) {
+ const result = await pool.query(
+ `
+ SELECT *
+ FROM categories
+ WHERE user_id = $1
+ ORDER BY type, name
+ `,
+ [userId]
+ );
+ return result.rows;
+}
+
+// Create a new category
+async function createCategory(userId, { name, type }) {
+ const result = await pool.query(
+ `
+ INSERT INTO categories (user_id, name, type)
+ VALUES ($1, $2, $3)
+ RETURNING *
+ `,
+ [userId, name, type]
+ );
+ return result.rows[0];
+}
+
+// seeder for first time users
+async function seedDefaultCategoriesForUser(userId) {
+ const defaults = [
+ { name: 'Salary', type: 'income' },
+ { name: 'Freelance', type: 'income' },
+ { name: 'Rent', type: 'expense' },
+ { name: 'Food', type: 'expense' },
+ { name: 'Utilities', type: 'expense' },
+ { name: 'Savings', type: 'expense' },
+ { name: 'Entertainment', type: 'expense' },
+ ];
+
+ for (const c of defaults) {
+ await createCategory(userId, c);
+ }
+ }
+
+module.exports = {
+ getCategoriesForUser,
+ createCategory,
+ seedDefaultCategoriesForUser,
+};
diff --git a/models/Transaction.js b/models/Transaction.js
new file mode 100644
index 0000000..6658825
--- /dev/null
+++ b/models/Transaction.js
@@ -0,0 +1,98 @@
+const { pool } = require('../config/database');
+
+async function getTransactionsForUser(userId) {
+ // Fetch transactions along with category names
+
+ const result = await pool.query(
+ `
+ SELECT t.*, c.name AS category_name
+ FROM transactions t
+ LEFT JOIN categories c ON t.category_id = c.id
+ WHERE t.user_id = $1
+ ORDER BY t.date DESC, t.created_at DESC
+ `,
+ [userId]
+ );
+ return result.rows;
+}
+// Create a new transaction
+async function createTransaction(userId, { categoryId, type, amount, description, date }) {
+ const result = await pool.query(
+ `
+ INSERT INTO transactions (user_id, category_id, type, amount, description, date)
+ VALUES ($1, $2, $3, $4, $5, $6)
+ RETURNING *
+ `,
+ [userId, categoryId || null, type, amount, description || null, date]
+ );
+ return result.rows[0];
+}
+// Get dashboard summary (total income, total expense, balance)
+async function getDashboardSummary(userId) {
+ const result = await pool.query(
+ `
+ SELECT
+ COALESCE(SUM(CASE WHEN type = 'income' THEN amount END), 0) AS total_income,
+ COALESCE(SUM(CASE WHEN type = 'expense' THEN amount END), 0) AS total_expense
+ FROM transactions
+ WHERE user_id = $1
+ `,
+ [userId]
+ );
+
+ const row = result.rows[0];
+ return {
+ totalIncome: Number(row.total_income),
+ totalExpense: Number(row.total_expense),
+ balance: Number(row.total_income) - Number(row.total_expense)
+ };
+}
+// Get a single transaction by ID
+async function getTransactionById(userId, transactionId) {
+ const result = await pool.query(
+ `
+ SELECT t.*, c.name AS category_name
+ FROM transactions t
+ LEFT JOIN categories c ON t.category_id = c.id
+ WHERE t.user_id = $1 AND t.id = $2
+ `,
+ [userId, transactionId]
+ );
+ return result.rows[0];
+}
+// Update a transaction
+async function updateTransaction(userId, transactionId, { amount, type, categoryId, description, date }) {
+ const result = await pool.query(
+ `
+ UPDATE transactions
+ SET amount = $1,
+ type = $2,
+ category_id = $3,
+ description = $4,
+ date = $5
+ WHERE id = $6 AND user_id = $7
+ RETURNING *
+ `,
+ [amount, type, categoryId, description, date, transactionId, userId]
+ );
+ return result.rows[0];
+}
+// Delete a transaction
+async function deleteTransaction(userId, transactionId) {
+ await pool.query(
+ `
+ DELETE FROM transactions
+ WHERE id = $1 AND user_id = $2
+ `,
+ [transactionId, userId]
+ );
+}
+
+module.exports = {
+ getTransactionsForUser,
+ createTransaction,
+ getDashboardSummary,
+ getTransactionById,
+ updateTransaction,
+ deleteTransaction,
+};
diff --git a/package.json b/package.json
index b21d016..7aff57a 100644
--- a/package.json
+++ b/package.json
@@ -20,16 +20,16 @@
"dependencies": {
"bcrypt": "^5.1.1",
"connect-pg-simple": "^10.0.0",
- "csurf": "^1.11.0",
- "dotenv": "^16.3.1",
+ "csurf": "^1.2.2",
+ "dotenv": "^16.6.1",
"ejs": "^3.1.9",
- "express": "^4.18.2",
+ "express": "^4.22.1",
"express-session": "^1.18.1",
"express-validator": "^7.0.1",
"multer": "^1.4.5-lts.2",
"pg": "^8.13.1"
},
"devDependencies": {
- "nodemon": "^3.0.2"
+ "nodemon": "^3.1.11"
}
}
diff --git a/public/css/budget.css b/public/css/budget.css
new file mode 100644
index 0000000..9fe07d3
--- /dev/null
+++ b/public/css/budget.css
@@ -0,0 +1,147 @@
+body {
+ font-family: Arial, sans-serif;
+ margin: 0;
+ padding: 0;
+ /* Updated: Soft yellow background */
+ background-color: #FFF5E1;
+ color: #333;
+}
+
+header {
+ /* Updated: Vibrant orange header background */
+ background-color: #FF9900;
+ color: #FFFFFF;
+ text-align: center;
+ padding: 15px;
+}
+
+.budget-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 20px;
+}
+
+section {
+ /* Updated: Lighter section background */
+ background: #FFF5E1;
+ border: 1px solid #FFCC00;
+ padding: 10px;
+ margin: 10px 0;
+ width: 100%;
+ max-width: 800px;
+ box-sizing: border-box;
+ border-radius: 8px;
+}
+
+/* Updated: Added text-align center to income-section */
+.income-section {
+ text-align: center;
+ /* Updated: Lighter section background */
+ background: #FFF5E1;
+ border: 1px solid #FFCC00;
+ padding: 10px;
+ margin: 10px 0;
+ width: 100%;
+ max-width: 800px;
+ box-sizing: border-box;
+ border-radius: 8px;
+}
+
+button {
+ /* Updated: Orange button background */
+ background-color: #FF9900;
+ color: #FFFFFF;
+ border: none;
+ padding: 8px 15px;
+ cursor: pointer;
+ border-radius: 4px;
+ /* Added margin for spacing around buttons */
+ margin: 5px;
+}
+
+button:hover {
+ opacity: 0.8;
+}
+
+.navbar {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ position: relative;
+ padding: 10px 20px;
+ border-bottom: 2px solid #ddd;
+ /* Updated: Darker orange/brown base */
+ background-color: #A0522D;
+}
+
+.navbar nav {
+ display: flex;
+ align-items: center;
+ gap: 20px;
+}
+
+.nav-home {
+ position: absolute;
+ left: 20px;
+ text-decoration: none;
+ font-weight: 600;
+ font-size: 1.1rem;
+ /* Updated: Bright yellow link color */
+ color: #FFCC00;
+}
+
+.nav-home:hover {
+ text-decoration: underline;
+}
+
+.navbar h1 {
+ margin: 0;
+}
+
+ul {
+ list-style-type: none;
+ padding: 0;
+/* Updated: Added text-align center to expense-inputs */
+.expense-inputs {
+ text-align: center;
+}
+
+/* Added margin to inputs and select for better spacing when centered */
+input, select {
+ margin: 5px;
+}
+
+/* Removes bullet points */
+main ul {
+ list-style-type: none;
+ padding-left: 0; /* Ensures the list items align with other content */
+}
+
+/* make the list items look cleaner */
+main ul li {
+ display: flex;
+ justify-content: space-between; /* Pushes the edit/delete buttons to the right */
+ padding: 8px 0;
+ border-bottom: 1px solid #FFCC00; /* Use your existing border color */
+ align-items: center;
+}
+
+/* Style for the edit/delete*/
+main ul li a {
+ margin-right: 10px;
+ color: #A0522D; /* Use your existing navbar color for links */
+ text-decoration: none;
+ font-size: 0.9em;
+}
+
+main ul li button {
+ /* Inherit your existing button styles*/
+ background-color: #DB4437; /* A distinct red for delete actions */
+ color: white;
+ border: none;
+ padding: 5px 10px;
+ cursor: pointer;
+ border-radius: 4px;
+}
+
diff --git a/public/css/style.css b/public/css/style.css
index bd05cbb..e2222ff 100644
--- a/public/css/style.css
+++ b/public/css/style.css
@@ -8,21 +8,24 @@
}
:root {
- --primary-color: #3498db;
- --primary-dark: #2980b9;
- --secondary-color: #2ecc71;
- --secondary-dark: #27ae60;
- --text-color: #333;
- --text-light: #666;
- --background-color: #f5f5f5;
- --border-color: #ddd;
- --error-color: #e74c3c;
- --success-color: #2ecc71;
- --warning-color: #f39c12;
- --white: #fff;
+ /* Orange and Brown Palette */
+ --primary-color: #e67e22;
+ --primary-dark: #d35400;
+ --secondary-color: #A0522D;
+ --secondary-dark: #8B4513;
+
+ --text-color: #333;
+ --text-light: #666;
+ --background-color: #f5f5f5;
+ --border-color: #ddd;
+ --error-color: #e74c3c;
+ --success-color: #2ecc71;
+ --warning-color: #f39c12;
+ --white: #fff;
--shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
+
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
@@ -203,10 +206,20 @@ input:focus {
background-color: var(--secondary-dark);
}
+.start-btn {
+ background-color: #e67e22;
+ color: var(--white);
+}
+
+.start-btn:hover {
+ background-color: #d35400;
+}
+
.action-buttons {
display: flex;
gap: 1rem;
margin-top: 2rem;
+ justify-content: center;
}
/*
@@ -299,12 +312,14 @@ input:focus {
}
.welcome-section h1 {
+ text-align: center;
font-size: 2.5rem;
margin-bottom: 1rem;
color: var(--primary-color);
}
.features-section {
+ text-align: center;
margin-top: 3rem;
}
@@ -315,6 +330,7 @@ input:focus {
}
.features-section h2:after {
+ text-align: center;
content: '';
display: block;
width: 50px;
@@ -324,6 +340,7 @@ input:focus {
}
.feature-grid {
+
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 2rem;
diff --git a/public/js/budget.js b/public/js/budget.js
new file mode 100644
index 0000000..6a30ca9
--- /dev/null
+++ b/public/js/budget.js
@@ -0,0 +1,52 @@
+// Get elements from the page
+const incomeInput = document.getElementById("income-input");
+const addIncomeButton = document.getElementById("add-income");
+const expenseAmountInput = document.getElementById("expense-amount");
+const expenseTypeSelect = document.getElementById("expense-type");
+const addExpenseButton = document.getElementById("add-expense");
+const expenseList = document.getElementById("expense-list");
+const totalIncomeDisplay = document.getElementById("total-income");
+const totalExpensesDisplay = document.getElementById("total-expenses");
+const balanceDisplay = document.getElementById("balance");
+
+// Variables to keep track of totals
+let totalIncome = 0;
+let totalExpenses = 0;
+
+// When "Enter" is clicked for income
+addIncomeButton.addEventListener("click", function() {
+ let income = parseFloat(incomeInput.value);
+
+ // Check if the input is a valid number
+ if (!isNaN(income)) {
+ totalIncome += income;
+ totalIncomeDisplay.textContent = totalIncome;
+ incomeInput.value = ""; // clear box
+ updateBalance();
+ }
+});
+
+// When "Add" is clicked for expense
+addExpenseButton.addEventListener("click", function() {
+ let expense = parseFloat(expenseAmountInput.value);
+ let type = expenseTypeSelect.value;
+
+ if (!isNaN(expense)) {
+ totalExpenses += expense;
+ totalExpensesDisplay.textContent = totalExpenses;
+
+ // Add to the expense list
+ let listItem = document.createElement("li");
+ listItem.textContent = type + ": $" + expense;
+ expenseList.appendChild(listItem);
+
+ expenseAmountInput.value = "";
+ updateBalance();
+ }
+});
+
+// Function to update balance
+function updateBalance() {
+ let balance = totalIncome - totalExpenses;
+ balanceDisplay.textContent = balance;
+}
diff --git a/routes/budget.js b/routes/budget.js
new file mode 100644
index 0000000..0c6b44d
--- /dev/null
+++ b/routes/budget.js
@@ -0,0 +1,38 @@
+// routes/budget.js
+
+const express = require('express');
+const router = express.Router();
+
+const Transaction = require('../models/Transaction');
+const Category = require('../models/Category');
+const { isAuthenticated } = require('../middlewares/auth');
+
+router.get('/budget', isAuthenticated, async (req, res, next) => {
+ try {
+ if (!req.session || !req.session.user) {
+ return res.redirect('/auth/login');
+ }
+
+ const userId = req.session.user.id;
+ console.log('HIT /budget route, userId =', userId);
+
+ const [summary, transactions, categories] = await Promise.all([
+ Transaction.getDashboardSummary(userId),
+ Transaction.getTransactionsForUser(userId),
+ Category.getCategoriesForUser(userId),
+ ]);
+ // If user has no categories yet, seed defaults once
+ if (!categories.length) {
+ await Category.seedDefaultCategoriesForUser(userId);
+ categories = await Category.getCategoriesForUser(userId);
+ }
+
+ console.log('Summary from DB:', summary);
+ res.render('budget', { summary, transactions, categories });
+ } catch (err) {
+ next(err);
+ }
+ });
+
+
+module.exports = router;
diff --git a/routes/index.js b/routes/index.js
index 8bbf05c..49fe7ca 100644
--- a/routes/index.js
+++ b/routes/index.js
@@ -9,7 +9,7 @@ const router = express.Router();
router.get('/', (req, res) => {
res.render('index', {
title: 'Home',
- message: 'Welcome to the Authentication Template'
+ message: 'Welcome to the Budget Planner'
});
});
@@ -21,4 +21,7 @@ router.get('/about', (req, res) => {
});
});
+
+
+
module.exports = router;
\ No newline at end of file
diff --git a/routes/transaction.js b/routes/transaction.js
new file mode 100644
index 0000000..9dbe8d7
--- /dev/null
+++ b/routes/transaction.js
@@ -0,0 +1,120 @@
+// routes/transaction.js
+const express = require('express');
+const router = express.Router();
+
+const Transaction = require('../models/Transaction');
+const { isAuthenticated } = require('../middlewares/auth');
+
+router.post('/transactions', isAuthenticated, async (req, res, next) => {
+ try {
+ console.log('Session in /transactions route:', req.session);
+ console.log('User in session:', req.session.user);
+
+ const userId = req.session.user.id; // use session.user.id
+ const { amount, type, category_id, description, date } = req.body;
+ // Basic validation
+ if (!amount || isNaN(Number(amount))) {
+ return res.status(400).send('Invalid amount');
+ }
+ if (type !== 'income' && type !== 'expense') {
+ return res.status(400).send('Invalid type');
+ }
+ // Create the transaction
+ await Transaction.createTransaction(userId, {
+ categoryId: category_id || null,
+ type,
+ amount,
+ description,
+ date: date || new Date(),
+ });
+
+ res.redirect('/budget');
+ } catch (err) {
+ next(err);
+ }
+});
+// Delete a transaction
+router.post('/transactions/:id/delete', isAuthenticated, async (req, res, next) => {
+ try {
+ // we need to get the user id from the session
+ const userId = req.session.user.id;
+ // and the transaction id from the route parameters
+ const transactionId = req.params.id;
+ // Safety: only delete rows belonging to this user
+ await Transaction.deleteTransaction(userId, transactionId);
+ res.redirect('/budget');
+ } catch (err) {
+ next(err);
+ }
+});
+
+// edit logic
+
+// Show edit form for a transaction
+router.get('/transactions/:id/edit', isAuthenticated, async (req, res, next) => {
+ try {
+ const userId = req.session.user.id;
+ const transactionId = req.params.id;
+
+ const transaction = await Transaction.getTransactionById(userId, transactionId);
+ if (!transaction) {
+ return res.status(404).send('Transaction not found');
+ }
+
+ const categories = await require('../models/Category').getCategoriesForUser(userId);
+
+ res.render('editTransaction', { transaction, categories });
+ } catch (err) {
+ next(err);
+ }
+});
+
+// Handle edit form submission
+router.post('/transactions/:id/edit', isAuthenticated, async (req, res, next) => {
+ try {
+ const userId = req.session.user.id;
+ const transactionId = req.params.id;
+ const { amount, type, category_id, description, date } = req.body;
+
+ if (!amount || isNaN(Number(amount))) {
+ return res.status(400).send('Invalid amount');
+ }
+
+ await Transaction.updateTransaction(userId, transactionId, {
+ amount,
+ type,
+ categoryId: category_id || null,
+ description,
+ date: date || new Date(),
+ });
+
+ res.redirect('/budget');
+ } catch (err) {
+ next(err);
+ }
+});
+
+
+// Transaction deletion route
+router.post('/transactions/delete/:id', isAuthenticated, async (req, res, next) => {
+ try {
+ const transactionId = req.params.id;
+ const userId = req.session.user.id;
+
+ const deleted = await Transaction.deleteTransaction(transactionId, userId);
+
+ if (deleted) {
+ // You might redirect back to the page they came from, or a default view
+ res.redirect('/login');
+ } else {
+ // Transaction not found error
+ res.status(404).send('Transaction not found or unauthorized');
+ }
+
+ } catch (err) {
+ next(err);
+ }
+});
+
+
+module.exports = router;
diff --git a/scripts/init-db.js b/scripts/init-db.js
index 42400d3..b96e319 100644
--- a/scripts/init-db.js
+++ b/scripts/init-db.js
@@ -35,6 +35,33 @@ const createTables = async () => {
`);
console.log('✓ Profile images table created');
+ // Create categories table
+ await pool.query(`
+ CREATE TABLE IF NOT EXISTS categories (
+ id SERIAL PRIMARY KEY,
+ user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
+ name TEXT NOT NULL,
+ type TEXT NOT NULL CHECK (type IN ('income', 'expense'))
+ )
+ `);
+ console.log('✓ Categories table created');
+
+ // Create transactions table
+ await pool.query(`
+ CREATE TABLE IF NOT EXISTS transactions (
+ id SERIAL PRIMARY KEY,
+ user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
+ category_id INTEGER REFERENCES categories(id),
+ type TEXT NOT NULL CHECK (type IN ('income', 'expense')),
+ amount NUMERIC(10, 2) NOT NULL CHECK (amount >= 0),
+ description TEXT,
+ date DATE NOT NULL DEFAULT CURRENT_DATE,
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+ )
+ `);
+ console.log('✓ Transactions table created');
+
+
// Create session table for connect-pg-simple
await pool.query(`
CREATE TABLE IF NOT EXISTS "session" (
diff --git a/views/about.ejs b/views/about.ejs
index 7514a62..6728a6b 100644
--- a/views/about.ejs
+++ b/views/about.ejs
@@ -3,9 +3,12 @@
About This Application
-
This is a starter template for a web application with user authentication features. It demonstrates:
+
A simple and secure budget planner that streamlines personal finance management. Users can easily register and log
+
in to access unique, practical tools designed to track spending habits. Effortlessly add total income, categorize expenses,
+
and instantly calculate your total balance, helping you stay in control of your financial picture every day.
+ Key Feautures
- User registration and login
- Session management with express-session
- Password hashing with bcrypt
@@ -32,4 +35,4 @@
-<%- include('./partials/footer') %>
\ No newline at end of file
+<%- include('./partials/footer') %>
diff --git a/views/budget.ejs b/views/budget.ejs
new file mode 100644
index 0000000..d47049b
--- /dev/null
+++ b/views/budget.ejs
@@ -0,0 +1,121 @@
+
+
+
+
+
+ Budget Planner
+
+
+
+
+
+
+ <%
+ const safeSummary = (typeof summary !== 'undefined' && summary)
+ ? summary
+ : { totalIncome: 0, totalExpense: 0, balance: 0 };
+ %>
+
+
+
+
+ Add Income
+
+
+ <% if (typeof transactions !== 'undefined' && transactions && transactions.length) { %>
+ <% transactions.forEach(t => { if (t.type === 'income') { %>
+ -
+ $<%= t.amount %> – <%= t.category_name || 'Uncategorized' %>
+
+
+ edit
+
+
+
+
+ <% } }) %>
+ <% } else { %>
+ - No income yet
+ <% } %>
+
+
+
+
+
+ Expenses
+
+
+ Add Expense
+
+
+ Recent Expenses
+
+ <% if (typeof transactions !== 'undefined' && transactions && transactions.length) { %>
+ <% transactions.forEach(t => { if (t.type === 'expense') { %>
+ -
+ $<%= t.amount %> – <%= t.category_name || 'Uncategorized' %>
+
+ edit
+
+
+ <% } }) %>
+ <% } else { %>
+ - No expenses yet
+ <% } %>
+
+
+
+
+
+ Summary
+ Total Income: $<%= safeSummary.totalIncome %>
+ Total Expenses: $<%= safeSummary.totalExpense %>
+ Balance: $<%= safeSummary.balance %>
+
+
+
+
+
+
+
diff --git a/views/design/Budget Planner Create Account.png b/views/design/Budget Planner Create Account.png
new file mode 100644
index 0000000..ada24ad
Binary files /dev/null and b/views/design/Budget Planner Create Account.png differ
diff --git a/views/design/Budget Planner Login.png b/views/design/Budget Planner Login.png
new file mode 100644
index 0000000..4097c14
Binary files /dev/null and b/views/design/Budget Planner Login.png differ
diff --git a/views/design/Budget Planner add value.png b/views/design/Budget Planner add value.png
new file mode 100644
index 0000000..a5a7bc5
Binary files /dev/null and b/views/design/Budget Planner add value.png differ
diff --git a/views/design/Budget Planner dashboard.png b/views/design/Budget Planner dashboard.png
new file mode 100644
index 0000000..5ea6d8b
Binary files /dev/null and b/views/design/Budget Planner dashboard.png differ
diff --git a/views/editTransaction.ejs b/views/editTransaction.ejs
new file mode 100644
index 0000000..06074ab
--- /dev/null
+++ b/views/editTransaction.ejs
@@ -0,0 +1,50 @@
+
+
+
+
+ Edit Transaction
+
+
+
+ Edit Transaction
+
+
+
+
diff --git a/views/index.ejs b/views/index.ejs
index f098628..937752d 100644
--- a/views/index.ejs
+++ b/views/index.ejs
@@ -3,16 +3,18 @@
<%= message %>
-
A simple authentication system for web applications
+
A simple Budget Planner for web applications
<% if (isAuthenticated) { %>
<% } else { %>
<% } %>
@@ -21,16 +23,16 @@
Features
-
User Authentication
-
Secure login and registration with password hashing
+
Allocation
+
Setting and tracking budgets per category
-
Session Management
-
Persistent sessions with secure cookies
+
Progress
+
Monitoring savgings and investment goals
-
Protected Routes
-
Restrict access to authenticated users only
+
Summary
+
Monthly totals
diff --git a/views/layouts/index.html b/views/layouts/index.html
new file mode 100644
index 0000000..11ab352
--- /dev/null
+++ b/views/layouts/index.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+ Budget Planner
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Budget Summary
+ Total Income: $0
+ Total Expenses: $0
+ Balance: $0
+
+
+
+
+
+
+
+
+
+
diff --git a/views/layouts/main.html b/views/layouts/main.html
index b2ad94d..e6fce9e 100644
--- a/views/layouts/main.html
+++ b/views/layouts/main.html
@@ -3,14 +3,14 @@
- {{title}} | Authentication Template
+ {{title}} | Budget Planner