dev daystate

This commit is contained in:
beo3000 2025-11-17 18:48:54 +01:00
parent 1026ac79f7
commit b8986818b7
13 changed files with 274 additions and 59 deletions

View File

@ -15,8 +15,8 @@
@foreach (var day in DaysState.Value.Days)
{
<MudListItem Text="@day.Date.ToShortDateString()"
OnClick="OnClick"
<MudListItem Text="@(GetDayStr(day))"
OnClick="@(() => OnClick(day))"
Value="@day" />
}
@ -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));
}
}

View File

@ -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> PlayersState *@
@inject IState<PlayerState> PlayerState
@inject IState<DayState> DayState
@inject IState<DaysState> DaysState
@if (@PlayerState.Value != null)
{
@ -17,11 +20,14 @@
<MudItem xs="12">
<MudPaper Class="d-flex align-center justify-center mud-width-full py-0">
<MudText Typo="Typo.h4">@PlayerState.Value.Name</MudText>
<StateSwitch TState="PlayerState"
Color="Color.Tertiary"
ValueSelector="@(state => state.Available)"
OnValueChanged="@(value => Dispatcher.Dispatch(new ChangePlayerAvailableAction(PlayerState.Value.Id, value)))" />
<MudText Typo="Typo.subtitle2">@(PlayerState.Value.Available? "anwesend": "abwesend")</MudText>
@if (DayState.Value.Status == DayStatus.Started)
{
<StateSwitch TState="PlayerState"
Color="Color.Tertiary"
ValueSelector="@(state => state.Available)"
OnValueChanged="@(value => Dispatcher.Dispatch(new ChangePlayerAvailableAction(PlayerState.Value.Id, value, DayState.Value, DaysState.Value)))" />
<MudText Typo="Typo.subtitle2">@(PlayerState.Value.Available ? "anwesend" : "abwesend")</MudText>
}
</MudPaper>
</MudItem>

View File

@ -9,6 +9,7 @@
@inject IDispatcher Dispatcher
@inject IState<UndoRedoState> UndoRedoState
@inject IState<ThrowPanelState> ThrowPanelState
@inject IState<DayState> DayState
@inject IDialogService DialogService
<MudTooltip Text="Undo" Color="Color.Primary" Placement="Placement.Bottom" Arrow="true">
@ -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));
}
}

View File

@ -36,13 +36,14 @@
{
case GameView.Throw:
<PanelToolbar>
@GetDayStr()
@if (DayState.Value.Status != DayStatus.Started)
{
<DayListMenu />
}
else
<DayListMenu/>
}
else
{
<ThrowPanelMenu />
<ThrowPanelMenu/>
}
</PanelToolbar>
break;
@ -60,26 +61,28 @@
<!-- Scrollbarer Inhalt -->
<MudContainer Class="mt-4">
<p>@GetDayStr()</p>
@switch (_gameView)
{
case GameView.Throw:
if (DayState.Value.Status != DayStatus.Started)
{
<DaysList />
<DaysList/>
}
else
{
<ThrowPanel />
<ThrowPanel/>
}
break;
case GameView.Board:
<BoardPanel />
<BoardPanel/>
break;
case GameView.Players:
<PlayersPanel />
<PlayersPanel/>
break;
case GameView.Player:
<PlayerPanel />
<PlayerPanel/>
break;
}
</MudContainer>
@ -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();

View File

@ -8,6 +8,7 @@ namespace KoogleApp.Data.Repository
Task<List<Day>> GetAllAsync(int year);
Task<Day?> GetActiveDayAsync();
Task<Day> AddAsync(Day day);
Task<Day> UpdateAsync(Day day);
}
public class DayRepository(IDbContextFactory<AppDbContext> contextFactory, ILogger<IDayRepository> logger)
@ -36,5 +37,13 @@ namespace KoogleApp.Data.Repository
await context.SaveChangesAsync();
return day;
}
public async Task<Day> UpdateAsync(Day day)
{
await using var context = await contextFactory.CreateDbContextAsync();
var res = context.Days.Update(day);
await context.SaveChangesAsync();
return res.Entity;
}
}
}

View File

@ -186,5 +186,11 @@ namespace KoogleApp.Data
var newDay = await _dayRepository.AddAsync(day);
return newDay;
}
public async Task<Day> UpdateDayAsync(Day day)
{
var modifiedDay = await _dayRepository.UpdateAsync(day);
return modifiedDay;
}
}
}

View File

@ -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<Day> 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;
}

View File

@ -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<int>(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<Day>(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
{

View File

@ -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<DayState>(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<int[]>(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<DayState>(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)
{

View File

@ -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<int[]>(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
};
}
}
}

View File

@ -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)
{
}
}

View File

@ -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);
}

View File

@ -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<PlayerState>(state.Players); // Kopie erstellen
var newList = new List<PlayerState>(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<PlayerState>();
foreach (var playerState in state.Players)
{
lst.Add(playerState with
{
Available = action.DayState.PlayerIds.Contains(playerState.Id)
});
}
return state with { Players = lst };
}
}
}