Auto stash before merge of "main" and "origin/main"
This commit is contained in:
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,8 +1,5 @@
|
||||
# ---> Composer
|
||||
composer.phar
|
||||
/vendor/
|
||||
|
||||
# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
|
||||
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
|
||||
composer.lock
|
||||
|
||||
/vendor/
|
||||
.DS_Store
|
||||
*.db
|
||||
|
||||
@@ -13,5 +13,12 @@
|
||||
"email": "hpz937+code@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {}
|
||||
"repositories": [{
|
||||
"type": "composer",
|
||||
"url": "https://git.hpz.pw/api/packages/hpz937/composer"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"hpz937/restclient": "1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
41
db_setup.php
Normal file
41
db_setup.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use Hpz937\BillReminder\Database\SQLiteAdapter;
|
||||
|
||||
// Initialize the SQLite database adapter
|
||||
$dbAdapter = new SQLiteAdapter();
|
||||
$db = $dbAdapter->connect();
|
||||
|
||||
// SQL for creating the 'users' table
|
||||
$createUsersTable = <<<SQL
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username VARCHAR(255) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) NOT NULL UNIQUE
|
||||
);
|
||||
SQL;
|
||||
|
||||
// SQL for creating the 'bills' table
|
||||
$createBillsTable = <<<SQL
|
||||
CREATE TABLE IF NOT EXISTS bills (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
due_date DATE NOT NULL,
|
||||
amount DECIMAL(10, 2) NOT NULL,
|
||||
description TEXT,
|
||||
is_paid INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
);
|
||||
SQL;
|
||||
|
||||
// Execute the SQL queries to create the tables
|
||||
try {
|
||||
$db->exec($createUsersTable);
|
||||
$db->exec($createBillsTable);
|
||||
echo "Database setup completed successfully.\n";
|
||||
} catch (Exception $e) {
|
||||
echo "Error setting up the database: " . $e->getMessage() . "\n";
|
||||
}
|
||||
79
public/assets/js/app.js
Normal file
79
public/assets/js/app.js
Normal file
@@ -0,0 +1,79 @@
|
||||
// main.js
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const addBillForm = document.getElementById('addBillForm');
|
||||
if (addBillForm) {
|
||||
addBillForm.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
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
|
||||
})
|
||||
.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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Load bills if on the dashboard page
|
||||
if (document.getElementById('billsTable')) {
|
||||
loadBills();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function loadBills() {
|
||||
const billsTableBody = document.querySelector('#billsTable tbody');
|
||||
billsTableBody.innerHTML = '<tr><td colspan="4" class="text-center">Loading bills...</td></tr>'; // Loading indicator
|
||||
|
||||
axios.get('/api/bills')
|
||||
.then(function(response) {
|
||||
const bills = response.data;
|
||||
billsTableBody.innerHTML = ''; // Clear loading indicator
|
||||
|
||||
bills.forEach(function(bill) {
|
||||
const row = `
|
||||
<tr>
|
||||
<td>${bill.description}</td>
|
||||
<td>$${parseFloat(bill.amount).toFixed(2)}</td>
|
||||
<td>${bill.due_date}</td>
|
||||
<td>
|
||||
<!-- Add action buttons here -->
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
billsTableBody.innerHTML += row;
|
||||
});
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Error loading bills:', error);
|
||||
billsTableBody.innerHTML = '<tr><td colspan="4" class="text-center">Error loading bills.</td></tr>'; // Error message
|
||||
});
|
||||
}
|
||||
181
public/index.php
Normal file
181
public/index.php
Normal file
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
use Hpz937\BillReminder\Bill\Bill;
|
||||
use Hpz937\BillReminder\Database\SQLiteAdapter;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
session_start();
|
||||
|
||||
$request = $_SERVER['REQUEST_URI'];
|
||||
|
||||
// Initialize database connection
|
||||
// $dbConfig = require __DIR__ . '/../config/database.php'; // Assuming you have a config file
|
||||
$db = new \Hpz937\BillReminder\Database\SQLiteAdapter(); // Or whichever adapter you're using
|
||||
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Initialize your database and Bill class instance
|
||||
$db = new SQLiteAdapter();
|
||||
$billManager = new Bill($db);
|
||||
|
||||
$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;
|
||||
}
|
||||
80
src/Bill/Bill.php
Normal file
80
src/Bill/Bill.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Hpz937\BillReminder\Bill;
|
||||
|
||||
use Hpz937\BillReminder\Database\DatabaseInterface;
|
||||
use Exception;
|
||||
|
||||
class Bill
|
||||
{
|
||||
private $db;
|
||||
|
||||
public function __construct(DatabaseInterface $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
public function addBill($userId, $dueDate, $amount, $description)
|
||||
{
|
||||
$sql = "INSERT INTO bills (user_id, due_date, amount, description, is_paid) VALUES (:user_id, :due_date, :amount, :description, 0)";
|
||||
$params = [
|
||||
':user_id' => $userId,
|
||||
':due_date' => $dueDate,
|
||||
':amount' => $amount,
|
||||
':description' => $description
|
||||
];
|
||||
|
||||
try {
|
||||
$this->db->query($sql, $params);
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
// Handle or log the error appropriately
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function editBill($billId, $dueDate, $amount, $description)
|
||||
{
|
||||
$sql = "UPDATE bills SET due_date = :due_date, amount = :amount, description = :description WHERE id = :id";
|
||||
$params = [
|
||||
':due_date' => $dueDate,
|
||||
':amount' => $amount,
|
||||
':description' => $description,
|
||||
':id' => $billId
|
||||
];
|
||||
|
||||
try {
|
||||
$this->db->query($sql, $params);
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
// Handle or log the error appropriately
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function markAsPaid($billId)
|
||||
{
|
||||
$sql = "UPDATE bills SET is_paid = 1 WHERE id = :id";
|
||||
$params = [':id' => $billId];
|
||||
|
||||
try {
|
||||
$this->db->query($sql, $params);
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
// Handle or log the error appropriately
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getBillsByUserId($userId) {
|
||||
$sql = "SELECT * FROM bills WHERE user_id = :user_id ORDER BY due_date ASC";
|
||||
$params = [':user_id' => $userId];
|
||||
|
||||
try {
|
||||
return $this->db->query($sql, $params);
|
||||
} catch (Exception $e) {
|
||||
// Handle or log the error appropriately
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/Database/DatabaseInterface.php
Normal file
10
src/Database/DatabaseInterface.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Hpz937\BillReminder\Database;
|
||||
|
||||
interface DatabaseInterface
|
||||
{
|
||||
public function connect();
|
||||
public function query(string $query, array $params = []);
|
||||
public function close();
|
||||
}
|
||||
47
src/Database/SQLiteAdapter.php
Normal file
47
src/Database/SQLiteAdapter.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Hpz937\BillReminder\Database;
|
||||
|
||||
use PDO;
|
||||
use PDOException;
|
||||
|
||||
class SQLiteAdapter implements DatabaseInterface
|
||||
{
|
||||
private $connection;
|
||||
|
||||
public function connect()
|
||||
{
|
||||
if ($this->connection === null) {
|
||||
try {
|
||||
$this->connection = new PDO('sqlite:' . __DIR__ . '/../../database.db');
|
||||
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
} catch (PDOException $e) {
|
||||
// In a real application, you might want to use a more sophisticated error handling approach
|
||||
die("Connection error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
if (preg_match('/^(SELECT|SHOW|PRAGMA)/i', $query)) {
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
$this->connection = null;
|
||||
}
|
||||
}
|
||||
50
src/Notification/NftyNotification.php
Normal file
50
src/Notification/NftyNotification.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Hpz937\BillReminder\Notification;
|
||||
|
||||
use Hpz937\Restclient\RestClient;
|
||||
use Exception;
|
||||
|
||||
class NftyNotification implements NotificationInterface
|
||||
{
|
||||
private $restClient;
|
||||
private $apiKey;
|
||||
|
||||
public function __construct(RestClient $restClient, string $apiKey)
|
||||
{
|
||||
$this->restClient = $restClient;
|
||||
$this->apiKey = $apiKey;
|
||||
|
||||
// Set the base URL for the nfty.sh API if it's consistent for all requests
|
||||
$this->restClient->setBaseUrl('https://api.nfty.sh');
|
||||
|
||||
// Set the headers required for authentication and content type, if not already set in RestClient
|
||||
$this->restClient->setHeaders([
|
||||
'Authorization: Bearer ' . $this->apiKey,
|
||||
'Content-Type: application/json' // Assuming JSON content type, adjust if necessary
|
||||
]);
|
||||
}
|
||||
|
||||
public function send(string $to, string $message): bool
|
||||
{
|
||||
$endpoint = '/send'; // Adjust the endpoint if necessary
|
||||
$data = [
|
||||
'to' => $to,
|
||||
'message' => $message,
|
||||
];
|
||||
|
||||
try {
|
||||
$this->restClient->post($endpoint, $data);
|
||||
$response = $this->restClient->getResponse();
|
||||
|
||||
// Assuming the API returns a JSON response indicating success, adjust as necessary
|
||||
$decodedResponse = $this->restClient->decodeJson();
|
||||
|
||||
// Check the decoded response for success indication, adjust the condition based on actual API response structure
|
||||
return isset($decodedResponse['success']) && $decodedResponse['success'];
|
||||
} catch (Exception $e) {
|
||||
// Log or handle the error as needed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/Notification/NotificationInterface.php
Normal file
8
src/Notification/NotificationInterface.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Hpz937\BillReminder\Notification;
|
||||
|
||||
interface NotificationInterface
|
||||
{
|
||||
public function send(string $to, string $message): bool;
|
||||
}
|
||||
69
src/Settings/Settings.php
Normal file
69
src/Settings/Settings.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Hpz937\BillReminder\Settings;
|
||||
|
||||
use Hpz937\BillReminder\Database\DatabaseInterface;
|
||||
use Exception;
|
||||
|
||||
class Settings
|
||||
{
|
||||
private $db;
|
||||
|
||||
public function __construct(DatabaseInterface $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
public function saveSettings($userId, $notificationPeriod)
|
||||
{
|
||||
// Check if settings already exist for the user
|
||||
if ($this->settingsExist($userId)) {
|
||||
// Update existing settings
|
||||
$sql = "UPDATE settings SET notification_period = :notification_period WHERE user_id = :user_id";
|
||||
} else {
|
||||
// Insert new settings
|
||||
$sql = "INSERT INTO settings (user_id, notification_period) VALUES (:user_id, :notification_period)";
|
||||
}
|
||||
|
||||
$params = [
|
||||
':user_id' => $userId,
|
||||
':notification_period' => $notificationPeriod,
|
||||
];
|
||||
|
||||
try {
|
||||
$this->db->query($sql, $params);
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
// Handle or log the error appropriately
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getSettings($userId)
|
||||
{
|
||||
$sql = "SELECT * FROM settings WHERE user_id = :user_id";
|
||||
$params = [':user_id' => $userId];
|
||||
|
||||
try {
|
||||
$settings = $this->db->query($sql, $params);
|
||||
return $settings ? $settings[0] : null;
|
||||
} catch (Exception $e) {
|
||||
// Handle or log the error appropriately
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function settingsExist($userId)
|
||||
{
|
||||
$sql = "SELECT id FROM settings WHERE user_id = :user_id";
|
||||
$params = [':user_id' => $userId];
|
||||
|
||||
try {
|
||||
$result = $this->db->query($sql, $params);
|
||||
return !empty($result);
|
||||
} catch (Exception $e) {
|
||||
// Handle or log the error appropriately
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
76
src/User/User.php
Normal file
76
src/User/User.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Hpz937\BillReminder\User;
|
||||
|
||||
use Hpz937\BillReminder\Database\DatabaseInterface;
|
||||
use Exception;
|
||||
|
||||
class User
|
||||
{
|
||||
private $db;
|
||||
|
||||
public function __construct(DatabaseInterface $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
public function register($username, $password, $email)
|
||||
{
|
||||
// Check if the username or email already exists
|
||||
if ($this->userExists($username, $email)) {
|
||||
throw new Exception("Username or email already exists.");
|
||||
}
|
||||
|
||||
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
|
||||
$sql = "INSERT INTO users (username, password, email) VALUES (:username, :password, :email)";
|
||||
$params = [
|
||||
':username' => $username,
|
||||
':password' => $hashedPassword,
|
||||
':email' => $email
|
||||
];
|
||||
|
||||
try {
|
||||
$this->db->query($sql, $params);
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
// Handle or log the error appropriately
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function login($username, $password)
|
||||
{
|
||||
$sql = "SELECT * FROM users WHERE username = :username";
|
||||
$params = [':username' => $username];
|
||||
|
||||
try {
|
||||
$user = $this->db->query($sql, $params);
|
||||
if ($user && password_verify($password, $user[0]['password'])) {
|
||||
// Set session or token here as per your session management strategy
|
||||
$_SESSION['user_id'] = $user[0]['id'];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (Exception $e) {
|
||||
// Handle or log the error appropriately
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function userExists($username, $email)
|
||||
{
|
||||
$sql = "SELECT id FROM users WHERE username = :username OR email = :email";
|
||||
$params = [
|
||||
':username' => $username,
|
||||
':email' => $email
|
||||
];
|
||||
|
||||
try {
|
||||
$result = $this->db->query($sql, $params);
|
||||
return !empty($result);
|
||||
} catch (Exception $e) {
|
||||
// Handle or log the error appropriately
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
views/auth/login.php
Normal file
14
views/auth/login.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php $content = function() { ?>
|
||||
<h2>Login</h2>
|
||||
<form action="/login" method="post">
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" class="form-control" id="username" name="username" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Login</button>
|
||||
</form>
|
||||
<?php }; include __DIR__ . '/../layouts/app.php'; ?>
|
||||
42
views/auth/register.php
Normal file
42
views/auth/register.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
// Check if the user is already logged in
|
||||
if (isset($_SESSION['user_id'])) {
|
||||
// Redirect to the dashboard if the user is already logged in
|
||||
header('Location: /dashboard');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Include error handling
|
||||
$error = $_SESSION['error'] ?? '';
|
||||
unset($_SESSION['error']); // Clear the error after displaying
|
||||
|
||||
$content = function() use ($error) { ?>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<h2 class="mt-5">Register</h2>
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<?= htmlspecialchars($error) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<form action="/register" method="post">
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" class="form-control" id="username" name="username" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" class="form-control" id="email" name="email" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Register</button>
|
||||
</form>
|
||||
<p class="mt-3">Already have an account? <a href="/">Login here</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php };
|
||||
|
||||
include __DIR__ . '/../layouts/app.php';
|
||||
74
views/dashboard.php
Normal file
74
views/dashboard.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
use Hpz937\BillReminder\Database\SqLiteAdapter;
|
||||
use Hpz937\BillReminder\Bill\Bill;
|
||||
// Assuming session_start() is called in the front controller or app.php
|
||||
|
||||
// Redirect to login page if the user is not logged in
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: /');
|
||||
exit;
|
||||
}
|
||||
|
||||
$content = function() { /* use ($bills) if fetching bills from the database */
|
||||
|
||||
?>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<h2 class="mt-5">Dashboard</h2>
|
||||
<button type="button" class="btn btn-primary mb-3" data-bs-toggle="modal" data-bs-target="#addBillModal">Add New Bill</button>
|
||||
|
||||
<!-- Bills Table -->
|
||||
<table class="table" id="billsTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Description</th>
|
||||
<th scope="col">Amount</th>
|
||||
<th scope="col">Due Date</th>
|
||||
<th scope="col">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Bills will be loaded here by Axios -->
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<!-- Add Bill Modal -->
|
||||
<div class="modal fade" id="addBillModal" tabindex="-1" role="dialog" aria-labelledby="addBillModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="addBillModalLabel">Add New Bill</h5>
|
||||
<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="/add-bill" method="post">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<input type="text" class="form-control" id="description" name="description" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="amount">Amount</label>
|
||||
<input type="number" class="form-control" id="amount" name="amount" step="0.01" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="due_date">Due Date</label>
|
||||
<input type="date" class="form-control" id="due_date" name="due_date" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-primary">Add Bill</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<?php };
|
||||
|
||||
include __DIR__ . '/layouts/app.php';
|
||||
30
views/home.php
Normal file
30
views/home.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
// Assuming session_start() is called in the front controller or app.php
|
||||
|
||||
$content = function() { ?>
|
||||
<div class="jumbotron">
|
||||
<h1 class="display-4">Welcome to Bill Reminder!</h1>
|
||||
<p class="lead">Never miss a payment again with our easy-to-use bill management system.</p>
|
||||
<hr class="my-4">
|
||||
<p>Get started by logging in or registering a new account.</p>
|
||||
<a class="btn btn-primary btn-lg" href="/login" role="button">Login</a>
|
||||
<a class="btn btn-secondary btn-lg" href="/register" role="button">Register</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<h2>Track Your Bills</h2>
|
||||
<p>Keep all your bills in one place and get reminders so you can pay them on time, every time.</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h2>Easy to Use</h2>
|
||||
<p>Our intuitive interface makes managing your bills simple, whether you're at home or on the go.</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h2>Secure</h2>
|
||||
<p>Your security is our top priority. We use state-of-the-art security measures to protect your information.</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php };
|
||||
|
||||
include __DIR__ . '/layouts/app.php';
|
||||
32
views/layouts/app.php
Normal file
32
views/layouts/app.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Bill Reminder</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<a class="navbar-brand" href="#">Bill Reminder</a>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item"><a class="nav-link" href="/dashboard">Dashboard</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/settings">Settings</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item"><a class="nav-link" href="/logout">Logout</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<?php if (isset($content) && is_callable($content)) $content(); ?>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
||||
<script src="/assets/js/app.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user