moved ConfigProvider up in the hierarchy (to main.jsx) to wrap the whole App
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -25,3 +25,6 @@ frontend/*.sw?
|
|||||||
|
|
||||||
# Do not commit _pycache_ directories
|
# Do not commit _pycache_ directories
|
||||||
backend/__pycache__/
|
backend/__pycache__/
|
||||||
|
backend/endpoints/__pycache__/
|
||||||
|
backend/models/schemas/__pycache__/
|
||||||
|
backend/models/sql/__pycache__/
|
||||||
@@ -1 +1,4 @@
|
|||||||
|
# esto esta aqui porque es un entorno local
|
||||||
|
# y además un usuario y contraseña bastante
|
||||||
|
# genéricos
|
||||||
DB_URL = "mysql+aiomysql://root:root@localhost:3306/DAD"
|
DB_URL = "mysql+aiomysql://root:root@localhost:3306/DAD"
|
||||||
@@ -4,4 +4,5 @@ contextlib2
|
|||||||
dotenv
|
dotenv
|
||||||
pydantic
|
pydantic
|
||||||
sqlalchemy
|
sqlalchemy
|
||||||
db
|
databases
|
||||||
|
aiomysql
|
||||||
|
|||||||
@@ -6,6 +6,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"appConfig": {
|
"appConfig": {
|
||||||
|
"endpoints": {
|
||||||
|
"baseUrl": "http://localhost:8080/api/v1",
|
||||||
|
"sensors": "sensors",
|
||||||
|
"sensor": "sensors/sensor"
|
||||||
|
},
|
||||||
"historyChartConfig": {
|
"historyChartConfig": {
|
||||||
"timeLabels": [
|
"timeLabels": [
|
||||||
"08:00",
|
"08:00",
|
||||||
|
|||||||
@@ -3,16 +3,13 @@ import 'leaflet/dist/leaflet.css'
|
|||||||
import 'bootstrap/dist/css/bootstrap.min.css'
|
import 'bootstrap/dist/css/bootstrap.min.css'
|
||||||
import 'bootstrap/dist/js/bootstrap.bundle.min.js'
|
import 'bootstrap/dist/js/bootstrap.bundle.min.js'
|
||||||
|
|
||||||
import { ThemeProvider } from '../contexts/ThemeContext.jsx'
|
|
||||||
|
|
||||||
import Home from '../pages/Home.jsx'
|
import Home from '../pages/Home.jsx'
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ThemeProvider>
|
{/* Planeo añadir un React Router */}
|
||||||
<Home />
|
<Home />
|
||||||
</ThemeProvider>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,16 +6,28 @@ import PropTypes from "prop-types";
|
|||||||
|
|
||||||
import { useTheme } from "../contexts/ThemeContext.jsx";
|
import { useTheme } from "../contexts/ThemeContext.jsx";
|
||||||
import { DataProvider, useData } from "../contexts/DataContext.jsx";
|
import { DataProvider, useData } from "../contexts/DataContext.jsx";
|
||||||
import { ConfigProvider, useConfig } from "../contexts/ConfigContext.jsx";
|
import { useConfig } from "../contexts/ConfigContext.jsx";
|
||||||
|
|
||||||
ChartJS.register(LineElement, PointElement, LinearScale, CategoryScale, Filler);
|
ChartJS.register(LineElement, PointElement, LinearScale, CategoryScale, Filler);
|
||||||
|
|
||||||
const HistoryCharts = () => {
|
const HistoryCharts = () => {
|
||||||
|
const { config, configLoading, configError } = useConfig();
|
||||||
|
|
||||||
|
if (configLoading) return <p>Cargando configuración...</p>;
|
||||||
|
if (configError) return <p>Error al cargar configuración: {configError}</p>;
|
||||||
|
if (!config) return <p>Configuración no disponible.</p>;
|
||||||
|
|
||||||
|
const BASE = config.appConfig.endpoints.baseUrl;
|
||||||
|
const ENDPOINT = config.appConfig.endpoints.sensors;
|
||||||
|
|
||||||
|
const reqConfig = {
|
||||||
|
baseUrl: `${BASE}/${ENDPOINT}`,
|
||||||
|
params: {}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataProvider apiUrl="https://contaminus.miarma.net/api/v1/sensors">
|
<DataProvider config={reqConfig}>
|
||||||
<ConfigProvider>
|
<HistoryChartsContent />
|
||||||
<HistoryChartsContent />
|
|
||||||
</ConfigProvider>
|
|
||||||
</DataProvider>
|
</DataProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { MapContainer, TileLayer, Circle, Popup } from 'react-leaflet';
|
import { MapContainer, TileLayer, Circle, Popup } from 'react-leaflet';
|
||||||
|
|
||||||
|
|
||||||
import { ConfigProvider } from '../contexts/ConfigContext.jsx';
|
|
||||||
import { useConfig } from '../contexts/ConfigContext.jsx';
|
import { useConfig } from '../contexts/ConfigContext.jsx';
|
||||||
|
|
||||||
import { DataProvider } from '../contexts/DataContext.jsx';
|
import { DataProvider } from '../contexts/DataContext.jsx';
|
||||||
@@ -41,23 +39,41 @@ const PollutionCircles = ({ data }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const PollutionMap = () => {
|
const PollutionMap = () => {
|
||||||
|
const { config, configLoading, configError } = useConfig();
|
||||||
|
|
||||||
|
if (configLoading) return <p>Cargando configuración...</p>;
|
||||||
|
if (configError) return <p>Error al cargar configuración: {configError}</p>;
|
||||||
|
if (!config) return <p>Configuración no disponible.</p>;
|
||||||
|
|
||||||
|
const BASE = config.appConfig.endpoints.baseUrl;
|
||||||
|
const ENDPOINT = config.appConfig.endpoints.sensors;
|
||||||
|
|
||||||
|
const reqConfig = {
|
||||||
|
baseUrl: `${BASE}/${ENDPOINT}`,
|
||||||
|
params: {}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataProvider apiUrl="https://contaminus.miarma.net/api/v1/sensors">
|
<DataProvider config={reqConfig}>
|
||||||
<ConfigProvider>
|
<PollutionMapContent />
|
||||||
<PollutionMapContent />
|
|
||||||
</ConfigProvider>
|
|
||||||
</DataProvider>
|
</DataProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const PollutionMapContent = () => {
|
const PollutionMapContent = () => {
|
||||||
const { config } = useConfig();
|
const { config, configLoading, configError } = useConfig();
|
||||||
|
const { data, dataLoading, dataError } = useData();
|
||||||
|
|
||||||
|
if (configLoading) return <p>Cargando configuración...</p>;
|
||||||
|
if (configError) return <p>Error al cargar configuración: {configError}</p>;
|
||||||
|
if (!config) return <p>Configuración no disponible.</p>;
|
||||||
|
|
||||||
|
if (dataLoading) return <p>Cargando datos...</p>;
|
||||||
|
if (dataError) return <p>Error al cargar datos: {configError}</p>;
|
||||||
|
if (!data) return <p>Datos no disponibles.</p>;
|
||||||
|
|
||||||
const SEVILLA = config?.userConfig.city;
|
const SEVILLA = config?.userConfig.city;
|
||||||
|
|
||||||
const { data, loading } = useData();
|
|
||||||
|
|
||||||
if (loading) return <p>Cargando datos...</p>;
|
|
||||||
|
|
||||||
const pollutionData = data.map((sensor) => ({
|
const pollutionData = data.map((sensor) => ({
|
||||||
lat: sensor.lat,
|
lat: sensor.lat,
|
||||||
lng: sensor.lon,
|
lng: sensor.lon,
|
||||||
|
|||||||
@@ -4,9 +4,28 @@ import CardContainer from './CardContainer';
|
|||||||
import { DataProvider } from '../contexts/DataContext';
|
import { DataProvider } from '../contexts/DataContext';
|
||||||
import { useData } from '../contexts/DataContext';
|
import { useData } from '../contexts/DataContext';
|
||||||
|
|
||||||
|
import { useConfig } from '../contexts/ConfigContext';
|
||||||
|
|
||||||
const SummaryCards = () => {
|
const SummaryCards = () => {
|
||||||
|
const { config, configLoading, configError } = useConfig();
|
||||||
|
|
||||||
|
if (configLoading) return <p>Cargando configuración...</p>;
|
||||||
|
if (configError) return <p>Error al cargar configuración: {configError}</p>;
|
||||||
|
if (!config) return <p>Configuración no disponible.</p>;
|
||||||
|
|
||||||
|
const BASE = config.appConfig.endpoints.baseUrl;
|
||||||
|
const ENDPOINT = config.appConfig.endpoints.sensors;
|
||||||
|
|
||||||
|
const reqConfig = {
|
||||||
|
baseUrl: `${BASE}/${ENDPOINT}`,
|
||||||
|
params: {
|
||||||
|
_sort: 'timestamp',
|
||||||
|
_order: 'desc'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataProvider apiUrl="https://contaminus.miarma.net/api/v1/sensors?_sort=timestamp&_order=desc">
|
<DataProvider config={reqConfig}>
|
||||||
<SummaryCardsContent />
|
<SummaryCardsContent />
|
||||||
</DataProvider>
|
</DataProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ const ConfigContext = createContext();
|
|||||||
|
|
||||||
export const ConfigProvider = ({ children }) => {
|
export const ConfigProvider = ({ children }) => {
|
||||||
const [config, setConfig] = useState(null);
|
const [config, setConfig] = useState(null);
|
||||||
const [loading, setLoading] = useState(true);
|
const [configLoading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState(null);
|
const [configError, setError] = useState(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchConfig = async () => {
|
const fetchConfig = async () => {
|
||||||
@@ -26,7 +26,7 @@ export const ConfigProvider = ({ children }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfigContext.Provider value={{ config, loading, error }}>
|
<ConfigContext.Provider value={{ config, configLoading, configError }}>
|
||||||
{children}
|
{children}
|
||||||
</ConfigContext.Provider>
|
</ConfigContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,15 +3,17 @@ import PropTypes from "prop-types";
|
|||||||
|
|
||||||
const DataContext = createContext();
|
const DataContext = createContext();
|
||||||
|
|
||||||
export const DataProvider = ({ children, apiUrl }) => {
|
export const DataProvider = ({ children, config }) => {
|
||||||
const [data, setData] = useState(null);
|
const [data, setData] = useState(null);
|
||||||
const [loading, setLoading] = useState(true);
|
const [dataLoading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState(null);
|
const [dataError, setError] = useState(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(apiUrl);
|
const queryParams = new URLSearchParams(config.params).toString();
|
||||||
|
const url = `${config.baseUrl}?${queryParams}`;
|
||||||
|
const response = await fetch(url);
|
||||||
if (!response.ok) throw new Error("Error al obtener datos");
|
if (!response.ok) throw new Error("Error al obtener datos");
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
setData(result);
|
setData(result);
|
||||||
@@ -23,10 +25,10 @@ export const DataProvider = ({ children, apiUrl }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fetchData();
|
fetchData();
|
||||||
}, [apiUrl]);
|
}, [config]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataContext.Provider value={{ data, loading, error }}>
|
<DataContext.Provider value={{ data, dataLoading, dataError }}>
|
||||||
{children}
|
{children}
|
||||||
</DataContext.Provider>
|
</DataContext.Provider>
|
||||||
);
|
);
|
||||||
@@ -34,7 +36,10 @@ export const DataProvider = ({ children, apiUrl }) => {
|
|||||||
|
|
||||||
DataProvider.propTypes = {
|
DataProvider.propTypes = {
|
||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
apiUrl: PropTypes.string.isRequired,
|
config: PropTypes.shape({
|
||||||
|
baseUrl: PropTypes.string.isRequired,
|
||||||
|
params: PropTypes.object,
|
||||||
|
}).isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useData = () => useContext(DataContext);
|
export const useData = () => useContext(DataContext);
|
||||||
@@ -39,6 +39,7 @@
|
|||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.card-text {
|
p.card-text {
|
||||||
|
|||||||
@@ -3,8 +3,15 @@ import { createRoot } from 'react-dom/client'
|
|||||||
import './css/index.css'
|
import './css/index.css'
|
||||||
import App from './components/App.jsx'
|
import App from './components/App.jsx'
|
||||||
|
|
||||||
|
import { ThemeProvider } from './contexts/ThemeContext.jsx'
|
||||||
|
import { ConfigProvider } from './contexts/ConfigContext.jsx'
|
||||||
|
|
||||||
createRoot(document.getElementById('root')).render(
|
createRoot(document.getElementById('root')).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<App />
|
<ThemeProvider>
|
||||||
|
<ConfigProvider>
|
||||||
|
<App />
|
||||||
|
</ConfigProvider>
|
||||||
|
</ThemeProvider>
|
||||||
</StrictMode>,
|
</StrictMode>,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ const Home = () => {
|
|||||||
<Dashboard>
|
<Dashboard>
|
||||||
<SummaryCards />
|
<SummaryCards />
|
||||||
<PollutionMap />
|
<PollutionMap />
|
||||||
{/* */}
|
|
||||||
<HistoryCharts />
|
<HistoryCharts />
|
||||||
</Dashboard>
|
</Dashboard>
|
||||||
<ThemeButton />
|
<ThemeButton />
|
||||||
|
|||||||
Reference in New Issue
Block a user