Batch bestiary add produces a single undo entry
All checks were successful
CI / check (push) Successful in 1m10s
CI / build-image (push) Successful in 15s

Extract addOneFromBestiary (no undo) and build addMultipleFromBestiary
on top so confirming N creatures from the bestiary panel creates one
undo entry that restores the entire batch, not N individual entries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-27 00:07:25 +01:00
parent 541e04b732
commit 9437272fe0
3 changed files with 70 additions and 12 deletions

View File

@@ -298,9 +298,10 @@ export function useEncounter() {
setEvents((prev) => [...prev, ...result]);
}, [makeStore]);
const addFromBestiary = useCallback(
(entry: BestiaryIndexEntry): CreatureId | null => {
const snapshot = encounterRef.current;
const addOneFromBestiary = useCallback(
(
entry: BestiaryIndexEntry,
): { cId: CreatureId; events: DomainEvent[] } | null => {
const store = makeStore();
const existingNames = store.get().combatants.map((c) => c.name);
const { newName, renames } = resolveCreatureName(
@@ -328,8 +329,20 @@ export function useEncounter() {
creatureId: cId,
});
if (isDomainError(result)) {
store.save(snapshot);
if (isDomainError(result)) return null;
return { cId, events: result };
},
[makeStore],
);
const addFromBestiary = useCallback(
(entry: BestiaryIndexEntry): CreatureId | null => {
const snapshot = encounterRef.current;
const added = addOneFromBestiary(entry);
if (!added) {
makeStore().save(snapshot);
return null;
}
@@ -337,10 +350,36 @@ export function useEncounter() {
undoRedoRef.current = newState;
setUndoRedoState(newState);
setEvents((prev) => [...prev, ...result]);
return cId;
setEvents((prev) => [...prev, ...added.events]);
return added.cId;
},
[makeStore],
[makeStore, addOneFromBestiary],
);
const addMultipleFromBestiary = useCallback(
(entry: BestiaryIndexEntry, count: number): CreatureId | null => {
const snapshot = encounterRef.current;
const allEvents: DomainEvent[] = [];
let lastCId: CreatureId | null = null;
for (let i = 0; i < count; i++) {
const added = addOneFromBestiary(entry);
if (!added) {
makeStore().save(snapshot);
return null;
}
allEvents.push(...added.events);
lastCId = added.cId;
}
const newState = pushUndo(undoRedoRef.current, snapshot);
undoRedoRef.current = newState;
setUndoRedoState(newState);
setEvents((prev) => [...prev, ...allEvents]);
return lastCId;
},
[makeStore, addOneFromBestiary],
);
const addFromPlayerCharacter = useCallback(
@@ -426,6 +465,7 @@ export function useEncounter() {
toggleCondition,
toggleConcentration,
addFromBestiary,
addMultipleFromBestiary,
addFromPlayerCharacter,
undo: undoAction,
redo: redoAction,