bar graph fix
This commit is contained in:
parent
43318fb8cd
commit
8c3d749197
15 changed files with 973 additions and 401 deletions
|
|
@ -7,6 +7,7 @@ import {
|
|||
} from "recharts";
|
||||
import { IconRefresh } from "@tabler/icons-react";
|
||||
import SideNav from "../components/SideNav";
|
||||
import HelpTooltip from "../components/HelpTooltip";
|
||||
|
||||
// ── Types ────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -406,20 +407,25 @@ export default function AnalyticsPage() {
|
|||
</div>
|
||||
|
||||
{/* Range picker */}
|
||||
<div className="flex flex-col gap-2 items-end">
|
||||
<div className="flex flex-col gap-1.5 items-end">
|
||||
<span className="text-[10px] font-medium text-foreground-sec">Time Range</span>
|
||||
<div className="flex gap-1 bg-secondary/50 rounded-xl p-1">
|
||||
{PRESETS.map(({ label, h }) => (
|
||||
<button key={h} onClick={() => { setPresetH(h); setAppliedRange(null); setShowCustom(false); }}
|
||||
className={"px-3 py-1.5 rounded-lg text-xs font-medium transition-colors cursor-pointer " +
|
||||
(!appliedRange && presetH === h ? "bg-blue text-white" : "text-foreground-sec hover:text-foreground")}>
|
||||
{label}
|
||||
</button>
|
||||
<HelpTooltip key={h} text={`Show data for the last ${label}.`}>
|
||||
<button onClick={() => { setPresetH(h); setAppliedRange(null); setShowCustom(false); }}
|
||||
className={"px-3 py-1.5 rounded-lg text-xs font-medium transition-colors cursor-pointer " +
|
||||
(!appliedRange && presetH === h ? "bg-blue text-white" : "text-foreground-sec hover:text-foreground")}>
|
||||
{label}
|
||||
</button>
|
||||
</HelpTooltip>
|
||||
))}
|
||||
<button onClick={() => setShowCustom(s => !s)}
|
||||
className={"px-3 py-1.5 rounded-lg text-xs font-medium transition-colors cursor-pointer " +
|
||||
(showCustom || appliedRange ? "bg-blue text-white" : "text-foreground-sec hover:text-foreground")}>
|
||||
Custom
|
||||
</button>
|
||||
<HelpTooltip text="Enter a custom date and time range to query exactly the data you want.">
|
||||
<button onClick={() => setShowCustom(s => !s)}
|
||||
className={"px-3 py-1.5 rounded-lg text-xs font-medium transition-colors cursor-pointer " +
|
||||
(showCustom || appliedRange ? "bg-blue text-white" : "text-foreground-sec hover:text-foreground")}>
|
||||
Custom
|
||||
</button>
|
||||
</HelpTooltip>
|
||||
</div>
|
||||
|
||||
{/* Custom date range picker */}
|
||||
|
|
@ -435,11 +441,13 @@ export default function AnalyticsPage() {
|
|||
<input type="datetime-local" value={customTo} onChange={e => setCustomTo(e.target.value)}
|
||||
className="bg-secondary/60 border border-secondary rounded-lg px-2 py-1 text-foreground text-xs outline-none focus:border-blue/60" />
|
||||
</div>
|
||||
<button
|
||||
onClick={() => { if (customFrom && customTo) { setAppliedRange({ from: customFrom, to: customTo }); setShowCustom(false); } }}
|
||||
className="px-3 py-1 bg-blue/10 border border-blue/30 text-blue rounded-lg font-medium hover:bg-blue/20 transition-colors cursor-pointer">
|
||||
Apply
|
||||
</button>
|
||||
<HelpTooltip text="Apply the selected custom date range to the chart.">
|
||||
<button
|
||||
onClick={() => { if (customFrom && customTo) { setAppliedRange({ from: customFrom, to: customTo }); setShowCustom(false); } }}
|
||||
className="px-3 py-1 bg-blue/10 border border-blue/30 text-blue rounded-lg font-medium hover:bg-blue/20 transition-colors cursor-pointer">
|
||||
Apply
|
||||
</button>
|
||||
</HelpTooltip>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -464,38 +472,54 @@ export default function AnalyticsPage() {
|
|||
{/* Chart card */}
|
||||
<div className="bg-primary border border-secondary rounded-2xl p-5 mb-8">
|
||||
{/* Controls row */}
|
||||
<div className="flex flex-wrap items-center justify-between gap-3 mb-4">
|
||||
<div className="flex items-center gap-3 flex-wrap">
|
||||
<div className="flex flex-wrap items-end justify-between gap-x-4 gap-y-3 mb-4">
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<h2 className="text-sm font-medium text-foreground">Power over time</h2>
|
||||
{deviceNames.map(name => {
|
||||
const active = activeDevices.has(name);
|
||||
const color = DEVICE_COLORS[name] ?? "#888";
|
||||
return (
|
||||
<button key={name} onClick={() => toggleDevice(name)}
|
||||
className="flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs font-medium transition-all cursor-pointer border"
|
||||
style={{ borderColor: active ? color + "55" : "transparent", background: active ? color + "18" : "transparent", color: active ? color : "var(--color-foreground-sec)" }}>
|
||||
<span className="w-2 h-2 rounded-full" style={{ background: active ? color : "var(--color-secondary)" }} />
|
||||
<span className="capitalize">{name}</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{isZoomed && (
|
||||
<button onClick={resetZoom}
|
||||
className="flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs font-medium text-foreground-sec hover:text-foreground border border-secondary hover:border-secondary/80 transition-colors cursor-pointer">
|
||||
<IconRefresh size={11} />
|
||||
Reset zoom
|
||||
</button>
|
||||
{deviceNames.length > 0 && (
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-[10px] font-medium text-foreground-sec">Devices</span>
|
||||
<div className="flex items-center gap-1.5 flex-wrap">
|
||||
{deviceNames.map(name => {
|
||||
const active = activeDevices.has(name);
|
||||
const color = DEVICE_COLORS[name] ?? "#888";
|
||||
return (
|
||||
<HelpTooltip key={name} text={`Toggle ${name} on or off in the chart.`}>
|
||||
<button onClick={() => toggleDevice(name)}
|
||||
className="flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs font-medium transition-all cursor-pointer border"
|
||||
style={{ borderColor: active ? color + "55" : "transparent", background: active ? color + "18" : "transparent", color: active ? color : "var(--color-foreground-sec)" }}>
|
||||
<span className="w-2 h-2 rounded-full" style={{ background: active ? color : "var(--color-secondary)" }} />
|
||||
<span className="capitalize">{name}</span>
|
||||
</button>
|
||||
</HelpTooltip>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex gap-0.5 bg-secondary/50 rounded-lg p-0.5">
|
||||
{(["line", "bar", "candle"] as ChartType[]).map(type => (
|
||||
<button key={type} onClick={() => { setChartType(type); resetZoom(); }}
|
||||
className={"px-3 py-1 rounded-md text-xs font-medium transition-colors cursor-pointer capitalize " +
|
||||
(chartType === type ? "bg-primary text-foreground shadow-sm" : "text-foreground-sec hover:text-foreground")}>
|
||||
{type}
|
||||
</div>
|
||||
<div className="flex items-end gap-3">
|
||||
{isZoomed && (
|
||||
<HelpTooltip text="Reset the chart zoom back to the full selected time range.">
|
||||
<button onClick={resetZoom}
|
||||
className="flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs font-medium text-foreground-sec hover:text-foreground border border-secondary hover:border-secondary/80 transition-colors cursor-pointer">
|
||||
<IconRefresh size={11} />
|
||||
Reset zoom
|
||||
</button>
|
||||
))}
|
||||
</HelpTooltip>
|
||||
)}
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-[10px] font-medium text-foreground-sec">Chart Type</span>
|
||||
<div className="flex gap-0.5 bg-secondary/50 rounded-lg p-0.5">
|
||||
{(["line", "bar", "candle"] as ChartType[]).map(type => (
|
||||
<HelpTooltip key={type} text={type === "line" ? "Line chart: shows power over time as a smooth curve." : type === "bar" ? "Bar chart: shows aggregated energy per time bucket." : "Candlestick chart: shows min/max/open/close power per period."}>
|
||||
<button onClick={() => { setChartType(type); resetZoom(); }}
|
||||
className={"px-3 py-1 rounded-md text-xs font-medium transition-colors cursor-pointer capitalize " +
|
||||
(chartType === type ? "bg-primary text-foreground shadow-sm" : "text-foreground-sec hover:text-foreground")}>
|
||||
{type}
|
||||
</button>
|
||||
</HelpTooltip>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue