colored kanban

This commit is contained in:
Flatlogic Bot 2025-11-19 15:33:48 +00:00
parent a15f3f4df0
commit e9e4d72aef
10 changed files with 320 additions and 12 deletions

View File

@ -1,15 +1,23 @@
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
require_once 'db/config.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$title = $_POST['title'] ?? '';
$description = $_POST['description'] ?? '';
$user_id = $_SESSION['user_id'];
if (!empty($title)) {
try {
$pdo = db();
$stmt = $pdo->prepare("INSERT INTO tasks (title, description) VALUES (?, ?)");
$stmt->execute([$title, $description]);
$stmt = $pdo->prepare("INSERT INTO tasks (title, description, user_id) VALUES (?, ?, ?)");
$stmt->execute([$title, $description, $user_id]);
} catch (PDOException $e) {
header("Location: index.php?error=" . urlencode("Database error: " . $e->getMessage()));
exit;

View File

@ -11,11 +11,11 @@ body {
}
.kanban-column {
background-color: #e9ecef;
border-radius: 0.5rem;
padding: 1rem;
width: 320px;
flex-shrink: 0;
transition: background-color 0.3s ease;
}
.kanban-column h3 {
@ -25,16 +25,40 @@ body {
}
.task-card {
background-color: #fff;
border: 1px solid #dee2e6;
border-radius: 0.25rem;
padding: 1rem;
margin-bottom: 1rem;
cursor: grab;
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
transition: background-color 0.3s ease, color 0.3s ease;
}
.task-card:active {
cursor: grabbing;
background-color: #f1f3f5;
}
/* Column and Task Colors */
#kanban-column-to-do {
background-color: #e9ecef; /* Light Grey */
}
#kanban-column-to-do .task-card {
background-color: #ffffff; /* White */
color: #212529; /* Dark Grey */
}
#kanban-column-in-progress {
background-color: #dbeafe; /* Light Blue */
}
#kanban-column-in-progress .task-card {
background-color: #3b82f6; /* Blue */
color: #ffffff; /* White */
}
#kanban-column-done {
background-color: #d1fae5; /* Light Green */
}
#kanban-column-done .task-card {
background-color: #10b981; /* Green */
color: #ffffff; /* White */
}

View File

@ -0,0 +1,8 @@
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@ -0,0 +1,7 @@
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'app_35849' AND TABLE_NAME = 'tasks' AND COLUMN_NAME = 'user_id') THEN
ALTER TABLE `tasks` ADD `user_id` INT(11) NULL AFTER `id`;
END IF;
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = 'app_35849' AND TABLE_NAME = 'tasks' AND CONSTRAINT_NAME = 'fk_tasks_user_id') THEN
ALTER TABLE `tasks` ADD CONSTRAINT `fk_tasks_user_id` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
END IF;

112
debug.log
View File

@ -492,3 +492,115 @@
2025-11-19 15:28:53 - Parsed input: Task ID = 3, New Status = Done
2025-11-19 15:28:53 - Task ID and New Status are present. Updating database...
2025-11-19 15:28:53 - Database update successful. Rows affected: 1
2025-11-19 15:29:44 - update_task_status.php accessed.
2025-11-19 15:29:44 - Request method not allowed: HEAD
2025-11-19 15:29:50 - update_task_status.php accessed.
2025-11-19 15:29:50 - Request method not allowed: HEAD
2025-11-19 15:30:59 - update_task_status.php accessed.
2025-11-19 15:30:59 - Request method not allowed: HEAD
2025-11-19 15:31:00 - update_task_status.php accessed.
2025-11-19 15:31:00 - Request method not allowed: HEAD
2025-11-19 15:31:01 - update_task_status.php accessed.
2025-11-19 15:31:01 - Request method not allowed: HEAD
2025-11-19 15:31:04 - update_task_status.php accessed.
2025-11-19 15:31:04 - Request method not allowed: HEAD
2025-11-19 15:31:05 - update_task_status.php accessed.
2025-11-19 15:31:05 - Request method not allowed: HEAD
2025-11-19 15:31:05 - update_task_status.php accessed.
2025-11-19 15:31:05 - Request method not allowed: HEAD
2025-11-19 15:31:07 - update_task_status.php accessed.
2025-11-19 15:31:07 - Request method not allowed: HEAD
2025-11-19 15:31:08 - update_task_status.php accessed.
2025-11-19 15:31:08 - Request method not allowed: HEAD
2025-11-19 15:31:10 - update_task_status.php accessed.
2025-11-19 15:31:10 - Request method not allowed: HEAD
2025-11-19 15:31:10 - update_task_status.php accessed.
2025-11-19 15:31:10 - Request method not allowed: HEAD
2025-11-19 15:31:10 - update_task_status.php accessed.
2025-11-19 15:31:10 - Request method not allowed: HEAD
2025-11-19 15:31:12 - update_task_status.php accessed.
2025-11-19 15:31:12 - Request method not allowed: HEAD
2025-11-19 15:31:13 - update_task_status.php accessed.
2025-11-19 15:31:13 - Request method not allowed: HEAD
2025-11-19 15:31:15 - update_task_status.php accessed.
2025-11-19 15:31:15 - Request method not allowed: HEAD
2025-11-19 15:31:16 - update_task_status.php accessed.
2025-11-19 15:31:16 - Request method not allowed: HEAD
2025-11-19 15:31:16 - update_task_status.php accessed.
2025-11-19 15:31:16 - Request method not allowed: HEAD
2025-11-19 15:31:17 - update_task_status.php accessed.
2025-11-19 15:31:17 - Request method not allowed: HEAD
2025-11-19 15:31:18 - update_task_status.php accessed.
2025-11-19 15:31:18 - Request method not allowed: HEAD
2025-11-19 15:31:20 - update_task_status.php accessed.
2025-11-19 15:31:20 - Request method not allowed: HEAD
2025-11-19 15:31:21 - update_task_status.php accessed.
2025-11-19 15:31:21 - Request method not allowed: HEAD
2025-11-19 15:31:21 - update_task_status.php accessed.
2025-11-19 15:31:21 - Request method not allowed: HEAD
2025-11-19 15:31:22 - update_task_status.php accessed.
2025-11-19 15:31:22 - Request method not allowed: HEAD
2025-11-19 15:31:23 - update_task_status.php accessed.
2025-11-19 15:31:23 - Request method not allowed: HEAD
2025-11-19 15:31:25 - update_task_status.php accessed.
2025-11-19 15:31:25 - Request method not allowed: HEAD
2025-11-19 15:31:25 - update_task_status.php accessed.
2025-11-19 15:31:25 - Request method is POST.
2025-11-19 15:31:25 - Raw input: {"task_id":"1","new_status":"Done"}
2025-11-19 15:31:25 - Parsed input: Task ID = 1, New Status = Done
2025-11-19 15:31:25 - Task ID and New Status are present. Updating database...
2025-11-19 15:31:25 - Database update successful. Rows affected: 1
2025-11-19 15:31:26 - update_task_status.php accessed.
2025-11-19 15:31:26 - Request method not allowed: HEAD
2025-11-19 15:31:26 - update_task_status.php accessed.
2025-11-19 15:31:26 - Request method not allowed: HEAD
2025-11-19 15:31:26 - update_task_status.php accessed.
2025-11-19 15:31:26 - Request method is POST.
2025-11-19 15:31:26 - Raw input: {"task_id":"1","new_status":"In Progress"}
2025-11-19 15:31:26 - Parsed input: Task ID = 1, New Status = In Progress
2025-11-19 15:31:26 - Task ID and New Status are present. Updating database...
2025-11-19 15:31:26 - Database update successful. Rows affected: 1
2025-11-19 15:31:27 - update_task_status.php accessed.
2025-11-19 15:31:27 - Request method not allowed: HEAD
2025-11-19 15:31:27 - update_task_status.php accessed.
2025-11-19 15:31:27 - Request method is POST.
2025-11-19 15:31:27 - Raw input: {"task_id":"1","new_status":"To Do"}
2025-11-19 15:31:27 - Parsed input: Task ID = 1, New Status = To Do
2025-11-19 15:31:27 - Task ID and New Status are present. Updating database...
2025-11-19 15:31:27 - Database update successful. Rows affected: 1
2025-11-19 15:31:28 - update_task_status.php accessed.
2025-11-19 15:31:28 - Request method not allowed: HEAD
2025-11-19 15:31:31 - update_task_status.php accessed.
2025-11-19 15:31:31 - Request method not allowed: HEAD
2025-11-19 15:31:31 - update_task_status.php accessed.
2025-11-19 15:31:31 - Request method is POST.
2025-11-19 15:31:31 - Raw input: {"task_id":"1","new_status":"In Progress"}
2025-11-19 15:31:31 - Parsed input: Task ID = 1, New Status = In Progress
2025-11-19 15:31:31 - Task ID and New Status are present. Updating database...
2025-11-19 15:31:31 - Database update successful. Rows affected: 1
2025-11-19 15:31:33 - update_task_status.php accessed.
2025-11-19 15:31:33 - Request method not allowed: HEAD
2025-11-19 15:31:33 - update_task_status.php accessed.
2025-11-19 15:31:33 - Request method is POST.
2025-11-19 15:31:33 - Raw input: {"task_id":"1","new_status":"Done"}
2025-11-19 15:31:33 - Parsed input: Task ID = 1, New Status = Done
2025-11-19 15:31:33 - Task ID and New Status are present. Updating database...
2025-11-19 15:31:33 - Database update successful. Rows affected: 1
2025-11-19 15:31:37 - update_task_status.php accessed.
2025-11-19 15:31:37 - Request method not allowed: HEAD
2025-11-19 15:31:43 - update_task_status.php accessed.
2025-11-19 15:31:43 - Request method not allowed: HEAD
2025-11-19 15:31:48 - update_task_status.php accessed.
2025-11-19 15:31:48 - Request method not allowed: HEAD
2025-11-19 15:31:53 - update_task_status.php accessed.
2025-11-19 15:31:53 - Request method not allowed: HEAD
2025-11-19 15:31:58 - update_task_status.php accessed.
2025-11-19 15:31:58 - Request method not allowed: HEAD
2025-11-19 15:32:03 - update_task_status.php accessed.
2025-11-19 15:32:03 - Request method not allowed: HEAD
2025-11-19 15:32:03 - update_task_status.php accessed.
2025-11-19 15:32:03 - Request method is POST.
2025-11-19 15:32:03 - Raw input: {"task_id":"2","new_status":"In Progress"}
2025-11-19 15:32:03 - Parsed input: Task ID = 2, New Status = In Progress
2025-11-19 15:32:03 - Task ID and New Status are present. Updating database...
2025-11-19 15:32:03 - Database update failed or status unchanged. Rows affected: 0

View File

@ -25,11 +25,14 @@
<div class="container-fluid">
<a class="navbar-brand fw-bold" href="#">🚀 Task Manager</a>
<span class="navbar-text">
<?php echo date('Y-m-d H:i:s'); ?>
Welcome, <?php echo htmlspecialchars($_SESSION['username']); ?>!
</span>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addTaskModal">
<i class="bi bi-plus-lg"></i> Add Task
</button>
<div>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addTaskModal">
<i class="bi bi-plus-lg"></i> Add Task
</button>
<a href="logout.php" class="btn btn-outline-secondary">Logout</a>
</div>
</div>
</nav>

View File

@ -1,4 +1,11 @@
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
require_once 'db/config.php';
require_once 'header.php';
@ -9,8 +16,12 @@ function run_migrations() {
$migration_dir = 'db/migrations';
$files = glob($migration_dir . '/*.sql');
foreach ($files as $file) {
$sql = file_get_contents($file);
$pdo->exec($sql);
try {
$sql = file_get_contents($file);
$pdo->exec($sql);
} catch (PDOException $e) {
// Ignore errors, like column already exists
}
}
} catch (PDOException $e) {
// In a real app, you'd log this error.
@ -26,7 +37,8 @@ run_migrations();
$tasks = [];
try {
$pdo = db();
$stmt = $pdo->query("SELECT * FROM tasks ORDER BY created_at DESC");
$stmt = $pdo->prepare("SELECT * FROM tasks WHERE user_id = ? ORDER BY created_at DESC");
$stmt->execute([$_SESSION['user_id']]);
$tasks = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
echo '<div class="alert alert-danger">Database error: Could not fetch tasks.</div>';

56
login.php Normal file
View File

@ -0,0 +1,56 @@
<?php
session_start();
require_once 'db/config.php';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
if (empty($username) || empty($password)) {
$error = 'Please fill in all fields.';
} else {
$stmt = db()->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
header('Location: index.php');
exit;
} else {
$error = 'Invalid username or password.';
}
}
}
include 'header.php';
?>
<div class="container">
<h1 class="mt-5">Login</h1>
<?php if ($error): ?>
<div class="alert alert-danger" role="alert">
<?php echo $error; ?>
</div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
<p class="mt-3">Don't have an account? <a href="register.php">Register here</a>.</p>
</div>
<?php include 'footer.php'; ?>

5
logout.php Normal file
View File

@ -0,0 +1,5 @@
<?php
session_start();
session_destroy();
header('Location: login.php');
exit;

73
register.php Normal file
View File

@ -0,0 +1,73 @@
<?php
session_start();
require_once 'db/config.php';
$error = '';
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
$password_confirm = $_POST['password_confirm'];
if (empty($username) || empty($password) || empty($password_confirm)) {
$error = 'Please fill in all fields.';
} elseif ($password !== $password_confirm) {
$error = 'Passwords do not match.';
} else {
$stmt = db()->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
if ($user) {
$error = 'Username already exists.';
} else {
$password_hash = password_hash($password, PASSWORD_DEFAULT);
$stmt = db()->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
if ($stmt->execute([$username, $password_hash])) {
$success = 'Registration successful. You can now <a href="login.php">login</a>.';
} else {
$error = 'An error occurred. Please try again.';
}
}
}
}
include 'header.php';
?>
<div class="container">
<h1 class="mt-5">Register</h1>
<?php if ($error): ?>
<div class="alert alert-danger" role="alert">
<?php echo $error; ?>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success" role="alert">
<?php echo $success; ?>
</div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<div class="form-group">
<label for="password_confirm">Confirm Password</label>
<input type="password" class="form-control" id="password_confirm" name="password_confirm" required>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
<p class="mt-3">Already have an account? <a href="login.php">Login here</a>.</p>
</div>
<?php include 'footer.php'; ?>