From b8986818b73dc82fb70b20c65e763c8f4a30c5db Mon Sep 17 00:00:00 2001 From: beo3000 Date: Mon, 17 Nov 2025 18:48:54 +0100 Subject: [PATCH] dev daystate --- KoogleApp/Components/Controls/DaysList.razor | 15 ++-- .../Components/Controls/PlayerPanel.razor | 16 ++-- .../Components/Controls/ThrowPanelMenu.razor | 13 ++- KoogleApp/Components/Pages/Game.razor | 37 ++++++-- KoogleApp/Data/Repository/DayRepository.cs | 9 ++ KoogleApp/Data/SharedDataService.cs | 6 ++ KoogleApp/Store/DayFeature/Actions.cs | 15 ++-- KoogleApp/Store/DayFeature/Effects.cs | 60 +++++++++++-- KoogleApp/Store/DayFeature/Reducers.cs | 88 +++++++++++++++---- KoogleApp/Store/DayFeature/Selector.cs | 37 ++++++++ KoogleApp/Store/DayFeature/State.cs | 8 +- KoogleApp/Store/Player/Actions.cs | 2 +- KoogleApp/Store/Player/Reducers.cs | 27 ++++-- 13 files changed, 274 insertions(+), 59 deletions(-) create mode 100644 KoogleApp/Store/DayFeature/Selector.cs diff --git a/KoogleApp/Components/Controls/DaysList.razor b/KoogleApp/Components/Controls/DaysList.razor index 86cb8eb..94871ad 100644 --- a/KoogleApp/Components/Controls/DaysList.razor +++ b/KoogleApp/Components/Controls/DaysList.razor @@ -15,8 +15,8 @@ @foreach (var day in DaysState.Value.Days) { - } @@ -26,6 +26,11 @@ @code { private DayState _selectedValue; + private string GetDayStr(DayState day) + { + return $"{day.Date.ToShortDateString()} - {day.Status}/{(int)day.Status} ({day.Id}), (P:{day.PlayerIds.Select(_ => _.ToString()).Aggregate((a, b) => $"{a},{b}")})"; + } + public DayState? SelectedValue { get => _selectedValue; @@ -34,7 +39,7 @@ protected override void OnInitialized() { - if (DaysState.Value.Loaded) + if (!DaysState.Value.Loaded) { Dispatcher.Dispatch(new LoadDaysAction()); } @@ -42,9 +47,9 @@ base.OnInitialized(); } - private void OnClick(MouseEventArgs obj) + private void OnClick(DayState dayState) { - + Dispatcher.Dispatch(new ChangeSelectedDay(dayState)); } } diff --git a/KoogleApp/Components/Controls/PlayerPanel.razor b/KoogleApp/Components/Controls/PlayerPanel.razor index fc88d8f..62ecea1 100644 --- a/KoogleApp/Components/Controls/PlayerPanel.razor +++ b/KoogleApp/Components/Controls/PlayerPanel.razor @@ -2,6 +2,7 @@ @using KoogleApp.Model @using KoogleApp.Model.EventMessages @using KoogleApp.Services; +@using KoogleApp.Store.DayFeature @using KoogleApp.Store.Player @inherits FluxorComponent @@ -9,6 +10,8 @@ @inject IDispatcher Dispatcher @* @inject IState PlayersState *@ @inject IState PlayerState +@inject IState DayState +@inject IState DaysState @if (@PlayerState.Value != null) { @@ -17,11 +20,14 @@ @PlayerState.Value.Name - - @(PlayerState.Value.Available? "anwesend": "abwesend") + @if (DayState.Value.Status == DayStatus.Started) + { + + @(PlayerState.Value.Available ? "anwesend" : "abwesend") + } diff --git a/KoogleApp/Components/Controls/ThrowPanelMenu.razor b/KoogleApp/Components/Controls/ThrowPanelMenu.razor index 3986a95..e09aa0b 100644 --- a/KoogleApp/Components/Controls/ThrowPanelMenu.razor +++ b/KoogleApp/Components/Controls/ThrowPanelMenu.razor @@ -9,6 +9,7 @@ @inject IDispatcher Dispatcher @inject IState UndoRedoState @inject IState ThrowPanelState +@inject IState DayState @inject IDialogService DialogService @@ -67,7 +68,7 @@ } else { - var result = await DialogService.ShowMessageBox("Spiel beenden?", "Spiel wirklich abbrechen?", "JA", "NEIN"); + var result = await DialogService.ShowMessageBox("Spiel beenden?", "Spiel wirklich abbrechen?", "JA", "NEIN", cancelText: "Abbrechen"); if (result.Value) { var action = new StartStopAction(ThrowPanelState.Value, null); @@ -82,9 +83,15 @@ // await InvokeAsync(StateHasChanged); } - private void CloseDayClick(MouseEventArgs obj) + private async Task CloseDayClick(MouseEventArgs obj) { - Dispatcher.Dispatch(new CloseDayStateAction()); + var result = await DialogService.ShowMessageBox("Spiel Abschließen?", "Spiel wirklich abbrechen?", "JA abschließen", "NEIN offen lassen", cancelText: "Abbrechen"); + if (!result.HasValue) + { + return; + } + + Dispatcher.Dispatch(new ChangeDayStatusAction(DayState.Value, result.Value ? DayStatus.Closed : DayStatus.Postponed)); } } diff --git a/KoogleApp/Components/Pages/Game.razor b/KoogleApp/Components/Pages/Game.razor index c6aeb01..c02c2d4 100644 --- a/KoogleApp/Components/Pages/Game.razor +++ b/KoogleApp/Components/Pages/Game.razor @@ -36,13 +36,14 @@ { case GameView.Throw: + @GetDayStr() @if (DayState.Value.Status != DayStatus.Started) { - - } - else + + } + else { - + } break; @@ -60,26 +61,28 @@ +

@GetDayStr()

@switch (_gameView) { case GameView.Throw: if (DayState.Value.Status != DayStatus.Started) { - + } else { - + } + break; case GameView.Board: - + break; case GameView.Players: - + break; case GameView.Player: - + break; }
@@ -117,6 +120,22 @@ } } + private string GetDayStr() + { + if (DayState.Value == null) + { + return ""; + } + var day = DayState.Value; + var res = $"{day.Date.ToShortDateString()} - {day.Status}/{(int)day.Status} ({day.Id})"; + if (day.PlayerIds.Length > 0) + { + res += $" (P:{day.PlayerIds.Select(_ => _.ToString()).Aggregate((a, b) => $"{a},{b}")})"; + } + return res; + } + + protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); diff --git a/KoogleApp/Data/Repository/DayRepository.cs b/KoogleApp/Data/Repository/DayRepository.cs index 5b90dfb..a1c6aaa 100644 --- a/KoogleApp/Data/Repository/DayRepository.cs +++ b/KoogleApp/Data/Repository/DayRepository.cs @@ -8,6 +8,7 @@ namespace KoogleApp.Data.Repository Task> GetAllAsync(int year); Task GetActiveDayAsync(); Task AddAsync(Day day); + Task UpdateAsync(Day day); } public class DayRepository(IDbContextFactory contextFactory, ILogger logger) @@ -36,5 +37,13 @@ namespace KoogleApp.Data.Repository await context.SaveChangesAsync(); return day; } + + public async Task UpdateAsync(Day day) + { + await using var context = await contextFactory.CreateDbContextAsync(); + var res = context.Days.Update(day); + await context.SaveChangesAsync(); + return res.Entity; + } } } diff --git a/KoogleApp/Data/SharedDataService.cs b/KoogleApp/Data/SharedDataService.cs index a3003bb..96d633a 100644 --- a/KoogleApp/Data/SharedDataService.cs +++ b/KoogleApp/Data/SharedDataService.cs @@ -186,5 +186,11 @@ namespace KoogleApp.Data var newDay = await _dayRepository.AddAsync(day); return newDay; } + + public async Task UpdateDayAsync(Day day) + { + var modifiedDay = await _dayRepository.UpdateAsync(day); + return modifiedDay; + } } } diff --git a/KoogleApp/Store/DayFeature/Actions.cs b/KoogleApp/Store/DayFeature/Actions.cs index c01f875..b954f8e 100644 --- a/KoogleApp/Store/DayFeature/Actions.cs +++ b/KoogleApp/Store/DayFeature/Actions.cs @@ -8,22 +8,25 @@ namespace KoogleApp.Store.DayFeature public record LoadDaysAction(); - public record DayStateLoadedAction(Day Day); + public record DayLoadedAction(Day Day); + + public record DayStateLoadedAction(DayState DayState); public record DaysStateLoadedAction(List Days, int Year); - public record AddDayStateAction(DayModel DayModel); + //public record AddDayStateAction(DayModel DayModel); + public record ChangeSelectedDay(DayState DayState); - public record CloseDayStateAction(); + public record ChangeDayStatusAction(DayState DayState, DayStatus Status); - public class DayModelSubmitSuccessAction { } + public record DayModelSubmitSuccessAction(Day Day) { } - public class DayModelSubmitFailureAction(string errorMessage) + public record DayModelSubmitFailureAction(string errorMessage) { public string ErrorMessage { get; } = errorMessage; } - public class DayModelSubmitAction(DayModel dayModel) + public record DayModelSubmitAction(DayModel dayModel) { public DayModel DayModel { get; } = dayModel; } diff --git a/KoogleApp/Store/DayFeature/Effects.cs b/KoogleApp/Store/DayFeature/Effects.cs index 569f86c..64c97eb 100644 --- a/KoogleApp/Store/DayFeature/Effects.cs +++ b/KoogleApp/Store/DayFeature/Effects.cs @@ -2,6 +2,7 @@ using Fluxor.Blazor.Web; using KoogleApp.Data; using KoogleApp.Model; +using KoogleApp.Store.Player; using System.Net.Http; using System.Runtime.InteropServices.JavaScript; using System.Text.Json; @@ -16,7 +17,7 @@ namespace KoogleApp.Store.DayFeature var day = await dataService.GetActiveDayAsync(); if (day != null) { - dispatcher.Dispatch(new DayStateLoadedAction(day)); + dispatcher.Dispatch(new DayLoadedAction(day)); } } @@ -31,20 +32,67 @@ namespace KoogleApp.Store.DayFeature } } + [EffectMethod] + public async Task HandelChangeDayStateAction(ChangeDayStatusAction action, IDispatcher dispatcher) + { + var day = DayStateSelector.DbConvert(action.DayState); + day.Status = action.Status; + await dataService.UpdateDayAsync(day); + } + + [EffectMethod] + public async Task HandelChangeSelectedDay(ChangeSelectedDay action, IDispatcher dispatcher) + { + var day = DayStateSelector.DbConvert(action.DayState); + day.Status = DayStatus.Started; + await dataService.UpdateDayAsync(day); + } + + [EffectMethod] + public async Task HandelChangePlayerAvailableAction(ChangePlayerAvailableAction action, IDispatcher dispatcher) + { + var newList = new List(action.DayState.PlayerIds); // Kopie erstellen + if (action.IsAvailable) + { + newList.Add(action.PlayerId); + } + else + { + newList.Remove(action.PlayerId); + } + + var day = DayStateSelector.DbConvert(action.DayState); + day.Players = JsonSerializer.Serialize(newList); + await dataService.UpdateDayAsync(day); + + + // Update an DayState senden + dispatcher.Dispatch(new DayStateLoadedAction(DayStateSelector.DbConvert(day))); + + + var newDays = new List(action.DaysState.Days.Select(_ => DayStateSelector.DbConvert(_))); + var idx = newDays.FindIndex(p => p.Id == action.DayState.Id); + newDays[idx].Players = day.Players; + + // Update an DaysState senden + dispatcher.Dispatch(new DaysStateLoadedAction(newDays, action.DaysState.Year)); + } + [EffectMethod] public async Task SubmitDayModel(DayModelSubmitAction action, IDispatcher dispatcher) { var msg = ""; + Day? day = null; try { - var day = await dataService.AddDayAsync(new Day + day = await dataService.AddDayAsync(new Day { Status = DayStatus.Started, CreatedAt = DateTime.UtcNow, Players = JsonSerializer.Serialize(action.DayModel.Players.Select(_ => _.Id)), PostDate = action.DayModel.PostDate.Value }); - dispatcher.Dispatch(new DayStateLoadedAction(day)); + dispatcher.Dispatch(new DayLoadedAction(day)); } catch (Exception e) { @@ -52,10 +100,10 @@ namespace KoogleApp.Store.DayFeature } //var response = await _httpClient.PostAsJsonAsync("Feedback", action.UserFeedbackModel); - if (1==1) + if (day != null && string.IsNullOrEmpty(msg)) { - dispatcher.Dispatch(new AddDayStateAction(action.DayModel)); - dispatcher.Dispatch(new DayModelSubmitSuccessAction()); + //dispatcher.Dispatch(new AddDayStateAction(action.DayModel)); + dispatcher.Dispatch(new DayModelSubmitSuccessAction(day)); } else { diff --git a/KoogleApp/Store/DayFeature/Reducers.cs b/KoogleApp/Store/DayFeature/Reducers.cs index 4fe92b4..9e10572 100644 --- a/KoogleApp/Store/DayFeature/Reducers.cs +++ b/KoogleApp/Store/DayFeature/Reducers.cs @@ -1,45 +1,64 @@ -using System.Text.Json; -using Fluxor; +using Fluxor; using KoogleApp.Model; using KoogleApp.Store.Game.Setup; +using KoogleApp.Store.Player; +using System.Text.Json; +using Microsoft.Identity.Client; namespace KoogleApp.Store.DayFeature { public static class DayStateReducers { - + [ReducerMethod] - public static DayState OnCloseDayStateAction(DayState state, CloseDayStateAction action) + public static DayState OnChangeDayStatusAction(DayState state, ChangeDayStatusAction action) { return state with { - Status = DayStatus.Finished + Status = action.Status }; } [ReducerMethod] - public static DayState OnAddDayStateAction(DayState state, AddDayStateAction action) + public static DaysState OnChangeDayStatusAction(DaysState state, ChangeDayStatusAction action) { - return new DayState(0, action.DayModel.PostDate.Value, DayStatus.Started, PlayerIds: []); + var newList = new List(state.Days); // Kopie erstellen + var idx = state.Days.FindIndex(p => p.Id == action.DayState.Id); + if (idx >= 0) + { + newList[idx] = newList[idx] with { Status = action.Status }; // Element ändern + return state with { Days = newList }; + } + + return state; + } + + [ReducerMethod] + public static DayState OnDayLoadedAction(DayState state, DayLoadedAction action) + { + var day = DayStateSelector.DbConvert(action.Day); + return day; } [ReducerMethod] - public static DaysState OnAddDayStateAction(DaysState state, AddDayStateAction action) + + public static DayState OnChangeSelectedDay(DayState state, ChangeSelectedDay action) { - state.Days.Add(new DayState(0, action.DayModel.PostDate.Value, DayStatus.Started, PlayerIds: [])); - return state; + return action.DayState with + { + Status = DayStatus.Started + }; } - [ReducerMethod] public static DayState OnDayStateLoadedAction(DayState state, DayStateLoadedAction action) { return state with { - Id = action.Day.Id, - Date = action.Day.PostDate, - Status = action.Day.Status, - PlayerIds = JsonSerializer.Deserialize(action.Day.Players) + Id = action.DayState.Id, + Date = action.DayState.Date, + Status = action.DayState.Status, + PlayerIds = action.DayState.PlayerIds }; } @@ -50,13 +69,41 @@ namespace KoogleApp.Store.DayFeature { Loaded = true, Year = action.Year, - Days = action.Days.Select(_ => new DayState(_.Id, _.PostDate, _.Status, PlayerIds: [])).ToList() + Days = action.Days.Select(DayStateSelector.DbConvert).ToList() }; + } + [ReducerMethod] + public static DayState OnChangePlayerAvailableAction(DayState state, + ChangePlayerAvailableAction action) + { + if (state.Status != DayStatus.Started) + { + throw new InvalidOperationException("ChangePlayerAvailableAction not allowed when day not started"); + } + + var ids = state.PlayerIds.ToList(); + if (action.IsAvailable) + { + ids.Add(action.PlayerId); + } + else + { + ids.Remove(action.PlayerId); + } + + return state with + { + PlayerIds = ids.ToArray() + }; } + + + // MODEL REDUCERS + [ReducerMethod(typeof(DayModelSubmitAction))] public static DayModelState OnSubmit(DayModelState state) { @@ -81,6 +128,15 @@ namespace KoogleApp.Store.DayFeature }; } + [ReducerMethod] + public static DaysState OnSubmitSuccess(DaysState state, DayModelSubmitSuccessAction action) + { + var newList = new List(state.Days); + var dayState = DayStateSelector.DbConvert(action.Day); + newList.Add(dayState); + return state with { Days = newList }; + } + [ReducerMethod] public static DayModelState OnSubmitFailure(DayModelState state, DayModelSubmitFailureAction action) { diff --git a/KoogleApp/Store/DayFeature/Selector.cs b/KoogleApp/Store/DayFeature/Selector.cs new file mode 100644 index 0000000..19aeedd --- /dev/null +++ b/KoogleApp/Store/DayFeature/Selector.cs @@ -0,0 +1,37 @@ +using KoogleApp.Model; +using System; +using System.Text.Json; + +namespace KoogleApp.Store.DayFeature +{ + public static class DayStateSelector + { + public static DayState DbConvert(Day day) + { + return new DayState + { + Id = day.Id, + Date = day.PostDate, + Status = day.Status, + PlayerIds = JsonSerializer.Deserialize(day.Players), + CreatedAt = day.CreatedAt, + ModifiedAt = day.ModifiedAt, + ModifiedBy = day.ModifiedBy + }; + } + + public static Day DbConvert(DayState dayState) + { + return new Day + { + Id = dayState.Id, + PostDate = dayState.Date, + Status = dayState.Status, + Players = JsonSerializer.Serialize(dayState.PlayerIds), + CreatedAt = dayState.CreatedAt, + ModifiedAt = dayState.ModifiedAt, + ModifiedBy = dayState.ModifiedBy + }; + } + } +} diff --git a/KoogleApp/Store/DayFeature/State.cs b/KoogleApp/Store/DayFeature/State.cs index b3f706b..c0f4058 100644 --- a/KoogleApp/Store/DayFeature/State.cs +++ b/KoogleApp/Store/DayFeature/State.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices.JavaScript; using Fluxor; using KoogleApp.Model; using KoogleApp.Store.ModelFeature; @@ -10,7 +11,8 @@ namespace KoogleApp.Store.DayFeature { New, Started, - Finished + Postponed, + Closed } [FeatureState] @@ -23,9 +25,9 @@ namespace KoogleApp.Store.DayFeature } [FeatureState] - public record DayState(int Id, DateTime Date, DayStatus Status, int[] PlayerIds) + public record DayState(int Id, DateTime Date, DayStatus Status, int[] PlayerIds, DateTime CreatedAt, DateTime? ModifiedAt, string ModifiedBy) { - public DayState() : this(Id: 0, Date: DateTime.Today, Status: DayStatus.New, PlayerIds: []) + public DayState() : this(Id: 0, Date: DateTime.Today, Status: DayStatus.New, PlayerIds: [], CreatedAt: DateTime.MinValue, ModifiedAt: DateTime.MinValue, ModifiedBy:String.Empty) { } } diff --git a/KoogleApp/Store/Player/Actions.cs b/KoogleApp/Store/Player/Actions.cs index 6c84f34..b57928a 100644 --- a/KoogleApp/Store/Player/Actions.cs +++ b/KoogleApp/Store/Player/Actions.cs @@ -9,5 +9,5 @@ namespace KoogleApp.Store.Player public record SelectPlayerAction(PlayerState? Player); - public record ChangePlayerAvailableAction(int PlayerId, bool IsAvailable); + public record ChangePlayerAvailableAction(int PlayerId, bool IsAvailable, DayState DayState, DaysState DaysState); } diff --git a/KoogleApp/Store/Player/Reducers.cs b/KoogleApp/Store/Player/Reducers.cs index 73bc07e..eb2a08c 100644 --- a/KoogleApp/Store/Player/Reducers.cs +++ b/KoogleApp/Store/Player/Reducers.cs @@ -14,10 +14,11 @@ namespace KoogleApp.Store.Player var playerIds = action.DayState.PlayerIds; var players = action.Players - .Select(p => new PlayerState(p.Name, p.Id, Available: playerIds.Contains(p.Id), PlayerStatus: PlayerStatus.Guest)) + .Select(p => new PlayerState(p.Name, p.Id, Available: playerIds.Contains(p.Id), + PlayerStatus: PlayerStatus.Guest)) .ToList(); - return state with { Players = players, Loaded = true}; + return state with { Players = players, Loaded = true }; } [ReducerMethod] @@ -36,15 +37,15 @@ namespace KoogleApp.Store.Player [ReducerMethod] public static PlayersState OnChangePlayerAvailableAction(PlayersState state, ChangePlayerAvailableAction action) { - var newList = new List(state.Players); // Kopie erstellen + var newList = new List(state.Players); // Kopie erstellen var idx = state.Players.FindIndex(p => p.Id == action.PlayerId); - newList[idx] = newList[idx] with { Available = action.IsAvailable }; // Element ändern + newList[idx] = newList[idx] with { Available = action.IsAvailable }; // Element ändern return state with { Players = newList }; } [ReducerMethod] - public static PlayersState OnDayStateLoadedAction(PlayersState state, DayStateLoadedAction action) + public static PlayersState OnDayLoadedAction(PlayersState state, DayLoadedAction action) { if (state.Players.Count == 0) { @@ -63,5 +64,21 @@ namespace KoogleApp.Store.Player }; return res; } + + [ReducerMethod] + public static PlayersState OnChangeSelectedDay(PlayersState state, ChangeSelectedDay action) + { + var lst = new List(); + + foreach (var playerState in state.Players) + { + lst.Add(playerState with + { + Available = action.DayState.PlayerIds.Contains(playerState.Id) + }); + } + + return state with { Players = lst }; + } } }