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_id = $_SESSION['user_id'] ?? null;
$user_role = $_SESSION['user_role'] ?? null;
if (!$user_id || !in_array($user_role, ['superuser', 'area_admin', 'district_admin', 'assembly_admin'])) {
header('Location: ../dashboard.php');
exit();
}
$db = new CopMadinaDB();
$conn = $db->getConnection();
// Get comprehensive statistics based on user role
$where_clause = "";
$params = [];
// For now, show all data for admin users
// Role-based filtering would need user details from database
// Event statistics - Updated to use correct table names
$event_stats_query = "
SELECT
COUNT(DISTINCT e.id) as total_events,
COUNT(DISTINCT CASE WHEN e.status = 'published' THEN e.id END) as active_events,
COUNT(DISTINCT CASE WHEN e.status = 'completed' THEN e.id END) as completed_events,
(
SELECT COUNT(*) FROM (
SELECT id FROM event_registrations WHERE status = 'confirmed'
UNION ALL
SELECT id FROM nonmember_registrations WHERE status = 'confirmed'
) as combined_registrations
) as total_registrations,
COALESCE(SUM(CASE WHEN er.status = 'confirmed' THEN er.amount_paid ELSE 0 END), 0) +
COALESCE(SUM(CASE WHEN nr.status = 'confirmed' THEN nr.amount_paid ELSE 0 END), 0) as total_revenue
FROM events e
LEFT JOIN event_registrations er ON e.id = er.event_id
LEFT JOIN nonmember_registrations nr ON e.id = nr.event_id
LEFT JOIN areas a ON e.area_id = a.id
LEFT JOIN districts d ON e.district_id = d.id
LEFT JOIN assemblies ass ON e.assembly_id = ass.id
$where_clause
";
$stmt = $conn->prepare($event_stats_query);
$stmt->execute($params);
$event_stats = $stmt->fetch() ?: [];
// Monthly registration trends - Updated to use correct table names
$monthly_query = "
SELECT
DATE_FORMAT(combined.created_at, '%Y-%m') as month,
COUNT(*) as registrations,
SUM(CASE WHEN combined.status = 'confirmed' THEN COALESCE(combined.amount_paid, 0) ELSE 0 END) as revenue
FROM (
SELECT er.created_at, er.status, COALESCE(er.amount_paid, 0) as amount_paid FROM event_registrations er WHERE er.created_at IS NOT NULL
UNION ALL
SELECT nr.created_at, nr.status, COALESCE(nr.amount_paid, 0) as amount_paid FROM nonmember_registrations nr WHERE nr.created_at IS NOT NULL
) as combined
WHERE combined.created_at IS NOT NULL
GROUP BY DATE_FORMAT(combined.created_at, '%Y-%m')
HAVING month IS NOT NULL
ORDER BY month DESC
LIMIT 12
";
$stmt = $conn->prepare($monthly_query);
$stmt->execute();
$monthly_data = $stmt->fetchAll() ?: [];
// Top events by registrations - Fixed subquery issue
$top_events_query = "
SELECT
e.title,
e.start_date as event_date,
COALESCE(member_regs.count, 0) + COALESCE(nonmember_regs.count, 0) as registration_count,
COALESCE(member_regs.revenue, 0) + COALESCE(nonmember_regs.revenue, 0) as revenue
FROM events e
LEFT JOIN (
SELECT
event_id,
COUNT(*) as count,
SUM(CASE WHEN status = 'confirmed' THEN amount_paid ELSE 0 END) as revenue
FROM event_registrations
GROUP BY event_id
) member_regs ON e.id = member_regs.event_id
LEFT JOIN (
SELECT
event_id,
COUNT(*) as count,
SUM(CASE WHEN status = 'confirmed' THEN amount_paid ELSE 0 END) as revenue
FROM nonmember_registrations
GROUP BY event_id
) nonmember_regs ON e.id = nonmember_regs.event_id
LEFT JOIN areas a ON e.area_id = a.id
LEFT JOIN districts d ON e.district_id = d.id
LEFT JOIN assemblies ass ON e.assembly_id = ass.id
$where_clause
ORDER BY registration_count DESC
LIMIT 10
";
$stmt = $conn->prepare($top_events_query);
$stmt->execute($params);
$top_events = $stmt->fetchAll() ?: [];
// User statistics - Updated to use correct table structure
$user_stats_query = "
SELECT
COUNT(*) as total_users,
COUNT(CASE WHEN status = 'active' THEN 1 END) as active_users,
COUNT(CASE WHEN role = 'member' THEN 1 END) as members,
COUNT(CASE WHEN role LIKE '%admin%' THEN 1 END) as admins
FROM users u
$where_clause
";
$stmt = $conn->prepare($user_stats_query);
$stmt->execute($params);
$user_stats = $stmt->fetch() ?: [];
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reports & Analytics - COP Madina Conference</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.min.js"></script>
</head>
<body class="bg-gradient-to-br from-slate-50 to-blue-50 min-h-screen">
<div 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 -->
<header class="bg-white/80 backdrop-blur-sm shadow-lg border-b border-slate-200/50">
<div class="flex items-center justify-between px-8 py-6">
<div>
<h1 class="text-3xl font-bold bg-gradient-to-r from-violet-600 to-purple-600 bg-clip-text text-transparent flex items-center">
<div class="p-2 rounded-xl bg-gradient-to-br from-violet-500 to-purple-600 mr-3">
<i class="fas fa-chart-bar text-white"></i>
</div>
Reports & Analytics
</h1>
<p class="text-slate-600 mt-1">Comprehensive insights and statistics</p>
</div>
<button onclick="window.print()"
class="px-6 py-3 bg-gradient-to-r from-violet-600 to-purple-600 hover:from-violet-700 hover:to-purple-700 text-white font-medium rounded-xl transition-all duration-200 flex items-center space-x-2 shadow-lg">
<i class="fas fa-print"></i>
<span>Print Report</span>
</button>
</div>
</header>
<!-- Content -->
<main class="flex-1 overflow-y-auto p-8">
<!-- Overview Statistics -->
<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">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-semibold text-slate-600 uppercase tracking-wider">Total Events</p>
<p class="text-3xl font-bold text-slate-800"><?php echo $event_stats['total_events'] ?? 0; ?></p>
<p class="text-xs text-violet-600 mt-1">
<?php echo $event_stats['active_events'] ?? 0; ?> active
</p>
</div>
<div class="p-4 rounded-2xl bg-gradient-to-br from-violet-500 to-purple-600">
<i class="fas fa-calendar-alt text-white text-2xl"></i>
</div>
</div>
</div>
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-lg p-6 border border-slate-200/50">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-semibold text-slate-600 uppercase tracking-wider">Registrations</p>
<p class="text-3xl font-bold text-slate-800"><?php echo $event_stats['total_registrations'] ?? 0; ?></p>
<p class="text-xs text-emerald-600 mt-1">All time</p>
</div>
<div class="p-4 rounded-2xl bg-gradient-to-br from-emerald-500 to-teal-600">
<i class="fas fa-users text-white text-2xl"></i>
</div>
</div>
</div>
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-lg p-6 border border-slate-200/50">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-semibold text-slate-600 uppercase tracking-wider">Total Revenue</p>
<p class="text-3xl font-bold text-slate-800">GH₵<?php echo number_format($event_stats['total_revenue'] ?? 0, 2); ?></p>
<p class="text-xs text-green-600 mt-1">Confirmed only</p>
</div>
<div class="p-4 rounded-2xl bg-gradient-to-br from-green-500 to-emerald-600">
<i class="fas fa-dollar-sign text-white text-2xl"></i>
</div>
</div>
</div>
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-lg p-6 border border-slate-200/50">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-semibold text-slate-600 uppercase tracking-wider">Active Users</p>
<p class="text-3xl font-bold text-slate-800"><?php echo $user_stats['active_users'] ?? 0; ?></p>
<p class="text-xs text-blue-600 mt-1">
<?php echo $user_stats['members'] ?? 0; ?> members
</p>
</div>
<div class="p-4 rounded-2xl bg-gradient-to-br from-blue-500 to-indigo-600">
<i class="fas fa-user-friends text-white text-2xl"></i>
</div>
</div>
</div>
</div>
<!-- Charts Section -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
<!-- Monthly Trends Chart -->
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-lg border border-slate-200/50 p-6">
<h3 class="text-lg font-semibold text-slate-800 mb-4">Monthly Registration Trends</h3>
<canvas id="monthlyChart" width="400" height="200"></canvas>
</div>
<!-- Revenue Chart -->
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-lg border border-slate-200/50 p-6">
<h3 class="text-lg font-semibold text-slate-800 mb-4">Monthly Revenue</h3>
<canvas id="revenueChart" width="400" height="200"></canvas>
</div>
</div>
<!-- Top Events Table -->
<div class="bg-white/70 backdrop-blur-sm rounded-2xl shadow-lg border border-slate-200/50 mb-8">
<div class="p-6 border-b border-slate-200/50">
<h3 class="text-lg font-semibold text-slate-800">Top Events by Registration</h3>
</div>
<div class="overflow-x-auto">
<table class="w-full">
<thead class="bg-slate-50/50 border-b border-slate-200/50">
<tr>
<th class="px-6 py-4 text-left text-sm font-semibold text-slate-700">Event</th>
<th class="px-6 py-4 text-left text-sm font-semibold text-slate-700">Date</th>
<th class="px-6 py-4 text-center text-sm font-semibold text-slate-700">Registrations</th>
<th class="px-6 py-4 text-center text-sm font-semibold text-slate-700">Revenue</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-200/50">
<?php foreach ($top_events as $event): ?>
<tr class="hover:bg-slate-50/50 transition-colors">
<td class="px-6 py-4">
<div class="font-semibold text-slate-800"><?php echo htmlspecialchars($event['title']); ?></div>
</td>
<td class="px-6 py-4 text-sm text-slate-600">
<?php echo date('M j, Y', strtotime($event['event_date'])); ?>
</td>
<td class="px-6 py-4 text-center">
<span class="px-3 py-1 bg-violet-100 text-violet-800 rounded-full text-sm font-semibold">
<?php echo $event['registration_count']; ?>
</span>
</td>
<td class="px-6 py-4 text-center font-semibold text-green-600">
GH₵<?php echo number_format($event['revenue'], 2); ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<!-- Summary Cards -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="bg-gradient-to-br from-violet-500 to-purple-600 rounded-2xl shadow-lg p-6 text-white">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold">Event Performance</h3>
<i class="fas fa-chart-line text-2xl opacity-80"></i>
</div>
<div class="space-y-2">
<div class="flex justify-between">
<span>Completion Rate:</span>
<span class="font-semibold">
<?php
$total = $event_stats['total_events'] ?? 1;
$completed = $event_stats['completed_events'] ?? 0;
echo round(($completed / $total) * 100, 1);
?>%
</span>
</div>
<div class="flex justify-between">
<span>Avg. Registrations:</span>
<span class="font-semibold">
<?php
echo $total > 0 ? round(($event_stats['total_registrations'] ?? 0) / $total, 1) : 0;
?>
</span>
</div>
</div>
</div>
<div class="bg-gradient-to-br from-emerald-500 to-teal-600 rounded-2xl shadow-lg p-6 text-white">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold">Revenue Insights</h3>
<i class="fas fa-money-bill-wave text-2xl opacity-80"></i>
</div>
<div class="space-y-2">
<div class="flex justify-between">
<span>Avg. per Event:</span>
<span class="font-semibold">
GH₵<?php
echo $total > 0 ? number_format(($event_stats['total_revenue'] ?? 0) / $total, 2) : '0.00';
?>
</span>
</div>
<div class="flex justify-between">
<span>Avg. per Registration:</span>
<span class="font-semibold">
GH₵<?php
$reg_total = $event_stats['total_registrations'] ?? 1;
echo $reg_total > 0 ? number_format(($event_stats['total_revenue'] ?? 0) / $reg_total, 2) : '0.00';
?>
</span>
</div>
</div>
</div>
<div class="bg-gradient-to-br from-blue-500 to-indigo-600 rounded-2xl shadow-lg p-6 text-white">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold">User Engagement</h3>
<i class="fas fa-users text-2xl opacity-80"></i>
</div>
<div class="space-y-2">
<div class="flex justify-between">
<span>Admin Users:</span>
<span class="font-semibold"><?php echo $user_stats['admins'] ?? 0; ?></span>
</div>
<div class="flex justify-between">
<span>Member Users:</span>
<span class="font-semibold"><?php echo $user_stats['members'] ?? 0; ?></span>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script>
// Wait for DOM and Chart.js to load
document.addEventListener('DOMContentLoaded', function() {
// Check if Chart.js is loaded
if (typeof Chart === 'undefined') {
console.error('Chart.js not loaded');
return;
}
// Monthly Registration Trends Chart
const monthlyCtx = document.getElementById('monthlyChart');
const revenueCtx = document.getElementById('revenueChart');
if (!monthlyCtx || !revenueCtx) {
console.error('Chart canvas elements not found');
return;
}
const monthlyData = <?php echo json_encode(array_reverse($monthly_data)); ?>;
console.log('Monthly data:', monthlyData);
// Check if we have data
if (!monthlyData || monthlyData.length === 0) {
console.warn('No monthly data available for charts');
// Show placeholder message
monthlyCtx.parentElement.innerHTML = '<div class="flex items-center justify-center h-48 text-gray-500"><p>No data available for chart</p></div>';
revenueCtx.parentElement.innerHTML = '<div class="flex items-center justify-center h-48 text-gray-500"><p>No data available for chart</p></div>';
return;
}
// Monthly Registration Chart
new Chart(monthlyCtx.getContext('2d'), {
type: 'line',
data: {
labels: monthlyData.map(item => {
if (!item.month) return 'Unknown';
const date = new Date(item.month + '-01');
return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
}),
datasets: [{
label: 'Registrations',
data: monthlyData.map(item => parseInt(item.registrations) || 0),
borderColor: 'rgb(139, 92, 246)',
backgroundColor: 'rgba(139, 92, 246, 0.1)',
tension: 0.4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Monthly Revenue Chart
new Chart(revenueCtx.getContext('2d'), {
type: 'bar',
data: {
labels: monthlyData.map(item => {
if (!item.month) return 'Unknown';
const date = new Date(item.month + '-01');
return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
}),
datasets: [{
label: 'Revenue',
data: monthlyData.map(item => parseFloat(item.revenue) || 0),
backgroundColor: 'rgba(16, 185, 129, 0.8)',
borderColor: 'rgb(16, 185, 129)',
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: true,
ticks: {
callback: function(value) {
return 'GH₵' + value.toFixed(2);
}
}
}
}
}
});
});
</script>
</body>
</html>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists