Files
zibo-dashboard/public/userarea/scadenzario/index.php
T
2026-05-24 00:15:09 +03:00

1439 lines
67 KiB
PHP

<?php include('../include/headscript.php'); ?>
<?php
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// Optional filter: show only deadlines of a given subject (used by "Storico" link from subjects CRUD)
$filterSubjectId = isset($_GET['subject_id']) && is_numeric($_GET['subject_id']) ? (int)$_GET['subject_id'] : null;
$filterSubjectName = null;
if ($filterSubjectId) {
$s = $pdo->prepare("SELECT name FROM scad_subjects WHERE id = ?");
$s->execute([$filterSubjectId]);
$filterSubjectName = $s->fetchColumn() ?: null;
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 e.id, dep.name AS department_name
FROM employees e
LEFT JOIN departments dep ON dep.id = e.department_id
WHERE e.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,
s.color AS subject_color,
f.name AS function_name,
GROUP_CONCAT(DISTINCT CONCAT(e.first_name, ' ', e.last_name) ORDER BY e.first_name SEPARATOR ', ') as responsabili,
GROUP_CONCAT(DISTINCT dep.name ORDER BY dep.name SEPARATOR ', ') as reparti_persone,
d.departments as reparti_assegnati,
(SELECT COUNT(*) FROM scad_deadline_attachments att WHERE att.deadline_id = d.id) as attachment_count
FROM scad_deadlines d
LEFT JOIN scad_subjects s ON s.id = d.subject_id
LEFT JOIN scad_functions f ON f.id = d.function_id
LEFT JOIN scad_deadline_employee de ON de.deadline_id = d.id
LEFT JOIN employees e ON e.id = de.employee_id
LEFT JOIN departments dep ON dep.id = e.department_id
";
$where = [];
$params = [];
if ($filterSubjectId) {
$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_name'] ?? '');
$params[] = (string)($filterMyEmployee['department_name'] ?? '');
}
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);
$stmt->execute($params);
$deadlines = $stmt->fetchAll(PDO::FETCH_ASSOC);
require __DIR__ . '/include/deadline_form_data.php';
$today = date('Y-m-d');
function getContrastTextColor($hexColor)
{
$hexColor = trim($hexColor);
if ($hexColor === '') {
return '#ffffff';
}
$hexColor = ltrim($hexColor, '#');
if (strlen($hexColor) === 3) {
$hexColor = $hexColor[0] . $hexColor[0] .
$hexColor[1] . $hexColor[1] .
$hexColor[2] . $hexColor[2];
}
if (strlen($hexColor) !== 6) {
return '#ffffff';
}
$r = hexdec(substr($hexColor, 0, 2));
$g = hexdec(substr($hexColor, 2, 2));
$b = hexdec(substr($hexColor, 4, 2));
$brightness = (($r * 299) + ($g * 587) + ($b * 114)) / 1000;
return ($brightness > 150) ? '#000000' : '#ffffff';
}
?>
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php
$scriptDir = dirname($_SERVER['SCRIPT_NAME']);
// Go up from /userarea/scadenzario to /userarea/
$baseHref = dirname($scriptDir) . '/';
?>
<base href="<?= $baseHref ?>">
<?php include('../cssinclude.php'); ?>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/1.13.7/css/dataTables.bootstrap5.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css" rel="stylesheet">
<title>Scadenzario - Lista Scadenze</title>
<script>
if (window.innerWidth > 1024) document.addEventListener('DOMContentLoaded', function() {
document.getElementById('appWrapper').classList.add('toggled')
})
</script>
<style>
:root {
--scad-primary: #5a8fd8;
--scad-primary-hover: #4578c0;
--scad-heading: #2c3e6b;
--scad-card-bg: linear-gradient(135deg, #f0f4ff 0%, #e8eeff 100%);
--scad-card-border: #dde4f0;
--scad-red: #dc3545;
--scad-orange: #e8930c;
--scad-green: #198754;
--scad-blue: #5a8fd8;
}
.scad-card {
border: none;
border-radius: 0.75rem;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
overflow: hidden;
}
.scad-card .card-header {
background: var(--scad-card-bg);
border-bottom: 1px solid var(--scad-card-border);
padding: 1rem 1.25rem;
}
.scad-card .card-header h5 {
font-weight: 700;
color: var(--scad-heading);
margin: 0;
font-size: 1.1rem;
letter-spacing: -0.01em;
}
.scad-card .card-body {
padding: 1.25rem;
}
.btn-scad-primary {
background: var(--scad-primary);
border: none;
color: #fff;
font-weight: 600;
font-size: 0.85rem;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: all 0.2s;
}
.btn-scad-primary:hover {
background: var(--scad-primary-hover);
color: #fff;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(90, 143, 216, 0.35);
}
.btn-scad-outline {
background: transparent;
border: 1.5px solid var(--scad-primary);
color: var(--scad-primary);
font-weight: 600;
font-size: 0.85rem;
padding: 0.45rem 1rem;
border-radius: 0.5rem;
transition: all 0.2s;
}
.btn-scad-outline:hover {
background: var(--scad-primary);
color: #fff;
transform: translateY(-1px);
}
/* Quick filter buttons */
.btn-quick-filter {
border: none;
font-weight: 700;
font-size: 0.85rem;
height: 38px;
padding: 0 0.85rem;
border-radius: 0.55rem;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.45rem;
transition: all 0.2s ease;
white-space: nowrap;
}
.btn-quick-warning {
background: #fff3cd;
color: #8a5a00;
border: 1px solid #ffd966;
}
.btn-quick-warning:hover,
.btn-quick-warning.active {
background: #ffc107;
color: #000;
box-shadow: 0 4px 12px rgba(255, 193, 7, 0.35);
transform: translateY(-1px);
}
.btn-quick-danger {
background: #fde2e6;
color: #b02a37;
border: 1px solid #f5a3ad;
}
.btn-quick-danger:hover,
.btn-quick-danger.active {
background: #dc3545;
color: #fff;
box-shadow: 0 4px 12px rgba(220, 53, 69, 0.35);
transform: translateY(-1px);
}
@media (max-width: 575.98px) {
.btn-quick-filter span {
display: none;
}
.btn-quick-filter {
width: 38px;
padding: 0;
}
}
/* Action buttons */
.btn-action {
width: 32px;
height: 32px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 0.4rem;
border: none;
transition: all 0.2s;
font-size: 0.78rem;
}
.btn-action-edit {
background: #eef3ff;
color: var(--scad-primary);
}
.btn-action-edit:hover {
background: var(--scad-primary);
color: #fff;
transform: translateY(-1px);
box-shadow: 0 3px 8px rgba(90, 143, 216, 0.3);
}
.btn-action-complete {
background: #e8f5e9;
color: var(--scad-green);
}
.btn-action-complete:hover {
background: var(--scad-green);
color: #fff;
transform: translateY(-1px);
box-shadow: 0 3px 8px rgba(25, 135, 84, 0.3);
}
.btn-action-delete {
background: #fff0f0;
color: var(--scad-red);
}
.btn-action-delete:hover {
background: var(--scad-red);
color: #fff;
transform: translateY(-1px);
box-shadow: 0 3px 8px rgba(220, 53, 69, 0.3);
}
/* Status badges */
.badge-status {
font-weight: 600;
font-size: 0.75rem;
padding: 0.35em 0.65em;
border-radius: 2rem;
display: inline-block;
white-space: nowrap;
}
.badge-attiva {
background: #5a8fd8 !important;
color: #ffffff !important;
}
.badge-scaduta {
background: #dc3545 !important;
color: #ffffff !important;
}
.badge-in-scadenza {
background: #ffc107 !important;
color: #000000 !important;
}
.badge-completata {
background: #198754 !important;
color: #ffffff !important;
}
/* Row coloring */
#deadlinesTable tbody tr.row-overdue {
background-color: #fff5f5;
}
#deadlinesTable tbody tr.row-approaching {
background-color: #fffbeb;
}
#deadlinesTable tbody tr.row-completed {
opacity: 0.6;
}
#deadlinesTable tbody tr:hover {
filter: brightness(0.97);
}
/* Subject color full row - soft background */
#deadlinesTable tbody tr[data-subject-color] td {
background-color: var(--subject-row-bg, transparent) !important;
}
#deadlinesTable tbody tr[data-subject-color] td:first-child {
border-left: 4px solid var(--subject-color, transparent);
}
/* Keep hover readable */
#deadlinesTable tbody tr[data-subject-color]:hover td {
background-color: var(--subject-row-bg-hover, var(--subject-row-bg, transparent)) !important;
}
.subject-chip {
display: inline-block;
padding: 0.15rem 0.55rem;
border-radius: 1rem;
font-size: 0.72rem;
font-weight: 600;
color: #fff;
letter-spacing: 0.02em;
white-space: nowrap;
}
.deadline-card[data-subject-color] {
border-left: 4px solid var(--subject-color, var(--scad-card-border));
}
/* Filter banner (subject history mode) */
.subject-filter-banner {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
padding: 0.75rem 1rem;
background: var(--scad-card-bg);
border: 1px solid var(--scad-card-border);
border-radius: 0.5rem;
margin-bottom: 1rem;
font-size: 0.9rem;
}
/* Filter bar */
.filter-bar .form-select {
border-radius: 0.5rem;
font-size: 0.85rem;
border-color: #d0d9e8;
min-width: 160px;
}
.filter-bar .form-select:focus {
border-color: var(--scad-primary);
box-shadow: 0 0 0 0.2rem rgba(90, 143, 216, 0.15);
}
/* Modal groups */
.form-section-title {
font-size: 0.8rem;
font-weight: 700;
color: var(--scad-heading);
text-transform: uppercase;
letter-spacing: 0.04em;
margin-bottom: 0.75rem;
padding-bottom: 0.4rem;
border-bottom: 2px solid #e8eeff;
}
.modal-backdrop {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
}
.modal {
position: fixed;
}
.modal-content {
background: #fff !important;
}
.modal-body {
background: #fff !important;
}
.modal-footer {
background: #fff !important;
}
.modal-header {
background: var(--scad-card-bg);
border-bottom: 1px solid var(--scad-card-border);
}
.modal-title {
font-weight: 700;
color: var(--scad-heading);
}
/* Empty state */
.empty-state {
text-align: center;
padding: 3rem 1rem;
color: #8e99b0;
}
.empty-state i {
font-size: 2.5rem;
margin-bottom: 0.75rem;
color: #c5cfe0;
display: block;
}
/* Table text overflow */
#deadlinesTable td {
max-width: 250px;
overflow: hidden;
text-overflow: ellipsis;
}
#deadlinesTable td:first-child {
max-width: 110px;
width: 110px;
}
/* Attachment list in modal */
.att-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.5rem 0.75rem;
background: #f8f9fa;
border-radius: 0.4rem;
margin-bottom: 0.4rem;
font-size: 0.85rem;
}
.att-item .att-name {
color: var(--scad-heading);
font-weight: 500;
word-break: break-all;
}
.att-item .att-actions {
display: flex;
gap: 0.4rem;
flex-shrink: 0;
margin-left: 0.5rem;
}
.att-item .att-actions a,
.att-item .att-actions button {
width: 28px;
height: 28px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 0.3rem;
border: none;
font-size: 0.75rem;
transition: all 0.15s;
}
.att-item .att-download {
background: #eef3ff;
color: var(--scad-primary);
text-decoration: none;
}
.att-item .att-download:hover {
background: var(--scad-primary);
color: #fff;
}
.att-item .att-remove {
background: #fff0f0;
color: var(--scad-red);
cursor: pointer;
}
.att-item .att-remove:hover {
background: var(--scad-red);
color: #fff;
}
/* Select2 tweaks */
.select2-container--bootstrap-5 .select2-selection {
min-height: 38px;
border-color: #d0d9e8;
}
/* Mobile cards */
.deadline-card {
border: 1px solid #e2e8f0;
border-radius: 0.75rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.07);
padding: 1rem 1rem 0.85rem;
margin-bottom: 1rem;
transition: box-shadow 0.2s;
border-left: 5px solid var(--scad-blue);
background: #fff;
}
.deadline-card:active {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.deadline-card.card-overdue {
border-left-color: var(--scad-red);
background: #fff8f8;
border-color: #fcd5d5;
}
.deadline-card.card-approaching {
border-left-color: var(--scad-orange);
background: #fffdf5;
border-color: #fce9b8;
}
.deadline-card.card-completed {
border-left-color: #adb5bd;
opacity: 0.55;
border-color: #dee2e6;
}
.deadline-card .card-topic {
font-weight: 700;
font-size: 0.95rem;
color: var(--scad-heading);
margin-bottom: 0.35rem;
line-height: 1.3;
}
.deadline-card .card-meta {
font-size: 0.8rem;
color: #6c757d;
display: flex;
flex-wrap: wrap;
gap: 0.3rem 1rem;
margin-bottom: 0.5rem;
}
.deadline-card .card-meta i {
width: 14px;
text-align: center;
}
.deadline-card .card-actions {
display: flex;
gap: 0.5rem;
align-items: center;
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;
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>
</head>
<body>
<div class="wrapper" id="appWrapper">
<?php include('../include/navbar.php'); ?>
<?php include('../include/topbar.php'); ?>
<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>
<i class="fa-solid fa-filter me-2"></i>
<strong>Storico per argomento:</strong>
<?= htmlspecialchars($filterSubjectName, ENT_QUOTES, 'UTF-8') ?>
<span class="text-muted ms-2">(tutte le scadenze — aperte e chiuse)</span>
</div>
<a href="scadenzario/index.php" class="btn btn-sm btn-light border">
<i class="fa-solid fa-xmark me-1"></i> Rimuovi filtro
</a>
</div>
<?php endif; ?>
<?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_name'] ?? '—', ENT_QUOTES, 'UTF-8') ?>)</span>
</div>
<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 flex-wrap">
<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>
<button id="btnQuickApproaching" type="button" class="btn-quick-filter btn-quick-warning flex-shrink-0" title="Mostra scadenze in scadenza">
<i class="fa-solid fa-triangle-exclamation"></i>
<span>In scadenza</span>
</button>
<button id="btnQuickOverdue" type="button" class="btn-quick-filter btn-quick-danger flex-shrink-0" title="Mostra scadenze scadute">
<i class="fa-solid fa-circle-exclamation"></i>
<span>Scadute</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['name'], ENT_QUOTES, 'UTF-8') ?>">
<?= htmlspecialchars($dept['name'], ENT_QUOTES, 'UTF-8') ?>
<?= !empty($dept['code']) ? ' (' . htmlspecialchars($dept['code'], 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>
<!-- Main Card -->
<div class="card scad-card">
<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"><i class="fa-solid fa-calendar-check me-2"></i>Lista Scadenze</h5>
<div class="header-actions d-flex gap-2 flex-wrap">
<!-- 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/functions/index.php" class="btn btn-scad-outline d-none d-md-inline-flex align-items-center gap-2">
<i class="fa-solid fa-briefcase"></i><span>Funzioni</span>
</a>
<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-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/functions/index.php"><i class="fa-solid fa-briefcase"></i> Funzioni</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">
<?php if (count($deadlines) === 0): ?>
<div class="empty-state">
<i class="fa-solid fa-calendar-xmark"></i>
<p>Nessuna scadenza registrata.<br>Clicca <strong>"Nuova Scadenza"</strong> per aggiungere la prima.</p>
</div>
<?php else: ?>
<?php
// Pre-compute status for each row (used by both views)
$processedDeadlines = [];
foreach ($deadlines as $row) {
$dueDate = $row['due_date'];
$nDays = (int)$row['notification_days'];
$approachDate = date('Y-m-d', strtotime($today . ' + ' . $nDays . ' days'));
$isCompleted = $row['status'] === 'completed';
$isOverdue = !$isCompleted && $dueDate < $today;
$isApproaching = !$isCompleted && !$isOverdue && $dueDate <= $approachDate;
if ($isCompleted) {
$statusLabel = 'Completata';
$statusClass = 'badge-completata';
$statusKey = 'completata';
$rowClass = 'row-completed';
$cardClass = 'card-completed';
} elseif ($isOverdue) {
$statusLabel = 'Scaduta';
$statusClass = 'badge-scaduta';
$statusKey = 'scaduta';
$rowClass = 'row-overdue';
$cardClass = 'card-overdue';
} elseif ($isApproaching) {
$statusLabel = 'In scadenza';
$statusClass = 'badge-in-scadenza';
$statusKey = 'in-scadenza';
$rowClass = 'row-approaching';
$cardClass = 'card-approaching';
} else {
$statusLabel = 'Attiva';
$statusClass = 'badge-attiva';
$statusKey = 'attiva';
$rowClass = '';
$cardClass = '';
}
$row['_dueFmt'] = date('d/m/Y', strtotime($dueDate));
$row['_checkFmt'] = $row['check_date'] ? date('d/m/Y', strtotime($row['check_date'])) : '—';
$row['_statusLabel'] = $statusLabel;
$row['_statusClass'] = $statusClass;
$row['_statusKey'] = $statusKey;
$row['_rowClass'] = $rowClass;
$row['_cardClass'] = $cardClass;
$row['_isCompleted'] = $isCompleted;
// Merge assigned departments + employee departments
$allDepts = [];
if (!empty($row['reparti_assegnati'])) $allDepts = array_map('trim', explode(',', $row['reparti_assegnati']));
if (!empty($row['reparti_persone'])) $allDepts = array_merge($allDepts, array_map('trim', explode(',', $row['reparti_persone'])));
$row['reparti'] = implode(', ', array_unique(array_filter($allDepts)));
$processedDeadlines[] = $row;
}
?>
<!-- MOBILE: Cards (visible < md) -->
<div class="d-md-none" id="mobileCards">
<?php foreach ($processedDeadlines as $row): ?>
<div class="deadline-card <?= $row['_cardClass'] ?>"
data-id="<?= (int)$row['id'] ?>"
data-status="<?= $row['_statusKey'] ?>"
data-subject-id="<?= (int)($row['subject_id'] ?? 0) ?>"
<?php if (!empty($row['subject_color'])): ?>data-subject-color="<?= htmlspecialchars($row['subject_color'], ENT_QUOTES, 'UTF-8') ?>" style="--subject-color: <?= htmlspecialchars($row['subject_color'], ENT_QUOTES, 'UTF-8') ?>" <?php endif; ?>
data-department="<?= htmlspecialchars($row['reparti'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
data-employees="<?= htmlspecialchars($row['responsabili'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
data-due-date="<?= htmlspecialchars($row['due_date'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
data-check-date="<?= htmlspecialchars($row['check_date'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
data-recurrence="<?= htmlspecialchars($row['recurrence_type'] ?? 'once', ENT_QUOTES, 'UTF-8') ?>"
data-att-count="<?= (int)$row['attachment_count'] ?>">
<?php if (!empty($row['subject_name'])): ?>
<div class="mb-1"><?php
$subjectBadgeBg = $row['subject_color'] ?: '#6c757d';
$subjectBadgeText = getContrastTextColor($subjectBadgeBg);
?>
<span class="subject-chip" style="background: <?= htmlspecialchars($subjectBadgeBg, ENT_QUOTES, 'UTF-8') ?>; color: <?= $subjectBadgeText ?>;">
<?= htmlspecialchars($row['subject_name'], ENT_QUOTES, 'UTF-8') ?>
</span>
</div>
<?php endif; ?>
<div class="d-flex justify-content-between align-items-start mb-1">
<a href="scadenzario/detail.php?id=<?= (int)$row['id'] ?>" class="card-topic text-decoration-none"><?= htmlspecialchars($row['topic'], ENT_QUOTES, 'UTF-8') ?></a>
<span class="badge-status <?= $row['_statusClass'] ?> ms-2 flex-shrink-0"><?= $row['_statusLabel'] ?></span>
</div>
<div class="card-meta">
<span><i class="fa-regular fa-calendar"></i> <?= $row['_dueFmt'] ?></span>
<?php if ($row['reparti']): ?>
<span><i class="fa-regular fa-building"></i> <?= htmlspecialchars($row['reparti'], ENT_QUOTES, 'UTF-8') ?></span>
<?php endif; ?>
<?php if ($row['responsabili']): ?>
<span><i class="fa-regular fa-user"></i> <?= htmlspecialchars($row['responsabili'], ENT_QUOTES, 'UTF-8') ?></span>
<?php endif; ?>
<?php if ($row['law_regulation']): ?>
<span><i class="fa-regular fa-file-lines"></i> <?= htmlspecialchars($row['law_regulation'], ENT_QUOTES, 'UTF-8') ?></span>
<?php endif; ?>
<?php if ((int)$row['attachment_count'] > 0): ?>
<span><i class="fa-solid fa-paperclip"></i> <?= (int)$row['attachment_count'] ?></span>
<?php endif; ?>
</div>
<?php if (!$row['_isCompleted']): ?>
<div class="card-actions">
<div class="d-flex gap-1">
<button class="btn-action btn-action-edit btn-edit" title="Modifica"><i class="fa-solid fa-pen"></i></button>
<button class="btn-action btn-action-complete btn-complete" title="Completa"><i class="fa-solid fa-check"></i></button>
<button class="btn-action btn-action-delete btn-delete" title="Elimina"><i class="fa-solid fa-trash"></i></button>
</div>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<!-- DESKTOP: DataTable (visible >= md) -->
<div class="d-none d-md-block">
<div class="table-responsive">
<table id="deadlinesTable" class="table table-hover align-middle mb-0" style="width:100%">
<thead>
<tr>
<th style="width:110px">Argomento</th>
<th>Dettaglio</th>
<th class="d-none d-lg-table-cell">Legge/Art.</th>
<th>Scadenza</th>
<th class="d-none d-lg-table-cell">Verifica</th>
<th>Funzione</th>
<th>Responsabili</th>
<th>Stato</th>
<th class="text-center" style="width:120px">Azioni</th>
</tr>
</thead>
<tbody>
<?php foreach ($processedDeadlines as $row): ?>
<tr class="<?= $row['_rowClass'] ?>"
data-id="<?= (int)$row['id'] ?>"
data-status="<?= $row['_statusKey'] ?>"
data-subject-id="<?= (int)($row['subject_id'] ?? 0) ?>"
<?php if (!empty($row['subject_color'])): ?>
<?php
$subjectColor = htmlspecialchars($row['subject_color'], ENT_QUOTES, 'UTF-8');
$subjectRowBg = $subjectColor . '1A'; // circa 10% opacity
$subjectRowBgHover = $subjectColor . '2A'; // circa 16% opacity
?>
data-subject-color="<?= $subjectColor ?>"
style="--subject-color: <?= $subjectColor ?>; --subject-row-bg: <?= $subjectRowBg ?>; --subject-row-bg-hover: <?= $subjectRowBgHover ?>;"
<?php endif; ?>
data-department="<?= htmlspecialchars($row['reparti'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
data-employees="<?= htmlspecialchars($row['responsabili'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
data-due-date="<?= htmlspecialchars($row['due_date'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
data-check-date="<?= htmlspecialchars($row['check_date'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
data-recurrence="<?= htmlspecialchars($row['recurrence_type'] ?? 'once', ENT_QUOTES, 'UTF-8') ?>"
data-att-count="<?= (int)$row['attachment_count'] ?>">
<td>
<?php if (!empty($row['subject_name'])): ?>
<?php
$subjectBadgeBg = $row['subject_color'] ?: '#6c757d';
$subjectBadgeText = getContrastTextColor($subjectBadgeBg);
?>
<span class="subject-chip" style="background: <?= htmlspecialchars($subjectBadgeBg, ENT_QUOTES, 'UTF-8') ?>; color: <?= $subjectBadgeText ?>;">
<?= htmlspecialchars($row['subject_name'], ENT_QUOTES, 'UTF-8') ?>
</span>
<?php else: ?>
<span class="text-muted">—</span>
<?php endif; ?>
</td>
<td>
<a href="scadenzario/detail.php?id=<?= (int)$row['id'] ?>" class="fw-semibold text-decoration-none" style="color:var(--scad-heading)"><?= htmlspecialchars($row['topic'], ENT_QUOTES, 'UTF-8') ?></a>
<?php if ((int)$row['attachment_count'] > 0): ?>
<span class="text-muted ms-1" title="<?= (int)$row['attachment_count'] ?> allegati"><i class="fa-solid fa-paperclip"></i> <?= (int)$row['attachment_count'] ?></span>
<?php endif; ?>
</td>
<td class="d-none d-lg-table-cell text-muted"><?= htmlspecialchars($row['law_regulation'] ?? '—', ENT_QUOTES, 'UTF-8') ?></td>
<td><span class="text-nowrap"><?= $row['_dueFmt'] ?></span></td>
<td class="d-none d-lg-table-cell text-muted"><?= $row['_checkFmt'] ?></td>
<td>
<?php if (!empty($row['function_name'])): ?>
<span class="text-muted">
<i class="fa-solid fa-briefcase me-1"></i>
<?= htmlspecialchars($row['function_name'], ENT_QUOTES, 'UTF-8') ?>
</span>
<?php else: ?>
<span class="text-muted">—</span>
<?php endif; ?>
</td>
<td>
<?php if ($row['reparti']): ?><span class="text-muted"><i class="fa-regular fa-building me-1"></i><?= htmlspecialchars($row['reparti'], ENT_QUOTES, 'UTF-8') ?></span><?php endif; ?>
<?php if ($row['reparti'] && $row['responsabili']): ?><br><?php endif; ?>
<?php if ($row['responsabili']): ?><span><i class="fa-regular fa-user me-1"></i><?= htmlspecialchars($row['responsabili'], ENT_QUOTES, 'UTF-8') ?></span><?php endif; ?>
<?php if (!$row['reparti'] && !$row['responsabili']): ?>—<?php endif; ?>
</td>
<td><span class="badge-status <?= $row['_statusClass'] ?>"><?= $row['_statusLabel'] ?></span></td>
<td class="text-center">
<?php if (!$row['_isCompleted']): ?>
<div class="d-inline-flex gap-1">
<button class="btn-action btn-action-edit btn-edit" title="Modifica"><i class="fa-solid fa-pen"></i></button>
<button class="btn-action btn-action-complete btn-complete" title="Completa"><i class="fa-solid fa-check"></i></button>
<button class="btn-action btn-action-delete btn-delete" title="Elimina"><i class="fa-solid fa-trash"></i></button>
</div>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php include('../include/footer.php'); ?>
</div>
<?php include __DIR__ . '/include/deadline_modal.php'; ?>
<?php include('../jsinclude.php'); ?>
<script src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.13.7/js/dataTables.bootstrap5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/i18n/it.js"></script>
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/l10n/it.js"></script>
<script>
$(document).ready(function() {
// --- Flatpickr date range ---
function formatDate(d) {
return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
}
var fpOpts = {
mode: 'range',
dateFormat: 'd/m/Y',
locale: 'it',
allowInput: false,
onChange: function() {
if (typeof applyFiltersRefresh === 'function') {
applyFiltersRefresh();
}
}
};
var fpDue = flatpickr('#filterDueRange', fpOpts);
var fpCheck = flatpickr('#filterCheckRange', fpOpts);
// --- DataTables custom filters ---
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
if (settings.nTable.id !== 'deadlinesTable') return true;
var row = settings.aoData[dataIndex].nTr;
var statusFilter = $('#filterStatus').val();
var deptFilter = $('#filterDepartment').val();
if (statusFilter === 'non-completata') {
if (row.getAttribute('data-status') === 'completata') return false;
} else if (statusFilter && row.getAttribute('data-status') !== statusFilter) return false;
if (deptFilter && (row.getAttribute('data-department') || '').indexOf(deptFilter) === -1) return false;
var subjFilter = $('#filterSubject').val();
if (subjFilter && String(row.getAttribute('data-subject-id')) !== String(subjFilter)) return false;
var empFilter = $('#filterEmployee').val();
if (empFilter && (row.getAttribute('data-employees') || '').indexOf(empFilter) === -1) return false;
var dueDates = fpDue.selectedDates;
var dueVal = row.getAttribute('data-due-date') || '';
if (dueDates.length >= 1 && dueVal < formatDate(dueDates[0])) return false;
if (dueDates.length >= 2 && dueVal > formatDate(dueDates[1])) return false;
var chkDates = fpCheck.selectedDates;
var chkVal = row.getAttribute('data-check-date') || '';
if (chkDates.length >= 1 && (!chkVal || chkVal < formatDate(chkDates[0]))) return false;
if (chkDates.length >= 2 && (!chkVal || chkVal > formatDate(chkDates[1]))) return false;
return true;
});
// --- DataTables init ---
var table = null;
if ($('#deadlinesTable').length) {
table = $('#deadlinesTable').DataTable({
order: [
[3, 'asc']
],
pageLength: 25,
language: {
url: 'https://cdn.datatables.net/plug-ins/1.13.7/i18n/it-IT.json'
},
columnDefs: [{
orderable: false,
targets: -1
}]
});
}
// --- Filters ---
function filterCards() {
var statusVal = $('#filterStatus').val();
var deptVal = $('#filterDepartment').val();
var subjVal = $('#filterSubject').val();
$('#mobileCards .deadline-card').each(function() {
var show = true;
if (statusVal === 'non-completata') {
if ($(this).data('status') === 'completata') show = false;
} else if (statusVal && $(this).data('status') !== statusVal) show = false;
if (deptVal && ($(this).data('department') || '').indexOf(deptVal) === -1) show = false;
if (subjVal && String($(this).data('subject-id')) !== String(subjVal)) show = false;
var empVal = $('#filterEmployee').val();
if (empVal && ($(this).data('employees') || '').indexOf(empVal) === -1) show = false;
var dueDates = fpDue.selectedDates;
var dueVal = $(this).data('due-date') || '';
if (dueDates.length >= 1 && dueVal < formatDate(dueDates[0])) show = false;
if (dueDates.length >= 2 && dueVal > formatDate(dueDates[1])) show = false;
var chkDates = fpCheck.selectedDates;
var chkVal = $(this).data('check-date') || '';
if (chkDates.length >= 1 && (!chkVal || chkVal < formatDate(chkDates[0]))) show = false;
if (chkDates.length >= 2 && (!chkVal || chkVal > formatDate(chkDates[1]))) show = false;
$(this).toggle(show);
});
}
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() {
applyFiltersRefresh();
});
function applyFiltersRefresh() {
if (table) table.draw();
filterCards();
updateFilterBadge();
updateQuickFilterButtons();
}
function updateQuickFilterButtons() {
var statusVal = $('#filterStatus').val();
$('#btnQuickApproaching').toggleClass('active', statusVal === 'in-scadenza');
$('#btnQuickOverdue').toggleClass('active', statusVal === 'scaduta');
}
function resetFilters() {
$('#filterStatus').val('non-completata');
$('#filterDepartment').val('');
$('#filterEmployee').val('');
$('#filterSubject').val('');
fpDue.clear();
fpCheck.clear();
applyFiltersRefresh();
}
$('#btnResetFilters, #btnResetFiltersModal').on('click', resetFilters);
$('#btnQuickApproaching').on('click', function() {
$('#filterStatus').val('in-scadenza');
applyFiltersRefresh();
});
$('#btnQuickOverdue').on('click', function() {
$('#filterStatus').val('scaduta');
applyFiltersRefresh();
});
// 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
applyFiltersRefresh();
document.getElementById('btnAddDeadline').addEventListener('click', function() {
if (window.openDeadlineCreate) window.openDeadlineCreate();
});
// Edit with confirmation
$(document).on('click', '.btn-edit', function() {
var id = $(this).closest('[data-id]').data('id');
Swal.fire({
title: 'Vuoi modificare il record?',
text: 'Stai per aprire questo record in modifica.',
icon: 'question',
showCancelButton: true,
confirmButtonColor: '#5a8fd8',
cancelButtonText: 'Annulla',
confirmButtonText: 'Sì, modifica',
reverseButtons: true
}).then(function(result) {
if (result.isConfirmed && window.openDeadlineEdit) {
window.openDeadlineEdit(id);
}
});
});
// Complete
function submitComplete(id, createNext, copyAttachments) {
var fd = new FormData();
fd.append('id', id);
fd.append('create_next', createNext ? '1' : '0');
fd.append('copy_attachments', copyAttachments ? '1' : '0');
fetch('scadenzario/ajax/complete_deadline.php', {
method: 'POST',
body: fd
})
.then(function(r) {
return r.json();
})
.then(function(data) {
if (data.success) {
Swal.fire({
icon: 'success',
title: 'Completata',
text: data.message,
timer: 1800,
showConfirmButton: false
})
.then(function() {
// Open the new deadline's detail page with the edit modal auto-opening
if (data.new_id) {
window.location = 'scadenzario/detail.php?id=' + data.new_id + '#edit';
} else {
location.reload();
}
});
} else {
Swal.fire('Errore', data.message, 'error');
}
})
.catch(function() {
Swal.fire('Errore', 'Errore di connessione.', 'error');
});
}
$(document).on('click', '.btn-complete', function() {
var el = $(this).closest('[data-id]');
var id = el.data('id');
var recurrence = el.data('recurrence') || 'once';
var attCount = parseInt(el.data('att-count'), 10) || 0;
// Non-recurring: simple confirm, no new deadline is created
if (recurrence === 'once') {
Swal.fire({
title: 'Completare la scadenza?',
text: 'La scadenza verrà contrassegnata come completata.',
icon: 'question',
showCancelButton: true,
confirmButtonColor: '#198754',
cancelButtonText: 'Annulla',
confirmButtonText: 'Completa',
reverseButtons: true
}).then(function(result) {
if (result.isConfirmed) {
submitComplete(id, false, false);
}
});
return;
}
// Recurring: ask whether to create the next deadline; optionally carry attachments over
var attCheckbox = attCount > 0 ?
'<div class="form-check d-flex align-items-center justify-content-center gap-2 mt-3">' +
'<input class="form-check-input" type="checkbox" id="swCopyAtt" checked>' +
'<label class="form-check-label" for="swCopyAtt">Copia gli allegati (' + attCount + ') sulla nuova scadenza</label>' +
'</div>' :
'';
Swal.fire({
title: 'Completare la scadenza?',
html: 'Vuoi creare automaticamente la prossima scadenza ricorrente?' + attCheckbox,
icon: 'question',
showCancelButton: true,
showDenyButton: true,
confirmButtonColor: '#198754',
denyButtonColor: '#6c757d',
confirmButtonText: 'Completa e crea la prossima',
denyButtonText: 'Completa senza nuova',
cancelButtonText: 'Annulla',
reverseButtons: true
}).then(function(result) {
if (result.isConfirmed) {
var copy = attCount > 0 ? document.getElementById('swCopyAtt').checked : false;
submitComplete(id, true, copy);
} else if (result.isDenied) {
submitComplete(id, false, false);
}
});
});
// Delete
$(document).on('click', '.btn-delete', function() {
var el = $(this).closest('[data-id]');
var id = el.data('id');
Swal.fire({
title: 'Eliminare la scadenza?',
text: 'Questa azione non può essere annullata.',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#dc3545',
cancelButtonText: 'Annulla',
confirmButtonText: 'Elimina'
}).then(function(result) {
if (result.isConfirmed) {
fetch('scadenzario/ajax/delete_deadline.php?id=' + id)
.then(function(r) {
return r.json();
})
.then(function(data) {
if (data.success) {
Swal.fire({
icon: 'success',
title: 'Eliminata',
text: data.message,
timer: 1500,
showConfirmButton: false
})
.then(function() {
location.reload();
});
} else {
Swal.fire('Errore', data.message, 'error');
}
})
.catch(function() {
Swal.fire('Errore', 'Errore di connessione.', 'error');
});
}
});
});
// Stampa
function doStampa() {
var params = [];
var s = $('#filterStatus').val();
var d = $('#filterDepartment').val();
var emp = $('#filterEmployee').val();
if (s) params.push('status=' + encodeURIComponent(s));
if (d) params.push('department=' + encodeURIComponent(d));
if (emp) params.push('employee=' + encodeURIComponent(emp));
var dueDates = fpDue.selectedDates;
if (dueDates.length >= 1) params.push('due_from=' + formatDate(dueDates[0]));
if (dueDates.length >= 2) params.push('due_to=' + formatDate(dueDates[1]));
var chkDates = fpCheck.selectedDates;
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>
<?php include __DIR__ . '/include/deadline_modal_js.php'; ?>
</body>
</html>