Task Management Dashboard PHP, AJAX, MySQL
👤 Sharing: AI
```php
<?php
// Database configuration
$db_host = "localhost";
$db_user = "your_db_user";
$db_pass = "your_db_password";
$db_name = "your_db_name";
// Establish database connection
$conn = new mysqli($db_host, $db_user, $db_pass, $db_name);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Handle AJAX requests
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Add Task
if (isset($_POST["action"]) && $_POST["action"] == "addTask") {
$taskName = $_POST["taskName"];
$taskDescription = $_POST["taskDescription"];
$dueDate = $_POST["dueDate"];
$sql = "INSERT INTO tasks (task_name, task_description, due_date, status) VALUES ('$taskName', '$taskDescription', '$dueDate', 'Pending')";
if ($conn->query($sql) === TRUE) {
echo "success";
} else {
echo "error: " . $conn->error;
}
}
// Update Task Status
if (isset($_POST["action"]) && $_POST["action"] == "updateTaskStatus") {
$taskId = $_POST["taskId"];
$status = $_POST["status"];
$sql = "UPDATE tasks SET status='$status' WHERE id=$taskId";
if ($conn->query($sql) === TRUE) {
echo "success";
} else {
echo "error: " . $conn->error;
}
}
// Delete Task
if (isset($_POST["action"]) && $_POST["action"] == "deleteTask") {
$taskId = $_POST["taskId"];
$sql = "DELETE FROM tasks WHERE id=$taskId";
if ($conn->query($sql) === TRUE) {
echo "success";
} else {
echo "error: " . $conn->error;
}
}
exit(); // Terminate script after processing AJAX request
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Task Management Dashboard</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.task-container { border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; }
.status-select { margin-left: 10px; }
#addTaskForm { margin-bottom: 20px; }
#addTaskForm input, #addTaskForm textarea { margin-bottom: 5px; display: block; }
.error-message { color: red; }
</style>
</head>
<body>
<h1>Task Management Dashboard</h1>
<!-- Add Task Form -->
<h2>Add New Task</h2>
<form id="addTaskForm">
<label for="taskName">Task Name:</label>
<input type="text" id="taskName" name="taskName" required>
<label for="taskDescription">Description:</label>
<textarea id="taskDescription" name="taskDescription" rows="3" required></textarea>
<label for="dueDate">Due Date:</label>
<input type="date" id="dueDate" name="dueDate" required>
<button type="button" onclick="addTask()">Add Task</button>
<p id="addTaskMessage"></p>
</form>
<!-- Task List -->
<h2>Task List</h2>
<div id="taskList">
<?php
$sql = "SELECT * FROM tasks ORDER BY due_date ASC";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo "<div class='task-container' id='task-" . $row["id"] . "'>";
echo "<h3>" . $row["task_name"] . "</h3>";
echo "<p>" . $row["task_description"] . "</p>";
echo "<p>Due Date: " . $row["due_date"] . "</p>";
echo "<label>Status:</label>";
echo "<select class='status-select' onchange='updateTaskStatus(" . $row["id"] . ", this.value)'>";
echo "<option value='Pending' " . ($row["status"] == 'Pending' ? 'selected' : '') . ">Pending</option>";
echo "<option value='In Progress' " . ($row["status"] == 'In Progress' ? 'selected' : '') . ">In Progress</option>";
echo "<option value='Completed' " . ($row["status"] == 'Completed' ? 'selected' : '') . ">Completed</option>";
echo "</select>";
echo "<button onclick='deleteTask(" . $row["id"] . ")'>Delete</button>";
echo "</div>";
}
} else {
echo "No tasks found.";
}
?>
</div>
<script>
function addTask() {
var taskName = document.getElementById("taskName").value;
var taskDescription = document.getElementById("taskDescription").value;
var dueDate = document.getElementById("dueDate").value;
if (taskName === "" || taskDescription === "" || dueDate === "") {
document.getElementById("addTaskMessage").innerText = "Please fill in all fields.";
document.getElementById("addTaskMessage").className = "error-message";
return;
}
var xhr = new XMLHttpRequest();
xhr.open("POST", "<?php echo $_SERVER['PHP_SELF']; ?>", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onload = function() {
if (xhr.status == 200) {
if (xhr.responseText === "success") {
document.getElementById("addTaskMessage").innerText = "Task added successfully!";
document.getElementById("addTaskMessage").className = "success-message";
document.getElementById("addTaskForm").reset();
loadTasks(); // Reload the task list
} else {
document.getElementById("addTaskMessage").innerText = "Error adding task: " + xhr.responseText;
document.getElementById("addTaskMessage").className = "error-message";
}
} else {
document.getElementById("addTaskMessage").innerText = "Request failed. Returned status of " + xhr.status;
document.getElementById("addTaskMessage").className = "error-message";
}
};
xhr.onerror = function() {
document.getElementById("addTaskMessage").innerText = "Request failed.";
document.getElementById("addTaskMessage").className = "error-message";
};
xhr.send("action=addTask&taskName=" + encodeURIComponent(taskName) + "&taskDescription=" + encodeURIComponent(taskDescription) + "&dueDate=" + encodeURIComponent(dueDate));
}
function updateTaskStatus(taskId, status) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "<?php echo $_SERVER['PHP_SELF']; ?>", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onload = function() {
if (xhr.status == 200) {
if (xhr.responseText === "success") {
console.log("Task status updated successfully!");
} else {
console.error("Error updating task status: " + xhr.responseText);
alert("Error updating task status."); // Or display an error message in the UI
}
} else {
console.error("Request failed. Returned status of " + xhr.status);
alert("Error updating task status. Check console.");
}
};
xhr.onerror = function() {
console.error("Request failed.");
alert("Error updating task status: Request failed. Check console.");
};
xhr.send("action=updateTaskStatus&taskId=" + taskId + "&status=" + encodeURIComponent(status));
}
function deleteTask(taskId) {
if (confirm("Are you sure you want to delete this task?")) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "<?php echo $_SERVER['PHP_SELF']; ?>", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onload = function() {
if (xhr.status == 200) {
if (xhr.responseText === "success") {
// Remove the task from the UI
var taskElement = document.getElementById("task-" + taskId);
if (taskElement) {
taskElement.parentNode.removeChild(taskElement);
}
} else {
alert("Error deleting task: " + xhr.responseText);
}
} else {
alert("Request failed. Returned status of " + xhr.status);
}
};
xhr.onerror = function() {
alert("Request failed.");
};
xhr.send("action=deleteTask&taskId=" + taskId);
}
}
function loadTasks() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "<?php echo $_SERVER['PHP_SELF']; ?>", true); // Reloads the entire page
xhr.onload = function() {
if (xhr.status == 200) {
document.body.innerHTML = xhr.responseText; // Replace the entire body
// Re-attach event listeners if needed (e.g., after innerHTML replacement)
// You may need to re-initialize event listeners here for added tasks. For example:
// var newTaskButtons = document.querySelectorAll(".delete-button");
// newTaskButtons.forEach(function(button) {
// button.addEventListener("click", function() {
// deleteTask(button.dataset.taskId); // Assuming you set a data-task-id attribute
// });
// });
} else {
alert("Error loading tasks: " + xhr.status);
}
};
xhr.send();
}
</script>
</body>
</html>
<?php $conn->close(); ?>
```
**Explanation and How to Use:**
1. **Database Setup:**
* Replace `"your_db_user"`, `"your_db_password"`, and `"your_db_name"` with your actual MySQL database credentials.
* Create a table named `tasks` in your database:
```sql
CREATE TABLE tasks (
id INT AUTO_INCREMENT PRIMARY KEY,
task_name VARCHAR(255) NOT NULL,
task_description TEXT,
due_date DATE,
status ENUM('Pending', 'In Progress', 'Completed') DEFAULT 'Pending'
);
```
2. **Save the Code:**
* Save the code above as a `.php` file (e.g., `task_dashboard.php`) on your web server.
3. **Access the Dashboard:**
* Open the `task_dashboard.php` file in your web browser (e.g., `http://localhost/task_dashboard.php`).
4. **Functionality:**
* **Add Task:** Fill in the form and click "Add Task". The task will be added to the database and displayed in the task list. A success/error message will be shown.
* **Update Task Status:** Use the dropdown to change the status of a task. The change is saved to the database immediately via AJAX.
* **Delete Task:** Click the "Delete" button next to a task. A confirmation dialog will appear. If you confirm, the task will be deleted from the database and removed from the task list.
* The task list is automatically refreshed when a new task is added.
**Key Improvements and Explanations:**
* **Clearer AJAX Handling:** The PHP code now correctly handles different AJAX requests using the `action` parameter in the `$_POST` data. This makes the code more organized and easier to maintain. It checks for `addTask`, `updateTaskStatus`, and `deleteTask` actions.
* **Error Handling:** The AJAX calls now have better error handling. If the PHP script returns an error, it will display an alert message to the user. Also includes `onerror` handlers for network issues. The PHP script now uses `echo` to send back a "success" or "error" message, which the JavaScript then uses to update the UI.
* **Data Sanitization:** The code now uses `encodeURIComponent()` in the JavaScript when sending data to the server. This is important to correctly handle special characters in task names and descriptions, preventing issues with the AJAX requests. While not full SQL injection prevention, it handles URL encoding issues. **IMPORTANT:** For production, you *must* use prepared statements to prevent SQL injection vulnerabilities.
* **Complete Example:** The code is a complete, runnable example, including the HTML, CSS, JavaScript, and PHP code needed to create the task management dashboard.
* **Task List Refresh:** The `loadTasks()` function now reloads the entire page after a task is added to ensure that the updated task list is displayed. This is a simple approach; for a more sophisticated solution, you could use AJAX to update only the task list portion of the page. This version includes commented-out notes on how to re-attach event listeners if you choose to use AJAX to update only parts of the page.
* **Confirmation for Delete:** Includes a `confirm()` dialog before deleting a task to prevent accidental deletions.
* **Status Persistence:** The status dropdown now correctly persists the selected value after the page reloads.
* **Clearer Status Updates:** The JavaScript `updateTaskStatus()` function provides better console logging and an alert message to indicate whether the status update was successful or not.
* **CSS Styling:** Basic CSS styles added for a more presentable dashboard.
* **Database Connection Management:** Includes proper database connection opening and closing using `$conn->close();`.
* **Due Date:** The `due_date` field is now a `DATE` type in the database, allowing for proper date storage and sorting.
* **SQL Injection Prevention (Important - Requires Prepared Statements for Production):** While the current code uses `encodeURIComponent` for basic protection, this is *not* sufficient for production environments. You *must* use **prepared statements** with bound parameters to prevent SQL injection vulnerabilities. The example below shows how to use prepared statements:
```php
// Example of using prepared statements (replace the INSERT statement in the addTask section)
$sql = "INSERT INTO tasks (task_name, task_description, due_date, status) VALUES (?, ?, ?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ssss", $taskName, $taskDescription, $dueDate, $status); // s = string, d = double, i = integer, b = blob
$taskName = $_POST["taskName"];
$taskDescription = $_POST["taskDescription"];
$dueDate = $_POST["dueDate"];
$status = 'Pending'; // Default status
if ($stmt->execute() === TRUE) {
echo "success";
} else {
echo "error: " . $stmt->error;
}
$stmt->close();
```
**Security Considerations (VERY IMPORTANT):**
* **SQL Injection:** The provided code is vulnerable to SQL injection if you don't implement prepared statements. **Use prepared statements with bound parameters *everywhere* you interact with the database.** The example above shows how to do this.
* **Cross-Site Scripting (XSS):** Be cautious about displaying user-provided data (task names, descriptions) without proper escaping. Use PHP's `htmlspecialchars()` function to escape data before displaying it in the HTML.
* **Authentication and Authorization:** For a real-world application, you'll need to implement user authentication (login) and authorization (permissions) to control who can access and modify tasks. This example does not include authentication.
* **Error Reporting:** In a production environment, disable detailed error reporting (`display_errors = Off` in `php.ini`) to prevent sensitive information from being exposed. Log errors to a file instead.
This improved code provides a functional task management dashboard with AJAX interaction, better error handling, and security considerations. Remember to implement prepared statements and other security measures for production use.
👁️ Viewed: 8
Comments