netgescon-master/resources/views/components/layout/header/user-menu.blade.php
2025-07-20 14:57:25 +00:00

307 lines
9.4 KiB
PHP

{{--
========================================
MENU UTENTE HEADER
========================================
Dropdown menu utente con profile, impostazioni, logout.
Props:
- $showAvatar (bool): Mostra avatar utente
- $showStatus (bool): Mostra stato online/offline
- $avatarSize (string): Dimensione avatar (sm, md, lg)
Autore: NetGesCon Development Team
Data: 2024
========================================
--}}
@props([
'showAvatar' => true,
'showStatus' => true,
'avatarSize' => 'md'
])
@php
$user = Auth::user();
$avatarSizes = [
'sm' => '32px',
'md' => '40px',
'lg' => '48px'
];
$currentSize = $avatarSizes[$avatarSize] ?? $avatarSizes['md'];
@endphp
<div class="netgescon-user-menu dropdown">
{{-- Trigger utente --}}
<button class="btn btn-outline-secondary d-flex align-items-center"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
aria-label="Menu utente">
{{-- Avatar --}}
@if($showAvatar)
<div class="user-avatar me-2 position-relative" style="width: {{ $currentSize }}; height: {{ $currentSize }};">
@if($user->avatar)
<img src="{{ asset('storage/' . $user->avatar) }}"
alt="Avatar {{ $user->name }}"
class="rounded-circle w-100 h-100 object-fit-cover">
@else
<div class="avatar-placeholder rounded-circle w-100 h-100 d-flex align-items-center justify-content-center bg-primary text-white">
{{ strtoupper(substr($user->name, 0, 1)) }}
</div>
@endif
{{-- Status indicator --}}
@if($showStatus)
<span class="position-absolute bottom-0 end-0 status-indicator bg-success border border-white rounded-circle"
title="Online"></span>
@endif
</div>
@endif
{{-- Nome utente (nascosto su mobile) --}}
<span class="d-none d-md-inline">{{ $user->name }}</span>
{{-- Freccia dropdown --}}
<i class="fas fa-chevron-down ms-2 small"></i>
</button>
{{-- Dropdown menu --}}
<ul class="dropdown-menu dropdown-menu-end user-dropdown">
{{-- Header utente --}}
<li class="dropdown-header user-info">
<div class="d-flex align-items-center">
@if($showAvatar)
<div class="user-avatar-large me-3">
@if($user->avatar)
<img src="{{ asset('storage/' . $user->avatar) }}"
alt="Avatar {{ $user->name }}"
class="rounded-circle" style="width: 50px; height: 50px;">
@else
<div class="avatar-placeholder rounded-circle bg-primary text-white d-flex align-items-center justify-content-center"
style="width: 50px; height: 50px; font-size: 1.25rem;">
{{ strtoupper(substr($user->name, 0, 1)) }}
</div>
@endif
</div>
@endif
<div>
<div class="fw-semibold">{{ $user->name }}</div>
<small class="text-muted">{{ $user->email }}</small>
@if($user->roles->isNotEmpty())
<div>
<span class="badge bg-secondary small">{{ $user->roles->first()->name }}</span>
</div>
@endif
</div>
</div>
</li>
<li><hr class="dropdown-divider"></li>
{{-- Menu items --}}
<li>
<a class="dropdown-item" href="{{ route('profile.edit') }}">
<i class="fas fa-user me-2"></i>Il mio profilo
</a>
</li>
<li>
<a class="dropdown-item" href="{{ route('profile.edit') }}" title="Impostazioni profilo">
<i class="fas fa-cog me-2"></i>Impostazioni
</a>
</li>
<li>
<a class="dropdown-item" href="#" title="Notifiche (in sviluppo)">
<i class="fas fa-bell me-2"></i>Notifiche
@php $unreadNotifications = 0; /* TODO: implementare conteggio */ @endphp
@if($unreadNotifications > 0)
<span class="badge bg-danger ms-auto">{{ $unreadNotifications }}</span>
@endif
</a>
</li>
{{-- Separatore --}}
<li><hr class="dropdown-divider"></li>
{{-- Azioni admin (solo per ruoli appropriati) --}}
@if($user->hasRole(['super-admin', 'admin']))
<li>
<a class="dropdown-item" href="{{ route('admin.dashboard') }}">
<i class="fas fa-tachometer-alt me-2"></i>Pannello Admin
</a>
</li>
@if($user->hasRole('super-admin'))
<li>
<a class="dropdown-item" href="{{ route('superadmin.dashboard') }}">
<i class="fas fa-crown me-2 text-warning"></i>Super Admin
</a>
</li>
@endif
<li><hr class="dropdown-divider"></li>
@endif
{{-- Cambio tema --}}
<li>
<button type="button" class="dropdown-item" id="themeToggle">
<i class="fas fa-moon me-2" id="themeIcon"></i>
<span id="themeText">Tema scuro</span>
</button>
</li>
{{-- Aiuto --}}
<li>
<a class="dropdown-item" href="#" title="Centro aiuto (in sviluppo)">
<i class="fas fa-question-circle me-2"></i>Aiuto
</a>
</li>
{{-- Logout --}}
<li><hr class="dropdown-divider"></li>
<li>
<form method="POST" action="{{ route('logout') }}" class="d-inline">
@csrf
<button type="submit" class="dropdown-item text-danger">
<i class="fas fa-sign-out-alt me-2"></i>Logout
</button>
</form>
</li>
</ul>
</div>
{{-- CSS per menu utente --}}
@push('styles')
<style>
.user-dropdown {
width: 280px;
border: none;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}
.user-info {
padding: 1rem;
background: linear-gradient(135deg, var(--bs-primary), var(--bs-info));
color: white;
margin-bottom: 0;
}
.user-info .text-muted {
color: rgba(255, 255, 255, 0.8) !important;
}
.user-info .badge {
background-color: rgba(255, 255, 255, 0.2) !important;
}
.status-indicator {
width: 12px;
height: 12px;
}
.avatar-placeholder {
font-weight: 600;
font-size: 0.875rem;
}
.dropdown-item {
padding: 0.75rem 1rem;
transition: all 0.2s ease;
}
.dropdown-item:hover {
background-color: var(--bs-light);
}
.dropdown-item.text-danger:hover {
background-color: var(--bs-danger);
color: white !important;
}
/* Tema scuro */
.dark .user-dropdown {
background-color: var(--bs-dark);
border-color: var(--bs-gray-700);
}
.dark .dropdown-item:hover {
background-color: var(--bs-gray-800);
}
.dark .user-info {
background: linear-gradient(135deg, var(--bs-primary), var(--bs-secondary));
}
/* Responsive */
@media (max-width: 768px) {
.user-dropdown {
width: 250px;
}
}
</style>
@endpush
{{-- JavaScript per menu utente --}}
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', function() {
// Toggle tema
const themeToggle = document.getElementById('themeToggle');
const themeIcon = document.getElementById('themeIcon');
const themeText = document.getElementById('themeText');
if (themeToggle) {
// Stato iniziale
const isDark = document.documentElement.classList.contains('dark') ||
localStorage.getItem('theme') === 'dark';
updateThemeButton(isDark);
themeToggle.addEventListener('click', function() {
const currentTheme = localStorage.getItem('theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
localStorage.setItem('theme', newTheme);
document.documentElement.classList.toggle('dark', newTheme === 'dark');
updateThemeButton(newTheme === 'dark');
// Notifica cambio tema
if (typeof window.updateTheme === 'function') {
window.updateTheme(newTheme);
}
});
}
function updateThemeButton(isDark) {
if (themeIcon && themeText) {
if (isDark) {
themeIcon.className = 'fas fa-sun me-2';
themeText.textContent = 'Tema chiaro';
} else {
themeIcon.className = 'fas fa-moon me-2';
themeText.textContent = 'Tema scuro';
}
}
}
// Conferma logout
const logoutForm = document.querySelector('form[action*="logout"]');
if (logoutForm) {
logoutForm.addEventListener('submit', function(e) {
if (!confirm('Sei sicuro di voler uscire?')) {
e.preventDefault();
}
});
}
});
</script>
@endpush