Cancellazione attività

This commit is contained in:
2025-06-26 09:26:50 +02:00
parent 10c1435dba
commit a34e673cd2
38 changed files with 443 additions and 231 deletions

View File

@@ -1,7 +1,9 @@
@using System.Globalization
@using Template.Shared.Core.Messages
@using CommunityToolkit.Mvvm.Messaging
@using Template.Shared.Core.Messages.Back
@inherits LayoutComponentBase
@inject IJSRuntime JS
@inject IMessenger Messenger
@inject BackNavigationService BackService
<MudThemeProvider Theme="_currentTheme" @ref="@_mudThemeProvider" @bind-IsDarkMode="@IsDarkMode" />

View File

@@ -1,4 +1,11 @@
@using CommunityToolkit.Mvvm.Messaging
@using Template.Shared.Core.Dto
@using Template.Shared.Core.Entity
@using Template.Shared.Core.Messages.Activity.Copy
@using Template.Shared.Core.Messages.Activity.New
@inject IDialogService Dialog
@inject IMessenger Messenger
@inject CopyActivityService CopyActivityService
<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")">
@@ -39,7 +46,7 @@
</ActivatorContent>
<ChildContent>
<MudMenuItem Disabled="true">Nuovo contatto</MudMenuItem>
<MudMenuItem OnClick="() => ModalHelpers.OpenActivityForm(Dialog)">Nuova attivit<69></MudMenuItem>
<MudMenuItem OnClick="CreateActivity">Nuova attivit<69></MudMenuItem>
</ChildContent>
</MudMenu>
}
@@ -53,6 +60,8 @@
protected override Task OnInitializedAsync()
{
CopyActivityService.OnCopyActivity += async dto => await CreateActivity(dto);
NavigationManager.LocationChanged += (_, args) =>
{
var location = args.Location.Remove(0, NavigationManager.BaseUri.Length);
@@ -71,5 +80,17 @@
};
return Task.CompletedTask;
}
private Task CreateActivity() => CreateActivity(null);
private async Task CreateActivity(ActivityDTO? activity)
{
var result = await ModalHelpers.OpenActivityForm(Dialog, activity, null);
if (result is { Canceled: false, Data: not null } && result.Data.GetType() == typeof(StbActivity))
{
Messenger.Send(new NewActivityMessage(((StbActivity)result.Data).ActivityId));
}
}
}

View File

@@ -5,8 +5,11 @@
@using Template.Shared.Components.SingleElements
@using Template.Shared.Components.Layout.Spinner
@using Template.Shared.Components.SingleElements.BottomSheet
@using Template.Shared.Core.Entity
@using Template.Shared.Core.Messages.Activity.New
@inject IManageDataService ManageData
@inject IJSRuntime JS
@inject NewActivityService NewActivity
<HeaderLayout Title="@_headerTitle"
ShowFilter="true"
@@ -14,7 +17,7 @@
OnFilterToggle="ToggleFilter"
OnCalendarToggle="ToggleExpanded"/>
<div @ref="weekSliderRef" class="container week-slider @(Expanded ? "expanded" : "") @(SliderAnimation)">
<div @ref="_weekSliderRef" class="container week-slider @(Expanded ? "expanded" : "") @(SliderAnimation)">
@if (Expanded)
{
<!-- Vista mensile -->
@@ -154,7 +157,7 @@
else if (FilteredActivities is { Count: > 0 })
{
<Virtualize Items="FilteredActivities" Context="activity">
<ActivityCard Activity="activity" ActivityChanged="OnActivityChanged"/>
<ActivityCard Activity="activity" ActivityChanged="OnActivityChanged" ActivityDeleted="OnActivityDeleted" />
</Virtualize>
}
else
@@ -173,7 +176,7 @@
private record CategoryData(string CssClass, string Title);
// Cache per rendering
private DayData[] _monthDaysData = Array.Empty<DayData>();
private DayData[] _monthDaysData = [];
private readonly DayData[] _weekDaysData = new DayData[7];
private string _headerTitle = string.Empty;
private readonly Dictionary<DateTime, List<ActivityDTO>> _eventsCache = new();
@@ -181,10 +184,10 @@
private bool _isInitialized = false;
// Stato UI
private bool Expanded { get; set; } = false;
private bool Expanded { get; set; }
private string SliderAnimation { get; set; } = string.Empty;
private ElementReference weekSliderRef;
private DotNetObjectReference<Calendar>? dotNetHelper;
private ElementReference _weekSliderRef;
private DotNetObjectReference<Calendar>? _dotNetHelper;
// Stato calendario
private DateTime SelectedDate { get; set; } = DateTime.Today;
@@ -217,6 +220,8 @@
protected override void OnInitialized()
{
PrepareRenderingData();
NewActivity.OnActivityCreated += async activityId => await OnActivityCreated(activityId);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
@@ -225,8 +230,8 @@
{
Filter.User = new HashSet<string> { UserSession.User.Username };
dotNetHelper = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("calendarSwipe.register", weekSliderRef, dotNetHelper);
_dotNetHelper = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("calendarSwipe.register", _weekSliderRef, _dotNetHelper);
_internalMonth = new DateTime(SelectedDate.Year, SelectedDate.Month, 1);
await LoadMonthData();
@@ -360,13 +365,13 @@
filteredActivity = filteredActivity
.Where(x => Filter.Result.IsNullOrEmpty() || (x.ActivityResultId != null && x.ActivityResultId.Equals(Filter.Result)));
filteredActivity = filteredActivity
.Where(x => Filter.User.IsNullOrEmpty() || (x.UserName != null && Filter.User!.Contains(x.UserName)));
filteredActivity = filteredActivity
.Where(x => Filter.Category == null || x.Category.Equals(Filter.Category));
return filteredActivity.ToList();
}
@@ -526,7 +531,53 @@
public void Dispose()
{
dotNetHelper?.Dispose();
_dotNetHelper?.Dispose();
}
private async Task OnActivityDeleted(ActivityDTO activity)
{
IsLoading = true;
await ManageData.DeleteActivity(activity);
var indexActivity = MonthActivities?.FindIndex(x => x.ActivityId.Equals(activity.ActivityId));
if (indexActivity != null)
{
MonthActivities?.RemoveAt(indexActivity.Value);
PrepareRenderingData();
ApplyFilter();
}
IsLoading = false;
}
private async Task OnActivityCreated(string activityId)
{
IsLoading = true;
var activity = (await ManageData.GetActivity(x => x.ActivityId.Equals(activityId))).LastOrDefault();
if (activity == null)
{
IsLoading = false;
return;
}
var date = activity.EffectiveDate ?? activity.EstimatedDate;
if (CurrentMonth.Month != date!.Value.Month)
{
IsLoading = false;
return;
}
MonthActivities.Add(activity);
PrepareRenderingData();
IsLoading = false;
ApplyFilter();
}
private async Task OnActivityChanged(string activityId)
@@ -538,10 +589,8 @@
{
MonthActivities![indexActivity.Value] = newActivity[0];
PrepareRenderingData(); // Ricalcola i dati di rendering
ApplyFilter();
}
ApplyFilter();
StateHasChanged();
}
private void ToggleFilter()

View File

@@ -80,52 +80,4 @@
.status.online { color: var(--mud-palette-success); }
.status.offline { color: var(--mud-palette-error); }
.container-button {
width: 100%;
box-shadow: var(--custom-box-shadow);
padding: .5rem 0;
border-radius: 12px;
margin-bottom: 2rem;
}
.container-button .divider {
margin: .5rem 0 .5rem 3rem;
width: unset;
}
.container-button ::deep .button-settings { border: none !important; }
.container-button ::deep .button-settings .mud-icon-root {
border-radius: 6px;
padding: 2px;
min-width: 25px;
min-height: 25px;
}
.container-button ::deep .button-settings.green-icon .mud-icon-root {
border: 1px solid var(--mud-palette-success);
background: hsl(from var(--mud-palette-success-lighten) h s 95%);
color: var(--mud-palette-success-darken);
}
.container-button ::deep .button-settings.red-icon .mud-icon-root {
border: 1px solid var(--mud-palette-error);
background: hsl(from var(--mud-palette-error-lighten) h s 95%);
color: var(--mud-palette-error-darken);
}
.container-button ::deep .button-settings .mud-button-label {
justify-content: flex-start;
text-transform: capitalize;
font-size: 1rem;
}
.container-button ::deep .button-settings.exit { padding: 0; }
.container-button ::deep .button-settings.exit .mud-button-label {
justify-content: center;
font-size: 1.1rem;
line-height: normal;
}
.status.offline { color: var(--mud-palette-error); }

View File

@@ -65,6 +65,7 @@
@code {
[Parameter] public ActivityDTO Activity { get; set; } = new();
[Parameter] public EventCallback<string> ActivityChanged { get; set; }
[Parameter] public EventCallback<ActivityDTO> ActivityDeleted { get; set; }
private TimeSpan? Durata { get; set; }
@@ -80,11 +81,16 @@
private async Task OpenActivity()
{
var result = await ModalHelpers.OpenActivityForm(Dialog, Activity.ActivityId);
var result = await ModalHelpers.OpenActivityForm(Dialog, null, Activity.ActivityId);
if (result is { Canceled: false, Data: not null } && result.Data.GetType() == typeof(StbActivity))
switch (result)
{
await ActivityChanged.InvokeAsync(((StbActivity)result.Data).ActivityId);
case { Canceled: false, Data: not null } when result.Data.GetType() == typeof(StbActivity):
await ActivityChanged.InvokeAsync(((StbActivity)result.Data).ActivityId);
break;
case { Canceled: false, Data: not null } when result.Data.GetType() == typeof(ActivityDTO):
await ActivityDeleted.InvokeAsync((ActivityDTO)result.Data);
break;
}
}
}

View File

@@ -7,7 +7,7 @@
.c-modal {
border-radius: 16px;
box-shadow: var(--custom-box-shadow);
box-shadow: var(--exception-box-shadow);
padding: 16px;
}

View File

@@ -1,13 +1,16 @@
@using System.Globalization
@using CommunityToolkit.Mvvm.Messaging
@using Template.Shared.Core.Dto
@using Template.Shared.Components.Layout
@using Template.Shared.Core.Entity
@using Template.Shared.Core.Interface
@using Template.Shared.Components.Layout.Overlay
@using Template.Shared.Components.SingleElements.BottomSheet
@using Template.Shared.Core.Messages.Activity.Copy
@inject IManageDataService ManageData
@inject INetworkService NetworkService
@inject IIntegryApiService IntegryApiService
@inject IMessenger Messenger
<MudDialog Class="customDialog-form">
<DialogContent>
@@ -30,12 +33,19 @@
<div class="form-container">
<span class="disable-full-width">Commessa</span>
<MudSelectExtended FullWidth="true" ReadOnly="@(IsView || Commesse.IsNullOrEmpty())" T="string?" Variant="Variant.Text" @bind-Value="ActivityModel.CodJcom" @bind-Value:after="OnCommessaChanged" Class="customIcon-select" AdornmentIcon="@Icons.Material.Filled.Code">
@foreach (var com in Commesse)
{
<MudSelectItemExtended Class="custom-item-select" Value="@com.CodJcom">@($"{com.CodJcom} - {com.Descrizione}")</MudSelectItemExtended>
}
</MudSelectExtended>
@if (Commesse.IsNullOrEmpty())
{
<span class="warning-text">Nessuna commessa presente</span>
}
else
{
<MudSelectExtended FullWidth="true" ReadOnly="@(IsView || Commesse.IsNullOrEmpty())" T="string?" Variant="Variant.Text" @bind-Value="ActivityModel.CodJcom" @bind-Value:after="OnCommessaChanged" Class="customIcon-select" AdornmentIcon="@Icons.Material.Filled.Code">
@foreach (var com in Commesse)
{
<MudSelectItemExtended Class="custom-item-select" Value="@com.CodJcom">@($"{com.CodJcom} - {com.Descrizione}")</MudSelectItemExtended>
}
</MudSelectExtended>
}
</div>
</div>
@@ -105,7 +115,44 @@
<div class="input-card">
<MudTextField ReadOnly="IsView" T="string?" Placeholder="Note" Variant="Variant.Text" Lines="4" @bind-Value="ActivityModel.Note" @bind-Value:after="OnAfterChangeValue" DebounceInterval="500" OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
@if (!IsNew)
{
<div class="container-button">
<MudButton Class="button-settings gray-icon"
FullWidth="true"
StartIcon="@Icons.Material.Filled.ContentCopy"
Size="Size.Medium"
OnClick="Duplica"
Variant="Variant.Outlined">
Duplica
</MudButton>
<div class="divider"></div>
<MudButton Class="button-settings red-icon"
FullWidth="true"
StartIcon="@Icons.Material.Outlined.Delete"
Size="Size.Medium"
OnClick="DeleteActivity"
Variant="Variant.Outlined">
Elimina
</MudButton>
</div>
}
</div>
<MudMessageBox @ref="ConfirmDelete" Class="c-messageBox" Title="Attenzione!" CancelText="Annulla">
<MessageContent>
Confermi la cancellazione dell'attività corrente?
</MessageContent>
<YesButton>
<MudButton Size="Size.Small" Variant="Variant.Filled" Color="Color.Error"
StartIcon="@Icons.Material.Filled.DeleteForever">
Cancella
</MudButton>
</YesButton>
</MudMessageBox>
</DialogContent>
</MudDialog>
@@ -117,6 +164,7 @@
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; }
[Parameter] public string? Id { get; set; }
[Parameter] public ActivityDTO? ActivityCopied { get; set; }
private ActivityDTO OriginalModel { get; set; } = new();
private ActivityDTO ActivityModel { get; set; } = new();
@@ -139,6 +187,8 @@
private bool OpenEsito { get; set; } = false;
private MudMessageBox ConfirmDelete { get; set; }
protected override async Task OnInitializedAsync()
{
_ = LoadData();
@@ -148,6 +198,11 @@
if (!Id.IsNullOrEmpty())
ActivityModel = (await ManageData.GetActivity(x => x.ActivityId.Equals(Id))).Last();
if (ActivityCopied != null)
{
ActivityModel = ActivityCopied.Clone();
}
if (IsNew)
{
ActivityModel.EstimatedTime = DateTime.Today.Add(TimeSpan.FromHours(DateTime.Now.Hour));
@@ -200,11 +255,7 @@
Clienti = await ManageData.GetTable<AnagClie>(x => x.FlagStato.Equals("A"));
Pros = await ManageData.GetTable<PtbPros>();
ActivityType = await ManageData.GetTable<StbActivityType>(x => x.FlagTipologia.Equals("A"));
if (IsNew)
{
await LoadCommesse();
}
await LoadCommesse();
}
private async Task LoadCommesse() =>
@@ -218,11 +269,11 @@
var listToReturn = new List<string>();
listToReturn.AddRange(
Clienti.Where(x => x.RagSoc.Contains(value, StringComparison.OrdinalIgnoreCase)).Select(x => x.RagSoc)
Clienti.Where(x => x.RagSoc.Contains(value, StringComparison.OrdinalIgnoreCase)).Select(x => $"{x.CodAnag} - {x.RagSoc}")
);
listToReturn.AddRange(
Pros.Where(x => x.RagSoc.Contains(value, StringComparison.OrdinalIgnoreCase)).Select(x => x.RagSoc)
Pros.Where(x => x.RagSoc.Contains(value, StringComparison.OrdinalIgnoreCase)).Select(x => $"{x.CodPpro} - {x.RagSoc}")
);
return listToReturn;
@@ -231,6 +282,7 @@
private async Task OnClienteChanged()
{
string? codAnag = null;
ActivityModel.CodJcom = null;
var cliente = Clienti.LastOrDefault(x => ActivityModel.Cliente != null && x.RagSoc.Contains(ActivityModel.Cliente, StringComparison.OrdinalIgnoreCase));
if (cliente is null)
@@ -278,4 +330,42 @@
StateHasChanged();
}
private async Task DeleteActivity()
{
var result = await ConfirmDelete.ShowAsync();
if (result is true)
{
VisibleOverlay = true;
StateHasChanged();
try
{
await IntegryApiService.DeleteActivity(ActivityModel.ActivityId);
ActivityModel.Deleted = true;
SuccessAnimation = true;
StateHasChanged();
await Task.Delay(1250);
MudDialog.Close(ActivityModel);
}
catch (Exception e)
{
VisibleOverlay = false;
StateHasChanged();
Snackbar.Add("Impossibile cancellare l'attività", Severity.Error);
}
}
}
private void Duplica()
{
var activityCopy = ActivityModel.Clone();
MudDialog.Cancel();
Messenger.Send(new CopyActivityMessage(activityCopy));
}
}

View File

@@ -0,0 +1,4 @@
.container-button {
background: var(--mud-palette-background-gray) !important;
box-shadow: unset;
}