diff --git a/wearables-dashboard/bun.lockb b/wearables-dashboard/bun.lockb
index 867d462..46897f2 100644
Binary files a/wearables-dashboard/bun.lockb and b/wearables-dashboard/bun.lockb differ
diff --git a/wearables-dashboard/index.html b/wearables-dashboard/index.html
index 341cd59..f3304aa 100644
--- a/wearables-dashboard/index.html
+++ b/wearables-dashboard/index.html
@@ -8,7 +8,7 @@
rel="stylesheet"
/>
-
Flex showcase
+ Healthosia - Luzmo Flex SDK sample application
diff --git a/wearables-dashboard/package-lock.json b/wearables-dashboard/package-lock.json
index 5a6b459..261fea2 100644
--- a/wearables-dashboard/package-lock.json
+++ b/wearables-dashboard/package-lock.json
@@ -13,6 +13,7 @@
"@luzmo/react-embed": "next",
"@mui/icons-material": "^5.16.4",
"@mui/lab": "^5.0.0-alpha.172",
+ "axios": "^1.7.7",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"userflow.js": "^2.12.1"
@@ -2060,6 +2061,23 @@
"node": ">=8"
}
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/axios": {
+ "version": "1.7.7",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
+ "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/babel-plugin-macros": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
@@ -2195,6 +2213,18 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -2263,6 +2293,15 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -2768,6 +2807,40 @@
"integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
"dev": true
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -3221,6 +3294,27 @@
"node": ">=8.6"
}
},
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
@@ -3472,6 +3566,12 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
diff --git a/wearables-dashboard/package.json b/wearables-dashboard/package.json
index 458a146..af280d3 100644
--- a/wearables-dashboard/package.json
+++ b/wearables-dashboard/package.json
@@ -17,6 +17,7 @@
"@luzmo/react-embed": "next",
"@mui/icons-material": "^5.16.4",
"@mui/lab": "^5.0.0-alpha.172",
+ "axios": "^1.7.7",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"userflow.js": "^2.12.1"
diff --git a/wearables-dashboard/src/App.tsx b/wearables-dashboard/src/App.tsx
index 65010b4..b326b8e 100644
--- a/wearables-dashboard/src/App.tsx
+++ b/wearables-dashboard/src/App.tsx
@@ -13,6 +13,27 @@ const theme = createTheme({
typography: {
fontFamily: "Lato",
},
+ palette: {
+ primary: {
+ main: "#6440EB",
+ },
+ secondary: {
+ main: "#fefefe",
+ },
+ // background color for the entire app
+ background: {
+ default: "#f4f5fd",
+ },
+ },
+ breakpoints: {
+ values: {
+ xs: 0,
+ sm: 900,
+ md: 1200,
+ lg: 1536,
+ xl: 1920,
+ },
+ },
});
import "./App.css";
@@ -33,23 +54,23 @@ function App() {
<>
-
-
- {selectedTab === "analytics" && }
- {selectedTab === "settings" && (
-
-
-
-
-
- )}
-
+
+
+ {selectedTab === "analytics" && }
+ {selectedTab === "settings" && (
+
+
+
+
+
+ )}
+
+
>
diff --git a/wearables-dashboard/src/components/Analytics/Analytics.tsx b/wearables-dashboard/src/components/Analytics/Analytics.tsx
index cc355df..6835db5 100644
--- a/wearables-dashboard/src/components/Analytics/Analytics.tsx
+++ b/wearables-dashboard/src/components/Analytics/Analytics.tsx
@@ -1,4 +1,5 @@
-import { Grid, Box, Tabs, Tab } from "@mui/material";
+import { useState, SyntheticEvent, useEffect } from "react";
+import { Grid, Box, Tabs, Tab, Typography, Stack, Paper } from "@mui/material";
import { useTheme } from "@mui/material/styles";
import {
@@ -7,6 +8,8 @@ import {
VizItemOptions,
} from "@luzmo/react-embed";
+import { useUser } from "../../services/UserService";
+
import { SleepTimeline } from "../SleepTimeline/SleepTimeline";
import { heattableOptions, heatTableSlots } from "./sleep/heatTableConsts";
@@ -28,19 +31,27 @@ import {
areaChartOptions as stepsAreaChartOptions,
areaChartSlots as stepsAreaChartSlots,
} from "./steps/areaChartConsts";
+import {
+ circleGaugeOptions,
+ circleGaugeSlots,
+} from "./sleep/circleGaugeConsts";
import "./Analytics.css";
-import { useState, SyntheticEvent } from "react";
import {
- numberWidgetOptions,
- numberWidgetSlots,
-} from "./sleep/numberWidgetConsts";
-import { useUser } from "../../services/UserService";
+ getSleepScoreLastNight,
+ getStepsPerDay,
+} from "../../services/DataService";
const LUZMO_VIZ_ITEM_SMALL_STYLE = { width: "100%", height: "10rem" };
const LUZMO_VIZ_ITEM_MEDIUM_STYLE = { width: "100%", height: "20rem" };
const LUZMO_VIZ_ITEM_LARGE_STYLE = { width: "100%", height: "40rem" };
+const TEXTUAL_INSIGHTS_STYLE = {
+ textAlign: "center",
+ paddingY: "0.5rem",
+ paddingX: "0.2rem",
+};
+
interface TabPanelProps {
children?: React.ReactNode;
index: number;
@@ -64,11 +75,67 @@ function CustomTabPanel(props: TabPanelProps) {
}
export default function Analytics() {
+ const { user } = useUser();
+ const theme = useTheme();
const [value, setValue] = useState(0);
+ const [sleepScoreYesterday, setSleepScoreYesterday] = useState<
+ number | undefined
+ >(undefined);
+ const [sleepScoreDayBefore, setSleepScoreDayBefore] = useState<
+ number | undefined
+ >(undefined);
+ const [averageKcalBurned, setAverageKcalBurned] = useState<
+ number | undefined
+ >(undefined);
+ const [stepsToday, setStepsToday] = useState(undefined);
- const theme = useTheme();
+ useEffect(() => {
+ if (!user) return;
- const { user } = useUser();
+ setSleepScoreYesterday(undefined);
+
+ // Fetch sleep score from yesterday
+ getSleepScoreLastNight(user.id).then((sleepScores) => {
+ setSleepScoreYesterday(
+ sleepScores.lastNightSleepScore > -1
+ ? Math.round(sleepScores.lastNightSleepScore * 100)
+ : undefined
+ );
+
+ setSleepScoreDayBefore(
+ sleepScores.previousNightSleepScore > -1
+ ? Math.round(sleepScores.previousNightSleepScore * 100)
+ : undefined
+ );
+ });
+ }, [user]);
+
+ useEffect(() => {
+ if (!user) return;
+
+ setStepsToday(undefined);
+
+ // Fetch sleep score from yesterday
+ getStepsPerDay(user.id).then((stepsPerDay) => {
+ // Check if the first entry is from today & set the steps
+ setStepsToday(
+ stepsPerDay[0].date ===
+ new Date(new Date().toISOString().split("T")[0]).toISOString()
+ ? stepsPerDay[0].steps
+ : 0
+ );
+
+ // Calculate the average steps per day to estimate the kcal burned
+ const totalSteps = stepsPerDay.reduce(
+ (acc, current) => acc + current.steps,
+ 0
+ );
+
+ setAverageKcalBurned(
+ Math.round((totalSteps / stepsPerDay.length) * 0.04)
+ );
+ });
+ }, [user]);
const stepDevice = user
? user.devices.find((d) => d.type === "steps")
@@ -81,60 +148,67 @@ export default function Analytics() {
const hasSleepData = sleepDevice !== undefined;
let stepDatetimeLevel = "day";
- let sleepDatetimeLevel = "day";
if (stepDevice) {
stepDatetimeLevel =
stepDevice.intervalInSeconds > 1800
- ? "day"
+ ? "week"
: stepDevice.intervalInSeconds > 60
- ? "hour"
- : "minute";
- }
- if (sleepDevice) {
- sleepDatetimeLevel =
- sleepDevice.intervalInSeconds > 1800
? "day"
- : sleepDevice.intervalInSeconds > 60
- ? "hour"
- : "minute";
+ : "hour";
}
+ const hourOfDay = new Date().getHours();
+ const timeOfDay =
+ hourOfDay > 6 && hourOfDay < 12
+ ? "morning"
+ : hourOfDay >= 12 && hourOfDay < 18
+ ? "afternoon"
+ : hourOfDay < 22
+ ? "evening"
+ : "night";
+
+ const [defaultTab, setDefaultTab] = useState(
+ hasSleepData ? (hourOfDay < 15 ? 1 : 0) : 0
+ );
+
// Create the necessary filters to filter to the user's data
/*
* NOTE:
* This is a mock implementation, which performs the filtering on the client side.
* In a real-world scenario, the filtering must be done server side in the Authorization request for security purposes!
*/
- const filtersToApply: FilterGroup[] = [
- {
- condition: "and",
- filters: [
- // Steps filter on Patient ID column
+ const filtersToApply: FilterGroup[] = user
+ ? [
{
- expression: "? = ?",
- parameters: [
+ condition: "and",
+ filters: [
+ // Steps filter on Patient ID column
{
- column_id: "572740ed-aeed-4aeb-b318-d059e8be35a6",
- dataset_id: "1c759996-74fd-438d-bcba-eb58838a5b03",
+ expression: "? = ?",
+ parameters: [
+ {
+ column_id: "572740ed-aeed-4aeb-b318-d059e8be35a6",
+ dataset_id: "1c759996-74fd-438d-bcba-eb58838a5b03",
+ },
+ user.id,
+ ],
},
- user.id,
- ],
- },
- // Sleep filter on Patient ID column
- {
- expression: "? = ?",
- parameters: [
+ // Sleep filter on Patient ID column
{
- column_id: "695b3aee-6772-4aa6-bb50-a67a88bfc26b",
- dataset_id: "f0e0df8c-87fc-4bdc-ab7f-8cd744146284",
+ expression: "? = ?",
+ parameters: [
+ {
+ column_id: "695b3aee-6772-4aa6-bb50-a67a88bfc26b",
+ dataset_id: "f0e0df8c-87fc-4bdc-ab7f-8cd744146284",
+ },
+ user.id,
+ ],
},
- user.id,
],
},
- ],
- },
- ];
+ ]
+ : [];
const handleSleepTabChange = (_: SyntheticEvent, newValue: number) => {
setValue(newValue);
@@ -145,7 +219,7 @@ export default function Analytics() {
...widgetOptions,
theme: {
font: {
- fontFamily: "Lato",
+ fontFamily: theme.typography.fontFamily,
},
mainColor: theme.palette.primary.main,
},
@@ -166,68 +240,158 @@ export default function Analytics() {
<>
{/* Create Luzmo number evolution widget with steps info */}
{hasStepsData && (
-
-
-
- )}
- {hasSleepData && (
- <>
- {/* Create Luzmo number evolution widget with sleep info */}
-
+
+
+
+ Good {timeOfDay} {user?.name}!
+
+
+ {hasSleepData && sleepScoreYesterday && sleepScoreDayBefore && (
+
+ Your sleep score was {sleepScoreYesterday}%{" "}
+ last night, which is{" "}
+ {sleepScoreDayBefore > sleepScoreYesterday
+ ? "less than"
+ : sleepScoreDayBefore < sleepScoreYesterday
+ ? "more than"
+ : "equal to"}{" "}
+ the night before ({sleepScoreDayBefore}%).
+
+ )}
+ {hasSleepData && !sleepScoreYesterday && (
+
+ Loading sleep insights...
+
+ )}
+ {hasStepsData && stepsToday && (
+
+ Based on your walking history, you should have used about{" "}
+ {averageKcalBurned} kcal by the end of today
+ (currently at {stepsToday} steps today).
+
+ )}
+ {hasStepsData && !stepsToday && (
+
+ Loading step insights...
+
+ )}
+
+
+
+
+
+ )}
+ {hasSleepData && (
+ <>
+ {/* Create Luzmo circular gauge widget with sleep info */}
+
+
+
+
{/* Create sleep timeline */}
-
-
+
+
+
+
{/* Create Luzmo sleep insights with custom tabs element */}
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+ {defaultTab === 0 && (
+
+ )}
+ {defaultTab === 1 && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+
>
)}
@@ -235,37 +399,44 @@ export default function Analytics() {
{hasStepsData && (
<>
-
+
+
+
-
-
-
- {/* Create Luzmo line chart with steps info */}
-
+
+
+
+ {!hasSleepData && (
+
+
+
+
+
+ )}
>
)}
>
diff --git a/wearables-dashboard/src/components/Analytics/sleep/areaChartConsts.ts b/wearables-dashboard/src/components/Analytics/sleep/areaChartConsts.ts
index 88b2063..cd2ed08 100644
--- a/wearables-dashboard/src/components/Analytics/sleep/areaChartConsts.ts
+++ b/wearables-dashboard/src/components/Analytics/sleep/areaChartConsts.ts
@@ -2,7 +2,7 @@ import { VizItemOptions } from "@luzmo/react-embed";
import { Slots } from "@luzmo/react-embed";
export const areaChartOptions: VizItemOptions = {
- interpolation: "step-after",
+ interpolation: "step-before",
interactivity: {
brush: true,
urlConfig: {
diff --git a/wearables-dashboard/src/components/Analytics/sleep/circleGaugeConsts.ts b/wearables-dashboard/src/components/Analytics/sleep/circleGaugeConsts.ts
new file mode 100644
index 0000000..aa4b549
--- /dev/null
+++ b/wearables-dashboard/src/components/Analytics/sleep/circleGaugeConsts.ts
@@ -0,0 +1,28 @@
+import { VizItemOptions } from "@luzmo/react-embed";
+import { Slots } from "@luzmo/react-embed";
+
+export const circleGaugeOptions: VizItemOptions = {
+ circle: {
+ degrees: 360,
+ flip: false,
+ },
+};
+
+export const circleGaugeSlots: Slots = [
+ {
+ name: "measure",
+ content: [
+ {
+ column: "d0ff1497-fa36-4dce-9480-a03e2f65c5ee",
+ set: "f0e0df8c-87fc-4bdc-ab7f-8cd744146284",
+ label: {
+ en: "Average sleep score",
+ },
+ type: "numeric",
+
+ format: ",.0a%",
+ aggregationFunc: "average",
+ },
+ ],
+ },
+];
diff --git a/wearables-dashboard/src/components/Analytics/sleep/heatTableConsts.ts b/wearables-dashboard/src/components/Analytics/sleep/heatTableConsts.ts
index bf0c8e8..e65cd27 100644
--- a/wearables-dashboard/src/components/Analytics/sleep/heatTableConsts.ts
+++ b/wearables-dashboard/src/components/Analytics/sleep/heatTableConsts.ts
@@ -92,7 +92,7 @@ export const heattableOptions: VizItemOptions = {
spacing: null,
},
interactivity: {
- select: true,
+ select: false,
urlConfig: {
target: "_blank",
url: null,
diff --git a/wearables-dashboard/src/components/Analytics/steps/heightNumberWidgetConsts.ts b/wearables-dashboard/src/components/Analytics/steps/heightNumberWidgetConsts.ts
index 2208198..0ed34c6 100644
--- a/wearables-dashboard/src/components/Analytics/steps/heightNumberWidgetConsts.ts
+++ b/wearables-dashboard/src/components/Analytics/steps/heightNumberWidgetConsts.ts
@@ -56,7 +56,7 @@ export function getHeightNumberWidgetSlots(datetimeLevel: string): Slot[] {
column: "24bf0c70-5464-4131-81af-9281e6d3c4f0",
set: "1c759996-74fd-438d-bcba-eb58838a5b03",
label: {
- en: `Height meters per ${datetimeLevel}`,
+ en: `Height meters climbed per ${datetimeLevel}`,
},
type: "numeric",
format: ",.3as",
diff --git a/wearables-dashboard/src/components/Analytics/steps/stepsNumberWidgetConsts.ts b/wearables-dashboard/src/components/Analytics/steps/stepsNumberWidgetConsts.ts
index d4ab0b0..ff4d5bb 100644
--- a/wearables-dashboard/src/components/Analytics/steps/stepsNumberWidgetConsts.ts
+++ b/wearables-dashboard/src/components/Analytics/steps/stepsNumberWidgetConsts.ts
@@ -12,7 +12,7 @@ export function getStepNumberWidgetSlots(datetimeLevel: string): Slot[] {
column: "27978dfd-7218-40a4-88cf-59de2df91935",
set: "1c759996-74fd-438d-bcba-eb58838a5b03",
label: {
- en: `Number of steps by ${datetimeLevel}`,
+ en: `Number of steps per ${datetimeLevel}`,
},
type: "numeric",
format: ",.3as",
@@ -81,7 +81,7 @@ export const stepNumberWidgetSlots: Slot[] = [
column: "27978dfd-7218-40a4-88cf-59de2df91935",
set: "1c759996-74fd-438d-bcba-eb58838a5b03",
label: {
- en: "Number of steps by day",
+ en: "Total steps per day",
},
type: "numeric",
format: ",.3as",
diff --git a/wearables-dashboard/src/components/Settings/UserDevices.tsx b/wearables-dashboard/src/components/Settings/UserDevices.tsx
index c9b930f..7f021f4 100644
--- a/wearables-dashboard/src/components/Settings/UserDevices.tsx
+++ b/wearables-dashboard/src/components/Settings/UserDevices.tsx
@@ -1,4 +1,3 @@
-import React from "react";
import {
Card,
CardContent,
@@ -6,9 +5,12 @@ import {
List,
ListItem,
ListItemText,
- ListSubheader,
+ ListItemIcon,
Divider,
} from "@mui/material";
+import DirectionsWalkIcon from "@mui/icons-material/DirectionsWalk";
+import NightsStayIcon from "@mui/icons-material/NightsStay";
+import DeviceUnknownIcon from "@mui/icons-material/DeviceUnknown";
import { User } from "../../types/types";
@@ -38,18 +40,19 @@ export const UserDevices = ({ user }: { user: User }) => {
- {user.name}'s Devices
+ Your devices
-