Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
.externalNativeBuild
.cxx
local.properties
/app/src/main/java/com/example/listifyjetapp/utils/constants/Constants.kt
10 changes: 7 additions & 3 deletions app/src/main/java/com/example/listifyjetapp/model/ListModel.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
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,
@SerializedName("shared_with") val sharedWith: List<SharedUsers>
)
17 changes: 17 additions & 0 deletions app/src/main/java/com/example/listifyjetapp/model/User.kt
Original file line number Diff line number Diff line change
@@ -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,
)

102 changes: 102 additions & 0 deletions app/src/main/java/com/example/listifyjetapp/screens/lists/ListRow.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
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 ListRow(
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(
modifier = Modifier.padding(horizontal = 8.dp),

) {
Text(
text = list.name,
color = ListifyColor.TextBlack,
fontSize = 20.sp,
//fontWeight = FontWeight.SemiBold
)

if (list.share) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
modifier = Modifier.size(16.dp),
tint = ListifyColor.IconGreen,
imageVector = Icons.Default.Share,
contentDescription = "Shared with"
)
Text(
text = list.sharedWith.take(3).joinToString(", ") { it.username },
maxLines = 1,
overflow = TextOverflow.Ellipsis,
color = ListifyColor.TextGrey,
fontSize = 16.sp
)
}
}

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()
}
Original file line number Diff line number Diff line change
@@ -1,40 +1,93 @@
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
import androidx.compose.foundation.layout.fillMaxSize
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.material3.CircularProgressIndicator
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.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

@Composable
fun ListifyListsScreen(
viewModel: ListsViewModel = hiltViewModel()
) {
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
) {

if (viewModel.lists.isEmpty()) {
Text(text = "You don't have any lists yet.")
} else {
LazyColumn {
items(viewModel.lists) {list ->
Text(text = list.name)
val searchTextState = remember { mutableStateOf("") }
val keyboardController = LocalSoftwareKeyboardController.current

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
)){
// Filter lists by search input
val results = filterListItems(searchTextState.value, viewModel.lists)

items(results) {list ->
ListRow(list)
}
}
}
}
}
}

}
Original file line number Diff line number Diff line change
@@ -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<ListModel>()
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
}
}
}
2 changes: 2 additions & 0 deletions app/src/main/java/com/example/listifyjetapp/ui/theme/Color.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Original file line number Diff line number Diff line change
@@ -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<ListModel>): List<ListModel> {

return if (input.isEmpty()) {
listItems
} else {
listItems.filter { it.name.contains(input, ignoreCase = true) }
}

}
Original file line number Diff line number Diff line change
@@ -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<String>,
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,
)
}
Loading