PR with the new mood logging feature, improved insights screen, and latest patches.#42
Conversation
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (26)
📝 WalkthroughWalkthroughThis PR introduces a Mood Log System: Types, Store, Sync, and Home Check-In UI
Insights Overhaul, Hydration Error Handling, and Supporting Changes
Sequence Diagram(s)sequenceDiagram
participant HomeScreen
participant HomeMoodCheckInCard
participant useMoodLogStore
participant requestSync
participant Supabase
HomeScreen->>HomeMoodCheckInCard: render (moodLogs, hydration state)
HomeMoodCheckInCard->>useMoodLogStore: getTodayMoodLog(userId, today)
useMoodLogStore-->>HomeMoodCheckInCard: existing log or null
HomeMoodCheckInCard->>useMoodLogStore: updateMoodLog or addMoodLog
useMoodLogStore-->>HomeMoodCheckInCard: success
HomeMoodCheckInCard->>requestSync: runAutoSync("mood_change")
requestSync->>useMoodLogStore: markMoodLogsPendingSync
requestSync->>Supabase: upsert mood_logs (push)
Supabase-->>requestSync: syncedIds / failedIds
requestSync->>Supabase: select mood_logs (pull)
Supabase-->>requestSync: remoteMoodLogs
requestSync->>useMoodLogStore: markSynced / mergeRemoteMoodLogs
sequenceDiagram
participant Screen
participant ZustandStore
participant AsyncStorage
participant ScreenErrorState
Screen->>ZustandStore: subscribe (hydrationError)
ZustandStore->>AsyncStorage: persist rehydrate
AsyncStorage-->>ZustandStore: error (e.g. parse failure)
ZustandStore->>ZustandStore: normalizeAppError → hydrationError
ZustandStore-->>Screen: hydrationError set
Screen->>ScreenErrorState: render with error + onRetry
ScreenErrorState-->>Screen: user taps Retry
Screen->>ZustandStore: setState({hasHydrated:false, hydrationError:null})
Screen->>ZustandStore: persist.rehydrate()
AsyncStorage-->>ZustandStore: success
ZustandStore-->>Screen: hydrationError = null
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 21
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
store/useSyncStore.ts (1)
56-82: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winReset the sync hydration error in
clearSyncStateForUser.After introducing
hydrationError, this cleanup path still preserves it. That lets a previous user's sync-store hydration failure survive sign-out/local-data clearing and show up for the next session.Suggested fix
clearSyncStateForUser: (userId) => set((state) => { if (state.lastSyncUserId !== userId) { - return state; + return state.hydrationError ? { hydrationError: null } : state; } return { + hydrationError: null, isSyncing: false, lastAttemptAt: null, lastSyncErrorCode: null,🤖 Prompt for 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. In `@store/useSyncStore.ts` around lines 56 - 82, Reset the new hydrationError field when clearing a user’s sync state so stale hydration failures don’t leak into the next session. Update clearSyncStateForUser in useSyncStore to include hydrationError in the returned reset state alongside the existing sync fields, keeping the same userId guard and reset behavior.store/useAIInsightReportStore.ts (1)
29-39: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winDrop the cache hydration error when clearing a user's reports.
hydrationErroris now global store state, butclearReportsForUsernever resets it. Since account cleanup references this store, a stale cache-load failure can leak into the next signed-in user even after their reports are cleared.Suggested fix
clearReportsForUser: (userId) => set((state) => { if (!state.reportsByUser[userId]) { - return state; + return state.hydrationError ? { hydrationError: null } : state; } @@ - return { reportsByUser }; + return { + hydrationError: null, + reportsByUser, + }; }),Also applies to: 47-99
🤖 Prompt for 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. In `@store/useAIInsightReportStore.ts` around lines 29 - 39, The clearReportsForUser action in useAIInsightReportStore leaves the global hydrationError untouched, so a previous cache-load failure can carry over to the next user. Update clearReportsForUser to reset hydrationError whenever a user’s reports are cleared, and make sure any related cleanup paths in the store that remove user-scoped report data also clear this global error state.store/useChatStore.ts (1)
58-70: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winClear chat hydration errors during user-data cleanup.
After adding the global
hydrationError,clearMessagesForUserstill only filtersmessages. The account cleanup path already touches this store, so a failed chat rehydrate can survive sign-out and keep the next session in an error state.Suggested fix
clearMessagesForUser: (userId) => set((state) => ({ + hydrationError: null, messages: state.messages.filter((message) => message.userId !== userId), })),🤖 Prompt for 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. In `@store/useChatStore.ts` around lines 58 - 70, `clearMessagesForUser` currently removes only the user’s messages, but it should also reset any lingering `hydrationError` during account cleanup. Update the `clearMessagesForUser` action in `useChatStore` so that when it clears messages for a given user, it also clears the store’s `hydrationError` state to avoid carrying a failed rehydrate into the next session.
🤖 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 `@components/achievements/AchievementsScreen.tsx`:
- Around line 130-132: The retryJournalHydration flow is resetting hydration
flags through useJournalStore.setState, which still goes through the persisted
store and can overwrite saved journal data before rehydrate() completes. Update
this retry path to use a separate non-persisted hydration reset mechanism in
useJournalStore/persist handling so only hasHydrated and hydrationError are
cleared without writing the current initial allEntries snapshot back to storage.
Ensure retryJournalHydration still triggers persist.rehydrate() afterward.
In `@components/home/mood/HomeMoodCheckInCard.tsx`:
- Around line 58-74: The save action in HomeMoodCheckInCard should also be
blocked when mood log hydration has failed, because hasHydrated can be true even
while the store is still in an error state. Update the actionDisabled logic in
HomeMoodCheckInCard to include moodLogHydrationError, and ensure the UI uses
getHelperText to surface a retry/recovery path before allowing save again. Apply
the same guard anywhere else in the card’s save flow that relies on hasHydrated
or isSavedSelection so incomplete allMoodLogs state cannot be written over.
In `@components/home/mood/HomeSelectedMood.tsx`:
- Around line 22-27: Normalize the text styles in HomeSelectedMood so all Text
classes use leading-6, including the loading state and the other mismatching
instances referenced in the component. Update the relevant Text elements in
HomeSelectedMood to match the repo typography rule and keep the existing class
patterns consistent with leading-6 throughout.
- Around line 73-77: The saved-time formatter is hardcoded to "en-US", which
forces one locale for everyone; update formatSavedTime in HomeSelectedMood to
use the device/user locale instead of a fixed locale so the time label matches
local formatting preferences. Keep the existing hour and minute options, but
source the locale dynamically from the runtime/environment rather than a literal
string.
In `@components/home/mood/MoodOption.tsx`:
- Around line 42-49: The mood option label in MoodOption should follow the
typography rule by using leading-6 instead of the current line-height class.
Update the Text element in MoodOption so the new mood option text keeps the
repo-wide leading-6 convention, and check any nearby text styles in this
component for the same mismatch.
In `@components/insights/insights-screen.tsx`:
- Around line 141-154: The mood journey card is still using a fixed weekly data
source, so it can drift from the currently selected period. Update
`getLocalInsights()` and the `insights`/`derivedInsights` flow in
`insights-screen.tsx` so the mood journey chart is built from the same period
inputs as `deriveInsights` (for example by passing `selectedPeriod` and
`selectedReferenceDate` through to the mood journey helper instead of always
calling `getWeeklyMoodJourney(entries)`). Make sure the period-aware logic is
applied consistently in the related helpers and render paths so the summary
cards and chart always reflect one time window.
- Around line 186-192: The recurring themes lookup in insights-screen.tsx is
incorrectly backfilling from whichever report exists, which can leak themes from
the wrong timeframe. Update the recurringThemes useMemo logic around
getRecurringThemes so it only uses a report that matches selectedPeriod and
selectedReferenceDate, or returns no fallback when the current period has no
local themes. Make sure the same period-aware rule is applied anywhere else the
recurring themes fallback is computed, including the related block referenced by
the comment.
In `@components/insights/MoodDistributionCard.tsx`:
- Around line 25-34: The MoodDistributionCard text styles still use leading-5 in
several rows, which breaks the repo’s typography standard. Update the Text
elements in MoodDistributionCard to use leading-6 consistently, including the
affected repeated blocks in the render output, and verify the
label/count/percentage lines all match the same leading-6 rule.
- Line 18: The `MoodDistributionCard` empty-state branch is using the generic
onboarding message whenever `moodDistribution` is empty, even if
`entriesWithoutMood` indicates there are existing entries with no mood. Update
the conditional rendering in `MoodDistributionCard` to distinguish “no entries
yet” from “entries exist but none have moods,” and show the omitted-mood state
for the latter instead of the start-adding-moods onboarding state.
In `@components/journal-history/journal-history-screen.tsx`:
- Around line 158-160: The retryJournalHydration helper is mutating the
persisted journal store before rehydration, which can overwrite saved entries
with the fallback state. Update retryJournalHydration to avoid calling
useJournalStore.setState for hasHydrated and hydrationError before
useJournalStore.persist.rehydrate(), and instead clear hydration UI state in a
non-persisted way or after rehydrate completes while keeping the persisted
journal payload untouched.
In `@components/profile/profile-screen.tsx`:
- Around line 117-130: Manual sync should be blocked when journal hydration
fails, because the screen currently relies on hasHydrated alone even though the
rehydrate contract can set hasHydrated true on failure. Update the manual sync
path in profile-screen.tsx to use journalDataReady (or explicitly check
hydrationError) the same way the export guard does, so sync cannot run against
an unavailable in-memory journal snapshot. Use the existing identifiers
journalDataReady, hasHydrated, hydrationError, and the manual sync handler in
ProfileScreen to keep the behavior consistent.
In `@docs/insights-data-audit.md`:
- Line 1: Add a top-level H1 heading before the table in the markdown document
to satisfy the lint rule. Update the document so the table remains intact, but
is preceded by a clear title at the top of the file; this change should be made
in the same markdown file and does not require altering the table content
itself.
In `@hooks/useEntryReflection.ts`:
- Around line 73-77: The cache hydration error handling in useEntryReflection is
too final and blocks refresh, generate, and regenerate for the whole session.
Add an explicit rehydrate path in the useEntryReflection hook by calling
useEntryReflectionStore.persist.rehydrate() before bailing out, then clear
hydrationError if rehydration succeeds so the reflection actions can recover
from transient failures.
In `@lib/sync/moodLogSync.ts`:
- Around line 147-151: The restore flow in moodLogSync currently uses
rows.map(parseMoodLogRow), so a single malformed cloud record can throw and
abort the entire sync. Update the row-processing logic in the affected
restore/mapping path (including the section around parseMoodLogRow and
mapMoodLogRowToMoodLog, plus the same pattern in the later matching block) to
catch per-row parse failures, skip invalid mood_logs entries, and continue
syncing the remaining valid rows instead of propagating the error.
- Around line 5-12: The hardcoded moodIds allowlist in moodLogSync duplicates
the canonical mood set and can drift from the shared source. Replace this local
array with the shared mood metadata from constants/moods.ts (or an exported
helper derived from it) so isMoodId() validates against the single source of
truth and stays in sync with any mood additions or renames.
In `@store/journal-store.ts`:
- Line 291: The hydration runtime flags are being written through the persisted
journal store, which can accidentally persist stale state and overwrite
recoverable entries. Move the hydration-only state and updates for hasHydrated
and hydrationError out of useJournalStore into a non-persisted store/slice, or
otherwise suppress persistence when onRehydrateStorage and the retry handlers
update these values. Keep the persisted journal data focused on allEntries and
related durable fields only.
In `@store/notification-preferences-store.ts`:
- Around line 37-43: The resetNotificationPreferences action in
notification-preferences-store still preserves hydrationError, so resetting
after a failed rehydrate can leave stale local-storage errors behind. Update the
reset logic in the store initializer to reset both the default notification
preference fields and hydrationError together, using the existing
resetNotificationPreferences and setHydrationError symbols so the store returns
to a clean state after reset.
In `@store/useAchievementStore.ts`:
- Line 129: The hydration error handling in useAchievementStore is currently
persisted, so an onRehydrateStorage failure can write default
achievementNotificationsByUserId data back into storage and overwrite existing
history. Update setHydrationError so it only affects runtime state, either by
moving hydrationError to a non-persisted field or by routing it through a
non-persisted action that bypasses persist, and keep the existing notifications
data out of any hydration-failure write path.
In `@store/useEntryReflectionStore.ts`:
- Line 77: Hydration state is still being written through the persisted
reflection store, which can overwrite cached reflections during rehydrate
failures. Update useEntryReflectionStore so setHydrationError and setHasHydrated
live outside the persisted slice, or split hydration state into a separate
non-persisted store. Keep the persisted store focused on reflection data only,
and ensure the hydration callbacks in useEntryReflectionStore no longer trigger
persist-backed updates.
In `@store/useMoodLogStore.ts`:
- Around line 83-112: The mood log mutations can run before Zustand persist
hydration completes, and later rehydration may overwrite the newly added or
updated entry. Update the `useMoodLogStore` actions (`addMoodLog` and
`updateMoodLog`) to block writes until `hasHydrated` is true, and make the home
mood save path check that hydration guard before calling them. Use the existing
`onRehydrateStorage`/`hasHydrated` state in `useMoodLogStore` so `allMoodLogs`
is not mutated until hydration finishes.
- Around line 115-122: The `clearMoodLogsForUser` action only filters
`allMoodLogs`, so a previous session’s store-wide hydration failure can persist
after account cleanup. Update `clearMoodLogsForUser` in `useMoodLogStore` to
also reset `hydrationError` to null when removing a user’s mood logs, keeping
the store state clean for the next session.
---
Outside diff comments:
In `@store/useAIInsightReportStore.ts`:
- Around line 29-39: The clearReportsForUser action in useAIInsightReportStore
leaves the global hydrationError untouched, so a previous cache-load failure can
carry over to the next user. Update clearReportsForUser to reset hydrationError
whenever a user’s reports are cleared, and make sure any related cleanup paths
in the store that remove user-scoped report data also clear this global error
state.
In `@store/useChatStore.ts`:
- Around line 58-70: `clearMessagesForUser` currently removes only the user’s
messages, but it should also reset any lingering `hydrationError` during account
cleanup. Update the `clearMessagesForUser` action in `useChatStore` so that when
it clears messages for a given user, it also clears the store’s `hydrationError`
state to avoid carrying a failed rehydrate into the next session.
In `@store/useSyncStore.ts`:
- Around line 56-82: Reset the new hydrationError field when clearing a user’s
sync state so stale hydration failures don’t leak into the next session. Update
clearSyncStateForUser in useSyncStore to include hydrationError in the returned
reset state alongside the existing sync fields, keeping the same userId guard
and reset behavior.
🪄 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: Repository UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 3da5e11d-2cd1-4719-9251-e0c8f40e31e6
📒 Files selected for processing (54)
AGENTS.mdapp/insights/report/[periodType].tsxcomponents/achievements/AchievementsScreen.tsxcomponents/ai-chat/ai-chat-screen.tsxcomponents/home/home-screen.tsxcomponents/home/mood/HomeMoodCheckInCard.tsxcomponents/home/mood/HomeSelectedMood.tsxcomponents/home/mood/MoodCheckInAction.tsxcomponents/home/mood/MoodOption.tsxcomponents/home/mood/MoodSpectrumSelector.tsxcomponents/insights/InsightsPeriodNavigator.tsxcomponents/insights/InsightsPeriodSelector.tsxcomponents/insights/InsightsSummaryGrid.tsxcomponents/insights/JournalingRhythmCard.tsxcomponents/insights/MoodDistributionCard.tsxcomponents/insights/RecurringThemesCard.tsxcomponents/insights/insights-screen.tsxcomponents/insights/report/ReportScreenStates.tsxcomponents/journal-editor/journal-editor-screen.tsxcomponents/journal-history/journal-calendar-view.tsxcomponents/journal-history/journal-history-screen.tsxcomponents/profile/notification-settings-screen.tsxcomponents/profile/profile-screen.tsxcomponents/states/ScreenErrorState.tsxcomponents/states/StaleDataNotice.tsxcomponents/sync/SyncStatusIndicator.tsxcomponents/sync/SyncStatusRow.tsxcomponents/sync/auto-sync-manager.tsxdata/home.tsdocs/home-mood-check-in.mddocs/insights-data-audit.mddocs/screen-state-audit.mdhooks/useAIInsightReport.tshooks/useAutoSync.tshooks/useEntryReflection.tshooks/useSyncStatus.tslib/account/clearLocalUserData.tslib/errors/normalizeAppError.tslib/insights/deriveInsights.tslib/insights/insightPeriodUtils.tslib/sync/mergeMoodLogs.tslib/sync/moodLogSync.tslib/sync/moodLogTwoWaySync.tslib/sync/requestSync.tsstore/journal-store.tsstore/notification-preferences-store.tsstore/useAIInsightReportStore.tsstore/useAchievementStore.tsstore/useChatStore.tsstore/useEntryReflectionStore.tsstore/useMoodLogStore.tsstore/useSyncStore.tstypes/insights.tstypes/moodLog.ts
💤 Files with no reviewable changes (1)
- data/home.ts
|
Caution Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted. Error details |
Summary by CodeRabbit
New Features
Bug Fixes