Electricity Monitor - Copy this React, Tailwind Component to your project
Import React, { useState, useEffect } from "react"; import { Line } from "react chartjs 2"; import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend } from "chart.js"; import { FaPowerOff, FaWifi, FaExclamationTriangle, FaBolt, FaChartLine, FaHistory } from "react icons/fa"; ChartJS.register( CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend ); const ElectricityMonitor = () => { const [meterStatus, setMeterStatus] = useState("online"); const [currentRate, setCurrentRate] = useState(0.12); const [viewMode, setViewMode] = useState("daily"); const [startDate, setStartDate] = useState(""); const [endDate, setEndDate] = useState(""); const [communicationStatus, setCommunicationStatus] = useState("connected"); const dummyData = { daily: { labels: ["00:00", "04:00", "08:00", "12:00", "16:00", "20:00", "23:59"], values: [2.5, 1.8, 3.2, 4.5, 3.8, 5.2, 4.1] }, weekly: { labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], values: [25.5, 28.8, 22.2, 24.5, 26.8, 30.2, 27.1] }, monthly: { labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"], values: [750, 680, 820, 790, 840, 910] } }; const chartData = { labels: dummyData[viewMode].labels, datasets: [ { label: "Electricity Usage (kWh)", data: dummyData[viewMode].values, borderColor: "rgb(6, 182, 212)", backgroundColor: "rgba(6, 182, 212, 0.1)", tension: 0.4, fill: true } ] }; const chartOptions = { responsive: true, plugins: { legend: { position: "top", labels: { color: "#e2e8f0" } }, title: { display: true, text: `${viewMode.charAt(0).toUpperCase() + viewMode.slice(1)} Electricity Usage`, color: "#e2e8f0" } }, scales: { y: { grid: { color: "rgba(148, 163, 184, 0.1)" }, ticks: { color: "#e2e8f0" } }, x: { grid: { color: "rgba(148, 163, 184, 0.1)" }, ticks: { color: "#e2e8f0" } } } }; const calculateIntervalCost = () => { const usage = dummyData[viewMode].values.reduce((a, b) => a + b, 0); return (usage * currentRate).toFixed(2); }; const totalUsage = dummyData[viewMode].values.reduce((a, b) => a + b, 0); return ( <div className="min h screen bg slate 900 text slate 200"> <header className="bg slate 800 shadow lg border b border cyan 500/20 p 6"> <div className="container mx auto"> <div className="flex justify between items center"> <div> <h1 className="text 3xl font bold text cyan 400 flex items center gap 2"> <FaBolt className="text cyan 400" /> 智慧電表: 套房001 </h1> <div className="flex items center mt 2"> <FaPowerOff className={`mr 2 ${meterStatus === "online" ? "text emerald 400" : "text red 400"}`} /> <span className="capitalize">{meterStatus}</span> </div> </div> <div className="text right"> <p className="text sm text slate 400">Last Updated:</p> <p className="font semibold text cyan 400">{new Date().toLocaleString()}</p> </div> </div> </div> </header> <main className="container mx auto py 8 px 4"> <section className="grid grid cols 1 md:grid cols 2 gap 6 mb 8"> <div className="bg slate 800 p 6 rounded lg shadow xl border border cyan 500/20 hover:border cyan 500/40 transition all"> <h2 className="text xl font semibold mb 4 flex items center gap 2"> <FaBolt /> 用電量 </h2> <div className="text 4xl font bold text cyan 400 mb 4"> {dummyData[viewMode].values[dummyData[viewMode].values.length 1]} kWh </div> <div className="flex items center space x 4"> <label className="text slate 300">電價 (元/kWh):</label> <input type="number" value={currentRate} onChange={(e) => setCurrentRate(parseFloat(e.target.value))} step="0.01" className="bg slate 700 border border slate 600 rounded px 2 py 1 w 24 text cyan 400 focus:outline none focus:border cyan 500" /> </div> </div> <div className="bg slate 800 p 6 rounded lg shadow xl border border cyan 500/20 hover:border cyan 500/40 transition all"> <h2 className="text xl font semibold mb 4 flex items center gap 2"> <FaChartLine /> 累積用電量 </h2> <div className="text 4xl font bold text emerald 400 mb 4"> {totalUsage.toFixed(2)} kWh </div> <p className="text slate 300"> Estimated Cost: <span className="text emerald 400">${(totalUsage * currentRate).toFixed(2)}</span> </p> </div> </section> <section className="bg slate 800 p 6 rounded lg shadow xl border border cyan 500/20 hover:border cyan 500/40 transition all mb 8"> <div className="flex justify between items center mb 6"> <h2 className="text xl font semibold flex items center gap 2"> <FaChartLine /> 用電區間與篩選 </h2> <div className="flex space x 2"> {["daily", "weekly", "monthly"].map((mode) => ( <button key={mode} onClick={() => setViewMode(mode)} className={`px 4 py 2 rounded md transition all ${viewMode === mode ? "bg cyan 500 text white" : "bg slate 700 hover:bg slate 600"}`} > {mode.charAt(0).toUpperCase() + mode.slice(1)} </button> ))} </div> </div> <div className="flex flex wrap gap 4 mb 6"> <div> <label className="block text slate 300 mb 1">篩選日期:</label> <input type="date" value={startDate} onChange={(e) => setStartDate(e.target.value)} className="bg slate 700 border border slate 600 rounded px 3 py 2 text cyan 400 focus:outline none focus:border cyan 500" /> <input type="date" value={endDate} onChange={(e) => setEndDate(e.target.value)} className="bg slate 700 border border slate 600 rounded px 3 py 2 text cyan 400 focus:outline none focus:border cyan 500" /> </div> </div> <div className="text slate 300 mt 4"> 區間電費: <span className="text emerald 400">${calculateIntervalCost()}</span> </div> <div className="h [400px] mt 6
