87db67f979
Updated the MudPaper component styling in multiple files to use a consistent padding class of "pa-3 pa-md-6" instead of "pa-6". This change enhances the visual consistency of the UI across the Calendar, Events, Students, and Teams components, improving the overall user experience.
234 lines
10 KiB
Plaintext
234 lines
10 KiB
Plaintext
@page "/events/edit"
|
|
@attribute [Authorize]
|
|
@using Microsoft.EntityFrameworkCore
|
|
@using WebApp.Components.Shared.Components
|
|
@using Core.Utility
|
|
@using MudBlazor
|
|
@using System.ComponentModel.DataAnnotations
|
|
@using WebApp.Services
|
|
@inject AppDbContext context
|
|
@inject NavigationManager NavigationManager
|
|
@inject ISnackbar Snackbar
|
|
@inject FormValidationService ValidationService
|
|
@inject EventDefinitionService EventDefinitionService
|
|
|
|
@if (EventDefinition is null || _editContext is null)
|
|
{
|
|
<p><em>Loading...</em></p>
|
|
return;
|
|
}
|
|
|
|
<PageHeader
|
|
Title="Edit"
|
|
Subtitle="Event"
|
|
ShowBackButton="true"
|
|
BackButtonUrl="@(ReturnUrl ?? "/events")" />
|
|
|
|
<EditForm EditContext="@_editContext" OnValidSubmit="OnValidSubmit" OnInvalidSubmit="OnInvalidSubmit" Enhance>
|
|
<FormChangeTracker @ref="_formChangeTracker" />
|
|
<AntiforgeryToken />
|
|
<DataAnnotationsValidator />
|
|
|
|
<ValidationErrorDisplay Errors="_validationErrors" />
|
|
|
|
<MudStack Spacing="4">
|
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
|
<MudText Typo="Typo.h5" Class="mb-4">Basic Information</MudText>
|
|
<MudGrid Spacing="3">
|
|
<MudItem xs="12" sm="6">
|
|
<MudTextField T="string" Label="Event Name" @bind-Value="EventDefinition.Name" For="@(() => EventDefinition.Name)" Variant="Variant.Outlined"></MudTextField>
|
|
</MudItem>
|
|
<MudItem xs="12" sm="6">
|
|
<MudTextField T="string" Label="Short Name" @bind-Value="EventDefinition.ShortName" For="@(() => EventDefinition.ShortName)" Variant="Variant.Outlined"></MudTextField>
|
|
</MudItem>
|
|
<MudItem xs="12">
|
|
<MudText Typo="Typo.subtitle2" Class="mb-2 mud-text-secondary">Event Format</MudText>
|
|
<MudRadioGroup T="EventFormat" @bind-Value="@EventDefinition.EventFormat" For="@(() => EventDefinition.EventFormat)">
|
|
@foreach (EventFormat format in Enum.GetValues(typeof(EventFormat)))
|
|
{
|
|
<MudRadio T="EventFormat" Value="@format">@format.ToString()</MudRadio>
|
|
}
|
|
</MudRadioGroup>
|
|
</MudItem>
|
|
<MudItem xs="12" sm="6">
|
|
<MudNumericField T="int?" Label="Level of Effort" @bind-Value="EventDefinition.LevelOfEffort" For="@(() => EventDefinition.LevelOfEffort)" Variant="Variant.Outlined"></MudNumericField>
|
|
</MudItem>
|
|
</MudGrid>
|
|
</MudPaper>
|
|
|
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
|
<MudText Typo="Typo.h5" Class="mb-4">Event Details</MudText>
|
|
<MudGrid Spacing="3">
|
|
<MudItem xs="12">
|
|
<MudTextField T="string" Label="Description" AutoGrow="true" Lines="3" @bind-Value="EventDefinition.Description" For="@(() => EventDefinition.Description)" Variant="Variant.Outlined"></MudTextField>
|
|
</MudItem>
|
|
<MudItem xs="12">
|
|
<MudTextField T="string" Label="Theme" AutoGrow="true" Lines="2" @bind-Value="EventDefinition.Theme" For="@(() => EventDefinition.Theme)" Variant="Variant.Outlined"></MudTextField>
|
|
</MudItem>
|
|
<MudItem xs="12">
|
|
<MudTextField T="string" Label="Documentation" @bind-Value="EventDefinition.Documentation" For="@(() => EventDefinition.Documentation)" Variant="Variant.Outlined"></MudTextField>
|
|
</MudItem>
|
|
<MudItem xs="12">
|
|
<MudTextField T="string" Label="Related Careers" AutoGrow="true" Lines="5" @bind-Value="EventDefinition.RelatedCareersText" HelperText="Enter one career per line (bullet points will be removed automatically)" Variant="Variant.Outlined"></MudTextField>
|
|
</MudItem>
|
|
</MudGrid>
|
|
</MudPaper>
|
|
|
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
|
<MudText Typo="Typo.h5" Class="mb-4">Team Configuration</MudText>
|
|
<MudGrid Spacing="3">
|
|
<MudItem xs="12">
|
|
<MudTextField T="string" Label="Nationals Eligibility" @bind-Value="EventDefinition.Eligibility" For="@(() => EventDefinition.Eligibility)" Variant="Variant.Outlined"></MudTextField>
|
|
</MudItem>
|
|
<MudItem xs="12" sm="6">
|
|
<MudNumericField T="int" Label="Minimum Team Size" @bind-Value="EventDefinition.MinTeamSize" For="@(() => EventDefinition.MinTeamSize)" Variant="Variant.Outlined"></MudNumericField>
|
|
</MudItem>
|
|
<MudItem xs="12" sm="6">
|
|
<MudNumericField T="int" Label="Maximum Team Size" @bind-Value="EventDefinition.MaxTeamSize" For="@(() => EventDefinition.MaxTeamSize)" Variant="Variant.Outlined"></MudNumericField>
|
|
</MudItem>
|
|
<MudItem xs="12" sm="6">
|
|
<MudNumericField T="int" Label="Team Count at Regionals" @bind-Value="EventDefinition.ChapterEligibilityCountRegionals" For="@(() => EventDefinition.ChapterEligibilityCountRegionals)" Variant="Variant.Outlined"></MudNumericField>
|
|
</MudItem>
|
|
<MudItem xs="12" sm="6">
|
|
<MudNumericField T="int" Label="Team Count at State" @bind-Value="EventDefinition.ChapterEligibilityCountState" For="@(() => EventDefinition.ChapterEligibilityCountState)" Variant="Variant.Outlined"></MudNumericField>
|
|
</MudItem>
|
|
</MudGrid>
|
|
</MudPaper>
|
|
|
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
|
<MudText Typo="Typo.h5" Class="mb-4">Competition Details</MudText>
|
|
<MudGrid Spacing="3">
|
|
<MudItem xs="12">
|
|
<MudTextField T="string" Label="Semifinalist Activity" @bind-Value="EventDefinition.SemifinalistActivity" For="@(() => EventDefinition.SemifinalistActivity)" Variant="Variant.Outlined"></MudTextField>
|
|
</MudItem>
|
|
<MudItem xs="12">
|
|
<MudCheckBox T="bool" Label="On Site Activity" @bind-Value="EventDefinition.OnSiteActivity" For="@(() => EventDefinition.OnSiteActivity)"></MudCheckBox>
|
|
</MudItem>
|
|
<MudItem xs="12">
|
|
<MudCheckBox T="bool" Label="Requires Presubmission" @bind-Value="EventDefinition.Presubmission" For="@(() => EventDefinition.Presubmission)"></MudCheckBox>
|
|
</MudItem>
|
|
</MudGrid>
|
|
|
|
<FormActions>
|
|
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary">Save</MudButton>
|
|
<MudButton OnClick="HandleCancel" Variant="Variant.Text">Cancel</MudButton>
|
|
</FormActions>
|
|
</MudPaper>
|
|
</MudStack>
|
|
</EditForm>
|
|
|
|
@code {
|
|
[SupplyParameterFromQuery]
|
|
private int Id { get; set; }
|
|
|
|
[SupplyParameterFromQuery]
|
|
private string? ReturnUrl { get; set; }
|
|
|
|
[SupplyParameterFromForm]
|
|
private EventDefinition? EventDefinition { get; set; }
|
|
|
|
private FormChangeTracker? _formChangeTracker;
|
|
private EditContext? _editContext;
|
|
private List<string> _validationErrors = new();
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
EventDefinition ??= await context.Events
|
|
.Include(e => e.RelatedCareers)
|
|
.FirstOrDefaultAsync(m => m.Id == Id);
|
|
|
|
if (EventDefinition is null)
|
|
{
|
|
NavigationManager.NavigateTo("notfound");
|
|
}
|
|
else
|
|
{
|
|
// Populate RelatedCareersText from RelatedCareers collection
|
|
EventDefinition.RelatedCareersText = string.Join("\n", EventDefinition.RelatedCareers.Select(c => c.Name));
|
|
|
|
// Create EditContext for validation
|
|
_editContext = new EditContext(EventDefinition);
|
|
}
|
|
}
|
|
|
|
private void OnInvalidSubmit(EditContext editContext)
|
|
{
|
|
_validationErrors = ValidationService.HandleInvalidSubmit(editContext, EventDefinition!, errors => _validationErrors = errors);
|
|
StateHasChanged();
|
|
}
|
|
|
|
// To protect from overposting attacks, enable the specific properties you want to bind to.
|
|
// For more information, see https://learn.microsoft.com/aspnet/core/blazor/forms/#mitigate-overposting-attacks.
|
|
private async Task OnValidSubmit()
|
|
{
|
|
try
|
|
{
|
|
// Get the tracked entity from the database
|
|
var trackedEntity = await context.Events
|
|
.Include(e => e.RelatedCareers)
|
|
.FirstOrDefaultAsync(e => e.Id == EventDefinition!.Id);
|
|
|
|
if (trackedEntity == null)
|
|
{
|
|
Snackbar.Add("Event not found. It may have been deleted.", Severity.Error);
|
|
NavigationManager.NavigateTo("notfound");
|
|
return;
|
|
}
|
|
|
|
// Update scalar properties from the form-bound entity
|
|
context.Entry(trackedEntity).CurrentValues.SetValues(EventDefinition!);
|
|
|
|
// Normalize and process related careers
|
|
await EventDefinitionService.ProcessRelatedCareersAsync(trackedEntity);
|
|
|
|
await context.SaveChangesAsync();
|
|
_validationErrors.Clear();
|
|
Snackbar.Add($"Event '{EventDefinition!.Name}' saved successfully.", Severity.Success);
|
|
_formChangeTracker?.AllowNavigation();
|
|
NavigationManager.NavigateTo(ReturnUrl ?? "/events");
|
|
}
|
|
catch (DbUpdateConcurrencyException ex)
|
|
{
|
|
if (!ValidationService.HandleDbUpdateConcurrencyException(
|
|
ex,
|
|
() => EventDefinitionExists(EventDefinition!.Id),
|
|
"event",
|
|
() => NavigationManager.NavigateTo("notfound")))
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
catch (DbUpdateException ex)
|
|
{
|
|
ValidationService.HandleDbUpdateException(
|
|
ex,
|
|
"An error occurred while saving the event.",
|
|
"event",
|
|
"saving",
|
|
"name");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ValidationService.HandleException(ex);
|
|
}
|
|
}
|
|
|
|
|
|
private async Task HandleCancel()
|
|
{
|
|
// Discard all in-memory changes by reloading from database
|
|
if (EventDefinition != null)
|
|
{
|
|
await context.Entry(EventDefinition).ReloadAsync();
|
|
}
|
|
|
|
_formChangeTracker?.AllowNavigation();
|
|
NavigationManager.NavigateTo(ReturnUrl ?? "/events");
|
|
}
|
|
|
|
private bool EventDefinitionExists(int id)
|
|
{
|
|
return context.Events.Any(e => e.Id == id);
|
|
}
|
|
}
|