447 lines
18 KiB
PHP
447 lines
18 KiB
PHP
{{-- Dashboard gestione comuni italiani SuperAdmin --}}
|
|
@extends('admin.layouts.netgescon')
|
|
|
|
@section('title', 'Gestione Comuni Italiani')
|
|
|
|
@section('content')
|
|
<div class="container-fluid">
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="d-flex align-items-center justify-content-between">
|
|
<div>
|
|
<h1 class="h4 mb-1 text-primary">
|
|
<i class="fas fa-map-marked-alt me-2"></i>Gestione Comuni Italiani
|
|
</h1>
|
|
<p class="text-muted mb-0 small">
|
|
Importazione, gestione e ricerca comuni italiani da archivi ufficiali
|
|
</p>
|
|
</div>
|
|
<div class="text-muted text-end small">
|
|
<i class="fas fa-crown me-1"></i>SuperAdmin Panel
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Statistiche comuni --}}
|
|
<div class="row mb-4">
|
|
<div class="col-md-3">
|
|
<div class="card bg-primary text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-grow-1">
|
|
<h6 class="card-title mb-1 small">
|
|
<i class="fas fa-city me-2"></i>Comuni Totali
|
|
</h6>
|
|
<h3 class="mb-0">{{ number_format($stats['comuni_totali']) }}</h3>
|
|
<small class="opacity-75">Comuni caricati</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card bg-success text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-grow-1">
|
|
<h6 class="card-title mb-1 small">
|
|
<i class="fas fa-map me-2"></i>Regioni
|
|
</h6>
|
|
<h3 class="mb-0">{{ $stats['regioni_totali'] }}</h3>
|
|
<small class="opacity-75">Regioni coperte</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card bg-info text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-grow-1">
|
|
<h6 class="card-title mb-1 small">
|
|
<i class="fas fa-location-dot me-2"></i>Province
|
|
</h6>
|
|
<h3 class="mb-0">{{ $stats['province_totali'] }}</h3>
|
|
<small class="opacity-75">Province coperte</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card bg-warning text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-grow-1">
|
|
<h6 class="card-title mb-1 small">
|
|
<i class="fas fa-clock me-2"></i>Ultimo Aggiornamento
|
|
</h6>
|
|
<div class="mb-0">
|
|
@if($stats['ultimo_aggiornamento'])
|
|
{{ \Carbon\Carbon::parse($stats['ultimo_aggiornamento'])->format('d/m/Y') }}
|
|
@else
|
|
<small>Nessun dato</small>
|
|
@endif
|
|
</div>
|
|
<small class="opacity-75">Data ultimo import</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Sezioni gestione --}}
|
|
<div class="row">
|
|
{{-- Upload ZIP --}}
|
|
<div class="col-md-6 mb-4">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-file-archive me-2"></i>Importazione da ZIP
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="text-muted">
|
|
Carica un file ZIP contenente i dati dei comuni italiani in formato JSON.
|
|
Il sistema supporta l'importazione di più file JSON contemporaneamente.
|
|
</p>
|
|
|
|
<form id="upload-form" enctype="multipart/form-data">
|
|
@csrf
|
|
<div class="mb-3">
|
|
<label for="zip_file" class="form-label">File ZIP</label>
|
|
<input type="file" class="form-control" id="zip_file" name="zip_file" accept=".zip" required>
|
|
<div class="form-text">Formato supportato: ZIP (max 50MB)</div>
|
|
</div>
|
|
|
|
<div class="form-check mb-3">
|
|
<input class="form-check-input" type="checkbox" id="overwrite" name="overwrite">
|
|
<label class="form-check-label" for="overwrite">
|
|
Sovrascrivi dati esistenti
|
|
</label>
|
|
<div class="form-text text-warning">
|
|
<i class="fas fa-exclamation-triangle me-1"></i>
|
|
Se selezionato, i comuni esistenti verranno aggiornati
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fas fa-upload me-2"></i>Avvia Importazione
|
|
</button>
|
|
</form>
|
|
|
|
<div id="upload-progress" class="mt-3" style="display: none;">
|
|
<div class="progress">
|
|
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%"></div>
|
|
</div>
|
|
<div class="text-center mt-2">
|
|
<small class="text-muted">Importazione in corso...</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Ricerca comuni --}}
|
|
<div class="col-md-6 mb-4">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-search me-2"></i>Ricerca Comuni
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<label for="search-comuni" class="form-label">Cerca comune</label>
|
|
<input type="text" class="form-control" id="search-comuni" placeholder="Nome comune o codice catastale">
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="filter-regione" class="form-label">Regione</label>
|
|
<select class="form-select" id="filter-regione">
|
|
<option value="">Tutte le regioni</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="filter-provincia" class="form-label">Provincia</label>
|
|
<select class="form-select" id="filter-provincia">
|
|
<option value="">Tutte le province</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="button" class="btn btn-info w-100" onclick="searchComuni()">
|
|
<i class="fas fa-search me-2"></i>Cerca
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Risultati ricerca --}}
|
|
<div class="row" id="search-results" style="display: none;">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-list me-2"></i>Risultati Ricerca
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-striped" id="comuni-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Denominazione</th>
|
|
<th>Cod. Catastale</th>
|
|
<th>CAP</th>
|
|
<th>Provincia</th>
|
|
<th>Regione</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="comuni-table-body">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Azioni amministrative --}}
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<div class="card border-danger">
|
|
<div class="card-header bg-danger text-white">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-exclamation-triangle me-2"></i>Azioni Amministrative
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<button type="button" class="btn btn-outline-info w-100" onclick="exportComuni()">
|
|
<i class="fas fa-download me-2"></i>Esporta Comuni
|
|
</button>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<button type="button" class="btn btn-outline-warning w-100" onclick="showStats()">
|
|
<i class="fas fa-chart-bar me-2"></i>Statistiche Dettagliate
|
|
</button>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<button type="button" class="btn btn-outline-danger w-100" onclick="resetDatabase()">
|
|
<i class="fas fa-trash me-2"></i>Reset Database
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Modal statistiche --}}
|
|
<div class="modal fade" id="statsModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">
|
|
<i class="fas fa-chart-bar me-2"></i>Statistiche Dettagliate
|
|
</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body" id="stats-content">
|
|
<div class="text-center">
|
|
<i class="fas fa-spinner fa-spin"></i> Caricamento...
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@push('scripts')
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Upload form handler
|
|
document.getElementById('upload-form').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const formData = new FormData(this);
|
|
const progressContainer = document.getElementById('upload-progress');
|
|
const progressBar = progressContainer.querySelector('.progress-bar');
|
|
|
|
// Mostra progress bar
|
|
progressContainer.style.display = 'block';
|
|
progressBar.style.width = '0%';
|
|
|
|
fetch('{{ route("superadmin.comuni.upload") }}', {
|
|
method: 'POST',
|
|
body: formData,
|
|
headers: {
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
progressBar.style.width = '100%';
|
|
|
|
if (data.success) {
|
|
alert('Importazione completata: ' + data.message);
|
|
window.location.reload();
|
|
} else {
|
|
alert('Errore: ' + data.message);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Errore:', error);
|
|
alert('Errore durante l\'importazione');
|
|
})
|
|
.finally(() => {
|
|
progressContainer.style.display = 'none';
|
|
});
|
|
});
|
|
});
|
|
|
|
function searchComuni() {
|
|
const query = document.getElementById('search-comuni').value;
|
|
const regione = document.getElementById('filter-regione').value;
|
|
const provincia = document.getElementById('filter-provincia').value;
|
|
|
|
const params = new URLSearchParams();
|
|
if (query) params.append('q', query);
|
|
if (regione) params.append('regione', regione);
|
|
if (provincia) params.append('provincia', provincia);
|
|
|
|
fetch(`{{ route("superadmin.comuni.search") }}?${params}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
displaySearchResults(data);
|
|
})
|
|
.catch(error => {
|
|
console.error('Errore ricerca:', error);
|
|
alert('Errore durante la ricerca');
|
|
});
|
|
}
|
|
|
|
function displaySearchResults(comuni) {
|
|
const tbody = document.getElementById('comuni-table-body');
|
|
const resultsContainer = document.getElementById('search-results');
|
|
|
|
tbody.innerHTML = '';
|
|
|
|
comuni.forEach(comune => {
|
|
const row = tbody.insertRow();
|
|
row.innerHTML = `
|
|
<td>${comune.denominazione}</td>
|
|
<td>${comune.codice_catastale || '-'}</td>
|
|
<td>${comune.cap || '-'}</td>
|
|
<td>${comune.provincia || '-'}</td>
|
|
<td>${comune.regione || '-'}</td>
|
|
`;
|
|
});
|
|
|
|
resultsContainer.style.display = 'block';
|
|
}
|
|
|
|
function exportComuni() {
|
|
const regione = document.getElementById('filter-regione').value;
|
|
const provincia = document.getElementById('filter-provincia').value;
|
|
|
|
const params = new URLSearchParams();
|
|
if (regione) params.append('regione', regione);
|
|
if (provincia) params.append('provincia', provincia);
|
|
|
|
window.open(`{{ route("superadmin.comuni.export") }}?${params}`, '_blank');
|
|
}
|
|
|
|
function showStats() {
|
|
const modal = new bootstrap.Modal(document.getElementById('statsModal'));
|
|
modal.show();
|
|
|
|
fetch('{{ route("superadmin.comuni.stats") }}')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
document.getElementById('stats-content').innerHTML = generateStatsHTML(data);
|
|
})
|
|
.catch(error => {
|
|
document.getElementById('stats-content').innerHTML = '<div class="alert alert-danger">Errore nel caricamento delle statistiche</div>';
|
|
});
|
|
}
|
|
|
|
function generateStatsHTML(data) {
|
|
return `
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6>Comuni per Regione (Top 10)</h6>
|
|
<ul class="list-group">
|
|
${data.per_regione.slice(0, 10).map(item =>
|
|
`<li class="list-group-item d-flex justify-content-between">
|
|
<span>${item.regione || 'N/D'}</span>
|
|
<badge class="badge bg-primary">${item.totale}</badge>
|
|
</li>`
|
|
).join('')}
|
|
</ul>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6>Totali</h6>
|
|
<ul class="list-group">
|
|
<li class="list-group-item d-flex justify-content-between">
|
|
<span>Comuni totali</span>
|
|
<badge class="badge bg-success">${data.totali.comuni}</badge>
|
|
</li>
|
|
<li class="list-group-item d-flex justify-content-between">
|
|
<span>Regioni</span>
|
|
<badge class="badge bg-info">${data.totali.regioni}</badge>
|
|
</li>
|
|
<li class="list-group-item d-flex justify-content-between">
|
|
<span>Province</span>
|
|
<badge class="badge bg-warning">${data.totali.province}</badge>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
function resetDatabase() {
|
|
if (!confirm('ATTENZIONE: Questa operazione eliminerà TUTTI i comuni dal database. Sei sicuro?')) {
|
|
return;
|
|
}
|
|
|
|
const confirmation = prompt('Per confermare, scrivi "RESET_COMUNI":');
|
|
if (confirmation !== 'RESET_COMUNI') {
|
|
alert('Operazione annullata');
|
|
return;
|
|
}
|
|
|
|
fetch('{{ route("superadmin.comuni.reset") }}', {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ confirm: 'RESET_COMUNI' })
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
alert(data.message);
|
|
window.location.reload();
|
|
} else {
|
|
alert('Errore: ' + data.message);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Errore:', error);
|
|
alert('Errore durante il reset');
|
|
});
|
|
}
|
|
</script>
|
|
@endpush
|
|
@endsection
|