✨Feature: implement town market functionality with treasure selling and stashing
This commit is contained in:
100
src/App.tsx
100
src/App.tsx
@@ -12,6 +12,7 @@ import {
|
||||
startCombatInCurrentRoom,
|
||||
travelCurrentExit,
|
||||
} from "@/rules/runState";
|
||||
import { queueTreasureForSale, sellPendingTreasure, sendTreasureToStash } from "@/rules/town";
|
||||
import type { RunState } from "@/types/state";
|
||||
|
||||
function createDemoRun() {
|
||||
@@ -114,6 +115,8 @@ function App() {
|
||||
);
|
||||
const equippedItems = run.adventurerSnapshot.inventory.equipped;
|
||||
const latestLoot = run.lootedItems.slice(-4).reverse();
|
||||
const pendingSales = run.townState.pendingSales;
|
||||
const stash = run.townState.stash;
|
||||
|
||||
const handleReset = () => {
|
||||
setRun(createDemoRun());
|
||||
@@ -156,6 +159,18 @@ function App() {
|
||||
);
|
||||
};
|
||||
|
||||
const handleQueueSale = (definitionId: string) => {
|
||||
setRun((previous) => queueTreasureForSale(sampleContentPack, previous, definitionId).run);
|
||||
};
|
||||
|
||||
const handleStashTreasure = (definitionId: string) => {
|
||||
setRun((previous) => sendTreasureToStash(sampleContentPack, previous, definitionId).run);
|
||||
};
|
||||
|
||||
const handleSellPending = () => {
|
||||
setRun((previous) => sellPendingTreasure(sampleContentPack, previous).run);
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="app-shell">
|
||||
<section className="hero">
|
||||
@@ -335,6 +350,91 @@ function App() {
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article className="panel panel-town">
|
||||
<div className="panel-header">
|
||||
<h2>Town Market</h2>
|
||||
<span>{run.townState.visits} town actions</span>
|
||||
</div>
|
||||
<div className="town-summary">
|
||||
<div className="inventory-badge">
|
||||
<span>Known Services</span>
|
||||
<strong>{run.townState.knownServices.length}</strong>
|
||||
</div>
|
||||
<div className="inventory-badge">
|
||||
<span>Queued Sales</span>
|
||||
<strong>{pendingSales.length}</strong>
|
||||
</div>
|
||||
<div className="inventory-badge">
|
||||
<span>Stash</span>
|
||||
<strong>{stash.length}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="town-actions">
|
||||
<button
|
||||
className="button button-primary"
|
||||
onClick={handleSellPending}
|
||||
disabled={pendingSales.length === 0}
|
||||
>
|
||||
Sell Queued Treasure
|
||||
</button>
|
||||
</div>
|
||||
<section className="town-section">
|
||||
<span className="inventory-label">Treasure In Pack</span>
|
||||
<div className="inventory-list">
|
||||
{carriedTreasure.length === 0 ? (
|
||||
<p className="supporting-text">No treasure available for town actions.</p>
|
||||
) : (
|
||||
carriedTreasure.map((entry) => (
|
||||
<article key={`town-pack-${entry.definitionId}`} className="town-card">
|
||||
<div>
|
||||
<strong>{formatInventoryEntry(entry.definitionId, entry.quantity)}</strong>
|
||||
<span>Choose whether to sell or stash this treasure.</span>
|
||||
</div>
|
||||
<div className="enemy-actions">
|
||||
<button className="button" onClick={() => handleStashTreasure(entry.definitionId)}>
|
||||
Send To Stash
|
||||
</button>
|
||||
<button className="button button-primary" onClick={() => handleQueueSale(entry.definitionId)}>
|
||||
Queue For Sale
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
<section className="town-section">
|
||||
<span className="inventory-label">Pending Sales</span>
|
||||
<div className="inventory-list">
|
||||
{pendingSales.length === 0 ? (
|
||||
<p className="supporting-text">Nothing queued at the market.</p>
|
||||
) : (
|
||||
pendingSales.map((entry) => (
|
||||
<article key={`pending-${entry.definitionId}`} className="inventory-card inventory-card-treasure">
|
||||
<strong>{formatInventoryEntry(entry.definitionId, entry.quantity)}</strong>
|
||||
<span>Ready to convert into gold</span>
|
||||
</article>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
<section className="town-section">
|
||||
<span className="inventory-label">Town Stash</span>
|
||||
<div className="inventory-list">
|
||||
{stash.length === 0 ? (
|
||||
<p className="supporting-text">The stash is empty.</p>
|
||||
) : (
|
||||
stash.map((entry) => (
|
||||
<article key={`stash-${entry.definitionId}`} className="inventory-card">
|
||||
<strong>{formatInventoryEntry(entry.definitionId, entry.quantity)}</strong>
|
||||
<span>Held safely in town storage</span>
|
||||
</article>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
|
||||
<article className="panel">
|
||||
<div className="panel-header">
|
||||
<h2>Current Room</h2>
|
||||
|
||||
Reference in New Issue
Block a user