deadline widget

This commit is contained in:
r.mubarakzyanov 2026-04-19 09:14:19 +03:00
parent 1fadc22178
commit dd5edab2f3
4 changed files with 395 additions and 112 deletions

View File

@ -296,6 +296,11 @@
<div class="page-wrapper">
<div class="page-content">
<?php
$pdo = DBHandlerSelect::getInstance()->getConnection();
include(__DIR__ . '/scadenzario/include/my_deadlines_widget.php');
?>
<h3 class="dashboard-title">Dashboard Produzione</h3>
<!-- ===== STATISTICHE PRINCIPALI ===== -->

View File

@ -98,58 +98,81 @@ $departments = $pdo->query("SELECT DISTINCT department FROM employees WHERE depa
<div class="page-wrapper">
<div class="page-content">
<nav class="scad-breadcrumb" aria-label="breadcrumb">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="scadenzario/index.php">Scadenzario</a></li>
<li class="breadcrumb-item active" aria-current="page">Calendario</li>
</ol>
</nav>
<?php include(__DIR__ . '/include/my_deadlines_widget.php'); ?>
<div class="d-flex gap-2 mb-3">
<a href="scadenzario/index.php" class="btn btn-scad-outline d-inline-flex align-items-center gap-2">
<i class="fa-solid fa-list"></i><span>Lista Scadenze</span>
</a>
<div class="d-flex gap-2 mb-3 flex-wrap align-items-center">
<button type="button" class="btn btn-scad-outline d-inline-flex align-items-center gap-2" data-bs-toggle="modal" data-bs-target="#filtersModal">
<i class="fa-solid fa-filter"></i>
<span>Filtri</span>
<span id="filterCountBadge" class="badge bg-primary rounded-pill d-none" style="font-size:0.7rem">0</span>
</button>
<button id="btnResetFilters" type="button" class="btn btn-light border d-inline-flex align-items-center justify-content-center gap-1" title="Reset filtri" style="min-width:38px;height:38px">
<i class="fa-solid fa-rotate-left"></i>
<span class="d-none d-sm-inline">Reset</span>
</button>
<span id="activeFiltersSummary" class="text-muted small text-truncate d-none d-md-inline"></span>
</div>
<div id="activeFiltersSummaryMobile" class="text-muted small d-md-none mb-2" style="padding-left:0.25rem"></div>
<div class="filter-bar mb-3">
<div class="row g-2 align-items-center">
<div class="col-12 col-sm-6 col-md-auto">
<select id="filterStatus" class="form-select" style="font-size:0.85rem;border-color:#d0d9e8;min-width:160px">
<option value="non-completata" selected>Stato: Non completate</option>
<option value="">Stato: Tutti</option>
<option value="attiva">Attive</option>
<option value="in-scadenza">In scadenza</option>
<option value="scaduta">Scadute</option>
<option value="completata">Completate</option>
</select>
</div>
<div class="col-12 col-sm-6 col-md-auto">
<select id="filterDepartment" class="form-select" style="font-size:0.85rem;border-color:#d0d9e8;min-width:160px">
<option value="">Reparto: Tutti</option>
<?php foreach ($departments as $dept): ?>
<option value="<?= htmlspecialchars($dept, ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($dept, ENT_QUOTES, 'UTF-8') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-12 col-sm-6 col-md-auto">
<select id="filterEmployee" class="form-select" style="font-size:0.85rem;border-color:#d0d9e8;min-width:160px">
<option value="">Responsabile: Tutti</option>
<?php foreach ($employees as $emp): ?>
<option value="<?= htmlspecialchars(trim($emp['first_name'] . ' ' . $emp['last_name']), ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars(trim($emp['first_name'] . ' ' . $emp['last_name']), ENT_QUOTES, 'UTF-8') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-12 col-sm-auto">
<button id="btnResetFilters" class="btn btn-sm btn-light border w-100 w-sm-auto" title="Reset filtri">
<i class="fa-solid fa-rotate-left me-1"></i> Reset
</button>
<!-- Filters Modal -->
<div class="modal fade" id="filtersModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fa-solid fa-filter me-2"></i>Filtri calendario</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Chiudi"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label fw-semibold">Stato</label>
<select id="filterStatus" class="form-select">
<option value="non-completata" selected>Non completate</option>
<option value="">Tutti</option>
<option value="attiva">Attive</option>
<option value="in-scadenza">In scadenza</option>
<option value="scaduta">Scadute</option>
<option value="completata">Completate</option>
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Reparto</label>
<select id="filterDepartment" class="form-select">
<option value="">Tutti</option>
<?php foreach ($departments as $dept): ?>
<option value="<?= htmlspecialchars($dept, ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($dept, ENT_QUOTES, 'UTF-8') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-0">
<label class="form-label fw-semibold">Responsabile</label>
<select id="filterEmployee" class="form-select">
<option value="">Tutti</option>
<?php foreach ($employees as $emp): ?>
<option value="<?= htmlspecialchars(trim($emp['first_name'] . ' ' . $emp['last_name']), ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars(trim($emp['first_name'] . ' ' . $emp['last_name']), ENT_QUOTES, 'UTF-8') ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light border" id="btnResetFiltersModal">
<i class="fa-solid fa-rotate-left me-1"></i> Reset
</button>
<button type="button" class="btn btn-scad-primary" data-bs-dismiss="modal">
<i class="fa-solid fa-check me-1"></i> Applica
</button>
</div>
</div>
</div>
</div>
<div class="card scad-card">
<div class="card-header d-flex align-items-center justify-content-between">
<h5><i class="fa-solid fa-calendar-days me-2"></i>Calendario Scadenze</h5>
<div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
<h5 class="d-none d-md-flex align-items-center mb-0"><i class="fa-solid fa-calendar-days me-2"></i>Calendario Scadenze</h5>
<div class="header-actions d-flex gap-2 flex-wrap ms-auto">
<a href="scadenzario/index.php" class="btn btn-scad-outline d-inline-flex align-items-center gap-2">
<i class="fa-solid fa-list"></i><span>Lista Scadenze</span>
</a>
</div>
</div>
<div class="card-body">
<div class="legend">
@ -211,15 +234,41 @@ $departments = $pdo->query("SELECT DISTINCT department FROM employees WHERE depa
calendar.render();
// Filters
function updateFilterBadge() {
var active = 0;
var summary = [];
var st = document.getElementById('filterStatus');
var stv = st.value;
if (stv && stv !== 'non-completata') { active++; summary.push(st.options[st.selectedIndex].text); }
var dept = document.getElementById('filterDepartment').value;
if (dept) { active++; summary.push('Reparto: ' + dept); }
var emp = document.getElementById('filterEmployee').value;
if (emp) { active++; summary.push('Responsabile: ' + emp); }
var badge = document.getElementById('filterCountBadge');
if (active > 0) { badge.textContent = active; badge.classList.remove('d-none'); }
else { badge.classList.add('d-none'); }
var summaryText = summary.length ? summary.slice(0, 2).join(' • ') + (summary.length > 2 ? ' +' + (summary.length - 2) : '') : '';
document.getElementById('activeFiltersSummary').textContent = summaryText;
document.getElementById('activeFiltersSummaryMobile').textContent = summaryText;
}
document.querySelectorAll('#filterStatus, #filterDepartment, #filterEmployee').forEach(function(el) {
el.addEventListener('change', function() { calendar.refetchEvents(); });
el.addEventListener('change', function() { calendar.refetchEvents(); updateFilterBadge(); });
});
document.getElementById('btnResetFilters').addEventListener('click', function() {
function resetFilters() {
document.getElementById('filterStatus').value = 'non-completata';
document.getElementById('filterDepartment').value = '';
document.getElementById('filterEmployee').value = '';
calendar.refetchEvents();
});
updateFilterBadge();
}
document.getElementById('btnResetFilters').addEventListener('click', resetFilters);
document.getElementById('btnResetFiltersModal').addEventListener('click', resetFilters);
updateFilterBadge();
});
</script>
</body>

View File

@ -0,0 +1,91 @@
<?php
/**
* Renders two status banners for the current user:
* - red -> overdue deadlines (scaduta)
* - orange -> approaching deadlines (in scadenza)
* Scope: deadlines assigned directly to the user OR to their department.
*/
$_empStmt = $pdo->prepare("SELECT id, department FROM employees WHERE auth_user_id = ? LIMIT 1");
$_empStmt->execute([(int)$iduserlogin]);
$_emp = $_empStmt->fetch(PDO::FETCH_ASSOC) ?: null;
$_overdue = 0;
$_approaching = 0;
if ($_emp) {
$_empId = (int)$_emp['id'];
$_deptRaw = (string)($_emp['department'] ?? '');
$_dept = trim($_deptRaw);
$_sql = "
SELECT
SUM(CASE WHEN d.due_date < CURDATE() THEN 1 ELSE 0 END) AS overdue_cnt,
SUM(CASE WHEN d.due_date >= CURDATE()
AND d.due_date <= DATE_ADD(CURDATE(), INTERVAL d.notification_days DAY)
THEN 1 ELSE 0 END) AS approaching_cnt
FROM scad_deadlines d
WHERE d.status <> 'completed'
AND (
d.id IN (SELECT deadline_id FROM scad_deadline_employee WHERE employee_id = ?)
OR (? <> '' AND FIND_IN_SET(?, REPLACE(d.departments, ', ', ',')) > 0)
)
";
$_st = $pdo->prepare($_sql);
$_st->execute([$_empId, $_dept, $_dept]);
$_row = $_st->fetch(PDO::FETCH_ASSOC) ?: [];
$_overdue = (int)($_row['overdue_cnt'] ?? 0);
$_approaching = (int)($_row['approaching_cnt'] ?? 0);
}
if (!$_emp || ($_overdue === 0 && $_approaching === 0)) {
return;
}
?>
<style>
.my-deadlines-widgets { display: flex; gap: 0.75rem; margin-bottom: 1rem; flex-wrap: wrap; }
.my-deadlines-widgets .mdw {
flex: 1 1 260px;
display: flex; align-items: center; gap: 0.9rem;
padding: 0.85rem 1rem;
border-radius: 0.6rem;
text-decoration: none;
color: #fff;
box-shadow: 0 2px 6px rgba(0,0,0,0.08);
transition: transform 0.15s, box-shadow 0.15s;
}
.my-deadlines-widgets .mdw:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0,0,0,0.15); color: #fff; }
.my-deadlines-widgets .mdw-red { background: linear-gradient(135deg, #dc3545 0%, #b02a37 100%); }
.my-deadlines-widgets .mdw-orange { background: linear-gradient(135deg, #e8930c 0%, #c77a00 100%); }
.my-deadlines-widgets .mdw-icon {
width: 42px; height: 42px; border-radius: 50%;
display: flex; align-items: center; justify-content: center;
background: rgba(255,255,255,0.22); font-size: 1.2rem; flex-shrink: 0;
}
.my-deadlines-widgets .mdw-body { flex: 1; line-height: 1.2; }
.my-deadlines-widgets .mdw-count { font-size: 1.6rem; font-weight: 700; }
.my-deadlines-widgets .mdw-label { font-size: 0.8rem; opacity: 0.95; }
.my-deadlines-widgets .mdw-arrow { opacity: 0.7; font-size: 0.9rem; }
</style>
<div class="my-deadlines-widgets">
<?php if ($_overdue > 0): ?>
<a class="mdw mdw-red" href="scadenzario/index.php?filter_my=1&filter_status=scaduta">
<span class="mdw-icon"><i class="fa-solid fa-triangle-exclamation"></i></span>
<span class="mdw-body">
<span class="mdw-count"><?= $_overdue ?></span>
<span class="mdw-label d-block">Scadenz<?= $_overdue === 1 ? 'a' : 'e' ?> scadut<?= $_overdue === 1 ? 'a' : 'e' ?> — <?= $_dept !== '' ? htmlspecialchars($_dept, ENT_QUOTES, 'UTF-8') : 'personali' ?></span>
</span>
<span class="mdw-arrow"><i class="fa-solid fa-arrow-right"></i></span>
</a>
<?php endif; ?>
<?php if ($_approaching > 0): ?>
<a class="mdw mdw-orange" href="scadenzario/index.php?filter_my=1&filter_status=in-scadenza">
<span class="mdw-icon"><i class="fa-solid fa-clock"></i></span>
<span class="mdw-body">
<span class="mdw-count"><?= $_approaching ?></span>
<span class="mdw-label d-block">In scadenza a breve <?= $_dept !== '' ? htmlspecialchars($_dept, ENT_QUOTES, 'UTF-8') : 'personali' ?></span>
</span>
<span class="mdw-arrow"><i class="fa-solid fa-arrow-right"></i></span>
</a>
<?php endif; ?>
</div>

View File

@ -13,6 +13,16 @@ if ($filterSubjectId) {
if (!$filterSubjectName) { $filterSubjectId = null; }
}
// Optional filter: limit to deadlines assigned to the current user (directly OR via department)
$filterMy = !empty($_GET['filter_my']);
$filterMyEmployee = null;
if ($filterMy) {
$st = $pdo->prepare("SELECT id, department FROM employees WHERE auth_user_id = ? LIMIT 1");
$st->execute([(int)$iduserlogin]);
$filterMyEmployee = $st->fetch(PDO::FETCH_ASSOC) ?: null;
if (!$filterMyEmployee) { $filterMy = false; }
}
$sql = "
SELECT d.*,
s.name AS subject_name,
@ -26,11 +36,22 @@ $sql = "
LEFT JOIN scad_deadline_employee de ON de.deadline_id = d.id
LEFT JOIN employees e ON e.id = de.employee_id
";
$where = [];
$params = [];
if ($filterSubjectId) {
$sql .= " WHERE d.subject_id = ?";
$where[] = "d.subject_id = ?";
$params[] = $filterSubjectId;
}
if ($filterMy && $filterMyEmployee) {
$where[] = "(d.id IN (SELECT deadline_id FROM scad_deadline_employee WHERE employee_id = ?)"
. " OR (? <> '' AND FIND_IN_SET(?, REPLACE(d.departments, ', ', ',')) > 0))";
$params[] = (int)$filterMyEmployee['id'];
$params[] = (string)($filterMyEmployee['department'] ?? '');
$params[] = (string)($filterMyEmployee['department'] ?? '');
}
if (!empty($where)) {
$sql .= " WHERE " . implode(' AND ', $where);
}
$sql .= " GROUP BY d.id ORDER BY (d.status = 'completed') ASC, d.due_date ASC";
$stmt = $pdo->prepare($sql);
@ -277,10 +298,29 @@ $today = date('Y-m-d');
justify-content: space-between;
}
.header-menu-btn {
width: 38px !important;
height: 38px !important;
padding: 0 !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
line-height: 1 !important;
font-size: 1rem !important;
position: relative;
}
.header-menu-btn i {
display: block;
line-height: 1;
margin: 0;
font-size: 1rem;
}
.header-menu-btn::after { display: none !important; }
@media (max-width: 575.98px) {
.scad-card .card-header { flex-direction: column; gap: 0.75rem; }
.header-actions { width: 100%; }
.header-actions .btn { width: 100%; justify-content: center; }
.scad-card .card-header { flex-direction: column; gap: 0.75rem; align-items: flex-start !important; }
.header-actions { width: 100%; justify-content: flex-end; }
.header-actions #btnAddDeadline { flex: 1; justify-content: center; }
.filter-bar .form-select { width: 100%; }
}
</style>
@ -292,6 +332,8 @@ $today = date('Y-m-d');
<div class="page-wrapper">
<div class="page-content">
<?php include(__DIR__ . '/include/my_deadlines_widget.php'); ?>
<?php if ($filterSubjectId): ?>
<div class="subject-filter-banner">
<div>
@ -306,60 +348,105 @@ $today = date('Y-m-d');
</div>
<?php endif; ?>
<!-- Filter Bar -->
<div class="filter-bar mb-3">
<div class="row g-2 align-items-center mb-2">
<div class="col-12 col-sm-6 col-md-auto">
<select id="filterStatus" class="form-select">
<?php if ($filterSubjectId): ?>
<option value="" selected>Stato: Tutti</option>
<option value="non-completata">Stato: Non completate</option>
<?php else: ?>
<option value="non-completata" selected>Stato: Non completate</option>
<option value="">Stato: Tutti</option>
<?php endif; ?>
<option value="attiva">Attive</option>
<option value="in-scadenza">In scadenza</option>
<option value="scaduta">Scadute</option>
<option value="completata">Completate</option>
</select>
</div>
<div class="col-12 col-sm-6 col-md-auto">
<select id="filterSubject" class="form-select">
<option value="">Argomento: Tutti</option>
<?php foreach ($subjects as $s): ?>
<option value="<?= (int)$s['id'] ?>" <?= $filterSubjectId === (int)$s['id'] ? 'selected' : '' ?>><?= htmlspecialchars($s['name'], ENT_QUOTES, 'UTF-8') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-12 col-sm-6 col-md-auto">
<select id="filterDepartment" class="form-select">
<option value="">Reparto: Tutti</option>
<?php foreach ($departments as $dept): ?>
<option value="<?= htmlspecialchars($dept, ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($dept, ENT_QUOTES, 'UTF-8') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-12 col-sm-6 col-md-auto">
<select id="filterEmployee" class="form-select">
<option value="">Responsabile: Tutti</option>
<?php foreach ($employees as $emp): ?>
<option value="<?= htmlspecialchars(trim($emp['first_name'] . ' ' . $emp['last_name']), ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars(trim($emp['first_name'] . ' ' . $emp['last_name']), ENT_QUOTES, 'UTF-8') ?></option>
<?php endforeach; ?>
</select>
</div>
<?php if ($filterMy): ?>
<div class="subject-filter-banner">
<div>
<i class="fa-solid fa-user-check me-2"></i>
<strong>Le mie scadenze</strong>
<span class="text-muted ms-2">(assegnate a me o al reparto <?= htmlspecialchars($filterMyEmployee['department'] ?? '—', ENT_QUOTES, 'UTF-8') ?>)</span>
</div>
<div class="row g-2 align-items-center">
<div class="col-12 col-sm-6 col-md-auto">
<input type="text" class="form-control" id="filterDueRange" placeholder="Scadenza: da — a" readonly style="font-size:0.85rem;border-color:#d0d9e8;min-width:220px;background:#fff">
</div>
<div class="col-12 col-sm-6 col-md-auto">
<input type="text" class="form-control" id="filterCheckRange" placeholder="Controllo: da — a" readonly style="font-size:0.85rem;border-color:#d0d9e8;min-width:220px;background:#fff">
</div>
<div class="col-12 col-sm-auto">
<button id="btnResetFilters" class="btn btn-sm btn-light border w-100 w-sm-auto" title="Reset filtri">
<i class="fa-solid fa-rotate-left me-1"></i> Reset
</button>
<a href="scadenzario/index.php" class="btn btn-sm btn-light border">
<i class="fa-solid fa-xmark me-1"></i> Tutte le scadenze
</a>
</div>
<?php endif; ?>
<!-- Filter Toolbar -->
<div class="filter-toolbar mb-3">
<div class="d-flex align-items-center gap-2">
<button type="button" class="btn btn-scad-outline d-inline-flex align-items-center gap-2 flex-shrink-0" data-bs-toggle="modal" data-bs-target="#filtersModal">
<i class="fa-solid fa-filter"></i>
<span>Filtri</span>
<span id="filterCountBadge" class="badge bg-primary rounded-pill d-none" style="font-size:0.7rem">0</span>
</button>
<button id="btnResetFilters" type="button" class="btn btn-light border d-inline-flex align-items-center justify-content-center gap-1 flex-shrink-0" title="Reset filtri" style="min-width:38px;height:38px">
<i class="fa-solid fa-rotate-left"></i>
<span class="d-none d-sm-inline">Reset</span>
</button>
<span id="activeFiltersSummary" class="text-muted small text-truncate d-none d-md-inline"></span>
</div>
<div id="activeFiltersSummaryMobile" class="text-muted small d-md-none mt-1" style="padding-left:0.25rem"></div>
</div>
<!-- Filters Modal -->
<div class="modal fade" id="filtersModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fa-solid fa-filter me-2"></i>Filtri scadenze</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Chiudi"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label fw-semibold">Stato</label>
<select id="filterStatus" class="form-select">
<?php if ($filterSubjectId): ?>
<option value="" selected>Tutti</option>
<option value="non-completata">Non completate</option>
<?php else: ?>
<option value="non-completata" selected>Non completate</option>
<option value="">Tutti</option>
<?php endif; ?>
<option value="attiva">Attive</option>
<option value="in-scadenza">In scadenza</option>
<option value="scaduta">Scadute</option>
<option value="completata">Completate</option>
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Argomento</label>
<select id="filterSubject" class="form-select">
<option value="">Tutti</option>
<?php foreach ($subjects as $s): ?>
<option value="<?= (int)$s['id'] ?>" <?= $filterSubjectId === (int)$s['id'] ? 'selected' : '' ?>><?= htmlspecialchars($s['name'], ENT_QUOTES, 'UTF-8') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Reparto</label>
<select id="filterDepartment" class="form-select">
<option value="">Tutti</option>
<?php foreach ($departments as $dept): ?>
<option value="<?= htmlspecialchars($dept, ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($dept, ENT_QUOTES, 'UTF-8') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Responsabile</label>
<select id="filterEmployee" class="form-select">
<option value="">Tutti</option>
<?php foreach ($employees as $emp): ?>
<option value="<?= htmlspecialchars(trim($emp['first_name'] . ' ' . $emp['last_name']), ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars(trim($emp['first_name'] . ' ' . $emp['last_name']), ENT_QUOTES, 'UTF-8') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Data scadenza (intervallo)</label>
<input type="text" class="form-control" id="filterDueRange" placeholder="da — a" readonly>
</div>
<div class="mb-0">
<label class="form-label fw-semibold">Data ultimo controllo (intervallo)</label>
<input type="text" class="form-control" id="filterCheckRange" placeholder="da — a" readonly>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light border" id="btnResetFiltersModal">
<i class="fa-solid fa-rotate-left me-1"></i> Reset
</button>
<button type="button" class="btn btn-scad-primary" data-bs-dismiss="modal">
<i class="fa-solid fa-check me-1"></i> Applica
</button>
</div>
</div>
</div>
</div>
@ -367,20 +454,34 @@ $today = date('Y-m-d');
<!-- Main Card -->
<div class="card scad-card">
<div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
<h5><i class="fa-solid fa-calendar-check me-2"></i>Lista Scadenze</h5>
<h5 class="d-none d-md-flex align-items-center"><i class="fa-solid fa-calendar-check me-2"></i>Lista Scadenze</h5>
<div class="header-actions d-flex gap-2 flex-wrap">
<a href="scadenzario/subjects/index.php" class="btn btn-scad-outline d-inline-flex align-items-center gap-2">
<!-- Desktop (≥md): tutte le azioni visibili -->
<a href="scadenzario/subjects/index.php" class="btn btn-scad-outline d-none d-md-inline-flex align-items-center gap-2">
<i class="fa-solid fa-tags"></i><span>Argomenti</span>
</a>
<a href="scadenzario/calendar.php" class="btn btn-scad-outline d-inline-flex align-items-center gap-2">
<a href="scadenzario/calendar.php" class="btn btn-scad-outline d-none d-md-inline-flex align-items-center gap-2">
<i class="fa-solid fa-calendar-days"></i><span>Calendario</span>
</a>
<button class="btn btn-scad-outline d-inline-flex align-items-center gap-2" id="btnStampa">
<button class="btn btn-scad-outline d-none d-md-inline-flex align-items-center gap-2" id="btnStampa">
<i class="fa-solid fa-print"></i><span>Stampa</span>
</button>
<button class="btn btn-scad-primary d-inline-flex align-items-center gap-2" id="btnAddDeadline">
<i class="fa-solid fa-plus"></i><span>Nuova Scadenza</span>
</button>
<!-- Mobile (<md): menu a tendina con le altre azioni -->
<div class="dropdown d-md-none">
<button class="btn btn-scad-outline header-menu-btn" type="button" data-bs-toggle="dropdown" aria-expanded="false" title="Altre azioni">
<i class="fa-solid fa-bars"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item d-flex align-items-center gap-2" href="scadenzario/subjects/index.php"><i class="fa-solid fa-tags"></i> Argomenti</a></li>
<li><a class="dropdown-item d-flex align-items-center gap-2" href="scadenzario/calendar.php"><i class="fa-solid fa-calendar-days"></i> Calendario</a></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2" id="btnStampaMobile"><i class="fa-solid fa-print"></i> Stampa</button></li>
</ul>
</div>
</div>
</div>
<div class="card-body">
@ -705,6 +806,7 @@ $today = date('Y-m-d');
onChange: function() {
if (table) table.draw();
filterCards();
if (typeof updateFilterBadge === 'function') updateFilterBadge();
}
};
var fpDue = flatpickr('#filterDueRange', fpOpts);
@ -832,11 +934,34 @@ $today = date('Y-m-d');
});
}
function updateFilterBadge() {
var active = 0;
var summary = [];
var st = $('#filterStatus').val();
if (st && st !== 'non-completata') { active++; summary.push($('#filterStatus option:selected').text()); }
var subj = $('#filterSubject').val();
if (subj) { active++; summary.push('Argomento: ' + $('#filterSubject option:selected').text()); }
var dept = $('#filterDepartment').val();
if (dept) { active++; summary.push('Reparto: ' + dept); }
var emp = $('#filterEmployee').val();
if (emp) { active++; summary.push('Responsabile: ' + emp); }
if (fpDue.selectedDates.length) { active++; summary.push('Scadenza: ' + $('#filterDueRange').val()); }
if (fpCheck.selectedDates.length) { active++; summary.push('Controllo: ' + $('#filterCheckRange').val()); }
var $badge = $('#filterCountBadge');
if (active > 0) $badge.text(active).removeClass('d-none');
else $badge.addClass('d-none');
var summaryText = summary.length ? summary.slice(0, 2).join(' • ') + (summary.length > 2 ? ' +' + (summary.length - 2) : '') : '';
$('#activeFiltersSummary, #activeFiltersSummaryMobile').text(summaryText);
}
$('#filterStatus, #filterDepartment, #filterEmployee, #filterSubject').on('change', function() {
if (table) table.draw();
filterCards();
updateFilterBadge();
});
$('#btnResetFilters').on('click', function() {
function resetFilters() {
$('#filterStatus').val('non-completata');
$('#filterDepartment').val('');
$('#filterEmployee').val('');
@ -845,11 +970,21 @@ $today = date('Y-m-d');
fpCheck.clear();
if (table) table.draw();
filterCards();
});
updateFilterBadge();
}
$('#btnResetFilters, #btnResetFiltersModal').on('click', resetFilters);
// Apply URL filters (e.g. from dashboard widgets)
(function () {
var qs = new URLSearchParams(window.location.search);
var qStatus = qs.get('filter_status');
if (qStatus) $('#filterStatus').val(qStatus);
})();
// Apply default filter on load
if (table) table.draw();
filterCards();
updateFilterBadge();
// --- Modal ---
var modal = new bootstrap.Modal(document.getElementById('deadlineModal'));
@ -1085,7 +1220,7 @@ $today = date('Y-m-d');
}
// Stampa
document.getElementById('btnStampa').addEventListener('click', function() {
function doStampa() {
var params = [];
var s = $('#filterStatus').val();
var d = $('#filterDepartment').val();
@ -1100,7 +1235,10 @@ $today = date('Y-m-d');
if (chkDates.length >= 1) params.push('check_from=' + formatDate(chkDates[0]));
if (chkDates.length >= 2) params.push('check_to=' + formatDate(chkDates[1]));
window.open('scadenzario/print.php' + (params.length ? '?' + params.join('&') : ''), '_blank');
});
}
document.getElementById('btnStampa').addEventListener('click', doStampa);
var btnStampaMobile = document.getElementById('btnStampaMobile');
if (btnStampaMobile) btnStampaMobile.addEventListener('click', doStampa);
});
</script>
</body>