diff --git a/web/src/components/packets/ErrorPacket.tsx b/web/src/components/packets/ErrorPacket.tsx index ee0fd95..b84e31c 100644 --- a/web/src/components/packets/ErrorPacket.tsx +++ b/web/src/components/packets/ErrorPacket.tsx @@ -1,6 +1,7 @@ import React from "react"; import { Packet } from "../../lib/types"; import { AlertTriangle } from "lucide-react"; +import { PacketCard } from "./PacketCard"; interface ErrorPacketProps { packet: Packet; @@ -14,29 +15,15 @@ export const ErrorPacket: React.FC = ({ packet }) => { } return ( -
-
-
-
- -
- - Decode Error - -
- - ID: {data.id || "No ID"} - -
- -
+ } + iconBgColor="bg-red-500" + label="Error" + > +
{data.decodeError}
- -
- Channel: {packet.info.channel} - Error -
-
+ ); }; \ No newline at end of file diff --git a/web/src/components/packets/GenericPacket.tsx b/web/src/components/packets/GenericPacket.tsx index 44187b6..f72720b 100644 --- a/web/src/components/packets/GenericPacket.tsx +++ b/web/src/components/packets/GenericPacket.tsx @@ -1,6 +1,7 @@ import React from "react"; import { Packet, PortNum, PortNumByName } from "../../lib/types"; import { Package } from "lucide-react"; +import { PacketCard } from "./PacketCard"; interface GenericPacketProps { packet: Packet; @@ -39,46 +40,30 @@ export const GenericPacket: React.FC = ({ packet }) => { }; return ( -
-
-
-
- -
- - From: {data.from ? `!${data.from.toString(16).toLowerCase()}` : "Unknown"} - + } + iconBgColor="bg-neutral-500" + label={getPortName(data.portNum)} + > +
+
+
Port
+
{getPortName(data.portNum)}
- - ID: {data.id || "No ID"} - -
- -
-
-
-
Port
-
{getPortName(data.portNum)}
-
-
-
Payload
-
{getPayloadDescription()}
-
-
-
To
-
{data.to || "Broadcast"}
-
-
-
Hop Limit
-
{data.hopLimit}
-
+
+
Payload
+
{getPayloadDescription()}
+
+
+
To
+
{data.to || "Broadcast"}
+
+
+
Hop Limit
+
{data.hopLimit}
- -
- Channel: {packet.info.channel} - {getPortName(data.portNum)} -
-
+
); }; \ No newline at end of file diff --git a/web/src/components/packets/NodeInfoPacket.tsx b/web/src/components/packets/NodeInfoPacket.tsx index 785769e..6baaffa 100644 --- a/web/src/components/packets/NodeInfoPacket.tsx +++ b/web/src/components/packets/NodeInfoPacket.tsx @@ -1,6 +1,7 @@ import React from "react"; import { Packet } from "../../lib/types"; import { User } from "lucide-react"; +import { PacketCard } from "./PacketCard"; interface NodeInfoPacketProps { packet: Packet; @@ -15,42 +16,26 @@ export const NodeInfoPacket: React.FC = ({ packet }) => { } return ( -
-
-
-
- -
- - From: {data.from ? `!${data.from.toString(16).toLowerCase()}` : "Unknown"} - + } + iconBgColor="bg-purple-500" + label="Node Info" + > +
+
+
Long Name
+
{nodeInfo.longName || "—"}
- - ID: {data.id || "No ID"} - -
- -
-
-
-
Long Name
-
{nodeInfo.longName || "—"}
-
-
-
Short Name
-
{nodeInfo.shortName || "—"}
-
-
-
ID
-
{nodeInfo.id || "—"}
-
+
+
Short Name
+
{nodeInfo.shortName || "—"}
+
+
+
ID
+
{nodeInfo.id || "—"}
- -
- Channel: {packet.info.channel} - Node Info -
-
+
); }; \ No newline at end of file diff --git a/web/src/components/packets/PacketCard.tsx b/web/src/components/packets/PacketCard.tsx new file mode 100644 index 0000000..f96ac75 --- /dev/null +++ b/web/src/components/packets/PacketCard.tsx @@ -0,0 +1,48 @@ +import React, { ReactNode } from "react"; +import { Packet } from "../../lib/types"; +import { LucideIcon } from "lucide-react"; + +interface PacketCardProps { + packet: Packet; + icon: ReactNode; + iconBgColor: string; + label: string; + children: ReactNode; +} + +export const PacketCard: React.FC = ({ + packet, + icon, + iconBgColor, + label, + children, +}) => { + const { data } = packet; + + return ( +
+
+
+
+ {icon} +
+ + From: {data.from ? `!${data.from.toString(16).toLowerCase()}` : "Unknown"} + +
+ + ID: {data.id || "No ID"} + +
+ +
+ {children} +
+ +
+ Channel: {packet.info.channel} + {label} +
+
+ ); +}; \ No newline at end of file diff --git a/web/src/components/packets/PositionPacket.tsx b/web/src/components/packets/PositionPacket.tsx index c2c9159..b03f72a 100644 --- a/web/src/components/packets/PositionPacket.tsx +++ b/web/src/components/packets/PositionPacket.tsx @@ -1,6 +1,7 @@ import React from "react"; import { Packet } from "../../lib/types"; import { MapPin } from "lucide-react"; +import { PacketCard } from "./PacketCard"; interface PositionPacketProps { packet: Packet; @@ -19,62 +20,46 @@ export const PositionPacket: React.FC = ({ packet }) => { const longitude = position.longitudeI ? position.longitudeI * 1e-7 : undefined; return ( -
-
-
-
- -
- - From: {data.from ? `!${data.from.toString(16).toLowerCase()}` : "Unknown"} - + } + iconBgColor="bg-emerald-500" + label="Position" + > +
+
+
Latitude
+
{latitude !== undefined ? latitude.toFixed(6) : 'N/A'}
- - ID: {data.id || "No ID"} - -
- -
-
-
-
Latitude
-
{latitude !== undefined ? latitude.toFixed(6) : 'N/A'}
-
-
-
Longitude
-
{longitude !== undefined ? longitude.toFixed(6) : 'N/A'}
-
- {position.altitude && ( -
-
Altitude
-
{position.altitude.toFixed(1)}m
-
- )} - {position.time && ( -
-
Time
-
{new Date(position.time * 1000).toLocaleTimeString()}
-
- )} - {position.locationSource && ( -
-
Source
-
{position.locationSource.replace('LOC_', '')}
-
- )} - {position.satsInView && ( -
-
Satellites
-
{position.satsInView}
-
- )} +
+
Longitude
+
{longitude !== undefined ? longitude.toFixed(6) : 'N/A'}
+ {position.altitude && ( +
+
Altitude
+
{position.altitude.toFixed(1)}m
+
+ )} + {position.time && ( +
+
Time
+
{new Date(position.time * 1000).toLocaleTimeString()}
+
+ )} + {position.locationSource && ( +
+
Source
+
{position.locationSource.replace('LOC_', '')}
+
+ )} + {position.satsInView && ( +
+
Satellites
+
{position.satsInView}
+
+ )}
- -
- Channel: {packet.info.channel} - Position -
-
+
); }; diff --git a/web/src/components/packets/TelemetryPacket.tsx b/web/src/components/packets/TelemetryPacket.tsx index aab31bb..00988e2 100644 --- a/web/src/components/packets/TelemetryPacket.tsx +++ b/web/src/components/packets/TelemetryPacket.tsx @@ -1,6 +1,7 @@ import React from "react"; import { Packet } from "../../lib/types"; import { BarChart } from "lucide-react"; +import { PacketCard } from "./PacketCard"; interface TelemetryPacketProps { packet: Packet; @@ -42,29 +43,13 @@ export const TelemetryPacket: React.FC = ({ packet }) => { }; return ( -
-
-
-
- -
- - From: {data.from ? `!${data.from.toString(16).toLowerCase()}` : "Unknown"} - -
- - ID: {data.id || "No ID"} - -
- -
- {renderTelemetryFields()} -
- -
- Channel: {packet.info.channel} - Telemetry -
-
+ } + iconBgColor="bg-amber-500" + label="Telemetry" + > + {renderTelemetryFields()} + ); }; \ No newline at end of file diff --git a/web/src/components/packets/TextMessagePacket.tsx b/web/src/components/packets/TextMessagePacket.tsx index 2acd8a5..646c107 100644 --- a/web/src/components/packets/TextMessagePacket.tsx +++ b/web/src/components/packets/TextMessagePacket.tsx @@ -1,6 +1,7 @@ import React from "react"; import { Packet } from "../../lib/types"; import { MessageSquareText } from "lucide-react"; +import { PacketCard } from "./PacketCard"; interface TextMessagePacketProps { packet: Packet; @@ -10,29 +11,13 @@ export const TextMessagePacket: React.FC = ({ packet }) const { data } = packet; return ( -
-
-
-
- -
- - From: {data.from ? `!${data.from.toString(16).toLowerCase()}` : "Unknown"} - -
- - ID: {data.id || "No ID"} - -
- -
- {data.textMessage || "Empty message"} -
- -
- Channel: {packet.info.channel} - Text Message -
-
+ } + iconBgColor="bg-blue-500" + label="Text Message" + > + {data.textMessage || "Empty message"} + ); }; \ No newline at end of file diff --git a/web/src/routes/packets.tsx b/web/src/routes/packets.tsx index 4363f46..ff229dd 100644 --- a/web/src/routes/packets.tsx +++ b/web/src/routes/packets.tsx @@ -26,22 +26,9 @@ export function PacketsRoute() { return (
-
-

- Mesh Network Packets -

- - -
- - -
); -} \ No newline at end of file +}