diff --git a/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt b/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt index be8ad00..d7465b0 100644 --- a/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt +++ b/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt @@ -172,7 +172,6 @@ fun StudeezNavGraph( composable(StudeezDestinations.ADD_TIMER_SCREEN) { AddTimerRoute( open = open, - openAndPopUp = openAndPopUp, goBack = goBack, viewModel = hiltViewModel() ) diff --git a/app/src/main/java/be/ugent/sel/studeez/common/composable/navbar/TimePickerComposable.kt b/app/src/main/java/be/ugent/sel/studeez/common/composable/navbar/TimePickerComposable.kt new file mode 100644 index 0000000..3a59519 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/common/composable/navbar/TimePickerComposable.kt @@ -0,0 +1,24 @@ +package be.ugent.sel.studeez.common.composable.navbar + +import android.app.TimePickerDialog +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext + +@Composable +fun BasicTimePicker( + onHoursChange: (Int) -> Unit, + onMinutesChange: (Int) -> Unit, + Hours: Int, + Minutes: Int, +): TimePickerDialog { + return TimePickerDialog( + LocalContext.current, + { _, mHour: Int, mMinute: Int -> + onHoursChange(mHour) + onMinutesChange(mMinute) + }, + Hours, + Minutes, + true + ) +} diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerUiState.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerUiState.kt index 9b17121..fcfa79a 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerUiState.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerUiState.kt @@ -1,11 +1,12 @@ package be.ugent.sel.studeez.screens.timer_overview.add_timer data class AddTimerUiState( - val studyTimeHours: Float = 1f, - val studyTimeMinutes: Float = 0f, + val studyTimeHours: Int = 1, + val studyTimeMinutes: Int = 0, val withBreaks: Boolean = false, - val breakTime: Float = 5f, - val repeats: Float = 1f, - val name: String = "", - val description: String = "", + val breakTimeMinutes: Int = 5, + val breakTimeHours: Int = 0, + val repeats: Int = 1, + val name: String = "Timer", + val description: String = "Long study session", ) \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerViewModel.kt index 7e79e1e..d507974 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/AddTimerViewModel.kt @@ -3,7 +3,6 @@ package be.ugent.sel.studeez.screens.timer_overview.add_timer import androidx.compose.runtime.mutableStateOf import be.ugent.sel.studeez.data.local.models.timer_info.CustomTimerInfo import be.ugent.sel.studeez.data.local.models.timer_info.PomodoroTimerInfo -import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo import be.ugent.sel.studeez.domain.LogService import be.ugent.sel.studeez.domain.TimerDAO import be.ugent.sel.studeez.screens.StudeezViewModel @@ -24,8 +23,11 @@ class AddTimerViewModel @Inject constructor( private val studyTimeMinutes get() = uiState.value.studyTimeMinutes - private val breakTime - get() = uiState.value.breakTime + private val breakTimeHours + get() = uiState.value.breakTimeHours + + private val breakTimeMinutes + get() = uiState.value.breakTimeMinutes private val repeats get() = uiState.value.repeats @@ -36,24 +38,28 @@ class AddTimerViewModel @Inject constructor( private val description get() = uiState.value.description - fun onStudyTimeHoursChange(newValue: Float) { + fun onStudyTimeHoursChange(newValue: Int) { uiState.value = uiState.value.copy(studyTimeHours = newValue) } - fun onStudyTimeMinutesChange(newValue: Float) { + fun onStudyTimeMinutesChange(newValue: Int) { uiState.value = uiState.value.copy(studyTimeMinutes = newValue) } - fun onWithBreaksChange(newValue: Boolean) { - uiState.value = uiState.value.copy(withBreaks = newValue) + fun onWithBreaksChange() { + uiState.value = uiState.value.copy(withBreaks = !uiState.value.withBreaks) } - fun onBreakTimeChange(newValue: Float) { - uiState.value = uiState.value.copy(breakTime = newValue) + fun onBreakTimeHourChange(newValue: Int) { + uiState.value = uiState.value.copy(breakTimeHours = newValue) } - fun onRepeatsChange(newValue: Float) { + fun onBreakTimeMinutesChange(newValue: Int) { + uiState.value = uiState.value.copy(breakTimeMinutes = newValue) + } + + fun onRepeatsChange(newValue: Int) { uiState.value = uiState.value.copy(repeats = newValue) } @@ -62,15 +68,15 @@ class AddTimerViewModel @Inject constructor( timerDAO.saveTimer(PomodoroTimerInfo( name = uiState.value.name, description = uiState.value.description, - studyTime = studyTimeHours.toInt() * 60 * 60 + studyTimeMinutes.toInt() * 60, - breakTime = breakTime.toInt() * 60, - repeats = repeats.toInt() + studyTime = studyTimeHours * 60 * 60 + studyTimeMinutes * 60, + breakTime = breakTimeHours * 60 * 60 + breakTimeMinutes * 60, + repeats = repeats )) } else { timerDAO.saveTimer(CustomTimerInfo( name = uiState.value.name, description = uiState.value.description, - studyTime = studyTimeHours.toInt() * 60 * 60 + studyTimeMinutes.toInt() * 60 + studyTime = studyTimeHours * 60 * 60 + studyTimeMinutes * 60 )) } } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/addTimerScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/addTimerScreen.kt index 772917d..77bdeda 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/addTimerScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/add_timer/addTimerScreen.kt @@ -6,45 +6,54 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.Button import androidx.compose.material.Checkbox -import androidx.compose.material.Slider import androidx.compose.material.Text import androidx.compose.material.TextField import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +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 be.ugent.sel.studeez.R import be.ugent.sel.studeez.common.composable.BasicButton import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate +import be.ugent.sel.studeez.common.composable.navbar.BasicTimePicker +import be.ugent.sel.studeez.navigation.StudeezDestinations import be.ugent.sel.studeez.resources import be.ugent.sel.studeez.ui.theme.StudeezTheme data class AddTimerActions( + val open: (String) -> Unit, val goBack: () -> Unit, - val onStudyTimeHoursChange: (Float) -> Unit, - val onStudyTimeMinutesChange: (Float) -> Unit, - val onBreakTimeChange: (Float) -> Unit, - val onRepeatsChange: (Float) -> Unit, - val onWithBreaksChange: (Boolean) -> Unit, + val onStudyTimeHoursChange: (Int) -> Unit, + val onStudyTimeMinutesChange: (Int) -> Unit, + val onBreakTimeHourChange: (Int) -> Unit, + val onBreakTimeMinutesChange: (Int) -> Unit, + val onRepeatsChange: (Int) -> Unit, + val onWithBreaksChange: () -> Unit, val addTimer: () -> Unit, val onNameChange: (String) -> Unit, val onDescriptionChange: (String) -> Unit, ) fun getAddTimerActions( + open: (String) -> Unit, goBack: () -> Unit, viewModel: AddTimerViewModel, ): AddTimerActions { return AddTimerActions( + open = open, goBack = goBack, onWithBreaksChange = viewModel::onWithBreaksChange, onStudyTimeHoursChange = viewModel::onStudyTimeHoursChange, onStudyTimeMinutesChange = viewModel::onStudyTimeMinutesChange, - onBreakTimeChange = viewModel::onBreakTimeChange, + onBreakTimeHourChange = viewModel::onBreakTimeHourChange, + onBreakTimeMinutesChange = viewModel::onBreakTimeMinutesChange, onRepeatsChange = viewModel::onRepeatsChange, addTimer = viewModel::addTimer, onNameChange = viewModel::onNameChange, @@ -55,7 +64,6 @@ fun getAddTimerActions( @Composable fun AddTimerRoute( open: (String) -> Unit, - openAndPopUp: (String, String) -> Unit, goBack: () -> Unit, viewModel: AddTimerViewModel, ) { @@ -63,6 +71,7 @@ fun AddTimerRoute( AddTimerScreen( addTimerActions = getAddTimerActions( + open = open, goBack = goBack, viewModel = viewModel, ), @@ -75,6 +84,20 @@ fun AddTimerScreen( addTimerActions: AddTimerActions, uiState: AddTimerUiState, ) { + val mStudyTimePicker = BasicTimePicker( + onHoursChange = addTimerActions.onStudyTimeHoursChange, + onMinutesChange = addTimerActions.onStudyTimeMinutesChange, + Hours = uiState.studyTimeHours, + Minutes = uiState.studyTimeMinutes + ) + + val mBreakTimePicker = BasicTimePicker( + onHoursChange = addTimerActions.onBreakTimeHourChange, + onMinutesChange = addTimerActions.onBreakTimeMinutesChange, + Hours = uiState.breakTimeHours, + Minutes = uiState.breakTimeMinutes + ) + SecondaryScreenTemplate( title = resources().getString(R.string.add_timer), popUp = addTimerActions.goBack @@ -82,52 +105,40 @@ fun AddTimerScreen( LazyColumn( modifier = Modifier .fillMaxWidth() - .padding(16.dp) + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally ) { item { Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center + modifier = Modifier + .padding(16.dp) ) { Text( - text = "How long do you want to study?", + text = stringResource(R.string.addTimer_question), textAlign = TextAlign.Center ) } } + item { Text( - text = "${uiState.studyTimeHours.toInt()} hour${ if (uiState.studyTimeHours == 1f) "" else "s"}" + text = uiState.studyTimeHours.toString() + stringResource(R.string.addTimer_studytime_1) + uiState.studyTimeMinutes + stringResource( + R.string.addTimer_studytime_2) ) } + item { - Slider( - value = uiState.studyTimeHours, - onValueChange = { - addTimerActions.onStudyTimeHoursChange(it) + Button( + onClick = { + mStudyTimePicker.show() }, - steps = 8, - valueRange = 1f..10f, - enabled = true - ) - } - item { - Text( - text = "${uiState.studyTimeMinutes.toInt()} minutes" - ) - } - item { - Slider( - value = uiState.studyTimeMinutes, - onValueChange = { - addTimerActions.onStudyTimeMinutesChange(it) - }, - steps = 11, - valueRange = 0f..60f, - enabled = true - ) + ) { + Text( + text = stringResource(R.string.addTimer_timepicker), + ) + } } + item { Row( modifier = Modifier.fillMaxWidth(), @@ -135,68 +146,99 @@ fun AddTimerScreen( horizontalArrangement = Arrangement.Center ) { Text( - text = "With breaks?", + text = stringResource(R.string.addTimer_break_question), ) Checkbox( checked = uiState.withBreaks, - onCheckedChange = { addTimerActions.onWithBreaksChange(it) } + onCheckedChange = { addTimerActions.onWithBreaksChange() } ) } } + + if (uiState.withBreaks) { + item { + Text( + text = if (uiState.repeats == 1) uiState.repeats.toString() + stringResource( + R.string.addTimer_break_1) + else uiState.repeats.toString() + stringResource( + R.string.addTimer_break_s) + ) + TextField( + value = uiState.repeats.toString(), + onValueChange = { it: String -> + it.toIntOrNull()?.let { it1 -> + addTimerActions.onRepeatsChange( + kotlin.math.abs(it1) + ) + } + } + ) + } + + item { + Text( + text = uiState.breakTimeHours.toString() + stringResource(R.string.breakTime_1) + uiState.breakTimeMinutes + stringResource( + R.string.breakTime_2) + ) + } + + item { + Button( + onClick = { + mBreakTimePicker.show() + }, + ) { + Text( + text = stringResource(R.string.addTimer_timepicker), + ) + } + } + } + item { Text( - text = if (uiState.withBreaks) "breaks of ${uiState.breakTime.toInt()} minutes" else "", - ) - } - item { - Slider( - value = uiState.breakTime, - onValueChange = { - addTimerActions.onBreakTimeChange(it) - }, - steps = 11, - valueRange = 0f..60f, - enabled = uiState.withBreaks - ) - } - item { - Text( - text = if (uiState.withBreaks) "${uiState.repeats.toInt()} breaks" else "" - ) - } - item { - Slider( - value = uiState.repeats, - onValueChange = { - addTimerActions.onRepeatsChange(it) - }, - steps = 8, - valueRange = 1f..10f, - enabled = uiState.withBreaks - ) - } - item { - Text( - text = "Timer name" + text = stringResource(R.string.addTimer_name) ) } + item { TextField( value = uiState.name, onValueChange = { addTimerActions.onNameChange(it) } ) } + + item { + if (uiState.name == "") { + Text( + text = stringResource(R.string.addTimer_name_error), + color = Color.Red + ) + } + } + item { Text( - text = "Timer description" + text = stringResource(R.string.addTimer_description) ) } + item { TextField( value = uiState.description, onValueChange = { addTimerActions.onDescriptionChange(it) } ) } + + item { + if (uiState.description == "") { + Text( + text = stringResource(R.string.addTimer_description_error), + color = Color.Red + ) + } + } + item { Row( modifier = Modifier @@ -208,7 +250,12 @@ fun AddTimerScreen( BasicButton( text = R.string.add_timer, modifier = Modifier, - onClick = addTimerActions.addTimer + onClick = { + if (uiState.description != "" && uiState.name != "") { + addTimerActions.addTimer() + addTimerActions.open(StudeezDestinations.TIMER_OVERVIEW_SCREEN) + } + } ) } } @@ -220,8 +267,8 @@ fun AddTimerScreen( @Composable fun AddTimerScreenPreview() { StudeezTheme { AddTimerScreen( - addTimerActions = AddTimerActions({}, {}, {}, {}, {}, {}, {}, {}, {}), + addTimerActions = AddTimerActions({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}), uiState = AddTimerUiState() ) } -} \ No newline at end of file +} diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionScreen.kt index 47e7f91..a3318bc 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionScreen.kt @@ -64,7 +64,9 @@ fun TimerSelectionScreen( drawerActions = drawerActions, navigationBarActions = navigationBarActions, ) { - LazyColumn(verticalArrangement = Arrangement.spacedBy(7.dp)) { + LazyColumn( + verticalArrangement = Arrangement.spacedBy(7.dp), + ) { // All timers items(timers.value) { timerInfo -> TimerEntry( diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 39abda6..50df45b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -79,4 +79,19 @@ About Studeez + + Timer description cannot be empty! + Timer description + Timer name cannot be empty! + Timer name + Open Time Picker + " hours and " + " minutes of breaktime" + " break" + " breaks" + With breaks? + " hours and " + " minutes of studytime" + How long do you want to study? +