Add Timelog: show the timer in the tab title and simplify the code

This is the first commit of the project, at the state that runs on
timelog.minhtrannhat.com.

Changes in this state:
- Remove redundant UI text from the sidebar, timer and insights pages.
- Show the remaining time and tag in the browser tab title while a
  session runs.
- Put the shared record type and the due and end helpers in
  src/shared/record.ts.
- Remove the startup tag migration and the one-time Forest import
  script. The live data does not need them.
- Remove unused CSS, Playwright ignore rules and duplicate helpers.
- Do not track Forest CSV exports, because they contain private data.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
minhtrannhatandClaude Opus 5.5 committed 2026-11-05 00:42:58 -05:00
commit a6ca255835
38 files changed
+2069

No files matched your search

+34
View File
@@ -0,0 +1,34 @@
import { describe, expect, test } from "bun:test";
import { countdown, pageTitle } from "../src/client/title.ts";
const start = +new Date(2026, 10, 5, 9, 0, 0);
const session = { startMs: start, targetSeconds: 25 * 60, tag: "Study" };
describe("browser tab title", () => {
test("is the app name when no session runs", () => {
expect(pageTitle(null, start)).toBe("Timelog");
});
test("shows the remaining time and tag while a session runs", () => {
expect(pageTitle(session, start)).toBe("25:00 · Study — Timelog");
expect(pageTitle(session, start + 61_500)).toBe("23:59 · Study — Timelog");
});
test("stops at 00:00 when the session is due", () => {
expect(pageTitle(session, start + 26 * 60_000)).toBe("00:00 · Study — Timelog");
});
test("countdown rounds partial seconds up", () => {
expect(countdown(1)).toBe("00:01");
expect(countdown(120 * 60_000)).toBe("120:00");
expect(countdown(-5)).toBe("00:00");
});
});
test("redundant UI text is gone", async () => {
const source = (await Bun.file("src/client/main.ts").text()).toLowerCase();
for (const text of [
"a quiet record of time", "local first", "forest csv / v1",
"one session at a time", "make time count", "actual logged time",
]) expect(source).not.toContain(text);
});