Skip to content

[2026-02-25] Feature: Quick Add from Local Cache Recents

Task Metadata

  • 📆 Date: 2026-02-25
  • 🚥 Status: Ready for Review
  • Beads Issue: 2512_genai_food_tracking-52v

Objective

Goal: Let users quickly re-log previously logged food items without an AI step, prioritizing the fastest possible path by reading already-available local cache data first.

  • Trigger: User request to support ultra-fast "quick add" of previously logged foods, ideally from local cache.
  • Constraints:
    • MVP should prioritize local cache reads and avoid backend schema/API changes.
    • Must preserve existing meal logging semantics (timestamp handling, logical date handling, optimistic updates).
    • Must degrade safely on cold cache (new user, cleared browser data, or no prior meal queries).

Technical Strategy

Build a local-cache-first "Quick Add Recents" path on top of existing meal query cache and existing addMeal mutation path.

  • Key Decisions:
    • Cache Source First: Read recents from existing TanStack Query meal cache (['meals', 'YYYY-MM-DD']) already persisted locally.
    • No New Write Path: Reuse the existing addMeal flow for consistency (optimistic updates, invalidation, and date logic).
    • Recents Model: Derive a lightweight in-memory list of unique meal templates (summary + macros + optional notes/emoji), sorted by frequency first and recency second.
    • Ultra-Speed UX (Updated): Use a compact "Quick Add Search" trigger that opens a keyword search UI over cached items; one-tap add from matched results defaults to quantity 1 and timestamp now.
    • Matching Scope (Initial): Use deterministic keyword includes matching first; defer fuzzy matching as a follow-up enhancement.
    • Safety: Strip source createdAt from recents before relogging so entries always log as "now" unless user edits time.
    • Cold Cache Behavior: If no recents are found, hide the quick-add panel and keep existing logging/relog flows unchanged.

Testing Strategy

  • Must Test:
  • Recents extraction/deduplication from cache across multiple dates.
  • One-tap quick add invokes addMeal with normalized payload and new timestamp semantics.
  • Cold cache state (panel hidden, no errors).
  • Guest + authenticated parity for quick add behavior.
  • Skip: Visual polish beyond basic functional UX in this initial pass.

Risk Analysis

  • Potential Regressions: Incorrect deduping could show duplicate recents or hide valid variants.
  • Data Freshness Risk: Cache-derived recents may lag behind server state until normal refetch occurs.
  • Timestamp Risk: Reusing old createdAt would mis-log entries in history if not explicitly stripped.
  • Security Implications: No auth model changes; client-only read of already-cached user data.
  • Files to Modify:
    • frontend/src/pages/Dashboard.tsx
    • frontend/src/hooks/useMeals.ts (reuse entrypoints as needed)
    • frontend/src/hooks/useQuickAddRecents.ts (new)
    • frontend/src/features/dashboard/components/QuickAddRecents.tsx (new)
    • frontend/src/features/dashboard/components/__tests__/... (new/updated)
    • frontend/src/hooks/__tests__/... (new/updated)
    • docs/architecture/frontend_offline.md (verify-and-close phase if behavior changes)

1. Recents Derivation (Hook)

// Pseudocode
const mealQueries = queryClient.getQueriesData<Meal[]>({ queryKey: ['meals'] });
const recentTemplates = dedupeAndRank(mealQueries);

2. One-Tap Quick Add (UI -> Existing Mutation)

// Pseudocode
const { createdAt: _oldCreatedAt, ...template } = normalizeMeal(item);
await addMeal(template, 1, undefined, new Date());

Critique & Gaps

  • Local cache can only offer meals already fetched on this device; it is not complete cross-device history.
  • One-tap speed can increase accidental logs without an explicit undo affordance.
  • Ranking strategy (recency vs frequency) can bias toward recently repeated foods and may need tuning.

Gap Analysis

  • Should MVP include only "recents" or both "recents + favorites" tagging?
  • Should quick-add default to immediate log, or stage-first for edit/confirmation?

Execution Plan

Stop: User Approval Required

Do not proceed with implementation until the user explicitly approves the Approach and Execution Plan.

  • Step 1: Finalize recents ranking/dedupe contract and preferred one-tap behavior.
  • Step 2: Implement recents hook + quick-add UI surface in dashboard.
  • Step 3: Wire one-tap quick add through existing addMeal mutation path.
  • Step 4: Add/adjust tests for recents derivation, quick add action, and cold cache fallback.
  • Verify: Run focused checks (bun run typecheck, bunx vitest run --environment node src/hooks/__tests__/useQuickAddRecents.test.tsx) and document jsdom worker blocker for UI tests in current environment.

Execution Notes

  • Approval: User approved execution with "please continue with implementation".
  • Implementation:
    • Added cache-derivation hook: frontend/src/hooks/useQuickAddRecents.ts.
      • Reads all cached ['meals', 'YYYY-MM-DD'] query entries via queryClient.getQueriesData.
      • Dedupes by normalized meal signature (summary, macros, notes, emoji, extended nutrients).
      • Ranks by latest createdAt (recency-first), with frequency as a tie-breaker.
      • Returns compact quick-add templates that intentionally drop source createdAt.
    • Added UI component: frontend/src/features/dashboard/components/QuickAddRecents.tsx.
      • Renders one-tap "Quick add" buttons from local cache recents.
      • Hidden automatically when cache has no recents.
    • Updated frontend/src/pages/Dashboard.tsx.
      • Integrated useQuickAddRecents.
      • Added handleQuickAddRecent to call existing addMeal mutation path.
      • Enforces fresh timestamp (new Date()) and strips old createdAt before logging.
      • Reuses registry snapshot flow used by normal confirm.
    • Follow-up design iteration from user feedback:
      • Replaced always-visible quick-add list with a small trigger button (Quick Add Search).
      • Added keyword search input for fast filtering of cached meals.
      • Implemented non-fuzzy matching (includes by terms); explicitly deferred fuzzy search.
      • Tracked deferred fuzzy enhancement as Beads follow-up: 2512_genai_food_tracking-53s.
    • Cache-search coverage fix from user validation feedback:
      • Removed hard cap (60) from recents source feeding quick-add search so older cached items remain searchable.
      • Removed search-result truncation (12) so keyword search returns all cache matches.
    • Ordering adjustment from user feedback:
      • Updated quick-add ranking to prioritize count first and recency second.
      • Added regression test coverage for count-vs-recency ordering behavior.
  • Testing:
    • Added unit tests: frontend/src/hooks/__tests__/useQuickAddRecents.test.tsx.
    • Updated dashboard integration tests: frontend/src/features/dashboard/__tests__/MealLoggingIntegration.test.tsx with quick-add behavior assertions.
    • bun run typecheck passes.
    • Hook unit tests pass under node env.
    • Resolved local test env blocker by pinning jsdom to 26.1.0 in frontend devDependencies (v27 runtime caused Class extends value undefined crash during jsdom bootstrap).
    • Resolved Playwright/dev-server contention by moving test web server to a dedicated port (PLAYWRIGHT_WEB_PORT, default 4173) in frontend/playwright.config.js.
    • Full quality gates now pass: task test (shared + backend + appsync eval + frontend + functional e2e + visual) and task lint.
    • Fixed a React hook-order regression in QuickAddRecents discovered during e2e runs by ensuring hooks execute before early return.
    • User Feedback (2026-02-25): "Quick search feels nice to use." User approved current iteration and will provide additional feedback after real-world usage.

User Approval & Key Learnings

Key Learnings

  • Quick Add Search interaction is intuitive enough for immediate use ("feels nice to use").
  • Practical, real-world usage feedback is still required before final closure.

User approved the current implementation on 2026-02-25 and requested a further iteration window based on practical daily usage.

Context Memory (AI-Only)

Summary for Future Context

Implemented cache-first quick add recents end-to-end in frontend using existing React Query meal cache and existing add mutation path. Added a new hook for recents derivation and a new dashboard quick-add UI. Logging path now supports one-tap add with fresh timestamp while preserving existing validation/optimistic behavior. Full test stack now passes after resolving jsdom compatibility and assigning Playwright to a dedicated test port.