netgescon-day0/docs/00-MASTER-DOCS-UNIFICATI/03-MANUALI-OPERATIVI/99-TROUBLESHOOTING.md

39 KiB
Executable File

🛠️ TROUBLESHOOTING - Guida Completa NetGescon

Guida alla risoluzione problemi dell'interfaccia universale
📅 Creato: 21/07/2025
🔄 Ultimo aggiornamento: 21/07/2025
🎯 Priorità: CRITICO


📋 OVERVIEW TROUBLESHOOTING

Questa guida fornisce SOLUZIONI IMMEDIATE per:

  • 🚨 Problemi Critici - Sistema non funzionante
  • ⚠️ Problemi Comuni - Errori frequenti dell'interfaccia
  • 🔧 Procedure di Recovery - Ripristino rapido del sistema
  • 🧪 Test e Validazione - Verifiche post-risoluzione
  • 📊 Monitoring e Prevenzione - Evitare problemi futuri

🎯 Filosofia del Troubleshooting

  • Diagnosi Rapida - Identificazione immediata del problema
  • Soluzioni Incrementali - Dal più semplice al più complesso
  • Backup Safety - Sempre conservare stati funzionanti
  • Documentazione Completa - Tracciare ogni intervento

🚨 PROBLEMI CRITICI

💥 Interfaccia Completamente Rotta

🔍 Sintomi:

  • Schermata bianca/nera
  • JavaScript errors nel console
  • CSS non caricato
  • Layout completamente distorto

🚑 Soluzione Immediata:

# 1. Backup immediato dello stato attuale
cp -r /var/www/netgescon /var/www/netgescon_backup_$(date +%Y%m%d_%H%M%S)

# 2. Ripristino da backup funzionante
cp -r /var/www/netgescon_backup_working/* /var/www/netgescon/

# 3. Clear cache Laravel
cd /var/www/netgescon
php artisan cache:clear
php artisan config:clear
php artisan view:clear
php artisan route:clear

# 4. Rebuild assets
npm run build

# 5. Fix permissions
sudo chown -R www-data:www-data /var/www/netgescon
sudo chmod -R 755 /var/www/netgescon

🧪 Verifica:

# Test basic functionality
curl -I http://localhost:8000
php artisan route:list | grep admin
npm run dev --dry-run

🎨 CSS Non Caricato / Stili Mancanti

🔍 Sintomi:

  • Layout senza stili
  • Elementi sovrapposti
  • Colori di default del browser
  • Font non applicati

🚑 Soluzione Immediata:

# 1. Check if CSS files exist
ls -la /var/www/netgescon/public/css/
ls -la /var/www/netgescon/public/build/

# 2. Rebuild CSS
cd /var/www/netgescon
npm run build

# 3. Check for compilation errors
npm run dev

# 4. Force browser cache clear
# Add timestamp to CSS includes

🛠️ Soluzione Completa:

<!-- In layouts/admin.blade.php -->
@if(app()->environment('local'))
    <!-- Development mode -->
    @vite(['resources/css/app.css', 'resources/js/app.js'])
@else
    <!-- Production mode with cache busting -->
    <link rel="stylesheet" href="{{ asset('css/netgescon-admin.css') }}?v={{ filemtime(public_path('css/netgescon-admin.css')) }}">
    <script src="{{ asset('js/netgescon-admin.js') }}?v={{ filemtime(public_path('js/netgescon-admin.js')) }}"></script>
@endif

JavaScript Non Funzionante

🔍 Sintomi:

  • Sidebar non si apre/chiude
  • Form non validano
  • AJAX requests falliscono
  • Animazioni non funzionano

🚑 Debug JavaScript:

// Add to console for immediate debugging
console.log('NetGescon Debug Info:');
console.log('App initialized:', window.NetGesconApp?.initialized);
console.log('jQuery loaded:', typeof $ !== 'undefined');
console.log('Bootstrap loaded:', typeof bootstrap !== 'undefined');
console.log('Config:', window.NetGesconConfig?.all());
console.log('Permissions:', window.PermissionManager?.permissions);

// Check for JavaScript errors
window.addEventListener('error', (e) => {
    console.error('JavaScript Error:', e.error);
    // Send to monitoring if available
    if (window.Sentry) {
        window.Sentry.captureException(e.error);
    }
});

🛠️ Fix JavaScript Issues:

# 1. Check JavaScript compilation
cd /var/www/netgescon
npm run build

# 2. Check for syntax errors
npm run lint

# 3. Test individual components
node -e "console.log('Node.js working')"

# 4. Rebuild node_modules if needed
rm -rf node_modules package-lock.json
npm install
npm run build

⚠️ PROBLEMI COMUNI

📱 Sidebar Non Funziona

🔍 Sintomi:

  • Sidebar non si apre su mobile
  • Toggle button non risponde
  • Overlay non appare

🚑 Fix Rapido:

// Emergency sidebar fix
function fixSidebar() {
    const sidebar = document.getElementById('sidebar');
    const toggle = document.getElementById('mobile-nav-toggle');
    const overlay = document.getElementById('sidebar-overlay');
    
    if (!sidebar || !toggle) {
        console.error('Sidebar elements missing');
        return;
    }
    
    // Create overlay if missing
    if (!overlay) {
        const newOverlay = document.createElement('div');
        newOverlay.id = 'sidebar-overlay';
        newOverlay.className = 'sidebar-overlay';
        document.body.appendChild(newOverlay);
    }
    
    // Fix event listeners
    toggle.addEventListener('click', () => {
        sidebar.classList.toggle('show');
        document.getElementById('sidebar-overlay').classList.toggle('show');
    });
    
    document.getElementById('sidebar-overlay').addEventListener('click', () => {
        sidebar.classList.remove('show');
        document.getElementById('sidebar-overlay').classList.remove('show');
    });
}

// Run fix
fixSidebar();

📊 Tabelle Non Responsive

🔍 Sintomi:

  • Tabelle escono dal container
  • Scroll orizzontale problematico
  • Mobile view non funziona

🚑 Fix Tabelle:

// Emergency table fix
function fixTables() {
    const tables = document.querySelectorAll('.table-responsive-mobile');
    
    tables.forEach(container => {
        const table = container.querySelector('table');
        if (!table) return;
        
        // Add horizontal scroll indicator
        if (!container.querySelector('.scroll-indicator')) {
            const indicator = document.createElement('div');
            indicator.className = 'scroll-indicator';
            indicator.innerHTML = '<i class="fas fa-arrow-right"></i> Scorri per vedere più colonne';
            indicator.style.cssText = `
                position: absolute;
                top: 50%;
                right: 10px;
                background: rgba(0,0,0,0.7);
                color: white;
                padding: 5px 10px;
                border-radius: 15px;
                font-size: 12px;
                pointer-events: none;
                z-index: 10;
            `;
            container.style.position = 'relative';
            container.appendChild(indicator);
            
            // Hide on scroll
            container.addEventListener('scroll', () => {
                const isScrolledToEnd = container.scrollLeft >= (container.scrollWidth - container.clientWidth - 10);
                indicator.style.opacity = isScrolledToEnd ? '0' : '1';
            });
        }
        
        // Mobile stack view for very small screens
        if (window.innerWidth <= 576 && !container.querySelector('.mobile-table-stack')) {
            createMobileTableStack(container, table);
        }
    });
}

function createMobileTableStack(container, table) {
    const mobileStack = document.createElement('div');
    mobileStack.className = 'mobile-table-stack';
    mobileStack.style.display = window.innerWidth <= 576 ? 'block' : 'none';
    
    const headers = Array.from(table.querySelectorAll('thead th')).map(th => th.textContent.trim());
    const rows = table.querySelectorAll('tbody tr');
    
    rows.forEach(row => {
        const cells = row.querySelectorAll('td');
        const mobileItem = document.createElement('div');
        mobileItem.className = 'mobile-table-item';
        mobileItem.style.cssText = `
            background: white;
            border: 1px solid #e2e8f0;
            border-radius: 8px;
            padding: 1rem;
            margin-bottom: 1rem;
        `;
        
        cells.forEach((cell, index) => {
            const itemRow = document.createElement('div');
            itemRow.style.cssText = `
                display: flex;
                justify-content: space-between;
                padding: 0.25rem 0;
                border-bottom: 1px solid #f1f5f9;
            `;
            
            const label = document.createElement('div');
            label.style.cssText = `
                font-weight: 500;
                color: #64748b;
                font-size: 0.875rem;
            `;
            label.textContent = headers[index] || `Campo ${index + 1}`;
            
            const value = document.createElement('div');
            value.style.cssText = `
                color: #0f172a;
                text-align: right;
            `;
            value.innerHTML = cell.innerHTML;
            
            itemRow.appendChild(label);
            itemRow.appendChild(value);
            mobileItem.appendChild(itemRow);
        });
        
        mobileStack.appendChild(mobileItem);
    });
    
    container.appendChild(mobileStack);
    
    // Hide original table on mobile
    table.style.display = window.innerWidth <= 576 ? 'none' : 'table';
}

// Run fix
fixTables();

🔐 Permessi Non Funzionano

🔍 Sintomi:

  • Elementi visibili che non dovrebbero esserlo
  • Azioni bloccate quando dovrebbero essere permesse
  • Errori 403 inaspettati

🚑 Debug Permessi:

// Permission debugging tool
function debugPermissions() {
    console.log('=== PERMISSION DEBUG ===');
    
    // Check user data
    const user = window.PermissionManager?.user;
    console.log('User:', user);
    console.log('Role:', user?.role);
    
    // Check permissions
    const permissions = window.PermissionManager?.permissions;
    console.log('Permissions:', permissions);
    
    // Test common permissions
    const testResources = ['stabili', 'condomini', 'unita', 'reports', 'users'];
    const testActions = ['read', 'create', 'update', 'delete'];
    
    testResources.forEach(resource => {
        console.log(`\n--- ${resource.toUpperCase()} ---`);
        testActions.forEach(action => {
            const hasPermission = window.PermissionManager?.can(resource, action);
            console.log(`${action}: ${hasPermission ? '✅' : '❌'}`);
        });
    });
    
    // Check problematic elements
    const permissionElements = document.querySelectorAll('[data-permission], [data-role]');
    console.log(`\nFound ${permissionElements.length} permission-controlled elements`);
    
    permissionElements.forEach((el, index) => {
        const permission = el.dataset.permission;
        const role = el.dataset.role;
        const action = el.dataset.action || 'read';
        const visible = el.style.display !== 'none' && !el.hasAttribute('aria-hidden');
        
        console.log(`Element ${index + 1}:`, {
            tag: el.tagName,
            permission,
            role,
            action,
            visible,
            shouldBeVisible: permission ? window.PermissionManager?.can(permission, action) : true
        });
    });
}

// Run debug
debugPermissions();

🛠️ Fix Permessi:

// Add to routes/web.php for emergency permission reset
Route::get('/debug/permissions/{user}', function($userId) {
    if (!auth()->user()->hasRole('super_admin')) {
        abort(403);
    }
    
    $user = User::findOrFail($userId);
    
    return response()->json([
        'user' => $user,
        'role' => $user->getRole(),
        'permissions' => $user->permissions,
        'default_level' => $user->getDefaultPermissionLevel(),
        'test_permissions' => [
            'stabili' => [
                'read' => $user->getPermissionLevel('stabili'),
                'create' => $user->getPermissionLevel('stabili'),
                'update' => $user->getPermissionLevel('stabili'),
                'delete' => $user->getPermissionLevel('stabili'),
            ]
        ]
    ]);
})->middleware(['auth', 'role:super_admin']);

📱 Problemi Mobile

🔍 Sintomi:

  • Layout rotto su mobile
  • Touch non funziona
  • Font troppo piccoli
  • Elementi non accessibili

🚑 Fix Mobile:

/* Emergency mobile fixes */
@media (max-width: 767px) {
    /* Ensure minimum touch targets */
    .btn, .nav-link, .form-input, .form-select {
        min-height: 44px !important;
        min-width: 44px !important;
    }
    
    /* Fix font sizes to prevent zoom */
    input, select, textarea {
        font-size: 16px !important;
    }
    
    /* Fix overlapping elements */
    .netgescon-content {
        padding: 1rem !important;
        margin-top: 60px !important;
    }
    
    /* Fix sidebar on mobile */
    .netgescon-sidebar {
        position: fixed !important;
        top: 60px !important;
        left: -280px !important;
        width: 280px !important;
        height: calc(100vh - 60px) !important;
        z-index: 999 !important;
        transition: left 0.3s ease !important;
    }
    
    .netgescon-sidebar.show {
        left: 0 !important;
    }
    
    /* Fix tables */
    .table-responsive-mobile {
        overflow-x: auto !important;
        -webkit-overflow-scrolling: touch !important;
    }
    
    /* Fix cards */
    .netgescon-card {
        margin-bottom: 1rem !important;
        padding: 1rem !important;
    }
    
    /* Fix buttons */
    .btn-group {
        flex-direction: column !important;
        width: 100% !important;
    }
    
    .btn-group .btn {
        width: 100% !important;
        margin-bottom: 0.5rem !important;
    }
}

🔧 PROCEDURE DI RECOVERY

💾 Backup e Restore

📁 Backup Completo:

#!/bin/bash
# create-backup.sh

DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/var/backups/netgescon"
SOURCE_DIR="/var/www/netgescon"

# Create backup directory
mkdir -p $BACKUP_DIR

# Backup files
echo "Backing up files..."
tar -czf "$BACKUP_DIR/netgescon_files_$DATE.tar.gz" -C "$SOURCE_DIR" .

# Backup database
echo "Backing up database..."
mysqldump -u root -p netgescon > "$BACKUP_DIR/netgescon_db_$DATE.sql"

# Backup config files
echo "Backing up configs..."
cp /etc/nginx/sites-available/netgescon "$BACKUP_DIR/nginx_config_$DATE"
cp /etc/php/8.2/fpm/pool.d/netgescon.conf "$BACKUP_DIR/php_config_$DATE"

# Create restore script
cat > "$BACKUP_DIR/restore_$DATE.sh" << EOF
#!/bin/bash
echo "Restoring NetGescon from backup $DATE..."

# Stop services
sudo systemctl stop nginx php8.2-fpm

# Restore files
sudo rm -rf /var/www/netgescon/*
sudo tar -xzf "$BACKUP_DIR/netgescon_files_$DATE.tar.gz" -C /var/www/netgescon/

# Restore database
mysql -u root -p netgescon < "$BACKUP_DIR/netgescon_db_$DATE.sql"

# Fix permissions
sudo chown -R www-data:www-data /var/www/netgescon
sudo chmod -R 755 /var/www/netgescon
sudo chmod -R 775 /var/www/netgescon/storage
sudo chmod -R 775 /var/www/netgescon/bootstrap/cache

# Restart services
sudo systemctl start php8.2-fpm nginx

echo "Restore completed!"
EOF

chmod +x "$BACKUP_DIR/restore_$DATE.sh"

echo "Backup completed: $BACKUP_DIR"
echo "To restore: sudo bash $BACKUP_DIR/restore_$DATE.sh"

🔄 Restore da Backup:

#!/bin/bash
# quick-restore.sh

# Find latest backup
LATEST_BACKUP=$(ls -t /var/backups/netgescon/netgescon_files_*.tar.gz | head -1)
LATEST_DB=$(ls -t /var/backups/netgescon/netgescon_db_*.sql | head -1)

if [ -z "$LATEST_BACKUP" ]; then
    echo "❌ No backup found!"
    exit 1
fi

echo "🔄 Restoring from: $LATEST_BACKUP"

# Backup current state first
cp -r /var/www/netgescon "/var/www/netgescon_before_restore_$(date +%Y%m%d_%H%M%S)"

# Stop services
sudo systemctl stop nginx php8.2-fpm

# Restore files
sudo rm -rf /var/www/netgescon/*
sudo tar -xzf "$LATEST_BACKUP" -C /var/www/netgescon/

# Restore database if available
if [ -n "$LATEST_DB" ]; then
    echo "🗄️ Restoring database..."
    mysql -u root -p netgescon < "$LATEST_DB"
fi

# Clear all caches
cd /var/www/netgescon
php artisan cache:clear
php artisan config:clear
php artisan view:clear
php artisan route:clear

# Fix permissions
sudo chown -R www-data:www-data /var/www/netgescon
sudo chmod -R 755 /var/www/netgescon
sudo chmod -R 775 /var/www/netgescon/storage
sudo chmod -R 775 /var/www/netgescon/bootstrap/cache

# Restart services
sudo systemctl start php8.2-fpm nginx

echo "✅ Restore completed!"
echo "🧪 Test the application: http://localhost:8000"

🔧 Reset Completo Sistema

🚨 Reset Interfaccia (EMERGENCY):

#!/bin/bash
# emergency-reset.sh

echo "🚨 EMERGENCY RESET - This will reset the interface to default state"
read -p "Are you sure? (type 'RESET' to confirm): " confirm

if [ "$confirm" != "RESET" ]; then
    echo "❌ Reset cancelled"
    exit 1
fi

# 1. Backup current state
BACKUP_DIR="/tmp/emergency_backup_$(date +%Y%m%d_%H%M%S)"
cp -r /var/www/netgescon "$BACKUP_DIR"
echo "📁 Current state backed up to: $BACKUP_DIR"

# 2. Reset to clean Laravel installation
cd /var/www/netgescon

# Clear all caches
php artisan cache:clear
php artisan config:clear
php artisan view:clear
php artisan route:clear
php artisan storage:link

# Reset config files
cp .env.example .env
php artisan key:generate

# 3. Reset database (if needed)
read -p "Reset database too? (y/N): " reset_db
if [ "$reset_db" = "y" ] || [ "$reset_db" = "Y" ]; then
    php artisan migrate:fresh --seed
fi

# 4. Rebuild assets
npm install
npm run build

# 5. Fix permissions
sudo chown -R www-data:www-data /var/www/netgescon
sudo chmod -R 755 /var/www/netgescon
sudo chmod -R 775 /var/www/netgescon/storage
sudo chmod -R 775 /var/www/netgescon/bootstrap/cache

# 6. Restart services
sudo systemctl restart nginx php8.2-fpm

echo "✅ Emergency reset completed!"
echo "🔧 Configure your .env file and test the application"
echo "📁 Previous state backed up to: $BACKUP_DIR"

🧪 TEST E VALIDAZIONE

Test Rapidi Post-Fix

#!/bin/bash
# quick-tests.sh

echo "🧪 Running Quick Validation Tests..."

# 1. Test web server
echo "📡 Testing web server..."
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8000)
if [ "$HTTP_CODE" = "200" ]; then
    echo "✅ Web server responding"
else
    echo "❌ Web server not responding (HTTP $HTTP_CODE)"
fi

# 2. Test database connection
echo "🗄️ Testing database..."
cd /var/www/netgescon
if php artisan tinker --execute="DB::connection()->getPdo(); echo 'DB Connected';" 2>/dev/null | grep -q "DB Connected"; then
    echo "✅ Database connection working"
else
    echo "❌ Database connection failed"
fi

# 3. Test assets
echo "🎨 Testing assets..."
if [ -f "public/css/netgescon-admin.css" ] && [ -f "public/js/netgescon-admin.js" ]; then
    echo "✅ Assets compiled"
else
    echo "❌ Assets missing"
fi

# 4. Test permissions
echo "🔐 Testing file permissions..."
if [ -w "storage/logs" ] && [ -w "bootstrap/cache" ]; then
    echo "✅ File permissions correct"
else
    echo "❌ File permissions incorrect"
fi

# 5. Test critical routes
echo "🛣️ Testing critical routes..."
ROUTES=$(php artisan route:list --compact | grep -E "(admin|login|dashboard)" | wc -l)
if [ "$ROUTES" -gt "0" ]; then
    echo "✅ Routes registered ($ROUTES found)"
else
    echo "❌ No routes found"
fi

echo "🏁 Quick tests completed!"

🔍 Test Completi Interfaccia

// Complete interface test suite
class InterfaceTests {
    constructor() {
        this.results = [];
        this.runTests();
    }
    
    async runTests() {
        console.log('🧪 Running Complete Interface Tests...');
        
        const tests = [
            () => this.testPageLoad(),
            () => this.testCSS(),
            () => this.testJavaScript(),
            () => this.testSidebar(),
            () => this.testResponsive(),
            () => this.testForms(),
            () => this.testTables(),
            () => this.testPermissions(),
            () => this.testAccessibility(),
            () => this.testPerformance()
        ];
        
        for (const test of tests) {
            try {
                const result = await test();
                this.results.push(result);
                this.logResult(result);
            } catch (error) {
                const result = { name: test.name, passed: false, error: error.message };
                this.results.push(result);
                this.logResult(result);
            }
        }
        
        this.generateReport();
    }
    
    testPageLoad() {
        const start = performance.now();
        const loaded = document.readyState === 'complete';
        const loadTime = performance.now() - start;
        
        return {
            name: 'Page Load',
            passed: loaded && loadTime < 3000,
            details: { loaded, loadTime: `${loadTime.toFixed(2)}ms` }
        };
    }
    
    testCSS() {
        const stylesheets = document.querySelectorAll('link[rel="stylesheet"]');
        const hasNetGesconCSS = Array.from(stylesheets).some(link => 
            link.href.includes('netgescon-admin.css')
        );
        
        // Test if critical styles are applied
        const body = document.body;
        const computedStyle = getComputedStyle(body);
        const hasStyles = computedStyle.fontFamily !== 'serif'; // Default would be serif
        
        return {
            name: 'CSS Loading',
            passed: hasNetGesconCSS && hasStyles,
            details: { 
                stylesheets: stylesheets.length,
                hasNetGesconCSS,
                hasStyles,
                fontFamily: computedStyle.fontFamily
            }
        };
    }
    
    testJavaScript() {
        const hasNetGesconApp = typeof window.NetGesconApp !== 'undefined';
        const hasPermissionManager = typeof window.PermissionManager !== 'undefined';
        const hasBootstrap = typeof window.bootstrap !== 'undefined';
        
        return {
            name: 'JavaScript Loading',
            passed: hasNetGesconApp && hasPermissionManager && hasBootstrap,
            details: { hasNetGesconApp, hasPermissionManager, hasBootstrap }
        };
    }
    
    testSidebar() {
        const sidebar = document.getElementById('sidebar');
        const toggle = document.getElementById('mobile-nav-toggle');
        
        if (!sidebar) {
            return { name: 'Sidebar', passed: false, details: { missing: 'sidebar element' } };
        }
        
        // Test toggle functionality
        const originalClass = sidebar.className;
        sidebar.classList.add('show');
        const canToggle = sidebar.classList.contains('show');
        sidebar.className = originalClass;
        
        return {
            name: 'Sidebar',
            passed: canToggle && (window.innerWidth >= 768 || toggle),
            details: { 
                hasSidebar: !!sidebar,
                hasToggle: !!toggle,
                canToggle
            }
        };
    }
    
    testResponsive() {
        const viewport = window.innerWidth;
        const isMobile = viewport < 768;
        const isTablet = viewport >= 768 && viewport < 1024;
        const isDesktop = viewport >= 1024;
        
        // Test grid systems
        const grids = document.querySelectorAll('.grid, .netgescon-grid, .stats-grid');
        const hasGrids = grids.length > 0;
        
        return {
            name: 'Responsive',
            passed: hasGrids,
            details: { 
                viewport,
                isMobile,
                isTablet,
                isDesktop,
                grids: grids.length
            }
        };
    }
    
    testForms() {
        const forms = document.querySelectorAll('form');
        const inputs = document.querySelectorAll('input, select, textarea');
        
        // Test form validation classes
        const hasValidationClasses = Array.from(inputs).some(input => 
            input.classList.contains('form-input') || 
            input.classList.contains('form-control')
        );
        
        return {
            name: 'Forms',
            passed: forms.length > 0 && hasValidationClasses,
            details: { 
                forms: forms.length,
                inputs: inputs.length,
                hasValidationClasses
            }
        };
    }
    
    testTables() {
        const tables = document.querySelectorAll('table');
        const responsiveTables = document.querySelectorAll('.table-responsive, .table-responsive-mobile');
        
        return {
            name: 'Tables',
            passed: tables.length === 0 || responsiveTables.length > 0,
            details: { 
                tables: tables.length,
                responsiveTables: responsiveTables.length
            }
        };
    }
    
    testPermissions() {
        const permissionElements = document.querySelectorAll('[data-permission], [data-role]');
        const hasPermissionManager = typeof window.PermissionManager !== 'undefined';
        
        return {
            name: 'Permissions',
            passed: hasPermissionManager,
            details: { 
                permissionElements: permissionElements.length,
                hasPermissionManager
            }
        };
    }
    
    testAccessibility() {
        // Test for basic accessibility features
        const images = document.querySelectorAll('img');
        const imagesWithAlt = Array.from(images).filter(img => img.hasAttribute('alt'));
        
        const buttons = document.querySelectorAll('button');
        const buttonsWithAriaLabel = Array.from(buttons).filter(btn => 
            btn.hasAttribute('aria-label') || btn.textContent.trim()
        );
        
        const altRatio = images.length ? imagesWithAlt.length / images.length : 1;
        const buttonRatio = buttons.length ? buttonsWithAriaLabel.length / buttons.length : 1;
        
        return {
            name: 'Accessibility',
            passed: altRatio >= 0.8 && buttonRatio >= 0.8,
            details: { 
                altRatio: `${(altRatio * 100).toFixed(1)}%`,
                buttonRatio: `${(buttonRatio * 100).toFixed(1)}%`
            }
        };
    }
    
    testPerformance() {
        const navigation = performance.getEntriesByType('navigation')[0];
        const loadTime = navigation ? navigation.loadEventEnd - navigation.fetchStart : 0;
        
        const resources = performance.getEntriesByType('resource');
        const slowResources = resources.filter(r => r.duration > 1000);
        
        return {
            name: 'Performance',
            passed: loadTime < 5000 && slowResources.length < 3,
            details: { 
                loadTime: `${loadTime.toFixed(2)}ms`,
                totalResources: resources.length,
                slowResources: slowResources.length
            }
        };
    }
    
    logResult(result) {
        const status = result.passed ? '✅' : '❌';
        console.log(`${status} ${result.name}:`, result.details);
        
        if (result.error) {
            console.error(`  Error: ${result.error}`);
        }
    }
    
    generateReport() {
        const passed = this.results.filter(r => r.passed).length;
        const total = this.results.length;
        const passRate = (passed / total * 100).toFixed(1);
        
        console.log('\n📊 Test Summary:');
        console.log(`Pass Rate: ${passRate}% (${passed}/${total})`);
        
        const failed = this.results.filter(r => !r.passed);
        if (failed.length > 0) {
            console.log('\n❌ Failed Tests:');
            failed.forEach(test => {
                console.log(`  - ${test.name}: ${test.error || 'Failed validation'}`);
            });
        }
        
        // Store results for later analysis
        window.InterfaceTestResults = {
            timestamp: new Date().toISOString(),
            passRate,
            results: this.results
        };
    }
}

// Run tests automatically in debug mode
if (window.location.search.includes('test=interface')) {
    document.addEventListener('DOMContentLoaded', () => {
        setTimeout(() => new InterfaceTests(), 2000);
    });
}

📊 MONITORING E PREVENZIONE

📈 Sistema di Monitoring

// /public/js/monitoring/health-check.js

class HealthMonitor {
    constructor() {
        this.checks = new Map();
        this.alerts = [];
        this.interval = 30000; // 30 seconds
        this.init();
    }
    
    init() {
        this.setupChecks();
        this.startMonitoring();
        this.setupErrorReporting();
    }
    
    setupChecks() {
        // Add health checks
        this.addCheck('javascript', () => this.checkJavaScript());
        this.addCheck('css', () => this.checkCSS());
        this.addCheck('api', () => this.checkAPI());
        this.addCheck('permissions', () => this.checkPermissions());
        this.addCheck('performance', () => this.checkPerformance());
    }
    
    addCheck(name, checkFn) {
        this.checks.set(name, {
            name,
            check: checkFn,
            lastRun: null,
            lastResult: null,
            consecutiveFailures: 0
        });
    }
    
    async startMonitoring() {
        setInterval(async () => {
            await this.runAllChecks();
        }, this.interval);
        
        // Run initial checks
        await this.runAllChecks();
    }
    
    async runAllChecks() {
        for (const [name, checkData] of this.checks) {
            try {
                const result = await checkData.check();
                this.handleCheckResult(name, result);
            } catch (error) {
                this.handleCheckResult(name, { 
                    healthy: false, 
                    error: error.message 
                });
            }
        }
    }
    
    handleCheckResult(name, result) {
        const checkData = this.checks.get(name);
        checkData.lastRun = Date.now();
        checkData.lastResult = result;
        
        if (result.healthy) {
            checkData.consecutiveFailures = 0;
        } else {
            checkData.consecutiveFailures++;
            
            // Alert after 3 consecutive failures
            if (checkData.consecutiveFailures >= 3) {
                this.createAlert(name, result);
            }
        }
    }
    
    createAlert(checkName, result) {
        const alert = {
            id: Date.now(),
            timestamp: new Date().toISOString(),
            check: checkName,
            message: result.error || `Health check ${checkName} failed`,
            severity: result.severity || 'warning',
            data: result
        };
        
        this.alerts.push(alert);
        this.notifyAlert(alert);
        
        // Keep only last 100 alerts
        if (this.alerts.length > 100) {
            this.alerts = this.alerts.slice(-100);
        }
    }
    
    notifyAlert(alert) {
        console.warn(`🚨 Health Alert [${alert.check}]:`, alert.message);
        
        // Send to external monitoring if available
        if (window.Sentry) {
            window.Sentry.captureMessage(alert.message, alert.severity);
        }
        
        // Show user notification for critical alerts
        if (alert.severity === 'critical' && window.NetGesconNotifications) {
            NetGesconNotifications.error(
                `Sistema: ${alert.message}`,
                { duration: 10000 }
            );
        }
    }
    
    // Health check functions
    checkJavaScript() {
        const errors = [];
        
        // Check core objects
        if (typeof window.NetGesconApp === 'undefined') {
            errors.push('NetGesconApp not loaded');
        }
        
        if (typeof window.PermissionManager === 'undefined') {
            errors.push('PermissionManager not loaded');
        }
        
        if (typeof window.bootstrap === 'undefined') {
            errors.push('Bootstrap not loaded');
        }
        
        return {
            healthy: errors.length === 0,
            errors,
            severity: errors.length > 0 ? 'critical' : 'info'
        };
    }
    
    checkCSS() {
        const stylesheets = document.querySelectorAll('link[rel="stylesheet"]');
        const netgesconCSS = Array.from(stylesheets).find(link => 
            link.href.includes('netgescon-admin.css')
        );
        
        if (!netgesconCSS) {
            return { 
                healthy: false, 
                error: 'NetGescon CSS not found',
                severity: 'critical'
            };
        }
        
        // Check if styles are actually applied
        const testElement = document.createElement('div');
        testElement.className = 'netgescon-card';
        testElement.style.position = 'absolute';
        testElement.style.visibility = 'hidden';
        document.body.appendChild(testElement);
        
        const styles = getComputedStyle(testElement);
        const hasStyles = styles.borderRadius && styles.borderRadius !== '0px';
        
        document.body.removeChild(testElement);
        
        return {
            healthy: hasStyles,
            error: hasStyles ? null : 'CSS styles not applied',
            severity: hasStyles ? 'info' : 'warning'
        };
    }
    
    async checkAPI() {
        try {
            const response = await fetch('/api/health');
            return {
                healthy: response.ok,
                status: response.status,
                severity: response.ok ? 'info' : 'critical'
            };
        } catch (error) {
            return {
                healthy: false,
                error: 'API not reachable',
                severity: 'critical'
            };
        }
    }
    
    checkPermissions() {
        const hasManager = typeof window.PermissionManager !== 'undefined';
        const hasPermissions = window.PermissionManager?.permissions;
        
        return {
            healthy: hasManager && hasPermissions,
            error: !hasManager ? 'Permission manager not loaded' : 
                   !hasPermissions ? 'Permissions not loaded' : null,
            severity: 'warning'
        };
    }
    
    checkPerformance() {
        const navigation = performance.getEntriesByType('navigation')[0];
        if (!navigation) {
            return { healthy: true, error: 'Performance data not available' };
        }
        
        const loadTime = navigation.loadEventEnd - navigation.fetchStart;
        const healthy = loadTime < 5000; // 5 seconds threshold
        
        return {
            healthy,
            loadTime,
            error: healthy ? null : `Page load time too slow: ${loadTime}ms`,
            severity: healthy ? 'info' : 'warning'
        };
    }
    
    setupErrorReporting() {
        // Global error handler
        window.addEventListener('error', (e) => {
            this.createAlert('javascript_error', {
                healthy: false,
                error: `${e.error?.message || e.message} at ${e.filename}:${e.lineno}`,
                severity: 'warning',
                stack: e.error?.stack
            });
        });
        
        // Unhandled promise rejection handler
        window.addEventListener('unhandledrejection', (e) => {
            this.createAlert('promise_rejection', {
                healthy: false,
                error: `Unhandled promise rejection: ${e.reason}`,
                severity: 'warning'
            });
        });
    }
    
    // Public methods for debugging
    getHealthStatus() {
        const status = {};
        for (const [name, checkData] of this.checks) {
            status[name] = {
                healthy: checkData.lastResult?.healthy,
                lastRun: checkData.lastRun ? new Date(checkData.lastRun).toISOString() : null,
                consecutiveFailures: checkData.consecutiveFailures,
                error: checkData.lastResult?.error
            };
        }
        return status;
    }
    
    getAlerts(severity = null) {
        return severity ? 
            this.alerts.filter(a => a.severity === severity) : 
            this.alerts;
    }
    
    forceCheck(checkName) {
        const checkData = this.checks.get(checkName);
        if (checkData) {
            return checkData.check();
        }
        throw new Error(`Check '${checkName}' not found`);
    }
}

// Initialize health monitor
document.addEventListener('DOMContentLoaded', () => {
    if (NetGesconConfig?.get('app.debug') || window.location.search.includes('monitor=true')) {
        window.HealthMonitor = new HealthMonitor();
        console.log('🏥 Health Monitor started');
    }
});

📚 QUICK REFERENCE

🚨 Emergency Commands

# Complete system restart
sudo systemctl restart nginx php8.2-fpm mysql

# Clear all Laravel caches
php artisan cache:clear && php artisan config:clear && php artisan view:clear && php artisan route:clear

# Rebuild assets
npm run build

# Fix permissions
sudo chown -R www-data:www-data /var/www/netgescon
sudo chmod -R 755 /var/www/netgescon
sudo chmod -R 775 /var/www/netgescon/storage /var/www/netgescon/bootstrap/cache

# Emergency backup
cp -r /var/www/netgescon "/var/backups/netgescon_emergency_$(date +%Y%m%d_%H%M%S)"

🔍 Debug URLs

# Interface tests
http://localhost:8000/?test=interface

# Health monitoring
http://localhost:8000/?monitor=true

# Permission debug
http://localhost:8000/debug/permissions/{user_id}

# Laravel debug info
http://localhost:8000/?debug=true

📞 Emergency JavaScript

// Emergency fixes you can run in browser console

// Fix sidebar
document.getElementById('mobile-nav-toggle')?.addEventListener('click', () => {
    document.getElementById('sidebar')?.classList.toggle('show');
});

// Force permission refresh
window.PermissionManager?.refreshPermissions();

// Clear local storage
localStorage.clear();

// Reload CSS
document.querySelectorAll('link[rel="stylesheet"]').forEach(link => {
    link.href = link.href + '?v=' + Date.now();
});

// Emergency user info
console.log('User:', window.NetGesconApp?.user);
console.log('Permissions:', window.PermissionManager?.permissions);
console.log('Config:', window.NetGesconConfig?.all());

📞 CONTATTI DI EMERGENZA

🛠️ Escalation Path

  1. Self-Service - Questa guida e procedure automatiche
  2. Developer - GitHub Copilot documentation
  3. System Admin - Server e infrastructure issues
  4. Database Admin - Data corruption o performance issues

📋 Incident Report Template

INCIDENT REPORT - NetGescon Interface
=====================================

Timestamp: [DATE TIME]
Severity: [CRITICAL/HIGH/MEDIUM/LOW]
Affected Users: [NUMBER/ALL/SPECIFIC]

PROBLEM DESCRIPTION:
- What happened?
- When did it start?
- What is the impact?

SYMPTOMS:
- Browser errors?
- UI not loading?
- Functionality broken?

ENVIRONMENT:
- URL: [URL]
- Browser: [BROWSER VERSION]
- Screen size: [RESOLUTION]
- User role: [ROLE]

ATTEMPTED FIXES:
- [ ] Cleared browser cache
- [ ] Tried different browser
- [ ] Checked console errors
- [ ] Ran quick tests
- [ ] Applied emergency fixes

RESOLUTION:
[What fixed the issue]

PREVENTION:
[How to prevent this in future]

📝 Documento mantenuto da: GitHub Copilot AI Assistant
🔗 Componente: Troubleshooting Guide NetGescon Interface v2.1.0
📞 Per supporto immediato: Consulta questa guida → Test automatici → Escalation