321 lines
9.8 KiB
PHP
321 lines
9.8 KiB
PHP
{{--
|
|
========================================
|
|
ALERT E MESSAGGI MODULARI
|
|
========================================
|
|
Sistema completo di messaggi flash, validazione
|
|
e notifiche con auto-dismiss e stack.
|
|
|
|
Props:
|
|
- $showValidation (bool): Mostra errori di validazione
|
|
- $showFlash (bool): Mostra messaggi flash
|
|
- $autoDismiss (int): Secondi per auto-dismiss (0 = mai)
|
|
- $position (string): Posizione (top, bottom)
|
|
|
|
Autore: NetGesCon Development Team
|
|
Data: 2024
|
|
========================================
|
|
--}}
|
|
|
|
@props([
|
|
'showValidation' => true,
|
|
'showFlash' => true,
|
|
'autoDismiss' => 5,
|
|
'position' => 'top'
|
|
])
|
|
|
|
<div class="netgescon-alerts position-relative">
|
|
|
|
{{-- Errori di Validazione --}}
|
|
@if($showValidation && $errors->any())
|
|
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
|
<div class="d-flex align-items-start">
|
|
<i class="fas fa-exclamation-triangle me-2 mt-1"></i>
|
|
<div class="flex-grow-1">
|
|
<h6 class="alert-heading mb-2">Errori di validazione</h6>
|
|
<ul class="mb-0 small">
|
|
@foreach ($errors->all() as $error)
|
|
<li>{{ $error }}</li>
|
|
@endforeach
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Chiudi"></button>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- Messaggi Flash di Successo --}}
|
|
@if($showFlash && session('success'))
|
|
<div class="alert alert-success alert-dismissible fade show"
|
|
role="alert"
|
|
@if($autoDismiss > 0) data-auto-dismiss="{{ $autoDismiss }}" @endif>
|
|
<div class="d-flex align-items-start">
|
|
<i class="fas fa-check-circle me-2 mt-1"></i>
|
|
<div class="flex-grow-1">
|
|
<strong>Successo!</strong>
|
|
<div>{{ session('success') }}</div>
|
|
</div>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Chiudi"></button>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- Messaggi Flash di Errore --}}
|
|
@if($showFlash && session('error'))
|
|
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
|
<div class="d-flex align-items-start">
|
|
<i class="fas fa-times-circle me-2 mt-1"></i>
|
|
<div class="flex-grow-1">
|
|
<strong>Errore!</strong>
|
|
<div>{{ session('error') }}</div>
|
|
</div>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Chiudi"></button>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- Messaggi Flash di Warning --}}
|
|
@if($showFlash && session('warning'))
|
|
<div class="alert alert-warning alert-dismissible fade show"
|
|
role="alert"
|
|
@if($autoDismiss > 0) data-auto-dismiss="{{ $autoDismiss }}" @endif>
|
|
<div class="d-flex align-items-start">
|
|
<i class="fas fa-exclamation-triangle me-2 mt-1"></i>
|
|
<div class="flex-grow-1">
|
|
<strong>Attenzione!</strong>
|
|
<div>{{ session('warning') }}</div>
|
|
</div>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Chiudi"></button>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- Messaggi Flash Informativi --}}
|
|
@if($showFlash && session('info'))
|
|
<div class="alert alert-info alert-dismissible fade show"
|
|
role="alert"
|
|
@if($autoDismiss > 0) data-auto-dismiss="{{ $autoDismiss }}" @endif>
|
|
<div class="d-flex align-items-start">
|
|
<i class="fas fa-info-circle me-2 mt-1"></i>
|
|
<div class="flex-grow-1">
|
|
<strong>Informazione</strong>
|
|
<div>{{ session('info') }}</div>
|
|
</div>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Chiudi"></button>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- Messaggi Flash Generici (con tipo personalizzato) --}}
|
|
@if($showFlash && session('message'))
|
|
@php
|
|
$messageType = session('message_type', 'info');
|
|
$icons = [
|
|
'success' => 'fas fa-check-circle',
|
|
'error' => 'fas fa-times-circle',
|
|
'warning' => 'fas fa-exclamation-triangle',
|
|
'info' => 'fas fa-info-circle',
|
|
'primary' => 'fas fa-star',
|
|
'secondary' => 'fas fa-bell'
|
|
];
|
|
$icon = $icons[$messageType] ?? 'fas fa-info-circle';
|
|
@endphp
|
|
|
|
<div class="alert alert-{{ $messageType }} alert-dismissible fade show"
|
|
role="alert"
|
|
@if($autoDismiss > 0) data-auto-dismiss="{{ $autoDismiss }}" @endif>
|
|
<div class="d-flex align-items-start">
|
|
<i class="{{ $icon }} me-2 mt-1"></i>
|
|
<div class="flex-grow-1">
|
|
{{ session('message') }}
|
|
</div>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Chiudi"></button>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- Container per alert dinamici (JavaScript) --}}
|
|
<div id="dynamic-alerts"></div>
|
|
|
|
</div>
|
|
|
|
{{-- CSS per alert --}}
|
|
@push('styles')
|
|
<style>
|
|
.netgescon-alerts {
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.netgescon-alerts .alert {
|
|
border: none;
|
|
border-radius: 0.5rem;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
|
|
.netgescon-alerts .alert:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.netgescon-alerts .alert-heading {
|
|
font-size: 1rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.netgescon-alerts .alert ul {
|
|
padding-left: 1rem;
|
|
}
|
|
|
|
.netgescon-alerts .alert ul li {
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.netgescon-alerts .alert ul li:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
/* Animazioni */
|
|
.netgescon-alerts .alert {
|
|
animation: slideInDown 0.3s ease-out;
|
|
}
|
|
|
|
@keyframes slideInDown {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(-10px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.netgescon-alerts .alert.fade.show {
|
|
transition: opacity 0.3s ease, transform 0.3s ease;
|
|
}
|
|
|
|
/* Auto-dismiss progress bar */
|
|
.alert[data-auto-dismiss] {
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.alert[data-auto-dismiss]::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
height: 3px;
|
|
background-color: currentColor;
|
|
opacity: 0.3;
|
|
animation: progressBar var(--duration, 5s) linear forwards;
|
|
}
|
|
|
|
@keyframes progressBar {
|
|
from { width: 100%; }
|
|
to { width: 0%; }
|
|
}
|
|
|
|
/* Tema scuro */
|
|
.dark .netgescon-alerts .alert {
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
/* Responsive */
|
|
@media (max-width: 768px) {
|
|
.netgescon-alerts .alert {
|
|
margin-bottom: 0.5rem;
|
|
border-radius: 0.375rem;
|
|
}
|
|
|
|
.netgescon-alerts .alert-heading {
|
|
font-size: 0.9rem;
|
|
}
|
|
}
|
|
|
|
/* Posizionamento fisso per toast */
|
|
.netgescon-alerts.position-fixed {
|
|
top: 20px;
|
|
right: 20px;
|
|
z-index: 1050;
|
|
max-width: 400px;
|
|
}
|
|
|
|
.netgescon-alerts.position-fixed.bottom {
|
|
top: auto;
|
|
bottom: 20px;
|
|
}
|
|
</style>
|
|
@endpush
|
|
|
|
{{-- JavaScript per funzionalità alert --}}
|
|
@push('scripts')
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Auto-dismiss alerts
|
|
const autoDismissAlerts = document.querySelectorAll('[data-auto-dismiss]');
|
|
|
|
autoDismissAlerts.forEach(alert => {
|
|
const duration = parseInt(alert.dataset.autoDismiss) * 1000;
|
|
|
|
// Imposta durata CSS
|
|
alert.style.setProperty('--duration', alert.dataset.autoDismiss + 's');
|
|
|
|
setTimeout(() => {
|
|
const bsAlert = new bootstrap.Alert(alert);
|
|
bsAlert.close();
|
|
}, duration);
|
|
});
|
|
|
|
// Funzione globale per creare alert dinamici
|
|
window.showAlert = function(message, type = 'info', autoDismiss = true) {
|
|
const alertContainer = document.getElementById('dynamic-alerts');
|
|
if (!alertContainer) return;
|
|
|
|
const icons = {
|
|
'success': 'fas fa-check-circle',
|
|
'error': 'fas fa-times-circle',
|
|
'warning': 'fas fa-exclamation-triangle',
|
|
'info': 'fas fa-info-circle',
|
|
'primary': 'fas fa-star',
|
|
'secondary': 'fas fa-bell'
|
|
};
|
|
|
|
const icon = icons[type] || icons.info;
|
|
const alertId = 'alert-' + Date.now();
|
|
|
|
const alertHtml = `
|
|
<div class="alert alert-${type} alert-dismissible fade show"
|
|
id="${alertId}"
|
|
role="alert"
|
|
${autoDismiss ? 'data-auto-dismiss="5"' : ''}>
|
|
<div class="d-flex align-items-start">
|
|
<i class="${icon} me-2 mt-1"></i>
|
|
<div class="flex-grow-1">${message}</div>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Chiudi"></button>
|
|
</div>
|
|
`;
|
|
|
|
alertContainer.insertAdjacentHTML('beforeend', alertHtml);
|
|
|
|
// Auto-dismiss se richiesto
|
|
if (autoDismiss) {
|
|
const alertElement = document.getElementById(alertId);
|
|
alertElement.style.setProperty('--duration', '5s');
|
|
|
|
setTimeout(() => {
|
|
const bsAlert = new bootstrap.Alert(alertElement);
|
|
bsAlert.close();
|
|
}, 5000);
|
|
}
|
|
};
|
|
|
|
// Funzioni helper
|
|
window.showSuccess = (message) => window.showAlert(message, 'success');
|
|
window.showError = (message) => window.showAlert(message, 'error');
|
|
window.showWarning = (message) => window.showAlert(message, 'warning');
|
|
window.showInfo = (message) => window.showAlert(message, 'info');
|
|
});
|
|
</script>
|
|
@endpush
|