feat: Add weapon selection to backpack
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import React, { useState, useEffect, useCallback, useRef } from "react";
|
||||
import "./fabula-ultima-sheet.css";
|
||||
import spellsFile from "../data/spells.yml";
|
||||
import weaponsFile from "../data/weapons.yml";
|
||||
|
||||
const STATUSES = ["Slow", "Enraged", "Dazed", "Weak", "Poisoned", "Shaken"];
|
||||
const FEELINGS = [
|
||||
@@ -235,6 +236,8 @@ export default function CharacterSheet() {
|
||||
const [otherClasses, setOtherClasses] = useState<ClassEntry[]>([]);
|
||||
const [spells, setSpells] = useState<Spell[]>([]);
|
||||
const [spellPickerOpen, setSpellPickerOpen] = useState(false);
|
||||
const [weaponPickerOpen, setWeaponPickerOpen] = useState(false);
|
||||
const [weaponCategory, setWeaponCategory] = useState<string>("all");
|
||||
const [statuses, setStatuses] = useState<CheckMap>({});
|
||||
const [martial, setMartial] = useState<CheckMap>({});
|
||||
const [disciplines, setDisciplines] = useState<CheckMap>({});
|
||||
@@ -1134,6 +1137,57 @@ export default function CharacterSheet() {
|
||||
placeholder="Items, notes, lore…"
|
||||
style={{ minHeight: 200 }}
|
||||
/>
|
||||
<button
|
||||
className="add-btn"
|
||||
style={{ marginTop: 8 }}
|
||||
onClick={() => { setWeaponCategory("all"); setWeaponPickerOpen(true); }}
|
||||
>
|
||||
+ Add Equipment
|
||||
</button>
|
||||
|
||||
{weaponPickerOpen && (() => {
|
||||
const allWeapons = (weaponsFile as WeaponsFile).weapons;
|
||||
const categories = ["all", ...Array.from(new Set(allWeapons.map(w => w.category))).sort()];
|
||||
const visible = weaponCategory === "all" ? allWeapons : allWeapons.filter(w => w.category === weaponCategory);
|
||||
return (
|
||||
<div className="spell-picker-overlay" onClick={() => setWeaponPickerOpen(false)}>
|
||||
<div className="spell-picker-modal" onClick={e => e.stopPropagation()}>
|
||||
<div className="spell-picker-header">
|
||||
<span>Choose a weapon</span>
|
||||
<button className="spell-picker-close" onClick={() => setWeaponPickerOpen(false)}>✕</button>
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: 6, flexWrap: "wrap", padding: "8px 14px", borderBottom: "1px solid var(--border)" }}>
|
||||
{categories.map(cat => (
|
||||
<button
|
||||
key={cat}
|
||||
className={`add-btn${weaponCategory === cat ? " active-filter" : ""}`}
|
||||
style={{ padding: "2px 8px", fontSize: "0.65rem", textTransform: "capitalize" }}
|
||||
onClick={() => setWeaponCategory(cat)}
|
||||
>
|
||||
{cat}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<ul className="spell-picker-list">
|
||||
{visible.map((w, i) => (
|
||||
<li
|
||||
key={i}
|
||||
className="spell-picker-item"
|
||||
onClick={() => {
|
||||
const line = `• ${w.name}: Acc ${w.accuracy}, Dmg ${w.damage}${w.description ? ` | ${w.description}` : ""}${w.cost > 0 ? ` (${w.cost}z)` : ""}`;
|
||||
f("backpack", fields.backpack ? fields.backpack + "\n" + line : line);
|
||||
setWeaponPickerOpen(false);
|
||||
}}
|
||||
>
|
||||
<span className="spell-picker-name">{w.name}</span>
|
||||
<span className="spell-picker-class">{w.category}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -923,6 +923,12 @@ input[type="number"] {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.add-btn.active-filter {
|
||||
background: var(--teal);
|
||||
color: var(--bg);
|
||||
border-color: var(--teal);
|
||||
}
|
||||
|
||||
/* ── DISCIPLINES ─────────────────────────────────── */
|
||||
.disciplines-row {
|
||||
display: flex;
|
||||
|
||||
13
src/globals.d.ts
vendored
13
src/globals.d.ts
vendored
@@ -5,6 +5,19 @@ declare module "*.yml" {
|
||||
export default data;
|
||||
}
|
||||
|
||||
interface WeaponTemplate {
|
||||
name: string;
|
||||
cost: number;
|
||||
accuracy: string;
|
||||
damage: string;
|
||||
category: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
interface WeaponsFile {
|
||||
weapons: WeaponTemplate[];
|
||||
}
|
||||
|
||||
interface SpellTemplate {
|
||||
name: string;
|
||||
cost: string;
|
||||
|
||||
Reference in New Issue
Block a user