Phase 8: Visitor Management - Visitor/VisitorLog/AccessZone models - Check-in/out with badge generation - Zone occupancy tracking - Kiosk and management pages Phase 9: Messaging & Communication - Announcements with priority levels - Acknowledgement tracking - Shift notes for team handoffs - AnnouncementBanner component Phase 10: Compliance & Audit Trail - Immutable AuditLog model - Document versioning and approval workflow - Acknowledgement tracking for SOPs - CSV export for audit logs Phase 11: Accessibility & i18n - WCAG 2.1 AA compliance utilities - react-i18next with EN/ES translations - User preferences context (theme, font size, etc) - High contrast and reduced motion support Phase 12: Hardware Integration - QR code generation for batches/plants/visitors - Printable label system - Visitor badge printing Phase 13: Advanced Features - Environmental monitoring (sensors, readings, alerts) - Financial tracking (transactions, P&L reports) - AI/ML insights (yield predictions, anomaly detection)
434 lines
14 KiB
Markdown
434 lines
14 KiB
Markdown
# Facility Layout Designer - Premium UX Specification
|
|
|
|
## 🎯 Design Vision
|
|
|
|
A **Figma-meets-SketchUp** experience for cannabis facility floor planning. Premium, intuitive, and powerful enough for compliance while beautiful enough for investor demos.
|
|
|
|
---
|
|
|
|
## 🏗️ Core Architecture
|
|
|
|
### Multi-Floor Support
|
|
|
|
```
|
|
PROPERTY
|
|
├── BUILDING 1 (Main Cultivation)
|
|
│ ├── FLOOR 1 (Ground)
|
|
│ │ ├── Veg Room A
|
|
│ │ ├── Veg Room B
|
|
│ │ └── Clone Room
|
|
│ └── FLOOR 2 (Upper)
|
|
│ ├── Flower Room A
|
|
│ ├── Flower Room B
|
|
│ └── Flower Room C
|
|
├── BUILDING 2 (Processing)
|
|
│ └── FLOOR 1
|
|
│ ├── Dry Room
|
|
│ ├── Cure Room
|
|
│ └── Trim Room
|
|
└── BUILDING 3 (Storage)
|
|
└── FLOOR 1
|
|
└── Vault
|
|
```
|
|
|
|
### Address Format with Floor
|
|
|
|
```
|
|
MAIN.GROW1.F2.FLOWER-A.LEFT.R3.C5.P1
|
|
↑
|
|
Floor 2
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 UI Layout (Premium Dark Mode)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
│ ⚡ Layout Designer [Building ▼] [Floor 1 ▼] 🔍 100% ⊞ ⊟ ↺ ↻ 💾 Save │
|
|
├───────────────┬─────────────────────────────────────────────┬───────────────┤
|
|
│ │ │ │
|
|
│ 📁 LAYERS │ │ 📐 INSPECTOR │
|
|
│ ───────── │ │ ─────────── │
|
|
│ │ [ CANVAS - FLOOR PLAN ] │ │
|
|
│ ▼ Floor 1 │ │ Selected: │
|
|
│ ├ Veg-A │ ┌─────────────┐ ┌─────────────┐ │ VEG ROOM A │
|
|
│ ├ Veg-B │ │ │ │ │ │ │
|
|
│ └ Clones │ │ VEG-A │ │ VEG-B │ │ Size: 40x30' │
|
|
│ │ │ 🌱 234 │ │ 🌱 189 │ │ Tables: 6 │
|
|
│ ▶ Floor 2 │ │ │ │ │ │ Capacity: 480│
|
|
│ │ └─────────────┘ └─────────────┘ │ Occupied: 423│
|
|
│ ───────── │ │ ▓▓▓▓▓▓▓▓░░ │
|
|
│ │ ┌────────────────────────────┐ │ 88% full │
|
|
│ 🧩 ELEMENTS │ │ │ │ │
|
|
│ ───────── │ │ CLONE ROOM │ │ ─────────── │
|
|
│ │ │ 🌱 120 │ │ POSITIONS │
|
|
│ ▢ Room │ │ │ │ [Grid View] │
|
|
│ ▦ Table │ └────────────────────────────┘ │ │
|
|
│ ═ Rack │ │ R1: ████████ │
|
|
│ ⊡ Position │ [AISLE] │ R2: █████░░░ │
|
|
│ │ │ R3: ████████ │
|
|
│ 🎨 STYLES │ │ R4: ░░░░░░░░ │
|
|
│ ───────── │ │ │
|
|
│ ● Veg │ │ [+ Add Row] │
|
|
│ ● Flower │ │ │
|
|
│ ● Dry │ │ │
|
|
│ ● Cure │ │ │
|
|
│ │ │ │
|
|
└───────────────┴─────────────────────────────────────────────┴───────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## ✨ Premium UX Features
|
|
|
|
### 1. Canvas Interactions
|
|
|
|
| Gesture | Action |
|
|
|---------|--------|
|
|
| **Scroll** | Pan canvas |
|
|
| **Pinch/Scroll+Ctrl** | Zoom |
|
|
| **Click element** | Select |
|
|
| **Double-click** | Edit properties |
|
|
| **Drag** | Move element |
|
|
| **Drag corner** | Resize |
|
|
| **Shift+Drag** | Constrain proportions |
|
|
| **Alt+Drag** | Duplicate |
|
|
| **Delete/Backspace** | Remove |
|
|
|
|
### 2. Floor Selector
|
|
|
|
- Dropdown showing all floors
|
|
- 3D mini-map showing floor stack
|
|
- Shift+PageUp/Down to switch floors
|
|
- Floor comparison overlay (ghost previous floor)
|
|
|
|
### 3. Smart Snapping
|
|
|
|
- **Snap to grid** (configurable: 1ft, 6", 1m)
|
|
- **Snap to edges** (align with adjacent rooms)
|
|
- **Snap to centers** (center alignment guides)
|
|
- **Smart dimensions** (show distances while dragging)
|
|
|
|
### 4. Element Library
|
|
|
|
```tsx
|
|
const ELEMENTS = {
|
|
rooms: [
|
|
{ type: 'VEG', icon: '🌱', color: 'emerald' },
|
|
{ type: 'FLOWER', icon: '🌸', color: 'purple' },
|
|
{ type: 'CLONE', icon: '🧬', color: 'blue' },
|
|
{ type: 'DRY', icon: '🍂', color: 'amber' },
|
|
{ type: 'CURE', icon: '🫙', color: 'orange' },
|
|
{ type: 'TRIM', icon: '✂️', color: 'slate' },
|
|
{ type: 'VAULT', icon: '🔒', color: 'zinc' },
|
|
],
|
|
fixtures: [
|
|
{ type: 'TABLE', icon: '▦', description: '4x8 grow table' },
|
|
{ type: 'RACK', icon: '═', description: 'Drying rack' },
|
|
{ type: 'TRAY', icon: '▢', description: 'Clone tray' },
|
|
{ type: 'HANGER', icon: '⌐', description: 'Vertical hanger' },
|
|
],
|
|
infrastructure: [
|
|
{ type: 'DOOR', icon: '🚪' },
|
|
{ type: 'HVAC', icon: '❄️' },
|
|
{ type: 'ELECTRICAL', icon: '⚡' },
|
|
{ type: 'WATER', icon: '💧' },
|
|
],
|
|
};
|
|
```
|
|
|
|
### 5. Inspector Panel
|
|
|
|
#### Room Properties
|
|
|
|
```
|
|
┌─────────────────────────────┐
|
|
│ VEG ROOM A │
|
|
│ ───────────────────────── │
|
|
│ │
|
|
│ 📍 Location │
|
|
│ Building: [Grow 1 ▼] │
|
|
│ Floor: [Floor 1 ▼] │
|
|
│ Code: [VEG-A ] │
|
|
│ │
|
|
│ 📐 Dimensions │
|
|
│ Width: [40] ft │
|
|
│ Height: [30] ft │
|
|
│ Area: 1,200 sq ft │
|
|
│ │
|
|
│ 🌱 Capacity │
|
|
│ Tables: [6 ] │
|
|
│ Positions: 480 │
|
|
│ Occupied: 423 (88%) │
|
|
│ │
|
|
│ 🎨 Appearance │
|
|
│ Color: [🟢 Emerald ▼] │
|
|
│ Label: [Vegetative A] │
|
|
│ │
|
|
│ [Delete Room] │
|
|
└─────────────────────────────┘
|
|
```
|
|
|
|
#### Table/Section Properties
|
|
|
|
```
|
|
┌─────────────────────────────┐
|
|
│ TABLE T1 │
|
|
│ ───────────────────────── │
|
|
│ │
|
|
│ 📐 Grid Configuration │
|
|
│ Rows: [6 ] │
|
|
│ Columns: [8 ] │
|
|
│ Spacing: [12] in │
|
|
│ │
|
|
│ Total Positions: 48 │
|
|
│ Occupied: 42 │
|
|
│ Empty: 6 │
|
|
│ │
|
|
│ 📊 Current Batch │
|
|
│ [OG Kush #4] - 42 plants │
|
|
│ │
|
|
│ [View Grid] [Edit Grid] │
|
|
└─────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 Visual Design System
|
|
|
|
### Color Palette (Dark Mode)
|
|
|
|
```css
|
|
/* Background */
|
|
--bg-canvas: #0f172a; /* Slate 900 */
|
|
--bg-sidebar: #1e293b; /* Slate 800 */
|
|
--bg-panel: #334155; /* Slate 700 */
|
|
|
|
/* Room Types */
|
|
--room-veg: #10b981; /* Emerald */
|
|
--room-flower: #a855f7; /* Purple */
|
|
--room-clone: #3b82f6; /* Blue */
|
|
--room-dry: #f59e0b; /* Amber */
|
|
--room-cure: #f97316; /* Orange */
|
|
--room-trim: #64748b; /* Slate */
|
|
|
|
/* Grid */
|
|
--grid-line: rgba(255,255,255,0.05);
|
|
--grid-major: rgba(255,255,255,0.1);
|
|
|
|
/* Selection */
|
|
--selection: #10b981;
|
|
--selection-glow: rgba(16,185,129,0.3);
|
|
```
|
|
|
|
### Typography
|
|
|
|
```css
|
|
--font-ui: 'Space Grotesk', system-ui;
|
|
--font-mono: 'JetBrains Mono', monospace;
|
|
|
|
/* Sizes */
|
|
--text-panel-title: 0.75rem; /* 12px */
|
|
--text-label: 0.875rem; /* 14px */
|
|
--text-input: 1rem; /* 16px */
|
|
```
|
|
|
|
### Glassmorphism Panels
|
|
|
|
```css
|
|
.panel {
|
|
background: rgba(30, 41, 59, 0.8);
|
|
backdrop-filter: blur(12px);
|
|
border: 1px solid rgba(255,255,255,0.1);
|
|
border-radius: 12px;
|
|
box-shadow: 0 8px 32px rgba(0,0,0,0.3);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🖥️ Component Architecture
|
|
|
|
```
|
|
LayoutDesigner/
|
|
├── LayoutDesigner.tsx # Main container
|
|
├── components/
|
|
│ ├── Canvas/
|
|
│ │ ├── Canvas.tsx # react-konva stage
|
|
│ │ ├── Grid.tsx # Background grid
|
|
│ │ ├── RoomShape.tsx # Room polygon
|
|
│ │ ├── TableShape.tsx # Table rectangle
|
|
│ │ ├── SelectionBox.tsx # Multi-select
|
|
│ │ └── Guides.tsx # Alignment guides
|
|
│ ├── Sidebar/
|
|
│ │ ├── Sidebar.tsx
|
|
│ │ ├── LayersPanel.tsx # Floor/room hierarchy
|
|
│ │ ├── ElementsPanel.tsx # Draggable elements
|
|
│ │ └── StylesPanel.tsx # Color/appearance
|
|
│ ├── Inspector/
|
|
│ │ ├── Inspector.tsx
|
|
│ │ ├── RoomInspector.tsx
|
|
│ │ ├── TableInspector.tsx
|
|
│ │ └── GridEditor.tsx # Position grid editor
|
|
│ ├── Toolbar/
|
|
│ │ ├── Toolbar.tsx
|
|
│ │ ├── ZoomControls.tsx
|
|
│ │ ├── FloorSelector.tsx
|
|
│ │ └── HistoryButtons.tsx
|
|
│ └── Modals/
|
|
│ ├── AddFloorModal.tsx
|
|
│ ├── AddBuildingModal.tsx
|
|
│ └── ImportExportModal.tsx
|
|
├── hooks/
|
|
│ ├── useCanvas.ts # Canvas state
|
|
│ ├── useSelection.ts # Selected elements
|
|
│ ├── useHistory.ts # Undo/redo
|
|
│ └── useDragDrop.ts # Element placement
|
|
├── stores/
|
|
│ └── layoutStore.ts # Zustand state
|
|
└── utils/
|
|
├── geometry.ts # Collision, bounds
|
|
├── addressGenerator.ts # Create addresses
|
|
└── exporters.ts # PDF, image export
|
|
```
|
|
|
|
---
|
|
|
|
## 📱 Responsive Behavior
|
|
|
|
### Desktop (1200px+)
|
|
|
|
- 3-column layout: Sidebar | Canvas | Inspector
|
|
- Full feature set
|
|
|
|
### Tablet (768-1199px)
|
|
|
|
- 2-column: Collapsible sidebar | Canvas
|
|
- Inspector as slide-over panel
|
|
- Touch-friendly controls
|
|
|
|
### Mobile (< 768px)
|
|
|
|
- Full-screen canvas
|
|
- Bottom sheet for elements/inspector
|
|
- Simplified tools
|
|
- "View Only" mode recommended
|
|
|
|
---
|
|
|
|
## ⌨️ Keyboard Shortcuts
|
|
|
|
| Shortcut | Action |
|
|
|----------|--------|
|
|
| `Space + Drag` | Pan |
|
|
| `Cmd/Ctrl + +/-` | Zoom |
|
|
| `Cmd/Ctrl + 0` | Fit to screen |
|
|
| `Cmd/Ctrl + Z` | Undo |
|
|
| `Cmd/Ctrl + Shift + Z` | Redo |
|
|
| `Cmd/Ctrl + D` | Duplicate |
|
|
| `Cmd/Ctrl + G` | Group |
|
|
| `Delete` | Remove selected |
|
|
| `Escape` | Deselect |
|
|
| `Tab` | Cycle selection |
|
|
| `1-9` | Quick zoom levels |
|
|
| `F` | Fit selection |
|
|
| `G` | Toggle grid |
|
|
| `S` | Toggle snap |
|
|
|
|
---
|
|
|
|
## 🔄 State Management (Zustand)
|
|
|
|
```typescript
|
|
interface LayoutState {
|
|
// Current context
|
|
propertyId: string;
|
|
buildingId: string;
|
|
floorId: string;
|
|
|
|
// Canvas
|
|
zoom: number;
|
|
pan: { x: number; y: number };
|
|
showGrid: boolean;
|
|
snapToGrid: boolean;
|
|
gridSize: number; // feet
|
|
|
|
// Selection
|
|
selectedIds: string[];
|
|
hoveredId: string | null;
|
|
|
|
// Elements
|
|
rooms: Room[];
|
|
sections: Section[];
|
|
positions: Position[];
|
|
|
|
// History
|
|
past: LayoutSnapshot[];
|
|
future: LayoutSnapshot[];
|
|
|
|
// Actions
|
|
addRoom: (room: Partial<Room>) => void;
|
|
updateRoom: (id: string, updates: Partial<Room>) => void;
|
|
deleteRoom: (id: string) => void;
|
|
undo: () => void;
|
|
redo: () => void;
|
|
// ... etc
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📄 Export Options
|
|
|
|
1. **PDF Floor Plan** - Printable blueprint with dimensions
|
|
2. **PNG/SVG Image** - For presentations
|
|
3. **JSON Layout** - Backup/restore
|
|
4. **METRC Location Report** - All addresses in compliance format
|
|
5. **Position Labels** - Generate QR labels for all positions
|
|
|
|
---
|
|
|
|
## 🚀 Implementation Priority
|
|
|
|
### Week 1: Foundation
|
|
|
|
- [ ] Zustand store setup
|
|
- [ ] Basic canvas with react-konva
|
|
- [ ] Grid rendering
|
|
- [ ] Pan & zoom
|
|
|
|
### Week 2: Elements
|
|
|
|
- [ ] Room shapes (create, select, move, resize)
|
|
- [ ] Sidebar with element library
|
|
- [ ] Drag to canvas
|
|
- [ ] Inspector panel
|
|
|
|
### Week 3: Multi-Floor
|
|
|
|
- [ ] Floor selector
|
|
- [ ] Floor switching
|
|
- [ ] Ghost overlay of other floors
|
|
- [ ] Building/floor CRUD
|
|
|
|
### Week 4: Positions
|
|
|
|
- [ ] Table grid generator
|
|
- [ ] Position grid view
|
|
- [ ] Occupancy visualization
|
|
- [ ] Plant placement integration
|
|
|
|
### Week 5: Polish
|
|
|
|
- [ ] Snap guides
|
|
- [ ] Keyboard shortcuts
|
|
- [ ] Undo/redo history
|
|
- [ ] Export functions
|
|
|
|
### Week 6: Integration
|
|
|
|
- [ ] API integration
|
|
- [ ] Real-time updates
|
|
- [ ] METRC address mapping
|
|
- [ ] QR code generation
|