Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions cypress/components/DropdownMenu.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,67 @@ describe('DropdownMenu Component', () => {
cy.get('button').click();
cy.get('[data-testid="test-content"]').should('be.visible');
});

it('persists state to localStorage when id is provided', () => {
const testId = 'test-dropdown-id';

// Clear storage before test
window.localStorage.clear();

// Spy on localStorage
cy.spy(window.localStorage, 'setItem').as('setItem');
cy.spy(window.localStorage, 'getItem').as('getItem');

// 1. Mount and open
cy.mount(
<DropdownMenu
label='Persist Test'
icon={mockIcon}
id={testId}
testMode={true}
>
{mockChildren}
</DropdownMenu>,
);

// Initially closed
cy.get('[data-testid="test-content"]').should('not.exist');

// Open it
cy.get('button').click();
cy.get('[data-testid="test-content"]').should('be.visible');

// Verify setItem was called
cy.get('@setItem').should(
'have.been.calledWith',
`sidebar_open_${testId}`,
'true',
);

// 2. Remount (simulate page reload)
cy.mount(
<DropdownMenu
label='Persist Test'
icon={mockIcon}
id={testId}
testMode={true}
>
{mockChildren}
</DropdownMenu>,
);

// Verify getItem was called
cy.get('@getItem').should('have.been.calledWith', `sidebar_open_${testId}`);

// Should be open immediately because of localStorage
cy.get('[data-testid="test-content"]').should('be.visible');

// 3. Close it
cy.get('button').click();
cy.get('@setItem').should(
'have.been.calledWith',
`sidebar_open_${testId}`,
'false',
);
});
});
1 change: 1 addition & 0 deletions pages/tools/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export default function Sidebar({
label={label}
icon={<IconComponent />}
count={checkedValues.length}
id={accessorKey}
>
{filterCriteria[accessorKey as FilterCriteriaFields]
?.map(String)
Expand Down
26 changes: 20 additions & 6 deletions pages/tools/components/ui/DropdownMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/* eslint-disable linebreak-style */
/* eslint-disable react-hooks/rules-of-hooks */
/* eslint-disable linebreak-style */
import { useRouter } from 'next/router';
import React, {
type ReactElement,
type ReactNode,
useEffect,
useState,
useRef,
} from 'react';
import {
Collapsible,
Expand All @@ -20,21 +20,35 @@ interface DropdownMenuProps {
icon: ReactElement;
count?: number;
testMode?: boolean;
id?: string;
}

export default function DropdownMenu({
children,
label,
icon,
count = 0,
id,
}: DropdownMenuProps) {
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const router = useRouter();

const isFirstRun = useRef(true);
useEffect(() => {
setIsDropdownOpen(false);
}, [router]);

if (id) {
const storedState = localStorage.getItem(`sidebar_open_${id}`);
if (storedState) {
setIsDropdownOpen(storedState === 'true');
}
}
}, [id]);
useEffect(() => {
if (id) {
if (isFirstRun.current) {
isFirstRun.current = false;
return;
}
localStorage.setItem(`sidebar_open_${id}`, String(isDropdownOpen));
}
}, [id, isDropdownOpen]);
return (
<div className='my-2 bg-slate-200 dark:bg-slate-900 p-2 rounded cursor-pointer transition-all duration-200 group'>
<Collapsible open={isDropdownOpen} onOpenChange={setIsDropdownOpen}>
Expand Down
Loading