v2
This commit is contained in:
parent
caaaf66daf
commit
23eab8271d
8
db/migrations/001_create_users_table.sql
Normal file
8
db/migrations/001_create_users_table.sql
Normal 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;
|
||||
12
includes/footer.php
Normal file
12
includes/footer.php
Normal file
@ -0,0 +1,12 @@
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="text-center text-muted py-4 mt-5 border-top">
|
||||
<p class="mb-0">© <?php echo date('Y'); ?> MyTaskManager. Built with <a href="https://flatlogic.com" target="_blank" class="text-decoration-none">Flatlogic</a>.</p>
|
||||
</footer>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||
</body>
|
||||
</html>
|
||||
91
includes/header.php
Normal file
91
includes/header.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
// Check for session message for toast notifications
|
||||
$message = null;
|
||||
if (isset($_SESSION['message'])) {
|
||||
$message = $_SESSION['message'];
|
||||
$message_type = $_SESSION['message_type'] ?? 'success';
|
||||
unset($_SESSION['message']);
|
||||
unset($_SESSION['message_type']);
|
||||
}
|
||||
|
||||
$current_user = $_SESSION['user_id'] ?? null;
|
||||
$current_username = $_SESSION['username'] ?? null;
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<!-- SEO and Meta Tags -->
|
||||
<title>MyTaskManager</title>
|
||||
<meta name="description" content="A simple and beautiful task manager built with Flatlogic.">
|
||||
<meta name="keywords" content="task manager, to-do list, productivity, project management, simple tasks, online to-do, Flatlogic Generator, php task manager">
|
||||
<meta property="og:title" content="MyTaskManager">
|
||||
<meta property="og:description" content="A simple and beautiful task manager built with Flatlogic.">
|
||||
<meta property="og:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
|
||||
|
||||
<!-- Stylesheets -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Navbar -->
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="index.php">
|
||||
<i class="bi bi-check2-square text-primary"></i>
|
||||
MyTaskManager
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<?php if ($current_user): ?>
|
||||
<li class="nav-item">
|
||||
<span class="navbar-text me-3">
|
||||
Welcome, <?php echo htmlspecialchars($current_username); ?>
|
||||
</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="btn btn-outline-danger" href="logout.php">Logout</a>
|
||||
</li>
|
||||
<?php else: ?>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="login.php">Login</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="btn btn-primary" href="register.php">Register</a>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="container my-5">
|
||||
|
||||
<!-- Toast Notification -->
|
||||
<?php if ($message): ?>
|
||||
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
||||
<div class="toast align-items-center text-white bg-<?php echo $message_type; ?> border-0 show" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">
|
||||
<?php echo htmlspecialchars($message); ?>
|
||||
</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
168
index.php
168
index.php
@ -1,30 +1,38 @@
|
||||
<?php
|
||||
// index.php
|
||||
// This must be the very first line to ensure sessions work correctly.
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
// Check if the user is logged in. If not, redirect to the login page.
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// --- CONFIG AND DB SETUP ---
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
|
||||
$message = null;
|
||||
$message_type = 'success';
|
||||
// The user ID is now securely retrieved from the session.
|
||||
$user_id = $_SESSION['user_id'];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
// Idempotent table creation
|
||||
$pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS tasks (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
status ENUM('pending', 'completed') DEFAULT 'pending' NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
");
|
||||
|
||||
// Idempotent table alteration to add user_id
|
||||
// This is a one-time setup; it's safe to run multiple times due to 'ADD COLUMN IF NOT EXISTS' or similar logic in some DBs, or it will error harmlessly if the column exists.
|
||||
// For broader compatibility, we'll wrap it in a try-catch that specifically ignores 'Duplicate column name' errors.
|
||||
try {
|
||||
$pdo->exec("ALTER TABLE tasks ADD COLUMN user_id INT NULL;");
|
||||
} catch (PDOException $e) {
|
||||
// Ignore error if the column already exists
|
||||
if (strpos($e->getMessage(), 'Duplicate column name') === false) {
|
||||
throw $e; // Re-throw if it's a different error
|
||||
}
|
||||
}
|
||||
|
||||
// --- HANDLE POST REQUESTS ---
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
if ($action === 'add_task') {
|
||||
@ -32,8 +40,8 @@ try {
|
||||
$description = trim($_POST['description'] ?? '');
|
||||
|
||||
if (!empty($title)) {
|
||||
$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]);
|
||||
$_SESSION['message'] = 'Task added successfully!';
|
||||
$_SESSION['message_type'] = 'success';
|
||||
} else {
|
||||
@ -42,17 +50,20 @@ try {
|
||||
}
|
||||
} elseif ($action === 'update_status') {
|
||||
$task_id = filter_var($_POST['task_id'] ?? 0, FILTER_VALIDATE_INT);
|
||||
$status = $_POST['status'] ?? 'pending'; // Get current status to toggle
|
||||
if ($task_id) {
|
||||
$stmt = $pdo->prepare("UPDATE tasks SET status = 'completed' WHERE id = ?");
|
||||
$stmt->execute([$task_id]);
|
||||
$_SESSION['message'] = 'Task marked as completed!';
|
||||
// Correctly toggle between pending and completed
|
||||
$new_status = ($status === 'completed') ? 'pending' : 'completed';
|
||||
$stmt = $pdo->prepare("UPDATE tasks SET status = ? WHERE id = ? AND user_id = ?");
|
||||
$stmt->execute([$new_status, $task_id, $user_id]);
|
||||
$_SESSION['message'] = 'Task status updated!';
|
||||
$_SESSION['message_type'] = 'success';
|
||||
}
|
||||
} elseif ($action === 'delete_task') {
|
||||
$task_id = filter_var($_POST['task_id'] ?? 0, FILTER_VALIDATE_INT);
|
||||
if ($task_id) {
|
||||
$stmt = $pdo->prepare("DELETE FROM tasks WHERE id = ?");
|
||||
$stmt->execute([$task_id]);
|
||||
$stmt = $pdo->prepare("DELETE FROM tasks WHERE id = ? AND user_id = ?");
|
||||
$stmt->execute([$task_id, $user_id]);
|
||||
$_SESSION['message'] = 'Task deleted successfully!';
|
||||
$_SESSION['message_type'] = 'success';
|
||||
}
|
||||
@ -63,65 +74,31 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check for session message
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
if (isset($_SESSION['message'])) {
|
||||
$message = $_SESSION['message'];
|
||||
$message_type = $_SESSION['message_type'];
|
||||
unset($_SESSION['message']);
|
||||
unset($_SESSION['message_type']);
|
||||
}
|
||||
|
||||
|
||||
// --- FETCH TASKS FOR DISPLAY ---
|
||||
$stmt = $pdo->query("SELECT * FROM tasks ORDER BY status ASC, created_at DESC");
|
||||
// Ensure the 'status' column exists before querying, or handle its absence gracefully.
|
||||
// For now, we assume it exists or the ALTER TABLE above would have created it.
|
||||
$stmt = $pdo->prepare("SELECT id, title, description, status, created_at FROM tasks WHERE user_id = ? ORDER BY status ASC, created_at DESC");
|
||||
$stmt->execute([$user_id]);
|
||||
$tasks = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
$error_message = "Database error: " . $e->getMessage();
|
||||
$tasks = [];
|
||||
$message = $error_message;
|
||||
$message_type = 'danger';
|
||||
// Log the error for debugging purposes
|
||||
error_log("Database error: " . $e->getMessage());
|
||||
|
||||
// Provide a user-friendly error message
|
||||
$error_message = "A database error occurred. Please try again later.";
|
||||
$tasks = []; // Ensure tasks is empty on error
|
||||
$_SESSION['message'] = $error_message;
|
||||
$_SESSION['message_type'] = 'danger';
|
||||
|
||||
// If the error was specifically about a missing 'status' column, we might want to try fetching without it or prompt for migration.
|
||||
// For this iteration, we'll assume the ALTER TABLE above handles it or the user will address it.
|
||||
}
|
||||
|
||||
// The header is now included AFTER all the logic, ensuring it's only included if the script runs successfully.
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<!-- SEO and Meta Tags -->
|
||||
<title>MyTaskManager</title>
|
||||
<meta name="description" content="A simple and beautiful task manager built with Flatlogic.">
|
||||
<meta name="keywords" content="task manager, to-do list, productivity, project management, simple tasks, online to-do, Flatlogic Generator, php task manager">
|
||||
<meta property="og:title" content="MyTaskManager">
|
||||
<meta property="og:description" content="A simple and beautiful task manager built with Flatlogic.">
|
||||
<meta property="og:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
|
||||
|
||||
<!-- Stylesheets -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Navbar -->
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="#">
|
||||
<i class="bi bi-check2-square text-primary"></i>
|
||||
MyTaskManager
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="container my-5">
|
||||
|
||||
<!-- Add Task Form -->
|
||||
<section id="add-task" class="mb-5">
|
||||
@ -156,7 +133,12 @@ try {
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="list-group">
|
||||
<?php foreach ($tasks as $task): ?>
|
||||
<?php foreach ($tasks as $task):
|
||||
// Determine button class and icon based on task status
|
||||
$button_class = ($task['status'] === 'completed') ? 'btn-warning' : 'btn-success';
|
||||
$button_icon = ($task['status'] === 'completed') ? 'bi-arrow-counterclockwise' : 'bi-check-lg';
|
||||
$button_title = ($task['status'] === 'completed') ? 'Mark as pending' : 'Mark as completed';
|
||||
?>
|
||||
<div class="list-group-item list-group-item-action task-card <?php echo $task['status'] === 'completed' ? 'completed' : ''; ?>">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<div>
|
||||
@ -164,15 +146,14 @@ try {
|
||||
<p class="mb-1 small text-muted"><?php echo htmlspecialchars($task['description']); ?></p>
|
||||
</div>
|
||||
<div class="d-flex gap-2 align-items-center">
|
||||
<?php if ($task['status'] === 'pending'): ?>
|
||||
<form action="index.php" method="POST" class="d-inline">
|
||||
<input type="hidden" name="action" value="update_status">
|
||||
<input type="hidden" name="task_id" value="<?php echo $task['id']; ?>">
|
||||
<button type="submit" class="btn btn-sm btn-success" title="Mark as completed">
|
||||
<i class="bi bi-check-lg"></i>
|
||||
<input type="hidden" name="status" value="<?php echo $task['status']; ?>">
|
||||
<button type="submit" class="btn btn-sm <?php echo $button_class; ?>" title="<?php echo $button_title; ?>">
|
||||
<i class="bi <?php echo $button_icon; ?>"></i>
|
||||
</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<form action="index.php" method="POST" class="d-inline delete-task-form">
|
||||
<input type="hidden" name="action" value="delete_task">
|
||||
<input type="hidden" name="task_id" value="<?php echo $task['id']; ?>">
|
||||
@ -188,29 +169,4 @@ try {
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
<!-- Toast Notification -->
|
||||
<?php if ($message): ?>
|
||||
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
||||
<div class="toast align-items-center text-white bg-<?php echo $message_type; ?> border-0" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">
|
||||
<?php echo htmlspecialchars($message); ?>
|
||||
</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="text-center text-muted py-4 mt-5 border-top">
|
||||
<p class="mb-0">© <?php echo date('Y'); ?> MyTaskManager. Built with <a href="https://flatlogic.com" target="_blank" class="text-decoration-none">Flatlogic</a>.</p>
|
||||
</footer>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||
</body>
|
||||
</html>
|
||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||
87
login.php
Normal file
87
login.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
|
||||
$errors = [];
|
||||
$username = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$username = trim($_POST['username'] ?? '');
|
||||
$password = $_POST['password'] ?? '';
|
||||
|
||||
// Validation
|
||||
if (empty($username)) {
|
||||
$errors[] = 'Username is required.';
|
||||
}
|
||||
if (empty($password)) {
|
||||
$errors[] = 'Password is required.';
|
||||
}
|
||||
|
||||
// If no validation errors, check credentials
|
||||
if (empty($errors)) {
|
||||
try {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT id, username, password FROM users WHERE username = ?");
|
||||
$stmt->execute([$username]);
|
||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($user && password_verify($password, $user['password'])) {
|
||||
// Regenerate session ID to prevent session fixation
|
||||
session_regenerate_id(true);
|
||||
|
||||
// Store user info in session
|
||||
$_SESSION['user_id'] = $user['id'];
|
||||
$_SESSION['username'] = $user['username'];
|
||||
|
||||
// Redirect to the main page
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
} else {
|
||||
$errors[] = 'Invalid username or password.';
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$errors[] = "Database error: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
?>
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-5">
|
||||
<div class="card task-card">
|
||||
<div class="card-body p-4">
|
||||
<h1 class="card-title h3 mb-4 text-center">Login to Your Account</h1>
|
||||
|
||||
<?php if (!empty($errors)): ?>
|
||||
<div class="alert alert-danger">
|
||||
<?php foreach ($errors as $error): ?>
|
||||
<p class="mb-0"><?php echo htmlspecialchars($error); ?></p>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form action="login.php" method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Username</label>
|
||||
<input type="text" class="form-control" id="username" name="username" value="<?php echo htmlspecialchars($username); ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100 py-2">Login</button>
|
||||
</form>
|
||||
<div class="text-center mt-4">
|
||||
<p class="mb-0">Don't have an account? <a href="register.php">Register here</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||
28
logout.php
Normal file
28
logout.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
// Unset all of the session variables
|
||||
$_SESSION = [];
|
||||
|
||||
// Destroy the session
|
||||
if (ini_get("session.use_cookies")) {
|
||||
$params = session_get_cookie_params();
|
||||
setcookie(session_name(), '', time() - 42000,
|
||||
$params["path"], $params["domain"],
|
||||
$params["secure"], $params["httponly"]
|
||||
);
|
||||
}
|
||||
|
||||
session_destroy();
|
||||
|
||||
// Start a new session to pass a logout message
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
$_SESSION['message'] = 'You have been logged out successfully.';
|
||||
$_SESSION['message_type'] = 'success';
|
||||
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
93
register.php
Normal file
93
register.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
|
||||
$errors = [];
|
||||
$username = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$username = trim($_POST['username'] ?? '');
|
||||
$password = $_POST['password'] ?? '';
|
||||
|
||||
// Validation
|
||||
if (empty($username)) {
|
||||
$errors[] = 'Username is required.';
|
||||
}
|
||||
if (empty($password)) {
|
||||
$errors[] = 'Password is required.';
|
||||
} elseif (strlen($password) < 6) {
|
||||
$errors[] = 'Password must be at least 6 characters long.';
|
||||
}
|
||||
|
||||
// Check if username already exists
|
||||
if (empty($errors)) {
|
||||
try {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = ?");
|
||||
$stmt->execute([$username]);
|
||||
if ($stmt->fetch()) {
|
||||
$errors[] = 'Username already taken. Please choose another one.';
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$errors[] = "Database error: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// If no errors, create user
|
||||
if (empty($errors)) {
|
||||
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
|
||||
$stmt->execute([$username, $hashed_password]);
|
||||
|
||||
$_SESSION['message'] = 'Registration successful! You can now log in.';
|
||||
$_SESSION['message_type'] = 'success';
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
} catch (PDOException $e) {
|
||||
$errors[] = "Database error on user creation: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
?>
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-5">
|
||||
<div class="card task-card">
|
||||
<div class="card-body p-4">
|
||||
<h1 class="card-title h3 mb-4 text-center">Create Your Account</h1>
|
||||
|
||||
<?php if (!empty($errors)): ?>
|
||||
<div class="alert alert-danger">
|
||||
<?php foreach ($errors as $error): ?>
|
||||
<p class="mb-0"><?php echo htmlspecialchars($error); ?></p>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form action="register.php" method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Username</label>
|
||||
<input type="text" class="form-control" id="username" name="username" value="<?php echo htmlspecialchars($username); ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
<div class="form-text">Password must be at least 6 characters long.</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100 py-2">Register</button>
|
||||
</form>
|
||||
<div class="text-center mt-4">
|
||||
<p class="mb-0">Already have an account? <a href="login.php">Log in here</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||
Loading…
x
Reference in New Issue
Block a user