fix(sidebar): unfreeze view after scan triggers history panel
forceView prop was overriding local activeView on every render. Once parent set sidebarForceView='history' after starting a scan, it never cleared, so clicks on other nav items were ignored. Treat forceView as a one-shot trigger via the previous-prop pattern; user clicks afterward control view.
This commit is contained in:
@@ -43,13 +43,19 @@ interface SidebarProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function Sidebar({ onAddNode, onAddGroupRect, onScan, onSave, onNodeApproved, forceView, highlightPendingId }: SidebarProps) {
|
export function Sidebar({ onAddNode, onAddGroupRect, onScan, onSave, onNodeApproved, forceView, highlightPendingId }: SidebarProps) {
|
||||||
const [_collapsed, setCollapsed] = useState(false)
|
const [collapsed, setCollapsed] = useState(false)
|
||||||
const [_activeView, setActiveView] = useState<SidebarView>('canvas')
|
const [activeView, setActiveView] = useState<SidebarView>(forceView ?? 'canvas')
|
||||||
|
const [prevForceView, setPrevForceView] = useState(forceView)
|
||||||
const logout = useAuthStore((s) => s.logout)
|
const logout = useAuthStore((s) => s.logout)
|
||||||
|
|
||||||
// When forceView is set, override local state without useEffect
|
// forceView acts as a one-shot trigger from parent; user clicks afterwards still control view.
|
||||||
const collapsed = forceView ? false : _collapsed
|
if (forceView !== prevForceView) {
|
||||||
const activeView = forceView ?? _activeView
|
setPrevForceView(forceView)
|
||||||
|
if (forceView) {
|
||||||
|
setActiveView(forceView)
|
||||||
|
setCollapsed(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const { nodes, hasUnsavedChanges, hideIp, toggleHideIp } = useCanvasStore()
|
const { nodes, hasUnsavedChanges, hideIp, toggleHideIp } = useCanvasStore()
|
||||||
|
|
||||||
|
|||||||
@@ -267,6 +267,18 @@ describe('Sidebar', () => {
|
|||||||
await waitFor(() => expect(screen.getByText('No scans yet')).toBeInTheDocument())
|
await waitFor(() => expect(screen.getByText('No scans yet')).toBeInTheDocument())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Regression: forceView used to override local state on every render, freezing
|
||||||
|
// the sidebar on whichever view the parent forced (e.g. 'history' after a scan).
|
||||||
|
it('allows switching views after forceView is set by parent', async () => {
|
||||||
|
const { rerender } = render(<Sidebar {...defaultProps} forceView="history" />)
|
||||||
|
await waitFor(() => expect(screen.getByText('No scans yet')).toBeInTheDocument())
|
||||||
|
// Parent keeps forceView as 'history'; user clicks another nav item.
|
||||||
|
rerender(<Sidebar {...defaultProps} forceView="history" />)
|
||||||
|
fireEvent.click(screen.getByText('Pending Devices'))
|
||||||
|
await waitFor(() => expect(screen.getByText('No pending devices')).toBeInTheDocument())
|
||||||
|
expect(screen.queryByText('No scans yet')).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
it('toggles Settings panel on Settings click', async () => {
|
it('toggles Settings panel on Settings click', async () => {
|
||||||
render(<Sidebar {...defaultProps} />)
|
render(<Sidebar {...defaultProps} />)
|
||||||
fireEvent.click(screen.getByText('Settings'))
|
fireEvent.click(screen.getByText('Settings'))
|
||||||
|
|||||||
Reference in New Issue
Block a user