backend-01

commit 0d12e43b8d89422bf5623c07f37a476907e5abe9

Author: Pedro Lucas Porcellis <porcellis@eletrotupi.com>

all: flesh out creating a bill

 app/controllers/BillsController.php | 51 +++++++++++++++++++
 app/daos/BillDAO.php | 82 +++++++++++++++++++++++++++++++
 app/models/Bill.php | 69 ++++++++++++++++++++++++++
 app/views/bill_create.php | 46 +++++++++++++++++


diff --git a/app/controllers/BillsController.php b/app/controllers/BillsController.php
new file mode 100644
index 0000000000000000000000000000000000000000..ba3543b5e49a43011ad72a21d1a19bf9be6950a6
--- /dev/null
+++ b/app/controllers/BillsController.php
@@ -0,0 +1,51 @@
+<?php
+
+require_once __DIR__ . '/../daos/BillDAO.php';
+require_once __DIR__ . '/../daos/TagDAO.php';
+require_once __DIR__ . '/../models/Bill.php';
+
+class BillsController {
+  private $billDAO;
+  private $tagDAO;
+
+  public function __construct() {
+    $this->billDAO = new BillDAO();
+    $this->tagDAO = new TagDAO();
+  }
+
+  public function create() {
+    $tags = $this->tagDAO->getAllTags();
+
+    return Template::render('bill_create', ['tags' => $tags]);
+  }
+
+  public function store() {
+    $data = $_POST;
+    $bill = new Bill(
+      null,
+      $data['title'],
+      $data['amount'],
+      $data['due_date'],
+      isset($data['paid']) ? true : false,
+      $_SESSION['user_id'],
+      []
+    );
+
+    $this->billDAO->create($bill, $data['tags']);
+
+    header('Location: /dashboard');
+    exit;
+  }
+
+  public function edit($id) {
+    // TODO: Implement edit method
+  }
+
+  public function update($id) {
+    // TODO: Implement update method
+  }
+
+  public function destroy($id) {
+    // TODO: Implement destroy method
+  }
+}




diff --git a/app/daos/BillDAO.php b/app/daos/BillDAO.php
new file mode 100644
index 0000000000000000000000000000000000000000..50eaa5a839935bcfdaa1b3ea11c236647097f48d
--- /dev/null
+++ b/app/daos/BillDAO.php
@@ -0,0 +1,82 @@
+<?php
+
+require_once __DIR__ . '/../../config/database.php';
+require_once __DIR__ . '/../models/Bill.php';
+
+class BillDAO {
+  private $db;
+
+  public function __construct() {
+    $this->db = getDatabaseConnection();
+  }
+
+  public function findAllByUserId($userId) {
+    $sql = 'SELECT b.*, GROUP_CONCAT(t.name) AS tags
+            FROM bills b
+            LEFT JOIN bill_tags bt ON b.id = bt.bill_id
+            LEFT JOIN tags t ON bt.tag_id = t.id
+            WHERE b.user_id = :user_id
+            GROUP BY b.id';
+
+    $stmt = $this->db->prepare($sql);
+    $stmt->bindParam(':user_id', $userId);
+    $stmt->execute();
+
+    $bills = [];
+
+    while ($billData = $stmt->fetch(PDO::FETCH_ASSOC)) {
+      $bills[] = new Bill(
+        $billData['id'],
+        $billData['title'],
+        $billData['amount'],
+        $billData['due_date'],
+        $billData['paid'],
+        $billData['user_id'],
+        $billData['tags']
+      );
+    }
+
+    return $bills;
+  }
+
+  public function create(Bill $bill, $tagIds) {
+    $this->db->beginTransaction();
+
+    try {
+      $stmt = $this->db->prepare('
+        INSERT INTO bills (title, amount, due_date, paid, user_id)
+        VALUES (:title, :amount, :due_date, :paid, :user_id)
+      ');
+
+      $stmt->bindValue(':title', $bill->getTitle());
+      $stmt->bindValue(':amount', $bill->getAmount());
+      $stmt->bindValue(':due_date', $bill->getDueDate());
+      $stmt->bindValue(':paid', $bill->isPaid());
+      $stmt->bindValue(':user_id', $bill->getUserId());
+      $stmt->execute();
+
+      $billId = $this->db->lastInsertId();
+
+      foreach ($tagIds as $tagId) {
+        $stmt = $this->db->prepare('
+          INSERT INTO bill_tags (bill_id, tag_id)
+          VALUES (:bill_id, :tag_id)
+        ');
+
+        $stmt->bindParam(':bill_id', $billId);
+        $stmt->bindParam(':tag_id', $tagId);
+        $stmt->execute();
+      }
+
+      $this->db->commit();
+
+      $bill->setId($billId);
+      $bill->setTags($tagIds);
+
+      return $bill;
+    } catch (Exception $e) {
+      $this->db->rollBack();
+      throw $e;
+    }
+  }
+}




diff --git a/app/models/Bill.php b/app/models/Bill.php
new file mode 100644
index 0000000000000000000000000000000000000000..18cec99b4cf17f00241059660735715bdd3ba052
--- /dev/null
+++ b/app/models/Bill.php
@@ -0,0 +1,69 @@
+<?php
+
+class Bill extends Base {
+  private $title;
+  private $amount;
+  private $dueDate;
+  private $paid;
+
+  private $userId;
+  private $tags;
+
+  public function __construct($id, $title, $amount, $dueDate, $paid, $userId, $tags) {
+    $this->id = $id;
+    $this->title = $title;
+    $this->amount = $amount;
+    $this->dueDate = $dueDate;
+    $this->paid = $paid;
+    $this->userId = $userId;
+    $this->tags = $tags;
+  }
+
+  public function getTitle() {
+    return $this->title;
+  }
+
+  public function getAmount() {
+    return $this->amount;
+  }
+
+  public function getDueDate() {
+    return $this->dueDate;
+  }
+
+  public function isPaid() {
+    return $this->paid;
+  }
+
+  public function setAmount($amount) {
+    $this->amount = $amount;
+  }
+
+  public function setDueDate($dueDate) {
+    $this->dueDate = $dueDate;
+  }
+
+  public function setPaid($paid) {
+    $this->paid = $paid;
+  }
+
+  public function getUserId() {
+    return $this->userId;
+  }
+
+  public function getTags() {
+    return $this->tags;
+  }
+
+  public function setTags($tags) {
+    $this->tags = $tags;
+  }
+
+  public function toArray() {
+    return [
+      'amount' => $this->amount,
+      'dueDate' => $this->dueDate,
+      'paid' => $this->paid
+    ];
+  }
+}




diff --git a/app/views/bill_create.php b/app/views/bill_create.php
new file mode 100644
index 0000000000000000000000000000000000000000..eb2ae5d2b32e6a390ded886f9120ed75d3a10dca
--- /dev/null
+++ b/app/views/bill_create.php
@@ -0,0 +1,46 @@
+<div class="container mx-auto mt-10">
+  <h1 class="text-2xl font-bold text-gray-700 mb-6">Adicionar Novo Gasto</h1>
+
+  <form action="/bills/create" method="POST" class="bg-white p-6 rounded shadow-md">
+    <div class="mb-4">
+      <label for="title" class="block text-sm font-medium text-gray-700">Título</label>
+      <input type="text" id="title" name="title" class="mt-1 block w-full border border-gray-300 rounded p-2" required />
+    </div>
+
+    <div class="mb-4">
+      <label for="amount" class="block text-sm font-medium text-gray-700">Valor</label>
+      <input type="number" id="amount" name="amount" class="mt-1 block w-full border border-gray-300 rounded p-2" required />
+    </div>
+
+    <div class="mb-4">
+      <label for="due_date" class="block text-sm font-medium text-gray-700">Vencimento</label>
+      <input type="date" id="due_date" name="due_date" class="mt-1 block w-full border border-gray-300 rounded p-2" required />
+    </div>
+
+    <div class="mb-4">
+      <label class="block text-sm font-medium text-gray-700">Tags</label>
+      <?php foreach ($tags as $tag) : ?>
+        <div class="flex items-center mb-2">
+          <input type="checkbox" name="tags[]" value="<?= htmlspecialchars($tag->getId()) ?>" id="tag_<?= $tag->getId() ?>" class="mr-2" />
+
+          <label for="tag_<?= $tag->getName() ?>" class="text-sm text-gray-700">
+            <?= htmlspecialchars($tag->getName()) ?>
+          </label>
+        </div>
+      <?php endforeach; ?>
+    </div>
+
+    <div class="mb-4">
+      <label class="flex items-center text-sm font-medium text-gray-700">
+      <input type="checkbox" name="paid" class="mr-2" />
+        Pago?
+      </label>
+    </div>
+
+    <div>
+      <button type="submit" class="bg-blue-600 text-white py-2 px-4 rounded hover:bg-blue-700">
+        Salvar Gasto
+      </button>
+    </div>
+  </form>
+</div>