Miglioramenti UI

This commit is contained in:
2025-06-17 12:58:12 +02:00
parent d6c7742501
commit 6600660315
15 changed files with 148 additions and 78 deletions

View File

@@ -51,6 +51,7 @@
<script src="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js"></script> <script src="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js"></script>
<script src="_content/Template.Shared/js/main.js"></script> <script src="_content/Template.Shared/js/main.js"></script>
<script src="_content/Template.Shared/js/calendar.js"></script> <script src="_content/Template.Shared/js/calendar.js"></script>
<script src="_content/Template.Shared/js/header.js"></script>
</body> </body>

View File

@@ -1,6 +1,6 @@
@inject IJSRuntime JS @inject IJSRuntime JS
<div class="container header"> <div class="@(Back ? "" : "container") header">
<div class="header-content @(Back ? "with-back" : "no-back")"> <div class="header-content @(Back ? "with-back" : "no-back")">
@if (Back) @if (Back)
{ {
@@ -24,9 +24,15 @@
{ {
<MudIconButton OnClick="OnFilterToggle" Icon="@Icons.Material.Outlined.FilterAlt" Color="Color.Dark"/> <MudIconButton OnClick="OnFilterToggle" Icon="@Icons.Material.Outlined.FilterAlt" Color="Color.Dark"/>
} }
@if (ShowCalendarToggle)
@* @if (ShowCalendarToggle)
{ {
<MudIconButton OnClick="OnCalendarToggle" Icon="@Icons.Material.Filled.CalendarMonth" Color="Color.Dark"/> <MudIconButton OnClick="OnCalendarToggle" Icon="@Icons.Material.Filled.CalendarMonth" Color="Color.Dark"/>
} *@
@if (ShowProfile)
{
<MudIconButton Class="user" OnClick="OpenPersonalInfo" Icon="@Icons.Material.Filled.Person" Color="Color.Dark"/>
} }
} }
else else
@@ -45,8 +51,9 @@
@code{ @code{
[Parameter] public string? Title { get; set; } [Parameter] public string? Title { get; set; }
[Parameter] public bool ShowFilter { get; set; } [Parameter] public bool ShowFilter { get; set; }
[Parameter] public bool ShowNotifications { get; set; } = true; [Parameter] public bool ShowProfile { get; set; } = true;
[Parameter] public bool Back { get; set; } [Parameter] public bool Back { get; set; }
[Parameter] public bool BackOnTop { get; set; }
[Parameter] public string BackTo { get; set; } = ""; [Parameter] public string BackTo { get; set; } = "";
[Parameter] public EventCallback OnFilterToggle { get; set; } [Parameter] public EventCallback OnFilterToggle { get; set; }
@@ -74,7 +81,9 @@
} }
await JS.InvokeVoidAsync("goBack"); await JS.InvokeVoidAsync("goBack");
} }
private void OpenPersonalInfo() =>
NavigationManager.NavigateTo("/PersonalInfo");
} }

View File

@@ -6,8 +6,6 @@
position: relative; position: relative;
} }
.header-content.with-back { margin: .6rem 0 0 0; }
.header-content.with-back .page-title { .header-content.with-back .page-title {
position: absolute; position: absolute;
left: 50%; left: 50%;
@@ -16,14 +14,10 @@
font-size: larger; font-size: larger;
} }
.left-section ::deep button, .right-section ::deep button { .right-section { min-height: 45px; }
font-size: 1.1rem;
}
.left-section ::deep .mud-button-icon-start { .left-section ::deep button, .right-section ::deep button { font-size: 1.1rem; }
margin-right: 3px !important;
}
.header-content.no-back .page-title { .left-section ::deep .mud-button-icon-start { margin-right: 3px !important; }
margin: 0;
} .header-content.no-back .page-title { margin: 0; }

View File

@@ -1,16 +1,14 @@
@inject IDialogService Dialog @inject IDialogService Dialog
@if (IsVisible) <div class="container animated-navbar @(IsVisible ? "show-nav" : "hide-nav") @(IsVisible? PlusVisible ? "with-plus" : "without-plus" : "with-plus")">
{ <nav class="navbar @(IsVisible? PlusVisible ? "with-plus" : "without-plus" : "with-plus")">
<nav class="navbar navbar-expand justify-content-center">
<div class="container-navbar"> <div class="container-navbar">
<ul class="navbar-nav nav-justified align-items-center w-100 text-center"> <ul class="navbar-nav flex-row nav-justified align-items-center w-100 text-center">
<li class="nav-item"> <li class="nav-item">
<NavLink class="nav-link" href="Users" Match="NavLinkMatch.All"> <NavLink class="nav-link" href="Users" Match="NavLinkMatch.All">
<div class="d-flex flex-column"> <div class="d-flex flex-column">
<i class="ri-group-line"></i> <i class="ri-group-line"></i>
@* <span>Contatti</span> *@ <span>Contatti</span>
</div> </div>
</NavLink> </NavLink>
</li> </li>
@@ -18,47 +16,40 @@
<NavLink class="nav-link" href="Calendar" Match="NavLinkMatch.All"> <NavLink class="nav-link" href="Calendar" Match="NavLinkMatch.All">
<div class="d-flex flex-column"> <div class="d-flex flex-column">
<i class="ri-calendar-todo-line"></i> <i class="ri-calendar-todo-line"></i>
@* <span>Agenda</span> *@ <span>Agenda</span>
</div> </div>
</NavLink> </NavLink>
</li> </li>
<li class="nav-item">
<NavLink class="nav-link" href="Notifications" Match="NavLinkMatch.All">
<div class="d-flex flex-column">
<i class="ri-notification-4-line"></i>
<span>Notifiche</span>
</div>
</NavLink>
</li>
</ul>
</div>
@if (PlusVisible)
<li class="nav-item plus-button"> {
<MudMenu PopoverClass="custom_popover" AnchorOrigin="Origin.TopCenter" TransformOrigin="Origin.BottomCenter"> <MudMenu PopoverClass="custom_popover" AnchorOrigin="Origin.TopLeft" TransformOrigin="Origin.BottomRight">
<ActivatorContent> <ActivatorContent>
<MudFab Class="custom-plus-button" Color="Color.Primary" Size="Size.Medium" IconSize="Size.Medium" StartIcon="@Icons.Material.Filled.Add"/> <MudFab Class="custom-plus-button" Color="Color.Surface" Size="Size.Medium" IconSize="Size.Medium" IconColor="Color.Primary" StartIcon="@Icons.Material.Filled.Add" />
</ActivatorContent> </ActivatorContent>
<ChildContent> <ChildContent>
<MudMenuItem Disabled="true">Nuovo contatto</MudMenuItem> <MudMenuItem Disabled="true">Nuovo contatto</MudMenuItem>
<MudMenuItem OnClick="() => ModalHelpers.OpenActivityForm(Dialog)">Nuova attivit<69></MudMenuItem> <MudMenuItem OnClick="() => ModalHelpers.OpenActivityForm(Dialog)">Nuova attivit<69></MudMenuItem>
</ChildContent> </ChildContent>
</MudMenu> </MudMenu>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="Notifications" Match="NavLinkMatch.All">
<div class="d-flex flex-column">
<i class="ri-notification-4-line"></i>
</div>
</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="PersonalInfo" Match="NavLinkMatch.All">
<div class="d-flex flex-column">
<i class="ri-user-line"></i>
@* <span>Profilo</span> *@
</div>
</NavLink>
</li>
</ul>
</div>
</nav>
} }
</nav>
</div>
@code @code
{ {
private bool IsVisible { get; set; } = true; private bool IsVisible { get; set; } = true;
private bool PlusVisible { get; set; } = true;
protected override Task OnInitializedAsync() protected override Task OnInitializedAsync()
{ {
@@ -66,10 +57,19 @@
{ {
var location = args.Location.Remove(0, NavigationManager.BaseUri.Length); var location = args.Location.Remove(0, NavigationManager.BaseUri.Length);
IsVisible = new List<string> { "Calendar", "Users", "PersonalInfo", "Notifications" } var newIsVisible = new List<string> { "Calendar", "Users", "Notifications" }
.Contains(location); .Contains(location);
var newPlusVisible = new List<string> { "Calendar", "Users" }
.Contains(location);
if (IsVisible == newIsVisible && PlusVisible == newPlusVisible) return;
IsVisible = newIsVisible;
PlusVisible = newPlusVisible;
StateHasChanged(); StateHasChanged();
}; };
return Task.CompletedTask; return Task.CompletedTask;
} }
} }

View File

@@ -1,17 +1,41 @@
.navbar { .animated-navbar {
background: transparent; background: transparent;
position: fixed; position: fixed;
bottom: 0; bottom: 0;
width: 100%; width: 100%;
z-index: 1001; z-index: 1001;
transition: all 0.3s ease-in-out;
}
.animated-navbar.show-nav { transform: translateY(0); }
.animated-navbar.hide-nav { transform: translateY(100%); }
.animated-navbar.with-plus { margin-left: 30px; }
.navbar {
padding-bottom: 1rem; padding-bottom: 1rem;
padding-top: 0 !important; padding-top: 0 !important;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: end;
transition: all 0.3s ease-in-out;
}
.navbar.with-plus { transform: translateX(-30px); }
.navbar.without-plus {
transform: translateX(0);
justify-content: center;
} }
.container-navbar { .container-navbar {
background: var(--mud-palette-surface); background: var(--mud-palette-surface);
border-radius: 15px; border-radius: 50px;
padding: 0 10px;
box-shadow: var(--custom-box-shadow); box-shadow: var(--custom-box-shadow);
transition: all 0.3s ease-in-out;
} }
.nav-item { font-size: 0.9rem; } .nav-item { font-size: 0.9rem; }
@@ -27,23 +51,27 @@
font-size: 2rem; font-size: 2rem;
} }
.nav-item ::deep .custom-plus-button:focus .mud-icon-root { .navbar ::deep .custom-plus-button {
transform: rotate(225deg); background: var(--mud-palette-surface);
box-shadow: var(--custom-box-shadow);
transition: all 0.3s ease-in-out;
} }
.nav-item ::deep .custom-plus-button:focus .mud-icon-root { transform: rotate(225deg); }
.nav-item ::deep a { .nav-item ::deep a {
display: flex; display: flex;
align-items: center; align-items: center;
line-height: 1.2; line-height: 1.2;
justify-content: center; justify-content: center;
padding-top: .5rem !important; padding-top: .25rem !important;
padding-bottom: .5rem !important; padding-bottom: .25rem !important;
} }
.nav-item ::deep a > div { .nav-item ::deep a > div {
-webkit-transition: all .1s ease-out; -webkit-transition: all .1s ease-out;
transition: all .1s ease-out; transition: all .1s ease-out;
min-width: 60px; min-width: 75px;
} }
.nav-item ::deep a.active > div { color: var(--mud-palette-primary); } .nav-item ::deep a.active > div { color: var(--mud-palette-primary); }

View File

@@ -214,6 +214,11 @@
} }
} }
protected override void OnInitialized()
{
PrepareRenderingData();
}
protected override async Task OnAfterRenderAsync(bool firstRender) protected override async Task OnAfterRenderAsync(bool firstRender)
{ {
if (firstRender) if (firstRender)
@@ -225,7 +230,6 @@
_internalMonth = new DateTime(SelectedDate.Year, SelectedDate.Month, 1); _internalMonth = new DateTime(SelectedDate.Year, SelectedDate.Month, 1);
await LoadMonthData(); await LoadMonthData();
PrepareRenderingData();
_isInitialized = true; _isInitialized = true;
ApplyFilter(); ApplyFilter();
StateHasChanged(); StateHasChanged();
@@ -283,7 +287,7 @@
_monthDaysData = new DayData[DaysInMonth]; _monthDaysData = new DayData[DaysInMonth];
var today = DateTime.Today; var today = DateTime.Today;
for (int d = 1; d <= DaysInMonth; d++) for (var d = 1; d <= DaysInMonth; d++)
{ {
var day = new DateTime(CurrentMonth.Year, CurrentMonth.Month, d); var day = new DateTime(CurrentMonth.Year, CurrentMonth.Month, d);
var isSelected = day.Date == SelectedDate.Date; var isSelected = day.Date == SelectedDate.Date;
@@ -291,7 +295,7 @@
var cssClass = isSelected ? "selected" : (isToday ? "today" : ""); var cssClass = isSelected ? "selected" : (isToday ? "today" : "");
var hasEvents = _eventsCache.ContainsKey(day.Date); var hasEvents = _eventsCache.ContainsKey(day.Date);
var eventCategories = hasEvents ? GetFilteredCategoriesForDay(day.Date) : Array.Empty<CategoryData>(); var eventCategories = hasEvents ? GetFilteredCategoriesForDay(day.Date) : [];
_monthDaysData[d - 1] = new DayData(day, cssClass, eventCategories.Length > 0, eventCategories); _monthDaysData[d - 1] = new DayData(day, cssClass, eventCategories.Length > 0, eventCategories);
} }
@@ -303,7 +307,7 @@
var today = DateTime.Today; var today = DateTime.Today;
var culture = new System.Globalization.CultureInfo("it-IT"); var culture = new System.Globalization.CultureInfo("it-IT");
for (int i = 0; i < 7; i++) for (var i = 0; i < 7; i++)
{ {
var day = start.AddDays(i); var day = start.AddDays(i);
var isSelected = day.Date == SelectedDate.Date; var isSelected = day.Date == SelectedDate.Date;
@@ -312,7 +316,7 @@
var cssClass = isSelected ? "selected" : (isToday ? "today" : ""); var cssClass = isSelected ? "selected" : (isToday ? "today" : "");
var dayName = day.ToString("ddd", culture); var dayName = day.ToString("ddd", culture);
var hasEvents = _eventsCache.ContainsKey(day.Date); var hasEvents = _eventsCache.ContainsKey(day.Date);
var eventCategories = hasEvents ? GetFilteredCategoriesForDay(day.Date) : Array.Empty<CategoryData>(); var eventCategories = hasEvents ? GetFilteredCategoriesForDay(day.Date) : [];
_weekDaysData[i] = new DayData(day, cssClass, eventCategories.Length > 0, eventCategories, dayName); _weekDaysData[i] = new DayData(day, cssClass, eventCategories.Length > 0, eventCategories, dayName);
} }

View File

@@ -121,7 +121,7 @@
flex-direction: column; flex-direction: column;
-ms-overflow-style: none; -ms-overflow-style: none;
scrollbar-width: none; scrollbar-width: none;
padding-bottom: 60px; padding-bottom: 70px;
height: calc(100% - 130px); height: calc(100% - 130px);
} }

View File

@@ -27,17 +27,16 @@ else
</div> </div>
<MudButton OnClick="SignInUser" Color="Color.Primary" Variant="Variant.Filled">Login</MudButton> <MudButton OnClick="SignInUser" Color="Color.Primary" Variant="Variant.Filled">Login</MudButton>
@if (_attemptFailed)
{
<MudAlert Class="my-3" Dense="true" Severity="Severity.Error" Variant="Variant.Filled">@ErrorMessage</MudAlert>
}
</div> </div>
<div class="my-4 login-footer"> <div class="my-4 login-footer">
<span>Powered by</span> <span>Powered by</span>
<img src="_content/Template.Shared/images/logoIntegry.svg" class="img-fluid" alt="Integry"> <img src="_content/Template.Shared/images/logoIntegry.svg" class="img-fluid" alt="Integry">
</div> </div>
@if (_attemptFailed)
{
<MudAlert Class="my-3" Dense="true" Severity="Severity.Error" Variant="Variant.Filled">@ErrorMessage</MudAlert>
}
</div> </div>
</div> </div>
} }

View File

@@ -2,7 +2,7 @@
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background: hsl(from var(--mud-palette-primary) h s 96%); background: var(--mud-palette-surface);
} }
.container-top-logo > span { .container-top-logo > span {
@@ -22,6 +22,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
z-index: 10;
} }
.login-form-container { .login-form-container {
@@ -31,20 +32,17 @@
} }
.container-login { .container-login {
background: var(--mud-palette-surface);
border-top-left-radius: 16px;
border-top-right-radius: 16px;
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 4px 16px 16px; padding: 4px 16px 16px;
box-shadow: 0 -2px 10px rgba(165, 165, 165, 0.5); justify-content: space-between;
} }
.login-footer { .login-footer {
width: 100%;
display: flex; display: flex;
align-items: center; justify-content: center;
justify-content: flex-end;
} }
.login-footer span { .login-footer span {

View File

@@ -8,7 +8,7 @@
@inject INetworkService NetworkService @inject INetworkService NetworkService
@inject IFormFactor FormFactor @inject IFormFactor FormFactor
<HeaderLayout Title="Profilo"/> <HeaderLayout BackTo="Indietro" Back="true" BackOnTop="true" Title="Profilo" ShowProfile="false"/>
<div class="container content"> <div class="container content">
<div class="container-primary-info"> <div class="container-primary-info">

View File

@@ -2,7 +2,7 @@
@page "/settings/{BackTo}" @page "/settings/{BackTo}"
@using Template.Shared.Components.Layout @using Template.Shared.Components.Layout
<HeaderLayout BackTo="@BackTo" ShowNotifications="false" Back="true" Title="Impostazioni"/> <HeaderLayout BackTo="@BackTo" Back="true" Title="Impostazioni"/>
<div class="content"> <div class="content">

View File

@@ -9,7 +9,7 @@
<MudDialog Class="customDialog-form"> <MudDialog Class="customDialog-form">
<DialogContent> <DialogContent>
<HeaderLayout Cancel="true" OnCancel="() => MudDialog.Cancel()" LabelSave="@LabelSave" OnSave="Save" ShowNotifications="false" Title="@(IsNew ? "Nuova" : $"{ActivityModel.ActivityId}")" /> <HeaderLayout ShowProfile="false" Cancel="true" OnCancel="() => MudDialog.Cancel()" LabelSave="@LabelSave" OnSave="Save" Title="@(IsNew ? "Nuova" : $"{ActivityModel.ActivityId}")" />
<div class="content"> <div class="content">
<div class="input-card"> <div class="input-card">

View File

@@ -183,6 +183,16 @@ h1:focus { outline: none; }
font-size: .9rem; font-size: .9rem;
} }
.container {
padding-right: var(--m-page-x) !important;
padding-left: var(--m-page-x) !important;
}
.lm-container {
padding-right: calc(var(--m-page-x) * 0.5) !important;
padding-left: calc(var(--m-page-x) * 0.5) !important;
}
@supports (-webkit-touch-callout: none) { @supports (-webkit-touch-callout: none) {
.status-bar-safe-area { .status-bar-safe-area {
display: flex; display: flex;

View File

@@ -6,4 +6,5 @@
--card-shadow: 5px 5px 10px 0 var(--gray-for-shadow); --card-shadow: 5px 5px 10px 0 var(--gray-for-shadow);
--custom-box-shadow: 1px 2px 5px rgba(165, 165, 165, 0.5); --custom-box-shadow: 1px 2px 5px rgba(165, 165, 165, 0.5);
--mud-default-borderradius: 12px !important; --mud-default-borderradius: 12px !important;
--m-page-x: 1.25rem;
} }

View File

@@ -0,0 +1,26 @@
window.blazorIosHeader = {
init: function () {
const largeTitleSection = document.querySelector('.large-title-section');
const largeTitle = document.querySelector('.large-title');
const centerTitle = document.querySelector('.center-title');
if (!largeTitleSection || !largeTitle || !centerTitle) return;
window.addEventListener('scroll', function () {
// Soglia simile a iOS: metà della sezione large title
const threshold = largeTitleSection.offsetHeight / 2;
if (window.scrollY > threshold) {
largeTitle.classList.add('hide');
centerTitle.classList.add('visible');
} else {
largeTitle.classList.remove('hide');
centerTitle.classList.remove('visible');
}
});
}
};
// Per compatibilità con il tuo GoBack Blazor
window.goBack = function () {
window.history.back();
}