From 35484fafe6bf85c6a6ca9eccec346e670d54d821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:20:56 -0400 Subject: [PATCH 01/64] Refactor: Update color theme for transaction type button --- .../src/main/java/com/soujunior/petjournal/ui/theme/Color.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt index 5954f02e..ffc05128 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt @@ -98,7 +98,6 @@ object ColorCustom { val color_border_pet_icon = Color(0xFF9C4DCC) val color_title_pet_icon = Color(0xFF222222) val color_placeholder = Color(0xFFCCCCCC) - val color_shadow_dialog = Color(0x4D000000) - val color_border_dialog = Color(0xFF8D4CD2) - val color_background_button_dialog = Color(0xFF9C4DFF) + val color_text_button_transaction_type = Color(0xFF8dD4CD2) + val color_border_button_transaction_type = Color(0xFFA2A9B1) } \ No newline at end of file From e83411e313ac3c519daa1123df8325595349ea04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:22:27 -0400 Subject: [PATCH 02/64] Refactor: Improve InputText component styling This commit refactors the `InputText` composable: - Updates padding from `16.sdp` to `16.dp`. - Modifies `titleText` styling: - Removes explicit `start` and `end` padding. - Changes text style from `MaterialTheme.typography.bodyMedium` to `MaterialTheme.typography.titleMedium`. - Adjusts `placeholderText` styling: - Sets text color to `ColorCustom.color_placeholder`. - Changes text style from a custom `TextStyle` to `MaterialTheme.typography.bodyMedium`. --- .../petjournal/ui/components/InputText.kt | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt index 0f8ab0ff..7e210fdb 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt @@ -40,7 +40,6 @@ import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import com.soujunior.petjournal.R import com.soujunior.petjournal.ui.theme.ColorCustom import com.soujunior.petjournal.ui.theme.ColorGrid @@ -64,17 +63,16 @@ fun InputText( ) { var showPassword by remember { mutableStateOf(false) } - Column(modifier = modifier.padding(top = 16.sdp)) { + Column(modifier = modifier.padding(16.dp)) { Row { Text( text = titleText, textAlign = TextAlign.Start, color = MaterialTheme.colorScheme.scrim, - style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight(500), + style = MaterialTheme.typography.titleMedium, modifier = modifier .fillMaxWidth() - .padding(start = 24.sdp, end = 24.sdp) ) } Row { @@ -134,12 +132,8 @@ fun InputText( if (textValue.isEmpty() && !hasAMask) { Text( text = placeholderText, - style = TextStyle( - fontSize = 14.sp, - lineHeight = 21.sp, - fontWeight = FontWeight(300), - color = MaterialTheme.colorScheme.scrim, - ) + color = ColorCustom.color_placeholder, + style = MaterialTheme.typography.bodyMedium ) } } From 0fe8f1695eb0a1aa0a683ae6d001a49af3b2523c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:23:24 -0400 Subject: [PATCH 03/64] Refactor: adjust PetSelectorItem component --- .../ui/components/PetSelectorItem.kt | 84 +++++++++++-------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetSelectorItem.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetSelectorItem.kt index 7a2e0e89..2c4eaa32 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetSelectorItem.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetSelectorItem.kt @@ -56,7 +56,7 @@ fun PetIcon( ambientColor = ColorCustom.color_spot_pet_icon ) .padding(1.dp) - .size(66.dp) + .size(55.dp) .background( color = backgroundColor, shape = RoundedCornerShape(8.dp) @@ -160,46 +160,56 @@ fun PetFilterList( var selectedPets by remember { mutableStateOf(listOf()) } - LazyRow( - modifier = Modifier - .fillMaxWidth() - .padding(top = 20.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - item { - PetFilterItem( - name = "Todos", - isSelected = selectedPets.contains(stringResource(R.string.label_all_pets)), - imageRes = null, - onSelect = { name -> - selectedPets = if (selectedPets.contains(name)) { - selectedPets - name - } else { - selectedPets + name + Column(modifier = Modifier.padding(16.dp)) { + Text( + text = "Quais pets precisam dessa tarefa?", + color = MaterialTheme.colorScheme.scrim, + fontWeight = FontWeight(500), + style = MaterialTheme.typography.titleMedium + ) + + LazyRow( + modifier = Modifier + .fillMaxWidth() + .padding(top = 20.dp, start = 10.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + item { + PetFilterItem( + name = "Todos", + isSelected = selectedPets.contains(stringResource(R.string.label_all_pets)), + imageRes = null, + onSelect = { name -> + selectedPets = if (selectedPets.contains(name)) { + selectedPets - name + } else { + selectedPets + name + } + onSelectedPet(if (selectedPets.contains(name)) name else "") } - onSelectedPet(if (selectedPets.contains(name)) name else "") - } - ) - } - items( - items = listPet, - key = { it.id } - ) { item -> - PetFilterItem( - name = item.name!!, - isSelected = selectedPets.contains(item.name), - imageRes = item.imageRes, - onSelect = { name -> - selectedPets = if (selectedPets.contains(name)) { - selectedPets - name - } else { - selectedPets + name + ) + } + items( + items = listPet, + key = { it.id } + ) { item -> + PetFilterItem( + name = item.name!!, + isSelected = selectedPets.contains(item.name), + imageRes = item.imageRes, + onSelect = { name -> + selectedPets = if (selectedPets.contains(name)) { + selectedPets - name + } else { + selectedPets + name + } + onSelectedPet(if (selectedPets.contains(name)) name else "") } - onSelectedPet(if (selectedPets.contains(name)) name else "") - } - ) + ) + } } } + } @Preview(showBackground = true, showSystemUi = false, device = "id:pixel_4_xl") From 1c2ef836cb21b060db2c86be972c7e5986697d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:23:56 -0400 Subject: [PATCH 04/64] feat: create RegisterTaskScreen --- .../registerTaskScreen/RegisterTaskScreen.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/RegisterTaskScreen.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/RegisterTaskScreen.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/RegisterTaskScreen.kt new file mode 100644 index 00000000..f5987a1b --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/RegisterTaskScreen.kt @@ -0,0 +1,10 @@ +package com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen + +import androidx.compose.runtime.Composable +import androidx.navigation.NavController +import com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen.components.ScreenRegisterTask + +@Composable +fun RegisterTaskScreen(navController: NavController) { + ScreenRegisterTask(navController) +} \ No newline at end of file From 9e338fe1aa7e00168ad62c3df7a7d8920cdc175c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:24:29 -0400 Subject: [PATCH 05/64] feat: Create TransactionTypeSelector component --- .../ui/components/TransactionTypeSelector.kt | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt new file mode 100644 index 00000000..b8f49ada --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt @@ -0,0 +1,146 @@ +package com.soujunior.petjournal.ui.components + +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.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +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.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.soujunior.petjournal.R +import com.soujunior.petjournal.ui.theme.ColorCustom +import com.soujunior.petjournal.ui.util.TransactionType + +@Composable +fun TransactionTypeSelector( + onSelectionChanged: (TransactionType?) -> Unit +) { + var selectedType by remember { mutableStateOf(null) } + + val selectedColor = ColorCustom.color_background_month_disabled + val unselectedColor = MaterialTheme.colorScheme.background + val borderColor = ColorCustom.color_border_button_transaction_type + + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxWidth() + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(16.dp) + ) { + ToggleButton( + text = stringResource(R.string.label_recurrent), + isSelected = selectedType == TransactionType.Recurrent, + onClick = { + val newType = TransactionType.Recurrent + selectedType = newType + onSelectionChanged(newType) + }, + selectedColor = selectedColor, + unselectedColor = unselectedColor, + borderColor = if (selectedType == TransactionType.Recurrent) selectedColor else borderColor + ) + + ToggleButton( + text = stringResource(R.string.label_one_off), + isSelected = selectedType == TransactionType.OneOff, + onClick = { + val newType = TransactionType.OneOff + selectedType = newType + onSelectionChanged(newType) + }, + selectedColor = selectedColor, + unselectedColor = unselectedColor, + borderColor = if (selectedType == TransactionType.OneOff) selectedColor else borderColor + ) + } + + if (selectedType == TransactionType.Recurrent) { + onSelectionChanged(selectedType) + } else { + onSelectionChanged(selectedType) + } + } +} + +@Composable +fun ToggleButton( + text: String, + isSelected: Boolean, + onClick: () -> Unit, + selectedColor: Color, + unselectedColor: Color, + borderColor: Color +) { + val backgroundColor = if (isSelected) selectedColor else unselectedColor + + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .width(150.dp) + .clip(RoundedCornerShape(50)) + .border(1.dp, borderColor, RoundedCornerShape(50)) + .background(backgroundColor) + .clickable { onClick() } + .padding(horizontal = 24.dp, vertical = 12.dp) + ) { + Text( + text = text, + color = ColorCustom.color_text_button_transaction_type, + style = MaterialTheme.typography.titleMedium, + ) + } +} + +@Preview(showBackground = true) +@Composable +fun TransactionTypeSelectorPreview() { + TransactionTypeSelector( + onSelectionChanged = {} + ) +} + +@Preview(showBackground = true) +@Composable +fun ToggleButtonPreview() { + Column(modifier = Modifier.padding(16.dp)) { + ToggleButton( + text = stringResource(R.string.label_recurrent), + isSelected = true, + onClick = {}, + selectedColor = ColorCustom.color_background_month_disabled, + unselectedColor = MaterialTheme.colorScheme.background, + borderColor = ColorCustom.color_border_button_transaction_type + ) + + ToggleButton( + text = stringResource(R.string.label_one_off), + isSelected = false, + onClick = {}, + selectedColor = ColorCustom.color_background_month_disabled, + unselectedColor = MaterialTheme.colorScheme.background, + borderColor = ColorCustom.color_border_button_transaction_type + ) + } + +} \ No newline at end of file From 965c2debdfb052349e05afa8eeef18fe079f64a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:24:50 -0400 Subject: [PATCH 06/64] feat: Create TransactionType enum --- .../java/com/soujunior/petjournal/ui/util/TransactionType.kt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/TransactionType.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/TransactionType.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/TransactionType.kt new file mode 100644 index 00000000..0a632ab5 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/TransactionType.kt @@ -0,0 +1,5 @@ +package com.soujunior.petjournal.ui.util + +enum class TransactionType { + Recurrent, OneOff +} \ No newline at end of file From 03699374dd5ec7857543a86f07e5417fe12522af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:25:07 -0400 Subject: [PATCH 07/64] Refactor: Rename DescriptionTextField to TextFieldCustom --- ...riptionTextField.kt => TextFieldCustom.kt} | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) rename petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/{DescriptionTextField.kt => TextFieldCustom.kt} (83%) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DescriptionTextField.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt similarity index 83% rename from petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DescriptionTextField.kt rename to petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt index e018df07..91c2864c 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DescriptionTextField.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt @@ -13,15 +13,15 @@ import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.soujunior.petjournal.R import com.soujunior.petjournal.ui.theme.ColorCustom @Composable -fun DescriptionTextField( +fun TextFieldCustom( + title:String, + placeholder:String, value: String, onValueChange: (String) -> Unit, modifier: Modifier = Modifier @@ -31,8 +31,9 @@ fun DescriptionTextField( .padding(16.dp) ) { Text( - text = stringResource(R.string.label_description), - fontWeight = FontWeight.Bold, + text = title, + color = MaterialTheme.colorScheme.scrim, + fontWeight = FontWeight(500), style = MaterialTheme.typography.titleMedium, ) @@ -43,9 +44,9 @@ fun DescriptionTextField( onValueChange = onValueChange, placeholder = { Text( - text = stringResource(R.string.enter_the_task_description_here), + text = placeholder, color = ColorCustom.color_placeholder, - style = MaterialTheme.typography.bodySmall + style = MaterialTheme.typography.bodyMedium ) }, modifier = Modifier @@ -64,7 +65,9 @@ fun DescriptionTextField( @Preview @Composable fun DescriptionTextFieldPreview() { - DescriptionTextField( + TextFieldCustom( + title = "Título", + placeholder = "Descrição", value = "", onValueChange = {} ) From ac1d516dd5dd64c08e8de08033ca6f26f873626c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:25:22 -0400 Subject: [PATCH 08/64] Refactor: Remove redundant strings and add recurrence strings --- petJournal/app/src/main/res/values/strings.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/petJournal/app/src/main/res/values/strings.xml b/petJournal/app/src/main/res/values/strings.xml index 7866e9c0..ddbe6fea 100644 --- a/petJournal/app/src/main/res/values/strings.xml +++ b/petJournal/app/src/main/res/values/strings.xml @@ -147,7 +147,6 @@ Essa tarefa é... Tarefa adicionada\ncom sucesso! Nova tarefa - Ir para a HomePage Ativo nos meses Todos Descrição @@ -157,9 +156,9 @@ Abrir Calendário 00/00/0000 dd/MM/yyyy - Tarefa adicionada\ncom sucesso! - Nova tarefa Ir para a HomePage AM PM + Recorrente + Pontual \ No newline at end of file From 6e8cf1bf4ad9a04ceccb33858e76ab95fe36e68e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:25:38 -0400 Subject: [PATCH 09/64] Refactor: Adjust SelectableButton layout and style --- .../ui/components/SelectableButtonData.kt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt index 8eb8733c..740815ea 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt @@ -40,8 +40,7 @@ fun SelectableButton( ) { androidx.compose.material3.Button( modifier = modifierSelectableButton - .height(70.dp) - .padding(top = 15.dp, end = 15.dp, bottom = 15.dp) + .height(40.dp) .then( if (isSelected) { Modifier.shadow( @@ -120,14 +119,16 @@ fun GroupSelectableButton( ) { Text( text = stringResource(R.string.label_select_main_category), - style = MaterialTheme.typography.titleLarge, + style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.scrim, fontWeight = FontWeight(500), lineHeight = 24.sp ) FlowRow( - modifier = Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() + .padding(top = 15.dp) ) { buttons.forEachIndexed { index, buttonInfo -> SelectableButton( @@ -142,7 +143,9 @@ fun GroupSelectableButton( onSelection("") } }, - modifierSelectableButton = Modifier.adaptiveWidthForTitle(buttonInfo.title) + modifierSelectableButton = Modifier + .adaptiveWidthForTitle(buttonInfo.title) + .padding(bottom = 15.dp, end = 15.dp) ) } } From f00f787a84d1e47e6cb97380ee82c1a0781b6d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:25:57 -0400 Subject: [PATCH 10/64] feat: Create ScreenRegisterTask screen This commit introduces the `ScreenRegisterTask` composable, a new screen for registering tasks within the application. Key changes include: - Addition of `ScreenRegisterTask.kt` file. - Implementation of the `ScreenRegisterTask` composable function, which includes: - A `ScaffoldCustom` for the basic screen structure with a top app bar titled "Nova tarefa" (New Task) and bottom navigation. - A `LazyColumn` to display various input fields and components for task registration. - `InputText` for the task name. - `TextFieldCustom` for the task description and an observation field. - `GroupSelectableButton` (functionality not fully detailed in the diff). - `PetFilterList` to select a pet associated with the task. - `TransactionTypeSelector` to choose between recurrent and one-off task types. - A `@Preview` function `ScreenRegisterTaskPreview` is included for UI development and testing. --- .../components/ScreenRegisterTask.kt | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt new file mode 100644 index 00000000..ae84a260 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt @@ -0,0 +1,125 @@ +package com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen.components + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.Text +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.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.navigation.NavController +import androidx.navigation.compose.rememberNavController +import com.soujunior.petjournal.R +import com.soujunior.petjournal.ui.components.GroupSelectableButton +import com.soujunior.petjournal.ui.components.InputText +import com.soujunior.petjournal.ui.components.PetFilterList +import com.soujunior.petjournal.ui.components.Pets +import com.soujunior.petjournal.ui.components.ScaffoldCustom +import com.soujunior.petjournal.ui.components.TextFieldCustom +import com.soujunior.petjournal.ui.components.TransactionTypeSelector +import com.soujunior.petjournal.ui.util.TransactionType + +@Composable +fun ScreenRegisterTask(navController: NavController) { + + val listPet = listOf( + Pets( + id = 1, + imageRes = painterResource(R.drawable.image_jujuba), + name = "Jujuba" + ), + Pets( + id = 2, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ) + ) + + val nameTask = remember { mutableStateOf("") } + val desc = remember { mutableStateOf("") } + var selectedType by remember { mutableStateOf(null) } + + Column(modifier = Modifier) { + ScaffoldCustom( + modifier = Modifier, + navigationUp = navController, + showTopBar = true, + titleTopBar = stringResource(R.string.label_new_task), + showBottomBarNavigation = true, + contentToUse = { + LazyColumn( + contentPadding = it, + content = { + item { + GroupSelectableButton() + } + item { + InputText( + modifier = Modifier, + placeholderText = "Digite aqui o nome da tarefa", + titleText = "Nome da tarefa", + textValue = nameTask.value, + onEvent = { t -> + nameTask.value = t + }, + ) + } + item { + TextFieldCustom( + title = stringResource(R.string.label_description), + placeholder = stringResource(R.string.enter_the_task_description_here), + value = desc.value, + onValueChange = { d -> + desc.value = d + } + ) + } + item { + PetFilterList( + listPet, + onSelectedPet = {} + ) + } + item { + Column { + TransactionTypeSelector( + onSelectionChanged = { type -> + selectedType = type + } + ) + + when (selectedType) { + TransactionType.Recurrent -> Text(text = "Recorrente") + TransactionType.OneOff -> Text(text = "Pontual") + null -> {} + } + } + } + item { + TextFieldCustom( + title = "Observação", + placeholder = "Digite aqui a sua observação", + value = desc.value, + onValueChange = { d -> + desc.value = d + } + ) + } + } + ) + } + ) + } +} + +@Preview(showBackground = true, showSystemUi = true, device = "id:pixel_4_xl") +@Composable +fun ScreenRegisterTaskPreview() { + val nav = rememberNavController() + ScreenRegisterTask(nav) +} \ No newline at end of file From 8340d398dfb9e65d0cf74826e17007eeb95a405b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:26:16 -0400 Subject: [PATCH 11/64] feat: integrate ScreenRegisterTask into MainActivity --- .../com/soujunior/petjournal/navigation/MainActivity.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/MainActivity.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/MainActivity.kt index e4db3ebb..65eed297 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/MainActivity.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/MainActivity.kt @@ -7,8 +7,9 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect import androidx.compose.ui.graphics.Color import androidx.core.view.WindowCompat +import androidx.navigation.compose.rememberNavController import com.google.accompanist.systemuicontroller.rememberSystemUiController -import com.soujunior.petjournal.ui.components.ActiveMonthsComponent +import com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen.components.ScreenRegisterTask import com.soujunior.petjournal.ui.theme.PetJournalTheme class MainActivity : ComponentActivity() { @@ -18,7 +19,8 @@ class MainActivity : ComponentActivity() { setContent { ChangeSystemBars() // PresentationManager() - ActiveMonthsComponent(activeMonths = setOf("Jan", "Mar", "Mai")) + val nav = rememberNavController() + ScreenRegisterTask(nav) } } } From 5d377316acde036c11122217db4425a5304db2fd Mon Sep 17 00:00:00 2001 From: Vinicius Tavares Date: Wed, 13 Aug 2025 17:20:29 -0300 Subject: [PATCH 12/64] mudancas no button3 e adicao da expansao do taskcard --- .../petjournal/ui/components/Button3.kt | 14 +- .../petjournal/ui/components/TaskCard.kt | 168 ++++++++++++++++++ 2 files changed, 177 insertions(+), 5 deletions(-) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/Button3.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/Button3.kt index f16788c2..d2b37434 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/Button3.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/Button3.kt @@ -21,6 +21,8 @@ import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import ir.kaaveh.sdpcompose.sdp import ir.kaaveh.sdpcompose.ssp @@ -31,6 +33,8 @@ fun Button3( enableButton: Boolean, modifier: Modifier = Modifier, text: String = "Button", + textSize: TextUnit = 12.ssp, + contentPaddingValues : Dp = 12.sdp, buttonColor: ButtonColors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.background), textColor: Color = MaterialTheme.colorScheme.primary, isLoading: Boolean = false @@ -54,20 +58,20 @@ fun Button3( ) , border = BorderStroke( - width = 2.sdp, + width = 1.sdp, color = Color(0xFF959EA6) ), shape = RoundedCornerShape(size = 50.dp), colors = buttonColor, - contentPadding = PaddingValues(12.sdp) + contentPadding = PaddingValues(contentPaddingValues) ) { if (!isLoading) { Text( text = text, - fontWeight = FontWeight.W900, - fontSize = 12.ssp, - style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.W500, + fontSize = textSize, + style = MaterialTheme.typography.headlineLarge, color = textColor ) } else { diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt new file mode 100644 index 00000000..d40cdcac --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt @@ -0,0 +1,168 @@ +package com.soujunior.petjournal.ui.components + +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.BorderStroke +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.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +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.draw.scale +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import ir.kaaveh.sdpcompose.sdp +import ir.kaaveh.sdpcompose.ssp +import kotlin.math.exp + +@Composable +fun TaskCard() { + var expanded by remember { mutableStateOf(true) } + + Surface( + shape = RoundedCornerShape(8.sdp), + tonalElevation = 2.dp, + modifier = Modifier + .padding(2.sdp) + .animateContentSize() // Animates the size change + ) { + Column { + // Main content: Title/Date on Start, Description on End + Row( + modifier = Modifier + .fillMaxWidth() + .padding(4.sdp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.Top + ) { + // Left side: Title and Date + Column( + modifier = Modifier.padding(horizontal = 8.sdp), + horizontalAlignment = Alignment.Start + ) { + Text( + text = "Carprofeno", + modifier = Modifier.padding(bottom = 2.sdp), + style = MaterialTheme.typography.titleMedium, + fontSize = 15.ssp + + ) + Text( + text = "12/08/2025 - 10:30", + style = MaterialTheme.typography.titleMedium, + color = Color.Gray, + fontSize = 10.ssp + ) + } + + // Right side: Description + Column(modifier = Modifier.padding(horizontal = 8.sdp), + horizontalAlignment = Alignment.Start){ + Text( + text = "Anti-inflamatorio não esteroide para alivio da dor e inflamação", + style = MaterialTheme.typography.titleSmall, + modifier = Modifier + .fillMaxWidth(1f) + .padding(start = 8.sdp) + ) + + if(expanded){ + Text( + text = "E mais um monte de coisa detalhada que vai aparecer quando expandir", + style = MaterialTheme.typography.titleSmall, + modifier = Modifier + .fillMaxWidth(1f) + .padding(start = 8.sdp, top = 8.sdp) + ) + } + } + + } + + // Expanded content + if (expanded) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 8.sdp, top = 16.sdp), + ) { + + Button( + onClick = {}, + modifier = Modifier + .width(100.sdp) + .height(25.sdp) + .align(Alignment.CenterHorizontally), + border = BorderStroke( + 1.sdp, Color(0xFF959EA6) + ), + shape = RoundedCornerShape(50.sdp), + colors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.background) + + ){ + // TODO: AJUSTAR A COR DO BOTÃO PARA A COR DA TAREFA + Text( + text = "Editar Tarefa", + fontSize = 10.ssp, + color = MaterialTheme.colorScheme.primary, + style = MaterialTheme.typography.headlineLarge + ) + } + } + } + + + // Bottom section: "Ver Mais" / "Ver Menos" + Box( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.error) + .clickable { expanded = !expanded } // Toggles the expanded state + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 6.sdp), + horizontalArrangement = Arrangement.Center + ) { + Text( + text = if (expanded) "Ver Menos" else "Ver Mais", + fontSize = 10.ssp, + color = MaterialTheme.colorScheme.background, + style = MaterialTheme.typography.displaySmall + ) + } + } + } + } +} + + +@Preview +@Composable +private fun TaskCardPreview() { + // TODO: Fazer ele receber os seguintes dados: Titulo, data, descrição menor, descrição normal + // TODO: Imagens dos pets, tipo de tarefa + TaskCard() +} From 6e241a1001080fc841c19b442a63775856094ca0 Mon Sep 17 00:00:00 2001 From: Vinicius Tavares Date: Thu, 14 Aug 2025 14:29:25 -0300 Subject: [PATCH 13/64] Finalizado o card em formato expandido --- .../petjournal/ui/components/PetItem.kt | 32 ++++-- .../petjournal/ui/components/TaskCard.kt | 97 +++++++++++++------ 2 files changed, 96 insertions(+), 33 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetItem.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetItem.kt index 62e0d0dc..82ef1432 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetItem.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetItem.kt @@ -1,6 +1,7 @@ package com.soujunior.petjournal.ui.components import android.widget.ImageView +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -13,7 +14,11 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import com.soujunior.petjournal.R import ir.kaaveh.sdpcompose.sdp import ir.kaaveh.sdpcompose.ssp @@ -34,12 +39,21 @@ fun PetItem( shape = RoundedCornerShape(16.sdp), onClick = onClick ) { - GlideImage( - modifier = Modifier.fillMaxSize(), - context = LocalContext.current, - url = imageRes, - scaleType = ImageView.ScaleType.CENTER_CROP - ) + if(!imageRes.isEmpty()) { + GlideImage( + modifier = Modifier.fillMaxSize(), + context = LocalContext.current, + url = imageRes, + scaleType = ImageView.ScaleType.CENTER_CROP + ) + }else{ + //placeholder de imagem vazia + Image( + painter = painterResource(id = R.drawable.image_pet_empty_selected), + contentDescription = "image description", + contentScale = ContentScale.Crop + ) + } } Text( @@ -50,4 +64,10 @@ fun PetItem( ) Spacer(Modifier.padding(bottom = 24.sdp)) } +} + +@Preview +@Composable +private fun previewPetItem(){ + PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) } \ No newline at end of file diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt index d40cdcac..9ebd1eb2 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt @@ -3,18 +3,18 @@ package com.soujunior.petjournal.ui.components import androidx.compose.animation.animateContentSize import androidx.compose.foundation.BorderStroke 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.aspectRatio import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults @@ -28,13 +28,11 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import ir.kaaveh.sdpcompose.sdp import ir.kaaveh.sdpcompose.ssp -import kotlin.math.exp @Composable fun TaskCard() { @@ -58,7 +56,9 @@ fun TaskCard() { ) { // Left side: Title and Date Column( - modifier = Modifier.padding(horizontal = 8.sdp), + modifier = Modifier + .padding(horizontal = 8.sdp) + .weight(0.4f), horizontalAlignment = Alignment.Start ) { Text( @@ -74,11 +74,58 @@ fun TaskCard() { color = Color.Gray, fontSize = 10.ssp ) + + /** + * Vai receber n ids de pets e vai criar a grid com as imagens dos respectivos pets + * */ + if (expanded) { + LazyVerticalGrid( + modifier = Modifier.fillMaxWidth(), + columns = GridCells.Fixed(3), + horizontalArrangement = Arrangement.Start + ) { + item { + Box(modifier = Modifier.aspectRatio(1f)) { + PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) + } + } + item { + Box(modifier = Modifier.aspectRatio(1f)) { + PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) + } + } + item { + Box(modifier = Modifier.aspectRatio(1f)) { + PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) + } + } + item { + Box(modifier = Modifier.aspectRatio(1f)) { + PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) + } + } + item { + Box(modifier = Modifier.aspectRatio(1f)) { + PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) + } + } + item { + Box(modifier = Modifier.aspectRatio(1f)) { + PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) + } + } + + } + } } // Right side: Description - Column(modifier = Modifier.padding(horizontal = 8.sdp), - horizontalAlignment = Alignment.Start){ + Column( + modifier = Modifier + .padding(horizontal = 8.sdp) + .weight(0.6f), + horizontalAlignment = Alignment.Start + ) { Text( text = "Anti-inflamatorio não esteroide para alivio da dor e inflamação", style = MaterialTheme.typography.titleSmall, @@ -87,7 +134,7 @@ fun TaskCard() { .padding(start = 8.sdp) ) - if(expanded){ + if (expanded) { Text( text = "E mais um monte de coisa detalhada que vai aparecer quando expandir", style = MaterialTheme.typography.titleSmall, @@ -97,7 +144,6 @@ fun TaskCard() { ) } } - } // Expanded content @@ -107,32 +153,30 @@ fun TaskCard() { .fillMaxWidth() .padding(bottom = 8.sdp, top = 16.sdp), ) { + Button( + onClick = {}, + modifier = Modifier + .width(100.sdp) + .height(25.sdp) + .align(Alignment.CenterHorizontally), + border = BorderStroke( + 1.sdp, Color(0xFF959EA6) + ), + shape = RoundedCornerShape(50.sdp), + colors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.background) - Button( - onClick = {}, - modifier = Modifier - .width(100.sdp) - .height(25.sdp) - .align(Alignment.CenterHorizontally), - border = BorderStroke( - 1.sdp, Color(0xFF959EA6) - ), - shape = RoundedCornerShape(50.sdp), - colors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.background) - - ){ - // TODO: AJUSTAR A COR DO BOTÃO PARA A COR DA TAREFA + ) { + // TODO: AJUSTAR A COR DO BOTÃO PARA A COR DA TAREFA Text( text = "Editar Tarefa", fontSize = 10.ssp, color = MaterialTheme.colorScheme.primary, style = MaterialTheme.typography.headlineLarge ) - } + } } } - // Bottom section: "Ver Mais" / "Ver Menos" Box( modifier = Modifier @@ -158,7 +202,6 @@ fun TaskCard() { } } - @Preview @Composable private fun TaskCardPreview() { From e46ad005b1bea3541551fb3e304decb68def9197 Mon Sep 17 00:00:00 2001 From: Vinicius Tavares Date: Thu, 14 Aug 2025 15:52:28 -0300 Subject: [PATCH 14/64] Adicionado Dummies para testar comportamento --- .../petjournal/ui/components/TaskCard.kt | 68 ++++----- .../ui/components/data/TaskTypes.kt | 134 ++++++++++++++++++ 2 files changed, 164 insertions(+), 38 deletions(-) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/TaskTypes.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt index 9ebd1eb2..83b0da5c 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt @@ -31,12 +31,16 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.soujunior.petjournal.ui.components.data.TaskData +import com.soujunior.petjournal.ui.components.data.TaskDummyData import ir.kaaveh.sdpcompose.sdp import ir.kaaveh.sdpcompose.ssp @Composable -fun TaskCard() { - var expanded by remember { mutableStateOf(true) } +fun TaskCard( + taskData: TaskData +) { + var expanded by remember { mutableStateOf(false) } Surface( shape = RoundedCornerShape(8.sdp), @@ -62,14 +66,14 @@ fun TaskCard() { horizontalAlignment = Alignment.Start ) { Text( - text = "Carprofeno", + text = taskData.titulo, modifier = Modifier.padding(bottom = 2.sdp), style = MaterialTheme.typography.titleMedium, fontSize = 15.ssp ) Text( - text = "12/08/2025 - 10:30", + text = taskData.dataHora, style = MaterialTheme.typography.titleMedium, color = Color.Gray, fontSize = 10.ssp @@ -84,37 +88,11 @@ fun TaskCard() { columns = GridCells.Fixed(3), horizontalArrangement = Arrangement.Start ) { - item { + items(taskData.pets.size) { index -> Box(modifier = Modifier.aspectRatio(1f)) { PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) } } - item { - Box(modifier = Modifier.aspectRatio(1f)) { - PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) - } - } - item { - Box(modifier = Modifier.aspectRatio(1f)) { - PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) - } - } - item { - Box(modifier = Modifier.aspectRatio(1f)) { - PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) - } - } - item { - Box(modifier = Modifier.aspectRatio(1f)) { - PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) - } - } - item { - Box(modifier = Modifier.aspectRatio(1f)) { - PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) - } - } - } } } @@ -126,8 +104,14 @@ fun TaskCard() { .weight(0.6f), horizontalAlignment = Alignment.Start ) { + val displayText = if (!expanded && taskData.descricaoResumida.length > 50) { + taskData.descricaoResumida.take(50) + "..." + } else { + taskData.descricaoResumida + } + Text( - text = "Anti-inflamatorio não esteroide para alivio da dor e inflamação", + text = displayText, style = MaterialTheme.typography.titleSmall, modifier = Modifier .fillMaxWidth(1f) @@ -136,7 +120,7 @@ fun TaskCard() { if (expanded) { Text( - text = "E mais um monte de coisa detalhada que vai aparecer quando expandir", + text = taskData.descricaoCompleta, style = MaterialTheme.typography.titleSmall, modifier = Modifier .fillMaxWidth(1f) @@ -170,7 +154,7 @@ fun TaskCard() { Text( text = "Editar Tarefa", fontSize = 10.ssp, - color = MaterialTheme.colorScheme.primary, + color = taskData.tipo.cor, style = MaterialTheme.typography.headlineLarge ) } @@ -181,7 +165,7 @@ fun TaskCard() { Box( modifier = Modifier .fillMaxWidth() - .background(MaterialTheme.colorScheme.error) + .background(taskData.tipo.cor) .clickable { expanded = !expanded } // Toggles the expanded state ) { Row( @@ -205,7 +189,15 @@ fun TaskCard() { @Preview @Composable private fun TaskCardPreview() { - // TODO: Fazer ele receber os seguintes dados: Titulo, data, descrição menor, descrição normal - // TODO: Imagens dos pets, tipo de tarefa - TaskCard() + Column(Modifier.padding(8.sdp)) { + TaskCard( + taskData = TaskDummyData.sampleTasks[0] + ) + TaskCard( + taskData = TaskDummyData.sampleTasks[1] + ) + TaskCard( + taskData = TaskDummyData.sampleTasks[2] + ) + } } diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/TaskTypes.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/TaskTypes.kt new file mode 100644 index 00000000..5e939f7f --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/TaskTypes.kt @@ -0,0 +1,134 @@ +package com.soujunior.petjournal.ui.components.data + +import androidx.compose.ui.graphics.Color + +data class TaskType( + val id: String, + val nome: String, + val cor: Color, + val icone: String? = null // Preparado para uso futuro +) + +object TaskTypes { + val VACINA = TaskType( + id = "vacina", + nome = "Vacina", + cor = Color(0xFFFA680E) + ) + + val CONSULTAS = TaskType( + id = "consultas", + nome = "Consultas", + cor = Color(0xFF20955E) + ) + + val RACAO = TaskType( + id = "racao", + nome = "Ração", + cor = Color(0xFF881803) + ) + + val MEDICAMENTOS = TaskType( + id = "medicamentos", + nome = "Medicamentos", + cor = Color(0xFF2F99E5) + ) + + val BANHOS = TaskType( + id = "banhos", + nome = "Banhos", + cor = Color(0xFFD03A94) + ) + + val PASSEIO = TaskType( + id = "passeio", + nome = "Passeio", + cor = Color(0xFFB78AF7) + ) + + // Lista com todos os tipos para facilitar iteração + val ALL_TYPES = listOf( + VACINA, + CONSULTAS, + RACAO, + MEDICAMENTOS, + BANHOS, + PASSEIO + ) + + // Função para buscar tipo por ID + fun getTypeById(id: String): TaskType? { + return ALL_TYPES.find { it.id == id } + } + + // Função para buscar tipo por nome + fun getTypeByName(nome: String): TaskType? { + return ALL_TYPES.find { it.nome.equals(nome, ignoreCase = true) } + } +} + +data class PetData( + val id: String, + val imageRes: String = "" // String vazia por enquanto +) + +data class TaskData( + val id: String, + val titulo: String, + val descricaoResumida: String, + val descricaoCompleta: String, + val dataHora: String, + val tipo: TaskType, + val pets: List = emptyList() +) + +// Dados dummy para exemplo/preview +object TaskDummyData { + private val samplePets = listOf( + PetData(id = "pet_001"), + PetData(id = "pet_002"), + PetData(id = "pet_003"), + PetData(id = "pet_004"), + PetData(id = "pet_005"), + PetData(id = "pet_006") + ) + + val sampleTasks = listOf( + TaskData( + id = "1", + titulo = "Carprofeno", + descricaoResumida = "Anti-inflamatorio não esteroide para alivio da dor e inflamação", + descricaoCompleta = "Medicamento anti-inflamatório não esteroide para alívio da dor e inflamação. Deve ser administrado com cuidado e seguindo as instruções veterinárias. Dosagem recomendada conforme peso do animal.", + dataHora = "12/08/2025 - 10:30", + tipo = TaskTypes.MEDICAMENTOS, + pets = listOf(samplePets[0], samplePets[1], samplePets[2]) + ), + TaskData( + id = "2", + titulo = "Vacina Antirrábica", + descricaoResumida = "Vacina obrigatória contra raiva para proteção do pet", + descricaoCompleta = "Vacina antirrábica anual obrigatória. Essencial para proteção contra a raiva e exigida por lei. Deve ser aplicada por veterinário e gera certificado de vacinação.", + dataHora = "15/08/2025 - 14:00", + tipo = TaskTypes.VACINA, + pets = listOf(samplePets[0]) + ), + TaskData( + id = "3", + titulo = "Consulta de Rotina", + descricaoResumida = "Check-up geral para avaliação da saúde do pet", + descricaoCompleta = "Consulta veterinária de rotina para avaliação geral da saúde, verificação de peso, exame físico completo e orientações sobre cuidados preventivos.", + dataHora = "20/08/2025 - 09:15", + tipo = TaskTypes.CONSULTAS, + pets = listOf(samplePets[1], samplePets[3]) + ), + TaskData( + id = "4", + titulo = "Ração Premium", + descricaoResumida = "Trocar para ração premium conforme orientação veterinária", + descricaoCompleta = "Mudança gradual para ração premium de alta qualidade. Fazer transição lenta misturando com a ração atual por 7 dias. Quantidade: 200g por dia dividida em 2 refeições.", + dataHora = "18/08/2025 - 18:00", + tipo = TaskTypes.RACAO, + pets = listOf(samplePets[0], samplePets[2], samplePets[4], samplePets[5]) + ) + ) +} From f3535823d96afc469a64ffc398c1d555666fd173 Mon Sep 17 00:00:00 2001 From: Vinicius Tavares Date: Mon, 18 Aug 2025 10:47:07 -0300 Subject: [PATCH 15/64] adicionado icone vetorizado para os cards; adicionado campo para icones vetorizados nos tipos de tarefas --- .../petjournal/ui/components/TaskCard.kt | 258 ++++++++++-------- .../ui/components/data/TaskTypes.kt | 33 ++- .../app/src/main/res/drawable/icone_banho.png | Bin 0 -> 896 bytes .../main/res/drawable/icone_banhos_vector.xml | 9 + .../src/main/res/drawable/icone_consulta.png | Bin 0 -> 1017 bytes .../res/drawable/icone_consultas_vector.xml | 13 + .../main/res/drawable/icone_medicamento.png | Bin 0 -> 843 bytes .../drawable/icone_medicamentos_vector.xml | 24 ++ .../src/main/res/drawable/icone_passeio.png | Bin 0 -> 1137 bytes .../res/drawable/icone_passeios_vector.xml | 11 + .../app/src/main/res/drawable/icone_racao.png | Bin 0 -> 865 bytes .../main/res/drawable/icone_racao_vector.xml | 9 + .../src/main/res/drawable/icone_vacinas.png | Bin 0 -> 732 bytes .../res/drawable/icone_vacinas_vector.xml | 13 + 14 files changed, 247 insertions(+), 123 deletions(-) create mode 100644 petJournal/app/src/main/res/drawable/icone_banho.png create mode 100644 petJournal/app/src/main/res/drawable/icone_banhos_vector.xml create mode 100644 petJournal/app/src/main/res/drawable/icone_consulta.png create mode 100644 petJournal/app/src/main/res/drawable/icone_consultas_vector.xml create mode 100644 petJournal/app/src/main/res/drawable/icone_medicamento.png create mode 100644 petJournal/app/src/main/res/drawable/icone_medicamentos_vector.xml create mode 100644 petJournal/app/src/main/res/drawable/icone_passeio.png create mode 100644 petJournal/app/src/main/res/drawable/icone_passeios_vector.xml create mode 100644 petJournal/app/src/main/res/drawable/icone_racao.png create mode 100644 petJournal/app/src/main/res/drawable/icone_racao_vector.xml create mode 100644 petJournal/app/src/main/res/drawable/icone_vacinas.png create mode 100644 petJournal/app/src/main/res/drawable/icone_vacinas_vector.xml diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt index 83b0da5c..16956c6b 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt @@ -11,13 +11,16 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -28,9 +31,13 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.soujunior.petjournal.R import com.soujunior.petjournal.ui.components.data.TaskData import com.soujunior.petjournal.ui.components.data.TaskDummyData import ir.kaaveh.sdpcompose.sdp @@ -40,149 +47,168 @@ import ir.kaaveh.sdpcompose.ssp fun TaskCard( taskData: TaskData ) { - var expanded by remember { mutableStateOf(false) } + var expanded by remember { mutableStateOf(true) } - Surface( - shape = RoundedCornerShape(8.sdp), - tonalElevation = 2.dp, - modifier = Modifier - .padding(2.sdp) - .animateContentSize() // Animates the size change + Box( + modifier = Modifier.clip(RectangleShape) ) { - Column { - // Main content: Title/Date on Start, Description on End - Row( - modifier = Modifier - .fillMaxWidth() - .padding(4.sdp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.Top - ) { - // Left side: Title and Date - Column( + Surface( + shape = RoundedCornerShape(8.sdp), + tonalElevation = 2.dp, + modifier = Modifier + .padding(2.sdp) + .animateContentSize() // Animates the size change + ) { + // Background icon when expanded - outside the Surface + if (expanded) { + Icon( + painter = painterResource(id = taskData.tipo.iconeVector!!), + contentDescription = "Ícone ${taskData.tipo.nome}", + tint = taskData.tipo.cor.copy(alpha = .5f), + modifier = Modifier + .align(Alignment.BottomStart) + .padding(start = 2.sdp, bottom = 42.sdp) + .size(150.sdp) + .offset(x = (-80).dp, y = (70).dp) + ) + } + Column { + // Main content: Title/Date on Start, Description on End + Row( modifier = Modifier - .padding(horizontal = 8.sdp) - .weight(0.4f), - horizontalAlignment = Alignment.Start + .fillMaxWidth() + .padding(4.sdp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.Top ) { - Text( - text = taskData.titulo, - modifier = Modifier.padding(bottom = 2.sdp), - style = MaterialTheme.typography.titleMedium, - fontSize = 15.ssp + // Left side: Title and Date + Column( + modifier = Modifier + .padding(horizontal = 8.sdp) + .weight(0.4f), + horizontalAlignment = Alignment.Start + ) { + Text( + text = taskData.titulo, + modifier = Modifier.padding(bottom = 2.sdp), + style = MaterialTheme.typography.titleMedium, + fontSize = 15.ssp - ) - Text( - text = taskData.dataHora, - style = MaterialTheme.typography.titleMedium, - color = Color.Gray, - fontSize = 10.ssp - ) + ) + Text( + text = taskData.dataHora, + style = MaterialTheme.typography.titleMedium, + color = Color.Gray, + fontSize = 10.ssp + ) - /** - * Vai receber n ids de pets e vai criar a grid com as imagens dos respectivos pets - * */ - if (expanded) { - LazyVerticalGrid( - modifier = Modifier.fillMaxWidth(), - columns = GridCells.Fixed(3), - horizontalArrangement = Arrangement.Start - ) { - items(taskData.pets.size) { index -> - Box(modifier = Modifier.aspectRatio(1f)) { - PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) + /** + * Vai receber n ids de pets e vai criar a grid com as imagens dos respectivos pets + * */ + if (expanded) { + LazyVerticalGrid( + modifier = Modifier.fillMaxWidth(), + columns = GridCells.Fixed(3), + horizontalArrangement = Arrangement.Start + ) { + items(taskData.pets.size) { index -> + Box(modifier = Modifier.aspectRatio(1f)) { + PetItem(modifier = Modifier, imageRes = "", name = "", onClick = {}) + } } } } } - } - - // Right side: Description - Column( - modifier = Modifier - .padding(horizontal = 8.sdp) - .weight(0.6f), - horizontalAlignment = Alignment.Start - ) { - val displayText = if (!expanded && taskData.descricaoResumida.length > 50) { - taskData.descricaoResumida.take(50) + "..." - } else { - taskData.descricaoResumida - } - Text( - text = displayText, - style = MaterialTheme.typography.titleSmall, + // Right side: Description + Column( modifier = Modifier - .fillMaxWidth(1f) - .padding(start = 8.sdp) - ) + .padding(horizontal = 8.sdp) + .weight(0.6f), + horizontalAlignment = Alignment.Start + ) { + val displayText = if (!expanded && taskData.descricaoResumida.length > 50) { + taskData.descricaoResumida.take(50) + "..." + } else { + taskData.descricaoResumida + } - if (expanded) { Text( - text = taskData.descricaoCompleta, + text = displayText, style = MaterialTheme.typography.titleSmall, modifier = Modifier .fillMaxWidth(1f) - .padding(start = 8.sdp, top = 8.sdp) + .padding(start = 8.sdp) ) + + if (expanded) { + Text( + text = taskData.descricaoCompleta, + style = MaterialTheme.typography.titleSmall, + modifier = Modifier + .fillMaxWidth(1f) + .padding(start = 8.sdp, top = 8.sdp) + ) + } } } - } - // Expanded content - if (expanded) { - Column( + // Expanded content + if (expanded) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 8.sdp, top = 16.sdp), + ) { + Button( + onClick = {}, + modifier = Modifier + .width(100.sdp) + .height(25.sdp) + .align(Alignment.CenterHorizontally), + border = BorderStroke( + 1.sdp, Color(0xFF959EA6) + ), + shape = RoundedCornerShape(50.sdp), + colors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.background) + + ) { + // TODO: AJUSTAR A COR DO BOTÃO PARA A COR DA TAREFA + Text( + text = "Editar Tarefa", + fontSize = 10.ssp, + color = taskData.tipo.cor, + style = MaterialTheme.typography.headlineLarge + ) + } + } + } + + // Bottom section: "Ver Mais" / "Ver Menos" + Box( modifier = Modifier .fillMaxWidth() - .padding(bottom = 8.sdp, top = 16.sdp), + .background(taskData.tipo.cor) + .clickable { expanded = !expanded } // Toggles the expanded state ) { - Button( - onClick = {}, + Row( modifier = Modifier - .width(100.sdp) - .height(25.sdp) - .align(Alignment.CenterHorizontally), - border = BorderStroke( - 1.sdp, Color(0xFF959EA6) - ), - shape = RoundedCornerShape(50.sdp), - colors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.background) - + .fillMaxWidth() + .padding(vertical = 6.sdp), + horizontalArrangement = Arrangement.Center ) { - // TODO: AJUSTAR A COR DO BOTÃO PARA A COR DA TAREFA Text( - text = "Editar Tarefa", + text = if (expanded) "Ver Menos" else "Ver Mais", fontSize = 10.ssp, - color = taskData.tipo.cor, - style = MaterialTheme.typography.headlineLarge + color = MaterialTheme.colorScheme.background, + style = MaterialTheme.typography.displaySmall ) } } } - - // Bottom section: "Ver Mais" / "Ver Menos" - Box( - modifier = Modifier - .fillMaxWidth() - .background(taskData.tipo.cor) - .clickable { expanded = !expanded } // Toggles the expanded state - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 6.sdp), - horizontalArrangement = Arrangement.Center - ) { - Text( - text = if (expanded) "Ver Menos" else "Ver Mais", - fontSize = 10.ssp, - color = MaterialTheme.colorScheme.background, - style = MaterialTheme.typography.displaySmall - ) - } - } } + + } } @@ -193,11 +219,11 @@ private fun TaskCardPreview() { TaskCard( taskData = TaskDummyData.sampleTasks[0] ) - TaskCard( - taskData = TaskDummyData.sampleTasks[1] - ) - TaskCard( - taskData = TaskDummyData.sampleTasks[2] - ) +// TaskCard( +// taskData = TaskDummyData.sampleTasks[1] +// ) +// TaskCard( +// taskData = TaskDummyData.sampleTasks[2] +// ) } } diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/TaskTypes.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/TaskTypes.kt index 5e939f7f..9e8cfe48 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/TaskTypes.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/TaskTypes.kt @@ -1,49 +1,68 @@ package com.soujunior.petjournal.ui.components.data +import androidx.annotation.DrawableRes import androidx.compose.ui.graphics.Color +import com.soujunior.petjournal.R data class TaskType( val id: String, val nome: String, val cor: Color, - val icone: String? = null // Preparado para uso futuro + @DrawableRes val icone: Int? = null, // Recebe um vetor drawable + @DrawableRes val iconeVector: Int? = null // Recebe um drawable vector ) object TaskTypes { val VACINA = TaskType( id = "vacina", nome = "Vacina", - cor = Color(0xFFFA680E) + cor = Color(0xFFFA680E), + icone = R.drawable.icone_vacinas, + iconeVector = R.drawable.icone_vacinas_vector ) val CONSULTAS = TaskType( id = "consultas", nome = "Consultas", - cor = Color(0xFF20955E) + cor = Color(0xFF20955E), + icone = R.drawable.icone_consulta, + iconeVector = R.drawable.icone_consultas_vector + ) val RACAO = TaskType( id = "racao", nome = "Ração", - cor = Color(0xFF881803) + cor = Color(0xFF881803), + icone = R.drawable.icone_racao, + iconeVector = R.drawable.icone_racao_vector ) val MEDICAMENTOS = TaskType( id = "medicamentos", nome = "Medicamentos", - cor = Color(0xFF2F99E5) + cor = Color(0xFF2F99E5), + icone = R.drawable.icone_medicamento, + iconeVector = R.drawable.icone_medicamentos_vector + ) val BANHOS = TaskType( id = "banhos", nome = "Banhos", - cor = Color(0xFFD03A94) + cor = Color(0xFFD03A94), + icone = R.drawable.icone_banho, + iconeVector = R.drawable.icone_banhos_vector + ) val PASSEIO = TaskType( id = "passeio", nome = "Passeio", - cor = Color(0xFFB78AF7) + cor = Color(0xFFB78AF7), + icone = R.drawable.icone_passeio, + iconeVector = R.drawable.icone_passeios_vector + ) // Lista com todos os tipos para facilitar iteração diff --git a/petJournal/app/src/main/res/drawable/icone_banho.png b/petJournal/app/src/main/res/drawable/icone_banho.png new file mode 100644 index 0000000000000000000000000000000000000000..85b6e0b80f7ba2e38a44bc9d25d9b01f6f359ead GIT binary patch literal 896 zcmV-`1AqL9P)X2d@r$9WDTn#a|381Rn>_JEbV=j+~W~TtNp?k4EPKx&=sVsHN zh}dGUGNc8;kZy3_{m~df7E(PjF|k{O(1hosPiop;H1Zg!EOi_d_8EUV@KW&96HO~o zV$4A35#RuFY6vqi1|>WYs=#FjZm`PB@QzuWG{l&K&?ADj`~AZqBtY&Q*EnD+My`qT zQ}^!Vde|~(9mEM)l`7|^A=GfcHFzCGh1-qIFyNqXcOHrms#M^a**oOkZE)}Ena^%4HC0gjz6XOF&uhqP{mO5r(it5YWJ^z@i|eH%1+)Q&=X*90X7I zCXW#|uyhdT)|vlr%X6LTmgiGe%)wqFDId^JAAuA} zMU*h}TOm9%9Q}kOQlea)Z=Or-%zHSVH0P&%y|)89&^fGcoXnd!Pa1K3JB)D-%BsQ2 zBA(%Ib&6=)U-;8Og$J7#jkaOencjr$S}cSol=th=ZF5;VZjn$;wtM`p*^MqyT)kG1 zpE~-R1RccG>$6(#)QME(mwCfgAq`~tb3v9qIZyheu + + diff --git a/petJournal/app/src/main/res/drawable/icone_consulta.png b/petJournal/app/src/main/res/drawable/icone_consulta.png new file mode 100644 index 0000000000000000000000000000000000000000..a8cb8b9cad66260b039ba033bd4a8183758e1c4f GIT binary patch literal 1017 zcmV%1 z$&l|~9z9=XKQ`8Y(i%wF=HIWLD{Zmn*0vrIx}2t-roBXE+z^~s*c71(EJX-VM1OB< zSJ>;#uf>TT@fYSGotX1!Trvt3fe7z3VT2<3{ti!W_P{u2k>>jTq@zG>jsn0kH3R`m z-EVt|%2G1q2dysnlIn;f=CrF5CD&aPS;1kvM*3<#r9APYfLm~Yx)wl^#2<_`Dg{Hl z-|FKBwL!u?`mC+z$;N13G1lyic=zQHMd!0r=q-&2>C;7Zu91tFyLwl9D@@e{8U`tqOQ} zfx;Ugo0O0T{VN3nFKzNuJQ^%c3UPvCO|^414f=|dN$n;5#Yu(em~lA1$lRL`jwf=Y zowaqQ+u6^}8*>6FPv9w6x6^?&)(Y_ML(Ndr&CLpm-~*rISIW#-7$lnXs^zQ4(U_s1 zmX->53q_B@XvAIJoskLNTeTPW?|O8Dx&t7j=4d;e-Cbt)DAE5?)}vY+!K4g3->9Ka zZZi5@=1iL?U0CXx(uaCkbE9TnX>Gch3VQK7b&~c}+nE!GkQ8Srt9A#-&b}Q1$u(ki z9T<~8MsCuMMi8Q`P8^Zixv1I?s~gbk>Na{OdU5m)uzO!o{*C?xggu=yj&z9+q)cB> zrp6C06Rj{55Al~e6I=URnLk1w{aZ%4o-r#C>wNFJlPcTXQkFT?lOg>`AsjNZIu_1m zDh`Cxc#5s3m;{c1x{ENtL5I^rMI9RGQ6Q#C4z$S;wGKH_?vIwf7vpJ<>Gso=%w)SP*a0t_1pjODG2M njKganje}iO3hIGZgw62}B4&5yV6}bS00000NkvXXu0mjfj&aaA literal 0 HcmV?d00001 diff --git a/petJournal/app/src/main/res/drawable/icone_consultas_vector.xml b/petJournal/app/src/main/res/drawable/icone_consultas_vector.xml new file mode 100644 index 00000000..d26b9e7a --- /dev/null +++ b/petJournal/app/src/main/res/drawable/icone_consultas_vector.xml @@ -0,0 +1,13 @@ + + + diff --git a/petJournal/app/src/main/res/drawable/icone_medicamento.png b/petJournal/app/src/main/res/drawable/icone_medicamento.png new file mode 100644 index 0000000000000000000000000000000000000000..325fa4f719f82c811109cac084bc2f845992160f GIT binary patch literal 843 zcmV-R1GM~!P)tVp7D&0s(vsMiT{|kwq6?M-vUijY&*QuyIfa_TtKbTg8~*LfpjY9{?;k zNa6!sj6)lN!ho@W259^4ynFa)0o&foYbyhvq`B+6-`#z4_q*Tyj=&>V;!7q4%yM>| za_jR@`&)Q`s2UpaRlT7e(*u`J>yux8WBA6IqPC-Rn~3NkSZkT&QhGaLMLUuTQy>6E zq>$Hln)H@%0PntSqo+Ak)HWO(4Q>>Iw`fLj;p^-a;=inh&^n@33u0nz7IGr0f$2R^Ru%q|YKn&tXT zzF7J6bvrj9~kq6hpczOFAlwmwA?PWhzl*QD7V@`t%kybMOt$MJ$T8zsip-FeVa>d^b2HPJvl$?2Ao7 zgzG5gQ@c>5rzIqhxA@t`jR-6f%tWkv9cgEqSSI+aln{wH8J>hlq2s(6 zzQuHnr^a}u?x!r_6JKKFiV$$e`DAIt6FPk0Z)J8)Rb+cyj&B53L8cS(7MFEKZLv-H z{EX3He`kC-?fjuE?KRW$Bt|-^>m&a{2pc2&YptOxzBIBJZHqw>Z`;IerHm~|k}WX8?9sHRPY4jI(|%bDBJV%sD5j}XS5z!f9k!Qw+iMo`ocnQzN^Ro>w>=MM@M V1CrG091;Kk002ovPDHLkV1g-LetZA` literal 0 HcmV?d00001 diff --git a/petJournal/app/src/main/res/drawable/icone_medicamentos_vector.xml b/petJournal/app/src/main/res/drawable/icone_medicamentos_vector.xml new file mode 100644 index 00000000..9f136be3 --- /dev/null +++ b/petJournal/app/src/main/res/drawable/icone_medicamentos_vector.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/petJournal/app/src/main/res/drawable/icone_passeio.png b/petJournal/app/src/main/res/drawable/icone_passeio.png new file mode 100644 index 0000000000000000000000000000000000000000..32e3ae1c68a170d80f8fbc5f97179718d3e7bb9c GIT binary patch literal 1137 zcmV-%1djWOP)b00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP1 z8%GfCo|TLik}7e6h!Y@A5b=_VluC?F5OadSgHcg=K)i%PJeZsSa)K!33QFZg@(Cc{nYi~nfU!;QhDJ7 zwSaK+Lu;#Ruc1BYbtX65yh6Zgo#aNrlg^h=*Lgzp!e92Q41R4=w znftf(6Zde=_}i;Vtw7LUq*N4Wf&qYjM+l=_8B#A5LM<|sk6^lAj}B6Z=NwH{z|a>& z_LOE7h(caIV95hq>>EC$DgEbHulYPOV z=n;MC8t%sZGrN3&wzA0)lTiW(R&U`w@@W;JZe|Zsf=TC-w^} zsUwU(JO5V|1n(m!Mvarr?a=U~f)2fp3B>KNaZ=iY1?XK(`Ycq7^kzBpRy|f|W5NnBT z0wd(Q{LYwOkpn^VQ%T3HBP4Mw`(1Z(7V4$@WL~RkV%%mRGjDizIX)t!qhyZX`J0n3 zhOh$auiXKMRYErN{=bZm5OlJilh1ByoKmtO=@C2g#?p72N3dmRv`S1qN>V8nSYME? z$K*yK72oMU){19cx5sh17lqwg=)a+||KtmaE5=ZoVhx0JYFbF&HFPr)=0w5X?thM9 z!TvFt{bCd#%#il_hSJqSfr1LeL1;m1xNk%R6Ap0BKI69>>1ojX?&taU|GV>0)u7DZ zz;f61mU}J)QKIkz6|tu|-e;c}m#H zo}HU(&VldyOO>R?_4X=qVcw@>`PmHH`HI@#zLu;O9A<@0?6Pz5MorFnu2wRk>6t!< zW*%2G>lZtX*5 zwLTjZR>HYIBQD!0-z^n&74>={WQ-~tJw9v>mPNov)`jqPO#REn00000NkvXXu0mjf D%cLUg literal 0 HcmV?d00001 diff --git a/petJournal/app/src/main/res/drawable/icone_passeios_vector.xml b/petJournal/app/src/main/res/drawable/icone_passeios_vector.xml new file mode 100644 index 00000000..c8c5cd02 --- /dev/null +++ b/petJournal/app/src/main/res/drawable/icone_passeios_vector.xml @@ -0,0 +1,11 @@ + + + diff --git a/petJournal/app/src/main/res/drawable/icone_racao.png b/petJournal/app/src/main/res/drawable/icone_racao.png new file mode 100644 index 0000000000000000000000000000000000000000..a58289f1f91e49dcd82ed187a9084103205a6279 GIT binary patch literal 865 zcmV-n1D^beP)Y0Q>TR_RPNB*_k(sup(RwtYQ($N`uw!!HpY0@SG2VA%yJZOLahm z&B+PL-Sfl4dA=G9@$rrN!4$jGZ?O7dU6sE*&~=`#0t2*cT}Q;Nhyo$t-JTJ^g^UxE zddn_U^ZW~706vr2a2!%`+qv&~@nQ;94sR#6A+hPs@;BNk0acQb=lC(9!115DsSQ-} z{EbKz!moIQ<(3WQSvI`W%_CcPjyCkA9LLI}AwilXq?(!6-Qj}xtIF)Vd>rS;8|q{w zQiWr+m?YF_4Nz~UQ1b>6M@B_px+-< zmfGnwAs)^n6zts%t~l{7WXvVS>QyW+OgfwJ$%Q4MG+7IUcTvJfGzdQNnFa(Q+khw8 zji5S7VnMGrc#D&hvzD@q@w9A!o~R6mf)*i6d^69<8=>2+u^k!4M1e rQ`fSr(%Qq8))@T#^V*Y60W07ia-LDXc@{Ge00000NkvXXu0mjfDAbJ^ literal 0 HcmV?d00001 diff --git a/petJournal/app/src/main/res/drawable/icone_racao_vector.xml b/petJournal/app/src/main/res/drawable/icone_racao_vector.xml new file mode 100644 index 00000000..3b46755b --- /dev/null +++ b/petJournal/app/src/main/res/drawable/icone_racao_vector.xml @@ -0,0 +1,9 @@ + + + diff --git a/petJournal/app/src/main/res/drawable/icone_vacinas.png b/petJournal/app/src/main/res/drawable/icone_vacinas.png new file mode 100644 index 0000000000000000000000000000000000000000..df84cfdf657f19983ff6b8e0b099f3cadc94530b GIT binary patch literal 732 zcmV<20wev2P)JN7W3oiTKy{{X~pd|(O{ERU;wM1`m_x{Bz z=mM0K9sMHMJ!W0$z*>Xiz^1bC!2k@QMg4W{kp=upUXG#;0XG2;CxdUlf5KBirC@?D z$Xi8VZRXVf2_N32KqN&dYeTKv!Aal_Met#8YBCmq&C(9(B^6i$p0bW&!)zM32j^f2 zBmh2#$i|>Z{@PFi#aVWTjtWc#wC^oveecE(flcyYduY9`4<*=T8U_Ve5m0iUfXV*3 z5b&KUey!EFvBV$aUI-Ar4yZ_#p;R?TTARzOkE-#eK%`3HQ+bGLP0w3SX>zCmR0*mm zWX~*oLoH3d4u&9JLJ5@$pFW2G9yok@{&g9x#+5sqN#iHkQ*qJrZjZn~#-38{TVXh+ zRg;X_!wh26W9o8I8A`X2%E_G+3^TwS*t{&**6^9`>@<#QPQH(-GgawFdtGcq8%it% zWMHrmC@vW(oLs4ebF*?lBy^}sLkS=mLO;Y{9OoGR;&MUg{$EHN91j=LT6~<4Zz-$u zH6k7+&qLsozIS(R0>mMhZ2MTqt2ogUAcza&{+HXgYe_qT9RNj^iyqJ!DY?$apXv{_ z>lL~wph{3GH3>wjeROFWs5aCtfNDYQ3W#KsQ`^)e5J~B&ZN+hyKuV~M&mgVvN7F!& zRnP#HJux;V>>3axP+bBdp*(asvN`Vx5Q#C&J|w#Ul#0ByIzBjrj_4m1bD)m`LpQ+y O0000 + + From 3dbb568c06cfbd57c6e6bff43f74012bc966bc0d Mon Sep 17 00:00:00 2001 From: Vinicius Tavares Date: Mon, 18 Aug 2025 14:02:01 -0300 Subject: [PATCH 16/64] inicio da implementacao da tela --- .../com/soujunior/petjournal/ui/components/TaskCard.kt | 2 +- .../{PetListScreen.kt.kt => PetListScreen.kt} | 0 .../screens_pets/taskListScreen/TaskListScreen.kt | 10 ++++++++++ .../screens_pets/taskListScreen/TaskListViewModel.kt | 2 ++ .../taskListScreen/TaskListViewModelImpl.kt | 4 ++++ .../screens_pets/taskListScreen/components/Screen.kt | 9 +++++++++ 6 files changed, 26 insertions(+), 1 deletion(-) rename petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/petListScreen/{PetListScreen.kt.kt => PetListScreen.kt} (100%) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/TaskListScreen.kt create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/TaskListViewModel.kt create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/TaskListViewModelImpl.kt create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/components/Screen.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt index 16956c6b..ce4084fd 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskCard.kt @@ -47,7 +47,7 @@ import ir.kaaveh.sdpcompose.ssp fun TaskCard( taskData: TaskData ) { - var expanded by remember { mutableStateOf(true) } + var expanded by remember { mutableStateOf(false) } Box( modifier = Modifier.clip(RectangleShape) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/petListScreen/PetListScreen.kt.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/petListScreen/PetListScreen.kt similarity index 100% rename from petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/petListScreen/PetListScreen.kt.kt rename to petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/petListScreen/PetListScreen.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/TaskListScreen.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/TaskListScreen.kt new file mode 100644 index 00000000..f402e532 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/TaskListScreen.kt @@ -0,0 +1,10 @@ +package com.soujunior.petjournal.ui.screens_app.screens_pets.taskListScreen + +import androidx.compose.runtime.Composable +import androidx.navigation.NavController +import com.soujunior.petjournal.ui.screens_app.screens_pets.taskListScreen.components.Screen + +@Composable +fun TaskListScreen(navController: NavController) { + Screen(navController) +} \ No newline at end of file diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/TaskListViewModel.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/TaskListViewModel.kt new file mode 100644 index 00000000..2cc1ec08 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/TaskListViewModel.kt @@ -0,0 +1,2 @@ +package com.soujunior.petjournal.ui.screens_app.screens_pets.taskListScreen + diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/TaskListViewModelImpl.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/TaskListViewModelImpl.kt new file mode 100644 index 00000000..b3cbcbd5 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/TaskListViewModelImpl.kt @@ -0,0 +1,4 @@ +package com.soujunior.petjournal.ui.screens_app.screens_pets.taskListScreen + +class TaskListViewModelImpl { +} \ No newline at end of file diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/components/Screen.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/components/Screen.kt new file mode 100644 index 00000000..34cce820 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/taskListScreen/components/Screen.kt @@ -0,0 +1,9 @@ +package com.soujunior.petjournal.ui.screens_app.screens_pets.taskListScreen.components + +import androidx.compose.runtime.Composable +import androidx.navigation.NavController + +@Composable +fun Screen(navController: NavController){ + +} \ No newline at end of file From 4a12d3561ccc4a336e8105fce13168281566a425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:09:10 -0400 Subject: [PATCH 17/64] feat: Add unfocused color for WheelTimePicker --- .../app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt index ffc05128..e56a9f54 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt @@ -100,4 +100,5 @@ object ColorCustom { val color_placeholder = Color(0xFFCCCCCC) val color_text_button_transaction_type = Color(0xFF8dD4CD2) val color_border_button_transaction_type = Color(0xFFA2A9B1) + val color_unfocused_wheelTimePicker = Color(0xFFDADADA) } \ No newline at end of file From be3d9e3b40eebf5ed00f7c5647fcfed0c1bb0990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:10:23 -0400 Subject: [PATCH 18/64] feat: Create DayPicker composable --- .../ui/components/data/DayPicker.kt | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/DayPicker.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/DayPicker.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/DayPicker.kt new file mode 100644 index 00000000..a5e3d4a4 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/DayPicker.kt @@ -0,0 +1,98 @@ +package com.soujunior.petjournal.ui.components.data + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.flow.distinctUntilChanged +import java.time.LocalDate + +@OptIn(ExperimentalFoundationApi::class) +@Composable +fun DayPicker( + onDaySelected: (Int) -> Unit +) { + val currentDate = remember { LocalDate.now() } + val totalDays = remember { currentDate.lengthOfMonth() } + + val days = remember { (1..totalDays).toList() } + + val listState = rememberLazyListState(initialFirstVisibleItemIndex = currentDate.dayOfMonth - 1) + + val flingBehavior = rememberSnapFlingBehavior(lazyListState = listState) + + LaunchedEffect(listState) { + snapshotFlow { listState.firstVisibleItemIndex } + .distinctUntilChanged() + .collect { index -> + onDaySelected(days.getOrNull(index + 1) ?: days.last()) + } + } + + Column( + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text(text = "DIA", style = MaterialTheme.typography.bodySmall) + + Box( + modifier = Modifier + .height(120.dp) + .width(60.dp), + contentAlignment = Alignment.Center + ) { + LazyColumn( + state = listState, + flingBehavior = flingBehavior, + contentPadding = PaddingValues(vertical = 40.dp), + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxHeight() + ) { + itemsIndexed(days) { index, day -> + val isSelected = listState.firstVisibleItemIndex == index + Text( + text = day.toString(), + fontSize = if (isSelected) 26.sp else 20.sp, + color = if (isSelected) Color.Black else Color.LightGray, + fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal, + modifier = Modifier.padding(vertical = 4.dp) + ) + } + } + } + } +} + + +@Preview +@Composable +fun DayPickerPreview(){ + var selectedDay by remember { mutableStateOf(LocalDate.now().dayOfMonth) } + + DayPicker( + onDaySelected = { selectedDay = it } + ) +} \ No newline at end of file From 7bbde0fe7c90f13fcdda83f9f257ab88ededcf97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:10:44 -0400 Subject: [PATCH 19/64] feat: Create OneOffTask composable --- .../ui/components/task/OneOffTask.kt | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/OneOffTask.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/OneOffTask.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/OneOffTask.kt new file mode 100644 index 00000000..3edf7ff7 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/OneOffTask.kt @@ -0,0 +1,51 @@ +package com.soujunior.petjournal.ui.components.task + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +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.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.soujunior.petjournal.ui.components.clock.TimePickerWithPeriodSelector +import com.soujunior.petjournal.ui.components.data.CustomDatePicker + +@Composable +fun OneOffTask( + onDateSelected: (Long?) -> Unit = {}, + onAmPmSelector: (String?) -> Unit = {}, + onTime: (Int, Int) -> Unit = { _, _ -> } +) { + var selectedTimestamp by remember { mutableStateOf(null) } + + Column(modifier = Modifier.padding(start = 20.dp, end = 20.dp)) { + CustomDatePicker( + label = "Data", + value = selectedTimestamp, + onValueChange = { + selectedTimestamp = it + onDateSelected(selectedTimestamp) + }, + modifier = Modifier.fillMaxWidth() + ) + + TimePickerWithPeriodSelector( + onAmPmSelector = { amPmSelector -> + onAmPmSelector(amPmSelector) + }, + onTime = { hour, minute -> + onTime(hour, minute) + } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun OneOffTaskPreview() { + OneOffTask() +} \ No newline at end of file From b0b471d9b95e2aae4281c09ebfaa9ac778cdb810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:11:07 -0400 Subject: [PATCH 20/64] feat: Create PeriodSelector composable --- .../ui/components/PeriodSelector.kt | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PeriodSelector.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PeriodSelector.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PeriodSelector.kt new file mode 100644 index 00000000..f20a537e --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PeriodSelector.kt @@ -0,0 +1,90 @@ +package com.soujunior.petjournal.ui.components + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.soujunior.petjournal.ui.util.SelectedPeriodType + +@Composable +fun PeriodSelector( + selected: SelectedPeriodType, + onSelectionChanged: (SelectedPeriodType) -> Unit +) { + val items = listOf(SelectedPeriodType.Diária, SelectedPeriodType.Semanal, SelectedPeriodType.Mensal) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + items.forEach { item -> + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .clickable { onSelectionChanged(item) } + .padding(horizontal = 8.dp) + ) { + Text( + text = item.name, + style = MaterialTheme.typography.bodyMedium, + color = if (selected == item) Color(0xFF8D4CD2) else Color.Black, + ) + if (selected == item) { + TriangleIndicator() + } else { + Spacer(modifier = Modifier.height(6.dp)) + } + } + } + } +} + +@Composable +fun TriangleIndicator( + color: Color = Color(0xFF8D4CD2), + modifier: Modifier = Modifier + .width(60.dp) + .height(2.dp) +) { + Canvas(modifier = modifier) { + val width = size.width + val height = size.height + + val inset = width * 0.1f + + val path = Path().apply { + moveTo(inset, 0f) + lineTo(width - inset, 0f) + lineTo(width, height) + lineTo(0f, height) + close() + } + + drawPath(path = path, color = color) + } +} + + +@Preview(showBackground = true) +@Composable +fun PeriodSelectorPreview() { + var selectedPeriod = SelectedPeriodType.Diária + PeriodSelector(selected = selectedPeriod) { + selectedPeriod = it + } +} \ No newline at end of file From 54ff2ba6053b6885d026879552e281786f890f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:11:26 -0400 Subject: [PATCH 21/64] feat: Create RecurringTask composable --- .../ui/components/task/RecurrentTask.kt | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/RecurrentTask.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/RecurrentTask.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/RecurrentTask.kt new file mode 100644 index 00000000..df35b3d9 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/RecurrentTask.kt @@ -0,0 +1,135 @@ +package com.soujunior.petjournal.ui.components.task + +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.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +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.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.soujunior.petjournal.ui.components.ActiveMonthsComponent +import com.soujunior.petjournal.ui.components.AmPmSelector +import com.soujunior.petjournal.ui.components.PeriodSelector +import com.soujunior.petjournal.ui.components.WeekDaySelector +import com.soujunior.petjournal.ui.components.clock.TimePickerWithPeriodSelector +import com.soujunior.petjournal.ui.components.clock.WheelTimePicker +import com.soujunior.petjournal.ui.components.data.DayPicker +import com.soujunior.petjournal.ui.util.SelectedPeriodType + +@Composable +fun RecurringTask( + activeMonths: Set = setOf(), + onAmPmSelector: (String?) -> Unit = {}, + onTime: (Int?, Int?) -> Unit = { _, _ -> }, + onWeekDaySelected: (String?) -> Unit = {}, + onDaySelected: (Int?) -> Unit = {}, +) { + var selectedPeriod by remember { mutableStateOf(SelectedPeriodType.Diária) } + PeriodSelector( + selected = selectedPeriod, + onSelectionChanged = { selectedPeriod = it } + ) + + when (selectedPeriod) { + SelectedPeriodType.Diária -> { + TimePickerWithPeriodSelector( + onAmPmSelector = { amPmSelector -> + onAmPmSelector(amPmSelector) + }, + onTime = { hour, minute -> + onTime(hour, minute) + } + ) + } + + SelectedPeriodType.Semanal -> { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + + WeekDaySelector( + onDaySelected = { weekDaySelected -> + onWeekDaySelected(weekDaySelected) + } + ) + + AmPmSelector( + onPeriodSelected = { amPmSelector -> + onAmPmSelector(amPmSelector) + } + ) + Box( + modifier = Modifier + .padding(start = 8.dp) + .height(150.dp) + .width(100.dp), + contentAlignment = Alignment.Center + ) { + WheelTimePicker( + onTimeChanged = { hour, minute -> + onTime(hour, minute) + } + ) + } + } + } + + SelectedPeriodType.Mensal -> { + Column { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + + DayPicker( + onDaySelected = { daySelected -> + onDaySelected(daySelected) + } + ) + AmPmSelector( + onPeriodSelected = { amPmSelector -> + onAmPmSelector(amPmSelector) + } + ) + Box( + modifier = Modifier + .height(150.dp) + .width(100.dp), + contentAlignment = Alignment.Center + ) { + WheelTimePicker( + onTimeChanged = { hour, minute -> + onTime(hour, minute) + } + ) + } + } + ActiveMonthsComponent(activeMonths = activeMonths) + } + + } + } +} + +@Preview(showBackground = true) +@Composable +fun RecurringTaskPreview() { + RecurringTask() +} \ No newline at end of file From 83b807f7715702d4fb5918b73f9873dc096dcef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:11:44 -0400 Subject: [PATCH 22/64] Refactor: Make GroupSelectableButton dynamic --- .../ui/components/SelectableButtonData.kt | 59 ++++++++++--------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt index 740815ea..7924a58c 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt @@ -81,36 +81,11 @@ fun SelectableButton( @OptIn(ExperimentalLayoutApi::class) @Composable fun GroupSelectableButton( + listOfTasks: List, onSelection: (String) -> Unit = {} ) { - val buttons = listOf( - SelectableButtonInfo( - stringResource(R.string.label_selectable_button_vaccines), - ColorCustom.color_selectable_button_1 - ), - SelectableButtonInfo( - stringResource(R.string.label_selectable_button_consultations), - ColorCustom.color_selectable_button_2 - ), - SelectableButtonInfo( - stringResource(R.string.label_selectable_button_medicine), - ColorCustom.color_selectable_button_3 - ), - SelectableButtonInfo( - stringResource(R.string.label_selectable_button_bath), - ColorCustom.color_selectable_button_4 - ), - SelectableButtonInfo( - stringResource(R.string.label_selectable_button_food), - ColorCustom.color_selectable_button_5 - ), - SelectableButtonInfo( - stringResource(R.string.label_selectable_button_pet_walk), - ColorCustom.color_selectable_button_6 - ), - ) - val selectionState = remember { mutableStateListOf(*Array(buttons.size) { false }) } + val selectionState = remember { mutableStateListOf(*Array(listOfTasks.size) { false }) } Column( modifier = Modifier @@ -130,7 +105,7 @@ fun GroupSelectableButton( .fillMaxWidth() .padding(top = 15.dp) ) { - buttons.forEachIndexed { index, buttonInfo -> + listOfTasks.forEachIndexed { index, buttonInfo -> SelectableButton( titleButton = buttonInfo.title, colorButton = buttonInfo.color, @@ -162,5 +137,31 @@ data class SelectableButtonInfo( @Preview(showBackground = true, showSystemUi = true, device = "id:pixel_4_xl") @Composable fun CustomSelectableButtonPreview() { - GroupSelectableButton() + val listOfTasks = listOf( + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_vaccines), + ColorCustom.color_selectable_button_1 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_consultations), + ColorCustom.color_selectable_button_2 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_medicine), + ColorCustom.color_selectable_button_3 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_bath), + ColorCustom.color_selectable_button_4 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_food), + ColorCustom.color_selectable_button_5 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_pet_walk), + ColorCustom.color_selectable_button_6 + ), + ) + GroupSelectableButton(listOfTasks) } \ No newline at end of file From 0dce3433d958be3fdf33cd1a4a830ad578542642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:12:00 -0400 Subject: [PATCH 23/64] feat: Add SelectedPeriodType enum --- .../com/soujunior/petjournal/ui/util/SelectedPeriodType.kt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/SelectedPeriodType.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/SelectedPeriodType.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/SelectedPeriodType.kt new file mode 100644 index 00000000..3fa0a40e --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/SelectedPeriodType.kt @@ -0,0 +1,5 @@ +package com.soujunior.petjournal.ui.util + +enum class SelectedPeriodType { + Diária, Semanal, Mensal +} \ No newline at end of file From 604a5f124b1fc1218651bb3b33645ff51245cd78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:12:25 -0400 Subject: [PATCH 24/64] Refactor: Update TextFieldCustom padding and add new string resources --- .../soujunior/petjournal/ui/components/TextFieldCustom.kt | 2 +- petJournal/app/src/main/res/values/strings.xml | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt index 91c2864c..d8318f72 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt @@ -28,7 +28,7 @@ fun TextFieldCustom( ) { Column( modifier = modifier - .padding(16.dp) + .padding(start = 16.dp, end = 16.dp) ) { Text( text = title, diff --git a/petJournal/app/src/main/res/values/strings.xml b/petJournal/app/src/main/res/values/strings.xml index ddbe6fea..631122de 100644 --- a/petJournal/app/src/main/res/values/strings.xml +++ b/petJournal/app/src/main/res/values/strings.xml @@ -161,4 +161,10 @@ PM Recorrente Pontual + Data + Digite aqui o nome da tarefa + Nome da tarefa + Observação + Digite aqui a sua observação + Salvar \ No newline at end of file From 45a57d4eaef9e1c85daa2ae8743d17bbd6427255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:12:42 -0400 Subject: [PATCH 25/64] feat: Create TimePickerWithPeriodSelector Composable --- .../clock/TimePickerWithPeriodSelector.kt | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/TimePickerWithPeriodSelector.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/TimePickerWithPeriodSelector.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/TimePickerWithPeriodSelector.kt new file mode 100644 index 00000000..32ead607 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/TimePickerWithPeriodSelector.kt @@ -0,0 +1,47 @@ +package com.soujunior.petjournal.ui.components.clock + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.soujunior.petjournal.ui.components.AmPmSelector + +@Composable +fun TimePickerWithPeriodSelector( + onAmPmSelector: (String) -> Unit, + onTime: (Int, Int) -> Unit +) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + AmPmSelector( + onPeriodSelected = { periodSelected -> + onAmPmSelector(periodSelected) + } + ) + Box( + modifier = Modifier + .padding(start = 8.dp) + .height(150.dp) + .width(100.dp), + contentAlignment = Alignment.Center + ) { + WheelTimePicker( + onTimeChanged = { hour, minute -> + onTime(hour, minute) + } + ) + } + } +} \ No newline at end of file From a840ae99cfb9b15e7b425a03ebd798e120438d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:12:57 -0400 Subject: [PATCH 26/64] Refactor: Adjust TransactionTypeSelector button size --- .../petjournal/ui/components/TransactionTypeSelector.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt index b8f49ada..fbdacd92 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape @@ -97,7 +98,7 @@ fun ToggleButton( Box( contentAlignment = Alignment.Center, modifier = Modifier - .width(150.dp) + .width(130.dp).height(50.dp) .clip(RoundedCornerShape(50)) .border(1.dp, borderColor, RoundedCornerShape(50)) .background(backgroundColor) From bc4cc3ad46226d640137f30ff16f0089090b27e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:13:19 -0400 Subject: [PATCH 27/64] Refactor: Update WheelTimePicker component --- .../ui/components/clock/WheelTimePicker.kt | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/WheelTimePicker.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/WheelTimePicker.kt index ab19cec4..ceadee14 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/WheelTimePicker.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/WheelTimePicker.kt @@ -23,7 +23,6 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.TextStyle @@ -32,6 +31,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.soujunior.petjournal.ui.theme.ColorCustom import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.filter import kotlin.math.abs @@ -59,7 +59,7 @@ fun WheelTimePicker( initialMinute: Int = 0, textStyle: TextStyle = MaterialTheme.typography.titleLarge, focusedColor: Color = Color.Black, - unfocusedColor: Color = Color.Gray, + unfocusedColor: Color = ColorCustom.color_unfocused_wheelTimePicker, onTimeChanged: (hour: Int, minute: Int) -> Unit ) { require(visibleItemsCount % 2 != 0) { "visibleItemsCount must be an odd number." } @@ -162,8 +162,10 @@ private fun PickerColumn( if (layoutInfo.visibleItemsInfo.isEmpty()) { -1 } else { - val viewportCenter = (layoutInfo.viewportStartOffset + layoutInfo.viewportEndOffset) / 2 - layoutInfo.visibleItemsInfo.minByOrNull { abs((it.offset + it.size / 2) - viewportCenter) }?.index ?: -1 + val viewportCenter = + (layoutInfo.viewportStartOffset + layoutInfo.viewportEndOffset) / 2 + layoutInfo.visibleItemsInfo.minByOrNull { abs((it.offset + it.size / 2) - viewportCenter) }?.index + ?: -1 } } } @@ -176,12 +178,14 @@ private fun PickerColumn( val layoutInfo = listState.layoutInfo if (layoutInfo.visibleItemsInfo.isEmpty()) return@collect - val viewportCenter = (layoutInfo.viewportStartOffset + layoutInfo.viewportEndOffset) / 2 + val viewportCenter = + (layoutInfo.viewportStartOffset + layoutInfo.viewportEndOffset) / 2 val centralItem = layoutInfo.visibleItemsInfo.minByOrNull { abs((it.offset + it.size / 2) - viewportCenter) } ?: return@collect - val itemDataIndex = (centralItem.index - halfVisibleItems).coerceIn(0, items.size - 1) + val itemDataIndex = + (centralItem.index - halfVisibleItems).coerceIn(0, items.size - 1) val delta = (centralItem.offset + centralItem.size / 2) - viewportCenter listState.animateScrollBy(delta.toFloat()) @@ -204,8 +208,14 @@ private fun PickerColumn( items(items.size) { dataIndex -> val lazyColumnIndex = dataIndex + halfVisibleItems val isFocused = (lazyColumnIndex == centralLazyColumnIndex) - val scale by animateFloatAsState(targetValue = if (isFocused) 1.2f else 1.0f, label = "scale") - val alpha by animateFloatAsState(targetValue = if (isFocused) 1.0f else 0.5f, label = "alpha") + val scale by animateFloatAsState( + targetValue = if (isFocused) 1.2f else 1.0f, + label = "scale" + ) + val alpha by animateFloatAsState( + targetValue = if (isFocused) 1.0f else 0.5f, + label = "alpha" + ) Box( modifier = Modifier.height(itemHeight), @@ -215,9 +225,9 @@ private fun PickerColumn( text = items[dataIndex], style = textStyle.copy( color = if (isFocused) focusedColor else unfocusedColor, - fontSize = textStyle.fontSize * scale + fontSize = 34.sp ), - modifier = Modifier.alpha(alpha) +// modifier = Modifier.alpha(alpha) ) } } From 74938de79cb6682633806e31f24908b8be63248a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:13:44 -0400 Subject: [PATCH 28/64] feat: Enhance ScreenRegisterTask UI and functionality --- .../components/ScreenRegisterTask.kt | 253 +++++++++++++----- 1 file changed, 187 insertions(+), 66 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt index ae84a260..9e9f8abf 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt @@ -1,32 +1,69 @@ package com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen.components +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material3.Text 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.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.navigation.NavController import androidx.navigation.compose.rememberNavController import com.soujunior.petjournal.R +import com.soujunior.petjournal.ui.components.Button3 import com.soujunior.petjournal.ui.components.GroupSelectableButton import com.soujunior.petjournal.ui.components.InputText import com.soujunior.petjournal.ui.components.PetFilterList import com.soujunior.petjournal.ui.components.Pets import com.soujunior.petjournal.ui.components.ScaffoldCustom +import com.soujunior.petjournal.ui.components.SelectableButtonInfo import com.soujunior.petjournal.ui.components.TextFieldCustom import com.soujunior.petjournal.ui.components.TransactionTypeSelector +import com.soujunior.petjournal.ui.components.task.OneOffTask +import com.soujunior.petjournal.ui.components.task.RecurringTask +import com.soujunior.petjournal.ui.theme.ColorCustom import com.soujunior.petjournal.ui.util.TransactionType +import ir.kaaveh.sdpcompose.sdp @Composable fun ScreenRegisterTask(navController: NavController) { + val listOfTasks = listOf( + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_vaccines), + ColorCustom.color_selectable_button_1 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_consultations), + ColorCustom.color_selectable_button_2 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_medicine), + ColorCustom.color_selectable_button_3 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_bath), + ColorCustom.color_selectable_button_4 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_food), + ColorCustom.color_selectable_button_5 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_pet_walk), + ColorCustom.color_selectable_button_6 + ), + ) + val listPet = listOf( Pets( id = 1, @@ -37,84 +74,168 @@ fun ScreenRegisterTask(navController: NavController) { id = 2, imageRes = painterResource(R.drawable.image_alfredo), name = "Alfredo" + ), + Pets( + id = 3, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 4, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 5, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 6, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 7, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 8, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 9, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" ) ) val nameTask = remember { mutableStateOf("") } val desc = remember { mutableStateOf("") } + val ob = remember { mutableStateOf("") } var selectedType by remember { mutableStateOf(null) } - Column(modifier = Modifier) { - ScaffoldCustom( - modifier = Modifier, - navigationUp = navController, - showTopBar = true, - titleTopBar = stringResource(R.string.label_new_task), - showBottomBarNavigation = true, - contentToUse = { - LazyColumn( - contentPadding = it, - content = { - item { - GroupSelectableButton() - } - item { - InputText( - modifier = Modifier, - placeholderText = "Digite aqui o nome da tarefa", - titleText = "Nome da tarefa", - textValue = nameTask.value, - onEvent = { t -> - nameTask.value = t - }, - ) - } - item { - TextFieldCustom( - title = stringResource(R.string.label_description), - placeholder = stringResource(R.string.enter_the_task_description_here), - value = desc.value, - onValueChange = { d -> - desc.value = d + ScaffoldCustom( + modifier = Modifier, + navigationUp = navController, + showTopBar = true, + titleTopBar = stringResource(R.string.label_new_task), + showBottomBarNavigation = true, + contentToUse = { paddingValues -> + Image( + painter = painterResource(R.drawable.rastro), + contentDescription = null, + modifier = Modifier + .fillMaxSize() + .offset(y = 300.sdp) + ) + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), + content = { + item { + GroupSelectableButton( + listOfTasks, + onSelection = { + + } + ) + } + item { + InputText( + modifier = Modifier.testTag("inputFieldTag"), + placeholderText = stringResource(R.string.enter_task_name_here), + titleText = stringResource(R.string.task_name), + textValue = nameTask.value, + onEvent = { t -> + nameTask.value = t + + }, + ) + } + item { + TextFieldCustom( + title = stringResource(R.string.label_description), + placeholder = stringResource(R.string.enter_the_task_description_here), + value = desc.value, + onValueChange = { d -> + desc.value = d + } + ) + } + item { + PetFilterList( + listPet, + onSelectedPet = { + + } + ) + } + item { + Column { + TransactionTypeSelector( + onSelectionChanged = { type -> + selectedType = type } ) - } - item { - PetFilterList( - listPet, - onSelectedPet = {} - ) - } - item { - Column { - TransactionTypeSelector( - onSelectionChanged = { type -> - selectedType = type - } - ) - - when (selectedType) { - TransactionType.Recurrent -> Text(text = "Recorrente") - TransactionType.OneOff -> Text(text = "Pontual") - null -> {} + + when (selectedType) { + TransactionType.Recurrent -> { + RecurringTask( + setOf(), + onAmPmSelector = { + + }, + onTime = { hour, minute -> + + }, + onWeekDaySelected = { + + }, + onDaySelected = { + + } + ) } - } - } - item { - TextFieldCustom( - title = "Observação", - placeholder = "Digite aqui a sua observação", - value = desc.value, - onValueChange = { d -> - desc.value = d + + TransactionType.OneOff -> { + OneOffTask( + onDateSelected = { + + }, + onAmPmSelector = { + + }, + onTime = { hour, minute -> + + } + ) } - ) + + null -> {} + } } } - ) - } - ) - } + item { + TextFieldCustom( + title = stringResource(R.string.label_observation), + placeholder = stringResource(R.string.enter_your_observation_here), + value = ob.value, + onValueChange = { o -> + ob.value = o + } + ) + } + item { + Button3(submit = { /*TODO*/ }, enableButton = true, text = stringResource(R.string.label_save_task)) + } + } + ) + } + ) } @Preview(showBackground = true, showSystemUi = true, device = "id:pixel_4_xl") From ff3ecdf8d32eb34c203b0c1a733eaade1f5df465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:14:09 -0400 Subject: [PATCH 29/64] Test: Add UI tests for ScreenRegisterTask components --- .../components/ScreenRegisterTaskTest.kt | 360 ++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 petJournal/app/src/androidTest/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTaskTest.kt diff --git a/petJournal/app/src/androidTest/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTaskTest.kt b/petJournal/app/src/androidTest/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTaskTest.kt new file mode 100644 index 00000000..b8fe2ad3 --- /dev/null +++ b/petJournal/app/src/androidTest/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTaskTest.kt @@ -0,0 +1,360 @@ +package com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen.components + +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.hasSetTextAction +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performTextInput +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.soujunior.petjournal.ui.components.GroupSelectableButton +import com.soujunior.petjournal.ui.components.InputText +import com.soujunior.petjournal.ui.components.PetFilterList +import com.soujunior.petjournal.ui.components.Pets +import com.soujunior.petjournal.ui.components.SelectableButtonInfo +import com.soujunior.petjournal.ui.components.TextFieldCustom +import com.soujunior.petjournal.ui.components.TransactionTypeSelector +import com.soujunior.petjournal.ui.components.task.OneOffTask +import com.soujunior.petjournal.ui.components.task.RecurringTask +import com.soujunior.petjournal.ui.theme.ColorCustom +import com.soujunior.petjournal.ui.util.TransactionType +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class ScreenRegisterTaskTest { + + @get:Rule + val composeTestRule = createComposeRule() + + private val pets = listOf( + Pets(id = 1, name = "Rex"), + Pets(id = 2, name = "Mia"), + Pets(id = 3, name = "Thor") + ) + + private val sampleListOfTasks = listOf( + SelectableButtonInfo("Vacinas", ColorCustom.color_selectable_button_1), + SelectableButtonInfo("Consultas", ColorCustom.color_selectable_button_2), + SelectableButtonInfo("Remédios", ColorCustom.color_selectable_button_3) + ) + + @Test + fun groupSelectableButton_displaysTitleCorrectly() { + composeTestRule.setContent { + GroupSelectableButton( + listOfTasks = sampleListOfTasks, + onSelection = {} + ) + } + + composeTestRule.onNodeWithText("Essa tarefa é...") + .assertIsDisplayed() + } + + @Test + fun groupSelectableButton_displaysAllButtons() { + composeTestRule.setContent { + GroupSelectableButton( + listOfTasks = sampleListOfTasks, + onSelection = {} + ) + } + + sampleListOfTasks.forEach { buttonInfo -> + composeTestRule.onNodeWithText(buttonInfo.title).assertIsDisplayed() + } + } + + @Test + fun groupSelectableButton_selectsAndDeselectsButtonCorrectly() { + composeTestRule.setContent { + GroupSelectableButton( + listOfTasks = sampleListOfTasks, + onSelection = {} + ) + } + + val firstButton = sampleListOfTasks[0] + + composeTestRule.onNodeWithText(firstButton.title).performClick() + + composeTestRule.onNodeWithText(firstButton.title).performClick() + } + + @Test + fun groupSelectableButton_selectsOnlyOneButtonAtATime_ifLogicImpliesThat() { + composeTestRule.setContent { + GroupSelectableButton( + listOfTasks = sampleListOfTasks, + onSelection = {} + ) + } + + val firstButton = sampleListOfTasks[0] + val secondButton = sampleListOfTasks[1] + + composeTestRule.onNodeWithText(firstButton.title).performClick() + + composeTestRule.onNodeWithText(secondButton.title).performClick() + + } + + @Test + fun inputText_displaysTitleCorrectly() { + val testTitle = "Nome da Tarefa" + composeTestRule.setContent { + InputText( + titleText = testTitle, + textValue = "", + onEvent = {} + ) + } + + composeTestRule.onNodeWithText(testTitle).assertIsDisplayed() + } + + @Test + fun inputText_displaysPlaceholder_whenTextValueIsEmptyAndNotMasked() { + val testPlaceholder = "Digite o nome da tarefa" + composeTestRule.setContent { + InputText( + placeholderText = testPlaceholder, + textValue = "", + onEvent = {}, + hasAMask = false + ) + } + + composeTestRule.onNodeWithText(testPlaceholder).assertIsDisplayed() + } + + @Test + fun inputText_doesNotDisplayPlaceholder_whenTextValueIsNotEmpty() { + val testPlaceholder = "Digite o nome da tarefa" + composeTestRule.setContent { + InputText( + placeholderText = testPlaceholder, + textValue = "Minha Tarefa", + onEvent = {}, + hasAMask = false + ) + } + + composeTestRule.onNodeWithText(testPlaceholder).assertDoesNotExist() + } + + @Test + fun inputText_displaysErrorMessages_whenTextErrorIsProvided() { + val errorMessages = listOf("Nome muito curto", "Nome inválido") + composeTestRule.setContent { + InputText( + textValue = "Ops", + onEvent = {}, + isError = true, + textError = errorMessages + ) + } + errorMessages.forEach { errorMessage -> + composeTestRule.onNodeWithText(errorMessage).assertIsDisplayed() + } + } + + private val title = "Descrição" + private val placeholder = "Digite a descrição aqui..." + + @Test + fun shouldDisplayTitleAndPlaceholder() { + composeTestRule.setContent { + TextFieldCustom( + title = title, + placeholder = placeholder, + value = "", + onValueChange = {} + ) + } + + composeTestRule.onNodeWithText(title).assertIsDisplayed() + + composeTestRule.onNodeWithText(placeholder).assertIsDisplayed() + } + + @Test + fun shouldUpdateTextWhenTyping() { + var textValue = "" + composeTestRule.setContent { + TextFieldCustom( + title = title, + placeholder = placeholder, + value = textValue, + onValueChange = { textValue = it } + ) + } + + val inputText = "Descrição do produto" + + composeTestRule.onNode( + hasSetTextAction() + ).performTextInput(inputText) + + assert(textValue == inputText) + } + + @Test + fun shouldDisplayTitleAndAllOption() { + composeTestRule.setContent { + PetFilterList(listPet = pets) + } + + composeTestRule.onNodeWithText("Quais pets precisam dessa tarefa?").assertIsDisplayed() + + composeTestRule.onNodeWithText("Todos").assertIsDisplayed() + } + + @Test + fun shouldDisplayAllPetsFromList() { + composeTestRule.setContent { + PetFilterList(listPet = pets) + } + + pets.forEach { pet -> + composeTestRule.onNodeWithText(pet.name!!).assertIsDisplayed() + } + } + + @Test + fun shouldSelectAndUnselectPet() { + var selected: String? = null + composeTestRule.setContent { + PetFilterList( + listPet = pets, + onSelectedPet = { selected = it } + ) + } + + composeTestRule.onNodeWithText("Rex").performClick() + assert(selected == "Rex") + + composeTestRule.onNodeWithText("Rex").performClick() + assert(selected == "") + } + + @Test + fun shouldSelectAllOption() { + var selected: String? = null + composeTestRule.setContent { + PetFilterList( + listPet = pets, + onSelectedPet = { selected = it } + ) + } + + composeTestRule.onNodeWithText("Todos").performClick() + assert(selected == "Todos") + + composeTestRule.onNodeWithText("Todos").performClick() + assert(selected == "") + } + + @Test + fun shouldShowRecurringTaskWhenRecurrentSelected() { + composeTestRule.setContent { + var selectedType: TransactionType? = null + + Column { + TransactionTypeSelector( + onSelectionChanged = { type -> + selectedType = type + } + ) + + when (selectedType) { + TransactionType.Recurrent -> { + RecurringTask( + setOf(), + onAmPmSelector = {}, + onTime = { _, _ -> }, + onWeekDaySelected = {}, + onDaySelected = {} + ) + } + + TransactionType.OneOff -> { + OneOffTask( + onDateSelected = {}, + onAmPmSelector = {}, + onTime = { _, _ -> } + ) + } + + null -> {} + } + } + } + + composeTestRule.onNodeWithText("Recorrente").performClick() + } + + @Test + fun shouldShowOneOffTaskWhenOneOffSelected() { + composeTestRule.setContent { + var selectedType: TransactionType? = null + + Column { + TransactionTypeSelector( + onSelectionChanged = { type -> + selectedType = type + } + ) + + when (selectedType) { + TransactionType.Recurrent -> { + RecurringTask( + setOf(), + onAmPmSelector = {}, + onTime = { _, _ -> }, + onWeekDaySelected = {}, + onDaySelected = {} + ) + } + + TransactionType.OneOff -> { + OneOffTask( + onDateSelected = {}, + onAmPmSelector = {}, + onTime = { _, _ -> } + ) + } + + null -> {} + } + } + } + + composeTestRule.onNodeWithText("Pontual").performClick() + } + + @Test + fun shouldUpdateObservationText() { + composeTestRule.setContent { + val ob = remember { mutableStateOf("") } + + TextFieldCustom( + title = "Observação", + placeholder = "Digite aqui a sua observação", + value = ob.value, + onValueChange = { ob.value = it }, + ) + } + + composeTestRule.onNodeWithText("Digite aqui a sua observação").assertIsDisplayed() + + val text = "Precisa dar o remédio às 14h" + composeTestRule.onNodeWithText("Digite aqui a sua observação").performTextInput(text) + } + +} \ No newline at end of file From 98135aa17f3788b6fbd545af55f93231e0b4df48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:20:56 -0400 Subject: [PATCH 30/64] Refactor: Update color theme for transaction type button --- .../src/main/java/com/soujunior/petjournal/ui/theme/Color.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt index 8fcf6daa..02768d65 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt @@ -95,7 +95,6 @@ object ColorCustom { val color_border_pet_icon = Color(0xFF9C4DCC) val color_title_pet_icon = Color(0xFF222222) val color_placeholder = Color(0xFFCCCCCC) - val color_shadow_dialog = Color(0x4D000000) - val color_border_dialog = Color(0xFF8D4CD2) - val color_background_button_dialog = Color(0xFF9C4DFF) + val color_text_button_transaction_type = Color(0xFF8dD4CD2) + val color_border_button_transaction_type = Color(0xFFA2A9B1) } \ No newline at end of file From 6cd5d547e2bce5fa4ed48d542bb048328f04a642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:22:27 -0400 Subject: [PATCH 31/64] Refactor: Improve InputText component styling This commit refactors the `InputText` composable: - Updates padding from `16.sdp` to `16.dp`. - Modifies `titleText` styling: - Removes explicit `start` and `end` padding. - Changes text style from `MaterialTheme.typography.bodyMedium` to `MaterialTheme.typography.titleMedium`. - Adjusts `placeholderText` styling: - Sets text color to `ColorCustom.color_placeholder`. - Changes text style from a custom `TextStyle` to `MaterialTheme.typography.bodyMedium`. --- .../petjournal/ui/components/InputText.kt | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt index 0f8ab0ff..7e210fdb 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt @@ -40,7 +40,6 @@ import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import com.soujunior.petjournal.R import com.soujunior.petjournal.ui.theme.ColorCustom import com.soujunior.petjournal.ui.theme.ColorGrid @@ -64,17 +63,16 @@ fun InputText( ) { var showPassword by remember { mutableStateOf(false) } - Column(modifier = modifier.padding(top = 16.sdp)) { + Column(modifier = modifier.padding(16.dp)) { Row { Text( text = titleText, textAlign = TextAlign.Start, color = MaterialTheme.colorScheme.scrim, - style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight(500), + style = MaterialTheme.typography.titleMedium, modifier = modifier .fillMaxWidth() - .padding(start = 24.sdp, end = 24.sdp) ) } Row { @@ -134,12 +132,8 @@ fun InputText( if (textValue.isEmpty() && !hasAMask) { Text( text = placeholderText, - style = TextStyle( - fontSize = 14.sp, - lineHeight = 21.sp, - fontWeight = FontWeight(300), - color = MaterialTheme.colorScheme.scrim, - ) + color = ColorCustom.color_placeholder, + style = MaterialTheme.typography.bodyMedium ) } } From fca4ac25fa1418269a1a25bdfdbdbcd826fadaf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:23:24 -0400 Subject: [PATCH 32/64] Refactor: adjust PetSelectorItem component --- .../ui/components/PetSelectorItem.kt | 84 +++++++++++-------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetSelectorItem.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetSelectorItem.kt index 7a2e0e89..2c4eaa32 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetSelectorItem.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetSelectorItem.kt @@ -56,7 +56,7 @@ fun PetIcon( ambientColor = ColorCustom.color_spot_pet_icon ) .padding(1.dp) - .size(66.dp) + .size(55.dp) .background( color = backgroundColor, shape = RoundedCornerShape(8.dp) @@ -160,46 +160,56 @@ fun PetFilterList( var selectedPets by remember { mutableStateOf(listOf()) } - LazyRow( - modifier = Modifier - .fillMaxWidth() - .padding(top = 20.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - item { - PetFilterItem( - name = "Todos", - isSelected = selectedPets.contains(stringResource(R.string.label_all_pets)), - imageRes = null, - onSelect = { name -> - selectedPets = if (selectedPets.contains(name)) { - selectedPets - name - } else { - selectedPets + name + Column(modifier = Modifier.padding(16.dp)) { + Text( + text = "Quais pets precisam dessa tarefa?", + color = MaterialTheme.colorScheme.scrim, + fontWeight = FontWeight(500), + style = MaterialTheme.typography.titleMedium + ) + + LazyRow( + modifier = Modifier + .fillMaxWidth() + .padding(top = 20.dp, start = 10.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + item { + PetFilterItem( + name = "Todos", + isSelected = selectedPets.contains(stringResource(R.string.label_all_pets)), + imageRes = null, + onSelect = { name -> + selectedPets = if (selectedPets.contains(name)) { + selectedPets - name + } else { + selectedPets + name + } + onSelectedPet(if (selectedPets.contains(name)) name else "") } - onSelectedPet(if (selectedPets.contains(name)) name else "") - } - ) - } - items( - items = listPet, - key = { it.id } - ) { item -> - PetFilterItem( - name = item.name!!, - isSelected = selectedPets.contains(item.name), - imageRes = item.imageRes, - onSelect = { name -> - selectedPets = if (selectedPets.contains(name)) { - selectedPets - name - } else { - selectedPets + name + ) + } + items( + items = listPet, + key = { it.id } + ) { item -> + PetFilterItem( + name = item.name!!, + isSelected = selectedPets.contains(item.name), + imageRes = item.imageRes, + onSelect = { name -> + selectedPets = if (selectedPets.contains(name)) { + selectedPets - name + } else { + selectedPets + name + } + onSelectedPet(if (selectedPets.contains(name)) name else "") } - onSelectedPet(if (selectedPets.contains(name)) name else "") - } - ) + ) + } } } + } @Preview(showBackground = true, showSystemUi = false, device = "id:pixel_4_xl") From 4f3291a0e756d67c5b69cca6bc06d1330ab71abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:23:56 -0400 Subject: [PATCH 33/64] feat: create RegisterTaskScreen --- .../registerTaskScreen/RegisterTaskScreen.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/RegisterTaskScreen.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/RegisterTaskScreen.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/RegisterTaskScreen.kt new file mode 100644 index 00000000..f5987a1b --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/RegisterTaskScreen.kt @@ -0,0 +1,10 @@ +package com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen + +import androidx.compose.runtime.Composable +import androidx.navigation.NavController +import com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen.components.ScreenRegisterTask + +@Composable +fun RegisterTaskScreen(navController: NavController) { + ScreenRegisterTask(navController) +} \ No newline at end of file From 80c7e49eada4dd9d09b8425f8832c00540374edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:24:29 -0400 Subject: [PATCH 34/64] feat: Create TransactionTypeSelector component --- .../ui/components/TransactionTypeSelector.kt | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt new file mode 100644 index 00000000..b8f49ada --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt @@ -0,0 +1,146 @@ +package com.soujunior.petjournal.ui.components + +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.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +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.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.soujunior.petjournal.R +import com.soujunior.petjournal.ui.theme.ColorCustom +import com.soujunior.petjournal.ui.util.TransactionType + +@Composable +fun TransactionTypeSelector( + onSelectionChanged: (TransactionType?) -> Unit +) { + var selectedType by remember { mutableStateOf(null) } + + val selectedColor = ColorCustom.color_background_month_disabled + val unselectedColor = MaterialTheme.colorScheme.background + val borderColor = ColorCustom.color_border_button_transaction_type + + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxWidth() + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(16.dp) + ) { + ToggleButton( + text = stringResource(R.string.label_recurrent), + isSelected = selectedType == TransactionType.Recurrent, + onClick = { + val newType = TransactionType.Recurrent + selectedType = newType + onSelectionChanged(newType) + }, + selectedColor = selectedColor, + unselectedColor = unselectedColor, + borderColor = if (selectedType == TransactionType.Recurrent) selectedColor else borderColor + ) + + ToggleButton( + text = stringResource(R.string.label_one_off), + isSelected = selectedType == TransactionType.OneOff, + onClick = { + val newType = TransactionType.OneOff + selectedType = newType + onSelectionChanged(newType) + }, + selectedColor = selectedColor, + unselectedColor = unselectedColor, + borderColor = if (selectedType == TransactionType.OneOff) selectedColor else borderColor + ) + } + + if (selectedType == TransactionType.Recurrent) { + onSelectionChanged(selectedType) + } else { + onSelectionChanged(selectedType) + } + } +} + +@Composable +fun ToggleButton( + text: String, + isSelected: Boolean, + onClick: () -> Unit, + selectedColor: Color, + unselectedColor: Color, + borderColor: Color +) { + val backgroundColor = if (isSelected) selectedColor else unselectedColor + + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .width(150.dp) + .clip(RoundedCornerShape(50)) + .border(1.dp, borderColor, RoundedCornerShape(50)) + .background(backgroundColor) + .clickable { onClick() } + .padding(horizontal = 24.dp, vertical = 12.dp) + ) { + Text( + text = text, + color = ColorCustom.color_text_button_transaction_type, + style = MaterialTheme.typography.titleMedium, + ) + } +} + +@Preview(showBackground = true) +@Composable +fun TransactionTypeSelectorPreview() { + TransactionTypeSelector( + onSelectionChanged = {} + ) +} + +@Preview(showBackground = true) +@Composable +fun ToggleButtonPreview() { + Column(modifier = Modifier.padding(16.dp)) { + ToggleButton( + text = stringResource(R.string.label_recurrent), + isSelected = true, + onClick = {}, + selectedColor = ColorCustom.color_background_month_disabled, + unselectedColor = MaterialTheme.colorScheme.background, + borderColor = ColorCustom.color_border_button_transaction_type + ) + + ToggleButton( + text = stringResource(R.string.label_one_off), + isSelected = false, + onClick = {}, + selectedColor = ColorCustom.color_background_month_disabled, + unselectedColor = MaterialTheme.colorScheme.background, + borderColor = ColorCustom.color_border_button_transaction_type + ) + } + +} \ No newline at end of file From 66e9541c0ef092a2ea8a5d81955af13b940fb36b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:24:50 -0400 Subject: [PATCH 35/64] feat: Create TransactionType enum --- .../java/com/soujunior/petjournal/ui/util/TransactionType.kt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/TransactionType.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/TransactionType.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/TransactionType.kt new file mode 100644 index 00000000..0a632ab5 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/TransactionType.kt @@ -0,0 +1,5 @@ +package com.soujunior.petjournal.ui.util + +enum class TransactionType { + Recurrent, OneOff +} \ No newline at end of file From 47bcb1c420548c678d928cfcc917e1bd1a8ec816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:25:07 -0400 Subject: [PATCH 36/64] Refactor: Rename DescriptionTextField to TextFieldCustom --- ...riptionTextField.kt => TextFieldCustom.kt} | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) rename petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/{DescriptionTextField.kt => TextFieldCustom.kt} (83%) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DescriptionTextField.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt similarity index 83% rename from petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DescriptionTextField.kt rename to petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt index e018df07..91c2864c 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DescriptionTextField.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt @@ -13,15 +13,15 @@ import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.soujunior.petjournal.R import com.soujunior.petjournal.ui.theme.ColorCustom @Composable -fun DescriptionTextField( +fun TextFieldCustom( + title:String, + placeholder:String, value: String, onValueChange: (String) -> Unit, modifier: Modifier = Modifier @@ -31,8 +31,9 @@ fun DescriptionTextField( .padding(16.dp) ) { Text( - text = stringResource(R.string.label_description), - fontWeight = FontWeight.Bold, + text = title, + color = MaterialTheme.colorScheme.scrim, + fontWeight = FontWeight(500), style = MaterialTheme.typography.titleMedium, ) @@ -43,9 +44,9 @@ fun DescriptionTextField( onValueChange = onValueChange, placeholder = { Text( - text = stringResource(R.string.enter_the_task_description_here), + text = placeholder, color = ColorCustom.color_placeholder, - style = MaterialTheme.typography.bodySmall + style = MaterialTheme.typography.bodyMedium ) }, modifier = Modifier @@ -64,7 +65,9 @@ fun DescriptionTextField( @Preview @Composable fun DescriptionTextFieldPreview() { - DescriptionTextField( + TextFieldCustom( + title = "Título", + placeholder = "Descrição", value = "", onValueChange = {} ) From e37e6c849f7f1c38758dce7bcf6433269d14e719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:25:22 -0400 Subject: [PATCH 37/64] Refactor: Remove redundant strings and add recurrence strings # Conflicts: # petJournal/app/src/main/res/values/strings.xml --- petJournal/app/src/main/res/values/strings.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/petJournal/app/src/main/res/values/strings.xml b/petJournal/app/src/main/res/values/strings.xml index be1d9d82..ddbe6fea 100644 --- a/petJournal/app/src/main/res/values/strings.xml +++ b/petJournal/app/src/main/res/values/strings.xml @@ -145,6 +145,8 @@ Ração Passeio Essa tarefa é... + Tarefa adicionada\ncom sucesso! + Nova tarefa Ativo nos meses Todos Descrição @@ -154,9 +156,9 @@ Abrir Calendário 00/00/0000 dd/MM/yyyy - Tarefa adicionada\ncom sucesso! - Nova tarefa Ir para a HomePage AM PM + Recorrente + Pontual \ No newline at end of file From 3ce4e77635e83c3adb85cb2b02d42f25586c70a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:25:38 -0400 Subject: [PATCH 38/64] Refactor: Adjust SelectableButton layout and style --- .../ui/components/SelectableButtonData.kt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt index 8eb8733c..740815ea 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt @@ -40,8 +40,7 @@ fun SelectableButton( ) { androidx.compose.material3.Button( modifier = modifierSelectableButton - .height(70.dp) - .padding(top = 15.dp, end = 15.dp, bottom = 15.dp) + .height(40.dp) .then( if (isSelected) { Modifier.shadow( @@ -120,14 +119,16 @@ fun GroupSelectableButton( ) { Text( text = stringResource(R.string.label_select_main_category), - style = MaterialTheme.typography.titleLarge, + style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.scrim, fontWeight = FontWeight(500), lineHeight = 24.sp ) FlowRow( - modifier = Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() + .padding(top = 15.dp) ) { buttons.forEachIndexed { index, buttonInfo -> SelectableButton( @@ -142,7 +143,9 @@ fun GroupSelectableButton( onSelection("") } }, - modifierSelectableButton = Modifier.adaptiveWidthForTitle(buttonInfo.title) + modifierSelectableButton = Modifier + .adaptiveWidthForTitle(buttonInfo.title) + .padding(bottom = 15.dp, end = 15.dp) ) } } From 6bbc63c77d23a87c0f506f09453cb46baebc1540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:25:57 -0400 Subject: [PATCH 39/64] feat: Create ScreenRegisterTask screen This commit introduces the `ScreenRegisterTask` composable, a new screen for registering tasks within the application. Key changes include: - Addition of `ScreenRegisterTask.kt` file. - Implementation of the `ScreenRegisterTask` composable function, which includes: - A `ScaffoldCustom` for the basic screen structure with a top app bar titled "Nova tarefa" (New Task) and bottom navigation. - A `LazyColumn` to display various input fields and components for task registration. - `InputText` for the task name. - `TextFieldCustom` for the task description and an observation field. - `GroupSelectableButton` (functionality not fully detailed in the diff). - `PetFilterList` to select a pet associated with the task. - `TransactionTypeSelector` to choose between recurrent and one-off task types. - A `@Preview` function `ScreenRegisterTaskPreview` is included for UI development and testing. --- .../components/ScreenRegisterTask.kt | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt new file mode 100644 index 00000000..ae84a260 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt @@ -0,0 +1,125 @@ +package com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen.components + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.Text +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.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.navigation.NavController +import androidx.navigation.compose.rememberNavController +import com.soujunior.petjournal.R +import com.soujunior.petjournal.ui.components.GroupSelectableButton +import com.soujunior.petjournal.ui.components.InputText +import com.soujunior.petjournal.ui.components.PetFilterList +import com.soujunior.petjournal.ui.components.Pets +import com.soujunior.petjournal.ui.components.ScaffoldCustom +import com.soujunior.petjournal.ui.components.TextFieldCustom +import com.soujunior.petjournal.ui.components.TransactionTypeSelector +import com.soujunior.petjournal.ui.util.TransactionType + +@Composable +fun ScreenRegisterTask(navController: NavController) { + + val listPet = listOf( + Pets( + id = 1, + imageRes = painterResource(R.drawable.image_jujuba), + name = "Jujuba" + ), + Pets( + id = 2, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ) + ) + + val nameTask = remember { mutableStateOf("") } + val desc = remember { mutableStateOf("") } + var selectedType by remember { mutableStateOf(null) } + + Column(modifier = Modifier) { + ScaffoldCustom( + modifier = Modifier, + navigationUp = navController, + showTopBar = true, + titleTopBar = stringResource(R.string.label_new_task), + showBottomBarNavigation = true, + contentToUse = { + LazyColumn( + contentPadding = it, + content = { + item { + GroupSelectableButton() + } + item { + InputText( + modifier = Modifier, + placeholderText = "Digite aqui o nome da tarefa", + titleText = "Nome da tarefa", + textValue = nameTask.value, + onEvent = { t -> + nameTask.value = t + }, + ) + } + item { + TextFieldCustom( + title = stringResource(R.string.label_description), + placeholder = stringResource(R.string.enter_the_task_description_here), + value = desc.value, + onValueChange = { d -> + desc.value = d + } + ) + } + item { + PetFilterList( + listPet, + onSelectedPet = {} + ) + } + item { + Column { + TransactionTypeSelector( + onSelectionChanged = { type -> + selectedType = type + } + ) + + when (selectedType) { + TransactionType.Recurrent -> Text(text = "Recorrente") + TransactionType.OneOff -> Text(text = "Pontual") + null -> {} + } + } + } + item { + TextFieldCustom( + title = "Observação", + placeholder = "Digite aqui a sua observação", + value = desc.value, + onValueChange = { d -> + desc.value = d + } + ) + } + } + ) + } + ) + } +} + +@Preview(showBackground = true, showSystemUi = true, device = "id:pixel_4_xl") +@Composable +fun ScreenRegisterTaskPreview() { + val nav = rememberNavController() + ScreenRegisterTask(nav) +} \ No newline at end of file From 877916d76d50ab94619eac96ab2cdc11cd69e8d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 2 Aug 2025 15:26:16 -0400 Subject: [PATCH 40/64] feat: integrate ScreenRegisterTask into MainActivity --- .../com/soujunior/petjournal/navigation/MainActivity.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/MainActivity.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/MainActivity.kt index e4db3ebb..65eed297 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/MainActivity.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/MainActivity.kt @@ -7,8 +7,9 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect import androidx.compose.ui.graphics.Color import androidx.core.view.WindowCompat +import androidx.navigation.compose.rememberNavController import com.google.accompanist.systemuicontroller.rememberSystemUiController -import com.soujunior.petjournal.ui.components.ActiveMonthsComponent +import com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen.components.ScreenRegisterTask import com.soujunior.petjournal.ui.theme.PetJournalTheme class MainActivity : ComponentActivity() { @@ -18,7 +19,8 @@ class MainActivity : ComponentActivity() { setContent { ChangeSystemBars() // PresentationManager() - ActiveMonthsComponent(activeMonths = setOf("Jan", "Mar", "Mai")) + val nav = rememberNavController() + ScreenRegisterTask(nav) } } } From b297eb557f001ba2bb487b41e32ddcc7e8186a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:09:10 -0400 Subject: [PATCH 41/64] feat: Add unfocused color for WheelTimePicker --- .../app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt index 02768d65..dff0a3be 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/theme/Color.kt @@ -97,4 +97,5 @@ object ColorCustom { val color_placeholder = Color(0xFFCCCCCC) val color_text_button_transaction_type = Color(0xFF8dD4CD2) val color_border_button_transaction_type = Color(0xFFA2A9B1) + val color_unfocused_wheelTimePicker = Color(0xFFDADADA) } \ No newline at end of file From 58179ea965e53dc68f00b124fed5442ee9006860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:10:23 -0400 Subject: [PATCH 42/64] feat: Create DayPicker composable --- .../ui/components/data/DayPicker.kt | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/DayPicker.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/DayPicker.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/DayPicker.kt new file mode 100644 index 00000000..a5e3d4a4 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/data/DayPicker.kt @@ -0,0 +1,98 @@ +package com.soujunior.petjournal.ui.components.data + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.flow.distinctUntilChanged +import java.time.LocalDate + +@OptIn(ExperimentalFoundationApi::class) +@Composable +fun DayPicker( + onDaySelected: (Int) -> Unit +) { + val currentDate = remember { LocalDate.now() } + val totalDays = remember { currentDate.lengthOfMonth() } + + val days = remember { (1..totalDays).toList() } + + val listState = rememberLazyListState(initialFirstVisibleItemIndex = currentDate.dayOfMonth - 1) + + val flingBehavior = rememberSnapFlingBehavior(lazyListState = listState) + + LaunchedEffect(listState) { + snapshotFlow { listState.firstVisibleItemIndex } + .distinctUntilChanged() + .collect { index -> + onDaySelected(days.getOrNull(index + 1) ?: days.last()) + } + } + + Column( + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text(text = "DIA", style = MaterialTheme.typography.bodySmall) + + Box( + modifier = Modifier + .height(120.dp) + .width(60.dp), + contentAlignment = Alignment.Center + ) { + LazyColumn( + state = listState, + flingBehavior = flingBehavior, + contentPadding = PaddingValues(vertical = 40.dp), + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxHeight() + ) { + itemsIndexed(days) { index, day -> + val isSelected = listState.firstVisibleItemIndex == index + Text( + text = day.toString(), + fontSize = if (isSelected) 26.sp else 20.sp, + color = if (isSelected) Color.Black else Color.LightGray, + fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal, + modifier = Modifier.padding(vertical = 4.dp) + ) + } + } + } + } +} + + +@Preview +@Composable +fun DayPickerPreview(){ + var selectedDay by remember { mutableStateOf(LocalDate.now().dayOfMonth) } + + DayPicker( + onDaySelected = { selectedDay = it } + ) +} \ No newline at end of file From b79d4d1da5c763e2ce501c329beea98ddc0fbf02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:10:44 -0400 Subject: [PATCH 43/64] feat: Create OneOffTask composable --- .../ui/components/task/OneOffTask.kt | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/OneOffTask.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/OneOffTask.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/OneOffTask.kt new file mode 100644 index 00000000..3edf7ff7 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/OneOffTask.kt @@ -0,0 +1,51 @@ +package com.soujunior.petjournal.ui.components.task + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +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.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.soujunior.petjournal.ui.components.clock.TimePickerWithPeriodSelector +import com.soujunior.petjournal.ui.components.data.CustomDatePicker + +@Composable +fun OneOffTask( + onDateSelected: (Long?) -> Unit = {}, + onAmPmSelector: (String?) -> Unit = {}, + onTime: (Int, Int) -> Unit = { _, _ -> } +) { + var selectedTimestamp by remember { mutableStateOf(null) } + + Column(modifier = Modifier.padding(start = 20.dp, end = 20.dp)) { + CustomDatePicker( + label = "Data", + value = selectedTimestamp, + onValueChange = { + selectedTimestamp = it + onDateSelected(selectedTimestamp) + }, + modifier = Modifier.fillMaxWidth() + ) + + TimePickerWithPeriodSelector( + onAmPmSelector = { amPmSelector -> + onAmPmSelector(amPmSelector) + }, + onTime = { hour, minute -> + onTime(hour, minute) + } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun OneOffTaskPreview() { + OneOffTask() +} \ No newline at end of file From f80dfe965d5d79bc96a46f36f8a5205ad1be79c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:11:07 -0400 Subject: [PATCH 44/64] feat: Create PeriodSelector composable --- .../ui/components/PeriodSelector.kt | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PeriodSelector.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PeriodSelector.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PeriodSelector.kt new file mode 100644 index 00000000..f20a537e --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PeriodSelector.kt @@ -0,0 +1,90 @@ +package com.soujunior.petjournal.ui.components + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.soujunior.petjournal.ui.util.SelectedPeriodType + +@Composable +fun PeriodSelector( + selected: SelectedPeriodType, + onSelectionChanged: (SelectedPeriodType) -> Unit +) { + val items = listOf(SelectedPeriodType.Diária, SelectedPeriodType.Semanal, SelectedPeriodType.Mensal) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + items.forEach { item -> + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .clickable { onSelectionChanged(item) } + .padding(horizontal = 8.dp) + ) { + Text( + text = item.name, + style = MaterialTheme.typography.bodyMedium, + color = if (selected == item) Color(0xFF8D4CD2) else Color.Black, + ) + if (selected == item) { + TriangleIndicator() + } else { + Spacer(modifier = Modifier.height(6.dp)) + } + } + } + } +} + +@Composable +fun TriangleIndicator( + color: Color = Color(0xFF8D4CD2), + modifier: Modifier = Modifier + .width(60.dp) + .height(2.dp) +) { + Canvas(modifier = modifier) { + val width = size.width + val height = size.height + + val inset = width * 0.1f + + val path = Path().apply { + moveTo(inset, 0f) + lineTo(width - inset, 0f) + lineTo(width, height) + lineTo(0f, height) + close() + } + + drawPath(path = path, color = color) + } +} + + +@Preview(showBackground = true) +@Composable +fun PeriodSelectorPreview() { + var selectedPeriod = SelectedPeriodType.Diária + PeriodSelector(selected = selectedPeriod) { + selectedPeriod = it + } +} \ No newline at end of file From ceefb67a52d855281fcb9bc8ea2b2773ab104e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:11:26 -0400 Subject: [PATCH 45/64] feat: Create RecurringTask composable --- .../ui/components/task/RecurrentTask.kt | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/RecurrentTask.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/RecurrentTask.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/RecurrentTask.kt new file mode 100644 index 00000000..df35b3d9 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/RecurrentTask.kt @@ -0,0 +1,135 @@ +package com.soujunior.petjournal.ui.components.task + +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.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +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.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.soujunior.petjournal.ui.components.ActiveMonthsComponent +import com.soujunior.petjournal.ui.components.AmPmSelector +import com.soujunior.petjournal.ui.components.PeriodSelector +import com.soujunior.petjournal.ui.components.WeekDaySelector +import com.soujunior.petjournal.ui.components.clock.TimePickerWithPeriodSelector +import com.soujunior.petjournal.ui.components.clock.WheelTimePicker +import com.soujunior.petjournal.ui.components.data.DayPicker +import com.soujunior.petjournal.ui.util.SelectedPeriodType + +@Composable +fun RecurringTask( + activeMonths: Set = setOf(), + onAmPmSelector: (String?) -> Unit = {}, + onTime: (Int?, Int?) -> Unit = { _, _ -> }, + onWeekDaySelected: (String?) -> Unit = {}, + onDaySelected: (Int?) -> Unit = {}, +) { + var selectedPeriod by remember { mutableStateOf(SelectedPeriodType.Diária) } + PeriodSelector( + selected = selectedPeriod, + onSelectionChanged = { selectedPeriod = it } + ) + + when (selectedPeriod) { + SelectedPeriodType.Diária -> { + TimePickerWithPeriodSelector( + onAmPmSelector = { amPmSelector -> + onAmPmSelector(amPmSelector) + }, + onTime = { hour, minute -> + onTime(hour, minute) + } + ) + } + + SelectedPeriodType.Semanal -> { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + + WeekDaySelector( + onDaySelected = { weekDaySelected -> + onWeekDaySelected(weekDaySelected) + } + ) + + AmPmSelector( + onPeriodSelected = { amPmSelector -> + onAmPmSelector(amPmSelector) + } + ) + Box( + modifier = Modifier + .padding(start = 8.dp) + .height(150.dp) + .width(100.dp), + contentAlignment = Alignment.Center + ) { + WheelTimePicker( + onTimeChanged = { hour, minute -> + onTime(hour, minute) + } + ) + } + } + } + + SelectedPeriodType.Mensal -> { + Column { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + + DayPicker( + onDaySelected = { daySelected -> + onDaySelected(daySelected) + } + ) + AmPmSelector( + onPeriodSelected = { amPmSelector -> + onAmPmSelector(amPmSelector) + } + ) + Box( + modifier = Modifier + .height(150.dp) + .width(100.dp), + contentAlignment = Alignment.Center + ) { + WheelTimePicker( + onTimeChanged = { hour, minute -> + onTime(hour, minute) + } + ) + } + } + ActiveMonthsComponent(activeMonths = activeMonths) + } + + } + } +} + +@Preview(showBackground = true) +@Composable +fun RecurringTaskPreview() { + RecurringTask() +} \ No newline at end of file From f2b51ba92a80238f9627964e9860a215ae095886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:11:44 -0400 Subject: [PATCH 46/64] Refactor: Make GroupSelectableButton dynamic --- .../ui/components/SelectableButtonData.kt | 59 ++++++++++--------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt index 740815ea..7924a58c 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt @@ -81,36 +81,11 @@ fun SelectableButton( @OptIn(ExperimentalLayoutApi::class) @Composable fun GroupSelectableButton( + listOfTasks: List, onSelection: (String) -> Unit = {} ) { - val buttons = listOf( - SelectableButtonInfo( - stringResource(R.string.label_selectable_button_vaccines), - ColorCustom.color_selectable_button_1 - ), - SelectableButtonInfo( - stringResource(R.string.label_selectable_button_consultations), - ColorCustom.color_selectable_button_2 - ), - SelectableButtonInfo( - stringResource(R.string.label_selectable_button_medicine), - ColorCustom.color_selectable_button_3 - ), - SelectableButtonInfo( - stringResource(R.string.label_selectable_button_bath), - ColorCustom.color_selectable_button_4 - ), - SelectableButtonInfo( - stringResource(R.string.label_selectable_button_food), - ColorCustom.color_selectable_button_5 - ), - SelectableButtonInfo( - stringResource(R.string.label_selectable_button_pet_walk), - ColorCustom.color_selectable_button_6 - ), - ) - val selectionState = remember { mutableStateListOf(*Array(buttons.size) { false }) } + val selectionState = remember { mutableStateListOf(*Array(listOfTasks.size) { false }) } Column( modifier = Modifier @@ -130,7 +105,7 @@ fun GroupSelectableButton( .fillMaxWidth() .padding(top = 15.dp) ) { - buttons.forEachIndexed { index, buttonInfo -> + listOfTasks.forEachIndexed { index, buttonInfo -> SelectableButton( titleButton = buttonInfo.title, colorButton = buttonInfo.color, @@ -162,5 +137,31 @@ data class SelectableButtonInfo( @Preview(showBackground = true, showSystemUi = true, device = "id:pixel_4_xl") @Composable fun CustomSelectableButtonPreview() { - GroupSelectableButton() + val listOfTasks = listOf( + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_vaccines), + ColorCustom.color_selectable_button_1 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_consultations), + ColorCustom.color_selectable_button_2 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_medicine), + ColorCustom.color_selectable_button_3 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_bath), + ColorCustom.color_selectable_button_4 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_food), + ColorCustom.color_selectable_button_5 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_pet_walk), + ColorCustom.color_selectable_button_6 + ), + ) + GroupSelectableButton(listOfTasks) } \ No newline at end of file From 1cc96ba92a00a74ace6ccb20c12899213edf5426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:12:00 -0400 Subject: [PATCH 47/64] feat: Add SelectedPeriodType enum --- .../com/soujunior/petjournal/ui/util/SelectedPeriodType.kt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/SelectedPeriodType.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/SelectedPeriodType.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/SelectedPeriodType.kt new file mode 100644 index 00000000..3fa0a40e --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/util/SelectedPeriodType.kt @@ -0,0 +1,5 @@ +package com.soujunior.petjournal.ui.util + +enum class SelectedPeriodType { + Diária, Semanal, Mensal +} \ No newline at end of file From ba315cbbe1b1724e330c467f1416fb2cbc33c1f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:12:25 -0400 Subject: [PATCH 48/64] Refactor: Update TextFieldCustom padding and add new string resources --- .../soujunior/petjournal/ui/components/TextFieldCustom.kt | 2 +- petJournal/app/src/main/res/values/strings.xml | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt index 91c2864c..d8318f72 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt @@ -28,7 +28,7 @@ fun TextFieldCustom( ) { Column( modifier = modifier - .padding(16.dp) + .padding(start = 16.dp, end = 16.dp) ) { Text( text = title, diff --git a/petJournal/app/src/main/res/values/strings.xml b/petJournal/app/src/main/res/values/strings.xml index ddbe6fea..631122de 100644 --- a/petJournal/app/src/main/res/values/strings.xml +++ b/petJournal/app/src/main/res/values/strings.xml @@ -161,4 +161,10 @@ PM Recorrente Pontual + Data + Digite aqui o nome da tarefa + Nome da tarefa + Observação + Digite aqui a sua observação + Salvar \ No newline at end of file From 4ea5e675e23ef42ef43e2d4d4080a312b401f969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:12:42 -0400 Subject: [PATCH 49/64] feat: Create TimePickerWithPeriodSelector Composable --- .../clock/TimePickerWithPeriodSelector.kt | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/TimePickerWithPeriodSelector.kt diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/TimePickerWithPeriodSelector.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/TimePickerWithPeriodSelector.kt new file mode 100644 index 00000000..32ead607 --- /dev/null +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/TimePickerWithPeriodSelector.kt @@ -0,0 +1,47 @@ +package com.soujunior.petjournal.ui.components.clock + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.soujunior.petjournal.ui.components.AmPmSelector + +@Composable +fun TimePickerWithPeriodSelector( + onAmPmSelector: (String) -> Unit, + onTime: (Int, Int) -> Unit +) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + AmPmSelector( + onPeriodSelected = { periodSelected -> + onAmPmSelector(periodSelected) + } + ) + Box( + modifier = Modifier + .padding(start = 8.dp) + .height(150.dp) + .width(100.dp), + contentAlignment = Alignment.Center + ) { + WheelTimePicker( + onTimeChanged = { hour, minute -> + onTime(hour, minute) + } + ) + } + } +} \ No newline at end of file From dcb9f30f4b3b124fcebec3ee2802963e9b56df77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:12:57 -0400 Subject: [PATCH 50/64] Refactor: Adjust TransactionTypeSelector button size --- .../petjournal/ui/components/TransactionTypeSelector.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt index b8f49ada..fbdacd92 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape @@ -97,7 +98,7 @@ fun ToggleButton( Box( contentAlignment = Alignment.Center, modifier = Modifier - .width(150.dp) + .width(130.dp).height(50.dp) .clip(RoundedCornerShape(50)) .border(1.dp, borderColor, RoundedCornerShape(50)) .background(backgroundColor) From 7a5a3f7937653f04b67f57e2fd60e29c2a5afe0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:13:19 -0400 Subject: [PATCH 51/64] Refactor: Update WheelTimePicker component --- .../ui/components/clock/WheelTimePicker.kt | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/WheelTimePicker.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/WheelTimePicker.kt index ab19cec4..ceadee14 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/WheelTimePicker.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/WheelTimePicker.kt @@ -23,7 +23,6 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.TextStyle @@ -32,6 +31,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.soujunior.petjournal.ui.theme.ColorCustom import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.filter import kotlin.math.abs @@ -59,7 +59,7 @@ fun WheelTimePicker( initialMinute: Int = 0, textStyle: TextStyle = MaterialTheme.typography.titleLarge, focusedColor: Color = Color.Black, - unfocusedColor: Color = Color.Gray, + unfocusedColor: Color = ColorCustom.color_unfocused_wheelTimePicker, onTimeChanged: (hour: Int, minute: Int) -> Unit ) { require(visibleItemsCount % 2 != 0) { "visibleItemsCount must be an odd number." } @@ -162,8 +162,10 @@ private fun PickerColumn( if (layoutInfo.visibleItemsInfo.isEmpty()) { -1 } else { - val viewportCenter = (layoutInfo.viewportStartOffset + layoutInfo.viewportEndOffset) / 2 - layoutInfo.visibleItemsInfo.minByOrNull { abs((it.offset + it.size / 2) - viewportCenter) }?.index ?: -1 + val viewportCenter = + (layoutInfo.viewportStartOffset + layoutInfo.viewportEndOffset) / 2 + layoutInfo.visibleItemsInfo.minByOrNull { abs((it.offset + it.size / 2) - viewportCenter) }?.index + ?: -1 } } } @@ -176,12 +178,14 @@ private fun PickerColumn( val layoutInfo = listState.layoutInfo if (layoutInfo.visibleItemsInfo.isEmpty()) return@collect - val viewportCenter = (layoutInfo.viewportStartOffset + layoutInfo.viewportEndOffset) / 2 + val viewportCenter = + (layoutInfo.viewportStartOffset + layoutInfo.viewportEndOffset) / 2 val centralItem = layoutInfo.visibleItemsInfo.minByOrNull { abs((it.offset + it.size / 2) - viewportCenter) } ?: return@collect - val itemDataIndex = (centralItem.index - halfVisibleItems).coerceIn(0, items.size - 1) + val itemDataIndex = + (centralItem.index - halfVisibleItems).coerceIn(0, items.size - 1) val delta = (centralItem.offset + centralItem.size / 2) - viewportCenter listState.animateScrollBy(delta.toFloat()) @@ -204,8 +208,14 @@ private fun PickerColumn( items(items.size) { dataIndex -> val lazyColumnIndex = dataIndex + halfVisibleItems val isFocused = (lazyColumnIndex == centralLazyColumnIndex) - val scale by animateFloatAsState(targetValue = if (isFocused) 1.2f else 1.0f, label = "scale") - val alpha by animateFloatAsState(targetValue = if (isFocused) 1.0f else 0.5f, label = "alpha") + val scale by animateFloatAsState( + targetValue = if (isFocused) 1.2f else 1.0f, + label = "scale" + ) + val alpha by animateFloatAsState( + targetValue = if (isFocused) 1.0f else 0.5f, + label = "alpha" + ) Box( modifier = Modifier.height(itemHeight), @@ -215,9 +225,9 @@ private fun PickerColumn( text = items[dataIndex], style = textStyle.copy( color = if (isFocused) focusedColor else unfocusedColor, - fontSize = textStyle.fontSize * scale + fontSize = 34.sp ), - modifier = Modifier.alpha(alpha) +// modifier = Modifier.alpha(alpha) ) } } From 805ac724ceeda7606280fe3f2406707575533e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:13:44 -0400 Subject: [PATCH 52/64] feat: Enhance ScreenRegisterTask UI and functionality --- .../components/ScreenRegisterTask.kt | 253 +++++++++++++----- 1 file changed, 187 insertions(+), 66 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt index ae84a260..9e9f8abf 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt @@ -1,32 +1,69 @@ package com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen.components +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material3.Text 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.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.navigation.NavController import androidx.navigation.compose.rememberNavController import com.soujunior.petjournal.R +import com.soujunior.petjournal.ui.components.Button3 import com.soujunior.petjournal.ui.components.GroupSelectableButton import com.soujunior.petjournal.ui.components.InputText import com.soujunior.petjournal.ui.components.PetFilterList import com.soujunior.petjournal.ui.components.Pets import com.soujunior.petjournal.ui.components.ScaffoldCustom +import com.soujunior.petjournal.ui.components.SelectableButtonInfo import com.soujunior.petjournal.ui.components.TextFieldCustom import com.soujunior.petjournal.ui.components.TransactionTypeSelector +import com.soujunior.petjournal.ui.components.task.OneOffTask +import com.soujunior.petjournal.ui.components.task.RecurringTask +import com.soujunior.petjournal.ui.theme.ColorCustom import com.soujunior.petjournal.ui.util.TransactionType +import ir.kaaveh.sdpcompose.sdp @Composable fun ScreenRegisterTask(navController: NavController) { + val listOfTasks = listOf( + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_vaccines), + ColorCustom.color_selectable_button_1 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_consultations), + ColorCustom.color_selectable_button_2 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_medicine), + ColorCustom.color_selectable_button_3 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_bath), + ColorCustom.color_selectable_button_4 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_food), + ColorCustom.color_selectable_button_5 + ), + SelectableButtonInfo( + stringResource(R.string.label_selectable_button_pet_walk), + ColorCustom.color_selectable_button_6 + ), + ) + val listPet = listOf( Pets( id = 1, @@ -37,84 +74,168 @@ fun ScreenRegisterTask(navController: NavController) { id = 2, imageRes = painterResource(R.drawable.image_alfredo), name = "Alfredo" + ), + Pets( + id = 3, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 4, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 5, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 6, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 7, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 8, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 9, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" ) ) val nameTask = remember { mutableStateOf("") } val desc = remember { mutableStateOf("") } + val ob = remember { mutableStateOf("") } var selectedType by remember { mutableStateOf(null) } - Column(modifier = Modifier) { - ScaffoldCustom( - modifier = Modifier, - navigationUp = navController, - showTopBar = true, - titleTopBar = stringResource(R.string.label_new_task), - showBottomBarNavigation = true, - contentToUse = { - LazyColumn( - contentPadding = it, - content = { - item { - GroupSelectableButton() - } - item { - InputText( - modifier = Modifier, - placeholderText = "Digite aqui o nome da tarefa", - titleText = "Nome da tarefa", - textValue = nameTask.value, - onEvent = { t -> - nameTask.value = t - }, - ) - } - item { - TextFieldCustom( - title = stringResource(R.string.label_description), - placeholder = stringResource(R.string.enter_the_task_description_here), - value = desc.value, - onValueChange = { d -> - desc.value = d + ScaffoldCustom( + modifier = Modifier, + navigationUp = navController, + showTopBar = true, + titleTopBar = stringResource(R.string.label_new_task), + showBottomBarNavigation = true, + contentToUse = { paddingValues -> + Image( + painter = painterResource(R.drawable.rastro), + contentDescription = null, + modifier = Modifier + .fillMaxSize() + .offset(y = 300.sdp) + ) + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), + content = { + item { + GroupSelectableButton( + listOfTasks, + onSelection = { + + } + ) + } + item { + InputText( + modifier = Modifier.testTag("inputFieldTag"), + placeholderText = stringResource(R.string.enter_task_name_here), + titleText = stringResource(R.string.task_name), + textValue = nameTask.value, + onEvent = { t -> + nameTask.value = t + + }, + ) + } + item { + TextFieldCustom( + title = stringResource(R.string.label_description), + placeholder = stringResource(R.string.enter_the_task_description_here), + value = desc.value, + onValueChange = { d -> + desc.value = d + } + ) + } + item { + PetFilterList( + listPet, + onSelectedPet = { + + } + ) + } + item { + Column { + TransactionTypeSelector( + onSelectionChanged = { type -> + selectedType = type } ) - } - item { - PetFilterList( - listPet, - onSelectedPet = {} - ) - } - item { - Column { - TransactionTypeSelector( - onSelectionChanged = { type -> - selectedType = type - } - ) - - when (selectedType) { - TransactionType.Recurrent -> Text(text = "Recorrente") - TransactionType.OneOff -> Text(text = "Pontual") - null -> {} + + when (selectedType) { + TransactionType.Recurrent -> { + RecurringTask( + setOf(), + onAmPmSelector = { + + }, + onTime = { hour, minute -> + + }, + onWeekDaySelected = { + + }, + onDaySelected = { + + } + ) } - } - } - item { - TextFieldCustom( - title = "Observação", - placeholder = "Digite aqui a sua observação", - value = desc.value, - onValueChange = { d -> - desc.value = d + + TransactionType.OneOff -> { + OneOffTask( + onDateSelected = { + + }, + onAmPmSelector = { + + }, + onTime = { hour, minute -> + + } + ) } - ) + + null -> {} + } } } - ) - } - ) - } + item { + TextFieldCustom( + title = stringResource(R.string.label_observation), + placeholder = stringResource(R.string.enter_your_observation_here), + value = ob.value, + onValueChange = { o -> + ob.value = o + } + ) + } + item { + Button3(submit = { /*TODO*/ }, enableButton = true, text = stringResource(R.string.label_save_task)) + } + } + ) + } + ) } @Preview(showBackground = true, showSystemUi = true, device = "id:pixel_4_xl") From 45bf5b27787b560f4fc8e438fc6e33646617f3db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20Oliveira=20Sim=C3=A3o?= Date: Sat, 30 Aug 2025 15:14:09 -0400 Subject: [PATCH 53/64] Test: Add UI tests for ScreenRegisterTask components --- .../components/ScreenRegisterTaskTest.kt | 360 ++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 petJournal/app/src/androidTest/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTaskTest.kt diff --git a/petJournal/app/src/androidTest/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTaskTest.kt b/petJournal/app/src/androidTest/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTaskTest.kt new file mode 100644 index 00000000..b8fe2ad3 --- /dev/null +++ b/petJournal/app/src/androidTest/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTaskTest.kt @@ -0,0 +1,360 @@ +package com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen.components + +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.hasSetTextAction +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performTextInput +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.soujunior.petjournal.ui.components.GroupSelectableButton +import com.soujunior.petjournal.ui.components.InputText +import com.soujunior.petjournal.ui.components.PetFilterList +import com.soujunior.petjournal.ui.components.Pets +import com.soujunior.petjournal.ui.components.SelectableButtonInfo +import com.soujunior.petjournal.ui.components.TextFieldCustom +import com.soujunior.petjournal.ui.components.TransactionTypeSelector +import com.soujunior.petjournal.ui.components.task.OneOffTask +import com.soujunior.petjournal.ui.components.task.RecurringTask +import com.soujunior.petjournal.ui.theme.ColorCustom +import com.soujunior.petjournal.ui.util.TransactionType +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class ScreenRegisterTaskTest { + + @get:Rule + val composeTestRule = createComposeRule() + + private val pets = listOf( + Pets(id = 1, name = "Rex"), + Pets(id = 2, name = "Mia"), + Pets(id = 3, name = "Thor") + ) + + private val sampleListOfTasks = listOf( + SelectableButtonInfo("Vacinas", ColorCustom.color_selectable_button_1), + SelectableButtonInfo("Consultas", ColorCustom.color_selectable_button_2), + SelectableButtonInfo("Remédios", ColorCustom.color_selectable_button_3) + ) + + @Test + fun groupSelectableButton_displaysTitleCorrectly() { + composeTestRule.setContent { + GroupSelectableButton( + listOfTasks = sampleListOfTasks, + onSelection = {} + ) + } + + composeTestRule.onNodeWithText("Essa tarefa é...") + .assertIsDisplayed() + } + + @Test + fun groupSelectableButton_displaysAllButtons() { + composeTestRule.setContent { + GroupSelectableButton( + listOfTasks = sampleListOfTasks, + onSelection = {} + ) + } + + sampleListOfTasks.forEach { buttonInfo -> + composeTestRule.onNodeWithText(buttonInfo.title).assertIsDisplayed() + } + } + + @Test + fun groupSelectableButton_selectsAndDeselectsButtonCorrectly() { + composeTestRule.setContent { + GroupSelectableButton( + listOfTasks = sampleListOfTasks, + onSelection = {} + ) + } + + val firstButton = sampleListOfTasks[0] + + composeTestRule.onNodeWithText(firstButton.title).performClick() + + composeTestRule.onNodeWithText(firstButton.title).performClick() + } + + @Test + fun groupSelectableButton_selectsOnlyOneButtonAtATime_ifLogicImpliesThat() { + composeTestRule.setContent { + GroupSelectableButton( + listOfTasks = sampleListOfTasks, + onSelection = {} + ) + } + + val firstButton = sampleListOfTasks[0] + val secondButton = sampleListOfTasks[1] + + composeTestRule.onNodeWithText(firstButton.title).performClick() + + composeTestRule.onNodeWithText(secondButton.title).performClick() + + } + + @Test + fun inputText_displaysTitleCorrectly() { + val testTitle = "Nome da Tarefa" + composeTestRule.setContent { + InputText( + titleText = testTitle, + textValue = "", + onEvent = {} + ) + } + + composeTestRule.onNodeWithText(testTitle).assertIsDisplayed() + } + + @Test + fun inputText_displaysPlaceholder_whenTextValueIsEmptyAndNotMasked() { + val testPlaceholder = "Digite o nome da tarefa" + composeTestRule.setContent { + InputText( + placeholderText = testPlaceholder, + textValue = "", + onEvent = {}, + hasAMask = false + ) + } + + composeTestRule.onNodeWithText(testPlaceholder).assertIsDisplayed() + } + + @Test + fun inputText_doesNotDisplayPlaceholder_whenTextValueIsNotEmpty() { + val testPlaceholder = "Digite o nome da tarefa" + composeTestRule.setContent { + InputText( + placeholderText = testPlaceholder, + textValue = "Minha Tarefa", + onEvent = {}, + hasAMask = false + ) + } + + composeTestRule.onNodeWithText(testPlaceholder).assertDoesNotExist() + } + + @Test + fun inputText_displaysErrorMessages_whenTextErrorIsProvided() { + val errorMessages = listOf("Nome muito curto", "Nome inválido") + composeTestRule.setContent { + InputText( + textValue = "Ops", + onEvent = {}, + isError = true, + textError = errorMessages + ) + } + errorMessages.forEach { errorMessage -> + composeTestRule.onNodeWithText(errorMessage).assertIsDisplayed() + } + } + + private val title = "Descrição" + private val placeholder = "Digite a descrição aqui..." + + @Test + fun shouldDisplayTitleAndPlaceholder() { + composeTestRule.setContent { + TextFieldCustom( + title = title, + placeholder = placeholder, + value = "", + onValueChange = {} + ) + } + + composeTestRule.onNodeWithText(title).assertIsDisplayed() + + composeTestRule.onNodeWithText(placeholder).assertIsDisplayed() + } + + @Test + fun shouldUpdateTextWhenTyping() { + var textValue = "" + composeTestRule.setContent { + TextFieldCustom( + title = title, + placeholder = placeholder, + value = textValue, + onValueChange = { textValue = it } + ) + } + + val inputText = "Descrição do produto" + + composeTestRule.onNode( + hasSetTextAction() + ).performTextInput(inputText) + + assert(textValue == inputText) + } + + @Test + fun shouldDisplayTitleAndAllOption() { + composeTestRule.setContent { + PetFilterList(listPet = pets) + } + + composeTestRule.onNodeWithText("Quais pets precisam dessa tarefa?").assertIsDisplayed() + + composeTestRule.onNodeWithText("Todos").assertIsDisplayed() + } + + @Test + fun shouldDisplayAllPetsFromList() { + composeTestRule.setContent { + PetFilterList(listPet = pets) + } + + pets.forEach { pet -> + composeTestRule.onNodeWithText(pet.name!!).assertIsDisplayed() + } + } + + @Test + fun shouldSelectAndUnselectPet() { + var selected: String? = null + composeTestRule.setContent { + PetFilterList( + listPet = pets, + onSelectedPet = { selected = it } + ) + } + + composeTestRule.onNodeWithText("Rex").performClick() + assert(selected == "Rex") + + composeTestRule.onNodeWithText("Rex").performClick() + assert(selected == "") + } + + @Test + fun shouldSelectAllOption() { + var selected: String? = null + composeTestRule.setContent { + PetFilterList( + listPet = pets, + onSelectedPet = { selected = it } + ) + } + + composeTestRule.onNodeWithText("Todos").performClick() + assert(selected == "Todos") + + composeTestRule.onNodeWithText("Todos").performClick() + assert(selected == "") + } + + @Test + fun shouldShowRecurringTaskWhenRecurrentSelected() { + composeTestRule.setContent { + var selectedType: TransactionType? = null + + Column { + TransactionTypeSelector( + onSelectionChanged = { type -> + selectedType = type + } + ) + + when (selectedType) { + TransactionType.Recurrent -> { + RecurringTask( + setOf(), + onAmPmSelector = {}, + onTime = { _, _ -> }, + onWeekDaySelected = {}, + onDaySelected = {} + ) + } + + TransactionType.OneOff -> { + OneOffTask( + onDateSelected = {}, + onAmPmSelector = {}, + onTime = { _, _ -> } + ) + } + + null -> {} + } + } + } + + composeTestRule.onNodeWithText("Recorrente").performClick() + } + + @Test + fun shouldShowOneOffTaskWhenOneOffSelected() { + composeTestRule.setContent { + var selectedType: TransactionType? = null + + Column { + TransactionTypeSelector( + onSelectionChanged = { type -> + selectedType = type + } + ) + + when (selectedType) { + TransactionType.Recurrent -> { + RecurringTask( + setOf(), + onAmPmSelector = {}, + onTime = { _, _ -> }, + onWeekDaySelected = {}, + onDaySelected = {} + ) + } + + TransactionType.OneOff -> { + OneOffTask( + onDateSelected = {}, + onAmPmSelector = {}, + onTime = { _, _ -> } + ) + } + + null -> {} + } + } + } + + composeTestRule.onNodeWithText("Pontual").performClick() + } + + @Test + fun shouldUpdateObservationText() { + composeTestRule.setContent { + val ob = remember { mutableStateOf("") } + + TextFieldCustom( + title = "Observação", + placeholder = "Digite aqui a sua observação", + value = ob.value, + onValueChange = { ob.value = it }, + ) + } + + composeTestRule.onNodeWithText("Digite aqui a sua observação").assertIsDisplayed() + + val text = "Precisa dar o remédio às 14h" + composeTestRule.onNodeWithText("Digite aqui a sua observação").performTextInput(text) + } + +} \ No newline at end of file From c3b26bd5724f7ad62d803237a9e6c093a9b625b8 Mon Sep 17 00:00:00 2001 From: Gustavo Oliveira <42920754+gusoliveira21@users.noreply.github.com> Date: Wed, 29 Oct 2025 01:42:56 -0300 Subject: [PATCH 54/64] feat(ui): improve UI components styling and functionality - Update ActiveMonthsComponent with better styling - Enhance DateInputText component layout - Refactor DropDown component structure - Remove title text from DualActionButton for cleaner design - Improve InputText component with better padding and layout - Update NavigationBarItems styling These changes enhance the overall UI consistency and user experience. --- .../ui/components/ActiveMonthsComponent.kt | 6 ++++-- .../petjournal/ui/components/DateInputText.kt | 5 +++-- .../petjournal/ui/components/DropDown.kt | 5 ++--- .../ui/components/DualActionButton.kt | 13 ------------- .../petjournal/ui/components/InputText.kt | 18 ++++++++++-------- .../ui/components/NavigationBarItems.kt | 2 +- 6 files changed, 20 insertions(+), 29 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/ActiveMonthsComponent.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/ActiveMonthsComponent.kt index 5a83c5b6..36ad6244 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/ActiveMonthsComponent.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/ActiveMonthsComponent.kt @@ -74,7 +74,8 @@ fun ActiveMonthsComponent(activeMonths: Set) { Text( text = month, style = MaterialTheme.typography.labelLarge, - color = if (isActive) MaterialTheme.colorScheme.onPrimary else ColorCustom.color_border_dialog, + //todo: corrigir ColorCustom.color_border_dialog, + color = if (isActive) MaterialTheme.colorScheme.onPrimary else ColorCustom.error_color, fontWeight = FontWeight(400) ) } @@ -104,7 +105,8 @@ fun ActiveMonthsComponent(activeMonths: Set) { ) { Text( text = month, - color = if (isActive) MaterialTheme.colorScheme.onPrimary else ColorCustom.color_border_dialog, + //todo: corrigir ColorCustom.color_border_dialog, + color = if (isActive) MaterialTheme.colorScheme.onPrimary else ColorCustom.error_color, fontWeight = FontWeight(400) ) } diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DateInputText.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DateInputText.kt index e1d48763..9221ee6d 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DateInputText.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DateInputText.kt @@ -47,6 +47,7 @@ import ir.kaaveh.sdpcompose.ssp @Composable fun DateInputText( modifier: Modifier = Modifier, + textTitleModifier: Modifier = Modifier, textInputModifier: Modifier = Modifier, placeholderText: String = "Placeholder", titleText: String = "Title", @@ -67,9 +68,9 @@ fun DateInputText( color = MaterialTheme.colorScheme.scrim, style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight(500), - modifier = Modifier + modifier = textTitleModifier .fillMaxWidth() - .padding(start = 24.sdp, end = 24.sdp) + .padding(end = 24.sdp) ) } Row { diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DropDown.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DropDown.kt index e9dbf7e8..c75537cc 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DropDown.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DropDown.kt @@ -47,6 +47,7 @@ import ir.kaaveh.sdpcompose.sdp @Composable fun DropDown( modifier: Modifier = Modifier, + textTitleModifier: Modifier = Modifier, textInputModifier: Modifier = Modifier, placeholderText: String = "Porte do seu pet", titleText: String = "Title", @@ -66,9 +67,7 @@ fun DropDown( color = MaterialTheme.colorScheme.scrim, style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight(500), - modifier = Modifier - .fillMaxWidth() - .padding(start = 24.sdp, end = 24.sdp) + modifier = textTitleModifier.fillMaxWidth().padding(end = 24.sdp) ) } Row { diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DualActionButton.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DualActionButton.kt index 5e752de0..d99f56ba 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DualActionButton.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/DualActionButton.kt @@ -43,20 +43,7 @@ fun DualActionButton( rightButtonTextColor: Color = MaterialTheme.colorScheme.primary, isLoading: Boolean = false ) { - Column(modifier = modifier) { - Row { - Text( - text = titleText, - textAlign = TextAlign.Start, - color = MaterialTheme.colorScheme.scrim, - style = MaterialTheme.typography.bodyMedium, - fontWeight = FontWeight(500), - modifier = Modifier - .fillMaxWidth() - .padding(start = 24.sdp, end = 24.sdp) - ) - } Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt index 7e210fdb..687a2d50 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt @@ -39,6 +39,7 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.soujunior.petjournal.R import com.soujunior.petjournal.ui.theme.ColorCustom @@ -59,11 +60,12 @@ fun InputText( onEvent: (String) -> Unit, hasAMask: Boolean = false, keyboardOptions: KeyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Text), - visualTransformation: VisualTransformation = VisualTransformation.None + visualTransformation: VisualTransformation = VisualTransformation.None, + textTitleModifier: Modifier = Modifier ) { var showPassword by remember { mutableStateOf(false) } - Column(modifier = modifier.padding(16.dp)) { + Column(modifier = modifier) { Row { Text( text = titleText, @@ -71,7 +73,7 @@ fun InputText( color = MaterialTheme.colorScheme.scrim, fontWeight = FontWeight(500), style = MaterialTheme.typography.titleMedium, - modifier = modifier + modifier = textTitleModifier .fillMaxWidth() ) } @@ -88,7 +90,7 @@ fun InputText( color = MaterialTheme.colorScheme.surface, shape = RoundedCornerShape(size = 12.dp) ) - .padding(2.sdp) + .padding(0.sdp) .fillMaxWidth() .testTag("inputField_test") .drawBehind { @@ -119,16 +121,16 @@ fun InputText( else PasswordVisualTransformation() } else visualTransformation, keyboardOptions = keyboardOptions, - decorationBox = { + decorationBox = { innerTextField -> Row( modifier = Modifier - .background(Color.White) - .padding(start = 14.sdp), + .padding(horizontal = 14.sdp), verticalAlignment = Alignment.CenterVertically ) { Box( modifier = Modifier.weight(1f) ) { + innerTextField() if (textValue.isEmpty() && !hasAMask) { Text( text = placeholderText, @@ -188,5 +190,5 @@ fun InputText( @Preview(showBackground = true, showSystemUi = false, device = "id:pixel_4_xl") @Composable fun InputTextPreview() { - InputText(Modifier, onEvent = {}, textValue = "") + InputText(textValue = "", onEvent = {},) } \ No newline at end of file diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/NavigationBarItems.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/NavigationBarItems.kt index 706ec91a..852d4803 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/NavigationBarItems.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/NavigationBarItems.kt @@ -25,7 +25,7 @@ sealed class NavigationBarItems( object Pets : NavigationBarItems( title = "Pets", - route = "pets/introRegisterPet", + route = "pets/petListScreen", icons = R.drawable.ic_pet, group = "pets" ) From 8e1a89cac00a241f7f25bb92852264c76df9b7d0 Mon Sep 17 00:00:00 2001 From: Gustavo Oliveira <42920754+gusoliveira21@users.noreply.github.com> Date: Wed, 29 Oct 2025 01:43:08 -0300 Subject: [PATCH 55/64] refactor(strings): update pet registration string label - Change 'Cadastro Pet' to 'Cadastro' for better UX - Simplifies the registration screen title --- petJournal/app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/petJournal/app/src/main/res/values/strings.xml b/petJournal/app/src/main/res/values/strings.xml index 631122de..6bcf5344 100644 --- a/petJournal/app/src/main/res/values/strings.xml +++ b/petJournal/app/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ PetJournal - Cadastro Pet + Cadastro Raças Nome Pequeno (6kg a 14kg) From 3af5ae58c8d06a0120181796cc11e3f592fb6782 Mon Sep 17 00:00:00 2001 From: Gustavo Oliveira <42920754+gusoliveira21@users.noreply.github.com> Date: Wed, 29 Oct 2025 01:43:14 -0300 Subject: [PATCH 56/64] fix(ui): apply temporary color fixes to TaskSuccessDialog - Replace missing ColorCustom properties with error_color as temporary solution - Add TODO comments for proper color implementation - Ensures dialog renders correctly while proper colors are being defined This is a temporary fix that should be replaced once proper color definitions are available. --- .../ui/components/TaskSuccessDialog.kt | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskSuccessDialog.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskSuccessDialog.kt index e8f3f655..35736250 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskSuccessDialog.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TaskSuccessDialog.kt @@ -51,10 +51,13 @@ fun TaskSuccessDialog( modifier = modifier .shadow( elevation = 3.dp, - spotColor = ColorCustom.color_shadow_dialog, - ambientColor = ColorCustom.color_shadow_dialog + //todo: Corrigir ColorCustom.color_shadow_dialog, + spotColor = ColorCustom.error_color, + //todo: Corrigir ColorCustom.color_shadow_dialog, + ambientColor = ColorCustom.error_color ) - .border(2.dp, ColorCustom.color_border_dialog, RoundedCornerShape(16.dp)) + //todo: Corrigir ColorCustom.color_border_dialog, + .border(2.dp, ColorCustom.error_color, RoundedCornerShape(16.dp)) .width(330.dp) .height(338.dp) .background( @@ -90,7 +93,8 @@ fun TaskSuccessDialog( .fillMaxWidth() .padding(start = 16.dp, end = 16.dp), onClick = onNewTaskClick, - border = BorderStroke(1.dp, ColorCustom.color_background_button_dialog), + //todo: Corrigir ColorCustom.color_background_button_dialog, + border = BorderStroke(1.dp, ColorCustom.error_color), shape = RoundedCornerShape(12.dp) ) { Icon( @@ -99,14 +103,16 @@ fun TaskSuccessDialog( .height(24.dp), imageVector = Icons.Default.Add, contentDescription = null, - tint = ColorCustom.color_background_button_dialog + //todo: Corrigir ColorCustom.color_background_button_dialog, + tint = ColorCustom.error_color ) Spacer(modifier = Modifier.width(8.dp)) Text( text = stringResource(R.string.label_new_task), style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight(600), - color = ColorCustom.color_border_dialog + //todo: Corrigir ColorCustom.color_border_dialog, + color = ColorCustom.error_color ) } @@ -115,7 +121,8 @@ fun TaskSuccessDialog( .fillMaxWidth() .padding(start = 16.dp, end = 16.dp, top = 6.dp), onClick = onGoToHomeClick, - colors = ButtonDefaults.buttonColors(containerColor = ColorCustom.color_border_dialog), + //todo: Corrigir ColorCustom.color_border_dialog, + colors = ButtonDefaults.buttonColors(containerColor = ColorCustom.error_color), shape = RoundedCornerShape(12.dp) ) { Text( From 26f131e848a4081819faf102b59f3b9dc0f46bac Mon Sep 17 00:00:00 2001 From: Gustavo Oliveira <42920754+gusoliveira21@users.noreply.github.com> Date: Wed, 29 Oct 2025 01:47:40 -0300 Subject: [PATCH 57/64] feat(ui): improve register pet screen layout and add preview components - Refactor layout structure with better spacing and padding - Add navigationBarsPadding for better screen adaptation - Improve LazyColumn arrangement with consistent spacing - Add individual title labels for DualActionButton components - Create comprehensive preview components for all form elements - Enhance component styling and MaterialTheme usage - Remove redundant padding and improve component organization This improves the overall user experience and developer preview capabilities. --- .../registerPetScreen/components/Screen.kt | 332 +++++++++++++----- 1 file changed, 250 insertions(+), 82 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerPetScreen/components/Screen.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerPetScreen/components/Screen.kt index 14208cc3..6e3a9ac8 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerPetScreen/components/Screen.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerPetScreen/components/Screen.kt @@ -4,14 +4,20 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.AbsoluteAlignment import androidx.compose.ui.Alignment @@ -20,6 +26,8 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.navigation.NavController import androidx.navigation.compose.rememberNavController @@ -39,7 +47,10 @@ import ir.kaaveh.sdpcompose.sdp fun Screen(navController: NavController) { Column(modifier = Modifier) { ScaffoldCustom( - modifier = Modifier, + modifier = Modifier + .navigationBarsPadding() + .fillMaxSize() + , navigationUp = navController, showTopBar = true, titleTopBar = stringResource(R.string.edit_pet_data), @@ -54,31 +65,25 @@ fun Screen(navController: NavController) { .offset(y = 300.sdp) .align(AbsoluteAlignment.Left) ) + LazyColumn( horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Top, + verticalArrangement = Arrangement.spacedBy(12.sdp), modifier = Modifier .fillMaxSize() .fillMaxHeight() - .padding( - top = it.calculateTopPadding() + 12.sdp, - bottom = it.calculateBottomPadding() + 2.sdp - ) + .padding(it) .background(Color.Transparent), + contentPadding = PaddingValues(horizontal = 24.sdp), content = { item { ImagePet() } item { InputText( - textInputModifier = Modifier - .testTag("inputField_test") - .padding( - start = 24.sdp, - end = 24.sdp, - bottom = 12.sdp, - top = 4.sdp - ), + modifier = Modifier, + textTitleModifier = Modifier.padding(bottom = 4.sdp), + textInputModifier = Modifier.testTag("inputField_test"), placeholderText = stringResource(R.string.placeholder_name_pet), titleText = stringResource(R.string.pet_name), textValue = "", @@ -87,12 +92,8 @@ fun Screen(navController: NavController) { } item { DropDown( - textInputModifier = Modifier.padding( - start = 24.sdp, - end = 24.sdp, - bottom = 12.sdp, - top = 4.sdp - ), + textInputModifier = Modifier, + textTitleModifier = Modifier.padding(bottom = 4.sdp), placeholderText = stringResource(R.string.placeholder_breed), titleText = stringResource(R.string.breed), textValue = "", @@ -101,12 +102,8 @@ fun Screen(navController: NavController) { } item { DropDown( - textInputModifier = Modifier.padding( - start = 24.sdp, - end = 24.sdp, - bottom = 12.sdp, - top = 4.sdp - ), + textInputModifier = Modifier, + textTitleModifier = Modifier.padding(bottom = 4.sdp), placeholderText = stringResource(R.string.placeholder_size), titleText = stringResource(R.string.size), textValue = "", @@ -115,44 +112,29 @@ fun Screen(navController: NavController) { } item { DateInputText( - textInputModifier = Modifier.padding( - start = 24.sdp, - end = 24.sdp, - bottom = 12.sdp, - top = 4.sdp - ), + textInputModifier = Modifier, + textTitleModifier = Modifier.padding(bottom = 4.sdp), titleText = stringResource(R.string.pet_birth_date), placeholderText = stringResource(R.string.placeholder_text_DD_MM_YYYY), textValue = "", onEvent = { }, - // Será necessário criar uma função para formatar a data -// visualTransformation = { date -> -// formatDate(date) -// } + // visualTransformation = { date -> + // formatDate(date) + // } ) } item { DropDown( - textInputModifier = Modifier.padding( - start = 24.sdp, - end = 24.sdp, - bottom = 12.sdp, - top = 4.sdp - ), - placeholderText = stringResource(R.string.placeholder_weight), - titleText = stringResource(R.string.weight), + textTitleModifier = Modifier.padding(bottom = 4.sdp), + placeholderText = stringResource(id = R.string.placeholder_weight), + titleText = stringResource(id = R.string.weight), textValue = "", onEvent = { } ) } item { DropDown( - textInputModifier = Modifier.padding( - start = 24.sdp, - end = 24.sdp, - bottom = 12.sdp, - top = 4.sdp - ), + textInputModifier = Modifier.padding(top = 4.sdp), placeholderText = stringResource(R.string.placeholder_type), titleText = stringResource(R.string.type), textValue = "", @@ -160,40 +142,58 @@ fun Screen(navController: NavController) { ) } item { - DualActionButton( - buttonModifier = Modifier.padding( - start = 32.sdp, - end = 24.sdp, - bottom = 32.sdp, - top = 8.sdp - ), - titleText = stringResource(R.string.pet_sex), - rightButtonSubmit = {}, - leftButtonSubmit = {}, - enableButton = true, - leftButtonText = stringResource(R.string.male), - rightButtonText = stringResource(R.string.female) - ) + Column{ + Row { + Text( + text = stringResource(R.string.pet_sex), + textAlign = TextAlign.Start, + color = MaterialTheme.colorScheme.scrim, + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight(500), + modifier = Modifier + .padding(bottom = 8.sdp) + .fillMaxWidth() + ) + } + DualActionButton( + buttonModifier = Modifier, + titleText = stringResource(R.string.pet_sex), + rightButtonSubmit = {}, + leftButtonSubmit = {}, + enableButton = true, + leftButtonText = stringResource(R.string.male), + rightButtonText = stringResource(R.string.female) + ) + } } item { - DualActionButton( - buttonModifier = Modifier.padding( - start = 32.sdp, - end = 24.sdp, - bottom = 32.sdp, - top = 8.sdp - ), - titleText = stringResource(R.string.castrated), - rightButtonSubmit = {}, - leftButtonSubmit = {}, - enableButton = true, - leftButtonText = stringResource(R.string.yes), - rightButtonText = stringResource(R.string.no), - leftButtonColor = ButtonDefaults.buttonColors(androidx.compose.material3.MaterialTheme.colorScheme.background), - rightButtonColor = ButtonDefaults.buttonColors(androidx.compose.material3.MaterialTheme.colorScheme.primary), - leftButtonTextColor = androidx.compose.material3.MaterialTheme.colorScheme.primary, - rightButtonTextColor = androidx.compose.material3.MaterialTheme.colorScheme.onPrimary, - ) + Column{ + Row { + Text( + text = stringResource(R.string.pet_registration), + textAlign = TextAlign.Start, + color = MaterialTheme.colorScheme.scrim, + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight(500), + modifier = Modifier + .padding(bottom = 8.sdp) + .fillMaxWidth() + ) + } + DualActionButton( + buttonModifier = Modifier, + titleText = stringResource(R.string.castrated), + rightButtonSubmit = {}, + leftButtonSubmit = {}, + enableButton = true, + leftButtonText = stringResource(R.string.yes), + rightButtonText = stringResource(R.string.no), + leftButtonColor = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.background), + rightButtonColor = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.primary), + leftButtonTextColor = MaterialTheme.colorScheme.primary, + rightButtonTextColor = MaterialTheme.colorScheme.onPrimary, + ) + } } item { Spacer(modifier = Modifier.height(20.sdp)) @@ -222,4 +222,172 @@ fun ScreenPreview() { Screen(nav) } ) +} + +@Preview(showBackground = true) +@Composable +fun InputTextPreview() { + PetJournalTheme { + InputText( + modifier = Modifier, + textTitleModifier = Modifier.padding(bottom = 4.sdp), + textInputModifier = Modifier.testTag("inputField_test"), + placeholderText = stringResource(R.string.placeholder_name_pet), + titleText = stringResource(R.string.pet_name), + textValue = "", + onEvent = { } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun DropDownBreedPreview() { + PetJournalTheme { + DropDown( + textInputModifier = Modifier, + textTitleModifier = Modifier.padding(bottom = 4.sdp), + placeholderText = stringResource(R.string.placeholder_breed), + titleText = stringResource(R.string.breed), + textValue = "", + onEvent = { } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun DropDownSizePreview() { + PetJournalTheme { + DropDown( + textInputModifier = Modifier, + textTitleModifier = Modifier.padding(bottom = 4.sdp), + placeholderText = stringResource(R.string.placeholder_size), + titleText = stringResource(R.string.size), + textValue = "", + onEvent = { } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun DateInputTextPreview() { + PetJournalTheme { + DateInputText( + textInputModifier = Modifier, + textTitleModifier = Modifier.padding(bottom = 4.sdp), + titleText = stringResource(R.string.pet_birth_date), + placeholderText = stringResource(R.string.placeholder_text_DD_MM_YYYY), + textValue = "", + onEvent = { }, + // visualTransformation = { date -> + // formatDate(date) + // } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun DropDownWeightPreview() { + PetJournalTheme { + DropDown( + textTitleModifier = Modifier.padding(bottom = 4.sdp), + placeholderText = stringResource(id = R.string.placeholder_weight), + titleText = stringResource(id = R.string.weight), + textValue = "", + onEvent = { } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun DropDownTypePreview() { + PetJournalTheme { + DropDown( + textInputModifier = Modifier.padding(top = 4.sdp), + placeholderText = stringResource(R.string.placeholder_type), + titleText = stringResource(R.string.type), + textValue = "", + onEvent = { } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun DualActionSexPreview() { + PetJournalTheme { + Column{ + Row { + Text( + text = stringResource(R.string.pet_sex), + textAlign = TextAlign.Start, + color = MaterialTheme.colorScheme.scrim, + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight(500), + modifier = Modifier + .padding(bottom = 8.sdp) + .fillMaxWidth() + ) + } + DualActionButton( + buttonModifier = Modifier, + titleText = stringResource(R.string.pet_sex), + rightButtonSubmit = {}, + leftButtonSubmit = {}, + enableButton = true, + leftButtonText = stringResource(R.string.male), + rightButtonText = stringResource(R.string.female) + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun DualActionCastratedPreview() { + PetJournalTheme { + Column{ + Row { + Text( + text = stringResource(R.string.pet_registration), + textAlign = TextAlign.Start, + color = MaterialTheme.colorScheme.scrim, + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight(500), + modifier = Modifier + .padding(bottom = 8.sdp) + .fillMaxWidth() + ) + } + DualActionButton( + buttonModifier = Modifier, + titleText = stringResource(R.string.castrated), + rightButtonSubmit = {}, + leftButtonSubmit = {}, + enableButton = true, + leftButtonText = stringResource(R.string.yes), + rightButtonText = stringResource(R.string.no), + leftButtonColor = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.background), + rightButtonColor = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.primary), + leftButtonTextColor = MaterialTheme.colorScheme.primary, + rightButtonTextColor = MaterialTheme.colorScheme.onPrimary, + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun Button3SavePreview() { + PetJournalTheme { + Button3( + submit = {}, + enableButton = true, + text = stringResource(R.string.save) + ) + } } \ No newline at end of file From 72a80bfd38993af74f696d271d8155d0f87cd64e Mon Sep 17 00:00:00 2001 From: Gustavo Oliveira <42920754+gusoliveira21@users.noreply.github.com> Date: Wed, 29 Oct 2025 01:47:48 -0300 Subject: [PATCH 58/64] fix(navigation): update pet list route and add navigation functionality - Update NavHostElements route from 'pets/petList' to 'pets/petListScreen' - Add navigation functionality to PetItemMore component - Connect pet list screen to register pet screen navigation - Remove commented navigation route This ensures proper navigation flow between pet list and registration screens. --- .../com/soujunior/petjournal/navigation/NavHostElements.kt | 3 +-- .../screens_pets/petListScreen/components/Screen.kt | 6 +++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/NavHostElements.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/NavHostElements.kt index 75918754..c9a1715d 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/NavHostElements.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/NavHostElements.kt @@ -55,8 +55,7 @@ fun NavHostMainContent() { composable("account_manager") { AccountManager() } composable("tutorScreen") { TutorScreen(navController) } composable("pets/introRegisterPet") { IntroRegisterPetScreen(navController) } -// composable("pets/introRegisterPet") { RegisterPetScreen(navController) } - composable("pets/petList") { PetListScreen(navController) } + composable("pets/petListScreen") { PetListScreen(navController) } composable("pets/registerPet") { RegisterPetScreen(navController) } composable("pets/speciesChoice") { SpeciesChoiceScreen(navController) } diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/petListScreen/components/Screen.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/petListScreen/components/Screen.kt index 4f1221b5..64061903 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/petListScreen/components/Screen.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/petListScreen/components/Screen.kt @@ -141,7 +141,11 @@ fun Screen(navController: NavController) { ) } item { - PetItemMore(onClick = {}) + PetItemMore( + onClick = { + navController.navigate("pets/registerPet") + } + ) } } From 511af56d9066a20af4341fca3b2a4c8b7e28923e Mon Sep 17 00:00:00 2001 From: Gustavo Oliveira <42920754+gusoliveira21@users.noreply.github.com> Date: Wed, 29 Oct 2025 01:48:03 -0300 Subject: [PATCH 59/64] fix(test): correct parameter order in RegisterPetScreenTest - Fix parameter order in InputText test components - Ensure consistent parameter ordering for better test reliability - Update test structure to match component interface changes This improves test consistency and prevents parameter order issues. --- .../petjournal/screen_pets/RegisterPetScreenTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/petJournal/app/src/androidTest/java/com/soujunior/petjournal/screen_pets/RegisterPetScreenTest.kt b/petJournal/app/src/androidTest/java/com/soujunior/petjournal/screen_pets/RegisterPetScreenTest.kt index 8c302940..a1f83870 100644 --- a/petJournal/app/src/androidTest/java/com/soujunior/petjournal/screen_pets/RegisterPetScreenTest.kt +++ b/petJournal/app/src/androidTest/java/com/soujunior/petjournal/screen_pets/RegisterPetScreenTest.kt @@ -60,10 +60,10 @@ class RegisterPetScreenTest { composeTestRule.setContent { InputText( - titleText = stringResource(R.string.pet_name), placeholderText = stringResource(R.string.placeholder_name_pet), + titleText = stringResource(R.string.pet_name), textValue = actualText, - onEvent = { actualText = it } + onEvent = { actualText = it }, ) } @@ -81,9 +81,9 @@ class RegisterPetScreenTest { InputText( titleText = stringResource(R.string.pet_name), textValue = "", - onEvent = {}, isError = true, textError = listOf(errorMessage), + onEvent = {}, ) } From a8d8f5e8ee40539cac313c5434175e0c44047487 Mon Sep 17 00:00:00 2001 From: Gustavo Oliveira <42920754+gusoliveira21@users.noreply.github.com> Date: Thu, 6 Nov 2025 01:45:45 -0300 Subject: [PATCH 60/64] test(deps): add mockk-android dependency for android tests --- petJournal/app/build.gradle.kts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/petJournal/app/build.gradle.kts b/petJournal/app/build.gradle.kts index 567b704f..c312105e 100644 --- a/petJournal/app/build.gradle.kts +++ b/petJournal/app/build.gradle.kts @@ -120,7 +120,8 @@ dependencies { androidTestImplementation("androidx.test:runner:1.5.2") androidTestImplementation("androidx.arch.core:core-testing:2.1.0") - testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.2") + androidTestImplementation("io.mockk:mockk-android:1.12.0") + androidTestImplementation("io.mockk:mockk-agent:1.12.0") testImplementation("junit:junit:4.13.2") testImplementation("io.mockk:mockk:1.12.0") testImplementation("com.willowtreeapps.assertk:assertk-jvm:0.25") From 0ce481f1292636f5fd03d47547086e1558c1b0ff Mon Sep 17 00:00:00 2001 From: Gustavo Oliveira <42920754+gusoliveira21@users.noreply.github.com> Date: Thu, 6 Nov 2025 01:45:48 -0300 Subject: [PATCH 61/64] test(ui): add PetFilterList tests and expand ScreenRegisterTask tests --- .../componentes/PetFilterListTest.kt | 90 +++++++++++++++++++ .../components/ScreenRegisterTaskTest.kt | 77 ++++++++++++++-- 2 files changed, 162 insertions(+), 5 deletions(-) create mode 100644 petJournal/app/src/androidTest/java/com/soujunior/petjournal/componentes/PetFilterListTest.kt diff --git a/petJournal/app/src/androidTest/java/com/soujunior/petjournal/componentes/PetFilterListTest.kt b/petJournal/app/src/androidTest/java/com/soujunior/petjournal/componentes/PetFilterListTest.kt new file mode 100644 index 00000000..359d3c7f --- /dev/null +++ b/petJournal/app/src/androidTest/java/com/soujunior/petjournal/componentes/PetFilterListTest.kt @@ -0,0 +1,90 @@ +package com.soujunior.petjournal.componentes + +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.hasParent +import androidx.compose.ui.test.hasTestTag +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.performClick +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +import androidx.compose.ui.res.painterResource +import com.soujunior.petjournal.R // Para carregar imagens de preview +import com.soujunior.petjournal.ui.components.PetFilterList +import com.soujunior.petjournal.ui.components.Pets +import io.mockk.mockk +import org.mockito.Mockito.verify + +@RunWith(AndroidJUnit4::class) +class PetFilterListTest { + + @get:Rule + val composeTestRule = createComposeRule() + + private val mockOnSelectedPet: (String) -> Unit = mockk(relaxed = true) + + private val dummyPetList = listOf( + Pets( + id = 1, + imageRes = null, + name = "Jujuba" + ), + Pets( + id = 2, + imageRes = null, + name = "Alfredo" + ) + ) + + @Before + fun setUp() { + composeTestRule.setContent { + val listWithPainters = dummyPetList.map { + it.copy(imageRes = painterResource(id = R.drawable.penguim)) + } + + PetFilterList( + listPet = listWithPainters, + onSelectedPet = mockOnSelectedPet + ) + } + } + + @Test + fun test_PetFilterList_DisplaysItems() { + composeTestRule.onNodeWithTag("PetItem_Todos").assertIsDisplayed() + composeTestRule.onNodeWithTag("PetItem_Jujuba").assertIsDisplayed() + composeTestRule.onNodeWithTag("PetItem_Alfredo").assertIsDisplayed() + } + + @Test + fun test_PetFilterList_SelectsAndDeselectsPet() { + val jujubaSelectedIconMatcher = + hasParent(hasTestTag("PetItem_Jujuba")) and hasTestTag("SelectedIcon") + + composeTestRule.onNode(jujubaSelectedIconMatcher).assertDoesNotExist() + + composeTestRule.onNodeWithTag("PetItem_Jujuba").performClick() + + composeTestRule.onNode(jujubaSelectedIconMatcher).assertIsDisplayed() + + composeTestRule.onNodeWithTag("PetItem_Jujuba").performClick() + + composeTestRule.onNode(jujubaSelectedIconMatcher).assertDoesNotExist() + } + + @Test + fun test_PetFilterList_CallbackIsCalledOnSelection() { + composeTestRule.onNodeWithTag("PetItem_Alfredo").performClick() + + verify { mockOnSelectedPet("Alfredo") } + + composeTestRule.onNodeWithTag("PetItem_Todos").performClick() + + verify { mockOnSelectedPet("Todos") } + } +} \ No newline at end of file diff --git a/petJournal/app/src/androidTest/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTaskTest.kt b/petJournal/app/src/androidTest/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTaskTest.kt index b8fe2ad3..1970ae55 100644 --- a/petJournal/app/src/androidTest/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTaskTest.kt +++ b/petJournal/app/src/androidTest/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTaskTest.kt @@ -1,11 +1,15 @@ package com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen.components +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.hasSetTextAction import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTextInput @@ -111,7 +115,7 @@ class ScreenRegisterTaskTest { InputText( titleText = testTitle, textValue = "", - onEvent = {} + onEvent = {}, ) } @@ -126,7 +130,6 @@ class ScreenRegisterTaskTest { placeholderText = testPlaceholder, textValue = "", onEvent = {}, - hasAMask = false ) } @@ -141,7 +144,6 @@ class ScreenRegisterTaskTest { placeholderText = testPlaceholder, textValue = "Minha Tarefa", onEvent = {}, - hasAMask = false ) } @@ -154,9 +156,9 @@ class ScreenRegisterTaskTest { composeTestRule.setContent { InputText( textValue = "Ops", - onEvent = {}, isError = true, - textError = errorMessages + textError = errorMessages, + onEvent = {}, ) } errorMessages.forEach { errorMessage -> @@ -299,6 +301,61 @@ class ScreenRegisterTaskTest { composeTestRule.onNodeWithText("Recorrente").performClick() } + @Test + fun test_TransactionTypeSelector_TogglesConditionalUI_Correctly() { + + composeTestRule.setContent { + var selectedType: TransactionType? = null + + Column { + TransactionTypeSelector( + onSelectionChanged = { type -> + selectedType = type + } + ) + + when (selectedType) { + TransactionType.Recurrent -> { + Box(modifier = Modifier.testTag("RecurringTaskComponent")) { + RecurringTask( + setOf(), + onAmPmSelector = {}, + onTime = { _, _ -> }, + onWeekDaySelected = {}, + onDaySelected = {} + ) + } + } + + TransactionType.OneOff -> { + Box(modifier = Modifier.testTag("OneOffTaskComponent")) { + OneOffTask( + onDateSelected = {}, + onAmPmSelector = {}, + onTime = { _, _ -> } + ) + } + } + + null -> {} + } + } + } + + composeTestRule.onNodeWithTag("RecurringTaskComponent").assertDoesNotExist() + composeTestRule.onNodeWithTag("OneOffTaskComponent").assertDoesNotExist() + + composeTestRule.onNodeWithTag("TaskRecurrent").performClick() + + composeTestRule.onNodeWithTag("RecurringTaskComponent").assertIsDisplayed() + composeTestRule.onNodeWithTag("OneOffTaskComponent").assertDoesNotExist() + + composeTestRule.onNodeWithTag("TaskOneOff").performClick() + + composeTestRule.onNodeWithTag("RecurringTaskComponent").assertDoesNotExist() + composeTestRule.onNodeWithTag("OneOffTaskComponent").assertIsDisplayed() + } + @Test fun shouldShowOneOffTaskWhenOneOffSelected() { composeTestRule.setContent { @@ -357,4 +414,14 @@ class ScreenRegisterTaskTest { composeTestRule.onNodeWithText("Digite aqui a sua observação").performTextInput(text) } + @Test + fun test_TransactionTypeSelector_ShowsConditionalUI() { + composeTestRule.onNodeWithTag("RecurringTaskComponent").assertDoesNotExist() + + composeTestRule.onNodeWithTag("TaskRecurrent").performClick() + + composeTestRule.onNodeWithTag("RecurringTaskComponent").assertIsDisplayed() + composeTestRule.onNodeWithTag("OneOffTaskComponent").assertDoesNotExist() + } + } \ No newline at end of file From c4f3b6a5dd9f527279658fdf47a23445d58f022b Mon Sep 17 00:00:00 2001 From: Gustavo Oliveira <42920754+gusoliveira21@users.noreply.github.com> Date: Thu, 6 Nov 2025 01:45:52 -0300 Subject: [PATCH 62/64] refactor(ui): improve UI components with spacing and test tags --- .../petjournal/ui/components/InputText.kt | 4 +-- .../ui/components/PeriodSelector.kt | 1 + .../ui/components/PetSelectorItem.kt | 32 ++++++++++++++++--- .../ui/components/SelectableButtonData.kt | 32 ++++++++++--------- .../ui/components/TextFieldCustom.kt | 1 - .../ui/components/TransactionTypeSelector.kt | 4 +-- .../ui/components/clock/WheelTimePicker.kt | 3 +- .../ui/components/task/OneOffTask.kt | 2 +- .../ui/components/task/RecurrentTask.kt | 8 +++-- .../registerPetScreen/components/Screen.kt | 3 +- 10 files changed, 58 insertions(+), 32 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt index 687a2d50..d200d00e 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/InputText.kt @@ -6,6 +6,7 @@ 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.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -27,7 +28,6 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.shadow import androidx.compose.ui.geometry.CornerRadius -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource @@ -39,7 +39,6 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.soujunior.petjournal.R import com.soujunior.petjournal.ui.theme.ColorCustom @@ -77,6 +76,7 @@ fun InputText( .fillMaxWidth() ) } + Spacer(modifier = Modifier.height(8.dp)) Row { BasicTextField( modifier = textInputModifier diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PeriodSelector.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PeriodSelector.kt index f20a537e..8f79e586 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PeriodSelector.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PeriodSelector.kt @@ -56,6 +56,7 @@ fun PeriodSelector( @Composable fun TriangleIndicator( + //TODO: colocar na tabela de cores. color: Color = Color(0xFF8D4CD2), modifier: Modifier = Modifier .width(60.dp) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetSelectorItem.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetSelectorItem.kt index 2c4eaa32..6d991f39 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetSelectorItem.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/PetSelectorItem.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.vector.VectorPainter import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -77,6 +78,7 @@ fun PetIcon( modifier = Modifier .size(32.dp) .offset(y = 4.dp) + .testTag("SelectedIcon") ) } @@ -129,6 +131,7 @@ fun PetFilterItem( modifier = Modifier .padding(start = 8.dp, end = 8.dp) .clickable { onSelect(name) } + .testTag("PetItem_$name") ) { PetIcon( imageRes = if (name == "Todos") painterResource(id = R.drawable.icon_pet_selected) else imageRes, @@ -160,9 +163,9 @@ fun PetFilterList( var selectedPets by remember { mutableStateOf(listOf()) } - Column(modifier = Modifier.padding(16.dp)) { + Column(modifier = Modifier) { Text( - text = "Quais pets precisam dessa tarefa?", + text = stringResource(R.string.which_pets_need_this_task), color = MaterialTheme.colorScheme.scrim, fontWeight = FontWeight(500), style = MaterialTheme.typography.titleMedium @@ -171,12 +174,12 @@ fun PetFilterList( LazyRow( modifier = Modifier .fillMaxWidth() - .padding(top = 20.dp, start = 10.dp), + .padding(top = 8.dp, start = 10.dp), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { item { PetFilterItem( - name = "Todos", + name = stringResource(R.string.label_all_pets), isSelected = selectedPets.contains(stringResource(R.string.label_all_pets)), imageRes = null, onSelect = { name -> @@ -225,7 +228,26 @@ fun PetFilterListPreview() { id = 2, imageRes = painterResource(R.drawable.image_alfredo), name = "Alfredo" - ) + ),Pets( + id = 1423, + imageRes = painterResource(R.drawable.image_jujuba), + name = "Jujuba" + ), + Pets( + id = 245, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 1455, + imageRes = painterResource(R.drawable.image_jujuba), + name = "Jujuba" + ), + Pets( + id = 6452, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ) ) PetFilterList( diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt index 7924a58c..c2ab27ac 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/SelectableButtonData.kt @@ -1,6 +1,7 @@ package com.soujunior.petjournal.ui.components import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow @@ -8,6 +9,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -38,7 +40,7 @@ fun SelectableButton( modifierSelectableButton: Modifier = Modifier, onSelectionChanged: (String, Boolean) -> Unit ) { - androidx.compose.material3.Button( + Button( modifier = modifierSelectableButton .height(40.dp) .then( @@ -78,19 +80,21 @@ fun SelectableButton( } } + + @OptIn(ExperimentalLayoutApi::class) @Composable fun GroupSelectableButton( listOfTasks: List, - onSelection: (String) -> Unit = {} + onSelection: (String) -> Unit = {}, + modifier: Modifier = Modifier, + maxItemsInEachRow: Int = Int.MAX_VALUE ) { - val selectionState = remember { mutableStateListOf(*Array(listOfTasks.size) { false }) } Column( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(8.dp) ) { Text( text = stringResource(R.string.label_select_main_category), @@ -99,11 +103,10 @@ fun GroupSelectableButton( fontWeight = FontWeight(500), lineHeight = 24.sp ) - FlowRow( - modifier = Modifier - .fillMaxWidth() - .padding(top = 15.dp) + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(15.dp), + maxItemsInEachRow = maxItemsInEachRow ) { listOfTasks.forEachIndexed { index, buttonInfo -> SelectableButton( @@ -120,7 +123,7 @@ fun GroupSelectableButton( }, modifierSelectableButton = Modifier .adaptiveWidthForTitle(buttonInfo.title) - .padding(bottom = 15.dp, end = 15.dp) + .padding(bottom = 15.dp) ) } } @@ -133,10 +136,9 @@ data class SelectableButtonInfo( val color: Color ) - -@Preview(showBackground = true, showSystemUi = true, device = "id:pixel_4_xl") +@Preview() @Composable -fun CustomSelectableButtonPreview() { +fun CustomSelectableButtonWithoutDevicePreview() { val listOfTasks = listOf( SelectableButtonInfo( stringResource(R.string.label_selectable_button_vaccines), @@ -164,4 +166,4 @@ fun CustomSelectableButtonPreview() { ), ) GroupSelectableButton(listOfTasks) -} \ No newline at end of file +} diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt index d8318f72..d7ce79f6 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TextFieldCustom.kt @@ -28,7 +28,6 @@ fun TextFieldCustom( ) { Column( modifier = modifier - .padding(start = 16.dp, end = 16.dp) ) { Text( text = title, diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt index fbdacd92..898ad828 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/TransactionTypeSelector.kt @@ -42,12 +42,12 @@ fun TransactionTypeSelector( Column( horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.fillMaxWidth() + modifier = Modifier ) { Row( horizontalArrangement = Arrangement.spacedBy(16.dp), verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(16.dp) + modifier = Modifier ) { ToggleButton( text = stringResource(R.string.label_recurrent), diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/WheelTimePicker.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/WheelTimePicker.kt index ceadee14..4745640c 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/WheelTimePicker.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/clock/WheelTimePicker.kt @@ -23,6 +23,7 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.TextStyle @@ -227,7 +228,7 @@ private fun PickerColumn( color = if (isFocused) focusedColor else unfocusedColor, fontSize = 34.sp ), -// modifier = Modifier.alpha(alpha) + modifier = Modifier//.alpha(alpha) ) } } diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/OneOffTask.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/OneOffTask.kt index 3edf7ff7..90fd3575 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/OneOffTask.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/OneOffTask.kt @@ -22,7 +22,7 @@ fun OneOffTask( ) { var selectedTimestamp by remember { mutableStateOf(null) } - Column(modifier = Modifier.padding(start = 20.dp, end = 20.dp)) { + Column(modifier = Modifier) { CustomDatePicker( label = "Data", value = selectedTimestamp, diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/RecurrentTask.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/RecurrentTask.kt index df35b3d9..06a2e449 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/RecurrentTask.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/components/task/RecurrentTask.kt @@ -56,7 +56,8 @@ fun RecurringTask( Row( modifier = Modifier .fillMaxWidth() - .padding(top = 16.dp), +// .padding(top = 16.dp) +, horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { @@ -74,7 +75,7 @@ fun RecurringTask( ) Box( modifier = Modifier - .padding(start = 8.dp) +// .padding(start = 8.dp) .height(150.dp) .width(100.dp), contentAlignment = Alignment.Center @@ -93,7 +94,8 @@ fun RecurringTask( Row( modifier = Modifier .fillMaxWidth() - .padding(top = 16.dp), +// .padding(top = 16.dp) + , horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerPetScreen/components/Screen.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerPetScreen/components/Screen.kt index 6e3a9ac8..3cc0bb74 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerPetScreen/components/Screen.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerPetScreen/components/Screen.kt @@ -49,8 +49,7 @@ fun Screen(navController: NavController) { ScaffoldCustom( modifier = Modifier .navigationBarsPadding() - .fillMaxSize() - , + .fillMaxSize(), navigationUp = navController, showTopBar = true, titleTopBar = stringResource(R.string.edit_pet_data), From fac9f5b953e8b090b2a2e81bb9d7d5ff036e6301 Mon Sep 17 00:00:00 2001 From: Gustavo Oliveira <42920754+gusoliveira21@users.noreply.github.com> Date: Thu, 6 Nov 2025 01:45:55 -0300 Subject: [PATCH 63/64] feat(ui): improve register task screen layout and functionality --- .../components/ScreenRegisterTask.kt | 205 +++++++++++++++++- .../app/src/main/res/values/strings.xml | 1 + 2 files changed, 200 insertions(+), 6 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt index 9e9f8abf..bb3dd269 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/ui/screens_app/screens_pets/registerTaskScreen/components/ScreenRegisterTask.kt @@ -1,11 +1,18 @@ package com.soujunior.petjournal.ui.screens_app.screens_pets.registerTaskScreen.components import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.ModalDrawer import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -16,6 +23,7 @@ import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import androidx.navigation.NavController import androidx.navigation.compose.rememberNavController import com.soujunior.petjournal.R @@ -31,6 +39,7 @@ import com.soujunior.petjournal.ui.components.TransactionTypeSelector import com.soujunior.petjournal.ui.components.task.OneOffTask import com.soujunior.petjournal.ui.components.task.RecurringTask import com.soujunior.petjournal.ui.theme.ColorCustom +import com.soujunior.petjournal.ui.theme.PetJournalTheme import com.soujunior.petjournal.ui.util.TransactionType import ir.kaaveh.sdpcompose.sdp @@ -121,6 +130,8 @@ fun ScreenRegisterTask(navController: NavController) { modifier = Modifier, navigationUp = navController, showTopBar = true, + //todo: o valor desse Title bar precisa ser passado por parametro, + // assim ele se comportara tanto como "Nova tarefa" quanto "Editar tarefa". titleTopBar = stringResource(R.string.label_new_task), showBottomBarNavigation = true, contentToUse = { paddingValues -> @@ -135,14 +146,11 @@ fun ScreenRegisterTask(navController: NavController) { modifier = Modifier .fillMaxSize() .padding(paddingValues), + verticalArrangement = Arrangement.spacedBy(12.sdp), + contentPadding = PaddingValues(horizontal = 14.sdp), content = { item { - GroupSelectableButton( - listOfTasks, - onSelection = { - - } - ) + GroupSelectableButton(listOfTasks) } item { InputText( @@ -243,4 +251,189 @@ fun ScreenRegisterTask(navController: NavController) { fun ScreenRegisterTaskPreview() { val nav = rememberNavController() ScreenRegisterTask(nav) +} + + +private val listOfTasks = listOf( + SelectableButtonInfo( + "Vacinas", + ColorCustom.color_selectable_button_1 + ), + SelectableButtonInfo( + "Consultas", + ColorCustom.color_selectable_button_2 + ), + SelectableButtonInfo( + "Remédios", + ColorCustom.color_selectable_button_3 + ), + SelectableButtonInfo( + "Banho", + ColorCustom.color_selectable_button_4 + ), + SelectableButtonInfo( + "Comida", + ColorCustom.color_selectable_button_5 + ), + SelectableButtonInfo( + "Passeio", + ColorCustom.color_selectable_button_6 + ), +) + +@Preview(showBackground = true) +@Composable +fun GroupSelectableButtonPreview() { + PetJournalTheme { + GroupSelectableButton( + listOfTasks, + onSelection = { + + } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun InputTextTaskNamePreview() { + val nameTask = remember { mutableStateOf("") } + PetJournalTheme { + InputText( + modifier = Modifier.testTag("inputFieldTag"), + placeholderText = stringResource(R.string.enter_task_name_here), + titleText = stringResource(R.string.task_name), + textValue = nameTask.value, + onEvent = { t -> + nameTask.value = t + }, + ) + } +} + +@Preview(showBackground = true) +@Composable +fun TextFieldCustomDescriptionPreview() { + val desc = remember { mutableStateOf("") } + PetJournalTheme { + TextFieldCustom( + title = stringResource(R.string.label_description), + placeholder = stringResource(R.string.enter_the_task_description_here), + value = desc.value, + onValueChange = { d -> + desc.value = d + } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun PetFilterListPreview() { + val listPet = listOf( + Pets( + id = 1, + imageRes = painterResource(R.drawable.image_jujuba), + name = "Jujuba" + ), + Pets( + id = 2, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ), + Pets( + id = 3, + imageRes = painterResource(R.drawable.image_alfredo), + name = "Alfredo" + ) + ) + PetJournalTheme { + PetFilterList( + listPet, + onSelectedPet = { + + } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun TransactionTypeSelectorPreview() { + var selectedType by remember { mutableStateOf(null) } + PetJournalTheme { + TransactionTypeSelector( + onSelectionChanged = { type -> + selectedType = type + } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun RecurringTaskPreview() { + PetJournalTheme { + RecurringTask( + setOf(), + onAmPmSelector = { + + }, + onTime = { hour, minute -> + + }, + onWeekDaySelected = { + + }, + onDaySelected = { + + } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun OneOffTaskPreview() { + PetJournalTheme { + OneOffTask( + onDateSelected = { + + }, + onAmPmSelector = { + + }, + onTime = { hour, minute -> + + } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun TextFieldCustomObservationPreview() { + val ob = remember { mutableStateOf("") } + PetJournalTheme { + TextFieldCustom( + title = stringResource(R.string.label_observation), + placeholder = stringResource(R.string.enter_your_observation_here), + value = ob.value, + onValueChange = { o -> + ob.value = o + } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun Button3SaveTaskPreview() { + PetJournalTheme { + Button3( + submit = { /*TODO*/ }, + enableButton = true, + text = stringResource(R.string.label_save_task) + ) + } } \ No newline at end of file diff --git a/petJournal/app/src/main/res/values/strings.xml b/petJournal/app/src/main/res/values/strings.xml index 6bcf5344..c85b4cf4 100644 --- a/petJournal/app/src/main/res/values/strings.xml +++ b/petJournal/app/src/main/res/values/strings.xml @@ -167,4 +167,5 @@ Observação Digite aqui a sua observação Salvar + Quais pets precisam dessa tarefa? \ No newline at end of file From 63bc817660ffebaeaa3f7b5370ea606317ac3658 Mon Sep 17 00:00:00 2001 From: Gustavo Oliveira <42920754+gusoliveira21@users.noreply.github.com> Date: Thu, 6 Nov 2025 01:45:58 -0300 Subject: [PATCH 64/64] refactor(navigation): restore PresentationManager in MainActivity --- .../java/com/soujunior/petjournal/navigation/MainActivity.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/MainActivity.kt b/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/MainActivity.kt index 65eed297..651c5e25 100644 --- a/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/MainActivity.kt +++ b/petJournal/app/src/main/java/com/soujunior/petjournal/navigation/MainActivity.kt @@ -18,9 +18,7 @@ class MainActivity : ComponentActivity() { WindowCompat.setDecorFitsSystemWindows(window, false) setContent { ChangeSystemBars() -// PresentationManager() - val nav = rememberNavController() - ScreenRegisterTask(nav) + PresentationManager() } } }