# Cooking Log Design Record dates and comments when cooking a recipe, viewable on the recipe page and across all recipes by date. ## Data Model ### SQLite schema A single `cook_log` table: ```sql CREATE TABLE IF NOT EXISTS cook_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, recipe_filename TEXT NOT NULL, cooked_date TEXT NOT NULL, -- ISO date (YYYY-MM-DD) comment TEXT NOT NULL DEFAULT '', created_at TEXT NOT NULL -- ISO datetime ); CREATE INDEX idx_cook_log_recipe ON cook_log(recipe_filename); CREATE INDEX idx_cook_log_date ON cook_log(cooked_date DESC); ``` - `recipe_filename` is the lowercased filename with `.cook` stripped, matching the key used by the recipe index. - `cooked_date` stores the user-picked date (not necessarily today). - `comment` is optional (defaults to empty string). ### Haskell types New module `Roux.CookLog`: ```haskell data CookEntry = CookEntry { ceId :: Int , ceRecipeFilename :: Text , ceCookedDate :: Day , ceComment :: Text , ceCreatedAt :: UTCTime } ``` - `Day` (from `Data.Time.Calendar`) for dates. - `UTCTime` for `created_at`. ## API Endpoints All routes live in `Roux.Server` following existing patterns. | Method | Path | Purpose | |--------|------|---------| | `POST /cook-log/{filename}` | Record a cooking event | Form body: `cooked-date` (required, YYYY-MM-DD) + `comment` (optional). Returns JSON `{ ok: true }` on success, `{ error: "..." }` on failure. Multiple entries for the same date are allowed — no uniqueness constraint. | | `GET /cook-log/{filename}` | Fetch entries for one recipe | JSON array of `CookEntry`, sorted by `cooked_date DESC` | | `GET /cook-log` | Fetch all entries | JSON array of `CookEntry` with recipe info, sorted by `cooked_date DESC`, for cross-date view | ### DB connection SQLite database file at `/cook-log.db`. Opened once at server startup, passed to handlers via a shared value (same `IORef` pattern as the recipe state map). ### Library: `sqlite-simple` Minimal dependency. Pure SQL, typed results via `FromRow` instances. ``` dependencies: - sqlite-simple ``` ## Frontend Rendering ### "I cooked this" form at the top of the marginalia section ```html

Cook history

``` - `` gives a native date picker, defaults to today. - Comment is an optional text input, max 500 chars. - Form POSTs via `fetch()` with `FormData`, no page reload. - On success, JS appends the new entry to the entry list below. - On error, JS shows the error message inline. ### Entry list in the marginalia column ``` ── Mar 15 ── Used baking powder instead of soda, turned out fine ── Mar 2 ── Added extra vanilla ── Feb 20 ── ``` Rendered style: - Date centered between dashes, bold/small. - Comment below, plain text. - No comment = just the date separator line. ### Recipe page rendering `recipePage` in `Html.hs` accepts cook entries as an additional parameter (or fetches them server-side during page render). The log section renders inside the marginalia column, after Tags and before Notes. ### JavaScript Lightweight inline script (new constant alongside `recipeImageUploadJs`): ```javascript document.querySelector('.roux-cook-log-form').addEventListener('submit', async (e) => { e.preventDefault(); const form = e.target; const fd = new FormData(form); const res = await fetch('/cook-log/' + form.dataset.filename, { method: 'POST', body: fd }); if (!res.ok) return; const entry = await res.json(); // Prepend rendered entry to the list }); ``` ## Cross-Date View - Page at `/cook-history` showing all log entries grouped by month, newest first. - Each entry shows: date, recipe name (linked), comment (if any). - Accessible from a link in the main navbar ("Cook History"). - SSR rendered (no additional JS needed). ## Implementation Order 1. Add `sqlite-simple` dependency and `Roux.CookLog` module (types + DB ops) 2. Initialize DB at server startup (create table, open connection) 3. Implement POST/GET endpoints for single-recipe log entries 4. Integrate cook log entries into recipe page SSR in marginalia column 5. Add "I cooked this" form with JS submit handler 6. Implement cross-date view at `/cook-history` 7. Add nav link to cook history