import { useState, useEffect } from 'react'; import { COMPONENT_META, COMPONENT_TYPES } from '../types'; import type { ComponentType, ComponentStatus } from '../types'; interface AddComponentProps { rackId: string; totalUnits: number; initialPosition?: number; onSave: (data: ComponentFormData) => Promise; onClose: () => void; } export interface ComponentFormData { rack_id: string; name: string; type: ComponentType; position?: number | null; height_units: number; port_count?: number | null; sfp_count?: number | null; manufacturer?: string; model?: string; serial_number?: string; asset_tag?: string; ip_address?: string; mac_address?: string; status: ComponentStatus; notes: string; } export function AddComponentModal({ rackId, totalUnits, initialPosition, onSave, onClose }: AddComponentProps) { const [form, setForm] = useState({ rack_id: rackId, name: '', type: 'server', position: initialPosition ?? null, height_units: 1, port_count: null, sfp_count: null, manufacturer: '', model: '', serial_number: '', asset_tag: '', ip_address: '', mac_address: '', status: 'active', notes: '', }); const [saving, setSaving] = useState(false); const [error, setError] = useState(''); function set(key: keyof ComponentFormData, value: unknown) { setForm(f => ({ ...f, [key]: value })); } async function handleSubmit(e: React.FormEvent) { e.preventDefault(); if (!form.name.trim()) { setError('Name is required'); return; } setSaving(true); setError(''); try { await onSave({ ...form, position: form.position ? Number(form.position) : null, height_units: Number(form.height_units), port_count: (form.type === 'switch' || form.type === 'patch_panel') && form.port_count ? Number(form.port_count) : null, sfp_count: form.type === 'switch' && form.sfp_count ? Number(form.sfp_count) : null, manufacturer: form.manufacturer || undefined, model: form.model || undefined, serial_number: form.serial_number || undefined, asset_tag: form.asset_tag || undefined, ip_address: form.ip_address || undefined, mac_address: form.mac_address || undefined, }); } catch (err: unknown) { setError(err instanceof Error ? err.message : 'Failed to save'); setSaving(false); } } return (
e.target === e.currentTarget && onClose()}>

Add Component

set('name', e.target.value)} placeholder="e.g. Core Switch SW-01" className="form-input" />
set('position', e.target.value ? Number(e.target.value) : null)} placeholder="auto" className="form-input" /> Leave empty to leave unpositioned
set('height_units', Number(e.target.value))} className="form-input" />
{(form.type === 'switch' || form.type === 'patch_panel') && (
set('port_count', Number(e.target.value))} className="form-input" placeholder="24" /> {form.type === 'patch_panel' ? 'Number of RJ45 jacks on the front panel (e.g. 12, 24, 48)' : 'Total ethernet ports shown on the rack diagram (e.g. 8, 16, 24, 48)'}
{form.type === 'switch' && (
set('sfp_count', Number(e.target.value))} className="form-input" placeholder="0" /> SFP / fiber uplink slots (0–16)
)}
)}
set('manufacturer', e.target.value)} placeholder="e.g. Cisco" className="form-input" />
set('model', e.target.value)} placeholder="e.g. Catalyst 2960" className="form-input" />
set('ip_address', e.target.value)} placeholder="192.168.1.1" className="form-input" />
set('mac_address', e.target.value)} placeholder="AA:BB:CC:DD:EE:FF" className="form-input" />
set('serial_number', e.target.value)} className="form-input" />
set('asset_tag', e.target.value)} className="form-input" />
{error &&
{error}
}
); } // Generic modal for creating sites/rooms/racks interface SimpleCreateProps { title: string; fields: { key: string; label: string; placeholder?: string; type?: string; defaultValue?: string | number }[]; onSave: (data: Record) => Promise; onClose: () => void; } export function SimpleCreateModal({ title, fields, onSave, onClose }: SimpleCreateProps) { const [values, setValues] = useState>( Object.fromEntries(fields.map(f => [f.key, f.defaultValue ?? ''])) ); const [saving, setSaving] = useState(false); const [error, setError] = useState(''); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setSaving(true); setError(''); try { await onSave(values); } catch (err: unknown) { setError(err instanceof Error ? err.message : 'Failed to save'); setSaving(false); } } return (
e.target === e.currentTarget && onClose()}>

{title}

{fields.map(f => (
setValues(v => ({ ...v, [f.key]: f.type === 'number' ? Number(e.target.value) : e.target.value }))} placeholder={f.placeholder} className="form-input" />
))} {error &&
{error}
}
); }