Autosave: 20260215-003353

This commit is contained in:
Flatlogic Bot 2026-02-15 00:33:53 +00:00
parent f03a7a8de5
commit 10ea0441d5
2 changed files with 206 additions and 32 deletions

View File

@ -118,3 +118,42 @@ body {
font-size: 0.75rem;
color: #94a3b8;
}
/* Filter Sidebar Styles */
.filter-sidebar {
transition: all 0.3s ease;
width: 300px;
position: relative;
}
.filter-sidebar.collapsed {
width: 0;
overflow: hidden;
padding: 0;
margin: 0;
border: none;
opacity: 0;
}
.filter-toggle-btn {
position: absolute;
left: -40px;
top: 10px;
z-index: 10;
background: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 4px 0 0 4px;
padding: 5px 10px;
cursor: pointer;
box-shadow: -2px 0 5px rgba(0,0,0,0.05);
}
.filter-card {
position: sticky;
top: 90px;
}
.extra-small {
font-size: 0.7rem;
}

199
index.php
View File

@ -200,8 +200,59 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_supplier'])) {
}
// Fetch Data
$projects = db()->prepare("SELECT * FROM projects WHERE tenant_id = ? ORDER BY created_at DESC");
$projects->execute([$tenant_id]);
$search = $_GET['search'] ?? '';
$status_filter = $_GET['status'] ?? '';
$date_preset = $_GET['date_preset'] ?? '';
$start_from = $_GET['start_from'] ?? '';
$start_to = $_GET['start_to'] ?? '';
$query = "SELECT * FROM projects WHERE tenant_id = ?";
$params = [$tenant_id];
if ($search) {
$query .= " AND (name LIKE ? OR code LIKE ?)";
$params[] = "%$search%";
$params[] = "%$search%";
}
if ($status_filter) {
$query .= " AND status = ?";
$params[] = $status_filter;
}
if ($date_preset && $date_preset !== 'custom') {
switch ($date_preset) {
case 'today':
$query .= " AND start_date = CURRENT_DATE";
break;
case 'this_week':
$query .= " AND start_date >= DATE_SUB(CURRENT_DATE, INTERVAL WEEKDAY(CURRENT_DATE) DAY)";
break;
case 'last_week':
$query .= " AND start_date >= DATE_SUB(CURRENT_DATE, INTERVAL WEEKDAY(CURRENT_DATE) + 7 DAY) AND start_date < DATE_SUB(CURRENT_DATE, INTERVAL WEEKDAY(CURRENT_DATE) DAY)";
break;
case 'this_month':
$query .= " AND start_date >= DATE_FORMAT(CURRENT_DATE, '%Y-%m-01')";
break;
case 'last_month':
$query .= " AND start_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE, INTERVAL 1 MONTH), '%Y-%m-01') AND start_date < DATE_FORMAT(CURRENT_DATE, '%Y-%m-01')";
break;
case 'this_year':
$query .= " AND start_date >= DATE_FORMAT(CURRENT_DATE, '%Y-01-01')";
break;
case 'last_year':
$query .= " AND start_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE, INTERVAL 1 YEAR), '%Y-01-01') AND start_date < DATE_FORMAT(CURRENT_DATE, '%Y-01-01')";
break;
}
} elseif ($date_preset === 'custom' && $start_from && $start_to) {
$query .= " AND start_date BETWEEN ? AND ?";
$params[] = $start_from;
$params[] = $start_to;
}
$query .= " ORDER BY created_at DESC";
$projects = db()->prepare($query);
$projects->execute($params);
$projectList = $projects->fetchAll();
$employees = db()->prepare("
@ -272,6 +323,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'SR&ED Project Tracking
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SR&ED Manager - Dashboard</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link href="assets/css/custom.css?v=<?= time() ?>" rel="stylesheet">
</head>
@ -288,7 +340,6 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'SR&ED Project Tracking
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">Projects</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#addProjectModal">Add Project</a></li>
<li><a class="dropdown-item" href="index.php">List Projects</a></li>
</ul>
</li>
@ -356,36 +407,100 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'SR&ED Project Tracking
</div>
<?php endif; ?>
<div class="card mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
<span>Active Projects</span>
<button class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#addProjectModal">+ New Project</button>
<div class="d-flex gap-3 mb-4 position-relative">
<div class="flex-grow-1">
<div class="card h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<span>Active Projects</span>
<div class="d-flex gap-2">
<button class="btn btn-sm btn-outline-secondary" onclick="toggleFilters()"><i class="bi bi-funnel"></i> Filter</button>
<button class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#addProjectModal">+ New Project</button>
</div>
</div>
<div class="table-responsive">
<table class="table align-middle">
<thead>
<tr>
<th>Project Name</th>
<th>Code</th>
<th>Start Date</th>
<th>Status</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($projectList)): ?>
<tr><td colspan="5" class="text-center py-4 text-muted">No projects found matching the filters.</td></tr>
<?php endif; ?>
<?php foreach ($projectList as $p): ?>
<tr>
<td><strong><?= htmlspecialchars($p['name']) ?></strong></td>
<td><code class="text-primary"><?= htmlspecialchars($p['code']) ?></code></td>
<td><?= $p['start_date'] ?></td>
<td><span class="status-badge status-<?= str_replace('_', '-', $p['status']) ?>"><?= ucfirst(str_replace('_', ' ', $p['status'])) ?></span></td>
<td class="text-end">
<button class="btn btn-sm btn-outline-secondary">Edit</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<div class="table-responsive">
<table class="table align-middle">
<thead>
<tr>
<th>Project Name</th>
<th>Code</th>
<th>Start Date</th>
<th>Status</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($projectList as $p): ?>
<tr>
<td><strong><?= htmlspecialchars($p['name']) ?></strong></td>
<td><code class="text-primary"><?= htmlspecialchars($p['code']) ?></code></td>
<td><?= $p['start_date'] ?></td>
<td><span class="status-badge status-<?= $p['status'] ?>"><?= ucfirst($p['status']) ?></span></td>
<td class="text-end">
<button class="btn btn-sm btn-outline-secondary">Edit</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="filter-sidebar shadow-sm" id="projectFilterSidebar">
<div class="card filter-card">
<div class="card-header bg-light small fw-bold d-flex justify-content-between align-items-center">
<span>FILTERS</span>
<button type="button" class="btn-close extra-small" onclick="toggleFilters()"></button>
</div>
<div class="card-body p-3">
<form method="GET" id="filterForm">
<div class="mb-3">
<label class="form-label extra-small fw-bold text-uppercase text-muted">Search</label>
<input type="text" name="search" class="form-control form-control-sm" placeholder="Name or code..." value="<?= htmlspecialchars($search) ?>">
</div>
<div class="mb-3">
<label class="form-label extra-small fw-bold text-uppercase text-muted">Status</label>
<select name="status" class="form-select form-select-sm">
<option value="">All Statuses</option>
<option value="active" <?= $status_filter === 'active' ? 'selected' : '' ?>>Active</option>
<option value="on_hold" <?= $status_filter === 'on_hold' ? 'selected' : '' ?>>On Hold</option>
<option value="completed" <?= $status_filter === 'completed' ? 'selected' : '' ?>>Completed</option>
</select>
</div>
<div class="mb-3">
<label class="form-label extra-small fw-bold text-uppercase text-muted">Start Date</label>
<select name="date_preset" class="form-select form-select-sm" onchange="handleDatePreset(this.value)">
<option value="">Any Time</option>
<option value="today" <?= $date_preset === 'today' ? 'selected' : '' ?>>Today</option>
<option value="this_week" <?= $date_preset === 'this_week' ? 'selected' : '' ?>>This Week</option>
<option value="last_week" <?= $date_preset === 'last_week' ? 'selected' : '' ?>>Last Week</option>
<option value="this_month" <?= $date_preset === 'this_month' ? 'selected' : '' ?>>This Month</option>
<option value="last_month" <?= $date_preset === 'last_month' ? 'selected' : '' ?>>Last Month</option>
<option value="this_year" <?= $date_preset === 'this_year' ? 'selected' : '' ?>>This Year</option>
<option value="last_year" <?= $date_preset === 'last_year' ? 'selected' : '' ?>>Last Year</option>
<option value="custom" <?= $date_preset === 'custom' ? 'selected' : '' ?>>Custom Range...</option>
</select>
</div>
<div id="customDateRange" class="<?= $date_preset === 'custom' ? '' : 'd-none' ?>">
<div class="mb-2">
<label class="form-label extra-small text-muted">From</label>
<input type="date" name="start_from" class="form-control form-control-sm" value="<?= htmlspecialchars($start_from) ?>">
</div>
<div class="mb-3">
<label class="form-label extra-small text-muted">To</label>
<input type="date" name="start_to" class="form-control form-control-sm" value="<?= htmlspecialchars($start_to) ?>">
</div>
</div>
<div class="d-grid gap-2">
<button type="submit" class="btn btn-sm btn-primary">Apply Filters</button>
<a href="index.php" class="btn btn-sm btn-link text-decoration-none extra-small">Clear All</a>
</div>
</form>
</div>
</div>
</div>
</div>
@ -845,5 +960,25 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'SR&ED Project Tracking
<?php endforeach; ?>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
function toggleFilters() {
const sidebar = document.getElementById('projectFilterSidebar');
sidebar.classList.toggle('collapsed');
}
function handleDatePreset(value) {
const customRange = document.getElementById('customDateRange');
if (value === 'custom') {
customRange.classList.remove('d-none');
} else {
customRange.classList.add('d-none');
}
}
// Initial state check for sidebar on mobile
if (window.innerWidth < 992) {
document.getElementById('projectFilterSidebar').classList.add('collapsed');
}
</script>
</body>
</html>