fix(rack-planner): compute port data synchronously in PortConfigModal to prevent empty first render
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect, type FormEvent } from 'react';
|
import { useState, useEffect, useMemo, type FormEvent } from 'react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import type { Port, Vlan, VlanMode } from '../../types';
|
import type { Port, Vlan, VlanMode } from '../../types';
|
||||||
import { Modal } from '../ui/Modal';
|
import { Modal } from '../ui/Modal';
|
||||||
@@ -14,42 +14,45 @@ interface PortConfigModalProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function PortConfigModal({ portId, open, onClose }: PortConfigModalProps) {
|
export function PortConfigModal({ portId, open, onClose }: PortConfigModalProps) {
|
||||||
const { racks, fetchRacks } = useRackStore();
|
const { racks, fetchRacks, deleteConnection } = useRackStore();
|
||||||
const [port, setPort] = useState<Port | null>(null);
|
|
||||||
const [vlans, setVlans] = useState<Vlan[]>([]);
|
const [vlans, setVlans] = useState<Vlan[]>([]);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [fetching, setFetching] = useState(false);
|
||||||
|
|
||||||
|
// Synchronously find the port from the global store
|
||||||
|
const port = useMemo(() => {
|
||||||
|
for (const rack of racks) {
|
||||||
|
for (const mod of rack.modules) {
|
||||||
|
const found = mod.ports.find((p) => p.id === portId);
|
||||||
|
if (found) return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}, [racks, portId]);
|
||||||
|
|
||||||
|
// Form state
|
||||||
const [label, setLabel] = useState('');
|
const [label, setLabel] = useState('');
|
||||||
const [mode, setMode] = useState<VlanMode>('ACCESS');
|
const [mode, setMode] = useState<VlanMode>('ACCESS');
|
||||||
const [nativeVlanId, setNativeVlanId] = useState<string>('');
|
const [nativeVlanId, setNativeVlanId] = useState<string>('');
|
||||||
const [taggedVlanIds, setTaggedVlanIds] = useState<string[]>([]);
|
const [taggedVlanIds, setTaggedVlanIds] = useState<string[]>([]);
|
||||||
const [notes, setNotes] = useState('');
|
const [notes, setNotes] = useState('');
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [fetching, setFetching] = useState(false);
|
|
||||||
// Quick-create VLAN
|
// Quick-create VLAN
|
||||||
const [newVlanId, setNewVlanId] = useState('');
|
const [newVlanId, setNewVlanId] = useState('');
|
||||||
const [newVlanName, setNewVlanName] = useState('');
|
const [newVlanName, setNewVlanName] = useState('');
|
||||||
const [newVlanColor, setNewVlanColor] = useState('#3b82f6');
|
const [newVlanColor, setNewVlanColor] = useState('#3b82f6');
|
||||||
const [creatingVlan, setCreatingVlan] = useState(false);
|
const [creatingVlan, setCreatingVlan] = useState(false);
|
||||||
|
|
||||||
// Find the port from store
|
// Reset form state when port is found or changed
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) return;
|
if (port && open) {
|
||||||
let found: Port | undefined;
|
setLabel(port.label ?? '');
|
||||||
for (const rack of racks) {
|
setMode(port.mode);
|
||||||
for (const mod of rack.modules) {
|
setNativeVlanId(port.nativeVlan?.toString() ?? '');
|
||||||
found = mod.ports.find((p) => p.id === portId);
|
setTaggedVlanIds(port.vlans.filter((v) => v.tagged).map((v) => v.vlanId));
|
||||||
if (found) break;
|
setNotes(port.notes ?? '');
|
||||||
}
|
}
|
||||||
if (found) break;
|
}, [port, open]);
|
||||||
}
|
|
||||||
if (found) {
|
|
||||||
setPort(found);
|
|
||||||
setLabel(found.label ?? '');
|
|
||||||
setMode(found.mode);
|
|
||||||
setNativeVlanId(found.nativeVlan?.toString() ?? '');
|
|
||||||
setTaggedVlanIds(found.vlans.filter((v) => v.tagged).map((v) => v.vlanId));
|
|
||||||
setNotes(found.notes ?? '');
|
|
||||||
}
|
|
||||||
}, [open, portId, racks]);
|
|
||||||
|
|
||||||
// Load VLAN list
|
// Load VLAN list
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -125,7 +128,6 @@ export function PortConfigModal({ portId, open, onClose }: PortConfigModalProps)
|
|||||||
|
|
||||||
if (!port) return null;
|
if (!port) return null;
|
||||||
|
|
||||||
const { deleteConnection } = useRackStore();
|
|
||||||
const connections = [...(port.sourceConnections || []), ...(port.targetConnections || [])];
|
const connections = [...(port.sourceConnections || []), ...(port.targetConnections || [])];
|
||||||
|
|
||||||
async function handleDisconnect(connId: string) {
|
async function handleDisconnect(connId: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user