Files
furniture/CLAUDE.md
T
2026-10-17 12:09:36 -04:00

95 lines
3.8 KiB
Markdown

# Furniture Optimizer (hackathon project)
A web tool for venues (events, banquets, conferences) to lay out furniture in a room and, eventually, auto-optimize the layout.
## Current scope: Phase 1 (UI only)
The ONLY feature right now is drag-and-drop layout:
- Left palette with two source tiles: chair and table.
- Large rectangular room on the right (fixed 10m x 8m, drawn to scale, 1m = 60px, faint 0.5m grid).
- Click (no drag) a palette tile to open a settings menu for that furniture type:
- Available: how many of that type the venue has (number stepper, min = number already placed).
- Tables only: Seats per table (number stepper, min 1).
- Palette tiles show a badge with remaining count (available minus placed).
- Drag a tile into the room to create an item. The tile stays in the palette. If remaining is 0, the tile is greyed out and can't be dragged.
- Distinguish click from drag with a small movement threshold (about 5px).
- Drag existing items to move them. Items are clamped inside the room walls.
- No overlap allowed. Invalid position = red outline while dragging; on drop, snap back to last valid position (or cancel the add if new).
- Snap to the 0.5m grid on drop.
Do not build anything beyond this unless asked. Do not design in a way that blocks the roadmap below.
## Tech stack
- React + TypeScript, Vite
- react-konva (Konva) for the canvas
- State: single top-level store (useState/useReducer). Keep it centralized so an optimizer can read and write it later.
## Data model
```ts
type FurnitureType = "chair" | "table";
interface FurnitureItem {
id: string;
type: FurnitureType;
x: number; // meters, top-left, room coordinates
y: number;
width: number; // meters
height: number;
rotation: number; // degrees, always 0 for now
locked: boolean; // always false for now, reserved
}
interface Room { width: number; height: number; } // meters
// Per-type settings, edited via the palette menu
interface FurnitureTypeConfig {
type: FurnitureType;
available: number; // inventory count
seatsPerUnit?: number; // tables only: people who can sit at one
}
// remaining = available - items.filter(i => i.type === type).length
```
Seats per table is a type-level setting for now (applies to all tables). Per-table overrides come later. Chairs and table seats are independent for now.
Default sizes: chair 0.5 x 0.5 m, table 1.8 x 0.8 m.
## Conventions
- Store everything in meters. Convert to pixels only at render time (one `PX_PER_M` constant).
- Collision = axis-aligned bounding boxes. Keep collision and clamping logic in pure functions (no React or Konva imports) so the optimizer can reuse them.
- Keep geometry/rules logic separate from rendering components.
- Small, typed, readable code. No new dependencies without a good reason.
- Keep the UI minimal: light grey app background, room centered in the remaining space.
## Roadmap (not built yet, don't block)
Venue-focused features planned for later phases:
- Furniture inventory: set X amount of each furniture type
- Semi-custom furniture: couches, chairs, tables of any size and seating count
- Room import
- Furniture placement rules
- Locking furniture in place
- Custom seating limits (per table or global)
- Optimizers for: room loading/unloading flow, screen visibility, max comfort, max table access
- Optimization approach idea: user-set rule priorities, possibly a neural net with weights and biases to score "optimal placements" (undecided; start with hard constraints like no overlap, then weighted scoring)
- Input ideas: phone scanning of a room, manual entry
## Commands
```
npm install
npm run dev # start dev server
npm run build # production build
npx tsc --noEmit # type check
```
## Working agreement
- Ask before expanding scope past Phase 1.
- After changes, make sure the app builds and type checks.
- Hackathon pace: prefer simple and working over clever.