alerts.php
7.67 KB
<?php
require_once __DIR__ . '/../bootstrap.php';
require_once __DIR__ . '/../lib/feature_modules.php';
wp_feature_require_management(['alerts.view','alerts.send']);
if (!hasPermission('alerts.view') && !isAdminRole()) {
http_response_code(403);
die('Access denied.');
}
$pageTitle = 'Alerts';
if (isset($_GET['export']) && $_GET['export'] === 'csv') {
global $pdo;
$stmt = $pdo->query("SELECT alert_code, sent_by_name, sender_role, sent_at, title, message, target_type, target_value, priority, link_url, expires_at FROM alerts ORDER BY sent_at DESC");
$rows = [];
foreach ($stmt->fetchAll() as $r) {
$rows[] = [$r['alert_code'], $r['sent_by_name'], $r['sender_role'], $r['sent_at'], $r['title'], $r['message'], $r['target_type'], $r['target_value'], $r['priority'], $r['link_url'], $r['expires_at']];
}
wp_feature_csv_download('alerts_' . date('Ymd_His') . '.csv', ['Alert','Sent By','Sender Role','Sent At','Title','Message','Target Type','Target Value','Priority','Link','Expires At'], $rows);
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
global $pdo;
$action = $_POST['action'] ?? '';
if ($action === 'send_alert' && (hasPermission('alerts.send') || isAdminRole())) {
$title = trim((string)($_POST['title'] ?? ''));
$message = trim((string)($_POST['message'] ?? ''));
$targetType = trim((string)($_POST['target_type'] ?? 'all'));
$targetValue = trim((string)($_POST['target_value'] ?? ''));
$priority = trim((string)($_POST['priority'] ?? 'normal'));
$linkUrl = trim((string)($_POST['link_url'] ?? ''));
$expiresAt = trim((string)($_POST['expires_at'] ?? ''));
if ($title === '' || $message === '') {
wp_feature_flash_set('error', 'Title and message are required.');
app_redirect('management/alerts');
}
$code = wp_feature_generate_code('ALT', 'alerts', 'alert_code');
$stmt = $pdo->prepare("INSERT INTO alerts (alert_code, sent_by, sent_by_name, sender_role, sent_at, title, message, target_type, target_value, priority, link_url, expires_at) VALUES (?, ?, ?, ?, NOW(), ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$code, wp_feature_current_user_id(), wp_feature_current_user_name(), $_SESSION['user_role'] ?? '', $title, $message, $targetType, $targetValue, $priority, $linkUrl, $expiresAt !== '' ? $expiresAt : null]);
logActivity('alert_sent', 'alert', (int)$pdo->lastInsertId(), 'Sent alert ' . $code);
wp_feature_flash_set('success', 'Alert sent.');
app_redirect('management/alerts');
}
if ($action === 'mark_read') {
$id = (int)($_POST['id'] ?? 0);
if ($id > 0) {
$stmt = $pdo->prepare("INSERT IGNORE INTO alert_reads (alert_id, user_id, username, read_at) VALUES (?, ?, ?, NOW())");
$stmt->execute([$id, wp_feature_current_user_id(), wp_feature_current_user_name()]);
wp_feature_flash_set('success', 'Alert marked as read.');
}
app_redirect('management/alerts');
}
}
$userRole = strtolower((string)($_SESSION['user_role'] ?? ''));
$userName = strtolower(wp_feature_current_user_name());
$stmt = $pdo->query("SELECT * FROM alerts ORDER BY sent_at DESC LIMIT 200");
$allAlerts = $stmt->fetchAll() ?: [];
$reads = [];
$readStmt = $pdo->prepare("SELECT alert_id FROM alert_reads WHERE user_id = ? OR username = ?");
$readStmt->execute([wp_feature_current_user_id(), wp_feature_current_user_name()]);
foreach ($readStmt->fetchAll(PDO::FETCH_COLUMN) as $rid) { $reads[(int)$rid] = true; }
$alerts = [];
foreach ($allAlerts as $a) {
$expires = $a['expires_at'] ?? null;
if ($expires && strtotime((string)$expires) < time()) continue;
$targetType = strtolower((string)($a['target_type'] ?? 'all'));
$targetValue = strtolower((string)($a['target_value'] ?? ''));
$forMe = $targetType === 'all'
|| ($targetType === 'role' && $targetValue !== '' && str_contains($userRole, $targetValue))
|| ($targetType === 'user' && $targetValue !== '' && $targetValue === $userName);
if ($forMe) $alerts[] = $a;
}
$flash = wp_feature_flash_get();
include __DIR__ . '/../partials/header.php';
?>
<div class="content-header">
<div>
<h1 class="content-title">📣 Alerts</h1>
<p class="content-subtitle">Alerts are database-backed and can be exported whenever needed.</p>
</div>
<div class="d-flex gap-md" style="flex-wrap:wrap;">
<a class="btn btn-secondary" href="<?= e(app_url('management/alerts?export=csv')) ?>">⬇️ Export CSV</a>
</div>
</div>
<?php if ($flash): ?><div class="alert alert-<?= e($flash['type'] === 'error' ? 'error' : 'success') ?>" style="margin-bottom:16px;"><?= e($flash['message']) ?></div><?php endif; ?>
<div class="grid grid-2 mb-lg">
<div class="card">
<div class="card-header"><h3 class="card-title">Your Alerts</h3></div>
<?php if (!$alerts): ?>
<div class="text-muted">No active alerts for you.</div>
<?php else: foreach ($alerts as $a): ?>
<div style="padding:12px;border:1px solid var(--border);border-radius:10px;margin-bottom:12px;">
<div class="d-flex justify-between align-center" style="gap:12px;">
<strong><?= e($a['title']) ?></strong>
<span class="badge badge-muted"><?= e($a['priority']) ?></span>
</div>
<div class="text-muted" style="margin:6px 0;"><?= nl2br(e($a['message'])) ?></div>
<div class="text-muted" style="font-size:.9rem;">Sent by <?= e($a['sent_by_name']) ?> · <?= e($a['sent_at']) ?></div>
<div class="d-flex gap-md" style="margin-top:10px;flex-wrap:wrap;">
<?php if (!empty($a['link_url'])): ?><a class="btn btn-secondary btn-xs" href="<?= e($a['link_url']) ?>">Open Link</a><?php endif; ?>
<?php if (empty($reads[(int)$a['id']])): ?>
<form method="post"><input type="hidden" name="action" value="mark_read"><input type="hidden" name="id" value="<?= (int)$a['id'] ?>"><button class="btn btn-secondary btn-xs" type="submit">Mark Read</button></form>
<?php else: ?><span class="text-muted">Read</span><?php endif; ?>
</div>
</div>
<?php endforeach; endif; ?>
</div>
<div class="card">
<div class="card-header"><h3 class="card-title">Send Alert</h3></div>
<?php if (!(hasPermission('alerts.send') || isAdminRole())): ?>
<div class="text-muted">You can view alerts but cannot send them.</div>
<?php else: ?>
<form method="post" class="grid" style="gap:12px;">
<input type="hidden" name="action" value="send_alert">
<div><label class="field-label">Title</label><input class="input" type="text" name="title" required></div>
<div><label class="field-label">Message</label><textarea class="input" name="message" rows="4" required></textarea></div>
<div><label class="field-label">Target Type</label><select class="input" name="target_type"><option value="all">All</option><option value="role">Role</option><option value="user">User</option></select></div>
<div><label class="field-label">Target Value</label><input class="input" type="text" name="target_value" placeholder="role name or display name"></div>
<div><label class="field-label">Priority</label><select class="input" name="priority"><option value="normal">Normal</option><option value="important">Important</option><option value="urgent">Urgent</option></select></div>
<div><label class="field-label">Link URL</label><input class="input" type="text" name="link_url" placeholder="Optional"></div>
<div><label class="field-label">Expires At</label><input class="input" type="datetime-local" name="expires_at"></div>
<div><button class="btn btn-primary" type="submit">Send Alert</button></div>
</form>
<?php endif; ?>
</div>
</div>
<?php include __DIR__ . '/../partials/footer.php'; ?>