import { useEffect, useState } from "react";
import { formatQuantity, meterDef } from "~/lib/meters";
import type { MeterDef } from "~/lib/meters";
type Day = { day: string; meter: string; quantity: number };
function daysOf(period: string): string[] {
const [year, month] = period.split("-").map(Number);
const count = new Date(Date.UTC(year, month, 0)).getUTCDate();
return Array.from({ length: count }, (_, index) => `${period}-${String(index + 1).padStart(2, "0")}`);
}
const LABEL_DAYS = new Set([1, 8, 15, 22]);
/**
* Daily usage of one meter across the whole billing period: one slot per calendar day, so a single day of usage
* is a single bar instead of a full-width block. Includes a legend, a y-axis maximum and day labels.
*/
export function UsageChart({ days, meter, period }: { days: Day[]; meter: string; period: string }) {
const def = meterDef(meter);
const unit: MeterDef["unit"] = def?.unit ?? "count";
const byDay = new Map(days.filter((day) => day.meter === meter).map((day) => [day.day, day.quantity]));
const slots = daysOf(period).map((day) => ({ day, quantity: byDay.get(day) ?? 0 }));
const total = slots.reduce((sum, slot) => sum + slot.quantity, 0);
const peak = slots.reduce((best, slot) => (slot.quantity > best.quantity ? slot : best), slots[0]);
const max = Math.max(peak?.quantity ?? 0, 0);
const [today, setToday] = useState("9999-12-31");
useEffect(() => setToday(new Date().toISOString().slice(0, 10)), []);
return (
<div className="space-y-3 px-4 py-4">
<div className="flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-kumo-subtle">
<span className="flex items-center gap-1.5">
<span aria-hidden className="size-2.5 rounded-sm bg-accent-500" />
<span className="text-kumo-default">{def?.label ?? meter}</span>
<span>per day</span>
</span>
<span>
Total <span className="font-mono text-kumo-default">{formatQuantity(unit, total)}</span>
</span>
{max > 0 && peak && (