mirror of
https://github.com/meshtastic/web.git
synced 2026-05-19 11:45:17 -04:00
WIP
This commit is contained in:
@@ -24,7 +24,7 @@ export const Message = ({
|
||||
<div className={`shadow-md rounded-full mt-auto ${!isSender && 'ml-2'}`}>
|
||||
<Avatar
|
||||
size={30}
|
||||
name={'UNK'}
|
||||
name={senderName ?? 'UNK'}
|
||||
variant="beam"
|
||||
colors={['#213435', '#46685B', '#648A64', '#A6B985', '#E1E3AC']}
|
||||
/>
|
||||
@@ -42,7 +42,10 @@ export const Message = ({
|
||||
<div className="text-xs text-gray-600">{senderName}</div>
|
||||
</div>
|
||||
<div className="mt-auto mb-4 text-xs font-medium text-secondary mr-3 dark:text-gray-200">
|
||||
{rxTime.getHours()}:{rxTime.getMinutes()}
|
||||
{rxTime.toLocaleTimeString(undefined, {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
37
src/components/generic/Drawer.tsx
Normal file
37
src/components/generic/Drawer.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
|
||||
export interface DrawerProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Drawer = ({
|
||||
open,
|
||||
onClose,
|
||||
children,
|
||||
}: DrawerProps): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
{open && (
|
||||
<div
|
||||
className="z-10 fixed inset-0 transition-opacity"
|
||||
onClick={onClose}
|
||||
>
|
||||
<div
|
||||
className="absolute inset-0 bg-black opacity-50"
|
||||
tabIndex={0}
|
||||
></div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<aside
|
||||
className={`transform top-0 left-0 w-64 bg-white dark:bg-secondaryDark fixed h-full overflow-auto ease-in-out transition-all duration-300 z-30 ${
|
||||
open ? 'translate-x-0' : '-translate-x-full'
|
||||
}`}
|
||||
>
|
||||
{children}
|
||||
</aside>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,18 +1,16 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Dialog } from '@headlessui/react';
|
||||
import {
|
||||
AnnotationIcon,
|
||||
CogIcon,
|
||||
InformationCircleIcon,
|
||||
ViewGridIcon,
|
||||
XCircleIcon,
|
||||
} from '@heroicons/react/outline';
|
||||
|
||||
import { useAppDispatch, useAppSelector } from '../../hooks/redux';
|
||||
import { routes } from '../../router';
|
||||
import { closeMobileNav } from '../../slices/appSlice';
|
||||
import { Button } from '../generic/Button';
|
||||
import { Drawer } from '../generic/Drawer';
|
||||
import { MenuButton } from './MenuButton';
|
||||
|
||||
export const MobileNav = (): JSX.Element => {
|
||||
@@ -21,57 +19,46 @@ export const MobileNav = (): JSX.Element => {
|
||||
const mobileNavOpen = useAppSelector((state) => state.app.mobileNavOpen);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
<Drawer
|
||||
open={mobileNavOpen}
|
||||
onClose={() => dispatch(closeMobileNav())}
|
||||
className="flex fixed inset-0 z-10 overflow-y-auto"
|
||||
onClose={() => {
|
||||
dispatch(closeMobileNav());
|
||||
}}
|
||||
>
|
||||
<Dialog.Overlay className="fixed inset-0 backdrop-filter backdrop-blur" />
|
||||
|
||||
<div className="mx-auto w-full max-w-sm m-6 p-6 transform bg-white dark:bg-secondaryDark border dark:border-gray-600 rounded-3xl">
|
||||
<Button
|
||||
className="float-right"
|
||||
<div>
|
||||
<MenuButton
|
||||
icon={<AnnotationIcon />}
|
||||
text={'Messages'}
|
||||
link={routes.messages().link}
|
||||
clickAction={() => {
|
||||
dispatch(closeMobileNav());
|
||||
}}
|
||||
>
|
||||
<XCircleIcon className="w-6 h-6" />
|
||||
</Button>
|
||||
<div>
|
||||
<MenuButton
|
||||
icon={<AnnotationIcon />}
|
||||
text={'Messages'}
|
||||
link={routes.messages().link}
|
||||
clickAction={() => {
|
||||
dispatch(closeMobileNav());
|
||||
}}
|
||||
/>
|
||||
<MenuButton
|
||||
icon={<ViewGridIcon />}
|
||||
text={'Nodes'}
|
||||
link={routes.nodes().link}
|
||||
clickAction={() => {
|
||||
dispatch(closeMobileNav());
|
||||
}}
|
||||
/>
|
||||
<MenuButton
|
||||
icon={<CogIcon />}
|
||||
text={'Settings'}
|
||||
link={routes.settings().link}
|
||||
clickAction={() => {
|
||||
dispatch(closeMobileNav());
|
||||
}}
|
||||
/>
|
||||
<MenuButton
|
||||
icon={<InformationCircleIcon />}
|
||||
text={'About'}
|
||||
link={routes.about().link}
|
||||
clickAction={() => {
|
||||
dispatch(closeMobileNav());
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
/>
|
||||
<MenuButton
|
||||
icon={<ViewGridIcon />}
|
||||
text={'Nodes'}
|
||||
link={routes.nodes().link}
|
||||
clickAction={() => {
|
||||
dispatch(closeMobileNav());
|
||||
}}
|
||||
/>
|
||||
<MenuButton
|
||||
icon={<CogIcon />}
|
||||
text={'Settings'}
|
||||
link={routes.settings().link}
|
||||
clickAction={() => {
|
||||
dispatch(closeMobileNav());
|
||||
}}
|
||||
/>
|
||||
<MenuButton
|
||||
icon={<InformationCircleIcon />}
|
||||
text={'About'}
|
||||
link={routes.about().link}
|
||||
clickAction={() => {
|
||||
dispatch(closeMobileNav());
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Drawer>
|
||||
);
|
||||
};
|
||||
|
||||
23
src/components/nodes/Node.tsx
Normal file
23
src/components/nodes/Node.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
|
||||
import Avatar from 'boring-avatars';
|
||||
|
||||
import type { Protobuf } from '@meshtastic/meshtasticjs';
|
||||
|
||||
export interface NodeProps {
|
||||
node: Protobuf.NodeInfo;
|
||||
}
|
||||
|
||||
export const Node = ({ node }: NodeProps): JSX.Element => {
|
||||
return (
|
||||
<div className="flex space-x-4 items-center w-full rounded-md dark:bg-primaryDark shadow-md border dark:border-gray-600 p-2 mt-6 dark:text-white hover:bg-gray-200 dark:hover:bg-gray-900">
|
||||
<Avatar
|
||||
size={30}
|
||||
name={node.user?.longName ?? 'UNK'}
|
||||
variant="beam"
|
||||
colors={['#213435', '#46685B', '#648A64', '#A6B985', '#E1E3AC']}
|
||||
/>
|
||||
<div>{node.user?.longName}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,11 +1,17 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Node } from '../components/nodes/Node';
|
||||
import { PrimaryTemplate } from '../components/templates/PrimaryTemplate';
|
||||
import { useAppSelector } from '../hooks/redux';
|
||||
|
||||
export const Nodes = (): JSX.Element => {
|
||||
const nodes = useAppSelector((state) => state.meshtastic.nodes);
|
||||
|
||||
return (
|
||||
<PrimaryTemplate title="Administration" tagline="Node">
|
||||
<p>Nodes</p>
|
||||
{nodes.map((node) => (
|
||||
<Node key={node.num} node={node} />
|
||||
))}
|
||||
</PrimaryTemplate>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -34,12 +34,14 @@ export const Settings = (): JSX.Element => {
|
||||
<Input
|
||||
name={t('strings.wifi_ssid')}
|
||||
value={radioConfig.wifiSsid}
|
||||
onChange={(event) => {}}
|
||||
type="text"
|
||||
valid={true}
|
||||
/>
|
||||
<Input
|
||||
name={t('strings.wifi_psk')}
|
||||
value={radioConfig.wifiPassword}
|
||||
onChange={(event) => {}}
|
||||
type="text"
|
||||
valid={true}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user