refactor: App.js imports shared turn funcs (DRY), delete duplicates
Delete duplicate consts (DEFAULT_MAX_HP/INIT_MOD/MONSTER_DEFAULT_INIT_MOD, generateId, rollD20, formatInitMod) + funcs (sortParticipantsByInitiative, computeTurnOrderAfterRemoval, computeTurnOrderAfterAddition) from App.js. Import from @ttrpg/shared (1-list model). Kills second drift source. CRA resolves @ttrpg/shared via npm workspaces symlink. Build green.
This commit is contained in:
+4
-43
@@ -1,4 +1,5 @@
|
|||||||
import React, { useState, useEffect, useRef, useMemo } from 'react';
|
import React, { useState, useEffect, useRef, useMemo } from 'react';
|
||||||
|
import * as shared from '@ttrpg/shared';
|
||||||
import { initializeApp } from './storage';
|
import { initializeApp } from './storage';
|
||||||
import { getAuth, signInAnonymously, onAuthStateChanged, signInWithCustomToken } from './storage';
|
import { getAuth, signInAnonymously, onAuthStateChanged, signInWithCustomToken } from './storage';
|
||||||
import { getFirestore, doc, setDoc, addDoc, collection, onSnapshot, updateDoc, deleteDoc, query, orderBy, limit, writeBatch, getStorage, getStorageMode } from './storage';
|
import { getFirestore, doc, setDoc, addDoc, collection, onSnapshot, updateDoc, deleteDoc, query, orderBy, limit, writeBatch, getStorage, getStorageMode } from './storage';
|
||||||
@@ -46,9 +47,7 @@ if (typeof document !== 'undefined') {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
const APP_VERSION = 'v0.3';
|
const APP_VERSION = 'v0.3';
|
||||||
const DEFAULT_MAX_HP = 10;
|
const { DEFAULT_MAX_HP, DEFAULT_INIT_MOD, MONSTER_DEFAULT_INIT_MOD, generateId, rollD20, formatInitMod, sortParticipantsByInitiative, computeTurnOrderAfterRemoval, computeTurnOrderAfterAddition } = shared;
|
||||||
const DEFAULT_INIT_MOD = 0;
|
|
||||||
const MONSTER_DEFAULT_INIT_MOD = 2;
|
|
||||||
const ROLL_DISPLAY_DURATION = 5000;
|
const ROLL_DISPLAY_DURATION = 5000;
|
||||||
|
|
||||||
const CONDITIONS = [
|
const CONDITIONS = [
|
||||||
@@ -152,24 +151,8 @@ const getPath = {
|
|||||||
// UTILITY FUNCTIONS
|
// UTILITY FUNCTIONS
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
const generateId = () => crypto.randomUUID();
|
// generateId, rollD20, formatInitMod, sortParticipantsByInitiative,
|
||||||
const rollD20 = () => Math.floor(Math.random() * 20) + 1;
|
// computeTurnOrderAfterRemoval/Addition: imported from @ttrpg/shared (1-list model).
|
||||||
|
|
||||||
const formatInitMod = (mod) => {
|
|
||||||
if (mod === undefined || mod === null) return 'N/A';
|
|
||||||
return mod >= 0 ? `+${mod}` : `${mod}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortParticipantsByInitiative = (participants, originalOrder) => {
|
|
||||||
return [...participants].sort((a, b) => {
|
|
||||||
if (a.initiative === b.initiative) {
|
|
||||||
const indexA = originalOrder.findIndex(p => p.id === a.id);
|
|
||||||
const indexB = originalOrder.findIndex(p => p.id === b.id);
|
|
||||||
return indexA - indexB;
|
|
||||||
}
|
|
||||||
return b.initiative - a.initiative;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const LOG_QUERY = [orderBy('timestamp', 'desc'), limit(500)];
|
const LOG_QUERY = [orderBy('timestamp', 'desc'), limit(500)];
|
||||||
|
|
||||||
@@ -184,28 +167,6 @@ const logAction = async (message, context = {}, undoData = null) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns turnOrderIds/currentTurnParticipantId updates when a participant leaves active combat.
|
|
||||||
const computeTurnOrderAfterRemoval = (encounter, removedId, updatedParticipants) => {
|
|
||||||
if (!encounter.isStarted) return {};
|
|
||||||
const currentIds = encounter.turnOrderIds || [];
|
|
||||||
const newIds = currentIds.filter(id => id !== removedId);
|
|
||||||
const updates = { turnOrderIds: newIds };
|
|
||||||
if (encounter.currentTurnParticipantId === removedId) {
|
|
||||||
const removedPos = currentIds.indexOf(removedId);
|
|
||||||
const candidates = [...currentIds.slice(removedPos + 1), ...currentIds.slice(0, removedPos)];
|
|
||||||
const nextId = candidates.find(id => updatedParticipants.find(p => p.id === id && p.isActive)) ?? null;
|
|
||||||
updates.currentTurnParticipantId = nextId;
|
|
||||||
}
|
|
||||||
return updates;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns turnOrderIds update when a participant re-enters active combat mid-encounter.
|
|
||||||
const computeTurnOrderAfterAddition = (encounter, addedId) => {
|
|
||||||
if (!encounter.isStarted) return {};
|
|
||||||
const currentIds = encounter.turnOrderIds || [];
|
|
||||||
if (currentIds.includes(addedId)) return {};
|
|
||||||
return { turnOrderIds: [...currentIds, addedId] };
|
|
||||||
};
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// CUSTOM HOOKS
|
// CUSTOM HOOKS
|
||||||
|
|||||||
Reference in New Issue
Block a user