diff --git a/frontend/public/config/settings.dev.json b/frontend/public/config/settings.dev.json index f000526..8029fda 100644 --- a/frontend/public/config/settings.dev.json +++ b/frontend/public/config/settings.dev.json @@ -1,98 +1,77 @@ { - "userConfig": { - "city": [ - 37.38283, - -5.97317 - ] + "userConfig": { + "city": [37.38283, -5.97317] + }, + "appConfig": { + "endpoints": { + "DATA_URL": "http://localhost:8081/api/raw/v1", + "LOGIC_URL": "http://localhost:8082/api/v1", + + "GET_GROUPS": "/groups", + "GET_GROUP_BY_ID": "/groups/:groupId", + "POST_GROUPS": "/groups", + "PUT_GROUP_BY_ID": "/groups/:groupId", + + "GET_GROUP_DEVICES": "/groups/:groupId/devices", + "GET_DEVICE_BY_ID": "/groups/:groupId/devices/:deviceId", + "POST_DEVICES": "/groups/:groupId/devices", + "PUT_DEVICE_BY_ID": "/groups/:groupId/devices/:deviceId", + + "GET_DEVICE_LATEST_VALUES": "/groups/:groupId/devices/:deviceId/latest-values", + "GET_DEVICE_POLLUTION_MAP": "/groups/:groupId/devices/:deviceId/pollution-map", + "GET_DEVICE_HISTORY": "/groups/:groupId/devices/:deviceId/history", + + "GET_DEVICE_SENSORS": "/groups/:groupId/devices/:deviceId/sensors", + "GET_SENSOR_BY_ID": "/groups/:groupId/devices/:deviceId/sensors/:sensorId", + "POST_SENSORS": "/groups/:groupId/devices/:deviceId/sensors", + "PUT_SENSOR_BY_ID": "/groups/:groupId/devices/:deviceId/sensors/:sensorId", + "GET_SENSOR_VALUES": "/groups/:groupId/devices/:deviceId/sensors/:sensorId/values", + + "GET_ACTUATORS": "/groups/:groupId/devices/:deviceId/actuators", + "GET_ACTUATOR_BY_ID": "/groups/:groupId/devices/:deviceId/actuators/:actuator_id", + "POST_ACTUATORS": "/groups/:groupId/devices/:deviceId/actuators", + "PUT_ACTUATOR_BY_ID": "/groups/:groupId/devices/:deviceId/actuators/:actuator_id", + "GET_ACTUATOR_STATUS": "/groups/:groupId/devices/:deviceId/actuators/:actuator_id/status", + + "VIEW_LATEST_VALUES": "/v_latest_values", + "VIEW_POLLUTION_MAP": "/v_pollution_map", + "VIEW_SENSOR_HISTORY": "/v_sensor_history_by_device", + "VIEW_SENSOR_VALUES": "/v_sensor_values", + "VIEW_CO_BY_DEVICE": "/v_co_by_device", + "VIEW_GPS_BY_DEVICE": "/v_gps_by_device", + "VIEW_WEATHER_BY_DEVICE": "/v_weather_by_device" }, - "appConfig": { - "endpoints": { - "DATA_URL": "https://contaminus.miarma.net/api/raw/v1", - "LOGIC_URL": "https://contaminus.miarma.net/api/v1", - "GET_GROUPS": "/groups", - "GET_GROUP_BY_ID": "/groups/{0}", - "GET_GROUP_DEVICES": "/groups/{0}/devices", - "POST_GROUPS": "/groups", - "PUT_GROUP_BY_ID": "/groups/{0}", - "GET_DEVICES": "/devices", - "GET_DEVICE_BY_ID": "/devices/{0}", - "GET_DEVICE_SENSORS": "/devices/{0}/sensors", - "GET_DEVICE_LATEST_VALUES": "/devices/{0}/latest", - "GET_DEVICE_POLLUTION_MAP": "/devices/{0}/pollution-map", - "GET_DEVICE_HISTORY": "/devices/{0}/history", - "POST_DEVICES": "/devices", - "PUT_DEVICE_BY_ID": "/devices/{0}", - "GET_SENSORS": "/sensors", - "GET_SENSOR_BY_ID": "/sensors/{0}", - "GET_SENSOR_VALUES": "/sensors/{0}/values", - "POST_SENSORS": "/sensors", - "PUT_SENSOR_BY_ID": "/sensors/{0}", - "GET_ACTUATORS": "/actuators", - "GET_ACTUATOR_BY_ID": "/actuators/{0}", - "POST_ACTUATORS": "/actuators", - "PUT_ACTUATOR_BY_ID": "/actuators/{0}", - "GET_GPS_VALUES": "/gps-values", - "GET_GPS_VALUE_BY_ID": "/gps-values/{0}", - "POST_GPS_VALUES": "/gps-values", - "GET_AIR_VALUES": "/air-values", - "GET_AIR_VALUE_BY_ID": "/air-values/{0}", - "POST_AIR_VALUES": "/air-values" + "historyChartConfig": { + "chartOptionsDark": { + "responsive": true, + "maintainAspectRatio": false, + "scales": { + "x": { + "grid": { "color": "rgba(255, 255, 255, 0.1)" }, + "ticks": { "color": "#E0E0E0" } + }, + "y": { + "grid": { "color": "rgba(255, 255, 255, 0.1)" }, + "ticks": { "color": "#E0E0E0" } + } }, - "historyChartConfig": { - "chartOptionsDark": { - "responsive": true, - "maintainAspectRatio": false, - "scales": { - "x": { - "grid": { - "color": "rgba(255, 255, 255, 0.1)" - }, - "ticks": { - "color": "#E0E0E0" - } - }, - "y": { - "grid": { - "color": "rgba(255, 255, 255, 0.1)" - }, - "ticks": { - "color": "#E0E0E0" - } - } - }, - "plugins": { - "legend": { - "display": false - } - } - }, - "chartOptionsLight": { - "responsive": true, - "maintainAspectRatio": false, - "scales": { - "x": { - "grid": { - "color": "rgba(0, 0, 0, 0.1)" - }, - "ticks": { - "color": "#333" - } - }, - "y": { - "grid": { - "color": "rgba(0, 0, 0, 0.1)" - }, - "ticks": { - "color": "#333" - } - } - }, - "plugins": { - "legend": { - "display": false - } - } - } - } + "plugins": { "legend": { "display": false } } + }, + "chartOptionsLight": { + "responsive": true, + "maintainAspectRatio": false, + "scales": { + "x": { + "grid": { "color": "rgba(0, 0, 0, 0.1)" }, + "ticks": { "color": "#333" } + }, + "y": { + "grid": { "color": "rgba(0, 0, 0, 0.1)" }, + "ticks": { "color": "#333" } + } + }, + "plugins": { "legend": { "display": false } } + } } -} \ No newline at end of file + } +} diff --git a/frontend/public/config/settings.prod.json b/frontend/public/config/settings.prod.json index f000526..fc3c250 100644 --- a/frontend/public/config/settings.prod.json +++ b/frontend/public/config/settings.prod.json @@ -1,98 +1,77 @@ { - "userConfig": { - "city": [ - 37.38283, - -5.97317 - ] + "userConfig": { + "city": [37.38283, -5.97317] + }, + "appConfig": { + "endpoints": { + "DATA_URL": "https://contaminus.miarma.net/api/raw/v1", + "LOGIC_URL": "https://contaminus.miarma.net/api/v1", + + "GET_GROUPS": "/groups", + "GET_GROUP_BY_ID": "/groups/:groupId", + "POST_GROUPS": "/groups", + "PUT_GROUP_BY_ID": "/groups/:groupId", + + "GET_GROUP_DEVICES": "/groups/:groupId/devices", + "GET_DEVICE_BY_ID": "/groups/:groupId/devices/:deviceId", + "POST_DEVICES": "/groups/:groupId/devices", + "PUT_DEVICE_BY_ID": "/groups/:groupId/devices/:deviceId", + + "GET_DEVICE_LATEST_VALUES": "/groups/:groupId/devices/:deviceId/latest-values", + "GET_DEVICE_POLLUTION_MAP": "/groups/:groupId/devices/:deviceId/pollution-map", + "GET_DEVICE_HISTORY": "/groups/:groupId/devices/:deviceId/history", + + "GET_DEVICE_SENSORS": "/groups/:groupId/devices/:deviceId/sensors", + "GET_SENSOR_BY_ID": "/groups/:groupId/devices/:deviceId/sensors/:sensorId", + "POST_SENSORS": "/groups/:groupId/devices/:deviceId/sensors", + "PUT_SENSOR_BY_ID": "/groups/:groupId/devices/:deviceId/sensors/:sensorId", + "GET_SENSOR_VALUES": "/groups/:groupId/devices/:deviceId/sensors/:sensorId/values", + + "GET_ACTUATORS": "/groups/:groupId/devices/:deviceId/actuators", + "GET_ACTUATOR_BY_ID": "/groups/:groupId/devices/:deviceId/actuators/:actuator_id", + "POST_ACTUATORS": "/groups/:groupId/devices/:deviceId/actuators", + "PUT_ACTUATOR_BY_ID": "/groups/:groupId/devices/:deviceId/actuators/:actuator_id", + "GET_ACTUATOR_STATUS": "/groups/:groupId/devices/:deviceId/actuators/:actuator_id/status", + + "VIEW_LATEST_VALUES": "/v_latest_values", + "VIEW_POLLUTION_MAP": "/v_pollution_map", + "VIEW_SENSOR_HISTORY": "/v_sensor_history_by_device", + "VIEW_SENSOR_VALUES": "/v_sensor_values", + "VIEW_CO_BY_DEVICE": "/v_co_by_device", + "VIEW_GPS_BY_DEVICE": "/v_gps_by_device", + "VIEW_WEATHER_BY_DEVICE": "/v_weather_by_device" }, - "appConfig": { - "endpoints": { - "DATA_URL": "https://contaminus.miarma.net/api/raw/v1", - "LOGIC_URL": "https://contaminus.miarma.net/api/v1", - "GET_GROUPS": "/groups", - "GET_GROUP_BY_ID": "/groups/{0}", - "GET_GROUP_DEVICES": "/groups/{0}/devices", - "POST_GROUPS": "/groups", - "PUT_GROUP_BY_ID": "/groups/{0}", - "GET_DEVICES": "/devices", - "GET_DEVICE_BY_ID": "/devices/{0}", - "GET_DEVICE_SENSORS": "/devices/{0}/sensors", - "GET_DEVICE_LATEST_VALUES": "/devices/{0}/latest", - "GET_DEVICE_POLLUTION_MAP": "/devices/{0}/pollution-map", - "GET_DEVICE_HISTORY": "/devices/{0}/history", - "POST_DEVICES": "/devices", - "PUT_DEVICE_BY_ID": "/devices/{0}", - "GET_SENSORS": "/sensors", - "GET_SENSOR_BY_ID": "/sensors/{0}", - "GET_SENSOR_VALUES": "/sensors/{0}/values", - "POST_SENSORS": "/sensors", - "PUT_SENSOR_BY_ID": "/sensors/{0}", - "GET_ACTUATORS": "/actuators", - "GET_ACTUATOR_BY_ID": "/actuators/{0}", - "POST_ACTUATORS": "/actuators", - "PUT_ACTUATOR_BY_ID": "/actuators/{0}", - "GET_GPS_VALUES": "/gps-values", - "GET_GPS_VALUE_BY_ID": "/gps-values/{0}", - "POST_GPS_VALUES": "/gps-values", - "GET_AIR_VALUES": "/air-values", - "GET_AIR_VALUE_BY_ID": "/air-values/{0}", - "POST_AIR_VALUES": "/air-values" + "historyChartConfig": { + "chartOptionsDark": { + "responsive": true, + "maintainAspectRatio": false, + "scales": { + "x": { + "grid": { "color": "rgba(255, 255, 255, 0.1)" }, + "ticks": { "color": "#E0E0E0" } + }, + "y": { + "grid": { "color": "rgba(255, 255, 255, 0.1)" }, + "ticks": { "color": "#E0E0E0" } + } }, - "historyChartConfig": { - "chartOptionsDark": { - "responsive": true, - "maintainAspectRatio": false, - "scales": { - "x": { - "grid": { - "color": "rgba(255, 255, 255, 0.1)" - }, - "ticks": { - "color": "#E0E0E0" - } - }, - "y": { - "grid": { - "color": "rgba(255, 255, 255, 0.1)" - }, - "ticks": { - "color": "#E0E0E0" - } - } - }, - "plugins": { - "legend": { - "display": false - } - } - }, - "chartOptionsLight": { - "responsive": true, - "maintainAspectRatio": false, - "scales": { - "x": { - "grid": { - "color": "rgba(0, 0, 0, 0.1)" - }, - "ticks": { - "color": "#333" - } - }, - "y": { - "grid": { - "color": "rgba(0, 0, 0, 0.1)" - }, - "ticks": { - "color": "#333" - } - } - }, - "plugins": { - "legend": { - "display": false - } - } - } - } + "plugins": { "legend": { "display": false } } + }, + "chartOptionsLight": { + "responsive": true, + "maintainAspectRatio": false, + "scales": { + "x": { + "grid": { "color": "rgba(0, 0, 0, 0.1)" }, + "ticks": { "color": "#333" } + }, + "y": { + "grid": { "color": "rgba(0, 0, 0, 0.1)" }, + "ticks": { "color": "#333" } + } + }, + "plugins": { "legend": { "display": false } } + } } -} \ No newline at end of file + } +} diff --git a/frontend/public/images/favicon.ico b/frontend/public/images/favicon.ico index 859b5ae..25efbeb 100644 Binary files a/frontend/public/images/favicon.ico and b/frontend/public/images/favicon.ico differ diff --git a/frontend/public/images/logo.png b/frontend/public/images/logo.png index b66b936..0c3ac2a 100644 Binary files a/frontend/public/images/logo.png and b/frontend/public/images/logo.png differ diff --git a/frontend/src/components/App.jsx b/frontend/src/App.jsx similarity index 64% rename from frontend/src/components/App.jsx rename to frontend/src/App.jsx index be449d7..6534b1e 100644 --- a/frontend/src/components/App.jsx +++ b/frontend/src/App.jsx @@ -5,10 +5,11 @@ import 'bootstrap/dist/js/bootstrap.bundle.min.js' import Home from '@/pages/Home.jsx' import Dashboard from '@/pages/Dashboard.jsx' -import MenuButton from './MenuButton.jsx' -import SideMenu from './SideMenu.jsx' -import ThemeButton from '@/components/ThemeButton.jsx' -import Header from '@/components/Header.jsx' +import MenuButton from '@/components/layout/MenuButton.jsx' +import SideMenu from '@/components/layout/SideMenu.jsx' +import ThemeButton from '@/components/layout/ThemeButton.jsx' +import Header from '@/components/layout/Header.jsx' +import GroupView from '@/pages/GroupView.jsx' import { Routes, Route } from 'react-router-dom' import { useState } from 'react' @@ -30,10 +31,11 @@ const App = () => {
-
+
} /> - } /> + } /> + } />
diff --git a/frontend/src/components/HistoryCharts.jsx b/frontend/src/components/HistoryCharts.jsx index 2982fb1..a217207 100644 --- a/frontend/src/components/HistoryCharts.jsx +++ b/frontend/src/components/HistoryCharts.jsx @@ -1,6 +1,6 @@ import { Line } from "react-chartjs-2"; import { Chart as ChartJS, LineElement, PointElement, LinearScale, CategoryScale, Filler } from "chart.js"; -import CardContainer from "./CardContainer"; +import CardContainer from "./layout/CardContainer"; import "@/css/HistoryCharts.css"; import PropTypes from "prop-types"; @@ -11,26 +11,29 @@ import { useConfig } from "@/hooks/useConfig"; ChartJS.register(LineElement, PointElement, LinearScale, CategoryScale, Filler); -const HistoryCharts = () => { - const { config, configLoading, configError } = useConfig(); - - if (configLoading) return

Cargando configuraci贸n...

; - if (configError) return

Error al cargar configuraci贸n: {configError}

; - if (!config) return

Configuraci贸n no disponible.

; +const HistoryCharts = ({ groupId, deviceId }) => { + const { config, configLoading, configError } = useConfig(); - const BASE = config.appConfig.endpoints.DATA_URL; - const ENDPOINT = config.appConfig.endpoints.GET_SENSORS; + if (configLoading) return

Cargando configuraci贸n...

; + if (configError) return

Error al cargar configuraci贸n: {configError}

; + if (!config) return

Configuraci贸n no disponible.

; - const reqConfig = { - baseUrl: `${BASE}${ENDPOINT}`, - params: {} - } + const BASE = config.appConfig.endpoints.DATA_URL; + const ENDPOINT = config.appConfig.endpoints.GET_DEVICE_HISTORY; + const endp = ENDPOINT + .replace(':groupId', groupId) + .replace(':deviceId', deviceId); // si tu endpoint lo necesita - return ( - - - - ); + const reqConfig = { + baseUrl: `${BASE}${endp}`, + params: {} + }; + + return ( + + + + ); }; const HistoryChartsContent = () => { @@ -92,6 +95,11 @@ const HistoryChartsContent = () => { ); }; +HistoryCharts.propTypes = { + groupId: PropTypes.string.isRequired, + deviceId: PropTypes.string.isRequired +}; + HistoryChartsContent.propTypes = { options: PropTypes.object, timeLabels: PropTypes.array, diff --git a/frontend/src/components/LoadingIcon.jsx b/frontend/src/components/LoadingIcon.jsx new file mode 100644 index 0000000..e877e43 --- /dev/null +++ b/frontend/src/components/LoadingIcon.jsx @@ -0,0 +1,10 @@ +import { faSpinner } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; + +const LoadingIcon = () => { + return ( + + ); +} + +export default LoadingIcon; \ No newline at end of file diff --git a/frontend/src/components/PollutionMap.jsx b/frontend/src/components/PollutionMap.jsx index 6a794a7..cd640cd 100644 --- a/frontend/src/components/PollutionMap.jsx +++ b/frontend/src/components/PollutionMap.jsx @@ -39,29 +39,32 @@ const PollutionCircles = ({ data }) => { }); }; -const PollutionMap = ({ deviceId }) => { - const { config, configLoading, configError } = useConfig(); - - if (configLoading) return

Cargando configuraci贸n...

; - if (configError) return

Error al cargar configuraci贸n: {configError}

; - if (!config) return

Configuraci贸n no disponible.

; +const PollutionMap = ({ groupId, deviceId }) => { + const { config, configLoading, configError } = useConfig(); - const BASE = config.appConfig.endpoints.LOGIC_URL; - const ENDPOINT = config.appConfig.endpoints.GET_DEVICE_POLLUTION_MAP; - let endp = ENDPOINT.replace('{0}', deviceId); + if (configLoading) return

Cargando configuraci贸n...

; + if (configError) return

Error al cargar configuraci贸n: {configError}

; + if (!config) return

Configuraci贸n no disponible.

; - const reqConfig = { - baseUrl: `${BASE}${endp}`, - params: {} - } + const BASE = config.appConfig.endpoints.LOGIC_URL; + const ENDPOINT = config.appConfig.endpoints.GET_DEVICE_POLLUTION_MAP; + const endp = ENDPOINT + .replace(':groupId', groupId) + .replace(':deviceId', deviceId); - return ( - - - - ); + const reqConfig = { + baseUrl: `${BASE}${endp}`, + params: {} + }; + + return ( + + + + ); }; + const PollutionMapContent = () => { const { config, configLoading, configError } = useConfig(); const { data, dataLoading, dataError } = useDataContext(); @@ -102,6 +105,7 @@ const mapStyles = { }; PollutionMap.propTypes = { + groupId: PropTypes.number.isRequired, deviceId: PropTypes.number.isRequired }; diff --git a/frontend/src/components/SummaryCards.jsx b/frontend/src/components/SummaryCards.jsx index 427e8a7..ec30a24 100644 --- a/frontend/src/components/SummaryCards.jsx +++ b/frontend/src/components/SummaryCards.jsx @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import CardContainer from './CardContainer'; +import CardContainer from './layout/CardContainer'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faCloud, faClock, faTemperature0, faWater } from '@fortawesome/free-solid-svg-icons'; @@ -10,7 +10,7 @@ import { useDataContext } from '@/hooks/useDataContext'; import { useConfig } from '@/hooks/useConfig.js'; import { DateParser } from '@/util/dateParser'; -const SummaryCards = ({ deviceId }) => { +const SummaryCards = ({ groupId, deviceId }) => { const { config, configLoading, configError } = useConfig(); if (configLoading) return

Cargando configuraci贸n...

; @@ -19,19 +19,21 @@ const SummaryCards = ({ deviceId }) => { const BASE = config.appConfig.endpoints.LOGIC_URL; const ENDPOINT = config.appConfig.endpoints.GET_DEVICE_LATEST_VALUES; - const endp = ENDPOINT.replace('{0}', deviceId); + const endp = ENDPOINT + .replace(':groupId', groupId) + .replace(':deviceId', deviceId); // solo si lo necesitas as铆 const reqConfig = { baseUrl: `${BASE}${endp}`, params: {} - } + }; return ( ); -} +}; const SummaryCardsContent = () => { const { data, dataLoading, dataError } = useDataContext(); @@ -71,6 +73,7 @@ const SummaryCardsContent = () => { } SummaryCards.propTypes = { + groupId: PropTypes.string.isRequired, deviceId: PropTypes.number.isRequired }; diff --git a/frontend/src/components/Card.jsx b/frontend/src/components/layout/Card.jsx similarity index 100% rename from frontend/src/components/Card.jsx rename to frontend/src/components/layout/Card.jsx diff --git a/frontend/src/components/CardContainer.jsx b/frontend/src/components/layout/CardContainer.jsx similarity index 59% rename from frontend/src/components/CardContainer.jsx rename to frontend/src/components/layout/CardContainer.jsx index 6f57d68..2271a41 100644 --- a/frontend/src/components/CardContainer.jsx +++ b/frontend/src/components/layout/CardContainer.jsx @@ -1,19 +1,29 @@ import Card from "./Card.jsx"; import PropTypes from "prop-types"; +import { Link } from "react-router-dom"; -const CardContainer = ({ cards, className }) => { +const CardContainer = ({ links, cards, className }) => { return (
{cards.map((card, index) => ( + links ? ( + + +

{card.content}

+
+ + ) : (

{card.content}

+ ) ))}
); }; CardContainer.propTypes = { + links: Boolean, cards: PropTypes.arrayOf( PropTypes.shape({ title: PropTypes.string.isRequired, diff --git a/frontend/src/components/Header.jsx b/frontend/src/components/layout/Header.jsx similarity index 68% rename from frontend/src/components/Header.jsx rename to frontend/src/components/layout/Header.jsx index 2cd5da3..57ec2a2 100644 --- a/frontend/src/components/Header.jsx +++ b/frontend/src/components/layout/Header.jsx @@ -2,19 +2,18 @@ import PropTypes from 'prop-types'; import '@/css/Header.css'; import { useTheme } from "@/hooks/useTheme"; -const Header = (props) => { +const Header = ({ subtitle }) => { const { theme } = useTheme(); return (
-

{props.title}

-

{props.subtitle}

+ +

{subtitle}

); } Header.propTypes = { - title: PropTypes.string.isRequired, subtitle: PropTypes.string } diff --git a/frontend/src/components/MenuButton.jsx b/frontend/src/components/layout/MenuButton.jsx similarity index 100% rename from frontend/src/components/MenuButton.jsx rename to frontend/src/components/layout/MenuButton.jsx diff --git a/frontend/src/components/SideMenu.jsx b/frontend/src/components/layout/SideMenu.jsx similarity index 85% rename from frontend/src/components/SideMenu.jsx rename to frontend/src/components/layout/SideMenu.jsx index 5e0c938..f7e311a 100644 --- a/frontend/src/components/SideMenu.jsx +++ b/frontend/src/components/layout/SideMenu.jsx @@ -9,6 +9,8 @@ import { useDataContext } from "@/hooks/useDataContext"; import { useConfig } from '@/hooks/useConfig.js'; import { useTheme } from "@/hooks/useTheme"; +import { Link } from 'react-router-dom'; + import Card from './Card'; const SideMenu = ({ isOpen, onClose }) => { @@ -19,7 +21,7 @@ const SideMenu = ({ isOpen, onClose }) => { if (!config) return

Configuraci贸n no disponible.

; const BASE = config.appConfig.endpoints.DATA_URL; - const ENDPOINT = config.appConfig.endpoints.GET_DEVICES; + const ENDPOINT = config.appConfig.endpoints.GET_GROUPS; const reqConfig = { baseUrl: `${BASE}${ENDPOINT}`, @@ -51,18 +53,18 @@ const SideMenuContent = ({ isOpen, onClose }) => {
- {data.map(device => { + {data.map(group => { return ( - + {[]} - + ); })}
diff --git a/frontend/src/components/ThemeButton.jsx b/frontend/src/components/layout/ThemeButton.jsx similarity index 100% rename from frontend/src/components/ThemeButton.jsx rename to frontend/src/components/layout/ThemeButton.jsx diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index d01e062..931e19b 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -2,7 +2,7 @@ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import { BrowserRouter } from 'react-router-dom' import './css/index.css' -import App from './components/App.jsx' +import App from './App.jsx' import { ThemeProvider } from './context/ThemeContext.jsx' import { ConfigProvider } from './context/ConfigContext.jsx' diff --git a/frontend/src/pages/Dashboard.jsx b/frontend/src/pages/Dashboard.jsx index e1938fb..f5ca237 100644 --- a/frontend/src/pages/Dashboard.jsx +++ b/frontend/src/pages/Dashboard.jsx @@ -4,32 +4,16 @@ import SummaryCards from '@/components/SummaryCards.jsx' import { useParams } from 'react-router-dom'; -/** - * Dashboard.jsx - * - * Este archivo define el componente Dashboard, que es el panel de control de un device. - * - * Importaciones: - * - PollutionMap: Un componente que muestra un mapa de la contaminaci贸n. - * - HistoryCharts: Un componente que muestra gr谩ficos hist贸ricos de la contaminaci贸n. - * - SummaryCards: Un componente que muestra tarjetas resumen con informaci贸n relevante. - * - * Funcionalidad: - * - El componente Home utiliza una estructura de JSX para organizar y renderizar los componentes importados. - * - El componente Dashboard contiene los componentes SummaryCards, PollutionMap y HistoryCharts. - * - */ - const Dashboard = () => { - const { deviceId } = useParams(); + const { groupId, deviceId } = useParams(); return (
- - - + + +
); -} +}; export default Dashboard; diff --git a/frontend/src/pages/GroupView.jsx b/frontend/src/pages/GroupView.jsx new file mode 100644 index 0000000..7defdb5 --- /dev/null +++ b/frontend/src/pages/GroupView.jsx @@ -0,0 +1,49 @@ +import CardContainer from "@/components/layout/CardContainer"; +import LoadingIcon from "@/components/LoadingIcon"; + +import { useParams } from "react-router-dom"; +import { useConfig } from "@/hooks/useConfig"; +import { useDataContext } from "@/hooks/useDataContext"; + +import { DataProvider } from "@/context/DataContext"; + +const GroupView = () => { + const { groupId } = useParams(); + const { config, configLoading } = useConfig(); + + if (configLoading || !config) return

; + + const replacedEndpoint = config.appConfig.endpoints.GET_GROUP_DEVICES.replace(':groupId', groupId); + const reqConfig = { + baseUrl: `${config.appConfig.endpoints.DATA_URL}${replacedEndpoint}`, + }; + + return ( + + + + ); +} + +const GroupViewContent = () => { + const { data, dataLoading, dataError } = useDataContext(); + const { groupId } = useParams(); + + if (dataLoading) return

; + if (dataError) return

Error al cargar datos: {dataError}

; + + return ( + ({ + title: device.deviceName, + status: `ID: ${device.deviceId}`, + to: `/groups/${groupId}/devices/${device.deviceId}`, + styleMode: "override", + className: "col-12 col-md-6 col-lg-4", + }))} + /> + ); +} + +export default GroupView; \ No newline at end of file