diff --git a/app/routes/device.$deviceId.tsx b/app/routes/device.$deviceId.tsx new file mode 100644 index 00000000..c4cf35ce --- /dev/null +++ b/app/routes/device.$deviceId.tsx @@ -0,0 +1,250 @@ +import type { LinksFunction } from "@remix-run/node"; +import { NavBar } from "~/components/nav-bar"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "~/components/ui/card"; +import { Map, MapProvider, Marker } from "react-map-gl"; +import mapboxgl from "mapbox-gl/dist/mapbox-gl.css"; +import { diffFromCreateDate, getMinuteFormattedString } from "~/utils"; +import { Badge } from "~/components/ui/badge"; +import moment from "moment"; + +let deviceData = { + _id: "5b411d0e5dc1ec001b4f11c8", + createdAt: "2022-03-30T11:25:43.557Z", + updatedAt: "2023-10-26T06:28:23.033Z", + name: "Bahnhofstraße", + currentLocation: { + timestamp: "2018-07-07T20:05:34.723Z", + coordinates: [7.478471, 52.083515, 3.65], + type: "Point", + }, + exposure: "outdoor", + sensors: [ + { + title: "PM10", + unit: "µg/m³", + sensorType: "SDS 011", + icon: "osem-cloud", + _id: "5b411d0e5dc1ec001b4f11cc", + lastMeasurement: { + value: "23.73", + createdAt: "2023-10-13T06:28:23.027Z", + }, + }, + { + title: "PM2.5", + unit: "µg/m³", + sensorType: "SDS 011", + icon: "osem-cloud", + _id: "5b411d0e5dc1ec001b4f11cb", + lastMeasurement: { + value: "20.43", + createdAt: "2023-10-13T06:28:23.027Z", + }, + }, + { + title: "Temperatur", + unit: "°C", + sensorType: "DHT22", + icon: "osem-thermometer", + _id: "5b411d0e5dc1ec001b4f11ca", + lastMeasurement: { + value: "20.80", + createdAt: "2022-07-12T07:02:41.061Z", + }, + }, + { + title: "rel. Luftfeuchte", + unit: "%", + sensorType: "DHT22", + icon: "osem-humidity", + _id: "5b411d0e5dc1ec001b4f11c9", + lastMeasurement: { + value: "99.90", + createdAt: "2022-07-12T07:02:41.061Z", + }, + }, + ], + model: "luftdaten_sds011_dht22", + description: + "Mounted at the street side of my house. Traffic: approx. 8.000 vehicles/d", + image: "5b411d0e5dc1ec001b4f11c8_pblauf.jpg", + lastMeasurementAt: "2023-10-13T06:28:23.027Z", + grouptag: [""], + loc: [ + { + geometry: { + timestamp: "2018-07-07T20:05:34.723Z", + coordinates: [7.478471, 52.083515, 3.65], + type: "Point", + }, + type: "Feature", + }, + ], +}; + +//***************************************** +//* required to view mapbox proberly (Y.Q.) +export const links: LinksFunction = () => { + return [ + { + rel: "stylesheet", + href: mapboxgl, + }, + ]; +}; + +//********************************** +export default function DeviceDashboard() { + //* map marker + const marker = { + longitude: deviceData.currentLocation.coordinates[0], + latitude: deviceData.currentLocation.coordinates[1], + }; + + return ( +
+ + + {/* Left side - device info */} +
+ + + {deviceData.name} + {deviceData._id} + + + {/* properties */} +
+ + {deviceData.exposure.toUpperCase()} + + + {`${deviceData.sensors.length} SENSOR(S)`} + + + {/* Created {deviceData.createdAt.slice(0, 10)} */} + {diffFromCreateDate(deviceData.createdAt)} + + + {moment().diff(moment(deviceData.updatedAt), "days") > 3 ? ( + + INACTIVE + + ) : ( + + ACTIVE + + )} +
+ + {/* image */} +
+
+ {"name"} +
+

+ Mounted at the street side of my house. Traffic: approx. 8.000 + vehicles/d +

+
+ + {/* Map view */} +
+ + + + + +
+
+
+ + {/* Right side - measurements */} + + +
+ {deviceData.sensors.map((sensor: any) => ( + + + + + {sensor.lastMeasurement.value} {sensor.unit} + + + + {sensor.title}{" "} + + + {sensor.sensorType} + + + + +
+ {/*

5 minutes ago

*/} + {sensor.lastMeasurement?.createdAt === undefined || + moment().diff( + moment(sensor.lastMeasurement.createdAt), + "hours", + ) > 25 ? ( +

+ INACTIVE +

+ ) : ( +

+ {getMinuteFormattedString( + sensor.lastMeasurement.createdAt, + )} +

+ )} +
+
+ ))} +
+
+
+
+
+ ); +} diff --git a/app/utils.ts b/app/utils.ts index 95e0ac42..0c69486c 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -1,4 +1,5 @@ import { useMatches } from "@remix-run/react"; +import moment from "moment"; import { useMemo } from "react"; import type { User } from "~/models/user.server"; @@ -142,3 +143,29 @@ export function getFilteredDevices(devices: any, filterParams: URLSearchParams) } } } + +//* Get Minute Formatted String - last sensor measurement update +export function getMinuteFormattedString(lastMeasurementAt: string) { + const secondsAgo = moment().diff( + moment(lastMeasurementAt), + "seconds"); + + if (secondsAgo === null || secondsAgo === undefined) { + return "-"; + } else { + if (secondsAgo < 120) { + return "now"; + } + return `${Math.floor(secondsAgo / 60)} minutes ago`; + } +} + +export function diffFromCreateDate(DeviceCreatedAt: string) { + const createDate = moment(DeviceCreatedAt); + const yearsFromCreate = moment().diff(createDate, "years"); + return `Created ${ + yearsFromCreate === 0 + ? `${moment().diff(createDate, "days")} day(s)` + : `${yearsFromCreate} year` + (yearsFromCreate > 1 ? "s" : "") + } ago`; +} diff --git a/package.json b/package.json index 8780a077..37231807 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,7 @@ "lodash.debounce": "^4.0.8", "lucide-react": "^0.263.1", "mapbox-gl": "^2.14.1", + "moment": "^2.29.4", "morgan": "^1.10.0", "node-fetch": "^3.3.1", "postcss-import": "^15.1.0",