Add recent tag buttons under the tag picker

Under the TAG picker, the timer form shows buttons for the 3 different
tags from the most recent sessions, newest first. A tap selects the
tag. It does not start a session.

The minute buttons move under the DURATION field. They share the column
width, so all six stay on one line on desktop and on mobile.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
minhtrannhatandClaude Opus 5.5 committed 2026-11-08 15:10:12 -05:00
1 parent c90c0ddf9d
commit 52e8948d73
4 files changed
+59 -4

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
import { describe, expect, test } from "bun:test";
import { recentTags } from "../src/client/recent-tags.ts";
const at = (minute: number, tag: string, deleted = false) => ({ startMs: minute * 60_000, tag, deleted });
describe("recent tags", () => {
test("gives the 3 different tags from the most recent sessions, newest first", () => {
const records = [at(1, "Read"), at(2, "Study"), at(3, "Gym"), at(4, "Study"), at(5, "Code"), at(6, "Study")];
expect(recentTags(records)).toEqual(["Study", "Code", "Gym"]);
});
test("does not depend on the order of the records", () => {
expect(recentTags([at(9, "Code"), at(1, "Read"), at(5, "Study")])).toEqual(["Code", "Study", "Read"]);
});
test("ignores deleted sessions", () => {
expect(recentTags([at(1, "Read"), at(2, "Study", true)])).toEqual(["Read"]);
});
test("gives fewer tags when there are fewer than 3", () => {
expect(recentTags([at(1, "Study"), at(2, "Study")])).toEqual(["Study"]);
expect(recentTags([])).toEqual([]);
});
});
test("the timer form puts each row of buttons under its field", async () => {
const source = await Bun.file("src/client/main.ts").text();
const form = source.slice(source.indexOf('id="timer-tag"'), source.indexOf('data-action="start"'));
const tagRow = form.indexOf('data-action="pick-tag"');
const durationField = form.indexOf('id="timer-duration"');
const minuteRow = form.indexOf('data-action="duration"');
expect(tagRow).toBeGreaterThan(-1);
expect(tagRow).toBeLessThan(durationField);
expect(minuteRow).toBeGreaterThan(durationField);
});