diff --git a/docs/decisions/0005-journal-research.md b/docs/decisions/0005-journal-research.md index 77801f8..a0fa1fa 100644 --- a/docs/decisions/0005-journal-research.md +++ b/docs/decisions/0005-journal-research.md @@ -1,16 +1,128 @@ -# 0005 — Journal / mood tracking research +# 0005 — Journal / mood tracking Date: 2026-07-03 -Status: proposed +Status: accepted (2026-07-04) ## Context -Journal module (task 86) needs mood multi-select, charts over time, and insights. Research existing libraries/components for mood tracking or journaling and record build-vs-adopt. Gitea: [#20](https://gitea.ginnoir.com/ginnoir/famapp/issues/20) (epic [#19](https://gitea.ginnoir.com/ginnoir/famapp/issues/19)). +Journal module (task 86) needs per-user entries, mood multi-select, charts over time, insights, and `/api/v1/journal` endpoints. ADR research included [Giftyaning/Mood-Tracker](https://github.com/Giftyaning/Mood-Tracker) (Gitea [#20](https://gitea.ginnoir.com/ginnoir/famapp/issues/20), epic [#19](https://gitea.ginnoir.com/ginnoir/famapp/issues/19)). + +## Build-vs-adopt: Mood-Tracker + +**Decision: do not adopt the repo.** + +| Factor | Mood-Tracker | famapp need | +| ---------- | -------------------------- | ------------------------------------------- | +| License | None | Must have clear reuse rights | +| Stack | Vite SPA, JS, localStorage | Next.js 15, TypeScript, Postgres, Authentik | +| Mood model | Single-select, 5 presets | Multi-select fixed catalog | +| Fields | Title + plain text | Optional title + TipTap HTML, stress, pills | +| API / auth | None | `/api/v1/` + session + bearer token | +| Code shape | One 672-line `App.jsx` | `src/modules/journal/` manifest pattern | + +**Borrow (reimplement in TypeScript):** mood→numeric scoring, day streak, week-over-week trend, insight card layout. Not copied source. + +## What we decided (2026-07-04) + +| # | Topic | Choice | +| --- | -------------- | --------------------------------------------------------------------------------------------------- | +| 1 | Charts | **Build natively + Recharts** for mood/stress trends and correlation views | +| 2 | Moods | **Fixed catalog** (~8–12 presets with emoji + color); **multi-select** | +| 3 | Entries | **Multiple per day** allowed | +| 4 | Stress | Optional **1–10** slider | +| 5 | Insights v1 | **Core + correlations** — streak, top mood, avg stress; stress↔mood and pills↔avg-mood simple stats | +| 6 | Index calendar | **Month grid** with dots on days that have entries; tap day → filtered list | +| 7 | Entry shape | **Optional title** + rich-text body (shared `RichTextEditor`) | +| 8 | Chart points | **All entries** as individual points; x-axis uses **datetime** (not date-only rollup) | ## Decision -To be filled when research completes. +### Module: `src/modules/journal/` + +Standard module layout: `schema.ts`, `manifest.tsx`, `server/`, `components/`, app routes under `/journal`. + +### Data model + +Table `journal_entries`: + +- `household_id` — household scope for DB consistency +- `user_id` — **per-user privacy**; all reads/writes filter `user_id = current user` +- `recorded_at` timestamptz — required date+time (defaults to now on create) +- `title` text nullable — optional +- `body` text — HTML from shared rich-text editor (ADR 0004) +- `moods` jsonb — array of catalog mood ids (multi-select) +- `stress` smallint nullable — 1–10 +- `pills_taken` boolean nullable + +No household-shared journal in v1. Wife cannot see Matt's entries and vice versa. + +### Mood catalog + +Fixed in code (`src/modules/journal/mood-catalog.ts`): ids, label, emoji, color, numeric score for analytics. Users pick from catalog only (no custom tags in v1). + +### UI surfaces + +| Route | Purpose | +| ------------------------------- | -------------------------------------------------------------------------------------- | +| `/journal` | Recent 5–10 entries, browse all link, month calendar, links to mood tracker + insights | +| `/journal/new`, `/journal/[id]` | Create/edit entry (date/time required; rest optional) | +| `/journal/mood` | Recharts mood/stress over time (all entry points) | +| `/journal/insights` | Streak, top mood, correlations | + +Rich text: `RichTextEditor` / `RichTextContent` from `src/components/rich-text/`. No share viewer in v1. + +### Insights v1 + +- Entry streak (consecutive days with ≥1 entry) +- Most common mood (selected period) +- Average stress (7d / 30d) +- Week-over-week mood trend (score-based) +- **Correlations:** simple aggregates — avg mood score on days pills taken vs not; stress vs mood score scatter or grouped averages + +No ML / sentiment analysis in v1. + +### API + +Additive on ADR 0006 foundation: + +- `GET/POST /api/v1/journal/entries` +- `GET/PATCH/DELETE /api/v1/journal/entries/:id` + +Bearer token and session auth. Responses scoped to **token owner's user id** for journal (household token acts as owner user for API mutations per existing pattern, but journal entries are always stored with the authenticated user's id). + +Document in `docs/api/openapi.yaml`. + +### Testing + +- Playwright: `tests/e2e/journal.spec.ts` — create minimal entry → list → detail → mood tracker loads +- Unit tests for mood scoring / streak helpers where non-trivial ## Consequences -To be filled when research completes. +### Positive + +- Recharts gives proper time-series without maintaining custom chart code for long trends. +- Fixed mood catalog keeps insights comparable across entries. +- Per-user privacy matches personal journal expectations. +- Reuses rich-text stack from task 85. + +### Trade-offs + +- All-entry chart points mean busy days show multiple dots; datetime x-axis required. +- Fixed catalog may miss nuance — body text carries freeform detail. +- Correlation stats are descriptive only (no causation); keep copy honest in UI. +- Recharts adds bundle weight on `/journal/mood` and `/journal/insights` only (route-level code split). + +### Out of scope (ADR) + +- Household-shared journals +- LLM agent tools for journal (task 88) +- Custom user-defined mood tags +- Share links for journal entries + +## References + +- Task brief: `docs/tasks/86-journal-module.md` +- Rich text: `docs/decisions/0004-rich-text-editor.md` +- API: `docs/decisions/0006-api-llm-agent.md` +- Mood-Tracker research: https://github.com/Giftyaning/Mood-Tracker diff --git a/docs/decisions/README.md b/docs/decisions/README.md index 61abca8..ca0764b 100644 --- a/docs/decisions/README.md +++ b/docs/decisions/README.md @@ -27,6 +27,6 @@ What this costs us, what it buys us. - [0002 — List realtime uses Postgres NOTIFY and SSE](0002-list-sse-notify.md) - [0003 — Release workflow (commitlint + release-it)](0003-release-workflow.md) - [0004 — Rich-text editor library and storage format](0004-rich-text-editor.md) (accepted 2026-07-04) -- [0005 — Journal / mood tracking research](0005-journal-research.md) (proposed) +- [0005 — Journal / mood tracking](0005-journal-research.md) (accepted 2026-07-04) - [0006 — API auth and LLM agent architecture](0006-api-llm-agent.md) (accepted 2026-07-04)