Modernizzazione UI: nuovo tema dark e sidebar rivista

Aggiorna l’interfaccia Blazor con una palette dark moderna, font Inter, e una sidebar ridisegnata.
Riorganizza layout e navigazione, migliora la gestione errori e introduce nuovi stili per card, bottoni, input e badge.
Aggiunto `modern-pages.css` per header, griglie statistiche, alert e form più coerenti e attuali.
Migliora leggibilità, navigazione e user experience complessiva.
This commit is contained in:
2026-01-21 17:39:15 +01:00
parent ed42a41bcd
commit 70ed8f0a61
5 changed files with 708 additions and 158 deletions

View File

@@ -9,9 +9,13 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="~/" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet" />
<link href="css/app-wpf.css" rel="stylesheet" />
<link href="css/modern-pages.css" rel="stylesheet" />
<link href="css/animations.css" rel="stylesheet" />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>

View File

@@ -1,26 +1,103 @@
@inherits LayoutComponentBase
<div class="page">
<div class="sidebar">
<div class="app-container">
<aside class="app-sidebar">
<NavMenu />
</div>
</aside>
<main>
<!-- UserBanner rimosso - informazioni integrate nel toolbar dell'Index.razor -->
<article class="content">
<main class="app-main">
<article class="app-content">
@Body
</article>
</main>
</div>
<div id="blazor-error-ui">
<environment include="Staging,Production">
Si è verificato un errore.
</environment>
<environment include="Development">
Si è verificato un errore non gestito. Consultare la console del browser per ulteriori informazioni.
</environment>
<a href="" class="reload">Ricarica</a>
<a class="dismiss">??</a>
<div class="error-content">
<i class="bi bi-exclamation-triangle-fill"></i>
<span>Si e verificato un errore. <a href="" class="reload">Ricarica</a></span>
<button class="dismiss-btn" onclick="this.parentElement.parentElement.style.display='none'">×</button>
</div>
</div>
<style>
.app-container {
display: flex;
min-height: 100vh;
background: #0f0f0f;
}
.app-sidebar {
width: 260px;
min-width: 260px;
height: 100vh;
position: fixed;
left: 0;
top: 0;
z-index: 1000;
}
.app-main {
flex: 1;
margin-left: 260px;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.app-content {
flex: 1;
padding: 1.5rem;
overflow-y: auto;
}
#blazor-error-ui {
display: none;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 9999;
}
#blazor-error-ui .error-content {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 1rem 1.5rem;
background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
color: white;
font-weight: 500;
}
#blazor-error-ui .reload {
color: white;
text-decoration: underline;
}
#blazor-error-ui .dismiss-btn {
margin-left: auto;
background: none;
border: none;
color: white;
font-size: 1.5rem;
cursor: pointer;
opacity: 0.8;
}
#blazor-error-ui .dismiss-btn:hover {
opacity: 1;
}
@@media (max-width: 768px) {
.app-sidebar {
width: 100%;
height: auto;
position: relative;
}
.app-main {
margin-left: 0;
}
}
</style>

View File

@@ -2,138 +2,176 @@
@inject NavigationManager NavigationManager
@inject AuthenticationStateProvider AuthenticationStateProvider
<div class="sidebar">
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand d-flex align-items-center" href="">
<i class="bi bi-lightning-charge-fill me-2" style="font-size: 1.5rem; color: #ffc107;"></i>
<span class="fw-bold">AutoBidder</span>
</a>
</div>
<div class="nav-sidebar">
<div class="nav-header">
<a class="nav-brand" href="">
<div class="brand-icon">
<i class="bi bi-lightning-charge-fill"></i>
</div>
<span class="brand-text">AutoBidder</span>
</a>
</div>
<div class="nav-scrollable">
<nav class="flex-column px-3 mt-3">
<div class="nav-item px-2 mb-2 animate-fade-in-left stagger-item">
<NavLink class="nav-link hover-lift transition-all" href="" Match="NavLinkMatch.All">
<i class="bi bi-display me-2"></i> Monitor Aste
</NavLink>
</div>
<div class="nav-item px-2 mb-2 animate-fade-in-left stagger-item">
<NavLink class="nav-link hover-lift transition-all" href="freebids">
<i class="bi bi-gift me-2"></i> Puntate Gratuite
</NavLink>
</div>
<div class="nav-item px-2 mb-2 animate-fade-in-left stagger-item">
<NavLink class="nav-link hover-lift transition-all" href="statistics">
<i class="bi bi-bar-chart me-2"></i> Statistiche
</NavLink>
</div>
<div class="nav-item px-2 mb-2 animate-fade-in-left stagger-item">
<NavLink class="nav-link hover-lift transition-all" href="settings">
<i class="bi bi-gear me-2"></i> Impostazioni
</NavLink>
</div>
<nav class="nav-menu">
<div class="nav-section">
<NavLink class="nav-menu-item" href="" Match="NavLinkMatch.All">
<i class="bi bi-display"></i>
<span>Monitor Aste</span>
</NavLink>
<hr class="my-3 border-secondary" />
<NavLink class="nav-menu-item" href="freebids">
<i class="bi bi-gift"></i>
<span>Puntate Gratuite</span>
</NavLink>
<NavLink class="nav-menu-item" href="statistics">
<i class="bi bi-bar-chart"></i>
<span>Statistiche</span>
</NavLink>
<NavLink class="nav-menu-item" href="settings">
<i class="bi bi-gear"></i>
<span>Impostazioni</span>
</NavLink>
</div>
<div class="nav-footer">
<AuthorizeView>
<Authorized>
<div class="nav-item px-2 mb-2 animate-fade-in-left stagger-item">
<div class="user-info px-3 py-2 mb-2">
<i class="bi bi-person-circle me-2"></i>
<small class="text-muted">@context.User.Identity?.Name</small>
</div>
<a href="/Account/Logout" class="nav-link nav-link-logout hover-lift transition-all">
<i class="bi bi-box-arrow-right me-2"></i> Logout
</a>
<div class="user-badge">
<i class="bi bi-person-circle"></i>
<span>@context.User.Identity?.Name</span>
</div>
<a href="/Account/Logout" class="nav-menu-item logout-item">
<i class="bi bi-box-arrow-right"></i>
<span>Logout</span>
</a>
</Authorized>
</AuthorizeView>
</nav>
</div>
</div>
</nav>
</div>
<style>
.sidebar {
.nav-sidebar {
display: flex;
flex-direction: column;
}
.navbar-brand {
font-size: 1.3rem;
transition: all 0.3s ease;
color: white !important;
}
.navbar-brand:hover {
transform: scale(1.05);
text-shadow: 0 0 10px rgba(255, 193, 7, 0.5);
}
.nav-scrollable {
flex: 1;
overflow-y: auto;
padding-bottom: 2rem;
}
.nav-link {
border-radius: 8px;
margin: 0.25rem 0;
padding: 0.75rem 1rem;
font-weight: 500;
position: relative;
overflow: hidden;
color: rgba(255, 255, 255, 0.8) !important;
transition: all 0.3s ease;
}
.nav-link::before {
content: '';
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 4px;
background: linear-gradient(to bottom, #0dcaf0, #0d6efd);
transform: scaleY(0);
transition: transform 0.3s ease;
background: linear-gradient(180deg, #1a1d23 0%, #13151a 100%);
border-right: 1px solid rgba(255, 255, 255, 0.06);
}
.nav-link:hover {
background: rgba(255, 255, 255, 0.1);
color: white !important;
.nav-header {
padding: 1.25rem 1.5rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.nav-link:hover::before,
.nav-link.active::before {
transform: scaleY(1);
.nav-brand {
display: flex;
align-items: center;
gap: 0.75rem;
text-decoration: none;
transition: opacity 0.2s;
}
.nav-link.active {
background: linear-gradient(to right, rgba(13, 202, 240, 0.2), transparent);
font-weight: 600;
color: #0dcaf0 !important;
.nav-brand:hover {
opacity: 0.9;
}
.user-info {
background: rgba(255, 255, 255, 0.05);
.brand-icon {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
border-radius: 10px;
font-size: 1.25rem;
color: white;
}
.brand-text {
font-size: 1.25rem;
font-weight: 700;
color: white;
letter-spacing: -0.02em;
}
.nav-menu {
display: flex;
flex-direction: column;
flex: 1;
padding: 1rem 0.75rem;
overflow-y: auto;
}
.nav-section {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.nav-menu-item {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem 1rem;
border-radius: 8px;
color: rgba(255, 255, 255, 0.7);
color: rgba(255, 255, 255, 0.65);
text-decoration: none;
font-size: 0.9375rem;
font-weight: 500;
transition: all 0.15s ease;
}
.nav-link-logout {
background: rgba(220, 53, 69, 0.1) !important;
color: #dc3545 !important;
.nav-menu-item i {
font-size: 1.125rem;
width: 1.5rem;
text-align: center;
}
.nav-link-logout:hover {
background: rgba(220, 53, 69, 0.2) !important;
color: #ff4757 !important;
.nav-menu-item:hover {
background: rgba(255, 255, 255, 0.06);
color: white;
}
.nav-menu-item.active {
background: linear-gradient(135deg, rgba(99, 102, 241, 0.15) 0%, rgba(139, 92, 246, 0.15) 100%);
color: #a5b4fc;
}
.nav-menu-item.active i {
color: #818cf8;
}
.nav-footer {
padding: 1rem;
margin-top: auto;
padding-top: 1rem;
border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.user-badge {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem 1rem;
margin-bottom: 0.5rem;
background: rgba(255, 255, 255, 0.03);
border-radius: 8px;
color: rgba(255, 255, 255, 0.5);
font-size: 0.875rem;
}
.user-badge i {
font-size: 1.25rem;
}
.logout-item {
color: rgba(248, 113, 113, 0.8) !important;
}
.logout-item:hover {
background: rgba(248, 113, 113, 0.1) !important;
color: #f87171 !important;
}
</style>

View File

@@ -1,68 +1,271 @@
/* app-wpf.css - WPF Dark Theme + Modern Sidebar */
/* app-wpf.css - Modern Dark Theme */
:root {
/* WPF Dark Theme Palette */
--bg-primary: #1e1e1e;
--bg-secondary: #252526;
--bg-tertiary: #2d2d30;
--bg-hover: #3e3e42;
--bg-selected: #094771;
--border-color: #3e3e42;
--text-primary: #ffffff;
--text-secondary: #cccccc;
--text-muted: #808080;
/* Modern Dark Palette */
--bg-primary: #0f0f0f;
--bg-secondary: #171717;
--bg-tertiary: #1f1f1f;
--bg-card: #1a1a1a;
--bg-hover: #262626;
--bg-selected: #2d2d2d;
--border-color: rgba(255, 255, 255, 0.08);
--border-subtle: rgba(255, 255, 255, 0.04);
/* WPF Accent Colors */
--primary-color: #007acc;
--success-color: #00d800;
--warning-color: #ffb700;
--danger-color: #e81123;
--info-color: #00b7c3;
/* Text Colors */
--text-primary: #fafafa;
--text-secondary: #a1a1aa;
--text-muted: #71717a;
/* Log Syntax Colors */
--log-success: #00d800;
--log-warning: #ffb700;
--log-error: #f48771;
--log-info: #4ec9b0;
--log-debug: #569cd6;
--log-timestamp: #808080;
/* Accent Colors */
--primary: #6366f1;
--primary-hover: #4f46e5;
--success: #22c55e;
--warning: #f59e0b;
--danger: #ef4444;
--info: #3b82f6;
/* Gradients */
--gradient-primary: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
--gradient-success: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
--gradient-danger: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
/* Shadows */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.3);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.4);
/* Border Radius */
--radius-sm: 6px;
--radius-md: 10px;
--radius-lg: 14px;
--radius-xl: 20px;
}
/* === GLOBAL === */
* {
/* === GLOBAL RESET === */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
margin: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
background: var(--bg-primary);
color: var(--text-secondary);
font-size: 13px;
font-size: 14px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
/* === LAYOUT === */
/* === SCROLLBAR === */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.1);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.15);
}
/* === LAYOUT (legacy support) === */
.page {
display: flex;
height: 100vh;
overflow: hidden;
}
/* Sidebar Moderna - 250px come prima */
/* === MODERN CARD COMPONENT === */
.card-modern {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: 1.5rem;
transition: all 0.2s ease;
}
.card-modern:hover {
border-color: rgba(255, 255, 255, 0.12);
}
.card-header-modern {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
padding-bottom: 1rem;
border-bottom: 1px solid var(--border-subtle);
}
.card-title {
font-size: 1rem;
font-weight: 600;
color: var(--text-primary);
display: flex;
align-items: center;
gap: 0.5rem;
}
.card-title i {
color: var(--primary);
}
/* === MODERN BUTTON === */
.btn-modern {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.625rem 1.25rem;
font-size: 0.875rem;
font-weight: 500;
border-radius: var(--radius-md);
border: none;
cursor: pointer;
transition: all 0.15s ease;
}
.btn-primary-modern {
background: var(--gradient-primary);
color: white;
}
.btn-primary-modern:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.35);
}
.btn-success-modern {
background: var(--gradient-success);
color: white;
}
.btn-danger-modern {
background: var(--gradient-danger);
color: white;
}
.btn-ghost {
background: transparent;
border: 1px solid var(--border-color);
color: var(--text-secondary);
}
.btn-ghost:hover {
background: var(--bg-hover);
border-color: rgba(255, 255, 255, 0.15);
color: var(--text-primary);
}
/* === MODERN INPUT === */
.input-modern {
width: 100%;
padding: 0.75rem 1rem;
font-size: 0.875rem;
color: var(--text-primary);
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: var(--radius-md);
transition: all 0.15s ease;
}
.input-modern:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15);
}
.input-modern::placeholder {
color: var(--text-muted);
}
/* === BADGE === */
.badge-modern {
display: inline-flex;
align-items: center;
gap: 0.25rem;
padding: 0.25rem 0.625rem;
font-size: 0.75rem;
font-weight: 500;
border-radius: 9999px;
}
.badge-success {
background: rgba(34, 197, 94, 0.15);
color: #4ade80;
}
.badge-warning {
background: rgba(245, 158, 11, 0.15);
color: #fbbf24;
}
.badge-danger {
background: rgba(239, 68, 68, 0.15);
color: #f87171;
}
.badge-info {
background: rgba(59, 130, 246, 0.15);
color: #60a5fa;
}
/* === STAT CARD === */
.stat-card {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: 1.25rem;
}
.stat-card-label {
font-size: 0.8125rem;
color: var(--text-muted);
margin-bottom: 0.5rem;
}
.stat-card-value {
font-size: 1.75rem;
font-weight: 700;
color: var(--text-primary);
line-height: 1.2;
}
.stat-card-change {
font-size: 0.8125rem;
margin-top: 0.5rem;
}
.stat-card-change.positive {
color: var(--success);
}
.stat-card-change.negative {
color: var(--danger);
}
/* Sidebar Moderna - 260px */
.sidebar {
width: 250px;
width: 260px;
height: 100vh;
position: fixed;
left: 0;
top: 0;
background: linear-gradient(180deg, #1c2128 0%, #161b22 50%, #0d1117 100%);
background: linear-gradient(180deg, #1a1d23 0%, #13151a 100%);
border-right: 1px solid var(--border-color);
z-index: 1000;
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.5);
}
main {
margin-left: 250px;
margin-left: 260px;
flex: 1;
display: flex;
flex-direction: column;

View File

@@ -0,0 +1,228 @@
/* === MODERN PAGE STYLES (append to app-wpf.css) === */
.page-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1.5rem;
padding-bottom: 1rem;
border-bottom: 1px solid var(--border-color);
}
.page-header-icon {
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
background: var(--gradient-primary);
border-radius: var(--radius-md);
font-size: 1.5rem;
color: white;
}
.page-header-text h1,
.page-header-text h2 {
margin: 0;
font-size: 1.5rem;
font-weight: 700;
color: var(--text-primary);
}
.page-header-text p {
margin: 0.25rem 0 0;
font-size: 0.875rem;
color: var(--text-muted);
}
/* Modern Accordion */
.accordion-modern .accordion-item {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg) !important;
margin-bottom: 0.75rem;
overflow: hidden;
}
.accordion-modern .accordion-button {
background: transparent;
color: var(--text-primary);
font-weight: 600;
padding: 1rem 1.25rem;
box-shadow: none !important;
}
.accordion-modern .accordion-button:not(.collapsed) {
background: rgba(99, 102, 241, 0.08);
color: var(--primary);
}
.accordion-modern .accordion-button::after {
filter: invert(1);
}
.accordion-modern .accordion-body {
padding: 1.25rem;
background: var(--bg-secondary);
}
/* Modern Form Controls Override */
.settings-container .form-control,
.settings-container .form-select {
background: var(--bg-secondary) !important;
border: 1px solid var(--border-color) !important;
border-radius: var(--radius-md) !important;
color: var(--text-primary) !important;
padding: 0.75rem 1rem !important;
}
.settings-container .form-control:focus,
.settings-container .form-select:focus {
border-color: var(--primary) !important;
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15) !important;
}
/* Stats Grid */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.stat-box {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: 1.25rem;
transition: all 0.2s ease;
}
.stat-box:hover {
border-color: rgba(255, 255, 255, 0.12);
transform: translateY(-2px);
}
.stat-box-label {
font-size: 0.8125rem;
color: var(--text-muted);
margin-bottom: 0.5rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.stat-box-value {
font-size: 1.75rem;
font-weight: 700;
color: var(--text-primary);
}
.stat-box-value.success { color: var(--success); }
.stat-box-value.warning { color: var(--warning); }
.stat-box-value.danger { color: var(--danger); }
.stat-box-value.info { color: var(--info); }
/* Empty State */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 4rem 2rem;
text-align: center;
}
.empty-state-icon {
font-size: 4rem;
color: var(--text-muted);
opacity: 0.5;
margin-bottom: 1.5rem;
}
.empty-state-title {
font-size: 1.25rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 0.5rem;
}
.empty-state-text {
color: var(--text-muted);
max-width: 400px;
}
/* Settings Container Override */
.settings-container {
max-width: 1000px;
}
.settings-container .accordion-item {
background: var(--bg-card) !important;
border: 1px solid var(--border-color) !important;
border-radius: var(--radius-lg) !important;
margin-bottom: 0.75rem;
}
.settings-container .accordion-button {
background: transparent !important;
color: var(--text-primary) !important;
font-weight: 600;
}
.settings-container .accordion-button:not(.collapsed) {
background: rgba(99, 102, 241, 0.08) !important;
}
.settings-container .accordion-body {
background: var(--bg-secondary) !important;
border-top: 1px solid var(--border-color) !important;
}
/* Alert modernization */
.settings-container .alert {
border-radius: var(--radius-md) !important;
border: 1px solid !important;
}
.settings-container .alert-success {
background: rgba(34, 197, 94, 0.1) !important;
border-color: rgba(34, 197, 94, 0.3) !important;
color: #4ade80 !important;
}
.settings-container .alert-warning {
background: rgba(245, 158, 11, 0.1) !important;
border-color: rgba(245, 158, 11, 0.3) !important;
color: #fbbf24 !important;
}
.settings-container .alert-danger {
background: rgba(239, 68, 68, 0.1) !important;
border-color: rgba(239, 68, 68, 0.3) !important;
color: #f87171 !important;
}
/* Button modernization */
.settings-container .btn-primary {
background: var(--gradient-primary) !important;
border: none !important;
border-radius: var(--radius-md) !important;
}
.settings-container .btn-danger {
background: var(--gradient-danger) !important;
border: none !important;
border-radius: var(--radius-md) !important;
}
.settings-container .btn-outline-secondary {
background: transparent !important;
border: 1px solid var(--border-color) !important;
color: var(--text-secondary) !important;
border-radius: var(--radius-md) !important;
}
.settings-container .btn-outline-secondary:hover {
background: var(--bg-hover) !important;
color: var(--text-primary) !important;
}