temporary changes. Will merge with the other branch.
This commit is contained in:
parent
80cc72bb9d
commit
4d7e8e3daf
|
|
@ -1 +0,0 @@
|
||||||
LivingAi_Lg
|
|
||||||
|
|
@ -27,6 +27,7 @@ class UserNotFoundException(
|
||||||
|
|
||||||
class AuthApiClient(private val context: Context) {
|
class AuthApiClient(private val context: Context) {
|
||||||
|
|
||||||
|
private val route = "http://10.0.2.2:3000/"
|
||||||
private val tokenManager = TokenManager(context)
|
private val tokenManager = TokenManager(context)
|
||||||
|
|
||||||
val client = HttpClient(CIO) {
|
val client = HttpClient(CIO) {
|
||||||
|
|
@ -64,7 +65,7 @@ class AuthApiClient(private val context: Context) {
|
||||||
|
|
||||||
android.util.Log.d("AuthApiClient", "refreshTokens: Calling /auth/refresh endpoint")
|
android.util.Log.d("AuthApiClient", "refreshTokens: Calling /auth/refresh endpoint")
|
||||||
try {
|
try {
|
||||||
val response: RefreshResponse = client.post("http://10.0.2.2:3000/auth/refresh") {
|
val response: RefreshResponse = client.post("${route}auth/refresh") {
|
||||||
markAsRefreshTokenRequest()
|
markAsRefreshTokenRequest()
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(RefreshRequest(refreshToken))
|
setBody(RefreshRequest(refreshToken))
|
||||||
|
|
@ -84,7 +85,7 @@ class AuthApiClient(private val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultRequest {
|
defaultRequest {
|
||||||
url("http://10.0.2.2:3000/")
|
url(route)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,87 +1,87 @@
|
||||||
package com.example.livingai_lg.ui.components
|
package com.example.livingai_lg.ui.components
|
||||||
|
|
||||||
import androidx.compose.foundation.LocalIndication
|
import androidx.compose.foundation.LocalIndication
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyRow
|
import androidx.compose.foundation.lazy.LazyRow
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.example.livingai_lg.ui.models.AnimalType
|
import com.example.livingai_lg.ui.models.AnimalType
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AnimalTypeSelector(
|
fun AnimalTypeSelector(
|
||||||
animalTypes: List<AnimalType>,
|
animalTypes: List<AnimalType>,
|
||||||
selectedAnimalType: MutableState<String?>,
|
selectedAnimalType: String?,
|
||||||
onAnimalTypeSelected: (String) -> Unit
|
onAnimalTypeSelected: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
val selectedAnimalType: String = selectedAnimalType.value ?: ""
|
val selectedAnimalType: String = selectedAnimalType ?: ""
|
||||||
|
|
||||||
LazyRow(
|
LazyRow(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
items(animalTypes.size) { index ->
|
items(animalTypes.size) { index ->
|
||||||
AnimalTypeButton(
|
AnimalTypeButton(
|
||||||
animalType = animalTypes[index],
|
animalType = animalTypes[index],
|
||||||
isSelected = selectedAnimalType == animalTypes[index].id,
|
isSelected = selectedAnimalType == animalTypes[index].id,
|
||||||
onClick = { onAnimalTypeSelected(animalTypes[index].id) }
|
onClick = { onAnimalTypeSelected(animalTypes[index].id) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun AnimalTypeButton(
|
private fun AnimalTypeButton(
|
||||||
animalType: AnimalType,
|
animalType: AnimalType,
|
||||||
isSelected: Boolean,
|
isSelected: Boolean,
|
||||||
onClick: () -> Unit
|
onClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable(
|
.clickable(
|
||||||
indication = LocalIndication.current,
|
indication = LocalIndication.current,
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
onClick = onClick
|
onClick = onClick
|
||||||
)
|
)
|
||||||
.padding(4.dp),
|
.padding(4.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(48.dp)
|
.size(48.dp)
|
||||||
.background(
|
.background(
|
||||||
if (isSelected) Color(0xFFEDE9FE) else Color.White,
|
if (isSelected) Color(0xFFEDE9FE) else Color.White,
|
||||||
RoundedCornerShape(24.dp)
|
RoundedCornerShape(24.dp)
|
||||||
),
|
),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = animalType.emoji,
|
text = animalType.emoji,
|
||||||
fontSize = 24.sp
|
fontSize = 24.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = animalType.name,
|
text = animalType.name,
|
||||||
fontSize = 12.sp,
|
fontSize = 12.sp,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
color = Color(0xFF0A0A0A),
|
color = Color(0xFF0A0A0A),
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,93 +1,103 @@
|
||||||
package com.example.livingai_lg.ui.components
|
package com.example.livingai_lg.ui.components
|
||||||
|
|
||||||
import androidx.compose.foundation.LocalIndication
|
import androidx.compose.foundation.LocalIndication
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.example.livingai_lg.ui.models.BottomNavItemData
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.livingai_lg.ui.models.BottomNavItemData
|
||||||
@Composable
|
|
||||||
fun BottomNavigationBar(
|
@Composable
|
||||||
modifier: Modifier = Modifier,
|
fun BottomNavigationBar(
|
||||||
items: List<BottomNavItemData>,
|
modifier: Modifier = Modifier,
|
||||||
currentItem: String,
|
items: List<BottomNavItemData>,
|
||||||
onItemClick: (route: String) -> Unit = {}
|
currentItem: String,
|
||||||
) {
|
onItemClick: (route: String) -> Unit = {}
|
||||||
Column(
|
) {
|
||||||
modifier = modifier
|
Column(
|
||||||
.fillMaxWidth()
|
modifier = modifier
|
||||||
.background(Color.White)
|
.fillMaxWidth()
|
||||||
.border(1.dp, Color(0xFF000000).copy(alpha = 0.1f))
|
.background(Color.White)
|
||||||
) {
|
.border(1.dp, Color(0xFF000000).copy(alpha = 0.1f))
|
||||||
Row(
|
) {
|
||||||
modifier = Modifier
|
Row(
|
||||||
.fillMaxWidth()
|
modifier = Modifier
|
||||||
.height(66.dp)
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 8.dp),
|
.height(66.dp)
|
||||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
.padding(horizontal = 8.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||||
) {
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
items.forEach { item ->
|
|
||||||
val isSelected = item.label == currentItem
|
items.forEach { item ->
|
||||||
BottomNavItem(
|
val isSelected = item.label == currentItem
|
||||||
label = item.label,
|
BottomNavItem(
|
||||||
iconRes = item.iconRes,
|
label = item.label,
|
||||||
selected = isSelected,
|
iconRes = item.iconRes,
|
||||||
onClick = {
|
selected = isSelected,
|
||||||
if (!isSelected) {
|
onClick = {
|
||||||
onItemClick(item.route)
|
if (!isSelected) {
|
||||||
}
|
onItemClick(item.route)
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Composable
|
|
||||||
fun BottomNavItem(
|
@Composable
|
||||||
label: String,
|
fun BottomNavItem(
|
||||||
iconRes: Int,
|
label: String,
|
||||||
selected: Boolean,
|
iconRes: Any,
|
||||||
onClick: () -> Unit = {}
|
selected: Boolean,
|
||||||
) {
|
onClick: () -> Unit = {}
|
||||||
val color = if (selected) Color(0xFF1E88E5) else Color(0xFF0A0A0A)
|
) {
|
||||||
|
val color = if (selected) Color(0xFF1E88E5) else Color(0xFF0A0A0A)
|
||||||
Column(
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
Column(
|
||||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
modifier = Modifier
|
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
.padding(vertical = 4.dp)
|
modifier = Modifier
|
||||||
.clickable(
|
.padding(vertical = 4.dp)
|
||||||
indication = LocalIndication.current,
|
.clickable(
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
indication = LocalIndication.current,
|
||||||
onClick = onClick)
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
) {
|
onClick = onClick)
|
||||||
Icon(
|
) {
|
||||||
painter = painterResource(iconRes),
|
if(iconRes is Int) {
|
||||||
contentDescription = label,
|
Icon(
|
||||||
tint = color,
|
painter = painterResource(iconRes),
|
||||||
modifier = Modifier.size(24.dp)
|
contentDescription = label,
|
||||||
)
|
tint = color,
|
||||||
Text(
|
modifier = Modifier.size(24.dp)
|
||||||
text = label,
|
)
|
||||||
fontSize = 12.sp,
|
} else if(iconRes is ImageVector) {
|
||||||
fontWeight = FontWeight.Medium,
|
Icon(
|
||||||
color = color
|
imageVector = iconRes,
|
||||||
)
|
contentDescription = label,
|
||||||
}
|
tint = color,
|
||||||
}
|
modifier = Modifier.size(24.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = color
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,117 +1,118 @@
|
||||||
package com.example.livingai_lg.ui.components
|
package com.example.livingai_lg.ui.components
|
||||||
|
|
||||||
import androidx.compose.foundation.LocalIndication
|
import androidx.compose.foundation.LocalIndication
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.example.livingai_lg.ui.theme.AppTypography
|
import com.example.livingai_lg.ui.theme.AppTypography
|
||||||
import com.example.livingai_lg.ui.theme.FarmTextDark
|
import com.example.livingai_lg.ui.theme.FarmTextDark
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun DropdownInput(
|
fun DropdownInput(
|
||||||
label: String? = null, // optional label
|
label: String? = null, // optional label
|
||||||
selected: String,
|
selected: String,
|
||||||
options: List<String>,
|
options: List<String>,
|
||||||
expanded: Boolean,
|
expanded: Boolean,
|
||||||
onExpandedChange: (Boolean) -> Unit,
|
onExpandedChange: (Boolean) -> Unit,
|
||||||
onSelect: (String) -> Unit,
|
onSelect: (String) -> Unit,
|
||||||
placeholder: String = "Select", // NEW - custom placeholder
|
placeholder: String = "Select", // NEW - custom placeholder
|
||||||
modifier: Modifier = Modifier // NEW - allows width control
|
textColor: Color = Color.Black,
|
||||||
) {
|
modifier: Modifier = Modifier // NEW - allows width control
|
||||||
Column(
|
) {
|
||||||
modifier = modifier, // <-- now caller can control width
|
Column(
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
modifier = modifier, // <-- now caller can control width
|
||||||
) {
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
// Optional label
|
) {
|
||||||
if (label != null) {
|
// Optional label
|
||||||
Text(
|
// if (label != null) {
|
||||||
text = label,
|
Text(
|
||||||
fontSize = AppTypography.Body,
|
text = label?:" ",
|
||||||
fontWeight = FontWeight.Medium,
|
fontSize = AppTypography.Body,
|
||||||
color = FarmTextDark
|
fontWeight = FontWeight.Medium,
|
||||||
)
|
color = FarmTextDark
|
||||||
} else {
|
)
|
||||||
// Reserve label space so layout doesn’t shift
|
// } else {
|
||||||
Spacer(modifier = Modifier.height(20.dp)) // ← same height as label text line
|
// // Reserve label space so layout doesn’t shift
|
||||||
}
|
// Spacer(modifier = Modifier.height(20.dp)) // ← same height as label text line
|
||||||
|
// }
|
||||||
ExposedDropdownMenuBox(
|
|
||||||
expanded = expanded,
|
ExposedDropdownMenuBox(
|
||||||
onExpandedChange = { onExpandedChange(!expanded) }
|
expanded = expanded,
|
||||||
) {
|
onExpandedChange = { onExpandedChange(!expanded) }
|
||||||
// Anchor box
|
) {
|
||||||
Box(
|
// Anchor box
|
||||||
modifier = Modifier
|
Box(
|
||||||
.menuAnchor()
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.menuAnchor()
|
||||||
.height(52.dp)
|
.fillMaxWidth()
|
||||||
.shadow(2.dp, RoundedCornerShape(16.dp))
|
.height(52.dp)
|
||||||
.background(Color.White, RoundedCornerShape(16.dp))
|
.shadow(2.dp, RoundedCornerShape(16.dp))
|
||||||
.border(1.dp, Color(0xFFE5E7EB), RoundedCornerShape(16.dp))
|
.background(Color.White, RoundedCornerShape(16.dp))
|
||||||
.clickable(
|
.border(1.dp, Color(0xFFE5E7EB), RoundedCornerShape(16.dp))
|
||||||
indication = LocalIndication.current,
|
.clickable(
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
indication = LocalIndication.current,
|
||||||
) {
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
onExpandedChange(true)
|
) {
|
||||||
}
|
onExpandedChange(true)
|
||||||
.padding(horizontal = 16.dp),
|
}
|
||||||
contentAlignment = Alignment.CenterStart
|
.padding(horizontal = 16.dp),
|
||||||
) {
|
contentAlignment = Alignment.CenterStart
|
||||||
Row(
|
) {
|
||||||
modifier = Modifier.fillMaxWidth(),
|
Row(
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
modifier = Modifier.fillMaxWidth(),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
) {
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
// Custom placeholder support
|
|
||||||
Text(
|
// Custom placeholder support
|
||||||
text = selected.ifEmpty { placeholder },
|
Text(
|
||||||
fontSize = AppTypography.Body,
|
text = selected.ifEmpty { placeholder },
|
||||||
color = if (selected.isEmpty()) Color(0xFF99A1AF) else FarmTextDark
|
fontSize = AppTypography.Body,
|
||||||
)
|
color = if (selected.isEmpty()) Color(0xFF99A1AF) else textColor
|
||||||
|
)
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.ArrowDropDown,
|
Icon(
|
||||||
contentDescription = "Dropdown",
|
imageVector = Icons.Default.ArrowDropDown,
|
||||||
tint = FarmTextDark
|
contentDescription = "Dropdown",
|
||||||
)
|
tint = FarmTextDark
|
||||||
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Material3 Dropdown
|
|
||||||
ExposedDropdownMenu(
|
// Material3 Dropdown
|
||||||
expanded = expanded,
|
ExposedDropdownMenu(
|
||||||
onDismissRequest = { onExpandedChange(false) },
|
expanded = expanded,
|
||||||
modifier = Modifier.background(Color.White)
|
onDismissRequest = { onExpandedChange(false) },
|
||||||
) {
|
modifier = Modifier.background(Color.White)
|
||||||
options.forEach { item ->
|
) {
|
||||||
DropdownMenuItem(
|
options.forEach { item ->
|
||||||
text = {
|
DropdownMenuItem(
|
||||||
Text(item, fontSize = AppTypography.Body, color = FarmTextDark)
|
text = {
|
||||||
},
|
Text(item, fontSize = AppTypography.Body, color = FarmTextDark)
|
||||||
onClick = {
|
},
|
||||||
onSelect(item)
|
onClick = {
|
||||||
onExpandedChange(false)
|
onSelect(item)
|
||||||
}
|
onExpandedChange(false)
|
||||||
)
|
}
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,77 @@
|
||||||
package com.example.livingai_lg.ui.components
|
package com.example.livingai_lg.ui.components
|
||||||
|
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.fadeOut
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.animation.slideInHorizontally
|
import androidx.compose.animation.slideInHorizontally
|
||||||
import androidx.compose.animation.slideInVertically
|
import androidx.compose.animation.slideInVertically
|
||||||
import androidx.compose.animation.slideOutHorizontally
|
import androidx.compose.animation.slideOutHorizontally
|
||||||
import androidx.compose.animation.slideOutVertically
|
import androidx.compose.animation.slideOutVertically
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.example.livingai_lg.ui.screens.FilterScreen
|
import com.example.livingai_lg.ui.models.FiltersState
|
||||||
|
import com.example.livingai_lg.ui.screens.FilterScreen
|
||||||
@Composable
|
|
||||||
fun FilterOverlay(
|
@Composable
|
||||||
visible: Boolean,
|
fun FilterOverlay(
|
||||||
onDismiss: () -> Unit,
|
visible: Boolean,
|
||||||
onSubmitClick: () -> Unit = {},
|
appliedFilters: FiltersState,
|
||||||
) {
|
onDismiss: () -> Unit,
|
||||||
BackHandler(enabled = visible) { onDismiss() }
|
onSubmitClick: (filters: FiltersState) -> Unit = {},
|
||||||
|
) {
|
||||||
Box(
|
BackHandler(enabled = visible) { onDismiss() }
|
||||||
modifier = Modifier.fillMaxSize()
|
|
||||||
) {
|
Box(
|
||||||
// Dimmed background
|
modifier = Modifier.fillMaxSize()
|
||||||
AnimatedVisibility(
|
) {
|
||||||
visible = visible,
|
// Dimmed background
|
||||||
enter = fadeIn(),
|
AnimatedVisibility(
|
||||||
exit = fadeOut()
|
visible = visible,
|
||||||
) {
|
enter = fadeIn(),
|
||||||
Box(
|
exit = fadeOut()
|
||||||
modifier = Modifier
|
) {
|
||||||
.fillMaxSize()
|
Box(
|
||||||
.background(Color.Black.copy(alpha = 0.35f))
|
modifier = Modifier
|
||||||
.clickable(
|
.fillMaxSize()
|
||||||
indication = null,
|
.background(Color.Black.copy(alpha = 0.35f))
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
.clickable(
|
||||||
) { onDismiss() }
|
indication = null,
|
||||||
)
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
}
|
) { onDismiss() }
|
||||||
|
)
|
||||||
// Sliding panel
|
}
|
||||||
AnimatedVisibility(
|
|
||||||
visible = visible,
|
// Sliding panel
|
||||||
enter = slideInHorizontally(
|
AnimatedVisibility(
|
||||||
initialOffsetX = { it } // from right
|
visible = visible,
|
||||||
),
|
enter = slideInHorizontally(
|
||||||
exit = slideOutHorizontally(
|
initialOffsetX = { it } // from right
|
||||||
targetOffsetX = { it } // to right
|
),
|
||||||
),
|
exit = slideOutHorizontally(
|
||||||
modifier = Modifier
|
targetOffsetX = { it } // to right
|
||||||
.fillMaxHeight()
|
),
|
||||||
.align(Alignment.CenterEnd)
|
modifier = Modifier
|
||||||
) {
|
.fillMaxHeight()
|
||||||
FilterScreen(
|
.align(Alignment.CenterEnd)
|
||||||
onBackClick = onDismiss,
|
) {
|
||||||
onCancelClick = onDismiss,
|
FilterScreen(
|
||||||
onSubmitClick = {
|
appliedFilters,
|
||||||
onSubmitClick()
|
onBackClick = onDismiss,
|
||||||
onDismiss()
|
onCancelClick = onDismiss,
|
||||||
}
|
onSubmitClick = { filters ->
|
||||||
)
|
onSubmitClick(filters)
|
||||||
}
|
onDismiss()
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,137 +1,142 @@
|
||||||
package com.example.livingai_lg.ui.components
|
package com.example.livingai_lg.ui.components
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RangeFilter(
|
fun RangeFilter(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
|
||||||
label: String,
|
label: String,
|
||||||
min: Int,
|
min: Int,
|
||||||
max: Int,
|
max: Int,
|
||||||
valueFrom: Int,
|
valueFrom: Int,
|
||||||
valueTo: Int,
|
valueTo: Int,
|
||||||
onValueChange: (from: Int, to: Int) -> Unit,
|
modified: Boolean = false,
|
||||||
showSlider: Boolean = true,
|
onValueChange: (from: Int, to: Int) -> Unit,
|
||||||
valueFormatter: (Int) -> String = { it.toString() }
|
showSlider: Boolean = true,
|
||||||
) {
|
valueFormatter: (Int) -> String = { it.toString() }
|
||||||
var fromValue by remember(valueFrom) { mutableStateOf(valueFrom) }
|
) {
|
||||||
var toValue by remember(valueTo) { mutableStateOf(valueTo) }
|
var fromValue by remember(valueFrom) { mutableStateOf(valueFrom) }
|
||||||
|
var toValue by remember(valueTo) { mutableStateOf(valueTo) }
|
||||||
Column(modifier = modifier,
|
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
Column(modifier = modifier,
|
||||||
|
verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||||
// Label
|
|
||||||
Text(
|
// Label
|
||||||
text = label,
|
Text(
|
||||||
fontSize = 16.sp,
|
text = label,
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontSize = 16.sp,
|
||||||
color = Color(0xFF364153)
|
fontWeight = FontWeight.SemiBold,
|
||||||
)
|
color = Color(0xFF364153)
|
||||||
|
)
|
||||||
// Slider (optional)
|
|
||||||
if (showSlider) {
|
// Slider (optional)
|
||||||
RangeSlider(
|
if (showSlider) {
|
||||||
value = fromValue.toFloat()..toValue.toFloat(),
|
RangeSlider(
|
||||||
onValueChange = { range ->
|
value = fromValue.toFloat()..toValue.toFloat(),
|
||||||
fromValue = range.start.roundToInt()
|
onValueChange = { range ->
|
||||||
.coerceIn(min, toValue)
|
fromValue = range.start.roundToInt()
|
||||||
toValue = range.endInclusive.roundToInt()
|
.coerceIn(min, toValue)
|
||||||
.coerceIn(fromValue, max)
|
toValue = range.endInclusive.roundToInt()
|
||||||
|
.coerceIn(fromValue, max)
|
||||||
onValueChange(fromValue, toValue)
|
|
||||||
},
|
onValueChange(fromValue, toValue)
|
||||||
valueRange = min.toFloat()..max.toFloat(),
|
},
|
||||||
colors = SliderDefaults.colors(
|
valueRange = min.toFloat()..max.toFloat(),
|
||||||
thumbColor = Color(0xFFD9D9D9),
|
colors = SliderDefaults.colors(
|
||||||
activeTrackColor = Color(0xFFD9D9D9),
|
thumbColor = Color(0xFFD9D9D9),
|
||||||
inactiveTrackColor = Color(0xFFE5E7EB)
|
activeTrackColor = Color(0xFFD9D9D9),
|
||||||
)
|
inactiveTrackColor = Color(0xFFE5E7EB)
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
|
}
|
||||||
// Pills
|
|
||||||
Row(
|
// Pills
|
||||||
modifier = Modifier.fillMaxWidth(),
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
) {
|
verticalAlignment = Alignment.CenterVertically
|
||||||
RangePill(
|
) {
|
||||||
modifier = Modifier.weight(1f),
|
RangePill(
|
||||||
value = fromValue,
|
modifier = Modifier.weight(1f),
|
||||||
onValueChange = { newFrom ->
|
value = fromValue,
|
||||||
val safeFrom = newFrom.coerceIn(min, toValue)
|
modified = modified,
|
||||||
fromValue = safeFrom
|
onValueChange = { newFrom ->
|
||||||
onValueChange(safeFrom, toValue)
|
val safeFrom = newFrom.coerceIn(min, toValue)
|
||||||
},
|
fromValue = safeFrom
|
||||||
formatter = valueFormatter
|
onValueChange(safeFrom, toValue)
|
||||||
)
|
},
|
||||||
|
formatter = valueFormatter
|
||||||
Text("to", fontSize = 15.sp)
|
)
|
||||||
|
|
||||||
RangePill(
|
Text("to", fontSize = 15.sp)
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
value = toValue,
|
RangePill(
|
||||||
onValueChange = { newTo ->
|
modifier = Modifier.weight(1f),
|
||||||
val safeTo = newTo.coerceIn(fromValue, max)
|
value = toValue,
|
||||||
toValue = safeTo
|
modified = modified,
|
||||||
onValueChange(fromValue, safeTo)
|
onValueChange = { newTo ->
|
||||||
},
|
val safeTo = newTo.coerceIn(fromValue, max)
|
||||||
formatter = valueFormatter
|
toValue = safeTo
|
||||||
)
|
onValueChange(fromValue, safeTo)
|
||||||
}
|
},
|
||||||
|
formatter = valueFormatter
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
}
|
||||||
private fun RangePill(
|
}
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
value: Int,
|
@Composable
|
||||||
onValueChange: (Int) -> Unit,
|
private fun RangePill(
|
||||||
formatter: (Int) -> String
|
modifier: Modifier = Modifier,
|
||||||
) {
|
value: Int,
|
||||||
var text by remember(value) {
|
modified: Boolean = false,
|
||||||
mutableStateOf(formatter(value))
|
onValueChange: (Int) -> Unit,
|
||||||
}
|
formatter: (Int) -> String
|
||||||
|
) {
|
||||||
Box(
|
var text by remember(value) {
|
||||||
modifier = modifier
|
mutableStateOf(formatter(value))
|
||||||
.height(30.dp)
|
}
|
||||||
.background(Color.White, RoundedCornerShape(16.dp))
|
|
||||||
.border(1.dp, Color(0x12000000), RoundedCornerShape(16.dp))
|
Box(
|
||||||
.padding(horizontal = 8.dp),
|
modifier = modifier
|
||||||
contentAlignment = Alignment.Center
|
.height(30.dp)
|
||||||
) {
|
.background(Color.White, RoundedCornerShape(16.dp))
|
||||||
BasicTextField(
|
.border(1.dp, Color(0x12000000), RoundedCornerShape(16.dp))
|
||||||
value = text,
|
.padding(horizontal = 8.dp),
|
||||||
onValueChange = { input ->
|
contentAlignment = Alignment.Center
|
||||||
val digits = input.filter { it.isDigit() }
|
) {
|
||||||
text = digits
|
var modified = modified;
|
||||||
digits.toIntOrNull()?.let(onValueChange)
|
BasicTextField(
|
||||||
},
|
value = text,
|
||||||
singleLine = true,
|
onValueChange = { input ->
|
||||||
textStyle = TextStyle(
|
val digits = input.filter { it.isDigit() }
|
||||||
fontSize = 14.sp,
|
text = digits
|
||||||
color = Color(0xFF99A1AF)
|
digits.toIntOrNull()?.let(onValueChange)
|
||||||
),
|
},
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
|
singleLine = true,
|
||||||
)
|
textStyle = TextStyle(
|
||||||
}
|
fontSize = 14.sp,
|
||||||
}
|
color = if(modified) Color.Black else Color(0xFF99A1AF)
|
||||||
|
),
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
package com.example.livingai_lg.ui.components
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.slideInVertically
|
||||||
|
import androidx.compose.animation.slideOutVertically
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
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.material3.Button
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
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.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun WishlistNameOverlay(
|
||||||
|
onSave: (String) -> Unit,
|
||||||
|
onDismiss: () -> Unit
|
||||||
|
) {
|
||||||
|
var name by remember { mutableStateOf("") }
|
||||||
|
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = true,
|
||||||
|
enter = slideInVertically { -it },
|
||||||
|
exit = slideOutVertically { -it }
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.White)
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||||
|
Text(
|
||||||
|
text = "Save Filters",
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.SemiBold
|
||||||
|
)
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = name,
|
||||||
|
onValueChange = { name = it },
|
||||||
|
placeholder = { Text("Wishlist name") },
|
||||||
|
singleLine = true
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.End,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
TextButton(onClick = onDismiss) {
|
||||||
|
Text("Cancel")
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
if (name.isNotBlank()) {
|
||||||
|
onSave(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("Save")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,25 +1,28 @@
|
||||||
package com.example.livingai_lg.ui.models
|
package com.example.livingai_lg.ui.models
|
||||||
|
|
||||||
import com.example.livingai_lg.R
|
import androidx.compose.material.icons.Icons
|
||||||
import com.example.livingai_lg.ui.navigation.AppScreen
|
import androidx.compose.material.icons.outlined.Build
|
||||||
|
import androidx.compose.material.icons.outlined.Home
|
||||||
data class BottomNavItemData(
|
import com.example.livingai_lg.R
|
||||||
val label: String,
|
import com.example.livingai_lg.ui.navigation.AppScreen
|
||||||
val iconRes: Int,
|
|
||||||
val route: String,
|
data class BottomNavItemData(
|
||||||
)
|
val label: String,
|
||||||
|
val iconRes: Any,
|
||||||
val mainBottomNavItems = listOf(
|
val route: String,
|
||||||
BottomNavItemData("Home", R.drawable.ic_home , AppScreen.BUY_ANIMALS),
|
)
|
||||||
BottomNavItemData("Sell", R.drawable.ic_tag, AppScreen.CREATE_ANIMAL_LISTING),
|
|
||||||
// TODO:
|
val mainBottomNavItems = listOf(
|
||||||
BottomNavItemData("Chats", R.drawable.ic_chat, AppScreen.CHATS),
|
BottomNavItemData("Home", R.drawable.ic_home , AppScreen.BUY_ANIMALS),
|
||||||
BottomNavItemData("Services", R.drawable.ic_config, AppScreen.CREATE_PROFILE),
|
BottomNavItemData("Sell", R.drawable.ic_tag, AppScreen.CREATE_ANIMAL_LISTING),
|
||||||
BottomNavItemData("Mandi", R.drawable.ic_market, AppScreen.CREATE_PROFILE)
|
// TODO:
|
||||||
)
|
BottomNavItemData("Chats", R.drawable.ic_chat, AppScreen.CHATS),
|
||||||
|
BottomNavItemData("Services", R.drawable.ic_config, AppScreen.CREATE_PROFILE),
|
||||||
val chatBottomNavItems = listOf(
|
BottomNavItemData("Mandi", R.drawable.ic_shop2, AppScreen.CREATE_PROFILE)
|
||||||
BottomNavItemData("Contacts", R.drawable.ic_home ,"home"),
|
)
|
||||||
BottomNavItemData("Calls", R.drawable.ic_tag, "sell"),
|
|
||||||
BottomNavItemData("Chats", R.drawable.ic_chat, "chats"),
|
val chatBottomNavItems = listOf(
|
||||||
)
|
BottomNavItemData("Contacts", R.drawable.ic_home ,AppScreen.CONTACTS),
|
||||||
|
BottomNavItemData("Calls", R.drawable.ic_tag, AppScreen.CALLS),
|
||||||
|
BottomNavItemData("Chats", R.drawable.ic_chat, AppScreen.CHATS),
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.example.livingai_lg.ui.models
|
||||||
|
|
||||||
|
data class TextFilter(
|
||||||
|
val value: String = "",
|
||||||
|
val filterSet: Boolean = false
|
||||||
|
)
|
||||||
|
|
||||||
|
data class RangeFilterState(
|
||||||
|
val min: Int,
|
||||||
|
val max: Int,
|
||||||
|
val filterSet: Boolean = false
|
||||||
|
)
|
||||||
|
|
||||||
|
data class FiltersState(
|
||||||
|
val animal: TextFilter = TextFilter(),
|
||||||
|
val breed: TextFilter = TextFilter(),
|
||||||
|
val distance: TextFilter = TextFilter(),
|
||||||
|
val gender: TextFilter = TextFilter(),
|
||||||
|
|
||||||
|
val price: RangeFilterState = RangeFilterState(0, 90_000),
|
||||||
|
val age: RangeFilterState = RangeFilterState(0, 20),
|
||||||
|
val weight: RangeFilterState = RangeFilterState(0, 9_000),
|
||||||
|
val milkYield: RangeFilterState = RangeFilterState(0, 900),
|
||||||
|
|
||||||
|
val pregnancyStatuses: Set<String> = emptySet(),
|
||||||
|
|
||||||
|
val calving: RangeFilterState = RangeFilterState(0, 10)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
fun FiltersState.isDefault(): Boolean {
|
||||||
|
return animal.filterSet.not() &&
|
||||||
|
breed.filterSet.not() &&
|
||||||
|
distance.filterSet.not() &&
|
||||||
|
gender.filterSet.not() &&
|
||||||
|
price.filterSet.not() &&
|
||||||
|
age.filterSet.not() &&
|
||||||
|
weight.filterSet.not() &&
|
||||||
|
milkYield.filterSet.not() &&
|
||||||
|
pregnancyStatuses.isEmpty() &&
|
||||||
|
calving.filterSet.not()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.example.livingai_lg.ui.models
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
data class WishlistEntry(
|
||||||
|
val id: String = UUID.randomUUID().toString(),
|
||||||
|
val name: String,
|
||||||
|
val filters: FiltersState,
|
||||||
|
val createdAt: Long = System.currentTimeMillis()
|
||||||
|
)
|
||||||
|
|
||||||
|
object WishlistStore {
|
||||||
|
|
||||||
|
private val _wishlist =
|
||||||
|
MutableStateFlow<List<WishlistEntry>>(emptyList())
|
||||||
|
|
||||||
|
val wishlist: StateFlow<List<WishlistEntry>> = _wishlist
|
||||||
|
|
||||||
|
fun add(entry: WishlistEntry) {
|
||||||
|
_wishlist.value = _wishlist.value + entry
|
||||||
|
}
|
||||||
|
|
||||||
|
fun remove(id: String) {
|
||||||
|
_wishlist.value = _wishlist.value.filterNot { it.id == id }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clear() {
|
||||||
|
_wishlist.value = emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,327 +1,336 @@
|
||||||
package com.example.farmmarketplace.ui.screens
|
package com.example.farmmarketplace.ui.screens
|
||||||
|
|
||||||
import androidx.compose.foundation.LocalIndication
|
import androidx.compose.foundation.LocalIndication
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.automirrored.filled.CallMade
|
import androidx.compose.material.icons.automirrored.filled.CallMade
|
||||||
import androidx.compose.material.icons.automirrored.filled.CallMissed
|
import androidx.compose.material.icons.automirrored.filled.CallMissed
|
||||||
import androidx.compose.material.icons.automirrored.filled.CallReceived
|
import androidx.compose.material.icons.automirrored.filled.CallReceived
|
||||||
import androidx.compose.material.icons.filled.*
|
import androidx.compose.material.icons.filled.*
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.livingai_lg.ui.layout.BottomNavScaffold
|
||||||
data class CallRecord(
|
import com.example.livingai_lg.ui.models.chatBottomNavItems
|
||||||
val id: String,
|
|
||||||
val name: String,
|
data class CallRecord(
|
||||||
val initials: String,
|
val id: String,
|
||||||
val callType: CallType,
|
val name: String,
|
||||||
val duration: String,
|
val initials: String,
|
||||||
val timestamp: String,
|
val callType: CallType,
|
||||||
val isVideoCall: Boolean = false
|
val duration: String,
|
||||||
)
|
val timestamp: String,
|
||||||
|
val isVideoCall: Boolean = false
|
||||||
enum class CallType {
|
)
|
||||||
INCOMING,
|
|
||||||
OUTGOING,
|
enum class CallType {
|
||||||
MISSED
|
INCOMING,
|
||||||
}
|
OUTGOING,
|
||||||
|
MISSED
|
||||||
@Composable
|
}
|
||||||
fun CallsScreen(
|
|
||||||
onBackClick: () -> Unit = {},
|
@Composable
|
||||||
onCallClick: () -> Unit = {},
|
fun CallsScreen(
|
||||||
onMenuClick: () -> Unit = {},
|
onBackClick: () -> Unit = {},
|
||||||
onCallItemClick: (String) -> Unit = {},
|
onCallClick: () -> Unit = {},
|
||||||
onTabClick: (route: String) -> Unit = {}
|
onMenuClick: () -> Unit = {},
|
||||||
) {
|
onCallItemClick: (String) -> Unit = {},
|
||||||
val callHistory = listOf(
|
onTabClick: (route: String) -> Unit = {}
|
||||||
CallRecord(
|
) {
|
||||||
id = "1",
|
val callHistory = listOf(
|
||||||
name = "Farmer Kumar",
|
CallRecord(
|
||||||
initials = "FK",
|
id = "1",
|
||||||
callType = CallType.INCOMING,
|
name = "Farmer Kumar",
|
||||||
duration = "5m 23s",
|
initials = "FK",
|
||||||
timestamp = "Today, 2:30 PM"
|
callType = CallType.INCOMING,
|
||||||
),
|
duration = "5m 23s",
|
||||||
CallRecord(
|
timestamp = "Today, 2:30 PM"
|
||||||
id = "2",
|
),
|
||||||
name = "Seller Raj",
|
CallRecord(
|
||||||
initials = "SR",
|
id = "2",
|
||||||
callType = CallType.OUTGOING,
|
name = "Seller Raj",
|
||||||
duration = "2m 10s",
|
initials = "SR",
|
||||||
timestamp = "Today, 11:45 AM"
|
callType = CallType.OUTGOING,
|
||||||
),
|
duration = "2m 10s",
|
||||||
CallRecord(
|
timestamp = "Today, 11:45 AM"
|
||||||
id = "3",
|
),
|
||||||
name = "Buyer Priya",
|
CallRecord(
|
||||||
initials = "BP",
|
id = "3",
|
||||||
callType = CallType.MISSED,
|
name = "Buyer Priya",
|
||||||
duration = "",
|
initials = "BP",
|
||||||
timestamp = "Yesterday, 8:15 PM"
|
callType = CallType.MISSED,
|
||||||
),
|
duration = "",
|
||||||
CallRecord(
|
timestamp = "Yesterday, 8:15 PM"
|
||||||
id = "4",
|
),
|
||||||
name = "Seller 1",
|
CallRecord(
|
||||||
initials = "S1",
|
id = "4",
|
||||||
callType = CallType.OUTGOING,
|
name = "Seller 1",
|
||||||
duration = "8m 45s",
|
initials = "S1",
|
||||||
timestamp = "Yesterday, 5:30 PM",
|
callType = CallType.OUTGOING,
|
||||||
isVideoCall = true
|
duration = "8m 45s",
|
||||||
),
|
timestamp = "Yesterday, 5:30 PM",
|
||||||
CallRecord(
|
isVideoCall = true
|
||||||
id = "5",
|
),
|
||||||
name = "Veterinarian",
|
CallRecord(
|
||||||
initials = "V",
|
id = "5",
|
||||||
callType = CallType.INCOMING,
|
name = "Veterinarian",
|
||||||
duration = "12m 30s",
|
initials = "V",
|
||||||
timestamp = "2 days ago"
|
callType = CallType.INCOMING,
|
||||||
)
|
duration = "12m 30s",
|
||||||
)
|
timestamp = "2 days ago"
|
||||||
|
)
|
||||||
Box(
|
)
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
Box(
|
||||||
.background(Color(0xFFFCFBF8))
|
modifier = Modifier
|
||||||
) {
|
.fillMaxSize()
|
||||||
Column(
|
.background(Color(0xFFFCFBF8))
|
||||||
modifier = Modifier.fillMaxSize()
|
) {
|
||||||
) {
|
BottomNavScaffold(
|
||||||
CallsHeader(
|
items = chatBottomNavItems,
|
||||||
onBackClick = onBackClick,
|
currentItem = "Calls",
|
||||||
onCallClick = onCallClick,
|
onBottomNavItemClick = onTabClick,
|
||||||
onMenuClick = onMenuClick
|
) { paddingValues ->
|
||||||
)
|
|
||||||
|
Column(
|
||||||
LazyColumn(
|
modifier = Modifier.fillMaxSize().padding(paddingValues)
|
||||||
modifier = Modifier
|
) {
|
||||||
.fillMaxWidth()
|
CallsHeader(
|
||||||
.weight(1f)
|
onBackClick = onBackClick,
|
||||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
onCallClick = onCallClick,
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
onMenuClick = onMenuClick
|
||||||
) {
|
)
|
||||||
items(callHistory) { call ->
|
|
||||||
CallHistoryItem(
|
LazyColumn(
|
||||||
call = call,
|
modifier = Modifier
|
||||||
onClick = { onCallItemClick(call.id) }
|
.fillMaxWidth()
|
||||||
)
|
.weight(1f)
|
||||||
}
|
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||||
}
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
ContactsBottomNav(
|
items(callHistory) { call ->
|
||||||
currentTab = ContactsTab.CALLS,
|
CallHistoryItem(
|
||||||
onTabClick = onTabClick
|
call = call,
|
||||||
)
|
onClick = { onCallItemClick(call.id) }
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
// ContactsBottomNav(
|
||||||
fun CallsHeader(
|
// currentTab = ContactsTab.CALLS,
|
||||||
onBackClick: () -> Unit,
|
// onTabClick = onTabClick
|
||||||
onCallClick: () -> Unit,
|
// )
|
||||||
onMenuClick: () -> Unit,
|
}
|
||||||
modifier: Modifier = Modifier
|
}
|
||||||
) {
|
}
|
||||||
Column(
|
}
|
||||||
modifier = modifier
|
|
||||||
.fillMaxWidth()
|
@Composable
|
||||||
.height(65.dp)
|
fun CallsHeader(
|
||||||
.border(
|
onBackClick: () -> Unit,
|
||||||
width = 1.078.dp,
|
onCallClick: () -> Unit,
|
||||||
color = Color(0xFF000000).copy(alpha = 0.1f)
|
onMenuClick: () -> Unit,
|
||||||
)
|
modifier: Modifier = Modifier
|
||||||
.background(Color(0xFFFCFBF8))
|
) {
|
||||||
) {
|
Column(
|
||||||
Row(
|
modifier = modifier
|
||||||
modifier = Modifier
|
.fillMaxWidth()
|
||||||
.fillMaxWidth()
|
.height(65.dp)
|
||||||
.padding(horizontal = 14.dp, vertical = 10.dp),
|
.border(
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
width = 1.078.dp,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
color = Color(0xFF000000).copy(alpha = 0.1f)
|
||||||
) {
|
)
|
||||||
Row(
|
.background(Color(0xFFFCFBF8))
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
) {
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
Row(
|
||||||
) {
|
modifier = Modifier
|
||||||
Icon(
|
.fillMaxWidth()
|
||||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
.padding(horizontal = 14.dp, vertical = 10.dp),
|
||||||
contentDescription = "Back",
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
tint = Color(0xFF0A0A0A),
|
verticalAlignment = Alignment.CenterVertically
|
||||||
modifier = Modifier
|
) {
|
||||||
.size(26.dp)
|
Row(
|
||||||
.clickable(
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
indication = LocalIndication.current,
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
) {
|
||||||
) { onBackClick() }
|
Icon(
|
||||||
)
|
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
|
contentDescription = "Back",
|
||||||
Text(
|
tint = Color(0xFF0A0A0A),
|
||||||
text = "Calls",
|
modifier = Modifier
|
||||||
fontSize = 24.sp,
|
.size(26.dp)
|
||||||
fontWeight = FontWeight.Medium,
|
.clickable(
|
||||||
color = Color(0xFF0A0A0A),
|
indication = LocalIndication.current,
|
||||||
lineHeight = 42.sp
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
)
|
) { onBackClick() }
|
||||||
}
|
)
|
||||||
|
|
||||||
Row(
|
Text(
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
text = "Calls",
|
||||||
verticalAlignment = Alignment.CenterVertically
|
fontSize = 24.sp,
|
||||||
) {
|
fontWeight = FontWeight.Medium,
|
||||||
Icon(
|
color = Color(0xFF0A0A0A),
|
||||||
imageVector = Icons.Default.Phone,
|
lineHeight = 42.sp
|
||||||
contentDescription = "New Call",
|
)
|
||||||
tint = Color(0xFF0A0A0A),
|
}
|
||||||
modifier = Modifier
|
|
||||||
.size(20.dp)
|
Row(
|
||||||
.clickable(
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
indication = LocalIndication.current,
|
verticalAlignment = Alignment.CenterVertically
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
) {
|
||||||
) { onCallClick() }
|
Icon(
|
||||||
)
|
imageVector = Icons.Default.Phone,
|
||||||
|
contentDescription = "New Call",
|
||||||
Icon(
|
tint = Color(0xFF0A0A0A),
|
||||||
imageVector = Icons.Default.MoreVert,
|
modifier = Modifier
|
||||||
contentDescription = "Menu",
|
.size(20.dp)
|
||||||
tint = Color(0xFF0A0A0A),
|
.clickable(
|
||||||
modifier = Modifier
|
indication = LocalIndication.current,
|
||||||
.size(20.dp)
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
.clickable(
|
) { onCallClick() }
|
||||||
indication = LocalIndication.current,
|
)
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
|
||||||
) { onMenuClick() }
|
Icon(
|
||||||
)
|
imageVector = Icons.Default.MoreVert,
|
||||||
}
|
contentDescription = "Menu",
|
||||||
}
|
tint = Color(0xFF0A0A0A),
|
||||||
}
|
modifier = Modifier
|
||||||
}
|
.size(20.dp)
|
||||||
|
.clickable(
|
||||||
@Composable
|
indication = LocalIndication.current,
|
||||||
fun CallHistoryItem(
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
call: CallRecord,
|
) { onMenuClick() }
|
||||||
onClick: () -> Unit,
|
)
|
||||||
modifier: Modifier = Modifier
|
}
|
||||||
) {
|
}
|
||||||
Row(
|
}
|
||||||
modifier = modifier
|
}
|
||||||
.fillMaxWidth()
|
|
||||||
.height(76.dp)
|
@Composable
|
||||||
.border(
|
fun CallHistoryItem(
|
||||||
width = 1.078.dp,
|
call: CallRecord,
|
||||||
color = Color(0xFF000000).copy(alpha = 0.1f),
|
onClick: () -> Unit,
|
||||||
shape = RoundedCornerShape(12.dp)
|
modifier: Modifier = Modifier
|
||||||
)
|
) {
|
||||||
.background(Color(0xFFFCFBF8), RoundedCornerShape(12.dp))
|
Row(
|
||||||
.clickable(
|
modifier = modifier
|
||||||
indication = LocalIndication.current,
|
.fillMaxWidth()
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
.height(76.dp)
|
||||||
) { onClick() }
|
.border(
|
||||||
.padding(horizontal = 16.dp, vertical = 14.dp),
|
width = 1.078.dp,
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
color = Color(0xFF000000).copy(alpha = 0.1f),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
shape = RoundedCornerShape(12.dp)
|
||||||
) {
|
)
|
||||||
Row(
|
.background(Color(0xFFFCFBF8), RoundedCornerShape(12.dp))
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
.clickable(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
indication = LocalIndication.current,
|
||||||
modifier = Modifier.weight(1f)
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
) {
|
) { onClick() }
|
||||||
Box(
|
.padding(horizontal = 16.dp, vertical = 14.dp),
|
||||||
modifier = Modifier
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
.size(48.dp)
|
verticalAlignment = Alignment.CenterVertically
|
||||||
.background(Color(0xFFE5E7EB), CircleShape),
|
) {
|
||||||
contentAlignment = Alignment.Center
|
Row(
|
||||||
) {
|
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
Text(
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
text = call.initials,
|
modifier = Modifier.weight(1f)
|
||||||
fontSize = 14.sp,
|
) {
|
||||||
fontWeight = FontWeight.Medium,
|
Box(
|
||||||
color = Color(0xFF0A0A0A),
|
modifier = Modifier
|
||||||
lineHeight = 21.sp
|
.size(48.dp)
|
||||||
)
|
.background(Color(0xFFE5E7EB), CircleShape),
|
||||||
}
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
Column(
|
Text(
|
||||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
text = call.initials,
|
||||||
) {
|
fontSize = 14.sp,
|
||||||
Text(
|
fontWeight = FontWeight.Medium,
|
||||||
text = call.name,
|
color = Color(0xFF0A0A0A),
|
||||||
fontSize = 16.sp,
|
lineHeight = 21.sp
|
||||||
fontWeight = FontWeight.Medium,
|
)
|
||||||
color = Color(0xFF1E2939),
|
}
|
||||||
lineHeight = 20.sp,
|
|
||||||
letterSpacing = (-0.312).sp
|
Column(
|
||||||
)
|
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
|
) {
|
||||||
Row(
|
Text(
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
text = call.name,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
fontSize = 16.sp,
|
||||||
) {
|
fontWeight = FontWeight.Medium,
|
||||||
Icon(
|
color = Color(0xFF1E2939),
|
||||||
imageVector = when (call.callType) {
|
lineHeight = 20.sp,
|
||||||
CallType.INCOMING -> Icons.AutoMirrored.Filled.CallReceived
|
letterSpacing = (-0.312).sp
|
||||||
CallType.OUTGOING -> Icons.AutoMirrored.Filled.CallMade
|
)
|
||||||
CallType.MISSED -> Icons.AutoMirrored.Filled.CallMissed
|
|
||||||
},
|
Row(
|
||||||
contentDescription = call.callType.name,
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
tint = when (call.callType) {
|
verticalAlignment = Alignment.CenterVertically
|
||||||
CallType.INCOMING -> Color(0xFF00A63E)
|
) {
|
||||||
CallType.OUTGOING -> Color(0xFF155DFC)
|
Icon(
|
||||||
CallType.MISSED -> Color(0xFFE7000B)
|
imageVector = when (call.callType) {
|
||||||
},
|
CallType.INCOMING -> Icons.AutoMirrored.Filled.CallReceived
|
||||||
modifier = Modifier.size(20.dp)
|
CallType.OUTGOING -> Icons.AutoMirrored.Filled.CallMade
|
||||||
)
|
CallType.MISSED -> Icons.AutoMirrored.Filled.CallMissed
|
||||||
|
},
|
||||||
Text(
|
contentDescription = call.callType.name,
|
||||||
text = when (call.callType) {
|
tint = when (call.callType) {
|
||||||
CallType.INCOMING -> "Incoming • ${call.duration}"
|
CallType.INCOMING -> Color(0xFF00A63E)
|
||||||
CallType.OUTGOING -> "Outgoing • ${call.duration}"
|
CallType.OUTGOING -> Color(0xFF155DFC)
|
||||||
CallType.MISSED -> "Missed"
|
CallType.MISSED -> Color(0xFFE7000B)
|
||||||
},
|
},
|
||||||
fontSize = 12.sp,
|
modifier = Modifier.size(20.dp)
|
||||||
fontWeight = FontWeight.Normal,
|
)
|
||||||
color = Color(0xFF717182),
|
|
||||||
lineHeight = 16.sp
|
Text(
|
||||||
)
|
text = when (call.callType) {
|
||||||
}
|
CallType.INCOMING -> "Incoming • ${call.duration}"
|
||||||
}
|
CallType.OUTGOING -> "Outgoing • ${call.duration}"
|
||||||
}
|
CallType.MISSED -> "Missed"
|
||||||
|
},
|
||||||
Column(
|
fontSize = 12.sp,
|
||||||
horizontalAlignment = Alignment.End,
|
fontWeight = FontWeight.Normal,
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
color = Color(0xFF717182),
|
||||||
) {
|
lineHeight = 16.sp
|
||||||
Text(
|
)
|
||||||
text = call.timestamp,
|
}
|
||||||
fontSize = 12.sp,
|
}
|
||||||
fontWeight = FontWeight.Normal,
|
}
|
||||||
color = Color(0xFF717182),
|
|
||||||
lineHeight = 16.sp
|
Column(
|
||||||
)
|
horizontalAlignment = Alignment.End,
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
Icon(
|
) {
|
||||||
imageVector = if (call.isVideoCall) Icons.Default.Videocam else Icons.Default.Phone,
|
Text(
|
||||||
contentDescription = if (call.isVideoCall) "Video Call" else "Voice Call",
|
text = call.timestamp,
|
||||||
tint = Color(0xFF030213),
|
fontSize = 12.sp,
|
||||||
modifier = Modifier.size(24.dp)
|
fontWeight = FontWeight.Normal,
|
||||||
)
|
color = Color(0xFF717182),
|
||||||
}
|
lineHeight = 16.sp
|
||||||
}
|
)
|
||||||
}
|
|
||||||
|
Icon(
|
||||||
|
imageVector = if (call.isVideoCall) Icons.Default.Videocam else Icons.Default.Phone,
|
||||||
|
contentDescription = if (call.isVideoCall) "Video Call" else "Voice Call",
|
||||||
|
tint = Color(0xFF030213),
|
||||||
|
modifier = Modifier.size(24.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,333 +1,341 @@
|
||||||
package com.example.livingai_lg.ui.screens.chat
|
package com.example.livingai_lg.ui.screens.chat
|
||||||
|
|
||||||
import androidx.compose.foundation.LocalIndication
|
import androidx.compose.foundation.LocalIndication
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.*
|
import androidx.compose.material.icons.filled.*
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.example.farmmarketplace.ui.screens.ContactsBottomNav
|
import com.example.farmmarketplace.ui.screens.ContactsBottomNav
|
||||||
import com.example.farmmarketplace.ui.screens.ContactsTab
|
import com.example.farmmarketplace.ui.screens.ContactsTab
|
||||||
|
import com.example.livingai_lg.ui.layout.BottomNavScaffold
|
||||||
data class ChatPreview(
|
import com.example.livingai_lg.ui.models.chatBottomNavItems
|
||||||
val id: String,
|
|
||||||
val name: String,
|
data class ChatPreview(
|
||||||
val initials: String,
|
val id: String,
|
||||||
val lastMessage: String,
|
val name: String,
|
||||||
val timestamp: String,
|
val initials: String,
|
||||||
val isOnline: Boolean = false,
|
val lastMessage: String,
|
||||||
val unreadCount: Int = 0
|
val timestamp: String,
|
||||||
)
|
val isOnline: Boolean = false,
|
||||||
|
val unreadCount: Int = 0
|
||||||
@Composable
|
)
|
||||||
fun ChatsScreen(
|
|
||||||
onBackClick: () -> Unit = {},
|
@Composable
|
||||||
onNewChatClick: () -> Unit = {},
|
fun ChatsScreen(
|
||||||
onMenuClick: () -> Unit = {},
|
onBackClick: () -> Unit = {},
|
||||||
onChatItemClick: (String) -> Unit = {},
|
onNewChatClick: () -> Unit = {},
|
||||||
onTabClick: (route: String) -> Unit = {}
|
onMenuClick: () -> Unit = {},
|
||||||
) {
|
onChatItemClick: (String) -> Unit = {},
|
||||||
val chatList = listOf(
|
onTabClick: (route: String) -> Unit = {}
|
||||||
ChatPreview(
|
) {
|
||||||
id = "1",
|
val chatList = listOf(
|
||||||
name = "Farmer Kumar",
|
ChatPreview(
|
||||||
initials = "FK",
|
id = "1",
|
||||||
lastMessage = "The cows are healthy and ready for viewing",
|
name = "Farmer Kumar",
|
||||||
timestamp = "Today, 2:30 PM",
|
initials = "FK",
|
||||||
isOnline = true,
|
lastMessage = "The cows are healthy and ready for viewing",
|
||||||
unreadCount = 2
|
timestamp = "Today, 2:30 PM",
|
||||||
),
|
isOnline = true,
|
||||||
ChatPreview(
|
unreadCount = 2
|
||||||
id = "2",
|
),
|
||||||
name = "Seller Raj",
|
ChatPreview(
|
||||||
initials = "SR",
|
id = "2",
|
||||||
lastMessage = "You: Can you send more photos?",
|
name = "Seller Raj",
|
||||||
timestamp = "Today, 11:45 AM",
|
initials = "SR",
|
||||||
isOnline = true,
|
lastMessage = "You: Can you send more photos?",
|
||||||
unreadCount = 0
|
timestamp = "Today, 11:45 AM",
|
||||||
),
|
isOnline = true,
|
||||||
ChatPreview(
|
unreadCount = 0
|
||||||
id = "3",
|
),
|
||||||
name = "Buyer Priya",
|
ChatPreview(
|
||||||
initials = "BP",
|
id = "3",
|
||||||
lastMessage = "What's the best time to visit?",
|
name = "Buyer Priya",
|
||||||
timestamp = "Yesterday, 8:15 PM",
|
initials = "BP",
|
||||||
isOnline = false,
|
lastMessage = "What's the best time to visit?",
|
||||||
unreadCount = 1
|
timestamp = "Yesterday, 8:15 PM",
|
||||||
),
|
isOnline = false,
|
||||||
ChatPreview(
|
unreadCount = 1
|
||||||
id = "4",
|
),
|
||||||
name = "Seller 1",
|
ChatPreview(
|
||||||
initials = "S1",
|
id = "4",
|
||||||
lastMessage = "You: Thanks for the information",
|
name = "Seller 1",
|
||||||
timestamp = "Yesterday, 5:30 PM",
|
initials = "S1",
|
||||||
isOnline = true,
|
lastMessage = "You: Thanks for the information",
|
||||||
unreadCount = 0
|
timestamp = "Yesterday, 5:30 PM",
|
||||||
),
|
isOnline = true,
|
||||||
ChatPreview(
|
unreadCount = 0
|
||||||
id = "5",
|
),
|
||||||
name = "Veterinarian",
|
ChatPreview(
|
||||||
initials = "V",
|
id = "5",
|
||||||
lastMessage = "The animal health check is complete",
|
name = "Veterinarian",
|
||||||
timestamp = "2 days ago",
|
initials = "V",
|
||||||
isOnline = false,
|
lastMessage = "The animal health check is complete",
|
||||||
unreadCount = 0
|
timestamp = "2 days ago",
|
||||||
),
|
isOnline = false,
|
||||||
ChatPreview(
|
unreadCount = 0
|
||||||
id = "6",
|
),
|
||||||
name = "Market Vendor",
|
ChatPreview(
|
||||||
initials = "MV",
|
id = "6",
|
||||||
lastMessage = "You: Available this weekend?",
|
name = "Market Vendor",
|
||||||
timestamp = "3 days ago",
|
initials = "MV",
|
||||||
isOnline = false,
|
lastMessage = "You: Available this weekend?",
|
||||||
unreadCount = 0
|
timestamp = "3 days ago",
|
||||||
)
|
isOnline = false,
|
||||||
)
|
unreadCount = 0
|
||||||
|
)
|
||||||
Box(
|
)
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
Box(
|
||||||
.background(Color(0xFFFCFBF8))
|
modifier = Modifier
|
||||||
) {
|
.fillMaxSize()
|
||||||
Column(
|
.background(Color(0xFFFCFBF8))
|
||||||
modifier = Modifier.fillMaxSize()
|
) {
|
||||||
) {
|
BottomNavScaffold(
|
||||||
ChatsHeader(
|
items = chatBottomNavItems,
|
||||||
onBackClick = onBackClick,
|
currentItem = "Chats",
|
||||||
onNewChatClick = onNewChatClick,
|
onBottomNavItemClick = onTabClick,
|
||||||
onMenuClick = onMenuClick
|
) { paddingValues ->
|
||||||
)
|
Column(
|
||||||
|
modifier = Modifier.fillMaxSize().padding(paddingValues)
|
||||||
LazyColumn(
|
) {
|
||||||
modifier = Modifier
|
ChatsHeader(
|
||||||
.fillMaxWidth()
|
onBackClick = onBackClick,
|
||||||
.weight(1f)
|
onNewChatClick = onNewChatClick,
|
||||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
onMenuClick = onMenuClick
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
)
|
||||||
) {
|
|
||||||
items(chatList) { chat ->
|
LazyColumn(
|
||||||
ChatListItem(
|
modifier = Modifier
|
||||||
chat = chat,
|
.fillMaxWidth()
|
||||||
onClick = { onChatItemClick(chat.id) }
|
.weight(1f)
|
||||||
)
|
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||||
}
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
}
|
) {
|
||||||
|
items(chatList) { chat ->
|
||||||
ContactsBottomNav(
|
ChatListItem(
|
||||||
currentTab = ContactsTab.CHATS,
|
chat = chat,
|
||||||
onTabClick = onTabClick
|
onClick = { onChatItemClick(chat.id) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// ContactsBottomNav(
|
||||||
@Composable
|
// currentTab = ContactsTab.CHATS,
|
||||||
fun ChatsHeader(
|
// onTabClick = onTabClick
|
||||||
onBackClick: () -> Unit,
|
// )
|
||||||
onNewChatClick: () -> Unit,
|
}
|
||||||
onMenuClick: () -> Unit,
|
}
|
||||||
modifier: Modifier = Modifier
|
}
|
||||||
) {
|
}
|
||||||
Column(
|
|
||||||
modifier = modifier
|
@Composable
|
||||||
.fillMaxWidth()
|
fun ChatsHeader(
|
||||||
.height(65.dp)
|
onBackClick: () -> Unit,
|
||||||
.border(
|
onNewChatClick: () -> Unit,
|
||||||
width = 1.078.dp,
|
onMenuClick: () -> Unit,
|
||||||
color = Color(0xFF000000).copy(alpha = 0.1f)
|
modifier: Modifier = Modifier
|
||||||
)
|
) {
|
||||||
.background(Color(0xFFFCFBF8))
|
Column(
|
||||||
) {
|
modifier = modifier
|
||||||
Row(
|
.fillMaxWidth()
|
||||||
modifier = Modifier
|
.height(65.dp)
|
||||||
.fillMaxWidth()
|
.border(
|
||||||
.padding(horizontal = 14.dp, vertical = 10.dp),
|
width = 1.078.dp,
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
color = Color(0xFF000000).copy(alpha = 0.1f)
|
||||||
verticalAlignment = Alignment.CenterVertically
|
)
|
||||||
) {
|
.background(Color(0xFFFCFBF8))
|
||||||
Row(
|
) {
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
modifier = Modifier
|
||||||
) {
|
.fillMaxWidth()
|
||||||
Icon(
|
.padding(horizontal = 14.dp, vertical = 10.dp),
|
||||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
contentDescription = "Back",
|
verticalAlignment = Alignment.CenterVertically
|
||||||
tint = Color(0xFF0A0A0A),
|
) {
|
||||||
modifier = Modifier
|
Row(
|
||||||
.size(26.dp)
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
.clickable(
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
indication = LocalIndication.current,
|
) {
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
Icon(
|
||||||
) { onBackClick() }
|
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
)
|
contentDescription = "Back",
|
||||||
|
tint = Color(0xFF0A0A0A),
|
||||||
Text(
|
modifier = Modifier
|
||||||
text = "Chats",
|
.size(26.dp)
|
||||||
fontSize = 24.sp,
|
.clickable(
|
||||||
fontWeight = FontWeight.Medium,
|
indication = LocalIndication.current,
|
||||||
color = Color(0xFF0A0A0A),
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
lineHeight = 42.sp
|
) { onBackClick() }
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
Text(
|
||||||
Row(
|
text = "Chats",
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
fontSize = 24.sp,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
fontWeight = FontWeight.Medium,
|
||||||
) {
|
color = Color(0xFF0A0A0A),
|
||||||
Icon(
|
lineHeight = 42.sp
|
||||||
imageVector = Icons.Default.Edit,
|
)
|
||||||
contentDescription = "New Chat",
|
}
|
||||||
tint = Color(0xFF0A0A0A),
|
|
||||||
modifier = Modifier
|
Row(
|
||||||
.size(20.dp)
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
.clickable(
|
verticalAlignment = Alignment.CenterVertically
|
||||||
indication = LocalIndication.current,
|
) {
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
Icon(
|
||||||
) { onNewChatClick() }
|
imageVector = Icons.Default.Edit,
|
||||||
)
|
contentDescription = "New Chat",
|
||||||
|
tint = Color(0xFF0A0A0A),
|
||||||
Icon(
|
modifier = Modifier
|
||||||
imageVector = Icons.Default.MoreVert,
|
.size(20.dp)
|
||||||
contentDescription = "Menu",
|
.clickable(
|
||||||
tint = Color(0xFF0A0A0A),
|
indication = LocalIndication.current,
|
||||||
modifier = Modifier
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
.size(20.dp)
|
) { onNewChatClick() }
|
||||||
.clickable(
|
)
|
||||||
indication = LocalIndication.current,
|
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
Icon(
|
||||||
) { onMenuClick() }
|
imageVector = Icons.Default.MoreVert,
|
||||||
)
|
contentDescription = "Menu",
|
||||||
}
|
tint = Color(0xFF0A0A0A),
|
||||||
}
|
modifier = Modifier
|
||||||
}
|
.size(20.dp)
|
||||||
}
|
.clickable(
|
||||||
|
indication = LocalIndication.current,
|
||||||
@Composable
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
fun ChatListItem(
|
) { onMenuClick() }
|
||||||
chat: ChatPreview,
|
)
|
||||||
onClick: () -> Unit,
|
}
|
||||||
modifier: Modifier = Modifier
|
}
|
||||||
) {
|
}
|
||||||
Row(
|
}
|
||||||
modifier = modifier
|
|
||||||
.fillMaxWidth()
|
@Composable
|
||||||
.height(76.dp)
|
fun ChatListItem(
|
||||||
.border(
|
chat: ChatPreview,
|
||||||
width = 1.078.dp,
|
onClick: () -> Unit,
|
||||||
color = Color(0xFF000000).copy(alpha = 0.1f),
|
modifier: Modifier = Modifier
|
||||||
shape = RoundedCornerShape(12.dp)
|
) {
|
||||||
)
|
Row(
|
||||||
.background(Color(0xFFFCFBF8), RoundedCornerShape(12.dp))
|
modifier = modifier
|
||||||
.clickable(
|
.fillMaxWidth()
|
||||||
indication = LocalIndication.current,
|
.height(76.dp)
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
.border(
|
||||||
) { onClick() }
|
width = 1.078.dp,
|
||||||
.padding(horizontal = 16.dp, vertical = 14.dp),
|
color = Color(0xFF000000).copy(alpha = 0.1f),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
shape = RoundedCornerShape(12.dp)
|
||||||
verticalAlignment = Alignment.CenterVertically
|
)
|
||||||
) {
|
.background(Color(0xFFFCFBF8), RoundedCornerShape(12.dp))
|
||||||
Row(
|
.clickable(
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
indication = LocalIndication.current,
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
modifier = Modifier.weight(1f)
|
) { onClick() }
|
||||||
) {
|
.padding(horizontal = 16.dp, vertical = 14.dp),
|
||||||
Box(
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
modifier = Modifier
|
verticalAlignment = Alignment.CenterVertically
|
||||||
.size(48.dp)
|
) {
|
||||||
.background(Color(0xFFE5E7EB), CircleShape),
|
Row(
|
||||||
contentAlignment = Alignment.Center
|
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
) {
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
Text(
|
modifier = Modifier.weight(1f)
|
||||||
text = chat.initials,
|
) {
|
||||||
fontSize = 14.sp,
|
Box(
|
||||||
fontWeight = FontWeight.Medium,
|
modifier = Modifier
|
||||||
color = Color(0xFF0A0A0A),
|
.size(48.dp)
|
||||||
lineHeight = 21.sp
|
.background(Color(0xFFE5E7EB), CircleShape),
|
||||||
)
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
if (chat.isOnline) {
|
Text(
|
||||||
Box(
|
text = chat.initials,
|
||||||
modifier = Modifier
|
fontSize = 14.sp,
|
||||||
.align(Alignment.BottomEnd)
|
fontWeight = FontWeight.Medium,
|
||||||
.size(12.dp)
|
color = Color(0xFF0A0A0A),
|
||||||
.background(Color(0xFF00A63E), CircleShape)
|
lineHeight = 21.sp
|
||||||
.border(2.dp, Color.White, CircleShape)
|
)
|
||||||
)
|
|
||||||
}
|
if (chat.isOnline) {
|
||||||
}
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
Column(
|
.align(Alignment.BottomEnd)
|
||||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
.size(12.dp)
|
||||||
modifier = Modifier.weight(1f)
|
.background(Color(0xFF00A63E), CircleShape)
|
||||||
) {
|
.border(2.dp, Color.White, CircleShape)
|
||||||
Text(
|
)
|
||||||
text = chat.name,
|
}
|
||||||
fontSize = 16.sp,
|
}
|
||||||
fontWeight = FontWeight.Medium,
|
|
||||||
color = Color(0xFF1E2939),
|
Column(
|
||||||
lineHeight = 20.sp,
|
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
letterSpacing = (-0.312).sp
|
modifier = Modifier.weight(1f)
|
||||||
)
|
) {
|
||||||
|
Text(
|
||||||
Text(
|
text = chat.name,
|
||||||
text = chat.lastMessage,
|
fontSize = 16.sp,
|
||||||
fontSize = 12.sp,
|
fontWeight = FontWeight.Medium,
|
||||||
fontWeight = FontWeight.Normal,
|
color = Color(0xFF1E2939),
|
||||||
color = Color(0xFF717182),
|
lineHeight = 20.sp,
|
||||||
lineHeight = 16.sp,
|
letterSpacing = (-0.312).sp
|
||||||
maxLines = 1,
|
)
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
Text(
|
||||||
}
|
text = chat.lastMessage,
|
||||||
}
|
fontSize = 12.sp,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
Column(
|
color = Color(0xFF717182),
|
||||||
horizontalAlignment = Alignment.End,
|
lineHeight = 16.sp,
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
maxLines = 1,
|
||||||
) {
|
overflow = TextOverflow.Ellipsis
|
||||||
Text(
|
)
|
||||||
text = chat.timestamp,
|
}
|
||||||
fontSize = 12.sp,
|
}
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
color = Color(0xFF717182),
|
Column(
|
||||||
lineHeight = 16.sp
|
horizontalAlignment = Alignment.End,
|
||||||
)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
if (chat.unreadCount > 0) {
|
Text(
|
||||||
Box(
|
text = chat.timestamp,
|
||||||
modifier = Modifier
|
fontSize = 12.sp,
|
||||||
.size(24.dp)
|
fontWeight = FontWeight.Normal,
|
||||||
.background(Color(0xFF155DFC), CircleShape),
|
color = Color(0xFF717182),
|
||||||
contentAlignment = Alignment.Center
|
lineHeight = 16.sp
|
||||||
) {
|
)
|
||||||
Text(
|
|
||||||
text = chat.unreadCount.toString(),
|
if (chat.unreadCount > 0) {
|
||||||
fontSize = 10.sp,
|
Box(
|
||||||
fontWeight = FontWeight.Medium,
|
modifier = Modifier
|
||||||
color = Color.White,
|
.size(24.dp)
|
||||||
lineHeight = 14.sp
|
.background(Color(0xFF155DFC), CircleShape),
|
||||||
)
|
contentAlignment = Alignment.Center
|
||||||
}
|
) {
|
||||||
}
|
Text(
|
||||||
}
|
text = chat.unreadCount.toString(),
|
||||||
}
|
fontSize = 10.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = Color.White,
|
||||||
|
lineHeight = 14.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,422 +1,432 @@
|
||||||
package com.example.farmmarketplace.ui.screens
|
package com.example.farmmarketplace.ui.screens
|
||||||
|
|
||||||
import androidx.compose.foundation.LocalIndication
|
import androidx.compose.foundation.LocalIndication
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.automirrored.filled.Chat
|
import androidx.compose.material.icons.automirrored.filled.Chat
|
||||||
import androidx.compose.material.icons.automirrored.filled.Message
|
import androidx.compose.material.icons.automirrored.filled.Message
|
||||||
import androidx.compose.material.icons.automirrored.outlined.Message
|
import androidx.compose.material.icons.automirrored.outlined.Message
|
||||||
import androidx.compose.material.icons.filled.Chat
|
import androidx.compose.material.icons.filled.Chat
|
||||||
import androidx.compose.material.icons.filled.Contacts
|
import androidx.compose.material.icons.filled.Contacts
|
||||||
import androidx.compose.material.icons.filled.Message
|
import androidx.compose.material.icons.filled.Message
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
import androidx.compose.material.icons.filled.Phone
|
import androidx.compose.material.icons.filled.Phone
|
||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
import androidx.compose.material.icons.outlined.Phone
|
import androidx.compose.material.icons.outlined.Phone
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.graphics.vector.path
|
import androidx.compose.ui.graphics.vector.path
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.example.livingai_lg.ui.navigation.AppScreen
|
import com.example.livingai_lg.ui.layout.BottomNavScaffold
|
||||||
|
import com.example.livingai_lg.ui.models.chatBottomNavItems
|
||||||
data class Contact(
|
import com.example.livingai_lg.ui.models.mainBottomNavItems
|
||||||
val id: String,
|
import com.example.livingai_lg.ui.navigation.AppScreen
|
||||||
val name: String,
|
|
||||||
val initials: String,
|
data class Contact(
|
||||||
val status: String,
|
val id: String,
|
||||||
val isOnline: Boolean = false,
|
val name: String,
|
||||||
val phoneNumber: String? = null
|
val initials: String,
|
||||||
)
|
val status: String,
|
||||||
|
val isOnline: Boolean = false,
|
||||||
enum class ContactsTab {
|
val phoneNumber: String? = null
|
||||||
CONTACTS,
|
)
|
||||||
CALLS,
|
|
||||||
CHATS
|
enum class ContactsTab {
|
||||||
}
|
CONTACTS,
|
||||||
|
CALLS,
|
||||||
@Composable
|
CHATS
|
||||||
fun ContactsScreen(
|
}
|
||||||
onBackClick: () -> Unit = {},
|
|
||||||
onSearchClick: () -> Unit = {},
|
@Composable
|
||||||
onMenuClick: () -> Unit = {},
|
fun ContactsScreen(
|
||||||
onContactClick: (String) -> Unit = {},
|
onBackClick: () -> Unit = {},
|
||||||
onCallClick: (String) -> Unit = {},
|
onSearchClick: () -> Unit = {},
|
||||||
onMessageClick: (String) -> Unit = {},
|
onMenuClick: () -> Unit = {},
|
||||||
onTabClick: (route: String) -> Unit = {}
|
onContactClick: (String) -> Unit = {},
|
||||||
) {
|
onCallClick: (String) -> Unit = {},
|
||||||
val contacts = listOf(
|
onMessageClick: (String) -> Unit = {},
|
||||||
Contact(
|
onTabClick: (route: String) -> Unit = {}
|
||||||
id = "1",
|
) {
|
||||||
name = "Farmer Kumar",
|
val contacts = listOf(
|
||||||
initials = "FK",
|
Contact(
|
||||||
status = "Online",
|
id = "1",
|
||||||
isOnline = true
|
name = "Farmer Kumar",
|
||||||
),
|
initials = "FK",
|
||||||
Contact(
|
status = "Online",
|
||||||
id = "2",
|
isOnline = true
|
||||||
name = "Seller Raj",
|
),
|
||||||
initials = "SR",
|
Contact(
|
||||||
status = "+91 98765 43211",
|
id = "2",
|
||||||
isOnline = false,
|
name = "Seller Raj",
|
||||||
phoneNumber = "+91 98765 43211"
|
initials = "SR",
|
||||||
),
|
status = "+91 98765 43211",
|
||||||
Contact(
|
isOnline = false,
|
||||||
id = "3",
|
phoneNumber = "+91 98765 43211"
|
||||||
name = "Buyer Priya",
|
),
|
||||||
initials = "BP",
|
Contact(
|
||||||
status = "Online",
|
id = "3",
|
||||||
isOnline = true
|
name = "Buyer Priya",
|
||||||
),
|
initials = "BP",
|
||||||
Contact(
|
status = "Online",
|
||||||
id = "4",
|
isOnline = true
|
||||||
name = "Seller 1",
|
),
|
||||||
initials = "S1",
|
Contact(
|
||||||
status = "+91 98765 43213",
|
id = "4",
|
||||||
isOnline = false,
|
name = "Seller 1",
|
||||||
phoneNumber = "+91 98765 43213"
|
initials = "S1",
|
||||||
),
|
status = "+91 98765 43213",
|
||||||
Contact(
|
isOnline = false,
|
||||||
id = "5",
|
phoneNumber = "+91 98765 43213"
|
||||||
name = "Veterinarian",
|
),
|
||||||
initials = "V",
|
Contact(
|
||||||
status = "Online",
|
id = "5",
|
||||||
isOnline = true
|
name = "Veterinarian",
|
||||||
),
|
initials = "V",
|
||||||
Contact(
|
status = "Online",
|
||||||
id = "6",
|
isOnline = true
|
||||||
name = "Farm Supply",
|
),
|
||||||
initials = "FS",
|
Contact(
|
||||||
status = "+91 98765 43215",
|
id = "6",
|
||||||
isOnline = false,
|
name = "Farm Supply",
|
||||||
phoneNumber = "+91 98765 43215"
|
initials = "FS",
|
||||||
),
|
status = "+91 98765 43215",
|
||||||
Contact(
|
isOnline = false,
|
||||||
id = "7",
|
phoneNumber = "+91 98765 43215"
|
||||||
name = "Transport Co.",
|
),
|
||||||
initials = "TC",
|
Contact(
|
||||||
status = "+91 98765 43216",
|
id = "7",
|
||||||
isOnline = false,
|
name = "Transport Co.",
|
||||||
phoneNumber = "+91 98765 43216"
|
initials = "TC",
|
||||||
)
|
status = "+91 98765 43216",
|
||||||
)
|
isOnline = false,
|
||||||
|
phoneNumber = "+91 98765 43216"
|
||||||
Box(
|
)
|
||||||
modifier = Modifier
|
)
|
||||||
.fillMaxSize()
|
|
||||||
.background(Color(0xFFFCFBF8))
|
Box(
|
||||||
) {
|
modifier = Modifier
|
||||||
Column(
|
.fillMaxSize()
|
||||||
modifier = Modifier.fillMaxSize()
|
.background(Color(0xFFFCFBF8))
|
||||||
) {
|
) {
|
||||||
ContactsHeader(
|
BottomNavScaffold(
|
||||||
onBackClick = onBackClick,
|
items = chatBottomNavItems,
|
||||||
onSearchClick = onSearchClick,
|
currentItem = "Contacts",
|
||||||
onMenuClick = onMenuClick
|
onBottomNavItemClick = onTabClick,
|
||||||
)
|
) { paddingValues ->
|
||||||
|
|
||||||
LazyColumn(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxSize().padding(paddingValues)
|
||||||
.fillMaxWidth()
|
) {
|
||||||
.weight(1f)
|
ContactsHeader(
|
||||||
) {
|
onBackClick = onBackClick,
|
||||||
items(contacts) { contact ->
|
onSearchClick = onSearchClick,
|
||||||
ContactItem(
|
onMenuClick = onMenuClick
|
||||||
contact = contact,
|
)
|
||||||
onContactClick = { onContactClick(contact.id) },
|
|
||||||
onCallClick = { onCallClick(contact.id) },
|
LazyColumn(
|
||||||
onMessageClick = { onMessageClick(contact.id) }
|
modifier = Modifier
|
||||||
)
|
.fillMaxWidth()
|
||||||
}
|
.weight(1f)
|
||||||
}
|
) {
|
||||||
|
items(contacts) { contact ->
|
||||||
ContactsBottomNav(
|
ContactItem(
|
||||||
currentTab = ContactsTab.CONTACTS,
|
contact = contact,
|
||||||
onTabClick = onTabClick
|
onContactClick = { onContactClick(contact.id) },
|
||||||
)
|
onCallClick = { onCallClick(contact.id) },
|
||||||
}
|
onMessageClick = { onMessageClick(contact.id) }
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Composable
|
|
||||||
fun ContactsHeader(
|
// ContactsBottomNav(
|
||||||
onBackClick: () -> Unit,
|
// currentTab = ContactsTab.CONTACTS,
|
||||||
onSearchClick: () -> Unit,
|
// onTabClick = onTabClick
|
||||||
onMenuClick: () -> Unit,
|
// )
|
||||||
modifier: Modifier = Modifier
|
}
|
||||||
) {
|
}
|
||||||
Column(
|
}
|
||||||
modifier = modifier
|
}
|
||||||
.fillMaxWidth()
|
|
||||||
.height(65.dp)
|
@Composable
|
||||||
.border(
|
fun ContactsHeader(
|
||||||
width = 1.078.dp,
|
onBackClick: () -> Unit,
|
||||||
color = Color(0xFF000000).copy(alpha = 0.1f)
|
onSearchClick: () -> Unit,
|
||||||
)
|
onMenuClick: () -> Unit,
|
||||||
.background(Color(0xFFFCFBF8))
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
Row(
|
Column(
|
||||||
modifier = Modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
.height(65.dp)
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
.border(
|
||||||
verticalAlignment = Alignment.CenterVertically
|
width = 1.078.dp,
|
||||||
) {
|
color = Color(0xFF000000).copy(alpha = 0.1f)
|
||||||
Row(
|
)
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
.background(Color(0xFFFCFBF8))
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
) {
|
||||||
) {
|
Row(
|
||||||
Icon(
|
modifier = Modifier
|
||||||
imageVector = Icons.AutoMirrored.Default.ArrowBack,
|
.fillMaxWidth()
|
||||||
contentDescription = "Back",
|
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||||
tint = Color(0xFF0A0A0A),
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
modifier = Modifier
|
verticalAlignment = Alignment.CenterVertically
|
||||||
.size(26.dp)
|
) {
|
||||||
.clickable(
|
Row(
|
||||||
indication = LocalIndication.current,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) { onBackClick() }
|
) {
|
||||||
)
|
Icon(
|
||||||
|
imageVector = Icons.AutoMirrored.Default.ArrowBack,
|
||||||
Text(
|
contentDescription = "Back",
|
||||||
text = "Contacts",
|
tint = Color(0xFF0A0A0A),
|
||||||
fontSize = 24.sp,
|
modifier = Modifier
|
||||||
fontWeight = FontWeight.Medium,
|
.size(26.dp)
|
||||||
color = Color(0xFF0A0A0A),
|
.clickable(
|
||||||
lineHeight = 42.sp
|
indication = LocalIndication.current,
|
||||||
)
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
}
|
) { onBackClick() }
|
||||||
|
)
|
||||||
Row(
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
Text(
|
||||||
verticalAlignment = Alignment.CenterVertically
|
text = "Contacts",
|
||||||
) {
|
fontSize = 24.sp,
|
||||||
Icon(
|
fontWeight = FontWeight.Medium,
|
||||||
imageVector = Icons.Default.Search,
|
color = Color(0xFF0A0A0A),
|
||||||
contentDescription = "Search",
|
lineHeight = 42.sp
|
||||||
tint = Color(0xFF0A0A0A),
|
)
|
||||||
modifier = Modifier
|
}
|
||||||
.size(20.dp)
|
|
||||||
.clickable(
|
Row(
|
||||||
indication = LocalIndication.current,
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) { onSearchClick() }
|
) {
|
||||||
)
|
Icon(
|
||||||
|
imageVector = Icons.Default.Search,
|
||||||
Icon(
|
contentDescription = "Search",
|
||||||
imageVector = Icons.Default.MoreVert,
|
tint = Color(0xFF0A0A0A),
|
||||||
contentDescription = "Menu",
|
modifier = Modifier
|
||||||
tint = Color(0xFF0A0A0A),
|
.size(20.dp)
|
||||||
modifier = Modifier
|
.clickable(
|
||||||
.size(20.dp)
|
indication = LocalIndication.current,
|
||||||
.clickable(
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
indication = LocalIndication.current,
|
) { onSearchClick() }
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
)
|
||||||
) { onMenuClick() }
|
|
||||||
)
|
Icon(
|
||||||
}
|
imageVector = Icons.Default.MoreVert,
|
||||||
}
|
contentDescription = "Menu",
|
||||||
}
|
tint = Color(0xFF0A0A0A),
|
||||||
}
|
modifier = Modifier
|
||||||
|
.size(20.dp)
|
||||||
@Composable
|
.clickable(
|
||||||
fun ContactItem(
|
indication = LocalIndication.current,
|
||||||
contact: Contact,
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
onContactClick: () -> Unit,
|
) { onMenuClick() }
|
||||||
onCallClick: () -> Unit,
|
)
|
||||||
onMessageClick: () -> Unit,
|
}
|
||||||
modifier: Modifier = Modifier
|
}
|
||||||
) {
|
}
|
||||||
Row(
|
}
|
||||||
modifier = modifier
|
|
||||||
.fillMaxWidth()
|
@Composable
|
||||||
.height(73.dp)
|
fun ContactItem(
|
||||||
.border(
|
contact: Contact,
|
||||||
width = 1.078.dp,
|
onContactClick: () -> Unit,
|
||||||
color = Color(0xFF000000).copy(alpha = 0.05f)
|
onCallClick: () -> Unit,
|
||||||
)
|
onMessageClick: () -> Unit,
|
||||||
.background(Color(0xFFFCFBF8))
|
modifier: Modifier = Modifier
|
||||||
.clickable(
|
) {
|
||||||
indication = LocalIndication.current,
|
Row(
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
modifier = modifier
|
||||||
) { onContactClick() }
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
.height(73.dp)
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
.border(
|
||||||
verticalAlignment = Alignment.CenterVertically
|
width = 1.078.dp,
|
||||||
) {
|
color = Color(0xFF000000).copy(alpha = 0.05f)
|
||||||
Row(
|
)
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
.background(Color(0xFFFCFBF8))
|
||||||
verticalAlignment = Alignment.CenterVertically
|
.clickable(
|
||||||
) {
|
indication = LocalIndication.current,
|
||||||
Box(
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
modifier = Modifier
|
) { onContactClick() }
|
||||||
.size(48.dp)
|
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||||
.background(Color(0xFFE5E7EB), CircleShape),
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
contentAlignment = Alignment.Center
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Text(
|
Row(
|
||||||
text = contact.initials,
|
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
fontSize = 14.sp,
|
verticalAlignment = Alignment.CenterVertically
|
||||||
fontWeight = FontWeight.Medium,
|
) {
|
||||||
color = Color(0xFF0A0A0A),
|
Box(
|
||||||
lineHeight = 21.sp
|
modifier = Modifier
|
||||||
)
|
.size(48.dp)
|
||||||
}
|
.background(Color(0xFFE5E7EB), CircleShape),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
Column(
|
) {
|
||||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
Text(
|
||||||
) {
|
text = contact.initials,
|
||||||
Text(
|
fontSize = 14.sp,
|
||||||
text = contact.name,
|
fontWeight = FontWeight.Medium,
|
||||||
fontSize = 16.sp,
|
color = Color(0xFF0A0A0A),
|
||||||
fontWeight = FontWeight.Medium,
|
lineHeight = 21.sp
|
||||||
color = Color(0xFF1E2939),
|
)
|
||||||
lineHeight = 20.sp,
|
}
|
||||||
letterSpacing = (-0.312).sp
|
|
||||||
)
|
Column(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
Text(
|
) {
|
||||||
text = contact.status,
|
Text(
|
||||||
fontSize = 12.sp,
|
text = contact.name,
|
||||||
fontWeight = FontWeight.Normal,
|
fontSize = 16.sp,
|
||||||
color = Color(0xFF717182),
|
fontWeight = FontWeight.Medium,
|
||||||
lineHeight = 16.sp
|
color = Color(0xFF1E2939),
|
||||||
)
|
lineHeight = 20.sp,
|
||||||
}
|
letterSpacing = (-0.312).sp
|
||||||
}
|
)
|
||||||
|
|
||||||
Row(
|
Text(
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
text = contact.status,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
fontSize = 12.sp,
|
||||||
) {
|
fontWeight = FontWeight.Normal,
|
||||||
Box(
|
color = Color(0xFF717182),
|
||||||
modifier = Modifier
|
lineHeight = 16.sp
|
||||||
.size(36.dp)
|
)
|
||||||
.clickable(
|
}
|
||||||
indication = LocalIndication.current,
|
}
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
|
||||||
) { onCallClick() },
|
Row(
|
||||||
contentAlignment = Alignment.Center
|
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
) {
|
verticalAlignment = Alignment.CenterVertically
|
||||||
Icon(
|
) {
|
||||||
imageVector = Icons.Outlined.Phone,
|
Box(
|
||||||
contentDescription = "Call",
|
modifier = Modifier
|
||||||
tint = Color(0xFF030213),
|
.size(36.dp)
|
||||||
modifier = Modifier.size(20.dp)
|
.clickable(
|
||||||
)
|
indication = LocalIndication.current,
|
||||||
}
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
|
) { onCallClick() },
|
||||||
Box(
|
contentAlignment = Alignment.Center
|
||||||
modifier = Modifier
|
) {
|
||||||
.size(36.dp)
|
Icon(
|
||||||
.clickable(
|
imageVector = Icons.Outlined.Phone,
|
||||||
indication = LocalIndication.current,
|
contentDescription = "Call",
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
tint = Color(0xFF030213),
|
||||||
) { onMessageClick() },
|
modifier = Modifier.size(20.dp)
|
||||||
contentAlignment = Alignment.Center
|
)
|
||||||
) {
|
}
|
||||||
Icon(
|
|
||||||
imageVector = Icons.AutoMirrored.Outlined.Message,
|
Box(
|
||||||
contentDescription = "Message",
|
modifier = Modifier
|
||||||
tint = Color(0xFF030213),
|
.size(36.dp)
|
||||||
modifier = Modifier.size(20.dp)
|
.clickable(
|
||||||
)
|
indication = LocalIndication.current,
|
||||||
}
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
}
|
) { onMessageClick() },
|
||||||
}
|
contentAlignment = Alignment.Center
|
||||||
}
|
) {
|
||||||
|
Icon(
|
||||||
@Composable
|
imageVector = Icons.AutoMirrored.Outlined.Message,
|
||||||
fun ContactsBottomNav(
|
contentDescription = "Message",
|
||||||
currentTab: ContactsTab,
|
tint = Color(0xFF030213),
|
||||||
onTabClick: (route: String) -> Unit,
|
modifier = Modifier.size(20.dp)
|
||||||
modifier: Modifier = Modifier
|
)
|
||||||
) {
|
}
|
||||||
Row(
|
}
|
||||||
modifier = modifier
|
}
|
||||||
.fillMaxWidth()
|
}
|
||||||
.height(65.dp)
|
|
||||||
.border(
|
@Composable
|
||||||
width = 1.078.dp,
|
fun ContactsBottomNav(
|
||||||
color = Color(0xFF000000).copy(alpha = 0.1f)
|
currentTab: ContactsTab,
|
||||||
)
|
onTabClick: (route: String) -> Unit,
|
||||||
.background(Color(0xFFFCFBF8))
|
modifier: Modifier = Modifier
|
||||||
.padding(horizontal = 32.dp),
|
) {
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically
|
modifier = modifier
|
||||||
) {
|
.fillMaxWidth()
|
||||||
|
.height(65.dp)
|
||||||
ContactsTabItem(
|
.border(
|
||||||
icon = Icons.AutoMirrored.Filled.Chat,
|
width = 1.078.dp,
|
||||||
label = "Chats",
|
color = Color(0xFF000000).copy(alpha = 0.1f)
|
||||||
isSelected = currentTab == ContactsTab.CHATS,
|
)
|
||||||
onClick = { onTabClick(AppScreen.CHATS) }
|
.background(Color(0xFFFCFBF8))
|
||||||
)
|
.padding(horizontal = 32.dp),
|
||||||
ContactsTabItem(
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
icon = Icons.Default.Phone,
|
verticalAlignment = Alignment.CenterVertically
|
||||||
label = "Calls",
|
) {
|
||||||
isSelected = currentTab == ContactsTab.CALLS,
|
|
||||||
onClick = { onTabClick(AppScreen.CALLS) }
|
ContactsTabItem(
|
||||||
)
|
icon = Icons.AutoMirrored.Filled.Chat,
|
||||||
ContactsTabItem(
|
label = "Chats",
|
||||||
icon = Icons.Default.Contacts,
|
isSelected = currentTab == ContactsTab.CHATS,
|
||||||
label = "Contacts",
|
onClick = { onTabClick(AppScreen.CHATS) }
|
||||||
isSelected = currentTab == ContactsTab.CONTACTS,
|
)
|
||||||
onClick = { onTabClick(AppScreen.CONTACTS) }
|
ContactsTabItem(
|
||||||
)
|
icon = Icons.Default.Phone,
|
||||||
|
label = "Calls",
|
||||||
|
isSelected = currentTab == ContactsTab.CALLS,
|
||||||
}
|
onClick = { onTabClick(AppScreen.CALLS) }
|
||||||
}
|
)
|
||||||
|
ContactsTabItem(
|
||||||
@Composable
|
icon = Icons.Default.Contacts,
|
||||||
fun ContactsTabItem(
|
label = "Contacts",
|
||||||
icon: ImageVector,
|
isSelected = currentTab == ContactsTab.CONTACTS,
|
||||||
label: String,
|
onClick = { onTabClick(AppScreen.CONTACTS) }
|
||||||
isSelected: Boolean,
|
)
|
||||||
onClick: () -> Unit,
|
|
||||||
modifier: Modifier = Modifier
|
|
||||||
) {
|
}
|
||||||
Column(
|
}
|
||||||
modifier = modifier
|
|
||||||
.clickable(
|
@Composable
|
||||||
indication = LocalIndication.current,
|
fun ContactsTabItem(
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
icon: ImageVector,
|
||||||
) { onClick() }
|
label: String,
|
||||||
.padding(4.dp),
|
isSelected: Boolean,
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
onClick: () -> Unit,
|
||||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
Icon(
|
Column(
|
||||||
imageVector = icon,
|
modifier = modifier
|
||||||
contentDescription = label,
|
.clickable(
|
||||||
tint = Color(0xFF0A0A0A),
|
indication = LocalIndication.current,
|
||||||
modifier = Modifier.size(24.dp)
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
)
|
) { onClick() }
|
||||||
|
.padding(4.dp),
|
||||||
Text(
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
text = label,
|
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
fontSize = 12.sp,
|
) {
|
||||||
fontWeight = FontWeight.Medium,
|
Icon(
|
||||||
color = Color(0xFF0A0A0A),
|
imageVector = icon,
|
||||||
lineHeight = 16.sp,
|
contentDescription = label,
|
||||||
textAlign = TextAlign.Center
|
tint = Color(0xFF0A0A0A),
|
||||||
)
|
modifier = Modifier.size(24.dp)
|
||||||
}
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = Color(0xFF0A0A0A),
|
||||||
|
lineHeight = 16.sp,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue