Sensor Data Visualization - Copy this React, Tailwind Component to your project
Import React, { useState } from 'react'; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, Brush } from 'recharts'; export const SensorDataVisualization = () => { const [fechaInicio, setFechaInicio] = useState(''); const [sensores, setSensores] = useState([ { id: 1, nombre: 'Sensor 1', tipo: 'Temperatura', data: [], visible: true }, { id: 2, nombre: 'Sensor 2', tipo: 'Humedad', data: [], visible: true }, { id: 2, nombre: 'Sensor 3', tipo: 'Humedad', data: [], visible: true }, ]); const [sensorSeleccionado, setSensorSeleccionado] = useState(sensores[0]); const [dataZoom, setDataZoom] = useState([]); const [startX, setStartX] = useState(null); const [endX, setEndX] = useState(null); const handleAddData = () => { const fecha = new Date(fechaInicio); const mesAtras = new Date(fecha.getFullYear(), fecha.getMonth() 1, fecha.getDate()); const datos = []; for (let i = 0; i < 30; i++) { const fechaActual = new Date(mesAtras.getTime() + i * 24 * 60 * 60 * 1000); const fechaString = fechaActual.toISOString().split('T')[0]; if (sensorSeleccionado.tipo === 'Temperatura') { datos.push({ date: fechaString, temperatura: Math.random() * 30, humedad: 0 }); } else { datos.push({ date: fechaString, temperatura: 0, humedad: Math.random() * 100 }); } } const nuevosSensores = sensores.map((s) => { if (s.id === sensorSeleccionado.id) { return { ...s, data: [...s.data, ...datos] }; } return s; }); setSensores(nuevosSensores); }; const handleResetData = () => { const nuevosSensores = sensores.map((s) => ({ ...s, data: [] })); setSensores(nuevosSensores); }; const handleExportToCsv = () => { const csvContent = sensorSeleccionado.data.map((item) => Object.values(item).join(',')).join('\n'); const csvBlob = new Blob([csvContent], { type: 'text/csv' }); const csvUrl = URL.createObjectURL(csvBlob); const csvLink = document.createElement('a'); csvLink.href = csvUrl; csvLink.download = 'temperatura_humedad.csv'; csvLink.click(); }; const handleZoom = (range) => { if (range.length > 0) { const startIndex = sensorSeleccionado.data.findIndex((item) => item.date === range[0].date); const endIndex = sensorSeleccionado.data.findIndex((item) => item.date === range[1].date); setDataZoom(sensorSeleccionado.data.slice(startIndex, endIndex + 1)); } else { setDataZoom([]); } }; const handleToggleSensor = (id) => { const nuevosSensores = sensores.map((s) => { if (s.id === id) { return { ...s, visible: !s.visible }; } return s; }); setSensores(nuevosSensores); }; const datosGrafica = sensores.reduce((acumulado, s) => [...acumulado, ...s.data], []); return ( <div className="max w 6xl mx auto p 4"> <h2 className="text 2xl font bold mb 4">Gráfica de Temperatura y Humedad</h2> <div className="flex flex wrap justify center mb 4"> <input type="date" value={fechaInicio} onChange={(e) => setFechaInicio(e.target.value)} placeholder="Fecha de inicio" className="w full md:w 1/3 p 2 pl 10 text sm text gray 700 border border gray 300 rounded" /> <select value={sensorSeleccionado.id} onChange={(e) => setSensorSeleccionado(sensores.find((s) => s.id === parseInt(e.target.value)))} className="w full md:w 1/3 p 2 pl 10 text sm text gray 700 border border gray 300 rounded" > {sensores.map((s) => ( <option key={s.id} value={s.id}> {s.nombre} ({s.tipo}) </option> ))} </select> <button onClick={handleAddData} className="bg green 500 hover:bg green 700 text white font bold py 2 px 4 rounded mx 2" > Agregar datos </button> <button onClick={handleResetData} className="bg red 500 hover:bg red 700 text white font bold py 2 px 4 rounded mx 2" > Resetear </button> <button onClick={handleExportToCsv} className="bg blue 500 hover:bg blue 700 text white font bold py 2 px 4 rounded mx 2" > Exportar a CSV </button> </div> <div className="flex flex wrap justify center mb 4"> {sensores.map((s) => ( <div key={s.id} className="mx 2"> <input type="checkbox" checked={s.visible} onChange={() => handleToggleSensor(s.id)} className="mr 2" /> <span>{s.nombre} ({s.tipo})</span> </div> ))} </div> <LineChart width={800} height={400} data={datosGrafica}> <CartesianGrid strokeDasharray="3 3" /> <XAxis dataKey="date" /> <YAxis unit={'ºC'} /> <YAxis unit={'%Hr'} orientation="right" /> <Tooltip /> <Legend /> {sensores.map((s) => ( <Line key={s.id} type="monotone" dataKey={s.tipo === 'Temperatura' ? 'temperatura' : 'humedad'} stroke={s.tipo === 'Temperatura' ? '#8884d8' : '#82ca9d'} activeDot={{ r: 8 }} hide={!s.visible} /> ))} <Brush dataKey="date" height={30} stroke="#8884d8" onChange={(range) => handleZoom(range)} /> </LineChart> </div> ); };
