diff --git a/public/userarea/production_dashboard.php b/public/userarea/production_dashboard.php index 0bd0c60..9d764b9 100644 --- a/public/userarea/production_dashboard.php +++ b/public/userarea/production_dashboard.php @@ -296,6 +296,11 @@
+ getConnection(); + include(__DIR__ . '/scadenzario/include/my_deadlines_widget.php'); + ?> +

Dashboard Produzione

diff --git a/public/userarea/scadenzario/calendar.php b/public/userarea/scadenzario/calendar.php index 7a518f2..cb1a644 100644 --- a/public/userarea/scadenzario/calendar.php +++ b/public/userarea/scadenzario/calendar.php @@ -98,58 +98,81 @@ $departments = $pdo->query("SELECT DISTINCT department FROM employees WHERE depa
- + -
- - Lista Scadenze - +
+ + +
+
-
-
-
- -
-
- -
-
- -
-
- + +
-
-
Calendario Scadenze
+
+
Calendario Scadenze
+
@@ -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(); }); diff --git a/public/userarea/scadenzario/include/my_deadlines_widget.php b/public/userarea/scadenzario/include/my_deadlines_widget.php new file mode 100644 index 0000000..7b217a8 --- /dev/null +++ b/public/userarea/scadenzario/include/my_deadlines_widget.php @@ -0,0 +1,91 @@ + 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; +} +?> + + diff --git a/public/userarea/scadenzario/index.php b/public/userarea/scadenzario/index.php index 87da7f7..f4a0775 100644 --- a/public/userarea/scadenzario/index.php +++ b/public/userarea/scadenzario/index.php @@ -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%; } } @@ -292,6 +332,8 @@ $today = date('Y-m-d');
+ +
@@ -306,60 +348,105 @@ $today = date('Y-m-d');
- -
-
-
- -
-
- -
-
- -
-
- -
+ +
+
+ + Le mie scadenze + (assegnate a me o al reparto )
-
-
- -
-
- -
-
- + + Tutte le scadenze + +
+ + + +
+
+ + + +
+
+
+ + + @@ -367,20 +454,34 @@ $today = date('Y-m-d');
-
Lista Scadenze
+
Lista Scadenze
- + + Argomenti - + Calendario - + + + +
@@ -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); });