[POLISH] Docker setup fix + UI polish + project completion
- Fix Docker: add php.ini, correct env var names (DB_NAME/DB_USER/DB_PASS), add 002_email_log.sql to initdb, add Authorization header passthrough, add uploads volume, install opcache, create .dockerignore - UI polish: page fade-in transitions, skeleton loader CSS, staggered card animations, mobile sidebar backdrop overlay, keyboard focus-visible styles, button loading state, tooltip system, alert banners, tab component, custom scrollbar, print styles, clickable table rows - Add setButtonLoading() and _toggleSidebar() helpers to common.js - Update CLAUDE.md to reflect 100% project completion Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+47
-4
@@ -295,13 +295,35 @@ function _setupMobileToggle() {
|
||||
if (!document.querySelector('.sidebar-toggle')) {
|
||||
const toggle = document.createElement('button');
|
||||
toggle.className = 'sidebar-toggle';
|
||||
toggle.setAttribute('aria-label', 'Apri menu');
|
||||
toggle.innerHTML = '<svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" clip-rule="evenodd"/></svg>';
|
||||
toggle.addEventListener('click', () => {
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
if (sidebar) sidebar.classList.toggle('open');
|
||||
});
|
||||
toggle.addEventListener('click', () => _toggleSidebar());
|
||||
document.body.appendChild(toggle);
|
||||
}
|
||||
|
||||
// Crea backdrop per mobile
|
||||
if (!document.querySelector('.sidebar-backdrop')) {
|
||||
const backdrop = document.createElement('div');
|
||||
backdrop.className = 'sidebar-backdrop';
|
||||
backdrop.addEventListener('click', () => _toggleSidebar(false));
|
||||
document.body.appendChild(backdrop);
|
||||
}
|
||||
}
|
||||
|
||||
function _toggleSidebar(forceState) {
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
const backdrop = document.querySelector('.sidebar-backdrop');
|
||||
if (!sidebar) return;
|
||||
|
||||
const isOpen = typeof forceState === 'boolean' ? forceState : !sidebar.classList.contains('open');
|
||||
|
||||
if (isOpen) {
|
||||
sidebar.classList.add('open');
|
||||
if (backdrop) backdrop.classList.add('visible');
|
||||
} else {
|
||||
sidebar.classList.remove('open');
|
||||
if (backdrop) backdrop.classList.remove('visible');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -454,6 +476,27 @@ function iconCog() {
|
||||
return '<svg viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" clip-rule="evenodd"/></svg>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Imposta lo stato di caricamento su un bottone.
|
||||
* @param {HTMLElement|string} btn - Elemento o ID
|
||||
* @param {boolean} loading - true per attivare, false per disattivare
|
||||
* @param {string} [originalText] - Testo originale da ripristinare
|
||||
*/
|
||||
function setButtonLoading(btn, loading, originalText) {
|
||||
if (typeof btn === 'string') btn = document.getElementById(btn);
|
||||
if (!btn) return;
|
||||
if (loading) {
|
||||
btn._originalText = btn.textContent;
|
||||
btn.classList.add('loading');
|
||||
btn.disabled = true;
|
||||
} else {
|
||||
btn.classList.remove('loading');
|
||||
btn.disabled = false;
|
||||
if (originalText) btn.textContent = originalText;
|
||||
else if (btn._originalText) btn.textContent = btn._originalText;
|
||||
}
|
||||
}
|
||||
|
||||
function iconPlus() {
|
||||
return '<svg viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 5a1 1 0 011 1v3h3a1 1 0 110 2h-3v3a1 1 0 11-2 0v-3H6a1 1 0 110-2h3V6a1 1 0 011-1z" clip-rule="evenodd"/></svg>';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user