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

Refactor Statistics screen, improve text formatting/style #201

Merged
merged 5 commits into from
Nov 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/src/main/java/com/mensinator/app/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.mensinator.app

import android.app.Application
import com.mensinator.app.settings.SettingsViewModel
import com.mensinator.app.statistics.StatisticsViewModel
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.core.context.startKoin
Expand All @@ -22,6 +23,7 @@ class App : Application() {
singleOf(::NotificationScheduler) { bind<INotificationScheduler>() }

viewModel { SettingsViewModel(get(), get(), get()) }
viewModel { StatisticsViewModel(get(), get(), get(), get(), get()) }
}

override fun onCreate() {
Expand Down
17 changes: 8 additions & 9 deletions app/src/main/java/com/mensinator/app/CalculationsHelper.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package com.mensinator.app

import android.util.Log
import com.mensinator.app.extensions.roundToTwoDecimalPoints
import java.time.LocalDate
import kotlin.math.round

class CalculationsHelper(
private val dbHelper: IPeriodDatabaseHelper,
) : ICalculationsHelper {
private val periodHistory = dbHelper.getSettingByKey("period_history")?.value?.toIntOrNull() ?: 5
private val ovulationHistory = dbHelper.getSettingByKey("ovulation_history")?.value?.toIntOrNull() ?: 5
private val lutealCalculation = dbHelper.getSettingByKey("luteal_period_calculation")?.value?.toIntOrNull() ?: 0
private val periodHistory
get() = dbHelper.getSettingByKey("period_history")?.value?.toIntOrNull() ?: 5
private val ovulationHistory
get() = dbHelper.getSettingByKey("ovulation_history")?.value?.toIntOrNull() ?: 5
private val lutealCalculation
get() = dbHelper.getSettingByKey("luteal_period_calculation")?.value?.toIntOrNull() ?: 0

override fun calculateNextPeriod(): LocalDate {
val expectedPeriodDate: LocalDate
Expand Down Expand Up @@ -119,7 +122,7 @@ class CalculationsHelper(
if (growthRate.isEmpty()) {
return 0.0
}
return growthRate.average().roundTo2Decimals()
return growthRate.average().roundToTwoDecimalPoints()
}
}

Expand Down Expand Up @@ -221,8 +224,4 @@ class CalculationsHelper(
}

}

private fun Double.roundTo2Decimals(): Double {
return (round(this * 100) / 100)
}
}
113 changes: 0 additions & 113 deletions app/src/main/java/com/mensinator/app/StatisticsScreen.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.mensinator.app.extensions

import java.util.Locale
import kotlin.math.round

fun Double.formatToOneDecimalPoint(): String {
if (this.isNaN()) return "-"
return String.format(Locale.getDefault(), "%.1f", this)
}

fun Double.roundToTwoDecimalPoints(): Double {
return (round(this * 100) / 100)
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import androidx.navigation.compose.rememberNavController
import com.mensinator.app.*
import com.mensinator.app.R
import com.mensinator.app.settings.SettingsScreen
import com.mensinator.app.statistics.StatisticsScreen
import org.koin.compose.koinInject

enum class Screen(@StringRes val titleRes: Int) {
Expand Down
144 changes: 144 additions & 0 deletions app/src/main/java/com/mensinator/app/statistics/StatisticsScreen.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package com.mensinator.app.statistics

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.mensinator.app.R
import com.mensinator.app.navigation.displayCutoutExcludingStatusBarsPadding
import com.mensinator.app.ui.theme.MensinatorTheme
import org.koin.androidx.compose.koinViewModel

@Composable
fun StatisticsScreen(
modifier: Modifier = Modifier,
viewModel: StatisticsViewModel = koinViewModel(),
) {
val state = viewModel.viewState.collectAsStateWithLifecycle().value

LaunchedEffect(Unit) {
viewModel.refreshData()
}

StatisticsScreenContent(modifier, state)
}

@Composable
private fun StatisticsScreenContent(
modifier: Modifier = Modifier,
state: StatisticsViewModel.ViewState
) {
Column(
modifier = modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
.displayCutoutExcludingStatusBarsPadding()
.padding(horizontal = 16.dp)
) {
RowOfText(
stringResource(id = R.string.period_count),
state.trackedPeriods
)
RowOfText(
stringResource(id = R.string.average_cycle_length),
state.averageCycleLength
)
RowOfText(
stringResource(id = R.string.average_period_length),
state.averagePeriodLength
)
RowOfText(
stringResource(id = R.string.next_period_start_future),
state.periodPredictionDate
)
RowOfText(
stringResource(id = R.string.ovulation_count),
state.ovulationCount
)
RowOfText(
stringResource(id = R.string.average_ovulation_day),
state.follicleGrowthDays
)
RowOfText(
stringResource(id = R.string.next_predicted_ovulation),
state.ovulationPredictionDate
)
RowOfText(
stringResource(id = R.string.average_luteal_length),
state.averageLutealLength
)
}
}

@Composable
fun RowOfText(stringOne: String, stringTwo: String?) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Absolute.SpaceAround
) {
Text(
text = stringOne,
modifier = Modifier
.weight(0.7f)
.padding(end = 8.dp),
)
stringTwo?.let {
Text(
text = it,
modifier = Modifier.alignByBaseline().widthIn(max = 200.dp),
style = MaterialTheme.typography.titleMedium,
textAlign = TextAlign.End
)
}
}
}

@Preview(showBackground = true)
@Composable
private fun RowOfTextPreview() {
RowOfText("firstString", "secondstring")
}

@Preview(showBackground = true)
@Composable
private fun RowOfTextLongPreview() {
RowOfText("Very long first string, we could even use lorem ipsum here", "secondstring")
}

@Preview(showBackground = true)
@Composable
private fun RowOfTextLongSecondPreview() {
RowOfText("Short Text", "first string, we could even use lorem ipsum here")
}

@Preview(showBackground = true)
@Composable
private fun StatisticsScreenPreview() {
MensinatorTheme {
StatisticsScreenContent(
state = StatisticsViewModel.ViewState(
trackedPeriods = "3",
averageCycleLength = "28.5 days",
averagePeriodLength = "5.0 days",
periodPredictionDate = "28 Feb 2024",
ovulationCount = "4",
ovulationPredictionDate = "20 Mar 2024",
follicleGrowthDays = "14.0",
averageLutealLength = "15.0 days"
)
)
}
}
Loading