217 lines
6.7 KiB
PHP
217 lines
6.7 KiB
PHP
{{--
|
|
========================================
|
|
BARRA DI RICERCA HEADER
|
|
========================================
|
|
Componente di ricerca globale con autocompletamento
|
|
e filtri intelligenti.
|
|
|
|
Props:
|
|
- $placeholder (string): Testo placeholder
|
|
- $showFilters (bool): Mostra filtri avanzati
|
|
- $autoFocus (bool): Focus automatico su caricamento
|
|
|
|
Autore: NetGesCon Development Team
|
|
Data: 2024
|
|
========================================
|
|
--}}
|
|
|
|
@props([
|
|
'placeholder' => 'Cerca in NetGesCon...',
|
|
'showFilters' => false,
|
|
'autoFocus' => false
|
|
])
|
|
|
|
<div class="netgescon-search position-relative" style="max-width: 400px;">
|
|
<form action="#" method="GET" class="search-form" title="Ricerca globale (in sviluppo)">
|
|
|
|
{{-- Input principale compatto --}}
|
|
<div class="input-group input-group-sm">
|
|
<span class="input-group-text bg-transparent border-end-0">
|
|
<i class="fas fa-search text-muted"></i>
|
|
</span>
|
|
|
|
<input type="text"
|
|
name="q"
|
|
class="form-control border-start-0 ps-0"
|
|
placeholder="{{ $placeholder }}"
|
|
value="{{ request('q') }}"
|
|
autocomplete="off"
|
|
{{ $autoFocus ? 'autofocus' : '' }}
|
|
id="globalSearch"
|
|
data-bs-toggle="dropdown"
|
|
aria-expanded="false">
|
|
|
|
{{-- Pulsante filtri --}}
|
|
@if($showFilters)
|
|
<button class="btn btn-outline-secondary dropdown-toggle"
|
|
type="button"
|
|
data-bs-toggle="dropdown"
|
|
aria-label="Filtri di ricerca">
|
|
<i class="fas fa-filter"></i>
|
|
</button>
|
|
@endif
|
|
</div>
|
|
|
|
{{-- Dropdown Filtri --}}
|
|
@if($showFilters)
|
|
<ul class="dropdown-menu dropdown-menu-end search-filters">
|
|
<li><h6 class="dropdown-header">Filtra per categoria</h6></li>
|
|
<li>
|
|
<label class="dropdown-item">
|
|
<input type="checkbox" name="filters[]" value="stabili" class="form-check-input me-2">
|
|
Stabili
|
|
</label>
|
|
</li>
|
|
<li>
|
|
<label class="dropdown-item">
|
|
<input type="checkbox" name="filters[]" value="condomini" class="form-check-input me-2">
|
|
Condomini
|
|
</label>
|
|
</li>
|
|
<li>
|
|
<label class="dropdown-item">
|
|
<input type="checkbox" name="filters[]" value="documenti" class="form-check-input me-2">
|
|
Documenti
|
|
</label>
|
|
</li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li>
|
|
<button type="submit" class="dropdown-item text-primary">
|
|
<i class="fas fa-search me-2"></i>Cerca
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
@endif
|
|
|
|
</form>
|
|
|
|
{{-- Risultati in tempo reale (AJAX) --}}
|
|
<div class="search-results dropdown-menu w-100 d-none" id="searchResults">
|
|
<div class="p-3 text-center">
|
|
<div class="spinner-border spinner-border-sm" role="status">
|
|
<span class="visually-hidden">Caricamento...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{{-- CSS per ricerca --}}
|
|
@push('styles')
|
|
<style>
|
|
.netgescon-search {
|
|
max-width: 400px;
|
|
width: 100%;
|
|
}
|
|
|
|
.search-form .form-control:focus {
|
|
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
|
border-color: #80bdff;
|
|
}
|
|
|
|
.search-results {
|
|
max-height: 400px;
|
|
overflow-y: auto;
|
|
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
|
}
|
|
|
|
.search-result-item {
|
|
padding: 0.75rem 1rem;
|
|
border-bottom: 1px solid var(--bs-border-color);
|
|
transition: background-color 0.2s ease;
|
|
}
|
|
|
|
.search-result-item:hover {
|
|
background-color: var(--bs-light);
|
|
}
|
|
|
|
.search-result-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
/* Tema scuro */
|
|
.dark .search-result-item:hover {
|
|
background-color: var(--bs-dark);
|
|
}
|
|
|
|
/* Responsive */
|
|
@media (max-width: 768px) {
|
|
.netgescon-search {
|
|
max-width: 100%;
|
|
}
|
|
}
|
|
</style>
|
|
@endpush
|
|
|
|
{{-- JavaScript per funzionalità ricerca --}}
|
|
@push('scripts')
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const searchInput = document.getElementById('globalSearch');
|
|
const searchResults = document.getElementById('searchResults');
|
|
let searchTimeout;
|
|
|
|
if (searchInput) {
|
|
// Ricerca in tempo reale
|
|
searchInput.addEventListener('input', function() {
|
|
const query = this.value.trim();
|
|
|
|
clearTimeout(searchTimeout);
|
|
|
|
if (query.length < 2) {
|
|
searchResults.classList.add('d-none');
|
|
return;
|
|
}
|
|
|
|
searchTimeout = setTimeout(() => {
|
|
performSearch(query);
|
|
}, 300);
|
|
});
|
|
|
|
// Nascondi risultati quando si clicca fuori
|
|
document.addEventListener('click', function(e) {
|
|
if (!searchInput.contains(e.target) && !searchResults.contains(e.target)) {
|
|
searchResults.classList.add('d-none');
|
|
}
|
|
});
|
|
}
|
|
|
|
function performSearch(query) {
|
|
fetch(`#?q=${encodeURIComponent(query)}`, {
|
|
headers: {
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
displaySearchResults(data);
|
|
})
|
|
.catch(error => {
|
|
console.error('Errore ricerca:', error);
|
|
});
|
|
}
|
|
|
|
function displaySearchResults(results) {
|
|
if (!results || results.length === 0) {
|
|
searchResults.innerHTML = '<div class="p-3 text-muted">Nessun risultato trovato</div>';
|
|
} else {
|
|
searchResults.innerHTML = results.map(result => `
|
|
<a href="${result.url}" class="search-result-item d-block text-decoration-none">
|
|
<div class="d-flex align-items-center">
|
|
<i class="${result.icon} text-muted me-2"></i>
|
|
<div>
|
|
<div class="fw-semibold">${result.title}</div>
|
|
<small class="text-muted">${result.category}</small>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
`).join('');
|
|
}
|
|
|
|
searchResults.classList.remove('d-none');
|
|
}
|
|
});
|
|
</script>
|
|
@endpush
|