|
|
@@ -36,32 +36,27 @@ import androidx.compose.ui.res.stringResource
|
|
|
import androidx.compose.ui.tooling.preview.Preview
|
|
|
import androidx.compose.ui.unit.dp
|
|
|
import com.example.torus.R
|
|
|
+import com.example.torus.id.UuidV7
|
|
|
+import com.example.torus.model.DraftExercise
|
|
|
+import com.example.torus.model.ExerciseType
|
|
|
import com.example.torus.ui.theme.Sand
|
|
|
import com.example.torus.ui.theme.TorusTheme
|
|
|
-import java.util.UUID
|
|
|
import kotlinx.coroutines.launch
|
|
|
|
|
|
-private enum class ExerciseType {
|
|
|
- Weights,
|
|
|
- Run,
|
|
|
-}
|
|
|
-
|
|
|
-private data class DraftExercise(
|
|
|
- val id: String,
|
|
|
- val type: ExerciseType,
|
|
|
- val name: String = "",
|
|
|
-)
|
|
|
-
|
|
|
@Composable
|
|
|
-fun CreateWorkoutScreen(modifier: Modifier = Modifier) {
|
|
|
+fun CreateWorkoutScreen(
|
|
|
+ modifier: Modifier = Modifier,
|
|
|
+ onSaveWorkout: (workoutName: String, exercises: List<DraftExercise>) -> Unit = { _, _ -> }
|
|
|
+) {
|
|
|
var workoutName by rememberSaveable { mutableStateOf("") }
|
|
|
var showExerciseTypes by rememberSaveable { mutableStateOf(false) }
|
|
|
+ var isSaving by remember { mutableStateOf(false) }
|
|
|
val exercises = remember { mutableStateListOf<DraftExercise>() }
|
|
|
val scrollState = rememberScrollState()
|
|
|
val coroutineScope = rememberCoroutineScope()
|
|
|
|
|
|
fun addExercise(type: ExerciseType) {
|
|
|
- exercises += DraftExercise(id = UUID.randomUUID().toString(), type = type)
|
|
|
+ exercises += DraftExercise(id = UuidV7.generateString(), type = type)
|
|
|
showExerciseTypes = false
|
|
|
}
|
|
|
|
|
|
@@ -90,11 +85,12 @@ fun CreateWorkoutScreen(modifier: Modifier = Modifier) {
|
|
|
number = index + 1,
|
|
|
typeLabel = stringResource(exercise.type.labelRes),
|
|
|
name = exercise.name,
|
|
|
+ notes = exercise.notes,
|
|
|
onNameChange = { name ->
|
|
|
- val exerciseIndex = exercises.indexOfFirst { it.id == exercise.id }
|
|
|
- if (exerciseIndex >= 0) {
|
|
|
- exercises[exerciseIndex] = exercises[exerciseIndex].copy(name = name)
|
|
|
- }
|
|
|
+ updateExercise(exercises, exercise.id) { it.copy(name = name) }
|
|
|
+ },
|
|
|
+ onNotesChange = { notes ->
|
|
|
+ updateExercise(exercises, exercise.id) { it.copy(notes = notes) }
|
|
|
}
|
|
|
)
|
|
|
}
|
|
|
@@ -124,7 +120,13 @@ fun CreateWorkoutScreen(modifier: Modifier = Modifier) {
|
|
|
}
|
|
|
}
|
|
|
Button(
|
|
|
- onClick = {},
|
|
|
+ onClick = {
|
|
|
+ if (!isSaving) {
|
|
|
+ isSaving = true
|
|
|
+ onSaveWorkout(workoutName, exercises.toList())
|
|
|
+ }
|
|
|
+ },
|
|
|
+ enabled = !isSaving,
|
|
|
modifier = Modifier
|
|
|
.fillMaxWidth()
|
|
|
.padding(horizontal = 16.dp, vertical = 12.dp),
|
|
|
@@ -145,12 +147,25 @@ private val ExerciseType.labelRes: Int
|
|
|
ExerciseType.Run -> R.string.exercise_type_run
|
|
|
}
|
|
|
|
|
|
+private fun updateExercise(
|
|
|
+ exercises: MutableList<DraftExercise>,
|
|
|
+ id: String,
|
|
|
+ transform: (DraftExercise) -> DraftExercise
|
|
|
+) {
|
|
|
+ val index = exercises.indexOfFirst { it.id == id }
|
|
|
+ if (index >= 0) {
|
|
|
+ exercises[index] = transform(exercises[index])
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
@Composable
|
|
|
private fun NamedExerciseEditor(
|
|
|
number: Int,
|
|
|
typeLabel: String,
|
|
|
name: String,
|
|
|
- onNameChange: (String) -> Unit
|
|
|
+ notes: String,
|
|
|
+ onNameChange: (String) -> Unit,
|
|
|
+ onNotesChange: (String) -> Unit
|
|
|
) {
|
|
|
val shape = RoundedCornerShape(14.dp)
|
|
|
Column(
|
|
|
@@ -181,6 +196,13 @@ private fun NamedExerciseEditor(
|
|
|
onValueChange = onNameChange,
|
|
|
label = stringResource(R.string.exercise_name)
|
|
|
)
|
|
|
+ TorusTextField(
|
|
|
+ value = notes,
|
|
|
+ onValueChange = onNotesChange,
|
|
|
+ label = stringResource(R.string.exercise_notes),
|
|
|
+ singleLine = false,
|
|
|
+ minLines = 3
|
|
|
+ )
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -237,14 +259,17 @@ private fun TorusTextField(
|
|
|
value: String,
|
|
|
onValueChange: (String) -> Unit,
|
|
|
label: String,
|
|
|
- modifier: Modifier = Modifier
|
|
|
+ modifier: Modifier = Modifier,
|
|
|
+ singleLine: Boolean = true,
|
|
|
+ minLines: Int = 1
|
|
|
) {
|
|
|
OutlinedTextField(
|
|
|
value = value,
|
|
|
onValueChange = onValueChange,
|
|
|
modifier = modifier.fillMaxWidth(),
|
|
|
label = { Text(text = label) },
|
|
|
- singleLine = true,
|
|
|
+ singleLine = singleLine,
|
|
|
+ minLines = minLines,
|
|
|
shape = RoundedCornerShape(14.dp),
|
|
|
colors = torusTextFieldColors()
|
|
|
)
|