diff --git a/src/App.js b/src/App.js
index 5ba40edb9..ead8d00e1 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,23 +1,10 @@
-/**
-=========================================================
-* Material Dashboard 2 React - v2.2.0
-=========================================================
-
-* Product Page: https://www.creative-tim.com/product/material-dashboard-react
-* Copyright 2023 Creative Tim (https://www.creative-tim.com)
-
-Coded by www.creative-tim.com
-
- =========================================================
-
-* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-*/
-
import { useState, useEffect, useMemo } from "react";
-
-// react-router components
import { Routes, Route, Navigate, useLocation } from "react-router-dom";
+// AWS Amplify Imports
+import { Authenticator } from '@aws-amplify/ui-react';
+import '@aws-amplify/ui-react/styles.css';
+
// @mui material components
import { ThemeProvider } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
@@ -30,27 +17,18 @@ import MDBox from "components/MDBox";
import Sidenav from "examples/Sidenav";
import Configurator from "examples/Configurator";
-// Material Dashboard 2 React themes
+// Themes
import theme from "assets/theme";
-import themeRTL from "assets/theme/theme-rtl";
-
-// Material Dashboard 2 React Dark Mode themes
import themeDark from "assets/theme-dark";
-import themeDarkRTL from "assets/theme-dark/theme-rtl";
-// RTL plugins
-import rtlPlugin from "stylis-plugin-rtl";
-import { CacheProvider } from "@emotion/react";
-import createCache from "@emotion/cache";
-
-// Material Dashboard 2 React routes
+// Routes
import routes from "routes";
-// Material Dashboard 2 React contexts
+// Context
import { useMaterialUIController, setMiniSidenav, setOpenConfigurator } from "context";
-// Images
-import brandWhite from "assets/images/logo-ct.png";
+// Images (Update brandName to "Climate Wall")
+import brandWhite from "assets/images/logo-ct.png";
import brandDark from "assets/images/logo-ct-dark.png";
export default function App() {
@@ -65,21 +43,11 @@ export default function App() {
whiteSidenav,
darkMode,
} = controller;
+
const [onMouseEnter, setOnMouseEnter] = useState(false);
- const [rtlCache, setRtlCache] = useState(null);
const { pathname } = useLocation();
- // Cache for the rtl
- useMemo(() => {
- const cacheRtl = createCache({
- key: "rtl",
- stylisPlugins: [rtlPlugin],
- });
-
- setRtlCache(cacheRtl);
- }, []);
-
- // Open sidenav when mouse enter on mini sidenav
+ // Navigation handlers
const handleOnMouseEnter = () => {
if (miniSidenav && !onMouseEnter) {
setMiniSidenav(dispatch, false);
@@ -87,7 +55,6 @@ export default function App() {
}
};
- // Close sidenav when mouse leave mini sidenav
const handleOnMouseLeave = () => {
if (onMouseEnter) {
setMiniSidenav(dispatch, true);
@@ -95,104 +62,69 @@ export default function App() {
}
};
- // Change the openConfigurator state
const handleConfiguratorOpen = () => setOpenConfigurator(dispatch, !openConfigurator);
- // Setting the dir attribute for the body element
useEffect(() => {
document.body.setAttribute("dir", direction);
- }, [direction]);
-
- // Setting page scroll to 0 when changing the route
- useEffect(() => {
document.documentElement.scrollTop = 0;
document.scrollingElement.scrollTop = 0;
- }, [pathname]);
+ }, [direction, pathname]);
const getRoutes = (allRoutes) =>
allRoutes.map((route) => {
- if (route.collapse) {
- return getRoutes(route.collapse);
- }
-
+ if (route.collapse) return getRoutes(route.collapse);
if (route.route) {
return ;
}
-
return null;
});
- const configsButton = (
-
-
- settings
-
-
- );
-
- return direction === "rtl" ? (
-
-
-
- {layout === "dashboard" && (
- <>
-
-
- {configsButton}
- >
- )}
- {layout === "vr" && }
-
- {getRoutes(routes)}
- } />
-
-
-
- ) : (
-
-
- {layout === "dashboard" && (
- <>
-
-
- {configsButton}
- >
+ return (
+
+ {({ signOut, user }) => (
+
+
+ {layout === "dashboard" && (
+ <>
+
+
+ {/* Settings / Config Button */}
+
+ settings
+
+ >
+ )}
+
+
+ {getRoutes(routes)}
+ {/* The Navigate to /dashboard acts as your default protected view */}
+ } />
+
+
)}
- {layout === "vr" && }
-
- {getRoutes(routes)}
- } />
-
-
+
);
-}
+}
\ No newline at end of file
diff --git a/src/components/ReportDialog/index.js b/src/components/ReportDialog/index.js
new file mode 100644
index 000000000..bfe335c38
--- /dev/null
+++ b/src/components/ReportDialog/index.js
@@ -0,0 +1,54 @@
+import React, { useState } from "react";
+// @mui material components
+import Dialog from "@mui/material/Dialog";
+import DialogTitle from "@mui/material/DialogTitle";
+import DialogContent from "@mui/material/DialogContent";
+import DialogActions from "@mui/material/DialogActions";
+import MDButton from "components/MDButton";
+import MDBox from "components/MDBox";
+import MDTypography from "components/MDTypography";
+import { MenuItem, Select, FormControl, InputLabel } from "@mui/material";
+
+function ReportDialog({ open, onClose }) {
+ const [format, setFormat] = useState("pdf");
+
+ const handleDownload = async () => {
+ // API Call logic goes here
+ console.log(`Triggering API for ${format} report...`);
+ // Example: await API.post("myReportAPI", "/generate", { body: { format } });
+ onClose();
+ };
+
+ return (
+
+ );
+}
+
+export default ReportDialog;
\ No newline at end of file
diff --git a/src/examples/Navbars/DashboardNavbar/index.js b/src/examples/Navbars/DashboardNavbar/index.js
index 754bd847f..d013abb5f 100644
--- a/src/examples/Navbars/DashboardNavbar/index.js
+++ b/src/examples/Navbars/DashboardNavbar/index.js
@@ -1,42 +1,27 @@
-/**
-=========================================================
-* Material Dashboard 2 React - v2.2.0
-=========================================================
-
-* Product Page: https://www.creative-tim.com/product/material-dashboard-react
-* Copyright 2023 Creative Tim (https://www.creative-tim.com)
-
-Coded by www.creative-tim.com
-
- =========================================================
-
-* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-*/
-
import { useState, useEffect } from "react";
-
-// react-router components
import { useLocation, Link } from "react-router-dom";
-
-// prop-types is a library for typechecking of props.
import PropTypes from "prop-types";
-// @material-ui core components
+// @mui material components
import AppBar from "@mui/material/AppBar";
import Toolbar from "@mui/material/Toolbar";
import IconButton from "@mui/material/IconButton";
import Menu from "@mui/material/Menu";
import Icon from "@mui/material/Icon";
+import Tooltip from "@mui/material/Tooltip";
// Material Dashboard 2 React components
import MDBox from "components/MDBox";
import MDInput from "components/MDInput";
+// NEW: Import the Report Dialog you created earlier
+import ReportDialog from "components/ReportDialog";
+
// Material Dashboard 2 React example components
import Breadcrumbs from "examples/Breadcrumbs";
import NotificationItem from "examples/Items/NotificationItem";
-// Custom styles for DashboardNavbar
+// Custom styles
import {
navbar,
navbarContainer,
@@ -45,7 +30,6 @@ import {
navbarMobileMenu,
} from "examples/Navbars/DashboardNavbar/styles";
-// Material Dashboard 2 React context
import {
useMaterialUIController,
setTransparentNavbar,
@@ -58,31 +42,25 @@ function DashboardNavbar({ absolute, light, isMini }) {
const [controller, dispatch] = useMaterialUIController();
const { miniSidenav, transparentNavbar, fixedNavbar, openConfigurator, darkMode } = controller;
const [openMenu, setOpenMenu] = useState(false);
+
+ // NEW: State for Report Dialog
+ const [openReport, setOpenReport] = useState(false);
+
const route = useLocation().pathname.split("/").slice(1);
useEffect(() => {
- // Setting the navbar type
if (fixedNavbar) {
setNavbarType("sticky");
} else {
setNavbarType("static");
}
- // A function that sets the transparent state of the navbar.
function handleTransparentNavbar() {
setTransparentNavbar(dispatch, (fixedNavbar && window.scrollY === 0) || !fixedNavbar);
}
- /**
- The event listener that's calling the handleTransparentNavbar function when
- scrolling the window.
- */
window.addEventListener("scroll", handleTransparentNavbar);
-
- // Call the handleTransparentNavbar function to set the state with the initial value.
handleTransparentNavbar();
-
- // Remove event listener on cleanup
return () => window.removeEventListener("scroll", handleTransparentNavbar);
}, [dispatch, fixedNavbar]);
@@ -91,34 +69,25 @@ function DashboardNavbar({ absolute, light, isMini }) {
const handleOpenMenu = (event) => setOpenMenu(event.currentTarget);
const handleCloseMenu = () => setOpenMenu(false);
- // Render the notifications menu
const renderMenu = () => (
);
- // Styles for the navbar icons
const iconsStyle = ({ palette: { dark, white, text }, functions: { rgba } }) => ({
color: () => {
let colorValue = light || darkMode ? white.main : dark.main;
-
if (transparentNavbar && !light) {
colorValue = darkMode ? rgba(text.main, 0.6) : text.main;
}
-
return colorValue;
},
});
@@ -136,14 +105,31 @@ function DashboardNavbar({ absolute, light, isMini }) {
{isMini ? null : (
navbarRow(theme, { isMini })}>
-
+
-
+
+ {/* NEW: Report Generation Button */}
+
+ setOpenReport(true)}
+ >
+ description
+
+
+
+ {/* Profile Link (Redirects to Profile Page) */}
+
account_circle
+
+ {/* Mobile Menu Toggle */}
+
+ {/* Settings / Configurator */}
settings
+
+ {/* Notifications */}
notifications
@@ -181,22 +168,14 @@ function DashboardNavbar({ absolute, light, isMini }) {
)}
+
+ {/* NEW: The Dialog Component */}
+ setOpenReport(false)} />
);
}
-// Setting default values for the props of DashboardNavbar
-DashboardNavbar.defaultProps = {
- absolute: false,
- light: false,
- isMini: false,
-};
-
-// Typechecking props for the DashboardNavbar
-DashboardNavbar.propTypes = {
- absolute: PropTypes.bool,
- light: PropTypes.bool,
- isMini: PropTypes.bool,
-};
-
-export default DashboardNavbar;
+DashboardNavbar.defaultProps = { absolute: false, light: false, isMini: false };
+DashboardNavbar.propTypes = { absolute: PropTypes.bool, light: PropTypes.bool, isMini: PropTypes.bool };
+
+export default DashboardNavbar;
\ No newline at end of file
diff --git a/src/layouts/analytics/index.js b/src/layouts/analytics/index.js
new file mode 100644
index 000000000..cde659481
--- /dev/null
+++ b/src/layouts/analytics/index.js
@@ -0,0 +1,96 @@
+import React from "react";
+
+// @mui material components
+import Grid from "@mui/material/Grid";
+import Card from "@mui/material/Card";
+
+// Material Dashboard 2 React components
+import MDBox from "components/MDBox";
+import MDTypography from "components/MDTypography";
+
+// Material Dashboard 2 React example components
+import DashboardLayout from "examples/LayoutContainers/DashboardLayout";
+import DashboardNavbar from "examples/Navbars/DashboardNavbar";
+import Footer from "examples/Footer";
+import ComplexStatisticsCard from "examples/Cards/StatisticsCards/ComplexStatisticsCard";
+
+// Recharts for Historical Trends
+import {
+ AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer
+} from "recharts";
+
+const historicalData = [
+ { month: "Jan", efficiency: 85 },
+ { month: "Feb", efficiency: 88 },
+ { month: "Mar", efficiency: 92 },
+ { month: "Apr", efficiency: 90 },
+ { month: "May", efficiency: 95 },
+];
+
+function Analytics() {
+ return (
+
+
+
+ {/* Top Summary Metrics */}
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Historical Trend Chart */}
+
+
+
+ Historical Performance Summary
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default Analytics;
\ No newline at end of file
diff --git a/src/layouts/profile/components/PlatformSettings/index.js b/src/layouts/profile/components/PlatformSettings/index.js
index 398c0d4b6..6c1893db8 100644
--- a/src/layouts/profile/components/PlatformSettings/index.js
+++ b/src/layouts/profile/components/PlatformSettings/index.js
@@ -24,86 +24,87 @@ import MDBox from "components/MDBox";
import MDTypography from "components/MDTypography";
function PlatformSettings() {
- const [followsMe, setFollowsMe] = useState(true);
- const [answersPost, setAnswersPost] = useState(false);
- const [mentionsMe, setMentionsMe] = useState(true);
- const [newLaunches, setNewLaunches] = useState(false);
- const [productUpdate, setProductUpdate] = useState(true);
- const [newsletter, setNewsletter] = useState(false);
+ const [tempAlert, setTempAlert] = useState(true);
+ const [humidityAlert, setHumidityAlert] = useState(true);
+ const [offlineAlert, setOfflineAlert] = useState(true);
+ const [analyticsReport, setAnalyticsReport] = useState(false);
+ const [systemUpdate, setSystemUpdate] = useState(true);
+ const [hardwareHealth, setHardwareHealth] = useState(false);
return (
- platform settings
+ System Alerts & Settings
- account
+ Environmental Thresholds
- setFollowsMe(!followsMe)} />
+ setTempAlert(!tempAlert)} />
- Email me when someone follows me
+ Email me when temperature exceeds 28°C
- setAnswersPost(!answersPost)} />
+ setHumidityAlert(!humidityAlert)} />
- Email me when someone answers on my post
+ Notify if humidity drops below 30%
- setMentionsMe(!mentionsMe)} />
+ setOfflineAlert(!offlineAlert)} />
- Email me when someone mentions me
+ Urgent alert if a Climate Wall goes offline
+
- application
+ Reporting & Maintenance
- setNewLaunches(!newLaunches)} />
+ setAnalyticsReport(!analyticsReport)} />
- New launches and projects
+ Weekly CSV analytics report via email
- setProductUpdate(!productUpdate)} />
+ setSystemUpdate(!systemUpdate)} />
- Monthly product updates
+ Automatic firmware update notifications
- setNewsletter(!newsletter)} />
+ setHardwareHealth(!hardwareHealth)} />
- Subscribe to newsletter
+ Monthly hardware health summary
@@ -112,4 +113,4 @@ function PlatformSettings() {
);
}
-export default PlatformSettings;
+export default PlatformSettings;
\ No newline at end of file
diff --git a/src/layouts/profile/index.js b/src/layouts/profile/index.js
index f51f6108f..e7e5fdf4a 100644
--- a/src/layouts/profile/index.js
+++ b/src/layouts/profile/index.js
@@ -13,45 +13,53 @@ Coded by www.creative-tim.com
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
+// @mui material components
+import React, { useEffect, useState } from "react";
+import { Auth } from "aws-amplify"; // Integrated Cognito
+
// @mui material components
import Grid from "@mui/material/Grid";
import Divider from "@mui/material/Divider";
-// @mui icons
-import FacebookIcon from "@mui/icons-material/Facebook";
-import TwitterIcon from "@mui/icons-material/Twitter";
-import InstagramIcon from "@mui/icons-material/Instagram";
-
// Material Dashboard 2 React components
import MDBox from "components/MDBox";
import MDTypography from "components/MDTypography";
+import MDButton from "components/MDButton";
// Material Dashboard 2 React example components
import DashboardLayout from "examples/LayoutContainers/DashboardLayout";
import DashboardNavbar from "examples/Navbars/DashboardNavbar";
import Footer from "examples/Footer";
import ProfileInfoCard from "examples/Cards/InfoCards/ProfileInfoCard";
-import ProfilesList from "examples/Lists/ProfilesList";
-import DefaultProjectCard from "examples/Cards/ProjectCards/DefaultProjectCard";
// Overview page components
import Header from "layouts/profile/components/Header";
import PlatformSettings from "layouts/profile/components/PlatformSettings";
-// Data
-import profilesListData from "layouts/profile/data/profilesListData";
+function Overview() {
+ const [userData, setUserData] = useState({
+ username: "Loading...",
+ email: "Loading...",
+ role: "System Operator",
+ });
-// Images
-import homeDecor1 from "assets/images/home-decor-1.jpg";
-import homeDecor2 from "assets/images/home-decor-2.jpg";
-import homeDecor3 from "assets/images/home-decor-3.jpg";
-import homeDecor4 from "assets/images/home-decor-4.jpeg";
-import team1 from "assets/images/team-1.jpg";
-import team2 from "assets/images/team-2.jpg";
-import team3 from "assets/images/team-3.jpg";
-import team4 from "assets/images/team-4.jpg";
+ // Fetch real data from AWS Cognito
+ useEffect(() => {
+ async function fetchUser() {
+ try {
+ const user = await Auth.currentAuthenticatedUser();
+ setUserData({
+ username: user.attributes.nickname || user.username,
+ email: user.attributes.email,
+ role: "Climate Wall Administrator",
+ });
+ } catch (error) {
+ console.error("Not authenticated", error);
+ }
+ }
+ fetchUser();
+ }, []);
-function Overview() {
return (
@@ -59,145 +67,60 @@ function Overview() {
+ {/* Platform Settings: For Toggling Alerts/Notifications */}
+
+ {/* Profile Info: User Identity from Cognito */}
,
- color: "facebook",
- },
- {
- link: "https://twitter.com/creativetim",
- icon: ,
- color: "twitter",
- },
- {
- link: "https://www.instagram.com/creativetimofficial/",
- icon: ,
- color: "instagram",
- },
- ]}
+ // Social links removed for professional dashboard
action={{ route: "", tooltip: "Edit Profile" }}
shadow={false}
/>
+
+ {/* Quick Actions / Session Management */}
-
-
-
-
-
-
- Projects
-
-
-
- Architects design houses
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ Session Management
+
+
+ Auth.signOut()}
+ >
+ Log Out
+
+
+ Logged in as: {userData.email}
+
+
+
+
+ {/* Removed Projects section to focus on System Management */}
);
}
-export default Overview;
+export default Overview;
\ No newline at end of file
diff --git a/src/layouts/wall-details/index.js b/src/layouts/wall-details/index.js
new file mode 100644
index 000000000..3dd6bef1c
--- /dev/null
+++ b/src/layouts/wall-details/index.js
@@ -0,0 +1,102 @@
+import React from "react";
+import { useParams } from "react-router-dom";
+
+// @mui material components
+import Grid from "@mui/material/Grid";
+import Card from "@mui/material/Card";
+
+// Material Dashboard 2 React components
+import MDBox from "components/MDBox";
+import MDTypography from "components/MDTypography";
+
+// Material Dashboard 2 React example components
+import DashboardLayout from "examples/LayoutContainers/DashboardLayout";
+import DashboardNavbar from "examples/Navbars/DashboardNavbar";
+import Footer from "examples/Footer";
+
+// Recharts for Data Visualization
+import {
+ LineChart, Line, BarChart, Bar, XAxis, YAxis,
+ CartesianGrid, Tooltip, ResponsiveContainer, Legend
+} from "recharts";
+
+// Mock Data (In a real app, fetch this using the 'id')
+const mockData = [
+ { time: "00:00", temp: 20, humidity: 40 },
+ { time: "04:00", temp: 18, humidity: 42 },
+ { time: "08:00", temp: 22, humidity: 38 },
+ { time: "12:00", temp: 26, humidity: 35 },
+ { time: "16:00", temp: 25, humidity: 37 },
+ { time: "20:00", temp: 21, humidity: 39 },
+];
+
+function WallDetails() {
+ const { id } = useParams();
+
+ return (
+
+
+
+
+
+ Climate Wall: {id}
+
+
+ Detailed environmental metrics and real-time status.
+
+
+
+
+ {/* Temperature Trend */}
+
+
+
+ Temperature Trend (°C)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Humidity Trend */}
+
+
+
+ Humidity Levels (%)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default WallDetails;
\ No newline at end of file
diff --git a/src/routes.js b/src/routes.js
index a17b439ad..a402c3358 100644
--- a/src/routes.js
+++ b/src/routes.js
@@ -45,6 +45,7 @@ import Profile from "layouts/profile";
import SignIn from "layouts/authentication/sign-in";
import SignUp from "layouts/authentication/sign-up";
+
// @mui icons
import Icon from "@mui/material/Icon";
@@ -59,35 +60,11 @@ const routes = [
},
{
type: "collapse",
- name: "Tables",
- key: "tables",
- icon: table_view,
- route: "/tables",
- component: ,
- },
- {
- type: "collapse",
- name: "Billing",
- key: "billing",
- icon: receipt_long,
- route: "/billing",
- component: ,
- },
- {
- type: "collapse",
- name: "RTL",
- key: "rtl",
- icon: format_textdirection_r_to_l,
- route: "/rtl",
- component: ,
- },
- {
- type: "collapse",
- name: "Notifications",
- key: "notifications",
- icon: notifications,
- route: "/notifications",
- component: ,
+ name: "System Analytics",
+ key: "analytics",
+ icon: insights,
+ route: "/analytics",
+ component: ,
},
{
type: "collapse",
@@ -97,22 +74,17 @@ const routes = [
route: "/profile",
component: ,
},
+ /** INDIVIDUAL CLIMATE WALL METRICS
+ Type is set to 'none' or custom so it exists in the Router
+ but does NOT appear as a link in the sidebar.
+ */
{
- type: "collapse",
- name: "Sign In",
- key: "sign-in",
- icon: login,
- route: "/authentication/sign-in",
- component: ,
- },
- {
- type: "collapse",
- name: "Sign Up",
- key: "sign-up",
- icon: assignment,
- route: "/authentication/sign-up",
- component: ,
+ type: "route",
+ name: "Wall Details",
+ key: "wall-details",
+ route: "/wall/:id",
+ component: ,
},
];
-export default routes;
+export default routes;
\ No newline at end of file