refactor: fixed unsafe roles dialog and hook logic, added tests
This commit is contained in:
@@ -1,88 +1,91 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { UnsafeRolesDialog } from '@components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.tsx';
|
||||
import { useUnsafeRoles } from '@components/Dialog/UnsafeRolesDialog/useUnsafeRoles.ts';
|
||||
// deno-lint-ignore-file
|
||||
import { render, screen, fireEvent } from "@testing-library/react";
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import { UnsafeRolesDialog } from "@components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.tsx";
|
||||
import { eventBus } from "@core/utils/eventBus.ts";
|
||||
import { DeviceWrapper } from "@app/DeviceWrapper.tsx";
|
||||
|
||||
vi.mock('@components/Dialog/UnsafeRolesDialog/useUnsafeRoles', () => ({
|
||||
useUnsafeRoles: vi.fn()
|
||||
}));
|
||||
describe("UnsafeRolesDialog", () => {
|
||||
const mockDevice = {
|
||||
setDialogOpen: vi.fn(),
|
||||
};
|
||||
|
||||
describe('UnsafeRolesDialog', () => {
|
||||
const getConfirmStateMock = vi.fn();
|
||||
const toggleConfirmStateMock = vi.fn();
|
||||
const handleCloseDialogMock = vi.fn();
|
||||
const onOpenChangeMock = vi.fn();
|
||||
const renderWithDeviceContext = (ui: any) => {
|
||||
return render(
|
||||
<DeviceWrapper device={mockDevice}>
|
||||
{ui}
|
||||
</DeviceWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
it("renders the dialog when open is true", () => {
|
||||
renderWithDeviceContext(<UnsafeRolesDialog open={true} onOpenChange={vi.fn()} />);
|
||||
|
||||
getConfirmStateMock.mockReturnValue(false);
|
||||
const dialog = screen.getByRole('dialog');
|
||||
expect(dialog).toBeInTheDocument();
|
||||
|
||||
(useUnsafeRoles as any).mockReturnValue({
|
||||
getConfirmState: getConfirmStateMock,
|
||||
toggleConfirmState: toggleConfirmStateMock,
|
||||
handleCloseDialog: handleCloseDialogMock
|
||||
});
|
||||
expect(screen.getByText(/I have read the/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/understand the implications/i)).toBeInTheDocument();
|
||||
|
||||
const links = screen.getAllByRole('link');
|
||||
expect(links).toHaveLength(2);
|
||||
expect(links[0]).toHaveTextContent('Device Role Documentation');
|
||||
expect(links[1]).toHaveTextContent('Choosing The Right Device Role');
|
||||
});
|
||||
|
||||
it('should not render when open is false', () => {
|
||||
render(<UnsafeRolesDialog open={false} onOpenChange={onOpenChangeMock} />);
|
||||
it("displays the correct links", () => {
|
||||
renderWithDeviceContext(<UnsafeRolesDialog open={true} onOpenChange={vi.fn()} />);
|
||||
|
||||
expect(screen.queryByTestId('dialog')).not.toBeInTheDocument();
|
||||
const docLink = screen.getByRole("link", { name: /Device Role Documentation/i });
|
||||
const blogLink = screen.getByRole("link", { name: /Choosing The Right Device Role/i });
|
||||
|
||||
expect(docLink).toHaveAttribute("href", "https://meshtastic.org/docs/configuration/radio/device/");
|
||||
expect(blogLink).toHaveAttribute("href", "https://meshtastic.org/blog/choosing-the-right-device-role/");
|
||||
});
|
||||
|
||||
it('should render when open is true', () => {
|
||||
render(<UnsafeRolesDialog open={true} onOpenChange={onOpenChangeMock} />);
|
||||
it("does not allow confirmation until checkbox is checked", () => {
|
||||
renderWithDeviceContext(<UnsafeRolesDialog open={true} onOpenChange={vi.fn()} />);
|
||||
|
||||
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
||||
expect(screen.getByRole('heading')).toBeInTheDocument();
|
||||
expect(screen.getByText('Are you sure?')).toBeInTheDocument();
|
||||
expect(screen.getAllByRole('link')).length(2);
|
||||
expect(screen.getByRole('checkbox')).toBeInTheDocument();
|
||||
expect(screen.getByText('Yes, I know what I\'m doing')).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /dismiss/i })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /confirm/i })).toBeInTheDocument();
|
||||
const confirmButton = screen.getByRole("button", { name: /confirm/i });
|
||||
|
||||
expect(confirmButton).toBeDisabled();
|
||||
|
||||
const checkbox = screen.getByRole("checkbox");
|
||||
fireEvent.click(checkbox);
|
||||
|
||||
expect(confirmButton).toBeEnabled();
|
||||
});
|
||||
|
||||
it('should have disabled confirm button when checkbox is unchecked', () => {
|
||||
getConfirmStateMock.mockReturnValue(false);
|
||||
it("emits the correct event when closing via close button", () => {
|
||||
const eventSpy = vi.spyOn(eventBus, "emit");
|
||||
renderWithDeviceContext(<UnsafeRolesDialog open={true} onOpenChange={vi.fn()} />);
|
||||
|
||||
render(<UnsafeRolesDialog open={true} onOpenChange={onOpenChangeMock} />);
|
||||
const dismissButton = screen.getByRole("button", { name: /close/i });
|
||||
fireEvent.click(dismissButton);
|
||||
|
||||
expect(screen.getByRole('button', { name: /confirm/i })).toBeDisabled();
|
||||
expect(eventSpy).toHaveBeenCalledWith("dialog:unsafeRoles", { action: "dismiss" });
|
||||
});
|
||||
|
||||
it('should have enabled confirm button when checkbox is checked', () => {
|
||||
getConfirmStateMock.mockReturnValue(true);
|
||||
it("emits the correct event when dismissing", () => {
|
||||
const eventSpy = vi.spyOn(eventBus, "emit");
|
||||
renderWithDeviceContext(<UnsafeRolesDialog open={true} onOpenChange={vi.fn()} />);
|
||||
|
||||
render(<UnsafeRolesDialog open={true} onOpenChange={onOpenChangeMock} />);
|
||||
const dismissButton = screen.getByRole("button", { name: /dismiss/i });
|
||||
fireEvent.click(dismissButton);
|
||||
|
||||
expect(screen.getByRole('button', { name: /confirm/i })).not.toBeDisabled();
|
||||
expect(eventSpy).toHaveBeenCalledWith("dialog:unsafeRoles", { action: "dismiss" });
|
||||
});
|
||||
|
||||
it('should call toggleConfirmState when checkbox is clicked', () => {
|
||||
render(<UnsafeRolesDialog open={true} onOpenChange={onOpenChangeMock} />);
|
||||
it("emits the correct event when confirming", () => {
|
||||
const eventSpy = vi.spyOn(eventBus, "emit");
|
||||
renderWithDeviceContext(<UnsafeRolesDialog open={true} onOpenChange={vi.fn()} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('checkbox'));
|
||||
const checkbox = screen.getByRole("checkbox");
|
||||
const confirmButton = screen.getByRole("button", { name: /confirm/i });
|
||||
|
||||
expect(toggleConfirmStateMock).toHaveBeenCalledTimes(1);
|
||||
fireEvent.click(checkbox);
|
||||
fireEvent.click(confirmButton);
|
||||
|
||||
expect(eventSpy).toHaveBeenCalledWith("dialog:unsafeRoles", { action: "confirm" });
|
||||
});
|
||||
|
||||
it('should call handleCloseDialog with "dismiss" when dismiss button is clicked', () => {
|
||||
render(<UnsafeRolesDialog open={true} onOpenChange={onOpenChangeMock} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /dismiss/i }));
|
||||
|
||||
expect(handleCloseDialogMock).toHaveBeenCalledWith('dismiss');
|
||||
});
|
||||
|
||||
it('should call handleCloseDialog with "confirm" when confirm button is clicked', () => {
|
||||
getConfirmStateMock.mockReturnValue(true);
|
||||
|
||||
render(<UnsafeRolesDialog open={true} onOpenChange={onOpenChangeMock} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /confirm/i }));
|
||||
|
||||
expect(handleCloseDialogMock).toHaveBeenCalledWith("confirm");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
@@ -7,10 +8,11 @@ import {
|
||||
DialogTitle,
|
||||
} from "@components/UI/Dialog.tsx";
|
||||
import { Link } from "@components/UI/Typography/Link.tsx";
|
||||
import { Checkbox } from "../../UI/Checkbox/index.tsx";
|
||||
import { Label } from "@components/UI/Label.tsx";
|
||||
import { Checkbox } from "@components/UI/Checkbox/index.tsx";
|
||||
import { Button } from "@components/UI/Button.tsx";
|
||||
import { useUnsafeRoles } from "@components/Dialog/UnsafeRolesDialog/useUnsafeRoles.ts";
|
||||
import { useDevice } from "@core/stores/deviceStore.ts";
|
||||
import { useState } from "react";
|
||||
import { eventBus } from "@core/utils/eventBus.ts";
|
||||
|
||||
export interface RouterRoleDialogProps {
|
||||
open: boolean;
|
||||
@@ -18,34 +20,52 @@ export interface RouterRoleDialogProps {
|
||||
}
|
||||
|
||||
export const UnsafeRolesDialog = ({ open, onOpenChange }: RouterRoleDialogProps) => {
|
||||
const { getConfirmState, toggleConfirmState, handleCloseDialog } = useUnsafeRoles();
|
||||
const [confirmState, setConfirmState] = useState(false);
|
||||
const { setDialogOpen } = useDevice();
|
||||
|
||||
const deivceRoleLink = "https://meshtastic.org/docs/configuration/radio/device/";
|
||||
const deviceRoleLink = "https://meshtastic.org/docs/configuration/radio/device/";
|
||||
const choosingTheRightDeviceRoleLink = "https://meshtastic.org/blog/choosing-the-right-device-role/";
|
||||
|
||||
const handleCloseDialog = (action: 'confirm' | 'dismiss') => {
|
||||
setDialogOpen('unsafeRoles', false);
|
||||
setConfirmState(false);
|
||||
eventBus.emit('dialog:unsafeRoles', { action });
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="max-w-8 flex flex-col">
|
||||
<DialogClose onClick={() => handleCloseDialog('dismiss')} />
|
||||
<DialogHeader>
|
||||
<DialogTitle>Are you sure?</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogDescription className="text-md">
|
||||
I have read the <Link href={deivceRoleLink} className="">Device Role Documentation</Link>{" "}
|
||||
I have read the <Link href={deviceRoleLink} className="">Device Role Documentation</Link>{" "}
|
||||
and the blog post about <Link href={choosingTheRightDeviceRoleLink}>Choosing The Right Device Role</Link> and understand the implications of changing the role.
|
||||
</DialogDescription>
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox id="routerRole" checked={getConfirmState()} onChange={toggleConfirmState}>
|
||||
<Checkbox
|
||||
id="routerRole"
|
||||
checked={confirmState}
|
||||
onChange={() => setConfirmState(!confirmState)}
|
||||
>
|
||||
Yes, I know what I'm doing
|
||||
</Checkbox>
|
||||
</div>
|
||||
<DialogFooter className="mt-6">
|
||||
<Button variant="default" name="dismiss" onClick={() => handleCloseDialog("dismiss")}>
|
||||
Dismiss
|
||||
<Button
|
||||
variant="default"
|
||||
name="dismiss"
|
||||
onClick={() => handleCloseDialog('dismiss')}> Dismiss
|
||||
</Button>
|
||||
<Button variant="default" name="confirm" disabled={!getConfirmState()} onClick={() => handleCloseDialog("confirm")}>
|
||||
Confirm
|
||||
<Button
|
||||
variant="default"
|
||||
name="confirm"
|
||||
disabled={!confirmState}
|
||||
onClick={() => handleCloseDialog('confirm')}> Confirm
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</Dialog >
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { renderHook, act } from '@testing-library/react';
|
||||
import { useUnsafeRoles } from './useUnsafeRoles.ts';
|
||||
import { useDevice } from '@core/stores/deviceStore.ts';
|
||||
import useLocalStorage from '@core/hooks/useLocalStorage.ts';
|
||||
|
||||
vi.mock('@core/stores/deviceStore', () => ({
|
||||
useDevice: vi.fn()
|
||||
}));
|
||||
|
||||
vi.mock('@core/hooks/useLocalStorage', () => {
|
||||
return {
|
||||
default: vi.fn()
|
||||
};
|
||||
});
|
||||
|
||||
describe('useUnsafeRoles', () => {
|
||||
const setDialogOpenMock = vi.fn();
|
||||
const setAgreedToUnsafeRolesMock = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
|
||||
(useDevice as any).mockReturnValue({
|
||||
setDialogOpen: setDialogOpenMock
|
||||
});
|
||||
|
||||
(useLocalStorage as any).mockReturnValue([
|
||||
false,
|
||||
setAgreedToUnsafeRolesMock
|
||||
]);
|
||||
});
|
||||
|
||||
it('should initialize with correct default values', () => {
|
||||
const { result } = renderHook(() => useUnsafeRoles());
|
||||
|
||||
expect(result.current.agreedToUnSafeRoles).toBe(false);
|
||||
expect(result.current.getConfirmState()).toBe(false);
|
||||
});
|
||||
|
||||
it('should toggle confirm state correctly', () => {
|
||||
const { result } = renderHook(() => useUnsafeRoles());
|
||||
|
||||
act(() => {
|
||||
result.current.toggleConfirmState();
|
||||
});
|
||||
|
||||
expect(result.current.getConfirmState()).toBe(true);
|
||||
|
||||
act(() => {
|
||||
result.current.toggleConfirmState();
|
||||
});
|
||||
|
||||
expect(result.current.getConfirmState()).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle dialog close with dismiss state', () => {
|
||||
const { result } = renderHook(() => useUnsafeRoles());
|
||||
|
||||
act(() => {
|
||||
result.current.handleCloseDialog('dismiss');
|
||||
});
|
||||
|
||||
expect(setAgreedToUnsafeRolesMock).toHaveBeenCalledWith(false);
|
||||
expect(setDialogOpenMock).toHaveBeenCalledWith('unsafeRoles', false);
|
||||
});
|
||||
|
||||
it('should handle dialog close with confirm state', () => {
|
||||
const { result } = renderHook(() => useUnsafeRoles());
|
||||
|
||||
act(() => {
|
||||
result.current.handleCloseDialog('confirm');
|
||||
});
|
||||
|
||||
expect(setAgreedToUnsafeRolesMock).toHaveBeenCalledWith(true);
|
||||
expect(setDialogOpenMock).toHaveBeenCalledWith('unsafeRoles', false);
|
||||
});
|
||||
|
||||
it('should maintain state consistency across multiple operations', () => {
|
||||
const { result } = renderHook(() => useUnsafeRoles());
|
||||
|
||||
act(() => {
|
||||
result.current.toggleConfirmState();
|
||||
});
|
||||
expect(result.current.getConfirmState()).toBe(true);
|
||||
|
||||
act(() => {
|
||||
result.current.handleCloseDialog('confirm');
|
||||
});
|
||||
|
||||
expect(result.current.getConfirmState()).toBe(false);
|
||||
expect(setAgreedToUnsafeRolesMock).toHaveBeenCalledWith(true);
|
||||
|
||||
(useLocalStorage as any).mockReturnValue([
|
||||
true,
|
||||
setAgreedToUnsafeRolesMock
|
||||
]);
|
||||
|
||||
const { result: newResult } = renderHook(() => useUnsafeRoles());
|
||||
expect(newResult.current.agreedToUnSafeRoles).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -1,40 +0,0 @@
|
||||
import { useState, useCallback } from "react";
|
||||
import { useDevice } from "@core/stores/deviceStore.ts";
|
||||
import useLocalStorage from "@core/hooks/useLocalStorage.ts";
|
||||
|
||||
export const useUnsafeRoles = () => {
|
||||
const [agreedToUnSafeRoles, setAgreedToUnsafeRoles] = useLocalStorage("agreeToUnsafeRole", false);
|
||||
const [_confirmState, _setConfirmState] = useState(false);
|
||||
const { setDialogOpen } = useDevice();
|
||||
|
||||
const toggleConfirmState = useCallback(() => {
|
||||
setConfirmState(!_confirmState);
|
||||
}, [_confirmState]);
|
||||
|
||||
const setConfirmState = useCallback((state: boolean) => {
|
||||
_setConfirmState(state);
|
||||
}, [_setConfirmState]);
|
||||
|
||||
const getConfirmState = useCallback(() => {
|
||||
return _confirmState;
|
||||
}, [_confirmState]);
|
||||
|
||||
const handleCloseDialog = useCallback((closeState: "dismiss" | "confirm") => {
|
||||
if (closeState === "dismiss") {
|
||||
setAgreedToUnsafeRoles(false);
|
||||
setConfirmState(false);
|
||||
}
|
||||
if (closeState === "confirm") {
|
||||
setAgreedToUnsafeRoles(true);
|
||||
setConfirmState(false);
|
||||
}
|
||||
setDialogOpen("unsafeRoles", false);
|
||||
}, [setDialogOpen, setAgreedToUnsafeRoles]);
|
||||
|
||||
return {
|
||||
getConfirmState,
|
||||
toggleConfirmState,
|
||||
handleCloseDialog,
|
||||
agreedToUnSafeRoles
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,117 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach, Mock } from 'vitest';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useUnsafeRolesDialog, UNSAFE_ROLES } from "@components/Dialog/UnsafeRolesDialog/useUnsafeRolesDialog";
|
||||
import { eventBus } from "@core/utils/eventBus";
|
||||
|
||||
vi.mock('@core/utils/eventBus', () => ({
|
||||
eventBus: {
|
||||
on: vi.fn(),
|
||||
off: vi.fn(),
|
||||
emit: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const mockDevice = {
|
||||
setDialogOpen: vi.fn(),
|
||||
};
|
||||
|
||||
vi.mock('@core/stores/deviceStore', () => ({
|
||||
useDevice: () => ({
|
||||
setDialogOpen: mockDevice.setDialogOpen,
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('useUnsafeRolesDialog', () => {
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
const renderUnsafeRolesHook = () => {
|
||||
return renderHook(() => useUnsafeRolesDialog());
|
||||
};
|
||||
|
||||
describe('handleCloseDialog', () => {
|
||||
it('should call setDialogOpen with correct parameters when dialog is closed', () => {
|
||||
const { result } = renderUnsafeRolesHook();
|
||||
|
||||
result.current.handleCloseDialog();
|
||||
|
||||
expect(mockDevice.setDialogOpen).toHaveBeenCalledWith('unsafeRoles', false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateRoleSelection', () => {
|
||||
it('should resolve with true for safe roles without opening dialog', async () => {
|
||||
const { result } = renderUnsafeRolesHook();
|
||||
const safeRole = 'SAFE_ROLE';
|
||||
|
||||
const validationResult = await result.current.validateRoleSelection(safeRole);
|
||||
|
||||
expect(validationResult).toBe(true);
|
||||
expect(mockDevice.setDialogOpen).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should open dialog for unsafe roles and resolve with true when confirmed', async () => {
|
||||
const { result } = renderUnsafeRolesHook();
|
||||
|
||||
const validationPromise = result.current.validateRoleSelection(UNSAFE_ROLES[0]);
|
||||
|
||||
expect(mockDevice.setDialogOpen).toHaveBeenCalledWith('unsafeRoles', true);
|
||||
expect(eventBus.on).toHaveBeenCalledWith('dialog:unsafeRoles', expect.any(Function));
|
||||
|
||||
const onHandler = (eventBus.on as Mock).mock.calls[0][1];
|
||||
onHandler({ action: 'confirm' });
|
||||
const validationResult = await validationPromise;
|
||||
|
||||
expect(validationResult).toBe(true);
|
||||
expect(eventBus.off).toHaveBeenCalledWith('dialog:unsafeRoles', onHandler);
|
||||
});
|
||||
|
||||
it('should resolve with false when user dismisses the dialog', async () => {
|
||||
const { result } = renderUnsafeRolesHook();
|
||||
const validationPromise = result.current.validateRoleSelection(UNSAFE_ROLES[0]);
|
||||
const onHandler = (eventBus.on as Mock).mock.calls[0][1];
|
||||
onHandler({ action: 'dismiss' });
|
||||
|
||||
const validationResult = await validationPromise;
|
||||
expect(validationResult).toBe(false);
|
||||
expect(eventBus.off).toHaveBeenCalledWith('dialog:unsafeRoles', onHandler);
|
||||
});
|
||||
|
||||
it('should clean up event listener after response', async () => {
|
||||
const { result } = renderUnsafeRolesHook();
|
||||
|
||||
const validationPromise = result.current.validateRoleSelection(UNSAFE_ROLES[1]);
|
||||
const onHandler = (eventBus.on as Mock).mock.calls[0][1];
|
||||
|
||||
onHandler({ action: 'confirm' });
|
||||
await validationPromise;
|
||||
|
||||
expect(eventBus.off).toHaveBeenCalledWith('dialog:unsafeRoles', onHandler);
|
||||
});
|
||||
});
|
||||
|
||||
it('should work with all unsafe roles', async () => {
|
||||
const { result } = renderUnsafeRolesHook();
|
||||
|
||||
for (const unsafeRole of UNSAFE_ROLES) {
|
||||
mockDevice.setDialogOpen.mockClear();
|
||||
(eventBus.on as Mock).mockClear();
|
||||
|
||||
const validationPromise = result.current.validateRoleSelection(unsafeRole);
|
||||
|
||||
expect(mockDevice.setDialogOpen).toHaveBeenCalledWith('unsafeRoles', true);
|
||||
|
||||
const onHandler = (eventBus.on as Mock).mock.calls[0][1];
|
||||
onHandler({ action: 'confirm' });
|
||||
|
||||
const validationResult = await validationPromise;
|
||||
|
||||
expect(validationResult).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
import { useCallback } from "react";
|
||||
import { eventBus } from "@core/utils/eventBus.ts";
|
||||
import { useDevice } from "@core/stores/deviceStore.ts";
|
||||
|
||||
export const UNSAFE_ROLES = ["ROUTER", "REPEATER"];
|
||||
export type UnsafeRole = typeof UNSAFE_ROLES[number];
|
||||
|
||||
export const useUnsafeRolesDialog = () => {
|
||||
const { setDialogOpen } = useDevice();
|
||||
|
||||
const handleCloseDialog = useCallback(() => {
|
||||
setDialogOpen("unsafeRoles", false);
|
||||
}, [setDialogOpen]);
|
||||
|
||||
const validateRoleSelection = useCallback(
|
||||
(newRoleKey: string): Promise<boolean> => {
|
||||
if (!UNSAFE_ROLES.includes(newRoleKey as UnsafeRole)) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
setDialogOpen("unsafeRoles", true);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const handleResponse = ({ action }: { action: "confirm" | "dismiss" }) => {
|
||||
eventBus.off("dialog:unsafeRoles", handleResponse);
|
||||
resolve(action === "confirm");
|
||||
};
|
||||
|
||||
eventBus.on("dialog:unsafeRoles", handleResponse);
|
||||
});
|
||||
},
|
||||
[setDialogOpen]
|
||||
);
|
||||
|
||||
return {
|
||||
handleCloseDialog,
|
||||
validateRoleSelection,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user