Add notification preferences UI and subscription verification on launch

- Add NotificationPreferencesScreen (Android) and NotificationPreferencesView (iOS)
- Add NotificationPreferencesViewModel for shared business logic
- Wire up notification preferences from ProfileScreen on both platforms
- Add subscription verification on app launch for iOS (StoreKit) and Android (Google Play Billing)
- Update SubscriptionApi to match Go backend endpoints (/subscription/purchase/)
- Update StoreKit Configuration with correct product IDs and pricing ($2.99/month, $27.99/year)
- Update Android placeholder prices to match App Store pricing
- Fix NotificationPreference model to match Go backend schema

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-11-29 14:01:35 -06:00
parent 5a1a87fe8d
commit c748f792d0
21 changed files with 1032 additions and 38 deletions

View File

@@ -0,0 +1,67 @@
package com.example.casera.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.casera.models.NotificationPreference
import com.example.casera.models.UpdateNotificationPreferencesRequest
import com.example.casera.network.ApiResult
import com.example.casera.network.APILayer
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class NotificationPreferencesViewModel : ViewModel() {
private val _preferencesState = MutableStateFlow<ApiResult<NotificationPreference>>(ApiResult.Idle)
val preferencesState: StateFlow<ApiResult<NotificationPreference>> = _preferencesState
private val _updateState = MutableStateFlow<ApiResult<NotificationPreference>>(ApiResult.Idle)
val updateState: StateFlow<ApiResult<NotificationPreference>> = _updateState
fun loadPreferences() {
viewModelScope.launch {
_preferencesState.value = ApiResult.Loading
val result = APILayer.getNotificationPreferences()
_preferencesState.value = when (result) {
is ApiResult.Success -> ApiResult.Success(result.data)
is ApiResult.Error -> result
else -> ApiResult.Error("Unknown error")
}
}
}
fun updatePreference(
taskDueSoon: Boolean? = null,
taskOverdue: Boolean? = null,
taskCompleted: Boolean? = null,
taskAssigned: Boolean? = null,
residenceShared: Boolean? = null,
warrantyExpiring: Boolean? = null
) {
viewModelScope.launch {
_updateState.value = ApiResult.Loading
val request = UpdateNotificationPreferencesRequest(
taskDueSoon = taskDueSoon,
taskOverdue = taskOverdue,
taskCompleted = taskCompleted,
taskAssigned = taskAssigned,
residenceShared = residenceShared,
warrantyExpiring = warrantyExpiring
)
val result = APILayer.updateNotificationPreferences(request)
_updateState.value = when (result) {
is ApiResult.Success -> {
// Update the preferences state with the new values
_preferencesState.value = ApiResult.Success(result.data)
ApiResult.Success(result.data)
}
is ApiResult.Error -> result
else -> ApiResult.Error("Unknown error")
}
}
}
fun resetUpdateState() {
_updateState.value = ApiResult.Idle
}
}