]> git repositories - QuestLog.git/commitdiff
added a delete task feature
authorbochard <mail@tenkyuu.dev>
Fri, 30 May 2025 13:16:04 +0000 (21:16 +0800)
committerbochard <mail@bochard.net>
Thu, 17 Jul 2025 11:41:16 +0000 (19:41 +0800)
Classes/Tasks.php
TODO.TXT
includes/dashboard.php
includes/delete_task.php
js/tasks.js

index 867a06dbab67d563f791491e687dbc347e4e84d9..5280b5a78b71d694e7c3876f0628fa4f4029679d 100644 (file)
@@ -27,10 +27,17 @@ class Tasks extends DbConn {
   }
 
   public function addTask($pdo, $userId, $task){
-    $query = 'INSERT INTO tasks (task, user_id) VALUES (:task, :userId)';
+    $query = 'INSERT INTO tasks (task, user_id) VALUES (:task, :userId);';
     $stmt = $pdo->prepare($query);
     $stmt->bindParam(':task', $task);
     $stmt->bindParam(':userId', $userId);
     $stmt->execute();
   }
+
+  public function deleteTask($pdo, $taskId){
+    $query = 'DELETE FROM tasks WHERE task_id = :taskId;';
+    $stmt = $pdo->prepare($query);
+    $stmt->bindParam(':taskId', $taskId);
+    $stmt->execute();
+  }
 }
\ No newline at end of file
index 9ff158de96975ed7d522286b1edb9b006cf43b8f..b517d734ecbb96b0aec2176ad1fe922e58697be3 100644 (file)
--- a/TODO.TXT
+++ b/TODO.TXT
@@ -1,8 +1,7 @@
 1. encrypt passwords on signup
 2. add a session timer when user logged in
 3. don't give direct access to paths esp. when usr. is not logged in or that path must not be accessible
-4. add a short animation loading progress bar when user did some actions to a task 
-5. create 'deleting task' feature
+4. add a short animation loading progress bar when user did some actions to a task
 6. create 'editing task' feature
 7. create 'task sorting' feature
 8. create 'task search' feature
\ No newline at end of file
index 72ca48b7163f0e72b5d5d526f3eb99a48d5d68df..0b013c12ffc495634629646e48d7f31d440a3cde 100644 (file)
     transition-duration: 0.2s;
     transition-property: visibility, opacity;
   }
+  .table-container {
+    overflow: hidden;
+    overflow-y: scroll;
+    height: 200px;
+  }
+  thead {
+    top: 0;
+    z-index: 2;
+    position: sticky;
+  }
+  table {
+    width: 290px;
+  }
 </style>
 </head>
 <body style="display: flex; justify-content: center; align-items: center;">
         <button type="button" id="new-task-popup-open">Add task</button>
       </div>
 
-      <div class="field-row-stacked">
+      <div class="field-row-stacked" style="float: right; margin-left: 7px;">
+        <button type="button" id="edit-task" disabled>Edit</button>
+        <button type="button" id="delete-task" disabled>Delete</button>
+      </div>
+
+      <div class="field-row-stacked table-container">
         <table class="has-shadow">
           <thead>
             <tr>
-              <th style="width: 25px;"></th>
-              <th>task</th>
-              <th>created date</th>
+              <th style="width: 15%;"></th>
+              <th style="width: 85%; text-align: center;">Task</th>
             </tr>
           </thead>
           <tbody id="task-body">
index e1898f325a50d5c1a80760e2ed684dffd06bde53..d4eced75eda9b6c164ff81f07b112f50a3080192 100644 (file)
@@ -10,5 +10,38 @@ require_once __DIR__ . '/../Classes/Tasks.php';
 header('Content-Type: application/json');
 
 if($_SERVER['REQUEST_METHOD'] === 'POST'){
-  // will add here soon...
+  $taskIds = json_decode(file_get_contents('php://input'), true);
+
+  try{
+    $dbconn = new DbConn();
+    $pdo = $dbconn->getPdo();
+
+    $userId = $_SESSION['user_data']['user_id'];
+    $tasks = new Tasks($pdo, $userId);
+    $error = $tasks->error;
+    
+    foreach($taskIds as $taskId){
+      $tasks->isInputEmpty($taskId);
+      if(empty($error)){
+        $tasks->deleteTask($pdo, $taskId);
+      }
+    }
+
+    if(empty($error)){
+      $response = [
+        'status' => 'success',
+        'message' => 'Task deleted successfully!',
+      ];
+    } else{
+      $response = [
+        'status' => 'failed',
+        'message' => 'Failed to delete task.',
+      ];
+    }
+
+    echo json_encode($response);
+
+  } catch(PDOException $e){
+    die("Query failed: {$e}");
+  }
 }
\ No newline at end of file
index 59c85e0e434d1c02574485060802336ec10276e5..f60b14fa98e29b5cf3bc59a5a56c601880c069ed 100644 (file)
@@ -16,14 +16,16 @@ function loadTasks(){ // fetching tasks on database
         const tr = document.createElement('tr');
         tr.innerHTML = `
           <td style="text-align: center;">
-            <input type="checkbox" id="checkbox_${task.task_id}">
-            <label for="checkbox_${task.task_id}"></label>
+            <input type="checkbox" id="${task.task_id}">
+            <label for="${task.task_id}"></label>
           </td>
           <td>${task.task}</td>
-          <td>${task.created_datetime}</td>
         `;
 
         tbody.appendChild(tr);
+
+        // listen for checkboxes after loading tasks in DOM
+        addCheckboxListeners();
       });
     } else{
       const tr = document.createElement('tr');
@@ -36,6 +38,34 @@ function loadTasks(){ // fetching tasks on database
   });
 }
 
+function addCheckboxListeners(){
+  const checkboxes = document.querySelectorAll('#task-body input[type="checkbox"]');
+
+  checkboxes.forEach(function(checkbox){
+    checkbox.addEventListener('change', function(){
+      const isAnyChecked = Array.from(checkboxes).some(function(checkbox){
+        return checkbox.checked;
+      });
+
+      if(isAnyChecked){
+        removeDisabledAttributes();
+      } else{
+        setDisabledAttributes();
+      }
+    });
+  });
+}
+
+function removeDisabledAttributes(){
+  document.getElementById('edit-task').removeAttribute('disabled');
+  document.getElementById('delete-task').removeAttribute('disabled');
+};
+
+function setDisabledAttributes(){
+  document.getElementById('edit-task').setAttribute('disabled', true);
+  document.getElementById('delete-task').setAttribute('disabled', true);
+};
+
 function addTask(){ // adding task on database
   const taskInput = document.getElementById('task-name');
   const formData = new FormData(addTaskForm);
@@ -59,16 +89,48 @@ function addTask(){ // adding task on database
     console.log('Response from server:', data);
     console.log('Status:', data.status);
     console.log('Message:', data.message);
+    setTimeout(function(){
+    loadTasks();
+    }, 500);
+    setDisabledAttributes();
+    popupNewTaskClose();
   })
-  .catch(function(err){
-    console.error(err);
+  .catch(function(error){
+    console.error(error);
   });
-    
-  setTimeout(function(){
+}
+
+function deleteTask(){
+  const checkboxes = document.querySelectorAll('#task-body input[type="checkbox"]');
+  let isCheckedArray = [];
+
+  for(let checkbox of checkboxes){
+    if(checkbox.checked){
+      isCheckedArray.push(checkbox.id);
+    }
+  }
+
+  // after iterating and finding the id of a checkbox that is checked...
+  fetch('./includes/delete_task.php', {
+    method: 'POST',
+    headers: { 'Content-Type': 'application/json' },
+    body: JSON.stringify(isCheckedArray)
+  })
+  .then(function(response){
+    return response.json();
+  })
+  .then(function(data){
+    console.log('Response from server:', data);
+    console.log('Status:', data.status);
+    console.log('Message:', data.message);
+    setTimeout(function(){
     loadTasks();
-  }, 500);
-  
-  popupNewTaskClose();
+    }, 500);
+    setDisabledAttributes();
+  })
+  .catch(function(error){
+    console.error(error);
+  });
 }
 
 function resetTaskInputPlaceholder(){
@@ -110,6 +172,10 @@ document.getElementById('add-task-form').addEventListener('submit', function(e){
   addTask();
 });
 
+document.getElementById('delete-task').addEventListener('click', function(e){
+  e.preventDefault();
+  deleteTask();
+});
 
 // calls
 loadTasks();
\ No newline at end of file