You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

125 lines
3.6 KiB

import React from 'react';
import mapbox from 'mapbox-gl';
import { FiMapPin, FiXCircle } from 'react-icons/fi';
import { Marker } from '@app/components/Map/Marker';
import type { Node } from '@app/core/slices/meshtasticSlice.js';
import { Drawer } from '@components/generic/Drawer';
import { Map } from '@components/Map';
import { useAppSelector } from '@hooks/useAppSelector';
import { useBreakpoint } from '@hooks/useBreakpoint';
import { IconButton } from '@meshtastic/components';
import { NodeCard } from './NodeCard';
import { Sidebar } from './Sidebar';
export const Nodes = (): JSX.Element => {
const myNodeInfo = useAppSelector((state) => state.meshtastic.radio.hardware);
const nodes = useAppSelector((state) => state.meshtastic.nodes)
.slice()
.sort((a, b) =>
a.number === myNodeInfo.myNodeNum
? 1
: b?.lastHeard.getTime() - a?.lastHeard.getTime(),
);
const myNode = nodes.find((node) => node.number === myNodeInfo.myNodeNum);
const [navOpen, setNavOpen] = React.useState(false);
const { breakpoint } = useBreakpoint();
const [sidebarOpen, setSidebarOpen] = React.useState(false);
const [selectedNode, setSelectedNode] = React.useState<Node | undefined>();
return (
<div className="relative flex w-full dark:text-white">
<Drawer
open={breakpoint === 'sm' ? navOpen : true}
permenant={breakpoint !== 'sm'}
onClose={(): void => {
setNavOpen(!navOpen);
}}
>
<div className="flex items-center justify-between m-6 mr-6">
<div className="text-3xl 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 found.
</span>
)}
{myNode && (
<NodeCard
node={myNode}
isMyNode={true}
setSelected={(): void => {
setSelectedNode(myNode);
setSidebarOpen(true);
}}
/>
)}
{nodes
.filter((node) => node.number !== myNodeInfo.myNodeNum)
.map((node) => (
<NodeCard
key={node.number}
node={node}
setSelected={(): void => {
setSelectedNode(node);
setSidebarOpen(true);
}}
/>
))}
</Drawer>
{nodes.map((node) => {
return (
node.currentPosition && (
<Marker
center={
new mapbox.LngLat(
node.currentPosition.longitudeI / 1e7,
node.currentPosition.latitudeI / 1e7,
)
}
>
<div
onClick={(): void => {
setSelectedNode(node);
setSidebarOpen(true);
}}
className="z-50 bg-blue-500 border-2 border-blue-500 rounded-full bg-opacity-30"
>
<div className="m-4 ">
<FiMapPin className="w-5 h-5" />
</div>
</div>
</Marker>
)
);
})}
<Map />
{sidebarOpen && selectedNode && (
<Sidebar
closeSidebar={(): void => {
setSidebarOpen(false);
}}
node={selectedNode}
/>
)}
</div>
);
};