diff --git a/app/src/main/java/com/juandgaines/todoapp/MainActivity.kt b/app/src/main/java/com/juandgaines/todoapp/MainActivity.kt index 56dd795..98cf6a1 100644 --- a/app/src/main/java/com/juandgaines/todoapp/MainActivity.kt +++ b/app/src/main/java/com/juandgaines/todoapp/MainActivity.kt @@ -4,6 +4,7 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge +import com.juandgaines.todoapp.presentation.screens.detail.TaskScreen import com.juandgaines.todoapp.presentation.screens.home.HomeScreenRoot import com.juandgaines.todoapp.ui.theme.TodoAppTheme @@ -13,7 +14,7 @@ class MainActivity : ComponentActivity() { enableEdgeToEdge() setContent { TodoAppTheme() { - HomeScreenRoot() + } } } diff --git a/app/src/main/java/com/juandgaines/todoapp/presentation/screens/detail/TaskScreen.kt b/app/src/main/java/com/juandgaines/todoapp/presentation/screens/detail/TaskScreen.kt new file mode 100644 index 0000000..7fd5321 --- /dev/null +++ b/app/src/main/java/com/juandgaines/todoapp/presentation/screens/detail/TaskScreen.kt @@ -0,0 +1,281 @@ +package com.juandgaines.todoapp.presentation.screens.detail + +import android.content.res.Configuration.UI_MODE_NIGHT_YES +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.KeyboardArrowDown +import androidx.compose.material3.Button +import androidx.compose.material3.Checkbox +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextAlign.Companion +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import com.juandgaines.todoapp.R +import com.juandgaines.todoapp.domain.Category +import com.juandgaines.todoapp.presentation.screens.detail.providers.TaskScreenStatePreviewProvider +import com.juandgaines.todoapp.ui.theme.TodoAppTheme + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun TaskScreen( + modifier: Modifier = Modifier, + state: TaskScreenState +) { + + var isDescriptionFocus by remember { + mutableStateOf(false) + } + var isExpanded by remember { + mutableStateOf(false) + } + + Scaffold ( + topBar = { + TopAppBar( + title = { + Text( + style = MaterialTheme.typography.headlineSmall, + text = stringResource(R.string.task) + ) + } + ) + } + ){ padding-> + Column ( + verticalArrangement = Arrangement.spacedBy( + 8.dp + ), + modifier = Modifier + .fillMaxSize() + .padding(padding) + .padding(horizontal = 16.dp) + ){ + Row ( + verticalAlignment = Alignment.CenterVertically + ){ + Text( + text = stringResource(R.string.done), + style = MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colorScheme.onSurface + ), + modifier = Modifier.padding(8.dp) + ) + Checkbox( + checked = state.isTaskDone, + onCheckedChange = { + + }, + ) + Spacer( + modifier = Modifier.weight(1f) + ) + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.clickable { + isExpanded = true + } + ){ + + Text( + text = state.category?.toString() ?: stringResource(R.string.category), + style = MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colorScheme.onSurface + ), + modifier = Modifier.border( + width = 1.dp, + color = MaterialTheme.colorScheme.outline, + shape = RoundedCornerShape(8.dp) + ) + .padding(8.dp) + ) + Box ( + modifier = Modifier.padding(8.dp), + contentAlignment = Alignment.Center + ){ + Icon( + imageVector = Icons.Default.KeyboardArrowDown, + contentDescription = "Add Task", + tint = MaterialTheme.colorScheme.onSurface, + ) + DropdownMenu( + modifier = Modifier.background( + color = MaterialTheme.colorScheme.surfaceContainerHighest + ), + expanded = isExpanded, + onDismissRequest = { isExpanded = false } + ) { + Column { + Category.entries.forEach { category -> + Text( + text = category.name, + style = MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colorScheme.onSurface + ), + modifier = Modifier.padding(8.dp).padding( + 8.dp + ).clickable { + + } + ) + } + } + } + } + } + + + } + + BasicTextField( + value = state.taskName, + textStyle = MaterialTheme.typography.headlineLarge.copy( + color = MaterialTheme.colorScheme.onSurface, + fontWeight = FontWeight.Bold + ), + maxLines = 1, + onValueChange = { + + }, + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + , + decorationBox = { innerBox -> + Column ( + modifier = Modifier.fillMaxWidth(), + ){ + if(state.taskName.isEmpty()){ + Text( + modifier = Modifier.fillMaxWidth(), + text = stringResource(R.string.task_name), + color = MaterialTheme.colorScheme.onSurface.copy( + alpha = 0.5f + ), + style = MaterialTheme.typography.headlineLarge.copy( + fontWeight = FontWeight.Bold + ) + ) + } + else{ + innerBox() + } + } + } + ) + BasicTextField( + value = state.taskDescription ?: "", + textStyle = MaterialTheme.typography.bodyLarge.copy( + color = MaterialTheme.colorScheme.onSurface + ), + maxLines = 15, + onValueChange = { + + }, + modifier = Modifier + .fillMaxWidth() + .onFocusChanged { + isDescriptionFocus = it.isFocused + } + , + decorationBox = { innerBox -> + Column { + if(state.taskDescription.isNullOrEmpty() && !isDescriptionFocus){ + Text( + text = stringResource(R.string.task_description), + color = MaterialTheme.colorScheme.onSurface.copy( + alpha = 0.5f + ) + ) + }else{ + innerBox() + } + } + } + ) + Spacer( + modifier = Modifier.weight(1f) + ) + Button( + onClick = { }, + modifier = Modifier.fillMaxWidth() + .padding(46.dp) + ){ + Text( + text = stringResource(R.string.save), + style = MaterialTheme.typography.titleMedium.copy( + color = MaterialTheme.colorScheme.onPrimary + ) + ) + } + } + } +} + +@Composable +@Preview +fun TaskScreenLightPreview( + @PreviewParameter(TaskScreenStatePreviewProvider::class) state: TaskScreenState +){ + TodoAppTheme { + TaskScreen( + state = state + ) + } +} + +@Composable +@Preview( + uiMode = UI_MODE_NIGHT_YES +) +fun TaskScreenDarkPreview( + @PreviewParameter(TaskScreenStatePreviewProvider::class) state: TaskScreenState +){ + TodoAppTheme { + TaskScreen( + state = state + ) + } +} + + +data class TaskScreenState( + val taskName: String = "", + val taskDescription: String? = null, + val category:Category? = null, + val isTaskDone : Boolean = false, +) \ No newline at end of file diff --git a/app/src/main/java/com/juandgaines/todoapp/presentation/screens/detail/providers/TaskScreenStatePreviewProvider.kt b/app/src/main/java/com/juandgaines/todoapp/presentation/screens/detail/providers/TaskScreenStatePreviewProvider.kt new file mode 100644 index 0000000..20427b2 --- /dev/null +++ b/app/src/main/java/com/juandgaines/todoapp/presentation/screens/detail/providers/TaskScreenStatePreviewProvider.kt @@ -0,0 +1,42 @@ +package com.juandgaines.todoapp.presentation.screens.detail.providers + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import com.juandgaines.todoapp.domain.Category.OTHER +import com.juandgaines.todoapp.domain.Category.WORK +import com.juandgaines.todoapp.presentation.screens.detail.TaskScreenState + +class TaskScreenStatePreviewProvider:PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + TaskScreenState( + taskName = "Task 1", + taskDescription = "Description 1", + isTaskDone = false, + category = WORK + ), + TaskScreenState( + taskName = "Task 2", + taskDescription = "Description 2", + isTaskDone = true, + category = WORK + ), + TaskScreenState( + taskName = "Task 3", + taskDescription = "Description 3", + isTaskDone = false, + category = OTHER + ), + TaskScreenState( + taskName = "Task 4", + taskDescription = "Description 4", + isTaskDone = true, + category = null + ), + TaskScreenState( + taskName = "Task 5", + taskDescription = null, + isTaskDone = false, + category = null + ) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/juandgaines/todoapp/presentation/screens/home/HomeScreenViewModel.kt b/app/src/main/java/com/juandgaines/todoapp/presentation/screens/home/HomeScreenViewModel.kt index f4bc0b4..6969d7e 100644 --- a/app/src/main/java/com/juandgaines/todoapp/presentation/screens/home/HomeScreenViewModel.kt +++ b/app/src/main/java/com/juandgaines/todoapp/presentation/screens/home/HomeScreenViewModel.kt @@ -1,13 +1,11 @@ package com.juandgaines.todoapp.presentation.screens.home -import android.icu.text.DateFormat import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.juandgaines.todoapp.data.FakeTaskLocalDataSource -import com.juandgaines.todoapp.presentation.screens.home.HomeScreenAction.OnAddTask import com.juandgaines.todoapp.presentation.screens.home.HomeScreenAction.OnDeleteAllTasks import com.juandgaines.todoapp.presentation.screens.home.HomeScreenAction.OnDeleteTask import com.juandgaines.todoapp.presentation.screens.home.HomeScreenAction.OnToggleTask @@ -17,7 +15,6 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch import java.time.LocalDate -import java.time.LocalDateTime import java.time.format.DateTimeFormatter class HomeScreenViewModel:ViewModel() { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d100ea8..526e67e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7,4 +7,10 @@ All tasked deleted Task updated You have %s pending task + Task name + Task description + Task + Completed: + Category + Save \ No newline at end of file