diff --git a/src/Koogle.Web/Components/Pages/Admin/ClubEditDialog.razor b/src/Koogle.Web/Components/Pages/Admin/ClubEditDialog.razor new file mode 100644 index 0000000..0f04825 --- /dev/null +++ b/src/Koogle.Web/Components/Pages/Admin/ClubEditDialog.razor @@ -0,0 +1,97 @@ +@using Koogle.Application.DTOs +@using Koogle.Domain.Enums + + + + + @(IsEditMode ? "Club bearbeiten" : "Neuer Club") + + + + + + + + Keine + Durchschnitt + Maximum + + + + @GetCalculationDescription(_expenseCalculation) + + + + + Abbrechen + + @(IsEditMode ? "Speichern" : "Erstellen") + + + + +@code { + [CascadingParameter] + private IMudDialogInstance? MudDialog { get; set; } + + [Parameter] + public ClubDto? Club { get; set; } + + private MudForm? _form; + private bool _isValid; + private string _name = ""; + private ExpenseCalculation _expenseCalculation = ExpenseCalculation.None; + + private bool IsEditMode => Club is not null; + + protected override void OnInitialized() + { + if (Club is not null) + { + _name = Club.Name; + _expenseCalculation = Club.ExpenseCalculation; + } + } + + private static string GetCalculationDescription(ExpenseCalculation calculation) => calculation switch + { + ExpenseCalculation.None => "Keine automatische Kostenberechnung für abwesende Personen", + ExpenseCalculation.Average => "Abwesende Personen zahlen den Durchschnitt aller Kosten des Tages", + ExpenseCalculation.Maximum => "Abwesende Personen zahlen das Maximum aller Kosten des Tages", + _ => "" + }; + + private void Cancel() => MudDialog?.Cancel(); + + private void Submit() + { + if (!_isValid) return; + + if (IsEditMode) + { + var dto = new UpdateClubDto + { + Id = Club!.Id, + Name = _name, + ExpenseCalculation = _expenseCalculation + }; + MudDialog?.Close(DialogResult.Ok(dto)); + } + else + { + var dto = new CreateClubDto + { + Name = _name, + ExpenseCalculation = _expenseCalculation + }; + MudDialog?.Close(DialogResult.Ok(dto)); + } + } +} diff --git a/src/Koogle.Web/Components/Pages/Admin/Clubs.razor b/src/Koogle.Web/Components/Pages/Admin/Clubs.razor new file mode 100644 index 0000000..992b21f --- /dev/null +++ b/src/Koogle.Web/Components/Pages/Admin/Clubs.razor @@ -0,0 +1,170 @@ +@page "/admin/clubs" +@attribute [Authorize(Roles = "SuperAdmin")] + +@inherits Fluxor.Blazor.Web.Components.FluxorComponent + +@using Fluxor +@using Koogle.Application.DTOs +@using Koogle.Domain.Enums +@using Koogle.Web.Store.ClubState +@using Microsoft.AspNetCore.Authorization + +@inject IState ClubState +@inject IDispatcher Dispatcher +@inject ISnackbar Snackbar +@inject IDialogService DialogService + +Clubs verwalten + +Clubs verwalten + +@if (ClubState.Value.Error is not null) +{ + + @ClubState.Value.Error + +} + + + + + + + Neuer Club + + + + Name + Kostenberechnung + Mitglieder + Gäste + Tage + Erstellt + Aktionen + + + @context.Name + + + @GetCalculationLabel(context.ExpenseCalculation) + + + @context.MemberCount + @context.GuestCount + @context.DayCount + @context.CreatedAt.ToString("dd.MM.yyyy") + + + + + + + + + + + + + + Keine Clubs gefunden + + + +@code { + private string _searchString = ""; + + protected override void OnInitialized() + { + base.OnInitialized(); + Dispatcher.Dispatch(new LoadClubsAction()); + } + + private bool FilterFunc(ClubDto club) + { + if (string.IsNullOrWhiteSpace(_searchString)) + return true; + + return club.Name.Contains(_searchString, StringComparison.OrdinalIgnoreCase); + } + + private void ClearError() + { + Dispatcher.Dispatch(new ClearClubErrorAction()); + } + + private static string GetCalculationLabel(ExpenseCalculation calculation) => calculation switch + { + ExpenseCalculation.None => "Keine", + ExpenseCalculation.Average => "Durchschnitt", + ExpenseCalculation.Maximum => "Maximum", + _ => calculation.ToString() + }; + + private static Color GetCalculationColor(ExpenseCalculation calculation) => calculation switch + { + ExpenseCalculation.None => Color.Default, + ExpenseCalculation.Average => Color.Info, + ExpenseCalculation.Maximum => Color.Warning, + _ => Color.Default + }; + + private async Task OpenCreateDialog() + { + var dialog = await DialogService.ShowAsync("Neuer Club"); + var result = await dialog.Result; + + if (result != null && !result.Canceled && result.Data is CreateClubDto dto) + { + Dispatcher.Dispatch(new CreateClubAction(dto)); + Snackbar.Add("Club wird erstellt...", Severity.Info); + } + } + + private async Task OpenEditDialog(ClubDto club) + { + var parameters = new DialogParameters + { + { "Club", club } + }; + + var dialog = await DialogService.ShowAsync("Club bearbeiten", parameters); + var result = await dialog.Result; + + if (result != null && !result.Canceled && result.Data is UpdateClubDto dto) + { + Dispatcher.Dispatch(new UpdateClubAction(dto)); + Snackbar.Add("Club wird aktualisiert...", Severity.Info); + } + } + + private async Task ConfirmDelete(ClubDto club) + { + var parameters = new DialogParameters + { + { "ContentText", $"Möchten Sie den Club \"{club.Name}\" wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden." }, + { "ButtonText", "Löschen" }, + { "Color", Color.Error } + }; + + var dialog = await DialogService.ShowAsync("Club löschen", parameters); + var result = await dialog.Result; + + if (result != null && !result.Canceled) + { + Dispatcher.Dispatch(new DeleteClubAction(club.Id)); + Snackbar.Add("Club wird gelöscht...", Severity.Info); + } + } +} diff --git a/src/Koogle.Web/Components/Shared/ConfirmDialog.razor b/src/Koogle.Web/Components/Shared/ConfirmDialog.razor new file mode 100644 index 0000000..08b57c8 --- /dev/null +++ b/src/Koogle.Web/Components/Shared/ConfirmDialog.razor @@ -0,0 +1,26 @@ + + + @ContentText + + + Abbrechen + @ButtonText + + + +@code { + [CascadingParameter] + private IMudDialogInstance? MudDialog { get; set; } + + [Parameter] + public string ContentText { get; set; } = "Sind Sie sicher?"; + + [Parameter] + public string ButtonText { get; set; } = "OK"; + + [Parameter] + public Color Color { get; set; } = Color.Primary; + + private void Cancel() => MudDialog?.Cancel(); + private void Submit() => MudDialog?.Close(DialogResult.Ok(true)); +}