Skip to content

Commit

Permalink
Merge pull request #216 from PeriodPals/feat/alert/view-model
Browse files Browse the repository at this point in the history
Alert View Model
  • Loading branch information
agonzalez-r authored Nov 21, 2024
2 parents 71c6092 + e5ca8f0 commit b532942
Show file tree
Hide file tree
Showing 7 changed files with 525 additions and 11 deletions.
5 changes: 3 additions & 2 deletions app/src/main/java/com/android/periodpals/model/alert/Alert.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ package com.android.periodpals.model.alert
*/
data class Alert(
val id: String?, // given when created in supabase
val uid: String?,
val uid: String,
val name: String,
val product: Product,
val urgency: Urgency,
Expand All @@ -29,7 +29,8 @@ data class Alert(
/** Enum class representing the product requested with the alert. */
enum class Product {
TAMPON,
PAD
PAD,
TAMPON_AND_PAD,
}

/** Enum class representing the urgency level of the alert. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class AlertDto(
@SerialName("id") val id: String?,
@SerialName("uid") val uid: String?,
@SerialName("uid") val uid: String,
@SerialName("name") val name: String,
@SerialName("product") val product: Product,
@SerialName("urgency") val urgency: Urgency,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ interface AlertModel {
* Adds a new alert.
*
* @param alert The alert to be added.
* @param onSuccess Callback function to be called on successful addition, with the ID of the
* created alert as a parameter.
* @param onSuccess Callback function to be called on successful addition
* @param onFailure Callback function to be called on failure, with the exception as a parameter.
*/
suspend fun addAlert(alert: Alert, onSuccess: (String) -> Unit, onFailure: (Exception) -> Unit)
suspend fun addAlert(alert: Alert, onSuccess: () -> Unit, onFailure: (Exception) -> Unit)

/**
* Retrieves an alert by its ID.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class AlertModelSupabase(
*/
override suspend fun addAlert(
alert: Alert,
onSuccess: (String) -> Unit,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
) {
try {
Expand All @@ -40,7 +40,7 @@ class AlertModelSupabase(
val insertedAlert = insertedAlertDto.toAlert()
if (insertedAlert.id != null) {
Log.d(TAG, "addAlert: Success")
onSuccess(insertedAlert.id)
onSuccess()
} else {
Log.e(TAG, "addAlert: fail to create alert: ID is null")
onFailure(Exception("ID is null"))
Expand Down
142 changes: 142 additions & 0 deletions app/src/main/java/com/android/periodpals/model/alert/AlertViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package com.android.periodpals.model.alert

import android.util.Log
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch

private const val TAG = "AlertViewModel"

/**
* ViewModel for managing alert data.
*
* @property alertModelSupabase The repository used for loading and saving alerts.
* @property _alerts Mutable state holding the list of alerts.
* @property alerts Public state exposing the list of alerts.
*/
class AlertViewModel(private val alertModelSupabase: AlertModelSupabase) : ViewModel() {
// remove this?
private var _alerts = mutableStateOf<List<Alert>?>(listOf())
val alerts: State<List<Alert>?> = _alerts

/**
* Creates a new alert.
*
* @param alert The alert to be created.
*/
fun createAlert(alert: Alert) {
viewModelScope.launch {
alertModelSupabase.addAlert(
alert = alert,
onSuccess = {
Log.d(TAG, "createAlert: Success")
getAllAlerts() // refresh the alerts list
},
onFailure = { e -> Log.e(TAG, "createAlert: fail to create alert: ${e.message}") })
}
}

/**
* Retrieves an alert by its ID.
*
* @param idAlert The ID of the alert to be retrieved.
* @return The alert if found, null otherwise.
*/
fun getAlert(idAlert: String): Alert? {
var alert: Alert? = null
viewModelScope.launch {
alertModelSupabase.getAlert(
idAlert = idAlert,
onSuccess = { fetched ->
Log.d(TAG, "getAlert: Success")
alert = fetched
},
onFailure = { e -> Log.e(TAG, "getAlert: fail to get alert: ${e.message}") })
}
return alert
}

/**
* Retrieves all alerts.
*
* @return The list of all alerts.
*/
fun getAllAlerts(): List<Alert>? {
var alertsList: List<Alert>? = null
viewModelScope.launch {
alertModelSupabase.getAllAlerts(
onSuccess = { alerts ->
Log.d(TAG, "getAllAlerts: Success")
_alerts.value = alerts
alertsList = alerts
},
onFailure = { e -> Log.e(TAG, "getAllAlerts: fail to get alerts: ${e.message}") })
}
return alertsList
}

fun getPalAlerts(uid: String): List<Alert>? {
val palAlertList: List<Alert>? = getAllAlerts()
return palAlertList?.filter { it.uid != uid }
}

/**
* Retrieves alerts for a specific user by their UID.
*
* @param uid The UID of the user.
* @return The list of alerts for the user.
*/
fun getAlertsByUser(uid: String): List<Alert>? {
var alertsList: List<Alert>? = null
viewModelScope.launch {
alertModelSupabase.getAlertsFilteredBy(
// ideally the uid would not be passed as argument and instead we could get uid by
// UserViewModel.currentUser?.uid
cond = { eq("uid", uid) },
onSuccess = { alerts ->
Log.d(TAG, "getMyAlerts: Success")
alertsList = alerts
},
onFailure = { e -> Log.e(TAG, "getMyAlerts: fail to get alerts: ${e.message}") })
}
return alertsList
}

/**
* Updates an existing alert.
*
* @param alert The alert with updated parameters.
*/
fun updateAlert(alert: Alert) {
viewModelScope.launch {
alertModelSupabase.updateAlert(
alert = alert,
onSuccess = {
Log.d(TAG, "updateAlert: Success")
getAllAlerts()
},
onFailure = { e -> Log.e(TAG, "updateAlert: fail to update alert: ${e.message}") })
}
}

/**
* Deletes an alert.
*
* @param alert The alert to be deleted.
*/
fun deleteAlert(alert: Alert) {
viewModelScope.launch {
alert.id?.let {
alertModelSupabase.deleteAlertById(
idAlert = it,
onSuccess = {
Log.d(TAG, "deleteAlert: Success")
getAllAlerts()
},
onFailure = { e -> Log.e(TAG, "deleteAlert: fail to delete alert: ${e.message}") })
} ?: run { Log.e(TAG, "deleteAlert: fail to delete alert: id of the Alert is null") }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ class AlertModelSupabaseTest {

@Test
fun addAlertSuccess() = runBlocking {
var result = ""
var result = false

alertModelSupabase.addAlert(
alert = defaultAlert,
onSuccess = { result = it }, // Ensuring match with test expectation
onSuccess = { result = true }, // Ensuring match with test expectation
onFailure = { fail("should not call onFailure") })

assertEquals(defaultAlert.id, result)
assertEquals(true, result)
}

@Test
Expand Down
Loading

0 comments on commit b532942

Please sign in to comment.