Skip to content

v0.9 Phase 4: TownManager drawer + retire modal CRUD#67

Merged
jacuzzicoding merged 1 commit into
developmentfrom
feature/v09-phase-4-townmanager
May 3, 2026
Merged

v0.9 Phase 4: TownManager drawer + retire modal CRUD#67
jacuzzicoding merged 1 commit into
developmentfrom
feature/v09-phase-4-townmanager

Conversation

@jacuzzicoding
Copy link
Copy Markdown
Owner

Summary

Phase 4 of the v0.9.0-beta plan (docs/v0.9-plan.md § Phase 4). Replaces CreateTownModal, EditTownModal, and the Phase 2 sidebar bridge stubs with a single right-side TownManager drawer mounted at the App layout level.

Added

  • TownManager (src/components/TownManager.tsx) — 420px right-side drawer (bottom sheet at ≤720px). View / activate / inline-edit / delete towns; sticky + New town form in the footer. Mounts in App.tsx above the router so it overlays every route.
  • useUIStore (src/lib/uiStore.ts) — small non-persisted Zustand store: townManagerOpen, townManagerForceCreate, openTownManager(forceCreate?), closeTownManager().
  • Auto-open in create-locked mode whenever towns.length === 0 (replaces CreateTownModal's required={noTowns} flow). Scrim, Esc, and the close button are all suppressed in this state.
  • GAME_LIST export in src/lib/types.ts — ordered array used by the new-town form's game selector.
  • TownManager styles in src/index.css (drawer, list, edit/new forms, segmented hemisphere control, bottom-sheet variant).

Retired

  • src/components/modals/CreateTownModal.tsx — replaced by the drawer's New Town form.
  • src/components/modals/EditTownModal.tsx — replaced by the drawer's inline row edit.
  • src/components/shared/TownNameFields.tsx — no remaining consumers.
  • Sidebar bridge stubs from Phase 2: window.prompt town switcher, the inline Edit / + New buttons, and the inline NH/SH segmented hemisphere toggle. The single Switch town › button now opens the drawer; hemisphere is shown read-only in the sidebar and edited inside the drawer.
  • v0.8.1 greyed-out-buttons stopgap — no longer needed; the layout-level drawer renders correctly on category tabs.

Decisions

  • Decision 1 (game-immutability) honored. The inline edit form has no game <select>. Game is rendered as a read-only badge with the hint "Game can't be changed after creation." handleSave builds a patch of { name, hemisphere } only — gameId never appears. The v0.9.2 design's <select> (lines 104–106 of addons.jsx) was deliberately dropped per the plan's override.
  • Decision 5 honored. playerName removed from Town, useAppStore.createTown / updateTown, downloadCSV / buildCSV, and store.test.ts. No migration callback — Zustand persist silently drops unknown fields on the next write.
  • TownManager open/closed state lives in a separate useUIStore rather than inside useAppStore, so it isn't persisted to localStorage across reloads.
  • Auto-open in forceCreate mode preserves the prior modal-locked UX (no other UI reachable when zero towns exist) as a single behavior gate inside the new component, instead of duplicating the required plumbing.
  • updateTown now takes a TownPatch ({ name?, hemisphere? }). A null hemisphere from the form (non-ACNH games) is ignored so a stored hemisphere never gets clobbered if the game flag changes in the future.

Test plan

  • npm run build — passes (zero TypeScript errors).
  • npm test — 59 tests pass (2 files).
  • npm run lint — clean.
  • Pre-commit lint-staged (eslint + prettier) — clean.
  • Manual verification on dev preview once this lands. Key flows: create-first-town lock, switch active town, edit name + hemisphere on ACNH, edit on non-ACNH (no hemisphere row), delete with last-town guard, drawer renders on category tabs without z-index/overflow issues.

🤖 Generated with Claude Code

Replaces CreateTownModal, EditTownModal, and the Phase 2 sidebar
bridge stubs (window.prompt switcher, Edit/+New buttons, hemisphere
toggle) with a single right-side TownManager drawer mounted at the
App layout level. Drawer is a bottom sheet at <=720px.

Honors locked Decision 1: the inline edit form has no game <select>;
gameId is shown as a read-only badge and never appears in the patch
object passed to updateTown. Honors Decision 5 by removing playerName
from the Town type, store, CSV export, and tests.

Auto-opens in forceCreate mode when towns.length === 0, replacing
the previous CreateTownModal required={noTowns} pattern. Resolves
the v0.8.1 greyed-out-buttons stopgap because the drawer now mounts
above the router and is unaffected by overflow/z-index on category
tabs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
animalcrossingwebapp Ready Ready Preview, Comment May 3, 2026 10:59pm

@jacuzzicoding
Copy link
Copy Markdown
Owner Author

@claude Testing comment 1.

@jacuzzicoding
Copy link
Copy Markdown
Owner Author

@codex[agent] Testing comment 2.

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@Codex
Copy link
Copy Markdown
Contributor

Codex AI commented May 3, 2026

@codex[agent] Testing comment 2.

No action needed here; lint/test/build are green on my side. Latest commit on branch remains the existing TownManager change.

@jacuzzicoding jacuzzicoding merged commit 15ebf42 into development May 3, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants