# Fullplate — views and menus

Derived from `fullplate.md` (entities + actions). This file enumerates the UI surfaces the app needs and the dropdowns / menus that hang off them. No layout, no styling — just what surfaces exist and what choices they expose.

---

## Part 1 — Views

### Anonymous / auth

- **Sign-in.** Magic-link email request form + "check your email" confirmation state.
- **Magic-link callback.** Transient landing while the backend verifies the OTP and sets cookies; redirects onward.
- **Public share view (`/r/:slug`).** Two states:
  - Anonymous: metadata-only (title, hero, owner display name, "Sign in to save").
  - Authed: full recipe, plus `is_in_library` / `is_owner` affordances ("Save to library", "Fork", "I own this — open in my library").

### Library (authed home)

- **Library list.** Grid or list of `RecipeListItem`. Surfaces per-row `is_favorite`, `added_at`, `last_viewed_at`, `last_cooked_at`, `category_ids`, `tags`. Drives search, filter, sort.
- **Empty / onboarding state.** First-run prompts (Import URL / Paste / Create manual).
- **Trash.** Soft-deleted recipes, recoverable.

### Recipe — read

- **Recipe detail.** Hero, title, description, timings, equipment, ingredients (with a servings scaler against `base_servings`), steps, source, lineage parent (3 variants — see Part 3), my tags + favorite, "Cook this" entry, action menu.
- **Cook mode.** Step-by-step "doing it now" view derived from `steps`, with an ingredient checklist and timer affordances. Exits into the cook log entry view.

### Recipe — write

- **Recipe editor.** One shell for create + edit. Sections: title, hero asset, description, timings, equipment, ingredients (polymorphic rows including section headers), steps (polymorphic rows including section headers + inline images), source, categories, visibility, optional commit message.
- **Import draft review.** Preview the AI-extracted draft from URL or paste import before it's POSTed as a real recipe. Editable in place.

### Cook logs

- **Cook log entry.** Rating (1–5), notes (markdown ≤5000 chars), `cooked_at`. Reachable from cook mode or recipe detail.
- **Cook log history (per recipe).** Up to 50 of my own logs, newest first. Each row editable / deletable.
- **Cooking journal (cross-recipe).** All my cooks chronologically across the library — "what have I been cooking lately." Each row links back to the recipe + the log entry.

### History & lineage

- **Activity feed (per recipe).** Reverse-chronological `RecipeActivity` list. Per-event delta inspection + revert affordance. Owner-only.
- **Fork lineage view.** Parent (live / private / snapshot variant) + list of child forks I can see.

### Account

- **Profile & account.** Display name, avatar, storage usage, AI + import usage this period (`UsageAiCall`, `UsageImport`), current tier + tier capabilities. Sign-out and delete-account live here.
- **Subscription / upgrade.** Tier comparison driven by `SubscriptionTier` + `TierCapability`.
- **Tags manager.** Full distinct tag vocabulary; rename / delete from individual recipes.

### Cross-cutting

- **Global search results.** Title hits + master-ingredient hits. Ingredient-hit side gets its own filter / pane so "all my recipes that use chicken" is a first-class query backed by `RecipeIngredientUse`.
- **Tier-limit / quota states.** Not a view — a cross-cutting modal/toast surface. Every gated action (URL import, OCR, AI calls past the limit, upload past storage cap, advanced print) needs a blocked-state prompt that explains the limit and links to upgrade. Driven by `TierCapability`.
- **Error surfaces.** 404 (recipe not found, share slug invalid or non-public), 403 (not in library / not owner), 410 (hard-deleted), session-expired re-auth.

---

## Part 2 — Dropdowns and menus

### Global chrome

- **Avatar menu.** Profile, Subscription, Sign out, Delete account.
- **New-recipe split button.** Manual / Import URL / Paste text.

### Library

- **Sort dropdown.** Added (default) / Viewed / Alpha / Cooked.
- **Filter popovers.**
  - Categories — grouped by `kind` (cuisine, dietary, meal_type, technique, occasion). Multi-select.
  - Tags — multi-select from my tag vocabulary.
  - Favorites-only toggle.
- **Per-row "…" menu.** Favorite / Unfavorite, Add tag, Fork, Copy public link, Remove from library, Soft-delete (owner), Hard-delete (owner, confirm).

### Recipe detail "…"

- Edit, Fork, Visibility (Private / Public link), Copy public link, View history, Log a cook, Soft-delete, Hard-delete (confirm), Save to library (non-owner only).

### Recipe editor

- **Visibility.** Private / Public link.
- **Source picker.** Manual / URL / Person / Book. (Fork shown as a read-only badge — set by the fork action, not user-editable.)
- **Category multi-select.** Grouped by `kind`.
- **Ingredient row controls.**
  - Unit picker — grouped by `kind` (volume / weight / count / descriptive), tagged by `system` (us / metric / universal).
  - Master-ingredient typeahead — backed by `Search master ingredients`.
  - Toggle `is_optional`.
  - Add prep note.
  - Convert row → section header.
  - Reorder, delete.
- **Step row controls.** Attach images (asset picker), convert row → section header, reorder, delete.
- **Hero asset picker.** Upload new / pick existing owned asset.
- **Save menu.** Save / Save with commit message.

### Activity feed

- **Per-event menu.** Revert all changed fields / Revert selected fields / Inspect delta. Only present on `edited` (and `reverted`) events.

### Cook log

- **Rating picker.** 1–5.
- **Cooked-at picker.** Datetime, defaults to now.
- **Per-log "…".** Edit / Delete (soft).

### Reference-data pickers (reused across the app)

- Unit picker, Category picker, Master-ingredient search — all backed by the read-only list endpoints (`List units`, `List recipe categories`, `Search master ingredients`).

---

## Part 3 — Non-obvious UI implications

A few places where the schema/actions force UI choices that aren't visible at first glance:

- **Import draft review is its own view.** URL and paste imports return a draft `RecipeCreateRequest`, not a saved recipe. The client must show an editable preview before POSTing — there is no "imported recipe" state on the server.
- **Activity revert is per-field, not just per-event.** The API accepts a `fields?` array. The activity feed needs a UI that lets the user pick which fields of a past edit to roll back, not just a single "Revert" button.
- **Lineage parent has three variants.** `live` (linkable), `private` (the caller can't open it — show name only, no link), `snapshot` (parent is hard-deleted — show frozen title + owner, no link). Three different UI treatments, not one.
- **Hard-delete preserves the row.** Hard-deleted recipes still appear as `snapshot` lineage parents for child forks. They should not appear anywhere else in the UI — not library, not search, not public.
- **Library access gates a lot.** Favoriting, tagging, cook-logging, and authed recipe reads all require a `RecipeLibrary` row. Non-owners on public recipes need a clear "Save to library" step before those affordances unlock.
- **Servings scaler is client-side.** `base_servings` is the stored value; the scaled view is derived. The detail view needs a control for it but no API call.
- **Public link visibility manages `share_slug` automatically.** The editor's visibility dropdown is the only control — the slug is server-generated and read-only in the UI.
