Cleanup page template
This commit is contained in:
@@ -2,11 +2,11 @@ import React from 'react';
|
||||
|
||||
type DefaultDivProps = JSX.IntrinsicElements['div'];
|
||||
|
||||
interface SidebarItemProps extends DefaultDivProps {
|
||||
export interface SidebarItemProps extends DefaultDivProps {
|
||||
title: string;
|
||||
description: string;
|
||||
selected: boolean;
|
||||
icon: JSX.Element;
|
||||
selected?: boolean;
|
||||
}
|
||||
|
||||
export const SidebarItem = ({
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import React from 'react';
|
||||
|
||||
import { FiXCircle } from 'react-icons/fi';
|
||||
|
||||
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
||||
import { useBreakpoint } from '@app/hooks/breakpoint';
|
||||
import { Drawer } from '@components/generic/Drawer';
|
||||
import { SidebarItem, SidebarItemProps } from '@components/generic/SidebarItem';
|
||||
import { Tab } from '@headlessui/react';
|
||||
|
||||
export interface PageLayoutProps {
|
||||
title: string;
|
||||
sidebarItems: SidebarItemProps[];
|
||||
panels: JSX.Element[];
|
||||
emptyMessage?: string;
|
||||
}
|
||||
|
||||
export const PageLayout = ({
|
||||
title,
|
||||
sidebarItems,
|
||||
panels,
|
||||
emptyMessage,
|
||||
}: PageLayoutProps): JSX.Element => {
|
||||
const [navOpen, setNavOpen] = React.useState(false);
|
||||
|
||||
const { breakpoint } = useBreakpoint();
|
||||
|
||||
return (
|
||||
<Tab.Group>
|
||||
<div className="relative flex w-full dark:text-white">
|
||||
<Drawer
|
||||
open={breakpoint === 'sm' ? navOpen : true}
|
||||
permenant={breakpoint !== 'sm'}
|
||||
onClose={(): void => {
|
||||
setNavOpen(!navOpen);
|
||||
}}
|
||||
>
|
||||
<Tab.List className="flex flex-col border-b divide-y divide-gray-300 dark:divide-gray-600 dark:border-gray-600">
|
||||
<div className="flex items-center justify-between m-8 mr-6 md:my-10">
|
||||
<div className="text-4xl font-extrabold leading-none tracking-tight">
|
||||
{title}
|
||||
</div>
|
||||
<div className="md:hidden">
|
||||
<IconButton
|
||||
icon={<FiXCircle className="w-5 h-5" />}
|
||||
onClick={(): void => {
|
||||
setNavOpen(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{!sidebarItems.length && (
|
||||
<span className="p-4 text-sm text-gray-400 dark:text-gray-600">
|
||||
{emptyMessage}
|
||||
</span>
|
||||
)}
|
||||
{sidebarItems.map((props, index) => (
|
||||
<Tab
|
||||
key={index}
|
||||
onClick={(): void => {
|
||||
setNavOpen(false);
|
||||
}}
|
||||
>
|
||||
{({ selected }): JSX.Element => (
|
||||
<SidebarItem {...props} selected={selected} />
|
||||
)}
|
||||
</Tab>
|
||||
))}
|
||||
</Tab.List>
|
||||
</Drawer>
|
||||
<div className="flex w-full">
|
||||
<Tab.Panels className="flex w-full">
|
||||
{panels.map((Panel, index) => (
|
||||
<Tab.Panel key={index} className="flex w-full">
|
||||
{React.cloneElement(Panel, {
|
||||
key: index,
|
||||
navOpen: navOpen,
|
||||
setNavOpen: setNavOpen,
|
||||
})}
|
||||
</Tab.Panel>
|
||||
))}
|
||||
</Tab.Panels>
|
||||
</div>
|
||||
</div>
|
||||
</Tab.Group>
|
||||
);
|
||||
};
|
||||
+24
-87
@@ -1,102 +1,39 @@
|
||||
import React from 'react';
|
||||
|
||||
import Avatar from 'boring-avatars';
|
||||
import { FiXCircle } from 'react-icons/fi';
|
||||
|
||||
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
||||
import { useBreakpoint } from '@app/hooks/breakpoint';
|
||||
import { PageLayout } from '@app/components/templates/PageLayout.jsx';
|
||||
import { useAppSelector } from '@app/hooks/redux';
|
||||
import { Drawer } from '@components/generic/Drawer';
|
||||
import { SidebarItem } from '@components/generic/SidebarItem';
|
||||
import { Tab } from '@headlessui/react';
|
||||
import { Protobuf } from '@meshtastic/meshtasticjs';
|
||||
|
||||
import { Node } from './Node';
|
||||
|
||||
export const Nodes = (): JSX.Element => {
|
||||
const [navOpen, setNavOpen] = React.useState(false);
|
||||
|
||||
const { breakpoint } = useBreakpoint();
|
||||
|
||||
const nodes = useAppSelector((state) => state.meshtastic.nodes);
|
||||
|
||||
return (
|
||||
<Tab.Group>
|
||||
<div className="relative flex w-full dark:text-white">
|
||||
<Drawer
|
||||
open={breakpoint === 'sm' ? navOpen : true}
|
||||
permenant={breakpoint !== 'sm'}
|
||||
onClose={(): void => {
|
||||
setNavOpen(!navOpen);
|
||||
}}
|
||||
>
|
||||
<Tab.List className="flex flex-col border-b divide-y divide-gray-300 dark:divide-gray-600 dark:border-gray-600">
|
||||
<div className="flex items-center justify-between m-8 mr-6 md:my-10">
|
||||
<div className="text-4xl font-extrabold leading-none tracking-tight">
|
||||
Nodes
|
||||
</div>
|
||||
<div className="md:hidden">
|
||||
<IconButton
|
||||
icon={<FiXCircle className="w-5 h-5" />}
|
||||
onClick={(): void => {
|
||||
setNavOpen(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!nodes.length && (
|
||||
<span className="p-4 text-sm text-gray-400 dark:text-gray-600">
|
||||
No nodes discovered yet...
|
||||
</span>
|
||||
)}
|
||||
|
||||
{nodes.map((node) => (
|
||||
<Tab
|
||||
onClick={(): void => {
|
||||
setNavOpen(false);
|
||||
}}
|
||||
key={node.num}
|
||||
>
|
||||
{({ selected }): JSX.Element => (
|
||||
<SidebarItem
|
||||
title={node.user?.longName ?? node.num.toString()}
|
||||
description={
|
||||
node.user?.hwModel
|
||||
? Protobuf.HardwareModel[node.user.hwModel]
|
||||
: 'Unknown Hardware'
|
||||
}
|
||||
selected={selected}
|
||||
icon={
|
||||
<Avatar
|
||||
size={30}
|
||||
name={node.user?.longName ?? node.num.toString()}
|
||||
variant="beam"
|
||||
colors={[
|
||||
'#213435',
|
||||
'#46685B',
|
||||
'#648A64',
|
||||
'#A6B985',
|
||||
'#E1E3AC',
|
||||
]}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
))}
|
||||
</Tab.List>
|
||||
</Drawer>
|
||||
<div className="w-full">
|
||||
<Tab.Panels className="h-full">
|
||||
{nodes.map((node) => (
|
||||
<Tab.Panel className="h-full" key={node.num}>
|
||||
<Node navOpen={navOpen} setNavOpen={setNavOpen} node={node} />
|
||||
</Tab.Panel>
|
||||
))}
|
||||
</Tab.Panels>
|
||||
</div>
|
||||
</div>
|
||||
</Tab.Group>
|
||||
<PageLayout
|
||||
title="Nodes"
|
||||
emptyMessage="No nodes discovered yet..."
|
||||
sidebarItems={nodes.map((node) => {
|
||||
return {
|
||||
title: node.user?.longName ?? node.num.toString(),
|
||||
description: node.user?.hwModel
|
||||
? Protobuf.HardwareModel[node.user.hwModel]
|
||||
: 'Unknown Hardware',
|
||||
icon: (
|
||||
<Avatar
|
||||
size={30}
|
||||
name={node.user?.longName ?? node.num.toString()}
|
||||
variant="beam"
|
||||
colors={['#213435', '#46685B', '#648A64', '#A6B985', '#E1E3AC']}
|
||||
/>
|
||||
),
|
||||
};
|
||||
})}
|
||||
panels={nodes.map((node, index) => (
|
||||
<Node key={index} node={node} />
|
||||
))}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -12,8 +12,8 @@ import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
||||
import type { Protobuf } from '@meshtastic/meshtasticjs';
|
||||
|
||||
export interface NodeProps {
|
||||
navOpen: boolean;
|
||||
setNavOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
navOpen?: boolean;
|
||||
setNavOpen?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
node: Protobuf.NodeInfo;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export const Node = ({ navOpen, setNavOpen, node }: NodeProps): JSX.Element => {
|
||||
<IconButton
|
||||
icon={<FiMenu className="w-5 h-5" />}
|
||||
onClick={(): void => {
|
||||
setNavOpen(!navOpen);
|
||||
setNavOpen && setNavOpen(!navOpen);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ import { useAppSelector } from '@app/hooks/redux';
|
||||
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
||||
|
||||
export interface RangeTestProps {
|
||||
navOpen: boolean;
|
||||
setNavOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
navOpen?: boolean;
|
||||
setNavOpen?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
interface IFile {
|
||||
name: string;
|
||||
@@ -58,7 +58,7 @@ export const Files = ({ navOpen, setNavOpen }: RangeTestProps): JSX.Element => {
|
||||
<IconButton
|
||||
icon={<FiMenu className="w-5 h-5" />}
|
||||
onClick={(): void => {
|
||||
setNavOpen(!navOpen);
|
||||
setNavOpen && setNavOpen(!navOpen);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
||||
+18
-75
@@ -1,86 +1,29 @@
|
||||
import React from 'react';
|
||||
|
||||
import { FiFileText, FiRss, FiXCircle } from 'react-icons/fi';
|
||||
import { FiFileText, FiRss } from 'react-icons/fi';
|
||||
|
||||
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
||||
import { useBreakpoint } from '@app/hooks/breakpoint';
|
||||
import { Drawer } from '@components/generic/Drawer';
|
||||
import { SidebarItem } from '@components/generic/SidebarItem';
|
||||
import { Tab } from '@headlessui/react';
|
||||
import { PageLayout } from '@app/components/templates/PageLayout.jsx';
|
||||
|
||||
import { Files } from './Files';
|
||||
import { RangeTest } from './RangeTest';
|
||||
|
||||
export const Plugins = (): JSX.Element => {
|
||||
const [navOpen, setNavOpen] = React.useState(false);
|
||||
|
||||
const { breakpoint } = useBreakpoint();
|
||||
|
||||
return (
|
||||
<Tab.Group>
|
||||
<div className="relative flex w-full dark:text-white">
|
||||
<Drawer
|
||||
open={breakpoint === 'sm' ? navOpen : true}
|
||||
permenant={breakpoint !== 'sm'}
|
||||
onClose={(): void => {
|
||||
setNavOpen(!navOpen);
|
||||
}}
|
||||
>
|
||||
<Tab.List className="flex flex-col border-b divide-y divide-gray-300 dark:divide-gray-600 dark:border-gray-600">
|
||||
<div className="flex items-center justify-between m-8 mr-6 md:my-10">
|
||||
<div className="text-4xl font-extrabold leading-none tracking-tight">
|
||||
Plugins
|
||||
</div>
|
||||
<div className="md:hidden">
|
||||
<IconButton
|
||||
icon={<FiXCircle className="w-5 h-5" />}
|
||||
onClick={(): void => {
|
||||
setNavOpen(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Tab
|
||||
onClick={(): void => {
|
||||
setNavOpen(false);
|
||||
}}
|
||||
>
|
||||
{({ selected }): JSX.Element => (
|
||||
<SidebarItem
|
||||
title="Range Test"
|
||||
description="Test the range of your Meshtastic node"
|
||||
selected={selected}
|
||||
icon={<FiRss className="flex-shrink-0 w-6 h-6" />}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
<Tab
|
||||
onClick={(): void => {
|
||||
setNavOpen(false);
|
||||
}}
|
||||
>
|
||||
{({ selected }): JSX.Element => (
|
||||
<SidebarItem
|
||||
title="File Browser"
|
||||
description="HTTP only file browser"
|
||||
selected={selected}
|
||||
icon={<FiFileText className="flex-shrink-0 w-6 h-6" />}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
</Tab.List>
|
||||
</Drawer>
|
||||
<div className="flex w-full">
|
||||
<Tab.Panels className="flex w-full">
|
||||
<Tab.Panel className="flex w-full">
|
||||
<RangeTest navOpen={navOpen} setNavOpen={setNavOpen} />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel className="flex w-full">
|
||||
<Files navOpen={navOpen} setNavOpen={setNavOpen} />
|
||||
</Tab.Panel>
|
||||
</Tab.Panels>
|
||||
</div>
|
||||
</div>
|
||||
</Tab.Group>
|
||||
<PageLayout
|
||||
title="Plugins"
|
||||
sidebarItems={[
|
||||
{
|
||||
title: 'Range Test',
|
||||
description: 'Test the range of your Meshtastic node',
|
||||
icon: <FiRss className="flex-shrink-0 w-6 h-6" />,
|
||||
},
|
||||
{
|
||||
title: 'File Browser',
|
||||
description: 'HTTP only file browser',
|
||||
icon: <FiFileText className="flex-shrink-0 w-6 h-6" />,
|
||||
},
|
||||
]}
|
||||
panels={[<RangeTest key={1} />, <Files key={2} />]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,8 +15,8 @@ import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
||||
import type { RadioConfig_UserPreferences } from '@meshtastic/meshtasticjs/dist/generated';
|
||||
|
||||
export interface RangeTestProps {
|
||||
navOpen: boolean;
|
||||
setNavOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
navOpen?: boolean;
|
||||
setNavOpen?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export const RangeTest = ({
|
||||
@@ -49,7 +49,7 @@ export const RangeTest = ({
|
||||
<IconButton
|
||||
icon={<FiMenu className="w-5 h-5" />}
|
||||
onClick={(): void => {
|
||||
setNavOpen(!navOpen);
|
||||
setNavOpen && setNavOpen(!navOpen);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ import { Button } from '@components/generic/Button';
|
||||
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
||||
|
||||
export interface ChannelsProps {
|
||||
navOpen: boolean;
|
||||
setNavOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
navOpen?: boolean;
|
||||
setNavOpen?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export const Channels = ({
|
||||
@@ -30,7 +30,7 @@ export const Channels = ({
|
||||
<IconButton
|
||||
icon={<FiMenu className="w-5 h-5" />}
|
||||
onClick={(): void => {
|
||||
setNavOpen(!navOpen);
|
||||
setNavOpen && setNavOpen(!navOpen);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ import type {
|
||||
} from '@meshtastic/meshtasticjs/dist/types';
|
||||
|
||||
export interface ConnectionProps {
|
||||
navOpen: boolean;
|
||||
setNavOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
navOpen?: boolean;
|
||||
setNavOpen?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
enum connType {
|
||||
@@ -125,7 +125,7 @@ export const Connection = ({
|
||||
<IconButton
|
||||
icon={<FiMenu className="w-5 h-5" />}
|
||||
onClick={(): void => {
|
||||
setNavOpen(!navOpen);
|
||||
setNavOpen && setNavOpen(!navOpen);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
@@ -142,8 +142,8 @@ export const Connection = ({
|
||||
}
|
||||
>
|
||||
<Card
|
||||
title="Basic settings"
|
||||
description="Device name and user parameters"
|
||||
title="Connection Settings"
|
||||
description="HTTP, BLE and Serial Options"
|
||||
>
|
||||
<div className="w-full max-w-3xl p-10 md:max-w-xl">
|
||||
<form className="space-y-2" onSubmit={onSubmit}>
|
||||
|
||||
@@ -15,8 +15,8 @@ import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
||||
import { Protobuf } from '@meshtastic/meshtasticjs';
|
||||
|
||||
export interface DeviceProps {
|
||||
navOpen: boolean;
|
||||
setNavOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
navOpen?: boolean;
|
||||
setNavOpen?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export const Device = ({ navOpen, setNavOpen }: DeviceProps): JSX.Element => {
|
||||
@@ -46,7 +46,7 @@ export const Device = ({ navOpen, setNavOpen }: DeviceProps): JSX.Element => {
|
||||
<IconButton
|
||||
icon={<FiMenu className="w-5 h-5" />}
|
||||
onClick={(): void => {
|
||||
setNavOpen(!navOpen);
|
||||
setNavOpen && setNavOpen(!navOpen);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
||||
+38
-114
@@ -6,14 +6,9 @@ import {
|
||||
FiLink2,
|
||||
FiRss,
|
||||
FiSmartphone,
|
||||
FiXCircle,
|
||||
} from 'react-icons/fi';
|
||||
|
||||
import { IconButton } from '@app/components/generic/IconButton.jsx';
|
||||
import { useBreakpoint } from '@app/hooks/breakpoint';
|
||||
import { Drawer } from '@components/generic/Drawer';
|
||||
import { SidebarItem } from '@components/generic/SidebarItem';
|
||||
import { Tab } from '@headlessui/react';
|
||||
import { PageLayout } from '@app/components/templates/PageLayout.jsx';
|
||||
|
||||
import { Channels } from './Channels';
|
||||
import { Connection } from './Connection';
|
||||
@@ -22,114 +17,43 @@ import { Interface } from './Interface';
|
||||
import { Radio } from './Radio';
|
||||
|
||||
export const Settings = (): JSX.Element => {
|
||||
const [navOpen, setNavOpen] = React.useState(false);
|
||||
|
||||
const { breakpoint } = useBreakpoint();
|
||||
|
||||
return (
|
||||
<Tab.Group>
|
||||
<div className="relative flex w-full dark:text-white">
|
||||
<Drawer
|
||||
open={breakpoint === 'sm' ? navOpen : true}
|
||||
permenant={breakpoint !== 'sm'}
|
||||
onClose={(): void => {
|
||||
setNavOpen(!navOpen);
|
||||
}}
|
||||
>
|
||||
<Tab.List className="flex flex-col border-b divide-y divide-gray-300 dark:divide-gray-600 dark:border-gray-600">
|
||||
<div className="flex items-center justify-between m-8 mr-6 md:my-10">
|
||||
<div className="text-4xl font-extrabold leading-none tracking-tight">
|
||||
Settings
|
||||
</div>
|
||||
<div className="md:hidden">
|
||||
<IconButton
|
||||
icon={<FiXCircle className="w-5 h-5" />}
|
||||
onClick={(): void => {
|
||||
setNavOpen(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Tab
|
||||
onClick={(): void => {
|
||||
setNavOpen(false);
|
||||
}}
|
||||
>
|
||||
{({ selected }): JSX.Element => (
|
||||
<SidebarItem
|
||||
title="Connection"
|
||||
description="Method and peramaters for connecting to the device"
|
||||
selected={selected}
|
||||
icon={<FiLink2 className="flex-shrink-0 w-6 h-6" />}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
<Tab
|
||||
onClick={(): void => {
|
||||
setNavOpen(false);
|
||||
}}
|
||||
>
|
||||
{({ selected }): JSX.Element => (
|
||||
<SidebarItem
|
||||
title="Device"
|
||||
description="Device settings, such as device name and wifi settings"
|
||||
selected={selected}
|
||||
icon={<FiSmartphone className="flex-shrink-0 w-6 h-6" />}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
<Tab>
|
||||
{({ selected }): JSX.Element => (
|
||||
<SidebarItem
|
||||
title="Radio"
|
||||
description="Adjust radio power and frequency settings"
|
||||
selected={selected}
|
||||
icon={<FiRss className="flex-shrink-0 w-6 h-6" />}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
<Tab>
|
||||
{({ selected }): JSX.Element => (
|
||||
<SidebarItem
|
||||
title="Interface"
|
||||
description="Change language and other UI settings"
|
||||
selected={selected}
|
||||
icon={<FiLayout className="flex-shrink-0 w-6 h-6" />}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
<Tab>
|
||||
{({ selected }): JSX.Element => (
|
||||
<SidebarItem
|
||||
title="Channels"
|
||||
description="Manage channels"
|
||||
selected={selected}
|
||||
icon={<FiLayers className="flex-shrink-0 w-6 h-6" />}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
</Tab.List>
|
||||
</Drawer>
|
||||
<div className="flex w-full">
|
||||
<Tab.Panels className="flex w-full">
|
||||
<Tab.Panel className="flex w-full">
|
||||
<Connection navOpen={navOpen} setNavOpen={setNavOpen} />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel className="flex w-full">
|
||||
<Device navOpen={navOpen} setNavOpen={setNavOpen} />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel className="flex w-full">
|
||||
<Radio navOpen={navOpen} setNavOpen={setNavOpen} />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel className="flex w-full">
|
||||
<Interface navOpen={navOpen} setNavOpen={setNavOpen} />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel className="flex w-full">
|
||||
<Channels navOpen={navOpen} setNavOpen={setNavOpen} />
|
||||
</Tab.Panel>
|
||||
</Tab.Panels>
|
||||
</div>
|
||||
</div>
|
||||
</Tab.Group>
|
||||
<PageLayout
|
||||
title="Settings"
|
||||
sidebarItems={[
|
||||
{
|
||||
title: 'Connection',
|
||||
description: 'Method and peramaters for connecting to the device',
|
||||
icon: <FiLink2 className="flex-shrink-0 w-6 h-6" />,
|
||||
},
|
||||
{
|
||||
title: 'Device',
|
||||
description: 'Device settings, such as device name and wifi settings',
|
||||
icon: <FiSmartphone className="flex-shrink-0 w-6 h-6" />,
|
||||
},
|
||||
{
|
||||
title: 'Radio',
|
||||
description: 'Adjust radio power and frequency settings',
|
||||
icon: <FiRss className="flex-shrink-0 w-6 h-6" />,
|
||||
},
|
||||
{
|
||||
title: 'Interface',
|
||||
description: 'Change language and other UI settings',
|
||||
icon: <FiLayout className="flex-shrink-0 w-6 h-6" />,
|
||||
},
|
||||
{
|
||||
title: 'Channels',
|
||||
description: 'Manage channels',
|
||||
icon: <FiLayers className="flex-shrink-0 w-6 h-6" />,
|
||||
},
|
||||
]}
|
||||
panels={[
|
||||
<Connection key={1} />,
|
||||
<Device key={2} />,
|
||||
<Radio key={3} />,
|
||||
<Interface key={4} />,
|
||||
<Channels key={5} />,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -11,8 +11,8 @@ import { Button } from '@components/generic/Button';
|
||||
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
||||
|
||||
export interface InterfaceProps {
|
||||
navOpen: boolean;
|
||||
setNavOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
navOpen?: boolean;
|
||||
setNavOpen?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export const Interface = ({
|
||||
@@ -29,7 +29,7 @@ export const Interface = ({
|
||||
<Button
|
||||
icon={<FiMenu className="w-5 h-5" />}
|
||||
onClick={(): void => {
|
||||
setNavOpen(!navOpen);
|
||||
setNavOpen && setNavOpen(!navOpen);
|
||||
}}
|
||||
circle
|
||||
/>
|
||||
|
||||
@@ -16,8 +16,8 @@ import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
|
||||
import { Protobuf } from '@meshtastic/meshtasticjs';
|
||||
|
||||
export interface RadioProps {
|
||||
navOpen: boolean;
|
||||
setNavOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
navOpen?: boolean;
|
||||
setNavOpen?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export const Radio = ({ navOpen, setNavOpen }: RadioProps): JSX.Element => {
|
||||
@@ -40,7 +40,7 @@ export const Radio = ({ navOpen, setNavOpen }: RadioProps): JSX.Element => {
|
||||
<IconButton
|
||||
icon={<FiMenu className="w-5 h-5" />}
|
||||
onClick={(): void => {
|
||||
setNavOpen(!navOpen);
|
||||
setNavOpen && setNavOpen(!navOpen);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user