Skip to content

feat: show nutrition source quality - #2313

Merged
Asherlc merged 5 commits into
mainfrom
Asherlc/issue-2136-nutrition-source-breakdown
Jul 29, 2026
Merged

Asherlc merged 5 commits into
mainfrom
Asherlc/issue-2136-nutrition-source-breakdown

Conversation

@Asherlc

@Asherlc Asherlc commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Summary

  • separate itemized food, provider daily totals, and taken supplements in micronutrient analytics
  • report selected-window completeness, overlap, conflicts, and contributing or excluded sources
  • show the server-computed quality context and source contributions on web and mobile
  • document the query-time source contract and cover it with real PostgreSQL, unit, UI, and Storybook tests

Validation

  • pnpm vitest run --project unit packages/server/src/repositories/nutrition-analytics-repository.test.ts packages/server/src/routers/nutrition-analytics.test.ts
  • TEST_DATABASE_URL=... pnpm vitest run --project integration packages/server/src/repositories/nutrition-analytics-source-breakdown.integration.test.ts
  • focused web and mobile component/page tests
  • root, server, web, and mobile typechecks
  • pnpm --dir packages/web build
  • web and mobile Storybook builds
  • full pnpm test: 14,770 passed, 21 skipped; local command exited after an unrelated Docker-hung Compose test caused a Vitest worker RPC timeout
  • pnpm lint: code and policy checks passed; local analytics SQL validation could not connect to ClickHouse

Fixes #2136

Summary by Sourcery

Expose nutrition analytics source quality and per-source contributions across server, web, and mobile.

New Features:

  • Include server-computed nutrition data quality metrics (window completeness, overlap, conflicts, and source labels) in the micronutrient analytics API.
  • Add per-nutrient breakdown of itemized food, provider daily totals, and supplement intake, including per-source contribution rows.
  • Display nutrition data quality context and source contribution details in web and mobile nutrition analytics UIs before adequacy interpretation.

Enhancements:

  • Refine micronutrient analytics SQL to classify intake by type and aggregate per-source contributions using canonical nutrient and daily source-resolution views.
  • Extend micronutrient chart tooltips to show intake-type breakdown and escaped per-source contributions.
  • Document the nutrition analytics source and completeness contract and capture it in a TDD plan document.

Tests:

  • Add PostgreSQL integration tests validating source-type classification, per-source contributions, and data-quality metrics for nutrition analytics.
  • Expand server, router, web, and mobile tests to cover the new data-quality contract and source breakdown rendering.
  • Add Storybook stories for web and mobile nutrition data quality panels and updated micronutrient analytics states.

Summary by cubic

Shows nutrition data source quality and per-source contributions on web and mobile, computed on the server. Implements #2136 with completeness/overlap context and split averages for itemized food, provider daily totals, and supplements.

  • New Features

    • Server (packages/server): NutritionAnalyticsRepository returns per‑nutrient sourceBreakdown, adds providerDailyTotalAverage, and getMicronutrientDataQuality() (coverage, overlap, conflicts, contributing/excluded labels); router adds dataQuality to nutritionAnalytics.micronutrientAdequacyV2.
    • Web (packages/web) and Mobile (packages/mobile): NutritionDataQualityPanel appears before charts; nutrient rows/tooltips show itemized food, provider daily totals, supplements, and escaped per‑source contributions.
    • Shared: moved data‑quality message formatting to @dofek/nutrition for reuse in both clients.
    • Tests/Docs: added Postgres integration and expanded unit/router/UI tests; documented the server contract in packages/nutrition/README.md; recorded an Infisical iOS CI timeout in docs/production-incident-baseline.md.
  • Bug Fixes

    • Mobile: query micronutrient data once at the screen level and pass to child panels to preserve nutrition detail access across the page.

Written for commit 4e10645. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added nutrition data quality details, including coverage, completeness, overlaps, conflicts, and contributing or excluded sources.
    • Expanded micronutrient analytics with daily averages and breakdowns for itemized foods, provider totals, and supplements.
    • Added source contribution details to web chart tooltips and mobile nutrient views.
    • Added loading, complete, partial, and empty states for data quality displays.
  • Documentation

    • Documented the nutrition analytics source and data-quality contract.

Copilot AI review requested due to automatic review settings July 29, 2026 21:35

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @Asherlc, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@cursor

cursor Bot commented Jul 29, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Nutrition analytics now separates itemized food, provider daily totals, and supplements; reports selected-window data quality; and renders source context in web and mobile interfaces.

Changes

Nutrition analytics source context

Layer / File(s) Summary
Server contract and source projections
docs/superpowers/plans/..., packages/server/src/repositories/..., packages/server/src/routers/..., packages/nutrition/README.md
The V2 analytics response now includes intake-type averages, per-source contributions, completeness metrics, overlap/conflict counts, and source labels derived from existing nutrition views. Repository, router, unit, and Postgres integration coverage was added or updated.
Web source and quality rendering
packages/web/src/components/..., packages/web/src/pages/NutritionAnalyticsPage.tsx, packages/web/src/components/*test.tsx
The web page renders nutrition data quality, and chart tooltips display escaped per-source contribution lines with readable intake-type labels. Stories and tests cover loading, complete, empty, overlap, and all-history states.
Mobile source and quality rendering
packages/mobile/app/nutrition-analytics.tsx, packages/mobile/components/NutritionDataQualityPanel.*, packages/mobile/.storybook/..., packages/mobile/app/nutrition-analytics.test.tsx
The mobile screen consumes the shared analytics query, renders the data-quality panel, and displays formatted source breakdown details with supporting stories and assertions.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AnalyticsScreen
  participant NutritionAnalyticsRouter
  participant NutritionAnalyticsRepository
  participant Postgres
  AnalyticsScreen->>NutritionAnalyticsRouter: request micronutrientAdequacyV2
  NutritionAnalyticsRouter->>NutritionAnalyticsRepository: fetch nutrient review and data quality
  NutritionAnalyticsRepository->>Postgres: query source classifications and daily resolution
  Postgres-->>NutritionAnalyticsRepository: contributions and quality rows
  NutritionAnalyticsRepository-->>NutritionAnalyticsRouter: expanded analytics result
  NutritionAnalyticsRouter-->>AnalyticsScreen: nutrients, sourceBreakdown, and dataQuality
Loading

Assessment against linked issues

Objective Addressed Explanation
Separate food, supplements, and provider totals by source and intake type [#2136]
Show completeness and overlap before interpretation [#2136]

Suggested labels: area/server, area/web, area/mobile, type/feature

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 1 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title is relevant, but it violates the PR title rule by using "feat:" instead of the required area prefix and imperative mood. Rewrite it as an imperative, area-prefixed title such as "[web] show nutrition source quality" with no trailing punctuation.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai

sourcery-ai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Implements server-computed nutrition data quality and source breakdown for micronutrient analytics, extending the analytics query and DTOs to distinguish itemized food, provider daily totals, and supplements, and surfaces this context with new UI panels and tests on web and mobile.

Sequence diagram for micronutrientAdequacyV2 with data quality and source breakdown

sequenceDiagram
  actor User
  participant Client as WebOrMobileClient
  participant Router as nutritionAnalyticsRouter
  participant Repo as NutritionAnalyticsRepository
  participant DB as Postgres

  User->>Client: Open NutritionAnalyticsPage / NutritionAnalyticsScreen
  Client->>Router: trpc.nutritionAnalytics.micronutrientAdequacyV2({ days })
  Router->>Repo: new NutritionAnalyticsRepository(...)
  Router->>Repo: getMicronutrientSafetyReview(days)
  Repo->>DB: executeWithSchema(..., micronutrient query)
  DB-->>Repo: nutrient rows with source_breakdown
  Repo-->>Router: MicronutrientSafetyReview[]
  Router->>Repo: getMicronutrientDataQuality(days)
  Repo->>DB: executeWithSchema(..., NutritionAnalyticsDataQuality query)
  DB-->>Repo: daily rows from fitness.v_nutrition_daily
  Repo-->>Router: NutritionAnalyticsDataQuality
  Router->>Repo: getSupplementMedicationReview()
  Repo->>DB: executeWithSchema(..., supplement query)
  DB-->>Repo: supplement rows
  Repo-->>Router: SupplementMedicationReview
  Router-->>Client: MicronutrientSafetyReviewResult
  activate Client
  Client->>Client: MicronutrientChart uses intake.sourceBreakdown
  Client->>Client: NutritionDataQualityPanel uses dataQuality
  deactivate Client
Loading

File-Level Changes

Change Details Files
Extend micronutrient analytics repository and router to compute intake-type/source breakdown and selected-window data-quality metadata.
  • Augment MicronutrientSafetyReviewData with providerDailyTotalAverage and sourceBreakdown, and introduce NutritionSourceContribution, NutritionIntakeType, and NutritionAnalyticsDataQuality types.
  • Refactor the SQL in NutritionAnalyticsRepository to classify contributions by intake type using canonical nutrient and classification views, compute per-source daily averages, and project them as JSONB source_breakdown alongside separated intake averages.
  • Add getMicronutrientDataQuality to compute daysWithData, usableDays, overlapDays, conflictDays, completenessPercent, and aggregated contributing/excluded source labels from fitness.v_nutrition_daily.
  • Update nutritionAnalytics.micronutrientAdequacyV2 router method to fetch dataQuality from the repository and include it in MicronutrientSafetyReviewResult, plus extend tests for empty-range behavior.
packages/server/src/repositories/nutrition-analytics-repository.ts
packages/server/src/repositories/nutrition-analytics-repository.test.ts
packages/server/src/repositories/nutrition-analytics-source-breakdown.integration.test.ts
packages/server/src/routers/nutrition-analytics.ts
packages/server/src/routers/nutrition-analytics.test.ts
Expose nutrition data-quality context and source breakdown in mobile nutrition analytics UI.
  • Switch NutritionAnalyticsScreen to share a single micronutrientAdequacyV2 query across sections and pass results/flags into child components instead of re-querying.
  • Introduce NutritionDataQualityPanel component on mobile to display daysWithData, completeness, overlap/conflict wording, and contributing/excluded sources, with loading and empty states, and render it above adaptive TDEE and micronutrient sections.
  • Extend MicronutrientAdequacySection to accept the shared query result, and render per-intake-type daily averages and per-source contribution rows with readable labels and styling.
  • Add Storybook stories and tests for the mobile NutritionDataQualityPanel and update existing screen tests and story fixtures to include providerDailyTotalAverage and sourceBreakdown fields and validate the new text output.
packages/mobile/app/nutrition-analytics.tsx
packages/mobile/components/NutritionDataQualityPanel.tsx
packages/mobile/components/NutritionDataQualityPanel.test.tsx
packages/mobile/components/NutritionDataQualityPanel.stories.tsx
packages/mobile/app/nutrition-analytics.test.tsx
packages/mobile/.storybook/nutrition-analytics-story-link.ts
Expose nutrition data-quality context and source breakdown in web nutrition analytics UI and documentation.
  • Add NutritionDataQualityPanel React component on web to render server-provided daysWithData, completeness, overlap/conflict messages, and contributing/excluded sources (including all-history handling), with tests and Storybook stories for loading/partial/complete/empty states.
  • Render NutritionDataQualityPanel on NutritionAnalyticsPage above the adaptive TDEE and MicronutrientChart and wire it to the micronutrientAdequacyV2 query’s dataQuality and loading state.
  • Extend MicronutrientChart tooltip to display intake-type daily averages and escaped per-source contributions under a Sources section while preserving XSS protections, and update stories and tests to cover new fields and markup.
  • Update SupplementSafetyReviewPanel stories/tests and TimeRangeSelector consumer tests to account for the extended MicronutrientSafetyReviewResult shape including dataQuality and providerDailyTotalAverage, and document the analytics source contract and completeness behavior in packages/nutrition/README.md and a new TDD plan doc.
packages/web/src/components/NutritionDataQualityPanel.tsx
packages/web/src/components/NutritionDataQualityPanel.test.tsx
packages/web/src/components/NutritionDataQualityPanel.stories.tsx
packages/web/src/pages/NutritionAnalyticsPage.tsx
packages/web/src/components/MicronutrientChart.tsx
packages/web/src/components/MicronutrientChart.test.tsx
packages/web/src/components/MicronutrientChart.stories.tsx
packages/web/src/components/SupplementSafetyReviewPanel.stories.tsx
packages/web/src/components/SupplementSafetyReviewPanel.test.tsx
packages/web/src/components/TimeRangeSelector.consumers.test.tsx
packages/nutrition/README.md
docs/superpowers/plans/2026-07-29-nutrition-source-breakdown.md

Assessment against linked issues

Issue Objective Addressed Explanation
#2136 Separate food, provider daily totals, and supplements in nutrient analytics, including a per-source breakdown by intake type.
#2136 Expose selected-window data quality in analytics (completeness, overlap, conflicts, and contributing/excluded sources) and surface it in the web and mobile UIs before interpreting nutrient charts.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Show nutrition analytics data quality and per-source contributions

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Extend micronutrient analytics API with server-computed data-quality context
 (completeness/overlap/conflicts).
• Split nutrient intake into itemized food, provider daily totals, and supplements with per-source
 contributions.
• Render the new context and breakdown in web + mobile, backed by unit, integration, and UI tests.
Diagram

graph TD
  W["Web NutritionAnalyticsPage"] --> C["NutritionDataQualityPanel"] --> API(["nutritionAnalytics.micronutrientAdequacyV2"])
  M["Mobile NutritionAnalyticsScreen"] --> C --> API
  API --> R["NutritionAnalyticsRepository"] --> V[("Postgres views\n(v_nutrition_canonical_nutrient, v_nutrition_daily)")]
  W --> MC["MicronutrientChart tooltip"] --> API
  M --> MS["Micronutrient list details"] --> API
  subgraph Legend
    direction LR
    _ui["UI"] ~~~ _api(["API/Service"]) ~~~ _db[("Database/View")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Separate endpoint for dataQuality
  • ➕ Keeps micronutrientAdequacyV2 payload smaller for clients not rendering quality context
  • ➕ Allows independent caching/refresh of quality vs nutrient calculations
  • ➖ More client orchestration and loading-state coordination
  • ➖ Harder to guarantee UI ordering ('quality before interpretation') without extra coupling
2. Precompute/materialize daily source-quality metrics
  • ➕ Lower query cost for large windows and frequent refresh
  • ➕ Simplifies runtime calculations (especially overlap/conflict tallies)
  • ➖ Introduces a new storage path/maintenance complexity (refresh, backfill, correctness)
  • ➖ Conflicts with the stated design goal of keeping canonical views as source of truth
3. Client-side computation from raw daily rows
  • ➕ Server contract remains smaller; can iterate UI logic faster on clients
  • ➕ Avoids adding new DTO fields and router plumbing
  • ➖ Duplicated logic across web/mobile and higher risk of drift
  • ➖ Worse security/consistency posture (e.g., escaping, overlap rules, denominator rules)

Recommendation: Keep the current approach: compute and return dataQuality + sourceBreakdown on the server as part of micronutrientAdequacyV2. It enforces a single, documented contract for overlap/conflict/completeness semantics, avoids duplicated client logic, and aligns with the query-time-view design constraint while still providing strong integration and UI test coverage.

Files changed (23) +1286 / -51

Enhancement (7) +452 / -49
nutrition-analytics.tsxRender nutrition data-quality and source breakdown on mobile +92/-28

Render nutrition data-quality and source breakdown on mobile

• Adds a NutritionDataQualityPanel before micronutrient interpretation and refactors micronutrient adequacy rendering to reuse a single query result. Displays itemized vs provider daily totals vs supplements plus per-source contribution rows per nutrient.

packages/mobile/app/nutrition-analytics.tsx

NutritionDataQualityPanel.tsxIntroduce mobile NutritionDataQualityPanel component +82/-0

Introduce mobile NutritionDataQualityPanel component

• Adds a reusable panel component that renders server-provided completeness/overlap/conflict/source context, including a dedicated loading state. Avoids client-side recomputation by consuming the server DTO directly.

packages/mobile/components/NutritionDataQualityPanel.tsx

nutrition-analytics-repository.tsCompute intake-type/source breakdown and selected-window data quality +200/-20

Compute intake-type/source breakdown and selected-window data quality

• Extends the micronutrient safety review DTO to include providerDailyTotalAverage and per-source contribution rows with an explicit intakeType. Adds getMicronutrientDataQuality() to compute completeness/overlap/conflicts and contributing/excluded source labels from v_nutrition_daily, and updates SQL to classify contributions via v_nutrition_entry_classification and supplement dose events.

packages/server/src/repositories/nutrition-analytics-repository.ts

nutrition-analytics.tsExtend micronutrientAdequacyV2 response with dataQuality +5/-1

Extend micronutrientAdequacyV2 response with dataQuality

• Adds NutritionAnalyticsDataQuality to the router result type and fetches it alongside nutrients and professional review via Promise.all. Returns the new dataQuality block to clients.

packages/server/src/routers/nutrition-analytics.ts

MicronutrientChart.tsxShow intake-type split and per-source contributions in chart tooltip +16/-0

Show intake-type split and per-source contributions in chart tooltip

• Enhances tooltip HTML to include itemized food, provider daily totals, and supplement daily averages plus an optional Sources section. Escapes nutrient/unit/source label strings to avoid tooltip injection.

packages/web/src/components/MicronutrientChart.tsx

NutritionDataQualityPanel.tsxIntroduce web NutritionDataQualityPanel component +52/-0

Introduce web NutritionDataQualityPanel component

• Adds a web component that renders server-provided data-quality context with accessible loading semantics. Supports both selected-window and all-history wording based on selectedWindowDays/completenessPercent nullability.

packages/web/src/components/NutritionDataQualityPanel.tsx

NutritionAnalyticsPage.tsxRender nutrition data-quality context before web micronutrient charts +5/-0

Render nutrition data-quality context before web micronutrient charts

• Adds NutritionDataQualityPanel near the top of the page, fed directly from the micronutrientAdequacyV2 query’s dataQuality and loading state. Ensures users see completeness/overlap context before interpreting micronutrient charts.

packages/web/src/pages/NutritionAnalyticsPage.tsx

Tests (9) +540 / -2
nutrition-analytics.test.tsxAssert mobile screen renders data-quality panel and source breakdown +27/-0

Assert mobile screen renders data-quality panel and source breakdown

• Updates TRPC mocks to include dataQuality and per-source contributions. Adds expectations ensuring the quality context and intake/source lines appear in the rendered screen.

packages/mobile/app/nutrition-analytics.test.tsx

NutritionDataQualityPanel.test.tsxAdd unit tests for mobile NutritionDataQualityPanel +46/-0

Add unit tests for mobile NutritionDataQualityPanel

• Verifies completeness messaging, overlap/conflict messaging, and contributing/excluded source labels. Covers loading state behavior.

packages/mobile/components/NutritionDataQualityPanel.test.tsx

nutrition-analytics-repository.test.tsAdd repository tests for intake-type split, source rows, and dataQuality +104/-2

Add repository tests for intake-type split, source rows, and dataQuality

• Extends unit test harness to normalize new SQL fields and adds assertions for providerDailyTotalAverage, sourceBreakdown mapping/rounding, and server-computed data quality aggregation behavior.

packages/server/src/repositories/nutrition-analytics-repository.test.ts

nutrition-analytics-source-breakdown.integration.test.tsAdd Postgres integration test for source breakdown and quality metrics +241/-0

Add Postgres integration test for source breakdown and quality metrics

• Seeds real Postgres tables with itemized entries, provider daily aggregates, supplements, resolved overlap, and unresolved conflicts. Validates query-time classification, per-source contributions, and dataQuality completeness/overlap/conflict semantics end-to-end.

packages/server/src/repositories/nutrition-analytics-source-breakdown.integration.test.ts

nutrition-analytics.test.tsUpdate router tests to expect dataQuality in micronutrientAdequacyV2 +11/-0

Update router tests to expect dataQuality in micronutrientAdequacyV2

• Extends the expected V2 response shape to include the new server-provided dataQuality block even when nutrient results are empty.

packages/server/src/routers/nutrition-analytics.test.ts

MicronutrientChart.test.tsxTest web tooltip renders and escapes source breakdown content +24/-0

Test web tooltip renders and escapes source breakdown content

• Adds sourceBreakdown to fixtures and asserts tooltip includes itemized/provider/supplement lines and per-source rows. Extends XSS-escape coverage to include source labels rendered in the tooltip.

packages/web/src/components/MicronutrientChart.test.tsx

NutritionDataQualityPanel.test.tsxAdd unit tests for web NutritionDataQualityPanel +63/-0

Add unit tests for web NutritionDataQualityPanel

• Validates selected-window messaging, overlap/conflict wording, contributing/excluded sources, all-history behavior (no denominator), and loading state rendering.

packages/web/src/components/NutritionDataQualityPanel.test.tsx

SupplementSafetyReviewPanel.test.tsxUpdate supplement safety tests for new micronutrient contract fields +13/-0

Update supplement safety tests for new micronutrient contract fields

• Extends the test fixture result to include providerDailyTotalAverage, sourceBreakdown, and dataQuality to satisfy the updated types and rendering paths.

packages/web/src/components/SupplementSafetyReviewPanel.test.tsx

TimeRangeSelector.consumers.test.tsxUpdate TimeRangeSelector consumer mocks with dataQuality +11/-0

Update TimeRangeSelector consumer mocks with dataQuality

• Extends the mocked micronutrientAdequacyV2 response to include dataQuality so the consuming components/pages can typecheck and render against the new contract.

packages/web/src/components/TimeRangeSelector.consumers.test.tsx

Documentation (2) +91 / -0
2026-07-29-nutrition-source-breakdown.mdAdd TDD plan for nutrition source breakdown and quality contract +72/-0

Add TDD plan for nutrition source breakdown and quality contract

• Introduces a scoped TDD plan describing the intended server contract, UI requirements, and test strategy. Clarifies that all calculations remain query-time projections over canonical Postgres views.

docs/superpowers/plans/2026-07-29-nutrition-source-breakdown.md

README.mdDocument nutrition analytics source and completeness contract +19/-0

Document nutrition analytics source and completeness contract

• Documents the semantics of selected-window completeness, overlap/conflict reporting, and per-nutrient intake-type breakdown and per-source contributions. Explicitly states these values are query-time projections over canonical views and that all-history windows do not invent a calendar denominator.

packages/nutrition/README.md

Other (5) +203 / -0
nutrition-analytics-story-link.tsUpdate mobile Storybook nutrition analytics mocks for new contract +38/-0

Update mobile Storybook nutrition analytics mocks for new contract

• Extends mocked micronutrient results with providerDailyTotalAverage, per-source breakdown rows, and the top-level dataQuality block so stories render the new UI paths.

packages/mobile/.storybook/nutrition-analytics-story-link.ts

NutritionDataQualityPanel.stories.tsxAdd mobile Storybook stories for nutrition data quality panel states +68/-0

Add mobile Storybook stories for nutrition data quality panel states

• Creates Storybook coverage for partial-with-overlap, loading, complete, and empty dataQuality scenarios to validate rendering across expected states.

packages/mobile/components/NutritionDataQualityPanel.stories.tsx

MicronutrientChart.stories.tsxUpdate web MicronutrientChart stories for source breakdown fields +17/-0

Update web MicronutrientChart stories for source breakdown fields

• Extends story fixture rows with providerDailyTotalAverage and sourceBreakdown so tooltip rendering covers the new intake-type and source sections.

packages/web/src/components/MicronutrientChart.stories.tsx

NutritionDataQualityPanel.stories.tsxAdd web Storybook stories for nutrition data quality panel states +67/-0

Add web Storybook stories for nutrition data quality panel states

• Introduces Storybook scenarios for partial-with-overlap, loading, complete, and empty states using the shared server DTO shape.

packages/web/src/components/NutritionDataQualityPanel.stories.tsx

SupplementSafetyReviewPanel.stories.tsxUpdate supplement safety story fixtures for new micronutrient contract +13/-0

Update supplement safety story fixtures for new micronutrient contract

• Adds providerDailyTotalAverage, sourceBreakdown, and the top-level dataQuality object to keep story fixtures aligned with the updated API response shape.

packages/web/src/components/SupplementSafetyReviewPanel.stories.tsx

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Mobile Preview

Scan to open on device:

QR code for dofek://preview/pr-2313

Channel pr-2313
Deep Link dofek://preview/pr-2313
Commit bda0f04

To test on device:

  1. Build and install the preview client: PREVIEW_CHANNEL=pr-2313 pnpm expo prebuild --clean -p ios
  2. Or tap deep link on an existing preview build: dofek://preview/pr-2313

Each PR gets its own channel. Build a preview client with PREVIEW_CHANNEL=pr-{N} to test.

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Storybook previews for bda0f047 are ready:

This comment updates automatically on each PR push.

@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/mobile/components/NutritionDataQualityPanel.test.tsx`:
- Around line 11-46: Add a test case for the all-history branch of
NutritionDataQualityPanel by passing selectedWindowDays: null with data
representing 20 usable recorded days, then assert the rendered text is “20
recorded days are usable.” Keep the existing bounded-window and loading tests
unchanged.

In `@packages/mobile/components/NutritionDataQualityPanel.tsx`:
- Line 38: Update the panel View in NutritionDataQualityPanel so it does not
hide descendant accessibility content: remove the accessible grouping and label,
or replace the label with the complete coverage, conflict, and source summaries
while preserving separate loading, error, and data-state announcements.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bfac508e-8a26-4648-b7ef-a7b57a7568ed

📥 Commits

Reviewing files that changed from the base of the PR and between a2c4477 and 6bbd3fc.

📒 Files selected for processing (23)
  • docs/superpowers/plans/2026-07-29-nutrition-source-breakdown.md
  • packages/mobile/.storybook/nutrition-analytics-story-link.ts
  • packages/mobile/app/nutrition-analytics.test.tsx
  • packages/mobile/app/nutrition-analytics.tsx
  • packages/mobile/components/NutritionDataQualityPanel.stories.tsx
  • packages/mobile/components/NutritionDataQualityPanel.test.tsx
  • packages/mobile/components/NutritionDataQualityPanel.tsx
  • packages/nutrition/README.md
  • packages/server/src/repositories/nutrition-analytics-repository.test.ts
  • packages/server/src/repositories/nutrition-analytics-repository.ts
  • packages/server/src/repositories/nutrition-analytics-source-breakdown.integration.test.ts
  • packages/server/src/routers/nutrition-analytics.test.ts
  • packages/server/src/routers/nutrition-analytics.ts
  • packages/web/src/components/MicronutrientChart.stories.tsx
  • packages/web/src/components/MicronutrientChart.test.tsx
  • packages/web/src/components/MicronutrientChart.tsx
  • packages/web/src/components/NutritionDataQualityPanel.stories.tsx
  • packages/web/src/components/NutritionDataQualityPanel.test.tsx
  • packages/web/src/components/NutritionDataQualityPanel.tsx
  • packages/web/src/components/SupplementSafetyReviewPanel.stories.tsx
  • packages/web/src/components/SupplementSafetyReviewPanel.test.tsx
  • packages/web/src/components/TimeRangeSelector.consumers.test.tsx
  • packages/web/src/pages/NutritionAnalyticsPage.tsx

Comment thread packages/mobile/components/NutritionDataQualityPanel.test.tsx
Comment thread packages/mobile/components/NutritionDataQualityPanel.tsx Outdated
@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

@qodo-code-review

qodo-code-review Bot commented Jul 29, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 206 rules

Grey Divider


Remediation recommended

1. Duplicated data-quality message logic ✓ Resolved 📘 Rule violation ⌂ Architecture
Description
The coverage and overlap message-formatting logic is duplicated in both web and mobile
NutritionDataQualityPanel, instead of being centralized in a shared domain package. This increases
the risk of platform drift and inconsistent messaging over time.
Code

packages/web/src/components/NutritionDataQualityPanel.tsx[R21-28]

+  const coverage =
+    dataQuality.selectedWindowDays == null
+      ? `${dataQuality.usableDays} recorded days are usable.`
+      : `${dataQuality.usableDays} of ${dataQuality.selectedWindowDays} selected days are usable (${dataQuality.completenessPercent}% completeness).`;
+  const overlap =
+    dataQuality.overlapDays === 0
+      ? "No overlapping nutrition sources detected."
+      : `${dataQuality.overlapDays} ${dataQuality.overlapDays === 1 ? "day contains" : "days contain"} overlapping sources; ${dataQuality.conflictDays} ${dataQuality.conflictDays === 1 ? "remains" : "remain"} unresolved.`;
Relevance

●●● Strong

Strong precedent for centralizing duplicated web/mobile formatting logic into shared packages per
rule 773501.

PR-#2275
PR-#2150

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 773501 requires shared logic used by both web and mobile to be centralized in a
domain package. Both NutritionDataQualityPanel implementations contain the same message formatting
logic for coverage and overlap, indicating duplicated cross-platform logic.

Rule 773501: Mirror web and mobile changes and centralize shared logic in domain packages
packages/web/src/components/NutritionDataQualityPanel.tsx[21-28]
packages/mobile/components/NutritionDataQualityPanel.tsx[28-35]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`NutritionDataQualityPanel` duplicates the same `coverage` and `overlap` string-building logic in both `packages/web` and `packages/mobile`, violating the requirement to centralize shared logic in a domain package.

## Issue Context
This logic (pluralization, selected-window vs all-history wording) is shared business/formatting logic that should live in a domain package (e.g. `@dofek/nutrition` or `@dofek/format`) and be imported by both clients to prevent drift.

## Fix Focus Areas
- packages/web/src/components/NutritionDataQualityPanel.tsx[21-28]
- packages/mobile/components/NutritionDataQualityPanel.tsx[28-35]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Rounded sums don’t match ✓ Resolved 🐞 Bug ≡ Correctness
Description
MicronutrientSafetyReview.toDetail() rounds each source contribution independently, so the displayed
per-source contributions can fail to add up to the displayed totalDailyAverage despite the
documented contract. This is user-visible and can be triggered by small fractional contributions
(rounding-to-0) across multiple sources.
Code

packages/server/src/repositories/nutrition-analytics-repository.ts[R220-223]

+      sourceBreakdown: this.#row.sourceBreakdown.map((source) => ({
+        ...source,
+        dailyAverageContribution: Math.round(source.dailyAverageContribution * 10) / 10,
+      })),
Relevance

●●● Strong

User-visible contract mismatch; team recently accepted nutrition rounding/correctness fixes in same
area.

PR-#2236

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The server rounds the per-source dailyAverageContribution and the intake totals independently in
toDetail(), but the nutrition README explicitly claims per-source contributions add to the
displayed total daily average; these two statements are incompatible under independent rounding.

packages/server/src/repositories/nutrition-analytics-repository.ts[208-223]
packages/nutrition/README.md[33-37]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`MicronutrientSafetyReview.toDetail()` rounds `totalDailyAverage` and each `sourceBreakdown.dailyAverageContribution` separately to 1 decimal. Independent rounding can break the documented invariant that per-source contributions add to the *displayed* total.

## Issue Context
The docs state that per-source rows “add to the displayed total daily average”, but the server currently rounds each row independently.

## Fix Focus Areas
- packages/server/src/repositories/nutrition-analytics-repository.ts[208-227]
- packages/nutrition/README.md[33-37]

## Implementation guidance
Choose one:
1) **Round at render-time only**: keep server values unrounded (or higher precision) and only format in clients.
2) **Residual allocation**: after rounding all source contributions, compute `delta = roundedTotal - sum(roundedSources)` and apply `delta` to one contribution (e.g., largest absolute contribution) so displayed sums match.
3) **Relax the contract**: if (1) or (2) is undesirable, update docs/UI copy to state values are independently rounded and may not sum exactly.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

3. Correlated source JSON aggregation ✓ Resolved 🐞 Bug ➹ Performance
Description
The new source_breakdown JSON is built via a correlated subquery per nutrient (`WHERE nutrient_id
= summary.id`), which can become a scalability bottleneck as the number of nutrients/sources grows.
Consider pre-aggregating source summaries by nutrient and joining once to avoid planner-dependent
repeated work.
Code

packages/server/src/repositories/nutrition-analytics-repository.ts[R598-621]

+            COALESCE(
+              (
+                SELECT JSONB_AGG(
+                  JSONB_BUILD_OBJECT(
+                    'providerId', source.provider_id,
+                    'sourceLabel', source.source_label,
+                    'intakeType', source.intake_type,
+                    'dailyAverageContribution',
+                      source.total_amount / NULLIF(summary.days_tracked, 0),
+                    'daysTracked', source.days_tracked
+                  )
+                  ORDER BY source.intake_type, source.source_label, source.provider_id
+                )
+                FROM (
+                  SELECT
+                    provider_id,
+                    source_label,
+                    intake_type,
+                    SUM(source_amount) AS total_amount,
+                    COUNT(*)::integer AS days_tracked
+                  FROM source_daily
+                  WHERE nutrient_id = summary.id
+                  GROUP BY provider_id, source_label, intake_type
+                ) AS source
Relevance

●● Moderate

Perf refactor is plausible but planner-dependent; repo shows mixed precedent on larger SQL
performance rewrites.

PR-#1195
PR-#1359

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The SQL in getMicronutrientSafetyReview clearly shows the source_breakdown JSON aggregation
implemented as a correlated subquery that references summary.id, which is the specific pattern
that can lead to per-row repeated aggregation work depending on the planner.

packages/server/src/repositories/nutrition-analytics-repository.ts[589-624]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`getMicronutrientSafetyReview` builds `source_breakdown` using a correlated subquery against `source_daily` filtered by `summary.id`. This query shape is planner-dependent and can devolve into repeated scans/aggregations per nutrient.

## Issue Context
The final SELECT computes `source_breakdown` with a `SELECT JSONB_AGG(...) FROM (...) WHERE nutrient_id = summary.id` correlated to each row of `nutrient_summary`.

## Fix Focus Areas
- packages/server/src/repositories/nutrition-analytics-repository.ts[514-626]

## Implementation guidance
Refactor to compute a `source_summary` CTE grouped by `(nutrient_id, provider_id, source_label, intake_type)` and then a `source_breakdown` CTE grouped by `nutrient_id` that does the `JSONB_AGG(...) ORDER BY ...`. Finally `LEFT JOIN source_breakdown USING (nutrient_id)` in the outer SELECT.

(If you keep the current shape, consider validating with `EXPLAIN (ANALYZE, BUFFERS)` on representative data to ensure it does not execute as an N-per-nutrient subplan.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread packages/web/src/components/NutritionDataQualityPanel.tsx Outdated
Comment thread packages/server/src/repositories/nutrition-analytics-repository.ts
Comment thread packages/server/src/repositories/nutrition-analytics-repository.ts Outdated
@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

@Asherlc
Asherlc force-pushed the Asherlc/issue-2136-nutrition-source-breakdown branch from dec2ef2 to 46af337 Compare July 29, 2026 22:21
@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

@Asherlc
Asherlc merged commit 10443e2 into main Jul 29, 2026
102 checks passed
@Asherlc
Asherlc deleted the Asherlc/issue-2136-nutrition-source-breakdown branch July 29, 2026 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[NUTA-02] Food, supplements, and provider totals not separated in analytics

2 participants