95 lines
3.8 KiB
Markdown
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. |