475 lines
21 KiB
PHP
475 lines
21 KiB
PHP
<?php
|
|
/**
|
|
* Gestione Territori
|
|
* Territory Manager
|
|
*/
|
|
|
|
require_once 'config.php';
|
|
require_once 'functions.php';
|
|
require_once 'db.php';
|
|
|
|
requireLogin();
|
|
|
|
$page_title = 'Gestione Territori';
|
|
$db = getDB();
|
|
|
|
$action = $_GET['action'] ?? 'list';
|
|
$territory_id = $_GET['id'] ?? null;
|
|
|
|
// Gestione delle azioni POST
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
if (isset($_POST['action'])) {
|
|
switch ($_POST['action']) {
|
|
case 'add':
|
|
$numero = sanitize($_POST['numero']);
|
|
$zona = sanitize($_POST['zona']);
|
|
$tipologia = sanitize($_POST['tipologia']);
|
|
$note = sanitize($_POST['note'] ?? '');
|
|
|
|
// Gestione upload immagine
|
|
$image_path = null;
|
|
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
|
|
$file = $_FILES['image'];
|
|
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
|
|
|
|
if (in_array($ext, ALLOWED_EXTENSIONS) && $file['size'] <= MAX_FILE_SIZE) {
|
|
$filename = 'territory_' . time() . '_' . uniqid() . '.' . $ext;
|
|
$upload_dir = UPLOAD_PATH;
|
|
|
|
if (!is_dir($upload_dir)) {
|
|
mkdir($upload_dir, 0755, true);
|
|
}
|
|
|
|
if (move_uploaded_file($file['tmp_name'], $upload_dir . '/' . $filename)) {
|
|
$image_path = UPLOAD_URL . '/' . $filename;
|
|
}
|
|
}
|
|
}
|
|
|
|
$result = $db->query(
|
|
"INSERT INTO territories (numero, zona, tipologia, image_path, note) VALUES (?, ?, ?, ?, ?)",
|
|
[$numero, $zona, $tipologia, $image_path, $note]
|
|
);
|
|
|
|
if ($result) {
|
|
$territory_id = $db->getConnection()->lastInsertId();
|
|
logActivity('create', "Creato territorio $numero - $zona", 'territory', $territory_id);
|
|
setFlashMessage('Territorio aggiunto con successo', 'success');
|
|
} else {
|
|
setFlashMessage('Errore durante l\'aggiunta del territorio', 'error');
|
|
}
|
|
|
|
header('Location: territories.php');
|
|
exit;
|
|
break;
|
|
|
|
case 'edit':
|
|
$id = (int)$_POST['id'];
|
|
$numero = sanitize($_POST['numero']);
|
|
$zona = sanitize($_POST['zona']);
|
|
$tipologia = sanitize($_POST['tipologia']);
|
|
$note = sanitize($_POST['note'] ?? '');
|
|
|
|
// Gestione upload nuova immagine
|
|
$image_path = $_POST['current_image'] ?? null;
|
|
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
|
|
$file = $_FILES['image'];
|
|
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
|
|
|
|
if (in_array($ext, ALLOWED_EXTENSIONS) && $file['size'] <= MAX_FILE_SIZE) {
|
|
// Elimina vecchia immagine
|
|
if ($image_path && file_exists(BASE_PATH . $image_path)) {
|
|
unlink(BASE_PATH . $image_path);
|
|
}
|
|
|
|
$filename = 'territory_' . time() . '_' . uniqid() . '.' . $ext;
|
|
$upload_dir = UPLOAD_PATH;
|
|
|
|
if (!is_dir($upload_dir)) {
|
|
mkdir($upload_dir, 0755, true);
|
|
}
|
|
|
|
if (move_uploaded_file($file['tmp_name'], $upload_dir . '/' . $filename)) {
|
|
$image_path = UPLOAD_URL . '/' . $filename;
|
|
}
|
|
}
|
|
}
|
|
|
|
$result = $db->query(
|
|
"UPDATE territories SET numero = ?, zona = ?, tipologia = ?, image_path = ?, note = ? WHERE id = ?",
|
|
[$numero, $zona, $tipologia, $image_path, $note, $id]
|
|
);
|
|
|
|
if ($result) {
|
|
logActivity('update', "Modificato territorio $numero - $zona", 'territory', $id);
|
|
setFlashMessage('Territorio modificato con successo', 'success');
|
|
} else {
|
|
setFlashMessage('Errore durante la modifica del territorio', 'error');
|
|
}
|
|
|
|
header('Location: territories.php');
|
|
exit;
|
|
break;
|
|
|
|
case 'delete':
|
|
$id = (int)$_POST['id'];
|
|
|
|
// Recupera l'immagine per eliminarla
|
|
$territory = $db->fetchOne("SELECT numero, zona, image_path FROM territories WHERE id = ?", [$id]);
|
|
if ($territory && $territory['image_path']) {
|
|
$file_path = BASE_PATH . $territory['image_path'];
|
|
if (file_exists($file_path)) {
|
|
unlink($file_path);
|
|
}
|
|
}
|
|
|
|
$result = $db->query("DELETE FROM territories WHERE id = ?", [$id]);
|
|
|
|
if ($result) {
|
|
if ($territory) {
|
|
logActivity('delete', "Eliminato territorio {$territory['numero']} - {$territory['zona']}", 'territory', $id);
|
|
}
|
|
setFlashMessage('Territorio eliminato con successo', 'success');
|
|
} else {
|
|
setFlashMessage('Errore durante l\'eliminazione del territorio', 'error');
|
|
}
|
|
|
|
header('Location: territories.php');
|
|
exit;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Recupera dati per modifica
|
|
$territory = null;
|
|
if ($action === 'edit' && $territory_id) {
|
|
$territory = $db->fetchOne("SELECT * FROM territories WHERE id = ?", [$territory_id]);
|
|
if (!$territory) {
|
|
setFlashMessage('Territorio non trovato', 'error');
|
|
header('Location: territories.php');
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Lista territori con informazioni sullo stato
|
|
if ($action === 'list') {
|
|
$search = $_GET['search'] ?? '';
|
|
$filter_zona = $_GET['zona'] ?? '';
|
|
$filter_tipologia = $_GET['tipologia'] ?? '';
|
|
|
|
$where = [];
|
|
$params = [];
|
|
|
|
if ($search) {
|
|
$where[] = "(t.numero LIKE ? OR t.zona LIKE ? OR t.tipologia LIKE ?)";
|
|
$search_term = "%$search%";
|
|
$params[] = $search_term;
|
|
$params[] = $search_term;
|
|
$params[] = $search_term;
|
|
}
|
|
|
|
if ($filter_zona) {
|
|
$where[] = "t.zona = ?";
|
|
$params[] = $filter_zona;
|
|
}
|
|
|
|
if ($filter_tipologia) {
|
|
$where[] = "t.tipologia = ?";
|
|
$params[] = $filter_tipologia;
|
|
}
|
|
|
|
$where_clause = $where ? "WHERE " . implode(" AND ", $where) : "";
|
|
|
|
$territories = $db->fetchAll("
|
|
SELECT
|
|
t.*,
|
|
a.id as current_assignment_id,
|
|
a.assigned_to,
|
|
a.assigned_date,
|
|
DATEDIFF(CURDATE(), a.assigned_date) as days_assigned
|
|
FROM territories t
|
|
LEFT JOIN assignments a ON t.id = a.territory_id AND a.returned_date IS NULL
|
|
$where_clause
|
|
ORDER BY t.numero ASC
|
|
", $params);
|
|
|
|
// Ottieni liste per filtri
|
|
$zones = $db->fetchAll("SELECT DISTINCT zona FROM territories ORDER BY zona");
|
|
$types = $db->fetchAll("SELECT DISTINCT tipologia FROM territories ORDER BY tipologia");
|
|
}
|
|
|
|
include 'header.php';
|
|
?>
|
|
|
|
<?php if ($action === 'list'): ?>
|
|
<div class="page-header">
|
|
<h1>Gestione Territori</h1>
|
|
<a href="?action=add" class="btn btn-primary">+ Nuovo Territorio</a>
|
|
</div>
|
|
|
|
<!-- Filtri di ricerca -->
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<form method="GET" action="" class="filter-form">
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<input type="text" name="search" placeholder="Cerca numero, zona o tipologia..."
|
|
value="<?php echo htmlspecialchars($search); ?>" class="form-control">
|
|
</div>
|
|
<div class="form-group">
|
|
<select name="zona" class="form-control">
|
|
<option value="">Tutte le zone</option>
|
|
<?php foreach ($zones as $z): ?>
|
|
<option value="<?php echo htmlspecialchars($z['zona']); ?>"
|
|
<?php echo $filter_zona === $z['zona'] ? 'selected' : ''; ?>>
|
|
<?php echo htmlspecialchars($z['zona']); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<select name="tipologia" class="form-control">
|
|
<option value="">Tutte le tipologie</option>
|
|
<?php foreach ($types as $t): ?>
|
|
<option value="<?php echo htmlspecialchars($t['tipologia']); ?>"
|
|
<?php echo $filter_tipologia === $t['tipologia'] ? 'selected' : ''; ?>>
|
|
<?php echo htmlspecialchars($t['tipologia']); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary">Filtra</button>
|
|
<a href="territories.php" class="btn btn-secondary">Reset</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tabella territori -->
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<?php if (count($territories) > 0): ?>
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Numero</th>
|
|
<th>Zona</th>
|
|
<th>Tipologia</th>
|
|
<th>Stato</th>
|
|
<th>Assegnato a</th>
|
|
<th>Giorni</th>
|
|
<th>Azioni</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($territories as $t): ?>
|
|
<tr>
|
|
<td><strong><?php echo htmlspecialchars($t['numero']); ?></strong></td>
|
|
<td><?php echo htmlspecialchars($t['zona']); ?></td>
|
|
<td><?php echo htmlspecialchars($t['tipologia']); ?></td>
|
|
<td>
|
|
<?php if ($t['current_assignment_id']): ?>
|
|
<span class="badge badge-info">Assegnato</span>
|
|
<?php else: ?>
|
|
<span class="badge badge-success">Disponibile</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?php echo $t['assigned_to'] ? htmlspecialchars($t['assigned_to']) : '-'; ?></td>
|
|
<td><?php echo $t['days_assigned'] ?? '-'; ?></td>
|
|
<td class="actions">
|
|
<a href="?action=view&id=<?php echo $t['id']; ?>" class="btn btn-sm btn-secondary">Dettagli</a>
|
|
<a href="?action=edit&id=<?php echo $t['id']; ?>" class="btn btn-sm btn-primary">Modifica</a>
|
|
<?php if (!$t['current_assignment_id']): ?>
|
|
<form method="POST" style="display:inline;" onsubmit="return confirm('Sei sicuro di voler eliminare questo territorio?');">
|
|
<input type="hidden" name="action" value="delete">
|
|
<input type="hidden" name="id" value="<?php echo $t['id']; ?>">
|
|
<button type="submit" class="btn btn-sm btn-danger">Elimina</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php else: ?>
|
|
<p class="empty-state">Nessun territorio trovato</p>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php elseif ($action === 'add' || $action === 'edit'): ?>
|
|
<div class="page-header">
|
|
<h1><?php echo $action === 'add' ? 'Nuovo Territorio' : 'Modifica Territorio'; ?></h1>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<form method="POST" enctype="multipart/form-data">
|
|
<input type="hidden" name="action" value="<?php echo $action; ?>">
|
|
<?php if ($action === 'edit'): ?>
|
|
<input type="hidden" name="id" value="<?php echo $territory['id']; ?>">
|
|
<input type="hidden" name="current_image" value="<?php echo htmlspecialchars($territory['image_path'] ?? ''); ?>">
|
|
<?php endif; ?>
|
|
|
|
<div class="form-group">
|
|
<label for="numero">Numero Territorio *</label>
|
|
<input type="text" id="numero" name="numero" required
|
|
value="<?php echo $territory ? htmlspecialchars($territory['numero']) : ''; ?>" class="form-control">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="zona">Zona *</label>
|
|
<input type="text" id="zona" name="zona" required
|
|
value="<?php echo $territory ? htmlspecialchars($territory['zona']) : ''; ?>" class="form-control">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="tipologia">Tipologia *</label>
|
|
<input type="text" id="tipologia" name="tipologia" required
|
|
value="<?php echo $territory ? htmlspecialchars($territory['tipologia']) : ''; ?>" class="form-control">
|
|
<small class="form-help">Es: Residenziale, Commerciale, Rurale, ecc.</small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="image">Piantina Territorio</label>
|
|
<?php if ($territory && $territory['image_path']): ?>
|
|
<div class="current-image">
|
|
<img src="<?php echo htmlspecialchars($territory['image_path']); ?>" alt="Piantina" style="max-width: 300px; margin-bottom: 10px;">
|
|
</div>
|
|
<?php endif; ?>
|
|
<input type="file" id="image" name="image" accept="image/*,.pdf" class="form-control">
|
|
<small class="form-help">Formati supportati: JPG, PNG, GIF, PDF. Dimensione massima: 5 MB</small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="note">Note</label>
|
|
<textarea id="note" name="note" rows="4" class="form-control"><?php echo $territory ? htmlspecialchars($territory['note']) : ''; ?></textarea>
|
|
</div>
|
|
|
|
<div class="form-actions">
|
|
<button type="submit" class="btn btn-primary">
|
|
<?php echo $action === 'add' ? 'Aggiungi Territorio' : 'Salva Modifiche'; ?>
|
|
</button>
|
|
<a href="territories.php" class="btn btn-secondary">Annulla</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<?php elseif ($action === 'view' && $territory_id): ?>
|
|
<?php
|
|
$territory = $db->fetchOne("SELECT * FROM territories WHERE id = ?", [$territory_id]);
|
|
if (!$territory) {
|
|
setFlashMessage('Territorio non trovato', 'error');
|
|
header('Location: territories.php');
|
|
exit;
|
|
}
|
|
|
|
// Storico assegnazioni
|
|
$history = $db->fetchAll("
|
|
SELECT
|
|
assigned_to,
|
|
assigned_date,
|
|
returned_date,
|
|
DATEDIFF(COALESCE(returned_date, CURDATE()), assigned_date) as days_duration,
|
|
is_priority,
|
|
note
|
|
FROM assignments
|
|
WHERE territory_id = ?
|
|
ORDER BY assigned_date DESC
|
|
", [$territory_id]);
|
|
?>
|
|
|
|
<div class="page-header">
|
|
<h1>Dettagli Territorio: <?php echo htmlspecialchars($territory['numero']); ?></h1>
|
|
<div>
|
|
<a href="?action=edit&id=<?php echo $territory['id']; ?>" class="btn btn-primary">Modifica</a>
|
|
<a href="territories.php" class="btn btn-secondary">Torna alla Lista</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="detail-grid">
|
|
<div class="detail-item">
|
|
<strong>Numero:</strong> <?php echo htmlspecialchars($territory['numero']); ?>
|
|
</div>
|
|
<div class="detail-item">
|
|
<strong>Zona:</strong> <?php echo htmlspecialchars($territory['zona']); ?>
|
|
</div>
|
|
<div class="detail-item">
|
|
<strong>Tipologia:</strong> <?php echo htmlspecialchars($territory['tipologia']); ?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if ($territory['note']): ?>
|
|
<div class="detail-item">
|
|
<strong>Note:</strong>
|
|
<p><?php echo nl2br(htmlspecialchars($territory['note'])); ?></p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($territory['image_path']): ?>
|
|
<div class="detail-item">
|
|
<strong>Piantina:</strong><br>
|
|
<a href="<?php echo htmlspecialchars($territory['image_path']); ?>" target="_blank">
|
|
<img src="<?php echo htmlspecialchars($territory['image_path']); ?>"
|
|
alt="Piantina" style="max-width: 500px; margin-top: 10px; border: 1px solid #ddd;">
|
|
</a>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h2>Storico Assegnazioni</h2>
|
|
</div>
|
|
<div class="card-body">
|
|
<?php if (count($history) > 0): ?>
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Assegnato a</th>
|
|
<th>Data Assegnazione</th>
|
|
<th>Data Restituzione</th>
|
|
<th>Durata</th>
|
|
<th>Priorità</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($history as $h): ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars($h['assigned_to']); ?></td>
|
|
<td><?php echo formatDate($h['assigned_date']); ?></td>
|
|
<td>
|
|
<?php
|
|
if ($h['returned_date']) {
|
|
echo formatDate($h['returned_date']);
|
|
} else {
|
|
echo '<span class="badge badge-info">In corso</span>';
|
|
}
|
|
?>
|
|
</td>
|
|
<td><?php echo $h['days_duration']; ?> giorni</td>
|
|
<td>
|
|
<?php if ($h['is_priority']): ?>
|
|
<span class="badge badge-danger">Priorità</span>
|
|
<?php else: ?>
|
|
-
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php else: ?>
|
|
<p class="empty-state">Nessuna assegnazione storica</p>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php include 'footer.php'; ?>
|