Compare commits
2 Commits
01f1145698
...
e1a0969d6e
| Author | SHA1 | Date |
|---|---|---|
|
|
e1a0969d6e | |
|
|
9a8d435f09 |
|
|
@ -6,7 +6,8 @@
|
|||
"Bash(dotnet test:*)",
|
||||
"Bash(git checkout:*)",
|
||||
"Bash(git add:*)",
|
||||
"Bash(git commit:*)"
|
||||
"Bash(git commit:*)",
|
||||
"Bash(mkdir:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ NavMenu.razor:
|
|||
| ✓ | D2 | Personen | Person Pages | 1 Razor |
|
||||
| ✓ | D3 | Expenses | ExpenseState Fluxor | 4 State-Dateien |
|
||||
| ✓ | D4 | Expenses | Expense Pages | 1 Razor |
|
||||
| ☐ | E1 | Days | DayState Fluxor | 4 State-Dateien |
|
||||
| ✓ | E1 | Days | DayState Fluxor | 4 State-Dateien |
|
||||
| ☐ | E2 | Days | Days List Page | 1 Razor |
|
||||
| ☐ | E3 | Days | Day Details Page | 1 Razor |
|
||||
| ☐ | E4 | Days | PersonExpense Management | Components in DayDetails |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,171 @@
|
|||
using Koogle.Application.DTOs;
|
||||
|
||||
namespace Koogle.Web.Store.DayState;
|
||||
|
||||
// Load Days Actions
|
||||
|
||||
/// <summary>
|
||||
/// Action to load all days for the current club.
|
||||
/// </summary>
|
||||
public record LoadDaysAction(DayFilterDto? Filter = null);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when days are loaded successfully.
|
||||
/// </summary>
|
||||
public record LoadDaysSuccessAction(IReadOnlyList<DaySummaryDto> Days);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when loading days fails.
|
||||
/// </summary>
|
||||
public record LoadDaysFailureAction(string Error);
|
||||
|
||||
// Load Day Details Actions
|
||||
|
||||
/// <summary>
|
||||
/// Action to load a single day with full details.
|
||||
/// </summary>
|
||||
public record LoadDayDetailsAction(Guid DayId);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when day details are loaded successfully.
|
||||
/// </summary>
|
||||
public record LoadDayDetailsSuccessAction(DayDto Day);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when loading day details fails.
|
||||
/// </summary>
|
||||
public record LoadDayDetailsFailureAction(string Error);
|
||||
|
||||
// Create Day Actions
|
||||
|
||||
/// <summary>
|
||||
/// Action to create a new day.
|
||||
/// </summary>
|
||||
public record CreateDayAction(CreateDayDto Dto);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when day is created successfully.
|
||||
/// </summary>
|
||||
public record CreateDaySuccessAction(DayDto Day);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when creating day fails.
|
||||
/// </summary>
|
||||
public record CreateDayFailureAction(string Error);
|
||||
|
||||
// Update Day Actions
|
||||
|
||||
/// <summary>
|
||||
/// Action to update an existing day.
|
||||
/// </summary>
|
||||
public record UpdateDayAction(UpdateDayDto Dto);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when day is updated successfully.
|
||||
/// </summary>
|
||||
public record UpdateDaySuccessAction(DayDto Day);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when updating day fails.
|
||||
/// </summary>
|
||||
public record UpdateDayFailureAction(string Error);
|
||||
|
||||
// Delete Day Actions
|
||||
|
||||
/// <summary>
|
||||
/// Action to delete a day.
|
||||
/// </summary>
|
||||
public record DeleteDayAction(Guid Id);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when day is deleted successfully.
|
||||
/// </summary>
|
||||
public record DeleteDaySuccessAction(Guid Id);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when deleting day fails.
|
||||
/// </summary>
|
||||
public record DeleteDayFailureAction(string Error);
|
||||
|
||||
// Participant Actions
|
||||
|
||||
/// <summary>
|
||||
/// Action to add a participant to a day.
|
||||
/// </summary>
|
||||
public record AddDayParticipantAction(AddDayParticipantDto Dto);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when participant is added successfully.
|
||||
/// </summary>
|
||||
public record AddDayParticipantSuccessAction(DayDto Day);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when adding participant fails.
|
||||
/// </summary>
|
||||
public record AddDayParticipantFailureAction(string Error);
|
||||
|
||||
/// <summary>
|
||||
/// Action to remove a participant from a day.
|
||||
/// </summary>
|
||||
public record RemoveDayParticipantAction(RemoveDayParticipantDto Dto);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when participant is removed successfully.
|
||||
/// </summary>
|
||||
public record RemoveDayParticipantSuccessAction(DayDto Day);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when removing participant fails.
|
||||
/// </summary>
|
||||
public record RemoveDayParticipantFailureAction(string Error);
|
||||
|
||||
// Status Actions
|
||||
|
||||
/// <summary>
|
||||
/// Action to advance day status (New → Started → Closed).
|
||||
/// </summary>
|
||||
public record AdvanceDayStatusAction(Guid DayId);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when status is advanced successfully.
|
||||
/// </summary>
|
||||
public record AdvanceDayStatusSuccessAction(DayDto Day);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when advancing status fails.
|
||||
/// </summary>
|
||||
public record AdvanceDayStatusFailureAction(string Error);
|
||||
|
||||
// Available Persons Actions
|
||||
|
||||
/// <summary>
|
||||
/// Action to load available persons for participant selection.
|
||||
/// </summary>
|
||||
public record LoadAvailablePersonsAction;
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when available persons are loaded successfully.
|
||||
/// </summary>
|
||||
public record LoadAvailablePersonsSuccessAction(IReadOnlyList<PersonDto> Persons);
|
||||
|
||||
/// <summary>
|
||||
/// Action dispatched when loading available persons fails.
|
||||
/// </summary>
|
||||
public record LoadAvailablePersonsFailureAction(string Error);
|
||||
|
||||
// Selection and Error Actions
|
||||
|
||||
/// <summary>
|
||||
/// Action to select a day for editing.
|
||||
/// </summary>
|
||||
public record SelectDayAction(DayDto? Day);
|
||||
|
||||
/// <summary>
|
||||
/// Action to clear day error state.
|
||||
/// </summary>
|
||||
public record ClearDayErrorAction;
|
||||
|
||||
/// <summary>
|
||||
/// Action to set filter for day list.
|
||||
/// </summary>
|
||||
public record SetDayFilterAction(DayFilterDto? Filter);
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
using Fluxor;
|
||||
using Koogle.Application.Interfaces;
|
||||
|
||||
namespace Koogle.Web.Store.DayState;
|
||||
|
||||
/// <summary>
|
||||
/// Side effects for day state management.
|
||||
/// Handles async operations like API calls.
|
||||
/// </summary>
|
||||
public class DayEffects
|
||||
{
|
||||
private readonly IDayService _dayService;
|
||||
private readonly IPersonService _personService;
|
||||
private readonly ILogger<DayEffects> _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the DayEffects class.
|
||||
/// </summary>
|
||||
public DayEffects(IDayService dayService, IPersonService personService, ILogger<DayEffects> logger)
|
||||
{
|
||||
_dayService = dayService;
|
||||
_personService = personService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles LoadDaysAction - loads all days from service.
|
||||
/// </summary>
|
||||
[EffectMethod]
|
||||
public async Task HandleLoadDays(LoadDaysAction action, IDispatcher dispatcher)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("Loading days with filter {@Filter}", action.Filter);
|
||||
var result = await _dayService.GetAllAsync(action.Filter);
|
||||
dispatcher.Dispatch(new LoadDaysSuccessAction(result.Items));
|
||||
_logger.LogInformation("Loaded {Count} days", result.Items.Count);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to load days");
|
||||
dispatcher.Dispatch(new LoadDaysFailureAction(ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles LoadDayDetailsAction - loads day details from service.
|
||||
/// </summary>
|
||||
[EffectMethod]
|
||||
public async Task HandleLoadDayDetails(LoadDayDetailsAction action, IDispatcher dispatcher)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("Loading day details for {DayId}", action.DayId);
|
||||
var day = await _dayService.GetByIdAsync(action.DayId);
|
||||
|
||||
if (day is null)
|
||||
{
|
||||
dispatcher.Dispatch(new LoadDayDetailsFailureAction("Spieltag nicht gefunden."));
|
||||
return;
|
||||
}
|
||||
|
||||
dispatcher.Dispatch(new LoadDayDetailsSuccessAction(day));
|
||||
_logger.LogInformation("Loaded day details for {DayId}", action.DayId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to load day details for {DayId}", action.DayId);
|
||||
dispatcher.Dispatch(new LoadDayDetailsFailureAction(ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles CreateDayAction - creates a new day.
|
||||
/// </summary>
|
||||
[EffectMethod]
|
||||
public async Task HandleCreateDay(CreateDayAction action, IDispatcher dispatcher)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("Creating day for {PostDate}", action.Dto.PostDate);
|
||||
var day = await _dayService.CreateAsync(action.Dto);
|
||||
dispatcher.Dispatch(new CreateDaySuccessAction(day));
|
||||
_logger.LogInformation("Created day {Id} for {PostDate}", day.Id, day.PostDate);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to create day for {PostDate}", action.Dto.PostDate);
|
||||
dispatcher.Dispatch(new CreateDayFailureAction(ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles UpdateDayAction - updates an existing day.
|
||||
/// </summary>
|
||||
[EffectMethod]
|
||||
public async Task HandleUpdateDay(UpdateDayAction action, IDispatcher dispatcher)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("Updating day {Id}", action.Dto.Id);
|
||||
var day = await _dayService.UpdateAsync(action.Dto);
|
||||
dispatcher.Dispatch(new UpdateDaySuccessAction(day));
|
||||
_logger.LogInformation("Updated day {Id}", day.Id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to update day {Id}", action.Dto.Id);
|
||||
dispatcher.Dispatch(new UpdateDayFailureAction(ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles DeleteDayAction - deletes a day.
|
||||
/// </summary>
|
||||
[EffectMethod]
|
||||
public async Task HandleDeleteDay(DeleteDayAction action, IDispatcher dispatcher)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("Deleting day {Id}", action.Id);
|
||||
var success = await _dayService.DeleteAsync(action.Id);
|
||||
|
||||
if (success)
|
||||
{
|
||||
dispatcher.Dispatch(new DeleteDaySuccessAction(action.Id));
|
||||
_logger.LogInformation("Deleted day {Id}", action.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatcher.Dispatch(new DeleteDayFailureAction("Spieltag konnte nicht gelöscht werden."));
|
||||
_logger.LogWarning("Failed to delete day {Id} - not found or already deleted", action.Id);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to delete day {Id}", action.Id);
|
||||
dispatcher.Dispatch(new DeleteDayFailureAction(ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles AddDayParticipantAction - adds participant to day.
|
||||
/// </summary>
|
||||
[EffectMethod]
|
||||
public async Task HandleAddDayParticipant(AddDayParticipantAction action, IDispatcher dispatcher)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("Adding participant {PersonId} to day {DayId}", action.Dto.PersonId, action.Dto.DayId);
|
||||
var day = await _dayService.AddParticipantAsync(action.Dto);
|
||||
dispatcher.Dispatch(new AddDayParticipantSuccessAction(day));
|
||||
_logger.LogInformation("Added participant {PersonId} to day {DayId}", action.Dto.PersonId, action.Dto.DayId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to add participant {PersonId} to day {DayId}", action.Dto.PersonId, action.Dto.DayId);
|
||||
dispatcher.Dispatch(new AddDayParticipantFailureAction(ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles RemoveDayParticipantAction - removes participant from day.
|
||||
/// </summary>
|
||||
[EffectMethod]
|
||||
public async Task HandleRemoveDayParticipant(RemoveDayParticipantAction action, IDispatcher dispatcher)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("Removing participant {PersonId} from day {DayId}", action.Dto.PersonId, action.Dto.DayId);
|
||||
var day = await _dayService.RemoveParticipantAsync(action.Dto);
|
||||
dispatcher.Dispatch(new RemoveDayParticipantSuccessAction(day));
|
||||
_logger.LogInformation("Removed participant {PersonId} from day {DayId}", action.Dto.PersonId, action.Dto.DayId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to remove participant {PersonId} from day {DayId}", action.Dto.PersonId, action.Dto.DayId);
|
||||
dispatcher.Dispatch(new RemoveDayParticipantFailureAction(ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles AdvanceDayStatusAction - advances day status.
|
||||
/// </summary>
|
||||
[EffectMethod]
|
||||
public async Task HandleAdvanceDayStatus(AdvanceDayStatusAction action, IDispatcher dispatcher)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("Advancing status for day {DayId}", action.DayId);
|
||||
var day = await _dayService.AdvanceStatusAsync(action.DayId);
|
||||
dispatcher.Dispatch(new AdvanceDayStatusSuccessAction(day));
|
||||
_logger.LogInformation("Advanced status for day {DayId} to {Status}", action.DayId, day.Status);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to advance status for day {DayId}", action.DayId);
|
||||
dispatcher.Dispatch(new AdvanceDayStatusFailureAction(ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles LoadAvailablePersonsAction - loads all persons for selection.
|
||||
/// </summary>
|
||||
[EffectMethod]
|
||||
public async Task HandleLoadAvailablePersons(LoadAvailablePersonsAction action, IDispatcher dispatcher)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("Loading available persons");
|
||||
var persons = await _personService.GetAllAsync();
|
||||
dispatcher.Dispatch(new LoadAvailablePersonsSuccessAction(persons));
|
||||
_logger.LogInformation("Loaded {Count} available persons", persons.Count);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to load available persons");
|
||||
dispatcher.Dispatch(new LoadAvailablePersonsFailureAction(ex.Message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,423 @@
|
|||
using Fluxor;
|
||||
|
||||
namespace Koogle.Web.Store.DayState;
|
||||
|
||||
/// <summary>
|
||||
/// Reducers for day state management.
|
||||
/// </summary>
|
||||
public static class DayReducers
|
||||
{
|
||||
// Load Days Reducers
|
||||
|
||||
/// <summary>
|
||||
/// Handles LoadDaysAction - sets loading state and filter.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnLoadDays(DayState state, LoadDaysAction action)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = true,
|
||||
Error = null,
|
||||
Filter = action.Filter
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles LoadDaysSuccessAction - updates days list.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnLoadDaysSuccess(DayState state, LoadDaysSuccessAction action)
|
||||
=> state with
|
||||
{
|
||||
Days = action.Days,
|
||||
IsLoading = false
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles LoadDaysFailureAction - sets error state.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnLoadDaysFailure(DayState state, LoadDaysFailureAction action)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = false,
|
||||
Error = action.Error
|
||||
};
|
||||
|
||||
// Load Day Details Reducers
|
||||
|
||||
/// <summary>
|
||||
/// Handles LoadDayDetailsAction - sets loading state.
|
||||
/// </summary>
|
||||
[ReducerMethod(typeof(LoadDayDetailsAction))]
|
||||
public static DayState OnLoadDayDetails(DayState state)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = true,
|
||||
Error = null
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles LoadDayDetailsSuccessAction - sets selected day.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnLoadDayDetailsSuccess(DayState state, LoadDayDetailsSuccessAction action)
|
||||
=> state with
|
||||
{
|
||||
SelectedDay = action.Day,
|
||||
IsLoading = false
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles LoadDayDetailsFailureAction - sets error state.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnLoadDayDetailsFailure(DayState state, LoadDayDetailsFailureAction action)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = false,
|
||||
Error = action.Error
|
||||
};
|
||||
|
||||
// Create Day Reducers
|
||||
|
||||
/// <summary>
|
||||
/// Handles CreateDayAction - sets loading state.
|
||||
/// </summary>
|
||||
[ReducerMethod(typeof(CreateDayAction))]
|
||||
public static DayState OnCreateDay(DayState state)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = true,
|
||||
Error = null
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles CreateDaySuccessAction - adds day summary to list and sets as selected.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnCreateDaySuccess(DayState state, CreateDaySuccessAction action)
|
||||
{
|
||||
var summary = new Application.DTOs.DaySummaryDto
|
||||
{
|
||||
Id = action.Day.Id,
|
||||
PostDate = action.Day.PostDate,
|
||||
Status = action.Day.Status,
|
||||
ParticipantCount = action.Day.ParticipantCount
|
||||
};
|
||||
|
||||
return state with
|
||||
{
|
||||
Days = [.. state.Days, summary],
|
||||
SelectedDay = action.Day,
|
||||
IsLoading = false
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles CreateDayFailureAction - sets error state.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnCreateDayFailure(DayState state, CreateDayFailureAction action)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = false,
|
||||
Error = action.Error
|
||||
};
|
||||
|
||||
// Update Day Reducers
|
||||
|
||||
/// <summary>
|
||||
/// Handles UpdateDayAction - sets loading state.
|
||||
/// </summary>
|
||||
[ReducerMethod(typeof(UpdateDayAction))]
|
||||
public static DayState OnUpdateDay(DayState state)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = true,
|
||||
Error = null
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles UpdateDaySuccessAction - updates day in list and selected day.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnUpdateDaySuccess(DayState state, UpdateDaySuccessAction action)
|
||||
{
|
||||
var updatedDays = state.Days.Select(d =>
|
||||
d.Id == action.Day.Id
|
||||
? new Application.DTOs.DaySummaryDto
|
||||
{
|
||||
Id = action.Day.Id,
|
||||
PostDate = action.Day.PostDate,
|
||||
Status = action.Day.Status,
|
||||
ParticipantCount = action.Day.ParticipantCount
|
||||
}
|
||||
: d).ToList();
|
||||
|
||||
return state with
|
||||
{
|
||||
Days = updatedDays,
|
||||
SelectedDay = state.SelectedDay?.Id == action.Day.Id ? action.Day : state.SelectedDay,
|
||||
IsLoading = false
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles UpdateDayFailureAction - sets error state.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnUpdateDayFailure(DayState state, UpdateDayFailureAction action)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = false,
|
||||
Error = action.Error
|
||||
};
|
||||
|
||||
// Delete Day Reducers
|
||||
|
||||
/// <summary>
|
||||
/// Handles DeleteDayAction - sets loading state.
|
||||
/// </summary>
|
||||
[ReducerMethod(typeof(DeleteDayAction))]
|
||||
public static DayState OnDeleteDay(DayState state)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = true,
|
||||
Error = null
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles DeleteDaySuccessAction - removes day from list.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnDeleteDaySuccess(DayState state, DeleteDaySuccessAction action)
|
||||
=> state with
|
||||
{
|
||||
Days = state.Days.Where(d => d.Id != action.Id).ToList(),
|
||||
SelectedDay = state.SelectedDay?.Id == action.Id ? null : state.SelectedDay,
|
||||
IsLoading = false
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles DeleteDayFailureAction - sets error state.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnDeleteDayFailure(DayState state, DeleteDayFailureAction action)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = false,
|
||||
Error = action.Error
|
||||
};
|
||||
|
||||
// Participant Reducers
|
||||
|
||||
/// <summary>
|
||||
/// Handles AddDayParticipantAction - sets loading state.
|
||||
/// </summary>
|
||||
[ReducerMethod(typeof(AddDayParticipantAction))]
|
||||
public static DayState OnAddDayParticipant(DayState state)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = true,
|
||||
Error = null
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles AddDayParticipantSuccessAction - updates selected day and summary.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnAddDayParticipantSuccess(DayState state, AddDayParticipantSuccessAction action)
|
||||
{
|
||||
var updatedDays = state.Days.Select(d =>
|
||||
d.Id == action.Day.Id
|
||||
? new Application.DTOs.DaySummaryDto
|
||||
{
|
||||
Id = action.Day.Id,
|
||||
PostDate = action.Day.PostDate,
|
||||
Status = action.Day.Status,
|
||||
ParticipantCount = action.Day.ParticipantCount
|
||||
}
|
||||
: d).ToList();
|
||||
|
||||
return state with
|
||||
{
|
||||
Days = updatedDays,
|
||||
SelectedDay = action.Day,
|
||||
IsLoading = false
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles AddDayParticipantFailureAction - sets error state.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnAddDayParticipantFailure(DayState state, AddDayParticipantFailureAction action)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = false,
|
||||
Error = action.Error
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles RemoveDayParticipantAction - sets loading state.
|
||||
/// </summary>
|
||||
[ReducerMethod(typeof(RemoveDayParticipantAction))]
|
||||
public static DayState OnRemoveDayParticipant(DayState state)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = true,
|
||||
Error = null
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles RemoveDayParticipantSuccessAction - updates selected day and summary.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnRemoveDayParticipantSuccess(DayState state, RemoveDayParticipantSuccessAction action)
|
||||
{
|
||||
var updatedDays = state.Days.Select(d =>
|
||||
d.Id == action.Day.Id
|
||||
? new Application.DTOs.DaySummaryDto
|
||||
{
|
||||
Id = action.Day.Id,
|
||||
PostDate = action.Day.PostDate,
|
||||
Status = action.Day.Status,
|
||||
ParticipantCount = action.Day.ParticipantCount
|
||||
}
|
||||
: d).ToList();
|
||||
|
||||
return state with
|
||||
{
|
||||
Days = updatedDays,
|
||||
SelectedDay = action.Day,
|
||||
IsLoading = false
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles RemoveDayParticipantFailureAction - sets error state.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnRemoveDayParticipantFailure(DayState state, RemoveDayParticipantFailureAction action)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = false,
|
||||
Error = action.Error
|
||||
};
|
||||
|
||||
// Status Reducers
|
||||
|
||||
/// <summary>
|
||||
/// Handles AdvanceDayStatusAction - sets loading state.
|
||||
/// </summary>
|
||||
[ReducerMethod(typeof(AdvanceDayStatusAction))]
|
||||
public static DayState OnAdvanceDayStatus(DayState state)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = true,
|
||||
Error = null
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles AdvanceDayStatusSuccessAction - updates day status.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnAdvanceDayStatusSuccess(DayState state, AdvanceDayStatusSuccessAction action)
|
||||
{
|
||||
var updatedDays = state.Days.Select(d =>
|
||||
d.Id == action.Day.Id
|
||||
? new Application.DTOs.DaySummaryDto
|
||||
{
|
||||
Id = action.Day.Id,
|
||||
PostDate = action.Day.PostDate,
|
||||
Status = action.Day.Status,
|
||||
ParticipantCount = action.Day.ParticipantCount
|
||||
}
|
||||
: d).ToList();
|
||||
|
||||
return state with
|
||||
{
|
||||
Days = updatedDays,
|
||||
SelectedDay = state.SelectedDay?.Id == action.Day.Id ? action.Day : state.SelectedDay,
|
||||
IsLoading = false
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles AdvanceDayStatusFailureAction - sets error state.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnAdvanceDayStatusFailure(DayState state, AdvanceDayStatusFailureAction action)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = false,
|
||||
Error = action.Error
|
||||
};
|
||||
|
||||
// Available Persons Reducers
|
||||
|
||||
/// <summary>
|
||||
/// Handles LoadAvailablePersonsAction - sets loading state.
|
||||
/// </summary>
|
||||
[ReducerMethod(typeof(LoadAvailablePersonsAction))]
|
||||
public static DayState OnLoadAvailablePersons(DayState state)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = true,
|
||||
Error = null
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles LoadAvailablePersonsSuccessAction - sets available persons.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnLoadAvailablePersonsSuccess(DayState state, LoadAvailablePersonsSuccessAction action)
|
||||
=> state with
|
||||
{
|
||||
AvailablePersons = action.Persons,
|
||||
IsLoading = false
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles LoadAvailablePersonsFailureAction - sets error state.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnLoadAvailablePersonsFailure(DayState state, LoadAvailablePersonsFailureAction action)
|
||||
=> state with
|
||||
{
|
||||
IsLoading = false,
|
||||
Error = action.Error
|
||||
};
|
||||
|
||||
// Selection and Error Reducers
|
||||
|
||||
/// <summary>
|
||||
/// Handles SelectDayAction - sets selected day.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnSelectDay(DayState state, SelectDayAction action)
|
||||
=> state with
|
||||
{
|
||||
SelectedDay = action.Day
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles ClearDayErrorAction - clears error state.
|
||||
/// </summary>
|
||||
[ReducerMethod(typeof(ClearDayErrorAction))]
|
||||
public static DayState OnClearError(DayState state)
|
||||
=> state with
|
||||
{
|
||||
Error = null
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Handles SetDayFilterAction - sets filter.
|
||||
/// </summary>
|
||||
[ReducerMethod]
|
||||
public static DayState OnSetDayFilter(DayState state, SetDayFilterAction action)
|
||||
=> state with
|
||||
{
|
||||
Filter = action.Filter
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
using Fluxor;
|
||||
using Koogle.Application.DTOs;
|
||||
|
||||
namespace Koogle.Web.Store.DayState;
|
||||
|
||||
/// <summary>
|
||||
/// Fluxor state for day management.
|
||||
/// </summary>
|
||||
[FeatureState]
|
||||
public record DayState
|
||||
{
|
||||
/// <summary>
|
||||
/// List of day summaries for the current club.
|
||||
/// </summary>
|
||||
public IReadOnlyList<DaySummaryDto> Days { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Currently selected day with full details.
|
||||
/// </summary>
|
||||
public DayDto? SelectedDay { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Available persons for participant selection.
|
||||
/// </summary>
|
||||
public IReadOnlyList<PersonDto> AvailablePersons { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Current filter for day list.
|
||||
/// </summary>
|
||||
public DayFilterDto? Filter { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether a day operation is in progress.
|
||||
/// </summary>
|
||||
public bool IsLoading { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Error message if operation failed.
|
||||
/// </summary>
|
||||
public string? Error { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Private constructor for Fluxor initialization.
|
||||
/// </summary>
|
||||
private DayState() { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates the initial state.
|
||||
/// </summary>
|
||||
public static DayState Initial => new()
|
||||
{
|
||||
Days = [],
|
||||
SelectedDay = null,
|
||||
AvailablePersons = [],
|
||||
Filter = null,
|
||||
IsLoading = false,
|
||||
Error = null
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue