Sindbad~EG File Manager
<?php
require_once '../includes/functions.php';
// Check if user is logged in and has admin privileges
if (!isLoggedIn()) {
header('Location: ' . BASE_URL . 'login.php');
exit();
}
$user = getCurrentUser();
if (!in_array($user['role'], ['superuser', 'area_admin', 'district_admin', 'assembly_admin'])) {
header('Location: ' . BASE_URL . 'dashboard.php');
exit();
}
$db = new CopMadinaDB();
$conn = $db->getConnection();
// Get filter parameters
$event_filter = $_GET['event_id'] ?? '';
$participant_type = $_GET['participant_type'] ?? 'all';
$export = $_GET['export'] ?? '';
// Handle export requests
if ($export && in_array($export, ['csv', 'pdf'])) {
handleExport($export, $event_filter, $participant_type, $conn);
exit();
}
// Get all events for filter dropdown
$events = executeQuery("SELECT id, title, start_date, status FROM events ORDER BY start_date DESC")->fetchAll();
// Build participants query based on filters
$participants = getParticipants($event_filter, $participant_type, $conn);
// Get event statistics
$stats = getEventStatistics($event_filter, $conn);
function getParticipants($event_filter, $participant_type, $conn) {
$participants = [];
if ($participant_type === 'all' || $participant_type === 'members') {
// Get member registrations
$memberQuery = "
SELECT DISTINCT
er.id as registration_id,
er.event_id,
e.title as event_title,
u.first_name,
u.last_name,
u.email,
u.phone,
m.member_id,
'member' as participant_type,
er.registration_code,
er.payment_status,
er.amount_paid,
er.registration_date,
er.status,
er.checked_in_at,
er.checked_out_at,
COALESCE(a.name, ma.name) as area_name,
COALESCE(d.name, md.name) as district_name,
COALESCE(ass.name, mass.name) as assembly_name
FROM event_registrations er
JOIN users u ON er.user_id = u.id
LEFT JOIN members m ON u.members_id = m.id
JOIN events e ON er.event_id = e.id
LEFT JOIN areas a ON u.area_id = a.id
LEFT JOIN districts d ON u.district_id = d.id
LEFT JOIN assemblies ass ON u.assembly_id = ass.id
LEFT JOIN areas ma ON m.area_id = ma.id
LEFT JOIN districts md ON m.district_id = md.id
LEFT JOIN assemblies mass ON m.assembly_id = mass.id
";
$params = [];
if ($event_filter) {
$memberQuery .= " WHERE er.event_id = ?";
$params[] = $event_filter;
}
$memberQuery .= " ORDER BY er.registration_date DESC";
$stmt = $conn->prepare($memberQuery);
$stmt->execute($params);
$memberParticipants = $stmt->fetchAll();
$participants = array_merge($participants, $memberParticipants);
}
if ($participant_type === 'all' || $participant_type === 'nonmembers') {
// Get non-member registrations
$nonMemberQuery = "
SELECT DISTINCT
nr.id as registration_id,
nr.event_id,
e.title as event_title,
nr.first_name,
nr.last_name,
nr.email,
nr.phone,
NULL as member_id,
'nonmember' as participant_type,
nr.registration_code,
nr.payment_status,
nr.amount_paid,
nr.registration_date,
nr.status,
nr.checked_in_at,
nr.checked_out_at,
a.name as area_name,
d.name as district_name,
ass.name as assembly_name
FROM nonmember_registrations nr
JOIN events e ON nr.event_id = e.id
LEFT JOIN areas a ON nr.area_id = a.id
LEFT JOIN districts d ON nr.district_id = d.id
LEFT JOIN assemblies ass ON nr.assembly_id = ass.id
";
$params = [];
if ($event_filter) {
$nonMemberQuery .= " WHERE nr.event_id = ?";
$params[] = $event_filter;
}
$nonMemberQuery .= " ORDER BY nr.registration_date DESC";
$stmt = $conn->prepare($nonMemberQuery);
$stmt->execute($params);
$nonMemberParticipants = $stmt->fetchAll();
$participants = array_merge($participants, $nonMemberParticipants);
}
// Remove duplicates based on email and event_id
$uniqueParticipants = [];
$seen = [];
foreach ($participants as $participant) {
$key = $participant['email'] . '_' . $participant['event_id'];
if (!isset($seen[$key])) {
$seen[$key] = true;
$uniqueParticipants[] = $participant;
}
}
return $uniqueParticipants;
}
function getEventStatistics($event_filter, $conn) {
$stats = [
'total_participants' => 0,
'members' => 0,
'nonmembers' => 0,
'checked_in' => 0,
'total_revenue' => 0
];
$whereClause = $event_filter ? "WHERE event_id = ?" : "";
$params = $event_filter ? [$event_filter] : [];
// Member statistics
$memberStats = $conn->prepare("
SELECT
COUNT(*) as count,
COUNT(CASE WHEN checked_in_at IS NOT NULL THEN 1 END) as checked_in,
COALESCE(SUM(amount_paid), 0) as revenue
FROM event_registrations
$whereClause
");
$memberStats->execute($params);
$memberData = $memberStats->fetch();
// Non-member statistics
$nonMemberStats = $conn->prepare("
SELECT
COUNT(*) as count,
COUNT(CASE WHEN checked_in_at IS NOT NULL THEN 1 END) as checked_in,
COALESCE(SUM(amount_paid), 0) as revenue
FROM nonmember_registrations
$whereClause
");
$nonMemberStats->execute($params);
$nonMemberData = $nonMemberStats->fetch();
$stats['members'] = $memberData['count'];
$stats['nonmembers'] = $nonMemberData['count'];
$stats['total_participants'] = $stats['members'] + $stats['nonmembers'];
$stats['checked_in'] = $memberData['checked_in'] + $nonMemberData['checked_in'];
$stats['total_revenue'] = $memberData['revenue'] + $nonMemberData['revenue'];
return $stats;
}
function handleExport($format, $event_filter, $participant_type, $conn) {
$participants = getParticipants($event_filter, $participant_type, $conn);
if ($format === 'csv') {
exportCSV($participants, $event_filter);
} elseif ($format === 'pdf') {
exportPDF($participants, $event_filter);
}
}
function exportCSV($participants, $event_filter) {
$filename = 'event_participants_' . ($event_filter ? 'event_' . $event_filter . '_' : '') . date('Y-m-d') . '.csv';
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="' . $filename . '"');
$output = fopen('php://output', 'w');
// CSV Headers
fputcsv($output, [
'Registration ID',
'Event',
'First Name',
'Last Name',
'Email',
'Phone',
'Member ID',
'Type',
'Area',
'District',
'Assembly',
'Registration Code',
'Payment Status',
'Amount Paid',
'Registration Date',
'Status',
'Checked In',
'Checked Out'
]);
// CSV Data
foreach ($participants as $participant) {
fputcsv($output, [
$participant['registration_id'],
$participant['event_title'],
$participant['first_name'],
$participant['last_name'],
$participant['email'],
$participant['phone'],
$participant['member_id'] ?? 'N/A',
ucfirst($participant['participant_type']),
$participant['area_name'] ?? 'N/A',
$participant['district_name'] ?? 'N/A',
$participant['assembly_name'] ?? 'N/A',
$participant['registration_code'],
ucfirst($participant['payment_status']),
'GH₵' . number_format($participant['amount_paid'], 2),
date('Y-m-d H:i', strtotime($participant['registration_date'])),
ucfirst($participant['status']),
$participant['checked_in_at'] ? date('Y-m-d H:i', strtotime($participant['checked_in_at'])) : 'No',
$participant['checked_out_at'] ? date('Y-m-d H:i', strtotime($participant['checked_out_at'])) : 'No'
]);
}
fclose($output);
}
function exportPDF($participants, $event_filter) {
// Simple HTML to PDF conversion
$html = generatePDFHTML($participants, $event_filter);
$filename = 'event_participants_' . ($event_filter ? 'event_' . $event_filter . '_' : '') . date('Y-m-d') . '.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="' . $filename . '"');
// For now, we'll output HTML that can be printed as PDF
// In production, you'd use a library like TCPDF or DOMPDF
echo $html;
}
function generatePDFHTML($participants, $event_filter) {
$eventTitle = $event_filter ? "Event ID: $event_filter" : "All Events";
$html = "
<!DOCTYPE html>
<html>
<head>
<title>Event Participants Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1 { color: #333; text-align: center; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; font-weight: bold; }
.header { text-align: center; margin-bottom: 30px; }
</style>
</head>
<body>
<div class='header'>
<h1>Event Participants Report</h1>
<p><strong>$eventTitle</strong></p>
<p>Generated on: " . date('Y-m-d H:i:s') . "</p>
</div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Type</th>
<th>Member ID</th>
<th>Area</th>
<th>District</th>
<th>Assembly</th>
<th>Registration Code</th>
<th>Payment Status</th>
<th>Amount</th>
<th>Registration Date</th>
</tr>
</thead>
<tbody>";
foreach ($participants as $participant) {
$html .= "
<tr>
<td>{$participant['first_name']} {$participant['last_name']}</td>
<td>{$participant['email']}</td>
<td>{$participant['phone']}</td>
<td>" . ucfirst($participant['participant_type']) . "</td>
<td>" . ($participant['member_id'] ?? 'N/A') . "</td>
<td>" . ($participant['area_name'] ?? 'N/A') . "</td>
<td>" . ($participant['district_name'] ?? 'N/A') . "</td>
<td>" . ($participant['assembly_name'] ?? 'N/A') . "</td>
<td>{$participant['registration_code']}</td>
<td>" . ucfirst($participant['payment_status']) . "</td>
<td>GH₵" . number_format($participant['amount_paid'], 2) . "</td>
<td>" . date('Y-m-d H:i', strtotime($participant['registration_date'])) . "</td>
</tr>";
}
$html .= "
</tbody>
</table>
</body>
</html>";
return $html;
}
$settings = getSettings();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event Participants - <?php echo htmlspecialchars($settings['site_name'] ?? 'COP Madina'); ?></title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8'
}
},
animation: {
'fade-in': 'fadeIn 0.5s ease-out',
'slide-up': 'slideUp 0.6s ease-out',
'scale-in': 'scaleIn 0.3s ease-out'
},
keyframes: {
fadeIn: {
'0%': { opacity: '0', transform: 'translateY(10px)' },
'100%': { opacity: '1', transform: 'translateY(0)' }
},
slideUp: {
'0%': { opacity: '0', transform: 'translateY(20px)' },
'100%': { opacity: '1', transform: 'translateY(0)' }
},
scaleIn: {
'0%': { opacity: '0', transform: 'scale(0.95)' },
'100%': { opacity: '1', transform: 'scale(1)' }
}
}
}
}
}
</script>
</head>
<body class="bg-gradient-to-br from-slate-50 to-blue-50 min-h-screen">
<div id="app" class="flex h-screen">
<!-- Sidebar -->
<?php include 'includes/admin_sidebar.php'; ?>
<!-- Main Content -->
<div class="flex-1 flex flex-col overflow-hidden ml-72">
<!-- Header -->
<?php include 'includes/admin_header.php'; ?>
<!-- Page Actions & Filters -->
<div class="px-8 py-4 bg-white/50 border-b border-slate-200/50">
<div class="flex flex-col lg:flex-row lg:items-center lg:justify-between space-y-4 lg:space-y-0">
<!-- Filters -->
<div class="flex flex-col sm:flex-row items-start sm:items-center space-y-3 sm:space-y-0 sm:space-x-4">
<form method="GET" class="flex flex-col sm:flex-row items-start sm:items-center space-y-3 sm:space-y-0 sm:space-x-4">
<div class="flex items-center space-x-2">
<label for="event_id" class="text-sm font-medium text-slate-700">Event:</label>
<select name="event_id" id="event_id" class="px-3 py-2 border border-slate-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-orange-500">
<option value="">All Events</option>
<?php foreach ($events as $event): ?>
<option value="<?php echo $event['id']; ?>" <?php echo $event_filter == $event['id'] ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($event['title']); ?> (<?php echo date('M Y', strtotime($event['start_date'])); ?>)
</option>
<?php endforeach; ?>
</select>
</div>
<div class="flex items-center space-x-2">
<label for="participant_type" class="text-sm font-medium text-slate-700">Type:</label>
<select name="participant_type" id="participant_type" class="px-3 py-2 border border-slate-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-orange-500">
<option value="all" <?php echo $participant_type === 'all' ? 'selected' : ''; ?>>All Participants</option>
<option value="members" <?php echo $participant_type === 'members' ? 'selected' : ''; ?>>Members Only</option>
<option value="nonmembers" <?php echo $participant_type === 'nonmembers' ? 'selected' : ''; ?>>Non-Members Only</option>
</select>
</div>
<button type="submit" class="px-4 py-2 bg-orange-600 hover:bg-orange-700 text-white font-medium rounded-lg transition-colors">
<i class="fas fa-filter mr-2"></i>Filter
</button>
</form>
</div>
<!-- Export Buttons -->
<div class="flex items-center space-x-3">
<a href="?<?php echo http_build_query(array_merge($_GET, ['export' => 'csv'])); ?>"
class="px-4 py-2 bg-green-600 hover:bg-green-700 text-white font-medium rounded-lg transition-colors flex items-center space-x-2">
<i class="fas fa-file-csv"></i>
<span>Export CSV</span>
</a>
<a href="?<?php echo http_build_query(array_merge($_GET, ['export' => 'pdf'])); ?>"
class="px-4 py-2 bg-red-600 hover:bg-red-700 text-white font-medium rounded-lg transition-colors flex items-center space-x-2">
<i class="fas fa-file-pdf"></i>
<span>Export PDF</span>
</a>
</div>
</div>
</div>
<!-- Content -->
<main class="flex-1 overflow-y-auto p-8">
<!-- Statistics Cards -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-lg p-6 border border-slate-200/50 animate-fade-in">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-slate-600">Total Participants</p>
<p class="text-3xl font-bold text-slate-800"><?php echo number_format($stats['total_participants']); ?></p>
</div>
<div class="p-3 bg-orange-100 rounded-full">
<i class="fas fa-users text-orange-600 text-xl"></i>
</div>
</div>
</div>
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-lg p-6 border border-slate-200/50 animate-fade-in" style="animation-delay: 0.1s">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-slate-600">Members</p>
<p class="text-3xl font-bold text-blue-600"><?php echo number_format($stats['members']); ?></p>
</div>
<div class="p-3 bg-blue-100 rounded-full">
<i class="fas fa-user-check text-blue-600 text-xl"></i>
</div>
</div>
</div>
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-lg p-6 border border-slate-200/50 animate-fade-in" style="animation-delay: 0.2s">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-slate-600">Non-Members</p>
<p class="text-3xl font-bold text-green-600"><?php echo number_format($stats['nonmembers']); ?></p>
</div>
<div class="p-3 bg-green-100 rounded-full">
<i class="fas fa-user-plus text-green-600 text-xl"></i>
</div>
</div>
</div>
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-lg p-6 border border-slate-200/50 animate-fade-in" style="animation-delay: 0.3s">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-slate-600">Total Revenue</p>
<p class="text-3xl font-bold text-purple-600">GH₵<?php echo number_format($stats['total_revenue'], 2); ?></p>
</div>
<div class="p-3 bg-purple-100 rounded-full">
<i class="fas fa-dollar-sign text-purple-600 text-xl"></i>
</div>
</div>
</div>
</div>
<!-- Participants Table -->
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-lg border border-slate-200/50 animate-slide-up">
<div class="p-6 border-b border-slate-200/50">
<h2 class="text-xl font-bold text-slate-800">Event Participants</h2>
<p class="text-slate-600 mt-1">
<?php if ($event_filter): ?>
Showing participants for selected event
<?php else: ?>
Showing all event participants
<?php endif; ?>
(<?php echo number_format(count($participants)); ?> total)
</p>
</div>
<div class="overflow-x-auto">
<table class="w-full">
<thead class="bg-slate-50/50">
<tr>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">Participant</th>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">Event</th>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">Type</th>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">Church Info</th>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">Registration</th>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">Payment</th>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">Attendance</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-200/50">
<?php if (empty($participants)): ?>
<tr>
<td colspan="7" class="px-6 py-8 text-center text-slate-500">
<i class="fas fa-users text-4xl mb-4 opacity-50"></i>
<p>No participants found for the selected criteria.</p>
</td>
</tr>
<?php else: ?>
<?php foreach ($participants as $index => $participant): ?>
<tr class="hover:bg-slate-50/50 transition-colors animate-fade-in" style="animation-delay: <?php echo $index * 0.05; ?>s">
<td class="px-6 py-4">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10">
<div class="h-10 w-10 rounded-full bg-gradient-to-br from-orange-400 to-red-500 flex items-center justify-center text-white font-medium">
<?php echo strtoupper(substr($participant['first_name'], 0, 1) . substr($participant['last_name'], 0, 1)); ?>
</div>
</div>
<div class="ml-4">
<div class="text-sm font-medium text-slate-900">
<?php echo htmlspecialchars($participant['first_name'] . ' ' . $participant['last_name']); ?>
</div>
<div class="text-sm text-slate-500"><?php echo htmlspecialchars($participant['email']); ?></div>
<?php if ($participant['phone']): ?>
<div class="text-xs text-slate-400"><?php echo htmlspecialchars($participant['phone']); ?></div>
<?php endif; ?>
</div>
</div>
</td>
<td class="px-6 py-4">
<div class="text-sm font-medium text-slate-900"><?php echo htmlspecialchars($participant['event_title']); ?></div>
<div class="text-xs text-slate-500">Code: <?php echo htmlspecialchars($participant['registration_code']); ?></div>
</td>
<td class="px-6 py-4">
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium <?php
echo $participant['participant_type'] === 'member' ? 'bg-blue-100 text-blue-800' : 'bg-green-100 text-green-800';
?>">
<?php if ($participant['participant_type'] === 'member'): ?>
<i class="fas fa-user-check mr-1"></i>Member
<?php else: ?>
<i class="fas fa-user-plus mr-1"></i>Non-Member
<?php endif; ?>
</span>
<?php if ($participant['member_id']): ?>
<div class="text-xs text-slate-500 mt-1">ID: <?php echo htmlspecialchars($participant['member_id']); ?></div>
<?php endif; ?>
</td>
<td class="px-6 py-4">
<div class="space-y-1">
<?php if ($participant['area_name']): ?>
<div class="text-sm font-medium text-slate-900"><?php echo htmlspecialchars($participant['area_name']); ?></div>
<?php endif; ?>
<?php if ($participant['district_name']): ?>
<div class="text-xs text-slate-600"><?php echo htmlspecialchars($participant['district_name']); ?></div>
<?php endif; ?>
<?php if ($participant['assembly_name']): ?>
<div class="text-xs text-slate-500"><?php echo htmlspecialchars($participant['assembly_name']); ?></div>
<?php endif; ?>
<?php if (!$participant['area_name'] && !$participant['district_name'] && !$participant['assembly_name']): ?>
<div class="text-xs text-slate-400 italic">Not assigned</div>
<?php endif; ?>
</div>
</td>
<td class="px-6 py-4">
<div class="text-sm text-slate-900"><?php echo date('M j, Y', strtotime($participant['registration_date'])); ?></div>
<div class="text-xs text-slate-500"><?php echo date('g:i A', strtotime($participant['registration_date'])); ?></div>
</td>
<td class="px-6 py-4">
<div class="flex items-center">
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium <?php
echo $participant['payment_status'] === 'paid' ? 'bg-green-100 text-green-800' :
($participant['payment_status'] === 'pending' ? 'bg-yellow-100 text-yellow-800' : 'bg-red-100 text-red-800');
?>">
<?php echo ucfirst($participant['payment_status']); ?>
</span>
</div>
<div class="text-xs text-slate-500 mt-1">GH₵<?php echo number_format($participant['amount_paid'], 2); ?></div>
</td>
<td class="px-6 py-4">
<div class="flex items-center space-x-2">
<?php if ($participant['checked_in_at']): ?>
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800">
<i class="fas fa-check mr-1"></i>In
</span>
<?php else: ?>
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
<i class="fas fa-minus mr-1"></i>Not In
</span>
<?php endif; ?>
<?php if ($participant['checked_out_at']): ?>
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
<i class="fas fa-sign-out-alt mr-1"></i>Out
</span>
<?php endif; ?>
</div>
<?php if ($participant['checked_in_at']): ?>
<div class="text-xs text-slate-500 mt-1">
In: <?php echo date('M j, g:i A', strtotime($participant['checked_in_at'])); ?>
</div>
<?php endif; ?>
<?php if ($participant['checked_out_at']): ?>
<div class="text-xs text-slate-500">
Out: <?php echo date('M j, g:i A', strtotime($participant['checked_out_at'])); ?>
</div>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</main>
</div>
</div>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
// Add any Vue.js reactive data here if needed
}
},
methods: {
// Add any Vue.js methods here if needed
}
}).mount('#app');
</script>
</body>
</html>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists