Skip to content

refactor(web): adopt <DataState> in nutrition panels#1713

Merged
Skords-01 merged 1 commit into
mainfrom
devin/1777912773-nutrition-datastate-adoption
May 4, 2026
Merged

refactor(web): adopt <DataState> in nutrition panels#1713
Skords-01 merged 1 commit into
mainfrom
devin/1777912773-nutrition-datastate-adoption

Conversation

@Skords-01
Copy link
Copy Markdown
Owner

@Skords-01 Skords-01 commented May 4, 2026

Summary

Initiative 0011 PR 2.6 — adopt the unified <DataState> wrapper inside apps/web/src/modules/nutrition/NutritionApp.tsx for the Menu "plan" tab.

The day-plan generation skeleton (SkeletonText + Skeleton pill + 3× SkeletonMealCard) used to live in an ad-hoc inline ternary that the rest of the file scrolled through. It now flows through <DataState query={dayPlanQuery} skeleton={dayPlanLoadingSkeleton}> so the loading/empty/data contract matches what finyk (PR 2.4) and fizruk (PR 2.5) already do.

Visible behaviour is preserved: while dayPlanBusy is true the user sees the same shimmering cluster; otherwise <DailyPlanCard /> renders with the existing props (including dayPlan and dayPlanBusy so its internal "regenerate meal" affordances keep working). The Recipes sub-tab branch is unchanged.

Scope rationale: NutritionApp.tsx is the only consumer in apps/web/src/modules/nutrition/** that imports @shared/components/ui/Skeleton. The meal-sheet food search (foodBusy / offBusy) drives inline list states inside the search dropdown, not panel-level skeleton swaps, and is already abstracted at the hook layer (useFoodSearch); migrating it would require re-shaping the dropdown UX and is out of scope for this PR.

Governing Skill

  • Primary skill: sergeant-web-ui
  • Secondary skill (if truly needed): sergeant-feature-delivery

Playbook

Verification

pnpm --filter @sergeant/web typecheck
pnpm --filter @sergeant/web exec eslint src/modules/nutrition/NutritionApp.tsx
pnpm --filter @sergeant/web exec vitest run src/modules/nutrition

Results:

  • typecheck: ✅ exit 0 (tsc -p tsconfig.json --noEmit && tsc -p tsconfig.sw.json --noEmit).
  • eslint NutritionApp.tsx: ✅ no warnings, no errors.
  • vitest src/modules/nutrition: ✅ 17 files, 164 / 164 tests passed.

Additional checks:

  • Local smoke / manual validation completed
  • Surface-specific checks completed

Docs and Governance

  • I updated docs that changed with the behavior, contract, workflow, or rollout.
  • I checked whether AGENTS.md needed an update.
  • I checked whether a playbook or skill needed an update.
  • I checked whether governance docs or review docs needed an update.

Updated docs:

Risk and Rollout

  • User-visible risk: none. Pure presentation wrap; same skeleton DOM, same <DailyPlanCard /> props, same conditional. <DataState> only short-circuits to skeleton when query.data === undefined; with dayPlanBusy ? undefined : dayPlan, that maps 1:1 to the previous dayPlanBusy ? skeleton : card ternary.
  • Rollout / deploy order: ship as-is on merge to main. No DB / config / env changes.
  • Backout plan: revert this PR; standalone refactor with no follow-up dependents.

Hard Rule #15

  • I read AGENTS.md before coding.
  • Internal docs I touched are in Ukrainian.
  • I did not use --no-verify.

Reviewer Notes

  • The <DataState> contract treats data === undefined as the loading sentinel and null as a successful "empty" payload. Setting data: dayPlanBusy ? undefined : dayPlan keeps the original semantics: when not busy and dayPlan === null, <DailyPlanCard /> still renders (it owns the "Згенерувати план" empty/initial state itself).
  • I purposely did not migrate the food-search dropdown (useFoodSearch.foodBusy / offBusy) — those drive inline list states inside the meal-sheet search, not panel-level skeleton swaps, and would change UX semantics if wrapped.
  • Pre-existing CI failures on main (markdown link checker, governance sync, server apiV1.test.ts, mobile vite build against @sergeant/db-schema/sqlite, Argos visual regression) are unrelated to this change — observed identically on PR 2.4 (refactor(web): adopt <DataState> in finyk Mono panels #1703) and PR 2.5 (refactor(web): adopt <DataState> in fizruk Workouts journal #1709).

Summary by cubic

Adopted the unified DataState wrapper for the nutrition Menu “plan” tab to standardize loading/empty/data handling. Keeps the same skeleton UI and DailyPlanCard behavior.

  • Refactors
    • Replaced inline ternary with DataState in NutritionApp.tsx, adding dayPlanQuery and dayPlanLoadingSkeleton.
    • Preserved DailyPlanCard props and logic (dayPlan, dayPlanBusy, regenerate meal).
    • Left the Recipes sub-tab and food-search inline states unchanged.

Written for commit 7d064c7. Summary will update on new commits.

Summary by CodeRabbit

  • Refactor
    • Improved the daily plan loading experience by adopting a shared abstraction for handling loading states, replacing manual state checks with a more consistent pattern.

Wrap the nutrition Menu "plan" tab skeleton/card path with the unified
<DataState> wrapper so the day-plan generation skeleton flows through
the same loading contract that the rest of the web app already uses
(initiative 0011 PR 2.6).

The visible behaviour is preserved: while `dayPlanBusy` is `true` we
render the same SkeletonText + Skeleton + 3x SkeletonMealCard shimmer
cluster as before; otherwise <DailyPlanCard /> is rendered with the
existing props (including dayPlan/dayPlanBusy so its internal
"regenerate meal" affordances keep working). The recipes sub-tab
branch is unchanged.

Why DataState here (and not, say, in the meal-sheet food search):
NutritionApp.tsx is the only consumer in apps/web/src/modules/nutrition
that imports the shared <Skeleton> primitives; the food-search
`foodBusy`/`offBusy` flags drive inline list states, not panel-level
loading swaps, and are already abstracted at the hook layer.
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
sergeant Ready Ready Preview, Comment May 4, 2026 4:43pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 856482d7-010f-4c2d-8e6c-80902a1eda80

📥 Commits

Reviewing files that changed from the base of the PR and between 3097207 and 7d064c7.

📒 Files selected for processing (1)
  • apps/web/src/modules/nutrition/NutritionApp.tsx

📝 Walkthrough

Walkthrough

NutritionApp.tsx refactors the day-plan loading UI to use the shared DataState abstraction. A dayPlanQuery object wraps the existing dayPlanBusy and dayPlan state, a skeleton component is extracted, and conditional rendering logic is replaced with a DataState wrapper.

Changes

Day Plan Loading UI Refactor

Layer / File(s) Summary
Imports & Abstraction
apps/web/src/modules/nutrition/NutritionApp.tsx (lines 5–12)
Add DataState and DataStateQueryLike from @shared/components/ui/DataState to enable the new data-driven rendering pattern.
Query Object & Skeleton
apps/web/src/modules/nutrition/NutritionApp.tsx (lines 421–441)
Define dayPlanQuery (mapping dayPlanBusy and dayPlan to DataStateQueryLike<...>) and dayPlanLoadingSkeleton JSX block for the loading state.
Render Integration
apps/web/src/modules/nutrition/NutritionApp.tsx (lines 653–675)
Replace inline menuSubTab === "plan" conditional logic with DataState wrapper that supplies the query object, skeleton, and renders DailyPlanCard via children callback.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Suggested labels

size/M

Poem

🐰 Hops 'round the code with glee,
DataState sets loading free!
No more if-checks strewn about,
Clean abstraction, no doubt!
The plan now flows so neat,
This refactor is quite sweet! 🌱

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor(web): adopt in nutrition panels' directly and clearly describes the main change: adopting the DataState component in the nutrition module, which matches the core objective of replacing ad-hoc loading logic with the unified DataState wrapper.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch devin/1777912773-nutrition-datastate-adoption

Review rate limit: 9/10 reviews remaining, refill in 6 minutes.

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

⏱️ CI Pipeline Duration Report

Based on the last 50 successful runs on the default branch.

Overall Pipeline

Metric Value
p50 6m 26s
p95 7m 55s
p99 9m 3s
Current run 6m 12s
vs p95 -21.7%

Trend (last 20 runs): ▃▃▁▂▃▃▃▂▃▃▂▂▄▃▃▆▅▄█▆

Per-Job Breakdown

Job p50 p95 p99 Current vs p95
Accessibility (axe-core) 2m 5s 2m 21s 2m 23s 0s -100.0%
Commit messages (commitlint) 0s 0s 0s 34s N/A
Critical-flow E2E (Playwright) 1m 36s 1m 44s 1m 44s 5m 59s +245.2%
Migration lint (AGENTS rule 0s 0s 0s 11s N/A
Pipeline duration (p95 trend) 26s 27s 27s
Secret scan (gitleaks) 8s 11s 11s 12s +9.1%
Smoke E2E (Playwright) 1m 26s 1m 40s 1m 40s
Test coverage (vitest) 2m 4s 2m 33s 2m 33s 2m 6s -17.6%
Workflow lint (actionlint) 7s 7s 7s 7s +0.0%
check 4m 12s 4m 54s 5m 6s 55s -81.3%
tsconfig strict guard (PR-1.A) 5s 14s 14s 6s -57.1%

@Skords-01 Skords-01 merged commit 10aed13 into main May 4, 2026
33 of 50 checks passed
@Skords-01 Skords-01 deleted the devin/1777912773-nutrition-datastate-adoption branch May 4, 2026 16:56
Skords-01 pushed a commit that referenced this pull request May 4, 2026
Update initiative 0011 to reflect Phase 2 progress through 2026-05-04:

- Status header bumped to include the four open <DataState> consumer
  PRs: 2.4 #1703 (finyk), 2.5 #1709 (fizruk), 2.6 #1713 (nutrition),
  2.7 #1714 (routine). Last-validated handle aligned with the actual
  initiative owner (@Skords-01).
- Phase 2 table column 'Файли (приклад)' renamed to 'Файли (фактичні
  споживачі)' and ETA column replaced with Status (PR-link). Rows for
  2.4–2.7 now point at the actual landed targets, not the initial
  guess names from the proposal draft (MonoTransactionsPanel,
  WorkoutHistoryPanel, NutritionMealsPanel, RoutineList, etc. — none
  of those components physically exist in the repo).
- New explanatory note after the table records why the file list
  diverged from the original draft (real Skeleton-based loading sites
  per module) and documents the per-module finding for 2.6 / 2.7
  (NutritionApp.tsx Menu plan branch; RoutineTimeline.tsx calendar
  branch — both modules have exactly one consumer of
  @shared/components/ui/Skeleton).

Supersedes #1710 (single doc PR for 2.4 + 2.5 only); this combined
update is the cleaner record because all four <DataState> consumer
adoption PRs landed on the same day.

Closes the doc-side of initiative 0011 PR 2.6 + 2.7.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants