171 lines
6.8 KiB
PHP
171 lines
6.8 KiB
PHP
<?php
|
|
session_start();
|
|
require_once 'db.php';
|
|
|
|
$action = (string)($_GET['action'] ?? 'dashboard');
|
|
|
|
// API updates for task kanban drag n drop
|
|
if ($action === 'api') {
|
|
$api_action = $_GET['api_action'] ?? '';
|
|
if(!isset($_SESSION['user_id'])) die(json_encode(['status'=>'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;
|
|
}
|
|
|
|
// Mark all notifications as read
|
|
if (isset($_POST['mark_all_read'])) {
|
|
$pdo->prepare("UPDATE notifications SET is_read=1 WHERE user_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";
|
|
}
|