backend-01

commit 7b2c9104b118757607263e59e1235f63069b82f1

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

all: flesh tag creation, deletion and register bills routes

 app/controllers/TagsController.php | 42 +++++++++++++++++++++++++++
 app/daos/TagDAO.php | 49 ++++++++++++++++++++++++++++++++
 app/models/Tag.php | 15 +++++++++
 app/views/tag_create.php | 19 ++++++++++++
 app/views/tags.php | 45 +++++++++++++++++++++++++++++
 config/routes.php | 38 ++++++++++++++++++++++++
 schema.sql | 26 ++++++++++++++++


diff --git a/app/controllers/TagsController.php b/app/controllers/TagsController.php
new file mode 100644
index 0000000000000000000000000000000000000000..82ee8c4de40c24e9fdc85cd6a7a13880693c65f3
--- /dev/null
+++ b/app/controllers/TagsController.php
@@ -0,0 +1,42 @@
+<?php
+
+require_once __DIR__ . '/../daos/TagDAO.php';
+require_once __DIR__ . '/../models/Tag.php';
+
+class TagsController {
+  private $tagDAO;
+
+  public function __construct() {
+    $this->tagDAO = new TagDAO();
+  }
+
+  public function index() {
+    $tags = $this->tagDAO->getAllTags();
+
+    return Template::render('tags', ['tags' => $tags]);
+  }
+
+  public function create() {
+    return Template::render('tag_create');
+  }
+
+  public function store() {
+    $data = $_POST;
+    $tag = new Tag(
+      null,
+      $data['name']
+    );
+
+    $this->tagDAO->save($tag);
+
+    header('Location: /tags');
+    exit;
+  }
+
+  public function destroy($id) {
+    $this->tagDAO->delete($id);
+
+    header('Location: /tags');
+    exit;
+  }
+}




diff --git a/app/daos/TagDAO.php b/app/daos/TagDAO.php
new file mode 100644
index 0000000000000000000000000000000000000000..b32edbb16d03e72939b1bca18863d3c6dc452123
--- /dev/null
+++ b/app/daos/TagDAO.php
@@ -0,0 +1,49 @@
+<?php
+
+require_once __DIR__ . '/../../config/database.php';
+require_once __DIR__ . '/../models/Tag.php';
+
+class TagDAO {
+  private $db;
+
+  public function __construct() {
+    $this->db = getDatabaseConnection();
+  }
+
+  public function getAllTags() {
+    $sql = "SELECT id, name FROM tags";
+    $stmt = $this->db->prepare($sql);
+    $stmt->execute();
+
+    $tagsData = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+    if ($tagsData) {
+      $tags = [];
+
+      foreach ($tagsData as $tagData) {
+        $tags[] = new Tag($tagData['id'], $tagData['name']);
+      }
+
+      return $tags;
+    } else {
+      return [];
+    }
+  }
+
+  public function save(Tag $tag) {
+    $sql = "INSERT INTO tags (name) VALUES (:name)";
+    $stmt = $this->db->prepare($sql);
+    $stmt->bindValue(':name', $tag->getName());
+
+    $stmt->execute();
+  }
+
+  public function delete($id) {
+    $sql = "DELETE FROM tags WHERE id = :id";
+    $stmt = $this->db->prepare($sql);
+    $stmt->bindParam(':id', $id);
+
+    $stmt->execute();
+  }
+}
+




diff --git a/app/models/Tag.php b/app/models/Tag.php
new file mode 100644
index 0000000000000000000000000000000000000000..1f513ac1d18087879122f9fd244c6516221dd0db
--- /dev/null
+++ b/app/models/Tag.php
@@ -0,0 +1,15 @@
+<?php
+
+class Tag extends Base {
+  private $name;
+
+  public function __construct($id, $name) {
+    $this->id = $id;
+    $this->name = $name;
+  }
+
+  public function getName() {
+    return $this->name;
+  }
+}
+




diff --git a/app/views/tag_create.php b/app/views/tag_create.php
new file mode 100644
index 0000000000000000000000000000000000000000..1275942e07accb619c227f119fa72192eb252d09
--- /dev/null
+++ b/app/views/tag_create.php
@@ -0,0 +1,19 @@
+<div class="container mx-auto mt-10">
+  <div class="flex justify-between items-center mb-6">
+    <h1 class="text-2xl font-bold text-gray-700">Adicionar Nova Tag</h1>
+  </div>
+
+  <form action="/tags/create" method="POST" class="bg-white shadow-md rounded-lg p-6">
+    <div class="mb-4">
+      <label for="name" class="block text-gray-700">Nome</label>
+      <input type="text" id="name" name="name" required class="w-full px-4 py-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-600">
+    </div>
+
+    <div class="flex justify-end">
+      <button type="submit" class="bg-blue-600 text-white py-2 px-6 rounded hover:bg-blue-700">
+        Salvar Tag
+      </button>
+    </div>
+  </form>
+</div>
+




diff --git a/app/views/tags.php b/app/views/tags.php
new file mode 100644
index 0000000000000000000000000000000000000000..f3086d2eb0b86db5e7739221b14408b9e99f5185
--- /dev/null
+++ b/app/views/tags.php
@@ -0,0 +1,45 @@
+<div class="container mx-auto mt-10">
+  <div class="flex justify-between items-center mb-6">
+    <h1 class="text-2xl font-bold text-gray-700">Tags</h1>
+    <a href="/tags/create" class="bg-blue-600 text-white py-2 px-4 rounded hover:bg-blue-700">
+      + Adicionar Nova Tag
+    </a>
+  </div>
+
+  <?php if (empty($tags)) : ?>
+    <div class="text-center py-10 bg-white rounded-lg shadow-md">
+      <p class="text-xl text-gray-600">Nenhuma tag encontrada.</p>
+      <p class="text-gray-500 mt-2">Crie uma tag para melhor organizar as contas.</p>
+      <a href="/tags/create" class="mt-4 inline-block bg-blue-600 text-white py-2 px-4 rounded hover:bg-blue-700">
+        + Adicionar Nova Tag
+      </a>
+    </div>
+  <?php else : ?>
+    <div class="bg-white shadow-md rounded-lg overflow-hidden">
+      <table class="min-w-full table-auto">
+        <thead>
+          <tr class="bg-gray-200">
+            <th class="py-3 px-6 text-left">Nome</th>
+            <th class="py-3 px-6 text-right">Ações</th>
+          </tr>
+        </thead>
+        <tbody>
+          <?php foreach ($tags as $tag) : ?>
+            <tr class="border-b">
+              <td class="py-3 px-6"><?= htmlspecialchars($tag->getName()) ?></td>
+              <td class="py-3 px-6 flex justify-end space-x-2">
+                <a href="/tags/edit/<?= $tag->getId() ?>" class="text-yellow-600 hover:text-yellow-700">
+                  Editar
+                </a>
+
+                <a href="/tags/delete/<?= $tag->getId() ?>" class="text-red-600 hover:text-red-700">
+                  Apagar
+                </a>
+              </td>
+            </tr>
+          <?php endforeach; ?>
+        </tbody>
+      </table>
+    </div>
+  <?php endif; ?>
+</div>




diff --git a/config/routes.php b/config/routes.php
index 699eaaac8ce184992a1f99d081c29094a55f323a..732e1588f1d35ecf5c2f11ee5eee0246c08abde8 100644
--- a/config/routes.php
+++ b/config/routes.php
@@ -4,6 +4,8 @@ // TODO: Usar um autoload aqui
 require_once '../app/controllers/HelloController.php';
 require_once '../app/controllers/AuthController.php';
 require_once '../app/controllers/DashboardController.php';
+require_once '../app/controllers/BillsController.php';
+require_once '../app/controllers/TagsController.php';
 
 return function() {
   $uri = trim($_SERVER['REQUEST_URI'], '/');
@@ -32,6 +34,42 @@
   // GET /dashboard
   } elseif ($uri === 'dashboard') {
     return (new DashboardController())->index();
+
+  // GET /bills/create
+  } elseif ($uri === 'bills/create' && $method === 'GET') {
+    return (new BillsController())->create();
+
+  // POST /bills/create
+  } elseif ($uri === 'bills/create' && $method === 'POST') {
+    return (new BillsController())->store();
+
+  // GET /bills/edit/{id}
+  } elseif (preg_match('/^bills\/edit\/(\d+)$/', $uri, $matches) && $method === 'GET') {
+    return (new BillsController())->edit($matches[1]);
+
+  // POST /bills/edit/{id}
+  } elseif (preg_match('/^bills\/edit\/(\d+)$/', $uri, $matches) && $method === 'POST') {
+    return (new BillsController())->update($matches[1]);
+
+  // GET /bills/delete/{id}
+  } elseif (preg_match('/^bills\/delete\/(\d+)$/', $uri, $matches) && $method === 'GET') {
+    return (new BillsController())->destroy($matches[1]);
+
+  // GET /tags
+  } elseif ($uri === 'tags' && $method === 'GET') {
+    return (new TagsController())->index();
+
+  // GET /tags/create
+  } elseif ($uri === 'tags/create' && $method === 'GET') {
+    return (new TagsController())->create();
+
+  // POST /tags/create
+  } elseif ($uri === 'tags/create' && $method === 'POST') {
+    return (new TagsController())->store();
+
+  // GET /tags/delete/{id}
+  } elseif (preg_match('/^tags\/delete\/(\d+)$/', $uri, $matches) && $method === 'GET') {
+    return (new TagsController())->destroy($matches[1]);
 
   // GET /logout
   } elseif ($uri === 'logout') {




diff --git a/schema.sql b/schema.sql
index 91491fedccf89ba637583a1b1d85c51b38c95100..556b7ed09a5cf6c4760707217f97d37f9697b2f0 100644
--- a/schema.sql
+++ b/schema.sql
@@ -6,3 +6,29 @@   email VARCHAR(255) NOT NULL,
   created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
   updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
 );
+
+CREATE TABLE IF NOT EXISTS tags (
+  id INTEGER PRIMARY KEY AUTOINCREMENT,
+  name VARCHAR(255) NOT NULL,
+  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE TABLE IF NOT EXISTS bills (
+  id INTEGER PRIMARY KEY AUTOINCREMENT,
+  user_id INTEGER NOT NULL,
+  title VARCHAR(255) NOT NULL,
+  amount DECIMAL(10, 2) NOT NULL,
+  due_date DATE NOT NULL,
+  paid BOOLEAN DEFAULT FALSE,
+  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+  FOREIGN KEY (user_id) REFERENCES users(id)
+);
+
+CREATE TABLE IF NOT EXISTS bill_tags (
+  bill_id INTEGER NOT NULL,
+  tag_id INTEGER NOT NULL,
+  FOREIGN KEY (bill_id) REFERENCES bills(id),
+  FOREIGN KEY (tag_id) REFERENCES tags(id)
+);