Files
Task-Management/views/admin.php

534 lines
34 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
if(empty($_SESSION['is_admin'])) die("Access Denied");
// ── DB Migrations ─────────────────────────────────────────────────────────────
try { $pdo->exec("ALTER TABLE users ADD COLUMN profile_pic TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_endpoint TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_chat_id TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_template TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_session TEXT DEFAULT 'default'"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_api_key TEXT DEFAULT NULL"); } 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) {}
// ── Handle POST ───────────────────────────────────────────────────────────────
$success_msg = '';
$error_msg = '';
if($_SERVER['REQUEST_METHOD'] === 'POST') {
if(isset($_POST['create_user'])) {
$username = trim($_POST['username']);
$pass = password_hash($_POST['password'], PASSWORD_DEFAULT);
$is_admin = isset($_POST['is_admin']) ? 1 : 0;
try {
$stmt = $pdo->prepare("INSERT INTO users (username, password_hash, is_admin) VALUES (?, ?, ?)");
$stmt->execute([$username, $pass, $is_admin]);
$success_msg = "User '{$username}' created successfully!";
} catch(Exception $e) {
$error_msg = "Error: Username may already exist.";
}
}
if(isset($_POST['delete_user'])) {
$del_id = (int)$_POST['del_user_id'];
if($del_id != $user_id) {
$pdo->prepare("DELETE FROM users WHERE id=?")->execute([$del_id]);
$success_msg = "User deleted.";
} else {
$error_msg = "You cannot delete your own account.";
}
}
if(isset($_POST['toggle_admin'])) {
$tid = (int)$_POST['toggle_user_id'];
$newVal = (int)$_POST['new_admin_val'];
if($tid != $user_id) {
$pdo->prepare("UPDATE users SET is_admin=? WHERE id=?")->execute([$newVal, $tid]);
$success_msg = "User admin status updated.";
}
}
if(isset($_POST['create_group'])) {
try {
$stmt = $pdo->prepare("INSERT INTO groups (name) VALUES (?)");
$stmt->execute([$_POST['group_name']]);
$success_msg = "Group '{$_POST['group_name']}' created!";
} catch(Exception $e) {
$error_msg = "Group name may already exist.";
}
}
if(isset($_POST['delete_group'])) {
$gid = (int)$_POST['del_group_id'];
$pdo->prepare("DELETE FROM groups WHERE id=?")->execute([$gid]);
$success_msg = "Group deleted.";
}
if(isset($_POST['assign_group'])) {
$stmt = $pdo->prepare("INSERT OR IGNORE INTO user_groups (user_id, group_id) VALUES (?, ?)");
$stmt->execute([$_POST['user_id'], $_POST['group_id']]);
$success_msg = "User assigned to group.";
}
if(isset($_POST['remove_from_group'])) {
$pdo->prepare("DELETE FROM user_groups WHERE user_id=? AND group_id=?")->execute([$_POST['user_id'], $_POST['group_id']]);
$success_msg = "User removed from group.";
}
if(isset($_POST['update_user_channels'])) {
$ch = $_POST['channels'] ?? [];
$ch_str = is_array($ch) ? implode(',', $ch) : '';
$waha_ep = trim($_POST['waha_endpoint'] ?? '');
$waha_cid = trim($_POST['waha_chat_id'] ?? '');
$waha_tpl = trim($_POST['waha_template'] ?? '');
$waha_ses = trim($_POST['waha_session'] ?? '') ?: 'default';
$waha_key = trim($_POST['waha_api_key'] ?? '');
$stmt = $pdo->prepare("UPDATE users SET notify_channels=?, telegram_id=?, email=?, whatsapp_number=?, waha_endpoint=?, waha_chat_id=?, waha_template=?, waha_session=?, waha_api_key=? WHERE id=?");
$stmt->execute([$ch_str, $_POST['telegram_id'], $_POST['email'], $_POST['whatsapp_number'], $waha_ep ?: null, $waha_cid ?: null, $waha_tpl ?: null, $waha_ses, $waha_key ?: null, $_POST['user_id']]);
$success_msg = "User notification preferences updated!";
}
if(isset($_POST['update_sys_config'])) {
$stmt = $pdo->prepare("UPDATE system_config SET v=? WHERE k=?");
$stmt->execute([$_POST['completed_days'] ?? 7, 'completed_days']);
$stmt->execute([$_POST['archived_days'] ?? 90, 'archived_days']);
$success_msg = "System configuration saved!";
}
}
// ── Fetch Data ────────────────────────────────────────────────────────────────
$users = query("SELECT id, username, is_admin, notify_channels, telegram_id, email, whatsapp_number, profile_pic, waha_endpoint, waha_chat_id, waha_template, waha_session, waha_api_key FROM users ORDER BY is_admin DESC, username ASC")->fetchAll();
$all_groups = query("SELECT * FROM groups ORDER BY name")->fetchAll();
$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;
$waha_endpoint = query("SELECT v FROM system_config WHERE k='waha_endpoint'")->fetchColumn() ?: '';
$waha_chat_id = query("SELECT v FROM system_config WHERE k='waha_chat_id'")->fetchColumn() ?: '';
$waha_template = query("SELECT v FROM system_config WHERE k='waha_template'")->fetchColumn() ?: '';
// Activity stats for admin
$total_users = count($users);
$total_groups = count($all_groups);
$total_tasks = query("SELECT COUNT(*) FROM tasks")->fetchColumn();
$total_notes = 0; try { $total_notes = query("SELECT COUNT(*) FROM notes")->fetchColumn(); } catch(Exception $e) {}
$total_passwords = query("SELECT COUNT(*) FROM passwords")->fetchColumn();
$total_projects = query("SELECT COUNT(*) FROM projects")->fetchColumn();
// Activity log (recent, all users)
$recent_activity = [];
try {
$recent_activity = $pdo->query("SELECT al.*, u.username FROM activity_log al LEFT JOIN users u ON al.user_id=u.id ORDER BY al.created_at DESC LIMIT 20")->fetchAll();
} catch(Exception $e) {}
$active_tab = $_GET['tab'] ?? 'overview';
?>
<div class="header" style="margin-bottom:1rem;">
<h1 style="font-size:1.5rem; font-weight:700;"><i class="fa fa-shield-halved" style="color:var(--primary);"></i> Admin Panel</h1>
<span style="font-size:0.8rem; background:rgba(var(--primary-rgb),0.1); color:var(--primary); padding:4px 12px; border-radius:20px; font-weight:700;">ADMIN</span>
</div>
<?php if($success_msg): ?>
<div class="alert" style="background:rgba(16,185,129,0.12); color:#10B981; border:1px solid rgba(16,185,129,0.3); margin-bottom:1rem;"><?= htmlspecialchars($success_msg) ?></div>
<?php endif; ?>
<?php if($error_msg): ?>
<div class="alert" style="margin-bottom:1rem;"><?= htmlspecialchars($error_msg) ?></div>
<?php endif; ?>
<!-- ── Tabs ──────────────────────────────────────────────────────────────── -->
<div class="admin-tabs">
<button class="admin-tab <?= $active_tab==='overview'?'active':'' ?>" onclick="switchTab('overview')"><i class="fa fa-chart-line"></i> Overview</button>
<button class="admin-tab <?= $active_tab==='users'?'active':'' ?>" onclick="switchTab('users')"><i class="fa fa-users"></i> Users</button>
<button class="admin-tab <?= $active_tab==='groups'?'active':'' ?>" onclick="switchTab('groups')"><i class="fa fa-people-group"></i> Groups</button>
<button class="admin-tab <?= $active_tab==='channels'?'active':'' ?>" onclick="switchTab('channels')"><i class="fa fa-bell"></i> Notifications</button>
<button class="admin-tab <?= $active_tab==='config'?'active':'' ?>" onclick="switchTab('config')"><i class="fa fa-gear"></i> System Config</button>
</div>
<!-- ── Overview Tab ──────────────────────────────────────────────────────── -->
<div class="admin-tab-pane <?= $active_tab==='overview'?'active':'' ?>" id="tab-overview">
<!-- Stats Grid -->
<div style="display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:1rem; margin-bottom:1.5rem;">
<?php
$stats = [
['👤','Users',$total_users,'var(--primary)'],
['👥','Groups',$total_groups,'#10B981'],
['✅','Tasks',$total_tasks,'#F59E0B'],
['📝','Notes',$total_notes,'#8B5CF6'],
['🔐','Passwords',$total_passwords,'#EF4444'],
['📁','Projects',$total_projects,'#06B6D4'],
];
foreach($stats as [$icon,$label,$val,$col]):
?>
<div class="db-stat-card" style="border-top:3px solid <?= $col ?>; gap:0.35rem; padding:1rem;">
<div style="font-size:0.75rem; color:var(--text-light); font-weight:600; text-transform:uppercase;"><?= $label ?></div>
<div style="font-size:1.8rem; font-weight:700; color:<?= $col ?>;"><?= $icon ?> <?= $val ?></div>
</div>
<?php endforeach; ?>
</div>
<!-- Recent Activity -->
<div class="card">
<h3 style="font-size:1rem; font-weight:700; margin-bottom:1rem;">🕓 Recent Platform Activity</h3>
<?php if(empty($recent_activity)): ?>
<p style="color:var(--text-light); font-size:0.85rem;">No activity recorded yet.</p>
<?php else: ?>
<div style="display:flex; flex-direction:column; gap:0.5rem; max-height:320px; overflow-y:auto;">
<?php
$aic = ['#4F46E5','#10B981','#F59E0B','#EF4444','#8B5CF6'];
foreach($recent_activity as $log):
$t = strtotime($log['created_at']);
$diff = time()-$t;
$ago = $diff<60?'just now':($diff<3600?floor($diff/60).'m ago':($diff<86400?floor($diff/3600).'h ago':floor($diff/86400).'d ago'));
$col = $aic[crc32($log['username']??'')%count($aic)];
$init = strtoupper(mb_substr($log['username']??'S',0,1));
?>
<div class="log-item">
<div class="log-avatar" style="background:<?= $col ?>; flex-shrink:0;"><?= $init ?></div>
<div class="log-body">
<strong><?= htmlspecialchars($log['username']??'System') ?></strong>
<span class="log-detail"> · <?= htmlspecialchars($log['action']) ?><?= $log['detail']?' — '.htmlspecialchars(mb_substr($log['detail'],0,40)):'' ?></span>
</div>
<div class="log-time"><?= $ago ?></div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
<!-- ── Users Tab ─────────────────────────────────────────────────────────── -->
<div class="admin-tab-pane <?= $active_tab==='users'?'active':'' ?>" id="tab-users">
<div style="display:grid; grid-template-columns:340px 1fr; gap:1.5rem; align-items:start;">
<!-- Create User Form -->
<div class="card">
<h3 style="font-size:1rem; font-weight:700; margin-bottom:1rem;"><i class="fa fa-user-plus"></i> Create New User</h3>
<form method="POST">
<div class="form-group">
<label>Username</label>
<input type="text" name="username" class="form-control" placeholder="Enter username" required>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" class="form-control" placeholder="Set password" required>
</div>
<div class="form-group" style="display:flex; align-items:center; gap:0.5rem;">
<input type="checkbox" name="is_admin" id="new-user-admin" style="width:auto;">
<label for="new-user-admin" style="margin:0; font-weight:500;">Grant Admin Privileges</label>
</div>
<button type="submit" name="create_user" class="btn" style="width:100%;">
<i class="fa fa-plus"></i> Create User
</button>
</form>
</div>
<!-- User Cards -->
<div>
<h3 style="font-size:1rem; font-weight:700; margin-bottom:1rem;"><i class="fa fa-users"></i> All Users (<?= $total_users ?>)</h3>
<div class="admin-user-grid">
<?php foreach($users as $u):
$pic = $u['profile_pic'] ?? null;
$groups_of_u = query("SELECT g.name FROM groups g JOIN user_groups ug ON g.id=ug.group_id WHERE ug.user_id=?", [$u['id']])->fetchAll();
?>
<div class="admin-user-card">
<div class="admin-user-card-header">
<div class="admin-user-avatar">
<?php if($pic && file_exists($pic)): ?>
<img src="<?= htmlspecialchars($pic) ?>" style="width:100%;height:100%;object-fit:cover;border-radius:50%;" alt="">
<?php else: ?>
<?= strtoupper(mb_substr($u['username'],0,1)) ?>
<?php endif; ?>
</div>
<div style="flex:1; min-width:0;">
<div style="font-weight:700; font-size:0.9rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;"><?= htmlspecialchars($u['username']) ?></div>
<div style="margin-top:2px;">
<span class="<?= $u['is_admin'] ? 'admin-badge-admin' : 'admin-badge-user' ?>">
<?= $u['is_admin'] ? 'Admin' : 'User' ?>
</span>
</div>
</div>
</div>
<div style="font-size:0.75rem; color:var(--text-light); margin-bottom:0.75rem;">
<?php if($groups_of_u): ?>
<i class="fa fa-users" style="margin-right:4px;"></i>
<?= implode(', ', array_map(fn($g)=>htmlspecialchars($g['name']), $groups_of_u)) ?>
<?php else: ?>
<span style="font-style:italic;">No groups</span>
<?php endif; ?>
</div>
<!-- Actions -->
<div style="display:flex; gap:0.4rem; flex-wrap:wrap;">
<?php if($u['id'] != $user_id): ?>
<!-- Toggle admin -->
<form method="POST" style="display:inline;">
<input type="hidden" name="toggle_user_id" value="<?= $u['id'] ?>">
<input type="hidden" name="new_admin_val" value="<?= $u['is_admin']?0:1 ?>">
<button type="submit" name="toggle_admin" class="btn btn-sm btn-secondary" title="<?= $u['is_admin']?'Revoke Admin':'Grant Admin' ?>">
<i class="fa fa-<?= $u['is_admin']?'user-minus':'user-shield' ?>"></i>
</button>
</form>
<!-- Delete -->
<form method="POST" style="display:inline;" onsubmit="event.preventDefault(); appConfirm('Delete user <?= htmlspecialchars(addslashes($u['username'])) ?>?').then(y => { if(y) { this.onsubmit=null; this.submit(); } })">
<input type="hidden" name="del_user_id" value="<?= $u['id'] ?>">
<button type="submit" name="delete_user" class="btn btn-sm btn-danger" title="Delete user">
<i class="fa fa-trash"></i>
</button>
</form>
<?php else: ?>
<span style="font-size:0.75rem; color:var(--primary); font-style:italic; padding:4px 0;">(You)</span>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
<!-- ── Groups Tab ────────────────────────────────────────────────────────── -->
<div class="admin-tab-pane <?= $active_tab==='groups'?'active':'' ?>" id="tab-groups">
<div style="display:grid; grid-template-columns:340px 1fr; gap:1.5rem; align-items:start;">
<!-- Create Group + Assign -->
<div>
<div class="card">
<h3 style="font-size:1rem; font-weight:700; margin-bottom:1rem;"><i class="fa fa-folder-plus"></i> Create Group</h3>
<form method="POST" style="display:flex; gap:0.5rem;">
<input type="text" name="group_name" class="form-control" placeholder="Group name" required>
<button type="submit" name="create_group" class="btn btn-sm"><i class="fa fa-plus"></i> Create</button>
</form>
</div>
<div class="card">
<h3 style="font-size:1rem; font-weight:700; margin-bottom:1rem;"><i class="fa fa-user-plus"></i> Assign User to Group</h3>
<form method="POST">
<div class="form-group">
<label>User</label>
<select name="user_id" class="form-control" required>
<option value="">Select user...</option>
<?php foreach($users as $u): ?><option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['username']) ?></option><?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label>Group</label>
<select name="group_id" class="form-control" required>
<option value="">Select group...</option>
<?php foreach($all_groups as $g): ?><option value="<?= $g['id'] ?>"><?= htmlspecialchars($g['name']) ?></option><?php endforeach; ?>
</select>
</div>
<button type="submit" name="assign_group" class="btn" style="width:100%;"><i class="fa fa-link"></i> Assign</button>
</form>
</div>
</div>
<!-- Groups Breakdown -->
<div>
<h3 style="font-size:1rem; font-weight:700; margin-bottom:1rem;"><i class="fa fa-people-group"></i> All Groups (<?= $total_groups ?>)</h3>
<?php if(!$all_groups): ?>
<p style="color:var(--text-light);">No groups created yet.</p>
<?php endif; ?>
<div style="display:flex; flex-direction:column; gap:1rem;">
<?php foreach($all_groups as $g):
$stmt = $pdo->prepare("SELECT u.id, u.username FROM users u JOIN user_groups ug ON u.id=ug.user_id WHERE ug.group_id=?");
$stmt->execute([$g['id']]);
$g_users = $stmt->fetchAll();
?>
<div class="card" style="margin-bottom:0;">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.75rem;">
<div>
<div style="font-weight:700; font-size:1rem; color:var(--primary);">
<i class="fa fa-people-group"></i> <?= htmlspecialchars($g['name']) ?>
</div>
<div style="font-size:0.75rem; color:var(--text-light);"><?= count($g_users) ?> member<?= count($g_users)!=1?'s':'' ?></div>
</div>
<form method="POST" onsubmit="event.preventDefault(); appConfirm('Delete group <?= htmlspecialchars(addslashes($g['name'])) ?>?').then(y => { if(y) { this.onsubmit=null; this.submit(); } })">
<input type="hidden" name="del_group_id" value="<?= $g['id'] ?>">
<button type="submit" name="delete_group" class="btn btn-sm btn-danger"><i class="fa fa-trash"></i></button>
</form>
</div>
<?php if($g_users): ?>
<div style="display:flex; flex-wrap:wrap; gap:0.5rem;">
<?php foreach($g_users as $gu): ?>
<div style="display:flex; align-items:center; gap:0.35rem; background:rgba(var(--primary-rgb),0.07); border-radius:20px; padding:4px 10px;">
<span style="font-size:0.8rem; font-weight:600;"><?= htmlspecialchars($gu['username']) ?></span>
<form method="POST" style="display:inline;">
<input type="hidden" name="user_id" value="<?= $gu['id'] ?>">
<input type="hidden" name="group_id" value="<?= $g['id'] ?>">
<button type="submit" name="remove_from_group" class="btn btn-sm btn-danger" style="padding:1px 5px; font-size:0.7rem; border-radius:10px;" title="Remove from group">×</button>
</form>
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<p style="color:var(--text-light); font-size:0.8rem; font-style:italic;">No members yet.</p>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
<!-- ── Notifications Tab ──────────────────────────────────────────────────── -->
<div class="admin-tab-pane <?= $active_tab==='channels'?'active':'' ?>" id="tab-channels">
<div class="card">
<h3 style="font-size:1rem; font-weight:700; margin-bottom:0.5rem;"><i class="fa fa-bell"></i> User Notification Channels</h3>
<p style="font-size:0.85rem; color:var(--text-light); margin-bottom:1.25rem;">Configure notification channels per user. WAHA settings appear when <strong>WhatsApp</strong> is enabled.</p>
<?php foreach($users as $u):
$chs = explode(',', $u['notify_channels'] ?? '');
$uid = $u['id'];
$hasWA = in_array('whatsapp', $chs);
?>
<div class="card" style="margin-bottom:1rem; padding:1rem; border:1px solid var(--border);">
<form method="POST">
<input type="hidden" name="user_id" value="<?= $uid ?>">
<!-- User header row -->
<div style="display:flex; align-items:center; gap:0.75rem; flex-wrap:wrap;">
<!-- Avatar -->
<div style="width:36px;height:36px;border-radius:50%;background:var(--primary);color:#fff;display:flex;align-items:center;justify-content:center;font-size:0.85rem;font-weight:700;flex-shrink:0;overflow:hidden;">
<?php if(($u['profile_pic']??null) && file_exists($u['profile_pic'])): ?>
<img src="<?= htmlspecialchars($u['profile_pic']) ?>" style="width:100%;height:100%;object-fit:cover;">
<?php else: ?>
<?= strtoupper(mb_substr($u['username'],0,1)) ?>
<?php endif; ?>
</div>
<!-- Name & role -->
<div style="flex:1;">
<div style="font-weight:700; font-size:0.95rem;"><?= htmlspecialchars($u['username']) ?></div>
<div><span class="<?= $u['is_admin']?'admin-badge-admin':'admin-badge-user' ?>" style="font-size:0.7rem;"><?= $u['is_admin']?'Admin':'User' ?></span></div>
</div>
<!-- Save button -->
<button type="submit" name="update_user_channels" class="btn btn-sm"><i class="fa fa-save"></i> Save</button>
</div>
<!-- Channel checkboxes -->
<div style="display:flex; gap:1rem; flex-wrap:wrap; margin-top:0.85rem; padding-top:0.75rem; border-top:1px dashed var(--border);">
<?php foreach(['native','email','telegram','whatsapp'] as $ch): ?>
<label style="display:flex; align-items:center; gap:5px; font-size:0.85rem; cursor:pointer; font-weight:500;">
<input type="checkbox" name="channels[]" value="<?= $ch ?>"
<?= in_array($ch,$chs)?'checked':'' ?>
<?= $ch==='whatsapp' ? "onchange=\"toggleWAHA({$uid}, this.checked)\"" : '' ?>>
<?php
$icons = ['native'=>'🔔','email'=>'📧','telegram'=>'✈️','whatsapp'=>'📱'];
echo $icons[$ch] . ' ' . ucfirst($ch);
?>
</label>
<?php endforeach; ?>
</div>
<!-- Extra fields row -->
<div style="display:flex; gap:1rem; flex-wrap:wrap; margin-top:0.75rem; align-items:flex-end;">
<div class="form-group" style="margin:0; min-width:130px;">
<label style="font-size:0.75rem;">Telegram ID</label>
<input type="text" name="telegram_id" value="<?= htmlspecialchars($u['telegram_id']??'') ?>" class="form-control" style="padding:0.35rem;" placeholder="@username or ID">
</div>
<div class="form-group" style="margin:0; min-width:180px;">
<label style="font-size:0.75rem;">Email</label>
<input type="email" name="email" value="<?= htmlspecialchars($u['email']??'') ?>" class="form-control" style="padding:0.35rem;" placeholder="user@example.com">
</div>
<div class="form-group" style="margin:0; min-width:140px;">
<label style="font-size:0.75rem;">WhatsApp Number</label>
<input type="text" name="whatsapp_number" value="<?= htmlspecialchars($u['whatsapp_number']??'') ?>" class="form-control" style="padding:0.35rem;" placeholder="6281234567890">
</div>
</div>
<!-- WAHA expandable section -->
<div id="waha-section-<?= $uid ?>" style="<?= $hasWA ? '' : 'display:none;' ?> margin-top:0.75rem; padding:0.85rem; background:rgba(37,211,102,0.06); border:1px solid rgba(37,211,102,0.25); border-radius:8px;">
<div style="font-size:0.78rem; font-weight:700; color:#25D366; margin-bottom:0.65rem;"><i class="fab fa-whatsapp"></i> WAHA WhatsApp API Settings</div>
<div style="display:flex; gap:1rem; flex-wrap:wrap; align-items:flex-end;">
<div class="form-group" style="margin:0; flex:2; min-width:200px;">
<label style="font-size:0.75rem;">WAHA Endpoint URL</label>
<input type="text" name="waha_endpoint" value="<?= htmlspecialchars($u['waha_endpoint']??'') ?>" class="form-control" style="padding:0.35rem;" placeholder="http://localhost:3000/api/sendText">
</div>
<div class="form-group" style="margin:0; flex:1; min-width:120px;">
<label style="font-size:0.75rem;">Session Name</label>
<input type="text" name="waha_session" value="<?= htmlspecialchars($u['waha_session'] ?? 'default') ?>" class="form-control" style="padding:0.35rem;" placeholder="default">
</div>
<div class="form-group" style="margin:0; flex:1; min-width:160px;">
<label style="font-size:0.75rem;">Chat ID</label>
<input type="text" name="waha_chat_id" value="<?= htmlspecialchars($u['waha_chat_id']??'') ?>" class="form-control" style="padding:0.35rem;" placeholder="6281234567890@c.us">
</div>
<div class="form-group" style="margin:0; flex:1; min-width:160px;">
<label style="font-size:0.75rem;">API Key <span style="font-weight:400; color:var(--text-light);">(X-Api-Key)</span></label>
<input type="password" name="waha_api_key" value="<?= htmlspecialchars($u['waha_api_key']??'') ?>" class="form-control" style="padding:0.35rem; font-family:monospace;" placeholder="Leave blank if not required">
</div>
</div>
<div class="form-group" style="margin-top:0.6rem;">
<label style="font-size:0.75rem;">Message Template</label>
<textarea name="waha_template" class="form-control" rows="2" style="padding:0.35rem; font-size:0.8rem;" placeholder="*Alert:* {action} on {module} '{item}' by {user}"><?= htmlspecialchars($u['waha_template']??'') ?></textarea>
<div style="font-size:0.72rem; color:var(--text-light); margin-top:3px;">Variables: <code>{action}</code> <code>{module}</code> <code>{item}</code> <code>{user}</code> <code>{attachment_count}</code> <code>{due_date}</code> <code>{created_date}</code> <code>{updated_date}</code> <code>{assignor}</code> <code>{assignee}</code></div>
</div>
</div>
</form>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- ── System Config Tab ─────────────────────────────────────────────────── -->
<div class="admin-tab-pane <?= $active_tab==='config'?'active':'' ?>" id="tab-config">
<div class="card">
<h3 style="font-size:1rem; font-weight:700; margin-bottom:0.5rem;"><i class="fa fa-gear"></i> Kanban Auto-Archive Settings</h3>
<p style="font-size:0.85rem; color:var(--text-light); margin-bottom:1.5rem;">Control how long tasks stay in Completed or Archived states before being moved/deleted.</p>
<form method="POST">
<div style="display:grid; grid-template-columns:1fr 1fr; gap:1.5rem; max-width:600px;">
<div class="form-group" style="margin:0;">
<label>Completed tasks retain for (Days)</label>
<input type="number" name="completed_days" value="<?= htmlspecialchars($conf_comp) ?>" class="form-control" min="1" max="365">
<div style="font-size:0.75rem; color:var(--text-light); margin-top:4px;">Default: 7 days (before auto-moving to Archive)</div>
</div>
<div class="form-group" style="margin:0;">
<label>Archived tasks retain for (Days)</label>
<input type="number" name="archived_days" value="<?= htmlspecialchars($conf_arch) ?>" class="form-control" min="1" max="3650">
<div style="font-size:0.75rem; color:var(--text-light); margin-top:4px;">Default: 90 days (before permanent deletion)</div>
</div>
</div>
<button type="submit" name="update_sys_config" class="btn" style="margin-top:1.25rem;"><i class="fa fa-save"></i> Save Configuration</button>
</form>
</div>
<!-- Danger Zone -->
<div class="card" style="border:1px solid rgba(239,68,68,0.3);">
<h3 style="font-size:1rem; font-weight:700; margin-bottom:0.5rem; color:#EF4444;"><i class="fa fa-triangle-exclamation"></i> Danger Zone</h3>
<p style="font-size:0.85rem; color:var(--text-light); margin-bottom:1rem;">These actions are irreversible. Proceed with extreme caution.</p>
<div style="display:flex; gap:0.75rem; flex-wrap:wrap;">
<button class="btn btn-danger" onclick="appConfirm('Really purge all archive tasks?').then(y => { if(y) appAlert('Not implemented in this demo.'); })">
<i class="fa fa-trash"></i> Purge Archived Tasks
</button>
<button class="btn btn-danger" onclick="appConfirm('Really clear all activity logs?').then(y => { if(y) appAlert('Not implemented in this demo.'); })">
<i class="fa fa-eraser"></i> Clear Activity Logs
</button>
</div>
</div>
</div>
<script>
function switchTab(name) {
document.querySelectorAll('.admin-tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.admin-tab-pane').forEach(p => p.classList.remove('active'));
document.querySelector(`[onclick="switchTab('${name}')"]`).classList.add('active');
document.getElementById('tab-'+name).classList.add('active');
const url = new URL(window.location);
url.searchParams.set('tab', name);
history.replaceState({}, '', url);
}
function toggleWAHA(uid, enabled) {
const section = document.getElementById('waha-section-' + uid);
if (!section) return;
if (enabled) {
section.style.display = 'block';
section.style.animation = 'fadeIn 0.25s ease';
} else {
section.style.display = 'none';
}
}
</script>
<style>
@keyframes fadeIn { from { opacity:0; transform:translateY(-6px); } to { opacity:1; transform:none; } }
</style>