fix auto-open
This commit is contained in:
@@ -85,6 +85,14 @@ if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
|
|||||||
<base href="<?= $baseHref ?>">
|
<base href="<?= $baseHref ?>">
|
||||||
<?php include('../cssinclude.php'); ?>
|
<?php include('../cssinclude.php'); ?>
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
<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.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css" rel="stylesheet">
|
||||||
|
<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>
|
||||||
|
<?php include __DIR__ . '/include/deadline_modal_css.php'; ?>
|
||||||
<title><?= $deadline ? htmlspecialchars($deadline['topic'], ENT_QUOTES, 'UTF-8') . ' — ' : '' ?>Scadenzario</title>
|
<title><?= $deadline ? htmlspecialchars($deadline['topic'], ENT_QUOTES, 'UTF-8') . ' — ' : '' ?>Scadenzario</title>
|
||||||
<script>
|
<script>
|
||||||
if (window.innerWidth > 1024) document.addEventListener('DOMContentLoaded', function() {
|
if (window.innerWidth > 1024) document.addEventListener('DOMContentLoaded', function() {
|
||||||
@@ -755,12 +763,21 @@ if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
|
|||||||
</div>
|
</div>
|
||||||
<?php include('../include/footer.php'); ?>
|
<?php include('../include/footer.php'); ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php if ($deadline && !$isCompleted): ?>
|
||||||
|
<?php require __DIR__ . '/include/deadline_form_data.php'; ?>
|
||||||
|
<?php include __DIR__ . '/include/deadline_modal.php'; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php include('../jsinclude.php'); ?>
|
<?php include('../jsinclude.php'); ?>
|
||||||
<?php if ($deadline && !$isCompleted): ?>
|
<?php if ($deadline && !$isCompleted): ?>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
// Used by the shared modal JS to auto-open edit on "#edit"
|
||||||
|
window.SCAD_DETAIL_ID = <?= (int)$deadline['id'] ?>;
|
||||||
|
|
||||||
$('#btnModifica').on('click', function() {
|
$('#btnModifica').on('click', function() {
|
||||||
window.location.href = 'scadenzario/index.php?edit=<?= (int)$deadline['id'] ?>';
|
window.openDeadlineEdit(<?= (int)$deadline['id'] ?>);
|
||||||
});
|
});
|
||||||
|
|
||||||
function detailSubmitComplete(createNext, copyAttachments) {
|
function detailSubmitComplete(createNext, copyAttachments) {
|
||||||
@@ -787,7 +804,7 @@ if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
|
|||||||
})
|
})
|
||||||
.then(function() {
|
.then(function() {
|
||||||
if (data.new_id) {
|
if (data.new_id) {
|
||||||
window.location.href = 'scadenzario/index.php?edit=' + data.new_id;
|
window.location.href = 'scadenzario/detail.php?id=' + data.new_id + '#edit';
|
||||||
} else {
|
} else {
|
||||||
window.location.href = 'scadenzario/index.php';
|
window.location.href = 'scadenzario/index.php';
|
||||||
}
|
}
|
||||||
@@ -853,6 +870,7 @@ if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<?php include __DIR__ . '/include/deadline_modal_js.php'; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared data for the deadline modal form (used by index.php and detail.php).
|
||||||
|
* Populates $employees, $departments, $subjects. Safe to include more than once.
|
||||||
|
*/
|
||||||
|
if (!isset($pdo) || !$pdo) {
|
||||||
|
$pdo = DBHandlerSelect::getInstance()->getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($employees)) {
|
||||||
|
$employees = $pdo->query("
|
||||||
|
SELECT e.id, e.first_name, e.last_name, e.department_id, dep.name AS department_name
|
||||||
|
FROM employees e
|
||||||
|
LEFT JOIN departments dep ON dep.id = e.department_id
|
||||||
|
WHERE e.status = 'active'
|
||||||
|
ORDER BY e.first_name, e.last_name
|
||||||
|
")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($departments)) {
|
||||||
|
$departments = $pdo->query("
|
||||||
|
SELECT id, name, code, color
|
||||||
|
FROM departments
|
||||||
|
WHERE is_active = 1
|
||||||
|
ORDER BY sort_order ASC, name ASC
|
||||||
|
")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($subjects)) {
|
||||||
|
$subjects = $pdo->query("SELECT id, name, color FROM scad_subjects ORDER BY name")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared "Nuova/Modifica Scadenza" modal markup (used by index.php and detail.php).
|
||||||
|
* Requires $subjects, $departments, $employees in scope (see deadline_form_data.php).
|
||||||
|
* The accompanying JS lives in deadline_modal_js.php.
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<!-- Deadline Modal -->
|
||||||
|
<div class="modal fade" id="deadlineModal" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-xl modal-fullscreen-sm-down">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="modalTitle">Nuova Scadenza</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Chiudi"></button>
|
||||||
|
</div>
|
||||||
|
<form id="deadlineForm">
|
||||||
|
<div class="modal-body">
|
||||||
|
<input type="hidden" id="dlId" name="id" value="">
|
||||||
|
|
||||||
|
<!-- Group 1: Informazioni principali -->
|
||||||
|
<div class="form-section-title">Informazioni principali</div>
|
||||||
|
<div class="row g-3 mb-4">
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<label for="dlSubject" class="form-label fw-semibold">Argomento</label>
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<select class="form-select" id="dlSubject" name="subject_id" style="flex:1">
|
||||||
|
<option value="">— Nessuno —</option>
|
||||||
|
<?php foreach ($subjects as $s): ?>
|
||||||
|
<option value="<?= (int)$s['id'] ?>" data-color="<?= htmlspecialchars($s['color'], ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($s['name'], ENT_QUOTES, 'UTF-8') ?></option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
<a href="scadenzario/subjects/index.php" target="_blank" class="btn btn-scad-outline" title="Gestisci argomenti">
|
||||||
|
<i class="fa-solid fa-gear"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<label for="dlLaw" class="form-label fw-semibold">Legge / Articolo</label>
|
||||||
|
<input type="text" class="form-control" id="dlLaw" name="law_regulation" maxlength="500" placeholder="es. D.Lgs. 81/2008, D.M. 10.03.1998...">
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<label for="dlTopic" class="form-label fw-semibold">Dettaglio <span class="text-danger">*</span></label>
|
||||||
|
<textarea class="form-control" id="dlTopic" name="topic" required maxlength="500" rows="2" placeholder="es. Verifica estintori, Autorizzazione trasporto rifiuti..."></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Group 2: Date e frequenza -->
|
||||||
|
<div class="form-section-title">Date e frequenza</div>
|
||||||
|
<div class="row g-3 mb-4">
|
||||||
|
<div class="col-12 col-md-4">
|
||||||
|
<label for="dlRecurrence" class="form-label fw-semibold">Periodicità</label>
|
||||||
|
<select class="form-select" id="dlRecurrence" name="recurrence_type">
|
||||||
|
<option value="once">Una tantum</option>
|
||||||
|
<option value="monthly">Mensile</option>
|
||||||
|
<option value="quarterly">Trimestrale</option>
|
||||||
|
<option value="semiannual">Semestrale</option>
|
||||||
|
<option value="annual">Annuale</option>
|
||||||
|
<option value="biennial">Biennale</option>
|
||||||
|
<option value="triennial">Triennale</option>
|
||||||
|
<option value="quadriennial">Quadriennale</option>
|
||||||
|
<option value="quinquennial">Quinquennale</option>
|
||||||
|
<option value="decennial">Decennale</option>
|
||||||
|
<option value="quindecennial">Quindicennale</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-4">
|
||||||
|
<label for="dlDocDate" class="form-label fw-semibold">Data documento</label>
|
||||||
|
<input type="text" class="form-control js-date-it" id="dlDocDate" name="document_date" placeholder="gg/mm/aaaa" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-4">
|
||||||
|
<label for="dlDueDate" class="form-label fw-semibold">Data scadenza <span class="text-danger">*</span></label>
|
||||||
|
<input type="text" class="form-control js-date-it" id="dlDueDate" name="due_date" placeholder="gg/mm/aaaa" autocomplete="off" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-4">
|
||||||
|
<label for="dlCheckDate" class="form-label fw-semibold">Data ultimo controllo</label>
|
||||||
|
<input type="text" class="form-control js-date-it" id="dlCheckDate" name="check_date" placeholder="gg/mm/aaaa" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Group 3: Responsabili -->
|
||||||
|
<div class="form-section-title">Responsabili</div>
|
||||||
|
<div class="row g-3 mb-4">
|
||||||
|
<div class="col-12">
|
||||||
|
<label for="dlDepartments" class="form-label fw-semibold">Reparti</label>
|
||||||
|
<select class="form-select" id="dlDepartments" name="department_names[]" multiple>
|
||||||
|
<?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 class="form-text">Tutto il reparto sarà responsabile</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<label for="dlEmployees" class="form-label fw-semibold">Singoli responsabili</label>
|
||||||
|
<select class="form-select" id="dlEmployees" name="employee_ids[]" multiple>
|
||||||
|
<?php foreach ($employees as $emp): ?>
|
||||||
|
<option value="<?= (int)$emp['id'] ?>">
|
||||||
|
<?= htmlspecialchars($emp['first_name'] . ' ' . $emp['last_name'], ENT_QUOTES, 'UTF-8') ?><?php if (!empty($emp['department_name'])): ?> (<?= htmlspecialchars($emp['department_name'], ENT_QUOTES, 'UTF-8') ?>)<?php endif; ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Group 4: Dettagli aggiuntivi -->
|
||||||
|
<div class="form-section-title">Dettagli aggiuntivi</div>
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-12 col-md-4">
|
||||||
|
<label for="dlNotifDays" class="form-label fw-semibold">Giorni preavviso</label>
|
||||||
|
<input type="number" class="form-control" id="dlNotifDays" name="notification_days" value="7" min="1" max="365">
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-8">
|
||||||
|
<label for="dlStorage" class="form-label fw-semibold">Luogo archiviazione</label>
|
||||||
|
<input type="text" class="form-control" id="dlStorage" name="storage_location" maxlength="500" placeholder="es. Armadio A3, Server/Documenti/Sicurezza...">
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<label for="dlNotes" class="form-label fw-semibold">Note</label>
|
||||||
|
<textarea class="form-control" id="dlNotes" name="notes" rows="3" placeholder="es. Scadenza 09/06/2026, Attività in appalto a Ditta specializzata..."></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Group 5: Allegati -->
|
||||||
|
<div class="form-section-title mt-4">Allegati</div>
|
||||||
|
<div id="attachmentsList" class="mb-3"></div>
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-12">
|
||||||
|
<label for="dlFiles" class="form-label fw-semibold">Carica file</label>
|
||||||
|
<input type="file" class="form-control" id="dlFiles" multiple>
|
||||||
|
<div class="form-text">Puoi selezionare più file contemporaneamente</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Annulla</button>
|
||||||
|
<button type="submit" class="btn btn-scad-primary">
|
||||||
|
<i class="fa-solid fa-check me-1"></i> Salva
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared styles for the deadline modal (deadline_modal.php).
|
||||||
|
* Relies on the --scad-* CSS variables defined on each page's :root.
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<style>
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#deadlineModal.modal {
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
#deadlineModal .modal-content,
|
||||||
|
#deadlineModal .modal-body,
|
||||||
|
#deadlineModal .modal-footer {
|
||||||
|
background: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#deadlineModal .modal-header {
|
||||||
|
background: var(--scad-card-bg);
|
||||||
|
border-bottom: 1px solid var(--scad-card-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
#deadlineModal .modal-title {
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--scad-heading);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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, #dc3545);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.att-item .att-remove:hover {
|
||||||
|
background: var(--scad-red, #dc3545);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,277 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Self-contained JS for the deadline modal (deadline_modal.php).
|
||||||
|
* Requires jQuery, Bootstrap, flatpickr, select2 and SweetAlert2 to be loaded first.
|
||||||
|
*
|
||||||
|
* Exposes:
|
||||||
|
* window.openDeadlineCreate() — open the modal empty (new deadline)
|
||||||
|
* window.openDeadlineEdit(id) — fetch a deadline and open the modal in edit mode
|
||||||
|
*
|
||||||
|
* Auto-open on load:
|
||||||
|
* #edit=<id> → opens edit for that id
|
||||||
|
* #edit → opens edit for window.SCAD_DETAIL_ID (used by detail.php)
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
// --- Flatpickr date fields (visible dd/mm/yyyy, submitted yyyy-mm-dd) ---
|
||||||
|
var fpOptsDate = {
|
||||||
|
dateFormat: 'Y-m-d',
|
||||||
|
altInput: true,
|
||||||
|
altFormat: 'd/m/Y',
|
||||||
|
locale: 'it',
|
||||||
|
allowInput: true
|
||||||
|
};
|
||||||
|
var fpDocDate = flatpickr('#dlDocDate', fpOptsDate);
|
||||||
|
var fpDueDate = flatpickr('#dlDueDate', fpOptsDate);
|
||||||
|
var fpCheckDate = flatpickr('#dlCheckDate', fpOptsDate);
|
||||||
|
|
||||||
|
// --- Select2 ---
|
||||||
|
var s2Opts = {
|
||||||
|
theme: 'bootstrap-5',
|
||||||
|
allowClear: true,
|
||||||
|
dropdownParent: $('#deadlineModal .modal-body'),
|
||||||
|
language: 'it',
|
||||||
|
width: '100%'
|
||||||
|
};
|
||||||
|
$('#dlSubject').select2($.extend({}, s2Opts, { placeholder: 'Seleziona argomento...' }));
|
||||||
|
$('#dlDepartments').select2($.extend({}, s2Opts, { placeholder: 'Seleziona reparti...' }));
|
||||||
|
$('#dlEmployees').select2($.extend({}, s2Opts, { placeholder: 'Seleziona persone...' }));
|
||||||
|
|
||||||
|
// --- Auto-calc due_date from document_date + recurrence ---
|
||||||
|
var RECURRENCE_OFFSETS = {
|
||||||
|
monthly: { months: 1 },
|
||||||
|
quarterly: { months: 3 },
|
||||||
|
semiannual: { months: 6 },
|
||||||
|
annual: { years: 1 },
|
||||||
|
biennial: { years: 2 },
|
||||||
|
triennial: { years: 3 },
|
||||||
|
quadriennial: { years: 4 },
|
||||||
|
quinquennial: { years: 5 },
|
||||||
|
decennial: { years: 10 },
|
||||||
|
quindecennial: { years: 15 }
|
||||||
|
};
|
||||||
|
|
||||||
|
function computeDueDate() {
|
||||||
|
var docVal = document.getElementById('dlDocDate').value;
|
||||||
|
var recurrence = document.getElementById('dlRecurrence').value;
|
||||||
|
var offset = RECURRENCE_OFFSETS[recurrence];
|
||||||
|
if (!docVal || !offset) return;
|
||||||
|
var d = new Date(docVal + 'T00:00:00');
|
||||||
|
if (isNaN(d.getTime())) return;
|
||||||
|
if (offset.months) d.setMonth(d.getMonth() + offset.months);
|
||||||
|
if (offset.years) d.setFullYear(d.getFullYear() + offset.years);
|
||||||
|
var iso = d.getFullYear() + '-' +
|
||||||
|
String(d.getMonth() + 1).padStart(2, '0') + '-' +
|
||||||
|
String(d.getDate()).padStart(2, '0');
|
||||||
|
fpDueDate.setDate(iso, true, 'Y-m-d');
|
||||||
|
}
|
||||||
|
$('#dlDocDate, #dlRecurrence').on('change', computeDueDate);
|
||||||
|
|
||||||
|
// --- Modal instance ---
|
||||||
|
var modal = new bootstrap.Modal(document.getElementById('deadlineModal'));
|
||||||
|
var form = document.getElementById('deadlineForm');
|
||||||
|
|
||||||
|
// --- Render attachments list ---
|
||||||
|
function renderAttachments(attachments) {
|
||||||
|
var container = document.getElementById('attachmentsList');
|
||||||
|
if (!attachments || attachments.length === 0) {
|
||||||
|
container.innerHTML = '<div class="text-muted" style="font-size:0.85rem">Nessun allegato</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
container.innerHTML = attachments.map(function(a) {
|
||||||
|
return '<div class="att-item" data-att-id="' + a.id + '">' +
|
||||||
|
'<span class="att-name"><i class="fa-solid fa-paperclip me-1"></i>' + $('<span>').text(a.original_name).html() + '</span>' +
|
||||||
|
'<span class="att-actions">' +
|
||||||
|
'<a href="scadenzario/ajax/download_attachment.php?id=' + a.id + '" class="att-download" title="Scarica"><i class="fa-solid fa-download"></i></a>' +
|
||||||
|
'<button type="button" class="att-remove" title="Elimina" data-att-id="' + a.id + '"><i class="fa-solid fa-xmark"></i></button>' +
|
||||||
|
'</span></div>';
|
||||||
|
}).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Open modal (create) ---
|
||||||
|
window.openDeadlineCreate = function() {
|
||||||
|
form.reset();
|
||||||
|
document.getElementById('dlId').value = '';
|
||||||
|
document.getElementById('dlNotifDays').value = '7';
|
||||||
|
document.getElementById('modalTitle').textContent = 'Nuova Scadenza';
|
||||||
|
document.getElementById('dlFiles').value = '';
|
||||||
|
fpDocDate.clear();
|
||||||
|
fpDueDate.clear();
|
||||||
|
fpCheckDate.clear();
|
||||||
|
$('#dlSubject').val('').trigger('change');
|
||||||
|
$('#dlDepartments').val(null).trigger('change');
|
||||||
|
$('#dlEmployees').val(null).trigger('change');
|
||||||
|
renderAttachments([]);
|
||||||
|
modal.show();
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Open modal (edit) ---
|
||||||
|
window.openDeadlineEdit = function(id) {
|
||||||
|
fetch('scadenzario/ajax/get_deadline.php?id=' + id)
|
||||||
|
.then(function(r) {
|
||||||
|
return r.json();
|
||||||
|
})
|
||||||
|
.then(function(data) {
|
||||||
|
if (!data.success) {
|
||||||
|
Swal.fire('Errore', data.message, 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var d = data.data;
|
||||||
|
document.getElementById('dlId').value = d.id;
|
||||||
|
$('#dlSubject').val(d.subject_id || '').trigger('change');
|
||||||
|
document.getElementById('dlTopic').value = d.topic || '';
|
||||||
|
document.getElementById('dlLaw').value = d.law_regulation || '';
|
||||||
|
document.getElementById('dlRecurrence').value = d.recurrence_type || 'once';
|
||||||
|
fpDocDate.setDate(d.document_date || null, false, 'Y-m-d');
|
||||||
|
fpDueDate.setDate(d.due_date || null, false, 'Y-m-d');
|
||||||
|
fpCheckDate.setDate(d.check_date || null, false, 'Y-m-d');
|
||||||
|
document.getElementById('dlNotifDays').value = d.notification_days || 7;
|
||||||
|
document.getElementById('dlStorage').value = d.storage_location || '';
|
||||||
|
document.getElementById('dlNotes').value = d.notes || '';
|
||||||
|
document.getElementById('dlFiles').value = '';
|
||||||
|
document.getElementById('modalTitle').textContent = 'Modifica Scadenza';
|
||||||
|
$('#dlDepartments').val(d.department_names || []).trigger('change');
|
||||||
|
if (Array.isArray(d.employee_ids)) {
|
||||||
|
$('#dlEmployees').val(d.employee_ids.map(String)).trigger('change');
|
||||||
|
} else {
|
||||||
|
$('#dlEmployees').val(null).trigger('change');
|
||||||
|
}
|
||||||
|
renderAttachments(d.attachments || []);
|
||||||
|
modal.show();
|
||||||
|
})
|
||||||
|
.catch(function() {
|
||||||
|
Swal.fire('Errore', 'Errore di connessione.', 'error');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Save ---
|
||||||
|
var isSaving = false;
|
||||||
|
form.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (isSaving) return;
|
||||||
|
isSaving = true;
|
||||||
|
var saveBtn = form.querySelector('[type="submit"]');
|
||||||
|
saveBtn.disabled = true;
|
||||||
|
saveBtn.innerHTML = '<i class="fa-solid fa-spinner fa-spin me-1"></i> Salvataggio...';
|
||||||
|
var formData = new FormData(form);
|
||||||
|
|
||||||
|
fetch('scadenzario/ajax/save_deadline.php', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(function(r) {
|
||||||
|
return r.json();
|
||||||
|
})
|
||||||
|
.then(function(data) {
|
||||||
|
if (data.success) {
|
||||||
|
var deadlineId = data.id;
|
||||||
|
var fileInput = document.getElementById('dlFiles');
|
||||||
|
if (fileInput.files.length > 0) {
|
||||||
|
var fileData = new FormData();
|
||||||
|
fileData.append('deadline_id', deadlineId);
|
||||||
|
for (var i = 0; i < fileInput.files.length; i++) {
|
||||||
|
fileData.append('files[]', fileInput.files[i]);
|
||||||
|
}
|
||||||
|
return fetch('scadenzario/ajax/upload_attachment.php', {
|
||||||
|
method: 'POST',
|
||||||
|
body: fileData
|
||||||
|
})
|
||||||
|
.then(function(r) {
|
||||||
|
return r.json();
|
||||||
|
})
|
||||||
|
.then(function(upData) {
|
||||||
|
modal.hide();
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Salvato',
|
||||||
|
text: data.message + ' ' + upData.message,
|
||||||
|
timer: 2000,
|
||||||
|
showConfirmButton: false
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
location.reload();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
modal.hide();
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Salvato',
|
||||||
|
text: data.message,
|
||||||
|
timer: 1500,
|
||||||
|
showConfirmButton: false
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
location.reload();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Swal.fire('Errore', data.message, 'error');
|
||||||
|
isSaving = false;
|
||||||
|
saveBtn.disabled = false;
|
||||||
|
saveBtn.innerHTML = '<i class="fa-solid fa-check me-1"></i> Salva';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function() {
|
||||||
|
Swal.fire('Errore', 'Errore di connessione.', 'error');
|
||||||
|
isSaving = false;
|
||||||
|
saveBtn.disabled = false;
|
||||||
|
saveBtn.innerHTML = '<i class="fa-solid fa-check me-1"></i> Salva';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- Delete attachment ---
|
||||||
|
$(document).on('click', '.att-remove', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var btn = $(this);
|
||||||
|
var attId = btn.data('att-id');
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Rimuovere l\'allegato?',
|
||||||
|
text: 'Il collegamento verrà rimosso da questa scadenza. Il file resta disponibile se è usato da altre scadenze.',
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: '#dc3545',
|
||||||
|
cancelButtonText: 'Annulla',
|
||||||
|
confirmButtonText: 'Rimuovi',
|
||||||
|
reverseButtons: true
|
||||||
|
}).then(function(result) {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
fetch('scadenzario/ajax/delete_attachment.php?id=' + attId)
|
||||||
|
.then(function(r) {
|
||||||
|
return r.json();
|
||||||
|
})
|
||||||
|
.then(function(data) {
|
||||||
|
if (data.success) {
|
||||||
|
btn.closest('.att-item').remove();
|
||||||
|
if ($('#attachmentsList .att-item').length === 0) {
|
||||||
|
renderAttachments([]);
|
||||||
|
}
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Fatto',
|
||||||
|
text: data.message,
|
||||||
|
timer: 1800,
|
||||||
|
showConfirmButton: false
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Swal.fire('Errore', data.message, 'error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- Auto-open from hash (#edit=ID or #edit for the current detail page) ---
|
||||||
|
var hash = window.location.hash;
|
||||||
|
var hashMatch = hash.match(/^#edit=(\d+)$/);
|
||||||
|
var autoEditId = hashMatch ? hashMatch[1] :
|
||||||
|
(hash === '#edit' && window.SCAD_DETAIL_ID ? window.SCAD_DETAIL_ID : null);
|
||||||
|
if (autoEditId) {
|
||||||
|
history.replaceState(null, '', window.location.pathname + window.location.search);
|
||||||
|
window.openDeadlineEdit(autoEditId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -69,27 +69,7 @@ $stmt = $pdo->prepare($sql);
|
|||||||
$stmt->execute($params);
|
$stmt->execute($params);
|
||||||
$deadlines = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
$deadlines = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
$employees = $pdo->query("
|
require __DIR__ . '/include/deadline_form_data.php';
|
||||||
SELECT
|
|
||||||
e.id,
|
|
||||||
e.first_name,
|
|
||||||
e.last_name,
|
|
||||||
e.department_id,
|
|
||||||
dep.name AS department_name
|
|
||||||
FROM employees e
|
|
||||||
LEFT JOIN departments dep ON dep.id = e.department_id
|
|
||||||
WHERE e.status = 'active'
|
|
||||||
ORDER BY e.first_name, e.last_name
|
|
||||||
")->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
$departments = $pdo->query("
|
|
||||||
SELECT id, name, code, color
|
|
||||||
FROM departments
|
|
||||||
WHERE is_active = 1
|
|
||||||
ORDER BY sort_order ASC, name ASC
|
|
||||||
")->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
$subjects = $pdo->query("SELECT id, name, color FROM scad_subjects ORDER BY name")->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
$today = date('Y-m-d');
|
$today = date('Y-m-d');
|
||||||
|
|
||||||
@@ -1059,143 +1039,7 @@ function getContrastTextColor($hexColor)
|
|||||||
<?php include('../include/footer.php'); ?>
|
<?php include('../include/footer.php'); ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Deadline Modal -->
|
<?php include __DIR__ . '/include/deadline_modal.php'; ?>
|
||||||
<div class="modal fade" id="deadlineModal" tabindex="-1" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-xl modal-fullscreen-sm-down">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="modalTitle">Nuova Scadenza</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Chiudi"></button>
|
|
||||||
</div>
|
|
||||||
<form id="deadlineForm">
|
|
||||||
<div class="modal-body">
|
|
||||||
<input type="hidden" id="dlId" name="id" value="">
|
|
||||||
|
|
||||||
<!-- Group 1: Informazioni principali -->
|
|
||||||
<div class="form-section-title">Informazioni principali</div>
|
|
||||||
<div class="row g-3 mb-4">
|
|
||||||
<div class="col-12 col-md-6">
|
|
||||||
<label for="dlSubject" class="form-label fw-semibold">Argomento</label>
|
|
||||||
<div class="d-flex gap-2">
|
|
||||||
<select class="form-select" id="dlSubject" name="subject_id" style="flex:1">
|
|
||||||
<option value="">— Nessuno —</option>
|
|
||||||
<?php foreach ($subjects as $s): ?>
|
|
||||||
<option value="<?= (int)$s['id'] ?>" data-color="<?= htmlspecialchars($s['color'], ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($s['name'], ENT_QUOTES, 'UTF-8') ?></option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
<a href="scadenzario/subjects/index.php" target="_blank" class="btn btn-scad-outline" title="Gestisci argomenti">
|
|
||||||
<i class="fa-solid fa-gear"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-md-6">
|
|
||||||
<label for="dlLaw" class="form-label fw-semibold">Legge / Articolo</label>
|
|
||||||
<input type="text" class="form-control" id="dlLaw" name="law_regulation" maxlength="500" placeholder="es. D.Lgs. 81/2008, D.M. 10.03.1998...">
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<label for="dlTopic" class="form-label fw-semibold">Dettaglio <span class="text-danger">*</span></label>
|
|
||||||
<textarea class="form-control" id="dlTopic" name="topic" required maxlength="500" rows="2" placeholder="es. Verifica estintori, Autorizzazione trasporto rifiuti..."></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Group 2: Date e frequenza -->
|
|
||||||
<div class="form-section-title">Date e frequenza</div>
|
|
||||||
<div class="row g-3 mb-4">
|
|
||||||
<div class="col-12 col-md-4">
|
|
||||||
<label for="dlRecurrence" class="form-label fw-semibold">Periodicità</label>
|
|
||||||
<select class="form-select" id="dlRecurrence" name="recurrence_type">
|
|
||||||
<option value="once">Una tantum</option>
|
|
||||||
<option value="monthly">Mensile</option>
|
|
||||||
<option value="quarterly">Trimestrale</option>
|
|
||||||
<option value="semiannual">Semestrale</option>
|
|
||||||
<option value="annual">Annuale</option>
|
|
||||||
<option value="biennial">Biennale</option>
|
|
||||||
<option value="triennial">Triennale</option>
|
|
||||||
<option value="quadriennial">Quadriennale</option>
|
|
||||||
<option value="quinquennial">Quinquennale</option>
|
|
||||||
<option value="decennial">Decennale</option>
|
|
||||||
<option value="quindecennial">Quindicennale</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-md-4">
|
|
||||||
<label for="dlDocDate" class="form-label fw-semibold">Data documento</label>
|
|
||||||
<input type="text" class="form-control js-date-it" id="dlDocDate" name="document_date" placeholder="gg/mm/aaaa" autocomplete="off">
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-md-4">
|
|
||||||
<label for="dlDueDate" class="form-label fw-semibold">Data scadenza <span class="text-danger">*</span></label>
|
|
||||||
<input type="text" class="form-control js-date-it" id="dlDueDate" name="due_date" placeholder="gg/mm/aaaa" autocomplete="off" required>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-md-4">
|
|
||||||
<label for="dlCheckDate" class="form-label fw-semibold">Data ultimo controllo</label>
|
|
||||||
<input type="text" class="form-control js-date-it" id="dlCheckDate" name="check_date" placeholder="gg/mm/aaaa" autocomplete="off">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Group 3: Responsabili -->
|
|
||||||
<div class="form-section-title">Responsabili</div>
|
|
||||||
<div class="row g-3 mb-4">
|
|
||||||
<div class="col-12">
|
|
||||||
<label for="dlDepartments" class="form-label fw-semibold">Reparti</label>
|
|
||||||
<select class="form-select" id="dlDepartments" name="department_names[]" multiple>
|
|
||||||
<?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 class="form-text">Tutto il reparto sarà responsabile</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<label for="dlEmployees" class="form-label fw-semibold">Singoli responsabili</label>
|
|
||||||
<select class="form-select" id="dlEmployees" name="employee_ids[]" multiple>
|
|
||||||
<?php foreach ($employees as $emp): ?>
|
|
||||||
<option value="<?= (int)$emp['id'] ?>">
|
|
||||||
<?= htmlspecialchars($emp['first_name'] . ' ' . $emp['last_name'], ENT_QUOTES, 'UTF-8') ?><?php if (!empty($emp['department_name'])): ?> (<?= htmlspecialchars($emp['department_name'], ENT_QUOTES, 'UTF-8') ?>)<?php endif; ?>
|
|
||||||
</option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Group 4: Dettagli aggiuntivi -->
|
|
||||||
<div class="form-section-title">Dettagli aggiuntivi</div>
|
|
||||||
<div class="row g-3">
|
|
||||||
<div class="col-12 col-md-4">
|
|
||||||
<label for="dlNotifDays" class="form-label fw-semibold">Giorni preavviso</label>
|
|
||||||
<input type="number" class="form-control" id="dlNotifDays" name="notification_days" value="7" min="1" max="365">
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-md-8">
|
|
||||||
<label for="dlStorage" class="form-label fw-semibold">Luogo archiviazione</label>
|
|
||||||
<input type="text" class="form-control" id="dlStorage" name="storage_location" maxlength="500" placeholder="es. Armadio A3, Server/Documenti/Sicurezza...">
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<label for="dlNotes" class="form-label fw-semibold">Note</label>
|
|
||||||
<textarea class="form-control" id="dlNotes" name="notes" rows="3" placeholder="es. Scadenza 09/06/2026, Attività in appalto a Ditta specializzata..."></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Group 5: Allegati -->
|
|
||||||
<div class="form-section-title mt-4">Allegati</div>
|
|
||||||
<div id="attachmentsList" class="mb-3"></div>
|
|
||||||
<div class="row g-3">
|
|
||||||
<div class="col-12">
|
|
||||||
<label for="dlFiles" class="form-label fw-semibold">Carica file</label>
|
|
||||||
<input type="file" class="form-control" id="dlFiles" multiple>
|
|
||||||
<div class="form-text">Puoi selezionare più file contemporaneamente</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Annulla</button>
|
|
||||||
<button type="submit" class="btn btn-scad-primary">
|
|
||||||
<i class="fa-solid fa-check me-1"></i> Salva
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php include('../jsinclude.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/jquery.dataTables.min.js"></script>
|
||||||
@@ -1225,111 +1069,6 @@ function getContrastTextColor($hexColor)
|
|||||||
var fpDue = flatpickr('#filterDueRange', fpOpts);
|
var fpDue = flatpickr('#filterDueRange', fpOpts);
|
||||||
var fpCheck = flatpickr('#filterCheckRange', fpOpts);
|
var fpCheck = flatpickr('#filterCheckRange', fpOpts);
|
||||||
|
|
||||||
// --- Flatpickr Italian date fields in deadline modal ---
|
|
||||||
// Visible format: dd/mm/yyyy
|
|
||||||
// Submitted format: yyyy-mm-dd, compatible with MySQL DATE
|
|
||||||
var fpDocDate = flatpickr('#dlDocDate', {
|
|
||||||
dateFormat: 'Y-m-d',
|
|
||||||
altInput: true,
|
|
||||||
altFormat: 'd/m/Y',
|
|
||||||
locale: 'it',
|
|
||||||
allowInput: true
|
|
||||||
});
|
|
||||||
|
|
||||||
var fpDueDate = flatpickr('#dlDueDate', {
|
|
||||||
dateFormat: 'Y-m-d',
|
|
||||||
altInput: true,
|
|
||||||
altFormat: 'd/m/Y',
|
|
||||||
locale: 'it',
|
|
||||||
allowInput: true
|
|
||||||
});
|
|
||||||
|
|
||||||
var fpCheckDate = flatpickr('#dlCheckDate', {
|
|
||||||
dateFormat: 'Y-m-d',
|
|
||||||
altInput: true,
|
|
||||||
altFormat: 'd/m/Y',
|
|
||||||
locale: 'it',
|
|
||||||
allowInput: true
|
|
||||||
});
|
|
||||||
|
|
||||||
// --- Select2 ---
|
|
||||||
$('#dlSubject').select2({
|
|
||||||
theme: 'bootstrap-5',
|
|
||||||
placeholder: 'Seleziona argomento...',
|
|
||||||
allowClear: true,
|
|
||||||
dropdownParent: $('#deadlineModal .modal-body'),
|
|
||||||
language: 'it',
|
|
||||||
width: '100%'
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#dlDepartments').select2({
|
|
||||||
theme: 'bootstrap-5',
|
|
||||||
placeholder: 'Seleziona reparti...',
|
|
||||||
allowClear: true,
|
|
||||||
dropdownParent: $('#deadlineModal .modal-body'),
|
|
||||||
language: 'it',
|
|
||||||
width: '100%'
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#dlEmployees').select2({
|
|
||||||
theme: 'bootstrap-5',
|
|
||||||
placeholder: 'Seleziona persone...',
|
|
||||||
allowClear: true,
|
|
||||||
dropdownParent: $('#deadlineModal .modal-body'),
|
|
||||||
language: 'it',
|
|
||||||
width: '100%'
|
|
||||||
});
|
|
||||||
|
|
||||||
// --- Auto-calc due_date from document_date + recurrence ---
|
|
||||||
var RECURRENCE_OFFSETS = {
|
|
||||||
monthly: {
|
|
||||||
months: 1
|
|
||||||
},
|
|
||||||
quarterly: {
|
|
||||||
months: 3
|
|
||||||
},
|
|
||||||
semiannual: {
|
|
||||||
months: 6
|
|
||||||
},
|
|
||||||
annual: {
|
|
||||||
years: 1
|
|
||||||
},
|
|
||||||
biennial: {
|
|
||||||
years: 2
|
|
||||||
},
|
|
||||||
triennial: {
|
|
||||||
years: 3
|
|
||||||
},
|
|
||||||
quadriennial: {
|
|
||||||
years: 4
|
|
||||||
},
|
|
||||||
quinquennial: {
|
|
||||||
years: 5
|
|
||||||
},
|
|
||||||
decennial: {
|
|
||||||
years: 10
|
|
||||||
},
|
|
||||||
quindecennial: {
|
|
||||||
years: 15
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function computeDueDate() {
|
|
||||||
var docVal = document.getElementById('dlDocDate').value;
|
|
||||||
var recurrence = document.getElementById('dlRecurrence').value;
|
|
||||||
var offset = RECURRENCE_OFFSETS[recurrence];
|
|
||||||
if (!docVal || !offset) return;
|
|
||||||
var d = new Date(docVal + 'T00:00:00');
|
|
||||||
if (isNaN(d.getTime())) return;
|
|
||||||
if (offset.months) d.setMonth(d.getMonth() + offset.months);
|
|
||||||
if (offset.years) d.setFullYear(d.getFullYear() + offset.years);
|
|
||||||
var iso = d.getFullYear() + '-' +
|
|
||||||
String(d.getMonth() + 1).padStart(2, '0') + '-' +
|
|
||||||
String(d.getDate()).padStart(2, '0');
|
|
||||||
fpDueDate.setDate(iso, true, 'Y-m-d');
|
|
||||||
}
|
|
||||||
$('#dlDocDate, #dlRecurrence').on('change', computeDueDate);
|
|
||||||
|
|
||||||
// --- DataTables custom filters ---
|
// --- DataTables custom filters ---
|
||||||
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
|
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
|
||||||
if (settings.nTable.id !== 'deadlinesTable') return true;
|
if (settings.nTable.id !== 'deadlinesTable') return true;
|
||||||
@@ -1491,165 +1230,8 @@ function getContrastTextColor($hexColor)
|
|||||||
// Apply default filter on load
|
// Apply default filter on load
|
||||||
applyFiltersRefresh();
|
applyFiltersRefresh();
|
||||||
|
|
||||||
// --- Modal ---
|
|
||||||
var modal = new bootstrap.Modal(document.getElementById('deadlineModal'));
|
|
||||||
var form = document.getElementById('deadlineForm');
|
|
||||||
|
|
||||||
// Add
|
|
||||||
// Add
|
|
||||||
document.getElementById('btnAddDeadline').addEventListener('click', function() {
|
document.getElementById('btnAddDeadline').addEventListener('click', function() {
|
||||||
form.reset();
|
if (window.openDeadlineCreate) window.openDeadlineCreate();
|
||||||
|
|
||||||
document.getElementById('dlId').value = '';
|
|
||||||
document.getElementById('dlNotifDays').value = '7';
|
|
||||||
document.getElementById('modalTitle').textContent = 'Nuova Scadenza';
|
|
||||||
document.getElementById('dlFiles').value = '';
|
|
||||||
|
|
||||||
fpDocDate.clear();
|
|
||||||
fpDueDate.clear();
|
|
||||||
fpCheckDate.clear();
|
|
||||||
|
|
||||||
$('#dlSubject').val('').trigger('change');
|
|
||||||
$('#dlDepartments').val(null).trigger('change');
|
|
||||||
$('#dlEmployees').val(null).trigger('change');
|
|
||||||
|
|
||||||
renderAttachments([]);
|
|
||||||
modal.show();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Save
|
|
||||||
var isSaving = false;
|
|
||||||
form.addEventListener('submit', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
if (isSaving) return;
|
|
||||||
isSaving = true;
|
|
||||||
var saveBtn = form.querySelector('[type="submit"]');
|
|
||||||
saveBtn.disabled = true;
|
|
||||||
saveBtn.innerHTML = '<i class="fa-solid fa-spinner fa-spin me-1"></i> Salvataggio...';
|
|
||||||
var formData = new FormData(form);
|
|
||||||
|
|
||||||
fetch('scadenzario/ajax/save_deadline.php', {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData
|
|
||||||
})
|
|
||||||
.then(function(r) {
|
|
||||||
return r.json();
|
|
||||||
})
|
|
||||||
.then(function(data) {
|
|
||||||
if (data.success) {
|
|
||||||
var deadlineId = data.id;
|
|
||||||
var fileInput = document.getElementById('dlFiles');
|
|
||||||
if (fileInput.files.length > 0) {
|
|
||||||
// Upload files
|
|
||||||
var fileData = new FormData();
|
|
||||||
fileData.append('deadline_id', deadlineId);
|
|
||||||
for (var i = 0; i < fileInput.files.length; i++) {
|
|
||||||
fileData.append('files[]', fileInput.files[i]);
|
|
||||||
}
|
|
||||||
return fetch('scadenzario/ajax/upload_attachment.php', {
|
|
||||||
method: 'POST',
|
|
||||||
body: fileData
|
|
||||||
})
|
|
||||||
.then(function(r) {
|
|
||||||
return r.json();
|
|
||||||
})
|
|
||||||
.then(function(upData) {
|
|
||||||
modal.hide();
|
|
||||||
Swal.fire({
|
|
||||||
icon: 'success',
|
|
||||||
title: 'Salvato',
|
|
||||||
text: data.message + ' ' + upData.message,
|
|
||||||
timer: 2000,
|
|
||||||
showConfirmButton: false
|
|
||||||
})
|
|
||||||
.then(function() {
|
|
||||||
location.reload();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
modal.hide();
|
|
||||||
Swal.fire({
|
|
||||||
icon: 'success',
|
|
||||||
title: 'Salvato',
|
|
||||||
text: data.message,
|
|
||||||
timer: 1500,
|
|
||||||
showConfirmButton: false
|
|
||||||
})
|
|
||||||
.then(function() {
|
|
||||||
location.reload();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Swal.fire('Errore', data.message, 'error');
|
|
||||||
isSaving = false;
|
|
||||||
saveBtn.disabled = false;
|
|
||||||
saveBtn.innerHTML = '<i class="fa-solid fa-check me-1"></i> Salva';
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(function() {
|
|
||||||
Swal.fire('Errore', 'Errore di connessione.', 'error');
|
|
||||||
isSaving = false;
|
|
||||||
saveBtn.disabled = false;
|
|
||||||
saveBtn.innerHTML = '<i class="fa-solid fa-check me-1"></i> Salva';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Render attachments list
|
|
||||||
function renderAttachments(attachments) {
|
|
||||||
var container = document.getElementById('attachmentsList');
|
|
||||||
if (!attachments || attachments.length === 0) {
|
|
||||||
container.innerHTML = '<div class="text-muted" style="font-size:0.85rem">Nessun allegato</div>';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
container.innerHTML = attachments.map(function(a) {
|
|
||||||
return '<div class="att-item" data-att-id="' + a.id + '">' +
|
|
||||||
'<span class="att-name"><i class="fa-solid fa-paperclip me-1"></i>' + $('<span>').text(a.original_name).html() + '</span>' +
|
|
||||||
'<span class="att-actions">' +
|
|
||||||
'<a href="scadenzario/ajax/download_attachment.php?id=' + a.id + '" class="att-download" title="Scarica"><i class="fa-solid fa-download"></i></a>' +
|
|
||||||
'<button type="button" class="att-remove" title="Elimina" data-att-id="' + a.id + '"><i class="fa-solid fa-xmark"></i></button>' +
|
|
||||||
'</span></div>';
|
|
||||||
}).join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete attachment
|
|
||||||
$(document).on('click', '.att-remove', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
var btn = $(this);
|
|
||||||
var attId = btn.data('att-id');
|
|
||||||
Swal.fire({
|
|
||||||
title: 'Rimuovere l\'allegato?',
|
|
||||||
text: 'Il collegamento verrà rimosso da questa scadenza. Il file resta disponibile se è usato da altre scadenze.',
|
|
||||||
icon: 'warning',
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonColor: '#dc3545',
|
|
||||||
cancelButtonText: 'Annulla',
|
|
||||||
confirmButtonText: 'Rimuovi',
|
|
||||||
reverseButtons: true
|
|
||||||
}).then(function(result) {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
fetch('scadenzario/ajax/delete_attachment.php?id=' + attId)
|
|
||||||
.then(function(r) {
|
|
||||||
return r.json();
|
|
||||||
})
|
|
||||||
.then(function(data) {
|
|
||||||
if (data.success) {
|
|
||||||
btn.closest('.att-item').remove();
|
|
||||||
if ($('#attachmentsList .att-item').length === 0) {
|
|
||||||
renderAttachments([]);
|
|
||||||
}
|
|
||||||
Swal.fire({
|
|
||||||
icon: 'success',
|
|
||||||
title: 'Fatto',
|
|
||||||
text: data.message,
|
|
||||||
timer: 1800,
|
|
||||||
showConfirmButton: false
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Swal.fire('Errore', data.message, 'error');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Edit with confirmation
|
// Edit with confirmation
|
||||||
@@ -1666,52 +1248,9 @@ function getContrastTextColor($hexColor)
|
|||||||
confirmButtonText: 'Sì, modifica',
|
confirmButtonText: 'Sì, modifica',
|
||||||
reverseButtons: true
|
reverseButtons: true
|
||||||
}).then(function(result) {
|
}).then(function(result) {
|
||||||
if (!result.isConfirmed) {
|
if (result.isConfirmed && window.openDeadlineEdit) {
|
||||||
return;
|
window.openDeadlineEdit(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch('scadenzario/ajax/get_deadline.php?id=' + id)
|
|
||||||
.then(function(r) {
|
|
||||||
return r.json();
|
|
||||||
})
|
|
||||||
.then(function(data) {
|
|
||||||
if (!data.success) {
|
|
||||||
Swal.fire('Errore', data.message, 'error');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var d = data.data;
|
|
||||||
|
|
||||||
document.getElementById('dlId').value = d.id;
|
|
||||||
$('#dlSubject').val(d.subject_id || '').trigger('change');
|
|
||||||
document.getElementById('dlTopic').value = d.topic || '';
|
|
||||||
document.getElementById('dlLaw').value = d.law_regulation || '';
|
|
||||||
document.getElementById('dlRecurrence').value = d.recurrence_type || 'once';
|
|
||||||
fpDocDate.setDate(d.document_date || null, false, 'Y-m-d');
|
|
||||||
fpDueDate.setDate(d.due_date || null, false, 'Y-m-d');
|
|
||||||
fpCheckDate.setDate(d.check_date || null, false, 'Y-m-d');
|
|
||||||
document.getElementById('dlNotifDays').value = d.notification_days || 7;
|
|
||||||
document.getElementById('dlStorage').value = d.storage_location || '';
|
|
||||||
document.getElementById('dlNotes').value = d.notes || '';
|
|
||||||
document.getElementById('dlFiles').value = '';
|
|
||||||
|
|
||||||
document.getElementById('modalTitle').textContent = 'Modifica Scadenza';
|
|
||||||
|
|
||||||
$('#dlDepartments').val(d.department_names || []).trigger('change');
|
|
||||||
|
|
||||||
if (Array.isArray(d.employee_ids)) {
|
|
||||||
$('#dlEmployees').val(d.employee_ids.map(String)).trigger('change');
|
|
||||||
} else {
|
|
||||||
$('#dlEmployees').val(null).trigger('change');
|
|
||||||
}
|
|
||||||
|
|
||||||
renderAttachments(d.attachments || []);
|
|
||||||
|
|
||||||
modal.show();
|
|
||||||
})
|
|
||||||
.catch(function() {
|
|
||||||
Swal.fire('Errore', 'Errore di connessione.', 'error');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1739,9 +1278,9 @@ function getContrastTextColor($hexColor)
|
|||||||
showConfirmButton: false
|
showConfirmButton: false
|
||||||
})
|
})
|
||||||
.then(function() {
|
.then(function() {
|
||||||
// Auto-open the newly created deadline; otherwise just refresh the list
|
// Open the new deadline's detail page with the edit modal auto-opening
|
||||||
if (data.new_id) {
|
if (data.new_id) {
|
||||||
window.location = 'scadenzario/index.php?edit=' + data.new_id;
|
window.location = 'scadenzario/detail.php?id=' + data.new_id + '#edit';
|
||||||
} else {
|
} else {
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
@@ -1851,38 +1390,6 @@ function getContrastTextColor($hexColor)
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Auto-open edit modal from ?edit=ID
|
|
||||||
var urlParams = new URLSearchParams(window.location.search);
|
|
||||||
var editId = urlParams.get('edit');
|
|
||||||
if (editId) {
|
|
||||||
history.replaceState(null, '', 'scadenzario/index.php');
|
|
||||||
fetch('scadenzario/ajax/get_deadline.php?id=' + editId)
|
|
||||||
.then(function(r) {
|
|
||||||
return r.json();
|
|
||||||
})
|
|
||||||
.then(function(data) {
|
|
||||||
if (!data.success) return;
|
|
||||||
var d = data.data;
|
|
||||||
document.getElementById('dlId').value = d.id;
|
|
||||||
$('#dlSubject').val(d.subject_id || '').trigger('change');
|
|
||||||
document.getElementById('dlTopic').value = d.topic || '';
|
|
||||||
document.getElementById('dlLaw').value = d.law_regulation || '';
|
|
||||||
document.getElementById('dlRecurrence').value = d.recurrence_type || 'once';
|
|
||||||
fpDocDate.setDate(d.document_date || null, false, 'Y-m-d');
|
|
||||||
fpDueDate.setDate(d.due_date || null, false, 'Y-m-d');
|
|
||||||
fpCheckDate.setDate(d.check_date || null, false, 'Y-m-d');
|
|
||||||
document.getElementById('dlNotifDays').value = d.notification_days || 7;
|
|
||||||
document.getElementById('dlStorage').value = d.storage_location || '';
|
|
||||||
document.getElementById('dlNotes').value = d.notes || '';
|
|
||||||
document.getElementById('dlFiles').value = '';
|
|
||||||
document.getElementById('modalTitle').textContent = 'Modifica Scadenza';
|
|
||||||
$('#dlDepartments').val(d.department_names || []).trigger('change');
|
|
||||||
$('#dlEmployees').val(d.employee_ids.map(String)).trigger('change');
|
|
||||||
renderAttachments(d.attachments || []);
|
|
||||||
modal.show();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stampa
|
// Stampa
|
||||||
function doStampa() {
|
function doStampa() {
|
||||||
var params = [];
|
var params = [];
|
||||||
@@ -1905,6 +1412,7 @@ function getContrastTextColor($hexColor)
|
|||||||
if (btnStampaMobile) btnStampaMobile.addEventListener('click', doStampa);
|
if (btnStampaMobile) btnStampaMobile.addEventListener('click', doStampa);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<?php include __DIR__ . '/include/deadline_modal_js.php'; ?>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user