Sindbad~EG File Manager
<?php
// Get current page for active menu highlighting
$current_page = basename($_SERVER['PHP_SELF']);
// Get site settings
$db = new Database();
$conn = $db->getConnection();
$query = "SELECT setting_key, setting_value FROM settings WHERE setting_key IN ('site_title', 'site_logo')";
$stmt = $conn->prepare($query);
$stmt->execute();
$settings = [];
while ($row = $stmt->fetch()) {
$settings[$row['setting_key']] = $row['setting_value'];
}
?>
<!-- Mobile menu button -->
<div class="md:hidden">
<button id="mobileMenuBtn" class="bg-primary text-white p-2 rounded-lg shadow-lg">
<div class="menu-icon">
<span></span>
<span></span>
<span></span>
</div>
</button>
</div>
<!-- Sidebar -->
<div id="sidebar" class="sidebar fixed inset-y-0 left-0 z-40 w-64 bg-white shadow-lg">
<div class="flex flex-col h-full">
<!-- Logo -->
<div class="gradient-bg p-6">
<div class="flex items-center">
<img src="../<?php echo $settings['site_logo'] ?? SITE_LOGO; ?>" alt="Logo" class="h-8 w-8 mr-3">
</div>
</div>
<!-- User Info -->
<div class="p-4 border-b">
<div class="flex items-center">
<div class="w-10 h-10 bg-primary rounded-full flex items-center justify-center text-white font-bold">
<?php echo strtoupper(substr($_SESSION['full_name'] ?? 'U', 0, 1)); ?>
</div>
<div class="ml-3">
<p class="text-sm font-medium text-gray-900"><?php echo htmlspecialchars($_SESSION['full_name'] ?? 'Unknown User'); ?></p>
<p class="text-xs text-gray-500 capitalize"><?php echo htmlspecialchars($_SESSION['user_role'] ?? 'user'); ?></p>
</div>
</div>
</div>
<!-- Navigation -->
<nav class="flex-1 p-4">
<ul class="space-y-2">
<li>
<a href="dashboard.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'dashboard.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-tachometer-alt mr-3"></i>
Dashboard
</a>
</li>
<li>
<a href="programs.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'programs.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-calendar mr-3"></i>
Programs
</a>
</li>
<li>
<a href="forms.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'forms.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-edit mr-3"></i>
Form Management
</a>
</li>
<li>
<a href="attendance.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'attendance.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-users mr-3"></i>
Attendance Records
</a>
</li>
<li>
<a href="reports.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'reports.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-chart-bar mr-3"></i>
Reports
</a>
</li>
<li>
<a href="special_reports.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'special_reports.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-chart-line mr-3"></i>
Special Reports
</a>
</li>
<!-- Admin and Superuser only - Special Codes -->
<?php if (hasRole('admin') || hasRole('superuser')): ?>
<li>
<a href="special_codes.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'special_codes.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-key mr-3"></i>
Special Codes
</a>
</li>
<?php endif; ?>
<li>
<a href="locations.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'locations.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-map-marker-alt mr-3"></i>
Locations
</a>
</li>
<!-- Admin and Superuser only pages -->
<?php if (hasRole('admin') || hasRole('superuser')): ?>
<li>
<a href="settings.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'settings.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-cog mr-3"></i>
Settings
</a>
</li>
<li>
<a href="audit.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'audit.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-shield-alt mr-3"></i>
Audit Logs
</a>
</li>
<li>
<a href="email_management.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'email_management.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-envelope-open-text mr-3"></i>
Email Management
</a>
</li>
<li>
<a href="email_diagnostics.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'email_diagnostics.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-stethoscope mr-3"></i>
Email Diagnostics
</a>
</li>
<?php endif; ?>
<!-- Superuser only pages -->
<?php if (hasRole('superuser')): ?>
<li>
<a href="users.php" class="flex items-center px-4 py-2 text-gray-700 <?php echo ($current_page == 'users.php') ? 'bg-gray-100' : 'hover:bg-gray-100'; ?> rounded-lg">
<i class="fas fa-user-cog mr-3"></i>
User Management
</a>
</li>
<?php endif; ?>
</ul>
</nav>
<!-- Logout -->
<div class="p-4 border-t">
<a href="logout.php" class="flex items-center px-4 py-2 text-red-600 hover:bg-red-50 rounded-lg">
<i class="fas fa-sign-out-alt mr-3"></i>
Logout
</a>
</div>
</div>
</div>
<style>
/* Enhanced Mobile-Optimized Sidebar */
.sidebar {
transition: transform 0.3s ease-in-out;
z-index: 40;
}
/* Mobile: Sidebar starts closed */
@media (max-width: 767px) {
.sidebar {
transform: translateX(-100%);
}
.sidebar-open {
transform: translateX(0);
}
.sidebar-closed {
transform: translateX(-100%);
}
/* Mobile overlay */
.sidebar-overlay {
position: fixed;
inset: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 35;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out;
}
.sidebar-overlay.active {
opacity: 1;
visibility: visible;
}
/* Mobile menu button enhancements */
#mobileMenuBtn {
position: fixed;
top: 1rem;
left: 1rem;
z-index: 50;
background: #3B82F6;
color: white;
padding: 0.75rem;
border-radius: 0.5rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
border: none;
cursor: pointer;
transition: all 0.3s ease;
min-width: 44px;
min-height: 44px;
display: flex;
align-items: center;
justify-content: center;
}
#mobileMenuBtn:hover {
background: #2563EB;
transform: scale(1.05);
}
#mobileMenuBtn:active {
transform: scale(0.95);
}
/* Menu icon animation */
.menu-icon {
width: 20px;
height: 20px;
position: relative;
transition: all 0.3s ease;
}
.menu-icon span {
display: block;
position: absolute;
height: 2px;
width: 100%;
background: white;
border-radius: 1px;
opacity: 1;
left: 0;
transform: rotate(0deg);
transition: 0.25s ease-in-out;
}
.menu-icon span:nth-child(1) {
top: 0px;
}
.menu-icon span:nth-child(2) {
top: 8px;
}
.menu-icon span:nth-child(3) {
top: 16px;
}
/* Animated hamburger to X */
.menu-open .menu-icon span:nth-child(1) {
top: 8px;
transform: rotate(135deg);
}
.menu-open .menu-icon span:nth-child(2) {
opacity: 0;
left: -60px;
}
.menu-open .menu-icon span:nth-child(3) {
top: 8px;
transform: rotate(-135deg);
}
/* Mobile navigation improvements */
.sidebar .mobile-nav-item {
padding: 1rem 1.25rem;
border-bottom: 1px solid #e5e7eb;
transition: background-color 0.2s ease;
min-height: 56px;
display: flex;
align-items: center;
}
.sidebar .mobile-nav-item:hover {
background-color: #f3f4f6;
}
.sidebar .mobile-nav-item:active {
background-color: #e5e7eb;
}
/* Touch-friendly spacing */
.sidebar nav ul li a {
padding: 1rem 1.25rem;
min-height: 56px;
display: flex;
align-items: center;
font-size: 1rem;
transition: all 0.2s ease;
}
.sidebar nav ul li a i {
margin-right: 1rem;
width: 20px;
text-align: center;
font-size: 1.1rem;
}
/* User info mobile optimization */
.sidebar .p-4 {
padding: 1.25rem;
}
/* Logo section mobile */
.sidebar .gradient-bg {
padding: 1.5rem 1.25rem;
}
/* Logout button mobile */
.sidebar .border-t a {
padding: 1.25rem;
min-height: 60px;
display: flex;
align-items: center;
font-size: 1rem;
font-weight: 500;
}
}
/* Desktop: Sidebar always visible */
@media (min-width: 768px) {
.sidebar {
transform: translateX(0);
position: fixed;
}
.sidebar-closed {
transform: translateX(0);
}
.sidebar-open {
transform: translateX(0);
}
/* Hide mobile menu button on desktop */
#mobileMenuBtn {
display: none;
}
/* Hide overlay on desktop */
.sidebar-overlay {
display: none;
}
}
/* Smooth scrolling for mobile sidebar */
@media (max-width: 767px) {
.sidebar {
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
/* Custom scrollbar for mobile */
.sidebar::-webkit-scrollbar {
width: 4px;
}
.sidebar::-webkit-scrollbar-track {
background: #f1f1f1;
}
.sidebar::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 2px;
}
.sidebar::-webkit-scrollbar-thumb:hover {
background: #a1a1a1;
}
}
/* Focus states for accessibility */
.sidebar a:focus {
outline: 2px solid #3B82F6;
outline-offset: 2px;
}
#mobileMenuBtn:focus {
outline: 2px solid #ffffff;
outline-offset: 2px;
}
/* High contrast mode support */
@media (prefers-contrast: high) {
.sidebar {
border-right: 2px solid;
}
.sidebar nav ul li a {
border: 1px solid transparent;
}
.sidebar nav ul li a:hover,
.sidebar nav ul li a:focus {
border-color: currentColor;
}
}
/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
.sidebar,
.sidebar-overlay,
#mobileMenuBtn,
.menu-icon span {
transition: none;
}
}
</style>
<script>
// Enhanced Mobile-Optimized Sidebar JavaScript
document.addEventListener('DOMContentLoaded', function() {
const mobileMenuBtn = document.getElementById('mobileMenuBtn');
const sidebar = document.getElementById('sidebar');
let overlay = null;
let isOpen = false;
// Create overlay element
function createOverlay() {
if (!overlay) {
overlay = document.createElement('div');
overlay.className = 'sidebar-overlay';
document.body.appendChild(overlay);
// Close sidebar when clicking overlay
overlay.addEventListener('click', closeSidebar);
}
}
// Open sidebar
function openSidebar() {
if (window.innerWidth < 768) {
createOverlay();
sidebar.classList.remove('sidebar-closed');
sidebar.classList.add('sidebar-open');
overlay.classList.add('active');
mobileMenuBtn.classList.add('menu-open');
document.body.style.overflow = 'hidden'; // Prevent background scrolling
isOpen = true;
// Focus first menu item for accessibility
const firstMenuItem = sidebar.querySelector('nav ul li a');
if (firstMenuItem) {
setTimeout(() => firstMenuItem.focus(), 300);
}
}
}
// Close sidebar
function closeSidebar() {
if (window.innerWidth < 768) {
sidebar.classList.remove('sidebar-open');
sidebar.classList.add('sidebar-closed');
if (overlay) {
overlay.classList.remove('active');
}
mobileMenuBtn.classList.remove('menu-open');
document.body.style.overflow = ''; // Restore scrolling
isOpen = false;
// Return focus to menu button
mobileMenuBtn.focus();
}
}
// Toggle sidebar
function toggleSidebar() {
if (isOpen) {
closeSidebar();
} else {
openSidebar();
}
}
if (mobileMenuBtn && sidebar) {
// Menu button click handler
mobileMenuBtn.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
toggleSidebar();
});
// Close sidebar when clicking outside on mobile
document.addEventListener('click', function(e) {
if (window.innerWidth < 768 && isOpen &&
!sidebar.contains(e.target) &&
!mobileMenuBtn.contains(e.target)) {
closeSidebar();
}
});
// Handle escape key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && isOpen && window.innerWidth < 768) {
closeSidebar();
}
});
// Handle window resize
window.addEventListener('resize', function() {
if (window.innerWidth >= 768) {
// Desktop view - ensure sidebar is visible and clean up mobile states
sidebar.classList.remove('sidebar-open', 'sidebar-closed');
if (overlay) {
overlay.classList.remove('active');
}
mobileMenuBtn.classList.remove('menu-open');
document.body.style.overflow = '';
isOpen = false;
} else {
// Mobile view - ensure sidebar starts closed
if (!isOpen) {
sidebar.classList.add('sidebar-closed');
sidebar.classList.remove('sidebar-open');
}
}
});
// Initialize mobile state
if (window.innerWidth < 768) {
sidebar.classList.add('sidebar-closed');
createOverlay();
}
// Close sidebar when clicking on menu items (mobile)
const menuItems = sidebar.querySelectorAll('nav ul li a');
menuItems.forEach(item => {
item.addEventListener('click', function() {
if (window.innerWidth < 768) {
// Small delay to allow navigation to start
setTimeout(closeSidebar, 150);
}
});
});
// Touch gesture support for swipe to close
let touchStartX = 0;
let touchStartY = 0;
let isSwiping = false;
sidebar.addEventListener('touchstart', function(e) {
touchStartX = e.touches[0].clientX;
touchStartY = e.touches[0].clientY;
isSwiping = false;
}, { passive: true });
sidebar.addEventListener('touchmove', function(e) {
if (!touchStartX) return;
const touchEndX = e.touches[0].clientX;
const touchEndY = e.touches[0].clientY;
const deltaX = touchStartX - touchEndX;
const deltaY = Math.abs(touchStartY - touchEndY);
// If horizontal swipe is more significant than vertical
if (Math.abs(deltaX) > deltaY && Math.abs(deltaX) > 30) {
isSwiping = true;
// Swipe left to close (only if at the edge of sidebar)
if (deltaX > 50 && touchStartX < 50 && window.innerWidth < 768 && isOpen) {
closeSidebar();
}
}
}, { passive: true });
sidebar.addEventListener('touchend', function() {
touchStartX = 0;
touchStartY = 0;
isSwiping = false;
}, { passive: true });
}
// Prevent body scroll when sidebar is open on mobile
function preventBodyScroll(e) {
if (window.innerWidth < 768 && isOpen && !sidebar.contains(e.target)) {
e.preventDefault();
}
}
// Add scroll prevention
document.addEventListener('touchmove', preventBodyScroll, { passive: false });
document.addEventListener('wheel', preventBodyScroll, { passive: false });
});
</script>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists