refactor: split bloated state types into State + Actions interfaces (issue #102)
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m19s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m19s
- CombatState: split into CombatState (data) + CombatActions + CombatStore - PrestigeState: split into PrestigeState (data) + PrestigeActions + PrestigeStore - ManaState: split into ManaState (data) + ManaActions + ManaStore - GameState: deprecated, removed from barrel exports - crafting-actions: updated to use CraftingState instead of GameState - combat-utils/mana-utils: replaced Pick<GameState,...> with focused interfaces - DisciplineCardProps: split into Definition + Runtime + Callbacks - stores/index.ts: now exports both State and Actions types
This commit is contained in:
@@ -8,6 +8,8 @@ import { invokerDisciplines } from '@/lib/game/data/disciplines/invoker';
|
||||
import { calculateStatBonus, calculateManaDrain } from '@/lib/game/utils/discipline-math';
|
||||
import clsx from 'clsx';
|
||||
|
||||
// ─── Attunement Tabs ─────────────────────────────────────────────────────────
|
||||
|
||||
interface AttunementTab {
|
||||
key: string;
|
||||
label: string;
|
||||
@@ -21,7 +23,9 @@ const ATTUNEMENT_TABS: AttunementTab[] = [
|
||||
{ key: 'invoker', label: 'Invoker', items: invokerDisciplines },
|
||||
];
|
||||
|
||||
interface DisciplineCardProps {
|
||||
// ─── Discipline Card Props (split from monolithic 15-field interface) ────────
|
||||
|
||||
export interface DisciplineCardDefinition {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
@@ -33,32 +37,36 @@ interface DisciplineCardProps {
|
||||
drainBase: number;
|
||||
difficultyFactor: number;
|
||||
scalingFactor: number;
|
||||
}
|
||||
|
||||
export interface DisciplineCardRuntime {
|
||||
xp: number;
|
||||
paused: boolean;
|
||||
concurrentLimit: number;
|
||||
}
|
||||
|
||||
export interface DisciplineCardCallbacks {
|
||||
onToggle: (id: string, paused: boolean) => void;
|
||||
}
|
||||
|
||||
const DisciplineCard: React.FC<DisciplineCardProps> = ({
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
perkThresholds,
|
||||
perkValues,
|
||||
perkTypes,
|
||||
statBonus,
|
||||
baseValue,
|
||||
drainBase,
|
||||
difficultyFactor,
|
||||
scalingFactor,
|
||||
xp,
|
||||
paused,
|
||||
concurrentLimit,
|
||||
onToggle,
|
||||
}) => {
|
||||
interface DisciplineCardProps {
|
||||
definition: DisciplineCardDefinition;
|
||||
runtime: DisciplineCardRuntime;
|
||||
callbacks: DisciplineCardCallbacks;
|
||||
}
|
||||
|
||||
// ─── Discipline Card Component ───────────────────────────────────────────────
|
||||
|
||||
const DisciplineCard: React.FC<DisciplineCardProps> = ({ definition, runtime, callbacks }) => {
|
||||
const {
|
||||
id, name, description, perkThresholds, perkValues, perkTypes,
|
||||
statBonus, baseValue, drainBase, difficultyFactor, scalingFactor,
|
||||
} = definition;
|
||||
const { xp, paused: isPaused, concurrentLimit } = runtime;
|
||||
const { onToggle } = callbacks;
|
||||
|
||||
const displayXp = xp;
|
||||
const progressPercent = Math.min(displayXp / Math.max(1, concurrentLimit * 100), 100);
|
||||
const isPaused = paused;
|
||||
|
||||
const activeStatBonus = calculateStatBonus(baseValue, displayXp, scalingFactor);
|
||||
const estimatedDrain = calculateManaDrain(drainBase, displayXp, difficultyFactor);
|
||||
@@ -134,6 +142,8 @@ const DisciplineCard: React.FC<DisciplineCardProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
// ─── Disciplines Tab ─────────────────────────────────────────────────────────
|
||||
|
||||
export const DisciplinesTab: React.FC = () => {
|
||||
const activeIds = useDisciplineStore((s) => s.activeIds);
|
||||
const concurrentLimit = useDisciplineStore((s) => s.concurrentLimit);
|
||||
@@ -194,21 +204,27 @@ export const DisciplinesTab: React.FC = () => {
|
||||
return (
|
||||
<DisciplineCard
|
||||
key={disc.id}
|
||||
id={disc.id}
|
||||
name={disc.name}
|
||||
description={disc.description}
|
||||
perkThresholds={disc.perks?.map((p) => p.threshold)}
|
||||
perkValues={disc.perks?.map((p) => p.value)}
|
||||
perkTypes={disc.perks?.map((p) => p.type)}
|
||||
statBonus={disc.statBonus.stat}
|
||||
baseValue={disc.statBonus.baseValue}
|
||||
drainBase={disc.drainBase}
|
||||
difficultyFactor={disc.difficultyFactor}
|
||||
scalingFactor={disc.scalingFactor}
|
||||
xp={discState.xp}
|
||||
paused={discState.paused}
|
||||
concurrentLimit={concurrentLimit}
|
||||
onToggle={handleToggle}
|
||||
definition={{
|
||||
id: disc.id,
|
||||
name: disc.name,
|
||||
description: disc.description,
|
||||
perkThresholds: disc.perks?.map((p) => p.threshold),
|
||||
perkValues: disc.perks?.map((p) => p.value),
|
||||
perkTypes: disc.perks?.map((p) => p.type),
|
||||
statBonus: disc.statBonus.stat,
|
||||
baseValue: disc.statBonus.baseValue,
|
||||
drainBase: disc.drainBase,
|
||||
difficultyFactor: disc.difficultyFactor,
|
||||
scalingFactor: disc.scalingFactor,
|
||||
}}
|
||||
runtime={{
|
||||
xp: discState.xp,
|
||||
paused: discState.paused,
|
||||
concurrentLimit,
|
||||
}}
|
||||
callbacks={{
|
||||
onToggle: handleToggle,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user