4.5 KiB
4.5 KiB
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:
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_filenameis the lowercased filename with.cookstripped, matching the key used by the recipe index.cooked_datestores the user-picked date (not necessarily today).commentis optional (defaults to empty string).
Haskell types
New module Roux.CookLog:
data CookEntry = CookEntry
{ ceId :: Int
, ceRecipeFilename :: Text
, ceCookedDate :: Day
, ceComment :: Text
, ceCreatedAt :: UTCTime
}
Day(fromData.Time.Calendar) for dates.UTCTimeforcreated_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 <recipeDir>/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
<h2>Cook history</h2>
<form class="roux-cook-log-form" data-filename="pancakes">
<input type="date" name="cooked-date" value="2026-05-25">
<input type="text" name="comment" placeholder="Optional note..." maxlength="500">
<button type="submit">Log it</button>
</form>
<input type="date">gives a native date picker, defaults to today.- Comment is an optional text input, max 500 chars.
- Form POSTs via
fetch()withFormData, 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):
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-historyshowing 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
- Add
sqlite-simpledependency andRoux.CookLogmodule (types + DB ops) - Initialize DB at server startup (create table, open connection)
- Implement POST/GET endpoints for single-recipe log entries
- Integrate cook log entries into recipe page SSR in marginalia column
- Add "I cooked this" form with JS submit handler
- Implement cross-date view at
/cook-history - Add nav link to cook history