diff --git a/public/assets/js/app.js b/public/assets/js/app.js
index 594f52a..c2b3b7a 100644
--- a/public/assets/js/app.js
+++ b/public/assets/js/app.js
@@ -1,5 +1,3 @@
-// main.js
-
document.addEventListener('DOMContentLoaded', function() {
const addBillForm = document.getElementById('addBillForm');
if (addBillForm) {
@@ -8,37 +6,12 @@ document.addEventListener('DOMContentLoaded', function() {
const formData = new FormData(this);
axios.post('/api/add-bill', formData)
.then(function(response) {
- // Handle success, e.g., close modal, refresh bill list
console.log('Bill added successfully');
- loadBills(); // Reload the bills list
+ loadBills();
})
.catch(function(error) {
- // Handle error, e.g., display error message
console.error('Error adding bill:', error);
});
-
- document.querySelectorAll('.edit-bill-btn').forEach(button => {
- button.addEventListener('click', function() {
- const billId = this.getAttribute('data-bill-id');
- // Fetch bill details and populate the form in the modal
- // Then, handle the form submission similar to the add bill form
- });
- });
- document.querySelectorAll('.delete-bill-btn').forEach(button => {
- button.addEventListener('click', function() {
- const billId = this.getAttribute('data-bill-id');
- axios.post('/api/delete-bill', { id: billId })
- .then(function(response) {
- // Handle success
- console.log('Bill deleted successfully');
- loadBills(); // Reload the bills list
- })
- .catch(function(error) {
- // Handle error
- console.error('Error deleting bill:', error);
- });
- });
- });
});
}
@@ -46,17 +19,31 @@ document.addEventListener('DOMContentLoaded', function() {
if (document.getElementById('billsTable')) {
loadBills();
}
-});
+ // Event delegation for dynamically added "Mark as Paid" buttons
+ document.addEventListener('click', function(e) {
+ if (e.target && e.target.matches('.mark-bill-paid-btn')) {
+ const billId = e.target.getAttribute('data-bill-id');
+ axios.post('/api/mark-bill-paid', { id: billId })
+ .then(function(response) {
+ console.log('Bill marked as paid successfully');
+ loadBills();
+ })
+ .catch(function(error) {
+ console.error('Error marking bill as paid:', error);
+ });
+ }
+ });
+});
function loadBills() {
const billsTableBody = document.querySelector('#billsTable tbody');
- billsTableBody.innerHTML = '
| Loading bills... |
'; // Loading indicator
+ billsTableBody.innerHTML = '| Loading bills... |
';
axios.get('/api/bills')
.then(function(response) {
const bills = response.data;
- billsTableBody.innerHTML = ''; // Clear loading indicator
+ billsTableBody.innerHTML = '';
bills.forEach(function(bill) {
const row = `
@@ -65,7 +52,9 @@ function loadBills() {
$${parseFloat(bill.amount).toFixed(2)} |
${bill.due_date} |
-
+ ${bill.is_paid ? '' : ''}
+
+
|
`;
@@ -74,6 +63,6 @@ function loadBills() {
})
.catch(function(error) {
console.error('Error loading bills:', error);
- billsTableBody.innerHTML = '| Error loading bills. |
'; // Error message
+ billsTableBody.innerHTML = '| Error loading bills. |
';
});
}
diff --git a/public/index.php b/public/index.php
index 91a135c..9cac678 100644
--- a/public/index.php
+++ b/public/index.php
@@ -1,181 +1,41 @@
register('GET', '/', [HomeController::class, 'index']);
+// Auth Routes
+$router->register('GET', '/login', [AuthController::class, 'showLoginForm']);
+$router->register('POST', '/login', [AuthController::class, 'login']);
+$router->register('GET', '/register', [AuthController::class, 'showRegistrationForm']);
+$router->register('POST', '/register', [AuthController::class, 'register']);
-switch ($request) {
- case '/':
- require __DIR__ . '/../views/home.php';
- break;
- case '/login':
- if ($_SERVER['REQUEST_METHOD'] === 'POST') {
- $username = $_POST['username'] ?? '';
- $password = $_POST['password'] ?? '';
-
- if (empty($username) || empty($password)) {
- $error = 'Username and password are required.';
- require __DIR__ . '/../views/auth/login.php';
- break;
- }
-
- $user = new \Hpz937\BillReminder\User\User($db);
- if ($user->login($username, $password)) {
- header('Location: /dashboard');
- exit;
- } else {
- $error = 'Login failed. Please check your credentials.';
- require __DIR__ . '/../views/auth/login.php';
- }
- } else {
- require __DIR__ . '/../views/auth/login.php';
- }
- break;
-
- case '/register':
- if ($_SERVER['REQUEST_METHOD'] === 'POST') {
- // Extract form data
- $username = $_POST['username'] ?? '';
- $password = $_POST['password'] ?? '';
- $email = $_POST['email'] ?? '';
-
- // Perform validation (basic example)
- if (empty($username) || empty($password) || empty($email)) {
- // Handle validation error
- $error = 'All fields are required.';
- require __DIR__ . '/../views/auth/register.php';
- break;
- }
-
- // Instantiate User class and call register method
- $user = new \Hpz937\BillReminder\User\User($db); // Assume $db is your DatabaseInterface instance
- if ($user->register($username, $password, $email)) {
- // Redirect to login on success
- header('Location: /');
- exit;
- } else {
- // Handle registration error
- $error = 'Registration failed. Please try again.';
- require __DIR__ . '/../views/auth/register.php';
- }
- } else {
- require __DIR__ . '/../views/auth/register.php';
- }
- break;
-
- case '/dashboard':
- if (!isset($_SESSION['user_id'])) {
- header('Location: /login');
- exit;
- }
- require __DIR__ . '/../views/dashboard.php';
- break;
-
- case '/settings':
- if (!isset($_SESSION['user_id'])) {
- header('Location: /login');
- exit;
- }
- require __DIR__ . '/../views/settings.php';
- break;
+// Dashboard Routes
+$router->register('GET', '/dashboard', [DashboardController::class, 'viewDashboard']);
+$router->register('GET', '/settings', [DashboardController::class, 'viewSettings']);
- case '/api/bills':
- if (!isset($_SESSION['user_id'])) {
- // Return an error response if the user is not logged in
- echo json_encode(['error' => 'Unauthorized']);
- http_response_code(401);
- exit;
- }
+// API Routes
+$router->register('GET', '/api/bills', [ApiController::class, 'getBills']);
+$router->register('POST', '/api/mark-bill-paid', [ApiController::class, 'markBillPaid']);
+$router->register('POST', '/api/add-bill', [ApiController::class, 'addBill']);
+$router->register('POST', '/api/edit-bill', [ApiController::class, 'editBill']);
+$router->register('POST', '/api/delete-bill', [ApiController::class, 'deleteBill']);
- // Initialize your database and Bill class instance
- $db = new SQLiteAdapter();
- $billManager = new Bill($db);
+// Resolve the current request
+$requestMethod = $_SERVER['REQUEST_METHOD'];
+$requestUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
- $userId = $_SESSION['user_id'];
- $bills = $billManager->getBillsByUserId($userId); // Assuming $billManager is your Bill class instance
-
- // Return the bills as JSON
- header('Content-Type: application/json');
- echo json_encode($bills);
- break;
-
- case '/api/add-bill':
- if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SESSION['user_id'])) {
- // Extract bill details from POST data
- $userId = $_SESSION['user_id']; // Assuming you store user ID in session upon login
- $description = $_POST['description'] ?? '';
- $amount = $_POST['amount'] ?? '';
- $dueDate = $_POST['due_date'] ?? '';
-
- // Validate the inputs...
-
- // Insert the bill into the database
- $result = $billManager->addBill($userId, $dueDate, $amount, $description);
-
- if ($result) {
- echo json_encode(['success' => 'Bill added successfully']);
- } else {
- http_response_code(500);
- echo json_encode(['error' => 'Failed to add bill']);
- }
- exit;
- }
- break;
-
- case '/api/edit-bill':
- if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SESSION['user_id'])) {
- // Extract bill details and ID from POST data
- $billId = $_POST['id'] ?? '';
- $description = $_POST['description'] ?? '';
- $amount = $_POST['amount'] ?? '';
- $dueDate = $_POST['due_date'] ?? '';
-
- // Validate the inputs and ensure the bill belongs to the logged-in user...
-
- // Update the bill in the database
- $result = $billManager->editBill($billId, $dueDate, $amount, $description);
-
- if ($result) {
- echo json_encode(['success' => 'Bill updated successfully']);
- } else {
- http_response_code(500);
- echo json_encode(['error' => 'Failed to update bill']);
- }
- exit;
- }
- break;
- case '/api/delete-bill':
- if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SESSION['user_id'])) {
- // Extract bill ID from POST data
- $billId = $_POST['id'] ?? '';
-
- // Validate the ID and ensure the bill belongs to the logged-in user...
-
- // Delete the bill from the database
- $result = $billManager->deleteBill($billId);
-
- if ($result) {
- echo json_encode(['success' => 'Bill deleted successfully']);
- } else {
- http_response_code(500);
- echo json_encode(['error' => 'Failed to delete bill']);
- }
- exit;
- }
- break;
-
- default:
- http_response_code(404);
- echo 'Page not found';
- break;
-}
+$router->resolve($requestMethod, $requestUri);
diff --git a/src/Bill/Bill.php b/src/Bill/Bill.php
index 6ce8842..6d59b24 100644
--- a/src/Bill/Bill.php
+++ b/src/Bill/Bill.php
@@ -61,7 +61,8 @@ class Bill
$this->db->query($sql, $params);
return true;
} catch (Exception $e) {
- // Handle or log the error appropriately
+ //log the error
+ var_dump($e->getMessage());
return false;
}
}
diff --git a/src/Controller/ApiController.php b/src/Controller/ApiController.php
new file mode 100644
index 0000000..9161226
--- /dev/null
+++ b/src/Controller/ApiController.php
@@ -0,0 +1,77 @@
+db = new SQLiteAdapter();
+ }
+
+ public function getBills() {
+ if (!isset($_SESSION['user_id'])) {
+ echo json_encode(['error' => 'Unauthorized']);
+ http_response_code(401);
+ exit;
+ }
+
+ $billManager = new Bill($this->db);
+ $userId = $_SESSION['user_id'];
+ $bills = $billManager->getBillsByUserId($userId);
+
+ header('Content-Type: application/json');
+ echo json_encode($bills);
+ }
+
+ public function addBill() {
+ if (!isset($_SESSION['user_id'])) {
+ echo json_encode(['error' => 'Unauthorized or Invalid Request']);
+ http_response_code(401);
+ return;
+ }
+
+ $userId = $_SESSION['user_id'];
+ $description = $_POST['description'] ?? '';
+ $amount = $_POST['amount'] ?? '';
+ $dueDate = $_POST['due_date'] ?? '';
+
+ // Perform necessary validation on inputs
+
+ $billManager = new Bill($this->db);
+ $result = $billManager->addBill($userId, $description, $amount, $dueDate);
+
+ if ($result) {
+ echo json_encode(['success' => 'Bill added successfully']);
+ } else {
+ http_response_code(500);
+ echo json_encode(['error' => 'Failed to add bill']);
+ }
+ }
+
+ public function markBillPaid() {
+ if (!isset($_SESSION['user_id'])) {
+ echo json_encode(['error' => 'Unauthorized or Invalid Request']);
+ http_response_code(401);
+ return;
+ }
+
+ $json = json_decode(file_get_contents("php://input"), true);
+ $billId = $json['id'] ?? '';
+
+ // Perform necessary validation on inputs
+
+ $billManager = new Bill($this->db);
+ $result = $billManager->markAsPaid($billId);
+
+ if ($result) {
+ echo json_encode(['success' => 'Bill marked as paid']);
+ } else {
+ http_response_code(500);
+ echo json_encode(['error' => 'Failed to mark bill as paid']);
+ }
+ }
+}
diff --git a/src/Controller/AuthController.php b/src/Controller/AuthController.php
new file mode 100644
index 0000000..ca97d25
--- /dev/null
+++ b/src/Controller/AuthController.php
@@ -0,0 +1,62 @@
+db = new SQLiteAdapter();
+ }
+
+ public function showLoginForm() {
+ require PROJECT_ROOT . '/views/auth/login.php';
+ }
+
+ public function login() {
+ $username = $_POST['username'] ?? '';
+ $password = $_POST['password'] ?? '';
+
+ if (empty($username) || empty($password)) {
+ $error = 'Username and password are required.';
+ require PROJECT_ROOT . '/views/auth/login.php';
+ return;
+ }
+
+ $user = new User($this->db);
+ if ($user->login($username, $password)) {
+ header('Location: /dashboard');
+ exit;
+ } else {
+ $error = 'Login failed. Please check your credentials.';
+ require PROJECT_ROOT . '/views/auth/login.php';
+ }
+ }
+
+ public function showRegistrationForm() {
+ require PROJECT_ROOT . '/views/auth/register.php';
+ }
+
+ public function register() {
+ $username = $_POST['username'] ?? '';
+ $password = $_POST['password'] ?? '';
+ $email = $_POST['email'] ?? '';
+
+ if (empty($username) || empty($password) || empty($email)) {
+ $error = 'All fields are required.';
+ require PROJECT_ROOT . '/views/auth/register.php';
+ return;
+ }
+
+ $user = new User($this->db);
+ if ($user->register($username, $password, $email)) {
+ header('Location: /');
+ exit;
+ } else {
+ $error = 'Registration failed. Please try again.';
+ require PROJECT_ROOT . '/views/auth/register.php';
+ }
+ }
+}
diff --git a/src/Controller/DashboardController.php b/src/Controller/DashboardController.php
new file mode 100644
index 0000000..a616fda
--- /dev/null
+++ b/src/Controller/DashboardController.php
@@ -0,0 +1,21 @@
+connection === null) {
try {
- $this->connection = new PDO('sqlite:' . __DIR__ . '/../../database.db');
- $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
- } catch (PDOException $e) {
+ $this->connection = new SQLite3(__DIR__ . '/../../database.db');
+ } catch (Exception $e) {
// In a real application, you might want to use a more sophisticated error handling approach
die("Connection error: " . $e->getMessage());
}
@@ -24,17 +28,35 @@ class SQLiteAdapter implements DatabaseInterface
return $this->connection;
}
+ /**
+ * Query the database and return the result
+ *
+ * @param string $query
+ * @param array $params
+ * @return array|null
+ */
public function query(string $query, array $params = [])
{
$stmt = $this->connect()->prepare($query);
- if (!$stmt->execute($params)) {
- // Again, consider a more sophisticated error handling in a real application
- die("Query error: " . implode(", ", $stmt->errorInfo()));
+ foreach ($params as $key => $value) {
+ // var_dump($key, $value);
+ $stmt->bindValue($key, $value);
+ }
+
+ try {
+ // var_dump($stmt->getSQL(true));
+ $result = $stmt->execute();
+ } catch (Exception $e) {
+ die("Query error: " . $e->getMessage());
}
if (preg_match('/^(SELECT|SHOW|PRAGMA)/i', $query)) {
- return $stmt->fetchAll(PDO::FETCH_ASSOC);
+ $output = [];
+ while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
+ $output[] = $row;
+ }
+ return $output;
}
return null;
diff --git a/src/Routing/Router.php b/src/Routing/Router.php
new file mode 100644
index 0000000..4e39633
--- /dev/null
+++ b/src/Routing/Router.php
@@ -0,0 +1,26 @@
+routes[$method][$path] = $action;
+ }
+
+ public function resolve($method, $uri) {
+ if (isset($this->routes[$method][$uri])) {
+ $action = $this->routes[$method][$uri];
+ if (is_array($action)) {
+ list($class, $method) = $action;
+ return (new $class)->$method();
+ }
+ }
+
+ // Handle 404 Not Found
+ http_response_code(404);
+ echo 'Page not found';
+ }
+}
+
diff --git a/src/User/User.php b/src/User/User.php
index 8735d82..91a1275 100644
--- a/src/User/User.php
+++ b/src/User/User.php
@@ -45,9 +45,9 @@ class User
try {
$user = $this->db->query($sql, $params);
- if ($user && password_verify($password, $user[0]['password'])) {
+ if ($user && password_verify($password, $user['password'])) {
// Set session or token here as per your session management strategy
- $_SESSION['user_id'] = $user[0]['id'];
+ $_SESSION['user_id'] = $user['id'];
return true;
}
return false;
diff --git a/views/dashboard.php b/views/dashboard.php
index a1a5078..9f4ed41 100644
--- a/views/dashboard.php
+++ b/views/dashboard.php
@@ -43,7 +43,7 @@ $content = function() { /* use ($bills) if fetching bills from the database */
×
-