Sindbad~EG File Manager
<?php
require_once '../config/config.php';
// Check if user is logged in
if (!isLoggedIn()) {
redirect('login.php');
}
$db = new Database();
$conn = $db->getConnection();
// Pagination
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$per_page = 20;
$offset = ($page - 1) * $per_page;
// Filters
$program_filter = isset($_GET['program']) ? (int)$_GET['program'] : '';
$date_from = isset($_GET['date_from']) ? $_GET['date_from'] : '';
$date_to = isset($_GET['date_to']) ? $_GET['date_to'] : '';
$search = isset($_GET['search']) ? sanitizeInput($_GET['search']) : '';
// Build query conditions
$conditions = ['1=1'];
$params = [];
// Location restriction for admin users
if (hasRole('admin') && isset($_SESSION['location_id']) && $_SESSION['location_id']) {
$conditions[] = "p.location_id = ?";
$params[] = $_SESSION['location_id'];
}
if ($program_filter) {
$conditions[] = "ar.program_id = ?";
$params[] = $program_filter;
}
if ($date_from) {
$conditions[] = "DATE(ar.submitted_at) >= ?";
$params[] = $date_from;
}
if ($date_to) {
$conditions[] = "DATE(ar.submitted_at) <= ?";
$params[] = $date_to;
}
if ($search) {
$conditions[] = "(ar.full_name LIKE ? OR ar.email LIKE ? OR ar.district_name LIKE ? OR ar.assembly_name LIKE ?)";
$search_param = "%$search%";
$params = array_merge($params, [$search_param, $search_param, $search_param, $search_param]);
}
$where_clause = implode(' AND ', $conditions);
// Get total count
$count_query = "SELECT COUNT(*) as total
FROM attendance_records ar
JOIN programs p ON ar.program_id = p.id
WHERE $where_clause";
$count_stmt = $conn->prepare($count_query);
$count_stmt->execute($params);
$total_records = $count_stmt->fetch()['total'];
$total_pages = ceil($total_records / $per_page);
// Get attendance records
$query = "SELECT ar.*, p.name as program_name, l.name as location_name
FROM attendance_records ar
JOIN programs p ON ar.program_id = p.id
LEFT JOIN locations l ON p.location_id = l.id
WHERE $where_clause
ORDER BY ar.submitted_at DESC
LIMIT $per_page OFFSET $offset";
$stmt = $conn->prepare($query);
$stmt->execute($params);
$attendance_records = $stmt->fetchAll();
// Get programs for filter
$program_query = "SELECT id, name FROM programs WHERE is_active = 1";
if (hasRole('admin') && isset($_SESSION['location_id']) && $_SESSION['location_id']) {
$program_query .= " AND location_id = ?";
$program_stmt = $conn->prepare($program_query);
$program_stmt->execute([$_SESSION['location_id']]);
} else {
$program_stmt = $conn->prepare($program_query);
$program_stmt->execute();
}
$programs = $program_stmt->fetchAll();
// Handle delete action
if (isset($_POST['delete_id']) && hasRole('superuser')) {
$delete_id = (int)$_POST['delete_id'];
if (validateCSRFToken($_POST['csrf_token'] ?? '')) {
$delete_query = "DELETE FROM attendance_records WHERE id = ?";
$delete_stmt = $conn->prepare($delete_query);
$delete_stmt->execute([$delete_id]);
logActivity($_SESSION['user_id'], 'delete_attendance', "Deleted attendance record ID: $delete_id");
$_SESSION['success_message'] = 'Attendance record deleted successfully.';
redirect('attendance.php');
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Attendance Records - Admin Panel</title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#3B82F6',
secondary: '#F59E0B',
accent: '#6B7280'
}
}
}
}
</script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
.gradient-bg {
background: linear-gradient(135deg, #3B82F6 0%, #F59E0B 50%, #6B7280 100%);
}
</style>
</head>
<body class="bg-gray-50">
<!-- Include Sidebar -->
<?php include 'includes/sidebar.php'; ?>
<!-- Main Content -->
<div class="md:ml-64">
<!-- Header -->
<header class="bg-white shadow-sm border-b">
<div class="px-6 py-4">
<div class="flex items-center justify-between">
<h1 class="text-2xl font-bold text-gray-900">Attendance Records</h1>
<div class="flex items-center space-x-4">
<a href="reports.php" class="bg-primary text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition duration-300">
<i class="fas fa-download mr-2"></i>
Export Data
</a>
</div>
</div>
</div>
</header>
<!-- Content -->
<main class="p-6">
<!-- Success/Error Messages -->
<?php if (isset($_SESSION['success_message'])): ?>
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-6">
<div class="flex items-center">
<i class="fas fa-check-circle mr-2"></i>
<span><?php echo $_SESSION['success_message']; unset($_SESSION['success_message']); ?></span>
</div>
</div>
<?php endif; ?>
<!-- Filters -->
<div class="bg-white rounded-lg shadow p-6 mb-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">
<i class="fas fa-filter mr-2"></i>
Filter Records
</h3>
<form method="GET" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Program</label>
<select name="program" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary">
<option value="">All Programs</option>
<?php foreach ($programs as $program): ?>
<option value="<?php echo $program['id']; ?>" <?php echo ($program_filter == $program['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($program['name']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">From Date</label>
<input type="date" name="date_from" value="<?php echo $date_from; ?>"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">To Date</label>
<input type="date" name="date_to" value="<?php echo $date_to; ?>"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Search</label>
<input type="text" name="search" value="<?php echo htmlspecialchars($search); ?>"
placeholder="Name, email, district..."
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary">
</div>
<div class="flex items-end">
<button type="submit" class="w-full bg-primary text-white px-4 py-2 rounded-md hover:bg-blue-700 transition duration-300">
<i class="fas fa-search mr-2"></i>
Filter
</button>
</div>
</form>
<?php if ($program_filter || $date_from || $date_to || $search): ?>
<div class="mt-4">
<a href="attendance.php" class="text-primary hover:text-blue-700 text-sm">
<i class="fas fa-times mr-1"></i>
Clear Filters
</a>
</div>
<?php endif; ?>
</div>
<!-- Records Table -->
<div class="bg-white rounded-lg shadow overflow-hidden">
<div class="px-6 py-4 border-b">
<h3 class="text-lg font-semibold text-gray-900">
Attendance Records (<?php echo number_format($total_records); ?> total)
</h3>
</div>
<?php if (empty($attendance_records)): ?>
<div class="text-center py-12">
<i class="fas fa-users text-6xl text-gray-400 mb-4"></i>
<h3 class="text-xl font-semibold text-gray-700 mb-2">No Records Found</h3>
<p class="text-gray-500">No attendance records match your current filters.</p>
</div>
<?php else: ?>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Attendee
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Program
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Location
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Officer Type
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Contact
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
GPS Location
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Date/Time
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Actions
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<?php foreach ($attendance_records as $record): ?>
<tr class="hover:bg-gray-50">
<td class="px-6 py-4 whitespace-nowrap">
<div>
<div class="text-sm font-medium text-gray-900">
<?php echo htmlspecialchars($record['full_name']); ?>
</div>
<?php if ($record['district_name'] || $record['assembly_name']): ?>
<div class="text-sm text-gray-500">
<?php echo htmlspecialchars($record['district_name'] . ' - ' . $record['assembly_name']); ?>
</div>
<?php endif; ?>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900"><?php echo htmlspecialchars($record['program_name']); ?></div>
<?php if ($record['location_name']): ?>
<div class="text-sm text-gray-500"><?php echo htmlspecialchars($record['location_name']); ?></div>
<?php endif; ?>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
<?php echo htmlspecialchars($record['district_name'] ?? 'N/A'); ?>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
<?php if ($record['officer_type']): ?>
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
<i class="fas fa-user-tie mr-1"></i>
<?php echo htmlspecialchars($record['officer_type']); ?>
</span>
<?php else: ?>
<span class="text-gray-400 text-xs">Not specified</span>
<?php endif; ?>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<?php if ($record['email']): ?>
<div class="text-sm text-gray-900">
<i class="fas fa-envelope mr-1"></i>
<?php echo htmlspecialchars($record['email']); ?>
</div>
<?php endif; ?>
<?php if ($record['telephone']): ?>
<div class="text-sm text-gray-500">
<i class="fas fa-phone mr-1"></i>
<?php echo htmlspecialchars($record['telephone']); ?>
</div>
<?php endif; ?>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
<?php if ($record['latitude'] && $record['longitude']): ?>
<div class="flex items-center space-x-2">
<i class="fas fa-map-marker-alt text-blue-600"></i>
<div>
<div class="text-xs font-mono">
<?php echo number_format($record['latitude'], 4); ?>, <?php echo number_format($record['longitude'], 4); ?>
</div>
<?php if ($record['location_accuracy']): ?>
<div class="text-xs text-gray-500">
±<?php echo round($record['location_accuracy']); ?>m
</div>
<?php endif; ?>
<a href="https://www.google.com/maps?q=<?php echo $record['latitude']; ?>,<?php echo $record['longitude']; ?>"
target="_blank"
class="text-xs text-blue-600 hover:text-blue-800">
<i class="fas fa-external-link-alt mr-1"></i>View Map
</a>
</div>
</div>
<?php else: ?>
<span class="text-gray-400 text-xs">
<i class="fas fa-map-marker-alt"></i> No location
</span>
<?php endif; ?>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
<?php echo date('M j, Y', strtotime($record['submitted_at'])); ?><br>
<span class="text-gray-500"><?php echo date('g:i A', strtotime($record['submitted_at'])); ?></span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
<div class="flex space-x-2">
<button onclick="viewDetails(<?php echo $record['id']; ?>)"
class="text-primary hover:text-blue-700" title="View Details">
<i class="fas fa-eye"></i>
</button>
<?php if (hasRole('superuser')): ?>
<button onclick="editRecord(<?php echo $record['id']; ?>)"
class="text-green-600 hover:text-green-900" title="Edit Record">
<i class="fas fa-edit"></i>
</button>
<button onclick="deleteRecord(<?php echo $record['id']; ?>)"
class="text-red-600 hover:text-red-900" title="Delete Record">
<i class="fas fa-trash"></i>
</button>
<?php endif; ?>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<!-- Pagination -->
<?php if ($total_pages > 1): ?>
<div class="px-6 py-4 border-t">
<div class="flex items-center justify-between">
<div class="text-sm text-gray-700">
Showing <?php echo (($page - 1) * $per_page) + 1; ?> to
<?php echo min($page * $per_page, $total_records); ?> of
<?php echo $total_records; ?> results
</div>
<div class="flex space-x-2">
<?php if ($page > 1): ?>
<a href="?page=<?php echo $page - 1; ?>&<?php echo http_build_query($_GET); ?>"
class="px-3 py-2 text-sm bg-gray-200 text-gray-700 rounded hover:bg-gray-300">
Previous
</a>
<?php endif; ?>
<?php for ($i = max(1, $page - 2); $i <= min($total_pages, $page + 2); $i++): ?>
<a href="?page=<?php echo $i; ?>&<?php echo http_build_query($_GET); ?>"
class="px-3 py-2 text-sm <?php echo ($i == $page) ? 'bg-primary text-white' : 'bg-gray-200 text-gray-700 hover:bg-gray-300'; ?> rounded">
<?php echo $i; ?>
</a>
<?php endfor; ?>
<?php if ($page < $total_pages): ?>
<a href="?page=<?php echo $page + 1; ?>&<?php echo http_build_query($_GET); ?>"
class="px-3 py-2 text-sm bg-gray-200 text-gray-700 rounded hover:bg-gray-300">
Next
</a>
<?php endif; ?>
</div>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
</main>
</div>
<!-- View Details Modal -->
<div id="viewModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 hidden items-center justify-center z-50">
<div class="bg-white rounded-lg p-6 max-w-2xl mx-auto max-h-screen overflow-y-auto">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold text-gray-900">Attendance Details</h3>
<button onclick="closeViewModal()" class="text-gray-400 hover:text-gray-600">
<i class="fas fa-times"></i>
</button>
</div>
<div id="viewModalContent">
<!-- Content will be loaded here -->
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div id="deleteModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 hidden items-center justify-center z-50">
<div class="bg-white rounded-lg p-6 max-w-sm mx-auto">
<h3 class="text-lg font-semibold text-gray-900 mb-4">Confirm Delete</h3>
<p class="text-gray-600 mb-6">Are you sure you want to delete this attendance record? This action cannot be undone.</p>
<div class="flex justify-end space-x-4">
<button onclick="closeDeleteModal()" class="px-4 py-2 text-gray-600 hover:text-gray-800">
Cancel
</button>
<form method="POST" id="deleteForm" class="inline">
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
<input type="hidden" name="delete_id" id="deleteId">
<button type="submit" class="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700">
Delete
</button>
</form>
</div>
</div>
</div>
<script>
function viewDetails(id) {
// Show loading state
document.getElementById('viewModalContent').innerHTML = '<div class="text-center py-4"><i class="fas fa-spinner fa-spin text-2xl text-gray-400"></i><p class="text-gray-500 mt-2">Loading...</p></div>';
document.getElementById('viewModal').classList.remove('hidden');
document.getElementById('viewModal').classList.add('flex');
// Fetch attendance details
fetch('get_attendance_details.php?id=' + id)
.then(response => response.text())
.then(data => {
document.getElementById('viewModalContent').innerHTML = data;
})
.catch(error => {
document.getElementById('viewModalContent').innerHTML = '<div class="text-center py-4 text-red-600"><i class="fas fa-exclamation-triangle text-2xl"></i><p class="mt-2">Error loading details</p></div>';
});
}
function closeViewModal() {
document.getElementById('viewModal').classList.add('hidden');
document.getElementById('viewModal').classList.remove('flex');
}
function editRecord(id) {
// Redirect to edit page or show edit modal
window.location.href = 'edit_attendance.php?id=' + id;
}
function deleteRecord(id) {
document.getElementById('deleteId').value = id;
document.getElementById('deleteModal').classList.remove('hidden');
document.getElementById('deleteModal').classList.add('flex');
}
function closeDeleteModal() {
document.getElementById('deleteModal').classList.add('hidden');
document.getElementById('deleteModal').classList.remove('flex');
}
// Close modals when clicking outside
document.getElementById('viewModal').addEventListener('click', function(e) {
if (e.target === this) {
closeViewModal();
}
});
document.getElementById('deleteModal').addEventListener('click', function(e) {
if (e.target === this) {
closeDeleteModal();
}
});
</script>
</body>
</html>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists