diff --git a/app/src/main/java/app/closer/ui/home/HomeViewModel.kt b/app/src/main/java/app/closer/ui/home/HomeViewModel.kt index b945c8f3..19cc114e 100644 --- a/app/src/main/java/app/closer/ui/home/HomeViewModel.kt +++ b/app/src/main/java/app/closer/ui/home/HomeViewModel.kt @@ -70,7 +70,8 @@ enum class HomeActionTarget { Game, Challenge, DatePlan, - MemoryCapsule + MemoryCapsule, + DateMemories } enum class HomeActionTone { @@ -158,6 +159,8 @@ data class HomeUiState( val hasActiveChallenge: Boolean = false, val hasUpcomingDatePlan: Boolean = false, val hasUnlockedCapsule: Boolean = false, + // A completed date this user hasn't reflected on yet (drives the Home "reflect on your date" nudge). + val hasPendingDateReflection: Boolean = false, val weeklyRecapReady: Boolean = false, val reminderSentEvent: Boolean = false, /** "Thinking of you" nudge: in-flight guard + one-shot snackbar message (success or friendly error). */ @@ -192,7 +195,9 @@ class HomeViewModel @Inject constructor( private val outcomeRepository: OutcomeRepository, private val settingsRepository: SettingsRepository, private val activityDataSource: app.closer.data.remote.FirestoreActivityDataSource, - private val dailyQuestionResolver: app.closer.domain.usecase.DailyQuestionResolver + private val dailyQuestionResolver: app.closer.domain.usecase.DailyQuestionResolver, + private val dateMemoryDataSource: app.closer.data.remote.FirestoreDateMemoryDataSource, + private val dateReflectionDataSource: app.closer.data.remote.FirestoreDateReflectionDataSource ) : ViewModel() { private val _uiState = MutableStateFlow(HomeUiState()) @@ -289,6 +294,7 @@ class HomeViewModel @Inject constructor( var hasActiveChallenge = false var hasUpcomingDatePlan = false var hasUnlockedCapsule = false + var hasPendingDateReflection = false val coupleId = couple?.id if (couple != null && coupleId != null && uid != null) { coroutineScope { @@ -320,6 +326,16 @@ class HomeViewModel @Inject constructor( .any { it.status == "sealed" && it.unlockAt in 1L..now } }.getOrDefault(false) } + // Pending date reflection: the most recent completed date this user hasn't + // reflected on yet. The nudge chases the latest date; older un-reflected dates + // remain reachable from the Replay timeline. + val reflectionJob = async { + runCatching { + val latest = dateMemoryDataSource.getHistoryOnce(coupleId).firstOrNull() + latest != null && + !dateReflectionDataSource.hasReflected(coupleId, latest.id, uid) + }.getOrDefault(false) + } val (waitingSession, waitingRoute) = gameJob.await() hasWaitingGame = waitingSession != null waitingGameRoute = waitingRoute @@ -327,6 +343,7 @@ class HomeViewModel @Inject constructor( hasActiveChallenge = challengeJob.await() hasUpcomingDatePlan = dateJob.await() hasUnlockedCapsule = capsuleJob.await() + hasPendingDateReflection = reflectionJob.await() } } @@ -349,6 +366,7 @@ class HomeViewModel @Inject constructor( hasActiveChallenge = hasActiveChallenge, hasUpcomingDatePlan = hasUpcomingDatePlan, hasUnlockedCapsule = hasUnlockedCapsule, + hasPendingDateReflection = hasPendingDateReflection, showOutcomeBaselineDialog = showBaselineDialog, showOutcomeFollowUpDialog = followUpDay != null, outcomeFollowUpDay = followUpDay, @@ -619,6 +637,7 @@ class HomeViewModel @Inject constructor( weeklyRecapReady = weeklyRecapReady, capsuleUnlocked = hasUnlockedCapsule(), dateReminder = hasUpcomingDate(), + dateReflectionPending = hasPendingDateReflection, suggestedPackAvailable = categories.isNotEmpty(), exploreGamesAvailable = categories.isNotEmpty() ) @@ -759,6 +778,16 @@ class HomeViewModel @Inject constructor( tone = HomeActionTone.Ritual ) + Priority.DATE_REFLECTION_PENDING -> HomeAction( + eyebrow = "Date replay", + title = partnerName?.let { "Reflect on your date with $it 💭" } + ?: "Reflect on your date 💭", + body = "Capture what the night meant to you. You'll reveal your reflections together when you're both ready.", + cta = "Add your reflection", + target = HomeActionTarget.DateMemories, + tone = HomeActionTone.Reflection + ) + Priority.SUGGESTED_PACK -> categories.firstOrNull()?.let { category -> HomeAction( eyebrow = "Suggested pack", @@ -845,11 +874,20 @@ class HomeViewModel @Inject constructor( ) } + if (hasPendingDateReflection) { + actions += PendingActionCard( + title = "Reflect on your date", + subtitle = "Capture the night, then reveal together.", + priority = 6, + target = HomeActionTarget.DateMemories + ) + } + if (hasUnlockedCapsule()) { actions += PendingActionCard( title = "Capsule unlocked", subtitle = "A saved memory is ready to open together.", - priority = 6, + priority = 7, target = HomeActionTarget.MemoryCapsule ) }