Aggiunta ricerca indirizzo

This commit is contained in:
2025-07-24 15:51:01 +02:00
parent b34f6cb213
commit 9c69884cc9
11 changed files with 453 additions and 196 deletions

View File

@@ -0,0 +1,124 @@
@using salesbook.Shared.Components.Layout.Spinner
@using salesbook.Shared.Core.Dto
@using salesbook.Shared.Core.Interface
@using salesbook.Shared.Components.Layout.Overlay
@inject IIntegryApiService IntegryApiService
<div class="bottom-sheet-backdrop @(IsSheetVisible ? "show" : "")" @onclick="CloseBottomSheet"></div>
<div class="bottom-sheet-container @(IsSheetVisible ? "show" : "")">
<div style="height: 95vh" class="bottom-sheet pb-safe-area">
<div class="title">
<MudText Typo="Typo.h6">
<b>Cerca indirizzo</b>
</MudText>
<MudIconButton Icon="@Icons.Material.Filled.Close" OnClick="() => CloseBottomSheet()"/>
</div>
<div class="input-card clearButton">
<MudTextField T="string?" Placeholder="Cerca..." Variant="Variant.Text" @bind-Value="Address" DebounceInterval="500" OnDebounceIntervalElapsed="SearchAllAddress" />
<MudIconButton Class="closeIcon" Icon="@Icons.Material.Filled.Close" OnClick="() => Address = null" />
</div>
<div>
@if (Loading)
{
<SpinnerLayout />
}
else
{
if (Addresses != null)
{
foreach (var address in Addresses)
{
<b><span @onclick="() => OnSelectAddress(address.PlaceId)">@address.Description</span></b>
<div class="divider"></div>
}
}
else
{
<NoDataAvailable Text="Nessun idirizzo trovato" />
}
}
</div>
</div>
</div>
<SaveOverlay VisibleOverlay="VisibleOverlay" SuccessAnimation="SuccessAnimation"/>
@code {
[Parameter] public string Region { get; set; }
[Parameter] public IndirizzoDTO Indirizzo { get; set; }
[Parameter] public EventCallback<IndirizzoDTO> IndirizzoChanged { get; set; }
[Parameter] public bool IsSheetVisible { get; set; }
[Parameter] public EventCallback<bool> IsSheetVisibleChanged { get; set; }
private bool Loading { get; set; }
private string? Address { get; set; }
private List<AutoCompleteAddressDTO>? Addresses { get; set; }
private string? Uuid { get; set; }
//Overlay for save
private bool VisibleOverlay { get; set; }
private bool SuccessAnimation { get; set; }
protected override async Task OnParametersSetAsync()
{
if (IsSheetVisible)
{
Uuid = Guid.NewGuid().ToString();
Address = null;
Addresses = null;
}
}
private void CloseBottomSheet()
{
IsSheetVisible = false;
IsSheetVisibleChanged.InvokeAsync(IsSheetVisible);
}
private async Task SearchAllAddress()
{
if (Address == null || Uuid == null) return;
Loading = true;
StateHasChanged();
Addresses = await IntegryApiService.AutoCompleteAddress(Address, Region, Uuid);
Loading = false;
StateHasChanged();
}
private async Task OnSelectAddress(string placeId)
{
CloseBottomSheet();
VisibleOverlay = true;
StateHasChanged();
try
{
Indirizzo = await IntegryApiService.PlaceDetails(placeId, Uuid);
await IndirizzoChanged.InvokeAsync(Indirizzo);
}
catch (Exception e)
{
Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter;
Snackbar.Clear();
Snackbar.Add("Impossibile selezionare questo indirizzo", Severity.Error);
}
VisibleOverlay = false;
StateHasChanged();
}
}

View File

@@ -3,6 +3,7 @@
@using salesbook.Shared.Core.Interface
@using salesbook.Shared.Components.Layout.Overlay
@using salesbook.Shared.Core.Entity
@using salesbook.Shared.Components.SingleElements.BottomSheet
@inject IManageDataService ManageData
@inject INetworkService NetworkService
@inject IIntegryApiService IntegryApiService
@@ -13,141 +14,21 @@
<HeaderLayout ShowProfile="false" Cancel="true" OnCancel="() => MudDialog.Cancel()" LabelSave="@LabelSave" OnSave="Save" Title="@(IsNew ? "Nuovo" : $"{ContactModel.CodContact}")"/>
<div class="content">
<div class="input-card">
<MudTextField ReadOnly="IsView"
T="string?"
Placeholder="Azienda"
Variant="Variant.Text"
Lines="1"
@bind-Value="ContactModel.RagSoc"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
<div class="input-card">
<div class="form-container">
<span class="disable-full-width">P. IVA</span>
<div class="input-card">
<MudTextField ReadOnly="IsView"
T="string?"
Placeholder="Azienda"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.PartIva"
@bind-Value:after="OnAfterChangePIva"/>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Cod. Fiscale</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.CodFisc"
@bind-Value="ContactModel.RagSoc"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
</div>
<div class="input-card">
<div class="form-container">
<span class="disable-full-width">Tipo cliente</span>
@if (VtbTipi.IsNullOrEmpty())
{
<span class="warning-text">Nessun tipo cliente trovato</span>
}
else
{
<MudSelectExtended FullWidth="true" ReadOnly="@(IsView || VtbTipi.IsNullOrEmpty())" T="string?" Variant="Variant.Text" @bind-Value="ContactModel.CodVtip" @bind-Value:after="OnAfterChangeValue" Class="customIcon-select" AdornmentIcon="@Icons.Material.Filled.Code">
@foreach (var tipo in VtbTipi)
{
<MudSelectItemExtended Class="custom-item-select" Value="@tipo.CodVtip">@($"{tipo.CodVtip} - {tipo.Descrizione}")</MudSelectItemExtended>
}
</MudSelectExtended>
}
</div>
</div>
<div class="input-card">
<div class="form-container">
<span class="disable-full-width">Indirizzo</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
Lines="1"
FullWidth="true"
Class="customIcon-select"
@bind-Value="ContactModel.Indirizzo"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">CAP</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.Cap"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Città</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.Citta"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Provincia</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.Prov"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Nazione</span>
<div class="input-card">
<div class="form-container">
<span class="disable-full-width">Nazione</span>
@if (Nazioni.IsNullOrEmpty())
{
@@ -164,85 +45,215 @@
}
</MudSelectExtended>
}
</div>
</div>
<div class="input-card">
<div class="form-container">
<span class="disable-full-width">PEC</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.EMailPec"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
</div>
<div class="divider"></div>
<div class="input-card">
<div class="form-container">
<span class="disable-full-width">P. IVA</span>
<div class="form-container">
<span class="disable-full-width">E-Mail</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.PartIva"
@bind-Value:after="OnAfterChangePIva"/>
</div>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.EMail"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Cod. Fiscale</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.CodFisc"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
</div>
<div class="divider"></div>
<div class="input-card">
<div class="form-container">
<span class="disable-full-width">Tipo cliente</span>
<div class="form-container">
<span class="disable-full-width">Telefono</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.Telefono"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
</div>
@if (IsNew)
{
<div class="container-chip-persrif">
@if (!PersRifList.IsNullOrEmpty())
{
foreach (var item in PersRifList!.Select((p, index) => new { p, index }))
@if (VtbTipi.IsNullOrEmpty())
{
<MudChip T="string" Color="Color.Default" OnClick="() => OpenPersRifForm(item.index, item.p)" OnClose="() => OnRemovePersRif(item.index)">
@item.p.PersonaRif
</MudChip>
<span class="warning-text">Nessun tipo cliente trovato</span>
}
}
else
{
<MudSelectExtended FullWidth="true" ReadOnly="@(IsView || VtbTipi.IsNullOrEmpty())" T="string?" Variant="Variant.Text" @bind-Value="ContactModel.CodVtip" @bind-Value:after="OnAfterChangeValue" Class="customIcon-select" AdornmentIcon="@Icons.Material.Filled.Code">
@foreach (var tipo in VtbTipi)
{
<MudSelectItemExtended Class="custom-item-select" Value="@tipo.CodVtip">@($"{tipo.CodVtip} - {tipo.Descrizione}")</MudSelectItemExtended>
}
</MudSelectExtended>
}
</div>
</div>
@if (!IsView)
{
<div class="search-address" @onclick="() => OpenSearchAddress = !OpenSearchAddress">
<span>Cerca indirizzo</span>
<MudIcon Size="Size.Small" Icon="@Icons.Material.Rounded.Search"/>
</div>
}
<div class="input-card">
<div class="form-container">
<span class="disable-full-width">Indirizzo</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
Lines="1"
FullWidth="true"
Class="customIcon-select"
@bind-Value="ContactModel.Indirizzo"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">CAP</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.Cap"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Città</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.Citta"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Provincia</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
MaxLength="2"
Lines="1"
@bind-Value="ContactModel.Prov"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
</div>
<div class="container-button">
<MudButton Class="button-settings gray-icon"
FullWidth="true"
StartIcon="@Icons.Material.Filled.PersonAddAlt1"
Size="Size.Medium"
OnClick="NewPersRif"
Variant="Variant.Outlined">
Persona di riferimento
</MudButton>
<div class="input-card">
<div class="form-container">
<span class="disable-full-width">PEC</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.EMailPec"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">E-Mail</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.EMail"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Telefono</span>
<MudTextField ReadOnly="IsView"
T="string?"
Variant="Variant.Text"
FullWidth="true"
Class="customIcon-select"
Lines="1"
@bind-Value="ContactModel.Telefono"
@bind-Value:after="OnAfterChangeValue"
DebounceInterval="500"
OnDebounceIntervalElapsed="OnAfterChangeValue"/>
</div>
</div>
}
@if (IsNew)
{
<div class="container-chip-persrif">
@if (!PersRifList.IsNullOrEmpty())
{
foreach (var item in PersRifList!.Select((p, index) => new { p, index }))
{
<MudChip T="string" Color="Color.Default" OnClick="() => OpenPersRifForm(item.index, item.p)" OnClose="() => OnRemovePersRif(item.index)">
@item.p.PersonaRif
</MudChip>
}
}
</div>
<div class="container-button">
<MudButton Class="button-settings gray-icon"
FullWidth="true"
StartIcon="@Icons.Material.Filled.PersonAddAlt1"
Size="Size.Medium"
OnClick="NewPersRif"
Variant="Variant.Outlined">
Persona di riferimento
</MudButton>
</div>
}
</div>
<MudMessageBox MarkupMessage="new MarkupString(VatMessage)" @ref="CheckVat" Class="c-messageBox" Title="Verifica partita iva" CancelText="@(VatAlreadyRegistered ? "" : "Annulla")">
@@ -268,6 +279,8 @@
<SaveOverlay VisibleOverlay="VisibleOverlay" SuccessAnimation="SuccessAnimation"/>
<SearchAddress Region="@ContactModel.Nazione" @bind-IsSheetVisible="OpenSearchAddress" @bind-Indirizzo="Address" @bind-Indirizzo:after="OnAddressSet"/>
@code {
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; }
@@ -292,6 +305,10 @@
private string VatMessage { get; set; } = "";
private bool VatAlreadyRegistered { get; set; }
//BottomSeath
private bool OpenSearchAddress { get; set; }
private IndirizzoDTO Address { get; set; }
protected override async Task OnInitializedAsync()
{
Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter;
@@ -467,4 +484,12 @@
OnAfterChangeValue();
}
private void OnAddressSet()
{
ContactModel.Citta = Address.Citta;
ContactModel.Indirizzo = Address.Indirizzo;
ContactModel.Prov = Address.Prov;
ContactModel.Cap = Address.Cap;
}
}

View File

@@ -6,4 +6,14 @@
.container-chip-persrif {
width: 100%;
margin-bottom: 1rem;
}
.search-address {
width: 100%;
display: flex;
justify-content: space-between;
margin-bottom: 0.65rem;
color: var(--mud-palette-primary);
font-weight: 600;
align-items: center;
}