BROOKO icon
BROOKO UK NETWORK
Where code meets creativity & adventure
File viewer

alerts.php

Type
php
Size
7.67 KB
Modified
15 May
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'; ?>