From 82d268d9f830f427c7cac2b9e01e6565456f0dd5 Mon Sep 17 00:00:00 2001 From: MarcoE Date: Mon, 8 Sep 2025 10:24:50 +0200 Subject: [PATCH] =?UTF-8?q?Implementato=20controllo=20conessione=20disposi?= =?UTF-8?q?tivo=20e=20servizi.=20Completata=20pagination=20commesse=20e=20?= =?UTF-8?q?attivit=C3=A0=20per=20cliente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Core/Services/ManageDataService.cs | 8 +- .../Core/Services/NetworkService.cs | 4 +- salesbook.Maui/MauiProgram.cs | 2 +- .../Components/Layout/MainLayout.razor | 110 +++++- .../Components/Pages/Commessa.razor | 7 +- salesbook.Shared/Components/Pages/Home.razor | 2 +- salesbook.Shared/Components/Pages/Login.razor | 4 +- .../Components/Pages/PersonalInfo.razor | 4 +- salesbook.Shared/Components/Pages/User.razor | 337 +++++++++++++----- .../Components/Pages/User.razor.css | 19 +- .../SingleElements/Card/ActivityCard.razor | 22 +- .../SingleElements/Card/UserCard.razor | 19 +- .../SingleElements/Modal/ActivityForm.razor | 18 +- .../SingleElements/Modal/ContactForm.razor | 4 +- .../SingleElements/Modal/PersRifForm.razor | 2 +- .../Activity/CRMRetrieveActivityRequestDTO.cs | 3 + .../Core/Dto/PageState/UserPageState.cs | 4 +- .../Core/Interface/IIntegryApiService.cs | 2 + .../Core/Interface/INetworkService.cs | 2 + .../Core/Services/IntegryApiService.cs | 13 + salesbook.Shared/wwwroot/css/app.css | 36 ++ salesbook.Shared/wwwroot/js/main.js | 45 ++- salesbook.Web/Core/Services/NetworkService.cs | 2 + 23 files changed, 530 insertions(+), 139 deletions(-) diff --git a/salesbook.Maui/Core/Services/ManageDataService.cs b/salesbook.Maui/Core/Services/ManageDataService.cs index bf9fc14..9b6dc26 100644 --- a/salesbook.Maui/Core/Services/ManageDataService.cs +++ b/salesbook.Maui/Core/Services/ManageDataService.cs @@ -26,7 +26,7 @@ public class ManageDataService( whereCond ??= new WhereCondContact(); whereCond.OnlyContact = true; - if (networkService.IsNetworkAvailable()) + if (networkService.ConnectionAvailable) { var response = await integryApiService.RetrieveAnagClie( new CRMAnagRequestDTO @@ -58,7 +58,7 @@ public class ManageDataService( whereCond ??= new WhereCondContact(); whereCond.OnlyContact = true; - if (networkService.IsNetworkAvailable()) + if (networkService.ConnectionAvailable) { var response = await integryApiService.RetrieveProspect( new CRMProspectRequestDTO @@ -88,7 +88,7 @@ public class ManageDataService( List? prospectList; whereCond ??= new WhereCondContact(); - if (networkService.IsNetworkAvailable()) + if (networkService.ConnectionAvailable) { var clienti = await integryApiService.RetrieveAnagClie( new CRMAnagRequestDTO @@ -160,7 +160,7 @@ public class ManageDataService( { List? activities; - if (networkService.IsNetworkAvailable() && !useLocalDb) + if (networkService.ConnectionAvailable && !useLocalDb) { activities = await integryApiService.RetrieveActivity( new CRMRetrieveActivityRequestDTO diff --git a/salesbook.Maui/Core/Services/NetworkService.cs b/salesbook.Maui/Core/Services/NetworkService.cs index 4545bcc..5920c78 100644 --- a/salesbook.Maui/Core/Services/NetworkService.cs +++ b/salesbook.Maui/Core/Services/NetworkService.cs @@ -4,9 +4,11 @@ namespace salesbook.Maui.Core.Services; public class NetworkService : INetworkService { + public bool ConnectionAvailable { get; set; } + public bool IsNetworkAvailable() { - return false; + //return false; return Connectivity.Current.NetworkAccess == NetworkAccess.Internet; } diff --git a/salesbook.Maui/MauiProgram.cs b/salesbook.Maui/MauiProgram.cs index 6fed6d9..fac4479 100644 --- a/salesbook.Maui/MauiProgram.cs +++ b/salesbook.Maui/MauiProgram.cs @@ -54,7 +54,6 @@ namespace salesbook.Maui builder.Services.AddScoped(provider => provider.GetRequiredService()); - builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -80,6 +79,7 @@ namespace salesbook.Maui builder.Services.AddSingleton(); builder.Services.AddSingleton(); + builder.Services.AddSingleton(); builder.Services.AddSingleton(); return builder.Build(); diff --git a/salesbook.Shared/Components/Layout/MainLayout.razor b/salesbook.Shared/Components/Layout/MainLayout.razor index 0130251..eb1300e 100644 --- a/salesbook.Shared/Components/Layout/MainLayout.razor +++ b/salesbook.Shared/Components/Layout/MainLayout.razor @@ -1,10 +1,11 @@ @using System.Globalization -@using CommunityToolkit.Mvvm.Messaging +@using salesbook.Shared.Core.Interface @using salesbook.Shared.Core.Messages.Back @inherits LayoutComponentBase @inject IJSRuntime JS -@inject IMessenger Messenger @inject BackNavigationService BackService +@inject INetworkService NetworkService +@inject IIntegryApiService IntegryApiService @@ -13,13 +14,33 @@
+ +
+ @if (IsNetworkAvailable) + { + if(ServicesIsDown) + { + + Servizi offline + } + else + { + + Online + } + } + else + { + + Nessuna connessione + } +
@Body
-
@code { @@ -27,6 +48,50 @@ private bool IsDarkMode { get; set; } private string _mainContentClass = ""; + //Connection state + private bool FirstCheck { get; set; } = true; + private bool _isNetworkAvailable; + private bool _servicesIsDown; + private bool _showWarning; + + private DateTime _lastApiCheck = DateTime.MinValue; + private int _delaySeconds = 3; + + private CancellationTokenSource? _cts; + + private bool ServicesIsDown + { + get => _servicesIsDown; + set + { + if (_servicesIsDown == value) return; + _servicesIsDown = value; + StateHasChanged(); + } + } + + private bool IsNetworkAvailable + { + get => _isNetworkAvailable; + set + { + if (_isNetworkAvailable == value) return; + _isNetworkAvailable = value; + StateHasChanged(); + } + } + + private bool ShowWarning + { + get => _showWarning; + set + { + if (_showWarning == value) return; + _showWarning = value; + StateHasChanged(); + } + } + private readonly MudTheme _currentTheme = new() { PaletteLight = new PaletteLight() @@ -81,6 +146,9 @@ protected override void OnInitialized() { + _cts = new CancellationTokenSource(); + _ = CheckConnectionState(_cts.Token); + BackService.OnHardwareBack += async () => { await JS.InvokeVoidAsync("goBack"); }; var culture = new CultureInfo("it-IT", false); @@ -89,4 +157,40 @@ CultureInfo.CurrentUICulture = culture; } + private Task CheckConnectionState(CancellationToken token) + { + return Task.Run(async () => + { + while (!token.IsCancellationRequested) + { + var isNetworkAvailable = NetworkService.IsNetworkAvailable(); + var servicesDown = ServicesIsDown; + + if (isNetworkAvailable && (DateTime.UtcNow - _lastApiCheck).TotalSeconds >= _delaySeconds) + { + servicesDown = !await IntegryApiService.SystemOk(); + _lastApiCheck = DateTime.UtcNow; + } + + await InvokeAsync(async () => + { + IsNetworkAvailable = isNetworkAvailable; + ServicesIsDown = servicesDown; + + await Task.Delay(1500, token); + ShowWarning = !(IsNetworkAvailable && !ServicesIsDown); + NetworkService.ConnectionAvailable = !ShowWarning; + }); + + await Task.Delay(500, token); + } + }, token); + } + + public void Dispose() + { + _cts?.Cancel(); + _cts?.Dispose(); + } + } \ No newline at end of file diff --git a/salesbook.Shared/Components/Pages/Commessa.razor b/salesbook.Shared/Components/Pages/Commessa.razor index 42675a2..24d8b14 100644 --- a/salesbook.Shared/Components/Pages/Commessa.razor +++ b/salesbook.Shared/Components/Pages/Commessa.razor @@ -78,7 +78,7 @@ else {
- +
} @@ -148,7 +148,10 @@ else await Task.Run(async () => { var activities = await IntegryApiService.RetrieveActivity(new CRMRetrieveActivityRequestDTO { CodJcom = CodJcom }); - ActivityList = Mapper.Map>(activities); + ActivityList = Mapper.Map>(activities) + .OrderBy(x => + (x.EffectiveTime ?? x.EstimatedTime) ?? x.DataInsAct + ).ToList(); }); ActivityIsLoading = false; diff --git a/salesbook.Shared/Components/Pages/Home.razor b/salesbook.Shared/Components/Pages/Home.razor index c3b7444..d8e89ab 100644 --- a/salesbook.Shared/Components/Pages/Home.razor +++ b/salesbook.Shared/Components/Pages/Home.razor @@ -15,7 +15,7 @@ { var lastSyncDate = LocalStorage.Get("last-sync"); - if (!FormFactor.IsWeb() && NetworkService.IsNetworkAvailable() && lastSyncDate.Equals(DateTime.MinValue)) + if (!FormFactor.IsWeb() && NetworkService.ConnectionAvailable && lastSyncDate.Equals(DateTime.MinValue)) { NavigationManager.NavigateTo("/sync"); return; diff --git a/salesbook.Shared/Components/Pages/Login.razor b/salesbook.Shared/Components/Pages/Login.razor index fd39faf..baafd52 100644 --- a/salesbook.Shared/Components/Pages/Login.razor +++ b/salesbook.Shared/Components/Pages/Login.razor @@ -1,8 +1,10 @@ @page "/login" @using salesbook.Shared.Components.Layout.Spinner +@using salesbook.Shared.Core.Interface @using salesbook.Shared.Core.Services @inject IUserAccountService UserAccountService @inject AppAuthenticationStateProvider AuthenticationStateProvider +@inject INetworkService NetworkService @if (Spinner) { @@ -26,7 +28,7 @@ else - Login + Login @if (_attemptFailed) { @ErrorMessage diff --git a/salesbook.Shared/Components/Pages/PersonalInfo.razor b/salesbook.Shared/Components/Pages/PersonalInfo.razor index b3f2bd3..036fcbf 100644 --- a/salesbook.Shared/Components/Pages/PersonalInfo.razor +++ b/salesbook.Shared/Components/Pages/PersonalInfo.razor @@ -39,7 +39,7 @@
Status - @if (NetworkService.IsNetworkAvailable()) + @if (NetworkService.ConnectionAvailable) {
@@ -129,7 +129,7 @@ { await Task.Run(() => { - Unavailable = FormFactor.IsWeb() || !NetworkService.IsNetworkAvailable(); + Unavailable = FormFactor.IsWeb() || !NetworkService.ConnectionAvailable; LastSync = LocalStorage.Get("last-sync"); }); diff --git a/salesbook.Shared/Components/Pages/User.razor b/salesbook.Shared/Components/Pages/User.razor index 04f9e07..0da73a8 100644 --- a/salesbook.Shared/Components/Pages/User.razor +++ b/salesbook.Shared/Components/Pages/User.razor @@ -7,6 +7,7 @@ @using salesbook.Shared.Components.Layout.Spinner @using salesbook.Shared.Core.Dto @using salesbook.Shared.Components.SingleElements +@using salesbook.Shared.Core.Dto.Activity @using salesbook.Shared.Core.Dto.JobProgress @using salesbook.Shared.Core.Dto.PageState @implements IAsyncDisposable @@ -93,6 +94,7 @@ else +
    @@ -102,6 +104,9 @@ else
  • +
  • + +
@@ -150,8 +155,8 @@ else
@@ -179,46 +184,86 @@ else
} - @if (TotalPages > 1) + @if (TotalPagesCommesse > 1) {
- +
- 5 10 - 15 + 15
+ } + + } + - - - + +
+ @if (ActivityIsLoading) + { + + } + else if (ActivityList?.Count == 0) + { + + } + else if (ActivityList != null) + { + +
+ +
+ +
+ @foreach (var activity in CurrentPageActivity) + { + } - @*
- - Visualizzate: @CurrentPageCommesse.Count() / @FilteredCommesse.Count() - - @if (!string.IsNullOrEmpty(SearchTerm)) - { - - Filtro: "@SearchTerm" - - } -
*@ + @if (TotalPagesActivity > 1) + { +
+ +
+ +
+ + 5 + 15 + 30 + +
+ }
}
+ + + + } @@ -230,75 +275,77 @@ else private ContactDTO Anag { get; set; } = new(); private List? PersRif { get; set; } private List? Commesse { get; set; } + private List ActivityList { get; set; } = []; private StbUser? Agente { get; set; } private Dictionary?> Steps { get; set; } = new(); // Stati di caricamento private bool IsLoading { get; set; } = true; private bool IsLoadingCommesse { get; set; } = true; - private bool IsLoadingSteps { get; set; } = false; - private readonly HashSet _loadingSteps = new(); + private bool ActivityIsLoading { get; set; } = true; + private bool IsLoadingSteps { get; set; } + private readonly HashSet _loadingSteps = []; // Gestione tab - private int ActiveTab { get; set; } = 0; + private int ActiveTab { get; set; } - // Paginazione e filtri - private int _currentPage = 1; - private int _selectedPageSize = 5; - private string _searchTerm = string.Empty; - private List _filteredCommesse = new(); + // Paginazione e filtri per COMMESSE + private int _selectedPageCommesse = 1; + private int _selectedPageSizeCommesse = 5; + private string _searchTermCommesse = string.Empty; + private List _filteredCommesse = []; + + // Paginazione e filtri per ATTIVITÀ + private int _currentPageActivity = 1; + private int _selectedPageSizeActivity = 5; + private string _searchTermActivity = string.Empty; + private List _filteredActivity = []; // Cancellation tokens per gestire le richieste asincrone private CancellationTokenSource? _loadingCts; private CancellationTokenSource? _stepsCts; // Timer per il debounce della ricerca - private Timer? _searchTimer; + private Timer? _searchTimerCommesse; + private Timer? _searchTimerActivity; private const int SearchDelayMs = 300; - #region Properties + #region Properties per Commesse - private int CurrentPage + private int SelectedPageCommesse { - get => _currentPage; + get => _selectedPageCommesse; set { - if (_currentPage != value) - { - _currentPage = value; - _ = LoadStepsForCurrentPageAsync(); - } + if (_selectedPageCommesse == value) return; + _selectedPageCommesse = value; + _ = LoadStepsForCurrentPageAsync(); } } - private int SelectedPageSize + private int SelectedPageSizeCommesse { - get => _selectedPageSize; + get => _selectedPageSizeCommesse; set { - if (_selectedPageSize != value) - { - _selectedPageSize = value; - _currentPage = 1; - ApplyFilters(); - _ = LoadStepsForCurrentPageAsync(); - } + if (_selectedPageSizeCommesse == value) return; + _selectedPageSizeCommesse = value; + _selectedPageCommesse = 1; + ApplyFiltersCommesse(); + _ = LoadStepsForCurrentPageAsync(); } } - private string SearchTerm + private string SearchTermCommesse { - get => _searchTerm; + get => _searchTermCommesse; set { - if (_searchTerm != value) - { - _searchTerm = value; + if (_searchTermCommesse == value) return; + _searchTermCommesse = value; - // Debounce della ricerca - _searchTimer?.Dispose(); - _searchTimer = new Timer(async _ => await InvokeAsync(ApplyFilters), null, SearchDelayMs, Timeout.Infinite); - } + _searchTimerCommesse?.Dispose(); + _searchTimerCommesse = new Timer(async _ => await InvokeAsync(ApplyFiltersCommesse), null, SearchDelayMs, Timeout.Infinite); } } @@ -312,11 +359,67 @@ else } } - private int TotalPages => - FilteredCommesse.Count == 0 ? 1 : (int)Math.Ceiling(FilteredCommesse.Count / (double)SelectedPageSize); + private int TotalPagesCommesse => + FilteredCommesse.Count == 0 ? 1 : (int)Math.Ceiling(FilteredCommesse.Count / (double)SelectedPageSizeCommesse); private IEnumerable CurrentPageCommesse => - FilteredCommesse.Skip((CurrentPage - 1) * SelectedPageSize).Take(SelectedPageSize); + FilteredCommesse.Skip((SelectedPageCommesse - 1) * SelectedPageSizeCommesse).Take(SelectedPageSizeCommesse); + + #endregion + + #region Properties per Attività + + private int CurrentPageActivityIndex + { + get => _currentPageActivity; + set + { + if (_currentPageActivity == value) return; + _currentPageActivity = value; + StateHasChanged(); + } + } + + private int SelectedPageSizeActivity + { + get => _selectedPageSizeActivity; + set + { + if (_selectedPageSizeActivity == value) return; + _selectedPageSizeActivity = value; + _currentPageActivity = 1; + ApplyFiltersActivity(); + } + } + + private string SearchTermActivity + { + get => _searchTermActivity; + set + { + if (_searchTermActivity == value) return; + _searchTermActivity = value; + + _searchTimerActivity?.Dispose(); + _searchTimerActivity = new Timer(async _ => await InvokeAsync(ApplyFiltersActivity), null, SearchDelayMs, Timeout.Infinite); + } + } + + private List FilteredActivity + { + get => _filteredActivity; + set + { + _filteredActivity = value; + StateHasChanged(); + } + } + + private int TotalPagesActivity => + FilteredActivity.Count == 0 ? 1 : (int)Math.Ceiling(FilteredActivity.Count / (double)SelectedPageSizeActivity); + + private IEnumerable CurrentPageActivity => + FilteredActivity.Skip((CurrentPageActivityIndex - 1) * SelectedPageSizeActivity).Take(SelectedPageSizeActivity); #endregion @@ -339,7 +442,6 @@ else } catch (Exception ex) { - // Log dell'errore Console.WriteLine($"Errore in OnInitializedAsync: {ex.Message}"); } finally @@ -351,11 +453,12 @@ else public async ValueTask DisposeAsync() { - _loadingCts?.Cancel(); + _loadingCts?.CancelAsync(); _loadingCts?.Dispose(); - _stepsCts?.Cancel(); + _stepsCts?.CancelAsync(); _stepsCts?.Dispose(); - _searchTimer?.Dispose(); + _searchTimerCommesse?.DisposeAsync(); + _searchTimerActivity?.DisposeAsync(); } #endregion @@ -366,21 +469,18 @@ else { try { - // Caricamento dati principali await LoadAnagAsync(); await LoadPersRifAsync(); + _ = LoadActivity(); - // Caricamento agente if (!string.IsNullOrEmpty(Anag.CodVage)) { Agente = (await ManageData.GetTable(x => x.UserCode != null && x.UserCode.Equals(Anag.CodVage))) .LastOrDefault(); } - // Salvataggio in sessione SaveDataToSession(); - // Caricamento commesse in background _ = Task.Run(async () => await LoadCommesseAsync()); } catch (Exception ex) @@ -393,12 +493,12 @@ else { if (IsContact) { - var clie = (await ManageData.GetTable(x => x.CodAnag.Equals(CodContact))).Last(); + var clie = (await ManageData.GetTable(x => x.CodAnag!.Equals(CodContact))).Last(); Anag = Mapper.Map(clie); } else { - var pros = (await ManageData.GetTable(x => x.CodPpro.Equals(CodContact))).Last(); + var pros = (await ManageData.GetTable(x => x.CodPpro!.Equals(CodContact))).Last(); Anag = Mapper.Map(pros); } } @@ -407,16 +507,35 @@ else { if (IsContact) { - var pers = await ManageData.GetTable(x => x.CodAnag.Equals(Anag.CodContact)); + var pers = await ManageData.GetTable(x => x.CodAnag!.Equals(Anag.CodContact)); PersRif = Mapper.Map>(pers); } else { - var pers = await ManageData.GetTable(x => x.CodPpro.Equals(Anag.CodContact)); + var pers = await ManageData.GetTable(x => x.CodPpro!.Equals(Anag.CodContact)); PersRif = Mapper.Map>(pers); } } + private async Task LoadActivity() + { + await Task.Run(async () => + { + var activities = await IntegryApiService.RetrieveActivity(new CRMRetrieveActivityRequestDTO { CodAnag = Anag.CodContact }); + ActivityList = Mapper.Map>(activities) + .OrderByDescending(x => + (x.EffectiveTime ?? x.EstimatedTime) ?? x.DataInsAct + ).ToList(); + }); + + UserState.Activitys = ActivityList; + + ApplyFiltersActivity(); + + ActivityIsLoading = false; + StateHasChanged(); + } + private async Task LoadCommesseAsync() { try @@ -425,17 +544,14 @@ else Commesse = await ManageData.GetTable(x => x.CodAnag != null && x.CodAnag.Equals(CodContact)); - // Ordinamento ottimizzato Commesse = Commesse? - .OrderByDescending(x => x.LastUpd ?? DateTime.MinValue) - .ThenByDescending(x => x.CodJcom) + .OrderByDescending(x => x.CodJcom) .ToList(); UserState.Commesse = Commesse; - ApplyFilters(); + ApplyFiltersCommesse(); - // Caricamento steps per la prima pagina await LoadStepsForCurrentPageAsync(); } catch (Exception ex) @@ -455,11 +571,14 @@ else PersRif = UserState.PersRif; Commesse = UserState.Commesse; Agente = UserState.Agente; - Steps = UserState.Steps ?? new Dictionary?>(); + Steps = UserState.Steps; + ActivityList = UserState.Activitys; - ApplyFilters(); + ApplyFiltersCommesse(); + ApplyFiltersActivity(); IsLoadingCommesse = false; + ActivityIsLoading = false; } private void SaveDataToSession() @@ -469,6 +588,7 @@ else UserState.PersRif = PersRif; UserState.Agente = Agente; UserState.Steps = Steps; + UserState.Activitys = ActivityList; } #endregion @@ -560,30 +680,32 @@ else { ActiveTab = tabIndex; - // Se si passa alle commesse e non sono ancora state caricate if (tabIndex == 1 && Commesse == null) { _ = Task.Run(async () => await LoadCommesseAsync()); - } else if (tabIndex == 1 && Steps.IsNullOrEmpty()) + } + else if (tabIndex == 1 && Steps.IsNullOrEmpty()) { _ = Task.Run(async () => await LoadStepsForCurrentPageAsync()); } + else if (tabIndex == 2 && ActivityList?.Count == 0) + { + _ = Task.Run(async () => await LoadActivity()); + } } - private void ApplyFilters() + private void ApplyFiltersCommesse() { if (Commesse == null) { - FilteredCommesse = new List(); + FilteredCommesse = []; return; } var filtered = Commesse.AsEnumerable(); - - // Filtro per testo di ricerca - if (!string.IsNullOrWhiteSpace(SearchTerm)) + if (!string.IsNullOrWhiteSpace(SearchTermCommesse)) { - var searchLower = SearchTerm.ToLowerInvariant(); + var searchLower = SearchTermCommesse.ToLowerInvariant(); filtered = filtered.Where(c => c.CodJcom?.ToLowerInvariant().Contains(searchLower) == true || c.Descrizione?.ToLowerInvariant().Contains(searchLower) == true || @@ -591,21 +713,40 @@ else } FilteredCommesse = filtered.ToList(); + if (SelectedPageCommesse > TotalPagesCommesse && TotalPagesCommesse > 0) _selectedPageCommesse = 1; - // Reset della pagina se necessario - if (CurrentPage > TotalPages && TotalPages > 0) - { - _currentPage = 1; - } - - // Carica gli steps per la pagina corrente _ = LoadStepsForCurrentPageAsync(); } - private void ClearSearch() + private void ApplyFiltersActivity() { - SearchTerm = string.Empty; - ApplyFilters(); + var filtered = ActivityList.AsEnumerable(); + + if (!string.IsNullOrWhiteSpace(SearchTermActivity)) + { + var searchLower = SearchTermActivity.ToLowerInvariant(); + filtered = filtered.Where(a => + a.ActivityDescription?.ToLowerInvariant().Contains(searchLower) == true || + a.ActivityId?.ToLowerInvariant().Contains(searchLower) == true); + } + + FilteredActivity = filtered.ToList(); + if (CurrentPageActivityIndex > TotalPagesActivity && TotalPagesActivity > 0) + { + _currentPageActivity = 1; + } + } + + private void ClearSearchCommesse() + { + SearchTermCommesse = string.Empty; + ApplyFiltersCommesse(); + } + + private void ClearSearchActivity() + { + SearchTermActivity = string.Empty; + ApplyFiltersActivity(); } #endregion @@ -629,12 +770,10 @@ else if (result is { Canceled: false }) { - // Aggiorna i dati se necessario await LoadAnagAsync(); SaveDataToSession(); } } #endregion - } \ No newline at end of file diff --git a/salesbook.Shared/Components/Pages/User.razor.css b/salesbook.Shared/Components/Pages/User.razor.css index af8db86..b69a8da 100644 --- a/salesbook.Shared/Components/Pages/User.razor.css +++ b/salesbook.Shared/Components/Pages/User.razor.css @@ -165,10 +165,15 @@ gap: 1.25rem; } +.attivita-container { + display: flex; + flex-direction: column; + gap: 1.25rem; +} + /*-------------- TabPanel ----------------*/ - .box { display: flex; flex-direction: column; @@ -199,7 +204,7 @@ content: ''; display: block; height: 3px; - width: calc(100% / 2); + width: calc(100% / 3); position: absolute; bottom: 0; left: 0; @@ -223,7 +228,8 @@ /* tab attivo */ #tab1:checked ~ .box .tab-list .tab-item:nth-child(1), -#tab2:checked ~ .box .tab-list .tab-item:nth-child(2) { +#tab2:checked ~ .box .tab-list .tab-item:nth-child(2), +#tab3:checked ~ .box .tab-list .tab-item:nth-child(3) { opacity: 1; font-weight: bold; display: block; @@ -235,6 +241,8 @@ #tab2:checked ~ .box .tab-list::before { transform: translateX(100%); } +#tab3:checked ~ .box .tab-list::before { transform: translateX(200%); } + .tab-container { display: flex; flex-direction: column; @@ -257,7 +265,10 @@ } #tab1:checked ~ .tab-container .tab-content:nth-child(1), -#tab2:checked ~ .tab-container .tab-content:nth-child(2) { display: block; } +#tab2:checked ~ .tab-container .tab-content:nth-child(2), +#tab3:checked ~ .tab-container .tab-content:nth-child(3) { + display: block; +} @keyframes fade { from { diff --git a/salesbook.Shared/Components/SingleElements/Card/ActivityCard.razor b/salesbook.Shared/Components/SingleElements/Card/ActivityCard.razor index 9217641..7fa75f1 100644 --- a/salesbook.Shared/Components/SingleElements/Card/ActivityCard.razor +++ b/salesbook.Shared/Components/SingleElements/Card/ActivityCard.razor @@ -29,11 +29,25 @@ @if (Activity.EffectiveTime is null) { - @($"{Activity.EstimatedTime:t}") + if (ShowDate) + { + @($"{Activity.EstimatedTime:g}") + } + else + { + @($"{Activity.EstimatedTime:t}") + } } else { - @($"{Activity.EffectiveTime:t}") + if (ShowDate) + { + @($"{Activity.EffectiveTime:g}") + } + else + { + @($"{Activity.EffectiveTime:t}") + } } @@ -68,6 +82,8 @@ [Parameter] public EventCallback ActivityChanged { get; set; } [Parameter] public EventCallback ActivityDeleted { get; set; } + [Parameter] public bool ShowDate { get; set; } + private TimeSpan? Durata { get; set; } protected override void OnParametersSet() @@ -82,7 +98,7 @@ private async Task OpenActivity() { - var result = await ModalHelpers.OpenActivityForm(Dialog, null, Activity.ActivityId); + var result = await ModalHelpers.OpenActivityForm(Dialog, Activity, null); switch (result) { diff --git a/salesbook.Shared/Components/SingleElements/Card/UserCard.razor b/salesbook.Shared/Components/SingleElements/Card/UserCard.razor index ec53244..ef46fd5 100644 --- a/salesbook.Shared/Components/SingleElements/Card/UserCard.razor +++ b/salesbook.Shared/Components/SingleElements/Card/UserCard.razor @@ -25,11 +25,23 @@ @if (!Commesse.IsNullOrEmpty()) {
- @foreach (var commessa in Commesse!) + + @for (var i = 0; i < Commesse!.Count; i++) { + var commessa = Commesse[i]; +
- @($"{commessa.CodJcom} - {commessa.Descrizione}") + @if (i > 5 && Commesse.Count - i > 1) + { + @($"E altre {Commesse.Count - i} commesse") + } + else + { + @($"{commessa.CodJcom} - {commessa.Descrizione}") + }
+ + @if (i > 5 && Commesse.Count - i > 1) break; }
} @@ -63,7 +75,8 @@ if (ShowSectionCommesse) { - Commesse = await ManageData.GetTable(x => x.CodAnag.Equals(User.CodContact)); + Commesse = (await ManageData.GetTable(x => x.CodAnag.Equals(User.CodContact))) + .OrderByDescending(x => x.CodJcom).ToList(); IsLoading = false; StateHasChanged(); return; diff --git a/salesbook.Shared/Components/SingleElements/Modal/ActivityForm.razor b/salesbook.Shared/Components/SingleElements/Modal/ActivityForm.razor index c0ad846..b180839 100644 --- a/salesbook.Shared/Components/SingleElements/Modal/ActivityForm.razor +++ b/salesbook.Shared/Components/SingleElements/Modal/ActivityForm.razor @@ -250,8 +250,8 @@ private List Pros { get; set; } = []; private List? ActivityFileList { get; set; } - private bool IsNew => Id.IsNullOrEmpty(); - private bool IsView => !NetworkService.IsNetworkAvailable(); + private bool IsNew { get; set; } + private bool IsView => !NetworkService.ConnectionAvailable; private string? LabelSave { get; set; } @@ -276,18 +276,18 @@ { Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter; - _ = LoadData(); - - LabelSave = IsNew ? "Aggiungi" : null; - - if (!Id.IsNullOrEmpty()) - ActivityModel = (await ManageData.GetActivity(new WhereCondActivity { ActivityId = Id }, true)).Last(); - if (ActivityCopied != null) { ActivityModel = ActivityCopied.Clone(); } + else if (!Id.IsNullOrEmpty()) + ActivityModel = (await ManageData.GetActivity(new WhereCondActivity { ActivityId = Id }, true)).Last(); + if (Id.IsNullOrEmpty()) Id = ActivityModel.ActivityId; + IsNew = Id.IsNullOrEmpty(); + LabelSave = IsNew ? "Aggiungi" : null; + + _ = LoadData(); await LoadCommesse(); if (IsNew) diff --git a/salesbook.Shared/Components/SingleElements/Modal/ContactForm.razor b/salesbook.Shared/Components/SingleElements/Modal/ContactForm.razor index 337fa94..8b6ffbd 100644 --- a/salesbook.Shared/Components/SingleElements/Modal/ContactForm.razor +++ b/salesbook.Shared/Components/SingleElements/Modal/ContactForm.razor @@ -280,7 +280,7 @@ } else { - @if (NetworkService.IsNetworkAvailable() && !ContactModel.IsContact) + @if (NetworkService.ConnectionAvailable && !ContactModel.IsContact) { Users { get; set; } = []; private bool IsNew => OriginalModel is null; - private bool IsView => !NetworkService.IsNetworkAvailable(); + private bool IsView => !NetworkService.ConnectionAvailable; private string? LabelSave { get; set; } diff --git a/salesbook.Shared/Components/SingleElements/Modal/PersRifForm.razor b/salesbook.Shared/Components/SingleElements/Modal/PersRifForm.razor index b95a1ac..3e107ae 100644 --- a/salesbook.Shared/Components/SingleElements/Modal/PersRifForm.razor +++ b/salesbook.Shared/Components/SingleElements/Modal/PersRifForm.razor @@ -118,7 +118,7 @@ private PersRifDTO PersRifModel { get; set; } = new(); private bool IsNew => OriginalModel is null; - private bool IsView => !NetworkService.IsNetworkAvailable(); + private bool IsView => !NetworkService.ConnectionAvailable; private string? LabelSave { get; set; } diff --git a/salesbook.Shared/Core/Dto/Activity/CRMRetrieveActivityRequestDTO.cs b/salesbook.Shared/Core/Dto/Activity/CRMRetrieveActivityRequestDTO.cs index 44e201a..4da291b 100644 --- a/salesbook.Shared/Core/Dto/Activity/CRMRetrieveActivityRequestDTO.cs +++ b/salesbook.Shared/Core/Dto/Activity/CRMRetrieveActivityRequestDTO.cs @@ -10,6 +10,9 @@ public class CRMRetrieveActivityRequestDTO [JsonPropertyName("activityId")] public string? ActivityId { get; set; } + [JsonPropertyName("codAnag")] + public string? CodAnag { get; set; } + [JsonPropertyName("codJcom")] public string? CodJcom { get; set; } diff --git a/salesbook.Shared/Core/Dto/PageState/UserPageState.cs b/salesbook.Shared/Core/Dto/PageState/UserPageState.cs index a437ea1..efecc2a 100644 --- a/salesbook.Shared/Core/Dto/PageState/UserPageState.cs +++ b/salesbook.Shared/Core/Dto/PageState/UserPageState.cs @@ -1,4 +1,5 @@ -using salesbook.Shared.Core.Dto.JobProgress; +using salesbook.Shared.Core.Dto.Activity; +using salesbook.Shared.Core.Dto.JobProgress; using salesbook.Shared.Core.Entity; namespace salesbook.Shared.Core.Dto.PageState; @@ -12,4 +13,5 @@ public class UserPageState public List Commesse { get; set; } public StbUser? Agente { get; set; } public Dictionary?> Steps { get; set; } + public List Activitys { get; set; } } \ No newline at end of file diff --git a/salesbook.Shared/Core/Interface/IIntegryApiService.cs b/salesbook.Shared/Core/Interface/IIntegryApiService.cs index 80d7915..a8fdc7d 100644 --- a/salesbook.Shared/Core/Interface/IIntegryApiService.cs +++ b/salesbook.Shared/Core/Interface/IIntegryApiService.cs @@ -8,6 +8,8 @@ namespace salesbook.Shared.Core.Interface; public interface IIntegryApiService { + Task SystemOk(); + Task?> RetrieveActivity(CRMRetrieveActivityRequestDTO activityRequest); Task?> RetrieveAllCommesse(string? dateFilter = null); Task RetrieveAnagClie(CRMAnagRequestDTO request); diff --git a/salesbook.Shared/Core/Interface/INetworkService.cs b/salesbook.Shared/Core/Interface/INetworkService.cs index d397c46..1bec94c 100644 --- a/salesbook.Shared/Core/Interface/INetworkService.cs +++ b/salesbook.Shared/Core/Interface/INetworkService.cs @@ -2,5 +2,7 @@ public interface INetworkService { + public bool ConnectionAvailable { get; set; } + public bool IsNetworkAvailable(); } \ No newline at end of file diff --git a/salesbook.Shared/Core/Services/IntegryApiService.cs b/salesbook.Shared/Core/Services/IntegryApiService.cs index b12cb7a..c138b68 100644 --- a/salesbook.Shared/Core/Services/IntegryApiService.cs +++ b/salesbook.Shared/Core/Services/IntegryApiService.cs @@ -13,6 +13,19 @@ namespace salesbook.Shared.Core.Services; public class IntegryApiService(IIntegryApiRestClient integryApiRestClient, IUserSession userSession) : IIntegryApiService { + public async Task SystemOk() + { + try + { + await integryApiRestClient.Get("system/ok"); + return true; + } + catch (Exception e) + { + return false; + } + } + public Task?> RetrieveActivity(CRMRetrieveActivityRequestDTO activityRequest) => integryApiRestClient.AuthorizedPost?>("crm/retrieveActivity", activityRequest); diff --git a/salesbook.Shared/wwwroot/css/app.css b/salesbook.Shared/wwwroot/css/app.css index ba538cb..076314e 100644 --- a/salesbook.Shared/wwwroot/css/app.css +++ b/salesbook.Shared/wwwroot/css/app.css @@ -22,6 +22,42 @@ a, .btn-link { color: inherit; } +/*ServicesIsDown" : "SystemOk" : "NetworkKo*/ + +.Connection { + padding: 0 .75rem; + font-weight: 700; + display: flex; + flex-direction: row; + gap: 1rem; + font-size: larger; + transition: all 0.5s ease; + opacity: 0; + transform: translateY(-35px); + min-height: 35px; + align-items: center; +} + +.Connection.ServicesIsDown, .Connection.NetworkKo { + background-color: var(--mud-palette-error); + color: white; +} + +.Connection.SystemOk { + background-color: var(--mud-palette-success); + color: white; +} + +.Connection.Show { + opacity: 1; + transform: translateY(0); +} + +.page > .Connection.Hide ~ main { + transition: all 0.5s ease; + transform: translateY(-35px); +} + .btn-primary { color: #fff; background-color: var(--primary-color); diff --git a/salesbook.Shared/wwwroot/js/main.js b/salesbook.Shared/wwwroot/js/main.js index 5826476..b050ae1 100644 --- a/salesbook.Shared/wwwroot/js/main.js +++ b/salesbook.Shared/wwwroot/js/main.js @@ -38,16 +38,41 @@ function monitorExpandedClass(mutations) { }); } +// Funzione per monitorare bottom-sheet-container e gestire la navbar +function monitorBottomSheetClass(mutations) { + const bottomSheet = document.querySelector(".bottom-sheet-container"); + const navbar = document.querySelector(".animated-navbar"); + + if (!bottomSheet || !navbar) return; + + mutations.forEach(function (mutation) { + if (mutation.type === 'attributes' && mutation.attributeName === 'class' && mutation.target === bottomSheet) { + if (bottomSheet.classList.contains("show")) { + navbar.classList.remove("show-nav"); + navbar.classList.add("hide-nav"); + console.log("Navbar nascosta (hide-nav)"); + } else { + navbar.classList.remove("hide-nav"); + navbar.classList.add("show-nav"); + console.log("Navbar mostrata (show-nav)"); + } + } + }); +} + // Esegui la funzione tabindex inizialmente addTabindexToButtons(); -// Observer combinato per entrambe le funzionalità +// Observer combinato per tutte le funzionalità const observer = new MutationObserver((mutations) => { // Aggiungi tabindex ai nuovi bottoni addTabindexToButtons(); // Monitora le classi expanded monitorExpandedClass(mutations); + + // Monitora bottom-sheet-container + monitorBottomSheetClass(mutations); }); // Osserva sia i cambiamenti nel DOM che gli attributi @@ -56,4 +81,20 @@ observer.observe(document.body, { subtree: true, attributes: true, attributeFilter: ['class'] -}); \ No newline at end of file +}); + +// Sync iniziale per la navbar (nel caso la pagina parte già con .show) +document.addEventListener("DOMContentLoaded", () => { + const bottomSheet = document.querySelector(".bottom-sheet-container"); + const navbar = document.querySelector(".animated-navbar"); + + if (bottomSheet && navbar) { + if (bottomSheet.classList.contains("show")) { + navbar.classList.remove("show-nav"); + navbar.classList.add("hide-nav"); + } else { + navbar.classList.remove("hide-nav"); + navbar.classList.add("show-nav"); + } + } +}); diff --git a/salesbook.Web/Core/Services/NetworkService.cs b/salesbook.Web/Core/Services/NetworkService.cs index 918d89e..64b4044 100644 --- a/salesbook.Web/Core/Services/NetworkService.cs +++ b/salesbook.Web/Core/Services/NetworkService.cs @@ -4,6 +4,8 @@ namespace salesbook.Web.Core.Services; public class NetworkService : INetworkService { + public bool ConnectionAvailable { get; set; } + public bool IsNetworkAvailable() { return true;