netgescon-day0/docs/00-MASTER-DOCS-UNIFICATI/03-MANUALI-OPERATIVI/04-FOOTER.md

684 lines
18 KiB
Markdown
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🦶 FOOTER - Documentazione Completa NetGescon
> **Componente Footer dell'interfaccia universale**
> **📅 Creato:** 21/07/2025
> **🔄 Ultimo aggiornamento:** 21/07/2025
> **🎯 Priorità:** 🔥 CRITICA
---
## 📋 **OVERVIEW FOOTER**
Il Footer NetGescon è il componente **FIXED BOTTOM** che contiene:
- 📊 **Progress Bar Sistema**
- **Info Applicazione**
- 👤 **User Status Quick**
- 🕐 **Sistema Timestamp**
- 📡 **Connection Status**
- 🔄 **Auto-refresh Indicator**
### 📐 **Specifiche Layout**
- **Altezza:** `70px` fisso
- **Posizione:** `fixed bottom-0` sempre visibile
- **Z-index:** `999` sopra content ma sotto header
- **Background:** Sfumatura grigio scuro NetGescon
---
## 🎨 **DESIGN SPECIFICATIONS**
### 🌈 **Color Palette**
```css
/* Footer Background */
.netgescon-footer {
background: linear-gradient(135deg,
var(--netgescon-gray-800) 0%,
var(--netgescon-gray-900) 100%
);
border-top: 1px solid var(--netgescon-gray-700);
color: var(--netgescon-gray-300);
}
/* Progress Bar */
.footer-progress {
background: var(--netgescon-primary);
height: 3px;
transition: width 0.3s ease;
}
/* Status Indicators */
.status-online { color: var(--netgescon-success); }
.status-offline { color: var(--netgescon-danger); }
.status-warning { color: var(--netgescon-warning); }
```
### 📏 **Dimensions**
```css
.netgescon-footer {
height: 70px;
padding: 0 1.5rem;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 999;
display: flex;
align-items: center;
justify-content: space-between;
}
```
---
## 🧩 **STRUTTURA FOOTER**
### 📁 **File:** `components/menu/sections/footer.blade.php`
```blade
<footer class="netgescon-footer">
<!-- Progress Bar (top edge) -->
<div class="footer-progress-container absolute top-0 left-0 right-0 h-1 bg-gray-700">
<div id="footer-progress" class="footer-progress h-full w-0"></div>
</div>
<div class="footer-content flex items-center justify-between w-full">
<!-- Left Section - App Info -->
<div class="footer-left flex items-center space-x-6">
<!-- App Version -->
<div class="app-info flex items-center space-x-2 text-sm">
<i class="fas fa-code text-blue-400"></i>
<span class="text-gray-300">NetGescon</span>
<span class="text-blue-400 font-medium">v2.1.0</span>
</div>
<!-- Connection Status -->
<div class="connection-status flex items-center space-x-2 text-sm">
<i id="connection-icon" class="fas fa-wifi status-online"></i>
<span id="connection-text" class="text-gray-300">Online</span>
</div>
<!-- System Status -->
<div class="system-status flex items-center space-x-2 text-sm">
<i id="system-icon" class="fas fa-server text-green-400"></i>
<span id="system-text" class="text-gray-300">Sistema OK</span>
</div>
</div>
<!-- Center Section - Quick Actions (Desktop Only) -->
<div class="footer-center hidden lg:flex items-center space-x-4">
<!-- Auto-refresh -->
<div class="auto-refresh flex items-center space-x-2 text-sm">
<button id="auto-refresh-toggle"
class="flex items-center space-x-1 text-gray-400 hover:text-gray-200 transition-colors"
onclick="toggleAutoRefresh()">
<i id="refresh-icon" class="fas fa-sync-alt"></i>
<span>Auto-refresh</span>
</button>
<span id="refresh-timer" class="text-xs text-gray-500">30s</span>
</div>
<!-- Quick Stats -->
<div class="quick-stats flex items-center space-x-4 text-xs text-gray-400">
<span>CPU: <span id="cpu-usage" class="text-green-400">12%</span></span>
<span>Mem: <span id="mem-usage" class="text-blue-400">45%</span></span>
<span>Users: <span id="active-users" class="text-yellow-400">8</span></span>
</div>
</div>
<!-- Right Section - User & Time -->
<div class="footer-right flex items-center space-x-6">
<!-- Current User -->
<div class="current-user flex items-center space-x-2 text-sm">
<img src="{{ auth()->user()->avatar ?? asset('images/avatar-default.svg') }}"
alt="User" class="w-6 h-6 rounded-full border border-gray-600">
<span class="text-gray-300 hidden sm:block">{{ auth()->user()->name }}</span>
<span class="text-xs text-gray-500 hidden md:block">({{ auth()->user()->role }})</span>
</div>
<!-- Current Date/Time -->
<div class="datetime flex items-center space-x-2 text-sm">
<i class="fas fa-clock text-gray-400"></i>
<div class="flex flex-col items-end">
<span id="current-time" class="text-gray-300 font-medium">--:--</span>
<span id="current-date" class="text-xs text-gray-500 hidden lg:block">-- --- ----</span>
</div>
</div>
<!-- Session Timer -->
<div class="session-timer flex items-center space-x-1 text-xs text-gray-500">
<i class="fas fa-hourglass-half"></i>
<span id="session-time">0h 0m</span>
</div>
</div>
</div>
</footer>
```
---
## ⚡ **JAVASCRIPT FUNCTIONALITY**
### 📁 **File:** `/public/js/components/footer.js`
```javascript
/**
* Footer NetGescon - JavaScript Functions
*/
let autoRefreshInterval;
let autoRefreshEnabled = false;
let autoRefreshCountdown = 30;
let sessionStartTime = new Date();
// Inizializza footer
function initializeFooter() {
updateDateTime();
updateSessionTimer();
monitorConnection();
initializeSystemStatus();
initializeProgressBar();
// Update ogni secondo
setInterval(() => {
updateDateTime();
updateSessionTimer();
updateAutoRefreshTimer();
}, 1000);
// System stats ogni 30 secondi
setInterval(() => {
updateSystemStats();
}, 30000);
}
// Date/Time updates
function updateDateTime() {
const now = new Date();
// Time
const timeString = now.toLocaleTimeString('it-IT', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
document.getElementById('current-time').textContent = timeString;
// Date (desktop only)
const dateString = now.toLocaleDateString('it-IT', {
weekday: 'short',
day: '2-digit',
month: 'short',
year: 'numeric'
});
const dateEl = document.getElementById('current-date');
if (dateEl) dateEl.textContent = dateString;
}
// Session timer
function updateSessionTimer() {
const now = new Date();
const diff = now - sessionStartTime;
const hours = Math.floor(diff / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
document.getElementById('session-time').textContent = `${hours}h ${minutes}m`;
}
// Auto-refresh functionality
function toggleAutoRefresh() {
autoRefreshEnabled = !autoRefreshEnabled;
const icon = document.getElementById('refresh-icon');
const button = document.getElementById('auto-refresh-toggle');
if (autoRefreshEnabled) {
icon.classList.add('fa-spin');
button.classList.add('text-blue-400');
button.classList.remove('text-gray-400');
startAutoRefresh();
} else {
icon.classList.remove('fa-spin');
button.classList.remove('text-blue-400');
button.classList.add('text-gray-400');
stopAutoRefresh();
}
}
function startAutoRefresh() {
autoRefreshCountdown = 30;
autoRefreshInterval = setInterval(() => {
// Refresh current page data
refreshPageData();
autoRefreshCountdown = 30; // Reset
}, 30000);
}
function stopAutoRefresh() {
if (autoRefreshInterval) {
clearInterval(autoRefreshInterval);
autoRefreshInterval = null;
}
document.getElementById('refresh-timer').textContent = '30s';
}
function updateAutoRefreshTimer() {
if (autoRefreshEnabled && autoRefreshCountdown > 0) {
autoRefreshCountdown--;
document.getElementById('refresh-timer').textContent = `${autoRefreshCountdown}s`;
}
}
// Connection monitoring
function monitorConnection() {
const updateConnectionStatus = (online) => {
const icon = document.getElementById('connection-icon');
const text = document.getElementById('connection-text');
if (online) {
icon.className = 'fas fa-wifi status-online';
text.textContent = 'Online';
} else {
icon.className = 'fas fa-wifi-slash status-offline';
text.textContent = 'Offline';
}
};
// Check connection status
window.addEventListener('online', () => updateConnectionStatus(true));
window.addEventListener('offline', () => updateConnectionStatus(false));
// Initial check
updateConnectionStatus(navigator.onLine);
// Periodic ping check
setInterval(async () => {
try {
const response = await fetch('/api/ping', {
method: 'HEAD',
cache: 'no-cache'
});
updateConnectionStatus(response.ok);
} catch {
updateConnectionStatus(false);
}
}, 10000);
}
// System status monitoring
function initializeSystemStatus() {
updateSystemStats();
}
async function updateSystemStats() {
try {
const response = await fetch('/api/system-stats');
const stats = await response.json();
// CPU Usage
document.getElementById('cpu-usage').textContent = `${stats.cpu}%`;
document.getElementById('cpu-usage').className = getCpuClass(stats.cpu);
// Memory Usage
document.getElementById('mem-usage').textContent = `${stats.memory}%`;
document.getElementById('mem-usage').className = getMemClass(stats.memory);
// Active Users
document.getElementById('active-users').textContent = stats.activeUsers;
// System Status
updateSystemStatus(stats.status);
} catch (error) {
console.warn('Unable to fetch system stats:', error);
}
}
function getCpuClass(cpu) {
if (cpu < 50) return 'text-green-400';
if (cpu < 80) return 'text-yellow-400';
return 'text-red-400';
}
function getMemClass(memory) {
if (memory < 60) return 'text-blue-400';
if (memory < 85) return 'text-yellow-400';
return 'text-red-400';
}
function updateSystemStatus(status) {
const icon = document.getElementById('system-icon');
const text = document.getElementById('system-text');
switch (status) {
case 'ok':
icon.className = 'fas fa-server status-online';
text.textContent = 'Sistema OK';
break;
case 'warning':
icon.className = 'fas fa-exclamation-triangle status-warning';
text.textContent = 'Attenzione';
break;
case 'error':
icon.className = 'fas fa-exclamation-circle status-offline';
text.textContent = 'Errore';
break;
}
}
// Progress bar for page loading
function initializeProgressBar() {
const progressBar = document.getElementById('footer-progress');
// Show progress on AJAX requests
let activeRequests = 0;
// Listen to fetch requests
const originalFetch = window.fetch;
window.fetch = function(...args) {
activeRequests++;
updateProgressBar();
return originalFetch.apply(this, args)
.finally(() => {
activeRequests--;
updateProgressBar();
});
};
}
function updateProgressBar() {
const progressBar = document.getElementById('footer-progress');
if (activeRequests > 0) {
progressBar.style.width = '70%';
setTimeout(() => {
if (activeRequests === 0) {
progressBar.style.width = '100%';
setTimeout(() => {
progressBar.style.width = '0%';
}, 200);
}
}, 500);
}
}
// Page data refresh
async function refreshPageData() {
try {
const currentPath = window.location.pathname;
const response = await fetch(currentPath, {
headers: {
'X-Requested-With': 'XMLHttpRequest',
'X-Refresh-Data': 'true'
}
});
if (response.ok) {
// Update dynamic content only
const data = await response.json();
updateDynamicContent(data);
}
} catch (error) {
console.warn('Auto-refresh failed:', error);
}
}
function updateDynamicContent(data) {
// Update stats cards
if (data.stats) {
Object.keys(data.stats).forEach(key => {
const element = document.querySelector(`[data-stat="${key}"]`);
if (element) {
element.textContent = data.stats[key];
}
});
}
// Update notifications badge
if (data.notifications) {
const badge = document.querySelector('.notification-badge');
if (badge) {
badge.textContent = data.notifications.count;
badge.style.display = data.notifications.count > 0 ? 'flex' : 'none';
}
}
// Show update indicator
showUpdateIndicator();
}
function showUpdateIndicator() {
const indicator = document.createElement('div');
indicator.className = 'update-indicator fixed top-20 right-6 bg-green-500 text-white px-3 py-1 rounded text-sm z-50';
indicator.innerHTML = '<i class="fas fa-check mr-1"></i> Aggiornato';
document.body.appendChild(indicator);
setTimeout(() => {
indicator.style.opacity = '0';
setTimeout(() => indicator.remove(), 300);
}, 2000);
}
// Initialize on DOM ready
document.addEventListener('DOMContentLoaded', initializeFooter);
```
---
## 📱 **RESPONSIVE BEHAVIOR**
### 🖥️ **Desktop (≥1024px)**
```css
.netgescon-footer {
padding: 0 24px;
}
.footer-center {
display: flex;
}
.footer-right .hidden {
display: block;
}
```
### 📱 **Tablet (768px - 1023px)**
```css
.footer-center {
display: none;
}
.footer-left,
.footer-right {
flex-wrap: wrap;
}
```
### 📱 **Mobile (≤767px)**
```css
.netgescon-footer {
padding: 0 16px;
font-size: 0.875rem;
}
.footer-left {
flex-direction: column;
align-items: flex-start;
space-y: 2px;
}
.footer-right {
flex-direction: column;
align-items: flex-end;
space-y: 2px;
}
.hidden-mobile {
display: none;
}
```
---
## 🔧 **CONFIGURATION OPTIONS**
### ⚙️ **Footer Settings**
```javascript
// Configuration object
const footerConfig = {
autoRefresh: {
enabled: true,
interval: 30000, // 30 seconds
showTimer: true
},
systemStats: {
enabled: true,
interval: 30000,
showCpu: true,
showMemory: true,
showUsers: true
},
connection: {
monitoring: true,
pingInterval: 10000,
pingEndpoint: '/api/ping'
},
progress: {
showOnAjax: true,
animationDuration: 300
}
};
```
### 🎛️ **Customization Options**
```css
/* Custom footer height */
:root {
--footer-height: 70px;
}
/* Custom progress bar color */
.footer-progress {
background: var(--netgescon-accent);
}
/* Custom status colors */
.status-custom {
color: #your-color;
}
```
---
## 🧪 **TESTING CHECKLIST**
### ✅ **Functional Tests**
- [ ] Date/time updates correctly
- [ ] Session timer accurate
- [ ] Auto-refresh toggle works
- [ ] Connection status monitoring
- [ ] System stats display
- [ ] Progress bar animations
### ✅ **Visual Tests**
- [ ] Footer height consistent (70px)
- [ ] Elements alignment correct
- [ ] Icons display properly
- [ ] Text readability good
- [ ] Mobile layout responsive
### ✅ **Performance Tests**
- [ ] No memory leaks in timers
- [ ] Efficient update intervals
- [ ] Smooth animations
- [ ] Low CPU usage
---
## 🐛 **COMMON ISSUES & FIXES**
### 🚨 **Footer copre contenuto**
**Causa:** Padding bottom mancante nel body
**Fix:**
```css
body { padding-bottom: 70px; }
.content-area { margin-bottom: 70px; }
```
### 🚨 **Timer non funziona**
**Causa:** JavaScript intervals non inizializzati
**Fix:** Verifica initializeFooter() chiamata
### 🚨 **Stats non si aggiornano**
**Causa:** Endpoint API `/api/system-stats` mancante
**Fix:** Implementa route API o disabilita feature
### 🚨 **Progress bar non appare**
**Causa:** CSS z-index conflicts
**Fix:** Verifica z-index footer e progress bar
---
## 📊 **PERFORMANCE METRICS**
### 🎯 **Target Performance**
- **Update Frequency:** 1Hz (1 update/second)
- **API Calls:** Max 2/minute
- **Memory Usage:** < 5MB
- **CPU Impact:** < 1%
### 📈 **Monitoring**
```javascript
// Performance monitoring
const footerPerformance = {
updateCount: 0,
lastUpdate: Date.now(),
avgUpdateTime: 0,
measureUpdate(fn) {
const start = performance.now();
fn();
const end = performance.now();
this.updateCount++;
this.avgUpdateTime = (this.avgUpdateTime + (end - start)) / 2;
this.lastUpdate = Date.now();
}
};
```
---
## 📚 **FILES CORRELATI**
### 🧩 **Templates**
- `/resources/views/components/menu/sections/footer.blade.php`
### 🎨 **Styles**
- `/public/css/components/footer.css`
- `/public/css/netgescon-admin.css`
### ⚡ **JavaScript**
- `/public/js/components/footer.js`
- `/public/js/netgescon-admin.js`
### 🔗 **API Endpoints**
- `/api/ping` - Connection check
- `/api/system-stats` - System statistics
- `/api/refresh-data` - Page data refresh
---
## 🎯 **NEXT STEPS**
### 🔮 **Planned Improvements**
- [ ] **Real-time Notifications** - WebSocket integration
- [ ] **System Health Dashboard** - Detailed metrics
- [ ] **User Activity Tracker** - Session analytics
- [ ] **Quick Actions Menu** - Footer dropdown
- [ ] **Theme Preferences** - Footer controls
---
*📝 Documento mantenuto da: GitHub Copilot AI Assistant*
*🔗 Componente: Footer NetGescon Interface v2.1.0*