diff --git a/assets/css/custom.css b/assets/css/custom.css
index d15692f..27bafc2 100644
--- a/assets/css/custom.css
+++ b/assets/css/custom.css
@@ -148,3 +148,29 @@ body.dark-mode {
width: 1.25rem;
height: 1.25rem;
}
+
+.card {
+ border-radius: var(--border-radius);
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+}
+
+.card-title {
+ font-size: 1.25rem;
+ font-weight: 600;
+ margin-bottom: 0.5rem;
+}
+
+.card-text {
+ font-size: 0.9rem;
+ color: #6B7280; /* Neutral gray for description */
+}
+
+.dark-mode .card-text {
+ color: #9CA3AF;
+}
+
+.card-footer {
+ font-size: 0.8rem;
+ background-color: transparent;
+ border-top: none;
+}
diff --git a/assets/js/main.js b/assets/js/main.js
index 4b11284..7b49a6e 100644
--- a/assets/js/main.js
+++ b/assets/js/main.js
@@ -1,4 +1,5 @@
document.addEventListener('DOMContentLoaded', function () {
+ console.log('main.js: DOMContentLoaded event fired.');
const themeToggle = document.getElementById('theme-toggle');
const sidebarToggle = document.getElementById('sidebar-toggle');
const sidebar = document.querySelector('.sidebar');
@@ -31,4 +32,86 @@ document.addEventListener('DOMContentLoaded', function () {
mainContent.classList.toggle('expanded');
}
});
+
+ const addTaskForm = document.getElementById('addTaskForm');
+ if (addTaskForm) {
+ addTaskForm.addEventListener('submit', async function (e) {
+ console.log('main.js: addTaskForm submitted.');
+ e.preventDefault();
+
+ const formData = new FormData(this);
+ formData.append('action', 'addTask');
+
+ try {
+ const response = await fetch('index.php', {
+ method: 'POST',
+ body: formData
+ });
+ const result = await response.json();
+
+ if (result.success) {
+ alert(result.message);
+ this.reset(); // Clear form fields
+ // Close modal
+ const addTaskModal = bootstrap.Modal.getInstance(document.getElementById('addTaskModal'));
+ if (addTaskModal) {
+ addTaskModal.hide();
+ }
+ loadTasks(); // Refresh tasks list
+ } else {
+ alert('Error: ' + result.message);
+ }
+ } catch (error) {
+ console.error('Error adding task:', error);
+ alert('An unexpected error occurred while adding the task. Check console for details.');
+ }
+ });
+ }
+
+ // Function to load and display tasks
+ async function loadTasks() {
+ console.log('main.js: loadTasks() called.');
+ const tasksListDiv = document.getElementById('tasksList');
+ if (!tasksListDiv) return;
+
+ tasksListDiv.innerHTML = '
Loading tasks...
'; // Loading indicator
+
+ try {
+ const response = await fetch('index.php?action=getTasks');
+ const result = await response.json();
+
+ if (result.success && result.tasks) {
+ tasksListDiv.innerHTML = ''; // Clear loading indicator
+ if (result.tasks.length === 0) {
+ tasksListDiv.innerHTML = '';
+ return;
+ }
+ result.tasks.forEach(task => {
+ const taskCard = `
+
+
+
+
${task.title}
+
${task.description}
+
${task.status}
+
+
+
+
+ `;
+ tasksListDiv.innerHTML += taskCard;
+ });
+ } else {
+ tasksListDiv.innerHTML = 'Error loading tasks: ' + (result.message || 'Unknown error') + '
';
+ }
+ } catch (error) {
+ console.error('Error fetching tasks:', error);
+ tasksListDiv.innerHTML = 'An unexpected error occurred while fetching tasks. Check console for details.
';
+ }
+ }
+
+ // Initial load of tasks
+ loadTasks();
});
diff --git a/db/.applied_migrations b/db/.applied_migrations
new file mode 100644
index 0000000..0dbc99d
--- /dev/null
+++ b/db/.applied_migrations
@@ -0,0 +1 @@
+["001_create_tasks_table.sql"]
\ No newline at end of file
diff --git a/db/migrate.php b/db/migrate.php
new file mode 100644
index 0000000..de0cf49
--- /dev/null
+++ b/db/migrate.php
@@ -0,0 +1,52 @@
+exec($sql);
+ $appliedMigrations[] = $fileName;
+ } catch (PDOException $e) {
+ echo "Error applying migration {$fileName}: " . $e->getMessage() . "\n";
+ return false; // Stop on first error
+ }
+ } else {
+ echo "Migration already applied: {$fileName}\n";
+ }
+ }
+
+ file_put_contents($appliedMigrationsFile, json_encode($appliedMigrations));
+ echo "Migrations finished.\n";
+ return true;
+}
+
+// Run migrations if this script is executed directly
+if (realpath($argv[0]) === realpath(__FILE__)) {
+ try {
+ $pdo = db(); // Get PDO connection from config.php
+ runMigrations($pdo);
+ } catch (PDOException $e) {
+ echo "Database connection error: " . $e->getMessage() . "\n";
+ }
+}
+
diff --git a/db/migrations/001_create_tasks_table.sql b/db/migrations/001_create_tasks_table.sql
new file mode 100644
index 0000000..9a17310
--- /dev/null
+++ b/db/migrations/001_create_tasks_table.sql
@@ -0,0 +1,9 @@
+-- Create the tasks table
+CREATE TABLE IF NOT EXISTS tasks (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ title VARCHAR(255) NOT NULL,
+ description TEXT,
+ status ENUM('pending', 'in-progress', 'completed') DEFAULT 'pending',
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+);
diff --git a/index.php b/index.php
index 2558a2e..d1234c0 100644
--- a/index.php
+++ b/index.php
@@ -1,3 +1,49 @@
+ false, 'message' => 'Task title cannot be empty.']);
+ exit;
+ }
+
+ try {
+ $pdo = db();
+ $stmt = $pdo->prepare("INSERT INTO tasks (title, description) VALUES (:title, :description)");
+ $stmt->bindParam(':title', $title);
+ $stmt->bindParam(':description', $description);
+
+ if ($stmt->execute()) {
+ echo json_encode(['success' => true, 'message' => 'Task added successfully.', 'id' => $pdo->lastInsertId()]);
+ } else {
+ echo json_encode(['success' => false, 'message' => 'Failed to add task.']);
+ }
+ } catch (PDOException $e) {
+ echo json_encode(['success' => false, 'message' => 'Database error: ' . $e->getMessage()]);
+ }
+ exit;
+}
+
+if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['action']) && $_GET['action'] === 'getTasks') {
+ header('Content-Type: application/json');
+ try {
+ $pdo = db();
+ $stmt = $pdo->query("SELECT id, title, description, status, created_at FROM tasks ORDER BY created_at DESC");
+ $tasks = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ echo json_encode(['success' => true, 'tasks' => $tasks]);
+ } catch (PDOException $e) {
+ echo json_encode(['success' => false, 'message' => 'Database error: ' . $e->getMessage()]);
+ }
+ exit;
+}
+
+
@@ -64,7 +110,7 @@
-
+
@@ -75,6 +121,40 @@
This is your personal productivity dashboard. Let's get things done.
+
+
+
+
+
+