✨Feature: implement return to town and resume dungeon flow with state management
This commit is contained in:
66
src/App.tsx
66
src/App.tsx
@@ -9,6 +9,8 @@ import {
|
||||
isCurrentRoomCombatReady,
|
||||
resolveRunEnemyTurn,
|
||||
resolveRunPlayerTurn,
|
||||
resumeDungeon,
|
||||
returnToTown,
|
||||
startCombatInCurrentRoom,
|
||||
travelCurrentExit,
|
||||
} from "@/rules/runState";
|
||||
@@ -54,6 +56,7 @@ function App() {
|
||||
const currentRoom = run.currentRoomId ? currentLevel?.rooms[run.currentRoomId] : undefined;
|
||||
const availableMoves = getAvailableMoves(run);
|
||||
const combatReadyEncounter = isCurrentRoomCombatReady(run);
|
||||
const inTown = run.phase === "town";
|
||||
|
||||
const handleReset = () => {
|
||||
setRun(createDemoRun());
|
||||
@@ -96,6 +99,14 @@ function App() {
|
||||
);
|
||||
};
|
||||
|
||||
const handleReturnToTown = () => {
|
||||
setRun((previous) => returnToTown(previous).run);
|
||||
};
|
||||
|
||||
const handleResumeDungeon = () => {
|
||||
setRun((previous) => resumeDungeon(previous).run);
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="app-shell">
|
||||
<section className="hero">
|
||||
@@ -112,14 +123,21 @@ function App() {
|
||||
<button className="button button-primary" onClick={handleReset}>
|
||||
Reset Demo Run
|
||||
</button>
|
||||
<button
|
||||
className="button"
|
||||
onClick={inTown ? handleResumeDungeon : handleReturnToTown}
|
||||
disabled={Boolean(run.activeCombat)}
|
||||
>
|
||||
{inTown ? "Resume Dungeon" : "Return To Town"}
|
||||
</button>
|
||||
<div className="status-chip">
|
||||
<span>Run Status</span>
|
||||
<strong>{run.status}</strong>
|
||||
<span>Run Phase</span>
|
||||
<strong>{run.phase}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{combatReadyEncounter && !run.activeCombat ? (
|
||||
{combatReadyEncounter && !run.activeCombat && !inTown ? (
|
||||
<section className="alert-banner">
|
||||
<div>
|
||||
<span className="alert-kicker">Encounter Ready</span>
|
||||
@@ -175,9 +193,47 @@ function App() {
|
||||
<p className="supporting-text">
|
||||
Run rewards: {run.xpGained} XP earned, {run.defeatedCreatureIds.length} foes defeated.
|
||||
</p>
|
||||
<p className="supporting-text">
|
||||
{inTown
|
||||
? `The party is currently in town${run.lastTownAt ? ` as of ${new Date(run.lastTownAt).toLocaleString()}` : ""}.`
|
||||
: "The party is still delving below ground."}
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="panel">
|
||||
{inTown ? (
|
||||
<article className="panel panel-town-hub">
|
||||
<div className="panel-header">
|
||||
<h2>Town Hub</h2>
|
||||
<span>Between Delves</span>
|
||||
</div>
|
||||
<h3 className="room-title">Safe Harbor</h3>
|
||||
<p className="supporting-text">
|
||||
You are out of the dungeon. Review the current expedition, catch your breath, and
|
||||
then resume the delve from the same level when you are ready.
|
||||
</p>
|
||||
<div className="town-summary-grid">
|
||||
<div className="encounter-box">
|
||||
<span className="encounter-label">Current Gold</span>
|
||||
<strong>{run.adventurerSnapshot.inventory.currency.gold}</strong>
|
||||
</div>
|
||||
<div className="encounter-box">
|
||||
<span className="encounter-label">Rooms Found</span>
|
||||
<strong>{currentLevel?.discoveredRoomOrder.length ?? 0}</strong>
|
||||
</div>
|
||||
<div className="encounter-box">
|
||||
<span className="encounter-label">Foes Defeated</span>
|
||||
<strong>{run.defeatedCreatureIds.length}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="button-row">
|
||||
<button className="button button-primary" onClick={handleResumeDungeon}>
|
||||
Resume Delve
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
) : (
|
||||
<>
|
||||
<article className="panel">
|
||||
<div className="panel-header">
|
||||
<h2>Current Room</h2>
|
||||
<span>Level {run.currentLevel}</span>
|
||||
@@ -318,6 +374,8 @@ function App() {
|
||||
</p>
|
||||
)}
|
||||
</article>
|
||||
</>
|
||||
)}
|
||||
|
||||
<article className="panel panel-log">
|
||||
<div className="panel-header">
|
||||
|
||||
Reference in New Issue
Block a user