Skip to content

[SLEEP-02] Unify missing sleep data state - #2279

Merged
Asherlc merged 2 commits into
mainfrom
codex/issue-2126
Jul 29, 2026
Merged

Asherlc merged 2 commits into
mainfrom
codex/issue-2126

Conversation

@Asherlc

@Asherlc Asherlc commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Summary

  • collapse unavailable sleep performance and need cards into one full-width prerequisite card on web
  • replace duplicate Last Night and Sleep Coach empty cards with one Sleep Data Needed card on mobile
  • preserve the server-owned missing-sleep message and add tests plus Storybook states

Validation

  • pnpm exec vitest run packages/web/src/components/SleepOverviewCards.test.tsx "packages/mobile/app/(tabs)/index.test.tsx"
  • pnpm test:changed
  • pnpm typecheck
  • pnpm lint:sandbox
  • pnpm storybook:web:build

Closes #2126

Summary by Sourcery

Unify handling of missing sleep data across web and mobile by centralizing the sleep overview layout and showing a single prerequisite card when prior-night sleep is unavailable.

New Features:

  • Introduce a combined SleepOverviewCards component on web to coordinate display of sleep performance and sleep need cards, including a unified missing-data state.
  • Add a Sleep Data Needed card on mobile that replaces separate Last Night and Sleep Coach placeholders when prior-night sleep data is missing.

Bug Fixes:

  • Ensure the server-provided missing previous night sleep message is surfaced consistently in web and mobile UIs when sleep data is unavailable.

Enhancements:

  • Refine mobile dashboard logic and Storybook seeds to track sleep data availability via the sleepNeed availability field instead of duplicative placeholders.
  • Add Storybook stories and unit tests for the new unified sleep overview states on web and the mobile Today screen missing-sleep scenario.

Summary by cubic

Unifies the “missing previous-night sleep” state across web and mobile so users see a single “Sleep Data Needed” card with the server message when last night’s data is missing. Aligns with SLEEP-02/#2126.

  • New Features

    • Web: Added SleepOverviewCards and show one full-width prerequisite card when sleep data is missing; includes Storybook (Loading/NoData/Missing states) and tests.
    • Mobile: Replaced empty “Last Night” and “Sleep Coach” with one “Sleep Data Needed” card; hides the other cards; updated stories and tests.
  • Bug Fixes

    • Aligned Storybook seeds with the server MISSING_PREVIOUS_NIGHT_MESSAGE and added a sleepDataUnavailable toggle to reflect the missing-data state accurately.

Written for commit d1eb70f. Summary will update on new commits.

Review in cubic

Copilot AI review requested due to automatic review settings July 29, 2026 06:47
@Asherlc Asherlc linked an issue Jul 29, 2026 that may be closed by this pull request
@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.

@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.

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.

@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

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@Asherlc, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d754624c-f501-4784-8f9b-f05ac32dd605

📥 Commits

Reviewing files that changed from the base of the PR and between 1e66202 and d1eb70f.

📒 Files selected for processing (7)
  • packages/mobile/app/(tabs)/index.stories.tsx
  • packages/mobile/app/(tabs)/index.test.tsx
  • packages/mobile/app/(tabs)/index.tsx
  • packages/web/src/components/SleepOverviewCards.stories.tsx
  • packages/web/src/components/SleepOverviewCards.test.tsx
  • packages/web/src/components/SleepOverviewCards.tsx
  • packages/web/src/pages/SleepPage.tsx

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

Unifies the handling of missing prior-night sleep data across web and mobile by centralizing web sleep cards into a new SleepOverviewCards component and gating mobile sleep summary/coach sections behind a single “Sleep Data Needed” prerequisite state, with supporting tests and Storybook stories using the server-owned missing-sleep message.

Sequence diagram for unified mobile sleep data missing state

sequenceDiagram
  participant TodayScreen
  participant dashboardData
  participant SleepNeedCard
  participant SleepPerformanceCard
  participant SleepDataNeededCard

  TodayScreen->>dashboardData: read sleepNeed
  dashboardData-->>TodayScreen: sleepNeed
  TodayScreen->>TodayScreen: isSleepDataMissing = sleepNeed.availability === missing_previous_night

  alt sleepDataMissing
    TodayScreen->>SleepDataNeededCard: render Card title Sleep Data Needed with sleepNeed.message
    TodayScreen-x SleepNeedCard: skip rendering
    TodayScreen-x SleepPerformanceCard: skip rendering
  else sleepDataAvailable
    TodayScreen->>SleepPerformanceCard: render with sleepPerformance
    TodayScreen->>SleepNeedCard: render with sleepNeed
  end
Loading

File-Level Changes

Change Details Files
Introduce SleepOverviewCards on web to layout sleep performance/need cards and handle the full-width missing-sleep prerequisite state.
  • Replace separate SleepPerformanceCard and SleepNeedCard usage on SleepPage with new SleepOverviewCards container component.
  • Implement SleepOverviewCards to switch between a two-column layout and a single-column full-width layout when sleepNeed.availability is missing_previous_night.
  • Ensure SleepPerformanceCard is hidden while SleepNeedCard is still shown when sleep data is missing, using a shared data-testid for testing.
packages/web/src/pages/SleepPage.tsx
packages/web/src/components/SleepOverviewCards.tsx
Add web tests and Storybook coverage for SleepOverviewCards including loading, no-data, and missing-sleep states using the server-owned message.
  • Create SleepOverviewCards Storybook stories for default, loading, no-data, and missing_previous_night scenarios with realistic sample data.
  • Mock SleepNeedCard and SleepPerformanceCard and add unit tests to assert grid layout and card visibility for both available and missing_previous_night states.
  • Source the missing previous night message from the sleep-need-contract for consistency with server behavior.
packages/web/src/components/SleepOverviewCards.stories.tsx
packages/web/src/components/SleepOverviewCards.test.tsx
Unify mobile TodayScreen missing-sleep behavior into a single "Sleep Data Needed" card that suppresses Last Night and Sleep Coach when prior-night sleep is missing.
  • Introduce an isSleepDataMissing flag derived from sleepNeed.availability === missing_previous_night.
  • Render a dedicated Sleep Data Needed Card showing sleepNeed.message when isSleepDataMissing is true, before the normal sleep summary section.
  • Gate the existing sleep summary and Sleep Coach sections so they only render when sleep data is not missing, and remove the inline fallback message in the Sleep Coach card.
packages/mobile/app/(tabs)/index.tsx
Update mobile TodayScreen test and Storybook wiring to support the unified missing-sleep state and ensure it uses the server-provided message.
  • Adjust TodayScreen test to assert that only the Sleep Data Needed card appears when prior sleep is missing, and that Last Night, Sleep Coach, and legacy messages are absent.
  • Wire the Storybook MockProviders to accept a sleepDataUnavailable flag, controlling sleep.lastNight and sleepNeed availability/message via MISSING_PREVIOUS_NIGHT_MESSAGE.
  • Add a SleepDataNeeded Storybook story that uses sleepDataUnavailable=true to exercise the unified missing-sleep state in the Today tab.
packages/mobile/app/(tabs)/index.test.tsx
packages/mobile/app/(tabs)/index.stories.tsx

Assessment against linked issues

Issue Objective Addressed Explanation
#2126 On web Sleep page, replace blank/incomplete sleep cards shown when sleep data is missing with a single unified prerequisite state/card indicating that sleep data is needed.
#2126 On mobile Today screen, replace duplicate/empty sleep cards shown when sleep data is missing with a single unified Sleep Data Needed card (with a clear heading and message) instead of separate blank or redundant cards.

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

Unify missing sleep data states across web and mobile

🐞 Bug fix 🧪 Tests ✨ Enhancement 🕐 20-40 Minutes

Grey Divider

AI Description

• Replaces duplicate missing-sleep cards with one prerequisite state across web and mobile.
• Preserves the server-provided message as the single source of user guidance.
• Adds regression tests and Storybook scenarios for available, loading, and missing states.
Diagram

graph TD
A["Sleep Need API"] --> B{"Prior night missing?"}
B -- Yes --> C["Web Overview"] --> D["Full-width Need Card"]
B -- Yes --> E["Mobile Today"] --> F["Sleep Data Needed"]
B -- No --> G["Two Web Cards"]
B -- No --> H["Mobile Sleep Cards"]
Loading
High-Level Assessment

The current approach is appropriate: the web wrapper centralizes layout and visibility decisions without coupling the existing cards, while mobile branches once around its two sleep sections. Modifying each card independently was considered but would duplicate availability checks and make coordinated suppression harder; changing the server contract is unnecessary because it already provides the authoritative state and message.

Files changed (7) +234 / -38

Bug fix (2) +50 / -5
index.tsxCollapse mobile missing-sleep states into one card +16/-5

Collapse mobile missing-sleep states into one card

• Detects the missing_previous_night availability state and renders a single prerequisite card. Hides the separate Last Night and Sleep Coach cards for that state.

packages/mobile/app/(tabs)/index.tsx

SleepOverviewCards.tsxCoordinate web sleep overview cards by availability +34/-0

Coordinate web sleep overview cards by availability

• Introduces a wrapper that owns sleep card layout and visibility. It collapses missing prior-night data to the sleep-need card and otherwise renders both existing cards.

packages/web/src/components/SleepOverviewCards.tsx

Refactor (1) +7 / -6
SleepPage.tsxAdopt the unified sleep overview component +7/-6

Adopt the unified sleep overview component

• Replaces direct sleep performance and need card rendering with SleepOverviewCards. Passes through existing query data and loading states.

packages/web/src/pages/SleepPage.tsx

Tests (4) +177 / -27
index.stories.tsxAdd a mobile missing-sleep Storybook state +44/-24

Add a mobile missing-sleep Storybook state

• Makes seeded dashboard data configurable for missing prior-night sleep. Adds a Sleep Data Needed story using the server-owned prerequisite message.

packages/mobile/app/(tabs)/index.stories.tsx

index.test.tsxVerify the unified mobile prerequisite card +5/-3

Verify the unified mobile prerequisite card

• Updates the missing-sleep regression test to expect one Sleep Data Needed card. Confirms the Last Night, Sleep Coach, and generic empty states are suppressed while preserving the server message.

packages/mobile/app/(tabs)/index.test.tsx

SleepOverviewCards.stories.tsxDocument web sleep overview states in Storybook +75/-0

Document web sleep overview states in Storybook

• Adds stories for available, loading, empty, and missing prior-night sleep states. The missing-data story uses the shared server contract message.

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

SleepOverviewCards.test.tsxTest conditional web sleep card composition +53/-0

Test conditional web sleep card composition

• Verifies that missing sleep data produces one full-width sleep-need card without the performance card. Also confirms normal states retain both cards and the responsive two-column layout.

packages/web/src/components/SleepOverviewCards.test.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-2279

Channel pr-2279
Deep Link dofek://preview/pr-2279
Commit 833a986

To test on device:

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

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 833a9868 are ready:

This comment updates automatically on each PR push.

@qodo-code-review

qodo-code-review Bot commented Jul 29, 2026

Copy link
Copy Markdown

Code Review by Qodo

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

Context used
✅ Compliance rules (platform): 178 rules

Grey Divider


Informational

1. Missing story contradicts itself ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The new SleepDataNeeded story marks prior-night sleep as unavailable, but its independent Today
Plan fixture still displays yesterday's sleep performance as 88 (Good). This creates contradictory
Storybook output and weakens visual-regression coverage of the missing-sleep state.
Code

packages/mobile/app/(tabs)/index.stories.tsx[R260-263]

+export const SleepDataNeeded: Story = {
+  parameters: {
+    sleepDataUnavailable: true,
+  },
Relevance

⭐⭐⭐ High

PRs #2272 and #1222 accepted truthful, complete missing-data fixtures; #2207 emphasized Today Plan
freshness consistency.

PR-#2272
PR-#1222
PR-#2207

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The dashboard fixture conditionally emits missing_previous_night, but the Today Plan fixture is
always seeded with a Sleep performance value of 88 (Good) and yesterday's sleep freshness.
TodayPlanCard renders both supporting facts and freshness, so the contradiction is visible in the
new story.

packages/mobile/app/(tabs)/index.stories.tsx[71-111]
packages/mobile/components/TodayPlanCard.tsx[63-83]

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

## Issue description
The `SleepDataNeeded` story switches the dashboard to a missing-previous-night state while retaining a ready Today Plan that visibly claims yesterday's sleep performance was `88 (Good)`. Make the story's independently seeded query data represent one coherent missing-sleep state.

## Issue Context
When `sleepDataUnavailable` is true, either seed an appropriate insufficient-data Today Plan or remove its sleep-derived supporting fact and prior-night freshness value. Preserve the existing ready fixture for the default story.

## Fix Focus Areas
- packages/mobile/app/(tabs)/index.stories.tsx[71-111]
- packages/mobile/app/(tabs)/index.stories.tsx[260-263]

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


2. Story uses inline styles 📘 Rule violation ⚙ Maintainability
Description
The new Storybook decorator uses a static style object for width and maximum width instead of
Tailwind utilities. These layout values are directly expressible with Tailwind classes.
Code

packages/web/src/components/SleepOverviewCards.stories.tsx[34]

+      <div style={{ width: "100%", maxWidth: 900 }}>
Relevance

⭐ Low

PR #2226 explicitly rejected Tailwind-only feedback targeting newly introduced web inline styles.

PR-#2226

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 722046 requires changed UI files to use Tailwind utilities and identifies static
inline styles as a red flag. The cited decorator adds style={{ width: "100%", maxWidth: 900 }}
even though both declarations have direct Tailwind equivalents.

Rule 722046: Use Tailwind CSS utility classes for all styling
packages/web/src/components/SleepOverviewCards.stories.tsx[34-34]

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

## Issue description
The `SleepOverviewCards` Storybook decorator applies static layout styling through an inline `style` object rather than Tailwind utility classes.

## Issue Context
Replace the static width and maximum-width declarations with equivalent utilities such as `w-full max-w-[900px]`.

## Fix Focus Areas
- packages/web/src/components/SleepOverviewCards.stories.tsx[32-37]

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


3. SleepOverviewCards test renders component 📜 Skill insight ▣ Testability
Description
The new unit test renders SleepOverviewCards instead of exercising an exported builder and
asserting its returned configuration. This violates the required UI component testing approach.
Code

packages/web/src/components/SleepOverviewCards.test.tsx[R18-25]

+    render(
+      <SleepOverviewCards
+        sleepNeed={{
+          availability: "missing_previous_night",
+          message: MISSING_PREVIOUS_NIGHT_MESSAGE,
+        }}
+        sleepPerformance={null}
+      />,
Relevance

⭐ Low

PRs #2276 and #2275 explicitly rejected builder extraction and retained direct component-rendering
tests.

PR-#2276
PR-#2275

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 722152 explicitly identifies rendering a full UI component in its tests as a
failure. The cited test directly invokes render(<SleepOverviewCards ... />) and asserts on
rendered DOM output.

packages/web/src/components/SleepOverviewCards.test.tsx[18-30]
Skill: write-tests

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

## Issue description
The `SleepOverviewCards` tests render the component, while the compliance rule requires UI component tests to exercise exported builder functions and assert their returned configuration.

## Issue Context
Extract the layout and card-visibility decisions into a production-used exported builder. Have `SleepOverviewCards` consume that builder and update the tests to call it directly for missing-data and available-data states.

## Fix Focus Areas
- packages/web/src/components/SleepOverviewCards.tsx[13-31]
- packages/web/src/components/SleepOverviewCards.test.tsx[16-52]

ⓘ 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/mobile/app/(tabs)/index.stories.tsx
@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 4df0e47 into main Jul 29, 2026
100 checks passed
@Asherlc
Asherlc deleted the codex/issue-2126 branch July 29, 2026 07:09
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.

[SLEEP-02] Blank sleep card with no heading or action

2 participants