/** * RackConfigModal - Modal for configuring rack/section dimensions */ import { useState, useEffect } from 'react'; import { Table, Server, Box, GripVertical, Square, X } from 'lucide-react'; import { cn } from '../../lib/utils'; import type { RackData } from './RackVisualizer'; interface RackConfigModalProps { rack: RackData; isOpen: boolean; onClose: () => void; onSave: (updates: Partial) => void; } const SUBTYPE_OPTIONS = [ { value: 'TABLE', label: 'Table', Icon: Table, desc: 'Flat growing surface' }, { value: 'RACK', label: 'Rack', Icon: Server, desc: 'Multi-tier vertical rack' }, { value: 'TRAY', label: 'Tray', Icon: Box, desc: 'Flood/drain tray system' }, { value: 'HANGER', label: 'Hanger', Icon: GripVertical, desc: 'Hanging/drying racks' }, { value: 'FLOOR', label: 'Floor', Icon: Square, desc: 'Ground-level positions' }, ]; export function RackConfigModal({ rack, isOpen, onClose, onSave }: RackConfigModalProps) { const [name, setName] = useState(rack.name); const [code, setCode] = useState(rack.code || ''); const [subtype, setSubtype] = useState(rack.subtype); const [rows, setRows] = useState(rack.rows); const [columns, setColumns] = useState(rack.columns); const [tiers, setTiers] = useState(rack.tiers); const [saving, setSaving] = useState(false); // Reset form when rack changes useEffect(() => { setName(rack.name); setCode(rack.code || ''); setSubtype(rack.subtype); setRows(rack.rows); setColumns(rack.columns); setTiers(rack.tiers); }, [rack]); if (!isOpen) return null; const handleSave = async () => { setSaving(true); try { await onSave({ name, code: code || undefined, subtype, rows, columns, tiers, }); onClose(); } catch (e) { console.error('Failed to save rack config:', e); } finally { setSaving(false); } }; const totalSlots = rows * columns * tiers; return (
{/* Backdrop */}
{/* Modal */}
{/* Header */}

Configure Section

{/* Body */}
{/* Name & Code */}
setName(e.target.value)} className="w-full px-3 py-2 bg-secondary/50 border border-input rounded text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20 transition-all font-sans" placeholder="e.g., Table 1" />
setCode(e.target.value)} className="w-full px-3 py-2 bg-secondary/50 border border-input rounded text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20 transition-all font-mono" placeholder="e.g., T1" />
{/* Section Type */}
{SUBTYPE_OPTIONS.map((opt) => ( ))}
{/* Dimensions */}
setRows(Math.max(1, Math.min(50, parseInt(e.target.value) || 1)))} min={1} max={50} className="w-full px-3 py-2 bg-secondary/50 border border-input rounded text-foreground text-center focus:outline-none focus:border-primary font-mono" />
setColumns(Math.max(1, Math.min(50, parseInt(e.target.value) || 1)))} min={1} max={50} className="w-full px-3 py-2 bg-secondary/50 border border-input rounded text-foreground text-center focus:outline-none focus:border-primary font-mono" />
setTiers(Math.max(1, Math.min(10, parseInt(e.target.value) || 1)))} min={1} max={10} className="w-full px-3 py-2 bg-secondary/50 border border-input rounded text-foreground text-center focus:outline-none focus:border-primary font-mono" />

Total positions: {totalSlots}

{/* Visual Preview */}

Preview

{Array.from({ length: Math.min(rows * columns, 50) }, (_, i) => (
))}
{rows * columns > 50 && (

Showing first 50 slots

)}
{/* Footer */}
); } export default RackConfigModal;