From 532df6b9be673df502af3d00577093b258d19ccc Mon Sep 17 00:00:00 2001 From: Brad Cimbura Date: Fri, 9 Feb 2024 20:52:11 -0600 Subject: [PATCH] initial code commit --- Model/Bill.php | 21 ++++++ Model/User.php | 20 ++++++ Service/BillManager.php | 69 ++++++++++++++++++ Service/UserManager.php | 42 +++++++++++ View/PageRenderer.php | 32 +++++++++ composer.json | 9 ++- index.php | 27 +++++++ setup.php | 14 ++++ src/Database/DatabaseInterface.php | 14 ++++ src/Database/DatabaseSetup.php | 44 ++++++++++++ src/Database/SQLite3Database.php | 83 ++++++++++++++++++++++ src/Notification/NftyNotification.php | 44 ++++++++++++ src/Notification/NotificationInterface.php | 15 ++++ views/404.php | 0 views/dashboard.php | 50 +++++++++++++ views/home.php | 30 ++++++++ views/login.php | 35 +++++++++ views/register.php | 35 +++++++++ 18 files changed, 583 insertions(+), 1 deletion(-) create mode 100644 Model/Bill.php create mode 100644 Model/User.php create mode 100644 Service/BillManager.php create mode 100644 Service/UserManager.php create mode 100644 View/PageRenderer.php create mode 100644 index.php create mode 100644 setup.php create mode 100644 src/Database/DatabaseInterface.php create mode 100644 src/Database/DatabaseSetup.php create mode 100644 src/Database/SQLite3Database.php create mode 100644 src/Notification/NftyNotification.php create mode 100644 src/Notification/NotificationInterface.php create mode 100644 views/404.php create mode 100644 views/dashboard.php create mode 100644 views/home.php create mode 100644 views/login.php create mode 100644 views/register.php diff --git a/Model/Bill.php b/Model/Bill.php new file mode 100644 index 0000000..caff8fa --- /dev/null +++ b/Model/Bill.php @@ -0,0 +1,21 @@ +id = $id; + $this->dueDate = $dueDate; + $this->amount = $amount; + $this->description = $description; + $this->isPaid = $isPaid; + } + + // Additional methods as needed, such as getters and setters +} diff --git a/Model/User.php b/Model/User.php new file mode 100644 index 0000000..4e8e3ca --- /dev/null +++ b/Model/User.php @@ -0,0 +1,20 @@ +id = $id; + $this->username = $username; + $this->passwordHash = $passwordHash; + } + + // Add methods for password verification, etc. + public function verifyPassword(string $password): bool { + return password_verify($password, $this->passwordHash); + } +} diff --git a/Service/BillManager.php b/Service/BillManager.php new file mode 100644 index 0000000..bd6aa4e --- /dev/null +++ b/Service/BillManager.php @@ -0,0 +1,69 @@ +db = $db; + } + + public function createBill(Bill $bill): bool { + $sql = "INSERT INTO bills (dueDate, amount, description, isPaid) VALUES (:dueDate, :amount, :description, :isPaid)"; + $this->db->prepare($sql); + $this->db->execute([ + ':dueDate' => $bill->dueDate, + ':amount' => $bill->amount, + ':description' => $bill->description, + ':isPaid' => $bill->isPaid ? 1 : 0, + ]); + return $this->db->lastInsertId() > 0; + } + + public function getBill(int $id): ?Bill { + $sql = "SELECT * FROM bills WHERE id = :id"; + $this->db->prepare($sql); + $this->db->execute([':id' => $id]); + $result = $this->db->fetch(); + if ($result) { + return new Bill($result['id'], $result['dueDate'], $result['amount'], $result['description'], $result['isPaid'] == 1); + } + return null; + } + + + public function updateBill(Bill $bill): bool { + $sql = "UPDATE bills SET dueDate = :dueDate, amount = :amount, description = :description, isPaid = :isPaid WHERE id = :id"; + $this->db->prepare($sql); + return $this->db->execute([ + ':id' => $bill->id, + ':dueDate' => $bill->dueDate, + ':amount' => $bill->amount, + ':description' => $bill->description, + ':isPaid' => $bill->isPaid ? 1 : 0, + ]); + } + + + public function deleteBill(int $id): bool { + $sql = "DELETE FROM bills WHERE id = :id"; + $this->db->prepare($sql); + return $this->db->execute([':id' => $id]); + } + + + public function listBills(): array { + $sql = "SELECT * FROM bills"; + $this->db->prepare($sql); + $this->db->execute(); + $bills = []; + while ($row = $this->db->fetch()) { + $bills[] = new Bill($row['id'], $row['dueDate'], $row['amount'], $row['description'], $row['isPaid'] == 1); + } + return $bills; + } +} diff --git a/Service/UserManager.php b/Service/UserManager.php new file mode 100644 index 0000000..66606cd --- /dev/null +++ b/Service/UserManager.php @@ -0,0 +1,42 @@ +db = $db; + } + + public function register(string $username, string $password): bool { + $passwordHash = password_hash($password, PASSWORD_DEFAULT); + + $sql = "INSERT INTO users (username, passwordHash) VALUES (:username, :passwordHash)"; + $this->db->prepare($sql); + return $this->db->execute([ + ':username' => $username, + ':passwordHash' => $passwordHash, + ]); + } + + public function login(string $username, string $password): ?User { + $sql = "SELECT * FROM users WHERE username = :username"; + $this->db->prepare($sql); + $this->db->execute([':username' => $username]); + $result = $this->db->fetch(); + + if ($result && (new User($result['id'], $result['username'], $result['passwordHash']))->verifyPassword($password)) { + // Start or regenerate the session + session_regenerate_id(); + $_SESSION['user_id'] = $result['id']; + return new User($result['id'], $result['username'], $result['passwordHash']); + } + + return null; + } + + // Additional methods as needed, e.g., for password change, user details update, etc. +} diff --git a/View/PageRenderer.php b/View/PageRenderer.php new file mode 100644 index 0000000..a83ae65 --- /dev/null +++ b/View/PageRenderer.php @@ -0,0 +1,32 @@ + + + + + + + $title + + + + +
+HTML; + } + + public static function renderFooter() { + echo << + + + + + +HTML; + } +} diff --git a/composer.json b/composer.json index b22cd92..700713b 100644 --- a/composer.json +++ b/composer.json @@ -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" + } } diff --git a/index.php b/index.php new file mode 100644 index 0000000..6609e75 --- /dev/null +++ b/index.php @@ -0,0 +1,27 @@ +connect(); + +$databaseSetup = new DatabaseSetup($db); +$databaseSetup->setup(); + +// Continue with the rest of your application setup diff --git a/src/Database/DatabaseInterface.php b/src/Database/DatabaseInterface.php new file mode 100644 index 0000000..9a715c9 --- /dev/null +++ b/src/Database/DatabaseInterface.php @@ -0,0 +1,14 @@ +db = $db; + } + + public function setup(): void { + $this->createBillsTable(); + $this->createUsersTable(); + } + + private function createBillsTable(): void { + $sql = <<db->query($sql); + } + + private function createUsersTable(): void { + $sql = <<db->query($sql); + } + + // Additional methods to setup other tables as needed +} diff --git a/src/Database/SQLite3Database.php b/src/Database/SQLite3Database.php new file mode 100644 index 0000000..98866d5 --- /dev/null +++ b/src/Database/SQLite3Database.php @@ -0,0 +1,83 @@ +databaseFile = $databaseFile; + } + + public function connect() { + try { + $this->connection = new SQLite3($this->databaseFile); + } catch (Exception $e) { + throw new Exception("Unable to connect to SQLite database: " . $e->getMessage()); + } + } + + public function query(string $query) { + if (!$this->connection) { + throw new Exception("No database connection"); + } + return $this->connection->query($query); + } + + public function prepare(string $sql) { + if (!$this->connection) { + throw new Exception("No database connection"); + } + $this->statement = $this->connection->prepare($sql); + if (!$this->statement) { + throw new Exception("Failed to prepare SQL statement"); + } + } + + public function execute(array $parameters = []) { + if (!$this->statement) { + throw new Exception("No prepared statement"); + } + foreach ($parameters as $param => $value) { + $this->statement->bindValue($param, $value); + } + return $this->statement->execute(); + } + + public function fetch() { + if (!$this->statement) { + throw new Exception("No prepared statement"); + } + return $this->statement->fetchArray(SQLITE3_ASSOC); + } + + public function fetchAll() { + $data = []; + while ($row = $this->fetch()) { + $data[] = $row; + } + return $data; + } + + public function close() { + if ($this->connection) { + $this->connection->close(); + } + } +} diff --git a/src/Notification/NftyNotification.php b/src/Notification/NftyNotification.php new file mode 100644 index 0000000..50e8c98 --- /dev/null +++ b/src/Notification/NftyNotification.php @@ -0,0 +1,44 @@ +restClient = $restClient; + } + + public function send(string $to, string $message, array $options = []): bool { + try { + // ntfy.sh uses simple text/plain content type for the message body + $headers = ["Content-Type: text/plain"]; + if (isset($options['title'])) { + $headers[] = "Title: {$options['title']}"; + } + if (isset($options['priority'])) { + $headers[] = "Priority: {$options['priority']}"; + } + if (isset($options['tags'])) { + $headers[] = "Tags: {$options['tags']}"; + } + + $this->restClient->setHeaders($headers); + + // Use the RestClient's custom request method to mimic the file_get_contents approach + $this->restClient->post("https://ntfy.sh/{$this->to}", $message); + + // Since ntfy.sh returns a simple response, we might not need to decode JSON + $response = $this->restClient->getResponse(); + + // Check the response or HTTP status code as needed to determine success + return true; // Assuming the request was successful, adjust based on actual response handling + } catch (Exception $e) { + // Error handling logic + return false; + } + } +} diff --git a/src/Notification/NotificationInterface.php b/src/Notification/NotificationInterface.php new file mode 100644 index 0000000..51f5b48 --- /dev/null +++ b/src/Notification/NotificationInterface.php @@ -0,0 +1,15 @@ + + +

My Bills

+Add New Bill +
+ + + + + + + + + + + + + + + + + + + + + +
Due DateAmountDescriptionStatusActions
dueDate); ?>amount); ?>description); ?>isPaid ? 'Paid' : 'Pending'; ?> + Edit + Delete +
+
+ + diff --git a/views/home.php b/views/home.php new file mode 100644 index 0000000..72d7ded --- /dev/null +++ b/views/home.php @@ -0,0 +1,30 @@ + + +

Welcome to Bill Reminder

+

Manage your bills efficiently and never miss a payment.

+ + +

Hello, !

+ Go to Dashboard + Logout + + Login + Register + + + \ No newline at end of file diff --git a/views/login.php b/views/login.php new file mode 100644 index 0000000..e0c232e --- /dev/null +++ b/views/login.php @@ -0,0 +1,35 @@ + + + + + + Login + + + + +
+

Login

+
+
+ + +
+
+ + +
+ +
+
+ + + diff --git a/views/register.php b/views/register.php new file mode 100644 index 0000000..53951e5 --- /dev/null +++ b/views/register.php @@ -0,0 +1,35 @@ + + + + + + Register + + + + +
+

Register

+
+
+ + +
+
+ + +
+ +
+
+ + +