refactor: replace global WAHA notifications with granular user and group-specific templates and dispatch logic

This commit is contained in:
root
2026-03-30 01:02:23 +07:00
parent 68a764c0df
commit 596a233898
8 changed files with 502 additions and 131 deletions

View File

@@ -5,9 +5,23 @@ if(empty($_SESSION['is_admin'])) die("Access Denied");
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("ALTER TABLE users ADD COLUMN waha_template_task TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_template_note TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_template_password TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE users ADD COLUMN waha_template_file TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE groups ADD COLUMN notify_channels TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_endpoint TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_chat_id TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_api_key TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_session TEXT DEFAULT 'default'"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_template_task TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_template_note TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_template_password TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE groups ADD COLUMN waha_template_file TEXT DEFAULT NULL"); } catch(Exception $e) {}
try { $pdo->exec("ALTER TABLE groups ADD COLUMN profile_pic 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')");
@@ -53,11 +67,18 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
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!";
$name = trim($_POST['group_name']);
$pic_path = null;
if(isset($_FILES['group_pic']) && $_FILES['group_pic']['error'] === UPLOAD_ERR_OK) {
$ext = pathinfo($_FILES['group_pic']['name'], PATHINFO_EXTENSION);
$pic_path = 'uploads/group_' . time() . '_' . uniqid() . '.' . $ext;
move_uploaded_file($_FILES['group_pic']['tmp_name'], $pic_path);
}
$stmt = $pdo->prepare("INSERT INTO groups (name, profile_pic) VALUES (?, ?)");
$stmt->execute([$name, $pic_path]);
$success_msg = "Group '{$name}' created!";
} catch(Exception $e) {
$error_msg = "Group name may already exist.";
$error_msg = "Error: Group name may already exist.";
}
}
@@ -83,14 +104,59 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
$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']]);
$tpl_task = trim($_POST['waha_template_task'] ?? '');
$tpl_note = trim($_POST['waha_template_note'] ?? '');
$tpl_pass = trim($_POST['waha_template_password'] ?? '');
$tpl_file = trim($_POST['waha_template_file'] ?? '');
$stmt = $pdo->prepare("UPDATE users SET notify_channels=?, telegram_id=?, email=?, whatsapp_number=?, waha_endpoint=?, waha_chat_id=?, waha_template_task=?, waha_template_note=?, waha_template_password=?, waha_template_file=?, 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, $tpl_task ?: null, $tpl_note ?: null, $tpl_pass ?: null, $tpl_file ?: null, $waha_ses, $waha_key ?: null, $_POST['user_id']]);
$success_msg = "User notification preferences updated!";
}
if(isset($_POST['update_group_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_ses = trim($_POST['waha_session'] ?? '') ?: 'default';
$waha_key = trim($_POST['waha_api_key'] ?? '');
$tpl_task = trim($_POST['waha_template_task'] ?? '');
$tpl_note = trim($_POST['waha_template_note'] ?? '');
$tpl_pass = trim($_POST['waha_template_password'] ?? '');
$tpl_file = trim($_POST['waha_template_file'] ?? '');
$group_id = $_POST['group_id'];
$name = trim($_POST['group_name'] ?? '');
// Handle profile pic update
$pic_sql = "";
$pic_params = [];
if(isset($_POST['remove_pic']) && $_POST['remove_pic'] == '1') {
$old = query("SELECT profile_pic FROM groups WHERE id=?", [$group_id])->fetch();
if($old && $old['profile_pic'] && file_exists($old['profile_pic'])) @unlink($old['profile_pic']);
$pic_sql = ", profile_pic = NULL";
} elseif(isset($_FILES['group_pic']) && $_FILES['group_pic']['error'] === UPLOAD_ERR_OK) {
$old = query("SELECT profile_pic FROM groups WHERE id=?", [$group_id])->fetch();
if($old && $old['profile_pic'] && file_exists($old['profile_pic'])) @unlink($old['profile_pic']);
$ext = pathinfo($_FILES['group_pic']['name'], PATHINFO_EXTENSION);
$new_path = 'uploads/group_' . time() . '_' . uniqid() . '.' . $ext;
move_uploaded_file($_FILES['group_pic']['tmp_name'], $new_path);
$pic_sql = ", profile_pic = ?";
$pic_params[] = $new_path;
}
$sql = "UPDATE groups SET notify_channels=?, waha_endpoint=?, waha_chat_id=?, waha_template_task=?, waha_template_note=?, waha_template_password=?, waha_template_file=?, waha_session=?, waha_api_key=?, name=? $pic_sql WHERE id=?";
try {
$stmt = $pdo->prepare($sql);
$stmt->execute(array_merge([$ch_str, $waha_ep ?: null, $waha_cid ?: null, $tpl_task ?: null, $tpl_note ?: null, $tpl_pass ?: null, $tpl_file ?: null, $waha_ses, $waha_key ?: null, $name], $pic_params, [$group_id]));
$success_msg = "Group settings updated!";
} catch(Exception $e) {
$error_msg = "Error: Group name may already exist.";
}
}
if(isset($_POST['update_sys_config'])) {
$stmt = $pdo->prepare("UPDATE system_config SET v=? WHERE k=?");
$stmt->execute([$_POST['completed_days'] ?? 7, 'completed_days']);
@@ -100,7 +166,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
}
// ── 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();
$users = query("SELECT id, username, is_admin, notify_channels, telegram_id, email, whatsapp_number, profile_pic, waha_endpoint, waha_chat_id, waha_template_task, waha_template_note, waha_template_password, waha_template_file, 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;
@@ -292,10 +358,17 @@ $active_tab = $_GET['tab'] ?? 'overview';
<!-- 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>
<h3 style="font-size:1rem; font-weight:700; margin-bottom:1.25rem;"><i class="fa fa-folder-plus"></i> Create Group</h3>
<form method="POST" enctype="multipart/form-data">
<div class="form-group">
<label>Group Name</label>
<input type="text" name="group_name" class="form-control" placeholder="Enter group name" required>
</div>
<div class="form-group">
<label>Profile Picture</label>
<input type="file" name="group_pic" class="form-control" accept="image/*">
</div>
<button type="submit" name="create_group" class="btn" style="width:100%"><i class="fa fa-plus"></i> Create Group</button>
</form>
</div>
<div class="card">
@@ -333,18 +406,51 @@ $active_tab = $_GET['tab'] ?? 'overview';
$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']) ?>
<form method="POST" enctype="multipart/form-data">
<input type="hidden" name="update_group_channels" value="1">
<input type="hidden" name="group_id" value="<?= $g['id'] ?>">
<input type="hidden" name="group_name" value="<?= htmlspecialchars($g['name']) ?>">
<div style="display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:0.75rem;">
<div style="display:flex; align-items:center; gap:0.75rem;">
<div class="admin-user-avatar" style="width:42px; height:42px; font-size:1rem;">
<?php if($g['profile_pic'] && file_exists($g['profile_pic'])): ?>
<img src="<?= htmlspecialchars($g['profile_pic']) ?>" style="width:100%;height:100%;object-fit:cover;border-radius:50%;">
<?php else: ?>
<?= strtoupper(mb_substr($g['name'],0,1)) ?>
<?php endif; ?>
</div>
<div>
<input type="text" name="group_name" value="<?= htmlspecialchars($g['name']) ?>" class="form-control" style="font-weight:700; font-size:1rem; color:var(--primary); background:transparent; border:none; padding:0; height:auto; width:100%;" onchange="this.form.submit()">
<div style="font-size:0.75rem; color:var(--text-light);"><?= count($g_users) ?> member<?= count($g_users)!=1?'s':'' ?></div>
</div>
</div>
<div style="display:flex; gap:0.4rem;">
<label class="btn btn-sm btn-secondary" style="cursor:pointer;" title="Change Picture">
<i class="fa fa-camera"></i>
<input type="file" name="group_pic" style="display:none;" onchange="this.form.submit()">
</label>
<?php if($g['profile_pic']): ?>
<button type="submit" name="remove_pic" value="1" class="btn btn-sm btn-secondary" title="Remove Picture" onclick="return confirm('Remove profile picture?')"><i class="fa fa-image-slash"></i></button>
<?php endif; ?>
<button type="button" class="btn btn-sm btn-danger" onclick="appConfirm('Delete group <?= htmlspecialchars(addslashes($g['name'])) ?>?').then(y => { if(y) { document.getElementById('del-group-<?= $g['id'] ?>').submit(); } })"><i class="fa fa-trash"></i></button>
</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>
<!-- Hidden inputs for templates to preserve them when updating from here -->
<div style="display:none;">
<input type="text" name="waha_endpoint" value="<?= htmlspecialchars($g['waha_endpoint']??'') ?>">
<input type="text" name="waha_chat_id" value="<?= htmlspecialchars($g['waha_chat_id']??'') ?>">
<input type="text" name="waha_session" value="<?= htmlspecialchars($g['waha_session']??'default') ?>">
<input type="text" name="waha_api_key" value="<?= htmlspecialchars($g['waha_api_key']??'') ?>">
<textarea name="waha_template_task"><?= htmlspecialchars($g['waha_template_task']??'') ?></textarea>
<textarea name="waha_template_note"><?= htmlspecialchars($g['waha_template_note']??'') ?></textarea>
<textarea name="waha_template_password"><?= htmlspecialchars($g['waha_template_password']??'') ?></textarea>
<textarea name="waha_template_file"><?= htmlspecialchars($g['waha_template_file']??'') ?></textarea>
<?php $channels = explode(',', $g['notify_channels']??''); foreach($channels as $c): if(!$c) continue; ?>
<input type="checkbox" name="channels[]" value="<?= $c ?>" checked>
<?php endforeach; ?>
</div>
</form>
<form method="POST" id="del-group-<?= $g['id'] ?>" style="display:none;"><input type="hidden" name="del_group_id" value="<?= $g['id'] ?>"><input type="hidden" name="delete_group" value="1"></form>
<?php if($g_users): ?>
<div style="display:flex; flex-wrap:wrap; gap:0.5rem;">
<?php foreach($g_users as $gu): ?>
@@ -456,10 +562,27 @@ $active_tab = $_GET['tab'] ?? 'overview';
<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 style="margin-top:0.6rem;">
<label style="font-size:0.75rem;">Message Templates</label>
<div style="font-size:0.72rem; color:var(--text-light); margin-bottom:8px;">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 style="display:grid; grid-template-columns:1fr 1fr; gap:0.75rem;">
<div class="form-group" style="margin:0;">
<label style="font-size:0.7rem; color:var(--text-light);">Task</label>
<textarea name="waha_template_task" class="form-control" rows="2" style="padding:0.35rem; font-size:0.75rem;" placeholder="*Task Alert:* {action} on '{item}' by {user}"><?= htmlspecialchars($u['waha_template_task']??'') ?></textarea>
</div>
<div class="form-group" style="margin:0;">
<label style="font-size:0.7rem; color:var(--text-light);">Note</label>
<textarea name="waha_template_note" class="form-control" rows="2" style="padding:0.35rem; font-size:0.75rem;" placeholder="*Note Alert:* {action} on '{item}' by {user}"><?= htmlspecialchars($u['waha_template_note']??'') ?></textarea>
</div>
<div class="form-group" style="margin:0;">
<label style="font-size:0.7rem; color:var(--text-light);">Password</label>
<textarea name="waha_template_password" class="form-control" rows="2" style="padding:0.35rem; font-size:0.75rem;" placeholder="*Password Alert:* {action} on '{item}' by {user}"><?= htmlspecialchars($u['waha_template_password']??'') ?></textarea>
</div>
<div class="form-group" style="margin:0;">
<label style="font-size:0.7rem; color:var(--text-light);">File/Folder</label>
<textarea name="waha_template_file" class="form-control" rows="2" style="padding:0.35rem; font-size:0.75rem;" placeholder="*File Alert:* {action} on '{item}' by {user}"><?= htmlspecialchars($u['waha_template_file']??'') ?></textarea>
</div>
</div>
</div>
</div>
@@ -467,6 +590,96 @@ $active_tab = $_GET['tab'] ?? 'overview';
</div>
<?php endforeach; ?>
</div>
<!-- Group Notification Channels -->
<div class="card" style="margin-top:2rem;">
<h3 style="font-size:1rem; font-weight:700; margin-bottom:0.5rem;"><i class="fa fa-users"></i> Group Notification Channels</h3>
<p style="font-size:0.85rem; color:var(--text-light); margin-bottom:1.25rem;">Configure notification channels for an entire group. WAHA settings appear when <strong>WhatsApp</strong> is enabled.</p>
<?php foreach($all_groups as $g):
$chs = explode(',', $g['notify_channels'] ?? '');
$gid = $g['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="update_group_channels" value="1">
<input type="hidden" name="group_id" value="<?= $gid ?>">
<input type="hidden" name="group_name" value="<?= htmlspecialchars($g['name']) ?>">
<!-- Group header row -->
<div style="display:flex; align-items:center; gap:0.75rem; flex-wrap:wrap;">
<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(!empty($g['profile_pic']) && file_exists($g['profile_pic'])): ?>
<img src="<?= htmlspecialchars($g['profile_pic']) ?>" style="width:100%;height:100%;object-fit:cover;">
<?php else: ?>
<?= strtoupper(mb_substr($g['name'],0,1)) ?>
<?php endif; ?>
</div>
<div style="flex:1;">
<div style="font-weight:700; font-size:0.95rem;"><?= htmlspecialchars($g['name']) ?></div>
<div><span style="font-size:0.7rem; color:var(--text-light);">Group</span></div>
</div>
<button type="submit" name="update_group_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);">
<label style="display:flex; align-items:center; gap:5px; font-size:0.85rem; cursor:pointer; font-weight:500;">
<input type="checkbox" name="channels[]" value="whatsapp" <?= $hasWA?'checked':'' ?> onchange="toggleWAHAGroup(<?= $gid ?>, this.checked)">
📱 WhatsApp
</label>
</div>
<!-- WAHA expandable section -->
<div id="waha-group-section-<?= $gid ?>" 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($g['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($g['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($g['waha_chat_id']??'') ?>" class="form-control" style="padding:0.35rem;" placeholder="12345678@g.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($g['waha_api_key']??'') ?>" class="form-control" style="padding:0.35rem; font-family:monospace;" placeholder="Leave blank if not required">
</div>
</div>
<div style="margin-top:0.6rem;">
<label style="font-size:0.75rem;">Message Templates</label>
<div style="font-size:0.72rem; color:var(--text-light); margin-bottom:8px;">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 style="display:grid; grid-template-columns:1fr 1fr; gap:0.75rem;">
<div class="form-group" style="margin:0;">
<label style="font-size:0.7rem; color:var(--text-light);">Task</label>
<textarea name="waha_template_task" class="form-control" rows="2" style="padding:0.35rem; font-size:0.75rem;" placeholder="*Task Alert:* {action} on '{item}' by {user}"><?= htmlspecialchars($g['waha_template_task']??'') ?></textarea>
</div>
<div class="form-group" style="margin:0;">
<label style="font-size:0.7rem; color:var(--text-light);">Note</label>
<textarea name="waha_template_note" class="form-control" rows="2" style="padding:0.35rem; font-size:0.75rem;" placeholder="*Note Alert:* {action} on '{item}' by {user}"><?= htmlspecialchars($g['waha_template_note']??'') ?></textarea>
</div>
<div class="form-group" style="margin:0;">
<label style="font-size:0.7rem; color:var(--text-light);">Password</label>
<textarea name="waha_template_password" class="form-control" rows="2" style="padding:0.35rem; font-size:0.75rem;" placeholder="*Password Alert:* {action} on '{item}' by {user}"><?= htmlspecialchars($g['waha_template_password']??'') ?></textarea>
</div>
<div class="form-group" style="margin:0;">
<label style="font-size:0.7rem; color:var(--text-light);">File/Folder</label>
<textarea name="waha_template_file" class="form-control" rows="2" style="padding:0.35rem; font-size:0.75rem;" placeholder="*File Alert:* {action} on '{item}' by {user}"><?= htmlspecialchars($g['waha_template_file']??'') ?></textarea>
</div>
</div>
</div>
</div>
</form>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- ── System Config Tab ─────────────────────────────────────────────────── -->
@@ -527,6 +740,16 @@ function toggleWAHA(uid, enabled) {
section.style.display = 'none';
}
}
function toggleWAHAGroup(gid, enabled) {
const section = document.getElementById('waha-group-section-' + gid);
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; } }