From 4bc9bd70ad46b2cf851b2e322840e9b32c4ee9f1 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 12:42:00 -0400 Subject: [PATCH 01/33] - maps the JSON field shared_code to the Kotlin property sharedCode - maps the JSON field created_at - maps the JSON field item_count --- .../java/com/example/listifyjetapp/model/ListModel.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/example/listifyjetapp/model/ListModel.kt b/app/src/main/java/com/example/listifyjetapp/model/ListModel.kt index 09016c6..b58a842 100644 --- a/app/src/main/java/com/example/listifyjetapp/model/ListModel.kt +++ b/app/src/main/java/com/example/listifyjetapp/model/ListModel.kt @@ -1,11 +1,14 @@ package com.example.listifyjetapp.model -import java.time.LocalDateTime +import com.google.gson.annotations.SerializedName data class ListModel( val id: Int, val name: String, val share: Boolean, - val shareCode: String, // can be UUID or String - val createdAt: LocalDateTime + //val sharedCode: String, // can be UUID or String + //val createdAt: LocalDateTime + @SerializedName("shared_code") val sharedCode: String, + @SerializedName("created_at") val createdAt: String, + @SerializedName("item_count") val itemCount: Int, ) From 6988d2048958f69194546b3fade59f7de9bffc4e Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 12:44:25 -0400 Subject: [PATCH 02/33] - add colours --- app/src/main/java/com/example/listifyjetapp/ui/theme/Color.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/example/listifyjetapp/ui/theme/Color.kt b/app/src/main/java/com/example/listifyjetapp/ui/theme/Color.kt index 6b65d4a..d525909 100644 --- a/app/src/main/java/com/example/listifyjetapp/ui/theme/Color.kt +++ b/app/src/main/java/com/example/listifyjetapp/ui/theme/Color.kt @@ -12,6 +12,8 @@ val Pink40 = Color(0xFF7D5260) object ListifyColor { val SplashYellow = Color(0xFFFFCA3A) + val TextBlack = Color(0xff000000) val TextDark = Color(0xff3e4e50) val TextGrey = Color(0xff858585) + val IconGreen = Color(0xff0cc25f) } From 3c32bebbfd303accd95350aadb4d333160b5d750 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 12:48:51 -0400 Subject: [PATCH 03/33] - Create app top bar composable - check if top bar is in ListsScreen - check if goBackIcon is null --- .../listifyjetapp/widgets/ListifyTopBar.kt | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt diff --git a/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt b/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt new file mode 100644 index 0000000..fae85b5 --- /dev/null +++ b/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt @@ -0,0 +1,59 @@ +package com.example.listifyjetapp.widgets + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults.topAppBarColors +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +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 + +@OptIn(ExperimentalMaterial3Api::class) +@Preview +@Composable +fun ListifyTopBar( + title: String = "Screen Tittle", + isListsScreen: Boolean = true, + goBackIcon: ImageVector? = null, + onGoBackButtonClicked: () -> Unit = {} +) { + + CenterAlignedTopAppBar( + //modifier = Modifier.shadow(elevation = 5.dp), + colors = topAppBarColors(containerColor = Color.Transparent), + title = { + Text(text = title, fontWeight = FontWeight.ExtraBold, fontSize = 24.sp) + }, + actions = { + if (isListsScreen) { + IconButton(onClick = { }) { + Icon( + modifier = Modifier.size(24.dp), + imageVector = Icons.Default.Add, + contentDescription = "Add list icon" + ) + } + } + }, + navigationIcon = { + if (goBackIcon != null) { + Icon( + imageVector = goBackIcon, + contentDescription = "GO back icon", + modifier = Modifier.size(24.dp).clickable { onGoBackButtonClicked.invoke() } + ) + } + } + ) +} \ No newline at end of file From d227eab730984d1cd5bfe286ebe0be493e05252f Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 12:53:35 -0400 Subject: [PATCH 04/33] - Create search bar composable --- .../listifyjetapp/widgets/ListifySearchBar.kt | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 app/src/main/java/com/example/listifyjetapp/widgets/ListifySearchBar.kt diff --git a/app/src/main/java/com/example/listifyjetapp/widgets/ListifySearchBar.kt b/app/src/main/java/com/example/listifyjetapp/widgets/ListifySearchBar.kt new file mode 100644 index 0000000..8443b5f --- /dev/null +++ b/app/src/main/java/com/example/listifyjetapp/widgets/ListifySearchBar.kt @@ -0,0 +1,61 @@ +package com.example.listifyjetapp.widgets + + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.text.input.InputTransformation.Companion.keyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import com.example.listifyjetapp.ui.theme.ListifyColor + + +@Composable +fun ListifySearchBar( + searchTextValue: MutableState, + onValueChange: (String) -> Unit, + imeAction: ImeAction = ImeAction.Next, // what happen when you press "Next" + keyboardAction: KeyboardActions = KeyboardActions.Default // what to do when an action is triggered +) { + TextField( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(12.dp), + colors = TextFieldDefaults.colors( + unfocusedIndicatorColor = Color.Transparent, + focusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + + unfocusedLabelColor = ListifyColor.TextDark.copy(0.1f), + focusedContainerColor = ListifyColor.TextDark.copy(0.1f), + cursorColor = ListifyColor.TextDark, + ), + singleLine = true, + maxLines = 1, + leadingIcon = { + Icon( + imageVector = Icons.Default.Search, + contentDescription = "Search icon", + ) + }, + + value = searchTextValue.value, + onValueChange = onValueChange, + placeholder = { Text(text="Search") }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), // Sets the keyboard to normal text input. + keyboardActions = keyboardAction, + ) +} \ No newline at end of file From 1449a219f8d0eea0e825e98ae1d02d6b706a2095 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 12:59:52 -0400 Subject: [PATCH 05/33] - add isLoading state - Sets isLoading = true while waiting for the result. - resets isLoading to false --- .../screens/lists/ListsViewModel.kt | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListsViewModel.kt b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListsViewModel.kt index c96eee0..893ed77 100644 --- a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListsViewModel.kt +++ b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListsViewModel.kt @@ -1,29 +1,35 @@ package com.example.listifyjetapp.screens.lists import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.example.listifyjetapp.data.ListifyResult import com.example.listifyjetapp.model.ListModel import com.example.listifyjetapp.repository.ListsRepository import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class ListsViewModel @Inject constructor(private val repository: ListsRepository): ViewModel() { val lists = mutableStateListOf() + var isLoading = mutableStateOf(false) fun getUserLists(userId: Int) { viewModelScope.launch { - val result = repository.getUserLists(userId = userId) - when(result) { - is ListifyResult.Success -> { - lists.clear() - lists.addAll(result.data) + isLoading.value = true + val result = repository.getUserLists(userId = userId) + when (result) { + is ListifyResult.Success -> { + lists.clear() + lists.addAll(result.data) + } + + is ListifyResult.Failure -> Unit } - is ListifyResult.Failure -> Unit - } + isLoading.value = false } } } \ No newline at end of file From fe499a36c0d49140d8469452956b103773c2a069 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 14:31:44 -0400 Subject: [PATCH 06/33] - add top bar + search bar - track isLoading + load lists if isLoading is true --- .../screens/lists/ListifyListsScreen.kt | 139 +++++++++++++++++- 1 file changed, 131 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt index d313af2..9f4414f 100644 --- a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt +++ b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt @@ -1,17 +1,42 @@ package com.example.listifyjetapp.screens.lists +import android.util.Log +import androidx.compose.foundation.background +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.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight +import androidx.compose.material.icons.filled.Share +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import com.example.listifyjetapp.ui.theme.ListifyColor +import com.example.listifyjetapp.widgets.ListifySearchBar +import com.example.listifyjetapp.widgets.ListifyTopBar @Composable fun ListifyListsScreen( @@ -19,22 +44,120 @@ fun ListifyListsScreen( ) { LaunchedEffect(Unit) { viewModel.getUserLists(4) } - Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> + Scaffold( + modifier = Modifier.fillMaxSize(), + topBar = { ListifyTopBar( + title = "Lists", + isListsScreen = true, + ) } + ) { innerPadding -> Surface( modifier = Modifier.fillMaxSize().padding(innerPadding) ) { + Column( + modifier = Modifier.padding(horizontal = 16.dp), + verticalArrangement = Arrangement.Top, + horizontalAlignment = Alignment.CenterHorizontally + ) { + //val lists =viewModel.lists + //Log.d("Lists", lists.toString()) + val searchTextState = rememberSaveable { mutableStateOf("") } + val keyboardController = LocalSoftwareKeyboardController.current - if (viewModel.lists.isEmpty()) { - Text(text = "You don't have any lists yet.") - } else { - LazyColumn { - items(viewModel.lists) {list -> - Text(text = list.name) + ListifySearchBar( + searchTextValue = searchTextState, + onValueChange = {searchTextState.value = it}, + keyboardAction = KeyboardActions{ + // Trigger search logic or hide keyboard + searchTextState.value.trim() // perform the search + searchTextState.value = "" // clear text field when click Done, Next, etc + keyboardController?.hide() // hide keyboard + } + ) + //Text(text = "You don't have any lists yet.") + + if (viewModel.isLoading.value) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } else if (viewModel.lists.isEmpty()) { + Text(text = "You don't have any lists yet.") + } else { + LazyColumn(modifier = Modifier.padding( + vertical = 16.dp, + horizontal = 8.dp + )){ + + items(viewModel.lists) {list -> + Log.d("list", list.itemCount.toString()) + Row( + modifier = Modifier + .clickable { } + .padding(vertical = 16.dp) + .fillMaxWidth() + .background(Color.Transparent) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + // List info + Column { + Text( + text = list.name, + color = ListifyColor.TextBlack, + fontSize = 20.sp, + //fontWeight = FontWeight.SemiBold + ) + + if (list.share) { + Row { + Icon( + modifier = Modifier.size(16.dp), + tint = ListifyColor.IconGreen, + imageVector = Icons.Default.Share, + contentDescription = "Shared with" + + ) + } + } + + Text( + text = list.createdAt, + color = ListifyColor.TextGrey, + fontSize = 16.sp + ) + } + // List setting menu + + Row() { + Text( + text = list.itemCount.toString(), + color = ListifyColor.TextGrey, + fontSize = 16.sp + ) + + Icon( + imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight, + contentDescription = "Forward icon" + ) + + } + + } + + } + HorizontalDivider() + + } } } } } } - } \ No newline at end of file From d2f7e6fdfb37fe3fb255f3c2bbc8190f1958deac Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 14:45:23 -0400 Subject: [PATCH 07/33] - ignore file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index aa724b7..86f1fbc 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ .externalNativeBuild .cxx local.properties +/app/src/main/java/com/example/listifyjetapp/utils/constants/Constants.kt \ No newline at end of file From c606fb756de6ff013cc4bec01a949a8241a14959 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 21:59:19 -0400 Subject: [PATCH 08/33] - create User model - create SharedUsers model --- .../com/example/listifyjetapp/model/User.kt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 app/src/main/java/com/example/listifyjetapp/model/User.kt diff --git a/app/src/main/java/com/example/listifyjetapp/model/User.kt b/app/src/main/java/com/example/listifyjetapp/model/User.kt new file mode 100644 index 0000000..706255e --- /dev/null +++ b/app/src/main/java/com/example/listifyjetapp/model/User.kt @@ -0,0 +1,17 @@ +package com.example.listifyjetapp.model + +import com.google.gson.annotations.SerializedName + +data class User( + val id: Int, + val username: String, + val email: String, + val password: String, + @SerializedName("created_at") val createdAt: String +) + +data class SharedUsers( + @SerializedName("user_id") val userId: Int, + val username: String, +) + From df6e1576baa5f42e3ceaf7d6b8b3879a06728564 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 22:01:41 -0400 Subject: [PATCH 09/33] - add sharedWidth field --- app/src/main/java/com/example/listifyjetapp/model/ListModel.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/example/listifyjetapp/model/ListModel.kt b/app/src/main/java/com/example/listifyjetapp/model/ListModel.kt index b58a842..6d8079e 100644 --- a/app/src/main/java/com/example/listifyjetapp/model/ListModel.kt +++ b/app/src/main/java/com/example/listifyjetapp/model/ListModel.kt @@ -11,4 +11,5 @@ data class ListModel( @SerializedName("shared_code") val sharedCode: String, @SerializedName("created_at") val createdAt: String, @SerializedName("item_count") val itemCount: Int, + @SerializedName("shared_with") val sharedWith: List ) From c77faa7057f5bb35e603591008f2c12cdc3a0286 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 22:06:36 -0400 Subject: [PATCH 10/33] - create composable to show info of each list --- .../listifyjetapp/screens/lists/ListRow.kt | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt diff --git a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt new file mode 100644 index 0000000..c10a9d4 --- /dev/null +++ b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt @@ -0,0 +1,95 @@ +package com.example.listifyjetapp.screens.lists + +import androidx.compose.foundation.background +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.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight +import androidx.compose.material.icons.filled.Share +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +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.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.example.listifyjetapp.model.ListModel +import com.example.listifyjetapp.ui.theme.ListifyColor + +@Composable +fun ListItemComposable( + list: ListModel, + //viewModel: User +) { + Row( + modifier = Modifier + .clickable { } + .padding(vertical = 16.dp) + .fillMaxWidth() + .background(Color.Transparent) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + // List info + Column { + Text( + text = list.name, + color = ListifyColor.TextBlack, + fontSize = 20.sp, + //fontWeight = FontWeight.SemiBold + ) + + if (list.share) { + Row { + Icon( + modifier = Modifier.size(16.dp), + tint = ListifyColor.IconGreen, + imageVector = Icons.Default.Share, + contentDescription = "Shared with" + ) + Text( + text = list.sharedWith.take(8).joinToString(", ") { it.username }, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + + Text( + text = list.createdAt, + color = ListifyColor.TextGrey, + fontSize = 16.sp + ) + } + // List setting menu + + Row() { + Text( + text = list.itemCount.toString(), + color = ListifyColor.TextGrey, + fontSize = 16.sp + ) + + Icon( + imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight, + contentDescription = "Forward icon" + ) + + } + + } + + } + HorizontalDivider() +} \ No newline at end of file From b1347d490aa3b3e0fbf0c40fa87a42f152741f76 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 22:08:01 -0400 Subject: [PATCH 11/33] - rename composable --- .../java/com/example/listifyjetapp/screens/lists/ListRow.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt index c10a9d4..46a6875 100644 --- a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt +++ b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt @@ -25,7 +25,7 @@ import com.example.listifyjetapp.model.ListModel import com.example.listifyjetapp.ui.theme.ListifyColor @Composable -fun ListItemComposable( +fun ListRow( list: ListModel, //viewModel: User ) { From f9def51e42a9ff2fae20712296d1a3c0a34a8819 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 22:08:10 -0400 Subject: [PATCH 12/33] - render ListRow --- .../screens/lists/ListifyListsScreen.kt | 73 +------------------ 1 file changed, 1 insertion(+), 72 deletions(-) diff --git a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt index 9f4414f..8b6ae67 100644 --- a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt +++ b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt @@ -1,25 +1,15 @@ package com.example.listifyjetapp.screens.lists import android.util.Log -import androidx.compose.foundation.background -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.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.text.KeyboardActions -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight -import androidx.compose.material.icons.filled.Share import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -29,12 +19,9 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel -import com.example.listifyjetapp.ui.theme.ListifyColor import com.example.listifyjetapp.widgets.ListifySearchBar import com.example.listifyjetapp.widgets.ListifyTopBar @@ -93,66 +80,8 @@ fun ListifyListsScreen( )){ items(viewModel.lists) {list -> - Log.d("list", list.itemCount.toString()) - Row( - modifier = Modifier - .clickable { } - .padding(vertical = 16.dp) - .fillMaxWidth() - .background(Color.Transparent) - ) { - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - // List info - Column { - Text( - text = list.name, - color = ListifyColor.TextBlack, - fontSize = 20.sp, - //fontWeight = FontWeight.SemiBold - ) - if (list.share) { - Row { - Icon( - modifier = Modifier.size(16.dp), - tint = ListifyColor.IconGreen, - imageVector = Icons.Default.Share, - contentDescription = "Shared with" - - ) - } - } - - Text( - text = list.createdAt, - color = ListifyColor.TextGrey, - fontSize = 16.sp - ) - } - // List setting menu - - Row() { - Text( - text = list.itemCount.toString(), - color = ListifyColor.TextGrey, - fontSize = 16.sp - ) - - Icon( - imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight, - contentDescription = "Forward icon" - ) - - } - - } - - } - HorizontalDivider() + ListRow(list) } } From 8ff17e2796454698293f0c6a8554852dcf9b748b Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 23 Jul 2025 22:23:30 -0400 Subject: [PATCH 13/33] - add padding to list info column - center aligned list share row - style list share text --- .../listifyjetapp/screens/lists/ListRow.kt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt index 46a6875..a479b26 100644 --- a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt +++ b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt @@ -42,7 +42,10 @@ fun ListRow( horizontalArrangement = Arrangement.SpaceBetween ) { // List info - Column { + Column( + modifier = Modifier.padding(horizontal = 8.dp), + + ) { Text( text = list.name, color = ListifyColor.TextBlack, @@ -51,7 +54,9 @@ fun ListRow( ) if (list.share) { - Row { + Row( + verticalAlignment = Alignment.CenterVertically + ) { Icon( modifier = Modifier.size(16.dp), tint = ListifyColor.IconGreen, @@ -59,9 +64,11 @@ fun ListRow( contentDescription = "Shared with" ) Text( - text = list.sharedWith.take(8).joinToString(", ") { it.username }, + text = list.sharedWith.take(3).joinToString(", ") { it.username }, maxLines = 1, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, + color = ListifyColor.TextGrey, + fontSize = 16.sp ) } } From d183880a31fd615f3a3d2517c35089641af07768 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 15:31:17 -0400 Subject: [PATCH 14/33] - check if input is empty - show original lists if input is empty - if not show lists filtered by input --- .../example/listifyjetapp/utils/filterListItems.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 app/src/main/java/com/example/listifyjetapp/utils/filterListItems.kt diff --git a/app/src/main/java/com/example/listifyjetapp/utils/filterListItems.kt b/app/src/main/java/com/example/listifyjetapp/utils/filterListItems.kt new file mode 100644 index 0000000..e1c4f94 --- /dev/null +++ b/app/src/main/java/com/example/listifyjetapp/utils/filterListItems.kt @@ -0,0 +1,14 @@ +package com.example.listifyjetapp.utils + +import android.util.Log +import com.example.listifyjetapp.model.ListModel + +fun filterListItems(input: String, listItems: List): List { + + return if (input.isEmpty()) { + listItems + } else { + listItems.filter { it.name.contains(input, ignoreCase = true) } + } + +} From 51f611b02b6e65715e1527c1f3b29e970c815956 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 15:32:03 -0400 Subject: [PATCH 15/33] - filter lists by input --- .../screens/lists/ListifyListsScreen.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt index 8b6ae67..1deda8c 100644 --- a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt +++ b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt @@ -16,12 +16,14 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import com.example.listifyjetapp.utils.filterListItems import com.example.listifyjetapp.widgets.ListifySearchBar import com.example.listifyjetapp.widgets.ListifyTopBar @@ -47,9 +49,8 @@ fun ListifyListsScreen( verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.CenterHorizontally ) { - //val lists =viewModel.lists - //Log.d("Lists", lists.toString()) - val searchTextState = rememberSaveable { mutableStateOf("") } + + val searchTextState = remember { mutableStateOf("") } val keyboardController = LocalSoftwareKeyboardController.current ListifySearchBar( @@ -78,11 +79,11 @@ fun ListifyListsScreen( vertical = 16.dp, horizontal = 8.dp )){ + // Filter lists by search input + val results = filterListItems(searchTextState.value, viewModel.lists) - items(viewModel.lists) {list -> - + items(results) {list -> ListRow(list) - } } } From 6c5ee1e17581a25da8a4dd87a27243e4dcd389fa Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 15:32:59 -0400 Subject: [PATCH 16/33] - comment out reseting search text - keep search input when done is clicked --- .../example/listifyjetapp/screens/lists/ListifyListsScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt index 1deda8c..f551cbd 100644 --- a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt +++ b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt @@ -59,7 +59,7 @@ fun ListifyListsScreen( keyboardAction = KeyboardActions{ // Trigger search logic or hide keyboard searchTextState.value.trim() // perform the search - searchTextState.value = "" // clear text field when click Done, Next, etc + //searchTextState.value = "" // clear text field when click Done, Next, etc keyboardController?.hide() // hide keyboard } ) From f631965d2737dac5c966becd81aa0dbbf5b49bc2 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 19:42:10 -0400 Subject: [PATCH 17/33] - create dialog --- .../listifyjetapp/components/FormDialog.kt | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 app/src/main/java/com/example/listifyjetapp/components/FormDialog.kt diff --git a/app/src/main/java/com/example/listifyjetapp/components/FormDialog.kt b/app/src/main/java/com/example/listifyjetapp/components/FormDialog.kt new file mode 100644 index 0000000..9a40f38 --- /dev/null +++ b/app/src/main/java/com/example/listifyjetapp/components/FormDialog.kt @@ -0,0 +1,47 @@ +package com.example.listifyjetapp.components + +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.shape.RoundedCornerShape +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties + +@Composable +fun FormDialog( + onDismiss: () -> Unit = {}, + onConfirm: () -> Unit = {} +) { + Dialog ( + onDismissRequest = onDismiss, + properties = DialogProperties(usePlatformDefaultWidth = false) + ) { + Card( + elevation = CardDefaults.cardElevation(defaultElevation = 6.dp), + shape = RoundedCornerShape(15.dp), + modifier = Modifier.fillMaxWidth(0.95f) + ) { + Column( + modifier = Modifier.fillMaxWidth().padding(15.dp) + //verticalArrangement = Arrangement.SpaceBy(25.dp) + ) { + Text( + text = "Add new list", + textAlign = TextAlign.Center + ) + + Column { + Row { } + } + } + } + } +} \ No newline at end of file From f5a09b3b493ca70b5d924dbf59075816ef839d10 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 19:43:02 -0400 Subject: [PATCH 18/33] - pass in onAddButtonClick to handle showing dialog --- .../listifyjetapp/widgets/ListifyTopBar.kt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt b/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt index fae85b5..adbac57 100644 --- a/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt +++ b/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt @@ -26,7 +26,8 @@ fun ListifyTopBar( title: String = "Screen Tittle", isListsScreen: Boolean = true, goBackIcon: ImageVector? = null, - onGoBackButtonClicked: () -> Unit = {} + onGoBackButtonClicked: () -> Unit = {}, + onAddButtonClick: () -> Unit = {} ) { CenterAlignedTopAppBar( @@ -35,17 +36,17 @@ fun ListifyTopBar( title = { Text(text = title, fontWeight = FontWeight.ExtraBold, fontSize = 24.sp) }, + actions = { - if (isListsScreen) { - IconButton(onClick = { }) { - Icon( - modifier = Modifier.size(24.dp), - imageVector = Icons.Default.Add, - contentDescription = "Add list icon" - ) - } + IconButton(onClick = { onAddButtonClick() }) { + Icon( + modifier = Modifier.size(24.dp), + imageVector = Icons.Default.Add, + contentDescription = "Add list icon" + ) } }, + navigationIcon = { if (goBackIcon != null) { Icon( From 78d51d51f7376d5d305e41eb0da7f6a10cc62c4b Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 19:43:42 -0400 Subject: [PATCH 19/33] - show FormDialog when isDialogShown is true --- .../screens/lists/ListifyListsScreen.kt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt index f551cbd..b5e7c12 100644 --- a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt +++ b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt @@ -17,12 +17,12 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import com.example.listifyjetapp.components.FormDialog import com.example.listifyjetapp.utils.filterListItems import com.example.listifyjetapp.widgets.ListifySearchBar import com.example.listifyjetapp.widgets.ListifyTopBar @@ -33,11 +33,14 @@ fun ListifyListsScreen( ) { LaunchedEffect(Unit) { viewModel.getUserLists(4) } + val isDialogShown = remember { mutableStateOf(false) } + Scaffold( modifier = Modifier.fillMaxSize(), topBar = { ListifyTopBar( title = "Lists", isListsScreen = true, + onAddButtonClick = { isDialogShown.value = true } ) } ) { innerPadding -> @@ -63,7 +66,6 @@ fun ListifyListsScreen( keyboardController?.hide() // hide keyboard } ) - //Text(text = "You don't have any lists yet.") if (viewModel.isLoading.value) { Box( @@ -88,6 +90,13 @@ fun ListifyListsScreen( } } } + + if (isDialogShown.value) { + FormDialog( + onDismiss = { isDialogShown.value = false }, + onConfirm = {} + ) + } } } } \ No newline at end of file From b11e00e022af7b79f0bc49e3aa6ac04ae65b26ea Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 21:37:40 -0400 Subject: [PATCH 20/33] - create add list screen composable - can navigate back --- .../screens/forms/ListifyNewListScreen.kt | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 app/src/main/java/com/example/listifyjetapp/screens/forms/ListifyNewListScreen.kt diff --git a/app/src/main/java/com/example/listifyjetapp/screens/forms/ListifyNewListScreen.kt b/app/src/main/java/com/example/listifyjetapp/screens/forms/ListifyNewListScreen.kt new file mode 100644 index 0000000..a051c5a --- /dev/null +++ b/app/src/main/java/com/example/listifyjetapp/screens/forms/ListifyNewListScreen.kt @@ -0,0 +1,63 @@ +package com.example.listifyjetapp.screens.forms + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.ArrowBack + +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import com.example.listifyjetapp.widgets.FormInputField +import com.example.listifyjetapp.widgets.ListifyTopBar + +@Composable +fun ListifyNewListScreen( + navController: NavController, + onDismiss: () -> Unit = {}, + onConfirm: () -> Unit = {} +) { + + val formTextState = remember { mutableStateOf("") } + + Scaffold( + modifier = Modifier.fillMaxSize(), + topBar = { ListifyTopBar( + title = "New List", + isListsScreen = false, + //goBackIcon = Icons.AutoMirrored.Filled.ArrowBack, + onGoBackButtonClicked = {navController.popBackStack()}, + leftText = "Cancel", + rightText = "Save", + onAddButtonClick = { onConfirm() } + ) } + ) { innerPadding -> + + Surface( + modifier = Modifier.fillMaxSize().padding(innerPadding) + ) { + + Column( + modifier = Modifier.fillMaxWidth().padding(16.dp), + verticalArrangement = Arrangement.spacedBy(25.dp) + ) { + + Column() { + FormInputField( + textState=formTextState, + onValueChange={ formTextState.value = it } + ) + } + } + } + } +} \ No newline at end of file From cf6430a4c3ead500fbc49a604160b40d5de51999 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 21:39:04 -0400 Subject: [PATCH 21/33] - add let text param - add rightText, right Icon param - check if new params --- .../listifyjetapp/widgets/ListifyTopBar.kt | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt b/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt index adbac57..c7da4f4 100644 --- a/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt +++ b/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt @@ -1,6 +1,7 @@ package com.example.listifyjetapp.widgets import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add @@ -18,6 +19,7 @@ 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 com.example.listifyjetapp.ui.theme.ListifyColor @OptIn(ExperimentalMaterial3Api::class) @Preview @@ -26,6 +28,9 @@ fun ListifyTopBar( title: String = "Screen Tittle", isListsScreen: Boolean = true, goBackIcon: ImageVector? = null, + leftText: String? = "", + rightIcon: ImageVector? = null, + rightText: String? = "", onGoBackButtonClicked: () -> Unit = {}, onAddButtonClick: () -> Unit = {} ) { @@ -38,11 +43,22 @@ fun ListifyTopBar( }, actions = { - IconButton(onClick = { onAddButtonClick() }) { - Icon( - modifier = Modifier.size(24.dp), - imageVector = Icons.Default.Add, - contentDescription = "Add list icon" + if (rightIcon != null) { + IconButton(onClick = { onAddButtonClick() }) { + Icon( + modifier = Modifier.size(24.dp), + imageVector = rightIcon, //Icons.Default.Add, + contentDescription = "Add icon" + ) + } + } + + if (rightText.toString().isNotEmpty() && rightText != null) { + Text( + text = rightText, + modifier = Modifier.padding(horizontal = 16.dp), + fontSize = 20.sp, + color = ListifyColor.SplashYellow ) } }, @@ -55,6 +71,17 @@ fun ListifyTopBar( modifier = Modifier.size(24.dp).clickable { onGoBackButtonClicked.invoke() } ) } + if (leftText.toString().isNotEmpty() && leftText != null) { + Text( + text = leftText, + modifier = Modifier + .padding(horizontal = 16.dp) + .clickable { onGoBackButtonClicked.invoke() }, + fontSize = 20.sp, + color = ListifyColor.SplashYellow + ) + } + } ) } \ No newline at end of file From ebaf7cde716ff1d39bfa311bb257aa74f19f6406 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 21:39:33 -0400 Subject: [PATCH 22/33] - add route for ListifyNewListScreen --- .../example/listifyjetapp/navigation/ListifyNavigation.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/listifyjetapp/navigation/ListifyNavigation.kt b/app/src/main/java/com/example/listifyjetapp/navigation/ListifyNavigation.kt index 93eea4a..d052c78 100644 --- a/app/src/main/java/com/example/listifyjetapp/navigation/ListifyNavigation.kt +++ b/app/src/main/java/com/example/listifyjetapp/navigation/ListifyNavigation.kt @@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import com.example.listifyjetapp.screens.forms.ListifyNewListScreen import com.example.listifyjetapp.screens.lists.ListifyListsScreen import com.example.listifyjetapp.screens.profile.ListifyProfileScreen import com.example.listifyjetapp.screens.splash.ListifySplashScreen @@ -28,7 +29,12 @@ fun ListifyNavigation() { // TODO: Define a navigation route for ListsScreen composable(ListifyScreens.ListsScreen.route) { - ListifyListsScreen() + ListifyListsScreen(navController = navController) + } + + // TODO: Define a navigation route for NewListScreen + composable(ListifyScreens.NewListScreen.route) { + ListifyNewListScreen(navController = navController) } // TODO: Define a navigation route for DetailScreen From cad53ace8b18dea7e38418e2fff8e0aba67073f6 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 21:42:49 -0400 Subject: [PATCH 23/33] - create input field for adding new list --- .../listifyjetapp/widgets/FormInputField.kt | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 app/src/main/java/com/example/listifyjetapp/widgets/FormInputField.kt diff --git a/app/src/main/java/com/example/listifyjetapp/widgets/FormInputField.kt b/app/src/main/java/com/example/listifyjetapp/widgets/FormInputField.kt new file mode 100644 index 0000000..d74a32d --- /dev/null +++ b/app/src/main/java/com/example/listifyjetapp/widgets/FormInputField.kt @@ -0,0 +1,46 @@ +package com.example.listifyjetapp.widgets + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import com.example.listifyjetapp.ui.theme.ListifyColor + +@Composable +fun FormInputField( + textState: MutableState, + onValueChange: (String) -> Unit, +) { + + TextField( + modifier = Modifier.fillMaxWidth(), + + shape = RoundedCornerShape(12.dp), + colors = TextFieldDefaults.colors( + unfocusedIndicatorColor = Color.White, + focusedIndicatorColor = Color.White, + disabledIndicatorColor = Color.Transparent, + + unfocusedLabelColor = ListifyColor.TextDark, + unfocusedContainerColor = ListifyColor.TextDark.copy(0.1f), + focusedContainerColor = ListifyColor.TextDark.copy(0.1f), + cursorColor = ListifyColor.TextDark, + ), + singleLine = true, + maxLines = 1, + + value = textState.value, + onValueChange = onValueChange, + placeholder = { Text(text="e.g., grocery list") }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), // Sets the keyboard to normal text input. + ) +} \ No newline at end of file From 8710f2e9ea592b5d7040eabe9388aa3b4ee4a40b Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 21:45:35 -0400 Subject: [PATCH 24/33] - rename function --- .../listifyjetapp/screens/forms/ListifyNewListScreen.kt | 2 +- .../java/com/example/listifyjetapp/widgets/ListifyTopBar.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/example/listifyjetapp/screens/forms/ListifyNewListScreen.kt b/app/src/main/java/com/example/listifyjetapp/screens/forms/ListifyNewListScreen.kt index a051c5a..0e8695e 100644 --- a/app/src/main/java/com/example/listifyjetapp/screens/forms/ListifyNewListScreen.kt +++ b/app/src/main/java/com/example/listifyjetapp/screens/forms/ListifyNewListScreen.kt @@ -38,7 +38,7 @@ fun ListifyNewListScreen( onGoBackButtonClicked = {navController.popBackStack()}, leftText = "Cancel", rightText = "Save", - onAddButtonClick = { onConfirm() } + onRightButtonClick = { onConfirm() } ) } ) { innerPadding -> diff --git a/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt b/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt index c7da4f4..9bb9f47 100644 --- a/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt +++ b/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt @@ -32,7 +32,7 @@ fun ListifyTopBar( rightIcon: ImageVector? = null, rightText: String? = "", onGoBackButtonClicked: () -> Unit = {}, - onAddButtonClick: () -> Unit = {} + onRightButtonClick: () -> Unit = {} ) { CenterAlignedTopAppBar( @@ -44,7 +44,7 @@ fun ListifyTopBar( actions = { if (rightIcon != null) { - IconButton(onClick = { onAddButtonClick() }) { + IconButton(onClick = { onRightButtonClick() }) { Icon( modifier = Modifier.size(24.dp), imageVector = rightIcon, //Icons.Default.Add, From 0527bd1b9e2f1f0730592939691e4e119386d7a9 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 21:46:10 -0400 Subject: [PATCH 25/33] - add NewListScreen --- .../com/example/listifyjetapp/navigation/ListifyScreens.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/listifyjetapp/navigation/ListifyScreens.kt b/app/src/main/java/com/example/listifyjetapp/navigation/ListifyScreens.kt index 362fe94..e8130db 100644 --- a/app/src/main/java/com/example/listifyjetapp/navigation/ListifyScreens.kt +++ b/app/src/main/java/com/example/listifyjetapp/navigation/ListifyScreens.kt @@ -6,7 +6,8 @@ enum class ListifyScreens(val route: String) { DetailScreen("detail"), ProfileScreen("profile"), LoginScreen("login"), - SignupScreen("signup") + SignupScreen("signup"), + NewListScreen("new-list") } // navController.navigate(ListifyScreens.LoginScreen.route) \ No newline at end of file From d0c9b94f7bed70d5f113c0e378fcc4821f46e23f Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Thu, 24 Jul 2025 21:46:47 -0400 Subject: [PATCH 26/33] - remove isDialogShown state + if statement - add params for top bar --- .../screens/lists/ListifyListsScreen.kt | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt index b5e7c12..9ece679 100644 --- a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt +++ b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListifyListsScreen.kt @@ -1,6 +1,5 @@ package com.example.listifyjetapp.screens.lists -import android.util.Log import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -9,6 +8,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface @@ -22,25 +23,29 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel -import com.example.listifyjetapp.components.FormDialog +import androidx.navigation.NavController +import com.example.listifyjetapp.navigation.ListifyScreens import com.example.listifyjetapp.utils.filterListItems import com.example.listifyjetapp.widgets.ListifySearchBar import com.example.listifyjetapp.widgets.ListifyTopBar @Composable fun ListifyListsScreen( + navController: NavController, viewModel: ListsViewModel = hiltViewModel() ) { LaunchedEffect(Unit) { viewModel.getUserLists(4) } - val isDialogShown = remember { mutableStateOf(false) } Scaffold( modifier = Modifier.fillMaxSize(), topBar = { ListifyTopBar( title = "Lists", isListsScreen = true, - onAddButtonClick = { isDialogShown.value = true } + rightIcon = Icons.Default.Add, + onRightButtonClick = { + navController.navigate(ListifyScreens.NewListScreen.route) + } ) } ) { innerPadding -> @@ -62,7 +67,6 @@ fun ListifyListsScreen( keyboardAction = KeyboardActions{ // Trigger search logic or hide keyboard searchTextState.value.trim() // perform the search - //searchTextState.value = "" // clear text field when click Done, Next, etc keyboardController?.hide() // hide keyboard } ) @@ -91,12 +95,6 @@ fun ListifyListsScreen( } } - if (isDialogShown.value) { - FormDialog( - onDismiss = { isDialogShown.value = false }, - onConfirm = {} - ) - } } } } \ No newline at end of file From 192e5f44b67e564810b5eb86a9cd9a544310a487 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 30 Jul 2025 13:37:51 -0400 Subject: [PATCH 27/33] - add BaseList + listName models --- .../com/example/listifyjetapp/model/ListModel.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/listifyjetapp/model/ListModel.kt b/app/src/main/java/com/example/listifyjetapp/model/ListModel.kt index 6d8079e..d539814 100644 --- a/app/src/main/java/com/example/listifyjetapp/model/ListModel.kt +++ b/app/src/main/java/com/example/listifyjetapp/model/ListModel.kt @@ -2,7 +2,7 @@ package com.example.listifyjetapp.model import com.google.gson.annotations.SerializedName -data class ListModel( +data class BaseList( val id: Int, val name: String, val share: Boolean, @@ -10,6 +10,18 @@ data class ListModel( //val createdAt: LocalDateTime @SerializedName("shared_code") val sharedCode: String, @SerializedName("created_at") val createdAt: String, +) + +data class ListName ( + val name: String +) + +data class ListModel( + val id: Int, + val name: String, + val share: Boolean, + @SerializedName("shared_code") val sharedCode: String, + @SerializedName("created_at") val createdAt: String, @SerializedName("item_count") val itemCount: Int, @SerializedName("shared_with") val sharedWith: List ) From 66580565fa1d9161741e472a47d156188dbe0b72 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 30 Jul 2025 13:39:14 -0400 Subject: [PATCH 28/33] - add onRightButtonClick() --- .../java/com/example/listifyjetapp/widgets/ListifyTopBar.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt b/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt index 9bb9f47..4d88598 100644 --- a/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt +++ b/app/src/main/java/com/example/listifyjetapp/widgets/ListifyTopBar.kt @@ -56,7 +56,7 @@ fun ListifyTopBar( if (rightText.toString().isNotEmpty() && rightText != null) { Text( text = rightText, - modifier = Modifier.padding(horizontal = 16.dp), + modifier = Modifier.padding(horizontal = 16.dp).clickable { onRightButtonClick() }, fontSize = 20.sp, color = ListifyColor.SplashYellow ) From aa168e263f4f27d760352f709202d533991dfe25 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 30 Jul 2025 15:25:51 -0400 Subject: [PATCH 29/33] - add post request insertList() api - require userId + request as params - return a ListModel object --- .../java/com/example/listifyjetapp/network/ListsAPI.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/listifyjetapp/network/ListsAPI.kt b/app/src/main/java/com/example/listifyjetapp/network/ListsAPI.kt index 65b078d..97ab95f 100644 --- a/app/src/main/java/com/example/listifyjetapp/network/ListsAPI.kt +++ b/app/src/main/java/com/example/listifyjetapp/network/ListsAPI.kt @@ -2,7 +2,9 @@ package com.example.listifyjetapp.network import androidx.room.Update import com.example.listifyjetapp.model.ListModel +import com.example.listifyjetapp.model.ListName import com.example.listifyjetapp.model.User +import retrofit2.http.Body import retrofit2.http.DELETE import retrofit2.http.GET import retrofit2.http.PATCH @@ -59,7 +61,10 @@ interface ListifyAPI { // Post new list @POST("lists/{user_id}") - suspend fun createList(@Path("user_id") userId: Int) {} + suspend fun insertList( + @Path("user_id") userId: Int, + @Body request: ListName + ): ListModel // Get items by list id @GET("lists/{list_id}") From 35a307ca30e0c9cad16569993534fd5b1ebb1280 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 30 Jul 2025 15:27:16 -0400 Subject: [PATCH 30/33] - commit out broken import - rename file --- .../com/example/listifyjetapp/navigation/ListifyNavigation.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/example/listifyjetapp/navigation/ListifyNavigation.kt b/app/src/main/java/com/example/listifyjetapp/navigation/ListifyNavigation.kt index d052c78..3254950 100644 --- a/app/src/main/java/com/example/listifyjetapp/navigation/ListifyNavigation.kt +++ b/app/src/main/java/com/example/listifyjetapp/navigation/ListifyNavigation.kt @@ -4,9 +4,9 @@ import androidx.compose.runtime.Composable import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController -import com.example.listifyjetapp.screens.forms.ListifyNewListScreen +import com.example.listifyjetapp.screens.newList.ListifyNewListScreen import com.example.listifyjetapp.screens.lists.ListifyListsScreen -import com.example.listifyjetapp.screens.profile.ListifyProfileScreen +//import com.example.listifyjetapp.screens.profile.ListifyProfileScreen import com.example.listifyjetapp.screens.splash.ListifySplashScreen From dadbbe835c7c3da1f3219a08cc4edbe1a49cd04d Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 30 Jul 2025 17:11:14 -0400 Subject: [PATCH 31/33] - create insertListByUser api call - call insertList with userId + new list data - return a formatted ListModel response --- .../repository/ListsRepository.kt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/listifyjetapp/repository/ListsRepository.kt b/app/src/main/java/com/example/listifyjetapp/repository/ListsRepository.kt index e32626f..ce2cd61 100644 --- a/app/src/main/java/com/example/listifyjetapp/repository/ListsRepository.kt +++ b/app/src/main/java/com/example/listifyjetapp/repository/ListsRepository.kt @@ -1,8 +1,8 @@ package com.example.listifyjetapp.repository -import android.util.Log import com.example.listifyjetapp.data.ListifyResult import com.example.listifyjetapp.model.ListModel +import com.example.listifyjetapp.model.ListName import com.example.listifyjetapp.network.ListifyAPI import javax.inject.Inject @@ -18,4 +18,22 @@ class ListsRepository@Inject constructor(private val api: ListifyAPI){ return ListifyResult.Failure(e.message ?: "Error fetching lists") } } + + suspend fun insertListByUser(userId: Int, newListData: ListName): ListifyResult { + try { + val response = api.insertList(userId, newListData) + val formatedResponse = ListModel ( + id = response.id, + name = response.name, + share = response.share, + sharedCode = response.sharedCode, + createdAt = response.createdAt, + itemCount = 0, + sharedWith= emptyList() + ) + return ListifyResult.Success(data = formatedResponse) + } catch (e:Exception) { + return ListifyResult.Failure(e.message ?: "Error creating new list") + } + } } \ No newline at end of file From 7c2420f8836a4e4cb9869c8322d404ccf467e60b Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 30 Jul 2025 21:35:19 -0400 Subject: [PATCH 32/33] - implement list creation with state management - create insertListByUser suspense function to handle loading state + API response + navigation - add navigationComplete() to reset navigation state - implement StateFlow-based navigation stat --- .../screens/lists/ListsViewModel.kt | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListsViewModel.kt b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListsViewModel.kt index 893ed77..07086c4 100644 --- a/app/src/main/java/com/example/listifyjetapp/screens/lists/ListsViewModel.kt +++ b/app/src/main/java/com/example/listifyjetapp/screens/lists/ListsViewModel.kt @@ -4,11 +4,14 @@ import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import androidx.navigation.NavController import com.example.listifyjetapp.data.ListifyResult import com.example.listifyjetapp.model.ListModel +import com.example.listifyjetapp.model.ListName import com.example.listifyjetapp.repository.ListsRepository import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import javax.inject.Inject @@ -17,6 +20,9 @@ class ListsViewModel @Inject constructor(private val repository: ListsRepository val lists = mutableStateListOf() var isLoading = mutableStateOf(false) + private val _navigateBack = MutableStateFlow(false) + val navigateBack = _navigateBack.asStateFlow() + fun getUserLists(userId: Int) { viewModelScope.launch { isLoading.value = true @@ -32,4 +38,21 @@ class ListsViewModel @Inject constructor(private val repository: ListsRepository isLoading.value = false } } + + fun insertListByUser(userId: Int, newListName: ListName) + = viewModelScope.launch { + isLoading.value = true + val result = repository.insertListByUser(userId, newListName) + when (result) { + is ListifyResult.Success -> { + _navigateBack.value = true + } + is ListifyResult.Failure -> Unit + } + isLoading.value = false + } + + fun navigationComplete() { + _navigateBack.value = false + } } \ No newline at end of file From 1b945797087049152941fb1228a7e7bf11fe7499 Mon Sep 17 00:00:00 2001 From: jiyu13 Date: Wed, 30 Jul 2025 21:37:32 -0400 Subject: [PATCH 33/33] - add LaunchedEffect to observe navigation events - implement automatic back navigation on success - connect form submission via onSaveClick() --- .../ListifyNewListScreen.kt | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) rename app/src/main/java/com/example/listifyjetapp/screens/{forms => newList}/ListifyNewListScreen.kt (60%) diff --git a/app/src/main/java/com/example/listifyjetapp/screens/forms/ListifyNewListScreen.kt b/app/src/main/java/com/example/listifyjetapp/screens/newList/ListifyNewListScreen.kt similarity index 60% rename from app/src/main/java/com/example/listifyjetapp/screens/forms/ListifyNewListScreen.kt rename to app/src/main/java/com/example/listifyjetapp/screens/newList/ListifyNewListScreen.kt index 0e8695e..73be285 100644 --- a/app/src/main/java/com/example/listifyjetapp/screens/forms/ListifyNewListScreen.kt +++ b/app/src/main/java/com/example/listifyjetapp/screens/newList/ListifyNewListScreen.kt @@ -1,34 +1,48 @@ -package com.example.listifyjetapp.screens.forms +package com.example.listifyjetapp.screens.newList import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController +import com.example.listifyjetapp.model.ListName +import com.example.listifyjetapp.screens.lists.ListsViewModel import com.example.listifyjetapp.widgets.FormInputField import com.example.listifyjetapp.widgets.ListifyTopBar @Composable fun ListifyNewListScreen( navController: NavController, - onDismiss: () -> Unit = {}, - onConfirm: () -> Unit = {} + viewModel: ListsViewModel = hiltViewModel() ) { val formTextState = remember { mutableStateOf("") } + LaunchedEffect(viewModel.navigateBack) { + viewModel.navigateBack.collect { navigateBack -> + if (navigateBack) { + navController.popBackStack() + viewModel.navigationComplete() + } + } + } + + fun onSaveClick() { + val listName = ListName(name = formTextState.value) + viewModel.insertListByUser(4, listName) + } + Scaffold( modifier = Modifier.fillMaxSize(), topBar = { ListifyTopBar( @@ -38,16 +52,23 @@ fun ListifyNewListScreen( onGoBackButtonClicked = {navController.popBackStack()}, leftText = "Cancel", rightText = "Save", - onRightButtonClick = { onConfirm() } + onRightButtonClick = { + // TODO: save new list + onSaveClick() + } ) } ) { innerPadding -> Surface( - modifier = Modifier.fillMaxSize().padding(innerPadding) + modifier = Modifier + .fillMaxSize() + .padding(innerPadding) ) { Column( - modifier = Modifier.fillMaxWidth().padding(16.dp), + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), verticalArrangement = Arrangement.spacedBy(25.dp) ) {