Files
Rosary/admin/index.php
T
pguzman 663fde3909 Initial commit — Rosary Presenter App
Full source for loveandrosary.com: slide-based Rosary/novena/Divine Mercy
Chaplet presentation tool with multi-user roles, SVG bead ring, audio uploads,
donate strip, and public session profiles.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 18:44:08 -07:00

248 lines
11 KiB
PHP

<?php
/**
* admin/index.php — Dashboard. Shows sessions for current user (or all for admin+).
*/
require_once __DIR__ . '/../config/db.php';
require_once __DIR__ . '/../includes/auth.php';
require_auth();
$pdo = get_pdo();
$user = current_user();
$uid = (int)$user['id'];
$is_admin = has_role('admin');
$site_name = get_setting('site_name', APP_NAME);
// Handle deletions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['delete_group_id'])) {
$gid = (int)$_POST['delete_group_id'];
// Verify ownership or admin
if ($is_admin) {
$pdo->prepare('DELETE FROM sessions WHERE novena_group_id = ?')->execute([$gid]);
$pdo->prepare('DELETE FROM novena_groups WHERE id = ?')->execute([$gid]);
} else {
$pdo->prepare('DELETE FROM sessions WHERE novena_group_id = ? AND (SELECT user_id FROM novena_groups WHERE id = ?) = ?')
->execute([$gid, $gid, $uid]);
$pdo->prepare('DELETE FROM novena_groups WHERE id = ? AND user_id = ?')->execute([$gid, $uid]);
}
header('Location: ' . BASE_URL . '/admin/');
exit;
}
if (isset($_POST['delete_id'])) {
$id = (int)$_POST['delete_id'];
if ($is_admin) {
$pdo->prepare('DELETE FROM sessions WHERE id = ?')->execute([$id]);
} else {
$pdo->prepare('DELETE FROM sessions WHERE id = ? AND user_id = ?')->execute([$id, $uid]);
}
header('Location: ' . BASE_URL . '/admin/');
exit;
}
}
// Load sessions
if ($is_admin) {
$regular = $pdo->query("
SELECT s.*, 'session' AS row_type, u.username, u.display_name
FROM sessions s
LEFT JOIN users u ON u.id = s.user_id
WHERE s.novena_group_id IS NULL
ORDER BY s.created_at DESC
")->fetchAll();
$novena_groups = $pdo->query("
SELECT ng.*, 'novena_group' AS row_type, COUNT(s.id) AS day_count,
u.username, u.display_name
FROM novena_groups ng
LEFT JOIN sessions s ON s.novena_group_id = ng.id
LEFT JOIN users u ON u.id = ng.user_id
GROUP BY ng.id
ORDER BY ng.created_at DESC
")->fetchAll();
} else {
$regular = $pdo->prepare("
SELECT s.*, 'session' AS row_type, u.username, u.display_name
FROM sessions s
LEFT JOIN users u ON u.id = s.user_id
WHERE s.novena_group_id IS NULL AND s.user_id = ?
ORDER BY s.created_at DESC
");
$regular->execute([$uid]);
$regular = $regular->fetchAll();
$ng_stmt = $pdo->prepare("
SELECT ng.*, 'novena_group' AS row_type, COUNT(s.id) AS day_count,
u.username, u.display_name
FROM novena_groups ng
LEFT JOIN sessions s ON s.novena_group_id = ng.id
LEFT JOIN users u ON u.id = ng.user_id
WHERE ng.user_id = ?
GROUP BY ng.id
ORDER BY ng.created_at DESC
");
$ng_stmt->execute([$uid]);
$novena_groups = $ng_stmt->fetchAll();
}
$all_rows = array_merge($regular, $novena_groups);
usort($all_rows, fn($a, $b) => strcmp($b['created_at'], $a['created_at']));
$occasion_labels = [
'novena_deceased' => 'Novena for Deceased',
'divine_mercy_novena' => 'Divine Mercy Novena',
'general_rosary' => 'General Rosary',
'memorial' => 'Memorial',
];
$mystery_labels = [
'sorrowful' => 'Sorrowful',
'joyful' => 'Joyful',
'glorious' => 'Glorious',
'luminous' => 'Luminous',
'by_day_of_week' => 'By Day',
];
$novena_created = isset($_GET['novena_created']) ? (int)$_GET['novena_created'] : 0;
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/svg+xml" href="<?= BASE_URL ?>/favicon.svg">
<title>Dashboard — <?= htmlspecialchars($site_name) ?></title>
<link rel="stylesheet" href="<?= BASE_URL ?>/assets/css/setup.css">
</head>
<body>
<div class="admin-container">
<header class="admin-header">
<h1>&#x271D; <?= htmlspecialchars($site_name) ?></h1>
<div class="header-actions">
<a href="<?= BASE_URL ?>/" class="btn btn-ghost" style="font-size:13px">&#x2190; View Site</a>
<?php if (has_role('admin')): ?>
<a href="<?= BASE_URL ?>/admin/users.php" class="btn btn-ghost">Users</a>
<a href="<?= BASE_URL ?>/admin/audio.php" class="btn btn-ghost">Audio</a>
<?php endif; ?>
<?php if (has_role('superadmin')): ?>
<a href="<?= BASE_URL ?>/admin/settings.php" class="btn btn-ghost">Settings</a>
<?php endif; ?>
<a href="<?= BASE_URL ?>/admin/profile.php" class="btn btn-ghost"><?= htmlspecialchars($user['display_name'] ?: $user['username']) ?></a>
<a href="<?= BASE_URL ?>/logout" class="btn btn-ghost">Logout</a>
</div>
</header>
<main>
<?php if ($novena_created > 0): ?>
<div class="alert alert-success">
&#x2713; <?= $novena_created ?> novena day sessions created.
</div>
<?php endif; ?>
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:20px">
<h2 style="margin:0"><?= $is_admin ? 'All Sessions' : 'My Sessions' ?></h2>
<a href="<?= BASE_URL ?>/admin/setup.php" class="btn btn-primary">+ New Session</a>
</div>
<?php if (empty($all_rows)): ?>
<div class="empty-state">
<p>No sessions yet.</p>
<a href="<?= BASE_URL ?>/admin/setup.php" class="btn btn-primary">Create Your First Session</a>
</div>
<?php else: ?>
<div class="sessions-table-wrap">
<table class="sessions-table">
<thead>
<tr>
<th>Name</th>
<th>Occasion</th>
<th>Mysteries</th>
<?php if ($is_admin): ?><th>Owner</th><?php endif; ?>
<th>Public</th>
<th>Created</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($all_rows as $row): ?>
<?php if ($row['row_type'] === 'novena_group'): ?>
<tr class="novena-group-row">
<td class="session-name">
<span class="novena-group-icon">&#x271D;</span>
<?= htmlspecialchars($row['name']) ?>
<?php if ($row['subject_name']): ?>
<span class="subject-name"><?= htmlspecialchars($row['subject_name']) ?></span>
<?php endif; ?>
<span class="novena-badge">9-Day Novena</span>
</td>
<td><?= ($row['mystery_set'] === 'chaplet') ? 'Divine Mercy Novena' : 'Novena for Deceased' ?></td>
<td><?= htmlspecialchars($mystery_labels[$row['mystery_set']] ?? $row['mystery_set']) ?></td>
<?php if ($is_admin): ?>
<td><?= htmlspecialchars($row['display_name'] ?: ($row['username'] ?? '—')) ?></td>
<?php endif; ?>
<td><?= $row['is_public'] ? '<span style="color:#15803d">&#x2713; Yes</span>' : '<span style="color:#9ca3af">No</span>' ?></td>
<td><?= date('M j, Y', strtotime($row['created_at'])) ?></td>
<td class="actions">
<a href="<?= BASE_URL ?>/admin/novena_group.php?id=<?= $row['id'] ?>"
class="btn btn-sm btn-primary">View Days &rarr;</a>
<?php if ($is_admin || (int)$row['user_id'] === $uid): ?>
<form method="post" style="display:inline"
onsubmit="return confirm('Delete this entire novena (all 9 days)?')">
<input type="hidden" name="delete_group_id" value="<?= $row['id'] ?>">
<button type="submit" class="btn btn-sm btn-danger">Delete</button>
</form>
<?php endif; ?>
</td>
</tr>
<?php else: ?>
<tr>
<td class="session-name">
<?= htmlspecialchars($row['name']) ?>
<?php if ($row['subject_name']): ?>
<span class="subject-name"><?= htmlspecialchars($row['subject_name']) ?></span>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($occasion_labels[$row['occasion']] ?? $row['occasion']) ?></td>
<td><?= htmlspecialchars($mystery_labels[$row['mystery_set']] ?? $row['mystery_set']) ?></td>
<?php if ($is_admin): ?>
<td><?= htmlspecialchars($row['display_name'] ?: ($row['username'] ?? '—')) ?></td>
<?php endif; ?>
<td><?= $row['is_public'] ? '<span style="color:#15803d">&#x2713; Yes</span>' : '<span style="color:#9ca3af">No</span>' ?></td>
<td><?= date('M j, Y', strtotime($row['created_at'])) ?></td>
<td class="actions">
<?php
$slug_val = $row['slug'] ?? '';
$owner = $row['username'] ?? '';
$present_url = ($slug_val && $owner)
? BASE_URL . '/' . rawurlencode($owner) . '/' . rawurlencode($slug_val)
: BASE_URL . '/present.php?id=' . $row['id'];
?>
<a href="<?= htmlspecialchars($present_url) ?>"
target="_blank"
class="btn btn-sm btn-primary">Present</a>
<?php if ($is_admin || (int)$row['user_id'] === $uid): ?>
<a href="<?= BASE_URL ?>/admin/setup.php?id=<?= $row['id'] ?>"
class="btn btn-sm btn-secondary">Edit</a>
<form method="post" style="display:inline"
onsubmit="return confirm('Delete this session?')">
<input type="hidden" name="delete_id" value="<?= $row['id'] ?>">
<button type="submit" class="btn btn-sm btn-danger">Delete</button>
</form>
<?php endif; ?>
</td>
</tr>
<?php endif; ?>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</main>
</div>
</body>
</html>