diff --git a/src/Koogle.Web/Store/PersonState/PersonActions.cs b/src/Koogle.Web/Store/PersonState/PersonActions.cs
new file mode 100644
index 0000000..a54edb1
--- /dev/null
+++ b/src/Koogle.Web/Store/PersonState/PersonActions.cs
@@ -0,0 +1,73 @@
+using Koogle.Application.DTOs;
+
+namespace Koogle.Web.Store.PersonState;
+
+///
+/// Action to load all persons for the current club.
+///
+public record LoadPersonsAction;
+
+///
+/// Action dispatched when persons are loaded successfully.
+///
+public record LoadPersonsSuccessAction(IReadOnlyList Persons);
+
+///
+/// Action dispatched when loading persons fails.
+///
+public record LoadPersonsFailureAction(string Error);
+
+///
+/// Action to create a new person.
+///
+public record CreatePersonAction(CreatePersonDto Dto);
+
+///
+/// Action dispatched when person is created successfully.
+///
+public record CreatePersonSuccessAction(PersonDto Person);
+
+///
+/// Action dispatched when creating person fails.
+///
+public record CreatePersonFailureAction(string Error);
+
+///
+/// Action to update an existing person.
+///
+public record UpdatePersonAction(UpdatePersonDto Dto);
+
+///
+/// Action dispatched when person is updated successfully.
+///
+public record UpdatePersonSuccessAction(PersonDto Person);
+
+///
+/// Action dispatched when updating person fails.
+///
+public record UpdatePersonFailureAction(string Error);
+
+///
+/// Action to delete a person.
+///
+public record DeletePersonAction(Guid Id);
+
+///
+/// Action dispatched when person is deleted successfully.
+///
+public record DeletePersonSuccessAction(Guid Id);
+
+///
+/// Action dispatched when deleting person fails.
+///
+public record DeletePersonFailureAction(string Error);
+
+///
+/// Action to select a person for editing.
+///
+public record SelectPersonAction(PersonDto? Person);
+
+///
+/// Action to clear person error state.
+///
+public record ClearPersonErrorAction;
diff --git a/src/Koogle.Web/Store/PersonState/PersonEffects.cs b/src/Koogle.Web/Store/PersonState/PersonEffects.cs
new file mode 100644
index 0000000..d23e815
--- /dev/null
+++ b/src/Koogle.Web/Store/PersonState/PersonEffects.cs
@@ -0,0 +1,112 @@
+using Fluxor;
+using Koogle.Application.Interfaces;
+
+namespace Koogle.Web.Store.PersonState;
+
+///
+/// Side effects for person state management.
+/// Handles async operations like API calls.
+///
+public class PersonEffects
+{
+ private readonly IPersonService _personService;
+ private readonly ILogger _logger;
+
+ ///
+ /// Initializes a new instance of the PersonEffects class.
+ ///
+ public PersonEffects(IPersonService personService, ILogger logger)
+ {
+ _personService = personService;
+ _logger = logger;
+ }
+
+ ///
+ /// Handles LoadPersonsAction - loads all persons from service.
+ ///
+ [EffectMethod]
+ public async Task HandleLoadPersons(LoadPersonsAction action, IDispatcher dispatcher)
+ {
+ try
+ {
+ _logger.LogDebug("Loading persons");
+ var persons = await _personService.GetAllAsync();
+ dispatcher.Dispatch(new LoadPersonsSuccessAction(persons));
+ _logger.LogInformation("Loaded {Count} persons", persons.Count);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to load persons");
+ dispatcher.Dispatch(new LoadPersonsFailureAction(ex.Message));
+ }
+ }
+
+ ///
+ /// Handles CreatePersonAction - creates a new person.
+ ///
+ [EffectMethod]
+ public async Task HandleCreatePerson(CreatePersonAction action, IDispatcher dispatcher)
+ {
+ try
+ {
+ _logger.LogDebug("Creating person {Name}", action.Dto.Name);
+ var person = await _personService.CreateAsync(action.Dto);
+ dispatcher.Dispatch(new CreatePersonSuccessAction(person));
+ _logger.LogInformation("Created person {Name} with ID {Id}", person.Name, person.Id);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to create person {Name}", action.Dto.Name);
+ dispatcher.Dispatch(new CreatePersonFailureAction(ex.Message));
+ }
+ }
+
+ ///
+ /// Handles UpdatePersonAction - updates an existing person.
+ ///
+ [EffectMethod]
+ public async Task HandleUpdatePerson(UpdatePersonAction action, IDispatcher dispatcher)
+ {
+ try
+ {
+ _logger.LogDebug("Updating person {Id}", action.Dto.Id);
+ var person = await _personService.UpdateAsync(action.Dto);
+ dispatcher.Dispatch(new UpdatePersonSuccessAction(person));
+ _logger.LogInformation("Updated person {Name}", person.Name);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to update person {Id}", action.Dto.Id);
+ dispatcher.Dispatch(new UpdatePersonFailureAction(ex.Message));
+ }
+ }
+
+ ///
+ /// Handles DeletePersonAction - deletes a person.
+ ///
+ [EffectMethod]
+ public async Task HandleDeletePerson(DeletePersonAction action, IDispatcher dispatcher)
+ {
+ try
+ {
+ _logger.LogDebug("Deleting person {Id}", action.Id);
+ var success = await _personService.DeleteAsync(action.Id);
+
+ if (success)
+ {
+ dispatcher.Dispatch(new DeletePersonSuccessAction(action.Id));
+ _logger.LogInformation("Deleted person {Id}", action.Id);
+ }
+ else
+ {
+ dispatcher.Dispatch(new DeletePersonFailureAction("Person konnte nicht gelöscht werden."));
+ _logger.LogWarning("Failed to delete person {Id} - not found or already deleted", action.Id);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to delete person {Id}", action.Id);
+ dispatcher.Dispatch(new DeletePersonFailureAction(ex.Message));
+ }
+ }
+}
diff --git a/src/Koogle.Web/Store/PersonState/PersonReducers.cs b/src/Koogle.Web/Store/PersonState/PersonReducers.cs
new file mode 100644
index 0000000..1ee3c1d
--- /dev/null
+++ b/src/Koogle.Web/Store/PersonState/PersonReducers.cs
@@ -0,0 +1,163 @@
+using Fluxor;
+
+namespace Koogle.Web.Store.PersonState;
+
+///
+/// Reducers for person state management.
+///
+public static class PersonReducers
+{
+ ///
+ /// Handles LoadPersonsAction - sets loading state.
+ ///
+ [ReducerMethod(typeof(LoadPersonsAction))]
+ public static PersonState OnLoadPersons(PersonState state)
+ => state with
+ {
+ IsLoading = true,
+ Error = null
+ };
+
+ ///
+ /// Handles LoadPersonsSuccessAction - updates persons list.
+ ///
+ [ReducerMethod]
+ public static PersonState OnLoadPersonsSuccess(PersonState state, LoadPersonsSuccessAction action)
+ => state with
+ {
+ Persons = action.Persons,
+ IsLoading = false
+ };
+
+ ///
+ /// Handles LoadPersonsFailureAction - sets error state.
+ ///
+ [ReducerMethod]
+ public static PersonState OnLoadPersonsFailure(PersonState state, LoadPersonsFailureAction action)
+ => state with
+ {
+ IsLoading = false,
+ Error = action.Error
+ };
+
+ ///
+ /// Handles CreatePersonAction - sets loading state.
+ ///
+ [ReducerMethod(typeof(CreatePersonAction))]
+ public static PersonState OnCreatePerson(PersonState state)
+ => state with
+ {
+ IsLoading = true,
+ Error = null
+ };
+
+ ///
+ /// Handles CreatePersonSuccessAction - adds person to list.
+ ///
+ [ReducerMethod]
+ public static PersonState OnCreatePersonSuccess(PersonState state, CreatePersonSuccessAction action)
+ => state with
+ {
+ Persons = [.. state.Persons, action.Person],
+ IsLoading = false
+ };
+
+ ///
+ /// Handles CreatePersonFailureAction - sets error state.
+ ///
+ [ReducerMethod]
+ public static PersonState OnCreatePersonFailure(PersonState state, CreatePersonFailureAction action)
+ => state with
+ {
+ IsLoading = false,
+ Error = action.Error
+ };
+
+ ///
+ /// Handles UpdatePersonAction - sets loading state.
+ ///
+ [ReducerMethod(typeof(UpdatePersonAction))]
+ public static PersonState OnUpdatePerson(PersonState state)
+ => state with
+ {
+ IsLoading = true,
+ Error = null
+ };
+
+ ///
+ /// Handles UpdatePersonSuccessAction - replaces person in list.
+ ///
+ [ReducerMethod]
+ public static PersonState OnUpdatePersonSuccess(PersonState state, UpdatePersonSuccessAction action)
+ => state with
+ {
+ Persons = state.Persons.Select(p => p.Id == action.Person.Id ? action.Person : p).ToList(),
+ SelectedPerson = state.SelectedPerson?.Id == action.Person.Id ? action.Person : state.SelectedPerson,
+ IsLoading = false
+ };
+
+ ///
+ /// Handles UpdatePersonFailureAction - sets error state.
+ ///
+ [ReducerMethod]
+ public static PersonState OnUpdatePersonFailure(PersonState state, UpdatePersonFailureAction action)
+ => state with
+ {
+ IsLoading = false,
+ Error = action.Error
+ };
+
+ ///
+ /// Handles DeletePersonAction - sets loading state.
+ ///
+ [ReducerMethod(typeof(DeletePersonAction))]
+ public static PersonState OnDeletePerson(PersonState state)
+ => state with
+ {
+ IsLoading = true,
+ Error = null
+ };
+
+ ///
+ /// Handles DeletePersonSuccessAction - removes person from list.
+ ///
+ [ReducerMethod]
+ public static PersonState OnDeletePersonSuccess(PersonState state, DeletePersonSuccessAction action)
+ => state with
+ {
+ Persons = state.Persons.Where(p => p.Id != action.Id).ToList(),
+ SelectedPerson = state.SelectedPerson?.Id == action.Id ? null : state.SelectedPerson,
+ IsLoading = false
+ };
+
+ ///
+ /// Handles DeletePersonFailureAction - sets error state.
+ ///
+ [ReducerMethod]
+ public static PersonState OnDeletePersonFailure(PersonState state, DeletePersonFailureAction action)
+ => state with
+ {
+ IsLoading = false,
+ Error = action.Error
+ };
+
+ ///
+ /// Handles SelectPersonAction - sets selected person.
+ ///
+ [ReducerMethod]
+ public static PersonState OnSelectPerson(PersonState state, SelectPersonAction action)
+ => state with
+ {
+ SelectedPerson = action.Person
+ };
+
+ ///
+ /// Handles ClearPersonErrorAction - clears error state.
+ ///
+ [ReducerMethod(typeof(ClearPersonErrorAction))]
+ public static PersonState OnClearError(PersonState state)
+ => state with
+ {
+ Error = null
+ };
+}
diff --git a/src/Koogle.Web/Store/PersonState/PersonState.cs b/src/Koogle.Web/Store/PersonState/PersonState.cs
new file mode 100644
index 0000000..9fbf1ad
--- /dev/null
+++ b/src/Koogle.Web/Store/PersonState/PersonState.cs
@@ -0,0 +1,47 @@
+using Fluxor;
+using Koogle.Application.DTOs;
+
+namespace Koogle.Web.Store.PersonState;
+
+///
+/// Fluxor state for person management.
+///
+[FeatureState]
+public record PersonState
+{
+ ///
+ /// List of all persons for the current club.
+ ///
+ public IReadOnlyList Persons { get; init; } = [];
+
+ ///
+ /// Currently selected person for editing.
+ ///
+ public PersonDto? SelectedPerson { get; init; }
+
+ ///
+ /// Indicates whether a person operation is in progress.
+ ///
+ public bool IsLoading { get; init; }
+
+ ///
+ /// Error message if operation failed.
+ ///
+ public string? Error { get; init; }
+
+ ///
+ /// Private constructor for Fluxor initialization.
+ ///
+ private PersonState() { }
+
+ ///
+ /// Creates the initial state.
+ ///
+ public static PersonState Initial => new()
+ {
+ Persons = [],
+ SelectedPerson = null,
+ IsLoading = false,
+ Error = null
+ };
+}