|
|
|
@ -2,11 +2,17 @@ import type React from "react"; |
|
|
|
|
|
|
|
import maplibregl from "maplibre-gl"; |
|
|
|
import { Map, Marker, useMap } from "react-map-gl"; |
|
|
|
import { base16 } from "rfc4648"; |
|
|
|
|
|
|
|
import { Card } from "@app/components/Card.js"; |
|
|
|
import { IconButton } from "@app/components/IconButton.js"; |
|
|
|
import { Mono } from "@app/components/Mono.js"; |
|
|
|
import { useDevice } from "@core/providers/useDevice.js"; |
|
|
|
import { Hashicon } from "@emeraldpay/hashicon-react"; |
|
|
|
import { MapPinIcon } from "@heroicons/react/24/outline"; |
|
|
|
import { |
|
|
|
EllipsisHorizontalCircleIcon, |
|
|
|
MapPinIcon, |
|
|
|
} from "@heroicons/react/24/outline"; |
|
|
|
|
|
|
|
export const MapPage = (): JSX.Element => { |
|
|
|
const { nodes, waypoints } = useDevice(); |
|
|
|
@ -14,31 +20,49 @@ export const MapPage = (): JSX.Element => { |
|
|
|
|
|
|
|
return ( |
|
|
|
<div className="flex-grow"> |
|
|
|
<div className="absolute right-0 top-0 z-10 m-2 rounded-md bg-white p-2 shadow-md"> |
|
|
|
<div className="p-1 text-lg font-medium">Title</div> |
|
|
|
<div className="flex flex-col gap-2"> |
|
|
|
{nodes.map((n) => ( |
|
|
|
<div key={n.data.num} className="flex gap-2"> |
|
|
|
<Hashicon value={n.data.num.toString()} size={24} /> |
|
|
|
<div>{n.data.user?.longName}</div> |
|
|
|
<IconButton |
|
|
|
icon={<MapPinIcon className="h-4" />} |
|
|
|
size="sm" |
|
|
|
onClick={() => { |
|
|
|
if (n.data.position?.latitudeI) { |
|
|
|
map?.flyTo({ |
|
|
|
center: [ |
|
|
|
n.data.position.longitudeI / 1e7, |
|
|
|
n.data.position.latitudeI / 1e7, |
|
|
|
], |
|
|
|
zoom: 10, |
|
|
|
}); |
|
|
|
} |
|
|
|
}} |
|
|
|
/> |
|
|
|
</div> |
|
|
|
))} |
|
|
|
</div> |
|
|
|
<div className="absolute right-0 top-0 z-10 m-2"> |
|
|
|
<Card className="flex-col p-3"> |
|
|
|
<div className="p-1 text-lg font-medium">Title</div> |
|
|
|
<div className="flex flex-col gap-2"> |
|
|
|
{nodes.map((n) => ( |
|
|
|
<div |
|
|
|
className="flex gap-2 rounded-md p-2 hover:bg-slate-100" |
|
|
|
key={n.data.num} |
|
|
|
> |
|
|
|
<span className="my-auto shrink-0"> |
|
|
|
<Hashicon value={n.data.num.toString()} size={28} /> |
|
|
|
</span> |
|
|
|
<div className="flex flex-col"> |
|
|
|
<span className="font-medium">{n.data.user?.longName}</span> |
|
|
|
<Mono> |
|
|
|
{base16 |
|
|
|
.stringify(n.data.user?.macaddr ?? []) |
|
|
|
.match(/.{1,2}/g) |
|
|
|
?.join(":") ?? ""} |
|
|
|
</Mono> |
|
|
|
</div> |
|
|
|
<div className="my-auto ml-auto"> |
|
|
|
<IconButton |
|
|
|
variant="secondary" |
|
|
|
size="sm" |
|
|
|
icon={<EllipsisHorizontalCircleIcon className="h-4" />} |
|
|
|
onClick={() => { |
|
|
|
if (n.data.position?.latitudeI) { |
|
|
|
map?.flyTo({ |
|
|
|
center: [ |
|
|
|
n.data.position.longitudeI / 1e7, |
|
|
|
n.data.position.latitudeI / 1e7, |
|
|
|
], |
|
|
|
zoom: 10, |
|
|
|
}); |
|
|
|
} |
|
|
|
}} |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
))} |
|
|
|
</div> |
|
|
|
</Card> |
|
|
|
</div> |
|
|
|
<Map |
|
|
|
mapStyle="https://raw.githubusercontent.com/hc-oss/maplibre-gl-styles/master/styles/osm-mapnik/v8/default.json" |
|
|
|
|