From 2c81b93c8e71375f7e1cadbfb35f0a367cf030ee Mon Sep 17 00:00:00 2001 From: root Date: Thu, 26 Mar 2026 15:45:58 +0700 Subject: [PATCH] aaaa --- views/tasks.php | 1076 ----------------------------------------------- 1 file changed, 1076 deletions(-) delete mode 100644 views/tasks.php diff --git a/views/tasks.php b/views/tasks.php deleted file mode 100644 index 2e546ef..0000000 --- a/views/tasks.php +++ /dev/null @@ -1,1076 +0,0 @@ -exec("ALTER TABLE tasks ADD COLUMN assignor_type TEXT DEFAULT 'user'"); } catch(Exception $e) {} -try { $pdo->exec("ALTER TABLE tasks ADD COLUMN assignor_group_id INTEGER"); } catch(Exception $e) {} -try { $pdo->exec("ALTER TABLE tasks ADD COLUMN status_updated_at DATETIME"); } catch(Exception $e) {} -try { $pdo->exec("ALTER TABLE tasks ADD COLUMN due_date DATE"); } catch(Exception $e) {} -try { $pdo->exec("CREATE TABLE IF NOT EXISTS task_attachments (id INTEGER PRIMARY KEY AUTOINCREMENT, task_id INTEGER, file_name TEXT, file_path TEXT, owner_id INTEGER, created_at DATETIME DEFAULT CURRENT_TIMESTAMP)"); } catch(Exception $e) {} -try { - $pdo->exec("CREATE TABLE IF NOT EXISTS system_config (k TEXT PRIMARY KEY, v TEXT)"); - $pdo->exec("INSERT OR IGNORE INTO system_config (k, v) VALUES ('completed_days', '7')"); - $pdo->exec("INSERT OR IGNORE INTO system_config (k, v) VALUES ('archived_days', '90')"); -} catch(Exception $e) {} - -// Auto-cleanup lifecycle hooks -$conf_comp = query("SELECT v FROM system_config WHERE k='completed_days'")->fetchColumn() ?: 7; -$conf_arch = query("SELECT v FROM system_config WHERE k='archived_days'")->fetchColumn() ?: 90; - -if(is_numeric($conf_comp)) { - $pdo->exec("UPDATE tasks SET status='archived', status_updated_at=CURRENT_TIMESTAMP WHERE status='completed' AND datetime(COALESCE(status_updated_at, created_at), '+$conf_comp days') <= CURRENT_TIMESTAMP"); -} -if(is_numeric($conf_arch)) { - $pdo->exec("DELETE FROM tasks WHERE status='archived' AND datetime(COALESCE(status_updated_at, created_at), '+$conf_arch days') <= CURRENT_TIMESTAMP"); -} - -// Handle Task Deletions -if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_task'])) { - $del_id = $_POST['delete_task_id']; - $task_check = query("SELECT assignor_type, assignor_id, assignor_group_id FROM tasks WHERE id=?", [$del_id])->fetch(); - $user_groups = get_user_groups($user_id); - $my_group_ids = array_column($user_groups, 'id'); - - $can_delete = false; - if($task_check) { - if($task_check['assignor_type'] === 'user' && $task_check['assignor_id'] == $user_id) $can_delete = true; - if($task_check['assignor_type'] === 'group' && in_array($task_check['assignor_group_id'], $my_group_ids)) $can_delete = true; - if(!empty($_SESSION['is_admin'])) $can_delete = true; - } - - if($can_delete) { - query("DELETE FROM tasks WHERE id=?", [$del_id]); - } -} - -// Handle attachment deletion -if($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['delete_attachment']) || isset($_POST['delete_attachment_ajax']))) { - $att_id = $_POST['attachment_id']; - $att = query("SELECT owner_id, file_path FROM task_attachments WHERE id=?", [$att_id])->fetch(); - if($att && ($att['owner_id'] == $user_id || !empty($_SESSION['is_admin']))) { - @unlink($att['file_path']); - query("DELETE FROM task_attachments WHERE id=?", [$att_id]); - } - if(isset($_POST['delete_attachment_ajax'])) { - echo "OK"; exit; - } -} - -// Handle AJAX file upload for existing tasks -if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['upload_attachment_ajax'])) { - $task_id = (int)($_POST['task_id'] ?? 0); - $task = query("SELECT id FROM tasks WHERE id=?", [$task_id])->fetch(); - if($task && isset($_FILES['attachment_file'])) { - $files = $_FILES['attachment_file']; - $names = is_array($files['name']) ? $files['name'] : [$files['name']]; - $tmps = is_array($files['tmp_name']) ? $files['tmp_name'] : [$files['tmp_name']]; - $errors = is_array($files['error']) ? $files['error'] : [$files['error']]; - for($i = 0; $i < count($names); $i++) { - if($names[$i] && $errors[$i] === 0) { - $ext = strtolower(pathinfo($names[$i], PATHINFO_EXTENSION)); - $path = 'uploads/t_' . time() . '_' . rand(100, 999) . '.' . $ext; - if(!is_dir('uploads')) mkdir('uploads'); - if(move_uploaded_file($tmps[$i], $path)) { - $s = $pdo->prepare("INSERT INTO task_attachments (task_id, file_name, file_path, owner_id) VALUES (?, ?, ?, ?)"); - $s->execute([$task_id, $names[$i], $path, $user_id]); - } - } - } - echo json_encode(['success' => true]); exit; - } - echo json_encode(['success' => false, 'error' => 'Invalid task']); exit; -} - -// Handle form submission -if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['create_task'])) { - $title = $_POST['title']; - $desc = $_POST['description'] ?? ''; - $due_date = $_POST['due_date'] ?? null; - if(trim((string)$due_date) === '') $due_date = null; - - // Parse From - $from = $_POST['from_assignor']; // 'user_1' or 'group_2' - $f_parts = explode('_', $from); - $assignor_type = $f_parts[0]; // 'user' or 'group' - $assignor_group_id = ($assignor_type === 'group') ? $f_parts[1] : null; - - // Parse To Array (multi-assignee fallback to custom string) - $to_raw = trim((string)($_POST['to_assignee'] ?? '')); - $to_list = array_filter(array_map('trim', explode(',', $to_raw))); - - $a_type = 'custom'; - $a_id = null; - $custom_name = $to_raw; - - if(count($to_list) === 1) { - $single = reset($to_list); - $u = query("SELECT id FROM users WHERE username=?", [$single])->fetch(); - if($u) { - $a_type = 'user'; - $a_id = $u['id']; - $custom_name = null; - } else { - $g = query("SELECT id FROM groups WHERE name=?", [$single])->fetch(); - if($g) { - $a_type = 'group'; - $a_id = $g['id']; - $custom_name = null; - } - } - } - - $stmt = $pdo->prepare("INSERT INTO tasks (title, description, assignor_id, assignor_type, assignor_group_id, assignee_type, assignee_id, custom_assignee_name, status_updated_at, due_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?)"); - if(!$stmt->execute([$title, $desc, $user_id, $assignor_type, $assignor_group_id, $a_type, $a_id, $custom_name, $due_date])) { - if(isset($_POST['ajax_submit'])) { echo json_encode(['success'=>false, 'error'=>'Task insert failed']); exit; } - } - $new_task_id = $pdo->lastInsertId(); - - // Process attachments bundled in this single request - if(isset($_FILES['attachment_file'])) { - $files = $_FILES['attachment_file']; - $names = is_array($files['name']) ? $files['name'] : [$files['name']]; - $tmps = is_array($files['tmp_name']) ? $files['tmp_name'] : [$files['tmp_name']]; - $errors = is_array($files['error']) ? $files['error'] : [$files['error']]; - - for($i=0; $iprepare("INSERT INTO task_attachments (task_id, file_name, file_path, owner_id) VALUES (?, ?, ?, ?)"); - $stmt->execute([$new_task_id, $names[$i], $path, $user_id]); - } - } - } - } - - // Handle notifications - foreach($to_list as $rec) { - $u = query("SELECT id FROM users WHERE username=?", [$rec])->fetch(); - if($u) notify_user($u['id'], "You have been assigned a new task: $title"); - else { - $g = query("SELECT id FROM groups WHERE name=?", [$rec])->fetch(); - if($g) notify_group($g['id'], "Your group has been assigned a new task: $title"); - } - } - - if(isset($_POST['ajax_submit'])) { - echo json_encode(['success'=>true, 'redirect'=>'?action=tasks&msg_title='.urlencode('Task Created').'&msg_body='.urlencode('Task successfully created.')]); - exit; - } - header('Location: ?action=tasks'); - exit; -} - -// Fetch Assignable Entities for "From" -if(!isset($user_groups)) $user_groups = get_user_groups($user_id); -if(!isset($my_group_ids)) $my_group_ids = array_column($user_groups, 'id'); - -$from_options = []; -$from_options[] = ['val' => 'user_'.$user_id, 'label' => 'Myself ('.htmlspecialchars($current_user['username']).')']; -foreach($user_groups as $g) { - $from_options[] = ['val' => 'group_'.$g['id'], 'label' => htmlspecialchars($g['name']) . ' (Group)']; -} - -$all_u = query("SELECT id, username FROM users")->fetchAll(); -$all_g = query("SELECT id, name FROM groups")->fetchAll(); - -$group_in = implode(',', array_fill(0, count($my_group_ids), '?')) ?: '0'; - -$params = array_merge([$user_id], $my_group_ids, $my_group_ids, [$user_id]); - -$sql = "SELECT t.*, u.username as assignor_user_name, g.name as assignor_group_name, au.username as assignee_user_name, ag.name as assignee_group_name - FROM tasks t - LEFT JOIN users u ON t.assignor_id = u.id - LEFT JOIN groups g ON t.assignor_group_id = g.id - LEFT JOIN users au ON (t.assignee_type='user' AND t.assignee_id = au.id) - LEFT JOIN groups ag ON (t.assignee_type='group' AND t.assignee_id = ag.id) - WHERE (t.assignee_type='user' AND t.assignee_id = ?) - OR (t.assignee_type='group' AND t.assignee_id IN ($group_in)) - OR (t.assignor_type='group' AND t.assignor_group_id IN ($group_in)) - OR (t.assignor_type='user' AND t.assignor_id = ?) - ORDER BY t.created_at DESC"; -$stmt = $pdo->prepare($sql); -$stmt->execute($params); -$tasks = $stmt->fetchAll(); - -$t_ids = array_column($tasks, 'id'); -$attachments = []; -if($t_ids) { - $in = str_repeat('?,', count($t_ids) - 1) . '?'; - $stmt = $pdo->prepare("SELECT ta.*, u.username as owner_name FROM task_attachments ta LEFT JOIN users u ON ta.owner_id = u.id WHERE ta.task_id IN ($in) ORDER BY ta.created_at ASC"); - $stmt->execute($t_ids); - foreach($stmt->fetchAll() as $row) { - $attachments[$row['task_id']][] = $row; - } -} - -$kanban = ['pending' => [], 'in_progress' => [], 'completed' => [], 'archived' => []]; -foreach($tasks as $t) { - if(isset($kanban[$t['status']])) $kanban[$t['status']][] = $t; -} - -// Sort Pending by Due Date (Earliest first) -usort($kanban['pending'], function($a, $b) { - $da = $a['due_date'] ? strtotime($a['due_date']) : PHP_INT_MAX; - $db = $b['due_date'] ? strtotime($b['due_date']) : PHP_INT_MAX; - if($da == $db) return strtotime($b['created_at']) - strtotime($a['created_at']); - return $da - $db; -}); -?> - - - -
-
-
- Preview - -
-
-
-
- -
-
-
- -
- πŸ“ - -
- -
- - -
-
- -
- -
-
- -
- -
- - - - - -
-
- - - - - -
-
-
- -
- ['Pending','🟠'], 'in_progress'=>['In Progress','πŸ”΅'], 'completed'=>['Completed','🟒'], 'archived'=>['Archived','πŸ—„οΈ']] as $col_id => $col_data): ?> -
-
-
- -
-
- -
- -
-
- -
- -
- - - -
- - β–Ό -
-
- -
- '; - if($t['assignee_type'] == 'custom') echo 'πŸ‘€ '.htmlspecialchars((string)$t['custom_assignee_name']); - elseif($t['assignee_type'] == 'group') echo 'πŸ‘₯ '.htmlspecialchars($t['assignee_group_name']); - else echo 'πŸ‘€ '.htmlspecialchars($t['assignee_user_name'] ?? ''); - echo ''; - - echo '
'; - - $att_count = empty($attachments[$t['id']]) ? 0 : count($attachments[$t['id']]); - if($att_count > 0) { - echo ' '.$att_count.''; - } - - if($t['due_date']) { - $days_diff = (int)round((strtotime($t['due_date']) - strtotime(date('Y-m-d'))) / 86400); - if($days_diff < 0) { - echo 'Overdue by '.abs($days_diff).'d'; - } elseif($days_diff == 0) { - echo 'Due Today'; - } else { - echo ''.$days_diff.'d left'; - } - } - echo '
'; - ?> -
-
- -
- -
- - -
-
πŸ“… Created:
- -
⏰ Due Date:
- -
- -
-
- From: - - - -
-
- To: - - - -
-
- -
-
-
Attachments
- -
- - - -
- -
-
- - - -
- -
- -
πŸ“„
- - -
- - - - -
-
- - -
- - -
- - -
- - -
- -
- -
- -
-
- -
-
- -
- -