Skip to content

Commit be8500e

Browse files
committed
mockup with a sleek dashboard
1 parent 1ec26e7 commit be8500e

4 files changed

Lines changed: 800 additions & 0 deletions

File tree

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
"use client";
2+
import React, { useState } from "react";
3+
import {
4+
Container,
5+
Grid,
6+
Card,
7+
CardContent,
8+
Typography,
9+
TextField,
10+
Button,
11+
Select,
12+
MenuItem,
13+
InputLabel,
14+
FormControl,
15+
Table,
16+
TableBody,
17+
TableCell,
18+
TableContainer,
19+
TableHead,
20+
TableRow,
21+
Paper,
22+
} from "@mui/material";
23+
24+
const IoTDashboard: React.FC = () => {
25+
const [search, setSearch] = useState("");
26+
const [selectedPlan, setSelectedPlan] = useState("");
27+
const [params, setParams] = useState({ param1: "", param2: "", param3: "" });
28+
29+
const devices = [
30+
{ id: 1001, name: "Sensor A", status: "Online", lastSeen: "5 sec ago" },
31+
{ id: 1002, name: "Sensor B", status: "Offline", lastSeen: "3 min ago" },
32+
{ id: 1003, name: "Actuator X", status: "Online", lastSeen: "10 sec ago" },
33+
{ id: 1004, name: "Camera Y", status: "Online", lastSeen: "15 sec ago" },
34+
];
35+
36+
const plans = [
37+
"Temperature Calibration",
38+
"Humidity Sync",
39+
"Security Sweep",
40+
"Custom Data Capture",
41+
];
42+
43+
return (
44+
<Container>
45+
<Typography variant="h4" gutterBottom>
46+
IoT Dashboard
47+
</Typography>
48+
49+
{/* Worker & Environment Info */}
50+
<Grid container spacing={2}>
51+
<Grid item xs={4}>
52+
<Card>
53+
<CardContent>
54+
<Typography variant="h6">Worker Status</Typography>
55+
<Typography>Status: Active</Typography>
56+
<Typography>Worker #42</Typography>
57+
<Typography>CPU: 45%</Typography>
58+
</CardContent>
59+
</Card>
60+
</Grid>
61+
<Grid item xs={4}>
62+
<Card>
63+
<CardContent>
64+
<Typography variant="h6">Current Task</Typography>
65+
<Typography>Processing Data</Typography>
66+
<Typography>Task: Sensor Sync</Typography>
67+
<Typography>Progress: 75%</Typography>
68+
</CardContent>
69+
</Card>
70+
</Grid>
71+
<Grid item xs={4}>
72+
<Card>
73+
<CardContent>
74+
<Typography variant="h6">Environment</Typography>
75+
<Typography>Temperature: 22°C</Typography>
76+
<Typography>Humidity: 60%</Typography>
77+
<Typography>Pressure: 1013 hPa</Typography>
78+
</CardContent>
79+
</Card>
80+
</Grid>
81+
</Grid>
82+
83+
{/* Search Devices */}
84+
<TextField
85+
label="Search Devices"
86+
variant="outlined"
87+
fullWidth
88+
margin="normal"
89+
value={search}
90+
onChange={(e) => setSearch(e.target.value)}
91+
/>
92+
93+
{/* Active Devices Table */}
94+
<TableContainer component={Paper}>
95+
<Table>
96+
<TableHead>
97+
<TableRow>
98+
<TableCell>ID</TableCell>
99+
<TableCell>Name</TableCell>
100+
<TableCell>Status</TableCell>
101+
<TableCell>Last Seen</TableCell>
102+
</TableRow>
103+
</TableHead>
104+
<TableBody>
105+
{devices
106+
.filter((device) =>
107+
device.name.toLowerCase().includes(search.toLowerCase())
108+
)
109+
.map((device) => (
110+
<TableRow key={device.id}>
111+
<TableCell>{device.id}</TableCell>
112+
<TableCell>{device.name}</TableCell>
113+
<TableCell>{device.status}</TableCell>
114+
<TableCell>{device.lastSeen}</TableCell>
115+
</TableRow>
116+
))}
117+
</TableBody>
118+
</Table>
119+
</TableContainer>
120+
121+
{/* Plans & Parameter Submission */}
122+
<Grid container spacing={2} mt={2}>
123+
<Grid item xs={6}>
124+
<FormControl fullWidth>
125+
<InputLabel>Select Plan</InputLabel>
126+
<Select
127+
value={selectedPlan}
128+
onChange={(e) => setSelectedPlan(e.target.value)}
129+
>
130+
{plans.map((plan, index) => (
131+
<MenuItem key={index} value={plan}>
132+
{plan}
133+
</MenuItem>
134+
))}
135+
</Select>
136+
</FormControl>
137+
</Grid>
138+
<Grid item xs={6}>
139+
<TextField
140+
label="Parameter 1"
141+
fullWidth
142+
value={params.param1}
143+
onChange={(e) => setParams({ ...params, param1: e.target.value })}
144+
/>
145+
</Grid>
146+
<Grid item xs={6}>
147+
<TextField
148+
label="Parameter 2"
149+
fullWidth
150+
value={params.param2}
151+
onChange={(e) => setParams({ ...params, param2: e.target.value })}
152+
/>
153+
</Grid>
154+
<Grid item xs={6}>
155+
<TextField
156+
label="Parameter 3"
157+
fullWidth
158+
value={params.param3}
159+
onChange={(e) => setParams({ ...params, param3: e.target.value })}
160+
/>
161+
</Grid>
162+
</Grid>
163+
<Button variant="contained" color="primary" sx={{ mt: 2 }}>
164+
Submit Plan
165+
</Button>
166+
</Container>
167+
);
168+
};
169+
170+
export default IoTDashboard;
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { useState, useEffect } from 'react';
2+
import axios from 'axios';
3+
4+
export const useDevices = () => {
5+
const [devices, setDevices] = useState([]);
6+
const [loading, setLoading] = useState(true);
7+
8+
useEffect(() => {
9+
axios.get('/devices')
10+
.then(response => setDevices(response.data.devices))
11+
.finally(() => setLoading(false));
12+
}, []);
13+
14+
return { devices, loading };
15+
};
16+
17+
export const useDeviceByName = (name: string) => {
18+
const [device, setDevice] = useState(null);
19+
const [loading, setLoading] = useState(true);
20+
21+
useEffect(() => {
22+
axios.get(`/devices/${name}`)
23+
.then(response => setDevice(response.data))
24+
.finally(() => setLoading(false));
25+
}, [name]);
26+
27+
return { device, loading };
28+
};
29+
30+
export const useEnvironment = () => {
31+
const [environment, setEnvironment] = useState(null);
32+
const [loading, setLoading] = useState(true);
33+
34+
useEffect(() => {
35+
axios.get('/environment')
36+
.then(response => setEnvironment(response.data))
37+
.finally(() => setLoading(false));
38+
}, []);
39+
40+
return { environment, loading };
41+
};
42+
43+
export const usePlans = () => {
44+
const [plans, setPlans] = useState([]);
45+
const [loading, setLoading] = useState(true);
46+
47+
useEffect(() => {
48+
axios.get('/plans')
49+
.then(response => setPlans(response.data.plans))
50+
.finally(() => setLoading(false));
51+
}, []);
52+
53+
return { plans, loading };
54+
};
55+
56+
export const usePlanByName = (name: string) => {
57+
const [plan, setPlan] = useState(null);
58+
const [loading, setLoading] = useState(true);
59+
60+
useEffect(() => {
61+
axios.get(`/plans/${name}`)
62+
.then(response => setPlan(response.data))
63+
.finally(() => setLoading(false));
64+
}, [name]);
65+
66+
return { plan, loading };
67+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import Box from "@mui/material/Box";
2+
import IoTDashboard from "./components/IoTDashboard";
3+
4+
5+
6+
export default function IoTDashboardPage() {
7+
return <Box sx={{ backgroundColor: "white" }}>
8+
<h1>Dashboard</h1>
9+
<IoTDashboard />
10+
</Box>
11+
}

0 commit comments

Comments
 (0)