- IscrizioneEvento: creazione delle iscrizioni
This commit is contained in:
@ -12,6 +12,9 @@ public class InvitoEvento : EntitaBase
|
||||
[ForeignKey(nameof(Cliente))]
|
||||
public Guid? ClienteId { get; set; }
|
||||
public Cliente Cliente { get; set; }
|
||||
|
||||
[InverseProperty(nameof(IscrizioneEvento.InvitoEvento))]
|
||||
public List<IscrizioneEvento> IscrizioniEvento { get; set; }
|
||||
}
|
||||
|
||||
public class IscrizioneEvento : EntitaBase
|
||||
|
||||
@ -3,4 +3,7 @@ using StandManager.Domain.Entita;
|
||||
|
||||
namespace StandManager.Service.Interfaces;
|
||||
|
||||
public interface IIscrizioneEventoService : ITService<IscrizioneEvento>{}
|
||||
public interface IIscrizioneEventoService : ITService<IscrizioneEvento>
|
||||
{
|
||||
Task<IscrizioneEvento> Salva(IscrizioneEvento model);
|
||||
}
|
||||
|
||||
@ -13,4 +13,21 @@ public class IscrizioneEventoService : TService<IscrizioneEvento>, IIscrizioneEv
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<IscrizioneEvento> Salva(IscrizioneEvento entita)
|
||||
{
|
||||
bool isNuovaEntita = entita.Id == Guid.Empty;
|
||||
|
||||
entita.DataCreazione = isNuovaEntita ? DateTime.Now : entita.DataCreazione;
|
||||
entita.DataModifica = isNuovaEntita == false ? DateTime.Now : null;
|
||||
entita.IdUtenteCreazione = isNuovaEntita ? null : entita.IdUtenteCreazione;
|
||||
entita.IdUtenteModifica = isNuovaEntita == false ? null : null;
|
||||
|
||||
if (isNuovaEntita)
|
||||
await _unitOfWork.GetRepository<IscrizioneEvento>().Put(entita);
|
||||
|
||||
int result = await _unitOfWork.Salva();
|
||||
|
||||
return entita;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
@using Microsoft.AspNetCore.Authentication
|
||||
@inherits LayoutComponentBase
|
||||
@inject NavigationManager NavManager
|
||||
|
||||
<RadzenComponents @rendermode="InteractiveAuto" />
|
||||
|
||||
@ -44,7 +45,7 @@
|
||||
<div class="col">
|
||||
<!-- BEGIN NAVBAR MENU -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active">
|
||||
<li class="nav-item @GetActiveClass("/management")">
|
||||
<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>
|
||||
@ -52,7 +53,7 @@
|
||||
<span class="nav-link-title"> Home </span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<li class="nav-item @GetActiveClass("/management/Utenti")">
|
||||
<a class="nav-link" href="/management/Utenti">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fa-solid fa-house"></i>
|
||||
@ -60,7 +61,7 @@
|
||||
<span class="nav-link-title"> Utenti </span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<li class="nav-item @GetActiveClass("/management/Clienti")">
|
||||
<a class="nav-link" href="/management/Clienti">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fa-solid fa-address-card"></i>
|
||||
@ -68,7 +69,7 @@
|
||||
<span class="nav-link-title"> Clienti </span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<li class="nav-item @GetActiveClass("/management/Eventi")">
|
||||
<a class="nav-link" href="/management/Eventi">
|
||||
<span class="nav-link-icon d-md-none d-lg-inline-block">
|
||||
<i class="fa-solid fa-address-card"></i>
|
||||
@ -91,10 +92,27 @@
|
||||
[CascadingParameter]
|
||||
public HttpContext? httpContext { get; set; }
|
||||
|
||||
private string currentUrl = string.Empty;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
base.OnInitializedAsync();
|
||||
|
||||
var context = httpContext.GetRouteData();
|
||||
currentUrl = NavManager.ToBaseRelativePath(NavManager.Uri);
|
||||
}
|
||||
|
||||
private string GetActiveClass(string href)
|
||||
{
|
||||
string currentClean = currentUrl.Split("management").Last();
|
||||
string hrefClean = href.Split("management").Last();
|
||||
|
||||
|
||||
if (currentClean.Contains("?"))
|
||||
currentClean = currentClean.Substring(0, currentClean.IndexOf("?"));
|
||||
|
||||
var isActive = (currentClean.Contains(hrefClean, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(hrefClean)
|
||||
|| (string.IsNullOrEmpty(hrefClean) && string.IsNullOrEmpty(currentClean)));
|
||||
|
||||
return isActive ? "active" : "";
|
||||
}
|
||||
|
||||
}
|
||||
@ -4,24 +4,109 @@
|
||||
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using StandManager.Components.Layout
|
||||
@using StandManager.Model
|
||||
|
||||
@inject AuthenticationStateProvider auth
|
||||
@inject BodyClassService BodyClass
|
||||
@rendermode InteractiveServer
|
||||
|
||||
<PageTitle>Evento</PageTitle>
|
||||
<PageTitle>Iscrizioni Evento</PageTitle>
|
||||
|
||||
<header class="hero pb-0">
|
||||
<div class="container">
|
||||
@if (invitationId.HasValue)
|
||||
@if (invitationId.HasValue && invito != null)
|
||||
{
|
||||
<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>
|
||||
<div class="mb-2">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
@if (destinazioniList.Count() > 0)
|
||||
{
|
||||
<div class="row row-cards">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
Compila le destinazioni mancanti
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-5">
|
||||
<EditForm Model="iscrizione" OnValidSubmit="onIscrizioneSave" FormName="iscrizioneForm">
|
||||
<DataAnnotationsValidator />
|
||||
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-8 mb-3">
|
||||
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Destinazione</RadzenText>
|
||||
<RadzenDropDown @bind-Value="@iscrizione.Destinazione" Style="width: 100%" TextProperty="RagioneSociale"
|
||||
Data="@destinazioniList" Size="ButtonSize.Small" />
|
||||
<ValidationMessage For="@(() => iscrizione.Destinazione)" />
|
||||
</div>
|
||||
<div class="col-4 mb-3">
|
||||
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Numero di partecipanti</RadzenText>
|
||||
<RadzenNumeric ShowUpDown="false" TValue="int" TextAlign="TextAlign.Right" Style="width: 100%" aria-label="Partecipanti" @bind-Value="@iscrizione.Partecipanti" />
|
||||
<ValidationMessage For="@(() => iscrizione.Partecipanti)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 mb-3">
|
||||
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Note</RadzenText>
|
||||
<RadzenTextArea @bind-Value="@iscrizione.Note" Style="width: 100%;" Rows="3" />
|
||||
<ValidationMessage For="@(() => iscrizione.Note)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3 mb-3">
|
||||
<button type="button" class="btn btn-default w-100" @onclick="backToHome">
|
||||
Torna all'inserimento codice
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3 mb-3">
|
||||
<button type="submit" class="btn btn-primary w-100">
|
||||
Salva
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="text-danger mt-1">Non sono presenti destinazioni da compilare per questo evento!</div>
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
<h1 class="hero-title">Iscriviti ad un evento, inserisci il tuo codice di invito</h1>
|
||||
<div class="mb-2">
|
||||
<h1 class="hero-title">Iscriviti ad un evento, inserisci il tuo codice di invito</h1>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-9 mb-3">
|
||||
<RadzenTextBox @bind-Value="@invitationCode" Placeholder="Inserirci il codice invito" Style="width: 100%;" />
|
||||
@if (!string.IsNullOrEmpty(invalidCode))
|
||||
{
|
||||
<div class="text-danger mt-1">@invalidCode</div>
|
||||
}
|
||||
</div>
|
||||
<div class="col-3 mb-3">
|
||||
<button type="button" class="btn btn-primary w-100" @onclick="reloadWithCode">
|
||||
Invia
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</header>
|
||||
@ -33,14 +118,29 @@
|
||||
|
||||
private InvitoEvento invito { get; set; }
|
||||
|
||||
[SupplyParameterFromForm]
|
||||
private IscrizioneEventoViewModel iscrizione { get; set; } = new();
|
||||
private IEnumerable<DestinazioneViewModel> destinazioniList { get; set; }
|
||||
|
||||
public string invitationCode { get; set; } = string.Empty;
|
||||
private string invalidCode = string.Empty;
|
||||
|
||||
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))
|
||||
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).Include(y => y.IscrizioniEvento))
|
||||
: new();
|
||||
|
||||
if(invito == null)
|
||||
invalidCode = "Il codice inserito non risulta corretto";
|
||||
else
|
||||
{
|
||||
var destinazioniIds = invito.IscrizioniEvento?.Select(x => x.DestinazioneId).ToList() ?? new List<Guid?>();
|
||||
destinazioniList = (await _managerService.DestinazioneService.RicercaQueryable(filtro: x => x.ClienteId == invito.ClienteId && !destinazioniIds.Any(y => y == x.Id))).Select(x => (DestinazioneViewModel)x).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
@ -48,4 +148,36 @@
|
||||
if (firstRender)
|
||||
await BodyClass.SetBodyClass("body-marketing body-gradient");
|
||||
}
|
||||
|
||||
private void reloadWithCode()
|
||||
{
|
||||
if (Guid.TryParse(invitationCode, out Guid invitationCodeParsed))
|
||||
{
|
||||
_navManager.NavigateTo($"/{invitationCodeParsed}");
|
||||
}
|
||||
else
|
||||
{
|
||||
invalidCode = "Il codice inserito non risulta corretto";
|
||||
}
|
||||
}
|
||||
|
||||
private void backToHome()
|
||||
{
|
||||
_navManager.NavigateTo($"/");
|
||||
}
|
||||
|
||||
private async Task onIscrizioneSave()
|
||||
{
|
||||
var model = new IscrizioneEvento() { EventoId = invito.EventoId, InvitoEventoId = invito.Id, ClienteId = invito.ClienteId, DestinazioneId = iscrizione.Destinazione.Id };
|
||||
model = iscrizione.Map(model);
|
||||
|
||||
// TODO: Implementazione generazione QR Code
|
||||
model.QrCodeCode = Guid.NewGuid().ToString();
|
||||
|
||||
await _managerService.IscrizioneEventoService.Salva(model);
|
||||
|
||||
_navManager.NavigateTo($"/");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -112,7 +112,7 @@
|
||||
model = destinazione.Map(model);
|
||||
|
||||
if (destinazione.AgenteId.GetValueOrDefault() != Guid.Empty)
|
||||
model.Agente = await _managerService.UtenteService.RicercaPer(x => x.Id == destinazione.AgenteId);
|
||||
model.AgenteId = destinazione.AgenteId;
|
||||
|
||||
await _managerService.DestinazioneService.Salva(model, idClaim);
|
||||
_dialogService.Close(true);
|
||||
|
||||
53
StandManager/Model/IscrizioneEventoViewModel.cs
Normal file
53
StandManager/Model/IscrizioneEventoViewModel.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using StandManager.Domain.Entita;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace StandManager.Model;
|
||||
public class IscrizioneEventoViewModel
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public EventoViewModel Evento { get; set; }
|
||||
public InvitoEvento InvitoEvento { get; set; }
|
||||
public ClienteViewModel Cliente { get; set; }
|
||||
|
||||
[Required(ErrorMessage = "La destinazione è obbligatoria")]
|
||||
public DestinazioneViewModel Destinazione { get; set; }
|
||||
public int Partecipanti { get; set; }
|
||||
|
||||
[Required(ErrorMessage = "Le note sono obbligatorie")]
|
||||
public string Note { get; set; }
|
||||
public string QrCodeCode { get; set; }
|
||||
public bool ScanCompleto { get; set; }
|
||||
public DateTime? DataScan { get; set; }
|
||||
|
||||
public static implicit operator IscrizioneEventoViewModel(IscrizioneEvento model)
|
||||
{
|
||||
return model == null
|
||||
? null
|
||||
: new IscrizioneEventoViewModel()
|
||||
{
|
||||
Id = model.Id,
|
||||
Evento = model.Evento,
|
||||
InvitoEvento = model.InvitoEvento,
|
||||
Cliente = model.Cliente,
|
||||
Destinazione = model.Destinazione,
|
||||
Partecipanti = model.Partecipanti,
|
||||
Note = model.Note,
|
||||
QrCodeCode = model.QrCodeCode,
|
||||
ScanCompleto = model.ScanCompleto,
|
||||
DataScan = model.DataScan
|
||||
};
|
||||
}
|
||||
|
||||
public IscrizioneEvento Map(IscrizioneEvento model)
|
||||
{
|
||||
model.Partecipanti = Partecipanti;
|
||||
model.Note = Note;
|
||||
model.QrCodeCode = QrCodeCode;
|
||||
model.ScanCompleto = ScanCompleto;
|
||||
model.DataScan = DataScan;
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user