bar graph fix

This commit is contained in:
Jack Mechem 2026-05-22 15:10:54 -07:00
parent 43318fb8cd
commit 8c3d749197
15 changed files with 973 additions and 401 deletions

View file

@ -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>