629 lines
17 KiB
Markdown
Executable File
629 lines
17 KiB
Markdown
Executable File
# 📋 SIDEBAR - Documentazione Completa NetGescon
|
|
|
|
> **Componente Sidebar dell'interfaccia universale**
|
|
> **📅 Creato:** 21/07/2025
|
|
> **🔄 Ultimo aggiornamento:** 21/07/2025
|
|
> **🎯 Priorità:** 🔥 CRITICA
|
|
|
|
---
|
|
|
|
## 📋 **OVERVIEW SIDEBAR**
|
|
|
|
La Sidebar NetGescon è il componente **NAVIGATION PRINCIPALE** che contiene:
|
|
- 🏠 **Dashboard Links**
|
|
- 🏢 **Stabili Management**
|
|
- 🏘️ **Condomini Management**
|
|
- 💰 **Contabilità & Fiscale**
|
|
- 👥 **User & Admin Tools**
|
|
- ⚙️ **Sistema Permessi Integrato**
|
|
|
|
### 📐 **Specifiche Layout**
|
|
- **Larghezza:** `280px` desktop, `100%` mobile
|
|
- **Posizione:** `fixed left` sempre visibile desktop
|
|
- **Altezza:** `calc(100vh - 70px)` (header escluso)
|
|
- **Scroll:** Interno quando contenuto > viewport
|
|
|
|
---
|
|
|
|
## 🎨 **DESIGN SPECIFICATIONS**
|
|
|
|
### 🌈 **Color Palette**
|
|
```css
|
|
/* Sidebar Background */
|
|
.netgescon-sidebar {
|
|
background: var(--netgescon-gray-900);
|
|
border-right: 1px solid var(--netgescon-gray-700);
|
|
}
|
|
|
|
/* Menu Items */
|
|
.sidebar-link {
|
|
color: var(--netgescon-gray-300);
|
|
background: transparent;
|
|
}
|
|
|
|
.sidebar-link:hover {
|
|
color: var(--netgescon-gray-100);
|
|
background: var(--netgescon-gray-800);
|
|
}
|
|
|
|
.sidebar-link.active {
|
|
color: var(--netgescon-primary-light);
|
|
background: rgba(37, 99, 235, 0.1);
|
|
border-right: 3px solid var(--netgescon-primary);
|
|
}
|
|
```
|
|
|
|
### 📏 **Dimensions**
|
|
```css
|
|
.netgescon-sidebar {
|
|
width: 280px;
|
|
height: calc(100vh - 70px);
|
|
top: 70px;
|
|
left: 0;
|
|
position: fixed;
|
|
z-index: 999;
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
/* Mobile */
|
|
@media (max-width: 767px) {
|
|
.netgescon-sidebar {
|
|
width: 100%;
|
|
transform: translateX(-100%);
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
.netgescon-sidebar.mobile-open {
|
|
transform: translateX(0);
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🧩 **STRUTTURA MODULARE**
|
|
|
|
### 📁 **Directory Structure**
|
|
```
|
|
resources/views/components/menu/
|
|
├── sidebar.blade.php # File principale
|
|
└── sections/ # Componenti modulari
|
|
├── header.blade.php # Header sidebar con user info
|
|
├── dashboard.blade.php # Dashboard links
|
|
├── stabili.blade.php # Gestione stabili (submenu)
|
|
├── condomini.blade.php # Gestione condomini (submenu)
|
|
├── contabilita.blade.php # Contabilità (submenu)
|
|
├── fiscale.blade.php # Fiscale (submenu)
|
|
├── menu-semplici.blade.php # Menu senza submenu
|
|
├── footer.blade.php # Footer sidebar
|
|
├── menu-helpers.blade.php # Helper funzioni
|
|
└── permissions.blade.php # Sistema permessi
|
|
```
|
|
|
|
### 🎯 **Main Sidebar Component**
|
|
```blade
|
|
<!-- resources/views/components/menu/sidebar.blade.php -->
|
|
<nav class="netgescon-sidebar">
|
|
<!-- Sidebar Header -->
|
|
@include('components.menu.sections.header')
|
|
|
|
<!-- Navigation Menu -->
|
|
<div class="sidebar-nav">
|
|
<!-- Dashboard -->
|
|
@include('components.menu.sections.dashboard')
|
|
|
|
<!-- Stabili (con permessi) -->
|
|
@if(canUserAccessMenu('stabili'))
|
|
@include('components.menu.sections.stabili')
|
|
@endif
|
|
|
|
<!-- Condomini (con permessi) -->
|
|
@if(canUserAccessMenu('condomini'))
|
|
@include('components.menu.sections.condomini')
|
|
@endif
|
|
|
|
<!-- Sezione Economica -->
|
|
@if(canUserAccessAnyMenu(['contabilita', 'fiscale']))
|
|
<div class="menu-divider"></div>
|
|
<h6 class="menu-section-title">Gestione Economica</h6>
|
|
|
|
@if(canUserAccessMenu('contabilita'))
|
|
@include('components.menu.sections.contabilita')
|
|
@endif
|
|
|
|
@if(canUserAccessMenu('fiscale'))
|
|
@include('components.menu.sections.fiscale')
|
|
@endif
|
|
@endif
|
|
|
|
<!-- Menu Semplici -->
|
|
@include('components.menu.sections.menu-semplici')
|
|
</div>
|
|
|
|
<!-- Sidebar Footer -->
|
|
@include('components.menu.sections.footer')
|
|
</nav>
|
|
|
|
<!-- Overlay mobile -->
|
|
<div class="mobile-overlay hidden md:hidden" onclick="toggleMobileMenu()"></div>
|
|
```
|
|
|
|
---
|
|
|
|
## 👥 **SISTEMA PERMESSI**
|
|
|
|
### 🔐 **Ruoli Definiti**
|
|
```php
|
|
// Definiti in config/netgescon.php
|
|
'roles' => [
|
|
'super_admin' => 'Super Amministratore',
|
|
'admin' => 'Amministratore',
|
|
'amministratore' => 'Amministratore Condominio',
|
|
'collaboratore' => 'Collaboratore',
|
|
'ragioniere' => 'Ragioniere/Commercialista',
|
|
'condomino' => 'Condomino',
|
|
'guest' => 'Ospite'
|
|
];
|
|
```
|
|
|
|
### 🛡️ **Helper Functions**
|
|
```blade
|
|
<!-- resources/views/components/menu/sections/menu-helpers.blade.php -->
|
|
@php
|
|
/**
|
|
* Verifica se l'utente può accedere a una sezione menu
|
|
*/
|
|
function canUserAccessMenu($menuSection, $userRole = null) {
|
|
$userRole = $userRole ?? (auth()->user()->role ?? 'guest');
|
|
|
|
$permissions = [
|
|
'super_admin' => ['*'], // Accesso totale
|
|
'admin' => [
|
|
'dashboard', 'stabili', 'condomini', 'unita',
|
|
'contabilita', 'fiscale', 'comunicazioni',
|
|
'utenti', 'reports', 'impostazioni'
|
|
],
|
|
'amministratore' => [
|
|
'dashboard', 'stabili', 'condomini', 'unita',
|
|
'contabilita', 'comunicazioni', 'reports'
|
|
],
|
|
'collaboratore' => [
|
|
'dashboard', 'stabili', 'condomini', 'unita', 'comunicazioni'
|
|
],
|
|
'ragioniere' => [
|
|
'dashboard', 'contabilita', 'fiscale', 'reports'
|
|
],
|
|
'condomino' => [
|
|
'dashboard', 'comunicazioni', 'tickets'
|
|
],
|
|
'guest' => []
|
|
];
|
|
|
|
return in_array('*', $permissions[$userRole] ?? []) ||
|
|
in_array($menuSection, $permissions[$userRole] ?? []);
|
|
}
|
|
|
|
/**
|
|
* Verifica accesso a qualsiasi menu di una lista
|
|
*/
|
|
function canUserAccessAnyMenu($menuSections, $userRole = null) {
|
|
foreach ($menuSections as $section) {
|
|
if (canUserAccessMenu($section, $userRole)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
@endphp
|
|
```
|
|
|
|
---
|
|
|
|
## 🏠 **MENU SECTIONS DETAILED**
|
|
|
|
### 1. **📊 DASHBOARD**
|
|
```blade
|
|
<!-- components/menu/sections/dashboard.blade.php -->
|
|
<div class="menu-section">
|
|
<a href="{{ route('dashboard') }}"
|
|
class="sidebar-link {{ request()->routeIs('dashboard') ? 'active' : '' }}">
|
|
<i class="fas fa-tachometer-alt w-5"></i>
|
|
<span>Dashboard</span>
|
|
</a>
|
|
</div>
|
|
```
|
|
|
|
### 2. **🏢 STABILI (con Submenu)**
|
|
```blade
|
|
<!-- components/menu/sections/stabili.blade.php -->
|
|
<div class="menu-section">
|
|
<div class="menu-item-with-submenu">
|
|
<button class="sidebar-toggle" data-target="submenu-stabili">
|
|
<i class="fas fa-building w-5"></i>
|
|
<span>Gestione Stabili</span>
|
|
<i class="fas fa-chevron-down ml-auto transition-transform"></i>
|
|
</button>
|
|
|
|
<div id="submenu-stabili" class="submenu {{ request()->is('admin/stabili*') ? 'open' : '' }}">
|
|
<a href="{{ route('admin.stabili.index') }}"
|
|
class="submenu-link {{ request()->routeIs('admin.stabili.index') ? 'active' : '' }}">
|
|
<i class="fas fa-list w-4"></i>
|
|
<span>Elenco Stabili</span>
|
|
</a>
|
|
<a href="{{ route('admin.stabili.create') }}"
|
|
class="submenu-link {{ request()->routeIs('admin.stabili.create') ? 'active' : '' }}">
|
|
<i class="fas fa-plus w-4"></i>
|
|
<span>Nuovo Stabile</span>
|
|
</a>
|
|
<a href="{{ route('admin.stabili.reports') }}"
|
|
class="submenu-link {{ request()->routeIs('admin.stabili.reports') ? 'active' : '' }}">
|
|
<i class="fas fa-chart-bar w-4"></i>
|
|
<span>Report Stabili</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
### 3. **🏘️ CONDOMINI (con Submenu)**
|
|
```blade
|
|
<!-- components/menu/sections/condomini.blade.php -->
|
|
<div class="menu-section">
|
|
<div class="menu-item-with-submenu">
|
|
<button class="sidebar-toggle" data-target="submenu-condomini">
|
|
<i class="fas fa-home w-5"></i>
|
|
<span>Gestione Condomini</span>
|
|
<i class="fas fa-chevron-down ml-auto transition-transform"></i>
|
|
</button>
|
|
|
|
<div id="submenu-condomini" class="submenu {{ request()->is('admin/condomini*') ? 'open' : '' }}">
|
|
<a href="{{ route('admin.condomini.index') }}"
|
|
class="submenu-link {{ request()->routeIs('admin.condomini.index') ? 'active' : '' }}">
|
|
<i class="fas fa-list w-4"></i>
|
|
<span>Elenco Condomini</span>
|
|
</a>
|
|
<a href="{{ route('admin.condomini.create') }}"
|
|
class="submenu-link {{ request()->routeIs('admin.condomini.create') ? 'active' : '' }}">
|
|
<i class="fas fa-plus w-4"></i>
|
|
<span>Nuovo Condominio</span>
|
|
</a>
|
|
<a href="{{ route('admin.unita.index') }}"
|
|
class="submenu-link {{ request()->routeIs('admin.unita*') ? 'active' : '' }}">
|
|
<i class="fas fa-door-open w-4"></i>
|
|
<span>Unità Immobiliari</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
### 4. **💰 CONTABILITÀ (con Submenu)**
|
|
```blade
|
|
<!-- components/menu/sections/contabilita.blade.php -->
|
|
<div class="menu-section">
|
|
<div class="menu-item-with-submenu">
|
|
<button class="sidebar-toggle" data-target="submenu-contabilita">
|
|
<i class="fas fa-calculator w-5"></i>
|
|
<span>Contabilità</span>
|
|
<i class="fas fa-chevron-down ml-auto transition-transform"></i>
|
|
</button>
|
|
|
|
<div id="submenu-contabilita" class="submenu {{ request()->is('admin/contabilita*') ? 'open' : '' }}">
|
|
<a href="{{ route('admin.contabilita.budget') }}"
|
|
class="submenu-link">
|
|
<i class="fas fa-chart-pie w-4"></i>
|
|
<span>Budget Annuale</span>
|
|
</a>
|
|
<a href="{{ route('admin.contabilita.spese') }}"
|
|
class="submenu-link">
|
|
<i class="fas fa-receipt w-4"></i>
|
|
<span>Gestione Spese</span>
|
|
</a>
|
|
<a href="{{ route('admin.contabilita.ripartizioni') }}"
|
|
class="submenu-link">
|
|
<i class="fas fa-percentage w-4"></i>
|
|
<span>Ripartizioni</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
---
|
|
|
|
## ⚡ **JAVASCRIPT FUNCTIONALITY**
|
|
|
|
### 📁 **File:** `/public/js/components/sidebar.js`
|
|
|
|
```javascript
|
|
/**
|
|
* Sidebar NetGescon - JavaScript Functions
|
|
*/
|
|
|
|
// Inizializza sidebar
|
|
function initializeSidebar() {
|
|
initializeSubmenuToggles();
|
|
initializeActiveStates();
|
|
initializeMobileOverlay();
|
|
initializeScrollBehavior();
|
|
}
|
|
|
|
// Gestione submenu toggle
|
|
function initializeSubmenuToggles() {
|
|
const toggles = document.querySelectorAll('.sidebar-toggle');
|
|
|
|
toggles.forEach(toggle => {
|
|
toggle.addEventListener('click', function() {
|
|
const targetId = this.getAttribute('data-target');
|
|
const submenu = document.getElementById(targetId);
|
|
const chevron = this.querySelector('.fa-chevron-down');
|
|
|
|
// Toggle submenu
|
|
submenu.classList.toggle('open');
|
|
|
|
// Rotate chevron
|
|
chevron.classList.toggle('rotate-180');
|
|
|
|
// Store state in localStorage
|
|
localStorage.setItem(`submenu-${targetId}`, submenu.classList.contains('open'));
|
|
});
|
|
});
|
|
}
|
|
|
|
// Ripristina stato submenu da localStorage
|
|
function restoreSubmenuStates() {
|
|
const submenus = document.querySelectorAll('.submenu');
|
|
|
|
submenus.forEach(submenu => {
|
|
const stored = localStorage.getItem(`submenu-${submenu.id}`);
|
|
if (stored === 'true') {
|
|
submenu.classList.add('open');
|
|
const toggle = document.querySelector(`[data-target="${submenu.id}"]`);
|
|
const chevron = toggle.querySelector('.fa-chevron-down');
|
|
chevron.classList.add('rotate-180');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Active states management
|
|
function initializeActiveStates() {
|
|
const currentUrl = window.location.pathname;
|
|
const links = document.querySelectorAll('.sidebar-link, .submenu-link');
|
|
|
|
links.forEach(link => {
|
|
const href = link.getAttribute('href');
|
|
if (href && currentUrl.startsWith(href)) {
|
|
link.classList.add('active');
|
|
|
|
// Se è un submenu link, apri anche il parent
|
|
if (link.classList.contains('submenu-link')) {
|
|
const submenu = link.closest('.submenu');
|
|
if (submenu) {
|
|
submenu.classList.add('open');
|
|
const toggle = document.querySelector(`[data-target="${submenu.id}"]`);
|
|
const chevron = toggle.querySelector('.fa-chevron-down');
|
|
chevron.classList.add('rotate-180');
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Mobile behavior
|
|
function toggleMobileMenu() {
|
|
const sidebar = document.querySelector('.netgescon-sidebar');
|
|
const overlay = document.querySelector('.mobile-overlay');
|
|
|
|
sidebar.classList.toggle('mobile-open');
|
|
|
|
if (overlay) {
|
|
overlay.classList.toggle('hidden');
|
|
} else {
|
|
createMobileOverlay();
|
|
}
|
|
}
|
|
|
|
function createMobileOverlay() {
|
|
const overlay = document.createElement('div');
|
|
overlay.className = 'mobile-overlay fixed inset-0 bg-black bg-opacity-50 z-998 md:hidden';
|
|
overlay.onclick = toggleMobileMenu;
|
|
document.body.appendChild(overlay);
|
|
}
|
|
|
|
// Smooth scroll interno sidebar
|
|
function initializeScrollBehavior() {
|
|
const sidebar = document.querySelector('.netgescon-sidebar');
|
|
|
|
// Scroll to active item
|
|
const activeItem = sidebar.querySelector('.active');
|
|
if (activeItem) {
|
|
activeItem.scrollIntoView({
|
|
behavior: 'smooth',
|
|
block: 'center'
|
|
});
|
|
}
|
|
}
|
|
|
|
// Initialize on DOM ready
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
initializeSidebar();
|
|
restoreSubmenuStates();
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## 📱 **RESPONSIVE BEHAVIOR**
|
|
|
|
### 🖥️ **Desktop (≥768px)**
|
|
```css
|
|
.netgescon-sidebar {
|
|
position: fixed;
|
|
left: 0;
|
|
transform: none;
|
|
width: 280px;
|
|
}
|
|
|
|
.content-area {
|
|
margin-left: 280px;
|
|
}
|
|
```
|
|
|
|
### 📱 **Mobile (≤767px)**
|
|
```css
|
|
.netgescon-sidebar {
|
|
position: fixed;
|
|
left: 0;
|
|
width: 100%;
|
|
transform: translateX(-100%);
|
|
transition: transform 0.3s ease;
|
|
z-index: 1001;
|
|
}
|
|
|
|
.netgescon-sidebar.mobile-open {
|
|
transform: translateX(0);
|
|
}
|
|
|
|
.content-area {
|
|
margin-left: 0;
|
|
}
|
|
|
|
.mobile-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
z-index: 1000;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 **STYLING CLASSES**
|
|
|
|
### 🔧 **CSS Custom Properties**
|
|
```css
|
|
/* Sidebar Animations */
|
|
.submenu {
|
|
max-height: 0;
|
|
overflow: hidden;
|
|
transition: max-height 0.3s ease;
|
|
}
|
|
|
|
.submenu.open {
|
|
max-height: 500px;
|
|
}
|
|
|
|
/* Hover Effects */
|
|
.sidebar-link:hover {
|
|
transform: translateX(4px);
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
/* Active State */
|
|
.sidebar-link.active::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 3px;
|
|
background: var(--netgescon-primary);
|
|
}
|
|
|
|
/* Icon Spacing */
|
|
.sidebar-link i {
|
|
min-width: 20px;
|
|
margin-right: 12px;
|
|
}
|
|
|
|
/* Mobile Specific */
|
|
@media (max-width: 767px) {
|
|
.sidebar-link {
|
|
padding: 16px 20px;
|
|
font-size: 16px;
|
|
}
|
|
|
|
.submenu-link {
|
|
padding: 12px 40px;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🧪 **TESTING CHECKLIST**
|
|
|
|
### ✅ **Functional Tests**
|
|
- [ ] Submenu expand/collapse
|
|
- [ ] Active state highlighting
|
|
- [ ] Permission-based visibility
|
|
- [ ] Mobile menu toggle
|
|
- [ ] Scroll behavior
|
|
- [ ] State persistence
|
|
|
|
### ✅ **Visual Tests**
|
|
- [ ] Icon alignment
|
|
- [ ] Hover effects
|
|
- [ ] Active states styling
|
|
- [ ] Mobile responsive
|
|
- [ ] Smooth animations
|
|
|
|
### ✅ **Accessibility Tests**
|
|
- [ ] Keyboard navigation
|
|
- [ ] Screen reader compatibility
|
|
- [ ] Focus indicators
|
|
- [ ] ARIA labels
|
|
|
|
---
|
|
|
|
## 🐛 **COMMON ISSUES & FIXES**
|
|
|
|
### 🚨 **Submenu non si apre**
|
|
**Causa:** JavaScript non inizializzato o selettori errati
|
|
**Fix:** Verifica inizializzazione e selettori CSS
|
|
|
|
### 🚨 **Active state non funziona**
|
|
**Causa:** URL routing non corrispondente
|
|
**Fix:** Aggiorna logica comparazione URL
|
|
|
|
### 🚨 **Mobile overlay non scompare**
|
|
**Causa:** Event listener click non agganciato
|
|
**Fix:** Verifica function toggleMobileMenu()
|
|
|
|
### 🚨 **Permessi non funzionano**
|
|
**Causa:** Helper functions non caricate o ruoli errati
|
|
**Fix:** Verifica file permissions.blade.php e user roles
|
|
|
|
---
|
|
|
|
## 📚 **FILES CORRELATI**
|
|
|
|
### 🧩 **Templates**
|
|
- `/resources/views/components/menu/sidebar.blade.php`
|
|
- `/resources/views/components/menu/sections/` (directory)
|
|
|
|
### 🎨 **Styles**
|
|
- `/public/css/components/sidebar.css`
|
|
- `/public/css/netgescon-admin.css`
|
|
|
|
### ⚡ **JavaScript**
|
|
- `/public/js/components/sidebar.js`
|
|
- `/public/js/netgescon-admin.js`
|
|
|
|
---
|
|
|
|
## 🎯 **NEXT STEPS**
|
|
|
|
### 🔮 **Planned Improvements**
|
|
- [ ] **Sidebar Customization** - User preferences
|
|
- [ ] **Quick Search** - Search in menu items
|
|
- [ ] **Favorites** - Pin frequently used items
|
|
- [ ] **Breadcrumb Integration** - Sync with sidebar state
|
|
- [ ] **Dark Mode** - Theme switch
|
|
|
|
---
|
|
|
|
*📝 Documento mantenuto da: GitHub Copilot AI Assistant*
|
|
*🔗 Componente: Sidebar NetGescon Interface v2.1.0*
|