'error','msg'=>'unauthorized'])); if($api_action === 'update_task_status') { $task_id = $_POST['task_id'] ?? null; $status = $_POST['status'] ?? null; $stmt = $pdo->prepare("UPDATE tasks SET status = ?, status_updated_at = CURRENT_TIMESTAMP WHERE id = ?"); $stmt->execute([$status, $task_id]); echo json_encode(['status'=>'ok']); } exit; } if (!isset($_SESSION['user_id']) && $action !== 'login' && $action !== 'setup') { header('Location: ?action=login'); exit; } $user_id = $_SESSION['user_id'] ?? null; $current_user = null; $unread_notifications = 0; if ($user_id) { $current_user = get_user($user_id); $stmt = $pdo->prepare("SELECT COUNT(*) FROM notifications WHERE user_id = ? AND is_read = 0"); $stmt->execute([$user_id]); $unread_notifications = $stmt->fetchColumn(); } if ($action === 'logout') { session_destroy(); header('Location: ?action=login'); exit; } if ($action === 'setup') { include 'setup.php'; exit; } if ($action === 'login') { $error = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $username = trim((string)($_POST['username'] ?? '')); $password = trim((string)($_POST['password'] ?? '')); $stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?"); $stmt->execute([$username]); $user = $stmt->fetch(); if ($user && password_verify($password, $user['password_hash'])) { $_SESSION['user_id'] = $user['id']; $_SESSION['is_admin'] = $user['is_admin']; header('Location: ?action=dashboard'); exit; } else { $error = "Invalid username or password"; } } include 'views/login.php'; exit; } // Handle POST actions that need a redirect BEFORE layout outputs any HTML. if ($_SERVER['REQUEST_METHOD'] === 'POST' && $user_id) { // Mood setter if (isset($_POST['set_mood'])) { try { $pdo->exec("ALTER TABLE users ADD COLUMN mood TEXT DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("ALTER TABLE users ADD COLUMN mood_updated_at DATETIME DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("CREATE TABLE IF NOT EXISTS activity_log (id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER, action TEXT NOT NULL, detail TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE)"); } catch(Exception $e) {} $mood = trim((string)($_POST['mood'] ?? '')); $allowed = ['😊','😢','😠','😴','🤩','😟','😎','🤔','😐','🥳']; if (in_array($mood, $allowed) || $mood === '') { $pdo->prepare("UPDATE users SET mood=?, mood_updated_at=CURRENT_TIMESTAMP WHERE id=?") ->execute([$mood ?: null, $user_id]); try { $pdo->prepare("INSERT INTO activity_log (user_id, action, detail) VALUES (?, 'mood_set', ?)") ->execute([$user_id, $mood ?: 'cleared']); } catch(Exception $e) {} } header('Location: ?action=dashboard'); exit; } // Profile picture upload if (isset($_POST['upload_profile_pic'])) { // Ensure column exists try { $pdo->exec("ALTER TABLE users ADD COLUMN profile_pic TEXT DEFAULT NULL"); } catch(Exception $e) {} if (isset($_FILES['profile_pic']) && $_FILES['profile_pic']['error'] === 0) { $allowed_types = ['image/jpeg','image/png','image/gif','image/webp']; if (in_array($_FILES['profile_pic']['type'], $allowed_types)) { $ext = pathinfo($_FILES['profile_pic']['name'], PATHINFO_EXTENSION); $filename = 'avatar_' . $user_id . '_' . time() . '.' . $ext; $dest = 'uploads/' . $filename; if (move_uploaded_file($_FILES['profile_pic']['tmp_name'], $dest)) { // Delete old pic $old = $pdo->prepare("SELECT profile_pic FROM users WHERE id=?"); $old->execute([$user_id]); $old_pic = $old->fetchColumn(); if ($old_pic && file_exists($old_pic)) @unlink($old_pic); $pdo->prepare("UPDATE users SET profile_pic=? WHERE id=?")->execute([$dest, $user_id]); } } } header('Location: ?action=' . ($_POST['redirect_to'] ?? 'dashboard')); exit; } // Delete profile picture if (isset($_POST['delete_profile_pic'])) { try { $pdo->exec("ALTER TABLE users ADD COLUMN profile_pic TEXT DEFAULT NULL"); } catch(Exception $e) {} $old = $pdo->prepare("SELECT profile_pic FROM users WHERE id=?"); $old->execute([$user_id]); $old_pic = $old->fetchColumn(); if ($old_pic && file_exists($old_pic)) @unlink($old_pic); $pdo->prepare("UPDATE users SET profile_pic=NULL WHERE id=?")->execute([$user_id]); header('Location: ?action=' . ($_POST['redirect_to'] ?? 'dashboard')); exit; } // Change password if (isset($_POST['change_password'])) { $cur = trim($_POST['current_password'] ?? ''); $new = trim($_POST['new_password'] ?? ''); $cnf = trim($_POST['confirm_password'] ?? ''); $user = get_user($user_id); $pw_error = ''; if (!password_verify($cur, $user['password_hash'])) { $pw_error = 'Current password is incorrect.'; } elseif (strlen($new) < 6) { $pw_error = 'New password must be at least 6 characters.'; } elseif ($new !== $cnf) { $pw_error = 'Passwords do not match.'; } else { $pdo->prepare("UPDATE users SET password_hash=? WHERE id=?") ->execute([password_hash($new, PASSWORD_DEFAULT), $user_id]); } $_SESSION['pw_change_msg'] = $pw_error ?: 'success'; header('Location: ?action=' . ($_POST['redirect_to'] ?? 'dashboard')); exit; } } $view_file = 'views/' . basename($action) . '.php'; if (file_exists($view_file)) { $is_ajax_post = isset($_POST['ajax_submit']) || isset($_POST['delete_attachment_ajax']) || isset($_POST['upload_attachment_ajax']); if ($is_ajax_post) { include $view_file; } else { include 'views/layout_top.php'; include $view_file; include 'views/layout_bottom.php'; } } else { echo "404 Not Found"; }