Iscrizione

This commit is contained in:
2025-12-02 17:15:05 +01:00
parent aa13cf1fc7
commit b4a6484909
23 changed files with 1668 additions and 218 deletions

View File

@ -38,5 +38,6 @@
<script src="/js/site.js" type="text/javascript" asp-append-version="true"></script>
<script src="/Plugin/Select2/js/select2.full.min.js"></script>
<script src="_content/Radzen.Blazor/Radzen.Blazor.js?v=@(typeof(Radzen.Colors).Assembly.GetName().Version)"></script>
<script src="/js/BodyClass.js"></script>
</body>
</html>

View File

@ -43,21 +43,13 @@
<!-- BEGIN NAVBAR MENU -->
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="/">
<a class="nav-link" href="/management">
<span class="nav-link-icon d-md-none d-lg-inline-block">
<i class="fa-solid fa-house"></i>
</span>
<span class="nav-link-title"> Home </span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/management/dashboard">
<span class="nav-link-icon d-md-none d-lg-inline-block">
<i class="fa-solid fa-house"></i>
</span>
<span class="nav-link-title"> Dashboard </span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/management/Utenti">
<span class="nav-link-icon d-md-none d-lg-inline-block">

View File

@ -1,10 +1,51 @@
@page "/"
@page "/{invitationId:guid}"
@layout PublicLayout
@using Microsoft.EntityFrameworkCore
@using StandManager.Components.Layout
@inject BodyClassService BodyClass
@rendermode InteractiveServer
@using Microsoft.AspNetCore.Identity
@using StandManager.Domain.Entita
<PageTitle>Home</PageTitle>
<PageTitle>Evento</PageTitle>
<h1>Hello, world!</h1>
<header class="hero pb-0">
<div class="container">
@if (invitationId.HasValue)
{
<h1 class="hero-title">Ciao @invito.Cliente.RagioneSociale - Sei stato invitato a: @invito.Evento.Titolo</h1>
<p class="hero-description mt-4">
L'evento si terrà dal @invito.Evento.DataDa.ToString("dd/MM/yyyy") al @invito.Evento.DataA.ToString("dd/MM/yyyy"), presso: @invito.Evento.Luogo
</p>
}
else
{
<h1 class="hero-title">Iscriviti ad un evento, inserisci il tuo codice di invito</h1>
}
</div>
</header>
Welcome to your new app.
@code {
[Parameter]
public Guid? invitationId { get; set; }
private InvitoEvento invito { get; set; }
protected override async Task OnInitializedAsync()
{
base.OnInitializedAsync();
invito = invitationId.GetValueOrDefault() != Guid.Empty
? await _managerService.InvitoEventoService.RicercaPer(x => x.Id == invitationId && x.Eliminato == false,
includi: x => x.Include(y => y.Evento).Include(y => y.Cliente).ThenInclude(y => y.Destinazioni))
: new();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
await BodyClass.SetBodyClass("body-marketing body-gradient");
}
}

View File

@ -1,187 +1,85 @@
@page "/management/clienti"
@attribute [Authorize]
@page "/management/Clienti"
@using Microsoft.EntityFrameworkCore
@using StandManager.Domain.Entita
@using StandManager.Service.Interfaces
@inject IManagerService _managerService
@using StandManager.Model
<h3>Clienti</h3>
@rendermode InteractiveServer
@inject AuthenticationStateProvider auth
<PageTitle>Clienti</PageTitle>
@inject IManagerService _managerService
<div class="page-wrapper">
<!-- BEGIN PAGE BODY -->
<div class="page-body">
<div class="container-xl">
<div class="row row-cards">
<div class="col">
<!-- Page pre-title -->
<div class="page-pretitle">Overview</div>
<h2 class="page-title">Clienti</h2>
</div>
<div class="col-auto ms-auto">
<div class="btn-list">
<a href="/management/Utenti/Modifica" class="btn btn-primary btn-5 d-none d-sm-inline-block">
Nuovo cliente
</a>
</div>
</div>
<div class="col-lg-12">
<div class="card">
<div class="table-responsive">
<RadzenDataGrid @ref="clientiGrid" AllowFiltering="true" AllowColumnResize="true" AllowAlternatingRows="false" FilterMode="FilterMode.CheckBoxList" AllowSorting="true" PageSize="5"
AllowPaging="true" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true"
Data="@clienti" ColumnWidth="300px" LogicalFilterOperator="LogicalFilterOperator.Or" SelectionMode="DataGridSelectionMode.Single">
<Columns>
<RadzenDataGridColumn Property="@nameof(ClienteViewModel.Id)" Filterable="false" Title="ID" Width="80px" TextAlign="TextAlign.Center" />
<RadzenDataGridColumn Property="@nameof(ClienteViewModel.RagioneSociale)" Title="Ragione sociale" Width="160px" />
<RadzenDataGridColumn Property="@nameof(ClienteViewModel.PartitaIva)" Title="Partita IVA" Width="160px" />
<RadzenDataGridColumn Property="@nameof(ClienteViewModel.Agente)" Title="Agente" Width="200px" />
<h3>Clienti</h3>
@*BOZZA NEW VERSION*@
@* <RadzenDataGrid TItem="Cliente"
@ref="grid"
Data="@clienti"
AllowFiltering="true"
AllowColumnResize="true"
AllowAlternatingRows="false"
FilterMode="FilterMode.Advanced"
AllowSorting="true"
PageSize="5"
AllowPaging="true"
PagerHorizontalAlign="HorizontalAlign.Left"
ShowPagingSummary="true"
ColumnWidth="300px"
LogicalFilterOperator="LogicalFilterOperator.Or"
SelectionMode="DataGridSelectionMode.Single"
@bind-Value="clienteSelezionato"
EditMode="DataGridEditMode.Single">
<Columns>
@* Colonna comandi con toolbar Aggiungi + pulsanti Modifica/Elimina *@
@* <RadzenDataGridColumn TItem="Cliente" Context="cliente" Width="200px" Frozen="true">
<HeaderTemplate>
<RadzenButton Icon="add"
Text="Aggiungi"
Size="ButtonSize.Small"
Click="@AddRow" />
</HeaderTemplate>
<Template Context="cliente">
<RadzenButton Icon="edit"
ButtonStyle="ButtonStyle.Light"
Size="ButtonSize.Small"
Click="@(() => EditRow(cliente))" />
<RadzenButton Icon="delete"
ButtonStyle="ButtonStyle.Danger"
Size="ButtonSize.Small"
Click="@(() => DeleteRow(cliente))" />
</Template>
<EditTemplate Context="cliente">
<RadzenButton Icon="save"
ButtonStyle="ButtonStyle.Primary"
Size="ButtonSize.Small"
Click="@(() => SaveRow(cliente))" />
<RadzenButton Icon="cancel"
ButtonStyle="ButtonStyle.Light"
Size="ButtonSize.Small"
Click="@(() => CancelEdit(cliente))" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Property="@nameof(Cliente.Id)" Filterable="false" Title="ID" Width="80px" TextAlign="TextAlign.Center" />
<RadzenDataGridColumn Property="@nameof(Cliente.RagioneSociale)" Title="Ragione Sociale" Width="160px" />
<RadzenDataGridColumn Property="@nameof(Cliente.PartitaIva)" Title="Partita Iva" Width="160px" />
<RadzenDataGridColumn Property="@nameof(Cliente.Indirizzo)" Title="Indirizzo" Width="200px" />
<RadzenDataGridColumn Property="@nameof(Cliente.NumeroTelefono)" Title="Numero di Telefono" Width="120px" />
<RadzenDataGridColumn Property="@nameof(Cliente.Agente)" Title="Agente" Width="160px" />
<RadzenDataGridColumn Property="@nameof(Cliente.Citta)" Title="Città" Width="160px" />
</Columns>
</RadzenDataGrid>
<RadzenDataGridColumn Context="order" Filterable="false" Sortable="false" TextAlign="TextAlign.Right">
<Template Context="cliente">
<RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" class="rz-my-1 rz-ms-1" Click="@(args => EditRow(cliente))" @onclick:stopPropagation="true" />
<RadzenButton Icon="delete" ButtonStyle="ButtonStyle.Danger" Variant="Variant.Flat" Size="ButtonSize.Medium" Shade="Shade.Lighter" class="rz-my-1 rz-ms-1" Click="@(args => DeleteRow(cliente))" @onclick:stopPropagation="true" />
</Template>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@code {
RadzenDataGrid<Cliente>? grid;
List<Cliente> clienti = new();
Cliente? clienteSelezionato;
Cliente? clienteInInserimento; // per distinguere "nuovo" da "esistente"
protected override async Task OnInitializedAsync()
{
// Prima avevi IQueryable<Cliente>. Ora usiamo List<Cliente> per gestire facilmente CRUD in memoria
var query = await _managerService.ClienteService.RicercaQueryable(x => x.Eliminato == false);
clienti = await query.ToListAsync();
clienteSelezionato = clienti.FirstOrDefault();
}
// ========= COMANDI UI (toolbar + pulsanti riga) ==========
async Task AddRow()
{
// crea un nuovo cliente in edit
clienteInInserimento = new Cliente();
clienti.Insert(0, clienteInInserimento);
await grid!.InsertRow(clienteInInserimento);
}
async Task EditRow(Cliente cliente)
{
clienteInInserimento = null; // non è un "nuovo", è edit di esistente
await grid!.EditRow(cliente);
}
async Task SaveRow(Cliente cliente)
{
// Chiude la modalità edit a livello UI
await grid!.UpdateRow(cliente);
// Persistenza su DB
if (clienteInInserimento == cliente)
{
// INSERIMENTO
// TODO: sostituisci con il tuo metodo reale
// await _managerService.ClienteService.Inserisci(cliente);
// await _managerService.UnitOfWork.SalvaAsync();
clienteInInserimento = null;
}
else
{
// UPDATE
// TODO: sostituisci con il tuo metodo reale
// await _managerService.ClienteService.Aggiorna(cliente);
// await _managerService.UnitOfWork.SalvaAsync();
}
}
void CancelEdit(Cliente cliente)
{
if (clienteInInserimento == cliente)
{
// se annullo l'inserimento, tolgo la riga fittizia
clienti.Remove(cliente);
clienteInInserimento = null;
}
grid!.CancelEditRow(cliente);
}
async Task DeleteRow(Cliente cliente)
{
// Persistenza su DB
// TODO: soft-delete o hard-delete a seconda della tua logica:
// cliente.Eliminato = true;
// await _managerService.ClienteService.Aggiorna(cliente);
// await _managerService.UnitOfWork.SalvaAsync();
clienti.Remove(cliente);
await grid!.Reload();
}
}
*@
@*OLD VERSION*@
<RadzenDataGrid AllowFiltering="true" AllowColumnResize="true" AllowAlternatingRows="false" FilterMode="FilterMode.Advanced" AllowSorting="true" PageSize="5" AllowPaging="true" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true"
Data="@clienti" ColumnWidth="300px" LogicalFilterOperator="LogicalFilterOperator.Or" SelectionMode="DataGridSelectionMode.Single" @bind-Value=@clientiSelected>
<Columns>
<RadzenDataGridColumn Property="@nameof(Cliente.Id)" Filterable="false" Title="ID" Frozen="true" Width="80px" TextAlign="TextAlign.Center" />
<RadzenDataGridColumn Property="@nameof(Cliente.RagioneSociale)" Title="Ragione Sociale" Frozen="true" Width="160px" />
<RadzenDataGridColumn Property="@nameof(Cliente.PartitaIva)" Title="Partita Iva" Width="160px" />
<RadzenDataGridColumn Property="@nameof(Cliente.Indirizzo)" Title="Indirizzo" Width="200px" />
<RadzenDataGridColumn Property="@nameof(Cliente.NumeroTelefono)" Title="Numero di Telefono" Width="120px" />
<RadzenDataGridColumn Property="@nameof(Cliente.Agente)" Title="Agente" FormatString="{0:d}" Width="160px" />
<RadzenDataGridColumn Property="@nameof(Cliente.Citta)" Title="Città" FormatString="{0:d}" Width="160px" />
</Columns>
</RadzenDataGrid>
@code {
IQueryable<Cliente> clienti;
IList<Cliente> clientiSelected;
List<ClienteViewModel> clienti;
RadzenDataGrid<ClienteViewModel> clientiGrid;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
clienti = await _managerService.ClienteService.RicercaQueryable(x => x.Eliminato == false);
clientiSelected = new List<Cliente>() { clienti.FirstOrDefault() };
clienti = (await _managerService.ClienteService.RicercaQueryable(x => x.Eliminato == false, includi: x => x.Include(y => y.Agente)))
.Select(x => (ClienteViewModel)x).ToList();
}
}
private async Task EditRow(ClienteViewModel cliente)
{
_navManager.NavigateTo($"/management/Clienti/Modifica/{cliente.Id}");
}
private async Task DeleteRow(ClienteViewModel cliente)
{
var ok = await _dialogService.Confirm($"Vuoi davvero eliminare il cliente {cliente.RagioneSociale}?", "Conferma eliminazione", new ConfirmOptions { OkButtonText = "Sì", CancelButtonText = "No", Width = "400px" });
if (ok == true)
{
await _managerService.ClienteService.Elimina(cliente.Id, await MembershipUtils.GetUserId(auth));
clienti = (await _managerService.ClienteService.RicercaQueryable(x => x.Eliminato == false, includi: x => x.Include(y => y.Agente)))
.Select(x => (ClienteViewModel)x).ToList();
}
}
}

View File

@ -1,30 +0,0 @@
@page "/management/Dashboard"
@using Microsoft.AspNetCore.Authorization
@using StandManager.Components.Layout
@attribute [Authorize]
@rendermode InteractiveServer
<div class="page-wrapper">
<!-- BEGIN PAGE HEADER -->
<div class="page-header d-print-none" aria-label="Page header">
<div class="container-xl">
<div class="row g-2 align-items-center">
<div class="col">
<!-- Page pre-title -->
<div class="page-pretitle">Overview</div>
<h2 class="page-title">Dashboard</h2>
</div>
</div>
</div>
</div>
</div>
<Radzen.Blazor.RadzenButton Text="Ciao"></Radzen.Blazor.RadzenButton>
@code {
override protected void OnInitialized()
{
// Initialization logic can be added here if needed
var a = "CIAO";
}
}

View File

@ -0,0 +1,2 @@
@attribute [Authorize]
@page "/management"

View File

@ -0,0 +1,46 @@
using StandManager.Domain.Entita;
namespace StandManager.Model
{
public class ClienteViewModel
{
public Guid Id { get; set; }
public string RagioneSociale { get; set; }
public string PartitaIva { get; set; }
public string Cap { get; set; }
public string Citta { get; set; }
public string Indirizzo { get; set; }
public string Email { get; set; }
public string EmailInvito { get; set; }
public string NumeroTelefono { get; set; }
public string Agente { get; set; }
public Guid? AgenteId { get; set; }
public List<Destinazione> Destinazioni { get; set; }
public string Rid { get; set; }
public ClienteTipo TipologiaCliente { get; set; }
public static implicit operator ClienteViewModel(Cliente model)
{
return model == null
? null
: new ClienteViewModel()
{
Agente = model.Agente?.ToString(),
AgenteId = model.AgenteId,
Cap = model.Cap,
Citta = model.Citta,
Email = model.Email,
EmailInvito = model.EmailInvito,
Id = model.Id,
Destinazioni = model.Destinazioni,
Indirizzo = model.Indirizzo,
NumeroTelefono = model.NumeroTelefono,
PartitaIva = model.PartitaIva,
RagioneSociale = model.RagioneSociale,
Rid = model.Rid,
TipologiaCliente = model.TipologiaCliente
};
}
}
}

View File

@ -1,5 +1,6 @@
using StandManager.Domain.Entita;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace StandManager.Model
{
@ -37,4 +38,4 @@ namespace StandManager.Model
return model;
}
}
}
}

View File

@ -47,8 +47,9 @@ builder.Services.AddDbContext<StandManagerDbContext>(options =>
builder.Services.AddScoped(typeof(IStandManagerGenericRepository<>), typeof(StandManagerGenericRepository<>));
builder.Services.AddScoped<IStandManagerUnitOfWork, StandManagerUnitOfWork>();
builder.Services.AddScoped<IManagerService, ManagerService>();
builder.Services.AddScoped<BodyClassService>();
builder.Services.AddScoped<LayoutState>();
builder.Services.AddRadzenComponents();
builder.Services.AddHttpContextAccessor();

View File

@ -0,0 +1,23 @@
using Microsoft.JSInterop;
namespace StandManager.Utils
{
public class BodyClassService
{
private readonly IJSRuntime _js;
public BodyClassService(IJSRuntime js)
{
_js = js;
}
public async Task SetBodyClass(string? className)
=> await _js.InvokeVoidAsync("bodyClass.set", className);
public async Task Add(string className)
=> await _js.InvokeVoidAsync("bodyClass.add", className);
public async Task Remove(string className)
=> await _js.InvokeVoidAsync("bodyClass.remove", className);
}
}

View File

@ -0,0 +1,24 @@
window.bodyClass = {
set: function (className) {
// Rimuove tutte le classi attuali
document.body.className = "";
// Se la classe è valorizzata, la imposta
if (className) {
document.body.className = className;
}
},
add: function (className) {
document.body.classList.add(className);
},
remove: function (className) {
document.body.classList.remove(className);
},
// Utile se vuoi rimuovere tutto manualmente
clear: function () {
document.body.className = "";
}
};