Files
2026-05-27 23:29:53 +01:00

3.9 KiB

Tasks: enterprise-r3f-booking

Change ID: enterprise-r3f-booking Package: @suaveplan/r3f-booking Target path: r3f/commerce/r3f-booking Prerequisites on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/logger


0. Pre-flight (non-negotiable)

  • 0.1 Confirm clean working tree (git status reports nothing) and no in-flight worktrees with uncommitted work (git worktree list then git status in each)
  • 0.2 If any worktrees exist under .claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
  • 0.3 Confirm the package set in MANIFEST.md matches find packages -maxdepth 3 -name package.json count. Drift here means a prior change archived without regenerating the manifest.

1. Scaffold

  • Create directory tree per proposal.md.
  • package.json at 0.1.0, "sideEffects": false, exports "." + component + hook + schema subpaths.
  • Same dep stack as enterprise-r3f-earth (R3F + React stack).
  • tsconfig.json extending react-library.json; vitest.config.ts with jsdom, pool: 'forks', fileParallelism: false.
  • Scripts: lint, typecheck, test, test:coverage, build, docs:check.

2. Types, errors, and venue schema

  • Define all interfaces and Zod schemas (VenueDefinitionSchema, SectionDefinitionSchema, RowDefinitionSchema, SeatDefinitionSchema) in src/types/r3f-booking.types.ts.
  • Write r3f-booking.types.md (≥200 words).
  • src/error-codes.ts: R3F_BOOKING_INVALID_VENUE, R3F_BOOKING_SEAT_NOT_FOUND, R3F_BOOKING_MAX_SELECTION; eager registration.
  • Implement src/schemas/venue-schema/venue-schema.ts: export parseVenueDefinition(data: unknown): VenueDefinition using Zod; throw typed error on parse failure.
  • Write venue-schema.test.ts: valid full venue; missing required field; invalid seat status.

3. useVenueSelection hook

  • Implement useVenueSelection in src/hooks/use-venue-selection/use-venue-selection.ts:
    • useState<string[]> for selected seats.
    • select(seatId): add if maxSelectable not exceeded; throw R3F_BOOKING_MAX_SELECTION otherwise.
    • deselect(seatId) / clear() / isSelected(seatId).
  • Write use-venue-selection.test.ts: select/deselect/clear/isSelected; maxSelectable enforcement.
  • Write use-venue-selection.md (≥200 words).

4. Components

For each of VenueSeat, VenueSection, VenueFloorPlan, VenueMap:

  • Implement the R3F component:
    • VenueSeat: a <Box> mesh positioned in 3D space; color by status (green/red/grey/blue for selected); hover highlight; click → onSeatSelect/onSeatDeselect; keyboard aria-label.
    • VenueSection: grid of VenueSeat components laid out from RowDefinition[]; section label via <Html>.
    • VenueFloorPlan: flat 2D orthographic view showing all sections.
    • VenueMap: 3D perspective view wrapping all sections in a <Canvas> with OrbitControls.
  • Write .test.tsx for each: renders without crash; seat click fires callback; reserved seat click does nothing; { timeout: 5000 }.
  • Write .stories.tsx: default + playground + variants (e.g. concert hall vs office floor).
  • Write .md per component (≥200 words).

5. Docs + verify + publish

  • Root README.md: quick-start with sample venue JSON, selection hook example, component API table.
  • bunx turbo lint --filter=@suaveplan/r3f-booking — zero errors.
  • bunx turbo typecheck --filter=@suaveplan/r3f-booking — zero errors.
  • bunx turbo test --filter=@suaveplan/r3f-booking — all pass.
  • bunx turbo test:coverage --filter=@suaveplan/r3f-booking — 100%.
  • bun scripts/publish.ts --package @suaveplan/r3f-booking.
  • Update CLAUDE.md; archive to openspec/archive/2026-04-24-enterprise-r3f-booking/.