Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Home Screen: Get medications for the selected date from DB instead of filtering #143

Merged
merged 9 commits into from
Jul 1, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ interface MedicationDao {
"""
SELECT *
FROM medicationentity
WHERE endDate > :date
WHERE strftime('%Y-%m-%d', medicationTime / 1000, 'unixepoch', 'localtime') = :date
ORDER BY medicationTime ASC
"""
)
fun getMedicationsForDate(date: Date): Flow<List<MedicationEntity>>
fun getMedicationsForDate(date: String): Flow<List<MedicationEntity>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class MedicationRepositoryImpl(
}
}

override fun getMedicationsForDate(date: Date): Flow<List<Medication>> {
override fun getMedicationsForDate(date: String): Flow<List<Medication>> {
return dao.getMedicationsForDate(
date = date
).map { entities ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ interface MedicationRepository {

fun getAllMedications(): Flow<List<Medication>>

fun getMedicationsForDate(date: Date): Flow<List<Medication>>
fun getMedicationsForDate(date: String): Flow<List<Medication>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ fun Date.toFormattedMonthDateString(): String {
return sdf.format(this)
}

fun Date.toFormattedYeahMonthDateString(): String {
daniel-waiguru marked this conversation as resolved.
Show resolved Hide resolved
val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
return sdf.format(this)
}

fun String.toDate(): Date? {
return try {
val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
sdf.parse(this)
}catch (e: Exception) {
e.printStackTrace()
null
}
}

fun Date.toFormattedDateShortString(): String {
val sdf = SimpleDateFormat("dd", Locale.getDefault())
return sdf.format(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,28 +219,18 @@ fun EmptyCard(navController: NavController, analyticsHelper: AnalyticsHelper) {

@Composable
fun DailyMedications(navController: NavController, analyticsHelper: AnalyticsHelper, state: HomeState, viewModel: HomeViewModel, navigateToMedicationDetail: (Medication) -> Unit) {

var filteredMedications: List<Medication> by remember { mutableStateOf(emptyList()) }

DatesHeader(analyticsHelper) { selectedDate ->
val newMedicationList = state.medications
.filter { medication ->
medication.medicationTime.toFormattedDateString() == selectedDate.date.toFormattedDateString()
}
.sortedBy { it.medicationTime }

filteredMedications = newMedicationList
DatesHeader(analyticsHelper, state.lastSelectedDate) { selectedDate ->
viewModel.selectDate(selectedDate.date)
analyticsHelper.logEvent(AnalyticsEvents.HOME_NEW_DATE_SELECTED)
}

if (filteredMedications.isEmpty()) {
if (state.medications.isEmpty()) {
EmptyCard(navController, analyticsHelper)
} else {
LazyColumn(
modifier = Modifier,
) {
items(
items = filteredMedications,
items = state.medications,
itemContent = {
MedicationCard(
medication = it,
Expand All @@ -257,10 +247,15 @@ fun DailyMedications(navController: NavController, analyticsHelper: AnalyticsHel
@Composable
fun DatesHeader(
analyticsHelper: AnalyticsHelper,
onDateSelected: (CalendarModel.DateModel) -> Unit // Callback to pass the selected date
lastSelectedDate: String,
onDateSelected: (CalendarModel.DateModel) -> Unit // Callback to pass the selected date){}
) {
val dataSource = CalendarDataSource()
var calendarModel by remember { mutableStateOf(dataSource.getData(lastSelectedDate = dataSource.today)) }
var calendarModel by remember {
mutableStateOf(
dataSource.getData(lastSelectedDate = dataSource.getLastSelectedDate(lastSelectedDate))
)
}
Column(
modifier = Modifier
.fillMaxWidth()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.waseefakhtar.doseapp.feature.home.data

import com.waseefakhtar.doseapp.extension.toDate
import com.waseefakhtar.doseapp.extension.toFormattedDateString
import com.waseefakhtar.doseapp.feature.home.model.CalendarModel
import java.util.Calendar
Expand All @@ -12,6 +13,9 @@ class CalendarDataSource {
return Date()
}

fun getLastSelectedDate(dateString: String): Date {
return dateString.toDate() ?: today
}
fun getData(startDate: Date = today, lastSelectedDate: Date): CalendarModel {
val calendar = Calendar.getInstance()
calendar.time = startDate
Expand Down Expand Up @@ -45,7 +49,10 @@ class CalendarDataSource {
return CalendarModel(
selectedDate = toItemModel(lastSelectedDate, true),
visibleDates = dateList.map {
toItemModel(it, it == lastSelectedDate)
toItemModel(
date = it,
isSelectedDate = it.toFormattedDateString() == lastSelectedDate.toFormattedDateString()
)
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ class GetMedicationsUseCase @Inject constructor(
private val repository: MedicationRepository
) {

suspend fun getMedications(): Flow<List<Medication>> {
return repository.getAllMedications()
fun getMedications(date: String? = null): Flow<List<Medication>> {
return if (date != null) {
repository.getMedicationsForDate(date)
} else repository.getAllMedications()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ import com.waseefakhtar.doseapp.domain.model.Medication
data class HomeState(
val greeting: String = "",
val userName: String = "",
val lastSelectedDate: String = "",
val medications: List<Medication> = emptyList()
)
Original file line number Diff line number Diff line change
@@ -1,27 +1,44 @@
package com.waseefakhtar.doseapp.feature.home.viewmodel

import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.waseefakhtar.doseapp.domain.model.Medication
import com.waseefakhtar.doseapp.extension.toFormattedYeahMonthDateString
import com.waseefakhtar.doseapp.feature.home.usecase.GetMedicationsUseCase
import com.waseefakhtar.doseapp.feature.home.usecase.UpdateMedicationUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import java.util.Date
import javax.inject.Inject

@HiltViewModel
class HomeViewModel @Inject constructor(
private val getMedicationsUseCase: GetMedicationsUseCase,
private val updateMedicationUseCase: UpdateMedicationUseCase
private val updateMedicationUseCase: UpdateMedicationUseCase,
private val savedStateHandle: SavedStateHandle
) : ViewModel() {

var state by mutableStateOf(HomeState())
private set
private var dateFilter = savedStateHandle.getStateFlow(
DATE_FILTER_KEY,
Date().toFormattedYeahMonthDateString()
).onEach {
state = state.copy(
lastSelectedDate = it
)
}

init {
loadMedications()
Expand All @@ -37,16 +54,23 @@ class HomeViewModel @Inject constructor(
// TODO: Get greeting by checking system time
}

@OptIn(ExperimentalCoroutinesApi::class)
fun loadMedications() {
viewModelScope.launch {
getMedicationsUseCase.getMedications().onEach { medicationList ->
state = state.copy(
medications = medicationList
)
dateFilter.flatMapLatest { selectedDate ->
getMedicationsUseCase.getMedications(selectedDate).onEach { medicationList ->
state = state.copy(
medications = medicationList
)
}
}.launchIn(viewModelScope)
}
}

fun selectDate(date: Date) {
savedStateHandle[DATE_FILTER_KEY] = date.toFormattedYeahMonthDateString()
}

fun takeMedication(medication: Medication) {
viewModelScope.launch {
updateMedicationUseCase.updateMedication(medication)
Expand All @@ -56,4 +80,7 @@ class HomeViewModel @Inject constructor(
fun getUserPlan() {
// TODO: Get user plan
}
companion object {
const val DATE_FILTER_KEY = "com.waseefakhtar.doseapp.MedicationDateFilter"
daniel-waiguru marked this conversation as resolved.
Show resolved Hide resolved
}
}
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ version-name = "1.4.1"
accompanistPermissions = "0.33.2-alpha"
activity = "1.8.0"
androidxHilt = "1.1.0"
compose = "1.6.0-alpha08"
compose = "1.6.0-beta03"
daniel-waiguru marked this conversation as resolved.
Show resolved Hide resolved
composeCompiler = "1.5.4"
composeNavigation = "2.7.5"
core = "1.12.0"
Expand All @@ -25,7 +25,7 @@ ksp = "1.9.20-1.0.14" # KSP version must be aligned with kotlin https://github.c
ktlint = "10.3.0"
lifecycle = "2.7.0-beta01"
room = "2.6.0"
material3 = "1.2.0-alpha10"
material3 = "1.2.0-beta01"
okhttp = "4.10.0"

[libraries]
Expand Down
Loading