This commit is contained in:
timka123 committed 2026-10-18 18:02:05 +03:00
commit 17a0a3c4c9
121 files changed
+17641

No files matched your search

@@ -0,0 +1,109 @@
/**
* Pomodoros per day — magnitude over time, so: bars, one hue, baseline at zero.
*
* The goal line is the only reference mark; days that cleared it are the darker
* ramp step, which keeps "did I hit the goal" readable without a second colour.
*/
import { Box, Tooltip, Typography, useTheme } from "@mui/material";
import { shortDate } from "../../lib/format";
import type { VizPalette } from "../../lib/viz";
import ChartFrame from "./ChartFrame";
interface Day {
date: string;
pomodoros: number;
focus_minutes: number;
goal_met: boolean;
}
const HEIGHT = 160;
export default function FocusBars({
days,
goal,
palette,
title = "Pomodoros per day",
}: {
days: Day[];
goal: number;
palette: VizPalette;
title?: string;
}) {
const theme = useTheme();
const max = Math.max(goal, ...days.map((day) => day.pomodoros), 1);
const goalY = HEIGHT - (goal / max) * HEIGHT;
const slotWidth = 100 / Math.max(days.length, 1);
return (
<ChartFrame
title={title}
caption={`Last ${days.length} days · goal ${goal}/day`}
>
<Box sx={{ position: "relative", height: HEIGHT, display: "flex", alignItems: "flex-end", gap: "2px" }}>
{goal > 0 && (
<Box
sx={{
position: "absolute",
left: 0,
right: 0,
top: `${goalY}px`,
borderTop: `1px dashed ${palette.grid}`,
pointerEvents: "none",
}}
>
<Typography
variant="caption"
sx={{ position: "absolute", right: 0, top: -18, color: "text.secondary" }}
>
goal
</Typography>
</Box>
)}
{days.map((day) => {
const height = (day.pomodoros / max) * HEIGHT;
return (
<Tooltip
key={day.date}
title={
<Box>
<Typography variant="caption" sx={{ display: "block", fontWeight: 600 }}>
{day.date}
</Typography>
<Typography variant="caption" sx={{ display: "block" }}>
{day.pomodoros} pomodoros · {day.focus_minutes} min
</Typography>
</Box>
}
>
<Box
sx={{
flex: `0 0 calc(${slotWidth}% - 2px)`,
height: Math.max(height, day.pomodoros > 0 ? 4 : 2),
minHeight: 2,
borderRadius: "4px 4px 0 0",
bgcolor:
day.pomodoros === 0
? theme.palette.action.disabledBackground
: day.goal_met
? palette.sequential[4]
: palette.sequential[2],
transition: "height .3s",
cursor: "default",
}}
/>
</Tooltip>
);
})}
</Box>
<Box sx={{ display: "flex", justifyContent: "space-between", mt: 0.5 }}>
<Typography variant="caption" color="text.secondary">
{days.length ? shortDate(days[0].date) : ""}
</Typography>
<Typography variant="caption" color="text.secondary">
{days.length ? shortDate(days[days.length - 1].date) : ""}
</Typography>
</Box>
</ChartFrame>
);
}