[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
addMealflow 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
1and timestampnow. - Matching Scope (Initial): Use deterministic keyword
includesmatching first; defer fuzzy matching as a follow-up enhancement. - Safety: Strip source
createdAtfrom 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.
- Cache Source First: Read recents from existing TanStack Query meal cache (
Testing Strategy
- Must Test:
- Recents extraction/deduplication from cache across multiple dates.
- One-tap quick add invokes
addMealwith 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
createdAtwould 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.tsxfrontend/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)
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
addMealmutation 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 viaqueryClient.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.
- Reads all cached
- 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
handleQuickAddRecentto call existingaddMealmutation path. - Enforces fresh timestamp (
new Date()) and strips oldcreatedAtbefore logging. - Reuses registry snapshot flow used by normal confirm.
- Integrated
- 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 (
includesby terms); explicitly deferred fuzzy search. - Tracked deferred fuzzy enhancement as Beads follow-up:
2512_genai_food_tracking-53s.
- Replaced always-visible quick-add list with a small trigger button (
- 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.
- Removed hard cap (
- 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.
- Added cache-derivation hook:
- Testing:
- Added unit tests:
frontend/src/hooks/__tests__/useQuickAddRecents.test.tsx. - Updated dashboard integration tests:
frontend/src/features/dashboard/__tests__/MealLoggingIntegration.test.tsxwith quick-add behavior assertions. bun run typecheckpasses.- Hook unit tests pass under node env.
- Resolved local test env blocker by pinning
jsdomto26.1.0in frontend devDependencies (v27 runtime causedClass extends value undefinedcrash during jsdom bootstrap). - Resolved Playwright/dev-server contention by moving test web server to a dedicated port (
PLAYWRIGHT_WEB_PORT, default4173) infrontend/playwright.config.js. - Full quality gates now pass:
task test(shared + backend + appsync eval + frontend + functional e2e + visual) andtask lint. - Fixed a React hook-order regression in
QuickAddRecentsdiscovered 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.
- Added unit tests:
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.