From ee4eb442f8085560a9833183c60fe4d678b8506d Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Thu, 25 May 2023 11:59:25 +0700 Subject: [PATCH 01/73] creating detection result page ui --- app/build.gradle | 3 + .../capstone/techwasmark02/MainActivity.kt | 3 +- .../techwasmark02/ui/component/BottomBar.kt | 69 +++-- .../ui/component/DetectionsResultBox.kt | 276 ++++++++++++++++++ .../DetectionsResultSaveBottomSheet.kt | 57 ++++ .../component/UsableComponentBottomSheet.kt | 74 +++++ .../ui/component/UsableComponentItem.kt | 91 ++++++ .../detectionResult/DetectionResultScreen.kt | 235 +++++++++++++++ .../ui/screen/home/HomeScreen.kt | 2 +- app/src/main/res/drawable/ic_arrow_down.xml | 5 + app/src/main/res/drawable/ic_arrow_up.xml | 5 + 11 files changed, 792 insertions(+), 28 deletions(-) create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultSaveBottomSheet.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentBottomSheet.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentItem.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt create mode 100644 app/src/main/res/drawable/ic_arrow_down.xml create mode 100644 app/src/main/res/drawable/ic_arrow_up.xml diff --git a/app/build.gradle b/app/build.gradle index f2b037a..e8e1511 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,13 +55,16 @@ dependencies { implementation 'androidx.activity:activity-compose:1.7.1' implementation platform('androidx.compose:compose-bom:2022.10.00') implementation 'androidx.compose.ui:ui' + implementation "androidx.compose.ui:ui-util" implementation 'androidx.compose.ui:ui-graphics' implementation 'androidx.compose.ui:ui-tooling-preview' implementation 'androidx.compose.material3:material3' + implementation 'androidx.compose.material:material:1.4.3' // compose implementation 'androidx.navigation:navigation-compose:2.5.3' implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1' + implementation 'androidx.compose.foundation:foundation:1.4.3' //lifecycle implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1' diff --git a/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt b/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt index 2f9dacd..baf8b2e 100644 --- a/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt +++ b/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.ui.Modifier +import com.capstone.techwasmark02.ui.screen.detectionResult.DetectionResultScreen import com.capstone.techwasmark02.ui.screen.imageDetection.ImageDetectionScreen import com.capstone.techwasmark02.ui.screen.signIn.SignInScreen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @@ -23,7 +24,7 @@ class MainActivity : ComponentActivity() { modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { - ImageDetectionScreen() + DetectionResultScreen() } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt index cd43d69..13079d9 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt @@ -11,14 +11,18 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview @@ -34,46 +38,59 @@ fun DefaultBottomBar( modifier: Modifier = Modifier, selectedType: BottomBarItemType ) { - NavigationBar( - modifier = modifier - .graphicsLayer { - shape = BottomNavShape() - clip = true - } + Box( + modifier = Modifier .fillMaxWidth() - .height(60.dp), - containerColor = MaterialTheme.colorScheme.inverseSurface, - contentColor = MaterialTheme.colorScheme.inverseOnSurface, - + .padding(horizontal = 8.dp) + .padding(bottom = 8.dp) ) { - Row( - modifier = Modifier + NavigationBar( + modifier = modifier + .shadow( + elevation = 8.dp, + shape = BottomNavShape(), + clip = true + ) + .graphicsLayer { + shape = BottomNavShape() + clip = true + } + .clip(RoundedCornerShape(10.dp)) .fillMaxWidth() - .fillMaxHeight(), - verticalAlignment = Alignment.CenterVertically - ) { - Spacer(modifier = Modifier.weight(1f)) + .height(60.dp), + containerColor = MaterialTheme.colorScheme.inverseSurface, + contentColor = MaterialTheme.colorScheme.inverseOnSurface, + tonalElevation = 8.dp + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight(), + verticalAlignment = Alignment.CenterVertically + ) { + Spacer(modifier = Modifier.weight(1f)) - BottomBarItem(bottomBarItemType = BottomBarItemType.Home, selectedType = selectedType) + BottomBarItem(bottomBarItemType = BottomBarItemType.Home, selectedType = selectedType) - Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.weight(1f)) - BottomBarItem(bottomBarItemType = BottomBarItemType.Forum, selectedType = selectedType) + BottomBarItem(bottomBarItemType = BottomBarItemType.Forum, selectedType = selectedType) - Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.weight(1f)) - Spacer(modifier = Modifier.width(80.dp)) + Spacer(modifier = Modifier.width(80.dp)) - Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.weight(1f)) - BottomBarItem(bottomBarItemType = BottomBarItemType.Article, selectedType = selectedType) + BottomBarItem(bottomBarItemType = BottomBarItemType.Article, selectedType = selectedType) - Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.weight(1f)) - BottomBarItem(bottomBarItemType = BottomBarItemType.Profile, selectedType = selectedType) + BottomBarItem(bottomBarItemType = BottomBarItemType.Profile, selectedType = selectedType) - Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.weight(1f)) + } } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt new file mode 100644 index 0000000..134f08c --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt @@ -0,0 +1,276 @@ +package com.capstone.techwasmark02.ui.component + +import androidx.compose.foundation.ExperimentalFoundationApi +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.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.pager.PagerState +import androidx.compose.foundation.pager.VerticalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.TransformOrigin +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.util.lerp +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import kotlinx.coroutines.launch +import kotlin.math.absoluteValue + +@OptIn(ExperimentalFoundationApi::class) +@Composable +fun DetectionsResultBox( + modifier: Modifier = Modifier +) { + val pagerState = rememberPagerState() + val coroutineScope = rememberCoroutineScope() + + Box( + modifier = modifier + .fillMaxWidth() + .height(120.dp) + .clip(MaterialTheme.shapes.large) + .background(MaterialTheme.colorScheme.tertiary) + .padding(horizontal = 24.dp), + contentAlignment = Alignment.Center + ) { + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + Box( + modifier = Modifier + .size(84.dp) + .clip(MaterialTheme.shapes.large) + .background(MaterialTheme.colorScheme.primaryContainer) + ) + } + + VerticalPager( + pageCount = dummyDetectionResultList.size, + modifier = Modifier + .height(84.dp), + pageSpacing = (-50).dp, + state = pagerState, + ) { page -> + ResultListItem( + detectionResult = dummyDetectionResultList[page], + pagerState = pagerState, + page = page, + modifier = Modifier + ) + } + + Column( + modifier = Modifier + .fillMaxHeight() + ) { + val prevButtonVisible by remember { + derivedStateOf { + pagerState.currentPage > 0 + } + } + + val nextButtonVisible by remember { + derivedStateOf { + pagerState.currentPage < dummyDetectionResultList.size - 1 + } + } + + IconButton(onClick = { + val prevPageIndex = pagerState.currentPage - 1 + coroutineScope.launch { pagerState.animateScrollToPage(prevPageIndex) } + }, + enabled = prevButtonVisible, + ) { + Icon( + painter = painterResource(id = R.drawable.ic_arrow_up), + contentDescription = null, + tint = MaterialTheme.colorScheme.onTertiary, + modifier = Modifier + .alpha(if (prevButtonVisible) 1f else 0.3f), + ) + } + Spacer(modifier = Modifier.weight(1f)) + IconButton(onClick = { + val nextPageIndex = pagerState.currentPage + 1 + coroutineScope.launch { pagerState.animateScrollToPage(nextPageIndex) } + }, + enabled = nextButtonVisible + ) { + Icon( + painter = painterResource(id = R.drawable.ic_arrow_down), + contentDescription = null, + tint = MaterialTheme.colorScheme.onTertiary, + modifier = Modifier + .alpha(if (nextButtonVisible) 1f else 0.3f) + ) + } + } + } +} + +@OptIn(ExperimentalFoundationApi::class) +@Composable +fun ResultListItem( + detectionResult: DummyDetectionResult, + pagerState: PagerState, + page: Int, + modifier: Modifier = Modifier +) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = detectionResult.componentType, + style = MaterialTheme.typography.headlineSmall, + modifier = Modifier + .graphicsLayer { + val pageOffset = ( + (pagerState.currentPage - page) + pagerState.currentPageOffsetFraction).absoluteValue + alpha = lerp( + start = 0.2f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f) + ) + scaleX = lerp( + start = 0.6f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f) + ) + scaleY = lerp( + start = 0.6f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f) + ) + transformOrigin = TransformOrigin( + pivotFractionY = 0.4f, + pivotFractionX = 0.1f + ) + } + ) + Spacer(modifier = Modifier.weight(1f)) + + Box( + modifier = Modifier + .size(84.dp) + .background(Color.Transparent), + contentAlignment = Alignment.Center + ) { + Text( + text = "${detectionResult.detectionPercentage}%", + style = MaterialTheme.typography.headlineSmall.copy( + fontSize = 28.sp + ), + color = MaterialTheme.colorScheme.onPrimaryContainer, + modifier = Modifier + .graphicsLayer { + val pageOffset = ( + (pagerState.currentPage - page) + pagerState.currentPageOffsetFraction).absoluteValue + alpha = lerp( + start = 0.5f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f) + ) + scaleX = lerp( + start = 0.7f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f) + ) + scaleY = lerp( + start = 0.7f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f) + ) + transformOrigin = TransformOrigin( + pivotFractionY = 0.4f, + pivotFractionX = 0.5f + ) + } + ) + } + } +} + + +@Preview (showBackground = false) +@Composable +fun DetectionsResultBoxPreview() { + TechwasMark02Theme { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(20.dp) + ) { + DetectionsResultBox() + } + } +} + +@OptIn(ExperimentalFoundationApi::class) +@Preview (showBackground = true) +@Composable +fun ResultListItemPreview() { + TechwasMark02Theme { + Box( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.primaryContainer) + .padding(20.dp) + ) { + ResultListItem( + detectionResult = DummyDetectionResult( + componentType = "Laptop", + detectionPercentage = 70 + ), + pagerState = PagerState( + initialPage = 0, + initialPageOffsetFraction = 0f, + ), + page = 0 + ) + } + } +} + +data class DummyDetectionResult( + val componentType: String, + val detectionPercentage: Int +) + +private val dummyDetectionResultList: List = listOf( + DummyDetectionResult( + componentType = "Laptop", + detectionPercentage = 70 + ), + DummyDetectionResult( + componentType = "Mesin Cuci", + detectionPercentage = 20 + ), + DummyDetectionResult( + componentType = "Rice Cooker", + detectionPercentage = 10 + ) +) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultSaveBottomSheet.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultSaveBottomSheet.kt new file mode 100644 index 0000000..7a3f657 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultSaveBottomSheet.kt @@ -0,0 +1,57 @@ +package com.capstone.techwasmark02.ui.component + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme + +@Composable +fun DetectionsResultSaveBottomSheet(modifier: Modifier = Modifier) { + Column( + modifier = modifier + .fillMaxWidth() + .height(172.dp) + .background(MaterialTheme.colorScheme.tertiary) + .padding(horizontal = 20.dp) + .padding(top = 24.dp, bottom = 42.dp) + ) { + Text( + text = "Save your result", + style = MaterialTheme.typography.labelLarge + ) + + Spacer(modifier = Modifier.height(36.dp)) + + DefaultButton( + contentText = "Save", + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + ) + } +} + +@Preview +@Composable +fun DetectionsResultSaveBottomSheetPreview() { + TechwasMark02Theme { + Box( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.primaryContainer) + .padding(vertical = 20.dp) + ) { + DetectionsResultSaveBottomSheet() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentBottomSheet.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentBottomSheet.kt new file mode 100644 index 0000000..522a822 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentBottomSheet.kt @@ -0,0 +1,74 @@ +package com.capstone.techwasmark02.ui.component + +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.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme + +@Composable +fun UsableComponentBottomSheet(modifier: Modifier = Modifier) { + Column( + modifier = modifier + .fillMaxWidth() + .height(360.dp) + .background(MaterialTheme.colorScheme.tertiary) + .padding(top = 32.dp, bottom = 42.dp) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + ) { + Text( + text = "RAM", + style = MaterialTheme.typography.labelLarge + ) + + Text( + text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris tincidunt velit tortor, quis rutrum nunc viverra ac.", + style = MaterialTheme.typography.bodySmall + ) + + Spacer(modifier = Modifier.height(24.dp)) + } + + LazyRow( + contentPadding = PaddingValues(horizontal = 20.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + items(4) { + ArticleCardBig(modifier = Modifier.width(150.dp)) + } + } + } + +} + +@Preview (showBackground = true) +@Composable +fun UsableComponentBottomSheetPreview() { + TechwasMark02Theme { + Box( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.primaryContainer) + .padding(vertical = 20.dp) + ) { + UsableComponentBottomSheet() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentItem.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentItem.kt new file mode 100644 index 0000000..193c185 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentItem.kt @@ -0,0 +1,91 @@ +package com.capstone.techwasmark02.ui.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import coil.compose.rememberAsyncImagePainter +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import java.io.File +import kotlin.random.Random + +@Composable +fun UsableComponentItem( + modifier: Modifier = Modifier, + file: File? = null, + onClick: () -> Unit +) { + Row( + modifier = modifier + .width(155.dp) + .height(60.dp) + .clip(MaterialTheme.shapes.large) + .background(MaterialTheme.colorScheme.tertiary) + .clickable { onClick() } + ) { +// if (file != null) { +// +// } + Image( + painter = rememberAsyncImagePainter( + model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", + placeholder = painterResource(id = R.drawable.place_holder) + ), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .width(55.dp) + .fillMaxHeight() + ) + + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text( + text = "RAM", + style = MaterialTheme.typography.labelMedium.copy( + fontWeight = FontWeight.SemiBold + ), + ) + } + } +} + +@Preview (showBackground = true) +@Composable +fun UsableCompoenentItemPreview() { + TechwasMark02Theme { + Box( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.primaryContainer) + .padding(20.dp), + contentAlignment = Alignment.Center + ) { + UsableComponentItem( + onClick = {} + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt new file mode 100644 index 0000000..ce17b87 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt @@ -0,0 +1,235 @@ +package com.capstone.techwasmark02.ui.screen.detectionResult + +import androidx.activity.compose.BackHandler +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.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.ModalBottomSheetLayout +import androidx.compose.material.ModalBottomSheetValue +import androidx.compose.material.rememberModalBottomSheetState +import androidx.compose.material3.Button +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.capstone.techwasmark02.ui.component.ArticleCardBig +import com.capstone.techwasmark02.ui.component.DefaultButton +import com.capstone.techwasmark02.ui.component.DefaultTopBar +import com.capstone.techwasmark02.ui.component.DetectionsResultBox +import com.capstone.techwasmark02.ui.component.DetectionsResultSaveBottomSheet +import com.capstone.techwasmark02.ui.component.InverseButton +import com.capstone.techwasmark02.ui.component.UsableComponentBottomSheet +import com.capstone.techwasmark02.ui.component.UsableComponentItem +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import kotlinx.coroutines.launch + + +@Composable +fun DetectionResultScreen() { + DetectionResultContent() +} + +@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class) +@Composable +fun DetectionResultContent() { + val coroutineScope = rememberCoroutineScope() + val modalSheetState = rememberModalBottomSheetState( + initialValue = ModalBottomSheetValue.Hidden, + confirmStateChange = { it != ModalBottomSheetValue.HalfExpanded}, + skipHalfExpanded = true + ) + + var isOnBackClick by remember { + mutableStateOf(false) + } + + BackHandler(modalSheetState.isVisible) { + coroutineScope.launch { modalSheetState.hide() } + } + + BackHandler(!modalSheetState.isVisible) { + isOnBackClick = true + coroutineScope.launch { modalSheetState.show() } + } + + ModalBottomSheetLayout( + sheetState = modalSheetState, + sheetShape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp), + sheetContent = { + if (isOnBackClick) { + DetectionsResultSaveBottomSheet() + } else { + UsableComponentBottomSheet() + } + } + ) { + + Scaffold( + topBar = { + DefaultTopBar( + pageTitle = "Result", + onClickNavigationIcon = {} + ) + } + ) { innerPadding -> + val scrollState = rememberScrollState() + + Column( + modifier = Modifier + .verticalScroll(scrollState) + .padding(innerPadding) + .padding(bottom = 20.dp) + ) { + Box( + modifier = Modifier + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(236.dp) + .clip( + RoundedCornerShape( + bottomStart = 20.dp, + bottomEnd = 20.dp + ) + ) + .background(MaterialTheme.colorScheme.primary), + ) { + + } + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 138.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "Detected as", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onPrimary + ) + + DetectionsResultBox( + modifier = Modifier + .padding(horizontal = 20.dp) + ) + + } + } + + Column( + modifier = Modifier + .padding(horizontal = 20.dp) + .padding(top = 28.dp) + ) { + Text( + text = "Usable Components", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground + ) + + Spacer(modifier = Modifier.height(8.dp)) + + LazyVerticalGrid( + columns = GridCells.Fixed( + 2 + ), + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + modifier = Modifier.height(132.dp) + ) { + items(3) { item -> + UsableComponentItem( + onClick = { + isOnBackClick = false + coroutineScope.launch { + modalSheetState.show() + } + } + ) + } + } + + Spacer(modifier = Modifier.height(28.dp)) + + Text( + text = "Related Articles", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground + ) + + Spacer(modifier = Modifier.height(8.dp)) + } + + Column( + modifier = Modifier + .fillMaxWidth() + ) { + LazyRow( + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + items( + count = 10, + ) { item -> + ArticleCardBig( + modifier = Modifier + .width(150.dp) + ) + } + } + } + + Spacer(modifier = Modifier.height(28.dp)) + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 40.dp) + ) { + DefaultButton(contentText = "Drop Point", modifier = Modifier.fillMaxWidth()) + + Spacer(modifier = Modifier.height(20.dp)) + + InverseButton(contentText = "Check Out Forum", modifier = Modifier.fillMaxWidth()) + } + + } + } + + } +} + +@Preview +@Composable +fun DetectionResultContentPreview() { + TechwasMark02Theme { + DetectionResultContent() + } +} + diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index b980c26..3822d9f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -96,7 +96,7 @@ fun HomeContent() { } DetectionsFab( - modifier = Modifier.padding(bottom = 17.dp) + modifier = Modifier.padding(bottom = 25.dp) ) DefaultBottomBar(selectedType = BottomBarItemType.Home) diff --git a/app/src/main/res/drawable/ic_arrow_down.xml b/app/src/main/res/drawable/ic_arrow_down.xml new file mode 100644 index 0000000..e55596d --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_down.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_up.xml b/app/src/main/res/drawable/ic_arrow_up.xml new file mode 100644 index 0000000..0b0eae3 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_up.xml @@ -0,0 +1,5 @@ + + + From 00f89c3e3e5e528fbca1b68ea59ca157174cf1dc Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 22:55:02 +0700 Subject: [PATCH 02/73] add some dependencies for maps and pager --- .idea/discord.xml | 7 +++++++ app/build.gradle | 8 ++++++++ .../remote/response/UserRegisterResponse.kt | 2 ++ .../ui/component/SelectableText.kt | 2 ++ .../ui/screen/maps/MapsScreen.kt | 19 ++++++++++++++++++ .../ui/screen/splashScreen/SplashScreen.kt | 2 ++ app/src/main/res/drawable/forum_chat.png | Bin 0 -> 8342 bytes app/src/main/res/drawable/logo_techwase.png | Bin 0 -> 2679 bytes app/src/main/res/drawable/trash_bucket.png | Bin 0 -> 37073 bytes 9 files changed, 40 insertions(+) create mode 100644 .idea/discord.xml create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/remote/response/UserRegisterResponse.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt create mode 100644 app/src/main/res/drawable/forum_chat.png create mode 100644 app/src/main/res/drawable/logo_techwase.png create mode 100644 app/src/main/res/drawable/trash_bucket.png diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..30bab2a --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index e8e1511..39b5d18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,6 +3,7 @@ plugins { id 'org.jetbrains.kotlin.android' id 'org.jetbrains.kotlin.kapt' id 'dagger.hilt.android.plugin' + id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin' } android { @@ -99,6 +100,13 @@ dependencies { implementation 'com.squareup.moshi:moshi:1.14.0' implementation 'com.squareup.moshi:moshi-kotlin:1.14.0' + // Pager + implementation "com.google.accompanist:accompanist-pager:0.23.1" + + // Maps + implementation 'com.google.maps.android:maps-compose:2.10.0' + implementation 'com.google.android.gms:play-services-maps:18.1.0' + testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/UserRegisterResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/UserRegisterResponse.kt new file mode 100644 index 0000000..742252f --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/UserRegisterResponse.kt @@ -0,0 +1,2 @@ +package com.capstone.techwasmark02.data.remote.response + diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt new file mode 100644 index 0000000..7fa73aa --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt @@ -0,0 +1,2 @@ +package com.capstone.techwasmark02.ui.component + diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt new file mode 100644 index 0000000..8d0cd89 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt @@ -0,0 +1,19 @@ +package com.capstone.techwasmark02.ui.screen.maps + +import androidx.compose.runtime.Composable +import com.google.android.gms.maps.model.CameraPosition +import com.google.android.gms.maps.model.LatLng +import com.google.maps.android.compose.GoogleMap +import com.google.maps.android.compose.rememberCameraPositionState + +@Composable +fun MapScreen() { + val bucharest = LatLng(44.43, 26.09) + val cameraPositionState = rememberCameraPositionState { + position = CameraPosition.fromLatLngZoom(bucharest, 10f) + } + + GoogleMap( + cameraPositionState = cameraPositionState + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt new file mode 100644 index 0000000..b370353 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt @@ -0,0 +1,2 @@ +package com.capstone.techwasmark02.ui.screen.splashScreen + diff --git a/app/src/main/res/drawable/forum_chat.png b/app/src/main/res/drawable/forum_chat.png new file mode 100644 index 0000000000000000000000000000000000000000..85ac970d21c0c1adbfecdfc7a9403685be67923b GIT binary patch literal 8342 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/logo_techwase.png b/app/src/main/res/drawable/logo_techwase.png new file mode 100644 index 0000000000000000000000000000000000000000..7e42bd9055923ba146866ad132c62f767bdabfb6 GIT binary patch literal 2679 zcmV--3W)WIP);DXVhg4VdiC{|6~D5y2oYAPnC#?)mDc&hcpg;*=LD(KND zH6k|A7(Fs-RH9XJ0Wn7-?jl4HcV>D0?;U2sz%cU$#=-BLIrq+e|9#BI|KESP_X=<_ zLe#2YnNk@ghzJ!0Ay@#y1ks=pA*f6;0>l#fUO>+aU@)8$APErY5Rj_ZY8TgrWR1wZ zQc{&s3z80z3s$RC^%Y7+Dgmy9fC7UkTYYJM;VQ?bNkoSweqkh>0TIEdD>$e{N#r^$ z@tY-zaOl7G%0OBqg3(e4%IpbrTGDvYYeS5IEJv=+rPzKZl|Q@o;3}o9 zVzqPSGGS8~B^edREXdWBIkNSX^juc;ZX*a}PHU-u_&C+3vdpL6}9_ zTV--CW^&{mE4Z6Wek!1#z24R3XOTt~6?{_{n`q?m-*Y-bnsg!)yot~EeqvYNMDG5Rdyoo~Y0B7U4qODLt!a@T z@&1&pqq%o9pNMlKDv$yz#Jrx1r6u^T3)u`2b>je89)W3-2c%UW%GRGPy(LcHc9&4|y;*bZ8ce zX?;GjkYV04eoGAhvBNr!!iW7n<>L{-#=0!~+F`S7RNKM$6M0W&j%b@wD!m+LJBQm%-b^7vTXt z@x1IAIgJ#&OWKJDj^xiz-S~CUKX_UUH+eloP{A41b`a`OtU7z^Br?zM;Q8ccN|@P} zK{^$pYYs2tbJ!aDV${FMfk ztr)ezA{1;mp3FlBBg1gH@B(ia4q1*sua-QBuRN4Q;UowfC+xy!gZ^etq~~NzMQy>3 z#pHg`?!Cyq-;y$+^hF63kM;Sw>(I0dmLFV1Zu$qVy)bgyEV!4xc*MP;Uev?0UL$l3 zG`@Pz`E=6sZ+X09W|%;liRm&9t4D7_3$GwP#$ss3xv$_1Xk}O?bWZe%F$glr+Y2mx z`uY!tc*e0WHv^wif!V~f8K(F77$ZZ+a~YPc%-b^qqQSsxHilEzkMVsGw)Xa4+Jgb@ zhH_1@^}8{94K`=5v&c1TiIUv;MP33+FllS-p(8UHF}B~qT1Mm_v~F1D@n+-pNFJSv z05Us<|I*lduQ!#5`>!&M)i6EcWXyDe6_7N47)wjiO zLX267IgBRBdVKebZH0AA^vk4xUgI4wrj5f_4gl-}aAIr68a-bMl|-%~ zMzNbtU`>5<`lZ*))o=os250u2i*51yc--4{ZY#dd*$S6{V)ms4_jjAV%1xbO&6ASG z(e+!BfZapA>JatjAZ#Kp8rix(ub|f)S%wvd5@{RU09Szi%A?v&o* z-`OV4((gaRf&6dbO0XMAI-Me%dB}?6RZ1T6H0(5013QTA`A7IrBF#z@Q%x3|Hq7P3 z80hS0ab;o*R_i&XPCL?8DKxzg6{bC=^5ofsf?uw_vY>1WbgH$wTp?9pl^hEVdaayd zg=qEM$jieUQ@4%bWseDGZe_#u5H)!VimE*duz8!ocs4F(S#vPGTSa00xOAjuucfWG zJ4ip9Myb_HxDYu{b=qiKH~s8hvI$W)4VEkQS(UfkS#H_P)1Qu>>PBNvb-I!Et}sfv zK~x>Vx&T{awoI`i{lBl$xqDlv@nzCZiN0!4Cd9p3lA?x=vlm~ibOl2yYIReV-M{ouDr20l$=Z=J!6|o~ z8TcI*1L6fi>_@M4DET&C=mtx8Gsz34I_o00)5ui>(`W-aAERxvULAK;0Z$H}7hL{{waz0TA{E5gZ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/trash_bucket.png b/app/src/main/res/drawable/trash_bucket.png new file mode 100644 index 0000000000000000000000000000000000000000..d75895d0aab2da7ba96bb2192470a3d8db7f8483 GIT binary patch literal 37073 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 R`~Cm`002ovPDHLkV1h}qxy1kg literal 0 HcmV?d00001 From 2eb327b5409b6792edbb67fcbdb56caa7fa7ff68 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 22:55:31 +0700 Subject: [PATCH 03/73] configure permission for maps --- app/src/main/AndroidManifest.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a8a7842..167da98 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,6 +10,10 @@ + + + + + + Date: Fri, 26 May 2023 22:55:57 +0700 Subject: [PATCH 04/73] trying some screen --- .../main/java/com/capstone/techwasmark02/MainActivity.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt b/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt index baf8b2e..69b1ee6 100644 --- a/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt +++ b/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt @@ -7,9 +7,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.ui.Modifier -import com.capstone.techwasmark02.ui.screen.detectionResult.DetectionResultScreen -import com.capstone.techwasmark02.ui.screen.imageDetection.ImageDetectionScreen -import com.capstone.techwasmark02.ui.screen.signIn.SignInScreen +import com.capstone.techwasmark02.ui.screen.maps.MapsScreen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import dagger.hilt.android.AndroidEntryPoint @@ -24,7 +22,7 @@ class MainActivity : ComponentActivity() { modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { - DetectionResultScreen() + MapsScreen() } } } From 8dac324e6f8a207c3ad593c8e6db8e426c443b34 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 22:56:21 +0700 Subject: [PATCH 05/73] implement register --- .../techwasmark02/data/remote/apiService/TechwasUserApi.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasUserApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasUserApi.kt index cc4f41d..69ebf9f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasUserApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasUserApi.kt @@ -3,6 +3,7 @@ package com.capstone.techwasmark02.data.remote.apiService import com.capstone.techwasmark02.data.model.UserLoginInfo import com.capstone.techwasmark02.data.model.UserRegisterInfo import com.capstone.techwasmark02.data.remote.response.UserLoginResponse +import com.capstone.techwasmark02.data.remote.response.UserRegisterResponse import retrofit2.http.Body import retrofit2.http.POST @@ -16,9 +17,7 @@ interface TechwasUserApi { @POST("user/signup") suspend fun register( @Body userRegisterInfo: UserRegisterInfo - ) : String - - + ) : UserRegisterResponse companion object { const val BASE_URL = "https://the-prophecy-fwd5gpydiq-uc.a.run.app/" From 0e32261c4f791ea1de49d91ce2100cb8dd91ca45 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 22:56:45 +0700 Subject: [PATCH 06/73] add response for register --- .../data/remote/response/UserRegisterResponse.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/UserRegisterResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/UserRegisterResponse.kt index 742252f..79aefb1 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/UserRegisterResponse.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/UserRegisterResponse.kt @@ -1,2 +1,18 @@ package com.capstone.techwasmark02.data.remote.response +import com.google.gson.annotations.SerializedName + +data class UserRegisterResponse( + val error: String, + val message: String, + val registerResult: RegisterResult, +) + +data class RegisterResult( + val signupToken: SignUpToken, +) + +data class SignUpToken( + @SerializedName("access token") + val accessToken: String +) \ No newline at end of file From dd946d9b3f1cd48db81ae77b3746178f206ac850 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 22:57:03 +0700 Subject: [PATCH 07/73] implement register --- .../techwasmark02/repository/TechwasUserApiRepository.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasUserApiRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasUserApiRepository.kt index ca0821a..d943bff 100644 --- a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasUserApiRepository.kt +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasUserApiRepository.kt @@ -4,6 +4,7 @@ import com.capstone.techwasmark02.data.model.UserLoginInfo import com.capstone.techwasmark02.data.model.UserRegisterInfo import com.capstone.techwasmark02.data.remote.apiService.TechwasUserApi import com.capstone.techwasmark02.data.remote.response.UserLoginResponse +import com.capstone.techwasmark02.data.remote.response.UserRegisterResponse import com.capstone.techwasmark02.ui.common.UiState import java.lang.Exception import javax.inject.Inject @@ -22,7 +23,7 @@ class TechwasUserApiRepository @Inject constructor( return UiState.Success(data = response) } - suspend fun userRegister(userRegisterInfo: UserRegisterInfo) : UiState { + suspend fun userRegister(userRegisterInfo: UserRegisterInfo) : UiState { val response = try { userApi.register(userRegisterInfo) From 8e00e4b159aa9e58d43f8564a0f27da25d284b22 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 22:57:29 +0700 Subject: [PATCH 08/73] create some banner --- .../techwasmark02/ui/component/Banner.kt | 239 +++++++++++++++--- 1 file changed, 204 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt index 793e532..bf18cce 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt @@ -1,14 +1,20 @@ package com.capstone.techwasmark02.ui.component +import androidx.compose.foundation.Image 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.Spacer import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -18,9 +24,20 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Shadow +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.theme.Black20 +import com.capstone.techwasmark02.ui.theme.Green77 import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import com.capstone.techwasmark02.ui.theme.Yellow77 +import com.capstone.techwasmark02.ui.theme.poppins @Composable fun SignInBanner( @@ -101,45 +118,193 @@ fun SignUpBanner( @Composable fun DropPointBanner(modifier: Modifier = Modifier) { Box( - modifier = modifier - .height(175.dp) - .fillMaxWidth() - .shadow( - elevation = 12.dp, - shape = MaterialTheme.shapes.large, - clip = true, - ) - .clip(MaterialTheme.shapes.large) - .background( - MaterialTheme.colorScheme.primary, - ) - .padding(horizontal = 18.dp), - contentAlignment = Alignment.CenterEnd + modifier = modifier.height(190.dp), + contentAlignment = Alignment.BottomStart ) { - Column( + Box( modifier = Modifier - .fillMaxHeight(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.End + .height(175.dp) + .fillMaxWidth() + .clip(MaterialTheme.shapes.large) + .background( + Green77.copy(alpha = 0.5f), + ), + contentAlignment = Alignment.Center ) { - Text( - text = "Don't know where to", - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onPrimary, - ) - Text( - text = "put your e-waste?", - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onPrimary, - ) - Text( - text = "We've got you covered", - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onPrimary, - ) - Spacer(modifier = Modifier.height(12.dp)) - SmallButton(contentText = "LOCATE NOW") + Box( + modifier = Modifier + .fillMaxHeight() + .fillMaxWidth() + .clip(RoundedCornerShape(44.dp)) + .background( + Green77.copy(alpha = 0.5f) + ) + ) { + Box( + modifier = Modifier + .fillMaxHeight() + .fillMaxSize() + .clip(RoundedCornerShape(65.dp)) + .background( + Green77.copy(alpha = 0.7f) + ) + ) + } + Row( + modifier = Modifier + .padding(horizontal = 18.dp) + .fillMaxWidth() + .fillMaxHeight(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Spacer(modifier = Modifier.width(150.dp)) + Column( + modifier = Modifier.fillMaxWidth() + ) { + + val text = buildAnnotatedString { + append("Don't know where to put your ") + withStyle(style = SpanStyle(color = Yellow77)) { + append("e-waste?") + } + } + + Text( + text = text, + style = MaterialTheme.typography.labelLarge.copy( + shadow = Shadow( + color = Black20.copy( + alpha = 0.25f, + ), + offset = Offset(0f, 4.0f), + blurRadius = 4f + ), + fontSize = 22.sp, + lineHeight = 25.sp, + letterSpacing = 0.sp, + color = MaterialTheme.colorScheme.onPrimary, + fontFamily = poppins + ) + ) + Spacer(modifier = Modifier.height(10.dp)) + Row(modifier = Modifier.align(alignment = Alignment.CenterHorizontally)) { + SmallButton(contentText = "LOCATE NOW") + } + } + } + } + Image( + painter = painterResource(id = R.drawable.trash_bucket), + contentDescription = "Image", + modifier = Modifier + .height(400.dp) + .width(200.dp) + .offset(y = 0.dp, x = 10.dp) + ) + } +} + +@Composable +fun ForumBanner(modifier: Modifier = Modifier) { + Box( + modifier = modifier.height(190.dp), + contentAlignment = Alignment.BottomStart + ) { + Box( + modifier = Modifier + .height(175.dp) + .fillMaxWidth() + .clip(MaterialTheme.shapes.large) + .background( + Green77.copy(alpha = 0.5f), + ), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .fillMaxHeight() + .fillMaxWidth() + .clip(RoundedCornerShape(39.dp)) + .background( + Green77.copy(alpha = 0.5f) + ) + ) { + Box( + modifier = Modifier + .fillMaxHeight() + .fillMaxSize() + .clip(RoundedCornerShape(72.dp)) + .background( + Green77.copy(alpha = 0.7f) + ) + ) + } + Row( + modifier = Modifier + .padding(horizontal = 18.dp) + .fillMaxWidth() + .fillMaxHeight(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Spacer(modifier = Modifier.width(160.dp)) + Column( + modifier = Modifier.fillMaxWidth() + ) { + Row(modifier = Modifier.align(alignment = Alignment.CenterHorizontally)) { + SmallButton(contentText = "LOCATE NOW") + } + + Spacer(modifier = Modifier.height(10.dp)) + + val text = buildAnnotatedString { + append("Don't know where to put your ") + withStyle(style = SpanStyle(color = Yellow77)) { + append("e-waste?") + } + } + + Text( + text = "Join the discussions!", + modifier = Modifier.width(200.dp), + style = MaterialTheme.typography.labelSmall.copy( + shadow = Shadow( + color = Black20.copy( + alpha = 0.25f, + ), + offset = Offset(0f, 4.0f), + blurRadius = 4f, + ), + fontSize = 13.sp, + lineHeight = 25.sp, + letterSpacing = 0.sp, + color = MaterialTheme.colorScheme.onPrimary, + fontFamily = poppins, + textAlign = TextAlign.End + ) + ) + + Text( + text = "Get involved in discussion with other users.", + style = MaterialTheme.typography.bodyMedium, + fontSize = 11.sp, + textAlign = TextAlign.End, + color = MaterialTheme.colorScheme.onPrimary, + fontFamily = poppins + ) + + } + } } + Image( + painter = painterResource(id = R.drawable.forum_chat), + contentDescription = "Image", + modifier = Modifier + .height(400.dp) + .width(170.dp) + .offset(y = 0.dp, x = 20.dp) + ) } } @@ -171,6 +336,10 @@ fun HomeBannerPreview() { .padding(16.dp) ) { DropPointBanner() + + Spacer(modifier = Modifier.height(16.dp)) + + ForumBanner() } } From 11214a826323547770dbe9931acc5b9a464efadb Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 22:58:01 +0700 Subject: [PATCH 09/73] add selectableText for filter purpose --- .../ui/component/SelectableText.kt | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt index 7fa73aa..4f9d90b 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt @@ -1,2 +1,54 @@ package com.capstone.techwasmark02.ui.component +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.capstone.techwasmark02.ui.theme.Black20 +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme + +@Composable +fun SelectableText( + text: String, + selected: Boolean, + modifier: Modifier = Modifier, + activeColor: Color = MaterialTheme.colorScheme.primary, + inactiveColor: Color = Color.Transparent +) { + Box( + modifier = modifier + .background( + color = if (selected) activeColor else inactiveColor, + shape = RoundedCornerShape(15.dp) + ) + .padding(8.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = text, + style = MaterialTheme.typography.bodyMedium, + color = if (selected) Color.White else Black20 + ) + } +} + +@Preview(showBackground = true) +@Composable +fun SelectableTextPreview() { + TechwasMark02Theme { + Box(modifier = Modifier.padding(20.dp)){ + SelectableText( + text = "Click me", + selected = true + ) + } + } +} \ No newline at end of file From dde125ae40ea1ecdf6be36f20ab3b96c9ea9aae4 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 22:58:21 +0700 Subject: [PATCH 10/73] adjust some --- .../techwasmark02/ui/component/UserGreet.kt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/UserGreet.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/UserGreet.kt index 38255be..389f798 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/UserGreet.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/UserGreet.kt @@ -19,6 +19,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.capstone.techwasmark02.R @@ -40,16 +43,18 @@ fun UserGreet( Row( modifier = Modifier ) { + val text = buildAnnotatedString { + append("Hello,\n") + withStyle(style = SpanStyle(color = MaterialTheme.colorScheme.primary)) { + append("$userName.") + } + } + Text( - text = "Hello, ", + text = text, style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.inverseSurface, ) - Text( - text = "$userName.", - style = MaterialTheme.typography.headlineSmall, - color = MaterialTheme.colorScheme.primary - ) } Box( From 1ed5995facec73688ae722553981fe7d8322d103 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 22:58:48 +0700 Subject: [PATCH 11/73] implement pager --- .../ui/screen/home/HomeScreen.kt | 101 +++++++++++++++--- 1 file changed, 88 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index 3822d9f..65bbb88 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -1,5 +1,6 @@ package com.capstone.techwasmark02.ui.screen.home +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -7,10 +8,18 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Card import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold @@ -18,24 +27,50 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.lerp +import androidx.compose.ui.util.lerp import com.capstone.techwasmark02.ui.component.ArticleCardBig import com.capstone.techwasmark02.ui.component.DefaultBottomBar import com.capstone.techwasmark02.ui.component.DetectionsFab import com.capstone.techwasmark02.ui.component.DropPointBanner +import com.capstone.techwasmark02.ui.component.ForumBanner +import com.capstone.techwasmark02.ui.component.SelectableText import com.capstone.techwasmark02.ui.component.UserGreet import com.capstone.techwasmark02.ui.componentType.BottomBarItemType import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import kotlin.math.absoluteValue @Composable fun HomeScreen() { HomeContent() } -@OptIn(ExperimentalMaterial3Api::class) +@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable fun HomeContent() { + + val filterTypeList = listOf( + "General", + "Laptop", + "Baterai", + "Kabel", + "General", + "Laptop", + "Baterai", + "Kabel", + "General", + "Laptop", + "Baterai", + "Kabel", + "General", + "Laptop", + "Baterai", + "Kabel", + ) + Scaffold( ) { innerPadding -> @@ -49,6 +84,7 @@ fun HomeContent() { Column( modifier = Modifier .fillMaxSize() + .verticalScroll(rememberScrollState()) .padding(bottom = 60.dp, top = 20.dp), horizontalAlignment = Alignment.CenterHorizontally ) { @@ -58,7 +94,7 @@ fun HomeContent() { ) { UserGreet(userName = "Zhahrany") - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(10.dp)) DropPointBanner() @@ -69,28 +105,67 @@ fun HomeContent() { style = MaterialTheme.typography.labelLarge, modifier = Modifier.padding(start = 8.dp) ) - } - LazyRow( - contentPadding = PaddingValues(horizontal = 16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - items( - count = 10, + + LazyRow( + horizontalArrangement = Arrangement.Start, ) { - ArticleCardBig( - modifier = Modifier.width(240.dp) - ) + items( + items = filterTypeList, + ) { item -> + SelectableText( + text = item, + selected = false + ) + } } } Spacer(modifier = Modifier.height(20.dp)) + val pagerState = rememberPagerState() + HorizontalPager( + pageCount = 10, + state = pagerState, + contentPadding = PaddingValues(horizontal = 70.dp), + modifier = Modifier.fillMaxWidth() + ) { page -> + ArticleCardBig( + modifier = Modifier + .width(240.dp) + .graphicsLayer { + // Calculate the absolute offset for the current page from the + // scroll position. We use the absolute value which allows us to mirror + // any effects for both directions + val pageOffset = ( + (pagerState.currentPage - page) + pagerState + .currentPageOffsetFraction + ).absoluteValue + + lerp( + start = 0.85f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f) + ).also { scale -> + scaleX = scale + scaleY = scale + } + alpha = lerp( + start = 0.5f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f) + ) + } + ) + } + + Spacer(modifier = Modifier.height(20.dp)) + Column( modifier = Modifier .padding(horizontal = 16.dp) ) { - DropPointBanner() + ForumBanner() } } From a8560c3265d2b4b20155852c2c3954e4d9ce8fc4 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 22:59:04 +0700 Subject: [PATCH 12/73] add maps screen --- .../com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt index 8d0cd89..adf3627 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt @@ -7,10 +7,10 @@ import com.google.maps.android.compose.GoogleMap import com.google.maps.android.compose.rememberCameraPositionState @Composable -fun MapScreen() { - val bucharest = LatLng(44.43, 26.09) +fun MapsScreen() { + val diy = LatLng(-7.782275587997325, 110.36709993087182) val cameraPositionState = rememberCameraPositionState { - position = CameraPosition.fromLatLngZoom(bucharest, 10f) + position = CameraPosition.fromLatLngZoom(diy, 10f) } GoogleMap( From 8c135a59e636168d3b17406f002efe28518d9e88 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 22:59:26 +0700 Subject: [PATCH 13/73] implement register --- .../ui/screen/signUp/SignUpScreen.kt | 111 +++++++++++++----- 1 file changed, 84 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreen.kt index e2d2b39..b16bbb4 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreen.kt @@ -1,26 +1,34 @@ package com.capstone.techwasmark02.ui.screen.signUp import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import com.capstone.techwasmark02.data.model.UserRegisterInfo +import com.capstone.techwasmark02.data.remote.response.UserRegisterResponse +import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.DefaultButton import com.capstone.techwasmark02.ui.component.DefaultTextField import com.capstone.techwasmark02.ui.component.InverseTopBar @@ -29,29 +37,33 @@ import com.capstone.techwasmark02.ui.component.SignUpBanner import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @Composable -fun SignUpScreen() { - SignUpContent() +fun SignUpScreen( + viewModel: SignUpScreenViewModel = hiltViewModel() +) { + val userToSignUpState by viewModel.userToSignUpState.collectAsState() + val userToSignUpInfo by viewModel.userToSignUpInfo.collectAsState() + + SignUpContent( + userToSignUpInfo = userToSignUpInfo, + updateUserRegisterInfo = { viewModel.updateUserSignUpInfo(it) }, + userToSignUpState = userToSignUpState, + signUpUser = { viewModel.signUpUser() } + ) } @OptIn(ExperimentalMaterial3Api::class) @Composable -fun SignUpContent() { - var email by remember { - mutableStateOf("") - } - - var password by remember { - mutableStateOf("") - } +fun SignUpContent( + userToSignUpInfo: UserRegisterInfo, + updateUserRegisterInfo: (UserRegisterInfo) -> Unit, + userToSignUpState: UiState?, + signUpUser: () -> Unit +) { var showPassword by remember { mutableStateOf(false) } - var fullName by remember { - mutableStateOf("") - } - Scaffold( topBar = { InverseTopBar( @@ -94,8 +106,12 @@ fun SignUpContent() { Spacer(modifier = Modifier.height(20.dp)) DefaultTextField( - value = fullName, - onValueChange = { newValue -> fullName = newValue}, + value = userToSignUpInfo.fullname, + onValueChange = { newValue -> + updateUserRegisterInfo(userToSignUpInfo.copy( + fullname = newValue + )) + }, labelText = "Full Name", placeHolderText = "user full name", modifier = Modifier.fillMaxWidth() @@ -104,8 +120,12 @@ fun SignUpContent() { Spacer(modifier = Modifier.height(16.dp)) DefaultTextField( - value = email, - onValueChange = { newValue -> email = newValue}, + value = userToSignUpInfo.email, + onValueChange = { newValue -> + updateUserRegisterInfo(userToSignUpInfo.copy( + email = newValue + )) + }, labelText = "Email", placeHolderText = "user email", modifier = Modifier.fillMaxWidth() @@ -114,20 +134,52 @@ fun SignUpContent() { Spacer(modifier = Modifier.height(16.dp)) PasswordTextField( - value = password, - onValueChange = { newValue -> password = newValue}, + value = userToSignUpInfo.password, + onValueChange = { newValue -> + updateUserRegisterInfo(userToSignUpInfo.copy( + password = newValue + )) + }, showPassword = showPassword, toggleShowPassword = { showPassword = !showPassword }, modifier = Modifier.fillMaxWidth() ) - Spacer(modifier = Modifier.weight(1f)) - - DefaultButton(contentText = "Sign Up", modifier = Modifier - .fillMaxWidth() - .height(50.dp)) - + if(userToSignUpState != null) { + Box( + modifier = Modifier + .weight(1f) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + when(userToSignUpState) { + is UiState.Loading -> { + CircularProgressIndicator() + } + is UiState.Error -> { + userToSignUpState.message?.let { + Text(text = it) + } + } + is UiState.Success -> { + userToSignUpState.data?.message?.let { + Text(text = it) + } + } + } + } + } else { + Spacer(modifier = Modifier.weight(1f)) + } + + DefaultButton( + contentText = "Sign Up", + modifier = Modifier + .fillMaxWidth() + .height(50.dp), + onClick = signUpUser + ) } } } @@ -137,6 +189,11 @@ fun SignUpContent() { @Composable fun SingUpContentPreview() { TechwasMark02Theme { - SignUpContent() + SignUpContent( + userToSignUpState = null, + userToSignUpInfo = UserRegisterInfo("", "", ""), + updateUserRegisterInfo = {}, + signUpUser = {} + ) } } \ No newline at end of file From 32e581a45ab19794a0db089f83895e704ed83530 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 22:59:40 +0700 Subject: [PATCH 14/73] implement register --- .../ui/screen/signUp/SignUpScreenViewModel.kt | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreenViewModel.kt index a1dd5f2..6aac930 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreenViewModel.kt @@ -1,15 +1,59 @@ package com.capstone.techwasmark02.ui.screen.signUp import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.data.model.UserRegisterInfo +import com.capstone.techwasmark02.data.remote.response.UserRegisterResponse import com.capstone.techwasmark02.repository.PreferencesRepository import com.capstone.techwasmark02.repository.TechwasUserApiRepository +import com.capstone.techwasmark02.ui.common.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch import javax.inject.Inject +@HiltViewModel class SignUpScreenViewModel @Inject constructor( private val userApiRepository: TechwasUserApiRepository, private val preferencesRepository: PreferencesRepository ): ViewModel() { -// private val _userToSignUpState + private val _userToSignUpState: MutableStateFlow?> = + MutableStateFlow(null) + val userToSignUpState = _userToSignUpState.asStateFlow() + private val _userToSignUpInfo: MutableStateFlow = + MutableStateFlow( + UserRegisterInfo( + fullname = "", + email = "", + password = "" + ) + ) + val userToSignUpInfo = _userToSignUpInfo.asStateFlow() + + fun signUpUser() { + _userToSignUpState.value = UiState.Loading() + viewModelScope.launch { + val result = userApiRepository.userRegister(_userToSignUpInfo.value) + when (result) { + is UiState.Success -> { + _userToSignUpState.value = result + } + + is UiState.Error -> { + _userToSignUpState.value = result + } + + else -> { + // do nothing + } + } + } + } + + fun updateUserSignUpInfo(userToSignUpInfo: UserRegisterInfo) { + _userToSignUpInfo.value = userToSignUpInfo + } } \ No newline at end of file From 0263a2b101ac7511d8942d3c2d3f69e7e476e6a3 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 23:00:33 +0700 Subject: [PATCH 15/73] try create splashScreen --- .../ui/screen/splashScreen/SplashScreen.kt | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt index b370353..79fd81b 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt @@ -1,2 +1,85 @@ package com.capstone.techwasmark02.ui.screen.splashScreen +import android.window.SplashScreen +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.runtime.* +import androidx.compose.ui.draw.alpha +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.theme.Green77 +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import kotlinx.coroutines.delay + +@Composable +fun SplashScreen() { + + var animationState by remember { + mutableStateOf(false) + } + + val alphaAnim = animateFloatAsState( + targetValue = if (animationState) 1f else 0f, + animationSpec = tween( + durationMillis = 3000 // 3 sec + ) + ) + + LaunchedEffect(key1 = true) { + animationState = true + delay(4000) + // navController.navigate(Screen.Home.route) + } + + SplashContent(alpha = alphaAnim.value) +} + +@Composable +fun SplashContent(alpha: Float) { + Box( + modifier = Modifier + .background( + Green77 + ) + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + + Image( + painter = painterResource(id = R.drawable.logo_techwase), + contentDescription = "logo techwaste", + modifier = Modifier + .size(100.dp) + .alpha(alpha) + ) + } +} + +@Preview(showBackground = true) +@Composable +fun SplashScreenPreview() { + TechwasMark02Theme { + SplashContent(alpha = 1f) + } +} \ No newline at end of file From c0ebd10cae173bb1350ead0c5c06019a055d3991 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 23:00:52 +0700 Subject: [PATCH 16/73] add some colors --- .../main/java/com/capstone/techwasmark02/ui/theme/Color.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/theme/Color.kt b/app/src/main/java/com/capstone/techwasmark02/ui/theme/Color.kt index 8678a3f..8fc2f7f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/theme/Color.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/theme/Color.kt @@ -3,10 +3,13 @@ package com.capstone.techwasmark02.ui.theme import androidx.compose.ui.graphics.Color val Green35 = Color(0xff5bb915) +val Green77 = Color(0xFF54B800) val Black20 = Color(0xff323232) val Black12 = Color(0xff1F1F1F) val Lime56 = Color(0xff9ED54A) -val Mist97 = Color(0xffF1EEFF) \ No newline at end of file +val Mist97 = Color(0xffF1EEFF) + +val Yellow77 = Color(0xFFFFDF5D) \ No newline at end of file From b8e9a0ef69fa4b518ad938b2fe66ef5595c1b66c Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 26 May 2023 23:01:11 +0700 Subject: [PATCH 17/73] adding some dependencies for maps and pager --- build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 92d9f45..928c336 100644 --- a/build.gradle +++ b/build.gradle @@ -4,4 +4,5 @@ plugins { id 'com.android.library' version '8.0.1' apply false id 'org.jetbrains.kotlin.android' version '1.7.20' apply false id 'com.google.dagger.hilt.android' version '2.44' apply false -} \ No newline at end of file + id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin' version '2.0.1' apply false +} From 57a9350351212e4e1346d36758b60a98ab75f113 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 1 Jun 2023 23:24:58 +0700 Subject: [PATCH 18/73] add: make new component --- .../techwasmark02/ui/component/DetectBox.kt | 307 ++++++++++++++++++ .../techwasmark02/ui/component/ForumBox.kt | 103 ++++++ .../techwasmark02/ui/component/ProfileBox.kt | 2 + .../screen/profileUser/ProfileUserScreen.kt | 2 + .../singleArticle/SingleArticleScreen.kt | 2 + app/src/main/res/drawable/ic_center_focus.xml | 5 + app/src/main/res/drawable/ic_language.xml | 5 + app/src/main/res/drawable/ic_location_on.xml | 5 + app/src/main/res/drawable/ic_logout.xml | 5 + app/src/main/res/drawable/ic_menu_book.xml | 8 + .../main/res/drawable/ic_question_mark.xml | 5 + app/src/main/res/drawable/img_bg_green.png | Bin 0 -> 3746 bytes app/src/main/res/drawable/img_bg_purple.png | Bin 0 -> 2663 bytes app/src/main/res/drawable/img_bg_sakura.png | Bin 0 -> 2973 bytes app/src/main/res/drawable/logo_techwaste.png | Bin 0 -> 537 bytes 15 files changed, 449 insertions(+) create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt create mode 100644 app/src/main/res/drawable/ic_center_focus.xml create mode 100644 app/src/main/res/drawable/ic_language.xml create mode 100644 app/src/main/res/drawable/ic_location_on.xml create mode 100644 app/src/main/res/drawable/ic_logout.xml create mode 100644 app/src/main/res/drawable/ic_menu_book.xml create mode 100644 app/src/main/res/drawable/ic_question_mark.xml create mode 100644 app/src/main/res/drawable/img_bg_green.png create mode 100644 app/src/main/res/drawable/img_bg_purple.png create mode 100644 app/src/main/res/drawable/img_bg_sakura.png create mode 100644 app/src/main/res/drawable/logo_techwaste.png diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt new file mode 100644 index 0000000..8f5be62 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt @@ -0,0 +1,307 @@ +package com.capstone.techwasmark02.ui.component + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import com.capstone.techwasmark02.ui.theme.gray +import com.capstone.techwasmark02.ui.theme.purple +import com.capstone.techwasmark02.ui.theme.sakura + +@Composable +fun DetectBox1(modifier: Modifier = Modifier) { + BoxWithConstraints( + modifier = Modifier + .width(150.dp) + .height(160.dp) + .border( + BorderStroke( + width = 1.dp, + color = Color.Black + ), + shape = RoundedCornerShape(10.dp) + ) + .shadow( + elevation = 4.dp, + shape = RoundedCornerShape(10.dp) + ) + ) { + Image( + painter = painterResource(id = R.drawable.img_bg_green), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .fillMaxSize() + ) + Column( + modifier = Modifier.fillMaxSize() + ) { + Box( + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp, top = 16.dp) + ) { + Text( + text = "Detect\ne-waste", + style = MaterialTheme.typography.titleLarge, + color = Color.White + ) + } + } + + Spacer(modifier = Modifier.height(40.dp)) + + Box( + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.size(33.dp, 25.dp), + painter = painterResource(id = R.drawable.ic_center_focus), + contentDescription = null, + tint = Color.White + ) + Spacer(modifier = Modifier.weight(1f)) + SmallButton( + contentText = "Detect", + onClick = {}, + colorText = MaterialTheme.colorScheme.primary + ) + } + } + } + } +} + +@Composable +fun DetectBox2(modifier: Modifier = Modifier) { + BoxWithConstraints( + modifier = Modifier + .width(150.dp) + .height(160.dp) + ) { + Image( + painter = painterResource(id = R.drawable.img_bg_purple), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxSize() + ) + Column( + modifier = Modifier.fillMaxSize() + ) { + Box( + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp, top = 16.dp) + ) { + Text( + text = "E-waste\ncatalog", + style = MaterialTheme.typography.titleLarge, + color = Color.White + ) + } + } + + Spacer(modifier = Modifier.height(40.dp)) + + Box( + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.size(33.dp, 25.dp), + painter = painterResource(id = R.drawable.ic_menu_book), + contentDescription = null, + tint = Color.White + ) + Spacer(modifier = Modifier.weight(1f)) + SmallButton( + contentText = "Detect", + onClick = {}, + colorText = purple + ) + } + } + } + } +} + +@Composable +fun DetectBox3(modifier: Modifier = Modifier) { + BoxWithConstraints( + modifier = Modifier + .width(150.dp) + .height(160.dp) + ) { + Image( + painter = painterResource(id = R.drawable.img_bg_sakura), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxSize() + ) + Column( + modifier = Modifier.fillMaxSize() + ) { + Box( + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp, top = 16.dp) + ) { + Text( + text = "Nearby\ndrop point", + style = MaterialTheme.typography.titleLarge, + color = Color.White + ) + } + } + + Spacer(modifier = Modifier.height(40.dp)) + + Box( + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.size(33.dp, 25.dp), + painter = painterResource(id = R.drawable.ic_location_on), + contentDescription = null, + tint = Color.White + ) + Spacer(modifier = Modifier.weight(1f)) + SmallButton( + contentText = "Locate", + onClick = {}, + colorText = sakura + ) + } + } + } + } +} + +@Composable +fun DetectBox4(modifier: Modifier = Modifier) { + Box( + modifier = Modifier + .width(150.dp) + .height(160.dp) + .clip( + RoundedCornerShape( + 10.dp + ) + ) + .background(gray) + ) { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Box( + modifier = Modifier + .size(50.dp) + .clip(CircleShape) + .border( + BorderStroke( + width = 2.2.dp, + color = Color.Black + ), + shape = CircleShape + ) + ) { + Row( + modifier = Modifier.fillMaxSize(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Icon( + painter = painterResource(id = R.drawable.ic_question_mark), + contentDescription = null + ) + } + } + Text( + text = "About Us", + style = MaterialTheme.typography.titleMedium + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun DetectBoxPreview() { + TechwasMark02Theme { + Box(modifier = Modifier.padding(20.dp)) { + Column(modifier = Modifier.fillMaxWidth()) { + DetectBox1() + + Spacer(modifier = Modifier.height(20.dp)) + + DetectBox2() + + Spacer(modifier = Modifier.height(20.dp)) + + DetectBox3() + + Spacer(modifier = Modifier.height(20.dp)) + + DetectBox4() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt new file mode 100644 index 0000000..3d69834 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt @@ -0,0 +1,103 @@ +package com.capstone.techwasmark02.ui.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowForward +import androidx.compose.material.icons.filled.KeyboardArrowRight +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import coil.compose.rememberAsyncImagePainter +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import kotlin.random.Random + +@Composable +fun ForumBox() { + ForumBoxContent() +} + +@Composable +fun ForumBoxContent() { + Box( + modifier = Modifier + .fillMaxWidth() + .height(80.dp) + .clip(MaterialTheme.shapes.large) + .background(MaterialTheme.colorScheme.tertiary) + .padding(horizontal = 24.dp), + contentAlignment = Alignment.Center + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Image( + modifier = Modifier + .width(100.dp) + .height(60.dp) + .clip(MaterialTheme.shapes.large), + painter = rememberAsyncImagePainter( + model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", + placeholder = painterResource(id = R.drawable.place_holder), + ), + contentDescription = null, + ) + Column( + modifier = Modifier + .weight(1f) + .padding(start = 10.dp) + ) { + Text( + text = "Title", + style = MaterialTheme.typography.labelLarge + ) + Text( + text = "Subtitle", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) + ) + Text( + text = "Description", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) + ) + } + Icon( + imageVector = Icons.Default.KeyboardArrowRight, + contentDescription = "Arrow", + tint = MaterialTheme.colorScheme.onSurface + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun ForumBoxPreview() { + TechwasMark02Theme() { + Box(modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.primaryContainer) + .padding(20.dp)) { + ForumBox() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt new file mode 100644 index 0000000..7fa73aa --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt @@ -0,0 +1,2 @@ +package com.capstone.techwasmark02.ui.component + diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt new file mode 100644 index 0000000..8018202 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt @@ -0,0 +1,2 @@ +package com.capstone.techwasmark02.ui.screen.profileUser + diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt new file mode 100644 index 0000000..169053d --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt @@ -0,0 +1,2 @@ +package com.capstone.techwasmark02.ui.screen.singleArticle + diff --git a/app/src/main/res/drawable/ic_center_focus.xml b/app/src/main/res/drawable/ic_center_focus.xml new file mode 100644 index 0000000..e215d44 --- /dev/null +++ b/app/src/main/res/drawable/ic_center_focus.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_language.xml b/app/src/main/res/drawable/ic_language.xml new file mode 100644 index 0000000..a5061ae --- /dev/null +++ b/app/src/main/res/drawable/ic_language.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_location_on.xml b/app/src/main/res/drawable/ic_location_on.xml new file mode 100644 index 0000000..dd12113 --- /dev/null +++ b/app/src/main/res/drawable/ic_location_on.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_logout.xml b/app/src/main/res/drawable/ic_logout.xml new file mode 100644 index 0000000..bceb2ec --- /dev/null +++ b/app/src/main/res/drawable/ic_logout.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_menu_book.xml b/app/src/main/res/drawable/ic_menu_book.xml new file mode 100644 index 0000000..21e9852 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_book.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_question_mark.xml b/app/src/main/res/drawable/ic_question_mark.xml new file mode 100644 index 0000000..1d4bf08 --- /dev/null +++ b/app/src/main/res/drawable/ic_question_mark.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/img_bg_green.png b/app/src/main/res/drawable/img_bg_green.png new file mode 100644 index 0000000000000000000000000000000000000000..a3d4711a8572f8917359fd96d18ffff867e13cfa GIT binary patch literal 3746 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_bg_purple.png b/app/src/main/res/drawable/img_bg_purple.png new file mode 100644 index 0000000000000000000000000000000000000000..b01cacbbd91e29e2623ae61e42b8e0d0fad76faf GIT binary patch literal 2663 zcmbuB`#%$k8^#jMAFO*^XATx4TI4Agi$lotU0($3=Yvi`e<#-=*@X0-Bq0r?W%nXo(G$Muj!TLRo zoZ=2&)BIRo+X)URD{v4}|AuG;lP7afT1s*$iCN8Kij&FtOg|~AzhpE2^s$9_dG)8& z`t(2DQ!TDh=T##V-x)$ih}oEBh~Ab*Qi9sNl=+LMpijW$Puw)=*{SBuZ!@*W5tR>ZG(@y0W+LD zN7p1qH0WaXm`hD0TXOGfxJbuI)mFYTHmq)LnT*o1+}(r;Ns)v-~A@K=7m(epE3xboo^+V8r-Ir+zp^8a;V*yORr<9qYCLJCR&w-#u5vdomEF13Q=HIdgw*>VO2U0NptL zr>|Xn*hC&py7$RucQIoTcI*bwX7P*5;|4`dB)#K_?yy|0I9N+$E;e zQ}emZTw;=i>X*M8BqyZRAamaac{PD>aGq{=S?Ig+;6Gkodg~cc-T>AiyE;&Q>Ja?Wc8&L`A7VvMTb{c_z8%-Q$-xtEwa4qqJp9?%kb*U31(+z(NIha5f_18 z-pQqJ1l9m&(QCL!lNn3kz?%Zab@x441dhjk4)x9`nEOjJat=MT}LZrVbP` zmMsJAW>O6WIL^_k64&$FzBcZ2JK0e$y^APE@0KI)+E(yY`NnvIIUYU$gVDN09=OKM)a&jteIQ{X^d0C+bXiI;Ix>)%t5+Q!MaUCL0d zO)O;|Vn2b30d)=W>#f>!07;#1DO+%I1aGZx-D(xk4OEx0qWoLi8zUp^H+=^_oLRh;trN3S)zgxaG)sy|J>xAM1 zKW{ti)70>>#aY4ZkIS1=&)33m9+7p;$x1%|qJc`B2||U%2b?wZo3U=7Ob>Dl4tg&^ z)6&_k^0EX4Wc*U298EbTy%7I+@lDQjcH=A7bY*9o+qCze;Mr4a=cY^)qw*$#ilnnU zR_I`j+Hc>_T~SCZBupxEIDFbvQd zZ?m`VEuW-au~VgXX0$cziL+awrU=BH-ZbLPpy^%!hloLLHxb#Hxvz)~Y9=&LPYx^2 z5F=DN$!GnC&tq8T;4CKqp@Ufk6`Ufw_|2{Q+QlhLUm_<~KoBW`Z^gZ$GjS z3Y*{b&<8#hDR=sD_&0K>5hmyv;{{Xvf~RM^vR$yoENU<(KTp7}?}LIK zw?K!kf?kO$*uuZRGY;J;k(s#Hk1>=hj^d?rh9OaAop!z}sSci*%gCL)7=t!=>wT*V z<{7m)Gg@GpfmBj}tH&A26Y-BVmBriM+<(77L!C#fm`#U*{6_ZIpDYN+>I3cnPyjjv z^F-`tU8>**6uR)2Aj>7McmspRirfKYZ44v0q^h`Mz&GH3ns4!C3hB>lB`5(|UWIuA zqd~$*nD4R5A;$55=nMOF*;1w+y7kgK_aNa(`tT7W4gK%@MU44Ozg%VsW3aNfL5x^k zd+z67kGSTsXe^BteAqg1(|UOPwR=Y-?F)JmP#e}nl&JW9D?Dvl-E#748k-1ieuPX7 z(S}?uWu_k1*7FkrrYj_{HU2M5wT2D}sh>lXk79ckYt-PHHMVG2HWl;zzu@=$tB&MpV#X) zj%wY!#x2vfI6@8<2aU4kW~7%E%;S(K)Rz<|WtD(u%MzAnHNA8)qWM~DHy&yVPaMu{ yeApAe!LUgL3;R8CiY}nY&iH;8y%@Kxzb~i&YQC}bmgI2o7XlF0C^*B?C-HxG7v`4$ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_bg_sakura.png b/app/src/main/res/drawable/img_bg_sakura.png new file mode 100644 index 0000000000000000000000000000000000000000..b016ffde5ac7eb045646371992a9299afec405cd GIT binary patch literal 2973 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/logo_techwaste.png b/app/src/main/res/drawable/logo_techwaste.png new file mode 100644 index 0000000000000000000000000000000000000000..ff899fec22129b1b4b707a43c56e31ca2026831e GIT binary patch literal 537 zcmV+!0_OdRP)0{Xm z(LaEhE0I@`fpS6!YbE6o`#Z`2MBK|`5IKlEh`ft@(X9~TCq&z;Bcs<$I=Tfy@B;Eq zq;NJxLrY=E+X-6%+lH1v7M3aU8T%Ucik1NN9h`1so+~(5>m+EJ`hu_H40(N8e5ori zZ*-E39=o4XL-cP>w^uRqfVMq3s8P3u$AhAaN=H=r+M4KV7eug=ZlVmTkFK`C)*hR! z@9icWmPxVY;~`mNOm!?!u2aNkk&O;xA~OyHO?kxFPSiK@*m@i2(+O@I`M|cch*Sx* zlRCS|*$3DPki}G5?9C;)A!$>p#z`=#x6nl&DIc$8=82}5%A&_}A{ Date: Thu, 1 Jun 2023 23:25:31 +0700 Subject: [PATCH 19/73] modif: adjust smallButton --- .../java/com/capstone/techwasmark02/ui/component/Banner.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt index bf18cce..23904b1 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt @@ -189,7 +189,7 @@ fun DropPointBanner(modifier: Modifier = Modifier) { ) Spacer(modifier = Modifier.height(10.dp)) Row(modifier = Modifier.align(alignment = Alignment.CenterHorizontally)) { - SmallButton(contentText = "LOCATE NOW") + SmallButton(contentText = "LOCATE NOW", colorText = MaterialTheme.colorScheme.primary) } } } @@ -253,7 +253,7 @@ fun ForumBanner(modifier: Modifier = Modifier) { modifier = Modifier.fillMaxWidth() ) { Row(modifier = Modifier.align(alignment = Alignment.CenterHorizontally)) { - SmallButton(contentText = "LOCATE NOW") + SmallButton(contentText = "LOCATE NOW", colorText = MaterialTheme.colorScheme.primary) } Spacer(modifier = Modifier.height(10.dp)) From ac77c45a96baa469016ad5dbf9ebf624d5232c98 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 1 Jun 2023 23:26:31 +0700 Subject: [PATCH 20/73] modif: adjust smallButton --- .../capstone/techwasmark02/ui/component/Button.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/Button.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/Button.kt index 6cffb8c..8ad0b68 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/Button.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/Button.kt @@ -17,6 +17,7 @@ import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -73,7 +74,7 @@ fun InverseButton( } @Composable -fun SmallButton(modifier: Modifier = Modifier, contentText: String, onClick: () -> Unit = {}) { +fun SmallButton(modifier: Modifier = Modifier, contentText: String, onClick: () -> Unit = {}, colorText: Color) { Button( onClick = onClick, modifier = modifier @@ -83,9 +84,6 @@ fun SmallButton(modifier: Modifier = Modifier, contentText: String, onClick: () containerColor = MaterialTheme.colorScheme.tertiary ), shape = MaterialTheme.shapes.large, - elevation = ButtonDefaults.buttonElevation( - defaultElevation = 6.dp - ), contentPadding = PaddingValues(horizontal = 12.dp), ) { Text( @@ -93,7 +91,7 @@ fun SmallButton(modifier: Modifier = Modifier, contentText: String, onClick: () style = MaterialTheme.typography.bodySmall.copy( fontWeight = FontWeight.Bold ), - color = MaterialTheme.colorScheme.primary + color = colorText ) } } @@ -115,7 +113,10 @@ fun ButtonPreview() { Spacer(modifier = Modifier.height(16.dp)) - SmallButton(contentText = "LOCATE NOW") + SmallButton( + contentText = "LOCATE NOW", + colorText = MaterialTheme.colorScheme.primary + ) } } } From 88cd81e5642c57bd09f559dd6c4e7bf30ca3906e Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 1 Jun 2023 23:26:49 +0700 Subject: [PATCH 21/73] modif: make new component --- .../techwasmark02/ui/component/ForumBox.kt | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt index 3d69834..1040df5 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt @@ -8,11 +8,8 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowForward import androidx.compose.material.icons.filled.KeyboardArrowRight import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -21,6 +18,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -30,17 +29,16 @@ import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import kotlin.random.Random @Composable -fun ForumBox() { - ForumBoxContent() -} - -@Composable -fun ForumBoxContent() { +fun ForumBox(modifier: Modifier = Modifier) { Box( - modifier = Modifier + modifier = modifier .fillMaxWidth() .height(80.dp) .clip(MaterialTheme.shapes.large) + .shadow( + elevation = 4.dp, + clip = true + ) .background(MaterialTheme.colorScheme.tertiary) .padding(horizontal = 24.dp), contentAlignment = Alignment.Center @@ -58,6 +56,7 @@ fun ForumBoxContent() { model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", placeholder = painterResource(id = R.drawable.place_holder), ), + contentScale = ContentScale.FillHeight, contentDescription = null, ) Column( From 1315707a23edf0ff04f92e8d6b9a083186dd5b2d Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 1 Jun 2023 23:27:12 +0700 Subject: [PATCH 22/73] modif: make new component --- .../techwasmark02/ui/component/ProfileBox.kt | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt index 7fa73aa..dc33ddf 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt @@ -1,2 +1,90 @@ package com.capstone.techwasmark02.ui.component +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.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Warning +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme + +@Composable +fun ProfileBox(modifier: Modifier = Modifier) { + Box( + modifier = modifier + .fillMaxWidth() + .height(120.dp) + .clip(MaterialTheme.shapes.large) + .background(MaterialTheme.colorScheme.tertiary) + .padding(horizontal = 24.dp), + contentAlignment = Alignment.Center + ) { + Column { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.size(24.dp), + painter = painterResource(id = R.drawable.ic_language), + contentDescription = "Language", + tint = MaterialTheme.colorScheme.onTertiary + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = "Language", + style = MaterialTheme.typography.labelMedium + ) + } + Spacer(modifier = Modifier.height(8.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.size(24.dp), + painter = painterResource(id = R.drawable.ic_logout), + contentDescription = "Logout", + tint = Color.Red + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = "Logout", + style = MaterialTheme.typography.labelMedium, + color = Color.Red + ) + } + } + } +} + +@Preview(showBackground = false) +@Composable +fun ProfileBoxPreview() { + TechwasMark02Theme { + Box(modifier = Modifier.padding(20.dp)) { + ProfileBox() + } + } +} \ No newline at end of file From 1327464558dedcfc65e5a850ca96cbf86fdd77b1 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 1 Jun 2023 23:27:42 +0700 Subject: [PATCH 23/73] modif: adjust transparent topAppBar --- .../techwasmark02/ui/component/TopBar.kt | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt index b566d7b..0d52406 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt @@ -86,6 +86,41 @@ fun DefaultTopBar(pageTitle: String = "", onClickNavigationIcon: () -> Unit, mod ) } +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun TransparentTopBar(pageTitle: String = "", onClickNavigationIcon: () -> Unit, modifier: Modifier = Modifier) { + TopAppBar( + navigationIcon = { + IconButton( + onClick = onClickNavigationIcon, + ) { + Icon( + painter = painterResource(id = R.drawable.ic_arrow_back), + contentDescription = null, + tint = MaterialTheme.colorScheme.onPrimary, + modifier = Modifier.size(32.dp) + ) + } + }, + title = {}, + actions = { + Text( + text = pageTitle, + color = MaterialTheme.colorScheme.onPrimary, + style = MaterialTheme.typography.labelLarge.copy( + fontWeight = FontWeight.Normal + ), + modifier = Modifier + .padding(end = 20.dp) + ) + }, + colors = TopAppBarDefaults.smallTopAppBarColors( + containerColor = Color.Transparent, + ), + modifier = modifier + ) +} + @Preview (showBackground = true) @Composable fun InverseTopBarPreview() { @@ -116,4 +151,22 @@ fun DefaultTopBarPreview() { ) } } +} + +@Preview (showBackground = true) +@Composable +fun TransparantTopBarPreview() { + TechwasMark02Theme { + Box( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.onBackground) + .padding(20.dp) + ) { + TransparentTopBar( + pageTitle = "Detail", + onClickNavigationIcon = {} + ) + } + } } \ No newline at end of file From 52c097614557f9a5f1b9807e223e3bcc7f611c5b Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 1 Jun 2023 23:28:07 +0700 Subject: [PATCH 24/73] modif: re-make home screen --- .../ui/screen/home/HomeScreen.kt | 257 ++++++++++++------ 1 file changed, 180 insertions(+), 77 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index 65bbb88..01eff9a 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -1,15 +1,20 @@ package com.capstone.techwasmark02.ui.screen.home import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.Image 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.IntrinsicSize import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -18,22 +23,40 @@ import androidx.compose.foundation.lazy.items import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Notifications import androidx.compose.material3.Card import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.lerp import androidx.compose.ui.util.lerp +import coil.compose.rememberAsyncImagePainter +import com.capstone.techwasmark02.R import com.capstone.techwasmark02.ui.component.ArticleCardBig import com.capstone.techwasmark02.ui.component.DefaultBottomBar +import com.capstone.techwasmark02.ui.component.DetectBox1 +import com.capstone.techwasmark02.ui.component.DetectBox2 +import com.capstone.techwasmark02.ui.component.DetectBox3 +import com.capstone.techwasmark02.ui.component.DetectBox4 import com.capstone.techwasmark02.ui.component.DetectionsFab import com.capstone.techwasmark02.ui.component.DropPointBanner import com.capstone.techwasmark02.ui.component.ForumBanner @@ -41,7 +64,9 @@ import com.capstone.techwasmark02.ui.component.SelectableText import com.capstone.techwasmark02.ui.component.UserGreet import com.capstone.techwasmark02.ui.componentType.BottomBarItemType import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import com.capstone.techwasmark02.ui.theme.yellow import kotlin.math.absoluteValue +import kotlin.random.Random @Composable fun HomeScreen() { @@ -51,87 +76,144 @@ fun HomeScreen() { @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable fun HomeContent() { - - val filterTypeList = listOf( - "General", - "Laptop", - "Baterai", - "Kabel", - "General", - "Laptop", - "Baterai", - "Kabel", - "General", - "Laptop", - "Baterai", - "Kabel", - "General", - "Laptop", - "Baterai", - "Kabel", - ) - Scaffold( - + bottomBar = { + DefaultBottomBar( + selectedType = BottomBarItemType.Home + ) + } ) { innerPadding -> - Box( + val scrollState = rememberScrollState() + + Column( modifier = Modifier - .fillMaxSize() - .background(MaterialTheme.colorScheme.background) - .padding(innerPadding), - contentAlignment = Alignment.BottomCenter + .verticalScroll(scrollState) + .padding(innerPadding) + .background(MaterialTheme.colorScheme.primary) ) { - Column( + Box( modifier = Modifier - .fillMaxSize() - .verticalScroll(rememberScrollState()) - .padding(bottom = 60.dp, top = 20.dp), - horizontalAlignment = Alignment.CenterHorizontally + .fillMaxWidth() + .padding(top = 20.dp) ) { - Column( + Row( modifier = Modifier - .padding(horizontal = 16.dp) + .fillMaxWidth() + .padding(horizontal = 16.dp), + verticalAlignment = Alignment.Bottom ) { - UserGreet(userName = "Zhahrany") + Image( + modifier = Modifier.size(24.dp, 27.dp), + painter = painterResource(id = R.drawable.logo_techwaste), + contentDescription = null + ) + Text( + text = "Techwas", + modifier = Modifier + .padding(start = 4.dp) + .offset(y = 5.dp), + style = MaterialTheme.typography.labelLarge, + color = Color.White + ) + Spacer(modifier = Modifier.weight(1f)) + IconButton( + onClick = { }, + modifier = Modifier.size(21.dp, 24.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_nofitications), + contentDescription = null, + tint = Color.White + ) + } + } + } - Spacer(modifier = Modifier.height(10.dp)) + Spacer(modifier = Modifier.height(20.dp)) - DropPointBanner() + Box( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight() + .clip( + RoundedCornerShape( + topStart = 20.dp, + topEnd = 20.dp + ) + ) + .background(Color.White) + .height(928.dp) + ) { + Column(modifier = Modifier.fillMaxSize()) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 18.dp) + ) { + Text( + text = "Features", + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold + ) + } - Spacer(modifier = Modifier.height(20.dp)) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + DetectBox1() + DetectBox2() + } - Text( - text = "What's New?", - style = MaterialTheme.typography.labelLarge, - modifier = Modifier.padding(start = 8.dp) - ) + Spacer(modifier = Modifier.height(20.dp)) - LazyRow( - horizontalArrangement = Arrangement.Start, + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween ) { - items( - items = filterTypeList, - ) { item -> - SelectableText( - text = item, - selected = false - ) - } + DetectBox3() + DetectBox4() } - } - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(10.dp)) + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 18.dp), + horizontalArrangement = Arrangement.Center + ) { + Text( + text = "Articles", + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold + ) + + Spacer(modifier = Modifier.weight(1f)) + + Text( + text = "See all", + style = MaterialTheme.typography.labelMedium, + fontWeight = FontWeight.Bold, + color = yellow + ) + } - val pagerState = rememberPagerState() - HorizontalPager( - pageCount = 10, - state = pagerState, - contentPadding = PaddingValues(horizontal = 70.dp), - modifier = Modifier.fillMaxWidth() - ) { page -> - ArticleCardBig( + val pagerState = rememberPagerState() + HorizontalPager( + pageCount = 10, + state = pagerState, + contentPadding = PaddingValues(horizontal = 70.dp), + modifier = Modifier.fillMaxWidth() + ) { page -> + ArticleCardBig( modifier = Modifier - .width(240.dp) + .width(272.dp) + .height(139.dp) .graphicsLayer { // Calculate the absolute offset for the current page from the // scroll position. We use the absolute value which allows us to mirror @@ -156,25 +238,46 @@ fun HomeContent() { ) } ) - } + } + + Spacer(modifier = Modifier.height(10.dp)) - Spacer(modifier = Modifier.height(20.dp)) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 18.dp), + horizontalArrangement = Arrangement.Center + ) { + Text( + text = "Forums", + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold + ) - Column( - modifier = Modifier - .padding(horizontal = 16.dp) - ) { + Spacer(modifier = Modifier.weight(1f)) - ForumBanner() + Text( + text = "See all", + style = MaterialTheme.typography.labelMedium, + fontWeight = FontWeight.Bold, + color = yellow + ) + } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 18.dp), + horizontalArrangement = Arrangement.Center + ) { + ArticleCardBig( + modifier = Modifier + .width(320.dp) + .height(161.dp) + ) + } } } - - DetectionsFab( - modifier = Modifier.padding(bottom = 25.dp) - ) - - DefaultBottomBar(selectedType = BottomBarItemType.Home) } } } @@ -183,6 +286,6 @@ fun HomeContent() { @Composable fun HomeContentPreview() { TechwasMark02Theme { - HomeContent() + HomeScreen() } } \ No newline at end of file From aed7855e581633458b7d17bcdb81a5578c02057c Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 1 Jun 2023 23:28:23 +0700 Subject: [PATCH 25/73] modif: make profile screen --- .../screen/profileUser/ProfileUserScreen.kt | 197 ++++++++++++++++++ 1 file changed, 197 insertions(+) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt index 8018202..eaf9bdf 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt @@ -1,2 +1,199 @@ package com.capstone.techwasmark02.ui.screen.profileUser +import androidx.compose.foundation.Image +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.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import coil.compose.rememberAsyncImagePainter +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.component.ArticleCardBig +import com.capstone.techwasmark02.ui.component.DefaultBottomBar +import com.capstone.techwasmark02.ui.component.DefaultTopBar +import com.capstone.techwasmark02.ui.component.ForumBox +import com.capstone.techwasmark02.ui.component.ProfileBox +import com.capstone.techwasmark02.ui.componentType.BottomBarItemType +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import kotlin.random.Random + +@Composable +fun ProfileUserScreen() { + ProfileUserContent() +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ProfileUserContent() { + + Scaffold( + topBar = { + DefaultTopBar( + pageTitle = "Profile", + onClickNavigationIcon = {} + ) + }, + bottomBar = { + DefaultBottomBar( + selectedType = BottomBarItemType.Profile + ) + } + ) { innerPadding -> + val scrollState = rememberScrollState() + + Column( + modifier = Modifier + .verticalScroll(scrollState) + .padding(innerPadding) + .padding(bottom = 20.dp) + ) { + Box( + modifier = Modifier + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(236.dp) + .clip( + RoundedCornerShape( + bottomStart = 20.dp, + bottomEnd = 20.dp + ) + ) + .background(MaterialTheme.colorScheme.primary), + ) { + Column( + modifier = Modifier.align(Alignment.TopCenter), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Image( + modifier = Modifier + .size(120.dp) + .clip(CircleShape), + painter = rememberAsyncImagePainter( + model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", + placeholder = painterResource(id = R.drawable.place_holder), + ), + contentScale = ContentScale.FillHeight, + contentDescription = null + ) + + Spacer(modifier = Modifier.height(8.dp)) + + Text( + text = "User Full Name", + style = MaterialTheme.typography.labelLarge, + color = Color.White + ) + Text( + text = "user@gmail.com", + style = MaterialTheme.typography.bodyMedium, + color = Color.White + ) + } + } + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 200.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + ProfileBox( + modifier = Modifier + .padding(horizontal = 20.dp) + ) + } + } + + Spacer(modifier = Modifier.height(16.dp)) + + Column( + modifier = Modifier + .fillMaxWidth() + .height(600.dp) + ) { + Text( + text = "Bookmarks", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier.padding(horizontal = 16.dp) + ) + + Spacer(modifier = Modifier.height(8.dp)) + + LazyRow( + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + items( + count = 10, + ) { item -> + ArticleCardBig( + modifier = Modifier + .width(150.dp) + ) + } + } + + Spacer(modifier = Modifier.height(16.dp)) + + Text( + text = "Forum Histories", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier.padding(horizontal = 16.dp) + ) + + Spacer(modifier = Modifier.height(8.dp)) + + LazyColumn( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight(), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + items(count = 5) { + ForumBox(modifier = Modifier + .padding(horizontal = 16.dp) + ) + } + } + } + } + } +} + +@Preview +@Composable +fun ProfileUserScreenPreview() { + TechwasMark02Theme { + ProfileUserScreen() + } +} \ No newline at end of file From cd9e46329ec757321d79fe3ce080bd4d7760f0e5 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 1 Jun 2023 23:28:43 +0700 Subject: [PATCH 26/73] modif: add some colors --- .../main/java/com/capstone/techwasmark02/ui/theme/Color.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/theme/Color.kt b/app/src/main/java/com/capstone/techwasmark02/ui/theme/Color.kt index 8fc2f7f..da53aec 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/theme/Color.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/theme/Color.kt @@ -11,5 +11,8 @@ val Black12 = Color(0xff1F1F1F) val Lime56 = Color(0xff9ED54A) val Mist97 = Color(0xffF1EEFF) - -val Yellow77 = Color(0xFFFFDF5D) \ No newline at end of file +val purple = Color(0xff8385E4) +val Yellow77 = Color(0xFFFFDF5D) +val sakura = Color(0xFFF5A37B) +val gray = Color(0xFFD9D9D9) +val yellow = Color(0xFFFEBC1F) \ No newline at end of file From 84448e948f470aa9918e2061ed9c348f344ad109 Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Sat, 3 Jun 2023 08:47:00 +0700 Subject: [PATCH 27/73] adding cameraX --- app/build.gradle | 5 + app/src/main/AndroidManifest.xml | 7 +- .../capstone/techwasmark02/MainActivity.kt | 4 +- .../com/capstone/techwasmark02/TechwasApp.kt | 61 ++++ .../remote/apiService/TechwasPredictionApi.kt | 6 +- .../response/DetectionResultResponse.kt | 50 +++ .../TechwasPredictionApiRepository.kt | 3 +- .../techwasmark02/ui/component/CameraView.kt | 325 ++++++++++++++++++ .../techwasmark02/ui/component/DetectBox.kt | 242 +++---------- .../ui/componentType/FeatureBoxType.kt | 13 + .../techwasmark02/ui/navigation/Screen.kt | 7 + .../ui/screen/camera/CameraScreen.kt | 198 +++++++++++ .../ui/screen/camera/CameraScreenViewModel.kt | 72 ++++ .../detectionResult/DetectionResultScreen.kt | 66 +++- .../ui/screen/home/HomeScreen.kt | 297 ++++++++-------- .../imageDetection/ImageDetectionScreen.kt | 2 +- .../ImageDetectionScreenViewModel.kt | 20 +- .../ui/screen/maps/MapsScreen.kt | 34 +- 18 files changed, 1033 insertions(+), 379 deletions(-) create mode 100644 app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/remote/response/DetectionResultResponse.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/CameraView.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/componentType/FeatureBoxType.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreen.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreenViewModel.kt diff --git a/app/build.gradle b/app/build.gradle index 39b5d18..2c01b66 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -107,6 +107,11 @@ dependencies { implementation 'com.google.maps.android:maps-compose:2.10.0' implementation 'com.google.android.gms:play-services-maps:18.1.0' + // CameraX + implementation "androidx.camera:camera-camera2:1.2.3" + implementation "androidx.camera:camera-lifecycle:1.2.3" + implementation "androidx.camera:camera-view:1.3.0-alpha07" + testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 167da98..b65fc1e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ - + + + + NavHost( + navController = navController, + startDestination = Home.route, + modifier = Modifier + .padding(innerPadding) + ) { + composable(Home.route) { + HomeScreen(navController = navController) + } + + composable(Camera.route) { + CameraScreen(navController = navController) + } + + composable( + route = DetectionResult.route + "/{uri}/{result}", + arguments = listOf( + navArgument("uri") { + type = NavType.StringType + defaultValue = "Image to sent doesn't exist" + }, + navArgument("result") { + type = NavType.StringType + defaultValue = "Nothing to predict" + } + ) + ) { navBackStackEntry -> + val uri = navBackStackEntry.arguments?.getString("uri") + val result = navBackStackEntry.arguments?.getString("result") + + if (uri != null && result != null) { + DetectionResultScreen(stringUri = uri, detectionResult = result) + } + + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt index e74f63b..583c474 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt @@ -1,5 +1,6 @@ package com.capstone.techwasmark02.data.remote.apiService +import com.capstone.techwasmark02.data.remote.response.DetectionResultResponse import okhttp3.MultipartBody import retrofit2.http.Multipart import retrofit2.http.POST @@ -11,9 +12,10 @@ interface TechwasPredictionApi { @POST("predict/") suspend fun predict( @Part imageFile: MultipartBody.Part - ) : String + ) : DetectionResultResponse companion object { - const val BASE_URL = "https://e-waste-model-deployment-1gb-fwd5gpydiq-uc.a.run.app/" + const val BASE_URL = "http://35.222.181.110/" +// const val BASE_URL = "https://e-waste-model-deployment-1gb-fwd5gpydiq-uc.a.run.app/" } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/DetectionResultResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/DetectionResultResponse.kt new file mode 100644 index 0000000..8a758e4 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/DetectionResultResponse.kt @@ -0,0 +1,50 @@ +package com.capstone.techwasmark02.data.remote.response + +import com.google.gson.annotations.SerializedName + +data class DetectionResultResponse( + val predictions: Predictions, + val time_taken: String +) + +//data class DetectResult( +// val predictions: Predictions, +// val time_taken: String +//) + +data class Predictions( + @SerializedName("Cable") + val cable: Double?, + @SerializedName("CRT_TV") + val crtTv: Double?, + @SerializedName("E-kettle") + val eKettle: Double?, + @SerializedName("Refrigerator") + val refrigerator: Double?, + @SerializedName("Keyboard") + val keyboard: Double?, + @SerializedName("Laptop") + val laptop: Double?, + @SerializedName("Light Bulb") + val lightBulb: Double?, + @SerializedName("Monitor") + val monitor: Double?, + @SerializedName("Mouse") + val mouse: Double?, + @SerializedName("PCB") + val pcb: Double?, + @SerializedName("Phone") + val phone: Double?, + @SerializedName("Printer") + val printer: Double?, + @SerializedName("Rice Cooker") + val riceCooker: Double?, + @SerializedName("Washing Machine") + val washingMachine: Double? + +) + +data class ResultComponentType( + val name: String, + val percentage: Double +) \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasPredictionApiRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasPredictionApiRepository.kt index a7736b3..4dfb772 100644 --- a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasPredictionApiRepository.kt +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasPredictionApiRepository.kt @@ -1,6 +1,7 @@ package com.capstone.techwasmark02.repository import com.capstone.techwasmark02.data.remote.apiService.TechwasPredictionApi +import com.capstone.techwasmark02.data.remote.response.DetectionResultResponse import com.capstone.techwasmark02.ui.common.UiState import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MultipartBody @@ -12,7 +13,7 @@ class TechwasPredictionApiRepository @Inject constructor( private val predictionApi: TechwasPredictionApi ) { - suspend fun predictWaste(file: File): UiState { + suspend fun predictWaste(file: File): UiState { val imageFile = file.asRequestBody("image/jpeg".toMediaTypeOrNull()) val imageMultiPart: MultipartBody.Part = MultipartBody.Part.createFormData( name = "file", diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/CameraView.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/CameraView.kt new file mode 100644 index 0000000..409d062 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/CameraView.kt @@ -0,0 +1,325 @@ +package com.capstone.techwasmark02.ui.component + +import android.net.Uri +import android.util.Log +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.camera.core.CameraSelector +import androidx.camera.core.ImageCapture +import androidx.camera.core.ImageCaptureException +import androidx.camera.core.Preview +import androidx.camera.lifecycle.ProcessCameraProvider +import androidx.camera.view.PreviewView +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.blur +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import androidx.compose.ui.viewinterop.AndroidView +import coil.compose.AsyncImage +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import com.capstone.techwasmark02.R +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.io.File +import java.text.SimpleDateFormat +import java.util.Locale +import java.util.concurrent.Executor + +@Composable +fun CameraView( + outputDirectory: File, + executor: Executor, + onImageCaptured: (Uri) -> Unit, + onError: (ImageCaptureException) -> Unit +) { + val lensFacing = CameraSelector.LENS_FACING_BACK + val context = LocalContext.current + val lifecycleOwner = LocalLifecycleOwner.current + + val preview = Preview.Builder().build() + val previewView = remember { + PreviewView(context) + } + + var photoPreviewUri by remember { + mutableStateOf(Uri.EMPTY) + } + val imageCapture: ImageCapture = remember { + ImageCapture.Builder().build() + } + val cameraSelector = CameraSelector.Builder() + .requireLensFacing(lensFacing) + .build() + + val galleryLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.GetContent(), + onResult = { galleryImageUri -> + if(galleryImageUri != null) { + photoPreviewUri = galleryImageUri + onImageCaptured(galleryImageUri) + } + } + ) + + LaunchedEffect(key1 = lensFacing) { + val cameraProvider = withContext(Dispatchers.IO) { + withContext(Dispatchers.Main) { + ProcessCameraProvider.getInstance(context) + }.get() + } + cameraProvider.unbindAll() + cameraProvider.bindToLifecycle( + lifecycleOwner, + cameraSelector, + preview, + imageCapture + ) + + preview.setSurfaceProvider(previewView.surfaceProvider) + } + + Box(contentAlignment = Alignment.BottomCenter, modifier = Modifier.fillMaxSize()) { + TechwasMark02Theme() { + Box( + modifier = Modifier + .fillMaxSize() + ) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 8.dp, vertical = 16.dp) + .clip(RoundedCornerShape(20.dp)) + .background(Color.LightGray), + contentAlignment = Alignment.BottomCenter, + ) { + + if (photoPreviewUri != Uri.EMPTY) { + AsyncImage( + modifier = Modifier + .fillMaxSize() + .blur(16.dp), + model = photoPreviewUri, + contentDescription = null, + contentScale = ContentScale.Crop, + alpha = 0.7f + ) + AsyncImage( + modifier = Modifier + .fillMaxSize(), + model = photoPreviewUri, + contentDescription = "Selected image", + contentScale = ContentScale.Fit + ) + } else { + AndroidView({ previewView }, modifier = Modifier.fillMaxSize()) + } + + Row( + modifier = Modifier + .fillMaxWidth() + .height(intrinsicSize = IntrinsicSize.Max) + .padding(bottom = 16.dp), + horizontalArrangement = Arrangement.Center + ) { + Row( + modifier = Modifier + .weight(1f) + .fillMaxHeight() + .padding(start = 20.dp), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically + ) { + IconButton( + onClick = { galleryLauncher.launch("image/*") }, + modifier = Modifier + .clip(CircleShape) + .background(Color.White) + ) { + Icon(painter = painterResource(id = R.drawable.ic_gallery), contentDescription = null) + } + } + + Box( + Modifier + .clip(CircleShape) + ) { + Box( + modifier = Modifier + .size(62.dp) + .clip(CircleShape) + .background(Color.Transparent) + .border(2.dp, Color.White, CircleShape) + .clickable { + Log.i("kilo", "ON CLICK") + takePhoto( + filenameFormat = "yyyy-MM-dd-HH-mm-ss-SSS", + imageCapture = imageCapture, + outputDirectory = outputDirectory, + executor = executor, + onImageCaptured = { + photoPreviewUri = it + onImageCaptured(it) + }, + onError = onError + ) + }, + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .size(52.dp) + .clip(CircleShape) + .background(Color.White) + ) + } + } + + Spacer(modifier = Modifier.weight(1f)) + } + } + } + } + } +} + +private fun takePhoto( + filenameFormat: String, + imageCapture: ImageCapture, + outputDirectory: File, + executor: Executor, + onImageCaptured: (Uri) -> Unit, + onError: (ImageCaptureException) -> Unit +) { + + val photoFile = File( + outputDirectory, + SimpleDateFormat(filenameFormat, Locale.US).format(System.currentTimeMillis()) + ".jpg" + ) + + val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build() + + imageCapture.takePicture(outputOptions, executor, object: ImageCapture.OnImageSavedCallback { + override fun onError(exception: ImageCaptureException) { + Log.e("kilo", "Take photo error:", exception) + onError(exception) + } + + override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { + val savedUri = Uri.fromFile(photoFile) + onImageCaptured(savedUri) + } + }) +} + +@androidx.compose.ui.tooling.preview.Preview (showBackground = true) +@Composable +fun CameraViewPreview() { + TechwasMark02Theme() { + Box( + modifier = Modifier + .fillMaxSize() + ) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp, vertical = 20.dp) + .clip(RoundedCornerShape(20.dp)) + .background(Color.LightGray), + contentAlignment = Alignment.BottomCenter, + ) { +// AndroidView({ previewView }, modifier = Modifier.fillMaxSize()) + + Row( + modifier = Modifier + .fillMaxWidth() + .height(intrinsicSize = IntrinsicSize.Max) + .padding(bottom = 16.dp), + horizontalArrangement = Arrangement.Center + ) { + Row( + modifier = Modifier + .weight(1f) + .fillMaxHeight() + .padding(start = 20.dp), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically + ) { + IconButton( + onClick = { /*TODO*/ }, + modifier = Modifier + .clip(CircleShape) + .background(Color.White) + ) { + Icon(painter = painterResource(id = R.drawable.ic_gallery), contentDescription = null) + } + } + + Box( + Modifier + .clip(CircleShape) + ) { + Box( + modifier = Modifier + .size(62.dp) + .clip(CircleShape) + .background(Color.Transparent) + .border(2.dp, Color.White, CircleShape) + .clickable { +// Log.i("kilo", "ON CLICK") +// takePhoto( +// filenameFormat = "yyyy-MM-dd-HH-mm-ss-SSS", +// imageCapture = imageCapture, +// outputDirectory = outputDirectory, +// executor = executor, +// onImageCaptured = onImageCaptured, +// onError = onError +// ) + }, + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .size(52.dp) + .clip(CircleShape) + .background(Color.White) + ) + } + } + + Spacer(modifier = Modifier.weight(1f)) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt index 8f5be62..17ea83f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt @@ -4,9 +4,9 @@ import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -26,217 +26,83 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow -import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.componentType.FeatureBoxType import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import com.capstone.techwasmark02.ui.theme.gray -import com.capstone.techwasmark02.ui.theme.purple -import com.capstone.techwasmark02.ui.theme.sakura @Composable -fun DetectBox1(modifier: Modifier = Modifier) { - BoxWithConstraints( - modifier = Modifier +fun FeatureBox( + modifier: Modifier = Modifier, + featureBoxType: FeatureBoxType, + onClick: () -> Unit +) { + Box( + modifier = modifier .width(150.dp) .height(160.dp) - .border( - BorderStroke( - width = 1.dp, - color = Color.Black - ), - shape = RoundedCornerShape(10.dp) - ) .shadow( elevation = 4.dp, shape = RoundedCornerShape(10.dp) ) + .clickable { onClick() } ) { Image( - painter = painterResource(id = R.drawable.img_bg_green), + painter = painterResource(id = featureBoxType.backGround), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier .fillMaxSize() ) Column( - modifier = Modifier.fillMaxSize() - ) { - Box( - modifier = Modifier.fillMaxWidth() - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp, top = 16.dp) - ) { - Text( - text = "Detect\ne-waste", - style = MaterialTheme.typography.titleLarge, - color = Color.White - ) - } - } - - Spacer(modifier = Modifier.height(40.dp)) - - Box( - modifier = Modifier.fillMaxWidth() - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp, bottom = 16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - modifier = Modifier.size(33.dp, 25.dp), - painter = painterResource(id = R.drawable.ic_center_focus), - contentDescription = null, - tint = Color.White - ) - Spacer(modifier = Modifier.weight(1f)) - SmallButton( - contentText = "Detect", - onClick = {}, - colorText = MaterialTheme.colorScheme.primary - ) - } - } - } - } -} - -@Composable -fun DetectBox2(modifier: Modifier = Modifier) { - BoxWithConstraints( - modifier = Modifier - .width(150.dp) - .height(160.dp) - ) { - Image( - painter = painterResource(id = R.drawable.img_bg_purple), - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxSize() - ) - Column( - modifier = Modifier.fillMaxSize() - ) { - Box( - modifier = Modifier.fillMaxWidth() - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp, top = 16.dp) - ) { - Text( - text = "E-waste\ncatalog", - style = MaterialTheme.typography.titleLarge, - color = Color.White - ) - } - } - - Spacer(modifier = Modifier.height(40.dp)) - - Box( - modifier = Modifier.fillMaxWidth() - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp, bottom = 16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - modifier = Modifier.size(33.dp, 25.dp), - painter = painterResource(id = R.drawable.ic_menu_book), - contentDescription = null, - tint = Color.White - ) - Spacer(modifier = Modifier.weight(1f)) - SmallButton( - contentText = "Detect", - onClick = {}, - colorText = purple - ) - } - } - } - } -} - -@Composable -fun DetectBox3(modifier: Modifier = Modifier) { - BoxWithConstraints( - modifier = Modifier - .width(150.dp) - .height(160.dp) - ) { - Image( - painter = painterResource(id = R.drawable.img_bg_sakura), - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxSize() - ) - Column( - modifier = Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() + .padding(16.dp) ) { - Box( - modifier = Modifier.fillMaxWidth() + Row( + modifier = Modifier + .fillMaxWidth() ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp, top = 16.dp) - ) { - Text( - text = "Nearby\ndrop point", - style = MaterialTheme.typography.titleLarge, - color = Color.White - ) - } + Text( + text = featureBoxType.title, + style = MaterialTheme.typography.titleLarge, + color = Color.White + ) } Spacer(modifier = Modifier.height(40.dp)) - Box( - modifier = Modifier.fillMaxWidth() + Row( + modifier = Modifier + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp, bottom = 16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - modifier = Modifier.size(33.dp, 25.dp), - painter = painterResource(id = R.drawable.ic_location_on), - contentDescription = null, - tint = Color.White - ) - Spacer(modifier = Modifier.weight(1f)) - SmallButton( - contentText = "Locate", - onClick = {}, - colorText = sakura - ) - } + Icon( + modifier = Modifier.size(33.dp, 25.dp), + painter = painterResource(id = featureBoxType.icon), + contentDescription = null, + tint = Color.White + ) + Spacer(modifier = Modifier.weight(1f)) + SmallButton( + contentText = featureBoxType.buttonTitle, + onClick = onClick, + colorText = featureBoxType.buttonColor + ) } } } } @Composable -fun DetectBox4(modifier: Modifier = Modifier) { +fun AboutUsBox(modifier: Modifier = Modifier) { Box( - modifier = Modifier + modifier = modifier .width(150.dp) .height(160.dp) .clip( @@ -261,18 +127,13 @@ fun DetectBox4(modifier: Modifier = Modifier) { color = Color.Black ), shape = CircleShape - ) + ), + contentAlignment = Alignment.Center ) { - Row( - modifier = Modifier.fillMaxSize(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center - ) { - Icon( - painter = painterResource(id = R.drawable.ic_question_mark), - contentDescription = null - ) - } + Icon( + painter = painterResource(id = R.drawable.ic_question_mark), + contentDescription = null + ) } Text( text = "About Us", @@ -288,19 +149,22 @@ fun DetectBoxPreview() { TechwasMark02Theme { Box(modifier = Modifier.padding(20.dp)) { Column(modifier = Modifier.fillMaxWidth()) { - DetectBox1() + FeatureBox( + featureBoxType = FeatureBoxType.Detection, + onClick = {} + ) Spacer(modifier = Modifier.height(20.dp)) - DetectBox2() + FeatureBox(featureBoxType = FeatureBoxType.Catalog, onClick = {}) Spacer(modifier = Modifier.height(20.dp)) - DetectBox3() + FeatureBox(featureBoxType = FeatureBoxType.DropPoint, onClick = {}) Spacer(modifier = Modifier.height(20.dp)) - DetectBox4() + AboutUsBox() } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/FeatureBoxType.kt b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/FeatureBoxType.kt new file mode 100644 index 0000000..74e9d49 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/FeatureBoxType.kt @@ -0,0 +1,13 @@ +package com.capstone.techwasmark02.ui.componentType + +import androidx.compose.ui.graphics.Color +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.theme.Green35 +import com.capstone.techwasmark02.ui.theme.purple +import com.capstone.techwasmark02.ui.theme.sakura + +sealed class FeatureBoxType(val title: String, val buttonTitle: String, val icon: Int, val backGround: Int, val buttonColor: Color) { + object Detection: FeatureBoxType(title = "Detect e-waste", buttonTitle = "Detect", icon = R.drawable.ic_center_focus, backGround = R.drawable.img_bg_green, buttonColor = Green35) + object Catalog: FeatureBoxType(title = "E-waste catalog", buttonTitle = "Open", icon = R.drawable.ic_menu_book, backGround = R.drawable.img_bg_purple, buttonColor = purple) + object DropPoint: FeatureBoxType(title = "Nearby drop point", buttonTitle = "Locate", icon = R.drawable.ic_location_on, backGround = R.drawable.img_bg_sakura, buttonColor = sakura) +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt new file mode 100644 index 0000000..5ab3a4d --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt @@ -0,0 +1,7 @@ +package com.capstone.techwasmark02.ui.navigation + +sealed class Screen(val route: String) { + object Home: Screen(route = "home") + object Camera: Screen(route = "camera") + object DetectionResult: Screen(route = "detectionResult") +} diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreen.kt new file mode 100644 index 0000000..bd1d6d1 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreen.kt @@ -0,0 +1,198 @@ +package com.capstone.techwasmark02.ui.screen.camera + +import android.content.Context +import android.net.Uri +import android.util.Log +import android.widget.Toast +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavHostController +import com.capstone.techwasmark02.data.remote.response.DetectionResultResponse +import com.capstone.techwasmark02.ui.common.UiState +import com.capstone.techwasmark02.ui.component.CameraView +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.remote.response.Predictions +import com.capstone.techwasmark02.data.remote.response.ResultComponentType +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import java.io.File +import java.util.concurrent.Executors +import kotlin.reflect.full.memberProperties + +@Composable +fun CameraScreen( + viewModel: CameraScreenViewModel = hiltViewModel(), + navController: NavHostController +) { + + val photoUri by viewModel.photoUri.collectAsState() + val predictImageState by viewModel.predictImageState.collectAsState() + + CameraContent( + photoUri = photoUri, + predictImageState = predictImageState, + updatePhotoUri = { viewModel.updatePhotoUri(it) }, + predictImage = { viewModel.predictImage(it)}, + navigateToResult = { uri, result -> + navController.navigate("detectionResult/$uri/$result") + } + ) { viewModel.onSuccessPredictImage() } +} + +@Composable +fun CameraContent( + photoUri: Uri?, + predictImageState: UiState?, + updatePhotoUri: (Uri) -> Unit, + predictImage: (Context) -> Unit, + navigateToResult: (uri: String, result: String) -> Unit, + onSuccessPredictImage:() -> Unit +) { + + val context = LocalContext.current + val outputDirectory = getOutputDirectory(context) + val cameraExecutor = Executors.newSingleThreadExecutor() + + var imageIsTaken by remember { + mutableStateOf(false) + } + + LaunchedEffect(key1 = imageIsTaken) { + if (imageIsTaken) { + predictImage(context) + } + } + + LaunchedEffect(key1 = predictImageState) { + if (predictImageState != null) { + when (predictImageState) { + is UiState.Success -> { +// val predictResult = predictImageState.data?.predictions?.laptop.toString() +// Toast.makeText(context,"Result: $predictResult", Toast.LENGTH_SHORT).show() + val predictResult = predictImageState.data?.predictions?.let { + getAndSortResult( + it + ) + } + + val stringUri = Uri.encode(photoUri.toString()) + onSuccessPredictImage() + if (predictResult != null) { + navigateToResult(stringUri, predictResult) + } + } + is UiState.Error -> { + val predictResult = predictImageState.message + Toast.makeText(context,"$predictResult", Toast.LENGTH_SHORT).show() + imageIsTaken = false + } + is UiState.Loading -> { + Toast.makeText(context,"Your e-waste is being predicted", Toast.LENGTH_SHORT).show() + } + } + } + } + Box( + modifier = Modifier + .fillMaxSize() + ) { + CameraView( + outputDirectory = outputDirectory, + executor = cameraExecutor, + onImageCaptured = { uri -> + updatePhotoUri(uri) + imageIsTaken = true + }, + onError = { Log.e("zhahrany", "View error:", it)} + ) + + if (predictImageState != null) { + when (predictImageState) { + is UiState.Success, is UiState.Error -> { + // do nothing + } + is UiState.Loading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .fillMaxSize() + .alpha(0.3f) + .background(Color.Black), + ) {} + + CircularProgressIndicator( + color = Color.White + ) + } + } + } + } + } + +} + +private fun getOutputDirectory(context: Context): File { + val cacheDir = context.externalCacheDirs.firstOrNull()?.let { + File(it, context.resources.getString(R.string.app_name)).apply { mkdirs() } + } + + return if (cacheDir != null && cacheDir.exists()) cacheDir else context.filesDir +} + +private fun getAndSortResult(detectionResult: Predictions): String { + val resultComponentList = emptyList().toMutableList() + for (property in Predictions::class.memberProperties) { + if (property.get(detectionResult) != null) { + val resultComponentItem = ResultComponentType( + name = property.name, + percentage = property.get(detectionResult).toString().toDouble() + ) + resultComponentList.add(resultComponentItem) + } + } + + val sortedResultComponentList = resultComponentList.sortedWith(compareBy({it.percentage})).reversed() + + val stringResultList = emptyList().toMutableList() + + sortedResultComponentList.forEach { componentItem -> + val stringResultItem = "${componentItem.name}: ${componentItem.percentage}" + stringResultList.add(stringResultItem) + } + + return stringResultList.joinToString(separator = ",") + +} + +@Preview(showBackground = true) +@Composable +fun CameraScreenPreview() { + TechwasMark02Theme() { + CameraContent( + photoUri = null, + updatePhotoUri = {}, + navigateToResult = { uri, result -> }, + predictImage = {}, + predictImageState = null + ) {} + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreenViewModel.kt new file mode 100644 index 0000000..ef6c297 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreenViewModel.kt @@ -0,0 +1,72 @@ +package com.capstone.techwasmark02.ui.screen.camera + +import android.content.Context +import android.net.Uri +import android.webkit.MimeTypeMap +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.data.remote.response.DetectionResultResponse +import com.capstone.techwasmark02.repository.TechwasPredictionApiRepository +import com.capstone.techwasmark02.ui.common.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import java.io.File +import java.io.FileOutputStream +import javax.inject.Inject + +@HiltViewModel +class CameraScreenViewModel @Inject constructor( + private val predictionApiRepository: TechwasPredictionApiRepository +): ViewModel() { + + private val _photoUri: MutableStateFlow = MutableStateFlow(null) + val photoUri = _photoUri.asStateFlow() + + private val _predictImageState: MutableStateFlow?> = MutableStateFlow(null) + val predictImageState = _predictImageState.asStateFlow() + + fun updatePhotoUri(newUri: Uri) { + _photoUri.value = newUri + } + + fun predictImage(context: Context) { + _predictImageState.value = UiState.Loading() + + val imageFileToUpload = _photoUri.value?.let { convertUriToFile(context = context, uri = it) } + viewModelScope.launch { + _predictImageState.value = imageFileToUpload?.let { + predictionApiRepository.predictWaste(it) + } + } + } + + fun onSuccessPredictImage() { + _predictImageState.value = null + } + +} + +private fun convertUriToFile(context: Context, uri: Uri): File? { + val inputStream = context.contentResolver.openInputStream(uri) + inputStream?.let { + val file = createTempFile(context, getFileExtension(uri)) + val outputStream = FileOutputStream(file) + inputStream.copyTo(outputStream) + outputStream.close() + inputStream.close() + return file + } + return null +} + +private fun createTempFile(context: Context, fileExtension: String): File { + val directory = context.cacheDir + return File.createTempFile("temp", ".$fileExtension", directory) +} + +private fun getFileExtension(uri: Uri): String { + val extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(uri.toString()) + return extension ?: "jpg" // Default to "jpg" if extension is null +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt index ce17b87..ea6cbbb 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt @@ -1,5 +1,6 @@ package com.capstone.techwasmark02.ui.screen.detectionResult +import android.net.Uri import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -7,6 +8,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -33,9 +35,13 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.blur import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage import com.capstone.techwasmark02.ui.component.ArticleCardBig import com.capstone.techwasmark02.ui.component.DefaultButton import com.capstone.techwasmark02.ui.component.DefaultTopBar @@ -49,13 +55,23 @@ import kotlinx.coroutines.launch @Composable -fun DetectionResultScreen() { - DetectionResultContent() +fun DetectionResultScreen( + stringUri: String, + detectionResult: String +) { + DetectionResultContent( + stringUri = stringUri, + detectionResult = detectionResult + ) } @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class) @Composable -fun DetectionResultContent() { +fun DetectionResultContent( + stringUri: String, + detectionResult: String + +) { val coroutineScope = rememberCoroutineScope() val modalSheetState = rememberModalBottomSheetState( initialValue = ModalBottomSheetValue.Hidden, @@ -67,14 +83,16 @@ fun DetectionResultContent() { mutableStateOf(false) } - BackHandler(modalSheetState.isVisible) { - coroutineScope.launch { modalSheetState.hide() } - } + val photoUri = Uri.parse(stringUri) - BackHandler(!modalSheetState.isVisible) { - isOnBackClick = true - coroutineScope.launch { modalSheetState.show() } - } +// BackHandler(modalSheetState.isVisible) { +// coroutineScope.launch { modalSheetState.hide() } +// } +// +// BackHandler(!modalSheetState.isVisible) { +// isOnBackClick = true +// coroutineScope.launch { modalSheetState.show() } +// } ModalBottomSheetLayout( sheetState = modalSheetState, @@ -110,7 +128,7 @@ fun DetectionResultContent() { Box( modifier = Modifier .fillMaxWidth() - .height(236.dp) + .height(500.dp) .clip( RoundedCornerShape( bottomStart = 20.dp, @@ -119,13 +137,28 @@ fun DetectionResultContent() { ) .background(MaterialTheme.colorScheme.primary), ) { - + AsyncImage( + model = photoUri, + contentDescription = null, + contentScale = ContentScale.Crop, + alpha = 0.8f, + modifier = Modifier + .fillMaxSize() + .blur(16.dp) + ) + AsyncImage( + model = photoUri, + contentDescription = null, + contentScale = ContentScale.Fit, + modifier = Modifier + .fillMaxSize() + ) } Column( modifier = Modifier .fillMaxWidth() - .padding(top = 138.dp), + .padding(top = 402.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text( @@ -134,6 +167,8 @@ fun DetectionResultContent() { color = MaterialTheme.colorScheme.onPrimary ) + Text(text = detectionResult, color = Color.White) + DetectionsResultBox( modifier = Modifier .padding(horizontal = 20.dp) @@ -229,7 +264,10 @@ fun DetectionResultContent() { @Composable fun DetectionResultContentPreview() { TechwasMark02Theme { - DetectionResultContent() + DetectionResultContent( + stringUri = "", + detectionResult = "" + ) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index 01eff9a..d789063 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -1,12 +1,12 @@ package com.capstone.techwasmark02.ui.screen.home +import android.widget.Space import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image 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.IntrinsicSize import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -18,17 +18,11 @@ import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Notifications -import androidx.compose.material3.Card import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -41,84 +35,83 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.lerp import androidx.compose.ui.util.lerp -import coil.compose.rememberAsyncImagePainter +import androidx.navigation.NavHostController import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.component.AboutUsBox import com.capstone.techwasmark02.ui.component.ArticleCardBig import com.capstone.techwasmark02.ui.component.DefaultBottomBar -import com.capstone.techwasmark02.ui.component.DetectBox1 -import com.capstone.techwasmark02.ui.component.DetectBox2 -import com.capstone.techwasmark02.ui.component.DetectBox3 -import com.capstone.techwasmark02.ui.component.DetectBox4 -import com.capstone.techwasmark02.ui.component.DetectionsFab -import com.capstone.techwasmark02.ui.component.DropPointBanner -import com.capstone.techwasmark02.ui.component.ForumBanner -import com.capstone.techwasmark02.ui.component.SelectableText -import com.capstone.techwasmark02.ui.component.UserGreet +import com.capstone.techwasmark02.ui.component.FeatureBox import com.capstone.techwasmark02.ui.componentType.BottomBarItemType +import com.capstone.techwasmark02.ui.componentType.FeatureBoxType +import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import com.capstone.techwasmark02.ui.theme.yellow import kotlin.math.absoluteValue -import kotlin.random.Random @Composable -fun HomeScreen() { - HomeContent() +fun HomeScreen( + navController: NavHostController +) { + HomeContent( + navigateToCamera = { navController.navigate(Screen.Camera.route) } + ) } @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable -fun HomeContent() { +fun HomeContent( + navigateToCamera: () -> Unit +) { Scaffold( - bottomBar = { - DefaultBottomBar( - selectedType = BottomBarItemType.Home - ) - } ) { innerPadding -> val scrollState = rememberScrollState() - Column( + Box( modifier = Modifier - .verticalScroll(scrollState) - .padding(innerPadding) - .background(MaterialTheme.colorScheme.primary) + .fillMaxSize(), ) { - Box( + Column( modifier = Modifier - .fillMaxWidth() + .verticalScroll(scrollState) + .padding(innerPadding) + .background(MaterialTheme.colorScheme.primary) .padding(top = 20.dp) ) { Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp), - verticalAlignment = Alignment.Bottom + verticalAlignment = Alignment.CenterVertically ) { - Image( - modifier = Modifier.size(24.dp, 27.dp), - painter = painterResource(id = R.drawable.logo_techwaste), - contentDescription = null - ) - Text( - text = "Techwas", - modifier = Modifier - .padding(start = 4.dp) - .offset(y = 5.dp), - style = MaterialTheme.typography.labelLarge, - color = Color.White - ) + Row( + modifier = Modifier, + verticalAlignment = Alignment.Bottom + ) { + Image( + modifier = Modifier.size(24.dp, 27.dp), + painter = painterResource(id = R.drawable.logo_techwaste), + contentDescription = null + ) + Text( + text = "Techwas", + modifier = Modifier + .padding(start = 4.dp) + .offset(y = 5.dp), + style = MaterialTheme.typography.labelLarge, + color = Color.White + ) + } + Spacer(modifier = Modifier.weight(1f)) + IconButton( onClick = { }, - modifier = Modifier.size(21.dp, 24.dp) +// modifier = Modifier.size(21.dp, 24.dp) ) { Icon( painter = painterResource(id = R.drawable.ic_nofitications), @@ -127,82 +120,91 @@ fun HomeContent() { ) } } - } - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(20.dp)) - Box( - modifier = Modifier - .fillMaxWidth() - .fillMaxHeight() - .clip( - RoundedCornerShape( - topStart = 20.dp, - topEnd = 20.dp + Column( + modifier = Modifier + .fillMaxSize() + .clip( + RoundedCornerShape( + topStart = 20.dp, + topEnd = 20.dp + ) ) - ) - .background(Color.White) - .height(928.dp) - ) { - Column(modifier = Modifier.fillMaxSize()) { - Row( - modifier = Modifier + .background(Color.White) + .padding(bottom = 72.dp) + ) { + Column( + Modifier .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 18.dp) + .padding(horizontal = 20.dp) ) { - Text( - text = "Features", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold - ) - } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 18.dp) + ) { + Text( + text = "Features", + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold + ) + } - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - horizontalArrangement = Arrangement.SpaceBetween - ) { - DetectBox1() - DetectBox2() - } + Row( + modifier = Modifier + .fillMaxWidth(), + ) { + Spacer(modifier = Modifier.weight(1f)) + FeatureBox(featureBoxType = FeatureBoxType.Detection, onClick = navigateToCamera) + Spacer(modifier = Modifier.weight(3f)) + FeatureBox(featureBoxType = FeatureBoxType.Catalog, onClick = {}) + Spacer(modifier = Modifier.weight(1f)) +// DetectBox1() +// DetectBox2() + } - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(20.dp)) - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - horizontalArrangement = Arrangement.SpaceBetween - ) { - DetectBox3() - DetectBox4() - } + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Spacer(modifier = Modifier.weight(1f)) + FeatureBox(featureBoxType = FeatureBoxType.DropPoint, onClick = {}) + Spacer(modifier = Modifier.weight(3f)) + AboutUsBox() + Spacer(modifier = Modifier.weight(1f)) + } - Spacer(modifier = Modifier.height(10.dp)) + Spacer(modifier = Modifier.height(24.dp)) - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 18.dp), - horizontalArrangement = Arrangement.Center - ) { - Text( - text = "Articles", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold - ) + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + Text( + text = "Articles", + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold + ) - Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.weight(1f)) - Text( - text = "See all", - style = MaterialTheme.typography.labelMedium, - fontWeight = FontWeight.Bold, - color = yellow - ) + Text( + text = "See all", + style = MaterialTheme.typography.labelMedium, + fontWeight = FontWeight.Bold, + color = yellow + ) + } } + Spacer(modifier = Modifier.height(10.dp)) + val pagerState = rememberPagerState() HorizontalPager( pageCount = 10, @@ -240,44 +242,57 @@ fun HomeContent() { ) } - Spacer(modifier = Modifier.height(10.dp)) + Spacer(modifier = Modifier.height(24.dp)) - Row( + Column( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 18.dp), - horizontalArrangement = Arrangement.Center + .padding(horizontal = 20.dp) ) { - Text( - text = "Forums", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold - ) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 10.dp), + horizontalArrangement = Arrangement.Center + ) { + Text( + text = "Forums", + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold + ) - Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.weight(1f)) - Text( - text = "See all", - style = MaterialTheme.typography.labelMedium, - fontWeight = FontWeight.Bold, - color = yellow - ) - } + Text( + text = "See all", + style = MaterialTheme.typography.labelMedium, + fontWeight = FontWeight.Bold, + color = yellow + ) + } - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 18.dp), - horizontalArrangement = Arrangement.Center - ) { - ArticleCardBig( + Row( modifier = Modifier - .width(320.dp) - .height(161.dp) - ) + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + ArticleCardBig( + modifier = Modifier + .width(320.dp) + .height(161.dp) + ) + } } } } + + Column( + modifier = Modifier + .fillMaxSize() + ) { + Spacer(modifier = Modifier.weight(1f)) + DefaultBottomBar(selectedType = BottomBarItemType.Home) + } } } } @@ -286,6 +301,8 @@ fun HomeContent() { @Composable fun HomeContentPreview() { TechwasMark02Theme { - HomeScreen() + HomeContent( + navigateToCamera = {} + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/imageDetection/ImageDetectionScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/imageDetection/ImageDetectionScreen.kt index 589f85d..bfd39b3 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/imageDetection/ImageDetectionScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/imageDetection/ImageDetectionScreen.kt @@ -71,7 +71,7 @@ fun ImageDetectionScreen(viewModel: ImageDetectionScreenViewModel = hiltViewMode imageUri = imageUri, predictImageState = predictImageState, updateImageUri = { viewModel.updateImageUri(it) }, - predictImage = { viewModel.predictImage(it) } + predictImage = { } ) } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/imageDetection/ImageDetectionScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/imageDetection/ImageDetectionScreenViewModel.kt index 828c13f..ace2263 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/imageDetection/ImageDetectionScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/imageDetection/ImageDetectionScreenViewModel.kt @@ -65,16 +65,16 @@ class ImageDetectionScreenViewModel @Inject constructor( _imageUri.value = newUri } - fun predictImage(context: Context) { - _predictImageState.value = UiState.Loading() - - val imageFileToUpload = _imageUri.value?.let { convertUriToFile(context = context, uri = it) } - viewModelScope.launch { - _predictImageState.value = imageFileToUpload?.let { - predictionApiRepository.predictWaste(it) - } - } - } +// fun predictImage(context: Context) { +// _predictImageState.value = UiState.Loading() +// +// val imageFileToUpload = _imageUri.value?.let { convertUriToFile(context = context, uri = it) } +// viewModelScope.launch { +// _predictImageState.value = imageFileToUpload?.let { +// predictionApiRepository.predictWaste(it) +// } +// } +// } // private fun convertUriToFile(context: Context, uri: Uri): File? { // val inputStream = context.contentResolver.openInputStream(uri) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt index adf3627..41a796e 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt @@ -1,19 +1,19 @@ package com.capstone.techwasmark02.ui.screen.maps -import androidx.compose.runtime.Composable -import com.google.android.gms.maps.model.CameraPosition -import com.google.android.gms.maps.model.LatLng -import com.google.maps.android.compose.GoogleMap -import com.google.maps.android.compose.rememberCameraPositionState - -@Composable -fun MapsScreen() { - val diy = LatLng(-7.782275587997325, 110.36709993087182) - val cameraPositionState = rememberCameraPositionState { - position = CameraPosition.fromLatLngZoom(diy, 10f) - } - - GoogleMap( - cameraPositionState = cameraPositionState - ) -} \ No newline at end of file +//import androidx.compose.runtime.Composable +//import com.google.android.gms.maps.model.CameraPosition +//import com.google.android.gms.maps.model.LatLng +//import com.google.maps.android.compose.GoogleMap +//import com.google.maps.android.compose.rememberCameraPositionState +// +//@Composable +//fun MapsScreen() { +// val diy = LatLng(-7.782275587997325, 110.36709993087182) +// val cameraPositionState = rememberCameraPositionState { +// position = CameraPosition.fromLatLngZoom(diy, 10f) +// } +// +// GoogleMap( +// cameraPositionState = cameraPositionState +// ) +//} \ No newline at end of file From e9a6e06b681133ff6c658c3f622f9f4b35e6ed69 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Sat, 3 Jun 2023 19:51:19 +0700 Subject: [PATCH 28/73] modif: single article screen --- .idea/deploymentTargetDropDown.xml | 17 -- .../techwasmark02/ui/component/SearchBox.kt | 2 + .../ui/screen/article/ArticleScreen.kt | 2 + .../screen/article/ArticleScreenViewModel.kt | 4 + .../singleArticle/SingleArticleScreen.kt | 206 ++++++++++++++++++ app/src/main/res/drawable/ic_search.xml | 5 + 6 files changed, 219 insertions(+), 17 deletions(-) delete mode 100644 .idea/deploymentTargetDropDown.xml create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt create mode 100644 app/src/main/res/drawable/ic_search.xml diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml deleted file mode 100644 index 8d4e827..0000000 --- a/.idea/deploymentTargetDropDown.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt new file mode 100644 index 0000000..7fa73aa --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt @@ -0,0 +1,2 @@ +package com.capstone.techwasmark02.ui.component + diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt new file mode 100644 index 0000000..f17c861 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt @@ -0,0 +1,2 @@ +package com.capstone.techwasmark02.ui.screen.article + diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt new file mode 100644 index 0000000..abc49b1 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt @@ -0,0 +1,4 @@ +package com.capstone.techwasmark02.ui.screen.article + +class ArticleScreenViewModel { +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt index 169053d..95ef11f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt @@ -1,2 +1,208 @@ package com.capstone.techwasmark02.ui.screen.singleArticle +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Favorite +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import coil.compose.rememberAsyncImagePainter +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.component.DefaultButton +import com.capstone.techwasmark02.ui.component.TransparentTopBar +import com.capstone.techwasmark02.ui.theme.Mist97 +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import kotlin.random.Random + +@Composable +fun SingleArticleScreen() { + SingleArticleContent() +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SingleArticleContent() { + Scaffold( + topBar = { + TransparentTopBar( + pageTitle = "Detail", + onClickNavigationIcon = {}, + ) + }, + ) { innerPadding -> + val scrollState = rememberScrollState() + + Column( + modifier = Modifier + .padding(innerPadding) + .background(Color.White) + .fillMaxSize() + .verticalScroll(scrollState) + ) { + Spacer(modifier = Modifier.height(230.dp)) + Box( + modifier = Modifier + .fillMaxWidth() + .height(120.dp) + .background(Mist97) + .padding(horizontal = 16.dp), + contentAlignment = Alignment.BottomStart + ) { + Column(modifier = Modifier.padding(bottom = 10.dp, top = 10.dp)) { + Text( + text = "Battery", + style = MaterialTheme.typography.bodyMedium + ) + Text( + text = "What you can do with used batteries.", + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold, + ) + Text( + text = "Sumber: detik.com", + style = MaterialTheme.typography.bodyMedium + ) + } + } + Spacer(modifier = Modifier.height(16.dp)) + + Box( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + contentAlignment = Alignment.BottomStart + ) { + Text( + text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Vivamus nec feugiat quam, eu accumsan sapien. Integer " + + "auctor mauris sit amet fringilla commodo. Proin lorem " + + "lorem, sollicitudin sed volutpat a, pellentesque et odio. " + + "Suspendisse vitae libero et sem luctus hendrerit. Maecenas ut " + + "magna a odio laoreet tincidunt." + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Vivamus nec feugiat quam, eu accumsan sapien. Integer " + + "auctor mauris sit amet fringilla commodo. Proin lorem " + + "lorem, sollicitudin sed volutpat a, pellentesque et odio. " + + "Suspendisse vitae libero et sem luctus hendrerit. Maecenas ut " + + "magna a odio laoreet tincidunt.", + ) + } + Spacer(modifier = Modifier.height(50.dp)) + Box( + modifier = Modifier + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + DefaultButton( + contentText = "Share", + onClick = {}, + modifier = Modifier.width(150.dp) + ) + } + } + + Box( + modifier = Modifier + .fillMaxWidth() + .background(Mist97) + .height(300.dp) + ) { + + Box( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight() + .clip( + RoundedCornerShape( + topStart = 0.dp, + topEnd = 0.dp, + bottomEnd = 16.dp, + bottomStart = 16.dp + ) + ) + ) { + Image( + modifier = Modifier.matchParentSize(), + painter = rememberAsyncImagePainter( + model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", + placeholder = painterResource(id = R.drawable.place_holder), + ), + contentScale = ContentScale.FillHeight, + contentDescription = null + ) + Box( + modifier = Modifier + .matchParentSize() + .background( + Brush.verticalGradient( + colors = listOf(Color.Black.copy(alpha = 0.5f), Color.Transparent), + startY = 0f, + endY = 600f + ) + ) + ) + } + } + + Box( + modifier = Modifier + .fillMaxWidth() + .offset(y = (270).dp) + .padding(end = 16.dp), + contentAlignment = Alignment.CenterEnd + ) { + IconButton( + onClick = {}, + modifier = Modifier + .clip(CircleShape) + .shadow(elevation = 4.dp, clip = true) + .background(Color.White) + .size(50.dp) + ) { + Icon( + Icons.Default.Favorite, + tint = Color.Red, + contentDescription = null + ) + } + } + } +} + +@Preview(showBackground = true) +@Composable +fun SingleArticleScreenPreview() { + TechwasMark02Theme { + SingleArticleScreen() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_search.xml new file mode 100644 index 0000000..a5687c6 --- /dev/null +++ b/app/src/main/res/drawable/ic_search.xml @@ -0,0 +1,5 @@ + + + From eeb0064db5cca835236f38223b34a95f618e45a5 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Sun, 4 Jun 2023 19:34:24 +0700 Subject: [PATCH 29/73] modif: create Article & Maps --- app/build.gradle | 2 + app/src/main/AndroidManifest.xml | 6 +- .../capstone/techwasmark02/MainActivity.kt | 2 + .../com/capstone/techwasmark02/TechwasApp.kt | 5 + .../remote/apiService/TechwasArticleApi.kt | 15 ++ .../remote/response/ArticleResultResponse.kt | 23 +++ .../capstone/techwasmark02/di/AppModule.kt | 23 +++ .../repository/TechwasArticleRepository.kt | 19 ++ .../techwasmark02/ui/component/ArticleCard.kt | 76 +++++++- .../techwasmark02/ui/component/SearchBox.kt | 110 +++++++++++ .../ui/component/SelectableText.kt | 50 +++-- .../ui/componentType/ArticleFilterType.kt | 11 ++ .../techwasmark02/ui/navigation/Screen.kt | 8 + .../ui/screen/article/ArticleScreen.kt | 181 ++++++++++++++++++ .../screen/article/ArticleScreenViewModel.kt | 44 ++++- .../ui/screen/home/HomeScreen.kt | 11 +- .../ui/screen/maps/MapsScreen.kt | 152 +++++++++++++-- app/src/main/res/drawable/ic_my_location.xml | 5 + 18 files changed, 695 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/componentType/ArticleFilterType.kt create mode 100644 app/src/main/res/drawable/ic_my_location.xml diff --git a/app/build.gradle b/app/build.gradle index 2c01b66..773d2c7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -89,6 +89,7 @@ dependencies { // Dagger - Hilt implementation 'com.google.dagger:hilt-android:2.45' + implementation 'com.google.android.gms:play-services-location:21.0.1' kapt 'com.google.dagger:hilt-android-compiler:2.45' kapt 'androidx.hilt:hilt-compiler:1.0.0' implementation "androidx.hilt:hilt-navigation-compose:1.0.0" @@ -106,6 +107,7 @@ dependencies { // Maps implementation 'com.google.maps.android:maps-compose:2.10.0' implementation 'com.google.android.gms:play-services-maps:18.1.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.5.2' // CameraX implementation "androidx.camera:camera-camera2:1.2.3" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b65fc1e..28c17e6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -38,9 +38,9 @@ - - - + , + val error: String?, + val message: String?, +) + +data class ComponentListItem( + @SerializedName("componentId") + val componentId: Int?, + @SerializedName("articleImageURL") + val articleImageURL: String?, + @SerializedName("name") + val name: String?, + @SerializedName("id") + val id: Int?, + @SerializedName("desc") + val desc: String?, +) + diff --git a/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt b/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt index d9c151c..09b5c78 100644 --- a/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt +++ b/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt @@ -4,8 +4,10 @@ import android.content.Context import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.preferencesDataStore +import com.capstone.techwasmark02.data.remote.apiService.TechwasArticleApi import com.capstone.techwasmark02.data.remote.apiService.TechwasPredictionApi import com.capstone.techwasmark02.data.remote.apiService.TechwasUserApi +import com.capstone.techwasmark02.repository.TechwasArticleRepository import com.capstone.techwasmark02.repository.TechwasUserApiRepository import dagger.Module import dagger.Provides @@ -61,6 +63,23 @@ object AppModule { return retrofit.create(TechwasPredictionApi::class.java) } + @Provides + @Singleton + fun provideTechwasArticleApi(): TechwasArticleApi { + val loggingInterceptor = + HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(loggingInterceptor) + .build() + val retrofit = Retrofit.Builder() + .baseUrl(TechwasArticleApi.BASE_URL) + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(GsonConverterFactory.create()) + .client(client) + .build() + return retrofit.create(TechwasArticleApi::class.java) + } + @Provides @Singleton fun provideDataStorePreferences( @@ -74,4 +93,8 @@ object AppModule { api: TechwasUserApi ) = TechwasUserApiRepository(api) + fun provideTechwasArticleRepository( + apiArticle: TechwasArticleApi + ) = TechwasArticleRepository(apiArticle) + } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt new file mode 100644 index 0000000..c229b48 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt @@ -0,0 +1,19 @@ +package com.capstone.techwasmark02.repository + +import com.capstone.techwasmark02.data.remote.apiService.TechwasArticleApi +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.ui.common.UiState +import javax.inject.Inject + +class TechwasArticleRepository @Inject constructor( + private val articleApi: TechwasArticleApi +) { + suspend fun getAllArticle(): UiState { + val response = try { + articleApi.getAllArticle() + } catch (e: Exception) { + return UiState.Error(message = "fail to fetch article, ${e.message}") + } + return UiState.Success(data = response, message = "Success to fetch article") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt index 94943d4..10d7f9d 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt @@ -1,11 +1,11 @@ package com.capstone.techwasmark02.ui.component -import androidx.compose.foundation.Canvas import androidx.compose.foundation.Image 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.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -16,11 +16,9 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clipToBounds -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import coil.compose.rememberAsyncImagePainter @@ -77,6 +75,65 @@ fun ArticleCardBig( } } +@Composable +fun ArticleCardSmall( + modifier: Modifier = Modifier, + imgUrl: String?, + title: String?, + description: String?, +) { + ElevatedCard( + modifier = modifier, + shape = MaterialTheme.shapes.large, + elevation = CardDefaults.cardElevation( + defaultElevation = 6.dp + ) + ) { + Box( + modifier = Modifier + .height(107.dp) + ) { + Image( + modifier = Modifier + .fillMaxWidth() + .height(107.dp), + painter = rememberAsyncImagePainter( +// model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", + model = imgUrl, + placeholder = painterResource(id = R.drawable.place_holder), + ), + contentScale = ContentScale.Crop, + contentDescription = null + ) + } + Column( + modifier = Modifier + .fillMaxWidth() + .height(68.dp) + .background(MaterialTheme.colorScheme.tertiary) + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.Center + ) { + if (title != null) { + Text( + text = title, + style = MaterialTheme.typography.titleSmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + if (description != null) { + Text( + text = description, + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } +} + @Preview(showBackground = true) @Composable fun ArticleCardPreview() { @@ -87,7 +144,16 @@ fun ArticleCardPreview() { .background(MaterialTheme.colorScheme.background) .padding(20.dp) ) { - ArticleCardBig(modifier = Modifier.width(240.dp)) + Column { + ArticleCardBig(modifier = Modifier.width(240.dp)) + Spacer(modifier = Modifier.height(20.dp)) + ArticleCardSmall( + modifier = Modifier.width(150.dp), + imgUrl = "", + title = "judul satu", + description = "deskripsi ajah" + ) + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt index 7fa73aa..2f7588f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt @@ -1,2 +1,112 @@ package com.capstone.techwasmark02.ui.component +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SearchBox( + modifier: Modifier = Modifier, + value: String, + onValueChange: (String) -> Unit, +) { + + Box( + modifier = modifier + .fillMaxWidth() + .height(50.dp) + .shadow( + elevation = 4.dp, + shape = RoundedCornerShape(20.dp) + ) + .background(Color.White) + .clip(RoundedCornerShape(20.dp)) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + ) { + TextField( + modifier = Modifier + .fillMaxHeight(), + value = value, + onValueChange = onValueChange, + placeholder = { + Text( + text = "Search", + style = MaterialTheme.typography.bodyMedium, + color = Color.Gray + ) + }, + singleLine = true, + colors = TextFieldDefaults.textFieldColors( + containerColor = Color.White, + textColor = Color.Gray, + cursorColor = MaterialTheme.colorScheme.primary, + focusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent + ) + ) + Spacer(modifier = Modifier.weight(1f)) + Icon( + painter = painterResource(id = R.drawable.ic_search), + contentDescription = null, + tint = MaterialTheme.colorScheme.primary, + modifier = Modifier + .padding(end = 12.dp) + .align(Alignment.CenterVertically) + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun SearchBoxPreview() { + TechwasMark02Theme { + Box(modifier = Modifier.padding(20.dp)) { + + var value by remember { + mutableStateOf("") + } + + SearchBox( + value = value, + onValueChange = { newValue -> + value = newValue + } + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt index 4f9d90b..e643da8 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt @@ -2,41 +2,55 @@ package com.capstone.techwasmark02.ui.component import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.capstone.techwasmark02.ui.componentType.ArticleFilterType import com.capstone.techwasmark02.ui.theme.Black20 import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @Composable fun SelectableText( - text: String, - selected: Boolean, modifier: Modifier = Modifier, - activeColor: Color = MaterialTheme.colorScheme.primary, - inactiveColor: Color = Color.Transparent + filterType: ArticleFilterType, + selected: Boolean ) { - Box( - modifier = modifier - .background( - color = if (selected) activeColor else inactiveColor, - shape = RoundedCornerShape(15.dp) - ) - .padding(8.dp), - contentAlignment = Alignment.Center + Column( + modifier = modifier, + horizontalAlignment = Alignment.CenterHorizontally ) { - Text( - text = text, - style = MaterialTheme.typography.bodyMedium, - color = if (selected) Color.White else Black20 - ) + if(selected) { + Text( + text = filterType.type, + color = Color.White, + style = MaterialTheme.typography.bodySmall, + modifier = Modifier + .clip(RoundedCornerShape(15.dp)) + .background(MaterialTheme.colorScheme.primary) + .padding(horizontal = 11.dp, vertical = 6.dp) + ) + } else { + Text( + text = filterType.type, + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.bodySmall + ) + } } } @@ -46,7 +60,7 @@ fun SelectableTextPreview() { TechwasMark02Theme { Box(modifier = Modifier.padding(20.dp)){ SelectableText( - text = "Click me", + filterType = ArticleFilterType.General, selected = true ) } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/ArticleFilterType.kt b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/ArticleFilterType.kt new file mode 100644 index 0000000..d7e9baf --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/ArticleFilterType.kt @@ -0,0 +1,11 @@ +package com.capstone.techwasmark02.ui.componentType + +sealed class ArticleFilterType(val type: String) { + + object General: ArticleFilterType(type = "General") + + object Laptop: ArticleFilterType(type = "Laptop") + + object Battery: ArticleFilterType(type = "Battery") + +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt index 5ab3a4d..d9c8073 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt @@ -4,4 +4,12 @@ sealed class Screen(val route: String) { object Home: Screen(route = "home") object Camera: Screen(route = "camera") object DetectionResult: Screen(route = "detectionResult") + + object Article: Screen(route = "article") + + object SingleArticle: Screen(route = "singleArticle") + + object Splash: Screen(route = "splash") + + object Maps: Screen(route = "maps") } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt index f17c861..311ac8a 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt @@ -1,2 +1,183 @@ package com.capstone.techwasmark02.ui.screen.article +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +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.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.ui.common.UiState +import com.capstone.techwasmark02.ui.component.ArticleCardSmall +import com.capstone.techwasmark02.ui.component.DefaultBottomBar +import com.capstone.techwasmark02.ui.component.SearchBox +import com.capstone.techwasmark02.ui.component.SelectableText +import com.capstone.techwasmark02.ui.componentType.ArticleFilterType +import com.capstone.techwasmark02.ui.componentType.BottomBarItemType +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme + +@Composable +fun ArticleScreen( + viewModel: ArticleScreenViewModel = hiltViewModel() +) { + val articleList by viewModel.articleList.collectAsState() + + ArticleContent( + articleList = articleList, + ) +} + +@Composable +fun ArticleContent( + articleList: UiState? +) { + + var inputValue by remember { + mutableStateOf("") + } + + val filterTypeList = listOf( + ArticleFilterType.General, + ArticleFilterType.Battery, + ArticleFilterType.Laptop + ) + + val scrollState = rememberScrollState() + + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(scrollState) + .background(MaterialTheme.colorScheme.background) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + .padding(top = 20.dp) + ) { + Column( + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = "Articles", + style = MaterialTheme.typography.headlineLarge, + fontWeight = FontWeight.Bold + ) + + Spacer(modifier = Modifier.height(8.dp)) + + Text( + text = "Lorem ipsum dolor sit amet, consectetur", + style = MaterialTheme.typography.bodyLarge + ) + + Spacer(modifier = Modifier.height(16.dp)) + + SearchBox( + value = inputValue, + onValueChange = { newValue -> + inputValue = newValue + } + ) + + Spacer(modifier = Modifier.height(16.dp)) + + LazyRow( + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + items( + items = filterTypeList, + ) { item -> + SelectableText( + filterType = item, + selected = true + ) + } + } + + Spacer(modifier = Modifier.height(16.dp)) + + if (articleList != null) { + when (articleList) { + is UiState.Loading -> { + CircularProgressIndicator() + } + is UiState.Error -> { + articleList.message?.let { + Text(text = it) + } + } + is UiState.Success -> { + val componentListArticle = articleList.data?.componentList + if(componentListArticle != null) { + LazyVerticalGrid( + modifier = Modifier + .fillMaxWidth() + .height(600.dp), + columns = GridCells.Fixed(2), + contentPadding = PaddingValues(vertical = 8.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + items(componentListArticle) { item -> + ArticleCardSmall( + imgUrl = item?.articleImageURL, + title = item?.name, + description = item?.desc + ) + } + } + } + + } + } + + } else { + // jika null + } + } + } + } + + Column( + modifier = Modifier + .fillMaxSize() + ) { + Spacer(modifier = Modifier.weight(1f)) + DefaultBottomBar(selectedType = BottomBarItemType.Article) + } +} + +@Preview(showBackground = true) +@Composable +fun ArticleScreenPreview() { + TechwasMark02Theme { + ArticleScreen() + } +} diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt index abc49b1..3e2a28a 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt @@ -1,4 +1,46 @@ package com.capstone.techwasmark02.ui.screen.article -class ArticleScreenViewModel { +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.data.mappers.toUserSession +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.repository.TechwasArticleRepository +import com.capstone.techwasmark02.ui.common.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class ArticleScreenViewModel @Inject constructor( + private val articleRepository: TechwasArticleRepository +): ViewModel() { + + private val _articleList: MutableStateFlow?> = MutableStateFlow(null) + val articleList = _articleList.asStateFlow() + + init { + viewModelScope.launch { + getAllArticle() + } + } + + private fun getAllArticle() { + _articleList.value = UiState.Loading() + viewModelScope.launch { + val result = articleRepository.getAllArticle() + when(result) { + is UiState.Success -> { + _articleList.value = result + } + is UiState.Error -> { + _articleList.value = result + } + else -> { + // do nothing + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index d789063..e8b004b 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -58,14 +58,16 @@ fun HomeScreen( navController: NavHostController ) { HomeContent( - navigateToCamera = { navController.navigate(Screen.Camera.route) } + navigateToCamera = { navController.navigate(Screen.Camera.route) }, + navigateToMaps = { navController.navigate(Screen.Maps.route) } ) } @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable fun HomeContent( - navigateToCamera: () -> Unit + navigateToCamera: () -> Unit, + navigateToMaps: () -> Unit, ) { Scaffold( ) { innerPadding -> @@ -173,7 +175,7 @@ fun HomeContent( horizontalArrangement = Arrangement.SpaceBetween ) { Spacer(modifier = Modifier.weight(1f)) - FeatureBox(featureBoxType = FeatureBoxType.DropPoint, onClick = {}) + FeatureBox(featureBoxType = FeatureBoxType.DropPoint, onClick = navigateToMaps) Spacer(modifier = Modifier.weight(3f)) AboutUsBox() Spacer(modifier = Modifier.weight(1f)) @@ -302,7 +304,8 @@ fun HomeContent( fun HomeContentPreview() { TechwasMark02Theme { HomeContent( - navigateToCamera = {} + navigateToCamera = {}, + navigateToMaps = {}, ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt index 41a796e..f1b969d 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt @@ -1,19 +1,137 @@ package com.capstone.techwasmark02.ui.screen.maps -//import androidx.compose.runtime.Composable -//import com.google.android.gms.maps.model.CameraPosition -//import com.google.android.gms.maps.model.LatLng -//import com.google.maps.android.compose.GoogleMap -//import com.google.maps.android.compose.rememberCameraPositionState -// -//@Composable -//fun MapsScreen() { -// val diy = LatLng(-7.782275587997325, 110.36709993087182) -// val cameraPositionState = rememberCameraPositionState { -// position = CameraPosition.fromLatLngZoom(diy, 10f) -// } -// -// GoogleMap( -// cameraPositionState = cameraPositionState -// ) -//} \ No newline at end of file +import android.Manifest +import android.content.pm.PackageManager +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.platform.LocalContext +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import androidx.navigation.NavHostController +import com.capstone.techwasmark02.R +import com.google.android.gms.location.LocationServices +import com.google.android.gms.maps.model.BitmapDescriptorFactory +import com.google.android.gms.maps.model.CameraPosition +import com.google.android.gms.maps.model.LatLng +import com.google.maps.android.compose.GoogleMap +import com.google.maps.android.compose.Marker +import com.google.maps.android.compose.MarkerState +import com.google.maps.android.compose.rememberCameraPositionState +import kotlinx.coroutines.tasks.await + +data class MapMarkerInfo( + val position: LatLng, + val title: String, + val snippet: String +) +@Composable +fun MapsScreen(navController: NavHostController) { + val diy = LatLng(-7.782275587997325, 110.36709993087182) + + // posisi camera + val cameraPositionState = rememberCameraPositionState { + position = CameraPosition.fromLatLngZoom(diy, 12f) + } + + // dummy marker + val markerList = listOf( + MapMarkerInfo( + LatLng(-7.782589124314163, 110.38006889168956), + "Marker 1", + "Ini adalah marker 1" + ), + MapMarkerInfo( + LatLng(-7.8041473764088085, 110.39441386554735), + "Marker 2", + "Ini adalah marker 2" + ), + MapMarkerInfo( + LatLng(-7.790733483350418, 110.35766494375434), + "Marker 3", + "Ini adalah marker 3" + ), + MapMarkerInfo( + LatLng(-7.767737238844195, 110.35476371308648), + "Marker 4", + "Ini adalah marker 4" + ), + MapMarkerInfo( + LatLng(-7.774923700677788, 110.41182124955456), + "Marker 5", + "Ini adalah marker 5" + ), + MapMarkerInfo( + LatLng(-7.7798743027989685, 110.33864576493167), + "Marker 6", + "Ini adalah marker 6" + ), + MapMarkerInfo( + LatLng(-7.783068208639076, 110.3805524301342), + "Marker 7", + "Ini adalah marker 7" + ) + ) + + val context = LocalContext.current + val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context) + + var userLatLng by remember { mutableStateOf(null) } + var permissionGranted by remember { mutableStateOf(false) } + + val launcher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.RequestPermission() + ) { isGranted -> + permissionGranted = isGranted + } + + LaunchedEffect(permissionGranted) { + if (permissionGranted) { + val location = fusedLocationClient.lastLocation.await() + if (location != null) { + userLatLng = LatLng(location.latitude, location.longitude) + } + } + } + + LaunchedEffect(Unit) { + when { + ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED -> { + // Permission already granted + permissionGranted = true + } + else -> { + // Request permission + launcher.launch(Manifest.permission.ACCESS_FINE_LOCATION) + } + } + } + + GoogleMap( + // posisi camera + cameraPositionState = cameraPositionState, + ) { + markerList.forEach { marker -> + Marker( + state = MarkerState( + position = marker.position + ), + title = marker.title, + snippet = marker.snippet + ) + } + + userLatLng?.let { latLng -> + Marker( + state = MarkerState(position = latLng), + title = "Lokasi User", + snippet = "Ini adalah lokasi anda saat ini" + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_my_location.xml b/app/src/main/res/drawable/ic_my_location.xml new file mode 100644 index 0000000..11fdbe5 --- /dev/null +++ b/app/src/main/res/drawable/ic_my_location.xml @@ -0,0 +1,5 @@ + + + From 21d9609f7730441870f77463d4900812d492480e Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Sat, 3 Jun 2023 21:00:41 +0700 Subject: [PATCH 30/73] fixing single article --- .idea/deploymentTargetDropDown.xml | 17 ++ .../techwasmark02/ui/component/TopBar.kt | 4 - .../singleArticle/SingleArticleScreen.kt | 252 +++++++++--------- 3 files changed, 141 insertions(+), 132 deletions(-) create mode 100644 .idea/deploymentTargetDropDown.xml diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..88f656f --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt index 0d52406..1786e47 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt @@ -2,9 +2,7 @@ package com.capstone.techwasmark02.ui.component import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.ExperimentalMaterial3Api @@ -18,11 +16,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import com.capstone.techwasmark02.R import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt index 95ef11f..66e7cee 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt @@ -5,11 +5,9 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -53,147 +51,145 @@ fun SingleArticleScreen() { @OptIn(ExperimentalMaterial3Api::class) @Composable fun SingleArticleContent() { - Scaffold( - topBar = { - TransparentTopBar( - pageTitle = "Detail", - onClickNavigationIcon = {}, - ) - }, - ) { innerPadding -> + Scaffold { innerPadding -> val scrollState = rememberScrollState() - Column( + Box( modifier = Modifier - .padding(innerPadding) - .background(Color.White) .fillMaxSize() - .verticalScroll(scrollState) + .padding(innerPadding) ) { - Spacer(modifier = Modifier.height(230.dp)) - Box( - modifier = Modifier - .fillMaxWidth() - .height(120.dp) - .background(Mist97) - .padding(horizontal = 16.dp), - contentAlignment = Alignment.BottomStart - ) { - Column(modifier = Modifier.padding(bottom = 10.dp, top = 10.dp)) { - Text( - text = "Battery", - style = MaterialTheme.typography.bodyMedium - ) - Text( - text = "What you can do with used batteries.", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold, - ) - Text( - text = "Sumber: detik.com", - style = MaterialTheme.typography.bodyMedium - ) - } - } - Spacer(modifier = Modifier.height(16.dp)) - - Box( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - contentAlignment = Alignment.BottomStart - ) { - Text( - text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Vivamus nec feugiat quam, eu accumsan sapien. Integer " + - "auctor mauris sit amet fringilla commodo. Proin lorem " + - "lorem, sollicitudin sed volutpat a, pellentesque et odio. " + - "Suspendisse vitae libero et sem luctus hendrerit. Maecenas ut " + - "magna a odio laoreet tincidunt." + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Vivamus nec feugiat quam, eu accumsan sapien. Integer " + - "auctor mauris sit amet fringilla commodo. Proin lorem " + - "lorem, sollicitudin sed volutpat a, pellentesque et odio. " + - "Suspendisse vitae libero et sem luctus hendrerit. Maecenas ut " + - "magna a odio laoreet tincidunt.", - ) - } - Spacer(modifier = Modifier.height(50.dp)) - Box( + Column( modifier = Modifier - .fillMaxWidth(), - contentAlignment = Alignment.Center + .fillMaxSize() + .background(Color.White) + .verticalScroll(scrollState) ) { - DefaultButton( - contentText = "Share", - onClick = {}, - modifier = Modifier.width(150.dp) - ) - } - } - - Box( - modifier = Modifier - .fillMaxWidth() - .background(Mist97) - .height(300.dp) - ) { - Box( - modifier = Modifier - .fillMaxWidth() - .fillMaxHeight() - .clip( - RoundedCornerShape( - topStart = 0.dp, - topEnd = 0.dp, - bottomEnd = 16.dp, - bottomStart = 16.dp - ) - ) - ) { - Image( - modifier = Modifier.matchParentSize(), - painter = rememberAsyncImagePainter( - model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", - placeholder = painterResource(id = R.drawable.place_holder), - ), - contentScale = ContentScale.FillHeight, - contentDescription = null - ) Box( modifier = Modifier - .matchParentSize() - .background( - Brush.verticalGradient( - colors = listOf(Color.Black.copy(alpha = 0.5f), Color.Transparent), - startY = 0f, - endY = 600f + .fillMaxWidth() + .background(Mist97) + ) { + Column( + modifier = Modifier + .fillMaxSize() + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(300.dp) + .clip( + RoundedCornerShape( + topStart = 0.dp, + topEnd = 0.dp, + bottomEnd = 16.dp, + bottomStart = 16.dp + ) + ) + ) { + Image( + modifier = Modifier.matchParentSize(), + painter = rememberAsyncImagePainter( + model = "https://picsum.photos/seed/${Random.nextInt()}/320/300", + placeholder = painterResource(id = R.drawable.place_holder), + ), + contentScale = ContentScale.Crop, + contentDescription = null ) - ) - ) + } + + Column(modifier = Modifier + .padding(bottom = 10.dp, top = 10.dp) + .padding(horizontal = 16.dp) + ) { + Text( + text = "Battery", + style = MaterialTheme.typography.bodyMedium + ) + Text( + text = "What you can do with used batteries.", + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold, + ) + Text( + text = "Sumber: detik.com", + style = MaterialTheme.typography.bodyMedium + ) + } + } + + Box( + modifier = Modifier + .fillMaxWidth() + .padding(end = 16.dp, top = 270.dp), + contentAlignment = Alignment.CenterEnd + ) { + IconButton( + onClick = {}, + modifier = Modifier + .clip(CircleShape) + .shadow(elevation = 4.dp, clip = true) + .background(Color.White) + .size(50.dp) + ) { + Icon( + Icons.Default.Favorite, + tint = Color.Red, + contentDescription = null + ) + } + } + } + + Spacer(modifier = Modifier.height(16.dp)) + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + .padding(bottom = 20.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Vivamus nec feugiat quam, eu accumsan sapien. Integer " + + "auctor mauris sit amet fringilla commodo. Proin lorem " + + "lorem, sollicitudin sed volutpat a, pellentesque et odio. " + + "Suspendisse vitae libero et sem luctus hendrerit. Maecenas ut " + + "magna a odio laoreet tincidunt." + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Vivamus nec feugiat quam, eu accumsan sapien. Integer " + + "auctor mauris sit amet fringilla commodo. Proin lorem " + + "lorem, sollicitudin sed volutpat a, pellentesque et odio. " + + "Suspendisse vitae libero et sem luctus hendrerit. Maecenas ut " + + "magna a odio laoreet tincidunt.", + ) + + Spacer(modifier = Modifier.height(36.dp)) + + DefaultButton( + contentText = "Share", + onClick = {}, + modifier = Modifier.width(150.dp) + ) + } } - } - Box( - modifier = Modifier - .fillMaxWidth() - .offset(y = (270).dp) - .padding(end = 16.dp), - contentAlignment = Alignment.CenterEnd - ) { - IconButton( - onClick = {}, + Box( modifier = Modifier - .clip(CircleShape) - .shadow(elevation = 4.dp, clip = true) - .background(Color.White) - .size(50.dp) + .matchParentSize() + .background( + Brush.verticalGradient( + colors = listOf( + Color.Black.copy(alpha = 0.7f), + Color.Transparent + ), + startY = 0f, + endY = 600f + ) + ) ) { - Icon( - Icons.Default.Favorite, - tint = Color.Red, - contentDescription = null - ) + TransparentTopBar(onClickNavigationIcon = { /*TODO*/ }, pageTitle = "Detail") } } } From 298780b636163b612b845aba094d3bf89f025899 Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Sun, 4 Jun 2023 23:21:55 +0700 Subject: [PATCH 31/73] Combine everything --- app/build.gradle | 1 + .../capstone/techwasmark02/MainActivity.kt | 3 + .../com/capstone/techwasmark02/TechwasApp.kt | 36 +++ .../remote/apiService/TechwasComponentApi.kt | 26 ++ .../remote/apiService/TechwasPredictionApi.kt | 7 +- .../data/remote/response/ComponentResponse.kt | 14 + .../remote/response/ComponentsResponse.kt | 14 + .../response/DetectionResultResponse.kt | 87 +++--- .../capstone/techwasmark02/di/AppModule.kt | 25 ++ .../TechwasComponentApiRepository.kt | 33 +++ .../TechwasPredictionApiRepository.kt | 4 +- .../techwasmark02/ui/component/ArticleCard.kt | 70 +++-- .../techwasmark02/ui/component/BottomBar.kt | 123 ++++---- .../techwasmark02/ui/component/CameraView.kt | 19 +- .../techwasmark02/ui/component/CatalogCard.kt | 130 +++++++++ .../techwasmark02/ui/component/DetectBox.kt | 35 +-- .../ui/component/DetectionsResultBox.kt | 50 ++-- .../techwasmark02/ui/component/SearchBox.kt | 72 ++--- .../ui/component/SelectableText.kt | 11 +- .../techwasmark02/ui/navigation/Screen.kt | 4 + .../ui/screen/article/ArticleScreen.kt | 165 ++++++----- .../ui/screen/camera/CameraScreen.kt | 85 +++--- .../ui/screen/camera/CameraScreenViewModel.kt | 4 +- .../ui/screen/catalog/CatalogScreen.kt | 182 ++++++++++++ .../screen/catalog/CatalogScreenViewModel.kt | 31 ++ .../CatalogSingleComponentScreen.kt | 266 ++++++++++++++++++ .../CatalogSingleComponentScreenViewModel.kt | 32 +++ .../detectionResult/DetectionResultScreen.kt | 24 +- .../ui/screen/home/HomeScreen.kt | 77 +++-- .../screen/profileUser/ProfileUserScreen.kt | 33 ++- .../capstone/techwasmark02/ui/theme/Type.kt | 18 +- .../main/res/drawable/img_bg_catalog_card.png | Bin 0 -> 4179 bytes 32 files changed, 1311 insertions(+), 370 deletions(-) create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasComponentApi.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/remote/response/ComponentResponse.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/remote/response/ComponentsResponse.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/repository/TechwasComponentApiRepository.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/CatalogCard.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreenViewModel.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreenViewModel.kt create mode 100644 app/src/main/res/drawable/img_bg_catalog_card.png diff --git a/app/build.gradle b/app/build.gradle index 773d2c7..e3da66c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -108,6 +108,7 @@ dependencies { implementation 'com.google.maps.android:maps-compose:2.10.0' implementation 'com.google.android.gms:play-services-maps:18.1.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.5.2' + implementation 'com.google.android.gms:play-services-location:21.0.1' // CameraX implementation "androidx.camera:camera-camera2:1.2.3" diff --git a/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt b/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt index 4550816..570544a 100644 --- a/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt +++ b/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt @@ -8,6 +8,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.ui.Modifier import com.capstone.techwasmark02.ui.screen.article.ArticleScreen +import com.capstone.techwasmark02.ui.screen.catalog.CatalogScreen import com.capstone.techwasmark02.ui.screen.home.HomeScreen import com.capstone.techwasmark02.ui.screen.maps.MapsScreen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @@ -25,6 +26,8 @@ class MainActivity : ComponentActivity() { color = MaterialTheme.colorScheme.background ) { TechwasApp() +// CatalogScreen() + } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt index 7af74c4..fcf9d53 100644 --- a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt +++ b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt @@ -11,10 +11,14 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.capstone.techwasmark02.ui.navigation.Screen.* +import com.capstone.techwasmark02.ui.screen.article.ArticleScreen import com.capstone.techwasmark02.ui.screen.camera.CameraScreen +import com.capstone.techwasmark02.ui.screen.catalog.CatalogScreen +import com.capstone.techwasmark02.ui.screen.catalogSingleComponent.CatalogSingleComponentScreen import com.capstone.techwasmark02.ui.screen.detectionResult.DetectionResultScreen import com.capstone.techwasmark02.ui.screen.home.HomeScreen import com.capstone.techwasmark02.ui.screen.maps.MapsScreen +import com.capstone.techwasmark02.ui.screen.profileUser.ProfileUserScreen @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -32,6 +36,38 @@ fun TechwasApp() { HomeScreen(navController = navController) } + composable(Article.route) { + ArticleScreen(navController = navController) + } + + composable(Forum.route) { + + } + + composable(Profile.route) { + ProfileUserScreen(navController = navController) + } + + composable(Catalog.route) { + CatalogScreen(navController = navController) + } + + composable( + route = SingleCatalog.route + "/{componentJson}", + arguments = listOf( + navArgument("componentJson") { + type = NavType.StringType + defaultValue = "U fucked up" + } + ) + ) { navBackStackEntry -> + val componentJson = navBackStackEntry.arguments?.getString("componentJson") + + if (componentJson != null) { + CatalogSingleComponentScreen(componentJson = componentJson) + } + } + composable(Camera.route) { CameraScreen(navController = navController) } diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasComponentApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasComponentApi.kt new file mode 100644 index 0000000..73d98c6 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasComponentApi.kt @@ -0,0 +1,26 @@ +package com.capstone.techwasmark02.data.remote.apiService + +import com.capstone.techwasmark02.data.remote.response.ComponentResponse +import com.capstone.techwasmark02.data.remote.response.ComponentsResponse +import com.google.android.gms.common.internal.safeparcel.SafeParcelable.Param +import retrofit2.http.GET +import retrofit2.http.Header +import retrofit2.http.Path + +interface TechwasComponentApi { + + @GET("components/") + suspend fun fetchComponents( + @Header("Authorization") token: String, + ) : ComponentsResponse + + @GET("components/{id}") + suspend fun fetchComponentById( + @Header("Authorization") token: String, + @Path("id") id: Int + ) : ComponentResponse + + companion object { + const val BASE_URL = "https://the-prophecy-fwd5gpydiq-uc.a.run.app/" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt index 583c474..bd053a5 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt @@ -1,6 +1,7 @@ package com.capstone.techwasmark02.data.remote.apiService -import com.capstone.techwasmark02.data.remote.response.DetectionResultResponse + +import com.capstone.techwasmark02.data.remote.response.DetectionsResultResponse import okhttp3.MultipartBody import retrofit2.http.Multipart import retrofit2.http.POST @@ -12,10 +13,10 @@ interface TechwasPredictionApi { @POST("predict/") suspend fun predict( @Part imageFile: MultipartBody.Part - ) : DetectionResultResponse + ) : DetectionsResultResponse companion object { - const val BASE_URL = "http://35.222.181.110/" + const val BASE_URL = "http://34.135.12.100/" // const val BASE_URL = "https://e-waste-model-deployment-1gb-fwd5gpydiq-uc.a.run.app/" } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ComponentResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ComponentResponse.kt new file mode 100644 index 0000000..a9576c1 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ComponentResponse.kt @@ -0,0 +1,14 @@ +package com.capstone.techwasmark02.data.remote.response + +data class ComponentResponse( + val componentList: ComponentList, + val error: String, + val message: String +) + +data class ComponentList( + val desc: String, + val example: String, + val id: Int, + val name: String +) \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ComponentsResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ComponentsResponse.kt new file mode 100644 index 0000000..0833b79 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ComponentsResponse.kt @@ -0,0 +1,14 @@ +package com.capstone.techwasmark02.data.remote.response + +data class ComponentsResponse( + val components: List, + val error: String, + val message: String +) + +data class Component( + val desc: String, + val id: Int, + val imageExample: String, + val name: String +) \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/DetectionResultResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/DetectionResultResponse.kt index 8a758e4..65400b4 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/DetectionResultResponse.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/DetectionResultResponse.kt @@ -2,49 +2,60 @@ package com.capstone.techwasmark02.data.remote.response import com.google.gson.annotations.SerializedName -data class DetectionResultResponse( - val predictions: Predictions, - val time_taken: String -) - //data class DetectResult( // val predictions: Predictions, // val time_taken: String //) -data class Predictions( - @SerializedName("Cable") - val cable: Double?, - @SerializedName("CRT_TV") - val crtTv: Double?, - @SerializedName("E-kettle") - val eKettle: Double?, - @SerializedName("Refrigerator") - val refrigerator: Double?, - @SerializedName("Keyboard") - val keyboard: Double?, - @SerializedName("Laptop") - val laptop: Double?, - @SerializedName("Light Bulb") - val lightBulb: Double?, - @SerializedName("Monitor") - val monitor: Double?, - @SerializedName("Mouse") - val mouse: Double?, - @SerializedName("PCB") - val pcb: Double?, - @SerializedName("Phone") - val phone: Double?, - @SerializedName("Printer") - val printer: Double?, - @SerializedName("Rice Cooker") - val riceCooker: Double?, - @SerializedName("Washing Machine") - val washingMachine: Double? +//data class Predictions( +// @SerializedName("Cable") +// val cable: Double?, +// @SerializedName("CRT_TV") +// val crtTv: Double?, +// @SerializedName("E-kettle") +// val eKettle: Double?, +// @SerializedName("Refrigerator") +// val refrigerator: Double?, +// @SerializedName("Keyboard") +// val keyboard: Double?, +// @SerializedName("Laptop") +// val laptop: Double?, +// @SerializedName("Light Bulb") +// val lightBulb: Double?, +// @SerializedName("Monitor") +// val monitor: Double?, +// @SerializedName("Mouse") +// val mouse: Double?, +// @SerializedName("PCB") +// val pcb: Double?, +// @SerializedName("Phone") +// val phone: Double?, +// @SerializedName("Printer") +// val printer: Double?, +// @SerializedName("Rice Cooker") +// val riceCooker: Double?, +// @SerializedName("Washing Machine") +// val washingMachine: Double? +// +//) +// +//data class ResultComponentType( +// val name: String, +// val percentage: Double +//) +data class DetectionsResultResponse( + val Image_Url: String, + val predictions: List, + val time_taken: String +) +data class Prediction( + @SerializedName("Components ID") + val componentId: Int, + @SerializedName("Components Name") + val componentName: String, + @SerializedName("Components Value") + val componentValue: Double ) -data class ResultComponentType( - val name: String, - val percentage: Double -) \ No newline at end of file + diff --git a/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt b/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt index 09b5c78..b520047 100644 --- a/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt +++ b/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt @@ -5,9 +5,11 @@ import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.preferencesDataStore import com.capstone.techwasmark02.data.remote.apiService.TechwasArticleApi +import com.capstone.techwasmark02.data.remote.apiService.TechwasComponentApi import com.capstone.techwasmark02.data.remote.apiService.TechwasPredictionApi import com.capstone.techwasmark02.data.remote.apiService.TechwasUserApi import com.capstone.techwasmark02.repository.TechwasArticleRepository +import com.capstone.techwasmark02.repository.TechwasComponentApiRepository import com.capstone.techwasmark02.repository.TechwasUserApiRepository import dagger.Module import dagger.Provides @@ -80,6 +82,23 @@ object AppModule { return retrofit.create(TechwasArticleApi::class.java) } + @Provides + @Singleton + fun provideTechwasComponentApi(): TechwasComponentApi { + val loggingInterceptor = + HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(loggingInterceptor) + .build() + val retrofit = Retrofit.Builder() + .baseUrl(TechwasArticleApi.BASE_URL) + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(GsonConverterFactory.create()) + .client(client) + .build() + return retrofit.create(TechwasComponentApi::class.java) + } + @Provides @Singleton fun provideDataStorePreferences( @@ -93,8 +112,14 @@ object AppModule { api: TechwasUserApi ) = TechwasUserApiRepository(api) + @Provides fun provideTechwasArticleRepository( apiArticle: TechwasArticleApi ) = TechwasArticleRepository(apiArticle) + @Provides + fun provideTechwasComponentApiRepository( + api: TechwasComponentApi + ) = TechwasComponentApiRepository(api) + } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasComponentApiRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasComponentApiRepository.kt new file mode 100644 index 0000000..b9b836b --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasComponentApiRepository.kt @@ -0,0 +1,33 @@ +package com.capstone.techwasmark02.repository + +import com.capstone.techwasmark02.data.remote.apiService.TechwasComponentApi +import com.capstone.techwasmark02.data.remote.response.ComponentResponse +import com.capstone.techwasmark02.data.remote.response.ComponentsResponse +import com.capstone.techwasmark02.ui.common.UiState +import javax.inject.Inject + +class TechwasComponentApiRepository @Inject constructor( + private val componentApi: TechwasComponentApi +) { + + suspend fun fetchComponents(userToken: String = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg1ODcyMDkwLjMwNjU4ODJ9.cvaEjnnWe4Z3Hl-ImAIKyguTWeuntb6vOuwGCa1rr2w") : UiState { + + val response = try { + componentApi.fetchComponents(token = userToken) + } catch (e: Exception) { + return UiState.Error(message = e.message ?: "Fail to fetch components") + } + return UiState.Success(data = response) + } + + suspend fun fetchComponentById(userToken: String = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg1ODcyMDkwLjMwNjU4ODJ9.cvaEjnnWe4Z3Hl-ImAIKyguTWeuntb6vOuwGCa1rr2w", componentId: Int) : UiState { + + val response = try { + componentApi.fetchComponentById(token = userToken, id = componentId) + } catch (e: Exception) { + return UiState.Error(message = e.message ?: "Fail to fetch components") + } + return UiState.Success(data = response) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasPredictionApiRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasPredictionApiRepository.kt index 4dfb772..5cd8623 100644 --- a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasPredictionApiRepository.kt +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasPredictionApiRepository.kt @@ -1,7 +1,7 @@ package com.capstone.techwasmark02.repository import com.capstone.techwasmark02.data.remote.apiService.TechwasPredictionApi -import com.capstone.techwasmark02.data.remote.response.DetectionResultResponse +import com.capstone.techwasmark02.data.remote.response.DetectionsResultResponse import com.capstone.techwasmark02.ui.common.UiState import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MultipartBody @@ -13,7 +13,7 @@ class TechwasPredictionApiRepository @Inject constructor( private val predictionApi: TechwasPredictionApi ) { - suspend fun predictWaste(file: File): UiState { + suspend fun predictWaste(file: File): UiState { val imageFile = file.asRequestBody("image/jpeg".toMediaTypeOrNull()) val imageMultiPart: MultipartBody.Part = MultipartBody.Part.createFormData( name = "file", diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt index 10d7f9d..9403ddb 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt @@ -6,6 +6,8 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -31,46 +33,54 @@ fun ArticleCardBig( modifier: Modifier = Modifier ) { ElevatedCard( - modifier = modifier, + modifier = modifier + .height(175.dp), shape = MaterialTheme.shapes.large, elevation = CardDefaults.cardElevation( defaultElevation = 6.dp ) ) { - Box( - modifier = Modifier - .height(107.dp) - ) { - Image( - modifier = Modifier - .fillMaxWidth() - .height(107.dp), - painter = rememberAsyncImagePainter( - model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", - placeholder = painterResource(id = R.drawable.place_holder), - ), - contentScale = ContentScale.Crop, - contentDescription = null - ) - } Column( modifier = Modifier .fillMaxWidth() - .height(68.dp) + .fillMaxHeight() .background(MaterialTheme.colorScheme.tertiary) - .padding(horizontal = 16.dp), - verticalArrangement = Arrangement.Center ) { - Text( - text = "Do not throw electronic waste carelessly", - style = MaterialTheme.typography.titleSmall, - maxLines = 1 - ) - Text( - text = "Lorem ipsum dolor sit amet, consectetur...", - style = MaterialTheme.typography.bodySmall, - maxLines = 1 - ) + Box( + modifier = Modifier + .weight(1f) + ) { + Image( + modifier = Modifier + .fillMaxSize(), + painter = rememberAsyncImagePainter( + model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", + placeholder = painterResource(id = R.drawable.place_holder), + ), + contentScale = ContentScale.Crop, + contentDescription = null + ) + } + + Column( + modifier = Modifier + .padding(horizontal = 16.dp) + .height(64.dp), + verticalArrangement = Arrangement.Center + ) { + Text( + text = "Do not throw electronic waste carelessly", + style = MaterialTheme.typography.titleSmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = "Lorem ipsum dolor sit amet, consectetur...", + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt index 13079d9..4e78117 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt @@ -1,6 +1,6 @@ package com.capstone.techwasmark02.ui.component -import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -13,30 +13,28 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar -import androidx.compose.material3.NavigationBarDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow -import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.capstone.techwasmark02.R import com.capstone.techwasmark02.ui.componentType.BottomBarItemType import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme -import com.capstone.techwasmark02.ui.theme.customShape.BottomNavShape -import com.capstone.techwasmark02.ui.theme.customShape.BottomNavShape2 @Composable fun DefaultBottomBar( modifier: Modifier = Modifier, - selectedType: BottomBarItemType + selectedType: BottomBarItemType, + navigateToHome: () -> Unit, + navigateToForum: () -> Unit, + navigateToArticle: () -> Unit, + navigateToProfile: () -> Unit ) { Box( modifier = Modifier @@ -48,47 +46,38 @@ fun DefaultBottomBar( modifier = modifier .shadow( elevation = 8.dp, - shape = BottomNavShape(), +// shape = BottomNavShape(), clip = true ) - .graphicsLayer { - shape = BottomNavShape() - clip = true - } .clip(RoundedCornerShape(10.dp)) .fillMaxWidth() - .height(60.dp), + .height(64.dp), containerColor = MaterialTheme.colorScheme.inverseSurface, contentColor = MaterialTheme.colorScheme.inverseOnSurface, tonalElevation = 8.dp - ) { + ) { Row( modifier = Modifier .fillMaxWidth() - .fillMaxHeight(), - verticalAlignment = Alignment.CenterVertically + .fillMaxHeight() + .padding(horizontal = 24.dp), + verticalAlignment = Alignment.CenterVertically, ) { - Spacer(modifier = Modifier.weight(1f)) - BottomBarItem(bottomBarItemType = BottomBarItemType.Home, selectedType = selectedType) + BottomBarItem(bottomBarItemType = BottomBarItemType.Home, selectedType = selectedType, onClick = navigateToHome) Spacer(modifier = Modifier.weight(1f)) - BottomBarItem(bottomBarItemType = BottomBarItemType.Forum, selectedType = selectedType) + BottomBarItem(bottomBarItemType = BottomBarItemType.Forum, selectedType = selectedType, onClick = navigateToForum) Spacer(modifier = Modifier.weight(1f)) - Spacer(modifier = Modifier.width(80.dp)) + BottomBarItem(bottomBarItemType = BottomBarItemType.Article, selectedType = selectedType, onClick = navigateToArticle) Spacer(modifier = Modifier.weight(1f)) - BottomBarItem(bottomBarItemType = BottomBarItemType.Article, selectedType = selectedType) + BottomBarItem(bottomBarItemType = BottomBarItemType.Profile, selectedType = selectedType, onClick = navigateToProfile) - Spacer(modifier = Modifier.weight(1f)) - - BottomBarItem(bottomBarItemType = BottomBarItemType.Profile, selectedType = selectedType) - - Spacer(modifier = Modifier.weight(1f)) } } @@ -99,12 +88,14 @@ fun DefaultBottomBar( fun BottomBarItem( modifier: Modifier = Modifier, bottomBarItemType: BottomBarItemType, - selectedType: BottomBarItemType + selectedType: BottomBarItemType, + onClick: () -> Unit ) { Column( modifier = modifier .width(44.dp) - .height(44.dp), + .height(44.dp) + .clickable { onClick() }, horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.SpaceBetween ) { @@ -112,10 +103,10 @@ fun BottomBarItem( painter = painterResource(id = bottomBarItemType.icon), contentDescription = null, tint = if (selectedType == bottomBarItemType) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.inverseOnSurface - } + MaterialTheme.colorScheme.primary + } else { + MaterialTheme.colorScheme.inverseOnSurface + } ) Text( @@ -139,37 +130,43 @@ fun DefaultBottomBarPreview() { .fillMaxWidth() .padding(20.dp) ) { - DefaultBottomBar(selectedType = BottomBarItemType.Home) + DefaultBottomBar( + selectedType = BottomBarItemType.Home, + navigateToHome = {}, + navigateToArticle = {}, + navigateToForum = {}, + navigateToProfile = {} + ) } } } -@Composable -fun CheckBottomNav( - modifier: Modifier = Modifier -) { - Box( - modifier = modifier - .graphicsLayer { - shape = BottomNavShape() - clip = true - } - .fillMaxWidth() - .height(58.dp) - .background(MaterialTheme.colorScheme.inverseSurface) - ) { - - } -} - -@Preview (showBackground = true) -@Composable -fun CheckBottomNavPreview() { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(20.dp) - ) { - CheckBottomNav() - } -} \ No newline at end of file +//@Composable +//fun CheckBottomNav( +// modifier: Modifier = Modifier +//) { +// Box( +// modifier = modifier +// .graphicsLayer { +// shape = BottomNavShape() +// clip = true +// } +// .fillMaxWidth() +// .height(58.dp) +// .background(MaterialTheme.colorScheme.inverseSurface) +// ) { +// +// } +//} + +//@Preview (showBackground = true) +//@Composable +//fun CheckBottomNavPreview() { +// Box( +// modifier = Modifier +// .fillMaxWidth() +// .padding(20.dp) +// ) { +// CheckBottomNav() +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/CameraView.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/CameraView.kt index 409d062..0d0b0ac 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/CameraView.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/CameraView.kt @@ -28,6 +28,7 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -114,11 +115,19 @@ fun CameraView( Box( modifier = Modifier .fillMaxSize() + .background(MaterialTheme.colorScheme.primary) + .padding(top = 16.dp) ) { + Box(modifier = Modifier + .fillMaxSize() + .clip(RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp)) + .background(Color.White) + ) + Box( modifier = Modifier .fillMaxSize() - .padding(horizontal = 8.dp, vertical = 16.dp) + .padding(horizontal = 8.dp, vertical = 8.dp) .clip(RoundedCornerShape(20.dp)) .background(Color.LightGray), contentAlignment = Alignment.BottomCenter, @@ -249,7 +258,15 @@ fun CameraViewPreview() { Box( modifier = Modifier .fillMaxSize() + .background(MaterialTheme.colorScheme.primary) ) { + + Box(modifier = Modifier + .fillMaxSize() + .clip(RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp)) + .background(Color.White) + ) + Box( modifier = Modifier .fillMaxSize() diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/CatalogCard.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/CatalogCard.kt new file mode 100644 index 0000000..6aa362c --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/CatalogCard.kt @@ -0,0 +1,130 @@ +package com.capstone.techwasmark02.ui.component + +import android.net.Uri +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.remote.response.Component +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import kotlin.random.Random + +@Composable +fun CatalogCard( + modifier: Modifier = Modifier, + component: Component, +) { + + Box( + modifier = modifier + .width(300.dp) + .height(100.dp) +// .shadow( +// elevation = 6.dp, +// shape = RoundedCornerShape(20.dp) +// ) + .clip(RoundedCornerShape(20.dp)) + ) { + Image( + painter = painterResource(id = R.drawable.img_bg_catalog_card), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxSize() + ) + + Row( + modifier = Modifier + .fillMaxSize() + .padding(vertical = 8.dp) + .padding(start = 16.dp, end = 8.dp) + ) { + Column( + modifier = Modifier + .fillMaxHeight() + .weight(1f), + verticalArrangement = Arrangement.Center + ) { + Text( + text = component.name, + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.onPrimary + ) + + Text( + text = component.desc, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onPrimary, + maxLines = 3, + overflow = TextOverflow.Ellipsis + ) + } + + Spacer(modifier = Modifier.width(8.dp)) + + Box( + modifier = Modifier + .width(140.dp) + .fillMaxHeight() + .clip(RoundedCornerShape(20.dp)) + .background(Color.LightGray) + ) { + AsyncImage( + model = component.imageExample, + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .fillMaxSize() + ) + } + } + } +} + +@Preview(showBackground = true) +@Composable +fun CatalogCardPreview() { + TechwasMark02Theme { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(20.dp), + contentAlignment = Alignment.Center + ) { + CatalogCard( + component = Component( + desc = "A small portable personal computer that not very reliable and not very versatile.", + id = 1, + name = "Laptop", + imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" + ), + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt index 17ea83f..fffc040 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.capstone.techwasmark02.R @@ -75,7 +76,7 @@ fun FeatureBox( ) } - Spacer(modifier = Modifier.height(40.dp)) + Spacer(modifier = Modifier.weight(1f)) Row( modifier = Modifier @@ -83,7 +84,7 @@ fun FeatureBox( verticalAlignment = Alignment.CenterVertically ) { Icon( - modifier = Modifier.size(33.dp, 25.dp), + modifier = Modifier.size(34.dp), painter = painterResource(id = featureBoxType.icon), contentDescription = null, tint = Color.White @@ -123,7 +124,7 @@ fun AboutUsBox(modifier: Modifier = Modifier) { .clip(CircleShape) .border( BorderStroke( - width = 2.2.dp, + width = 2.dp, color = Color.Black ), shape = CircleShape @@ -137,7 +138,9 @@ fun AboutUsBox(modifier: Modifier = Modifier) { } Text( text = "About Us", - style = MaterialTheme.typography.titleMedium + style = MaterialTheme.typography.titleMedium.copy( + fontWeight = FontWeight.Medium + ) ) } } @@ -148,24 +151,24 @@ fun AboutUsBox(modifier: Modifier = Modifier) { fun DetectBoxPreview() { TechwasMark02Theme { Box(modifier = Modifier.padding(20.dp)) { - Column(modifier = Modifier.fillMaxWidth()) { - FeatureBox( - featureBoxType = FeatureBoxType.Detection, - onClick = {} - ) + Column(modifier = Modifier.fillMaxWidth()) { + FeatureBox( + featureBoxType = FeatureBoxType.Detection, + onClick = {} + ) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(20.dp)) - FeatureBox(featureBoxType = FeatureBoxType.Catalog, onClick = {}) + FeatureBox(featureBoxType = FeatureBoxType.Catalog, onClick = {}) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(20.dp)) - FeatureBox(featureBoxType = FeatureBoxType.DropPoint, onClick = {}) + FeatureBox(featureBoxType = FeatureBoxType.DropPoint, onClick = {}) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(20.dp)) - AboutUsBox() - } + AboutUsBox() + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt index 134f08c..21d5cf9 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt @@ -33,6 +33,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.util.lerp import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.remote.response.Prediction import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import kotlinx.coroutines.launch import kotlin.math.absoluteValue @@ -40,7 +41,8 @@ import kotlin.math.absoluteValue @OptIn(ExperimentalFoundationApi::class) @Composable fun DetectionsResultBox( - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + predictionList: List ) { val pagerState = rememberPagerState() val coroutineScope = rememberCoroutineScope() @@ -68,14 +70,14 @@ fun DetectionsResultBox( } VerticalPager( - pageCount = dummyDetectionResultList.size, + pageCount = predictionList.size, modifier = Modifier .height(84.dp), pageSpacing = (-50).dp, state = pagerState, ) { page -> ResultListItem( - detectionResult = dummyDetectionResultList[page], + detectionResult = predictionList[page], pagerState = pagerState, page = page, modifier = Modifier @@ -103,7 +105,7 @@ fun DetectionsResultBox( coroutineScope.launch { pagerState.animateScrollToPage(prevPageIndex) } }, enabled = prevButtonVisible, - ) { + ) { Icon( painter = painterResource(id = R.drawable.ic_arrow_up), contentDescription = null, @@ -134,7 +136,7 @@ fun DetectionsResultBox( @OptIn(ExperimentalFoundationApi::class) @Composable fun ResultListItem( - detectionResult: DummyDetectionResult, + detectionResult: Prediction, pagerState: PagerState, page: Int, modifier: Modifier = Modifier @@ -144,7 +146,7 @@ fun ResultListItem( verticalAlignment = Alignment.CenterVertically ) { Text( - text = detectionResult.componentType, + text = detectionResult.componentName, style = MaterialTheme.typography.headlineSmall, modifier = Modifier .graphicsLayer { @@ -180,7 +182,7 @@ fun ResultListItem( contentAlignment = Alignment.Center ) { Text( - text = "${detectionResult.detectionPercentage}%", + text = "${detectionResult.componentValue.toInt()}%", style = MaterialTheme.typography.headlineSmall.copy( fontSize = 28.sp ), @@ -224,7 +226,9 @@ fun DetectionsResultBoxPreview() { .fillMaxWidth() .padding(20.dp) ) { - DetectionsResultBox() + DetectionsResultBox( + predictionList = dummyDetectionResultList + ) } } } @@ -241,9 +245,10 @@ fun ResultListItemPreview() { .padding(20.dp) ) { ResultListItem( - detectionResult = DummyDetectionResult( - componentType = "Laptop", - detectionPercentage = 70 + detectionResult = Prediction( + componentId = 1, + componentName = "PCB", + componentValue = 80.988 ), pagerState = PagerState( initialPage = 0, @@ -260,17 +265,20 @@ data class DummyDetectionResult( val detectionPercentage: Int ) -private val dummyDetectionResultList: List = listOf( - DummyDetectionResult( - componentType = "Laptop", - detectionPercentage = 70 +private val dummyDetectionResultList: List = listOf( + Prediction( + componentId = 1, + componentName = "PCB", + componentValue = 80.00 ), - DummyDetectionResult( - componentType = "Mesin Cuci", - detectionPercentage = 20 + Prediction( + componentId = 2, + componentName = "Monitor", + componentValue = 15.00 ), - DummyDetectionResult( - componentType = "Rice Cooker", - detectionPercentage = 10 + Prediction( + componentId = 3, + componentName = "Mouse", + componentValue = 5.00 ) ) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt index 2f7588f..99b5538 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextField @@ -50,44 +51,43 @@ fun SearchBox( shape = RoundedCornerShape(20.dp) ) .background(Color.White) - .clip(RoundedCornerShape(20.dp)) + .clip(RoundedCornerShape(20.dp)), + contentAlignment = Alignment.Center ) { - Row( + TextField( modifier = Modifier - .fillMaxWidth() - ) { - TextField( - modifier = Modifier - .fillMaxHeight(), - value = value, - onValueChange = onValueChange, - placeholder = { - Text( - text = "Search", - style = MaterialTheme.typography.bodyMedium, - color = Color.Gray - ) - }, - singleLine = true, - colors = TextFieldDefaults.textFieldColors( - containerColor = Color.White, - textColor = Color.Gray, - cursorColor = MaterialTheme.colorScheme.primary, - focusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent - ) - ) - Spacer(modifier = Modifier.weight(1f)) - Icon( - painter = painterResource(id = R.drawable.ic_search), - contentDescription = null, - tint = MaterialTheme.colorScheme.primary, - modifier = Modifier - .padding(end = 12.dp) - .align(Alignment.CenterVertically) - ) - } + .fillMaxHeight() + .fillMaxWidth(), + value = value, + onValueChange = onValueChange, + placeholder = { + Text( + text = "Search", + style = MaterialTheme.typography.bodyMedium, + color = Color.Gray + ) + }, + singleLine = true, + colors = TextFieldDefaults.textFieldColors( + containerColor = Color.White, + textColor = Color.Gray, + cursorColor = MaterialTheme.colorScheme.primary, + focusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent + ), + trailingIcon = { + IconButton(onClick = { /*TODO*/ }) { + Icon( + painter = painterResource(id = R.drawable.ic_search), + contentDescription = null, + tint = MaterialTheme.colorScheme.primary, + modifier = Modifier + .padding(end = 12.dp) + ) + } + } + ) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt index e643da8..f66f402 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt @@ -3,10 +3,12 @@ package com.capstone.techwasmark02.ui.component import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon @@ -58,11 +60,18 @@ fun SelectableText( @Composable fun SelectableTextPreview() { TechwasMark02Theme { - Box(modifier = Modifier.padding(20.dp)){ + Row(modifier = Modifier.padding(20.dp), verticalAlignment = Alignment.CenterVertically){ SelectableText( filterType = ArticleFilterType.General, selected = true ) + + Spacer(modifier = Modifier.width(20.dp)) + + SelectableText( + filterType = ArticleFilterType.General, + selected = false + ) } } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt index d9c8073..6137a7b 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt @@ -2,7 +2,11 @@ package com.capstone.techwasmark02.ui.navigation sealed class Screen(val route: String) { object Home: Screen(route = "home") + object Forum: Screen(route = "forum") + object Profile: Screen(route = "profile") object Camera: Screen(route = "camera") + object Catalog: Screen(route = "catalog") + object SingleCatalog: Screen(route = "singleCatalog") object DetectionResult: Screen(route = "detectionResult") object Article: Screen(route = "article") diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt index 311ac8a..696e728 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt @@ -2,6 +2,7 @@ package com.capstone.techwasmark02.ui.screen.article 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.PaddingValues import androidx.compose.foundation.layout.Row @@ -26,11 +27,13 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavHostController import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.ArticleCardSmall @@ -39,22 +42,32 @@ import com.capstone.techwasmark02.ui.component.SearchBox import com.capstone.techwasmark02.ui.component.SelectableText import com.capstone.techwasmark02.ui.componentType.ArticleFilterType import com.capstone.techwasmark02.ui.componentType.BottomBarItemType +import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @Composable fun ArticleScreen( - viewModel: ArticleScreenViewModel = hiltViewModel() + viewModel: ArticleScreenViewModel = hiltViewModel(), + navController: NavHostController ) { val articleList by viewModel.articleList.collectAsState() ArticleContent( articleList = articleList, + navigateToHome = { navController.navigate(Screen.Home.route) }, + navigateToArticle = { navController.navigate(Screen.Article.route) }, + navigateToForum = { navController.navigate(Screen.Forum.route) }, + navigateToProfile = { navController.navigate(Screen.Profile.route) } ) } @Composable fun ArticleContent( - articleList: UiState? + articleList: UiState?, + navigateToHome: () -> Unit, + navigateToForum: () -> Unit, + navigateToArticle: () -> Unit, + navigateToProfile: () -> Unit ) { var inputValue by remember { @@ -72,94 +85,90 @@ fun ArticleContent( Column( modifier = Modifier .fillMaxSize() - .verticalScroll(scrollState) +// .verticalScroll(scrollState) .background(MaterialTheme.colorScheme.background) ) { - Row( + + Column( modifier = Modifier - .fillMaxWidth() + .fillMaxSize() .padding(horizontal = 16.dp) .padding(top = 20.dp) ) { - Column( - modifier = Modifier.fillMaxWidth() - ) { - Text( - text = "Articles", - style = MaterialTheme.typography.headlineLarge, - fontWeight = FontWeight.Bold - ) + Text( + text = "Articles", + style = MaterialTheme.typography.headlineLarge, + fontWeight = FontWeight.Bold + ) - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(8.dp)) - Text( - text = "Lorem ipsum dolor sit amet, consectetur", - style = MaterialTheme.typography.bodyLarge - ) + Text( + text = "Lorem ipsum dolor sit amet, consectetur", + style = MaterialTheme.typography.bodyLarge + ) - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(16.dp)) - SearchBox( - value = inputValue, - onValueChange = { newValue -> - inputValue = newValue - } - ) - - Spacer(modifier = Modifier.height(16.dp)) - - LazyRow( - horizontalArrangement = Arrangement.spacedBy(16.dp), - ) { - items( - items = filterTypeList, - ) { item -> - SelectableText( - filterType = item, - selected = true - ) - } + SearchBox( + value = inputValue, + onValueChange = { newValue -> + inputValue = newValue } + ) - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(16.dp)) + + LazyRow( + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + items( + items = filterTypeList, + ) { item -> + SelectableText( + filterType = item, + selected = true + ) + } + } - if (articleList != null) { - when (articleList) { - is UiState.Loading -> { + Spacer(modifier = Modifier.height(16.dp)) + + if (articleList != null) { + when (articleList) { + is UiState.Loading -> { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { CircularProgressIndicator() } - is UiState.Error -> { - articleList.message?.let { - Text(text = it) - } + } + is UiState.Error -> { + articleList.message?.let { + Text(text = it) } - is UiState.Success -> { - val componentListArticle = articleList.data?.componentList - if(componentListArticle != null) { - LazyVerticalGrid( - modifier = Modifier - .fillMaxWidth() - .height(600.dp), - columns = GridCells.Fixed(2), - contentPadding = PaddingValues(vertical = 8.dp), - verticalArrangement = Arrangement.spacedBy(16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp), - ) { - items(componentListArticle) { item -> - ArticleCardSmall( - imgUrl = item?.articleImageURL, - title = item?.name, - description = item?.desc - ) - } + } + is UiState.Success -> { + val componentListArticle = articleList.data?.componentList + if(componentListArticle != null) { + LazyVerticalGrid( + modifier = Modifier + .fillMaxWidth() + .height(600.dp), + columns = GridCells.Fixed(2), + contentPadding = PaddingValues(vertical = 8.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + items(componentListArticle) { item -> + ArticleCardSmall( + imgUrl = item?.articleImageURL, + title = item?.name, + description = item?.desc + ) } } - } - } - } else { - // jika null + } } } } @@ -170,7 +179,13 @@ fun ArticleContent( .fillMaxSize() ) { Spacer(modifier = Modifier.weight(1f)) - DefaultBottomBar(selectedType = BottomBarItemType.Article) + DefaultBottomBar( + selectedType = BottomBarItemType.Article, + navigateToProfile = navigateToProfile, + navigateToForum = navigateToForum, + navigateToArticle = navigateToArticle, + navigateToHome = navigateToHome + ) } } @@ -178,6 +193,12 @@ fun ArticleContent( @Composable fun ArticleScreenPreview() { TechwasMark02Theme { - ArticleScreen() + ArticleContent( + articleList = UiState.Loading(), + navigateToHome = {}, + navigateToArticle = {}, + navigateToForum = {}, + navigateToProfile = {} + ) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreen.kt index bd1d6d1..1be1cba 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreen.kt @@ -4,7 +4,6 @@ import android.content.Context import android.net.Uri import android.util.Log import android.widget.Toast -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.CircularProgressIndicator @@ -17,22 +16,20 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController -import com.capstone.techwasmark02.data.remote.response.DetectionResultResponse +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.remote.response.DetectionsResultResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.CameraView -import com.capstone.techwasmark02.R -import com.capstone.techwasmark02.data.remote.response.Predictions -import com.capstone.techwasmark02.data.remote.response.ResultComponentType import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import java.io.File import java.util.concurrent.Executors -import kotlin.reflect.full.memberProperties @Composable fun CameraScreen( @@ -57,7 +54,7 @@ fun CameraScreen( @Composable fun CameraContent( photoUri: Uri?, - predictImageState: UiState?, + predictImageState: UiState?, updatePhotoUri: (Uri) -> Unit, predictImage: (Context) -> Unit, navigateToResult: (uri: String, result: String) -> Unit, @@ -72,6 +69,11 @@ fun CameraContent( mutableStateOf(false) } + val moshi = Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .build() + val adapter = moshi.adapter(DetectionsResultResponse::class.java) + LaunchedEffect(key1 = imageIsTaken) { if (imageIsTaken) { predictImage(context) @@ -82,19 +84,20 @@ fun CameraContent( if (predictImageState != null) { when (predictImageState) { is UiState.Success -> { -// val predictResult = predictImageState.data?.predictions?.laptop.toString() + val predictResult = Uri.encode(adapter.toJson(predictImageState.data)) // Toast.makeText(context,"Result: $predictResult", Toast.LENGTH_SHORT).show() - val predictResult = predictImageState.data?.predictions?.let { - getAndSortResult( - it - ) - } +// val predictResult = predictImageState.data?.predictions?.let { +// getAndSortResult( +// it +// ) +// } val stringUri = Uri.encode(photoUri.toString()) onSuccessPredictImage() if (predictResult != null) { navigateToResult(stringUri, predictResult) } +// navigateToResult(stringUri, "alo") } is UiState.Error -> { val predictResult = predictImageState.message @@ -132,12 +135,6 @@ fun CameraContent( .fillMaxSize(), contentAlignment = Alignment.Center ) { - Box( - modifier = Modifier - .fillMaxSize() - .alpha(0.3f) - .background(Color.Black), - ) {} CircularProgressIndicator( color = Color.White @@ -158,30 +155,30 @@ private fun getOutputDirectory(context: Context): File { return if (cacheDir != null && cacheDir.exists()) cacheDir else context.filesDir } -private fun getAndSortResult(detectionResult: Predictions): String { - val resultComponentList = emptyList().toMutableList() - for (property in Predictions::class.memberProperties) { - if (property.get(detectionResult) != null) { - val resultComponentItem = ResultComponentType( - name = property.name, - percentage = property.get(detectionResult).toString().toDouble() - ) - resultComponentList.add(resultComponentItem) - } - } - - val sortedResultComponentList = resultComponentList.sortedWith(compareBy({it.percentage})).reversed() - - val stringResultList = emptyList().toMutableList() - - sortedResultComponentList.forEach { componentItem -> - val stringResultItem = "${componentItem.name}: ${componentItem.percentage}" - stringResultList.add(stringResultItem) - } - - return stringResultList.joinToString(separator = ",") - -} +//private fun getAndSortResult(detectionResult: Predictions): String { +// val resultComponentList = emptyList().toMutableList() +// for (property in Predictions::class.memberProperties) { +// if (property.get(detectionResult) != null) { +// val resultComponentItem = ResultComponentType( +// name = property.name, +// percentage = property.get(detectionResult).toString().toDouble() +// ) +// resultComponentList.add(resultComponentItem) +// } +// } +// +// val sortedResultComponentList = resultComponentList.sortedWith(compareBy({it.percentage})).reversed() +// +// val stringResultList = emptyList().toMutableList() +// +// sortedResultComponentList.forEach { componentItem -> +// val stringResultItem = "${componentItem.name}: ${componentItem.percentage}" +// stringResultList.add(stringResultItem) +// } +// +// return stringResultList.joinToString(separator = ",") +// +//} @Preview(showBackground = true) @Composable diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreenViewModel.kt index ef6c297..814b773 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/camera/CameraScreenViewModel.kt @@ -5,7 +5,7 @@ import android.net.Uri import android.webkit.MimeTypeMap import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.capstone.techwasmark02.data.remote.response.DetectionResultResponse +import com.capstone.techwasmark02.data.remote.response.DetectionsResultResponse import com.capstone.techwasmark02.repository.TechwasPredictionApiRepository import com.capstone.techwasmark02.ui.common.UiState import dagger.hilt.android.lifecycle.HiltViewModel @@ -24,7 +24,7 @@ class CameraScreenViewModel @Inject constructor( private val _photoUri: MutableStateFlow = MutableStateFlow(null) val photoUri = _photoUri.asStateFlow() - private val _predictImageState: MutableStateFlow?> = MutableStateFlow(null) + private val _predictImageState: MutableStateFlow?> = MutableStateFlow(null) val predictImageState = _predictImageState.asStateFlow() fun updatePhotoUri(newUri: Uri) { diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt new file mode 100644 index 0000000..8160ec6 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt @@ -0,0 +1,182 @@ +package com.capstone.techwasmark02.ui.screen.catalog + +import android.net.Uri +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavHostController +import com.capstone.techwasmark02.data.remote.response.Component +import com.capstone.techwasmark02.data.remote.response.ComponentsResponse +import com.capstone.techwasmark02.ui.common.UiState +import com.capstone.techwasmark02.ui.component.CatalogCard +import com.capstone.techwasmark02.ui.component.SearchBox +import com.capstone.techwasmark02.ui.navigation.Screen +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory + +@Composable +fun CatalogScreen( + viewModel: CatalogScreenViewModel = hiltViewModel(), + navController: NavHostController +) { + val componentsState by viewModel.componentState.collectAsState() + + CatalogContent( + componentsState = componentsState, + navigateToSingleComponent = { navController.navigate("${Screen.SingleCatalog.route}/$it") } + ) +} + +@Composable +fun CatalogContent( + componentsState: UiState?, + navigateToSingleComponent: (component: String) -> Unit +) { + val moshi = Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .build() + val adapter = moshi.adapter(Component::class.java) + + + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp) + .padding(top = 20.dp) + ) { + Text( + text = "Catalog", + style = MaterialTheme.typography.headlineSmall + ) + Text( + text = "Find your e-waste component here", + style = MaterialTheme.typography.bodyMedium + ) + + Spacer(modifier = Modifier.height(10.dp)) + + SearchBox(onValueChange = {}, value = "") + + Spacer(modifier = Modifier.height(16.dp)) + + if (componentsState != null) { + when(componentsState) { + is UiState.Success -> { + val components = componentsState.data?.components + + LazyColumn( + modifier = Modifier + .fillMaxSize(), + contentPadding = PaddingValues(bottom = 20.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + components?.size?.let { + items( + count = it, + ) {index -> + CatalogCard( + component = components[index], + modifier = Modifier + .fillMaxWidth() + .clickable { + val componentJson = Uri.encode(adapter.toJson(components[index])) + + navigateToSingleComponent(componentJson) + }, + ) + } + } + } + } + is UiState.Error -> { + + } + is UiState.Loading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + } + } + } +} + +@Preview (showBackground = true) +@Composable +fun CatalogScreenPreview() { + TechwasMark02Theme { + CatalogContent( + componentsState = UiState.Loading(), + navigateToSingleComponent = {} +// components = listOf( +// Component( +// desc = "A small portable personal computer that not very reliable and not very versatile.", +// id = 1, +// name = "Laptop", +// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" +// ), +// Component( +// desc = "A small portable personal computer that not very reliable and not very versatile.", +// id = 1, +// name = "Laptop", +// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" +// ), +// Component( +// desc = "A small portable personal computer that not very reliable and not very versatile.", +// id = 1, +// name = "Laptop", +// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" +// ), +// Component( +// desc = "A small portable personal computer that not very reliable and not very versatile.", +// id = 1, +// name = "Laptop", +// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" +// ), +// Component( +// desc = "A small portable personal computer that not very reliable and not very versatile.", +// id = 1, +// name = "Laptop", +// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" +// ), +// Component( +// desc = "A small portable personal computer that not very reliable and not very versatile.", +// id = 1, +// name = "Laptop", +// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" +// ), +// Component( +// desc = "A small portable personal computer that not very reliable and not very versatile.", +// id = 1, +// name = "Laptop", +// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" +// ) +// ) + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreenViewModel.kt new file mode 100644 index 0000000..3ad0384 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreenViewModel.kt @@ -0,0 +1,31 @@ +package com.capstone.techwasmark02.ui.screen.catalog + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.data.remote.response.ComponentsResponse +import com.capstone.techwasmark02.repository.PreferencesRepository +import com.capstone.techwasmark02.repository.TechwasComponentApiRepository +import com.capstone.techwasmark02.repository.TechwasUserApiRepository +import com.capstone.techwasmark02.ui.common.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class CatalogScreenViewModel @Inject constructor( + private val preferencesRepository: PreferencesRepository, + private val componentApiRepository: TechwasComponentApiRepository +): ViewModel() { + + private val _componentsState: MutableStateFlow?> = MutableStateFlow(null) + val componentState = _componentsState.asStateFlow() + + init { + viewModelScope.launch { + _componentsState.value = componentApiRepository.fetchComponents() + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt new file mode 100644 index 0000000..75aa5ed --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt @@ -0,0 +1,266 @@ +package com.capstone.techwasmark02.ui.screen.catalogSingleComponent + +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.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.blur +import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import coil.compose.AsyncImage +import com.capstone.techwasmark02.data.remote.response.Component +import com.capstone.techwasmark02.data.remote.response.ComponentResponse +import com.capstone.techwasmark02.data.remote.response.DetectionsResultResponse +import com.capstone.techwasmark02.ui.common.UiState +import com.capstone.techwasmark02.ui.component.ArticleCardBig +import com.capstone.techwasmark02.ui.component.DefaultButton +import com.capstone.techwasmark02.ui.component.DefaultTopBar +import com.capstone.techwasmark02.ui.component.InverseButton +import com.capstone.techwasmark02.ui.component.UsableComponentItem +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import kotlin.random.Random + +@Composable +fun CatalogSingleComponentScreen( + viewModel: CatalogSingleComponentScreenViewModel = hiltViewModel(), + componentJson: String +) { + + val componentState by viewModel.componentState.collectAsState() + + val moshi = Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .build() + val adapter = moshi.adapter(Component::class.java) + + val component = adapter.fromJson(componentJson) + + if (component != null) { + CatalogSingleComponentContent(component = component) + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun CatalogSingleComponentContent( + component: Component +) { + Scaffold( + topBar = { + DefaultTopBar( + pageTitle = "Result", + onClickNavigationIcon = {} + ) + } + ) { innerPadding -> + val scrollState = rememberScrollState() + + Column( + modifier = Modifier + .verticalScroll(scrollState) + .padding(innerPadding) + .padding(bottom = 20.dp) + ) { + Box( + modifier = Modifier + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(440.dp) + .clip( + RoundedCornerShape( + bottomStart = 20.dp, + bottomEnd = 20.dp + ) + ) + .background(MaterialTheme.colorScheme.primary), + ) { + AsyncImage( + model = component.imageExample, + contentDescription = null, + contentScale = ContentScale.Crop, + alpha = 0.8f, + modifier = Modifier + .fillMaxSize() + .blur(16.dp) + ) + AsyncImage( + model = component.imageExample, + contentDescription = null, + contentScale = ContentScale.Fit, + modifier = Modifier + .fillMaxSize() + ) + } + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 402.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Box( + modifier = Modifier + .padding(horizontal = 20.dp) + .fillMaxWidth() + .height(64.dp) + .clip(RoundedCornerShape(20.dp)) + .background(MaterialTheme.colorScheme.tertiary) + .padding(start = 20.dp), + contentAlignment = Alignment.CenterStart + ) { + component?.name?.let { + Text( + text = it, + style = MaterialTheme.typography.headlineSmall + ) + } + } + +// if (detectionsResultObj != null) { +// DetectionsResultBox( +// modifier = Modifier +// .padding(horizontal = 20.dp), +// predictionList = detectionsResultObj.predictions +// ) +// } + + } + } + + Column( + modifier = Modifier + .padding(horizontal = 20.dp) + .padding(top = 20.dp) + ) { + + component?.desc?.let { + Text( + text = it, + style = MaterialTheme.typography.bodyMedium + ) + } + + Spacer(modifier = Modifier.height(20.dp)) + + Text( + text = "Usable Components", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground + ) + + Spacer(modifier = Modifier.height(8.dp)) + + LazyVerticalGrid( + columns = GridCells.Fixed( + 2 + ), + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + modifier = Modifier.height(132.dp) + ) { + items(3) { item -> + UsableComponentItem( + onClick = {} +// onClick = { +// isOnBackClick = false +// coroutineScope.launch { +// modalSheetState.show() +// } +// } + ) + } + } + + Spacer(modifier = Modifier.height(28.dp)) + + Text( + text = "Related Articles", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground + ) + + Spacer(modifier = Modifier.height(8.dp)) + } + + Column( + modifier = Modifier + .fillMaxWidth() + ) { + LazyRow( + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + items( + count = 10, + ) { item -> + ArticleCardBig( + modifier = Modifier + .width(150.dp) + ) + } + } + } + + Spacer(modifier = Modifier.height(28.dp)) + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 40.dp) + ) { + DefaultButton(contentText = "Drop Point", modifier = Modifier.fillMaxWidth()) + + Spacer(modifier = Modifier.height(20.dp)) + + InverseButton(contentText = "Check Out Forum", modifier = Modifier.fillMaxWidth()) + } + + } + } +} + +@Preview(showBackground = true) +@Composable +fun CatalogSingleComponentScreenPreview() { + TechwasMark02Theme { + CatalogSingleComponentContent( + component = Component( + desc = "kdfiasu kadfiau kaud fiajdfkua dfja ufiauj dfkaud ifaju", + id = 2, + imageExample = "", + name = "Laptop" + ) + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreenViewModel.kt new file mode 100644 index 0000000..1d0b3b8 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreenViewModel.kt @@ -0,0 +1,32 @@ +package com.capstone.techwasmark02.ui.screen.catalogSingleComponent + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.data.remote.apiService.TechwasComponentApi +import com.capstone.techwasmark02.data.remote.response.Component +import com.capstone.techwasmark02.data.remote.response.ComponentResponse +import com.capstone.techwasmark02.repository.TechwasComponentApiRepository +import com.capstone.techwasmark02.ui.common.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class CatalogSingleComponentScreenViewModel @Inject constructor( + private val componentApiRepository: TechwasComponentApiRepository +) : ViewModel() { + + private val _componentState: MutableStateFlow> = MutableStateFlow(UiState.Loading()) + val componentState = _componentState.asStateFlow() + + + + suspend fun updateComponentState(componentId: Int) { + viewModelScope.launch { + _componentState.value = componentApiRepository.fetchComponentById(componentId = componentId) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt index ea6cbbb..c3b8130 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt @@ -42,6 +42,7 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import coil.compose.AsyncImage +import com.capstone.techwasmark02.data.remote.response.DetectionsResultResponse import com.capstone.techwasmark02.ui.component.ArticleCardBig import com.capstone.techwasmark02.ui.component.DefaultButton import com.capstone.techwasmark02.ui.component.DefaultTopBar @@ -51,6 +52,8 @@ import com.capstone.techwasmark02.ui.component.InverseButton import com.capstone.techwasmark02.ui.component.UsableComponentBottomSheet import com.capstone.techwasmark02.ui.component.UsableComponentItem import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import kotlinx.coroutines.launch @@ -85,6 +88,13 @@ fun DetectionResultContent( val photoUri = Uri.parse(stringUri) + val moshi = Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .build() + val adapter = moshi.adapter(DetectionsResultResponse::class.java) + + val detectionsResultObj = adapter.fromJson(detectionResult) + // BackHandler(modalSheetState.isVisible) { // coroutineScope.launch { modalSheetState.hide() } // } @@ -167,12 +177,13 @@ fun DetectionResultContent( color = MaterialTheme.colorScheme.onPrimary ) - Text(text = detectionResult, color = Color.White) - - DetectionsResultBox( - modifier = Modifier - .padding(horizontal = 20.dp) - ) + if (detectionsResultObj != null) { + DetectionsResultBox( + modifier = Modifier + .padding(horizontal = 20.dp), + predictionList = detectionsResultObj.predictions + ) + } } } @@ -270,4 +281,3 @@ fun DetectionResultContentPreview() { ) } } - diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index e8b004b..f412bae 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -48,7 +48,7 @@ import com.capstone.techwasmark02.ui.component.DefaultBottomBar import com.capstone.techwasmark02.ui.component.FeatureBox import com.capstone.techwasmark02.ui.componentType.BottomBarItemType import com.capstone.techwasmark02.ui.componentType.FeatureBoxType -import com.capstone.techwasmark02.ui.navigation.Screen +import com.capstone.techwasmark02.ui.navigation.Screen.* import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import com.capstone.techwasmark02.ui.theme.yellow import kotlin.math.absoluteValue @@ -58,8 +58,13 @@ fun HomeScreen( navController: NavHostController ) { HomeContent( - navigateToCamera = { navController.navigate(Screen.Camera.route) }, - navigateToMaps = { navController.navigate(Screen.Maps.route) } + navigateToCamera = { navController.navigate(Camera.route) }, + navigateToHome = { navController.navigate(Home.route) }, + navigateToArticle = { navController.navigate(Article.route) }, + navigateToForum = { navController.navigate(Forum.route) }, + navigateToProfile = { navController.navigate(Profile.route) }, + navigateToCatalog = { navController.navigate(Catalog.route) }, + navigateToMaps = { navController.navigate(Maps.route) } ) } @@ -67,12 +72,20 @@ fun HomeScreen( @Composable fun HomeContent( navigateToCamera: () -> Unit, - navigateToMaps: () -> Unit, + navigateToHome: () -> Unit, + navigateToForum: () -> Unit, + navigateToArticle: () -> Unit, + navigateToProfile: () -> Unit, + navigateToCatalog: () -> Unit, + navigateToMaps: () -> Unit ) { Scaffold( ) { innerPadding -> val scrollState = rememberScrollState() + val titlePaddingBottom = 10.dp + val titlePaddingTop = 24.dp + Box( modifier = Modifier .fillMaxSize(), @@ -135,8 +148,11 @@ fun HomeContent( ) ) .background(Color.White) - .padding(bottom = 72.dp) + .padding(bottom = 90.dp) ) { + + Spacer(modifier = Modifier.height(18.dp)) + Column( Modifier .fillMaxWidth() @@ -145,15 +161,15 @@ fun HomeContent( Row( modifier = Modifier .fillMaxWidth() - .padding(vertical = 18.dp) ) { Text( text = "Features", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold + style = MaterialTheme.typography.titleMedium, ) } + Spacer(modifier = Modifier.height(titlePaddingBottom)) + Row( modifier = Modifier .fillMaxWidth(), @@ -161,7 +177,7 @@ fun HomeContent( Spacer(modifier = Modifier.weight(1f)) FeatureBox(featureBoxType = FeatureBoxType.Detection, onClick = navigateToCamera) Spacer(modifier = Modifier.weight(3f)) - FeatureBox(featureBoxType = FeatureBoxType.Catalog, onClick = {}) + FeatureBox(featureBoxType = FeatureBoxType.Catalog, onClick = navigateToCatalog) Spacer(modifier = Modifier.weight(1f)) // DetectBox1() // DetectBox2() @@ -181,7 +197,7 @@ fun HomeContent( Spacer(modifier = Modifier.weight(1f)) } - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(titlePaddingTop)) Row( modifier = Modifier @@ -190,8 +206,7 @@ fun HomeContent( ) { Text( text = "Articles", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold + style = MaterialTheme.typography.titleMedium, ) Spacer(modifier = Modifier.weight(1f)) @@ -205,23 +220,20 @@ fun HomeContent( } } - Spacer(modifier = Modifier.height(10.dp)) + Spacer(modifier = Modifier.height(titlePaddingBottom)) val pagerState = rememberPagerState() HorizontalPager( pageCount = 10, state = pagerState, - contentPadding = PaddingValues(horizontal = 70.dp), + contentPadding = PaddingValues(horizontal = 56.dp), modifier = Modifier.fillMaxWidth() ) { page -> ArticleCardBig( modifier = Modifier - .width(272.dp) - .height(139.dp) + .width(280.dp) + .height(180.dp) .graphicsLayer { - // Calculate the absolute offset for the current page from the - // scroll position. We use the absolute value which allows us to mirror - // any effects for both directions val pageOffset = ( (pagerState.currentPage - page) + pagerState .currentPageOffsetFraction @@ -244,7 +256,7 @@ fun HomeContent( ) } - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(titlePaddingTop)) Column( modifier = Modifier @@ -253,14 +265,12 @@ fun HomeContent( ) { Row( modifier = Modifier - .fillMaxWidth() - .padding(bottom = 10.dp), + .fillMaxWidth(), horizontalArrangement = Arrangement.Center ) { Text( text = "Forums", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold + style = MaterialTheme.typography.titleMedium, ) Spacer(modifier = Modifier.weight(1f)) @@ -273,6 +283,8 @@ fun HomeContent( ) } + Spacer(modifier = Modifier.height(titlePaddingBottom)) + Row( modifier = Modifier .fillMaxWidth(), @@ -281,7 +293,7 @@ fun HomeContent( ArticleCardBig( modifier = Modifier .width(320.dp) - .height(161.dp) + .height(186.dp) ) } } @@ -293,7 +305,13 @@ fun HomeContent( .fillMaxSize() ) { Spacer(modifier = Modifier.weight(1f)) - DefaultBottomBar(selectedType = BottomBarItemType.Home) + DefaultBottomBar( + selectedType = BottomBarItemType.Home, + navigateToProfile = navigateToProfile, + navigateToForum = navigateToForum, + navigateToArticle = navigateToArticle, + navigateToHome = navigateToHome + ) } } } @@ -305,7 +323,12 @@ fun HomeContentPreview() { TechwasMark02Theme { HomeContent( navigateToCamera = {}, - navigateToMaps = {}, + navigateToHome = {}, + navigateToArticle = {}, + navigateToForum = {}, + navigateToProfile = {}, + navigateToCatalog = {}, + navigateToMaps = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt index eaf9bdf..663ef36 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.navigation.NavHostController import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R import com.capstone.techwasmark02.ui.component.ArticleCardBig @@ -40,17 +41,30 @@ import com.capstone.techwasmark02.ui.component.DefaultTopBar import com.capstone.techwasmark02.ui.component.ForumBox import com.capstone.techwasmark02.ui.component.ProfileBox import com.capstone.techwasmark02.ui.componentType.BottomBarItemType +import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import kotlin.random.Random @Composable -fun ProfileUserScreen() { - ProfileUserContent() +fun ProfileUserScreen( + navController: NavHostController +) { + ProfileUserContent( + navigateToHome = { navController.navigate(Screen.Home.route) }, + navigateToArticle = { navController.navigate(Screen.Article.route) }, + navigateToForum = { navController.navigate(Screen.Forum.route) }, + navigateToProfile = { navController.navigate(Screen.Profile.route) } + ) } @OptIn(ExperimentalMaterial3Api::class) @Composable -fun ProfileUserContent() { +fun ProfileUserContent( + navigateToHome: () -> Unit, + navigateToForum: () -> Unit, + navigateToArticle: () -> Unit, + navigateToProfile: () -> Unit +) { Scaffold( topBar = { @@ -61,7 +75,11 @@ fun ProfileUserContent() { }, bottomBar = { DefaultBottomBar( - selectedType = BottomBarItemType.Profile + selectedType = BottomBarItemType.Profile, + navigateToProfile = navigateToProfile, + navigateToForum = navigateToForum, + navigateToArticle = navigateToArticle, + navigateToHome = navigateToHome ) } ) { innerPadding -> @@ -194,6 +212,11 @@ fun ProfileUserContent() { @Composable fun ProfileUserScreenPreview() { TechwasMark02Theme { - ProfileUserScreen() + ProfileUserContent( + navigateToHome = {}, + navigateToArticle = {}, + navigateToForum = {}, + navigateToProfile = {} + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/theme/Type.kt b/app/src/main/java/com/capstone/techwasmark02/ui/theme/Type.kt index 3ece5d6..f574377 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/theme/Type.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/theme/Type.kt @@ -28,13 +28,27 @@ val Typography = Typography( lineHeight = 32.sp, letterSpacing = 0.sp ), - titleSmall = TextStyle( + titleLarge = TextStyle( + fontFamily = poppins, + fontWeight = FontWeight.Medium, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + titleMedium = TextStyle( fontFamily = poppins, fontWeight = FontWeight.Bold, fontSize = 20.sp, - lineHeight = 14.sp, + lineHeight = 24.sp, letterSpacing = 0.1.sp ), + titleSmall = TextStyle( + fontFamily = poppins, + fontWeight = FontWeight.Bold, + fontSize = 14.sp, + lineHeight = 24.sp, + letterSpacing = 0.15.sp + ), labelLarge = TextStyle( fontFamily = poppins, fontWeight = FontWeight.Bold, diff --git a/app/src/main/res/drawable/img_bg_catalog_card.png b/app/src/main/res/drawable/img_bg_catalog_card.png new file mode 100644 index 0000000000000000000000000000000000000000..c47d45086e9f8d4af815bff3df37337707f75f9b GIT binary patch literal 4179 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 literal 0 HcmV?d00001 From 9393d2e1230ffdc345deed37b4f939f0be013717 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 16:17:09 +0700 Subject: [PATCH 32/73] modif: idk --- .idea/deploymentTargetDropDown.xml | 4 +- .../remote/response/SingleArticleResponse.kt | 36 ++++++++++++ .../techwasmark02/ui/component/ArticleCard.kt | 1 + .../techwasmark02/ui/component/ForumBox.kt | 58 +++++++++++-------- .../screen/profileUser/ProfileUserScreen.kt | 17 +++--- .../SingleArticleScreenViewModel.kt | 4 ++ 6 files changed, 86 insertions(+), 34 deletions(-) create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/remote/response/SingleArticleResponse.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 88f656f..3b32c9e 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -7,11 +7,11 @@ - + - + \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/SingleArticleResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/SingleArticleResponse.kt new file mode 100644 index 0000000..2ec2174 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/SingleArticleResponse.kt @@ -0,0 +1,36 @@ +package com.capstone.techwasmark02.data.remote.response + +import com.google.gson.annotations.SerializedName + +data class SingleArticleResponse( + + @field:SerializedName("error") + val error: String? = null, + + @field:SerializedName("message") + val message: String? = null, + + @field:SerializedName("article") + val article: List? = null +) + +data class ArticleItem( + + @field:SerializedName("componentID") + val componentID: Int? = null, + + @field:SerializedName("articleImageURL") + val articleImageURL: String? = null, + + @field:SerializedName("name") + val name: String? = null, + + @field:SerializedName("description") + val description: String? = null, + + @field:SerializedName("id") + val id: Int? = null, + + @field:SerializedName("componentName") + val componentName: String? = null +) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt index 9403ddb..926ba9a 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt @@ -102,6 +102,7 @@ fun ArticleCardSmall( Box( modifier = Modifier .height(107.dp) + .fillMaxWidth() ) { Image( modifier = Modifier diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt index 1040df5..69ec2d8 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt @@ -5,10 +5,12 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.KeyboardArrowRight import androidx.compose.material3.Icon @@ -19,8 +21,10 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import coil.compose.rememberAsyncImagePainter @@ -29,60 +33,66 @@ import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import kotlin.random.Random @Composable -fun ForumBox(modifier: Modifier = Modifier) { +fun ForumBox( + modifier: Modifier = Modifier, +) { Box( modifier = modifier - .fillMaxWidth() .height(80.dp) - .clip(MaterialTheme.shapes.large) + .width(328.dp) + .clip(RoundedCornerShape(20.dp)) .shadow( - elevation = 4.dp, - clip = true + elevation = 8.dp, + shape = RoundedCornerShape(20.dp) ) - .background(MaterialTheme.colorScheme.tertiary) - .padding(horizontal = 24.dp), - contentAlignment = Alignment.Center + .background(Color.White) ) { Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth() + modifier + .fillMaxSize() + .padding(start = 7.17.dp, end = 27.5.dp), + verticalAlignment = Alignment.CenterVertically ) { Image( modifier = Modifier .width(100.dp) .height(60.dp) - .clip(MaterialTheme.shapes.large), + .clip(RoundedCornerShape(20.dp)), painter = rememberAsyncImagePainter( - model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", - placeholder = painterResource(id = R.drawable.place_holder), - ), - contentScale = ContentScale.FillHeight, - contentDescription = null, - ) + model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", + placeholder = painterResource(id = R.drawable.place_holder), + ), + contentScale = ContentScale.Crop, + contentDescription = null + ) Column( modifier = Modifier .weight(1f) - .padding(start = 10.dp) + .height(60.dp) + .padding(start = 8.2.dp) ) { Text( text = "Title", - style = MaterialTheme.typography.labelLarge + style = MaterialTheme.typography.labelMedium, + overflow = TextOverflow.Ellipsis ) Text( text = "Subtitle", style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), + overflow = TextOverflow.Ellipsis ) Text( text = "Description", style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), + overflow = TextOverflow.Ellipsis ) } Icon( imageVector = Icons.Default.KeyboardArrowRight, - contentDescription = "Arrow", - tint = MaterialTheme.colorScheme.onSurface + tint = MaterialTheme.colorScheme.onSurface, + contentDescription = null ) } } @@ -94,7 +104,7 @@ fun ForumBoxPreview() { TechwasMark02Theme() { Box(modifier = Modifier .fillMaxWidth() - .background(MaterialTheme.colorScheme.primaryContainer) + .background(MaterialTheme.colorScheme.background) .padding(20.dp)) { ForumBox() } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt index 663ef36..eab5847 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt @@ -36,6 +36,7 @@ import androidx.navigation.NavHostController import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R import com.capstone.techwasmark02.ui.component.ArticleCardBig +import com.capstone.techwasmark02.ui.component.ArticleCardSmall import com.capstone.techwasmark02.ui.component.DefaultBottomBar import com.capstone.techwasmark02.ui.component.DefaultTopBar import com.capstone.techwasmark02.ui.component.ForumBox @@ -173,9 +174,10 @@ fun ProfileUserContent( items( count = 10, ) { item -> - ArticleCardBig( - modifier = Modifier - .width(150.dp) + ArticleCardSmall( + imgUrl = "https://picsum.photos/seed/${Random.nextInt()}/320/120", + title = "Title Article $item", + description = "description article $item" ) } } @@ -194,13 +196,12 @@ fun ProfileUserContent( LazyColumn( modifier = Modifier .fillMaxWidth() - .fillMaxHeight(), - verticalArrangement = Arrangement.spacedBy(10.dp) + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(10.dp), + horizontalAlignment = Alignment.CenterHorizontally ) { items(count = 5) { - ForumBox(modifier = Modifier - .padding(horizontal = 16.dp) - ) + ForumBox(modifier = Modifier.fillMaxWidth()) } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt new file mode 100644 index 0000000..917c8e6 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt @@ -0,0 +1,4 @@ +package com.capstone.techwasmark02.ui.screen.singleArticle + +class SingleArticleScreenViewModel { +} \ No newline at end of file From 072c9fa8cc97afaf00ed51fe93d452adf720f94b Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 16:17:48 +0700 Subject: [PATCH 33/73] modif: menambah route singleArticle --- .../com/capstone/techwasmark02/TechwasApp.kt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt index fcf9d53..947bfc9 100644 --- a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt +++ b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt @@ -19,6 +19,7 @@ import com.capstone.techwasmark02.ui.screen.detectionResult.DetectionResultScree import com.capstone.techwasmark02.ui.screen.home.HomeScreen import com.capstone.techwasmark02.ui.screen.maps.MapsScreen import com.capstone.techwasmark02.ui.screen.profileUser.ProfileUserScreen +import com.capstone.techwasmark02.ui.screen.singleArticle.SingleArticleScreen @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -40,6 +41,22 @@ fun TechwasApp() { ArticleScreen(navController = navController) } + composable( + route = SingleArticle.route + "/{idArticle}", + arguments = listOf( + navArgument("idArticle") { + type = NavType.IntType + defaultValue = 1 + } + ) + ) { navBackStackEntry -> + val idArticle = navBackStackEntry.arguments?.getInt("idArticle") + + if(idArticle != null) { + SingleArticleScreen(idArticle = idArticle) + } + } + composable(Forum.route) { } From 883e4fa3bda50f38c581e340832a0eeb905a10c7 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 16:18:10 +0700 Subject: [PATCH 34/73] modif: menambah api article --- .../data/remote/apiService/TechwasArticleApi.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt index dd140fc..f862ead 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt @@ -1,14 +1,25 @@ package com.capstone.techwasmark02.data.remote.apiService import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse -import retrofit2.Response +import com.capstone.techwasmark02.data.remote.response.SingleArticleResponse import retrofit2.http.GET +import retrofit2.http.Path interface TechwasArticleApi { @GET("/allArticle") suspend fun getAllArticle(): ArticleResultResponse + @GET("/article/id/{id}") + suspend fun getArticleById( + @Path("id") id: Int + ): SingleArticleResponse + + @GET("/article/name/{name}") + suspend fun getArticleByName( + @Path("name") name: String + ): ArticleResultResponse + companion object { const val BASE_URL = "https://the-prophecy-fwd5gpydiq-uc.a.run.app/" } From 91a86cd1ac39ac5f8379c5f3f53d8a1f6f4c2fec Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 16:19:01 +0700 Subject: [PATCH 35/73] modif: penyesuaian response article --- .../data/remote/response/ArticleResultResponse.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt index 98fd000..6bb5a47 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt @@ -3,12 +3,12 @@ package com.capstone.techwasmark02.data.remote.response import com.google.gson.annotations.SerializedName data class ArticleResultResponse( - val componentList: List, + val componentList: List, val error: String?, val message: String?, ) -data class ComponentListItem( +data class ArticleList( @SerializedName("componentId") val componentId: Int?, @SerializedName("articleImageURL") From ce028fbc1b942ade1e5b1cec82eaa3ee71d3912c Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 16:19:30 +0700 Subject: [PATCH 36/73] modif: menambah method fetch article --- .../repository/TechwasArticleRepository.kt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt index c229b48..6023051 100644 --- a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt @@ -2,6 +2,7 @@ package com.capstone.techwasmark02.repository import com.capstone.techwasmark02.data.remote.apiService.TechwasArticleApi import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.data.remote.response.SingleArticleResponse import com.capstone.techwasmark02.ui.common.UiState import javax.inject.Inject @@ -16,4 +17,22 @@ class TechwasArticleRepository @Inject constructor( } return UiState.Success(data = response, message = "Success to fetch article") } + + suspend fun getArticleById(id: Int): UiState { + val response = try { + articleApi.getArticleById(id) + } catch (e: Exception) { + return UiState.Error(message = "fail to fetch article, ${e.message}") + } + return UiState.Success(data = response, message = "Success to fetch article") + } + + suspend fun getArticleByName(name: String): UiState { + val response = try { + articleApi.getArticleByName(name) + } catch (e: Exception) { + return UiState.Error(message = "fail to fetch article, ${e.message}") + } + return UiState.Success(data = response, message = "Success to fetch article") + } } \ No newline at end of file From 6198c2d4e978a73ff2fce332d22c22acc0f7c5ae Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 16:19:49 +0700 Subject: [PATCH 37/73] modif: adjust size --- .../com/capstone/techwasmark02/ui/component/ArticleCard.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt index 926ba9a..cb4ece7 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt @@ -2,6 +2,7 @@ package com.capstone.techwasmark02.ui.component import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -162,7 +163,7 @@ fun ArticleCardPreview() { modifier = Modifier.width(150.dp), imgUrl = "", title = "judul satu", - description = "deskripsi ajah" + description = "deskripsi ajah", ) } } From eebe9251dcf1af65a6ba2f29cd0c22d5cec5e0d9 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 16:20:16 +0700 Subject: [PATCH 38/73] modif: menambah id --- .../techwasmark02/ui/componentType/ArticleFilterType.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/ArticleFilterType.kt b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/ArticleFilterType.kt index d7e9baf..5e5cb73 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/ArticleFilterType.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/ArticleFilterType.kt @@ -1,11 +1,11 @@ package com.capstone.techwasmark02.ui.componentType -sealed class ArticleFilterType(val type: String) { +sealed class ArticleFilterType(val type: String, val id: Int) { - object General: ArticleFilterType(type = "General") + object General: ArticleFilterType(type = "General", id = 0) - object Laptop: ArticleFilterType(type = "Laptop") + object Laptop: ArticleFilterType(type = "Laptop", id = 1) - object Battery: ArticleFilterType(type = "Battery") + object Battery: ArticleFilterType(type = "Battery", id = 2) } \ No newline at end of file From cbc5d82cb5ee9242a94688a75f7aa56f3fe055bf Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 16:20:43 +0700 Subject: [PATCH 39/73] modif: implement search & filter --- .../ui/screen/article/ArticleScreen.kt | 50 ++++++++++++++----- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt index 696e728..5885b7c 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt @@ -1,16 +1,19 @@ package com.capstone.techwasmark02.ui.screen.article import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid @@ -53,7 +56,9 @@ fun ArticleScreen( val articleList by viewModel.articleList.collectAsState() ArticleContent( + viewModel = viewModel, articleList = articleList, + navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") }, navigateToHome = { navController.navigate(Screen.Home.route) }, navigateToArticle = { navController.navigate(Screen.Article.route) }, navigateToForum = { navController.navigate(Screen.Forum.route) }, @@ -63,7 +68,9 @@ fun ArticleScreen( @Composable fun ArticleContent( + viewModel: ArticleScreenViewModel, articleList: UiState?, + navigateToSingleArticle: (idArticle: Int) -> Unit, navigateToHome: () -> Unit, navigateToForum: () -> Unit, navigateToArticle: () -> Unit, @@ -80,12 +87,13 @@ fun ArticleContent( ArticleFilterType.Laptop ) - val scrollState = rememberScrollState() + var selectedFilter by remember { + mutableStateOf(filterTypeList.firstOrNull()) + } Column( modifier = Modifier .fillMaxSize() -// .verticalScroll(scrollState) .background(MaterialTheme.colorScheme.background) ) { @@ -114,20 +122,30 @@ fun ArticleContent( value = inputValue, onValueChange = { newValue -> inputValue = newValue - } + if(inputValue.isEmpty()) { + viewModel.getAllFilterArticle(selectedFilter?.id ?: 0) + } else { + viewModel.getArticleByName(inputValue, selectedFilter ?: ArticleFilterType.General) + } + }, ) Spacer(modifier = Modifier.height(16.dp)) LazyRow( horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalAlignment = Alignment.CenterVertically ) { items( items = filterTypeList, ) { item -> SelectableText( filterType = item, - selected = true + selected = item == selectedFilter, + modifier = Modifier.clickable(enabled = item != selectedFilter) { + selectedFilter = item + viewModel.getAllFilterArticle(item.id) + } ) } } @@ -152,7 +170,8 @@ fun ArticleContent( LazyVerticalGrid( modifier = Modifier .fillMaxWidth() - .height(600.dp), + .fillMaxHeight() + .padding(bottom = 20.dp), columns = GridCells.Fixed(2), contentPadding = PaddingValues(vertical = 8.dp), verticalArrangement = Arrangement.spacedBy(16.dp), @@ -160,9 +179,14 @@ fun ArticleContent( ) { items(componentListArticle) { item -> ArticleCardSmall( + modifier = Modifier + .width(150.dp) + .clickable { + item?.id?.let { navigateToSingleArticle(it) } + }, imgUrl = item?.articleImageURL, title = item?.name, - description = item?.desc + description = item?.desc, ) } } @@ -193,12 +217,12 @@ fun ArticleContent( @Composable fun ArticleScreenPreview() { TechwasMark02Theme { - ArticleContent( - articleList = UiState.Loading(), - navigateToHome = {}, - navigateToArticle = {}, - navigateToForum = {}, - navigateToProfile = {} - ) +// ArticleContent( +// articleList = UiState.Loading(), +// navigateToHome = {}, +// navigateToArticle = {}, +// navigateToForum = {}, +// navigateToProfile = {} +// ) } } From 31053c7bb2de5e2c60af6970276db68e712fd424 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 16:21:03 +0700 Subject: [PATCH 40/73] modif: menambah method fetch article --- .../screen/article/ArticleScreenViewModel.kt | 87 ++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt index 3e2a28a..638f37c 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt @@ -6,6 +6,7 @@ import com.capstone.techwasmark02.data.mappers.toUserSession import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.repository.TechwasArticleRepository import com.capstone.techwasmark02.ui.common.UiState +import com.capstone.techwasmark02.ui.componentType.ArticleFilterType import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -26,7 +27,7 @@ class ArticleScreenViewModel @Inject constructor( } } - private fun getAllArticle() { + fun getAllArticle() { _articleList.value = UiState.Loading() viewModelScope.launch { val result = articleRepository.getAllArticle() @@ -43,4 +44,88 @@ class ArticleScreenViewModel @Inject constructor( } } } + + fun getAllFilterArticle(id: Int) { + _articleList.value = UiState.Loading() + viewModelScope.launch { + val result = articleRepository.getAllArticle() + when(result) { + is UiState.Success -> { + if(id == 0) { + _articleList.value = result + } else { + val filteredArticles = result.data?.componentList?.filter { + it?.componentId == id + } + val filteredResult = ArticleResultResponse( + componentList = filteredArticles.orEmpty(), + error = result.message, + message = result.message + ) + _articleList.value = UiState.Success(filteredResult) + } + } + is UiState.Error -> { + _articleList.value = result + } + else -> { + // do nothing + } + } + } + } + +// fun getArticleByName(name: String) { +// _articleList.value = UiState.Loading() +// viewModelScope.launch { +// val result = articleRepository.getArticleByName(name) +// when(result) { +// is UiState.Success -> { +// _articleList.value = result +// } +// is UiState.Error -> { +// _articleList.value = result +// } +// else -> { +// // do nothing +// } +// } +// } +// } + + fun getArticleByName(name: String, filterType: ArticleFilterType) { + _articleList.value = UiState.Loading() + viewModelScope.launch { + if (name.isEmpty()) { // input kosong fetch article by filter + getAllFilterArticle(filterType.id) + } else { + val result = articleRepository.getAllArticle() + when(result) { + is UiState.Success -> { + val filteredArticles = if (filterType.id == 0) { // general + result.data?.componentList?.filter { + it?.name?.contains(name, ignoreCase = true) == true + } + } else { + result.data?.componentList?.filter { + it?.name?.contains(name, ignoreCase = true) == true && it.componentId == filterType.id + } + } + val filteredResult = ArticleResultResponse( + componentList = filteredArticles.orEmpty(), + error = result.message, + message = result.message + ) + _articleList.value = UiState.Success(filteredResult) + } + is UiState.Error -> { + _articleList.value = result + } + else -> { + // do nothing + } + } + } + } + } } \ No newline at end of file From d0e0e4616818ea4215c50e4eb152d5ee4746491b Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 16:21:29 +0700 Subject: [PATCH 41/73] modif: penyesuaian history forum --- .../techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt index eab5847..7aea6dc 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt @@ -175,6 +175,7 @@ fun ProfileUserContent( count = 10, ) { item -> ArticleCardSmall( + modifier = Modifier.width(150.dp), imgUrl = "https://picsum.photos/seed/${Random.nextInt()}/320/120", title = "Title Article $item", description = "description article $item" From 104f40e41c7746097a3e17e8e96063a2cff3ded9 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 16:21:53 +0700 Subject: [PATCH 42/73] modif: display detail article --- .../singleArticle/SingleArticleScreen.kt | 83 ++++++++++++------- 1 file changed, 55 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt index 66e7cee..194cdb5 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt @@ -24,6 +24,9 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -35,22 +38,48 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.viewModelScope +import androidx.navigation.NavController import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.data.remote.response.SingleArticleResponse +import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.DefaultButton import com.capstone.techwasmark02.ui.component.TransparentTopBar import com.capstone.techwasmark02.ui.theme.Mist97 import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import kotlinx.coroutines.launch import kotlin.random.Random @Composable -fun SingleArticleScreen() { - SingleArticleContent() +fun SingleArticleScreen( + idArticle: Int, + viewModel: SingleArticleScreenViewModel = hiltViewModel(), +) { + + LaunchedEffect(Unit) { + viewModel.viewModelScope.launch { + viewModel.getArticleById(idArticle) + } + } + + val articleResult by viewModel.articleResult.collectAsState() + + SingleArticleContent( + articleResult = articleResult, + ) } @OptIn(ExperimentalMaterial3Api::class) @Composable -fun SingleArticleContent() { +fun SingleArticleContent( + articleResult: UiState?, +) { + + val result = articleResult?.data?.article + Scaffold { innerPadding -> val scrollState = rememberScrollState() @@ -91,7 +120,7 @@ fun SingleArticleContent() { Image( modifier = Modifier.matchParentSize(), painter = rememberAsyncImagePainter( - model = "https://picsum.photos/seed/${Random.nextInt()}/320/300", + model = result?.get(0)?.articleImageURL, placeholder = painterResource(id = R.drawable.place_holder), ), contentScale = ContentScale.Crop, @@ -103,17 +132,21 @@ fun SingleArticleContent() { .padding(bottom = 10.dp, top = 10.dp) .padding(horizontal = 16.dp) ) { + result?.get(0)?.componentName?.let { + Text( + text = it, + style = MaterialTheme.typography.bodyMedium + ) + } + result?.get(0)?.name?.let { + Text( + text = it, + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold, + ) + } Text( - text = "Battery", - style = MaterialTheme.typography.bodyMedium - ) - Text( - text = "What you can do with used batteries.", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold, - ) - Text( - text = "Sumber: detik.com", + text = result?.get(0)?.id.toString(), style = MaterialTheme.typography.bodyMedium ) } @@ -151,19 +184,11 @@ fun SingleArticleContent() { .padding(bottom = 20.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - Text( - text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Vivamus nec feugiat quam, eu accumsan sapien. Integer " + - "auctor mauris sit amet fringilla commodo. Proin lorem " + - "lorem, sollicitudin sed volutpat a, pellentesque et odio. " + - "Suspendisse vitae libero et sem luctus hendrerit. Maecenas ut " + - "magna a odio laoreet tincidunt." + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Vivamus nec feugiat quam, eu accumsan sapien. Integer " + - "auctor mauris sit amet fringilla commodo. Proin lorem " + - "lorem, sollicitudin sed volutpat a, pellentesque et odio. " + - "Suspendisse vitae libero et sem luctus hendrerit. Maecenas ut " + - "magna a odio laoreet tincidunt.", - ) + result?.get(0)?.description?.let { + Text( + text = it, + ) + } Spacer(modifier = Modifier.height(36.dp)) @@ -199,6 +224,8 @@ fun SingleArticleContent() { @Composable fun SingleArticleScreenPreview() { TechwasMark02Theme { - SingleArticleScreen() + SingleArticleContent( + articleResult = UiState.Loading(), + ) } } \ No newline at end of file From 7d8c97c6c80ddd06ffed765cbb00aeaf74d51220 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 16:22:20 +0700 Subject: [PATCH 43/73] modif: membuat method untuk fetch single article --- .../SingleArticleScreenViewModel.kt | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt index 917c8e6..070c5c0 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt @@ -1,4 +1,40 @@ package com.capstone.techwasmark02.ui.screen.singleArticle -class SingleArticleScreenViewModel { +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.data.remote.response.SingleArticleResponse +import com.capstone.techwasmark02.repository.TechwasArticleRepository +import com.capstone.techwasmark02.ui.common.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class SingleArticleScreenViewModel @Inject constructor( + private val articleRepository: TechwasArticleRepository +): ViewModel() { + + private val _articleResult: MutableStateFlow?> = MutableStateFlow(null) + val articleResult = _articleResult.asStateFlow() + + fun getArticleById(id: Int) { + _articleResult.value = UiState.Loading() + viewModelScope.launch { + val result = articleRepository.getArticleById(id) + when(result) { + is UiState.Success -> { + _articleResult.value = result + } + is UiState.Error -> { + _articleResult.value = result + } + else -> { + // do nothing + } + } + } + } } \ No newline at end of file From 01df5db62ff2397aba7f4d3dae72c2521aa2d297 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 19:05:35 +0700 Subject: [PATCH 44/73] modif: menambah endpoint article by component id --- .../data/remote/apiService/TechwasArticleApi.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt index f862ead..9841caf 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt @@ -3,13 +3,21 @@ package com.capstone.techwasmark02.data.remote.apiService import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.SingleArticleResponse import retrofit2.http.GET +import retrofit2.http.Header import retrofit2.http.Path +import retrofit2.http.Query interface TechwasArticleApi { @GET("/allArticle") suspend fun getAllArticle(): ArticleResultResponse + @GET("/article/{id}") + suspend fun getArticleByComponentId( + @Header("Authorization") token: String, + @Query("compid") compid: Int + ): ArticleResultResponse + @GET("/article/id/{id}") suspend fun getArticleById( @Path("id") id: Int From e6d69b0cd9f14145c2674d54c59b94b8d09defc0 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 19:06:02 +0700 Subject: [PATCH 45/73] modif: mengubah nama list --- .../techwasmark02/data/remote/response/ArticleResultResponse.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt index 6bb5a47..cbd359b 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt @@ -3,7 +3,7 @@ package com.capstone.techwasmark02.data.remote.response import com.google.gson.annotations.SerializedName data class ArticleResultResponse( - val componentList: List, + val articleList: List, val error: String?, val message: String?, ) From b52b739e6ba0fb21db2af1b825d9250ff27368b8 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 19:06:27 +0700 Subject: [PATCH 46/73] modif: menambah method getArticleByComponentId --- .../techwasmark02/repository/TechwasArticleRepository.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt index 6023051..492e94e 100644 --- a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt @@ -35,4 +35,13 @@ class TechwasArticleRepository @Inject constructor( } return UiState.Success(data = response, message = "Success to fetch article") } + + suspend fun getArticleByComponentId(userToken: String, id: Int): UiState { + val response = try { + articleApi.getArticleByComponentId(token = userToken, compid = id) + } catch (e: Exception) { + return UiState.Error(message = "fail to fetch article, ${e.message}") + } + return UiState.Success(data = response, message = "Success to fetch article") + } } \ No newline at end of file From 6dd230247e86ee351da7e3108e868dd43237a728 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 19:06:52 +0700 Subject: [PATCH 47/73] modif: menambah type filter --- .../ui/componentType/ArticleFilterType.kt | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/ArticleFilterType.kt b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/ArticleFilterType.kt index 5e5cb73..adf78bc 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/ArticleFilterType.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/ArticleFilterType.kt @@ -4,8 +4,34 @@ sealed class ArticleFilterType(val type: String, val id: Int) { object General: ArticleFilterType(type = "General", id = 0) - object Laptop: ArticleFilterType(type = "Laptop", id = 1) + object Battery: ArticleFilterType(type = "Battery", id = 1) - object Battery: ArticleFilterType(type = "Battery", id = 2) + object Cable: ArticleFilterType(type = "Cable", id = 2) + + object CrtTv: ArticleFilterType(type = "CRT TV", id = 3) + + object EKettle: ArticleFilterType(type = "E-kettle", id = 4) + + object Refrigerator: ArticleFilterType(type = "Refrigerator", id = 5) + + object Keyboard: ArticleFilterType(type = "Keyboard", id = 6) + + object Laptop: ArticleFilterType(type = "Laptop", id = 7) + + object LightBulb: ArticleFilterType(type = "Light Bulb", id = 8) + + object Monitor: ArticleFilterType(type = "Monitor", id = 9) + + object Mouse: ArticleFilterType(type = "Mouse", id = 10) + + object PCB: ArticleFilterType(type = "PCB", id = 11) + + object Printer: ArticleFilterType(type = "Printer", id = 12) + + object RiceCooker: ArticleFilterType(type = "Rice Cooker", id = 13) + + object WashingMachine: ArticleFilterType(type = "Washing Machine", id = 14) + + object Phone: ArticleFilterType(type = "Phone", id = 15) } \ No newline at end of file From 16f39525a66999c8fbbd6d180febb35e3ae5c5ca Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 19:07:17 +0700 Subject: [PATCH 48/73] modif: penyesuaian articleList --- .../ui/screen/article/ArticleScreen.kt | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt index 5885b7c..9f48f48 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt @@ -84,7 +84,20 @@ fun ArticleContent( val filterTypeList = listOf( ArticleFilterType.General, ArticleFilterType.Battery, - ArticleFilterType.Laptop + ArticleFilterType.Cable, + ArticleFilterType.CrtTv, + ArticleFilterType.EKettle, + ArticleFilterType.Refrigerator, + ArticleFilterType.Keyboard, + ArticleFilterType.Laptop, + ArticleFilterType.LightBulb, + ArticleFilterType.Monitor, + ArticleFilterType.Mouse, + ArticleFilterType.PCB, + ArticleFilterType.Printer, + ArticleFilterType.RiceCooker, + ArticleFilterType.WashingMachine, + ArticleFilterType.Phone ) var selectedFilter by remember { @@ -165,8 +178,8 @@ fun ArticleContent( } } is UiState.Success -> { - val componentListArticle = articleList.data?.componentList - if(componentListArticle != null) { + val componentListArticle = articleList.data?.articleList + if(!componentListArticle.isNullOrEmpty()) { LazyVerticalGrid( modifier = Modifier .fillMaxWidth() @@ -190,6 +203,16 @@ fun ArticleContent( ) } } + } else { + Box( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.CenterHorizontally) + ) { + Text( + text = "Cari apa tuh kira-kira" + ) + } } } From da24d034fbc31ade76a68297eb6f93a53d6d348a Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Tue, 6 Jun 2023 19:07:43 +0700 Subject: [PATCH 49/73] modif: menambah method getArticleByComponentId --- .../screen/article/ArticleScreenViewModel.kt | 62 +++---------------- 1 file changed, 7 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt index 638f37c..a28e76d 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt @@ -23,47 +23,17 @@ class ArticleScreenViewModel @Inject constructor( init { viewModelScope.launch { - getAllArticle() + getAllFilterArticle(0) } } - fun getAllArticle() { - _articleList.value = UiState.Loading() - viewModelScope.launch { - val result = articleRepository.getAllArticle() - when(result) { - is UiState.Success -> { - _articleList.value = result - } - is UiState.Error -> { - _articleList.value = result - } - else -> { - // do nothing - } - } - } - } - fun getAllFilterArticle(id: Int) { _articleList.value = UiState.Loading() viewModelScope.launch { - val result = articleRepository.getAllArticle() + val result = articleRepository.getArticleByComponentId(userToken = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg2MDQ5NDcwLjc1NjgyMTR9.eJfMxHb3UsQu-kyzyzN_3PdV8OvvwTmD8vOyoTRENyQ'", id = id) when(result) { is UiState.Success -> { - if(id == 0) { - _articleList.value = result - } else { - val filteredArticles = result.data?.componentList?.filter { - it?.componentId == id - } - val filteredResult = ArticleResultResponse( - componentList = filteredArticles.orEmpty(), - error = result.message, - message = result.message - ) - _articleList.value = UiState.Success(filteredResult) - } + _articleList.value = result } is UiState.Error -> { _articleList.value = result @@ -75,44 +45,26 @@ class ArticleScreenViewModel @Inject constructor( } } -// fun getArticleByName(name: String) { -// _articleList.value = UiState.Loading() -// viewModelScope.launch { -// val result = articleRepository.getArticleByName(name) -// when(result) { -// is UiState.Success -> { -// _articleList.value = result -// } -// is UiState.Error -> { -// _articleList.value = result -// } -// else -> { -// // do nothing -// } -// } -// } -// } - fun getArticleByName(name: String, filterType: ArticleFilterType) { _articleList.value = UiState.Loading() viewModelScope.launch { if (name.isEmpty()) { // input kosong fetch article by filter getAllFilterArticle(filterType.id) } else { - val result = articleRepository.getAllArticle() + val result = articleRepository.getArticleByComponentId(userToken = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg2MDQ5NDcwLjc1NjgyMTR9.eJfMxHb3UsQu-kyzyzN_3PdV8OvvwTmD8vOyoTRENyQ'", id = filterType.id) when(result) { is UiState.Success -> { val filteredArticles = if (filterType.id == 0) { // general - result.data?.componentList?.filter { + result.data?.articleList?.filter { it?.name?.contains(name, ignoreCase = true) == true } } else { - result.data?.componentList?.filter { + result.data?.articleList?.filter { it?.name?.contains(name, ignoreCase = true) == true && it.componentId == filterType.id } } val filteredResult = ArticleResultResponse( - componentList = filteredArticles.orEmpty(), + articleList = filteredArticles.orEmpty(), error = result.message, message = result.message ) From 9a344f4308eee5a02e110ceb865f9f3908d4b33e Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Wed, 7 Jun 2023 14:13:05 +0700 Subject: [PATCH 50/73] Catalog card, catalog screen, components response in api, adding usable component --- .idea/deploymentTargetDropDown.xml | 4 +- .../remote/apiService/TechwasArticleApi.kt | 3 +- .../remote/apiService/TechwasComponentApi.kt | 6 + .../remote/response/ArticleResultResponse.kt | 6 + .../data/remote/response/ComponentResponse.kt | 14 + .../repository/TechwasArticleRepository.kt | 10 +- .../TechwasComponentApiRepository.kt | 14 +- .../techwasmark02/ui/component/ArticleCard.kt | 57 ++- .../techwasmark02/ui/component/BottomBar.kt | 55 ++- .../techwasmark02/ui/component/CatalogCard.kt | 11 +- .../ui/component/DetectionsResultBox.kt | 18 +- .../techwasmark02/ui/component/TopBar.kt | 24 +- .../component/UsableComponentBottomSheet.kt | 47 +- .../ui/component/UsableComponentItem.kt | 44 +- .../ui/screen/catalog/CatalogScreen.kt | 94 ++-- .../screen/catalog/CatalogScreenViewModel.kt | 9 + .../CatalogSingleComponentScreen.kt | 428 ++++++++++++------ .../CatalogSingleComponentScreenViewModel.kt | 31 +- .../detectionResult/DetectionResultScreen.kt | 261 ++++++++--- .../DetectionResultScreenViewModel.kt | 71 +++ .../ui/screen/home/HomeScreen.kt | 176 +++++-- .../ui/screen/home/HomeScreenViewModel.kt | 29 ++ 22 files changed, 1031 insertions(+), 381 deletions(-) create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreenViewModel.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreenViewModel.kt diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 3b32c9e..6394770 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -7,11 +7,11 @@ - + - + \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt index 9841caf..08f121e 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt @@ -1,5 +1,6 @@ package com.capstone.techwasmark02.data.remote.apiService +import com.capstone.techwasmark02.data.remote.response.AllArticleResultResponse import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.SingleArticleResponse import retrofit2.http.GET @@ -10,7 +11,7 @@ import retrofit2.http.Query interface TechwasArticleApi { @GET("/allArticle") - suspend fun getAllArticle(): ArticleResultResponse + suspend fun getAllArticle(): AllArticleResultResponse @GET("/article/{id}") suspend fun getArticleByComponentId( diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasComponentApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasComponentApi.kt index 73d98c6..ed07772 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasComponentApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasComponentApi.kt @@ -2,6 +2,7 @@ package com.capstone.techwasmark02.data.remote.apiService import com.capstone.techwasmark02.data.remote.response.ComponentResponse import com.capstone.techwasmark02.data.remote.response.ComponentsResponse +import com.capstone.techwasmark02.data.remote.response.UsableComponentsResponse import com.google.android.gms.common.internal.safeparcel.SafeParcelable.Param import retrofit2.http.GET import retrofit2.http.Header @@ -20,6 +21,11 @@ interface TechwasComponentApi { @Path("id") id: Int ) : ComponentResponse + @GET("smallparts/bycompid/{compid}") + suspend fun fetchUsableComponents( + @Path("compid") compid: Int + ) : UsableComponentsResponse + companion object { const val BASE_URL = "https://the-prophecy-fwd5gpydiq-uc.a.run.app/" } diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt index cbd359b..b7a4b03 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ArticleResultResponse.kt @@ -8,6 +8,12 @@ data class ArticleResultResponse( val message: String?, ) +data class AllArticleResultResponse( + val componentList: List, + val error: String?, + val message: String?, +) + data class ArticleList( @SerializedName("componentId") val componentId: Int?, diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ComponentResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ComponentResponse.kt index a9576c1..6363750 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ComponentResponse.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ComponentResponse.kt @@ -11,4 +11,18 @@ data class ComponentList( val example: String, val id: Int, val name: String +) + +data class UsableComponentsResponse( + val error: String, + val message: String, + val smallParts: List +) + +data class SmallPart( + val compID: Int, + val description: String, + val id: Int, + val imageURL: String, + val name: String ) \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt index 492e94e..76b98c9 100644 --- a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasArticleRepository.kt @@ -15,7 +15,13 @@ class TechwasArticleRepository @Inject constructor( } catch (e: Exception) { return UiState.Error(message = "fail to fetch article, ${e.message}") } - return UiState.Success(data = response, message = "Success to fetch article") + val articleResultResponse = ArticleResultResponse( + articleList = response.componentList, + error = response.error, + message = response.message + ) + + return UiState.Success(data = articleResultResponse, message = "Success to fetch article") } suspend fun getArticleById(id: Int): UiState { @@ -36,7 +42,7 @@ class TechwasArticleRepository @Inject constructor( return UiState.Success(data = response, message = "Success to fetch article") } - suspend fun getArticleByComponentId(userToken: String, id: Int): UiState { + suspend fun getArticleByComponentId(userToken: String = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg1ODcyMDkwLjMwNjU4ODJ9.cvaEjnnWe4Z3Hl-ImAIKyguTWeuntb6vOuwGCa1rr2w", id: Int): UiState { val response = try { articleApi.getArticleByComponentId(token = userToken, compid = id) } catch (e: Exception) { diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasComponentApiRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasComponentApiRepository.kt index b9b836b..f22ab12 100644 --- a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasComponentApiRepository.kt +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasComponentApiRepository.kt @@ -3,6 +3,7 @@ package com.capstone.techwasmark02.repository import com.capstone.techwasmark02.data.remote.apiService.TechwasComponentApi import com.capstone.techwasmark02.data.remote.response.ComponentResponse import com.capstone.techwasmark02.data.remote.response.ComponentsResponse +import com.capstone.techwasmark02.data.remote.response.UsableComponentsResponse import com.capstone.techwasmark02.ui.common.UiState import javax.inject.Inject @@ -10,7 +11,7 @@ class TechwasComponentApiRepository @Inject constructor( private val componentApi: TechwasComponentApi ) { - suspend fun fetchComponents(userToken: String = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg1ODcyMDkwLjMwNjU4ODJ9.cvaEjnnWe4Z3Hl-ImAIKyguTWeuntb6vOuwGCa1rr2w") : UiState { + suspend fun fetchComponents(userToken: String = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg1ODcyMDkwLjMwNjU4ODJ9.cvaEjnnWe4Z3Hl-ImAIKyguTWeuntb6vOuwGCa1rr2w") : UiState { val response = try { componentApi.fetchComponents(token = userToken) @@ -20,7 +21,7 @@ class TechwasComponentApiRepository @Inject constructor( return UiState.Success(data = response) } - suspend fun fetchComponentById(userToken: String = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg1ODcyMDkwLjMwNjU4ODJ9.cvaEjnnWe4Z3Hl-ImAIKyguTWeuntb6vOuwGCa1rr2w", componentId: Int) : UiState { + suspend fun fetchComponentById(userToken: String = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg1ODcyMDkwLjMwNjU4ODJ9.cvaEjnnWe4Z3Hl-ImAIKyguTWeuntb6vOuwGCa1rr2w", componentId: Int) : UiState { val response = try { componentApi.fetchComponentById(token = userToken, id = componentId) @@ -30,4 +31,13 @@ class TechwasComponentApiRepository @Inject constructor( return UiState.Success(data = response) } + suspend fun fetchUsableComponents(compId: Int): UiState { + val response = try { + componentApi.fetchUsableComponents(compid = compId) + } catch (e: Exception) { + return UiState.Error(message = e.message ?: "Fail to fetch usable components") + } + return UiState.Success(data = response) + } + } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt index cb4ece7..cfa957c 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt @@ -19,19 +19,23 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.remote.response.ArticleList import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import kotlin.random.Random @Composable fun ArticleCardBig( - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + article: ArticleList ) { ElevatedCard( modifier = modifier @@ -50,16 +54,14 @@ fun ArticleCardBig( Box( modifier = Modifier .weight(1f) + .background(Color.LightGray) ) { - Image( - modifier = Modifier - .fillMaxSize(), - painter = rememberAsyncImagePainter( - model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", - placeholder = painterResource(id = R.drawable.place_holder), - ), + AsyncImage( + model = article.articleImageURL, + contentDescription = null, contentScale = ContentScale.Crop, - contentDescription = null + modifier = Modifier + .fillMaxSize() ) } @@ -69,18 +71,22 @@ fun ArticleCardBig( .height(64.dp), verticalArrangement = Arrangement.Center ) { - Text( - text = "Do not throw electronic waste carelessly", - style = MaterialTheme.typography.titleSmall, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - Text( - text = "Lorem ipsum dolor sit amet, consectetur...", - style = MaterialTheme.typography.bodySmall, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) + article.name?.let { + Text( + text = it, + style = MaterialTheme.typography.titleSmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + article.desc?.let { + Text( + text = it, + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } } } } @@ -157,7 +163,14 @@ fun ArticleCardPreview() { .padding(20.dp) ) { Column { - ArticleCardBig(modifier = Modifier.width(240.dp)) + ArticleCardBig(modifier = Modifier.width(240.dp), article = ArticleList( + componentId = 2, + articleImageURL = null, + name = "Do not throw electronic was bg", + id = 2, + desc = "Lorem ipsum and the sum of the sum si sum for the sum" + ) + ) Spacer(modifier = Modifier.height(20.dp)) ArticleCardSmall( modifier = Modifier.width(150.dp), diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt index 4e78117..5dfed19 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt @@ -7,12 +7,15 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar import androidx.compose.material3.Text @@ -91,33 +94,37 @@ fun BottomBarItem( selectedType: BottomBarItemType, onClick: () -> Unit ) { - Column( + IconButton( + onClick = onClick, modifier = modifier - .width(44.dp) - .height(44.dp) - .clickable { onClick() }, - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceBetween + .size(44.dp) ) { - Icon( - painter = painterResource(id = bottomBarItemType.icon), - contentDescription = null, - tint = if (selectedType == bottomBarItemType) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.inverseOnSurface - } + Column( + modifier = Modifier + .fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceBetween + ) { + Icon( + painter = painterResource(id = bottomBarItemType.icon), + contentDescription = null, + tint = if (selectedType == bottomBarItemType) { + MaterialTheme.colorScheme.primary + } else { + MaterialTheme.colorScheme.inverseOnSurface + } - ) - Text( - text = bottomBarItemType.title, - style = MaterialTheme.typography.labelSmall, - color = if (selectedType == bottomBarItemType) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.inverseOnSurface - } - ) + ) + Text( + text = bottomBarItemType.title, + style = MaterialTheme.typography.labelSmall, + color = if (selectedType == bottomBarItemType) { + MaterialTheme.colorScheme.primary + } else { + MaterialTheme.colorScheme.inverseOnSurface + } + ) + } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/CatalogCard.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/CatalogCard.kt index 6aa362c..388ab58 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/CatalogCard.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/CatalogCard.kt @@ -22,6 +22,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource @@ -46,11 +47,11 @@ fun CatalogCard( modifier = modifier .width(300.dp) .height(100.dp) -// .shadow( -// elevation = 6.dp, -// shape = RoundedCornerShape(20.dp) -// ) - .clip(RoundedCornerShape(20.dp)) + .shadow( + elevation = 6.dp, + shape = RoundedCornerShape(20.dp) + ) +// .clip(RoundedCornerShape(20.dp)) ) { Image( painter = painterResource(id = R.drawable.img_bg_catalog_card), diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt index 21d5cf9..c562f00 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.ui.graphics.graphicsLayer @@ -42,16 +43,26 @@ import kotlin.math.absoluteValue @Composable fun DetectionsResultBox( modifier: Modifier = Modifier, - predictionList: List + predictionList: List, + updateSelectedPrediction: (Int) -> Unit ) { val pagerState = rememberPagerState() val coroutineScope = rememberCoroutineScope() + LaunchedEffect(pagerState) { + snapshotFlow { pagerState.currentPage }.collect { page -> + updateSelectedPrediction(page) + } + } + Box( modifier = modifier .fillMaxWidth() .height(120.dp) - .clip(MaterialTheme.shapes.large) + .shadow( + elevation = 6.dp, + shape = MaterialTheme.shapes.large + ) .background(MaterialTheme.colorScheme.tertiary) .padding(horizontal = 24.dp), contentAlignment = Alignment.Center @@ -227,7 +238,8 @@ fun DetectionsResultBoxPreview() { .padding(20.dp) ) { DetectionsResultBox( - predictionList = dummyDetectionResultList + predictionList = dummyDetectionResultList, + updateSelectedPrediction = {} ) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt index 1786e47..6c3f49c 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt @@ -34,7 +34,7 @@ fun InverseTopBar(onClickNavigationIcon: () -> Unit, modifier: Modifier = Modifi painter = painterResource(id = R.drawable.ic_arrow_back), contentDescription = null, tint = MaterialTheme.colorScheme.primary, - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) } }, @@ -59,21 +59,21 @@ fun DefaultTopBar(pageTitle: String = "", onClickNavigationIcon: () -> Unit, mod painter = painterResource(id = R.drawable.ic_arrow_back), contentDescription = null, tint = MaterialTheme.colorScheme.onPrimary, - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) } }, title = {}, actions = { - Text( - text = pageTitle, - color = MaterialTheme.colorScheme.onPrimary, - style = MaterialTheme.typography.labelLarge.copy( - fontWeight = FontWeight.Normal - ), - modifier = Modifier - .padding(end = 20.dp) - ) + Text( + text = pageTitle, + color = MaterialTheme.colorScheme.onPrimary, + style = MaterialTheme.typography.labelLarge.copy( + fontWeight = FontWeight.Normal + ), + modifier = Modifier + .padding(end = 20.dp) + ) }, colors = TopAppBarDefaults.smallTopAppBarColors( containerColor = MaterialTheme.colorScheme.primary, @@ -94,7 +94,7 @@ fun TransparentTopBar(pageTitle: String = "", onClickNavigationIcon: () -> Unit, painter = painterResource(id = R.drawable.ic_arrow_back), contentDescription = null, tint = MaterialTheme.colorScheme.onPrimary, - modifier = Modifier.size(32.dp) + modifier = Modifier.size(24.dp) ) } }, diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentBottomSheet.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentBottomSheet.kt index 522a822..83e5876 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentBottomSheet.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentBottomSheet.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -15,12 +16,20 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage +import com.capstone.techwasmark02.data.remote.response.SmallPart import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @Composable -fun UsableComponentBottomSheet(modifier: Modifier = Modifier) { +fun UsableComponentBottomSheet( + modifier: Modifier = Modifier, + smallPart: SmallPart +) { Column( modifier = modifier .fillMaxWidth() @@ -34,24 +43,30 @@ fun UsableComponentBottomSheet(modifier: Modifier = Modifier) { .padding(horizontal = 20.dp) ) { Text( - text = "RAM", + text = smallPart.name, style = MaterialTheme.typography.labelLarge ) Text( - text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris tincidunt velit tortor, quis rutrum nunc viverra ac.", + text = smallPart.description, style = MaterialTheme.typography.bodySmall ) Spacer(modifier = Modifier.height(24.dp)) - } - LazyRow( - contentPadding = PaddingValues(horizontal = 20.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - items(4) { - ArticleCardBig(modifier = Modifier.width(150.dp)) + Box( + modifier = Modifier + .fillMaxSize() + .clip(MaterialTheme.shapes.large) + .background(Color.LightGray) + ) { + AsyncImage( + model = smallPart.imageURL, + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .fillMaxSize() + ) } } } @@ -68,7 +83,15 @@ fun UsableComponentBottomSheetPreview() { .background(MaterialTheme.colorScheme.primaryContainer) .padding(vertical = 20.dp) ) { - UsableComponentBottomSheet() + UsableComponentBottomSheet( + smallPart = SmallPart( + compID = 0, + description = "jkdfau adkjfaku aksdufka ufausd f", + id = 0, + imageURL = "", + name = "RAM" + ) + ) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentItem.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentItem.kt index 193c185..c3fb4eb 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentItem.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentItem.kt @@ -17,13 +17,17 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.remote.response.SmallPart import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import java.io.File import kotlin.random.Random @@ -31,26 +35,24 @@ import kotlin.random.Random @Composable fun UsableComponentItem( modifier: Modifier = Modifier, - file: File? = null, - onClick: () -> Unit + onClick: () -> Unit, + usableComponent: SmallPart ) { Row( modifier = modifier - .width(155.dp) + .width(152.dp) .height(60.dp) - .clip(MaterialTheme.shapes.large) + .shadow( + elevation = 6.dp, + shape = MaterialTheme.shapes.large + ) .background(MaterialTheme.colorScheme.tertiary) .clickable { onClick() } ) { -// if (file != null) { -// -// } - Image( - painter = rememberAsyncImagePainter( - model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", - placeholder = painterResource(id = R.drawable.place_holder) - ), + AsyncImage( + model = usableComponent.imageURL, contentDescription = null, + placeholder = painterResource(id = R.drawable.place_holder), contentScale = ContentScale.Crop, modifier = Modifier .width(55.dp) @@ -59,14 +61,17 @@ fun UsableComponentItem( Box( modifier = Modifier - .fillMaxSize(), + .fillMaxSize() + .padding(8.dp), contentAlignment = Alignment.Center ) { Text( - text = "RAM", - style = MaterialTheme.typography.labelMedium.copy( + text = usableComponent.name, + style = MaterialTheme.typography.labelLarge.copy( fontWeight = FontWeight.SemiBold ), + overflow = TextOverflow.Ellipsis, + maxLines = 1 ) } } @@ -84,7 +89,14 @@ fun UsableCompoenentItemPreview() { contentAlignment = Alignment.Center ) { UsableComponentItem( - onClick = {} + onClick = {}, + usableComponent = SmallPart( + compID = 3, + description = "", + id = 2, + imageURL = "", + name = "RAM" + ) ) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt index 8160ec6..ea5aebf 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt @@ -19,6 +19,9 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview @@ -41,17 +44,22 @@ fun CatalogScreen( navController: NavHostController ) { val componentsState by viewModel.componentState.collectAsState() + val searchBoxValue by viewModel.searchBoxValue.collectAsState() CatalogContent( componentsState = componentsState, - navigateToSingleComponent = { navController.navigate("${Screen.SingleCatalog.route}/$it") } + navigateToSingleComponent = { navController.navigate("${Screen.SingleCatalog.route}/$it") }, + searchBoxValue = searchBoxValue, + onSearchBoxValueChange = { viewModel.updateSearchBoxValue(it) } ) } @Composable fun CatalogContent( componentsState: UiState?, - navigateToSingleComponent: (component: String) -> Unit + navigateToSingleComponent: (component: String) -> Unit, + searchBoxValue: String, + onSearchBoxValueChange: (String) -> Unit ) { val moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) @@ -76,7 +84,7 @@ fun CatalogContent( Spacer(modifier = Modifier.height(10.dp)) - SearchBox(onValueChange = {}, value = "") + SearchBox(onValueChange = onSearchBoxValueChange, value = searchBoxValue) Spacer(modifier = Modifier.height(16.dp)) @@ -85,24 +93,37 @@ fun CatalogContent( is UiState.Success -> { val components = componentsState.data?.components + var filteredComponents by remember { + mutableStateOf(components) + } + + LaunchedEffect(key1 = searchBoxValue) { + if (components != null) { + filteredComponents = searchComponent( + componentList = components, + searchBoxValue = searchBoxValue + ) + } + } + LazyColumn( modifier = Modifier .fillMaxSize(), contentPadding = PaddingValues(bottom = 20.dp), verticalArrangement = Arrangement.spacedBy(12.dp) ) { - components?.size?.let { + filteredComponents?.size?.let { items( count = it, ) {index -> CatalogCard( - component = components[index], + component = filteredComponents!![index], modifier = Modifier .fillMaxWidth() .clickable { - val componentJson = Uri.encode(adapter.toJson(components[index])) - - navigateToSingleComponent(componentJson) + val componentJson = + Uri.encode(adapter.toJson(filteredComponents!![index])) + navigateToSingleComponent(componentJson) }, ) } @@ -126,57 +147,24 @@ fun CatalogContent( } } +private fun searchComponent(componentList: List, searchBoxValue: String) : List { + if (searchBoxValue == "") { + return componentList + } + return componentList.filter { component -> + component.name.contains(searchBoxValue, ignoreCase = true) + } +} + @Preview (showBackground = true) @Composable fun CatalogScreenPreview() { TechwasMark02Theme { CatalogContent( componentsState = UiState.Loading(), - navigateToSingleComponent = {} -// components = listOf( -// Component( -// desc = "A small portable personal computer that not very reliable and not very versatile.", -// id = 1, -// name = "Laptop", -// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" -// ), -// Component( -// desc = "A small portable personal computer that not very reliable and not very versatile.", -// id = 1, -// name = "Laptop", -// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" -// ), -// Component( -// desc = "A small portable personal computer that not very reliable and not very versatile.", -// id = 1, -// name = "Laptop", -// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" -// ), -// Component( -// desc = "A small portable personal computer that not very reliable and not very versatile.", -// id = 1, -// name = "Laptop", -// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" -// ), -// Component( -// desc = "A small portable personal computer that not very reliable and not very versatile.", -// id = 1, -// name = "Laptop", -// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" -// ), -// Component( -// desc = "A small portable personal computer that not very reliable and not very versatile.", -// id = 1, -// name = "Laptop", -// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" -// ), -// Component( -// desc = "A small portable personal computer that not very reliable and not very versatile.", -// id = 1, -// name = "Laptop", -// imageExample = "https://picsum.photos/seed/${Random.nextInt()}/320/120" -// ) -// ) + navigateToSingleComponent = {}, + searchBoxValue = "", + onSearchBoxValueChange = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreenViewModel.kt index 3ad0384..a61299b 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreenViewModel.kt @@ -22,7 +22,16 @@ class CatalogScreenViewModel @Inject constructor( private val _componentsState: MutableStateFlow?> = MutableStateFlow(null) val componentState = _componentsState.asStateFlow() + private val _searchBoxValue: MutableStateFlow = MutableStateFlow("") + val searchBoxValue = _searchBoxValue.asStateFlow() + + fun updateSearchBoxValue(newValue: String) { + _searchBoxValue.value = newValue + } + init { + _componentsState.value = UiState.Loading() + viewModelScope.launch { _componentsState.value = componentApiRepository.fetchComponents() } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt index 75aa5ed..f786e1c 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt @@ -1,6 +1,7 @@ package com.capstone.techwasmark02.ui.screen.catalogSingleComponent import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -17,6 +18,10 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.ModalBottomSheetLayout +import androidx.compose.material.ModalBottomSheetValue +import androidx.compose.material.rememberModalBottomSheetState import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme @@ -26,27 +31,38 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.blur import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import coil.compose.AsyncImage +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.Component import com.capstone.techwasmark02.data.remote.response.ComponentResponse import com.capstone.techwasmark02.data.remote.response.DetectionsResultResponse +import com.capstone.techwasmark02.data.remote.response.SmallPart +import com.capstone.techwasmark02.data.remote.response.UsableComponentsResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.ArticleCardBig import com.capstone.techwasmark02.ui.component.DefaultButton import com.capstone.techwasmark02.ui.component.DefaultTopBar import com.capstone.techwasmark02.ui.component.InverseButton +import com.capstone.techwasmark02.ui.component.UsableComponentBottomSheet import com.capstone.techwasmark02.ui.component.UsableComponentItem import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import kotlinx.coroutines.launch import kotlin.random.Random @Composable @@ -55,97 +71,142 @@ fun CatalogSingleComponentScreen( componentJson: String ) { - val componentState by viewModel.componentState.collectAsState() - val moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) .build() val adapter = moshi.adapter(Component::class.java) - val component = adapter.fromJson(componentJson) + val usableComponentsState by viewModel.usableComponentsState.collectAsState() + val usableComponentList by viewModel.usableComponentList.collectAsState() + val relatedArticleListState by viewModel.relatedArticleListState.collectAsState() + if (component != null) { - CatalogSingleComponentContent(component = component) + CatalogSingleComponentContent( + component = component, + usableComponentsState = usableComponentsState, + updateUsableComponentsState = { viewModel.updateUsableComponentsState(it) }, + usableComponentList = usableComponentList, + updateUsableComponentsList = { viewModel.updateUsableComponentList(it) }, + relatedArticleListState = relatedArticleListState, + updateRelatedArticleListState = { viewModel.updateRelatedArticleListState(it) } + ) } } -@OptIn(ExperimentalMaterial3Api::class) +@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class) @Composable fun CatalogSingleComponentContent( - component: Component + component: Component, + usableComponentsState: UiState?, + updateUsableComponentsState: (Int) -> Unit, + usableComponentList: List, + updateUsableComponentsList: (List) -> Unit, + relatedArticleListState: UiState?, + updateRelatedArticleListState: (Int) -> Unit ) { - Scaffold( - topBar = { - DefaultTopBar( - pageTitle = "Result", - onClickNavigationIcon = {} - ) + + val modalSheetState = rememberModalBottomSheetState( + initialValue = ModalBottomSheetValue.Hidden, + confirmValueChange = { it != ModalBottomSheetValue.HalfExpanded}, + skipHalfExpanded = false + ) + + val coroutineScope = rememberCoroutineScope() + + var currentlyClickedUsableComponent by remember { + mutableStateOf(0) + } + + LaunchedEffect(Unit) { + updateUsableComponentsState(component.id) + updateRelatedArticleListState(component.id) + } + + ModalBottomSheetLayout( + sheetState = modalSheetState, + sheetShape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp), + sheetContent = { + if (usableComponentList.isNotEmpty()) { + UsableComponentBottomSheet( + smallPart = usableComponentList[currentlyClickedUsableComponent] + ) + } } - ) { innerPadding -> - val scrollState = rememberScrollState() - - Column( - modifier = Modifier - .verticalScroll(scrollState) - .padding(innerPadding) - .padding(bottom = 20.dp) - ) { - Box( + ) { + Scaffold( + topBar = { + DefaultTopBar( + pageTitle = "Result", + onClickNavigationIcon = {} + ) + } + ) { innerPadding -> + val scrollState = rememberScrollState() + + Column( modifier = Modifier + .verticalScroll(scrollState) + .padding(innerPadding) + .padding(bottom = 20.dp) ) { Box( modifier = Modifier - .fillMaxWidth() - .height(440.dp) - .clip( - RoundedCornerShape( - bottomStart = 20.dp, - bottomEnd = 20.dp - ) - ) - .background(MaterialTheme.colorScheme.primary), ) { - AsyncImage( - model = component.imageExample, - contentDescription = null, - contentScale = ContentScale.Crop, - alpha = 0.8f, - modifier = Modifier - .fillMaxSize() - .blur(16.dp) - ) - AsyncImage( - model = component.imageExample, - contentDescription = null, - contentScale = ContentScale.Fit, + Box( modifier = Modifier - .fillMaxSize() - ) - } + .fillMaxWidth() + .height(440.dp) + .clip( + RoundedCornerShape( + bottomStart = 20.dp, + bottomEnd = 20.dp + ) + ) + .background(MaterialTheme.colorScheme.primary), + ) { + AsyncImage( + model = component.imageExample, + contentDescription = null, + contentScale = ContentScale.Crop, + alpha = 0.8f, + modifier = Modifier + .fillMaxSize() + .blur(16.dp) + ) + AsyncImage( + model = component.imageExample, + contentDescription = null, + contentScale = ContentScale.Fit, + modifier = Modifier + .fillMaxSize() + ) + } - Column( - modifier = Modifier - .fillMaxWidth() - .padding(top = 402.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Box( + Column( modifier = Modifier - .padding(horizontal = 20.dp) .fillMaxWidth() - .height(64.dp) - .clip(RoundedCornerShape(20.dp)) - .background(MaterialTheme.colorScheme.tertiary) - .padding(start = 20.dp), - contentAlignment = Alignment.CenterStart + .padding(top = 402.dp), + horizontalAlignment = Alignment.CenterHorizontally ) { - component?.name?.let { + Box( + modifier = Modifier + .padding(horizontal = 20.dp) + .fillMaxWidth() + .height(64.dp) + .shadow( + elevation = 8.dp, + shape = RoundedCornerShape(20.dp) + ) + .background(MaterialTheme.colorScheme.tertiary) + .padding(start = 20.dp), + contentAlignment = Alignment.CenterStart + ) { Text( - text = it, + text = component.name, style = MaterialTheme.typography.headlineSmall ) } - } // if (detectionsResultObj != null) { // DetectionsResultBox( @@ -155,97 +216,194 @@ fun CatalogSingleComponentContent( // ) // } + } } - } - Column( - modifier = Modifier - .padding(horizontal = 20.dp) - .padding(top = 20.dp) - ) { + Column( + modifier = Modifier + .padding(horizontal = 20.dp) + .padding(top = 20.dp) + ) { - component?.desc?.let { Text( - text = it, + text = component.desc, style = MaterialTheme.typography.bodyMedium ) - } - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(20.dp)) - Text( - text = "Usable Components", - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onBackground - ) + Text( + text = "Usable Components", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground + ) - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(8.dp)) - LazyVerticalGrid( - columns = GridCells.Fixed( - 2 - ), - horizontalArrangement = Arrangement.spacedBy(16.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - modifier = Modifier.height(132.dp) - ) { - items(3) { item -> - UsableComponentItem( - onClick = {} -// onClick = { -// isOnBackClick = false -// coroutineScope.launch { -// modalSheetState.show() -// } -// } - ) + if (usableComponentsState != null) { + when(usableComponentsState) { + is UiState.Success -> { + LazyVerticalGrid( + columns = GridCells.Fixed( + 2 + ), + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + modifier = Modifier + .height(144.dp), + ) { + usableComponentsState.data?.smallParts?.size?.let { + items(it) { index -> + currentlyClickedUsableComponent = index + updateUsableComponentsList(usableComponentsState.data.smallParts) + + UsableComponentItem( + onClick = { + coroutineScope.launch { + modalSheetState.show() + } + }, + usableComponent = usableComponentsState.data.smallParts[index] + ) + } + } + + } + } + is UiState.Error -> { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + Text( + text = "Fail to fetch usable component", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + is UiState.Loading -> { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + } } + + Spacer(modifier = Modifier.height(20.dp)) + + Text( + text = "Related Articles", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground + ) + + Spacer(modifier = Modifier.height(8.dp)) } - Spacer(modifier = Modifier.height(28.dp)) - Text( - text = "Related Articles", - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onBackground - ) + if (relatedArticleListState != null) { + when(relatedArticleListState) { + is UiState.Loading -> { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is UiState.Error -> { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + Text( + text = "Fail to fetch article", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + is UiState.Success -> { + val articleList = relatedArticleListState.data?.articleList - Spacer(modifier = Modifier.height(8.dp)) - } + if (articleList?.isNotEmpty() == true) { + LazyRow( + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier.fillMaxWidth() + ) { + relatedArticleListState.data.articleList.let { + if (it.isNotEmpty()) { + items( + count = it.size, + ) { index -> + articleList.get(index)?.let { it1 -> + ArticleCardBig( + modifier = Modifier + .width(150.dp), + article = it1 + ) + } + } + } + } + } + } else { + Box( + modifier = Modifier + .fillMaxWidth() + .height(100.dp), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) - Column( - modifier = Modifier - .fillMaxWidth() - ) { - LazyRow( - contentPadding = PaddingValues(horizontal = 16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - items( - count = 10, - ) { item -> - ArticleCardBig( - modifier = Modifier - .width(150.dp) - ) + ) { + Text( + text = "There's no related article", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + } + } } } - } - Spacer(modifier = Modifier.height(28.dp)) + Spacer(modifier = Modifier.height(28.dp)) - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 40.dp) - ) { - DefaultButton(contentText = "Drop Point", modifier = Modifier.fillMaxWidth()) + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 40.dp) + ) { + DefaultButton(contentText = "Drop Point", modifier = Modifier.fillMaxWidth()) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(20.dp)) - InverseButton(contentText = "Check Out Forum", modifier = Modifier.fillMaxWidth()) - } + InverseButton(contentText = "Check Out Forum", modifier = Modifier.fillMaxWidth()) + } + } } } } @@ -260,7 +418,13 @@ fun CatalogSingleComponentScreenPreview() { id = 2, imageExample = "", name = "Laptop" - ) + ), + usableComponentsState = UiState.Loading(), + updateUsableComponentsState = {}, + usableComponentList = emptyList(), + updateUsableComponentsList = {}, + relatedArticleListState = UiState.Loading(), + updateRelatedArticleListState = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreenViewModel.kt index 1d0b3b8..8d58241 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreenViewModel.kt @@ -3,8 +3,12 @@ package com.capstone.techwasmark02.ui.screen.catalogSingleComponent import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.capstone.techwasmark02.data.remote.apiService.TechwasComponentApi +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.Component import com.capstone.techwasmark02.data.remote.response.ComponentResponse +import com.capstone.techwasmark02.data.remote.response.SmallPart +import com.capstone.techwasmark02.data.remote.response.UsableComponentsResponse +import com.capstone.techwasmark02.repository.TechwasArticleRepository import com.capstone.techwasmark02.repository.TechwasComponentApiRepository import com.capstone.techwasmark02.ui.common.UiState import dagger.hilt.android.lifecycle.HiltViewModel @@ -15,17 +19,34 @@ import javax.inject.Inject @HiltViewModel class CatalogSingleComponentScreenViewModel @Inject constructor( - private val componentApiRepository: TechwasComponentApiRepository + private val componentApiRepository: TechwasComponentApiRepository, + private val articleRepository: TechwasArticleRepository ) : ViewModel() { - private val _componentState: MutableStateFlow> = MutableStateFlow(UiState.Loading()) - val componentState = _componentState.asStateFlow() + private val _usableComponentsState: MutableStateFlow?> = MutableStateFlow(null) + val usableComponentsState = _usableComponentsState.asStateFlow() + private val _usableComponentList: MutableStateFlow> = MutableStateFlow(emptyList()) + val usableComponentList = _usableComponentList.asStateFlow() + private val _relatedArticleListState: MutableStateFlow?> = MutableStateFlow(null) + val relatedArticleListState = _relatedArticleListState.asStateFlow() - suspend fun updateComponentState(componentId: Int) { + fun updateUsableComponentsState(compId: Int) { + _usableComponentsState.value = UiState.Loading() viewModelScope.launch { - _componentState.value = componentApiRepository.fetchComponentById(componentId = componentId) + _usableComponentsState.value = componentApiRepository.fetchUsableComponents(compId) + } + } + + fun updateUsableComponentList(newList: List) { + _usableComponentList.value = newList + } + + fun updateRelatedArticleListState(compId: Int) { + _relatedArticleListState.value = UiState.Loading() + viewModelScope.launch { + _relatedArticleListState.value = articleRepository.getArticleByComponentId(id = compId) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt index c3b8130..3ea1a06 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt @@ -3,6 +3,7 @@ package com.capstone.techwasmark02.ui.screen.detectionResult import android.net.Uri import androidx.activity.compose.BackHandler import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -24,6 +25,7 @@ import androidx.compose.material.ModalBottomSheetLayout import androidx.compose.material.ModalBottomSheetValue import androidx.compose.material.rememberModalBottomSheetState import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold @@ -41,8 +43,14 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel import coil.compose.AsyncImage +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.DetectionsResultResponse +import com.capstone.techwasmark02.data.remote.response.Prediction +import com.capstone.techwasmark02.data.remote.response.SmallPart +import com.capstone.techwasmark02.data.remote.response.UsableComponentsResponse +import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.ArticleCardBig import com.capstone.techwasmark02.ui.component.DefaultButton import com.capstone.techwasmark02.ui.component.DefaultTopBar @@ -60,11 +68,25 @@ import kotlinx.coroutines.launch @Composable fun DetectionResultScreen( stringUri: String, - detectionResult: String + detectionResult: String, + viewModel: DetectionResultScreenViewModel = hiltViewModel() ) { + + val selectedPrediction by viewModel.selectedPrediction.collectAsState() + val usableComponentsListState by viewModel.usableComponentsListState.collectAsState() + val currentlySelectedUsableComponentList by viewModel.currentlySelectedUsableComponentList.collectAsState() + val relatedArticleListState by viewModel.relatedArticleListState.collectAsState() + DetectionResultContent( stringUri = stringUri, - detectionResult = detectionResult + detectionResult = detectionResult, + selectedPrediction = selectedPrediction, + updateSelectedPrediction = { viewModel.updateSelectedPrediction(it) }, + usableComponentsListState = usableComponentsListState, + fetchAllUsableComponents = { viewModel.fetchAllUsableComponents(it) }, + currentlySelectedUsableComponentList = currentlySelectedUsableComponentList, + updateCurrentlySelectedUsableComponentList = { viewModel.updateCurrentlySelectedUsableComponentList(it) }, + relatedArticleListState = relatedArticleListState, ) } @@ -72,46 +94,51 @@ fun DetectionResultScreen( @Composable fun DetectionResultContent( stringUri: String, - detectionResult: String - + detectionResult: String, + selectedPrediction: Int, + updateSelectedPrediction: (Int) -> Unit, + usableComponentsListState: List>?, + fetchAllUsableComponents: (List) -> Unit, + currentlySelectedUsableComponentList: List, + updateCurrentlySelectedUsableComponentList: (List) -> Unit, + relatedArticleListState: List>?, ) { val coroutineScope = rememberCoroutineScope() val modalSheetState = rememberModalBottomSheetState( initialValue = ModalBottomSheetValue.Hidden, - confirmStateChange = { it != ModalBottomSheetValue.HalfExpanded}, - skipHalfExpanded = true + confirmValueChange = { it != ModalBottomSheetValue.HalfExpanded}, + skipHalfExpanded = false ) - var isOnBackClick by remember { - mutableStateOf(false) - } - val photoUri = Uri.parse(stringUri) val moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) .build() val adapter = moshi.adapter(DetectionsResultResponse::class.java) - val detectionsResultObj = adapter.fromJson(detectionResult) -// BackHandler(modalSheetState.isVisible) { -// coroutineScope.launch { modalSheetState.hide() } -// } -// -// BackHandler(!modalSheetState.isVisible) { -// isOnBackClick = true -// coroutineScope.launch { modalSheetState.show() } -// } + LaunchedEffect(Unit) { + val componentIdList = detectionsResultObj?.predictions + + if (componentIdList != null) { + fetchAllUsableComponents(componentIdList) + } + } + + var currentlyClickedUsableComponent by remember { + mutableStateOf(0) + } ModalBottomSheetLayout( sheetState = modalSheetState, sheetShape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp), sheetContent = { - if (isOnBackClick) { - DetectionsResultSaveBottomSheet() - } else { - UsableComponentBottomSheet() + if (currentlySelectedUsableComponentList.isNotEmpty()) { + val currentUsableComponents = currentlySelectedUsableComponentList[currentlyClickedUsableComponent] + UsableComponentBottomSheet( + smallPart = currentUsableComponents + ) } } ) { @@ -181,7 +208,8 @@ fun DetectionResultContent( DetectionsResultBox( modifier = Modifier .padding(horizontal = 20.dp), - predictionList = detectionsResultObj.predictions + predictionList = detectionsResultObj.predictions, + updateSelectedPrediction = updateSelectedPrediction ) } @@ -201,23 +229,70 @@ fun DetectionResultContent( Spacer(modifier = Modifier.height(8.dp)) - LazyVerticalGrid( - columns = GridCells.Fixed( - 2 - ), - horizontalArrangement = Arrangement.spacedBy(16.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - modifier = Modifier.height(132.dp) - ) { - items(3) { item -> - UsableComponentItem( - onClick = { - isOnBackClick = false - coroutineScope.launch { - modalSheetState.show() + if (usableComponentsListState != null) { + val currentlySelectedPrediction = usableComponentsListState[selectedPrediction] + when(currentlySelectedPrediction) { + is UiState.Loading -> { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is UiState.Success -> { + LazyVerticalGrid( + columns = GridCells.Fixed( + 2 + ), + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + modifier = Modifier.height(132.dp) + ) { + val usableComponentList = currentlySelectedPrediction.data?.smallParts + + usableComponentList?.size?.let { + items(it) {index -> + currentlyClickedUsableComponent = index + updateCurrentlySelectedUsableComponentList(usableComponentList) + + UsableComponentItem( + onClick = { + coroutineScope.launch { + modalSheetState.show() + } + }, + usableComponent = usableComponentList[index] + ) + } } } - ) + } + is UiState.Error -> { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + Text( + text = "Fail to fetch usable component", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + } + } else { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() } } @@ -232,23 +307,92 @@ fun DetectionResultContent( Spacer(modifier = Modifier.height(8.dp)) } - Column( - modifier = Modifier - .fillMaxWidth() - ) { - LazyRow( - contentPadding = PaddingValues(horizontal = 16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - items( - count = 10, - ) { item -> - ArticleCardBig( + if (relatedArticleListState != null) { + val currentSelectedArticleListState = relatedArticleListState[selectedPrediction] + when(currentSelectedArticleListState) { + is UiState.Loading -> { + Box( modifier = Modifier - .width(150.dp) - ) + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is UiState.Error -> { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + Text( + text = "Fail to fetch article", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + is UiState.Success -> { + val articleList = relatedArticleListState[selectedPrediction].data?.articleList + + if (articleList?.isNotEmpty() == true) { + LazyRow( + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier.fillMaxWidth() + ) { + relatedArticleListState[selectedPrediction].data?.articleList?.let { + items( + count = it.size, + ) { index -> + articleList[index]?.let { it1 -> + ArticleCardBig( + modifier = Modifier + .width(150.dp), + article = it1 + ) + } + } + } + } + } else { + Box( + modifier = Modifier + .fillMaxWidth() + .height(100.dp), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) + + ) { + Text( + text = "There's no related article", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + } } } + } else { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } } Spacer(modifier = Modifier.height(28.dp)) @@ -262,7 +406,7 @@ fun DetectionResultContent( Spacer(modifier = Modifier.height(20.dp)) - InverseButton(contentText = "Check Out Forum", modifier = Modifier.fillMaxWidth()) + InverseButton(contentText = "Go to Forum", modifier = Modifier.fillMaxWidth()) } } @@ -277,7 +421,14 @@ fun DetectionResultContentPreview() { TechwasMark02Theme { DetectionResultContent( stringUri = "", - detectionResult = "" + detectionResult = "", + selectedPrediction = 0, + updateSelectedPrediction = {}, + usableComponentsListState = emptyList(), + fetchAllUsableComponents = {}, + currentlySelectedUsableComponentList = emptyList(), + updateCurrentlySelectedUsableComponentList = {}, + relatedArticleListState = emptyList() ) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreenViewModel.kt new file mode 100644 index 0000000..e7060b7 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreenViewModel.kt @@ -0,0 +1,71 @@ +package com.capstone.techwasmark02.ui.screen.detectionResult + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.data.remote.response.Prediction +import com.capstone.techwasmark02.data.remote.response.SmallPart +import com.capstone.techwasmark02.data.remote.response.UsableComponentsResponse +import com.capstone.techwasmark02.repository.TechwasArticleRepository +import com.capstone.techwasmark02.repository.TechwasComponentApiRepository +import com.capstone.techwasmark02.ui.common.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class DetectionResultScreenViewModel @Inject constructor( + private val componentApiRepository: TechwasComponentApiRepository, + private val articleRepository: TechwasArticleRepository +) : ViewModel() { + + private val _usableComponentsListState: MutableStateFlow>?> = MutableStateFlow(null) + val usableComponentsListState = _usableComponentsListState.asStateFlow() + + private val _selectedPrediction: MutableStateFlow = MutableStateFlow(0) + val selectedPrediction = _selectedPrediction.asStateFlow() + + private val _currentlySelectedUsableComponentList: MutableStateFlow> = MutableStateFlow( + emptyList() + ) + val currentlySelectedUsableComponentList = _currentlySelectedUsableComponentList.asStateFlow() + + private val _relatedArticleListState: MutableStateFlow>?> = MutableStateFlow(null) + val relatedArticleListState = _relatedArticleListState.asStateFlow() + + fun fetchAllUsableComponents(componentIdList: List) { + viewModelScope.launch { + val usableComponentsList = mutableListOf>() + val articlesList = mutableListOf>() + componentIdList.forEach { prediction -> + + prediction.componentId.let { + val usableComponents = componentApiRepository.fetchUsableComponents(compId = it) + usableComponentsList.add(usableComponents) + + val relatedArticleList = articleRepository.getArticleByComponentId(id = it) + articlesList.add(relatedArticleList) + } + } + _usableComponentsListState.value = usableComponentsList + _relatedArticleListState.value = articlesList + } + } + + fun updateSelectedPrediction(currentlySelectedPrediction: Int) { + _selectedPrediction.value = currentlySelectedPrediction + } + + fun updateCurrentlySelectedUsableComponentList(newList: List) { + _currentlySelectedUsableComponentList.value = newList + } + +// fun updateRelatedArticleListState(compId: Int) { +// _relatedArticleListState.value = UiState.Loading() +// viewModelScope.launch { +// _relatedArticleListState.value = articleRepository.getArticleByComponentId(id = compId) +// } +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index f412bae..c8f47f5 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -1,9 +1,17 @@ package com.capstone.techwasmark02.ui.screen.home +import android.Manifest +import android.content.Context +import android.content.pm.PackageManager +import android.util.Log import android.widget.Space +import androidx.activity.compose.ManagedActivityResultLauncher +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -23,6 +31,7 @@ import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -30,18 +39,26 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.util.lerp +import androidx.core.content.ContextCompat +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.remote.response.ArticleList +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.AboutUsBox import com.capstone.techwasmark02.ui.component.ArticleCardBig import com.capstone.techwasmark02.ui.component.DefaultBottomBar @@ -55,8 +72,12 @@ import kotlin.math.absoluteValue @Composable fun HomeScreen( + viewModel: HomeScreenViewModel = hiltViewModel(), navController: NavHostController ) { + + val latestArticleState by viewModel.latestArticleState.collectAsState() + HomeContent( navigateToCamera = { navController.navigate(Camera.route) }, navigateToHome = { navController.navigate(Home.route) }, @@ -64,7 +85,8 @@ fun HomeScreen( navigateToForum = { navController.navigate(Forum.route) }, navigateToProfile = { navController.navigate(Profile.route) }, navigateToCatalog = { navController.navigate(Catalog.route) }, - navigateToMaps = { navController.navigate(Maps.route) } + navigateToMaps = { navController.navigate(Maps.route) }, + latestArticleState = latestArticleState ) } @@ -77,8 +99,22 @@ fun HomeContent( navigateToArticle: () -> Unit, navigateToProfile: () -> Unit, navigateToCatalog: () -> Unit, - navigateToMaps: () -> Unit + navigateToMaps: () -> Unit, + latestArticleState: UiState? ) { + + val context = LocalContext.current + + val cameraPermissionLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.RequestPermission(), + onResult = { granted -> + if(granted) { + navigateToCamera() + } + } + ) + + Scaffold( ) { innerPadding -> val scrollState = rememberScrollState() @@ -175,7 +211,16 @@ fun HomeContent( .fillMaxWidth(), ) { Spacer(modifier = Modifier.weight(1f)) - FeatureBox(featureBoxType = FeatureBoxType.Detection, onClick = navigateToCamera) + FeatureBox( + featureBoxType = FeatureBoxType.Detection, + onClick = { + checkAndRequestCameraPermission( + context = context, + cameraPermissionLauncher = cameraPermissionLauncher, + onAlreadyGranted = navigateToCamera + ) + } + ) Spacer(modifier = Modifier.weight(3f)) FeatureBox(featureBoxType = FeatureBoxType.Catalog, onClick = navigateToCatalog) Spacer(modifier = Modifier.weight(1f)) @@ -215,7 +260,11 @@ fun HomeContent( text = "See all", style = MaterialTheme.typography.labelMedium, fontWeight = FontWeight.Bold, - color = yellow + color = yellow, + modifier = Modifier + .clickable { + navigateToArticle() + } ) } } @@ -223,37 +272,71 @@ fun HomeContent( Spacer(modifier = Modifier.height(titlePaddingBottom)) val pagerState = rememberPagerState() - HorizontalPager( - pageCount = 10, - state = pagerState, - contentPadding = PaddingValues(horizontal = 56.dp), - modifier = Modifier.fillMaxWidth() - ) { page -> - ArticleCardBig( - modifier = Modifier - .width(280.dp) - .height(180.dp) - .graphicsLayer { - val pageOffset = ( - (pagerState.currentPage - page) + pagerState - .currentPageOffsetFraction - ).absoluteValue - - lerp( - start = 0.85f, - stop = 1f, - fraction = 1f - pageOffset.coerceIn(0f, 1f) - ).also { scale -> - scaleX = scale - scaleY = scale + + if (latestArticleState != null) { + when(latestArticleState) { + is UiState.Loading -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(100.dp), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is UiState.Error -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(100.dp), + contentAlignment = Alignment.Center + ) { + Text(text = "No article to view") + } + } + is UiState.Success -> { + latestArticleState.data?.articleList?.size?.let { + HorizontalPager( + pageCount = it, + state = pagerState, + contentPadding = PaddingValues(horizontal = 56.dp), + modifier = Modifier.fillMaxWidth().height(180.dp) + ) { page -> + val articleList = latestArticleState.data.articleList + + articleList[page]?.let { it1 -> + ArticleCardBig( + modifier = Modifier + .width(280.dp) + .height(180.dp) + .graphicsLayer { + val pageOffset = ( + (pagerState.currentPage - page) + pagerState + .currentPageOffsetFraction + ).absoluteValue + + lerp( + start = 0.85f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f) + ).also { scale -> + scaleX = scale + scaleY = scale + } + alpha = lerp( + start = 0.5f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f) + ) + }, + article = it1 + ) + } } - alpha = lerp( - start = 0.5f, - stop = 1f, - fraction = 1f - pageOffset.coerceIn(0f, 1f) - ) } - ) + } + } } Spacer(modifier = Modifier.height(titlePaddingTop)) @@ -293,7 +376,14 @@ fun HomeContent( ArticleCardBig( modifier = Modifier .width(320.dp) - .height(186.dp) + .height(186.dp), + article = ArticleList( + componentId = 2, + articleImageURL = null, + name = "Forum title", + id = 2, + desc = "Forum description" + ) ) } } @@ -317,6 +407,21 @@ fun HomeContent( } } +private fun checkAndRequestCameraPermission(context: Context, cameraPermissionLauncher: ManagedActivityResultLauncher, onAlreadyGranted: () -> Unit) { + when (PackageManager.PERMISSION_GRANTED) { + ContextCompat.checkSelfPermission( + context, + Manifest.permission.CAMERA + ) -> { + Log.d("Zhahrany", "Permission has already granted") + onAlreadyGranted() + } + else -> { + cameraPermissionLauncher.launch(Manifest.permission.CAMERA) + } + } +} + @Preview @Composable fun HomeContentPreview() { @@ -328,7 +433,8 @@ fun HomeContentPreview() { navigateToForum = {}, navigateToProfile = {}, navigateToCatalog = {}, - navigateToMaps = {} + navigateToMaps = {}, + latestArticleState = UiState.Loading() ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreenViewModel.kt new file mode 100644 index 0000000..506271d --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreenViewModel.kt @@ -0,0 +1,29 @@ +package com.capstone.techwasmark02.ui.screen.home + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.repository.TechwasArticleRepository +import com.capstone.techwasmark02.ui.common.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class HomeScreenViewModel @Inject constructor( + private val articleApiRepository: TechwasArticleRepository +): ViewModel() { + + private val _latestArticleState: MutableStateFlow?> = MutableStateFlow(null) + val latestArticleState = _latestArticleState.asStateFlow() + + init { + _latestArticleState.value = UiState.Loading() + viewModelScope.launch { + _latestArticleState.value = articleApiRepository.getAllArticle() + } + } + +} \ No newline at end of file From 49db01669c2647805bf5354dfd54dc0145879fc6 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 8 Jun 2023 18:19:11 +0700 Subject: [PATCH 51/73] modif: idk --- .idea/deploymentTargetDropDown.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 6394770..b59392a 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -1,17 +1,17 @@ - + - + - - + + - - + + \ No newline at end of file From c4ed6171dad1126ea11d09aae047014af73b64be Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 8 Jun 2023 18:19:31 +0700 Subject: [PATCH 52/73] modif: ubah padding --- .../techwasmark02/ui/component/SelectableText.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt index f66f402..40c8f6f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.capstone.techwasmark02.ui.componentType.ArticleFilterType @@ -38,19 +39,23 @@ fun SelectableText( ) { if(selected) { Text( + maxLines = 1, text = filterType.type, color = Color.White, style = MaterialTheme.typography.bodySmall, modifier = Modifier .clip(RoundedCornerShape(15.dp)) .background(MaterialTheme.colorScheme.primary) - .padding(horizontal = 11.dp, vertical = 6.dp) + .padding(8.dp), + overflow = TextOverflow.Ellipsis ) } else { Text( + maxLines = 1, text = filterType.type, color = MaterialTheme.colorScheme.onBackground, - style = MaterialTheme.typography.bodySmall + style = MaterialTheme.typography.bodySmall, + overflow = TextOverflow.Ellipsis ) } } From 3d30e7c79958e3a66c7fe47348fc1769ac4067eb Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 8 Jun 2023 18:19:55 +0700 Subject: [PATCH 53/73] modif: adjust SelectableText --- .../ui/screen/article/ArticleScreen.kt | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt index 9f48f48..2933887 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt @@ -1,6 +1,7 @@ package com.capstone.techwasmark02.ui.screen.article import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -13,6 +14,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredWidthIn import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.grid.GridCells @@ -20,8 +22,10 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -32,6 +36,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -146,18 +151,29 @@ fun ArticleContent( Spacer(modifier = Modifier.height(16.dp)) LazyRow( + modifier = Modifier.height(48.dp), horizontalArrangement = Arrangement.spacedBy(16.dp), verticalAlignment = Alignment.CenterVertically ) { items( items = filterTypeList, ) { item -> - SelectableText( - filterType = item, - selected = item == selectedFilter, - modifier = Modifier.clickable(enabled = item != selectedFilter) { + IconButton( + modifier = Modifier.requiredWidthIn(min = 60.dp), + onClick = { selectedFilter = item viewModel.getAllFilterArticle(item.id) + }, + enabled = item != selectedFilter, + content = { + SelectableText( + filterType = item, + selected = item == selectedFilter, +// modifier = Modifier.clickable(enabled = item != selectedFilter) { +// selectedFilter = item +// viewModel.getAllFilterArticle(item.id) +// } + ) } ) } @@ -207,11 +223,25 @@ fun ArticleContent( Box( modifier = Modifier .fillMaxWidth() - .align(Alignment.CenterHorizontally) + .height(100.dp), + contentAlignment = Alignment.Center ) { - Text( - text = "Cari apa tuh kira-kira" - ) + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) + + ) { + Text( + text = "There's no related article", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } } } From f90f5f6934e9bdb1c9f2edcb6c1d816e70ecde2e Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 8 Jun 2023 18:20:22 +0700 Subject: [PATCH 54/73] modif: menambah fetch all article --- .../ui/screen/article/ArticleScreenViewModel.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt index a28e76d..9ace97b 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt @@ -30,7 +30,11 @@ class ArticleScreenViewModel @Inject constructor( fun getAllFilterArticle(id: Int) { _articleList.value = UiState.Loading() viewModelScope.launch { - val result = articleRepository.getArticleByComponentId(userToken = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg2MDQ5NDcwLjc1NjgyMTR9.eJfMxHb3UsQu-kyzyzN_3PdV8OvvwTmD8vOyoTRENyQ'", id = id) + val result = if(id == 0) { + articleRepository.getAllArticle() + } else { + articleRepository.getArticleByComponentId(userToken = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg2MDQ5NDcwLjc1NjgyMTR9.eJfMxHb3UsQu-kyzyzN_3PdV8OvvwTmD8vOyoTRENyQ'", id = id) + } when(result) { is UiState.Success -> { _articleList.value = result @@ -51,7 +55,11 @@ class ArticleScreenViewModel @Inject constructor( if (name.isEmpty()) { // input kosong fetch article by filter getAllFilterArticle(filterType.id) } else { - val result = articleRepository.getArticleByComponentId(userToken = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg2MDQ5NDcwLjc1NjgyMTR9.eJfMxHb3UsQu-kyzyzN_3PdV8OvvwTmD8vOyoTRENyQ'", id = filterType.id) + val result = if(filterType.id == 0) { + articleRepository.getAllArticle() + } else { + articleRepository.getArticleByComponentId(userToken = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiJ1c2VyQGV4YW1wbGUuY29tIiwiZXhwaXJ5IjoxNjg2MDQ5NDcwLjc1NjgyMTR9.eJfMxHb3UsQu-kyzyzN_3PdV8OvvwTmD8vOyoTRENyQ'", id = filterType.id) + } when(result) { is UiState.Success -> { val filteredArticles = if (filterType.id == 0) { // general From 8af88df75d3c1365d2451faf01d217b47901aea6 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 8 Jun 2023 18:21:11 +0700 Subject: [PATCH 55/73] modif: menambah AlertDialog ketika pengguna diluar jangkauan --- .../ui/screen/maps/MapsScreen.kt | 61 +++++++++++++++++-- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt index f1b969d..4a3d072 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt @@ -2,8 +2,13 @@ package com.capstone.techwasmark02.ui.screen.maps import android.Manifest import android.content.pm.PackageManager +import android.location.Location import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -11,10 +16,8 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext -import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.navigation.NavHostController -import com.capstone.techwasmark02.R import com.google.android.gms.location.LocationServices import com.google.android.gms.maps.model.BitmapDescriptorFactory import com.google.android.gms.maps.model.CameraPosition @@ -116,21 +119,69 @@ fun MapsScreen(navController: NavHostController) { // posisi camera cameraPositionState = cameraPositionState, ) { + // cari marker dengan jarak terdekat + var closestMarker: MapMarkerInfo? = null + var closestDistance = Float.MAX_VALUE + userLatLng?.let { userLocation -> + for (marker in markerList) { + val distanceResults = FloatArray(1) + Location.distanceBetween(userLocation.latitude, userLocation.longitude, marker.position.latitude, marker.position.longitude, distanceResults) + val distance = distanceResults[0] + if (distance < closestDistance) { + closestDistance = distance + closestMarker = marker + } + } + } + + // kasih cat marker nya bg markerList.forEach { marker -> + val markerIcon = if (marker == closestMarker) { + BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN) + } else { + BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE) + } + Marker( state = MarkerState( - position = marker.position + position = marker.position, ), + icon = markerIcon, title = marker.title, snippet = marker.snippet ) } userLatLng?.let { latLng -> + val maxDistance = 5000f // jarak maksimum user ke lokasi terdekat (meter) + if (closestDistance > maxDistance) { + AlertDialog( + onDismissRequest = { }, + title = { + Text( + text = "oh no, your location is too far", + style = MaterialTheme.typography.labelLarge + ) }, + text = { + Text( + text = "you are too far from the drop point", + style = MaterialTheme.typography.bodyMedium + ) }, + confirmButton = { + Button( + onClick = { + navController.popBackStack() + } + ) { + Text("Back") + } + }, + ) + } + Marker( state = MarkerState(position = latLng), - title = "Lokasi User", - snippet = "Ini adalah lokasi anda saat ini" + title = "Your Location", ) } } From fce5552d7c6715ba1c62f73b396e76d340fb84d5 Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Thu, 8 Jun 2023 18:32:34 +0700 Subject: [PATCH 56/73] modif: change name dummy marker --- .../ui/screen/maps/MapsScreen.kt | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt index 4a3d072..22b812b 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt @@ -46,38 +46,38 @@ fun MapsScreen(navController: NavHostController) { val markerList = listOf( MapMarkerInfo( LatLng(-7.782589124314163, 110.38006889168956), - "Marker 1", - "Ini adalah marker 1" + "Drop Point SKE 1", + "throw your e-waste here" ), MapMarkerInfo( LatLng(-7.8041473764088085, 110.39441386554735), - "Marker 2", - "Ini adalah marker 2" + "Drop Point SKE 2", + "throw your e-waste here" ), MapMarkerInfo( LatLng(-7.790733483350418, 110.35766494375434), - "Marker 3", - "Ini adalah marker 3" + "Drop Point SKE 3", + "throw your e-waste here" ), MapMarkerInfo( LatLng(-7.767737238844195, 110.35476371308648), - "Marker 4", - "Ini adalah marker 4" + "Drop Point SKE 4", + "throw your e-waste here" ), MapMarkerInfo( LatLng(-7.774923700677788, 110.41182124955456), - "Marker 5", - "Ini adalah marker 5" + "Drop Point SKE 5", + "throw your e-waste here" ), MapMarkerInfo( LatLng(-7.7798743027989685, 110.33864576493167), - "Marker 6", - "Ini adalah marker 6" + "Drop Point SKE 6", + "throw your e-waste here" ), MapMarkerInfo( LatLng(-7.783068208639076, 110.3805524301342), - "Marker 7", - "Ini adalah marker 7" + "Drop Point SKE 7", + "throw your e-waste here" ) ) From f7e3e4cc844d490bd7116d46a2e7c484d61c24fa Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Mon, 12 Jun 2023 14:34:47 +0700 Subject: [PATCH 57/73] modif: adjust forum card, profile, setting --- .idea/deploymentTargetDropDown.xml | 17 -- .../com/capstone/techwasmark02/TechwasApp.kt | 5 + .../techwasmark02/ui/component/ForumBox.kt | 12 +- .../techwasmark02/ui/component/ProfileBox.kt | 24 +- .../techwasmark02/ui/component/SettingItem.kt | 90 +++++++ .../ui/componentType/SettingItemType.kt | 14 ++ .../techwasmark02/ui/navigation/Screen.kt | 5 +- .../screen/profileUser/ProfileUserScreen.kt | 57 +++-- .../ui/screen/setting/SettingScreen.kt | 225 ++++++++++++++++++ .../capstone/techwasmark02/ui/theme/Color.kt | 3 +- app/src/main/res/drawable/ic_camera_fill.xml | 6 + app/src/main/res/drawable/ic_chat_buble.xml | 5 + .../res/drawable/ic_fill_notification.xml | 5 + app/src/main/res/drawable/ic_settings.xml | 5 + app/src/main/res/drawable/ic_shield.xml | 5 + 15 files changed, 425 insertions(+), 53 deletions(-) delete mode 100644 .idea/deploymentTargetDropDown.xml create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/SettingItem.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/componentType/SettingItemType.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreen.kt create mode 100644 app/src/main/res/drawable/ic_camera_fill.xml create mode 100644 app/src/main/res/drawable/ic_chat_buble.xml create mode 100644 app/src/main/res/drawable/ic_fill_notification.xml create mode 100644 app/src/main/res/drawable/ic_settings.xml create mode 100644 app/src/main/res/drawable/ic_shield.xml diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml deleted file mode 100644 index b59392a..0000000 --- a/.idea/deploymentTargetDropDown.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt index 947bfc9..aa5a878 100644 --- a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt +++ b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt @@ -19,6 +19,7 @@ import com.capstone.techwasmark02.ui.screen.detectionResult.DetectionResultScree import com.capstone.techwasmark02.ui.screen.home.HomeScreen import com.capstone.techwasmark02.ui.screen.maps.MapsScreen import com.capstone.techwasmark02.ui.screen.profileUser.ProfileUserScreen +import com.capstone.techwasmark02.ui.screen.setting.SettingScreen import com.capstone.techwasmark02.ui.screen.singleArticle.SingleArticleScreen @OptIn(ExperimentalMaterial3Api::class) @@ -114,6 +115,10 @@ fun TechwasApp() { composable(Maps.route) { MapsScreen(navController = navController) } + + composable(Setting.route) { + SettingScreen(navController = navController) + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt index 69ec2d8..76d0f84 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -40,24 +41,27 @@ fun ForumBox( modifier = modifier .height(80.dp) .width(328.dp) - .clip(RoundedCornerShape(20.dp)) .shadow( elevation = 8.dp, shape = RoundedCornerShape(20.dp) ) .background(Color.White) + .clip(RoundedCornerShape(20.dp)) ) { Row( modifier .fillMaxSize() - .padding(start = 7.17.dp, end = 27.5.dp), + .padding(end = 27.5.dp), verticalAlignment = Alignment.CenterVertically ) { Image( modifier = Modifier .width(100.dp) - .height(60.dp) - .clip(RoundedCornerShape(20.dp)), + .fillMaxHeight() + .clip(RoundedCornerShape( + topStart= 20.dp, + bottomStart= 20.dp + )), painter = rememberAsyncImagePainter( model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", placeholder = painterResource(id = R.drawable.place_holder), diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt index dc33ddf..d936d85 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt @@ -1,6 +1,7 @@ package com.capstone.techwasmark02.ui.component import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -28,7 +29,10 @@ import com.capstone.techwasmark02.R import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @Composable -fun ProfileBox(modifier: Modifier = Modifier) { +fun ProfileBox( + modifier: Modifier = Modifier, + navigateToSetting: () -> Unit +) { Box( modifier = modifier .fillMaxWidth() @@ -58,21 +62,23 @@ fun ProfileBox(modifier: Modifier = Modifier) { } Spacer(modifier = Modifier.height(8.dp)) Row( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .clickable { navigateToSetting() }, horizontalArrangement = Arrangement.Start, verticalAlignment = Alignment.CenterVertically ) { Icon( modifier = Modifier.size(24.dp), - painter = painterResource(id = R.drawable.ic_logout), - contentDescription = "Logout", - tint = Color.Red + painter = painterResource(id = R.drawable.ic_settings), + contentDescription = "Settings", + tint = MaterialTheme.colorScheme.onTertiary ) Spacer(modifier = Modifier.width(8.dp)) Text( - text = "Logout", + text = "Settings", style = MaterialTheme.typography.labelMedium, - color = Color.Red + color = MaterialTheme.colorScheme.onTertiary ) } } @@ -84,7 +90,9 @@ fun ProfileBox(modifier: Modifier = Modifier) { fun ProfileBoxPreview() { TechwasMark02Theme { Box(modifier = Modifier.padding(20.dp)) { - ProfileBox() + ProfileBox( + navigateToSetting = {} + ) } } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SettingItem.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SettingItem.kt new file mode 100644 index 0000000..64bc530 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SettingItem.kt @@ -0,0 +1,90 @@ +package com.capstone.techwasmark02.ui.component + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AccountCircle +import androidx.compose.material.icons.filled.ArrowForward +import androidx.compose.material.icons.filled.KeyboardArrowRight +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.capstone.techwasmark02.ui.componentType.SettingItemType +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme + +@Composable +fun SettingItem( + modifier: Modifier = Modifier, + icon: Int, + title: String +) { + Box( + modifier = modifier + .fillMaxWidth() + .height(56.dp) + .shadow( + elevation = 4.dp, + shape = RoundedCornerShape(10.dp) + ) + .background(Color.White), + contentAlignment = Alignment.Center + ) { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + painter = painterResource(id = icon), + tint = MaterialTheme.colorScheme.onSurface, + contentDescription = title + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = title, + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onTertiary + ) + } + Icon( + imageVector = Icons.Default.KeyboardArrowRight, + tint = MaterialTheme.colorScheme.onSurface, + contentDescription = null + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun SettingItemPreview() { + TechwasMark02Theme { + Box(modifier = Modifier.padding(20.dp)) { + SettingItem( + modifier = Modifier.fillMaxWidth(), + icon = SettingItemType.Password.icon, + title = SettingItemType.Password.title + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/SettingItemType.kt b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/SettingItemType.kt new file mode 100644 index 0000000..53b32fd --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/SettingItemType.kt @@ -0,0 +1,14 @@ +package com.capstone.techwasmark02.ui.componentType + +import com.capstone.techwasmark02.R + +sealed class SettingItemType(val title: String, val icon: Int) { + + object Password: SettingItemType(title = "Password and security", icon = R.drawable.ic_shield) + + object Comment: SettingItemType(title = "Comments you’ve posted", icon = R.drawable.ic_chat_buble) + + object Notification: SettingItemType(title = "Push Notifications", icon = R.drawable.ic_fill_notification) + + object Language: SettingItemType(title = "Language Preference", icon = R.drawable.ic_language) +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt index 6137a7b..5489446 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt @@ -8,12 +8,9 @@ sealed class Screen(val route: String) { object Catalog: Screen(route = "catalog") object SingleCatalog: Screen(route = "singleCatalog") object DetectionResult: Screen(route = "detectionResult") - object Article: Screen(route = "article") - object SingleArticle: Screen(route = "singleArticle") - object Splash: Screen(route = "splash") - object Maps: Screen(route = "maps") + object Setting: Screen(route = "setting") } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt index 7aea6dc..fad59ba 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt @@ -20,9 +20,13 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -54,7 +58,8 @@ fun ProfileUserScreen( navigateToHome = { navController.navigate(Screen.Home.route) }, navigateToArticle = { navController.navigate(Screen.Article.route) }, navigateToForum = { navController.navigate(Screen.Forum.route) }, - navigateToProfile = { navController.navigate(Screen.Profile.route) } + navigateToProfile = { navController.navigate(Screen.Profile.route) }, + navigateToSetting = { navController.navigate(Screen.Setting.route) }, ) } @@ -64,14 +69,26 @@ fun ProfileUserContent( navigateToHome: () -> Unit, navigateToForum: () -> Unit, navigateToArticle: () -> Unit, - navigateToProfile: () -> Unit + navigateToProfile: () -> Unit, + navigateToSetting: () -> Unit, ) { Scaffold( topBar = { - DefaultTopBar( - pageTitle = "Profile", - onClickNavigationIcon = {} + TopAppBar( + colors = TopAppBarDefaults.smallTopAppBarColors( + containerColor = MaterialTheme.colorScheme.primary, + ), + title = {}, + actions = { + IconButton(onClick = { navigateToSetting() }) { + Icon( + painter = painterResource(id = R.drawable.ic_settings), + contentDescription = null, + tint = Color.White + ) + } + } ) }, bottomBar = { @@ -138,17 +155,18 @@ fun ProfileUserContent( } } - Column( - modifier = Modifier - .fillMaxWidth() - .padding(top = 200.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - ProfileBox( - modifier = Modifier - .padding(horizontal = 20.dp) - ) - } +// Column( +// modifier = Modifier +// .fillMaxWidth() +// .padding(top = 200.dp), +// horizontalAlignment = Alignment.CenterHorizontally +// ) { +// ProfileBox( +// modifier = Modifier +// .padding(horizontal = 20.dp), +// navigateToSetting = navigateToSetting +// ) +// } } Spacer(modifier = Modifier.height(16.dp)) @@ -156,7 +174,7 @@ fun ProfileUserContent( Column( modifier = Modifier .fillMaxWidth() - .height(600.dp) + .height(700.dp) ) { Text( text = "Bookmarks", @@ -201,7 +219,7 @@ fun ProfileUserContent( verticalArrangement = Arrangement.spacedBy(10.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - items(count = 5) { + items(count = 10) { ForumBox(modifier = Modifier.fillMaxWidth()) } } @@ -218,7 +236,8 @@ fun ProfileUserScreenPreview() { navigateToHome = {}, navigateToArticle = {}, navigateToForum = {}, - navigateToProfile = {} + navigateToProfile = {}, + navigateToSetting = {}, ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreen.kt new file mode 100644 index 0000000..b8ec8c5 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreen.kt @@ -0,0 +1,225 @@ +package com.capstone.techwasmark02.ui.screen.setting + +import androidx.compose.foundation.Image +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.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Edit +import androidx.compose.material.icons.filled.ShoppingCart +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.navigation.NavHostController +import coil.compose.rememberAsyncImagePainter +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.component.ArticleCardSmall +import com.capstone.techwasmark02.ui.component.DefaultTopBar +import com.capstone.techwasmark02.ui.component.ForumBox +import com.capstone.techwasmark02.ui.component.SettingItem +import com.capstone.techwasmark02.ui.componentType.SettingItemType +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import com.capstone.techwasmark02.ui.theme.red +import kotlin.random.Random + +@Composable +fun SettingScreen( + navController: NavHostController +) { + SettingContent( + navigateToProfile = { navController.popBackStack() } + ) +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SettingContent( + navigateToProfile: () -> Unit +) { + + val settingItemList = listOf( + SettingItemType.Password, + SettingItemType.Comment, + SettingItemType.Notification, + SettingItemType.Language + ) + + Scaffold( + topBar = { + DefaultTopBar( + pageTitle = "", + onClickNavigationIcon = { + navigateToProfile() + } + ) + } + ) { innerPadding -> + + val scrollState = rememberScrollState() + + Column( + modifier = Modifier + .padding(innerPadding) + .background(MaterialTheme.colorScheme.primary) + ) { + Box( + modifier = Modifier.fillMaxHeight() + ) { + Box( + modifier = Modifier + .fillMaxWidth() + + ) { + Column( + modifier = Modifier + .fillMaxSize() + .align(Alignment.TopCenter), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Box { + Image( + modifier = Modifier + .size(120.dp) + .clip(CircleShape), + painter = rememberAsyncImagePainter( + model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", + placeholder = painterResource(id = R.drawable.place_holder), + ), + contentScale = ContentScale.FillHeight, + contentDescription = null + ) + Box( + modifier = Modifier + .matchParentSize() + .clip(CircleShape) + .background(Color.Black.copy(alpha = 0.3f)) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_camera_fill), + contentDescription = "Camera", + tint = Color.White, + modifier = Modifier + .align(Alignment.Center) + .size(32.dp) + ) + } + } + + Spacer(modifier = Modifier.height(8.dp)) + + Row(verticalAlignment = Alignment.CenterVertically) { + Text( + text = "User Full Name", + style = MaterialTheme.typography.labelLarge, + color = Color.White + ) + Icon( + imageVector = Icons.Default.Edit, + contentDescription = "Edit", + tint = Color.White, + modifier = Modifier + .padding(start = 8.dp) + .size(24.dp) + ) + } + + Text( + text = "user@gmail.com", + style = MaterialTheme.typography.bodyMedium, + color = Color.White + ) + + Spacer(modifier = Modifier.height(40.dp)) + + Box(modifier = Modifier + .fillMaxSize() + ) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(10.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + SettingItem( + icon = settingItemList[0].icon, + title = settingItemList[0].title, + ) + + SettingItem( + icon = settingItemList[1].icon, + title = settingItemList[1].title, + ) + + SettingItem( + icon = settingItemList[2].icon, + title = settingItemList[2].title, + ) + + SettingItem( + icon = settingItemList[3].icon, + title = settingItemList[3].title, + ) + + Spacer(modifier = Modifier.height(10.dp)) + + Button( + onClick = { }, + modifier = Modifier + .width(122.dp) + .height(41.dp) + .align(Alignment.End), + colors = ButtonDefaults.buttonColors(containerColor = red), + shape = RoundedCornerShape(10.dp) + ) { + Text(text = "Log out") + } + } + } + } + } + } + } + } +} + +@Preview(showBackground = true) +@Composable +fun SettingScreenPreview() { + TechwasMark02Theme { + SettingContent( + navigateToProfile = {} + ) + } +} diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/theme/Color.kt b/app/src/main/java/com/capstone/techwasmark02/ui/theme/Color.kt index da53aec..a569a46 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/theme/Color.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/theme/Color.kt @@ -15,4 +15,5 @@ val purple = Color(0xff8385E4) val Yellow77 = Color(0xFFFFDF5D) val sakura = Color(0xFFF5A37B) val gray = Color(0xFFD9D9D9) -val yellow = Color(0xFFFEBC1F) \ No newline at end of file +val yellow = Color(0xFFFEBC1F) +val red = Color(0xFFCD230F) \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_camera_fill.xml b/app/src/main/res/drawable/ic_camera_fill.xml new file mode 100644 index 0000000..43a4fd5 --- /dev/null +++ b/app/src/main/res/drawable/ic_camera_fill.xml @@ -0,0 +1,6 @@ + + + + diff --git a/app/src/main/res/drawable/ic_chat_buble.xml b/app/src/main/res/drawable/ic_chat_buble.xml new file mode 100644 index 0000000..3cf25bb --- /dev/null +++ b/app/src/main/res/drawable/ic_chat_buble.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_fill_notification.xml b/app/src/main/res/drawable/ic_fill_notification.xml new file mode 100644 index 0000000..1d038a4 --- /dev/null +++ b/app/src/main/res/drawable/ic_fill_notification.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml new file mode 100644 index 0000000..298a5a1 --- /dev/null +++ b/app/src/main/res/drawable/ic_settings.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_shield.xml b/app/src/main/res/drawable/ic_shield.xml new file mode 100644 index 0000000..e49a1f2 --- /dev/null +++ b/app/src/main/res/drawable/ic_shield.xml @@ -0,0 +1,5 @@ + + + From 335f36e2381a86ba632c794ee71dd1c5c30594dc Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Mon, 12 Jun 2023 23:05:56 +0700 Subject: [PATCH 58/73] change splashscreen --- .../ui/screen/splashScreen/SplashScreen.kt | 64 +++++++++++++------ 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt index 79fd81b..9b6e8d6 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt @@ -1,32 +1,33 @@ package com.capstone.techwasmark02.ui.screen.splashScreen -import android.window.SplashScreen import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.runtime.* -import androidx.compose.ui.draw.alpha import com.capstone.techwasmark02.R import com.capstone.techwasmark02.ui.theme.Green77 import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @@ -59,19 +60,46 @@ fun SplashScreen() { fun SplashContent(alpha: Float) { Box( modifier = Modifier - .background( - Green77 - ) - .fillMaxSize(), + .fillMaxSize() + .alpha(alpha) + .background(color = Green77), contentAlignment = Alignment.Center ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Image( + painter = painterResource(id = R.drawable.logo_techwaste), + contentDescription = null, + modifier = Modifier + .width(57.27.dp) + .height(63.9.dp) + ) + Text( + text = "Techwaste", + style = MaterialTheme.typography.headlineLarge, + fontWeight = FontWeight.Bold, + color = Color.White, + modifier = Modifier + .padding(start = 5.24.dp) + ) + } + } - Image( - painter = painterResource(id = R.drawable.logo_techwase), - contentDescription = "logo techwaste", + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.BottomCenter + ) { + Text( + text = "Copyright © 2023", + color= Color.White, + style = MaterialTheme.typography.labelMedium, modifier = Modifier - .size(100.dp) - .alpha(alpha) + .padding(bottom = 32.dp) ) } } From 6e8d8c44915cc4f902da1046239def5e8f3f82c6 Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Tue, 13 Jun 2023 08:43:00 +0700 Subject: [PATCH 59/73] onboarding, connecting navigation, transition --- .idea/deploymentTargetDropDown.xml | 17 + app/build.gradle | 4 + .../capstone/techwasmark02/MainActivity.kt | 1 - .../com/capstone/techwasmark02/TechwasApp.kt | 90 ++- .../remote/apiService/TechwasArticleApi.kt | 2 +- .../remote/apiService/TechwasComponentApi.kt | 3 +- .../remote/apiService/TechwasPredictionApi.kt | 2 +- .../data/remote/apiService/TechwasUserApi.kt | 2 +- .../response/DetectionResultResponse.kt | 42 +- .../techwasmark02/ui/component/ArticleCard.kt | 30 +- .../techwasmark02/ui/component/Banner.kt | 146 +++- .../techwasmark02/ui/component/BottomBar.kt | 163 ++-- .../techwasmark02/ui/component/Button.kt | 12 +- .../techwasmark02/ui/component/CameraView.kt | 3 +- .../techwasmark02/ui/component/CatalogCard.kt | 31 +- .../techwasmark02/ui/component/DetectBox.kt | 72 ++ .../ui/component/DetectionsResultBox.kt | 5 - .../techwasmark02/ui/component/HtmlText.kt | 69 ++ .../ui/component/MainTextField.kt | 218 +++-- .../techwasmark02/ui/component/SearchBox.kt | 4 - .../techwasmark02/ui/component/TopBar.kt | 5 + .../component/UsableComponentBottomSheet.kt | 4 - .../ui/component/UsableComponentItem.kt | 5 - .../ui/componentType/BottomBarItemType.kt | 10 +- .../ui/componentType/FeatureBoxType.kt | 2 +- .../techwasmark02/ui/navigation/Screen.kt | 258 +++++- .../ui/screen/article/ArticleScreen.kt | 20 - .../screen/catalog/CatalogScreenViewModel.kt | 3 - .../CatalogSingleComponentScreen.kt | 233 +++--- .../detectionResult/DetectionResultScreen.kt | 569 +++++++++----- .../ui/screen/forum/ForumScreen.kt | 22 + .../ui/screen/home/HomeScreen.kt | 106 ++- .../imageDetection/ImageDetectionScreen.kt | 1 - .../ui/screen/main/MainScreen.kt | 71 ++ .../ui/screen/main/MainScreenViewModel.kt | 19 + .../ui/screen/onBoarding/OnBoardingScreen.kt | 743 ++++++++++++++++++ .../screen/profileUser/ProfileUserScreen.kt | 21 - .../ui/screen/signIn/SignInScreen.kt | 58 +- .../ui/screen/signIn/SignInScreenViewModel.kt | 35 +- .../ui/screen/signUp/SignUpScreen.kt | 220 +++--- .../ui/screen/signUp/SignUpScreenViewModel.kt | 16 +- .../ui/screen/splashScreen/SplashScreen.kt | 25 +- .../splashScreen/SplashScreenViewModel.kt | 41 + .../capstone/techwasmark02/ui/theme/Theme.kt | 3 +- .../capstone/techwasmark02/ui/theme/Type.kt | 7 + .../techwasmark02/utils/html/FromHtml.kt | 43 + .../utils/html/TypeFaceSpanCompat.kt | 29 + app/src/main/res/drawable/forum_box.webp | Bin 0 -> 1374 bytes app/src/main/res/drawable/ic_arrow_left.xml | 5 + app/src/main/res/drawable/ic_arrow_right.xml | 5 + app/src/main/res/drawable/ic_sell.xml | 5 + .../main/res/drawable/ic_trash_outline.xml | 5 + .../main/res/drawable/img_bg_green_large.webp | Bin 0 -> 5266 bytes app/src/main/res/drawable/img_bg_signup.webp | Bin 0 -> 2874 bytes app/src/main/res/drawable/img_bg_singin.webp | Bin 0 -> 5894 bytes .../res/drawable/img_feature_article_box.webp | Bin 0 -> 614 bytes .../img_feature_article_illustration.webp | Bin 0 -> 3462 bytes .../res/drawable/img_feature_detect_box.webp | Bin 0 -> 562 bytes .../drawable/img_feature_detect_frame.webp | Bin 0 -> 650 bytes .../img_feature_detect_illustration.webp | Bin 0 -> 6446 bytes .../res/drawable/img_feature_forum_box.webp | Bin 0 -> 1374 bytes .../img_feature_forum_illustration.webp | Bin 0 -> 5728 bytes .../res/drawable/img_logo_onboarding.webp | Bin 0 -> 15012 bytes .../img_logo_onboarding_nooutline.webp | Bin 0 -> 5664 bytes .../img_logo_onboarding_nooutline_green.webp | Bin 0 -> 6360 bytes .../img_onboarding_ripple_peach_left.webp | Bin 0 -> 19558 bytes .../img_onboarding_ripple_peach_right.webp | Bin 0 -> 19914 bytes .../img_onboarding_ripple_purple_left.webp | Bin 0 -> 2510 bytes .../img_onboarding_ripple_purple_right.webp | Bin 0 -> 2526 bytes 69 files changed, 2640 insertions(+), 865 deletions(-) create mode 100644 .idea/deploymentTargetDropDown.xml create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/component/HtmlText.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreen.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreenViewModel.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreenViewModel.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/utils/html/FromHtml.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/utils/html/TypeFaceSpanCompat.kt create mode 100644 app/src/main/res/drawable/forum_box.webp create mode 100644 app/src/main/res/drawable/ic_arrow_left.xml create mode 100644 app/src/main/res/drawable/ic_arrow_right.xml create mode 100644 app/src/main/res/drawable/ic_sell.xml create mode 100644 app/src/main/res/drawable/ic_trash_outline.xml create mode 100644 app/src/main/res/drawable/img_bg_green_large.webp create mode 100644 app/src/main/res/drawable/img_bg_signup.webp create mode 100644 app/src/main/res/drawable/img_bg_singin.webp create mode 100644 app/src/main/res/drawable/img_feature_article_box.webp create mode 100644 app/src/main/res/drawable/img_feature_article_illustration.webp create mode 100644 app/src/main/res/drawable/img_feature_detect_box.webp create mode 100644 app/src/main/res/drawable/img_feature_detect_frame.webp create mode 100644 app/src/main/res/drawable/img_feature_detect_illustration.webp create mode 100644 app/src/main/res/drawable/img_feature_forum_box.webp create mode 100644 app/src/main/res/drawable/img_feature_forum_illustration.webp create mode 100644 app/src/main/res/drawable/img_logo_onboarding.webp create mode 100644 app/src/main/res/drawable/img_logo_onboarding_nooutline.webp create mode 100644 app/src/main/res/drawable/img_logo_onboarding_nooutline_green.webp create mode 100644 app/src/main/res/drawable/img_onboarding_ripple_peach_left.webp create mode 100644 app/src/main/res/drawable/img_onboarding_ripple_peach_right.webp create mode 100644 app/src/main/res/drawable/img_onboarding_ripple_purple_left.webp create mode 100644 app/src/main/res/drawable/img_onboarding_ripple_purple_right.webp diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..c6ba9c3 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index e3da66c..8af9832 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,6 +66,10 @@ dependencies { implementation 'androidx.navigation:navigation-compose:2.5.3' implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1' implementation 'androidx.compose.foundation:foundation:1.4.3' + implementation 'com.google.accompanist:accompanist-navigation-animation:0.30.0' + implementation 'androidx.compose.animation:animation-graphics:1.4.3' + implementation 'androidx.compose.animation:animation:1.4.3' + implementation 'androidx.compose.animation:animation-core:1.4.3' //lifecycle implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1' diff --git a/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt b/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt index 570544a..deb2e82 100644 --- a/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt +++ b/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt @@ -27,7 +27,6 @@ class MainActivity : ComponentActivity() { ) { TechwasApp() // CatalogScreen() - } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt index aa5a878..1a43a28 100644 --- a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt +++ b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt @@ -1,14 +1,15 @@ package com.capstone.techwasmark02 +import androidx.activity.compose.BackHandler +import androidx.compose.animation.AnimatedContentScope +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.core.tween import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.navigation.NavType -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.capstone.techwasmark02.ui.navigation.Screen.* import com.capstone.techwasmark02.ui.screen.article.ArticleScreen @@ -17,28 +18,79 @@ import com.capstone.techwasmark02.ui.screen.catalog.CatalogScreen import com.capstone.techwasmark02.ui.screen.catalogSingleComponent.CatalogSingleComponentScreen import com.capstone.techwasmark02.ui.screen.detectionResult.DetectionResultScreen import com.capstone.techwasmark02.ui.screen.home.HomeScreen +import com.capstone.techwasmark02.ui.screen.main.MainScreen import com.capstone.techwasmark02.ui.screen.maps.MapsScreen +import com.capstone.techwasmark02.ui.screen.onBoarding.OnBoardingScreen import com.capstone.techwasmark02.ui.screen.profileUser.ProfileUserScreen -import com.capstone.techwasmark02.ui.screen.setting.SettingScreen +import com.capstone.techwasmark02.ui.screen.signIn.SignInScreen +import com.capstone.techwasmark02.ui.screen.signUp.SignUpScreen import com.capstone.techwasmark02.ui.screen.singleArticle.SingleArticleScreen +import com.capstone.techwasmark02.ui.screen.splashScreen.SplashScreen +import com.google.accompanist.navigation.animation.AnimatedNavHost +import com.google.accompanist.navigation.animation.composable +import com.google.accompanist.navigation.animation.rememberAnimatedNavController -@OptIn(ExperimentalMaterial3Api::class) +@OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class) @Composable fun TechwasApp() { - val navController = rememberNavController() + val navController = rememberAnimatedNavController() Scaffold { innerPadding -> - NavHost( + AnimatedNavHost( navController = navController, - startDestination = Home.route, + startDestination = Splash.route, modifier = Modifier - .padding(innerPadding) - ) { - composable(Home.route) { + .padding(innerPadding), + + ) { + + composable( + route = Splash.route, + enterTransition = Splash.enterTransition, + exitTransition = Splash.exitTransition + ) { + SplashScreen(navController = navController) + } + + composable( + route = OnBoarding.route, + enterTransition = { + slideIntoContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + }, + exitTransition = OnBoarding.exitTransition + ) { + OnBoardingScreen(navController = navController) + } + + composable(SignIn.route) { + SignInScreen(navController = navController) + } + + composable(SignUp.route) { + SignUpScreen(navController = navController) + } + + composable( + route = Main.route, + enterTransition = Main.enterTransition, + exitTransition = Main.exitTransition + ) { + MainScreen(navController = navController) + } + + composable( + route = Home.route, + enterTransition = Home.enterTransition, + exitTransition = Home.exitTransition + ) { HomeScreen(navController = navController) } - composable(Article.route) { + composable( + route = Article.route, + enterTransition = Article.enterTransition, + exitTransition = Article.exitTransition + ) { ArticleScreen(navController = navController) } @@ -82,11 +134,15 @@ fun TechwasApp() { val componentJson = navBackStackEntry.arguments?.getString("componentJson") if (componentJson != null) { - CatalogSingleComponentScreen(componentJson = componentJson) + CatalogSingleComponentScreen(componentJson = componentJson, navController = navController) } } - composable(Camera.route) { + composable( + route = Camera.route, + enterTransition = Camera.enterTransition, + exitTransition = Camera.exitTransition + ) { CameraScreen(navController = navController) } @@ -107,7 +163,7 @@ fun TechwasApp() { val result = navBackStackEntry.arguments?.getString("result") if (uri != null && result != null) { - DetectionResultScreen(stringUri = uri, detectionResult = result) + DetectionResultScreen(stringUri = uri, detectionResult = result, navController = navController) } } @@ -115,10 +171,6 @@ fun TechwasApp() { composable(Maps.route) { MapsScreen(navController = navController) } - - composable(Setting.route) { - SettingScreen(navController = navController) - } } } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt index 08f121e..047540e 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasArticleApi.kt @@ -30,6 +30,6 @@ interface TechwasArticleApi { ): ArticleResultResponse companion object { - const val BASE_URL = "https://the-prophecy-fwd5gpydiq-uc.a.run.app/" + const val BASE_URL = "https://backend-api-56g32wdmqa-uc.a.run.app/" } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasComponentApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasComponentApi.kt index ed07772..ba3dc1e 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasComponentApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasComponentApi.kt @@ -3,7 +3,6 @@ package com.capstone.techwasmark02.data.remote.apiService import com.capstone.techwasmark02.data.remote.response.ComponentResponse import com.capstone.techwasmark02.data.remote.response.ComponentsResponse import com.capstone.techwasmark02.data.remote.response.UsableComponentsResponse -import com.google.android.gms.common.internal.safeparcel.SafeParcelable.Param import retrofit2.http.GET import retrofit2.http.Header import retrofit2.http.Path @@ -27,6 +26,6 @@ interface TechwasComponentApi { ) : UsableComponentsResponse companion object { - const val BASE_URL = "https://the-prophecy-fwd5gpydiq-uc.a.run.app/" + const val BASE_URL = "https://backend-api-56g32wdmqa-uc.a.run.app/" } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt index bd053a5..550d242 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt @@ -16,7 +16,7 @@ interface TechwasPredictionApi { ) : DetectionsResultResponse companion object { - const val BASE_URL = "http://34.135.12.100/" + const val BASE_URL = "http://35.202.94.119/" // const val BASE_URL = "https://e-waste-model-deployment-1gb-fwd5gpydiq-uc.a.run.app/" } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasUserApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasUserApi.kt index 69ebf9f..0e9767e 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasUserApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasUserApi.kt @@ -20,7 +20,7 @@ interface TechwasUserApi { ) : UserRegisterResponse companion object { - const val BASE_URL = "https://the-prophecy-fwd5gpydiq-uc.a.run.app/" + const val BASE_URL = "https://backend-api-56g32wdmqa-uc.a.run.app/" } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/DetectionResultResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/DetectionResultResponse.kt index 65400b4..c8a9ea4 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/DetectionResultResponse.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/DetectionResultResponse.kt @@ -2,47 +2,6 @@ package com.capstone.techwasmark02.data.remote.response import com.google.gson.annotations.SerializedName -//data class DetectResult( -// val predictions: Predictions, -// val time_taken: String -//) - -//data class Predictions( -// @SerializedName("Cable") -// val cable: Double?, -// @SerializedName("CRT_TV") -// val crtTv: Double?, -// @SerializedName("E-kettle") -// val eKettle: Double?, -// @SerializedName("Refrigerator") -// val refrigerator: Double?, -// @SerializedName("Keyboard") -// val keyboard: Double?, -// @SerializedName("Laptop") -// val laptop: Double?, -// @SerializedName("Light Bulb") -// val lightBulb: Double?, -// @SerializedName("Monitor") -// val monitor: Double?, -// @SerializedName("Mouse") -// val mouse: Double?, -// @SerializedName("PCB") -// val pcb: Double?, -// @SerializedName("Phone") -// val phone: Double?, -// @SerializedName("Printer") -// val printer: Double?, -// @SerializedName("Rice Cooker") -// val riceCooker: Double?, -// @SerializedName("Washing Machine") -// val washingMachine: Double? -// -//) -// -//data class ResultComponentType( -// val name: String, -// val percentage: Double -//) data class DetectionsResultResponse( val Image_Url: String, val predictions: List, @@ -59,3 +18,4 @@ data class Prediction( ) + diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt index cfa957c..72c930d 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ArticleCard.kt @@ -2,7 +2,6 @@ package com.capstone.techwasmark02.ui.component import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -22,15 +21,16 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import coil.compose.AsyncImage import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R import com.capstone.techwasmark02.data.remote.response.ArticleList import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme -import kotlin.random.Random @Composable fun ArticleCardBig( @@ -80,11 +80,14 @@ fun ArticleCardBig( ) } article.desc?.let { - Text( - text = it, - style = MaterialTheme.typography.bodySmall, - maxLines = 1, - overflow = TextOverflow.Ellipsis + HtmlText( + html = it, + textStyle = MaterialTheme.typography.bodySmall.copy( + color = Color.Black, + fontWeight = FontWeight.Normal, + fontSize = 7.sp + ), + maxLine = 1 ) } } @@ -141,11 +144,14 @@ fun ArticleCardSmall( ) } if (description != null) { - Text( - text = description, - style = MaterialTheme.typography.bodySmall, - maxLines = 1, - overflow = TextOverflow.Ellipsis + HtmlText( + html = description, + textStyle = MaterialTheme.typography.bodySmall.copy( + color = Color.Black, + fontWeight = FontWeight.Normal, + fontSize = 7.sp + ), + maxLine = 1 ) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt index 23904b1..94b0c33 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt @@ -24,9 +24,11 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Shadow +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview @@ -56,24 +58,66 @@ fun SignInBanner( .background( MaterialTheme.colorScheme.primary, ), - contentAlignment = Alignment.Center ) { - Text( - text = "Welcome to TechWaste", - style = MaterialTheme.typography.headlineSmall.copy( - shadow = Shadow( - color = MaterialTheme.colorScheme.onTertiary.copy( - alpha = 0.8f + + Image( + painter = painterResource(id = R.drawable.img_bg_singin), + contentDescription = null, + modifier = Modifier + .fillMaxSize(), + contentScale = ContentScale.Crop + ) + + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 24.dp), + verticalArrangement = Arrangement.Center + ) { + + Spacer(modifier = Modifier.height(10.dp)) + + Box( + modifier = Modifier + ) { + + Text( + text = "Welcome", + style = MaterialTheme.typography.headlineMedium.copy( + fontWeight = FontWeight.Bold ), - offset = Offset( - x = 0f, - y = 14f + color = MaterialTheme.colorScheme.onPrimary, + modifier = Modifier + .offset( + x = 0.dp, + y = -(18.dp) + ) + ) + + Text( + text = "to Techwaste!", + style = MaterialTheme.typography.headlineMedium.copy( + fontWeight = FontWeight.Bold ), - blurRadius = 16f + color = MaterialTheme.colorScheme.onPrimary, + modifier = Modifier + .offset( + x = 0.dp, + y = (10.dp) + ) ) - ), - color = MaterialTheme.colorScheme.onPrimary, - ) + } + + Spacer(modifier = Modifier.height(8.dp)) + + Text( + text = "Let's manage your e-waste properly.", + style = MaterialTheme.typography.bodyMedium.copy( + fontWeight = FontWeight.Medium + ), + color = MaterialTheme.colorScheme.onPrimary + ) + } } } @@ -83,7 +127,7 @@ fun SignUpBanner( ) { Box( modifier = modifier - .height(100.dp) + .height(150.dp) .fillMaxWidth() .shadow( elevation = 12.dp, @@ -94,24 +138,66 @@ fun SignUpBanner( .background( MaterialTheme.colorScheme.primary, ), - contentAlignment = Alignment.Center ) { - Text( - text = "Nice to meet you", - style = MaterialTheme.typography.headlineSmall.copy( - shadow = Shadow( - color = MaterialTheme.colorScheme.onTertiary.copy( - alpha = 0.8f + + Image( + painter = painterResource(id = R.drawable.img_bg_singin), + contentDescription = null, + modifier = Modifier + .fillMaxSize(), + contentScale = ContentScale.Crop + ) + + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 24.dp), + verticalArrangement = Arrangement.Center + ) { + Box( + modifier = Modifier + ) { + + Text( + text = "Let's start your", + style = MaterialTheme.typography.headlineSmall.copy( + fontWeight = FontWeight.Bold + ), + color = MaterialTheme.colorScheme.onPrimary, + modifier = Modifier + .offset( + x = 0.dp, + y = -(28.dp) + ) + ) + + Text( + text = "journey to dispose of", + style = MaterialTheme.typography.headlineSmall.copy( + fontWeight = FontWeight.Bold ), - offset = Offset( - x = 0f, - y = 14f + color = MaterialTheme.colorScheme.onPrimary, + modifier = Modifier + .offset( + x = 0.dp, + y = (0.dp) + ) + ) + + Text( + text = "to Techwaste!", + style = MaterialTheme.typography.headlineSmall.copy( + fontWeight = FontWeight.Bold ), - blurRadius = 16f + color = MaterialTheme.colorScheme.onPrimary, + modifier = Modifier + .offset( + x = 0.dp, + y = (28.dp) + ) ) - ), - color = MaterialTheme.colorScheme.onPrimary, - ) + } + } } } @@ -342,5 +428,5 @@ fun HomeBannerPreview() { ForumBanner() } } - + } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt index 5dfed19..2daa4ca 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/BottomBar.kt @@ -1,9 +1,10 @@ package com.capstone.techwasmark02.ui.component -import androidx.compose.foundation.clickable +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.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight @@ -34,10 +35,7 @@ import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme fun DefaultBottomBar( modifier: Modifier = Modifier, selectedType: BottomBarItemType, - navigateToHome: () -> Unit, - navigateToForum: () -> Unit, - navigateToArticle: () -> Unit, - navigateToProfile: () -> Unit + onClickBottomNavType: (bottomBarType: BottomBarItemType) -> Unit, ) { Box( modifier = Modifier @@ -66,68 +64,118 @@ fun DefaultBottomBar( .padding(horizontal = 24.dp), verticalAlignment = Alignment.CenterVertically, ) { - - BottomBarItem(bottomBarItemType = BottomBarItemType.Home, selectedType = selectedType, onClick = navigateToHome) + BottomBarItem( + bottomBarItemType = BottomBarItemType.Home, + selectedType = selectedType, + onClick = { + onClickBottomNavType(it) + }, + ) Spacer(modifier = Modifier.weight(1f)) - BottomBarItem(bottomBarItemType = BottomBarItemType.Forum, selectedType = selectedType, onClick = navigateToForum) + BottomBarItem( + bottomBarItemType = BottomBarItemType.Forum, + selectedType = selectedType, + onClick = { + onClickBottomNavType(it) + }, + ) Spacer(modifier = Modifier.weight(1f)) - BottomBarItem(bottomBarItemType = BottomBarItemType.Article, selectedType = selectedType, onClick = navigateToArticle) + BottomBarItem( + bottomBarItemType = BottomBarItemType.Article, + selectedType = selectedType, + onClick = { + onClickBottomNavType(it) + }, + ) Spacer(modifier = Modifier.weight(1f)) - BottomBarItem(bottomBarItemType = BottomBarItemType.Profile, selectedType = selectedType, onClick = navigateToProfile) - - + BottomBarItem( + bottomBarItemType = BottomBarItemType.Profile, + selectedType = selectedType, + onClick = { + onClickBottomNavType(it) + }, + ) } } } } + @Composable fun BottomBarItem( modifier: Modifier = Modifier, bottomBarItemType: BottomBarItemType, selectedType: BottomBarItemType, - onClick: () -> Unit + onClick: (BottomBarItemType) -> Unit, ) { - IconButton( - onClick = onClick, + Box( modifier = modifier - .size(44.dp) + .fillMaxHeight() + .width(IntrinsicSize.Max), + contentAlignment = Alignment.Center ) { - Column( - modifier = Modifier - .fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceBetween + + if (selectedType == bottomBarItemType) { + Column( + modifier = Modifier + .fillMaxHeight() + .fillMaxWidth(), + verticalArrangement = Arrangement.Bottom + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(4.dp) + .clip(RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp)) + .background(MaterialTheme.colorScheme.primary) + ) + } + } + + IconButton( + onClick = { + onClick(bottomBarItemType) + }, + modifier = modifier + .size(44.dp) ) { - Icon( - painter = painterResource(id = bottomBarItemType.icon), - contentDescription = null, - tint = if (selectedType == bottomBarItemType) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.inverseOnSurface - } + Column( + modifier = Modifier + .fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceBetween + ) { + Icon( + painter = painterResource(id = bottomBarItemType.icon), + contentDescription = null, + tint = if (selectedType == bottomBarItemType) { + MaterialTheme.colorScheme.primary + } else { + MaterialTheme.colorScheme.inverseOnSurface + } - ) - Text( - text = bottomBarItemType.title, - style = MaterialTheme.typography.labelSmall, - color = if (selectedType == bottomBarItemType) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.inverseOnSurface - } - ) + ) + Text( + text = bottomBarItemType.title, + style = MaterialTheme.typography.labelSmall, + color = if (selectedType == bottomBarItemType) { + MaterialTheme.colorScheme.primary + } else { + MaterialTheme.colorScheme.inverseOnSurface + } + ) + } } } } + @Preview(showBackground = true) @Composable fun DefaultBottomBarPreview() { @@ -139,41 +187,8 @@ fun DefaultBottomBarPreview() { ) { DefaultBottomBar( selectedType = BottomBarItemType.Home, - navigateToHome = {}, - navigateToArticle = {}, - navigateToForum = {}, - navigateToProfile = {} + onClickBottomNavType = {}, ) } } -} - -//@Composable -//fun CheckBottomNav( -// modifier: Modifier = Modifier -//) { -// Box( -// modifier = modifier -// .graphicsLayer { -// shape = BottomNavShape() -// clip = true -// } -// .fillMaxWidth() -// .height(58.dp) -// .background(MaterialTheme.colorScheme.inverseSurface) -// ) { -// -// } -//} - -//@Preview (showBackground = true) -//@Composable -//fun CheckBottomNavPreview() { -// Box( -// modifier = Modifier -// .fillMaxWidth() -// .padding(20.dp) -// ) { -// CheckBottomNav() -// } -//} \ No newline at end of file +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/Button.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/Button.kt index 8ad0b68..93d6896 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/Button.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/Button.kt @@ -1,16 +1,14 @@ package com.capstone.techwasmark02.ui.component import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.material3.Button +import androidx.compose.material3.ButtonColors import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton @@ -27,7 +25,8 @@ import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme fun DefaultButton( modifier: Modifier = Modifier, onClick: () -> Unit = {}, - contentText: String + contentText: String, + buttonColors: ButtonColors = ButtonDefaults.buttonColors() ) { Button( onClick = onClick, @@ -36,6 +35,7 @@ fun DefaultButton( elevation = ButtonDefaults.buttonElevation( defaultElevation = 4.dp ), + colors = buttonColors ) { Text( text = contentText, @@ -74,14 +74,14 @@ fun InverseButton( } @Composable -fun SmallButton(modifier: Modifier = Modifier, contentText: String, onClick: () -> Unit = {}, colorText: Color) { +fun SmallButton(modifier: Modifier = Modifier, contentText: String, onClick: () -> Unit = {}, colorText: Color, containerColor: Color = MaterialTheme.colorScheme.tertiary) { Button( onClick = onClick, modifier = modifier .height(28.dp), colors = ButtonDefaults.buttonColors( contentColor = MaterialTheme.colorScheme.onTertiary, - containerColor = MaterialTheme.colorScheme.tertiary + containerColor = containerColor ), shape = MaterialTheme.shapes.large, contentPadding = PaddingValues(horizontal = 12.dp), diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/CameraView.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/CameraView.kt index 0d0b0ac..61656fc 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/CameraView.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/CameraView.kt @@ -35,7 +35,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.blur @@ -48,8 +47,8 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import coil.compose.AsyncImage -import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.io.File diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/CatalogCard.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/CatalogCard.kt index 388ab58..fb20ae5 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/CatalogCard.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/CatalogCard.kt @@ -1,9 +1,7 @@ package com.capstone.techwasmark02.ui.component -import android.net.Uri import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -23,6 +21,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource @@ -33,8 +32,6 @@ import coil.compose.AsyncImage import com.capstone.techwasmark02.R import com.capstone.techwasmark02.data.remote.response.Component import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme -import com.squareup.moshi.Moshi -import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import kotlin.random.Random @Composable @@ -63,13 +60,13 @@ fun CatalogCard( Row( modifier = Modifier .fillMaxSize() - .padding(vertical = 8.dp) - .padding(start = 16.dp, end = 8.dp) ) { Column( modifier = Modifier .fillMaxHeight() - .weight(1f), + .weight(1f) + .padding(vertical = 8.dp) + .padding(start = 16.dp), verticalArrangement = Arrangement.Center ) { Text( @@ -89,13 +86,16 @@ fun CatalogCard( Spacer(modifier = Modifier.width(8.dp)) + Box( modifier = Modifier - .width(140.dp) + .width(150.dp) .fillMaxHeight() - .clip(RoundedCornerShape(20.dp)) + .clip(RoundedCornerShape(topEnd = 20.dp, bottomEnd = 20.dp)) .background(Color.LightGray) ) { + val greenColor = Color(0xff8bcd54) + AsyncImage( model = component.imageExample, contentDescription = null, @@ -103,6 +103,19 @@ fun CatalogCard( modifier = Modifier .fillMaxSize() ) + + Box( + + modifier = Modifier + .fillMaxSize() + .background( + Brush.horizontalGradient( + .0f to greenColor, + .4F to greenColor.copy(alpha = 0.4f), + .6F to Color.Transparent, + ) + ) + ) } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt index fffc040..3e51644 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectBox.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import com.capstone.techwasmark02.R import com.capstone.techwasmark02.ui.componentType.FeatureBoxType import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @@ -100,6 +101,72 @@ fun FeatureBox( } } +@Composable +fun FeatureBoxLarge( + modifier: Modifier = Modifier, + featureBoxType: FeatureBoxType, + onClick: () -> Unit +) { + Box( + modifier = modifier + .fillMaxWidth() + .height(160.dp) + .shadow( + elevation = 4.dp, + shape = RoundedCornerShape(10.dp) + ) + .clickable { onClick() } + ) { + Image( + painter = painterResource(id = featureBoxType.backGround), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .fillMaxSize() + ) + Column( + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + ) { + Text( + text = featureBoxType.title, + style = MaterialTheme.typography.titleLarge.copy( + fontSize = 28.sp, + fontWeight = FontWeight.SemiBold + ), + color = Color.White, + ) + } + + Spacer(modifier = Modifier.weight(1f)) + + Row( + modifier = Modifier + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.size(44.dp), + painter = painterResource(id = featureBoxType.icon), + contentDescription = null, + tint = Color.White + ) + Spacer(modifier = Modifier.weight(1f)) + SmallButton( + contentText = featureBoxType.buttonTitle, + onClick = onClick, + colorText = featureBoxType.buttonColor + ) + } + } + } +} + @Composable fun AboutUsBox(modifier: Modifier = Modifier) { Box( @@ -152,6 +219,11 @@ fun DetectBoxPreview() { TechwasMark02Theme { Box(modifier = Modifier.padding(20.dp)) { Column(modifier = Modifier.fillMaxWidth()) { + + FeatureBoxLarge(featureBoxType = FeatureBoxType.Detection, onClick = {}) + + Spacer(modifier = Modifier.height(20.dp)) + FeatureBox( featureBoxType = FeatureBoxType.Detection, onClick = {} diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt index c562f00..fc9847e 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/DetectionsResultBox.kt @@ -272,11 +272,6 @@ fun ResultListItemPreview() { } } -data class DummyDetectionResult( - val componentType: String, - val detectionPercentage: Int -) - private val dummyDetectionResultList: List = listOf( Prediction( componentId = 1, diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/HtmlText.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/HtmlText.kt new file mode 100644 index 0000000..da6a2d0 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/HtmlText.kt @@ -0,0 +1,69 @@ +package com.capstone.techwasmark02.ui.component + +import android.content.Context +import android.text.TextUtils +import android.util.TypedValue +import android.view.Gravity +import android.widget.TextView +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.viewinterop.AndroidView +import androidx.core.content.res.ResourcesCompat +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.utils.html.fromHtml +import kotlin.math.max + +private const val SPACING_FIX = 3f + +@Composable +fun HtmlText( + modifier: Modifier = Modifier, + html: String, + textStyle: TextStyle = MaterialTheme.typography.bodyMedium, + maxLine: Int? = null +) { + AndroidView( + modifier = modifier, + update = { it.text = fromHtml(it.context, html) }, + factory = { context -> + val spacingReady = + max(textStyle.lineHeight.value - textStyle.fontSize.value - SPACING_FIX, 0f) + val extraSpacing = spToPx(spacingReady.toInt(), context) + val gravity = when (textStyle.textAlign) { + TextAlign.Center -> Gravity.CENTER + TextAlign.End -> Gravity.END + else -> Gravity.START + } + val fontResId = when (textStyle.fontWeight) { + FontWeight.Medium -> R.font.poppins_medium + else -> R.font.poppins_regular + } + val font = ResourcesCompat.getFont(context, fontResId) + + TextView(context).apply { + // general style + textSize = textStyle.fontSize.value + setLineSpacing(extraSpacing, 1f) + setTextColor(textStyle.color.toArgb()) + setGravity(gravity) + typeface = font + if (maxLine != null) { + maxLines = maxLine + ellipsize = TextUtils.TruncateAt.END + } + } + } + ) +} + +fun spToPx(sp: Int, context: Context): Float = + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, + sp.toFloat(), + context.resources.displayMetrics + ) \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/MainTextField.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/MainTextField.kt index b42a779..37cfe76 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/MainTextField.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/MainTextField.kt @@ -1,24 +1,32 @@ package com.capstone.techwasmark02.ui.component +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text +import androidx.compose.material3.TextField import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import com.capstone.techwasmark02.R import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @@ -31,33 +39,66 @@ fun DefaultTextField( labelText: String, placeHolderText: String ) { - OutlinedTextField( - value = value, - onValueChange = onValueChange, - label = { - Text( - text = labelText, - style = MaterialTheme.typography.bodyMedium - ) - }, - placeholder = { - Text( - text = placeHolderText, - style = MaterialTheme.typography.bodyMedium - ) - }, - singleLine = true, - shape = MaterialTheme.shapes.large, - colors = TextFieldDefaults.outlinedTextFieldColors( - textColor = MaterialTheme.colorScheme.onTertiary, - containerColor = MaterialTheme.colorScheme.tertiary, - focusedLabelColor = MaterialTheme.colorScheme.onTertiary, - focusedBorderColor = MaterialTheme.colorScheme.onTertiary, - cursorColor = MaterialTheme.colorScheme.onTertiary, - ), - textStyle = MaterialTheme.typography.bodyMedium, + var hasFocus by remember { + mutableStateOf(false) + } + + val focusColor = if (hasFocus) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.6f) + + Box( modifier = modifier - ) + ) { + TextField( + value = value, + onValueChange = onValueChange, + placeholder = { + Text( + text = placeHolderText, + style = MaterialTheme.typography.bodyMedium + ) + }, + singleLine = true, + shape = MaterialTheme.shapes.large, + colors = TextFieldDefaults.textFieldColors( + textColor = if (hasFocus) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onTertiary, + containerColor = Color.Transparent, + focusedLabelColor = MaterialTheme.colorScheme.primary, + cursorColor = MaterialTheme.colorScheme.primary, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + placeholderColor = MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.6f), + focusedTrailingIconColor = focusColor + ), + textStyle = MaterialTheme.typography.bodyMedium.copy( + fontWeight = FontWeight.SemiBold + ), + modifier = modifier + .onFocusChanged { focusState -> hasFocus = focusState.hasFocus } + .border( + width = if (hasFocus) 3.dp else 1.5.dp, + color = if (hasFocus) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onTertiary.copy( + alpha = 0.6f + ), + shape = MaterialTheme.shapes.large + ), + ) + + Text( + text = labelText, + style = MaterialTheme.typography.labelMedium.copy( + fontWeight = FontWeight.SemiBold, + letterSpacing = 0.sp + ), + modifier = Modifier + .offset( + x = 16.dp, + y = -(10.dp) + ) + .background(MaterialTheme.colorScheme.background) + .padding(horizontal = 4.dp), + color = focusColor + ) + } } @OptIn(ExperimentalMaterial3Api::class) @@ -69,53 +110,85 @@ fun PasswordTextField( toggleShowPassword: () -> Unit, modifier: Modifier = Modifier ) { - OutlinedTextField( - value = value, - onValueChange = onValueChange, - modifier = modifier, - label = { - Text( - text = "Password", - style = MaterialTheme.typography.bodyMedium - ) - }, - placeholder = { - Text( - text = "user password", - style = MaterialTheme.typography.bodyMedium - ) - }, - singleLine = true, - shape = MaterialTheme.shapes.large, - colors = TextFieldDefaults.outlinedTextFieldColors( - textColor = MaterialTheme.colorScheme.onTertiary, - containerColor = MaterialTheme.colorScheme.tertiary, - focusedLabelColor = MaterialTheme.colorScheme.onTertiary, - focusedBorderColor = MaterialTheme.colorScheme.onTertiary, - cursorColor = MaterialTheme.colorScheme.onTertiary, - ), - textStyle = MaterialTheme.typography.bodyMedium, - visualTransformation = if (showPassword) { - VisualTransformation.None - } else { - PasswordVisualTransformation() - }, - trailingIcon = { - IconButton(onClick = toggleShowPassword ) { - if (showPassword) { - Icon( - painter = painterResource(id = R.drawable.ic_visibility_on), - contentDescription = null - ) - } else { - Icon( - painter = painterResource(id = R.drawable.ic_visibility_off), - contentDescription = null - ) + + var hasFocus by remember { + mutableStateOf(false) + } + + val focusColor = if (hasFocus) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.6f) + + Box( + modifier = Modifier + ) { + TextField( + value = value, + onValueChange = onValueChange, + modifier = modifier + .onFocusChanged { focusState -> hasFocus = focusState.hasFocus } + .border( + width = if (hasFocus) 3.dp else 1.5.dp, + color = focusColor, + shape = MaterialTheme.shapes.large + ), + placeholder = { + Text( + text = "user password", + style = MaterialTheme.typography.bodyMedium + ) + }, + singleLine = true, + shape = MaterialTheme.shapes.large, + colors = TextFieldDefaults.textFieldColors( + textColor = focusColor, + containerColor = Color.Transparent, + focusedLabelColor = MaterialTheme.colorScheme.primary, + cursorColor = MaterialTheme.colorScheme.primary, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + placeholderColor = MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.6f), + focusedTrailingIconColor = focusColor, + unfocusedLabelColor = focusColor + ), + textStyle = MaterialTheme.typography.bodyMedium, + visualTransformation = if (showPassword) { + VisualTransformation.None + } else { + PasswordVisualTransformation() + }, + trailingIcon = { + IconButton(onClick = toggleShowPassword ) { + if (showPassword) { + Icon( + painter = painterResource(id = R.drawable.ic_visibility_on), + contentDescription = null + ) + } else { + Icon( + painter = painterResource(id = R.drawable.ic_visibility_off), + contentDescription = null + ) + } } } - } - ) + ) + + + Text( + text = "Password", + style = MaterialTheme.typography.labelMedium.copy( + fontWeight = FontWeight.SemiBold, + letterSpacing = 0.sp + ), + modifier = Modifier + .offset( + x = 16.dp, + y = -(10.dp) + ) + .background(MaterialTheme.colorScheme.background) + .padding(horizontal = 4.dp), + color = focusColor + ) + } } @Preview (showBackground = true) @@ -134,6 +207,7 @@ fun TextFieldPreview() { Column( modifier = Modifier .fillMaxWidth() + .background(MaterialTheme.colorScheme.background) .padding(20.dp) ) { DefaultTextField( diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt index 99b5538..50613f9 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SearchBox.kt @@ -2,14 +2,10 @@ package com.capstone.techwasmark02.ui.component import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt index 6c3f49c..cfcd93d 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt @@ -1,5 +1,6 @@ package com.capstone.techwasmark02.ui.component +import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth @@ -25,6 +26,10 @@ import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @OptIn(ExperimentalMaterial3Api::class) @Composable fun InverseTopBar(onClickNavigationIcon: () -> Unit, modifier: Modifier = Modifier) { + BackHandler(true) { + onClickNavigationIcon() + } + TopAppBar( navigationIcon = { IconButton( diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentBottomSheet.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentBottomSheet.kt index 83e5876..d6da43c 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentBottomSheet.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentBottomSheet.kt @@ -1,17 +1,13 @@ package com.capstone.techwasmark02.ui.component 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.PaddingValues import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyRow import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentItem.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentItem.kt index c3fb4eb..7c338c9 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentItem.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/UsableComponentItem.kt @@ -1,6 +1,5 @@ package com.capstone.techwasmark02.ui.component -import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box @@ -16,7 +15,6 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource @@ -25,12 +23,9 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import coil.compose.AsyncImage -import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R import com.capstone.techwasmark02.data.remote.response.SmallPart import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme -import java.io.File -import kotlin.random.Random @Composable fun UsableComponentItem( diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/BottomBarItemType.kt b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/BottomBarItemType.kt index 8faca17..551b166 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/BottomBarItemType.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/BottomBarItemType.kt @@ -2,9 +2,9 @@ package com.capstone.techwasmark02.ui.componentType import com.capstone.techwasmark02.R -sealed class BottomBarItemType(val title: String, val icon: Int) { - object Home: BottomBarItemType(title = "Home", icon = R.drawable.ic_home) - object Forum: BottomBarItemType(title = "Forum", icon = R.drawable.ic_forum) - object Article: BottomBarItemType(title = "Article", icon = R.drawable.ic_article) - object Profile: BottomBarItemType(title = "Profile", icon = R.drawable.ic_profile) +sealed class BottomBarItemType(val title: String, val icon: Int, val pageIndex: Int) { + object Home: BottomBarItemType(title = "Home", icon = R.drawable.ic_home, pageIndex = 0) + object Forum: BottomBarItemType(title = "Forum", icon = R.drawable.ic_forum, pageIndex = 1) + object Article: BottomBarItemType(title = "Article", icon = R.drawable.ic_article, pageIndex = 2) + object Profile: BottomBarItemType(title = "Profile", icon = R.drawable.ic_profile, pageIndex = 3) } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/FeatureBoxType.kt b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/FeatureBoxType.kt index 74e9d49..7eeef60 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/FeatureBoxType.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/FeatureBoxType.kt @@ -7,7 +7,7 @@ import com.capstone.techwasmark02.ui.theme.purple import com.capstone.techwasmark02.ui.theme.sakura sealed class FeatureBoxType(val title: String, val buttonTitle: String, val icon: Int, val backGround: Int, val buttonColor: Color) { - object Detection: FeatureBoxType(title = "Detect e-waste", buttonTitle = "Detect", icon = R.drawable.ic_center_focus, backGround = R.drawable.img_bg_green, buttonColor = Green35) + object Detection: FeatureBoxType(title = "Detect\ne-waste", buttonTitle = "Detect", icon = R.drawable.ic_center_focus, backGround = R.drawable.img_bg_green_large, buttonColor = Green35) object Catalog: FeatureBoxType(title = "E-waste catalog", buttonTitle = "Open", icon = R.drawable.ic_menu_book, backGround = R.drawable.img_bg_purple, buttonColor = purple) object DropPoint: FeatureBoxType(title = "Nearby drop point", buttonTitle = "Locate", icon = R.drawable.ic_location_on, backGround = R.drawable.img_bg_sakura, buttonColor = sakura) } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt index 5489446..e36b438 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt @@ -1,16 +1,248 @@ package com.capstone.techwasmark02.ui.navigation -sealed class Screen(val route: String) { - object Home: Screen(route = "home") - object Forum: Screen(route = "forum") - object Profile: Screen(route = "profile") - object Camera: Screen(route = "camera") - object Catalog: Screen(route = "catalog") - object SingleCatalog: Screen(route = "singleCatalog") - object DetectionResult: Screen(route = "detectionResult") - object Article: Screen(route = "article") - object SingleArticle: Screen(route = "singleArticle") - object Splash: Screen(route = "splash") - object Maps: Screen(route = "maps") - object Setting: Screen(route = "setting") +import androidx.compose.animation.AnimatedContentScope +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.ExitTransition +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.navigation.NavBackStackEntry + +@OptIn(ExperimentalAnimationApi::class) +sealed class Screen constructor(val route: String, val enterTransition: (AnimatedContentScope.() -> EnterTransition?), val exitTransition: (AnimatedContentScope.() -> ExitTransition?)) { + + object OnBoarding: Screen( + route = "OnBoarding", + enterTransition = { + fadeIn(animationSpec = tween(700)) + }, + exitTransition = { +// slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + fadeOut( + animationSpec = tween(700) + ) + } + ) + + object SignIn: Screen( + route = "SignIn", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { + slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + } + ) + + object SignUp: Screen( + route = "SignUp", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { + slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + } + ) + + object Main: Screen( + route = "Main", + enterTransition = { +// slideIntoContainer( +// AnimatedContentScope.SlideDirection.Left, +// animationSpec = tween(700) +// ) + fadeIn(animationSpec = tween(300)) + }, + exitTransition = { +// slideOutOfContainer(AnimatedContentScope.SlideDirection.Up, animationSpec = tween(700)) + fadeOut( + animationSpec = tween(700) + ) + } + ) + + object Home: Screen( + route = "home", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { +// slideOutOfContainer( +// AnimatedContentScope.SlideDirection.Left, animationSpec = tween( +// durationMillis = 700, +// ) +// ) + fadeOut( + animationSpec = tween(700) + ) + } + ) + + object Forum: Screen( + route = "forum", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { + slideOutOfContainer( + AnimatedContentScope.SlideDirection.Left, animationSpec = tween( + durationMillis = 700, + ) + ) + } + ) + + object Profile: Screen( + route = "profile", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { + slideOutOfContainer( + AnimatedContentScope.SlideDirection.Left, animationSpec = tween( + durationMillis = 700, + ) + ) + } + ) + + object Setting: Screen( + route = "setting", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { + slideOutOfContainer( + AnimatedContentScope.SlideDirection.Left, animationSpec = tween( + durationMillis = 700, + ) + ) + } + ) + + object Camera: Screen( + route = "camera", + enterTransition = { +// slideIntoContainer( +// AnimatedContentScope.SlideDirection.Up, +// animationSpec = tween(700) +// ) + fadeIn(animationSpec = tween(1000)) + }, + exitTransition = { + slideOutOfContainer(AnimatedContentScope.SlideDirection.Down, animationSpec = tween(700)) + } + ) + + object Catalog: Screen( + route = "catalog", + enterTransition = { +// slideIntoContainer( +// AnimatedContentScope.SlideDirection.Left, +// animationSpec = tween(700) +// ) + fadeIn(animationSpec = tween(300)) + }, + exitTransition = { +// slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + fadeOut(animationSpec = tween(300)) + } + ) + + object SingleCatalog: Screen( + route = "singleCatalog", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { + slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + } + ) + + object DetectionResult: Screen( + route = "detectionResult", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { + slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + } + ) + + object Article: Screen( + route = "article", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { + slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + } + ) + + object SingleArticle: Screen( + route = "singleArticle", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { + slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + } + ) + + object Splash: Screen( + route = "splash", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { + slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + } + ) + + object Maps: Screen( + route = "maps", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { + slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + } + ) } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt index 2933887..401689c 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize @@ -21,9 +20,7 @@ import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -45,11 +42,9 @@ import androidx.navigation.NavHostController import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.ArticleCardSmall -import com.capstone.techwasmark02.ui.component.DefaultBottomBar import com.capstone.techwasmark02.ui.component.SearchBox import com.capstone.techwasmark02.ui.component.SelectableText import com.capstone.techwasmark02.ui.componentType.ArticleFilterType -import com.capstone.techwasmark02.ui.componentType.BottomBarItemType import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @@ -64,10 +59,6 @@ fun ArticleScreen( viewModel = viewModel, articleList = articleList, navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") }, - navigateToHome = { navController.navigate(Screen.Home.route) }, - navigateToArticle = { navController.navigate(Screen.Article.route) }, - navigateToForum = { navController.navigate(Screen.Forum.route) }, - navigateToProfile = { navController.navigate(Screen.Profile.route) } ) } @@ -76,10 +67,6 @@ fun ArticleContent( viewModel: ArticleScreenViewModel, articleList: UiState?, navigateToSingleArticle: (idArticle: Int) -> Unit, - navigateToHome: () -> Unit, - navigateToForum: () -> Unit, - navigateToArticle: () -> Unit, - navigateToProfile: () -> Unit ) { var inputValue by remember { @@ -256,13 +243,6 @@ fun ArticleContent( .fillMaxSize() ) { Spacer(modifier = Modifier.weight(1f)) - DefaultBottomBar( - selectedType = BottomBarItemType.Article, - navigateToProfile = navigateToProfile, - navigateToForum = navigateToForum, - navigateToArticle = navigateToArticle, - navigateToHome = navigateToHome - ) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreenViewModel.kt index a61299b..3175b1c 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreenViewModel.kt @@ -3,9 +3,7 @@ package com.capstone.techwasmark02.ui.screen.catalog import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.capstone.techwasmark02.data.remote.response.ComponentsResponse -import com.capstone.techwasmark02.repository.PreferencesRepository import com.capstone.techwasmark02.repository.TechwasComponentApiRepository -import com.capstone.techwasmark02.repository.TechwasUserApiRepository import com.capstone.techwasmark02.ui.common.UiState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -15,7 +13,6 @@ import javax.inject.Inject @HiltViewModel class CatalogScreenViewModel @Inject constructor( - private val preferencesRepository: PreferencesRepository, private val componentApiRepository: TechwasComponentApiRepository ): ViewModel() { diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt index f786e1c..fecb7aa 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt @@ -1,7 +1,9 @@ package com.capstone.techwasmark02.ui.screen.catalogSingleComponent +import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -10,6 +12,7 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyRow @@ -42,14 +45,15 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavHostController import coil.compose.AsyncImage import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.Component -import com.capstone.techwasmark02.data.remote.response.ComponentResponse -import com.capstone.techwasmark02.data.remote.response.DetectionsResultResponse import com.capstone.techwasmark02.data.remote.response.SmallPart import com.capstone.techwasmark02.data.remote.response.UsableComponentsResponse import com.capstone.techwasmark02.ui.common.UiState @@ -59,16 +63,17 @@ import com.capstone.techwasmark02.ui.component.DefaultTopBar import com.capstone.techwasmark02.ui.component.InverseButton import com.capstone.techwasmark02.ui.component.UsableComponentBottomSheet import com.capstone.techwasmark02.ui.component.UsableComponentItem +import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import kotlinx.coroutines.launch -import kotlin.random.Random @Composable fun CatalogSingleComponentScreen( viewModel: CatalogSingleComponentScreenViewModel = hiltViewModel(), - componentJson: String + componentJson: String, + navController: NavHostController ) { val moshi = Moshi.Builder() @@ -89,7 +94,8 @@ fun CatalogSingleComponentScreen( usableComponentList = usableComponentList, updateUsableComponentsList = { viewModel.updateUsableComponentList(it) }, relatedArticleListState = relatedArticleListState, - updateRelatedArticleListState = { viewModel.updateRelatedArticleListState(it) } + updateRelatedArticleListState = { viewModel.updateRelatedArticleListState(it) }, + navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") } ) } } @@ -103,8 +109,10 @@ fun CatalogSingleComponentContent( usableComponentList: List, updateUsableComponentsList: (List) -> Unit, relatedArticleListState: UiState?, - updateRelatedArticleListState: (Int) -> Unit -) { + updateRelatedArticleListState: (Int) -> Unit, + navigateToSingleArticle: (idArticle: Int) -> Unit, + + ) { val modalSheetState = rememberModalBottomSheetState( initialValue = ModalBottomSheetValue.Hidden, @@ -118,11 +126,24 @@ fun CatalogSingleComponentContent( mutableStateOf(0) } + var isBottomSheetOpen by remember { + mutableStateOf(false) + } + LaunchedEffect(Unit) { updateUsableComponentsState(component.id) updateRelatedArticleListState(component.id) } + BackHandler(isBottomSheetOpen) { + if (isBottomSheetOpen) { + coroutineScope.launch { + modalSheetState.hide() + isBottomSheetOpen = false + } + } + } + ModalBottomSheetLayout( sheetState = modalSheetState, sheetShape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp), @@ -150,6 +171,13 @@ fun CatalogSingleComponentContent( .padding(innerPadding) .padding(bottom = 20.dp) ) { + + var componentWidth by remember { + mutableStateOf(0.dp) + } + val density = LocalDensity.current + + Box( modifier = Modifier ) { @@ -163,17 +191,25 @@ fun CatalogSingleComponentContent( bottomEnd = 20.dp ) ) - .background(MaterialTheme.colorScheme.primary), + .background(Color(0xff656565)) + .onGloballyPositioned { + componentWidth = with(density) { + it.size.width.toDp() + } + } + .offset( + x = -(componentWidth * 15 / 88) + ), ) { - AsyncImage( - model = component.imageExample, - contentDescription = null, - contentScale = ContentScale.Crop, - alpha = 0.8f, - modifier = Modifier - .fillMaxSize() - .blur(16.dp) - ) +// AsyncImage( +// model = component.imageExample, +// contentDescription = null, +// contentScale = ContentScale.Crop, +// alpha = 0.8f, +// modifier = Modifier +// .fillMaxSize() +// .blur(16.dp) +// ) AsyncImage( model = component.imageExample, contentDescription = null, @@ -243,22 +279,23 @@ fun CatalogSingleComponentContent( if (usableComponentsState != null) { when(usableComponentsState) { is UiState.Success -> { - LazyVerticalGrid( - columns = GridCells.Fixed( - 2 - ), - horizontalArrangement = Arrangement.spacedBy(16.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - modifier = Modifier - .height(144.dp), - ) { - usableComponentsState.data?.smallParts?.size?.let { - items(it) { index -> + usableComponentsState.data?.smallParts?.size?.let { + LazyVerticalGrid( + columns = GridCells.Fixed( + 2 + ), + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + modifier = Modifier + .height((it * 72).dp), + ) { + items(usableComponentsState.data.smallParts.size) { index -> currentlyClickedUsableComponent = index updateUsableComponentsList(usableComponentsState.data.smallParts) UsableComponentItem( onClick = { + isBottomSheetOpen = true coroutineScope.launch { modalSheetState.show() } @@ -266,8 +303,8 @@ fun CatalogSingleComponentContent( usableComponent = usableComponentsState.data.smallParts[index] ) } - } + } } } is UiState.Error -> { @@ -309,82 +346,89 @@ fun CatalogSingleComponentContent( } - if (relatedArticleListState != null) { - when(relatedArticleListState) { - is UiState.Loading -> { - Box( - modifier = Modifier - .height(100.dp) - .fillMaxWidth(), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() - } + if (relatedArticleListState != null) { + when(relatedArticleListState) { + is UiState.Loading -> { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() } - is UiState.Error -> { - Box( - modifier = Modifier - .height(100.dp) - .fillMaxWidth(), - contentAlignment = Alignment.Center - ) { - Text( - text = "Fail to fetch article", - style = MaterialTheme.typography.labelSmall, - color = Color.Red - ) - } + } + is UiState.Error -> { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + Text( + text = "Fail to fetch article", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) } - is UiState.Success -> { - val articleList = relatedArticleListState.data?.articleList + } + is UiState.Success -> { + val articleList = relatedArticleListState.data?.articleList - if (articleList?.isNotEmpty() == true) { - LazyRow( - contentPadding = PaddingValues(horizontal = 16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp), - modifier = Modifier.fillMaxWidth() - ) { - relatedArticleListState.data.articleList.let { - if (it.isNotEmpty()) { - items( - count = it.size, - ) { index -> - articleList.get(index)?.let { it1 -> - ArticleCardBig( - modifier = Modifier - .width(150.dp), - article = it1 - ) - } + if (articleList?.isNotEmpty() == true) { + LazyRow( + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier.fillMaxWidth() + ) { + relatedArticleListState.data.articleList.let { + if (it.isNotEmpty()) { + items( + count = it.size, + ) { index -> + articleList.get(index)?.let { it1 -> + ArticleCardBig( + modifier = Modifier + .width(150.dp) + .clickable { + it1.id?.let { it2 -> + navigateToSingleArticle( + it2 + ) + } + }, + article = it1 + ) } } } } - } else { + } + } else { + Box( + modifier = Modifier + .fillMaxWidth() + .height(100.dp), + contentAlignment = Alignment.Center + ) { Box( modifier = Modifier - .fillMaxWidth() - .height(100.dp), - contentAlignment = Alignment.Center - ) { - Box( - modifier = Modifier - .border( - width = 1.dp, - color = Color.Red, - shape = RoundedCornerShape(20.dp) - ) - .padding(8.dp) - - ) { - Text( - text = "There's no related article", - style = MaterialTheme.typography.labelSmall, - color = Color.Red + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) ) - } + .padding(8.dp) + + ) { + Text( + text = "There's no related article", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) } } + } } } } @@ -424,7 +468,8 @@ fun CatalogSingleComponentScreenPreview() { usableComponentList = emptyList(), updateUsableComponentsList = {}, relatedArticleListState = UiState.Loading(), - updateRelatedArticleListState = {} + updateRelatedArticleListState = {}, + navigateToSingleArticle = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt index 3ea1a06..75efa1d 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt @@ -4,15 +4,18 @@ import android.net.Uri import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.grid.GridCells @@ -25,26 +28,35 @@ import androidx.compose.material.ModalBottomSheetLayout import androidx.compose.material.ModalBottomSheetValue import androidx.compose.material.rememberModalBottomSheetState import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.* +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.blur import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavHostController import coil.compose.AsyncImage +import com.capstone.techwasmark02.R import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.DetectionsResultResponse import com.capstone.techwasmark02.data.remote.response.Prediction @@ -52,13 +64,11 @@ import com.capstone.techwasmark02.data.remote.response.SmallPart import com.capstone.techwasmark02.data.remote.response.UsableComponentsResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.ArticleCardBig -import com.capstone.techwasmark02.ui.component.DefaultButton import com.capstone.techwasmark02.ui.component.DefaultTopBar import com.capstone.techwasmark02.ui.component.DetectionsResultBox -import com.capstone.techwasmark02.ui.component.DetectionsResultSaveBottomSheet -import com.capstone.techwasmark02.ui.component.InverseButton import com.capstone.techwasmark02.ui.component.UsableComponentBottomSheet import com.capstone.techwasmark02.ui.component.UsableComponentItem +import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory @@ -69,7 +79,8 @@ import kotlinx.coroutines.launch fun DetectionResultScreen( stringUri: String, detectionResult: String, - viewModel: DetectionResultScreenViewModel = hiltViewModel() + viewModel: DetectionResultScreenViewModel = hiltViewModel(), + navController: NavHostController ) { val selectedPrediction by viewModel.selectedPrediction.collectAsState() @@ -87,6 +98,8 @@ fun DetectionResultScreen( currentlySelectedUsableComponentList = currentlySelectedUsableComponentList, updateCurrentlySelectedUsableComponentList = { viewModel.updateCurrentlySelectedUsableComponentList(it) }, relatedArticleListState = relatedArticleListState, + navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") }, + navigateToMain = { navController.navigate(Screen.Main.route) } ) } @@ -102,6 +115,8 @@ fun DetectionResultContent( currentlySelectedUsableComponentList: List, updateCurrentlySelectedUsableComponentList: (List) -> Unit, relatedArticleListState: List>?, + navigateToSingleArticle: (idArticle: Int) -> Unit, + navigateToMain: () -> Unit ) { val coroutineScope = rememberCoroutineScope() val modalSheetState = rememberModalBottomSheetState( @@ -130,6 +145,23 @@ fun DetectionResultContent( mutableStateOf(0) } + var isBottomSheetOpen by remember { + mutableStateOf(false) + } + + BackHandler( + enabled = true + ) { + if (isBottomSheetOpen) { + coroutineScope.launch { + modalSheetState.hide() + isBottomSheetOpen = false + } + } else { + navigateToMain() + } + } + ModalBottomSheetLayout( sheetState = modalSheetState, sheetShape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp), @@ -147,91 +179,176 @@ fun DetectionResultContent( topBar = { DefaultTopBar( pageTitle = "Result", - onClickNavigationIcon = {} + onClickNavigationIcon = { + navigateToMain() + } ) } ) { innerPadding -> val scrollState = rememberScrollState() - Column( + Box( modifier = Modifier - .verticalScroll(scrollState) - .padding(innerPadding) - .padding(bottom = 20.dp) + .fillMaxSize() ) { - Box( + Column( modifier = Modifier + .verticalScroll(scrollState) + .padding(innerPadding) + .padding(bottom = 20.dp) ) { Box( modifier = Modifier - .fillMaxWidth() - .height(500.dp) - .clip( - RoundedCornerShape( - bottomStart = 20.dp, - bottomEnd = 20.dp - ) - ) - .background(MaterialTheme.colorScheme.primary), ) { - AsyncImage( - model = photoUri, - contentDescription = null, - contentScale = ContentScale.Crop, - alpha = 0.8f, + Box( modifier = Modifier - .fillMaxSize() - .blur(16.dp) - ) - AsyncImage( - model = photoUri, - contentDescription = null, - contentScale = ContentScale.Fit, + .fillMaxWidth() + .height(500.dp) + .clip( + RoundedCornerShape( + bottomStart = 20.dp, + bottomEnd = 20.dp + ) + ) + .background(MaterialTheme.colorScheme.primary), + ) { + AsyncImage( + model = photoUri, + contentDescription = null, + contentScale = ContentScale.Crop, + alpha = 0.8f, + modifier = Modifier + .fillMaxSize() + .blur(16.dp) + ) + AsyncImage( + model = photoUri, + contentDescription = null, + contentScale = ContentScale.Fit, + modifier = Modifier + .fillMaxSize() + ) + } + + Column( modifier = Modifier - .fillMaxSize() - ) + .fillMaxWidth() + .padding(top = 402.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "Detected as", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onPrimary + ) + + if (detectionsResultObj != null) { + DetectionsResultBox( + modifier = Modifier + .padding(horizontal = 20.dp), + predictionList = detectionsResultObj.predictions, + updateSelectedPrediction = updateSelectedPrediction + ) + } + + } } Column( modifier = Modifier - .fillMaxWidth() - .padding(top = 402.dp), - horizontalAlignment = Alignment.CenterHorizontally + .padding(horizontal = 20.dp) + .padding(top = 28.dp) ) { Text( - text = "Detected as", + text = "Usable Components", style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onPrimary + color = MaterialTheme.colorScheme.onBackground ) - if (detectionsResultObj != null) { - DetectionsResultBox( + Spacer(modifier = Modifier.height(8.dp)) + + if (usableComponentsListState != null) { + val currentlySelectedPrediction = usableComponentsListState[selectedPrediction] + when(currentlySelectedPrediction) { + is UiState.Loading -> { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is UiState.Success -> { + val usableComponentList = currentlySelectedPrediction.data?.smallParts + + usableComponentList?.size?.let { + LazyVerticalGrid( + columns = GridCells.Fixed( + 2 + ), + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + modifier = Modifier.height((it * 72).dp) + ) { + items(usableComponentList.size) {index -> + currentlyClickedUsableComponent = index + updateCurrentlySelectedUsableComponentList(usableComponentList) + + UsableComponentItem( + onClick = { + isBottomSheetOpen = true + coroutineScope.launch { + modalSheetState.show() + } + }, + usableComponent = usableComponentList[index] + ) + } + } + } + } + is UiState.Error -> { + Box( + modifier = Modifier + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + Text( + text = "Fail to fetch usable component", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + } + } else { + Box( modifier = Modifier - .padding(horizontal = 20.dp), - predictionList = detectionsResultObj.predictions, - updateSelectedPrediction = updateSelectedPrediction - ) + .height(100.dp) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } } - } - } + Spacer(modifier = Modifier.height(28.dp)) - Column( - modifier = Modifier - .padding(horizontal = 20.dp) - .padding(top = 28.dp) - ) { - Text( - text = "Usable Components", - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onBackground - ) + Text( + text = "Related Articles", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground + ) - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(8.dp)) + } - if (usableComponentsListState != null) { - val currentlySelectedPrediction = usableComponentsListState[selectedPrediction] - when(currentlySelectedPrediction) { + if (relatedArticleListState != null) { + val currentSelectedArticleListState = relatedArticleListState[selectedPrediction] + when(currentSelectedArticleListState) { is UiState.Loading -> { Box( modifier = Modifier @@ -242,34 +359,6 @@ fun DetectionResultContent( CircularProgressIndicator() } } - is UiState.Success -> { - LazyVerticalGrid( - columns = GridCells.Fixed( - 2 - ), - horizontalArrangement = Arrangement.spacedBy(16.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - modifier = Modifier.height(132.dp) - ) { - val usableComponentList = currentlySelectedPrediction.data?.smallParts - - usableComponentList?.size?.let { - items(it) {index -> - currentlyClickedUsableComponent = index - updateCurrentlySelectedUsableComponentList(usableComponentList) - - UsableComponentItem( - onClick = { - coroutineScope.launch { - modalSheetState.show() - } - }, - usableComponent = usableComponentList[index] - ) - } - } - } - } is UiState.Error -> { Box( modifier = Modifier @@ -278,12 +367,68 @@ fun DetectionResultContent( contentAlignment = Alignment.Center ) { Text( - text = "Fail to fetch usable component", + text = "Fail to fetch article", style = MaterialTheme.typography.labelSmall, color = Color.Red ) } } + is UiState.Success -> { + val articleList = relatedArticleListState[selectedPrediction].data?.articleList + + if (articleList?.isNotEmpty() == true) { + LazyRow( + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier.fillMaxWidth() + ) { + relatedArticleListState[selectedPrediction].data?.articleList?.let { + items( + count = it.size, + ) { index -> + articleList[index]?.let { it1 -> + ArticleCardBig( + modifier = Modifier + .width(150.dp) + .clickable { + it1.id?.let { it2 -> + navigateToSingleArticle( + it2 + ) + } + }, + article = it1 + ) + } + } + } + } + } else { + Box( + modifier = Modifier + .fillMaxWidth() + .height(100.dp), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) + + ) { + Text( + text = "There's no related article", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + } + } } } else { Box( @@ -296,139 +441,153 @@ fun DetectionResultContent( } } - Spacer(modifier = Modifier.height(28.dp)) - - Text( - text = "Related Articles", - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onBackground - ) + Spacer(modifier = Modifier.height(80.dp)) - Spacer(modifier = Modifier.height(8.dp)) } - if (relatedArticleListState != null) { - val currentSelectedArticleListState = relatedArticleListState[selectedPrediction] - when(currentSelectedArticleListState) { - is UiState.Loading -> { - Box( - modifier = Modifier - .height(100.dp) - .fillMaxWidth(), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() - } - } - is UiState.Error -> { - Box( - modifier = Modifier - .height(100.dp) - .fillMaxWidth(), - contentAlignment = Alignment.Center - ) { - Text( - text = "Fail to fetch article", - style = MaterialTheme.typography.labelSmall, - color = Color.Red - ) - } - } - is UiState.Success -> { - val articleList = relatedArticleListState[selectedPrediction].data?.articleList - - if (articleList?.isNotEmpty() == true) { - LazyRow( - contentPadding = PaddingValues(horizontal = 16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp), - modifier = Modifier.fillMaxWidth() - ) { - relatedArticleListState[selectedPrediction].data?.articleList?.let { - items( - count = it.size, - ) { index -> - articleList[index]?.let { it1 -> - ArticleCardBig( - modifier = Modifier - .width(150.dp), - article = it1 - ) - } - } - } - } - } else { - Box( - modifier = Modifier - .fillMaxWidth() - .height(100.dp), - contentAlignment = Alignment.Center - ) { - Box( - modifier = Modifier - .border( - width = 1.dp, - color = Color.Red, - shape = RoundedCornerShape(20.dp) - ) - .padding(8.dp) + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp) + ) { + Spacer(modifier = Modifier.weight(1f)) - ) { - Text( - text = "There's no related article", - style = MaterialTheme.typography.labelSmall, - color = Color.Red - ) - } - } - } - } - } - } else { - Box( - modifier = Modifier - .height(100.dp) - .fillMaxWidth(), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() - } + ThrowNSellButton() } + } + } - Spacer(modifier = Modifier.height(28.dp)) + } +} - Column( +@Composable +fun ThrowNSellButton() { + Row( + modifier = Modifier + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Button( + onClick = { /*TODO*/ }, + modifier = Modifier + .weight(1f) + .padding(vertical = 18.dp) +// .border( +// width = 2.dp, +// color = MaterialTheme.colorScheme.primary, +// shape = RoundedCornerShape(20.dp) +// ) + .shadow( + elevation = 8.dp, + shape = RoundedCornerShape(20.dp) + ), + colors = ButtonDefaults.buttonColors( + containerColor = Color.White, + contentColor = MaterialTheme.colorScheme.primary + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Start + ) { + Icon( + painter = painterResource(id = R.drawable.ic_trash_outline), + contentDescription = null, modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 40.dp) - ) { - DefaultButton(contentText = "Drop Point", modifier = Modifier.fillMaxWidth()) + .size(26.dp) + ) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.width(4.dp)) - InverseButton(contentText = "Go to Forum", modifier = Modifier.fillMaxWidth()) - } + Text( + text = "Throw it", + style = MaterialTheme.typography.labelMedium, + modifier = Modifier + .padding(top = 4.dp) + ) + } + } + + Spacer(modifier = Modifier.width(8.dp)) + + Button( + onClick = { /*TODO*/ }, + modifier = Modifier + .weight(1f) + .padding(vertical = 18.dp) +// .border( +// width = 2.dp, +// color = MaterialTheme.colorScheme.primary, +// shape = RoundedCornerShape(20.dp) +// ) + .shadow( + elevation = 8.dp, + shape = RoundedCornerShape(20.dp) + ), + colors = ButtonDefaults.buttonColors( + containerColor = Color.White, + contentColor = MaterialTheme.colorScheme.primary + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Start + ) { + Icon( + painter = painterResource(id = R.drawable.ic_sell), + contentDescription = null, + modifier = Modifier + .size(26.dp) + ) + + Spacer(modifier = Modifier.width(4.dp)) + Text( + text = "Sell it", + style = MaterialTheme.typography.labelMedium, + modifier = Modifier + .padding(top = 4.dp) + ) } } } } -@Preview +//@Preview +//@Composable +//fun DetectionResultContentPreview() { +// TechwasMark02Theme { +// DetectionResultContent( +// stringUri = "", +// detectionResult = "", +// selectedPrediction = 0, +// updateSelectedPrediction = {}, +// usableComponentsListState = emptyList(), +// fetchAllUsableComponents = {}, +// currentlySelectedUsableComponentList = emptyList(), +// updateCurrentlySelectedUsableComponentList = {}, +// relatedArticleListState = emptyList(), +// navigateToSingleArticle = {}, +// navigateToMain = {} +// ) +// } +//} + +@Preview(showBackground = true) @Composable -fun DetectionResultContentPreview() { +fun ThrowNSellButtonPreview() { TechwasMark02Theme { - DetectionResultContent( - stringUri = "", - detectionResult = "", - selectedPrediction = 0, - updateSelectedPrediction = {}, - usableComponentsListState = emptyList(), - fetchAllUsableComponents = {}, - currentlySelectedUsableComponentList = emptyList(), - updateCurrentlySelectedUsableComponentList = {}, - relatedArticleListState = emptyList() - ) + Box( + modifier = Modifier + .padding(20.dp) + ) { + ThrowNSellButton() + } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt new file mode 100644 index 0000000..3deb400 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt @@ -0,0 +1,22 @@ +package com.capstone.techwasmark02.ui.screen.forum + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color + +@Composable +fun ForumScreen() { + ForumContent() +} + +@Composable +fun ForumContent() { + Box( + modifier = Modifier + .fillMaxSize() + .background(Color.LightGray) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index c8f47f5..f09981c 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -4,7 +4,6 @@ import android.Manifest import android.content.Context import android.content.pm.PackageManager import android.util.Log -import android.widget.Space import androidx.activity.compose.ManagedActivityResultLauncher import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts @@ -59,13 +58,18 @@ import com.capstone.techwasmark02.R import com.capstone.techwasmark02.data.remote.response.ArticleList import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.ui.common.UiState -import com.capstone.techwasmark02.ui.component.AboutUsBox import com.capstone.techwasmark02.ui.component.ArticleCardBig -import com.capstone.techwasmark02.ui.component.DefaultBottomBar import com.capstone.techwasmark02.ui.component.FeatureBox -import com.capstone.techwasmark02.ui.componentType.BottomBarItemType +import com.capstone.techwasmark02.ui.component.FeatureBoxLarge import com.capstone.techwasmark02.ui.componentType.FeatureBoxType -import com.capstone.techwasmark02.ui.navigation.Screen.* +import com.capstone.techwasmark02.ui.navigation.Screen +import com.capstone.techwasmark02.ui.navigation.Screen.Article +import com.capstone.techwasmark02.ui.navigation.Screen.Camera +import com.capstone.techwasmark02.ui.navigation.Screen.Catalog +import com.capstone.techwasmark02.ui.navigation.Screen.Forum +import com.capstone.techwasmark02.ui.navigation.Screen.Home +import com.capstone.techwasmark02.ui.navigation.Screen.Maps +import com.capstone.techwasmark02.ui.navigation.Screen.Profile import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import com.capstone.techwasmark02.ui.theme.yellow import kotlin.math.absoluteValue @@ -86,6 +90,7 @@ fun HomeScreen( navigateToProfile = { navController.navigate(Profile.route) }, navigateToCatalog = { navController.navigate(Catalog.route) }, navigateToMaps = { navController.navigate(Maps.route) }, + navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") }, latestArticleState = latestArticleState ) } @@ -100,6 +105,7 @@ fun HomeContent( navigateToProfile: () -> Unit, navigateToCatalog: () -> Unit, navigateToMaps: () -> Unit, + navigateToSingleArticle: (idArticle: Int) -> Unit, latestArticleState: UiState? ) { @@ -141,19 +147,24 @@ fun HomeContent( ) { Row( modifier = Modifier, - verticalAlignment = Alignment.Bottom ) { - Image( - modifier = Modifier.size(24.dp, 27.dp), - painter = painterResource(id = R.drawable.logo_techwaste), - contentDescription = null - ) + Column( + modifier = Modifier + .fillMaxHeight(), + + ) { + Image( + modifier = Modifier.size(24.dp, 27.dp), + painter = painterResource(id = R.drawable.logo_techwaste), + contentDescription = null + ) + } Text( text = "Techwas", modifier = Modifier .padding(start = 4.dp) .offset(y = 5.dp), - style = MaterialTheme.typography.labelLarge, + style = MaterialTheme.typography.titleMedium, color = Color.White ) } @@ -208,10 +219,11 @@ fun HomeContent( Row( modifier = Modifier - .fillMaxWidth(), + .fillMaxWidth() + .padding(horizontal = 16.dp), ) { Spacer(modifier = Modifier.weight(1f)) - FeatureBox( + FeatureBoxLarge( featureBoxType = FeatureBoxType.Detection, onClick = { checkAndRequestCameraPermission( @@ -221,8 +233,6 @@ fun HomeContent( ) } ) - Spacer(modifier = Modifier.weight(3f)) - FeatureBox(featureBoxType = FeatureBoxType.Catalog, onClick = navigateToCatalog) Spacer(modifier = Modifier.weight(1f)) // DetectBox1() // DetectBox2() @@ -232,14 +242,13 @@ fun HomeContent( Row( modifier = Modifier - .fillMaxWidth(), + .fillMaxWidth() + .padding(horizontal = 16.dp), horizontalArrangement = Arrangement.SpaceBetween ) { - Spacer(modifier = Modifier.weight(1f)) FeatureBox(featureBoxType = FeatureBoxType.DropPoint, onClick = navigateToMaps) - Spacer(modifier = Modifier.weight(3f)) - AboutUsBox() Spacer(modifier = Modifier.weight(1f)) + FeatureBox(featureBoxType = FeatureBoxType.Catalog, onClick = navigateToCatalog) } Spacer(modifier = Modifier.height(titlePaddingTop)) @@ -271,9 +280,8 @@ fun HomeContent( Spacer(modifier = Modifier.height(titlePaddingBottom)) - val pagerState = rememberPagerState() - if (latestArticleState != null) { + when(latestArticleState) { is UiState.Loading -> { Box( @@ -297,11 +305,19 @@ fun HomeContent( } is UiState.Success -> { latestArticleState.data?.articleList?.size?.let { + + val pagerState = rememberPagerState( + initialPage = 0, + initialPageOffsetFraction = 0f, + ) + HorizontalPager( pageCount = it, state = pagerState, contentPadding = PaddingValues(horizontal = 56.dp), - modifier = Modifier.fillMaxWidth().height(180.dp) + modifier = Modifier + .fillMaxWidth() + .height(180.dp) ) { page -> val articleList = latestArticleState.data.articleList @@ -319,7 +335,10 @@ fun HomeContent( lerp( start = 0.85f, stop = 1f, - fraction = 1f - pageOffset.coerceIn(0f, 1f) + fraction = 1f - pageOffset.coerceIn( + 0f, + 1f + ) ).also { scale -> scaleX = scale scaleY = scale @@ -327,8 +346,18 @@ fun HomeContent( alpha = lerp( start = 0.5f, stop = 1f, - fraction = 1f - pageOffset.coerceIn(0f, 1f) + fraction = 1f - pageOffset.coerceIn( + 0f, + 1f + ) ) + } + .clickable { + it1.id?.let { it2 -> + navigateToSingleArticle( + it2 + ) + } }, article = it1 ) @@ -390,19 +419,19 @@ fun HomeContent( } } - Column( - modifier = Modifier - .fillMaxSize() - ) { - Spacer(modifier = Modifier.weight(1f)) - DefaultBottomBar( - selectedType = BottomBarItemType.Home, - navigateToProfile = navigateToProfile, - navigateToForum = navigateToForum, - navigateToArticle = navigateToArticle, - navigateToHome = navigateToHome - ) - } +// Column( +// modifier = Modifier +// .fillMaxSize() +// ) { +// Spacer(modifier = Modifier.weight(1f)) +// DefaultBottomBar( +// selectedType = BottomBarItemType.Home, +// navigateToProfile = navigateToProfile, +// navigateToForum = navigateToForum, +// navigateToArticle = navigateToArticle, +// navigateToHome = navigateToHome +// ) +// } } } } @@ -434,6 +463,7 @@ fun HomeContentPreview() { navigateToProfile = {}, navigateToCatalog = {}, navigateToMaps = {}, + navigateToSingleArticle = {}, latestArticleState = UiState.Loading() ) } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/imageDetection/ImageDetectionScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/imageDetection/ImageDetectionScreen.kt index bfd39b3..1a191b1 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/imageDetection/ImageDetectionScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/imageDetection/ImageDetectionScreen.kt @@ -44,7 +44,6 @@ import androidx.compose.ui.unit.dp import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.viewmodel.compose.viewModel import coil.compose.AsyncImage import com.capstone.techwasmark02.R import com.capstone.techwasmark02.ui.common.UiState diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreen.kt new file mode 100644 index 0000000..34c1818 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreen.kt @@ -0,0 +1,71 @@ +package com.capstone.techwasmark02.ui.screen.main + +import android.app.Activity +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavHostController +import com.capstone.techwasmark02.ui.component.DefaultBottomBar +import com.capstone.techwasmark02.ui.componentType.BottomBarItemType +import com.capstone.techwasmark02.ui.screen.article.ArticleScreen +import com.capstone.techwasmark02.ui.screen.forum.ForumScreen +import com.capstone.techwasmark02.ui.screen.home.HomeScreen +import com.capstone.techwasmark02.ui.screen.profileUser.ProfileUserScreen + +@Composable +fun MainScreen( + navController: NavHostController, + viewModel: MainScreenViewModel = viewModel() +) { + + val selectedBottomBarType by viewModel.selectedBottomBarType.collectAsState() + val activity = LocalContext.current as Activity + + + BackHandler( + enabled = true, + onBack = { + if(selectedBottomBarType.pageIndex != 0) { + viewModel.updateSelectedBottomBartype(BottomBarItemType.Home) + } else { + activity.finish() + } + } + ) + + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.BottomCenter + ) { + + when(selectedBottomBarType) { + is BottomBarItemType.Home -> { + HomeScreen(navController = navController) + } + is BottomBarItemType.Forum -> { + ForumScreen() + } + is BottomBarItemType.Article -> { + ArticleScreen(navController = navController) + } + is BottomBarItemType.Profile -> { + ProfileUserScreen(navController = navController) + } + } + + DefaultBottomBar( + selectedType = selectedBottomBarType, + onClickBottomNavType = { + viewModel.updateSelectedBottomBartype(it) + }, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreenViewModel.kt new file mode 100644 index 0000000..6691882 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreenViewModel.kt @@ -0,0 +1,19 @@ +package com.capstone.techwasmark02.ui.screen.main + +import androidx.lifecycle.ViewModel +import com.capstone.techwasmark02.ui.componentType.BottomBarItemType +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +class MainScreenViewModel: ViewModel() { + + private val _selectedBottomBarType: MutableStateFlow = MutableStateFlow( + BottomBarItemType.Home + ) + val selectedBottomBarType = _selectedBottomBarType.asStateFlow() + + fun updateSelectedBottomBartype(newItemType: BottomBarItemType) { + _selectedBottomBarType.value = newItemType + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt new file mode 100644 index 0000000..cdcb828 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt @@ -0,0 +1,743 @@ +package com.capstone.techwasmark02.ui.screen.onBoarding + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavHostController +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.component.DefaultButton +import com.capstone.techwasmark02.ui.navigation.Screen +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import com.google.accompanist.pager.ExperimentalPagerApi +import com.google.accompanist.pager.HorizontalPager +import com.google.accompanist.pager.rememberPagerState +import kotlinx.coroutines.launch + +@Composable +fun OnBoardingScreen( + navController: NavHostController +) { + OnBoardingContent( + navigateToHome = { navController.navigate(Screen.Home.route) }, + navigateToSignUp = { navController.navigate(Screen.SignUp.route) }, + navigateToSignIn = { navController.navigate(Screen.SignIn.route) }, + navigateToMain = { navController.navigate(Screen.Main.route) } + ) +} + +@OptIn(ExperimentalPagerApi::class) +@Composable +fun OnBoardingContent( + navigateToHome: () -> Unit, + navigateToSignIn: () -> Unit, + navigateToSignUp: () -> Unit, + navigateToMain: () -> Unit +) { + val pageCount = 3 + val pagerState = rememberPagerState() + val coroutineScope = rememberCoroutineScope() + + Box( + modifier = Modifier + .fillMaxSize() + ) { + HorizontalPager( + count = pageCount, + state = pagerState + ) { page -> + when(page) { + 0 -> { + OnBoardingContentFirst() + } + 1 -> { + OnBoardingContentSecond() + } + 2 -> { + OnBoardingContentThird( + navigateToHome = navigateToHome, + navigateToSignIn = navigateToSignIn, + navigateToSignUp = navigateToSignUp, + navigateToMain = navigateToMain + ) + } + } + } + + Column( + modifier = Modifier + .fillMaxSize() + ) { + if (pagerState.currentPage != 2) { + Row( + modifier = Modifier + .fillMaxWidth() + .height(60.dp) + .padding(top = 28.dp) + .padding(horizontal = 28.dp), + horizontalArrangement = Arrangement.End, + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier, + contentAlignment = Alignment.Center + ) { + Button( + onClick = { + coroutineScope.launch { + pagerState.animateScrollToPage(2) + } + }, + modifier = Modifier + .height(28.dp) + .width(58.dp), + colors = ButtonDefaults.buttonColors( + containerColor = Color.LightGray + ) + ) { + Text( + text = "", + style = MaterialTheme.typography.bodySmall.copy( + fontFamily = FontFamily.Default, + fontSize = 10.sp, + fontWeight = FontWeight.Medium + ) + ) + } + + Text( + text = "Skip", + style = MaterialTheme.typography.bodySmall.copy( + fontSize = 10.sp, + fontWeight = FontWeight.Medium + ), + color = Color.Black.copy(alpha = 0.6f), + modifier = Modifier + .padding(top = 2.dp) + .clickable { + coroutineScope.launch { + pagerState.animateScrollToPage(2) + } + } + ) + } + + } + } + + Spacer(modifier = Modifier.weight(1f)) + + Row( + modifier = Modifier + .fillMaxWidth() + .height(60.dp) + .padding(bottom = 28.dp) + .padding(horizontal = 28.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Spacer(modifier = Modifier.weight(1f)) + + Row( + modifier = Modifier + .width(170.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + val bulletColor = Color.LightGray.copy(alpha = 0.8f) + + Row( + modifier = Modifier + .weight(1f), + horizontalArrangement = Arrangement.Start + ) { + + if (pagerState.currentPage != 0) { + IconButton( + onClick = { + coroutineScope.launch { + pagerState.animateScrollToPage(pagerState.currentPage - 1) + } + }, + modifier = Modifier + .background(Color.Transparent) + ) { + Box( + modifier = Modifier + .size(30.dp) + .clip(CircleShape) + .background(bulletColor), + contentAlignment = Alignment.Center + ) { + Icon( + painter = painterResource(id = R.drawable.ic_arrow_left), + contentDescription = null, + tint = Color.Black.copy(alpha = 0.4f) + ) + } + } + } + } + + + repeat(pageCount) { iteration -> + val color = if (pagerState.currentPage == iteration) Color(0xffFFDE59) else bulletColor + + val size = if (pagerState.currentPage == iteration) 14.dp else 10.dp + + Box( + modifier = Modifier + .padding(4.dp) + .clip(CircleShape) + .background(color) + .size(size) + ) + } + + Row( + modifier = Modifier + .weight(1f), + horizontalArrangement = Arrangement.End + ) { + if (pagerState.currentPage != 2) { + IconButton( + onClick = { + coroutineScope.launch { + pagerState.animateScrollToPage(pagerState.currentPage + 1) + } + }, + modifier = Modifier + .background(Color.Transparent) + ) { + Box( + modifier = Modifier + .size(30.dp) + .clip(CircleShape) + .background(bulletColor), + contentAlignment = Alignment.Center + ) { + Icon( + painter = painterResource(id = R.drawable.ic_arrow_right), + contentDescription = null, + tint = Color.Black.copy(alpha = 0.4f) + ) + } + } + } + } + } + + Spacer(modifier = Modifier.weight(1f)) + + } + } + } +} + +@Composable +fun OnBoardingContentFirst() { + Box( + modifier = Modifier + .fillMaxSize() + + ) { + Column( + modifier = Modifier + .fillMaxSize(), + verticalArrangement = Arrangement.SpaceBetween + ) { + Row( + modifier = Modifier + .fillMaxWidth() + ) { + Image( + painter = painterResource( id = R.drawable.img_onboarding_ripple_peach_left, ), + contentDescription = null, + modifier = Modifier + .height(200.dp) + .width(240.dp) + ) + } + + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + Image( + painter = painterResource(id = R.drawable.img_onboarding_ripple_purple_right), + contentDescription = null, + modifier = Modifier + .height(200.dp) + .width(240.dp) + ) + } + } + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 120.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + + Spacer(modifier = Modifier.height(40.dp)) + + Image( + painter = painterResource(id = R.drawable.img_logo_onboarding), + contentDescription = null, + modifier = Modifier + .size(182.dp) + ) + + Spacer(modifier = Modifier.height(28.dp)) + + Text( + text = "Techwaste", + style = MaterialTheme.typography.headlineMedium, + color = MaterialTheme.colorScheme.primary + ) + + Spacer(modifier = Modifier.height(20.dp)) + + Text( + text = "It's an app developed by a\nteam of six students, aiming to\nenhance e-waste disposal!", + style = MaterialTheme.typography.bodyLarge, + textAlign = TextAlign.Center, + color = MaterialTheme.colorScheme.onBackground.copy( + alpha = 0.7f + ) + ) + + Spacer(modifier = Modifier.weight(1f)) + } + } +} + +@Composable +fun OnBoardingContentSecond() { + + Box( + modifier = Modifier + .fillMaxSize() + ) { + + Column( + modifier = Modifier + .fillMaxSize(), + verticalArrangement = Arrangement.SpaceBetween + ) { + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + Image( + painter = painterResource(id = R.drawable.img_onboarding_ripple_peach_right), + contentDescription = null, + modifier = Modifier + .height(200.dp) + .width(240.dp) + ) + } + + Row( + modifier = Modifier + .fillMaxWidth() + ) { + Image( + painter = painterResource(id = R.drawable.img_onboarding_ripple_purple_left), + contentDescription = null, + modifier = Modifier + .height(200.dp) + .width(240.dp) + ) + } + } + + Column( + modifier = Modifier + .fillMaxSize() + .height(IntrinsicSize.Max) + .padding(top = 80.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + + val boxHeight = 98.dp + + Box( + modifier = Modifier, + contentAlignment = Alignment.Center + ) { + Image( + painter = painterResource(id = R.drawable.img_feature_detect_box), + contentDescription = null, + modifier = Modifier + .width(92.dp) + .height(boxHeight) + ) + Image( + painter = painterResource(id = R.drawable.img_feature_detect_illustration), + contentDescription = null, + modifier = Modifier + .width(134.dp) + .height(127.dp) + ) + Image( + painter = painterResource(id = R.drawable.img_feature_detect_frame), + contentDescription = null, + modifier = Modifier + .size(100.dp) + ) + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = (boxHeight + 40.dp)), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "E-waste Classification", + style = MaterialTheme.typography.labelLarge.copy( + fontWeight = FontWeight.SemiBold + ) + ) + } + } + + Text( + text = "Upload an image of your e-waste and\nTechwaste will determine where it belongs", + style = MaterialTheme.typography.bodySmall.copy( + fontSize = 10.sp, + color = MaterialTheme.colorScheme.onBackground.copy( + alpha = 0.75f + ) + ), + textAlign = TextAlign.Center + ) + +// Spacer(modifier = Modifier.height(20.dp)) + + Row( + modifier = Modifier + .fillMaxWidth() + .height(IntrinsicSize.Max) + .padding(horizontal = 20.dp) + ) { + Column( + modifier = Modifier + .width(170.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Box( + modifier = Modifier + .height(180.dp) + .padding(bottom = 8.dp), + contentAlignment = Alignment.BottomCenter, + ) { + Image( + painter = painterResource(id = R.drawable.img_feature_article_box), + contentDescription = null, + modifier = Modifier + .height(98.dp) + .width(92.dp) + ) + + Image( + painter = painterResource(id = R.drawable.img_feature_article_illustration), + contentDescription = null, + modifier = Modifier + .size(145.dp) + ) + } + + Text( + text = "Articles", + style = MaterialTheme.typography.labelLarge.copy( + fontWeight = FontWeight.SemiBold + ), + ) + + Text( + text = "Know more about your\ne-waste and find out how to\nget fid of it properly", + style = MaterialTheme.typography.bodySmall.copy( + fontSize = 10.sp, + color = MaterialTheme.colorScheme.onBackground.copy( + alpha = 0.75f + ) + ), + textAlign = TextAlign.Center + ) + } + + Spacer(modifier = Modifier.weight(1f)) + + Box( + modifier = Modifier + .fillMaxHeight() + .width(170.dp), + contentAlignment = Alignment.TopCenter + ) { + Box( + modifier = Modifier + .height(180.dp) + .fillMaxWidth() + .padding(bottom = 8.dp), + contentAlignment = Alignment.BottomCenter, + ) { + Image( + painter = painterResource(id = R.drawable.img_feature_forum_box), + contentDescription = null, + modifier = Modifier + .height(98.dp) + .width(92.dp) + ) + + } + + Column( + modifier = Modifier + .fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer(modifier = Modifier.height(48.dp)) + Image( + painter = painterResource(id = R.drawable.img_feature_forum_illustration), + contentDescription = null, + modifier = Modifier + .height(166.dp) + .width(166.dp) + ) + } + + + Column( + modifier = Modifier + .fillMaxHeight() + .fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer(modifier = Modifier.weight(1f)) + + Text( + text = "Forum", + style = MaterialTheme.typography.labelLarge.copy( + fontWeight = FontWeight.SemiBold + ), + ) + + Text( + text = "Ask questions, share your\nthoughts, drop any interesting\nfacts about e-waste", + style = MaterialTheme.typography.bodySmall.copy( + fontSize = 10.sp, + color = MaterialTheme.colorScheme.onBackground.copy( + alpha = 0.75f + ) + ), + textAlign = TextAlign.Center + ) + } + } + } + } + } +} + +@Composable +fun OnBoardingContentThird( + navigateToHome: () -> Unit, + navigateToSignIn: () -> Unit, + navigateToSignUp: () -> Unit, + navigateToMain: () -> Unit +) { + Box( + modifier = Modifier + .fillMaxSize() + ) { + + Column( + modifier = Modifier + .fillMaxSize(), + verticalArrangement = Arrangement.SpaceBetween + ) { + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.Start + ) { + Image( + painter = painterResource(id = R.drawable.img_onboarding_ripple_peach_left), + contentDescription = null, + modifier = Modifier + .height(200.dp) + .width(240.dp) + ) + } + + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + Image( + painter = painterResource(id = R.drawable.img_onboarding_ripple_purple_right), + contentDescription = null, + modifier = Modifier + .height(200.dp) + .width(240.dp) + ) + } + } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(top = 120.dp, bottom = 100.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceBetween + ) { + + Column( + modifier = Modifier + .fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Image( + painter = painterResource(id = R.drawable.img_logo_onboarding_nooutline_green), + contentDescription = null, + modifier = Modifier + .height(164.dp) + .width(170.dp) + ) + + Spacer(modifier = Modifier.height(18.dp)) + + Text( + text = "Help us take care of\nelectronics waste.", + style = MaterialTheme.typography.headlineMedium, + color = MaterialTheme.colorScheme.primary, + textAlign = TextAlign.Center + ) + + Text( + text = "What would you like to do?", + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onBackground.copy( + alpha = 0.7f + ), + textAlign = TextAlign.Center + ) + } + + Spacer(modifier = Modifier.height(48.dp)) + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 28.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + DefaultButton( + contentText = "Let's get started", + modifier = Modifier + .height(50.dp) + .fillMaxWidth(), + buttonColors = ButtonDefaults.buttonColors( + containerColor = Color(0xffF7B595) + ), + onClick = navigateToSignUp + ) + + Spacer(modifier = Modifier.height(16.dp)) + + DefaultButton( + contentText = "Already have account", + modifier = Modifier + .height(50.dp) + .fillMaxWidth(), + buttonColors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.tertiary, + contentColor = Color.Black.copy( + alpha = 0.5f + ) + ), + onClick = navigateToSignIn + ) + + } + } + } +} + +@Preview(showBackground = true) +@Composable +fun OnBoardingScreenPreview() { + TechwasMark02Theme { + OnBoardingContent( + navigateToSignIn = {}, + navigateToSignUp = {}, + navigateToHome = {}, + navigateToMain = {} + ) + } +} + +@Preview(showBackground = true) +@Composable +fun OnBoardingContentFirstPreview() { + TechwasMark02Theme { + OnBoardingContentFirst() + } +} + +@Preview( showBackground = true) +@Composable +fun OnBoardingContentSecondPreview() { + TechwasMark02Theme { + OnBoardingContentSecond() + } +} + +@Preview(showBackground = true) +@Composable +fun OnBoardingContentThirdPreview() { + TechwasMark02Theme { + OnBoardingContentThird( + navigateToSignUp = {}, + navigateToHome = {}, + navigateToSignIn = {}, + navigateToMain = {} + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt index fad59ba..02410a5 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt @@ -55,10 +55,6 @@ fun ProfileUserScreen( navController: NavHostController ) { ProfileUserContent( - navigateToHome = { navController.navigate(Screen.Home.route) }, - navigateToArticle = { navController.navigate(Screen.Article.route) }, - navigateToForum = { navController.navigate(Screen.Forum.route) }, - navigateToProfile = { navController.navigate(Screen.Profile.route) }, navigateToSetting = { navController.navigate(Screen.Setting.route) }, ) } @@ -66,10 +62,6 @@ fun ProfileUserScreen( @OptIn(ExperimentalMaterial3Api::class) @Composable fun ProfileUserContent( - navigateToHome: () -> Unit, - navigateToForum: () -> Unit, - navigateToArticle: () -> Unit, - navigateToProfile: () -> Unit, navigateToSetting: () -> Unit, ) { @@ -91,15 +83,6 @@ fun ProfileUserContent( } ) }, - bottomBar = { - DefaultBottomBar( - selectedType = BottomBarItemType.Profile, - navigateToProfile = navigateToProfile, - navigateToForum = navigateToForum, - navigateToArticle = navigateToArticle, - navigateToHome = navigateToHome - ) - } ) { innerPadding -> val scrollState = rememberScrollState() @@ -233,10 +216,6 @@ fun ProfileUserContent( fun ProfileUserScreenPreview() { TechwasMark02Theme { ProfileUserContent( - navigateToHome = {}, - navigateToArticle = {}, - navigateToForum = {}, - navigateToProfile = {}, navigateToSetting = {}, ) } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt index faf1b82..b7d98ea 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt @@ -1,5 +1,6 @@ package com.capstone.techwasmark02.ui.screen.signIn +import android.widget.Toast import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -22,10 +23,12 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavHostController import com.capstone.techwasmark02.data.model.UserLoginInfo import com.capstone.techwasmark02.data.model.UserSession import com.capstone.techwasmark02.data.remote.response.UserLoginResponse @@ -34,22 +37,26 @@ import com.capstone.techwasmark02.ui.component.DefaultButton import com.capstone.techwasmark02.ui.component.DefaultTextField import com.capstone.techwasmark02.ui.component.PasswordTextField import com.capstone.techwasmark02.ui.component.SignInBanner +import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @Composable fun SignInScreen( viewModel: SignInScreenViewModel = hiltViewModel(), + navController: NavHostController ) { val userToSignInState by viewModel.userToSignInState.collectAsState() val userToSignInInfo by viewModel.userToSignInInfo.collectAsState() - val userSessionState by viewModel.userSessionState.collectAsState() +// val userSessionState by viewModel.userSessionState.collectAsState() SignInContent( userToSignInInfo = userToSignInInfo, updateUserLoginInfo = { viewModel.updateUserSignInInfo(it) }, userToSignInState = userToSignInState, signInUser = { viewModel.signInUser() }, - userSessionState = userSessionState + saveUserSession = { viewModel.saveUserSession() }, + navigateToMain = { navController.navigate(Screen.Main.route) } +// userSessionState = userSessionState ) } @@ -59,13 +66,17 @@ fun SignInContent( updateUserLoginInfo: (UserLoginInfo) -> Unit, userToSignInState: UiState?, signInUser: () -> Unit, - userSessionState: UserSession? + saveUserSession: () -> Unit, + navigateToMain: () -> Unit +// userSessionState: UserSession? ) { var showPassword by remember { mutableStateOf(false) } + val context = LocalContext.current + Column( modifier = Modifier .fillMaxSize() @@ -74,7 +85,6 @@ fun SignInContent( ) { SignInBanner( modifier = Modifier - ) Spacer(modifier = Modifier.height(16.dp)) @@ -93,15 +103,19 @@ fun SignInContent( ) { Text( text = "Sign In", - style = MaterialTheme.typography.headlineSmall + style = MaterialTheme.typography.headlineSmall, + color = MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.8f) ) Text( - text = "Please sign in to continue", - style = MaterialTheme.typography.bodySmall + text = "Please sign in! We're excited to have you on board!", + style = MaterialTheme.typography.bodyMedium.copy( + fontWeight = FontWeight.Medium + ), + color = MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.8f) ) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(28.dp)) DefaultTextField( value = userToSignInInfo.email, @@ -137,7 +151,10 @@ fun SignInContent( ) { Text( text = "Forgot your password?", - style = MaterialTheme.typography.bodySmall + style = MaterialTheme.typography.bodySmall.copy( + fontWeight = FontWeight.Medium + ), + color = MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.8f) ) } @@ -158,8 +175,13 @@ fun SignInContent( } } is UiState.Success -> { - userToSignInState.data?.loginResult?.token?.accessToken?.let { - Text(text = it) + saveUserSession() + + val username = userToSignInState.data?.loginResult?.userId?.username + Toast.makeText(context, "Welcome $username", Toast.LENGTH_SHORT).show() + + LaunchedEffect(Unit) { + navigateToMain() } } } @@ -168,13 +190,6 @@ fun SignInContent( Spacer(modifier = Modifier.weight(1f)) } - if (userSessionState != null) { - Text( - text = userSessionState.userLoginToken.accessToken, - modifier = Modifier.padding(vertical = 10.dp) - ) - } - DefaultButton( contentText = "Sign In", modifier = Modifier @@ -192,7 +207,8 @@ fun SignInContent( ) { Text( text = "Don't have an account?", - style = MaterialTheme.typography.bodySmall + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.8f) ) Spacer(modifier = Modifier.width(2.dp)) @@ -220,7 +236,9 @@ fun SingInContentPreview() { userToSignInInfo = UserLoginInfo("", ""), updateUserLoginInfo = {}, signInUser = {}, - userSessionState = null + saveUserSession = {}, + navigateToMain = {} +// userSessionState = null ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt index 0492c01..f9b8e31 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt @@ -32,39 +32,18 @@ class SignInScreenViewModel @Inject constructor( )) val userToSignInInfo = _userToSignInInfo.asStateFlow() - private val _userSessionState: MutableStateFlow = MutableStateFlow(null) - val userSessionState = _userSessionState.asStateFlow() - - init { + fun signInUser() { + _userToSignInState.value = UiState.Loading() viewModelScope.launch { - val result = preferencesRepository.getActiveSession() - when(result) { - is Resource.Error -> { - _userSessionState.value = null - } - is Resource.Success -> { - _userSessionState.value = result.data - } - } + _userToSignInState.value = userApiRepository.userLogin(_userToSignInInfo.value) } } - fun signInUser() { - _userToSignInState.value = UiState.Loading() + fun saveUserSession() { viewModelScope.launch { - val result = userApiRepository.userLogin(_userToSignInInfo.value) - when(result) { - is UiState.Success -> { - _userToSignInState.value = result - result.data?.loginResult?.toUserSession() - ?.let { preferencesRepository.saveSession(it) } - } - is UiState.Error -> { - _userToSignInState.value = result - } - else -> { - // do nothing - } + val userSession = _userToSignInState.value?.data?.loginResult?.toUserSession() + if (userSession != null) { + preferencesRepository.saveSession(userSession) } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreen.kt index b16bbb4..416c455 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreen.kt @@ -1,5 +1,6 @@ package com.capstone.techwasmark02.ui.screen.signUp +import android.widget.Toast import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -9,11 +10,10 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -23,22 +23,26 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavHostController import com.capstone.techwasmark02.data.model.UserRegisterInfo import com.capstone.techwasmark02.data.remote.response.UserRegisterResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.DefaultButton import com.capstone.techwasmark02.ui.component.DefaultTextField -import com.capstone.techwasmark02.ui.component.InverseTopBar import com.capstone.techwasmark02.ui.component.PasswordTextField import com.capstone.techwasmark02.ui.component.SignUpBanner +import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @Composable fun SignUpScreen( - viewModel: SignUpScreenViewModel = hiltViewModel() + viewModel: SignUpScreenViewModel = hiltViewModel(), + navController: NavHostController ) { val userToSignUpState by viewModel.userToSignUpState.collectAsState() val userToSignUpInfo by viewModel.userToSignUpInfo.collectAsState() @@ -47,140 +51,139 @@ fun SignUpScreen( userToSignUpInfo = userToSignUpInfo, updateUserRegisterInfo = { viewModel.updateUserSignUpInfo(it) }, userToSignUpState = userToSignUpState, - signUpUser = { viewModel.signUpUser() } + signUpUser = { viewModel.signUpUser() }, + navigateToSignIn = { navController.navigate(Screen.SignIn.route)} ) } -@OptIn(ExperimentalMaterial3Api::class) @Composable fun SignUpContent( userToSignUpInfo: UserRegisterInfo, updateUserRegisterInfo: (UserRegisterInfo) -> Unit, userToSignUpState: UiState?, - signUpUser: () -> Unit + signUpUser: () -> Unit, + navigateToSignIn: () -> Unit ) { var showPassword by remember { mutableStateOf(false) } - Scaffold( - topBar = { - InverseTopBar( - onClickNavigationIcon = {} - ) - } - ) { innerPadding -> + val context = LocalContext.current + + Column( + modifier = Modifier + .padding(top = 26.dp, bottom = 30.dp) + .padding(horizontal = 20.dp) + ) { + SignUpBanner() + + Spacer(modifier = Modifier.height(16.dp)) + Column( modifier = Modifier - .padding(innerPadding) - .padding(top = 26.dp, bottom = 30.dp) - .padding(horizontal = 20.dp) + .fillMaxSize() + .shadow( + elevation = 6.dp, + shape = MaterialTheme.shapes.large, + clip = true + ) + .clip(MaterialTheme.shapes.large) + .background(MaterialTheme.colorScheme.tertiary) + .padding(horizontal = 20.dp, vertical = 30.dp) ) { - SignUpBanner() - - Spacer(modifier = Modifier.height(16.dp)) + Text( + text = "Sign Up", + style = MaterialTheme.typography.headlineSmall + ) - Column( - modifier = Modifier - .fillMaxSize() - .shadow( - elevation = 6.dp, - shape = MaterialTheme.shapes.large, - clip = true - ) - .clip(MaterialTheme.shapes.large) - .background(MaterialTheme.colorScheme.tertiary) - .padding(horizontal = 20.dp, vertical = 30.dp) - ) { - Text( - text = "Sign Up", - style = MaterialTheme.typography.headlineSmall + Text( + text = "Just a few steps to help the earth managing e-waste!", + style = MaterialTheme.typography.bodySmall.copy( + fontWeight = FontWeight.Medium ) + ) - Text( - text = "Just a few steps to help the earth managing e-waste!", - style = MaterialTheme.typography.bodySmall - ) + Spacer(modifier = Modifier.height(20.dp)) + + DefaultTextField( + value = userToSignUpInfo.fullname, + onValueChange = { newValue -> + updateUserRegisterInfo(userToSignUpInfo.copy( + fullname = newValue + )) + }, + labelText = "Full Name", + placeHolderText = "user full name", + modifier = Modifier.fillMaxWidth() + ) - Spacer(modifier = Modifier.height(20.dp)) - - DefaultTextField( - value = userToSignUpInfo.fullname, - onValueChange = { newValue -> - updateUserRegisterInfo(userToSignUpInfo.copy( - fullname = newValue - )) - }, - labelText = "Full Name", - placeHolderText = "user full name", - modifier = Modifier.fillMaxWidth() - ) + Spacer(modifier = Modifier.height(16.dp)) - Spacer(modifier = Modifier.height(16.dp)) - - DefaultTextField( - value = userToSignUpInfo.email, - onValueChange = { newValue -> - updateUserRegisterInfo(userToSignUpInfo.copy( - email = newValue - )) - }, - labelText = "Email", - placeHolderText = "user email", - modifier = Modifier.fillMaxWidth() - ) + DefaultTextField( + value = userToSignUpInfo.email, + onValueChange = { newValue -> + updateUserRegisterInfo(userToSignUpInfo.copy( + email = newValue + )) + }, + labelText = "Email", + placeHolderText = "user email", + modifier = Modifier.fillMaxWidth() + ) - Spacer(modifier = Modifier.height(16.dp)) - - PasswordTextField( - value = userToSignUpInfo.password, - onValueChange = { newValue -> - updateUserRegisterInfo(userToSignUpInfo.copy( - password = newValue - )) - }, - showPassword = showPassword, - toggleShowPassword = { showPassword = !showPassword }, - modifier = Modifier.fillMaxWidth() - ) + Spacer(modifier = Modifier.height(16.dp)) + PasswordTextField( + value = userToSignUpInfo.password, + onValueChange = { newValue -> + updateUserRegisterInfo(userToSignUpInfo.copy( + password = newValue + )) + }, + showPassword = showPassword, + toggleShowPassword = { showPassword = !showPassword }, + modifier = Modifier.fillMaxWidth() + ) - if(userToSignUpState != null) { - Box( - modifier = Modifier - .weight(1f) - .fillMaxWidth(), - contentAlignment = Alignment.Center - ) { - when(userToSignUpState) { - is UiState.Loading -> { - CircularProgressIndicator() - } - is UiState.Error -> { - userToSignUpState.message?.let { - Text(text = it) - } + + if(userToSignUpState != null) { + Box( + modifier = Modifier + .weight(1f) + .fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + when(userToSignUpState) { + is UiState.Loading -> { + CircularProgressIndicator() + } + is UiState.Error -> { + userToSignUpState.message?.let { + Text(text = it) } - is UiState.Success -> { - userToSignUpState.data?.message?.let { - Text(text = it) - } + } + is UiState.Success -> { + + Toast.makeText(context, userToSignUpState.data?.message, Toast.LENGTH_SHORT).show() + + LaunchedEffect(Unit) { + navigateToSignIn() } } } - } else { - Spacer(modifier = Modifier.weight(1f)) } - - DefaultButton( - contentText = "Sign Up", - modifier = Modifier - .fillMaxWidth() - .height(50.dp), - onClick = signUpUser - ) + } else { + Spacer(modifier = Modifier.weight(1f)) } + + DefaultButton( + contentText = "Sign Up", + modifier = Modifier + .fillMaxWidth() + .height(50.dp), + onClick = signUpUser + ) } } } @@ -193,7 +196,8 @@ fun SingUpContentPreview() { userToSignUpState = null, userToSignUpInfo = UserRegisterInfo("", "", ""), updateUserRegisterInfo = {}, - signUpUser = {} + signUpUser = {}, + navigateToSignIn = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreenViewModel.kt index 6aac930..053ef28 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signUp/SignUpScreenViewModel.kt @@ -16,7 +16,6 @@ import javax.inject.Inject @HiltViewModel class SignUpScreenViewModel @Inject constructor( private val userApiRepository: TechwasUserApiRepository, - private val preferencesRepository: PreferencesRepository ): ViewModel() { private val _userToSignUpState: MutableStateFlow?> = @@ -36,20 +35,7 @@ class SignUpScreenViewModel @Inject constructor( fun signUpUser() { _userToSignUpState.value = UiState.Loading() viewModelScope.launch { - val result = userApiRepository.userRegister(_userToSignUpInfo.value) - when (result) { - is UiState.Success -> { - _userToSignUpState.value = result - } - - is UiState.Error -> { - _userToSignUpState.value = result - } - - else -> { - // do nothing - } - } + _userToSignUpState.value = userApiRepository.userRegister(_userToSignUpInfo.value) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt index 9b6e8d6..0358c2f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt @@ -16,6 +16,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -28,13 +29,21 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavHostController import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.Green77 import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import kotlinx.coroutines.delay @Composable -fun SplashScreen() { +fun SplashScreen( + viewModel: SplashScreenViewModel = hiltViewModel(), + navController: NavHostController +) { + + val userSession by viewModel.userSessionState.collectAsState() var animationState by remember { mutableStateOf(false) @@ -53,6 +62,18 @@ fun SplashScreen() { // navController.navigate(Screen.Home.route) } + LaunchedEffect(key1 = userSession) { + delay(4000) + + if (userSession != null) { + if (userSession!!.userLoginToken.accessToken == "") { + navController.navigate(Screen.OnBoarding.route) + } else { + navController.navigate(Screen.Main.route) + } + } + } + SplashContent(alpha = alphaAnim.value) } @@ -73,7 +94,7 @@ fun SplashContent(alpha: Float) { verticalAlignment = Alignment.CenterVertically ) { Image( - painter = painterResource(id = R.drawable.logo_techwaste), + painter = painterResource(id = R.drawable.img_logo_onboarding_nooutline), contentDescription = null, modifier = Modifier .width(57.27.dp) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreenViewModel.kt new file mode 100644 index 0000000..cecc022 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreenViewModel.kt @@ -0,0 +1,41 @@ +package com.capstone.techwasmark02.ui.screen.splashScreen + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.common.Resource +import com.capstone.techwasmark02.data.model.UserSession +import com.capstone.techwasmark02.data.remote.response.Token +import com.capstone.techwasmark02.data.remote.response.UserId +import com.capstone.techwasmark02.repository.PreferencesRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class SplashScreenViewModel @Inject constructor( + private val preferencesRepository: PreferencesRepository +): ViewModel() { + + private val _userSessionState: MutableStateFlow = MutableStateFlow(null) + val userSessionState = _userSessionState.asStateFlow() + + init { + viewModelScope.launch { + val result = preferencesRepository.getActiveSession() + when(result) { + is Resource.Error -> { + _userSessionState.value = UserSession( + userLoginToken = Token(accessToken = ""), + userNameId = UserId(username = "", id = 0) + ) + } + is Resource.Success -> { + _userSessionState.value = result.data + } + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/theme/Theme.kt b/app/src/main/java/com/capstone/techwasmark02/ui/theme/Theme.kt index 0f65185..f75438b 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/theme/Theme.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/theme/Theme.kt @@ -4,7 +4,6 @@ import android.app.Activity import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.darkColorScheme import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.material3.lightColorScheme @@ -34,7 +33,7 @@ private val LightColorScheme = lightColorScheme( inverseSurface = Black12, inverseOnSurface = Color.White, - background = Mist97, + background = Color.White, onBackground = Black20 ) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/theme/Type.kt b/app/src/main/java/com/capstone/techwasmark02/ui/theme/Type.kt index f574377..39d1932 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/theme/Type.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/theme/Type.kt @@ -21,6 +21,13 @@ val poppins = FontFamily( // Set of Material typography styles to start with val Typography = Typography( + headlineMedium = TextStyle( + fontFamily = poppins, + fontWeight = FontWeight.SemiBold, + fontSize = 28.sp, + lineHeight = 42.sp, + letterSpacing = 0.1.sp + ), headlineSmall = TextStyle( fontFamily = poppins, fontWeight = FontWeight.Bold, diff --git a/app/src/main/java/com/capstone/techwasmark02/utils/html/FromHtml.kt b/app/src/main/java/com/capstone/techwasmark02/utils/html/FromHtml.kt new file mode 100644 index 0000000..ae853fd --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/utils/html/FromHtml.kt @@ -0,0 +1,43 @@ +package com.capstone.techwasmark02.utils.html + +import android.content.Context +import android.graphics.Color +import android.graphics.Typeface +import android.text.Spannable +import android.text.TextPaint +import android.text.style.ForegroundColorSpan +import android.text.style.StyleSpan +import android.text.style.URLSpan +import android.text.style.UnderlineSpan +import androidx.core.content.res.ResourcesCompat +import androidx.core.text.HtmlCompat +import com.capstone.techwasmark02.R + +fun fromHtml(context: Context, html: String): Spannable = parse(html).apply { + removeLinksUnderline() + styleBold(context) +} + +private fun parse(html: String): Spannable = + (HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_COMPACT) as Spannable) + +private fun Spannable.removeLinksUnderline() { + for (s in getSpans(0, length, URLSpan::class.java)) { + setSpan(object : UnderlineSpan() { + override fun updateDrawState(tp: TextPaint) { + tp.isUnderlineText = false + } + }, getSpanStart(s), getSpanEnd(s), 0) + } +} + +private fun Spannable.styleBold(context: Context) { + val bold = ResourcesCompat.getFont(context, R.font.poppins_semi_bold)!! + for (s in getSpans(0, length, StyleSpan::class.java)) { + if (s.style == Typeface.BOLD) { + setSpan(ForegroundColorSpan(Color.BLACK), getSpanStart(s), getSpanEnd(s), 0) + setSpan(bold.getTypefaceSpan(), getSpanStart(s), getSpanEnd(s), 0) + } + } +} + diff --git a/app/src/main/java/com/capstone/techwasmark02/utils/html/TypeFaceSpanCompat.kt b/app/src/main/java/com/capstone/techwasmark02/utils/html/TypeFaceSpanCompat.kt new file mode 100644 index 0000000..8c6f25c --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/utils/html/TypeFaceSpanCompat.kt @@ -0,0 +1,29 @@ +package com.capstone.techwasmark02.utils.html + +import android.annotation.TargetApi +import android.graphics.Typeface +import android.os.Build +import android.text.TextPaint +import android.text.style.MetricAffectingSpan +import android.text.style.TypefaceSpan + +fun Typeface.getTypefaceSpan(): MetricAffectingSpan = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + typefaceSpanCompatV28(this) + } else { + CustomTypefaceSpan(this) + } + +@TargetApi(Build.VERSION_CODES.P) +private fun typefaceSpanCompatV28(typeface: Typeface) = TypefaceSpan(typeface) + +private class CustomTypefaceSpan(private val typeface: Typeface?) : MetricAffectingSpan() { + + override fun updateDrawState(paint: TextPaint) { + paint.typeface = typeface + } + + override fun updateMeasureState(paint: TextPaint) { + paint.typeface = typeface + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/forum_box.webp b/app/src/main/res/drawable/forum_box.webp new file mode 100644 index 0000000000000000000000000000000000000000..369fde8730195380efa5d4b7a35ddb01f559d5fa GIT binary patch literal 1374 zcmV-k1)=&n5P0>8Dp63GS8c_tzzz#Koj`{a+y zrm~m6J$c?FJp1Odsr299+}iT_WmECL-(L6a(A53unx6m`TearLW8VP)_^xWr(?cJ? z!O&H$`E2j@#Ub#vY8Pk5mMGW3^O}H36VPeGYXSyMK&y$_DkAiX0N*MCW~+!WDgr{M2$-!R zV9-Qxr(xZ+EXzE!vOs80pqoN~gJH3vz+y|YQ-HOh69vY?dJh|e69xK`>=a;g=tK!! zIW9m--%0|ZEoFkli2GnY|SSg3DmX z0NF=b00x`Lx&;ahtuQdRNxCUOk&6`u{Mc==ZVFK9XoUgrle5QcH~IkOhF%;1@bftI z{V**a3iqu*Cp=q4fYU^16#y+ zM!TjnfV`HlG5}%h?4ETC803wFmD%^p;sF2*Z;$mko`MM#!5qcINEAz9LeY?TpRf?- zC>RnSCM<;sr9$H4u^47Tk&t*TmcvXa4-&5?EQpyR3KMx_EQ*;ZN`kb7u`FgLqKGI0 z5^tvB4%5*X@pK|5#M4+!L=jH`DFvO}L5k%OCq)sMnXs(LX-Nv^SQI5<6oX?ykyDc# zOyy8AMmdi>nDQa#B~h5NQ6@%F7&9T~CRrHs zP&P(c2(xg0l7%TpEPzoKrVLyn3BxfN7QrYCV=5|xq@hH}g+^hRFi9+hrC~~eTq}+V zV!ar*QN;+iAXkhD*CADn30Fm~8xyWTsvUDYg2eS>!o5hW0cIj1E?lrv{Qn`R2WS4( z!(V2nhn;y=53ibYr-f@{%p)y4GRB-c9bDfr#+Wa3@S!=l)4d09H^qAj|;(0I(7OodGI~0FwYdkw~6P zC8VPvqBUB;uo4MnZrxr|yQL@l3_NkbZ!Y9ZfP8;)n-1@Trq;xl-Ilkl8mzBaND!Y4 zP7RBgEIrhDGHAc5ri*Vu9-GFmEsjZJhl8+`C5$p-xqr+^qh$*ZTS!quI^sH(qQ=N% zr_Uapz=DcrP1b%>B3Nn}rX4>I3>|u;ngphG)DQ|3aL^OEZzli%{^&BW)m^}TsJ|U3 z*jZHfW!8q5j=ZIi6hT<~7Gl8eY6JFr z;QuxI3ZcUFmJt{s>zji&wA4xu84!ZOZB#s`RjW+)qVSuJxL&njhJj)LY?>7hL)`PwMu4Rjx#RwZo$C0%4d?pbUZqOHN4evSI-e=$eS~ z%5{9?)Ba-*K{f(Z#zq}7?d;}!5lzALxEhPB1OgOWeFj6+HBJ8mNd`K(mGh%1r;nwa gVcL^)08j@HtH1yG#xFTk0I!B|82|tP literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/ic_arrow_left.xml b/app/src/main/res/drawable/ic_arrow_left.xml new file mode 100644 index 0000000..7d12a80 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_left.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_right.xml b/app/src/main/res/drawable/ic_arrow_right.xml new file mode 100644 index 0000000..e011dbc --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_right.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_sell.xml b/app/src/main/res/drawable/ic_sell.xml new file mode 100644 index 0000000..2b8e90e --- /dev/null +++ b/app/src/main/res/drawable/ic_sell.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_trash_outline.xml b/app/src/main/res/drawable/ic_trash_outline.xml new file mode 100644 index 0000000..d18155d --- /dev/null +++ b/app/src/main/res/drawable/ic_trash_outline.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/img_bg_green_large.webp b/app/src/main/res/drawable/img_bg_green_large.webp new file mode 100644 index 0000000000000000000000000000000000000000..b6084ede2d865a839c44a9ce08d4eb30a4fc7323 GIT binary patch literal 5266 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_bg_signup.webp b/app/src/main/res/drawable/img_bg_signup.webp new file mode 100644 index 0000000000000000000000000000000000000000..3a87dcfdf57edee5b5468ac2c7d73f5ad837783e GIT binary patch literal 2874 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_feature_article_box.webp b/app/src/main/res/drawable/img_feature_article_box.webp new file mode 100644 index 0000000000000000000000000000000000000000..af75c0a59fda48aba4370682fc218629363ae7e8 GIT binary patch literal 614 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_feature_detect_box.webp b/app/src/main/res/drawable/img_feature_detect_box.webp new file mode 100644 index 0000000000000000000000000000000000000000..bd102c42d10ec323d45b26058c37fbe4dcace5c5 GIT binary patch literal 562 zcmV-20?qwWNk&F00ssJ4MM6+kP&il$0000G0001q005H!06|PpNTdJ&00D4S+fE%_ z0};^LzyJa|0x*Dq2$h?l04}2U? zsRyr5oF4x5fjWVD=i(F=0Q=;?1gK781ttq7*=bD5gEk(z@nF9Ezx==azx@Bj#)EYp zn)0BDhb+dz04fU=5aVEM015{OZj}MW{WHE3k2N~QvzHl}6+FM!8I@JR>sgycV_lPg zQC3hmAYcIi0FV&?odGI}0F(eekwTqIrK2Muq1I|}uo4MpZrxt^m#^HTOqS@)(8uGgsc1})(oUi$B zRN=n905h#IY=ir#X3-)crWnGrfpduCqa#8`yh1FI@LL5STm4c@5*?JC3G?rki_fvB zt^ff3@cv?D>|gr!CKDd)zwT4_GXKuHEp9%x)fpuQd}#VYyODF55=0Yhl9aXP2EOy9Ys;7&1`AGk6& zPit_ttWyHIQh??)MI9wkvR|MIdpwcx2omZbanL%5lY#^4031ZZ>)t=}x^G0p1gPr&PyGzxC0&ytJW#X{Z`npj zX9_RZ-$OyOb=PO%1ht~KPB3vfbt6Mn!9?Q#%=T7z8s%fO>SnHDv>es{wZo0QCC-ur z%+t-V8R#h-fZ5!N0YIkk0N`##sAot)(9!8399@TVXD(U8HbVN!_GM z?WC`yoIgOU!mKJoamkz%Iyp6YvFW>|Fi}QcQw0>SQz{r^-sFIx$Y}URZ9`O&4keIv z%wS@~8m9pJq0bGZiNrHAH=*3hr^NqcZAsJF3aOP0gas6@Qy~BV{{Nb^U{PowMF7ZZ zE1)0W=NW{elzN`vKTTx{A&J|jo)%c|u2C}-p;!KDGyngJqbYCaq5h7>vNlr)Y8Faw zYM_ZSB)xd?4&n8m*tM>>%SWQH%@9SKY^pa1MfGM!bV9L^xj}m8INQwHU1V;vJ zi=2~aVt#WzF=6Qm*J*!2Q4|`KkX$C74e|Lc(SP#kP@SA{KdK%y!=ii7;jb{w8DjjXUj|w;d0O0{EJOBUy literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_feature_detect_illustration.webp b/app/src/main/res/drawable/img_feature_detect_illustration.webp new file mode 100644 index 0000000000000000000000000000000000000000..1bd983151b007dfa6f60a886bee1b059c30b92ec GIT binary patch literal 6446 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_feature_forum_box.webp b/app/src/main/res/drawable/img_feature_forum_box.webp new file mode 100644 index 0000000000000000000000000000000000000000..369fde8730195380efa5d4b7a35ddb01f559d5fa GIT binary patch literal 1374 zcmV-k1)=&n5P0>8Dp63GS8c_tzzz#Koj`{a+y zrm~m6J$c?FJp1Odsr299+}iT_WmECL-(L6a(A53unx6m`TearLW8VP)_^xWr(?cJ? z!O&H$`E2j@#Ub#vY8Pk5mMGW3^O}H36VPeGYXSyMK&y$_DkAiX0N*MCW~+!WDgr{M2$-!R zV9-Qxr(xZ+EXzE!vOs80pqoN~gJH3vz+y|YQ-HOh69vY?dJh|e69xK`>=a;g=tK!! zIW9m--%0|ZEoFkli2GnY|SSg3DmX z0NF=b00x`Lx&;ahtuQdRNxCUOk&6`u{Mc==ZVFK9XoUgrle5QcH~IkOhF%;1@bftI z{V**a3iqu*Cp=q4fYU^16#y+ zM!TjnfV`HlG5}%h?4ETC803wFmD%^p;sF2*Z;$mko`MM#!5qcINEAz9LeY?TpRf?- zC>RnSCM<;sr9$H4u^47Tk&t*TmcvXa4-&5?EQpyR3KMx_EQ*;ZN`kb7u`FgLqKGI0 z5^tvB4%5*X@pK|5#M4+!L=jH`DFvO}L5k%OCq)sMnXs(LX-Nv^SQI5<6oX?ykyDc# zOyy8AMmdi>nDQa#B~h5NQ6@%F7&9T~CRrHs zP&P(c2(xg0l7%TpEPzoKrVLyn3BxfN7QrYCV=5|xq@hH}g+^hRFi9+hrC~~eTq}+V zV!ar*QN;+iAXkhD*CADn30Fm~8xyWTsvUDYg2eS>!o5hW0cIj1E?lrv{Qn`R2WS4( z!(V2nhn;y=53ibYr-f@{%p)y4GRB-c9bDfr#+Wa3@S!=l)4d09H^qAj|;(0I(7OodGI~0FwYdkw~6P zC8VPvqBUB;uo4MnZrxr|yQL@l3_NkbZ!Y9ZfP8;)n-1@Trq;xl-Ilkl8mzBaND!Y4 zP7RBgEIrhDGHAc5ri*Vu9-GFmEsjZJhl8+`C5$p-xqr+^qh$*ZTS!quI^sH(qQ=N% zr_Uapz=DcrP1b%>B3Nn}rX4>I3>|u;ngphG)DQ|3aL^OEZzli%{^&BW)m^}TsJ|U3 z*jZHfW!8q5j=ZIi6hT<~7Gl8eY6JFr z;QuxI3ZcUFmJt{s>zji&wA4xu84!ZOZB#s`RjW+)qVSuJxL&njhJj)LY?>7hL)`PwMu4Rjx#RwZo$C0%4d?pbUZqOHN4evSI-e=$eS~ z%5{9?)Ba-*K{f(Z#zq}7?d;}!5lzALxEhPB1OgOWeFj6+HBJ8mNd`K(mGh%1r;nwa gVcL^)08j@HtH1yG#xFTk0I!B|82|tP literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_feature_forum_illustration.webp b/app/src/main/res/drawable/img_feature_forum_illustration.webp new file mode 100644 index 0000000000000000000000000000000000000000..7fd2d63ba7058f1efcf7ebbd5a502e22550b2309 GIT binary patch literal 5728 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 S?oZ$U`kep(000000001YCsG6e literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_logo_onboarding.webp b/app/src/main/res/drawable/img_logo_onboarding.webp new file mode 100644 index 0000000000000000000000000000000000000000..51c97d5f5f74b02b32061e75331c8cb54a5a0b86 GIT binary patch literal 15012 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 uXWVL8;}410001IMnv=g literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_logo_onboarding_nooutline.webp b/app/src/main/res/drawable/img_logo_onboarding_nooutline.webp new file mode 100644 index 0000000000000000000000000000000000000000..86f926ed27d45b353b0ddcfb3e758c51e75de5b8 GIT binary patch literal 5664 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 G0000)WS6c0 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_logo_onboarding_nooutline_green.webp b/app/src/main/res/drawable/img_logo_onboarding_nooutline_green.webp new file mode 100644 index 0000000000000000000000000000000000000000..3c1036b50583cbaf61a6b6a945f54845b2168e71 GIT binary patch literal 6360 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 a#pxsy-1bHz&CaGF^QasykN^Mx0001n|5cs< literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_onboarding_ripple_peach_left.webp b/app/src/main/res/drawable/img_onboarding_ripple_peach_left.webp new file mode 100644 index 0000000000000000000000000000000000000000..27433c9f6095f2391de9eb4889ae97773cd296c9 GIT binary patch literal 19558 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�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 V#Q#hDzr_Db{J+HiOZ>m&vjEBBDu4h0 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_onboarding_ripple_peach_right.webp b/app/src/main/res/drawable/img_onboarding_ripple_peach_right.webp new file mode 100644 index 0000000000000000000000000000000000000000..ff148c9684f21bd560824d429cdab03c0d7edacc GIT binary patch literal 19914 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 NssESyf2seM(i*;*O^N^j literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_onboarding_ripple_purple_left.webp b/app/src/main/res/drawable/img_onboarding_ripple_purple_left.webp new file mode 100644 index 0000000000000000000000000000000000000000..819fdddedf8993026bb983a919dfa5bfe0b1f8ab GIT binary patch literal 2510 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 Ygr=E=ql1He_s})7>EhsE>(v4W07CiErvLx| literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_onboarding_ripple_purple_right.webp b/app/src/main/res/drawable/img_onboarding_ripple_purple_right.webp new file mode 100644 index 0000000000000000000000000000000000000000..e76bb4b543818315e72b697d52476df39cfe479c GIT binary patch literal 2526 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 o^e Date: Wed, 14 Jun 2023 22:29:26 +0700 Subject: [PATCH 60/73] modif: change forum --- .../ui/screen/home/HomeScreen.kt | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index f09981c..5efe7fb 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -25,6 +25,7 @@ import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState @@ -61,6 +62,7 @@ import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.ArticleCardBig import com.capstone.techwasmark02.ui.component.FeatureBox import com.capstone.techwasmark02.ui.component.FeatureBoxLarge +import com.capstone.techwasmark02.ui.component.ForumBox import com.capstone.techwasmark02.ui.componentType.FeatureBoxType import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.navigation.Screen.Article @@ -373,6 +375,7 @@ fun HomeContent( Column( modifier = Modifier .fillMaxWidth() + .height(400.dp) .padding(horizontal = 20.dp) ) { Row( @@ -397,23 +400,14 @@ fun HomeContent( Spacer(modifier = Modifier.height(titlePaddingBottom)) - Row( + LazyColumn( modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center + .fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(10.dp), ) { - ArticleCardBig( - modifier = Modifier - .width(320.dp) - .height(186.dp), - article = ArticleList( - componentId = 2, - articleImageURL = null, - name = "Forum title", - id = 2, - desc = "Forum description" - ) - ) + items(count = 10) { + ForumBox(modifier = Modifier.fillMaxWidth()) + } } } } From 49c0babc5336e0f67c5a8cd4db1d9a270a44c8af Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Wed, 14 Jun 2023 22:30:00 +0700 Subject: [PATCH 61/73] transition and cleaning --- .../com/capstone/techwasmark02/TechwasApp.kt | 17 +- .../techwasmark02/ui/component/Banner.kt | 4 +- .../techwasmark02/ui/component/ForumBox.kt | 41 +- .../ui/component/SelectableText.kt | 65 +-- .../techwasmark02/ui/component/TopBar.kt | 14 +- .../ui/componentType/SettingItemType.kt | 8 +- .../techwasmark02/ui/navigation/Screen.kt | 64 ++- .../ui/screen/article/ArticleScreen.kt | 194 +++---- .../ui/screen/catalog/CatalogScreen.kt | 151 ++--- .../CatalogSingleComponentScreen.kt | 25 +- .../ui/screen/forum/ForumScreen.kt | 212 ++++++- .../ui/screen/forum/ForumScreenViewModel.kt | 2 + .../screen/forumSingle/ForumSingleScreen.kt | 521 ++++++++++++++++++ .../forumSingle/ForumSingleScreenViewModel.kt | 41 ++ .../ui/screen/home/HomeScreen.kt | 25 +- .../ui/screen/main/MainScreen.kt | 2 +- .../ui/screen/onBoarding/OnBoardingScreen.kt | 42 +- .../screen/profileUser/ProfileUserScreen.kt | 183 ++++-- .../profileUser/ProfileUserScreenViewModel.kt | 52 ++ .../ui/screen/setting/SettingScreen.kt | 107 +++- .../screen/setting/SettingScreenViewModel.kt | 41 ++ .../ui/screen/signIn/SignInScreenViewModel.kt | 12 +- .../singleArticle/SingleArticleScreen.kt | 19 +- .../ui/screen/splashScreen/SplashScreen.kt | 6 +- app/src/main/res/drawable/ic_create.xml | 5 + .../main/res/drawable/img_forum_hp_nyala.webp | Bin 0 -> 195116 bytes .../res/drawable/img_forum_laptop_bekas.webp | Bin 0 -> 24170 bytes .../drawable/img_profile_ripple_green.webp | Bin 0 -> 12228 bytes .../img_profile_ripple_green_reverse.webp | Bin 0 -> 12448 bytes app/src/main/res/drawable/img_user_1.webp | Bin 0 -> 49032 bytes app/src/main/res/drawable/img_user_2.webp | Bin 0 -> 22738 bytes app/src/main/res/drawable/img_user_3.webp | Bin 0 -> 17044 bytes app/src/main/res/drawable/img_user_4.webp | Bin 0 -> 20162 bytes 33 files changed, 1505 insertions(+), 348 deletions(-) create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreenViewModel.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreenViewModel.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreenViewModel.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreenViewModel.kt create mode 100644 app/src/main/res/drawable/ic_create.xml create mode 100644 app/src/main/res/drawable/img_forum_hp_nyala.webp create mode 100644 app/src/main/res/drawable/img_forum_laptop_bekas.webp create mode 100644 app/src/main/res/drawable/img_profile_ripple_green.webp create mode 100644 app/src/main/res/drawable/img_profile_ripple_green_reverse.webp create mode 100644 app/src/main/res/drawable/img_user_1.webp create mode 100644 app/src/main/res/drawable/img_user_2.webp create mode 100644 app/src/main/res/drawable/img_user_3.webp create mode 100644 app/src/main/res/drawable/img_user_4.webp diff --git a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt index 1a43a28..f6ecba2 100644 --- a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt +++ b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt @@ -17,11 +17,14 @@ import com.capstone.techwasmark02.ui.screen.camera.CameraScreen import com.capstone.techwasmark02.ui.screen.catalog.CatalogScreen import com.capstone.techwasmark02.ui.screen.catalogSingleComponent.CatalogSingleComponentScreen import com.capstone.techwasmark02.ui.screen.detectionResult.DetectionResultScreen +import com.capstone.techwasmark02.ui.screen.forum.ForumScreen +import com.capstone.techwasmark02.ui.screen.forumSingle.ForumSingleScreen import com.capstone.techwasmark02.ui.screen.home.HomeScreen import com.capstone.techwasmark02.ui.screen.main.MainScreen import com.capstone.techwasmark02.ui.screen.maps.MapsScreen import com.capstone.techwasmark02.ui.screen.onBoarding.OnBoardingScreen import com.capstone.techwasmark02.ui.screen.profileUser.ProfileUserScreen +import com.capstone.techwasmark02.ui.screen.setting.SettingScreen import com.capstone.techwasmark02.ui.screen.signIn.SignInScreen import com.capstone.techwasmark02.ui.screen.signUp.SignUpScreen import com.capstone.techwasmark02.ui.screen.singleArticle.SingleArticleScreen @@ -106,17 +109,29 @@ fun TechwasApp() { val idArticle = navBackStackEntry.arguments?.getInt("idArticle") if(idArticle != null) { - SingleArticleScreen(idArticle = idArticle) + SingleArticleScreen(idArticle = idArticle, navController = navController) } } composable(Forum.route) { + ForumScreen(navController = navController) + } + composable(SingleForum.route) { + ForumSingleScreen(navController = navController) } composable(Profile.route) { ProfileUserScreen(navController = navController) } + + composable( + route = Setting.route, + enterTransition = Setting.enterTransition, + exitTransition = Setting.exitTransition + ) { + SettingScreen(navController = navController) + } composable(Catalog.route) { CatalogScreen(navController = navController) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt index 94b0c33..26e7b94 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/Banner.kt @@ -141,7 +141,7 @@ fun SignUpBanner( ) { Image( - painter = painterResource(id = R.drawable.img_bg_singin), + painter = painterResource(id = R.drawable.img_bg_signup), contentDescription = null, modifier = Modifier .fillMaxSize(), @@ -185,7 +185,7 @@ fun SignUpBanner( ) Text( - text = "to Techwaste!", + text = "e-waste!", style = MaterialTheme.typography.headlineSmall.copy( fontWeight = FontWeight.Bold ), diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt index 76d0f84..0f480a1 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt @@ -2,6 +2,7 @@ package com.capstone.techwasmark02.ui.component import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -25,6 +26,7 @@ import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -36,6 +38,12 @@ import kotlin.random.Random @Composable fun ForumBox( modifier: Modifier = Modifier, + photoUrl: Int? = null, + onClick: () -> Unit = {}, + title: String, + place: String, + desc: String + ) { Box( modifier = modifier @@ -47,6 +55,9 @@ fun ForumBox( ) .background(Color.White) .clip(RoundedCornerShape(20.dp)) + .clickable { + onClick() + } ) { Row( modifier @@ -63,7 +74,7 @@ fun ForumBox( bottomStart= 20.dp )), painter = rememberAsyncImagePainter( - model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", + model = photoUrl ?: "https://picsum.photos/seed/${Random.nextInt()}/320/120", placeholder = painterResource(id = R.drawable.place_holder), ), contentScale = ContentScale.Crop, @@ -72,24 +83,28 @@ fun ForumBox( Column( modifier = Modifier .weight(1f) - .height(60.dp) .padding(start = 8.2.dp) ) { Text( - text = "Title", + text = title, style = MaterialTheme.typography.labelMedium, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, + maxLines = 1, + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f) ) Text( - text = "Subtitle", + text = desc, style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), - overflow = TextOverflow.Ellipsis + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f), + overflow = TextOverflow.Ellipsis, + maxLines = 1 ) Text( - text = "Description", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), + text = place, + style = MaterialTheme.typography.bodySmall.copy( + fontWeight = FontWeight.SemiBold + ), + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f), overflow = TextOverflow.Ellipsis ) } @@ -110,7 +125,11 @@ fun ForumBoxPreview() { .fillMaxWidth() .background(MaterialTheme.colorScheme.background) .padding(20.dp)) { - ForumBox() + ForumBox( + title = "Laptop Rusak", + desc = "Ini adalah akhir dunia", + place = "Bandung" + ) } } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt index 40c8f6f..b0ffd89 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt @@ -1,17 +1,17 @@ package com.capstone.techwasmark02.ui.component import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Icon +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -19,45 +19,36 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.capstone.techwasmark02.ui.componentType.ArticleFilterType -import com.capstone.techwasmark02.ui.theme.Black20 import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @Composable fun SelectableText( modifier: Modifier = Modifier, filterType: ArticleFilterType, - selected: Boolean + selected: Boolean, + onClick: () -> Unit ) { - Column( - modifier = modifier, - horizontalAlignment = Alignment.CenterHorizontally + Box( + modifier = modifier + .clip(RoundedCornerShape(20.dp)) + .clickable { + onClick() + } + .background( + if (selected) MaterialTheme.colorScheme.primary else Color.LightGray.copy(alpha = 0.6f) + ) + .padding(vertical = 4.dp, horizontal = 8.dp), ) { - if(selected) { - Text( - maxLines = 1, - text = filterType.type, - color = Color.White, - style = MaterialTheme.typography.bodySmall, - modifier = Modifier - .clip(RoundedCornerShape(15.dp)) - .background(MaterialTheme.colorScheme.primary) - .padding(8.dp), - overflow = TextOverflow.Ellipsis - ) - } else { - Text( - maxLines = 1, - text = filterType.type, - color = MaterialTheme.colorScheme.onBackground, - style = MaterialTheme.typography.bodySmall, - overflow = TextOverflow.Ellipsis - ) - } + Text( + maxLines = 1, + text = filterType.type, + style = MaterialTheme.typography.bodySmall, + modifier = Modifier, + color = if (selected) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onBackground + ) } } @@ -67,15 +58,17 @@ fun SelectableTextPreview() { TechwasMark02Theme { Row(modifier = Modifier.padding(20.dp), verticalAlignment = Alignment.CenterVertically){ SelectableText( - filterType = ArticleFilterType.General, - selected = true + filterType = ArticleFilterType.WashingMachine, + selected = true, + onClick = {} ) Spacer(modifier = Modifier.width(20.dp)) SelectableText( filterType = ArticleFilterType.General, - selected = false + selected = false, + onClick = {} ) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt index cfcd93d..ca0d008 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/TopBar.kt @@ -25,7 +25,7 @@ import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @OptIn(ExperimentalMaterial3Api::class) @Composable -fun InverseTopBar(onClickNavigationIcon: () -> Unit, modifier: Modifier = Modifier) { +fun InverseTopBar(onClickNavigationIcon: () -> Unit, modifier: Modifier = Modifier, pageTitle: String = "") { BackHandler(true) { onClickNavigationIcon() } @@ -44,7 +44,17 @@ fun InverseTopBar(onClickNavigationIcon: () -> Unit, modifier: Modifier = Modifi } }, title = {}, - actions = {}, + actions = { + Text( + text = pageTitle, + color = MaterialTheme.colorScheme.primary, + style = MaterialTheme.typography.labelLarge.copy( + fontWeight = FontWeight.Normal + ), + modifier = Modifier + .padding(end = 20.dp), + ) + }, colors = TopAppBarDefaults.smallTopAppBarColors( containerColor = Color.Transparent, ), diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/SettingItemType.kt b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/SettingItemType.kt index 53b32fd..2473e93 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/componentType/SettingItemType.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/componentType/SettingItemType.kt @@ -4,11 +4,11 @@ import com.capstone.techwasmark02.R sealed class SettingItemType(val title: String, val icon: Int) { - object Password: SettingItemType(title = "Password and security", icon = R.drawable.ic_shield) + object Password: SettingItemType(title = "Security", icon = R.drawable.ic_shield) - object Comment: SettingItemType(title = "Comments you’ve posted", icon = R.drawable.ic_chat_buble) + object Comment: SettingItemType(title = "Comments", icon = R.drawable.ic_chat_buble) - object Notification: SettingItemType(title = "Push Notifications", icon = R.drawable.ic_fill_notification) + object Notification: SettingItemType(title = "Notifications", icon = R.drawable.ic_fill_notification) - object Language: SettingItemType(title = "Language Preference", icon = R.drawable.ic_language) + object Language: SettingItemType(title = "Language", icon = R.drawable.ic_language) } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt index e36b438..caa872d 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt @@ -11,7 +11,6 @@ import androidx.navigation.NavBackStackEntry @OptIn(ExperimentalAnimationApi::class) sealed class Screen constructor(val route: String, val enterTransition: (AnimatedContentScope.() -> EnterTransition?), val exitTransition: (AnimatedContentScope.() -> ExitTransition?)) { - object OnBoarding: Screen( route = "OnBoarding", enterTransition = { @@ -28,26 +27,34 @@ sealed class Screen constructor(val route: String, val enterTransition: (Animat object SignIn: Screen( route = "SignIn", enterTransition = { - slideIntoContainer( - AnimatedContentScope.SlideDirection.Left, - animationSpec = tween(700) - ) +// slideIntoContainer( +// AnimatedContentScope.SlideDirection.Left, +// animationSpec = tween(700) +// ) + fadeIn(animationSpec = tween(700)) }, exitTransition = { - slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) +// slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + fadeOut( + animationSpec = tween(700) + ) } ) object SignUp: Screen( route = "SignUp", enterTransition = { - slideIntoContainer( - AnimatedContentScope.SlideDirection.Left, - animationSpec = tween(700) - ) +// slideIntoContainer( +// AnimatedContentScope.SlideDirection.Left, +// animationSpec = tween(700) +// ) + fadeIn(animationSpec = tween(700)) }, exitTransition = { - slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) +// slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + fadeOut( + animationSpec = tween(700) + ) } ) @@ -105,6 +112,23 @@ sealed class Screen constructor(val route: String, val enterTransition: (Animat } ) + object SingleForum: Screen( + route = "SingleForum", + enterTransition = { + slideIntoContainer( + AnimatedContentScope.SlideDirection.Left, + animationSpec = tween(700) + ) + }, + exitTransition = { + slideOutOfContainer( + AnimatedContentScope.SlideDirection.Left, animationSpec = tween( + durationMillis = 700, + ) + ) + } + ) + object Profile: Screen( route = "profile", enterTransition = { @@ -150,6 +174,7 @@ sealed class Screen constructor(val route: String, val enterTransition: (Animat }, exitTransition = { slideOutOfContainer(AnimatedContentScope.SlideDirection.Down, animationSpec = tween(700)) + fadeOut(animationSpec = tween(1000)) } ) @@ -223,13 +248,15 @@ sealed class Screen constructor(val route: String, val enterTransition: (Animat object Splash: Screen( route = "splash", enterTransition = { - slideIntoContainer( - AnimatedContentScope.SlideDirection.Left, - animationSpec = tween(700) - ) +// slideIntoContainer( +// AnimatedContentScope.SlideDirection.Left, +// animationSpec = tween(700) +// ) + fadeIn(animationSpec = tween(300)) }, exitTransition = { - slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) +// slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + fadeOut(animationSpec = tween(300)) } ) @@ -242,7 +269,10 @@ sealed class Screen constructor(val route: String, val enterTransition: (Animat ) }, exitTransition = { - slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700)) + slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween( + transitionDuration)) } ) } + +private const val transitionDuration = 300 \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt index 401689c..2dbce09 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt @@ -105,133 +105,135 @@ fun ArticleContent( Column( modifier = Modifier .fillMaxSize() - .padding(horizontal = 16.dp) - .padding(top = 20.dp) + .padding(top = 20.dp, bottom = 80.dp) ) { - Text( - text = "Articles", - style = MaterialTheme.typography.headlineLarge, - fontWeight = FontWeight.Bold - ) + Column( + modifier = Modifier + .padding(horizontal = 16.dp) + ) { + Text( + text = "Articles", + style = MaterialTheme.typography.headlineLarge, + fontWeight = FontWeight.Bold + ) - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(8.dp)) - Text( - text = "Lorem ipsum dolor sit amet, consectetur", - style = MaterialTheme.typography.bodyLarge - ) + Text( + text = "Check out these articles!", + style = MaterialTheme.typography.bodyLarge.copy( + fontWeight = FontWeight.Medium + ) + ) - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(16.dp)) - SearchBox( - value = inputValue, - onValueChange = { newValue -> - inputValue = newValue - if(inputValue.isEmpty()) { - viewModel.getAllFilterArticle(selectedFilter?.id ?: 0) - } else { - viewModel.getArticleByName(inputValue, selectedFilter ?: ArticleFilterType.General) - } - }, - ) + SearchBox( + value = inputValue, + onValueChange = { newValue -> + inputValue = newValue + if(inputValue.isEmpty()) { + viewModel.getAllFilterArticle(selectedFilter?.id ?: 0) + } else { + viewModel.getArticleByName(inputValue, selectedFilter ?: ArticleFilterType.General) + } + }, + ) - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(16.dp)) + } LazyRow( modifier = Modifier.height(48.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp), - verticalAlignment = Alignment.CenterVertically + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + contentPadding = PaddingValues(horizontal = 16.dp) ) { items( items = filterTypeList, ) { item -> - IconButton( - modifier = Modifier.requiredWidthIn(min = 60.dp), + SelectableText( + filterType = item, + selected = item == selectedFilter, onClick = { selectedFilter = item viewModel.getAllFilterArticle(item.id) - }, - enabled = item != selectedFilter, - content = { - SelectableText( - filterType = item, - selected = item == selectedFilter, -// modifier = Modifier.clickable(enabled = item != selectedFilter) { -// selectedFilter = item -// viewModel.getAllFilterArticle(item.id) -// } - ) } ) } } - Spacer(modifier = Modifier.height(16.dp)) + Column( + modifier = Modifier + .padding(horizontal = 16.dp) + ) { + Spacer(modifier = Modifier.height(16.dp)) - if (articleList != null) { - when (articleList) { - is UiState.Loading -> { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - CircularProgressIndicator() + if (articleList != null) { + when (articleList) { + is UiState.Loading -> { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + CircularProgressIndicator() + } } - } - is UiState.Error -> { - articleList.message?.let { - Text(text = it) + is UiState.Error -> { + articleList.message?.let { + Text(text = it) + } } - } - is UiState.Success -> { - val componentListArticle = articleList.data?.articleList - if(!componentListArticle.isNullOrEmpty()) { - LazyVerticalGrid( - modifier = Modifier - .fillMaxWidth() - .fillMaxHeight() - .padding(bottom = 20.dp), - columns = GridCells.Fixed(2), - contentPadding = PaddingValues(vertical = 8.dp), - verticalArrangement = Arrangement.spacedBy(16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp), - ) { - items(componentListArticle) { item -> - ArticleCardSmall( - modifier = Modifier - .width(150.dp) - .clickable { - item?.id?.let { navigateToSingleArticle(it) } - }, - imgUrl = item?.articleImageURL, - title = item?.name, - description = item?.desc, - ) + is UiState.Success -> { + val componentListArticle = articleList.data?.articleList + if(!componentListArticle.isNullOrEmpty()) { + LazyVerticalGrid( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight() + .padding(bottom = 20.dp), + columns = GridCells.Fixed(2), + contentPadding = PaddingValues(vertical = 8.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + items(componentListArticle) { item -> + ArticleCardSmall( + modifier = Modifier + .width(150.dp) + .clickable { + item?.id?.let { navigateToSingleArticle(it) } + }, + imgUrl = item?.articleImageURL, + title = item?.name, + description = item?.desc, + ) + } } - } - } else { - Box( - modifier = Modifier - .fillMaxWidth() - .height(100.dp), - contentAlignment = Alignment.Center - ) { + } else { Box( modifier = Modifier - .border( - width = 1.dp, - color = Color.Red, - shape = RoundedCornerShape(20.dp) - ) - .padding(8.dp) - + .fillMaxWidth() + .height(100.dp), + contentAlignment = Alignment.Center ) { - Text( - text = "There's no related article", - style = MaterialTheme.typography.labelSmall, - color = Color.Red - ) + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) + + ) { + Text( + text = "There's no related article", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } } } - } + } } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt index ea5aebf..dfca3a6 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt @@ -1,6 +1,7 @@ package com.capstone.techwasmark02.ui.screen.catalog import android.net.Uri +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -32,6 +33,8 @@ import com.capstone.techwasmark02.data.remote.response.Component import com.capstone.techwasmark02.data.remote.response.ComponentsResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.CatalogCard +import com.capstone.techwasmark02.ui.component.DefaultTopBar +import com.capstone.techwasmark02.ui.component.InverseTopBar import com.capstone.techwasmark02.ui.component.SearchBox import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @@ -50,7 +53,8 @@ fun CatalogScreen( componentsState = componentsState, navigateToSingleComponent = { navController.navigate("${Screen.SingleCatalog.route}/$it") }, searchBoxValue = searchBoxValue, - onSearchBoxValueChange = { viewModel.updateSearchBoxValue(it) } + onSearchBoxValueChange = { viewModel.updateSearchBoxValue(it) }, + navigateBackToMain = { navController.popBackStack() } ) } @@ -59,91 +63,103 @@ fun CatalogContent( componentsState: UiState?, navigateToSingleComponent: (component: String) -> Unit, searchBoxValue: String, - onSearchBoxValueChange: (String) -> Unit + onSearchBoxValueChange: (String) -> Unit, + navigateBackToMain: () -> Unit ) { val moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) .build() val adapter = moshi.adapter(Component::class.java) - - Column( + Box( modifier = Modifier .fillMaxSize() - .padding(horizontal = 16.dp) - .padding(top = 20.dp) ) { - Text( - text = "Catalog", - style = MaterialTheme.typography.headlineSmall - ) - Text( - text = "Find your e-waste component here", - style = MaterialTheme.typography.bodyMedium - ) - - Spacer(modifier = Modifier.height(10.dp)) - - SearchBox(onValueChange = onSearchBoxValueChange, value = searchBoxValue) - - Spacer(modifier = Modifier.height(16.dp)) - - if (componentsState != null) { - when(componentsState) { - is UiState.Success -> { - val components = componentsState.data?.components - - var filteredComponents by remember { - mutableStateOf(components) - } - - LaunchedEffect(key1 = searchBoxValue) { - if (components != null) { - filteredComponents = searchComponent( - componentList = components, - searchBoxValue = searchBoxValue - ) + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp) + .padding(top = 60.dp) + ) { + Text( + text = "Catalog", + style = MaterialTheme.typography.headlineSmall + ) + Text( + text = "Find your e-waste component here", + style = MaterialTheme.typography.bodyMedium + ) + + Spacer(modifier = Modifier.height(10.dp)) + + SearchBox(onValueChange = onSearchBoxValueChange, value = searchBoxValue) + + Spacer(modifier = Modifier.height(16.dp)) + + if (componentsState != null) { + when(componentsState) { + is UiState.Success -> { + val components = componentsState.data?.components + + var filteredComponents by remember { + mutableStateOf(components) } - } - LazyColumn( - modifier = Modifier - .fillMaxSize(), - contentPadding = PaddingValues(bottom = 20.dp), - verticalArrangement = Arrangement.spacedBy(12.dp) - ) { - filteredComponents?.size?.let { - items( - count = it, - ) {index -> - CatalogCard( - component = filteredComponents!![index], - modifier = Modifier - .fillMaxWidth() - .clickable { - val componentJson = - Uri.encode(adapter.toJson(filteredComponents!![index])) - navigateToSingleComponent(componentJson) - }, + LaunchedEffect(key1 = searchBoxValue) { + if (components != null) { + filteredComponents = searchComponent( + componentList = components, + searchBoxValue = searchBoxValue ) } } + + LazyColumn( + modifier = Modifier + .fillMaxSize(), + contentPadding = PaddingValues(bottom = 20.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + filteredComponents?.size?.let { + items( + count = it, + ) {index -> + CatalogCard( + component = filteredComponents!![index], + modifier = Modifier + .fillMaxWidth() + .clickable { + val componentJson = + Uri.encode(adapter.toJson(filteredComponents!![index])) + navigateToSingleComponent(componentJson) + }, + ) + } + } + } } - } - is UiState.Error -> { + is UiState.Error -> { - } - is UiState.Loading -> { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() + } + is UiState.Loading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } } } } } + + InverseTopBar( + onClickNavigationIcon = navigateBackToMain, + pageTitle = "Catalog", + modifier = Modifier + .background(MaterialTheme.colorScheme.background) + ) } } @@ -164,7 +180,8 @@ fun CatalogScreenPreview() { componentsState = UiState.Loading(), navigateToSingleComponent = {}, searchBoxValue = "", - onSearchBoxValueChange = {} + onSearchBoxValueChange = {}, + navigateBackToMain = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt index fecb7aa..103ea24 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreen.kt @@ -40,7 +40,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.blur import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color @@ -58,9 +57,7 @@ import com.capstone.techwasmark02.data.remote.response.SmallPart import com.capstone.techwasmark02.data.remote.response.UsableComponentsResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.ArticleCardBig -import com.capstone.techwasmark02.ui.component.DefaultButton import com.capstone.techwasmark02.ui.component.DefaultTopBar -import com.capstone.techwasmark02.ui.component.InverseButton import com.capstone.techwasmark02.ui.component.UsableComponentBottomSheet import com.capstone.techwasmark02.ui.component.UsableComponentItem import com.capstone.techwasmark02.ui.navigation.Screen @@ -95,7 +92,8 @@ fun CatalogSingleComponentScreen( updateUsableComponentsList = { viewModel.updateUsableComponentList(it) }, relatedArticleListState = relatedArticleListState, updateRelatedArticleListState = { viewModel.updateRelatedArticleListState(it) }, - navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") } + navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") }, + navigateBackToCatalog = { navController.popBackStack() } ) } } @@ -111,7 +109,7 @@ fun CatalogSingleComponentContent( relatedArticleListState: UiState?, updateRelatedArticleListState: (Int) -> Unit, navigateToSingleArticle: (idArticle: Int) -> Unit, - + navigateBackToCatalog: () -> Unit ) { val modalSheetState = rememberModalBottomSheetState( @@ -159,7 +157,7 @@ fun CatalogSingleComponentContent( topBar = { DefaultTopBar( pageTitle = "Result", - onClickNavigationIcon = {} + onClickNavigationIcon = { navigateBackToCatalog() } ) } ) { innerPadding -> @@ -435,18 +433,6 @@ fun CatalogSingleComponentContent( Spacer(modifier = Modifier.height(28.dp)) - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 40.dp) - ) { - DefaultButton(contentText = "Drop Point", modifier = Modifier.fillMaxWidth()) - - Spacer(modifier = Modifier.height(20.dp)) - - InverseButton(contentText = "Check Out Forum", modifier = Modifier.fillMaxWidth()) - } - } } } @@ -469,7 +455,8 @@ fun CatalogSingleComponentScreenPreview() { updateUsableComponentsList = {}, relatedArticleListState = UiState.Loading(), updateRelatedArticleListState = {}, - navigateToSingleArticle = {} + navigateToSingleArticle = {}, + navigateBackToCatalog = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt index 3deb400..2a718e9 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt @@ -1,22 +1,220 @@ package com.capstone.techwasmark02.ui.screen.forum import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredWidthIn +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.navigation.NavHostController +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.ui.component.ForumBox +import com.capstone.techwasmark02.ui.component.SearchBox +import com.capstone.techwasmark02.ui.component.SelectableText +import com.capstone.techwasmark02.ui.componentType.ArticleFilterType +import com.capstone.techwasmark02.ui.navigation.Screen +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @Composable -fun ForumScreen() { - ForumContent() +fun ForumScreen( + navController: NavHostController +) { + ForumContent( + navigateToSingleForum = { navController.navigate(Screen.SingleForum.route)} + ) } @Composable -fun ForumContent() { - Box( +fun ForumContent( + navigateToSingleForum: () -> Unit +) { + var inputValue by remember { + mutableStateOf("") + } + + val filterTypeList = listOf( + ArticleFilterType.General, + ArticleFilterType.Battery, + ArticleFilterType.Cable, + ArticleFilterType.CrtTv, + ArticleFilterType.EKettle, + ArticleFilterType.Refrigerator, + ArticleFilterType.Keyboard, + ArticleFilterType.Laptop, + ArticleFilterType.LightBulb, + ArticleFilterType.Monitor, + ArticleFilterType.Mouse, + ArticleFilterType.PCB, + ArticleFilterType.Printer, + ArticleFilterType.RiceCooker, + ArticleFilterType.WashingMachine, + ArticleFilterType.Phone + ) + + var selectedFilter by remember { + mutableStateOf(filterTypeList.firstOrNull()) + } + + Column( modifier = Modifier .fillMaxSize() - .background(Color.LightGray) - ) + .background(MaterialTheme.colorScheme.background) + ) { + + Column( + modifier = Modifier + .fillMaxSize() + .padding(top = 20.dp, bottom = 80.dp) + ) { + Column( + modifier = Modifier + .padding(horizontal = 16.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth(), + verticalAlignment = Alignment.Top + ) { + Column( + modifier = Modifier + .width(280.dp) + ) { + Text( + text = "Forum", + style = MaterialTheme.typography.headlineLarge, + fontWeight = FontWeight.Bold + ) + + Spacer(modifier = Modifier.height(8.dp)) + + Text( + text = "Share your thoughts and connect with others", + style = MaterialTheme.typography.bodyLarge.copy( + fontWeight = FontWeight.Medium + ) + ) + } + + Spacer(modifier = Modifier.weight(1f)) + + Box( + modifier = Modifier + .padding(top = 8.dp, end = 8.dp) + ) { + IconButton( + onClick = { /*TODO*/ }, + modifier = Modifier + .size(36.dp) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.primary) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_create), + contentDescription = null, + tint = MaterialTheme.colorScheme.onPrimary + ) + } + } + } + + Spacer(modifier = Modifier.height(16.dp)) + + SearchBox( + value = inputValue, + onValueChange = {}, + ) + + Spacer(modifier = Modifier.height(16.dp)) + } + + LazyRow( + modifier = Modifier.height(48.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + contentPadding = PaddingValues(horizontal = 16.dp) + ) { + items( + items = filterTypeList, + ) { item -> + SelectableText( + filterType = item, + selected = item == selectedFilter, + modifier = Modifier, + onClick = { + selectedFilter = item + } + ) + } + } + + + LazyColumn( + modifier = Modifier, + contentPadding = PaddingValues(vertical = 20.dp, horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Cara Hidupkan HP Masuk Toilet", + desc = "Jadi kemarin saya tidak sengaja menjatuhkan HP saya ke toilet", + place = "Malang", + photoUrl = R.drawable.img_forum_hp_nyala + ) + } + + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + photoUrl = R.drawable.img_forum_laptop_bekas, + onClick = navigateToSingleForum, + title = "Jual Laptop Mati Total", + desc = "Saya mempunyai laptop yang baru saja mati, pada saat tombol power tekan tidak ada respon apapun, kemungkinan masalah berada di battery. Selain itu kondisi masih bagus dan tidak ada kerusakan luar\nBagi yang berminat dapat mencoba menghubungi saya +6281396774583", + place = "Yogyakarta" + ) + } + } + + } + } +} + +@Preview +@Composable +fun ForumScreenPreview() { + TechwasMark02Theme { + ForumContent( + navigateToSingleForum = {} + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreenViewModel.kt new file mode 100644 index 0000000..672d9b4 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreenViewModel.kt @@ -0,0 +1,2 @@ +package com.capstone.techwasmark02.ui.screen.forum + diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt new file mode 100644 index 0000000..150a668 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt @@ -0,0 +1,521 @@ +package com.capstone.techwasmark02.ui.screen.forumSingle + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.Icon +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.DefaultShadowColor +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavHostController +import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.model.UserSession +import com.capstone.techwasmark02.data.remote.response.Token +import com.capstone.techwasmark02.data.remote.response.UserId +import com.capstone.techwasmark02.ui.component.DefaultTopBar +import com.capstone.techwasmark02.ui.component.TransparentTopBar +import com.capstone.techwasmark02.ui.screen.forum.ForumContent +import com.capstone.techwasmark02.ui.theme.Mist97 +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch + +@Composable +fun ForumSingleScreen( + viewModel: ForumSingleScreenViewModel = hiltViewModel(), + navController: NavHostController +) { + val userSession by viewModel.userSessionState.collectAsState() + + ForumSingleContent( + userSession = userSession, + navigateBackToForum = { navController.popBackStack() } + ) +} + +@Composable +fun ForumSingleContent( + userSession: UserSession?, + navigateBackToForum: () -> Unit +) { + Box( + modifier = Modifier + .fillMaxSize() + .background(Mist97) + ) { + + val scrollState = rememberScrollState() + + val coroutineScope = rememberCoroutineScope() + + var commentText by remember { + mutableStateOf("") + } + + var commentPosted by remember { + mutableStateOf(false) + } + + var showLastComment by remember { + mutableStateOf(false) + } + + var lastCommentText by remember { + mutableStateOf("") + } + + fun postLastComment() { + coroutineScope.launch { + commentPosted = true + delay(2000) + lastCommentText = commentText + commentPosted = false + commentText = "" + showLastComment = true + } + } + + LaunchedEffect(key1 = showLastComment) { + if (showLastComment) { + scrollState.animateScrollTo(scrollState.maxValue) + } + } + + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(scrollState) + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(360.dp) +// .height(100.dp) + .clip(RoundedCornerShape(bottomEnd = 20.dp, bottomStart = 20.dp)) + .background(MaterialTheme.colorScheme.primary) + ) { + Image( + painter = painterResource(id = R.drawable.img_forum_laptop_bekas), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .fillMaxSize() + ) + } + + Column( + modifier = Modifier + .padding(horizontal = 16.dp, vertical = 24.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "Yogyakarta", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.8f) + ) + Text( + text = "Laptop", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.8f) + ) + } + + Spacer(modifier = Modifier.height(4.dp)) + + Text( + text = "Jual Laptop Mati Total", + style = MaterialTheme.typography.titleMedium + ) + + Spacer(modifier = Modifier.height(10.dp)) + + Text( + text = "Saya mempunyai laptop yang baru saja mati, pada saat tombol power tekan tidak ada respon apapun, kemungkinan masalah berada di battery. Selain itu kondisi masih bagus dan tidak ada kerusakan luar\nBagi yang berminat dapat mencoba menghubungi saya +6281396774583", + style = MaterialTheme.typography.bodyMedium.copy( + fontWeight = FontWeight.Medium + ) + ) + + } + + Column( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.tertiary) + .padding(top = 24.dp, bottom = 72.dp) + ) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp) + ) { + Text( + text = "Comment", + style = MaterialTheme.typography.labelLarge + ) + + Spacer(modifier = Modifier.height(10.dp)) + + UserInComment( + username = "Sesar Dito", + comment = "Ga minat beli, tapi pengen kenalan", + photoUrl = R.drawable.img_user_2 + ) + + Spacer(modifier = Modifier.height(8.dp)) + + Row( + modifier = Modifier + .fillMaxWidth() + .height(IntrinsicSize.Max) + ) { + Box( + modifier = Modifier + .width(60.dp) + .fillMaxHeight(), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .fillMaxHeight() + .width(2.dp) + .background(Color.LightGray) + ) + } + + Spacer(modifier = Modifier.width(16.dp)) + + Column { + UserInComment( + username = "Ong Gabriel", + comment = "Sama aku saja", + photoUrl = R.drawable.img_user_3 + ) + + Spacer(modifier = Modifier.height(8.dp)) + + UserInComment( + username = "Dwi Nugroho", + comment = "Tolong jaga sikap", + photoUrl = R.drawable.img_user_4 + ) + } + } + + Spacer(modifier = Modifier.height(10.dp)) + + Text( + text = "Reply", + style = MaterialTheme.typography.bodySmall.copy( + fontWeight = FontWeight.Bold + ), + color = MaterialTheme.colorScheme.primary, + modifier = Modifier + .padding(start = 30.dp) + ) + + Spacer(modifier = Modifier.height(24.dp)) + + if (showLastComment && userSession != null) { + UserInComment( + username = userSession.userNameId.username, + comment = lastCommentText, + photoUrl = R.drawable.img_user_1 + ) + + Spacer(modifier = Modifier.height(10.dp)) + + Text( + text = "Reply", + style = MaterialTheme.typography.bodySmall.copy( + fontWeight = FontWeight.Bold + ), + color = MaterialTheme.colorScheme.primary, + modifier = Modifier + .padding(start = 30.dp) + ) + + Spacer(modifier = Modifier.height(24.dp)) + } + } + } + } + + Column( + modifier = Modifier + .fillMaxSize(), + verticalArrangement = Arrangement.Bottom + ) { + + Box( + modifier = Modifier + .fillMaxWidth() + .height(2.dp) + .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.5f)) + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.tertiary) + .padding(top = 10.dp, bottom = 10.dp, start = 16.dp, end = 20.dp), + verticalAlignment = Alignment.CenterVertically + ) { + + if (commentPosted) { + Box( + modifier = Modifier + .weight(1f) + .height(56.dp) + .border( + width = 2.dp, + color = MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.6f), + shape = RoundedCornerShape(20.dp) + ), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = Modifier + .size(24.dp) + ) + } + } else { + CommentTextField( + value = commentText, + onValueChange = { newValue -> + commentText = newValue + }, + modifier = Modifier + .weight(1f) + ) + } + + Spacer(modifier = Modifier.width(10.dp)) + + IconButton( + onClick = { postLastComment() }, + modifier = Modifier + .size(36.dp) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.primary) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_create), + contentDescription = null, + tint = MaterialTheme.colorScheme.onPrimary + ) + } + } + } + + Box( + modifier = Modifier + .matchParentSize() + .background( + Brush.verticalGradient( + colors = listOf( + Color.Black.copy(alpha = 0.7f), + Color.Transparent + ), + startY = 0f, + endY = 600f + ) + ) + ) { + TransparentTopBar(onClickNavigationIcon = { navigateBackToForum() }, pageTitle = "Detail Forum") + } + } +} + +@Preview (showBackground = true) +@Composable +fun ForumSingleScreenPreview() { + TechwasMark02Theme { + ForumSingleContent( + userSession = UserSession( + userNameId = UserId( + username = "Ghina", + id = 1 + ), + userLoginToken = Token( + accessToken = "" + ) + ), + navigateBackToForum = {} + ) + } +} + +@Composable +fun UserInComment( + username: String, + comment: String, + photoUrl: Int, + modifier: Modifier = Modifier +) { + Row( + modifier = modifier + .height(IntrinsicSize.Max), + verticalAlignment = Alignment.CenterVertically + ) { + Image( + painter = painterResource(id = photoUrl), + contentDescription = null, + modifier = Modifier + .clip(CircleShape) + .size(60.dp) + ) + + Spacer(modifier = Modifier.width(16.dp)) + + Column( + modifier = Modifier + .fillMaxHeight(), + verticalArrangement = Arrangement.Center + ) { + Text( + text = username, + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.8f) + ) + + Text( + text = comment, + style = MaterialTheme.typography.bodySmall.copy( + fontWeight = FontWeight.Medium + ), + color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.9f) + ) + } + } +} + +@Preview (showBackground = true) +@Composable +fun UserInCommentPreview() { + TechwasMark02Theme { + Box( + modifier = Modifier + .padding(10.dp) + ) { + UserInComment(username = "Ghori", comment = "Woow such a great insight", photoUrl = R.drawable.img_user_1) + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun CommentTextField( + value: String, + onValueChange: (String) -> Unit, + modifier: Modifier = Modifier +) { + + var hasFocus by remember { + mutableStateOf(false) + } + + val focusColor = if (hasFocus) MaterialTheme.colorScheme.onTertiary else MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.6f) + + TextField( + value = value, + onValueChange = onValueChange, + colors = TextFieldDefaults.textFieldColors( + textColor = MaterialTheme.colorScheme.onTertiary, + containerColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + focusedIndicatorColor = Color.Transparent, + cursorColor = MaterialTheme.colorScheme.onTertiary, + placeholderColor = MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.7f) + ), + shape = MaterialTheme.shapes.large, + placeholder = { + Text( + text = "Comments...", + style = MaterialTheme.typography.labelMedium.copy( + fontWeight = FontWeight.SemiBold + ) + ) + }, + modifier = modifier + .border( + width = if (hasFocus) 2.dp else 1.dp, + color = focusColor, + shape = MaterialTheme.shapes.large + ) + .height(56.dp) + .onFocusChanged { focusState -> hasFocus = focusState.hasFocus }, + textStyle = MaterialTheme.typography.labelMedium.copy( + fontWeight = FontWeight.Medium + ) + ) +} + +@Preview (showBackground = true) +@Composable +fun CommentTextFieldPreview() { + TechwasMark02Theme { + var value by remember { + mutableStateOf("") + } + + Box( + modifier = Modifier + .padding(10.dp) + ) { + CommentTextField( + value = value, + onValueChange = { newValue -> value = newValue} + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreenViewModel.kt new file mode 100644 index 0000000..a4931e7 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreenViewModel.kt @@ -0,0 +1,41 @@ +package com.capstone.techwasmark02.ui.screen.forumSingle + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.common.Resource +import com.capstone.techwasmark02.data.model.UserSession +import com.capstone.techwasmark02.data.remote.response.Token +import com.capstone.techwasmark02.data.remote.response.UserId +import com.capstone.techwasmark02.repository.PreferencesRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class ForumSingleScreenViewModel @Inject constructor( + private val preferencesRepository: PreferencesRepository +): ViewModel() { + + private val _userSessionState: MutableStateFlow = MutableStateFlow(null) + val userSessionState = _userSessionState.asStateFlow() + + init { + viewModelScope.launch { + val result = preferencesRepository.getActiveSession() + when(result) { + is Resource.Error -> { + _userSessionState.value = UserSession( + userLoginToken = Token(accessToken = ""), + userNameId = UserId(username = "", id = 0) + ) + } + is Resource.Success -> { + _userSessionState.value = result.data + } + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index f09981c..e6d2dfb 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -155,7 +155,7 @@ fun HomeContent( ) { Image( modifier = Modifier.size(24.dp, 27.dp), - painter = painterResource(id = R.drawable.logo_techwaste), + painter = painterResource(id = R.drawable.img_logo_onboarding_nooutline), contentDescription = null ) } @@ -219,10 +219,9 @@ fun HomeContent( Row( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), + .fillMaxWidth(), ) { - Spacer(modifier = Modifier.weight(1f)) + FeatureBoxLarge( featureBoxType = FeatureBoxType.Detection, onClick = { @@ -233,7 +232,7 @@ fun HomeContent( ) } ) - Spacer(modifier = Modifier.weight(1f)) + // DetectBox1() // DetectBox2() } @@ -242,13 +241,11 @@ fun HomeContent( Row( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - horizontalArrangement = Arrangement.SpaceBetween + .fillMaxWidth(), ) { - FeatureBox(featureBoxType = FeatureBoxType.DropPoint, onClick = navigateToMaps) - Spacer(modifier = Modifier.weight(1f)) - FeatureBox(featureBoxType = FeatureBoxType.Catalog, onClick = navigateToCatalog) + FeatureBox(featureBoxType = FeatureBoxType.DropPoint, onClick = navigateToMaps, modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.width(24.dp)) + FeatureBox(featureBoxType = FeatureBoxType.Catalog, onClick = navigateToCatalog, modifier = Modifier.weight(1f)) } Spacer(modifier = Modifier.height(titlePaddingTop)) @@ -314,7 +311,7 @@ fun HomeContent( HorizontalPager( pageCount = it, state = pagerState, - contentPadding = PaddingValues(horizontal = 56.dp), + contentPadding = PaddingValues(horizontal = 48.dp), modifier = Modifier .fillMaxWidth() .height(180.dp) @@ -324,7 +321,7 @@ fun HomeContent( articleList[page]?.let { it1 -> ArticleCardBig( modifier = Modifier - .width(280.dp) + .width(340.dp) .height(180.dp) .graphicsLayer { val pageOffset = ( @@ -344,7 +341,7 @@ fun HomeContent( scaleY = scale } alpha = lerp( - start = 0.5f, + start = 0.8f, stop = 1f, fraction = 1f - pageOffset.coerceIn( 0f, diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreen.kt index 34c1818..61337fe 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreen.kt @@ -51,7 +51,7 @@ fun MainScreen( HomeScreen(navController = navController) } is BottomBarItemType.Forum -> { - ForumScreen() + ForumScreen(navController = navController) } is BottomBarItemType.Article -> { ArticleScreen(navController = navController) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt index cdcb828..674a0ef 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt @@ -1,5 +1,13 @@ package com.capstone.techwasmark02.ui.screen.onBoarding +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.core.animateDpAsState +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.animateSizeAsState +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -24,16 +32,20 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavHostController @@ -70,6 +82,8 @@ fun OnBoardingContent( val pagerState = rememberPagerState() val coroutineScope = rememberCoroutineScope() + + Box( modifier = Modifier .fillMaxSize() @@ -100,7 +114,11 @@ fun OnBoardingContent( modifier = Modifier .fillMaxSize() ) { - if (pagerState.currentPage != 2) { + AnimatedVisibility( + visible = pagerState.currentPage != 2, + enter = fadeIn(), + exit = fadeOut() + ) { Row( modifier = Modifier .fillMaxWidth() @@ -183,7 +201,11 @@ fun OnBoardingContent( horizontalArrangement = Arrangement.Start ) { - if (pagerState.currentPage != 0) { + AnimatedVisibility( + visible = pagerState.currentPage != 0, + enter = fadeIn(), + exit = fadeOut() + ) { IconButton( onClick = { coroutineScope.launch { @@ -210,18 +232,22 @@ fun OnBoardingContent( } } - repeat(pageCount) { iteration -> val color = if (pagerState.currentPage == iteration) Color(0xffFFDE59) else bulletColor - val size = if (pagerState.currentPage == iteration) 14.dp else 10.dp +// val size = if (pagerState.currentPage == iteration) 14.dp else 10.dp + + val sidDp: Dp by animateDpAsState( + targetValue = if (pagerState.currentPage == iteration) 14.dp else 10.dp, + animationSpec = tween(durationMillis = 500) + ) Box( modifier = Modifier .padding(4.dp) .clip(CircleShape) .background(color) - .size(size) + .size(sidDp) ) } @@ -230,7 +256,11 @@ fun OnBoardingContent( .weight(1f), horizontalArrangement = Arrangement.End ) { - if (pagerState.currentPage != 2) { + AnimatedVisibility( + visible = pagerState.currentPage != 2, + enter = fadeIn(), + exit = fadeOut() + ) { IconButton( onClick = { coroutineScope.launch { diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt index 02410a5..dd51bc3 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt @@ -19,6 +19,7 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -28,17 +29,26 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.model.UserSession +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.data.remote.response.Token +import com.capstone.techwasmark02.data.remote.response.UserId +import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.ArticleCardBig import com.capstone.techwasmark02.ui.component.ArticleCardSmall import com.capstone.techwasmark02.ui.component.DefaultBottomBar @@ -52,10 +62,16 @@ import kotlin.random.Random @Composable fun ProfileUserScreen( + viewModel: ProfileUserScreenViewModel = hiltViewModel(), navController: NavHostController ) { + val userSession by viewModel.userSessionState.collectAsState() + val bookmarkedArticleState by viewModel.bookmarkedArticleState.collectAsState() + ProfileUserContent( navigateToSetting = { navController.navigate(Screen.Setting.route) }, + userSession = userSession, + bookmarkedArticleState = bookmarkedArticleState ) } @@ -63,6 +79,8 @@ fun ProfileUserScreen( @Composable fun ProfileUserContent( navigateToSetting: () -> Unit, + userSession: UserSession?, + bookmarkedArticleState: UiState? ) { Scaffold( @@ -90,7 +108,7 @@ fun ProfileUserContent( modifier = Modifier .verticalScroll(scrollState) .padding(innerPadding) - .padding(bottom = 20.dp) + .padding(bottom = 80.dp) ) { Box( modifier = Modifier @@ -98,14 +116,15 @@ fun ProfileUserContent( Box( modifier = Modifier .fillMaxWidth() - .height(236.dp) + .height(244.dp) .clip( RoundedCornerShape( bottomStart = 20.dp, bottomEnd = 20.dp ) ) - .background(MaterialTheme.colorScheme.primary), + .background(MaterialTheme.colorScheme.primary) + .padding(top = 20.dp), ) { Column( modifier = Modifier.align(Alignment.TopCenter), @@ -116,25 +135,35 @@ fun ProfileUserContent( .size(120.dp) .clip(CircleShape), painter = rememberAsyncImagePainter( - model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", + model = R.drawable.img_user_1, placeholder = painterResource(id = R.drawable.place_holder), ), contentScale = ContentScale.FillHeight, contentDescription = null ) - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(24.dp)) - Text( - text = "User Full Name", - style = MaterialTheme.typography.labelLarge, - color = Color.White - ) - Text( - text = "user@gmail.com", - style = MaterialTheme.typography.bodyMedium, - color = Color.White - ) + if (userSession != null) { + Text( + text = userSession.userNameId.username, + style = MaterialTheme.typography.titleMedium.copy( + fontWeight = FontWeight.SemiBold + ), + color = Color.White + ) + } else { + Text( + text = "User Full Name", + style = MaterialTheme.typography.labelLarge, + color = Color.White + ) + } +// Text( +// text = "user@gmail.com", +// style = MaterialTheme.typography.bodyMedium, +// color = Color.White +// ) } } @@ -168,19 +197,49 @@ fun ProfileUserContent( Spacer(modifier = Modifier.height(8.dp)) - LazyRow( - contentPadding = PaddingValues(horizontal = 16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - items( - count = 10, - ) { item -> - ArticleCardSmall( - modifier = Modifier.width(150.dp), - imgUrl = "https://picsum.photos/seed/${Random.nextInt()}/320/120", - title = "Title Article $item", - description = "description article $item" - ) + if (bookmarkedArticleState != null) { + when(bookmarkedArticleState) { + is UiState.Loading -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(100.dp), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is UiState.Error -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(100.dp), + contentAlignment = Alignment.Center + ) { + Text(text = "No article to view") + } + } + is UiState.Success -> { + bookmarkedArticleState.data?.articleList?.size?.let { + LazyRow( + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + items( + count = it, + ) { page -> + val article = bookmarkedArticleState.data.articleList[page] + + ArticleCardSmall( + modifier = Modifier.width(150.dp), + imgUrl = article?.articleImageURL, + title = article?.name, + description = article?.desc + ) + } + } + } + } } } @@ -200,10 +259,62 @@ fun ProfileUserContent( .fillMaxWidth() .padding(horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(10.dp), - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, + contentPadding = PaddingValues(vertical = 10.dp) ) { - items(count = 10) { - ForumBox(modifier = Modifier.fillMaxWidth()) + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Jual Laptop Mati Total", + desc = "\"Saya mempunyai laptop yang baru saja mati, pada saat tombol power tekan tidak ada respon apapun, kemungkinan masalah berada di battery. Selain itu kondisi masih bagus dan tidak ada kerusakan luar\\nBagi yang berminat dapat mencoba menghubungi saya +6281396774583\"", + place = "Yogyakarta", + photoUrl = R.drawable.img_forum_laptop_bekas + ) + } + + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Cara Hidupkan Hape Xiomi Lama", + desc = "Tiga belas hari yang lalu jatuh dari motor dan hp saya ikut jatuh dan terbentur", + place = "Merauke" + ) + } + + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Bagaiamana Cara Menyambung Kabel", + desc = "Saya akan memberikan langkah-langkah mudah untuk menyambung kabel elektronik", + place = "Solo" + ) + } + + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Dijual Kulkas Potable", + desc = "Dijual kulkas Samsung berumur dua tahun tetapi masih layak pakai, fungsi masih lengkap", + place = "Jakarta" + ) + } + + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Membuka Service Laptop di Daerah Pogung", + desc = "Membuka jasa service laptop dengan jaminan uang kembali apabila tidak berhasil", + place = "Yogyakarta" + ) + } + + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Membuat Kursus Membenarkan Laptop", + desc = "Membuka kursus untuk mengajarkan cara membenarkan laptop lama", + place = "Bali" + ) } } } @@ -217,6 +328,16 @@ fun ProfileUserScreenPreview() { TechwasMark02Theme { ProfileUserContent( navigateToSetting = {}, + userSession = UserSession( + userNameId = UserId( + username = "Ghina", + id = 1 + ), + userLoginToken = Token( + accessToken = "" + ) + ), + bookmarkedArticleState = null ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreenViewModel.kt new file mode 100644 index 0000000..092a5c3 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreenViewModel.kt @@ -0,0 +1,52 @@ +package com.capstone.techwasmark02.ui.screen.profileUser + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.common.Resource +import com.capstone.techwasmark02.data.model.UserSession +import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.data.remote.response.Token +import com.capstone.techwasmark02.data.remote.response.UserId +import com.capstone.techwasmark02.repository.PreferencesRepository +import com.capstone.techwasmark02.repository.TechwasArticleRepository +import com.capstone.techwasmark02.ui.common.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class ProfileUserScreenViewModel @Inject constructor( + private val preferencesRepository: PreferencesRepository, + private val articleApiRepository: TechwasArticleRepository +): ViewModel() { + + private val _userSessionState: MutableStateFlow = MutableStateFlow(null) + val userSessionState = _userSessionState.asStateFlow() + + private val _bookmarkedArticleState: MutableStateFlow?> = MutableStateFlow(null) + val bookmarkedArticleState = _bookmarkedArticleState.asStateFlow() + + init { + _bookmarkedArticleState.value = UiState.Loading() + + viewModelScope.launch { + _bookmarkedArticleState.value = articleApiRepository.getAllArticle() + + val result = preferencesRepository.getActiveSession() + when(result) { + is Resource.Error -> { + _userSessionState.value = UserSession( + userLoginToken = Token(accessToken = ""), + userNameId = UserId(username = "", id = 0) + ) + } + is Resource.Success -> { + _userSessionState.value = result.data + } + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreen.kt index b8ec8c5..bd2f549 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreen.kt @@ -33,6 +33,8 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -41,12 +43,17 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.model.UserSession +import com.capstone.techwasmark02.data.remote.response.Token +import com.capstone.techwasmark02.data.remote.response.UserId import com.capstone.techwasmark02.ui.component.ArticleCardSmall import com.capstone.techwasmark02.ui.component.DefaultTopBar import com.capstone.techwasmark02.ui.component.ForumBox +import com.capstone.techwasmark02.ui.component.InverseTopBar import com.capstone.techwasmark02.ui.component.SettingItem import com.capstone.techwasmark02.ui.componentType.SettingItemType import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @@ -55,17 +62,23 @@ import kotlin.random.Random @Composable fun SettingScreen( - navController: NavHostController + navController: NavHostController, + viewModel: SettingScreenViewModel = hiltViewModel() ) { + + val userSession by viewModel.userSessionState.collectAsState() + SettingContent( - navigateToProfile = { navController.popBackStack() } + navigateToProfile = { navController.popBackStack() }, + userSession = userSession ) } @OptIn(ExperimentalMaterial3Api::class) @Composable fun SettingContent( - navigateToProfile: () -> Unit + navigateToProfile: () -> Unit, + userSession: UserSession? ) { val settingItemList = listOf( @@ -75,23 +88,44 @@ fun SettingContent( SettingItemType.Language ) - Scaffold( - topBar = { - DefaultTopBar( - pageTitle = "", - onClickNavigationIcon = { - navigateToProfile() - } - ) + val scrollState = rememberScrollState() + + Box( + modifier = Modifier + .fillMaxSize() + ) { + Column( + modifier = Modifier + .fillMaxSize(), + verticalArrangement = Arrangement.SpaceBetween + ) { + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + Image( + painter = painterResource(id = R.drawable.img_profile_ripple_green_reverse), + contentDescription = null + ) + } + + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.Start + ) { + Image( + painter = painterResource(id = R.drawable.img_profile_ripple_green), + contentDescription = null + ) + } } - ) { innerPadding -> - val scrollState = rememberScrollState() Column( modifier = Modifier - .padding(innerPadding) - .background(MaterialTheme.colorScheme.primary) + .padding(top = 100.dp) ) { Box( modifier = Modifier.fillMaxHeight() @@ -113,7 +147,7 @@ fun SettingContent( .size(120.dp) .clip(CircleShape), painter = rememberAsyncImagePainter( - model = "https://picsum.photos/seed/${Random.nextInt()}/320/120", + model = R.drawable.img_user_1, placeholder = painterResource(id = R.drawable.place_holder), ), contentScale = ContentScale.FillHeight, @@ -136,29 +170,29 @@ fun SettingContent( } } - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(16.dp)) Row(verticalAlignment = Alignment.CenterVertically) { Text( - text = "User Full Name", + text = userSession?.userNameId?.username ?: "User Full Name", style = MaterialTheme.typography.labelLarge, - color = Color.White + color = MaterialTheme.colorScheme.onTertiary ) Icon( imageVector = Icons.Default.Edit, contentDescription = "Edit", - tint = Color.White, + tint = MaterialTheme.colorScheme.onTertiary, modifier = Modifier .padding(start = 8.dp) .size(24.dp) ) } - Text( - text = "user@gmail.com", - style = MaterialTheme.typography.bodyMedium, - color = Color.White - ) +// Text( +// text = "user@gmail.com", +// style = MaterialTheme.typography.bodyMedium, +// color = Color.White +// ) Spacer(modifier = Modifier.height(40.dp)) @@ -200,7 +234,11 @@ fun SettingContent( .width(122.dp) .height(41.dp) .align(Alignment.End), - colors = ButtonDefaults.buttonColors(containerColor = red), + colors = ButtonDefaults.buttonColors( + containerColor = red.copy( + alpha = 0.9f + ) + ), shape = RoundedCornerShape(10.dp) ) { Text(text = "Log out") @@ -211,6 +249,12 @@ fun SettingContent( } } } + + InverseTopBar( + onClickNavigationIcon = { + navigateToProfile() + } + ) } } @@ -219,7 +263,16 @@ fun SettingContent( fun SettingScreenPreview() { TechwasMark02Theme { SettingContent( - navigateToProfile = {} + navigateToProfile = {}, + userSession = UserSession( + userNameId = UserId( + username = "Ghina", + id = 1 + ), + userLoginToken = Token( + accessToken = "" + ) + ) ) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreenViewModel.kt new file mode 100644 index 0000000..8b69145 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreenViewModel.kt @@ -0,0 +1,41 @@ +package com.capstone.techwasmark02.ui.screen.setting + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.common.Resource +import com.capstone.techwasmark02.data.model.UserSession +import com.capstone.techwasmark02.data.remote.response.Token +import com.capstone.techwasmark02.data.remote.response.UserId +import com.capstone.techwasmark02.repository.PreferencesRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class SettingScreenViewModel @Inject constructor( + private val preferencesRepository: PreferencesRepository +): ViewModel() { + + private val _userSessionState: MutableStateFlow = MutableStateFlow(null) + val userSessionState = _userSessionState.asStateFlow() + + init { + viewModelScope.launch { + val result = preferencesRepository.getActiveSession() + when(result) { + is Resource.Error -> { + _userSessionState.value = UserSession( + userLoginToken = Token(accessToken = ""), + userNameId = UserId(username = "", id = 0) + ) + } + is Resource.Success -> { + _userSessionState.value = result.data + } + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt index f9b8e31..1c19c4f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt @@ -32,6 +32,9 @@ class SignInScreenViewModel @Inject constructor( )) val userToSignInInfo = _userToSignInInfo.asStateFlow() + private val _savedUsername: MutableStateFlow = MutableStateFlow(null) + val savedUsername = _savedUsername.asStateFlow() + fun signInUser() { _userToSignInState.value = UiState.Loading() viewModelScope.launch { @@ -43,7 +46,14 @@ class SignInScreenViewModel @Inject constructor( viewModelScope.launch { val userSession = _userToSignInState.value?.data?.loginResult?.toUserSession() if (userSession != null) { - preferencesRepository.saveSession(userSession) + val result = preferencesRepository.saveSession(userSession) + when(result) { + is Resource.Error -> { + result.data + } + is Resource.Success -> { + } + } } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt index 194cdb5..d642967 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt @@ -38,16 +38,20 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.viewModelScope import androidx.navigation.NavController +import androidx.navigation.NavHostController import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.SingleArticleResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.DefaultButton +import com.capstone.techwasmark02.ui.component.HtmlText import com.capstone.techwasmark02.ui.component.TransparentTopBar +import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.Mist97 import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import kotlinx.coroutines.launch @@ -57,6 +61,7 @@ import kotlin.random.Random fun SingleArticleScreen( idArticle: Int, viewModel: SingleArticleScreenViewModel = hiltViewModel(), + navController: NavHostController ) { LaunchedEffect(Unit) { @@ -69,6 +74,7 @@ fun SingleArticleScreen( SingleArticleContent( articleResult = articleResult, + navigateToArticle = { navController.popBackStack() } ) } @@ -76,6 +82,7 @@ fun SingleArticleScreen( @Composable fun SingleArticleContent( articleResult: UiState?, + navigateToArticle: () -> Unit ) { val result = articleResult?.data?.article @@ -185,8 +192,13 @@ fun SingleArticleContent( horizontalAlignment = Alignment.CenterHorizontally ) { result?.get(0)?.description?.let { - Text( - text = it, + HtmlText( + html = it, + textStyle = MaterialTheme.typography.bodyMedium.copy( + color = Color.Black, + fontWeight = FontWeight.Normal, + fontSize = 14.sp + ) ) } @@ -214,7 +226,7 @@ fun SingleArticleContent( ) ) ) { - TransparentTopBar(onClickNavigationIcon = { /*TODO*/ }, pageTitle = "Detail") + TransparentTopBar(onClickNavigationIcon = { navigateToArticle() }, pageTitle = "Detail") } } } @@ -226,6 +238,7 @@ fun SingleArticleScreenPreview() { TechwasMark02Theme { SingleArticleContent( articleResult = UiState.Loading(), + navigateToArticle = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt index 0358c2f..0ca3227 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt @@ -52,18 +52,18 @@ fun SplashScreen( val alphaAnim = animateFloatAsState( targetValue = if (animationState) 1f else 0f, animationSpec = tween( - durationMillis = 3000 // 3 sec + durationMillis = 1000 // 3 sec ) ) LaunchedEffect(key1 = true) { animationState = true - delay(4000) + delay(2000) // navController.navigate(Screen.Home.route) } LaunchedEffect(key1 = userSession) { - delay(4000) + delay(2000) if (userSession != null) { if (userSession!!.userLoginToken.accessToken == "") { diff --git a/app/src/main/res/drawable/ic_create.xml b/app/src/main/res/drawable/ic_create.xml new file mode 100644 index 0000000..0dfda73 --- /dev/null +++ b/app/src/main/res/drawable/ic_create.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/img_forum_hp_nyala.webp b/app/src/main/res/drawable/img_forum_hp_nyala.webp new file mode 100644 index 0000000000000000000000000000000000000000..85358aa07c45aa2807e8c3be8cd7fa7123f39c5a GIT binary patch literal 195116 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�V~sKW5K-ba%i(hE%>MF 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 F005bB>KOn4 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_profile_ripple_green.webp b/app/src/main/res/drawable/img_profile_ripple_green.webp new file mode 100644 index 0000000000000000000000000000000000000000..6c03f0352a252c28184f2cbf1817055a62c68f31 GIT binary patch literal 12228 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_profile_ripple_green_reverse.webp b/app/src/main/res/drawable/img_profile_ripple_green_reverse.webp new file mode 100644 index 0000000000000000000000000000000000000000..0e7dcd3c2fb467b76fb6697465b1329ff8f50f8e GIT binary patch literal 12448 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

Hk{oIj8&9>uuijU1MXBh1MYS4|UHqC0NM zABg5OJoXx`9mn}j4p;yD&lL;o;^_wG5OMR(#oEwW`y8^sQ$oJIb;Y!>6se!VA;=pA z-tjN)xYlu;%}@77stMx9+J@v1lpJzStJT^$X|U&nef#H%Y0*+w*q%iYrR|Mob{cB5 zbI2U_FL{h=dH@J!5=pmZgLFNo<6PM_Ua)dKYA^}vJMe-!!gu>}4{|uFh5A^oVlXCaRiz> z$_GmFE*}PYL^4^38KuJY9SLs z+`VJhy$o?PM ze|?Nn`r~Uc3UWok?$kD`z#o;PWJi&bPY|v`M6SyDI5D2UJwAUsCDRw2C81L8HuV}LgV`;A(G;hJy?x}QG=*ooT5 zg}vMR&sECX>xl;E6rz`|M#H#+<7vQ`8~<~Kw62!HDfR$nq{P8-FP9fiP_5RKIj3;V zO$KXg)pvWA0`8okQax&LieyGZ`zhPG+n4*v-YPYlpilA%8Z*b;IgSJJ60%?Z`Jbz! zF_jEX(bb?E5#}AoxoTuzIWv{gP@^(N;f(@$wV|`)I5=$E`-%5f=)Hb8%qZffn!iHF zahzKKarQL?`;$5$K?$rSpNP(<-xA(dJC3uBTbS$w|6G}fAS)K^;}aACa922v<8ZV6 zG!P$bTp3NIUwYh(f>74%*vCP;9h!?=yijK=t4ZJ#p9suwF3!Pnd9(MQs}dM)8=T_v zpDMRQ266KFH~!}q$$PJEl2N!_Y{qzVb544hFQ|%+{1Ix$C~oz8^H?^p_oID)=Dk() z1QQqqzPzx1I!@=}-04+3V6s(2D)-1J2pY|(aBj}OUL#uADq`~6;S~S>Id&e-$Bk%} zLP3X9;3*F#!K%DYx>xVU))-h&pMm5PIALCQMP5!KWG=Oa24x6M;S&dir#0)(NAbq{ zcdP*`bURNzVZ@L!E2c-xN5K?OWhO7L_CHlvYMf=WV zrtOsWif34omqJG|T=XfLkI9B%5Uxyu!dnzo`LX z=2Ek~*V+c>6z7Iy#cz$Km%~!T(6kc2#eMaPip(-MaNras)4WE%smk9zUvuPb3?Qsx zL#_U62ly11V~WVqo{m)*HTKc|Qv$-F%#x78DK3^Ni2(T5D-tkA`N@5*3QoMpGZCn%rgBRw|)f;<^Ds?Pg!E8IQHv^;KfKEvsYqp4SbBdfe z03e-#Qiya#o&!}@u}c`coIo3}fyraSQmi66k9a}6cTd2638hSSJXBX~HC8dt7!ovn z0aHT!kMUR^VMdV>2jGr>D9jTIoDj2m&_jFOFQ-V}F$`M*M@1GTPx4UJ)8rJccob*O zC3x1r;Q_E?b#Lq$2!uMU04Wa_Xtv?nsSO*rpCoEDh0v#c8{zNnx!*}y@~dH|Ft2&=$@Zb@j77nS6JV|_{rr{LZ_+{WaHzqI)}?i)L4 zD;b3=3Vy00IaGatr>*-|jM;OFIv9sPOOpKZrkk((x=2n@kK^1pNwTRE3%T8v*T>Km ziC!|-d?ureEn5=2Fozz|aaUkGtRj1Fw53fF6;CpBbXV%!S;axMRm-9bsfd8PM5TV1 zRj^I!S{o zX&}tTslsmhh+AhBb=(=^n3hKU<|>56+>^E)R`E?Zj#kMtOIn&F_iXM&oMNKeQIxhf zie}Q5Cx7IRanG?%#wjArVwgdZmnUwd;oUPTYRV~6pM{x|I}3;#@~E1bNp4y3+i{Ay zy}ZFbK2D-qA|c%9B7V1Y`F>8Z%Zx|!SK>%a0R55NZh@K*%qjZ3)f#15*tZ?rEvxxl zPI2;=+)E~990HY5DCQ1SuMMXtMlHp8O65n?^L0n(FsIlXUrXI8m8wEzQ$I>FF^oY8p5$R3%xXDyXna`-NauG2@MVuw?l?KgN}K(GsV*|lVinv=y~-BJ{9>r{b%hLETRN+l6b~|5wpRVS5TWF#Q0T}i9)+8NY|0SD zm6mD9npKPyYO^E#>$vljvx5peSM3TzinVx!7?ffXRzVP{upVHL#VX)DHQg1+bfF%q*Pc}{PCa*q zl&cC_VOD{4not>4uJGE%%_=+^s~{5!%)^D$g=I)i(SNlHWV#Tk2Vftk;6*)nFDdX` zF6g?KID1Y3ZOa-}sO>^%J7C2rZn{B%?U%ZcifXQnQ((u#MMi-)bS1F4-{chB_-qCC z<%%vGYH&tzE2Tj|Q?8H1Cz3!q9r+tgBj^&TN}9!Lq|00L>P5fyZB=OD8YR~uc9Zf~ zVE47*6s^Lh7D;sDb2MnMUxP^qI!7uMyWWNbmo^!8wLBq4YkwW!7? zY6$M)=OAcbB-8|rsdf=lYrWzXBh{UXROYtR6|cDUIf43AYfo^LvpG?>CIHDum)^Ie ztBS!fqQHmsTjY`^uAU@4hLh*H+-KgFSTI;@Lu7igmqrcFro)3Gt)XYnky4aIo;L3qno|{9Q^q7TOG+K#F{M7S<=zX){7%;pCXpJ5d=$0N6$gB(qUEAA%QNyoa4N@CUOyMKyin-9yWJ{#5np)57TfTR!@!L6!DS(Z5 z6l`a1(E5iD5Uok+JI}1}xId-IcH+AT3UyoRXm?o56?9Lm&Qp5D+D`Z*)NTz3gKDKmLtB$&8FPEP zp)kFRT=8zwmR2=2qNDL<=YQ)YG{pdqPR_W?OZ2%_*!W7B!6^~*EA+!nZi(NAWz4rAukxl6WYSI z6fiof`*a$rm*BIKEUQC2v^!Df10l6hH#erLp@@!&yq*@>W+1mRXjN zzS-ZyT{Ys9 zQ8R!dC118t%v_J?dr7PPh#6ZmL)NE!|4aYTYPw)5o9ofM>%cm;=mq}skgr^azdb<QVJq`gKbiUQ#(olG73;Lj*NzOWB^G8 zX890|gV)Vq9Z!V<5Uo=Q-!SuHfjgkW*?qf6ly4Y0oYO;0D*(~&u#|7$D&DrM6d)LI zCdQGuUxFL>Us}YJ}utWh2E3+ftc;L0#3LLMzoWf#!rU2NfL?;@X&=qou#_WMRXq-ubC=%gqQ=ZM|?--V^4k;8nPV{G%#50*}hLX4kt z(BJ>~8l@YpH|uEME1F5^2z4&&Nb)KMXChiQl6FU|gRXvLgJgaxT?y}?83svq<-Z$Hr8Z!wF$t4~xkTjnbEMRI$^=t;z^CU6p3CSymf9_w+O%@G-Bbmqn%t7-6{5o2nIrN5Ed2lbY?P3vB(pfLb2fp&m9j3l)D3r!hT4B|3g0H z!IlwU`IV+1ij0nWb_hN3cq8=Z9or@62ltC>Wtz!|v7U~;?l{iA|FcDTREvU1dOqt+ zTEUST73a@!j`8sT$i`r?uyJvCVf=o-zd*TO;P?CeaZTH0d&i>b`I895-$SA}f{__3 zNiO}EMGCny-{KBCjlQV6=&$Dp$4fjNL$r%+xS0GakMk>&d&j6z49e+CB_d-!S1iJD zf;rdsz_&P!%)a;Z^P|I*A71IR6VI+y@xqj)y=2iTSHdAKPg5NBDq=pzagu|zlYBYz zB?2TjVHtE>eT}@qiB)c@qDe0qMMa`S8fe4*B$*Mx1{>BKqH_Gv z2_Vj|qD^lZx#BY!wQ7pOvSjyHDduuI=5!b1ny83z&_xlVo;R6zc4U+(4AD+Szh1MH zH~`iqe5wj9$f1+Olo;`8J&hq+v0p{sUNgc^F9>xjR%=TV zk5Ud9b2yHZTvU>jle;JCT$3JscSa{TyW(Z2=-+!5^}Z_@+LkYtq%xJ35{NCZ|Fc{V{z5YXa1 z%~#i-W1NcVy=#>7EDY!3R&FbB9|k;aqYbBR(w_QV#XnOShxyu(6YFQISfZDWXePrQ zs0asY3Nv=B=QvJLY0}5^zQyY20!g06XvB6ZR_S$%8`p5A~eh|xqq{Il#|TiQuF{me-ZLzishpM5&C$a9QSu~F|E#o2!) zJeEOaIsol9IJ{Myj=4j&s9rc|dC4~ZG-Q-=!TVLL)eA?2s}Ss~{O4;D{*%UG=bF!H zTvU=I2wmSaCcRz^pNtakSFv2LTx7rVCowZo{(FW0;&0Fb!QNkq(k-gz8`sQ_&-SZW zuUC%7?(JtsP9D~N$~VL}l~b~tgFp4S-mlW}X3{XTWc~m!NbgU`l$7jbWMnM#r-zsDem)jk2 zJyD=po{J}(62hBFGOV}CK#8rUkga0t-aMkIZxtGiaGWRywpWwL9~P~=>1w;faf)(= ztn`|NgZ6b}i74Wgt605vkBGW@<`yvFKrspJ>T?3-YIR-^y}S&iE;vr(U{cQY-Ok=d zg9$fStSSP%eob+VCp5|Sqb#G*WNKWfj4~3f$?M-lnOzEE1qJqhdB4Pl`SIBcQw)TN zlCCItPOMWb2IY!OX>2c_yMFNlMHjtW#)^=zj-rNYUiPOBNDspXy zy_MU&&ukw3&zVg|f1w%weaLJknXk-pcb_nutQ^i=F`Hu(^(nKt`-L)_A(%(Z#%Og< z#ca67TF!mTY@nvPT<>RQW19N^W;WLg`-RzD?8EVz?yR%0-7!f3cdBH~`}s z(o;2HH97G=(ELV<)l7{O<}P?md_i1Xv;)kBHA3zT@tPgNQSuSI#v28iochnBT+3+d`^*(yU2CU{NuYTW;$ZBZC8(lZA+2VcP8L#=7G4%Vw z;u^4;Z&~6Y*3D|j6$J~%yRC(;@kW79@Hq=zlRQ;sL!}E0CCF%XC6@_!D1>`ZVJ{2s>+4?k zx<5lNVZgSKL{Ax&(dz(kL#N?>vVCi_@;7Jyt|2Y9&J_h?JfT?Ed0y{ujpgVyR}rrPyaMMXIL|mdo~&O*5A+OpX!o5DX^#CM6~-3-B4RW& zntgqX1F_ErXEls4kEfxVo{7DcimQ-%R}>tZ=k*R(KDLPpWs}D1qO+pAB6PVcaBhF) zSAOMmV2<0v*1GDOW=+!!XTiPHFU`HxdvLqhF0Ily754t==Y%SWGLT!*-di7-le60+ z7~|d9KfV>)q;^e-1E9j_OVkYVXt+R~P`v}{M0e)IU#8hsv{|NhTHJ0K1mcu;=G zvr!@Q*vveY+%sJkDjde$9`4~D?%{rh(=vL+py~R6O~347$JFnwt2YXaP@yxfLJYMT z$9Eg4252NeGT<;2w zP~mt4uPt6Rn!IHtK1+BnorP!OG1YaZMzwQS6(f6Z)D;CEP~755+UV7D^WgS0o z6<2W;S0Tm|)zwS?;C?7$KXn5@{D8*Ym}>sv9TdhBibtq${Sc0{`vA)TJiG3tzA~77 z=$-j_FeBSGrOVW=+t7`f8r5^)%L_||^X;9y)hnzDZgFvO%f3!+Bc?|kD~O$K4V<1o z$DKVdetMO*Q{jF&BYLJ82x|EQ4mjZ1pJf>^Gp~o}i*+2UU;|+a%#1Fa&V|{QnZ$8EOM`)o7@zV>N{bnhKf;jR)lL>n` zNN9~Ff7cBRXQkyVBorfv>+5}QeKNBWxs;jH3U$UBerZd?|C-hoMZ!ongx!@G)xqubG@t};nxCn99L~jEY?8QS435a(w)Kz!cFLvo z62fS=mkn;ca$#qCd6ZV6HoG0k7+NUHrucgAYktJ(GQ{P zF5}UKwjfGA(LauVF9CyV9IF|^RWPh|HYdR?jQ`ys+*@rLi|1_Vz_m{2vQM3DPRBN> zPhgHMi@rvPMvJ%GHLh`9F8ym;TU*04>%P5cG$cY_8MbW&$|(o09!hGsi3I|p=TJ?%3e$Y?@0?~I*T`W{1unG&nG|W zV^03O_Alr2RO|e17-p7%?D?5HbBr9>N34BTGcVTgSdtc+_2j;f$Cj~H{~yu3cjx^* e=Z`A0tz^cs_J?byMfv~K{C{fxKQ;fKaWW;NZ~y>+{_h3)&nYb`stAYw_Yr^( zXKP~j9gGY1|9Jo7`%n9S9*;`^ z;6IjmhX42e|I_>b@q}P%XKxAs05SgBtxe6ooBYKAf3c;ho#{XJlYg+gi=ztw0H*jC zV>tgE;9vZ=4}f9(U+nP@w)iiO`j3yQvglu*TmS$D!Qwv{uJRvj{2z?g`VTg-bhZNk z@CN?+lbbj?|Ba9LPcD-Gj^Qr?08svUA7TqLdoyPv7c*1h{}}&o-u|~-kl+7){QsM= z|Myt`U*-8{?)*3J9shsk1Q09re{2qk007q&0018MKQ{6#0021{0BG*|ADeLz0MHT# z0N`wyxH`N2Hy*@44I}^#fDFI@-~zq?$NU;?lN z*a4gY?f@S^ARr9z6A%YT0;B_S0EK`uKsBHq&;s}k=miV`#sM>cMZh{>2XF{D2iyQ2 z0dGJc5E_UGL;3@DH_zDINh5&{EMhHd;#stO%CJZJErV6G9W&!2|<^>i476Xc6R{+-rHwSkH_XCdvPX^BiuLf@i z9|oTX-vPe>e}RC4K!+fPV1VF-kb+QyFoAG_@PmkgNQWqeXoeVon1|SfxPkbDM1&-O zq=V#vl!nxVw19Mn41-LDEQV}?9E4niJcN9Nf`Y<=qJrXtl7iBLvWD`8ih|05s)6c( znuXejdVq$8#)YPX=7&~*HiCA64uejEu7vJ}o`XJweujaEA%bCrk$};Lv4;tQNrowh z>4KSqIfi+IMS-P&<$+azHHGzrjfE|QZHJwPJ%oLOLxrP)^Cxz#RSAw^K4}edFuZ16h--UlcKtrHK5Jk{Ma7BngC_(5!SVg!)L`0-S6hhQS zbU}kyr8=5Sd8Coz}c3Ml?4BBZrFggx8E4nPYS$ar%ZhCwAeEMYu z1O{OSH--v^T}CWMImRHy7RDnvz2GAuzX?JT#fw5%qq z8LSIzh-?yU{%oymf4i_E(|V3 zt|+b%Zb)tsZh!9I+%G&FJT5%-JlDJoyf(b$yeE8Ad}e%weEa;Q{6_qF{5t}~0)_&) z0y}~vf<}V*f_p+_LZ(8+LdU{1!q&o-!dD{9BF-XBB2S_`qQ0U%V&GzuVv%A~;%MS( z;_2dB5~LCq5)~3RlI)V+l08z8QnFINq?V-#rA?&Eq;F(6Wqf4@WD#UlWYcB$hq}ZVZrKG5op>(9oqU@tQtb(p$pi-{# zs4AiwtGcd6t>&uMr;epeud$=ar0J_Uu7#&%rPZnpt*x$Ito@)Pu9Kv5 zsLQS!rn{s^rRSkHs*k5{tKVsWY+z*2U~bU~y_GXqjwzVI^vnZuQ4n$~wpT$wtAZ#0F%mVOwJd zV`pgBW{+lXV?W^V#lgd2){)LJ%yGww$0^C_##z?6_&e~s-uG4)jK7QYge$dcsOzqq zfLn&!v%9)`g9oaIy~l(nt!ISiv6qBbkvD|5iFcn5iBF)M z3a|>-iqlHn%9$#$s@7_T>bx4PnxD0RTG!gMI>Wl9dfEEE2CjzcMvBJFCiJGrW?-{t z^G%Co%TB9S>uj4$TVFeGds7EvN6BxJ-x-~lov~eTT_IhdZm;f#9><=GUW?xSK7+pX ze$D=c0i}VdLD|8PA&H^>Vd3HK5&n_iqdcQ+V_ah`;~eA76YLXBlkAgCQyf#x)11?- zGu$)nvwX8%bAofd^J4Qu3(^bYi}H)JOKM9i%eu=uE2b+atG26u*4)~!_SW}J_RkN#AG{xi93dVh9}^vyov@z#K9x9~Iny~i zJa;^Qy9m2Pz0AC#zG}P{x}LbvygB^i{0DR!b%%Rba{u+d??Lfl>(TDt*;={T=!}^@HZ4{ZsaH17rsR{mTXZ@0Gzbc6q;QUkY*uN85@lo)Wa#C}Z z^VYriUVj8%?0@E&;W>O}aO&R+N(E(oYJfl=Ic+(Ig4>{!kNg*s52m-2ccxoGfI(^Z ziQsSlBv8>OHVE_ys;pV}cN1*w%Iz-m_W-4Ret+sXBKv5$^lvk`$T{=B1Z9DgZXrLQ z-#FixCb!dx-u&PBhXjZHS3#gF_z(B@?e`kXn%C`j!F9hkUp$Zt$O+W&QF0BM@xPC~ zA$sT*@Dmbz@mBE%fHFWJP)#dz0PmAa!o~D;z@8l=Qq)W|1^kupQ!KpynD#+92D{b`EK)~@XT~=(3G?5 zZ}(aD+45M^F>C`82XQW7uf`UEN@iGqeiqke&I~xiy7Z8SDHG8Im&WbQ>=9$Wgs>_hhHWbdnv{u=KX9C6DSj=ApFeV zu3IOh4YC`0+nHVu)N9RGc53Ju`-`a>$QwEgd)K`Ito52`_--$V-?s%XP$}>B+-uRo zAfdGjX;%uQ#)SofEWA_6q*3780-IlShgyeiIMA z#<@+2WFL!8lZQ~;$1>w%WZWsid7tvbkmq-t@W#7WH}CPzWJC=O?idoyt@?C8V{&a(dUVG&?}iX4=4{M31fMJMh11))?=&T4 zYp)^qcKzvv?lcZKB&GQ|A9N*jP=5s4Idf`|2FxzX6uiYzhn*;t#LOgW+~}rC&$sit zOBBpi&G2E=h4qy82R;Y~kal0TU@aIhrp;t5*ZI{8_ZY6okukEcuj}OV@>B*!rm?=` zD;Fi-u{kYKXx#9DF|z*k#~vmeY%JQyh09rbx3V=FtAYsq@ut{QqHIHwL9^B~SpsUznVfAJ0f%&iDr8kU% zJWgiHk!7Wf$bk;h{uS7!$_+OGo^|zbT^t)FFoEBa+05S>{GkQQ_0yD9PuT9<*!+)O z1?}ntx>t@f+GV&(ZCcJIbOFvC_DQ*U0SSE9DSG&iAzTJR^+jf0A1&<_D=v5W7ov8j z6)bvwZl*O7Ydqlkdk9y->*VPJ8^o>X6HRgEoz(C=(%pM#+M8qQHu}ou#bT#l3#YdQ z{Qvyg*2%{`M`GTxKotxHGdn!{c!zoCZ;>=S9)_B9>O;T=Ly+WZ4|DWwZxX7w;amDh z&LQ-rW!sOOkD}9^07Am#<(#;3ExpVz6{OS1CFyIe-2q#x6|i3Pq#^qVmSoWD-i$`j~w&uA>B zr7pKZFxUia*Zn^3!vQ*D^w|9VL8=)YEx!ekGd_zmt7O+9zAt|5+nndSF|thDXObcJ z=BJ?+U!9=uZtYyC{tN>QFD*?<>WvVhLjio`;a7Y$uh5>of1vp$wuGAKSET=wx^aT= zFjtz-5X7zC=S+Pc1~HiH9(2Xj}JN;nym1PXR~CdtQoE&kDiw$X=O%p z-BLphRyzkE*OQ{9aFV`T>!|0oB{X2l4YvKTeqWTbi@2HFosTTwI?o#m#S7qTQI^;q zIkBy4?P&O=6^Uz*v^b}3nIZYkkuicZaX^b(v$u;(1x!m<<-kpn3W ze;B<-5AQx)N0+80c__H~Td@cyMr^n*VI}z1*LOZ?s_Fb*0UFq7^A@Nbxrf#4U4o3Oy&LsOIb=(m3Y$J2$AXLFs2SFolh$p7{(~-xc&Rp6ug|xrV`g% zswr=a*EZz|W=qLyuf}vE*mgUB2pVfkCPJPC|N>uvR^3feR3CDsvK{n}2VRkJJMS1yjGxA6TtnIphT?`+T#zf}CeZ+jow zc_C5CoGNH(%e`~Vuei^_yS(~Jx);?rY5!y+qkAU|_C#>Zel#1ZFC<`Cc7%ME0109F zc!)Xq{dp09k1Et*Zwggf51Hr+GAPdO+8|D@s{`wvKJ^$F_nfQ!kvMWk55d7}^&?k| zS5gKHy4c-MxKl-D%OFS%1peBdKa3&0<&j7E@C7}f1|M#s5v~1Hy)V!mrP@=oX!$@O z8!6`JCx&h&`JPd-+v*t948TLwtpnEb(G3o520ui=Qot3y%u7fS|?UU!F&L=$t7X6QB?jzOuPLd_3<1?{1 z9jiOPvMafD0YS1U^4ox_rlv={>l>XfpU$#x2#NMCkkDw*n^7dlMc~U|Ldl}xm7Ql% zkg^@?)0F715m_XVH=m*OEg5MqpP=LRMRT96it}m<@B8f!7h3@X6&0%F6U|KV=ESya z+JH`2S$|2yE?dcWt5g#buj*Hs!eJ-NmdTHqDMhjfp|zzLQS~hws$x7Md0U7n+L~15B5bkg%E=8Nx;MLy{u;yIB&K%{Ie5L~f%2Rrk4JxCwiwBX) z_xckC@XsWWqDcn<1mgn8c%)E*xW~j1XhM6ELTSuKj<@iguus6~f}^iD&>$QQ!uv{Q zpk#1wlrgX;D70_duJbS##TV8Weh#j1nO$d!sIHOx#Ap}oMGgf6KmF1aN^nKWGlj^S zbeOq-H%&wU>t0}Mnj}Laq$M5-SX1|_@T3eD-3qTe+;WA-)`m7Uov5{B$^8Rrl zk?St;e!_d$@MP(kMyEUBw9NkmODf>^?YF_JW}I+9BH_ zJ%dFQDoKBh><#f7)rj)J5!!;(>qwbR(hS(;e?+W>{Hm1g#wjNH#;8U-ewWz>xr zGZR6U57h{B#@k+g_{fez&|}@Od;XP1SGtBQS+%O6fA=1otUM*#q-Rqo&;H8z)y|vl zXJ;gsby1aFiKOaYhb9b=N;v#Z6X$uP;!lLc^O|tHdAj|NcS+W;p(bNTvM7i#6;7tj zinpHT#c;Y74uy|7gu3mXTd}YY~^?kR+GNy0hTb?hnYSCI;?z3VH!zWoyf*G6~ zhs-WK1BHx7F|`m9a$gb77~rq7+-@|cpx)6G#b{RZLulneuJAqm{t`lFtXr)eA@-(2 z3i0l*LmCY*U?FTYPP?t^xkHasTJb8#ef3-r)$9Ym5n}DP4VF&tTyw<>AhsjuU{ZQe zBl9w;`~q2xsOH=ywPIEc0rPx3Q+EQ>Rk_2a&(6w8hFOb@XyVxoy3M+>UEFXRa-r3u zX((8Eg)*@iY*lD(g)7oKmIw>}j#DLcp8MQ%+#L7v8*-)Qa77;#t*$NEY)m9@ANB07 zfe{z?qv^SPh33szdCd=z4VxYWBO}Q!T)PkxE3x#Bv31(exmN7O@ln)ncg4JJp+sl8 zi}Ue;>fQtGOiUK(%}<=*(cZ>15~hDRb*-B{C6VDZQ^uf!Jenp45{2%%SS&lCZJ(RRSc4!3rs&2tl9BpvqwZ6v50~ z{$uHmE>K@h6rp8d*4Ij{iZ~hk@sB&!#_Pn) zl3(a>;}>`C&k&mQ6699ayOe6Pw*AB{2Z?nM&Tve5JuDqwWSA&!xptTo-E6v4^hFgh zhYB>~JPi3jE0DWMt)ZAX#6B10O3B_`Gol69nH4nCJKbzDMZNHK6uFuNKfh_foykl?*&IRMNma2$txv9jDZH;D5#RdafvZ<>g!o|T_!NH5q=eYo+VXh;zbY`IbKPUXZEL)gdreh>2?OU;+G2 zJ&n2G4rI(4Ndi!x`F!SlX!;|^Ro*YYp=HYCt@e&>rdOuhFQPEl6va{ut#LT_*4YMR z6{nBg6Wzb87+_n72YdEPc>Pp;OMw|A#^kY5qZ5OI&y5Kv)`%Mt#?M^YjCGkd7OVV8w}S zsq}eRo8#lsN*EtQbC560uOA2&>zu9WC_1s;oNf^859D}r%o@Ebza&N)eK&*WF>2bX z-q_E!24CHnz)14gb%0s%zVo&j%(KC6%lyZaNtGX2T{c4N&QuvT#{3jDi8h7I;oE~2 zCi0&@@?sIMB7C@76<$PP!#x_mT89kMMai(cl?!0;mS^HFTM>(|a3V*Tk(i>?sc=6w zit7y5K`rfLzuPjmiJ~oM5R5|Nt*j`kE*{MoG-B9g`I1=kPb^c1E--)yBJ1K^7fC=! zTwDnqUozUfa&!WZI4(ws%TS&f%IfA>&I|i;g-;cAAf~i-Sn^vOcG3$>q0I$A^(6_+ z1Ij1AO35r%(VFlU?l5;)AYi_m1a-D7xIOA&2i{KBfobKhg9nA4sww|AH5e+^qZt8U zWbp@a$IX|m5!nDH?_tTPT8(biqQF8e1sL%qux(>iX9JWcus!GIeFvie1lsQ zrvQKL*F=_@zBt%xaXgJ}UF(r5Iywo?Ox4n2^So5ld+uGRG%Iud-mt)=f8|O`?3H#q z@GY-X;3{-i;SOCvqQ3X0{ zZ;xGrO*8T#*CFY8P=dp>Ap$eOyX+O}PLkdwet7R0#YefTKWeu=>*iBQq!Hkq2S zE4YcU46wA#I8|HI$yfE72Tb7odrp#Yxwq zib3NL-W&Gi7O4_r&zZ{Jqs#VG(5onhG#}qyDFP>~qsEc#0YcHzj@Z~dKQNF>Q|NEs z`_q1!Kt{&>ARz(BLKGlt4g32}7E;1y3o+SZ52v%E*y4We79xsM5Tx^X3G#s`J?jkJQh%Y~@-H!eK zwLViO<{+YYPSp;F&?z}i`n))lD8l1~^^^r9iSvQx5GZ5edll^zGC$0vag(ST z*7Sz>N%HJM4FK}IMMA^5hgN2SIlBk~m9A33?sli~EuAraL|n;?Lw4lgaj}n>|kD zelgyr@Id0T3h&)?;#E0wB7Yj`BV}l8+6LB8D#XplGvDT0~fA5 z=SkPMC?JWXD8idR=gK5gjul`moF=zY#_wtG83}^Bt&@*k)uuRAMvTf%7SpP!&uDQ)ZdvpQLugd1#Sq~=$6C|i5uDx*-9aJqK*hD)5ocR7p{ zt>9CVk+8n$GW3lA+NNtQemqFo#tn4C<-b1+1a-ne3+%PvwkzuNB$=T8-gV=vDZ!-G zVUdSq$NGJ10(5-v#; z%SMztH}G5Acu{GG_GCXq1NI1qnl{qTnB=bYQ7P3?oOFr2i+dPdXVGSwjbP$i!LyiK z0SK@2rjso}yfUlWdHMLKscM;>*!x_z>j1i6^w^D|={NvlVxPJ|OdnF>w7E+^W(Ikg zKs`FgmOr$A$l@AMd?B}M5IOkUV7Ju8)5Q+j-$8vv`~@vde}*mwGTINyIbb|CydpMg zkfHWnnlm0R^siMb^Z7LcyK@nCL$TTB{V5`MAKzoQEPh61jh*dHdf>*B2tf1)uumD~ z;uR*^0Wv)R>~Zg!$gp}?qd|kXb~!e&KbUhA0ku^_V86Gv;Az+azT;Flb`Z_<@Q)s$ zZNX~9uFysE#X>oI`C={MS$5x!GN*%4uoH3TQhRsUF=h+su+&;%#`5$ZQrhQSr{@BY ztOa>H=!1eut{rj+RyNE#+KW{{OPXSP=<7nKv67Vgv>y6wMM1_+?Yz#6Wh!?bdj_sS z!_FZG&fnsO3U@wyho{G9(IBzBdduW8eY9fSy3x@c5KCEa7XvS!yv3Afwj}LRJ1HH! z5k00axM85jp*02qef5YY`7!gWWG;3uUuICuDsHf}Q;U?o@ zgJ^>`4pn7Vq3=_t3MeW4E!xVp$t6N$GlOuU|1wL%W+!qx?FaS)F$=K>#|U5N94pcV;~Tu%J2N3V&$$BP$5OD7kdD9k zhzP6^ke$fD6pk!-;rrv3v+_YeYS0D4Br*L${VbwkLCv0+itVZ` zUOo1O>N0!_9KS7xai3KY`l^20&qQV);g+H7PMdNbS@pf2RFG06(D;NW(IB`S=gY9m z)eEhT+flyEMW{n8iZ;r-5>mx1TGDu6Af1r#pyOSc2DH$AZkMr-`56h*M1Gc}om?HP zN3HTjn3KOyOTRvv1JS)K>wGQlO5k(xFskj}B{z0eUW{DCGjhlV_Io5~fSjEMujLRj z=*-cezR|%v-%AlmJwevifAymkrdKOx3keUol{v(T@~}BCmfdhUl{LZ|CWM#oTwL?P zW%wo37=D-1d=g){d)WgiB}tYJDf{e_|F<8eq6DG?1ga<&&R83i*1Y-4;RSEBXVcWW zJeSEIF8zIDGD29{j_PCxYMCEPvW>683{zOEJLiz9TrS%iJ8rfWcEAi>19cC`SUj^! z#cq=_^A-S3vHJUf8Xf z&Uuz}MkhGUzA!|$GeSUk%-}pgRc`W)@;SDu=V1nJJZ^c(ie>!-u`Gto_-Df9PEeDP zJ9vyW>|0?#=%l{*oLMc2QPW{E*<+J%%_^Na3b8!KRqLZGEjjN)oU|&hO>xxH$e~{) zHhjS4aEwi0*4$ttxqBk1u;EsHF*Vr`^|sOYb&G;`($;x6_1Hp3R{{T3&Ka_hF5qij zZrjtn3(0AjYO+UAecBD{JFcdcnv$BUlQwI2#A@ImT6pi*##u-#a`45Pv;6pB662Zz zP_r~GleYaz>#P=$>eZY04SHk^&*Mnbxr&5-HeFZ3p!7G`Z=SvBwKPT(U^P~knk$f| zFE-A@m7FlPGYlT2HyfL#BQ8Oxq?Gk!;@6Ue$C~pSX+?W=p|HvK2QaoQiyXRl zO6Hj%cFVts1m$YR@;gtgsb`_X@F74RxUWf5>xW05BBM9pZ!kgbt}C0oefr?MDJzNh zhi&5}lN7mcqV*|h9mkK%f>NtQ)&+v zw)H~SlDmVwe|1dDiyJUVWRz&>{$}8lV29s)(kEONC^mIUpDsjuyvJiR&EB9sjZ!y8 z`{Ocm))3zaJ+}}@c`-tc`1IbHbo*7gh~zp@el10l`mI(L4)v^3ioD zqx*R`gbMP?y&&@I;Sr5uh+lgCW+>1GiiUx7>9`6knLfLf3%*x;#UuIag?&KL_41l< zYIqLBrGV>#Mi4UVR~o%gPRQ%yww(C+av`AywagIAcuH@~3oJ}w#4-5D)}PzAZ28hs z!*hq!I7kd?IK8YQK^Ga0WjS6jb)g&{>PGT&(;Xya9IM9+yWXN3Q6dFOd~%8?O2_uHgXw=LGhS+til#~Mw%Q0jyeOAh!bqloL7K74-~phON` zELM%s{)2m{2({!Gb!s6yXvDepAy_<9mf>mu*+UdMMn`<(*}3Qqf9*BTYoAHmX{pa! zd+t>*AiC-(i9w!?ie7YLA|-chA{gQc9}~BK(G?c`VAkm*az)jTT2fn+laJWzawzkK9Y zBbnxS5A)i+vbfz;=Gs93Agk;1KM+R zLm_n7OHFK!(;~B94_c>a^^kO>V-X9ZfOM%mb{|rUQwrx`Ek{F5fyJFBnLeVh+^{Fb zr-FaZ!vaQHVLFL{FviJf#qz+t?CF50HeooFOwDZl(IdJ+3_*` zkNWUD63Assq zSE-uv=?XGvab3Vpa_K;2i_Wb#&X9xcDo$>U-p}|}eqMv; zQUw*~*MfA;rg3%(BW_oI02O4@@yoN7sf}Yw9Nih*MtI*K>l;~^LPOF^I!pFJ#NK4=yq&fw{seXsKZYRai32{mks6|tjWLxy^sZEwn$-M`kj?) zA(<% zBR2Q2k2c2)^p{3$SgeI>&UK+fV`3w^nU)3M=G#r{lHk*04WOn>0VAq>Lg0+f>3Xn2 z->H@RD0r`Q_BZ>~{}M&;J>P)0?|Fq1Xv_jhQA#me(J#2=%bW`3{ok{>2Nr!KqM%!` zjyh5@mB1T?zg}r1>wQS?;(xjcgni-}IoVRD-Cg%1 zch8dEjR4!91dVI3_XPT1B+hZqm+&-76V=9hH7OYG6um2nE}15yOA+KZg{`GH2H=gq zU347@L%ytzypwPmAw*`+Cv>={6%$c$GNZ-QN^7^kyDZutQgWy&Zff8h=xq=SyP`t( zUHJ-Wm3pct^0u|iJ&v|C2<*2ek!tXenlOS(u51m$0TJCQ7LcR9e=p^vg$NZwKa!5D zgXFY-2Pb6`nU^+wTy;b07=nWPsfv(c89;(Rpe2K)nwj`UjK}E(&mQLr&&ga=urzE7 z6NiVnHa)k2 z90**Wao;X(CkWpRDuSBJPpB>l+yZE@CpJc2f(}SZ8W&peLO*7+N9UD9_q)ve=3Z3> zUF-gEIrhBGUX~1uBpH0^f##5iYnycFRM#mWon7{huR;E;D)=BLLW`hVmAOV2+++0? zmV*N9$C??RHa@>d=IHcz-#xCHoYcuufN}l|f$3Ye*U*3=*s2I^?+gc{j6q7$n}5wW zz~!efo$@CY-fCR)>Cc#KC+moU2(5*-|08(EuuvkX6!0|YkVS~L6GJX)(Mh5<$BNNy)G^v4ehBI zt+tWvecz`MjjtkfTlypre=mnX5O)#~*&6^8jx7&zbTuqo)p^}euB_?PldPt+ia_XJ ziED=DWC)L$YYT6=tNT-ZPWXFk_Tx$$dhVj=2YZm{izBgW`Q}B#{Z~q#oX1ug9SrkP zKoZ6ts&M8*A_Dp|Q+Oh+ligBXLGZ|k5{CZGE6OE{AwH<27O7N#->PliZL>c&YQXkm2`Ba2h`=wEbR$jT2_P{j4T1$oa;%4Lplz`S7?b zp^X^Ha#<8l5k)qdFdn`^_lW>wWo^L1Pr4DyZWIjjOBHw>Ng@&Nrt|U)tc$N0q}tTo zKDJr`+o+8*<)$)fa(m!4;+z_nVK$5Ua3buCV9$q@X`if;I3}TJnMV6CB2#l_G+4jb z2;dmiDncnG${EdxA$fjnT@3T)V{`5a_^!PsO#(`Gf@9&J5+FK#mQyLz>y}99pe{%I z-CV!t@l!xz0EUw&3bQ`AqmMJLhu`kL99F^jN!6~riWmXJC_M862b!??K&$JgtdL#9 z+297++F#u{;|^)$(rJ{oOm1~6G#EOmk-w-~v)KOaW*bjSj*}Q<+bUKcI&1yveIYN< zs(=z_32=fR2VXUy77LF;-aZ>uYVvg+j;G!gQr-O(_>If1w4RjSWl=?KwAZ8FncEmT z2H3y3LVz@*zVp<-Q242nOE-Wc-jzV$4k-P(-0;pI$(nc-LopfR9bvzuXFc4^h|2f* zA;Vw;9hBke{~Ng}LA`>{W z8G$IGsQ8zm%z%sAgb~3ftha}*jkv+$Pka|dgbb|JFPndV;;^IE)QWFtOU5G?4qv*g zm&?9Nmz1uKekBgUHydd^BM}h?Gm;!GS^OAQ{1YpzEpW`55+jH(@Oa+E9_uFov)no&+k$e6$GMwPu8E;bVIeZtlCg*zowJ-ll&7$v?mi=xe?E-Gc461NlyOo7(5{ z%h}Ty1WgKCO)))*T)uo&y+bx5`h{N7vvtsJd77C1a|z0f~mw zz0h?-b+fvt$HekUth@oIZ^g~Xyya)^_LROn=VJbbu{K*78!9PieyjCr6aJ)|qz8#^ zr(%bc8qChiA<$5Jh6J%=!a3Rj9-$9zN%c$9gc9V**F+lD(1JeZqUdU$nX0S}{JQ-U zer`fPO9GY<{QdG(D26#KKYI3ENW&pjI)(jK{3AyH;$L!tql2v@?sE^R+w5$QEue=s zmX15OS0nY=U)%&OK7G{8{SjQEhYp&M=w7D&x5zY=N`1`B-dOorilpfQyd%#pyHn^i zsn1e``DN~2-DZx0!b4N9axDkqG4Y?k5Q|7`PrUp#k1@%Ez8cm=GM zDH^ZoRx$UByxvlx*HSqO!kYJkhM!BnVf8YkL65wQhHc5Hr|2~L)8U7Vy@7reG?c>> z_leEb;5ar|`%}xF6kiU$o#kUK8Q$NsDS_$Fq>GL8wO}0pugmDOi%e4{?o+%~nHds_y8^osTk^6To7%cs zGrPjR?%iOhLT!;k|B!fsr$!I4mK~Dayb@n@$TS}9Isv(CcA2g5;7!I?e`S@{f1|`G zsD$@lVvK#2DmbE_N$e9wgfqQ0 z^vLgsCpojc7FkTAZu3Pr^70b2?O|z|@=8loW0gEJS+0prd<^XTT z5}fAm-Jy#dlXqtzjSw*MO4Kt`D`80W8=LzrYpjgSB0=uK_sSv$kP>e2P4FYBYgm$} zu;=#q5EKmXjV(2N1HG{ll1xeew*cnkYvhHFtk2prd?E(0Tl^M>IXR#BMat8On0aaI z4(pEX`0DpLDU_o3uYp2WuR>)lt`PYf!LF|PQ)-Sw)3DiJ7zn80w7gvK4>H|R$nubd zJ!=Q~+#+w&z}Bk`r6)Hf(iK{FoVPG`O~`{~d^v5E>8oEy2W!`%{=|vP)Z|?9D{+*G zBV|>zyhNb8degiw-u=hf;qrxq5Dz9SQIDU-U(HNBW79I=@wp z*}Vz4pi7D!cm(~t8a!ERWMLreSI3^zj!`@YpL6BKza>jgoG@Rt9!lsQhkg5+PZo4dv{}u3LLfsRYgEb<~UkH7k zajJj?tuHD-h|HjNJApIfU=Y|LNaA-k27hq{i6p9g>}L0dq=2RtkqGo*=Fbq#79p)G zScFC+CJQ5X83~t+cM*KU?S_ zd->~R?_s;)Q$Tg_Cn%b&g-RFgehgpB`1uPTw4}pB+jS$s9SiwG0n<@WR>tcpJw7tp z7X}jcOutZ)?i)OBds6|45Zt7fd&sY{1$()NT!GL5%izWiiS+XOrvW?B=%c5R6ZtOf z%2rCY*3fsawK3oQ89$G{3G&sc9fuyQ(IBUgS`JzsCX8tea960O<+0OAY5Q9{+=h*A8mF$^m0sYqgHn2?T|7PWrjxp8Dl{+9C_l0LIJ6vB=*6=PT9pMEAofEPb+V-YiV-*wA*?f|JN zwIcN|);6z?3`{tF^~ZpGIzoCYU2(GVN|EGnIZdHf&sw~$-R-!P1ijCOQH50o*|o-R z=(48nWe#h5BC8NH+(^ih`5(0vi1yB2>K+|D5VE4Bm7~&LDvmVmM)H!_y=0>L%leea zXyB993!wuygQOLl>WX&}uY|fCwkAb&25{wA`pt}oe# z2}C@xOVbl>WjeC;C?(Y?JE`Y64Xjd2;ms}0sJkeUTO1|arhl#8gz21l_aYN1YQ zJBqF!!J?2DRVj?WdLfcPYNRp55&m3QSGEuvE;9c>&Z|H*;PF&Z7#Y;NAgUE&|QK3PuHt zm*qzk7zo4$QdytFu|`oOczb>0a+U6QB{{rL;@JS1c!!Ka^!J`5-! zju3FoyrWFvAfbJ`9|m^ISLJj2Lt!2bw8u79e@3K^(?19mm?t0@6FDAT1&_i_29)Ne( z04j5>YIM2U%n`K2fcgSSWaEUUvL%f{(=O?Kp}evw&N`yu8$PqOIo;AEV7;R}qEI_7E1^)f)d$nRga3)9)AklDU$n?kS4nb9UUfZAE-j4MaB5Jc9WwGenJF#=L}>(>s3iFWi>C9RF6cz<1*@66IUAnQe_flO2o-?~ z#?d^NS8mVBGAhT_rRW%ih3gO6z$2E+M$bLQK_>zNkmW7;%FQHEeAr6;DXKU}Mc;M!2DIq& zUK$0fh5fUnA*;Nu4Y3+A<~~Y*z+blmvnd+d=c`ktVl_d|77*7u5)JlP_+}ZMaI_wM&VVQ)+H!A$FEtzo+|O%9QAFanS6dZ~8myVpq5G`Vnn2H$N%9lW8or zyfMV0$nV+h5)GBWYx3REH|Nc;)a**sNeWe@QQAnHtyHe@IT&?X8@1XYWod#Wt{lEtT*m)@nbLf-@QNVN5v zhafx5`c9$BkW+<}f?>JE)T2S^*jOT9rpa8D*=Z|ZnUBB*Wg^Ra%7B%a6#%EmN^P9| zTb?8Z14@U^FT^YSj_Z{UjEB~zLApr<+DJk*f?8rHxjxK)jtqVx)Xwi46u4uE6rS{e zHeG%A6@OoC$y@GOrh_STWN91dRq`JX^vVoDX;Gao^Kh8EnulgS4Sffra)gqsOp@N~ zDu(LzkfZ?T@8sK3b)nGxxp%_4tk2O9y~OR(jpMW;+}eCmmKT!>l!`JKiHJnDtJ+`Q zrCHH^BykwqHys@@4z>#F`S}vJ1p1oWac>(5Z#o+XU=GtSo$a1(7O-GeR?e&BRYlC9 zCxt}}v}^}L;^!|w;kRiDOlb{%swWXrMV@zX88()rR|AFC`jkHjC}`{sS7LDJmX}6W z-=xRKV`<-v$fedqwxc0<6DLvi;17X=1jWwj_MSBL(NMQ4gu{z(tyQ?QEM z*{TFv@PM1%xb6bQn4ENSgc~L{{KIt@6=fSwr&fi@H#rk}@-Z34&;9WbV7Ml6btn7X z#L|DYTQc)Rs2cY$iQe!3*jv8wtn~{ z8BtOo*xXCXof$Ujx}>3W*C|RIUu?m!96;?s<#Tuu`u@&AcrEACZ^vt^^MuS9^LjIT zkkV@WD5xJC5wC{?wVOJIzU)NSw%#$q&>2bhp;k9My}=aSCxMB8L2kY}Tg}-3VY6kI zRx!S9MgPFY>&cy2wY5a}ohX3csLeG7i&Qd=0`zihroz1unZptylJXlV*1DD^Q74>3(6 zOHj<5!^y(CmLY&T!%{MmmO*^~DM|nCh0xzU?8^E4MQ9r6x3|%5D~wy5Kq%=nRiqaP ztqo3FG|QGH>$?mF$El6HJ6J7&J)IFWFni z2OF5E)R7W(c{+PBUbjWmbf9F4rtwnBoF-M@V%I1&?t3K}B@*mLxcLV9^YiZFoJ;dr zLO~5&WIFUOqKQ0o_(3{hxSbq`((ie0!>$k=(0~dgphUEq&sJwcA0_&s2wtvQtpMW- z@6>QhODOE_F8iAtB1JdJp2oOQ-LI9hTKw^ZXWh!b;q^5b#X?A5(Sn@fK($2snL=i0 z>IlP7H063>qliv(ojKuS-Gc&`ycZLok-CbiQzVy9wGZk0s=#6s$54v>>7=x3a0m@_ zlQ38(7a~^s@pMB$;I_t;{mJ8qaaLC0U9HL#rsS<(YG@t3gm+*{bg?cPvbAQ9h-VBU z>rlPj2elp^pRuG__j)j2yjE!GrcaXWCL2|81&UWfi~o$6+7uNlpBeHq(sydcP6=X3 zkfnbxXQ)mo808;EGY1C$%OsI1<}|5v2AaG{oYVQ@H^>bcYev$%n+IEZ)R3IV8TJJYv9X{@wy>etBic_ReV>R3^zPoItkpqUMZ>J*EU zS!zi6{qgr<#}He+Yl}PMU=Hu|5^~^4PJkeCe8q2~;i?{|k(~dPH5PK{*tXwHsov<; z=gdGo>#E|7-qp}Ka2wNkzt^nniW6Q8k-#q=1xnNlIJ)<|xCjK6JN-pUQfQa6$_DU- z5WfFUS?cE5n4kw>5&1(T!Og1uP0{l2(3>dYnyO9SzM(R^4vfr-ASN@d&2K(Q0Zhff zEQsn={!fWGI*}BUtP!Jz8ORADeYzKdIfE_}2fC!=S={U~h0+1+8w5{XIpVck-bSu} zV76Se>wsPl2a@C;rD%%jDqcS-AO#0UpN}<}Sqd`|NUoo*IQ;Z09>M?)hg-)W8Fpj{ zn*QA7uqBK(qeQN|wVPI4$ecu^@Zx;HALAnn5=v;3*a{&va+&tc0*TKR%q67j)UtPe!ajfpk{%$B>7a>!#<7f#H(gQLqx4r?5 zre=`U{M>=5n;LPMZMWv!U~Bt`Bs4w@(P-!P2KhxpyDT;Z@MP);Oq_$(EO}PbI&C9ALZp7kAcEdx3D!A_`UfMQi)1Ka}ML~oREzFdTdGV#BG!WEX z23&6b797G1=&vM%jIT-ne#iu%$s%1O+_uuOl8cvjCWwgFA zwx@Tc=ow&Jq!(gbT|-~Le)*n8eP0g;Z6Aplted`(@n`Ukwm)E^13D|EuJTYpA$Usk zsQ4=H*V4(@Sv-_3)D?-cr(0G(pBW&=;Qr9p{>7LKs{ z3rv<~dWw4QdXqGvCFl1KNd;KRyIuA11*I1OUtvF9RE>05Sn(EMfQ15^C6Ng^Xj-%# zyX8HJM@ShvQfF*r%WBgO%w>d{k0RLxfw-s1ni6}uMwcOwplL?$q*LuN(C^?_P`_DFLPhCc-}x>`a^mLng7Q z9&c!>@;?Chi%B6oP(b9WAR!LY+wzb3v-%hbJh(IuQG0}PPfR1AZ_J-& z$^S9s@`Ph|EDn6ZyFyE{u1`96M{;)d5v%uA@iqn1JKxqu>`WvPq^V9~?wWmo2_B*v zy2bcp8cdyci*Oh+P!6nYoF5+18GTIMN&HSRhv3~eefZY|XpaB#qK@0qHM%ZG1j^Xe zt&&9l+ID1azeJ&+!kN=t*ec~BFOuf;4Uk(8qyxf}tcJftI0n$9kt-5)w_3_RL7hVDv7ROWoQfb3nGvPbSJ)dJMvnEjXK_B@ubBNKb z3f~le?aMl4Gk!iq^!#rL^cVMHInF(84##E$z1#RNYxj+kEC$rsoJRxOQ~I6X!m4c5~FyMCV%kz7noj&NCCSzO@J2Lw?6UdaZ$NKz8Lm zLIZ=}cA|l&i|G)|Z5w#ls4cJ=U4eoKiuKOm@Vg%H5^{2>96dJ?U{8ZexeM3a;zMth zPbt6|XrB)F1?94P4nxtDV~t#VtR-Xwn=1u=<|p$_2+v1y4j-bPY;O);y-(FPVEpMZ zj4g+1&op3OK(vpRgvPq>m~HqnS(VvgcFL44^J^XKII?|oG^WJUSYam+-g1c#;rQCs zPhb=_jT$n)85m_hbZgyfD)#OUProxMYbO$(XQs2mI!v26#EiWSHy(vKG&uKY_Gyq? znW;nA)6D>$mu|gIhjoct@5Q{PFG6r7t`_HddG4`J9U5z{UuM5A zn~NMh1JU;3X6vmwf@vPK+An0!=0HVyQMZwTN)fu~%Ym@I^P7JD*wcr!H0|>%452KB zw`2N|CSphg%jL_^17LuN|6Lb3cWu_4V5>>t3-WtWGgCo7?wN=FCtp(rF(1*bEFbW% zQ7|yZMrC0->JoT+=Q#+G4BK>Sa=_%}6)L$j*$=`dpJ(Cw;cSq9Ns)EMZWCng7-91e zw4`x*I>C-cuy9%3kB+mGB4I}?9G59QpqyYKwNtSe_N!v5v9BfHQlvlpL7=XP+;o&% z84d6sya{(D-%#O1uxKH|j}PA1>G$u2*W!iB+tcw5GfQo~GPZ{kBIO@mYBAC|hX%=S z!vqBM-ZOz!#zk;UeswfdgomoxQVEoiYx(ETS+}^XoR{#LBbqMK7xUsFsB0>O=L3aq zW?3o6M&hRaSIC!Wi~?_8w@)hDfabop3x$-uQXV3ewb1JeC%hgKeo1?$p7>I0xt7Q- zUtS+R1|)KmQx>Kq*Vg&wE71?VA^|l|DLcE%me7VUPk)0-UGR!E>EKVk7mA=r;W#ei$LvN7cI zCJ}&;1#Oj8{{=^Ryt>o;S7}pXPdju|TbdCy6d-5cE;cHvh9Sn){7*3iqd8Eon`9!7j|J(4Zs0M+- zKSZo87d15MAd-2Obx2c2f*1~eBIAH>G7zu1;lR~6NY}Veg;Z#zaSC(;XqH;#-K!fF z&uR)(`rJ!_(Tih|^b<5Uf);ie6ck*yyvZCN|Jz=dEgow<7mXErXu@vZAs!ik9EdvW z>BJVp;CLf8;`9*0<9VmDG3P_dH~slW+sy&-ias`<>sC2_o#$7!tVi|(bFZQ6B%h{@ zyO`?*+kj66P3UZLM)p2>d)s*2v(|ANvPhxUuEQG4iq+c7#A?dJZNfv;wGmxUozueP zA+Ocw=1xCes>3GI5nKvbcvcw3P(RJRXtx*^^d+2pA5Ig1OiU-@8eGL;=E9Xc5nmn4FlP5Z1By7V#Gbp2F)|o6l{B6;sYkLrs&dp$ zC%tbH&{hm8R8!PG>Qs#2fBIje{))PEEdKiM2ej`Bp;N#5!4eIJu`)=NtXy9Qe*X~h zGT_g=opV?N4-O@i;M=zLv3B zPqB5*L?#Rrj+TXxyeDrB@}V<`Ar8Pd5x&@YwDc zDv-ksoON`v8?_XGSUA(x)2#u0yKYTz&3C?+2>)D3N^`-(0a<0z{zuC01fMXoi}Fqa zp!JltRl0@hJARP&E4AOS??_oxpf6=})KB~%j3e7r3?PQYyF0olE~+&h8cI}QE0{)b zClq=l)u0w_@;2OI#A45Ua|i{t+0W)eI_Vv;#NcN7Rk$7Orn9mPU;gTZavMZr$&W8a zExQfR@)Zrei?KGMNaucLO-N=GR0rdfWDa~EvCD2Qa#=;*^8nfnxcWSfz-fzQHJvww zu{7Hj1g_>f0=hp%cBMKNX-PW#m^soWaIUNM%lg2xh_10-wd{;`8EO*`Q;uyooJ#*hU!+n zT<_Um9}r~7?vl9k)AHBnfEtJ{ojUJ&YCo9YHLttk*Q2>8|Cp4N=@Dm9b2CXS6gAhg zIGs4w-ucZg4Y;}6;j6t5~X*PzOuzv$^P_*K(2^}1I{>cmE+Tr}dg4mubXPiFe9!;vPL3^GvHYOcE)K#1=GO_}65RI{bxXdkF;N^SZ_q zfM3z9o(Q+j+s-gvYuOKoNU9n82mYF37UJKnKn8>swvO9+jb&?zYbt>rk&DRT?diAQ zKWv+^@z_>KMMODo49n9?uZ(-Ct9trd<_mslH-q9Ft4myKsnW1+Ie_@_ikfFhNxEd{ zhIkSqkx0x!!sihwXuNjsS(;#dvJ0V`o?SL!IgT-z@3;R+RNi;oDixF88I`-S8XZdM zsl~+x2$g;|nF3vs+n1@ z@k};sTf}xdF-z*+2G&5jDHQ%iCsW4x#^fQUCK#y)mbO?*4ppi_vDv*9ZoeM8m+FxB z6+8!R87X2)FFZgad8-9pDg^%pD>K3027m+{#|I$I^2tyugz0Vnr|DF4+!*M7kPRw3 zSPnUh;X`6urk6>y$5Xt>)}Q5Xu-N3N4Vupjp+b{`cMt!T$Mg%w@~)^}Fu zkpDwm@9SD?g#s?MzvKXG@VtQFKLQ!w%+^U_zfgv$9WxZ}S%@wb;y^2U+9E6vB^hvn zteZWja(lqg6UVGecVfz?x~wJ&t<;%c2Uv!=f#qHnnCmzKz2uy6+~YxBJMUvJ@K%TspJwHu)SiH!-XPiZw(HWsoB zR3!j64IJ4P5mEdztg<2^W_15>_$dzBA>tSCr2UrKm1P^N%}N$fwsLt7(Yl&^bSW!^dL*~Epa_-y-6fk|qU@UyT1*03U4r>@Z_ z*ogSS%$sWun?^z1iDJxxuo$T02<|vMQ|H4xHz5v)-g{5sH;pMzl0-Gz`PHowUiBoR z(i&eAP9dO6c=Ep^0fM_Aopb09aD~4Tl~ng&Sl`9B|X!H$pu+7xc+KJpqF8KMcEE{b!;x_+gF5s2mYR zE%(b**^aE_)>3&KQ1qAAdUInj&p-hqut_^Q8A!_~xc7BV6u-U-#_|-ZEp1d&c6rO3 z>w|4IyKT0=TSYggqvqyqJW1;k(Fhj7rRdrSUap2KKkzJ}$3`Usr3>`&*Vm0m%fxCn z+pWT-QdTQ9>GYXD@%FwbRc2gAWi$}!m5^+Dj&s(1A)lT#YQrlm} zLLYWd6lp84EwwB$4({HJ6{|h#K^;Q#fS|<&cu3G1)#pvPJVvU#u#CP$9MRLV8j9NN zE_Q#nOu^Q6P6@cg!+YsWdyioL-_SwdfhP#bkG%FMqJ>ut)_HpnGXcuv_?bj`7lm_d z0xEg>4UMr%EJy(KN8gQjtaPO#vL8Bm{a{pZGX`9i?%Mbh;kw3cT-# zBPxJ%OQD#@7WHB4yN@M!Z*N-1u2mK0W$Zi@Y*KA7L;Z#UO%SSY+zL*RxO+a;`?Q{1 z!2)j1reQc`vRl)7&z+Tc-Y!cNI@9)5b~g5Z!?W9W^_~)G@S>kK^sv|dyYydt7sZsB z-wNeXZ5R&o_DGEbC3Eda�uGFA~U4^cvubvwLQ;#T>N$!{mf{$|dAgDnOEDEBb0a zhjS)_8$CoVlbn&3+I?0o`P2A2Rc)-d-0>o*m#pVEjgO>Fa>TUD#8IBvU$XR?aJ{{- z|2G)0Oka>YN3*Y@0LQcelxiC&!N^UNl`-^IbsyyJ*HCfCnZL0!Z@c&T1e`d59vsfi z{G73F8MP`WEyAi_l#jDDK+J_5Y&+{C|0>n$3z*}YOWDQYhW71!iwY0+i1L zbXHB4V^eszcg6b8E`_Wa=O}T2X*>75^W$URm2Lrlk~r+6aNHgS-3$x-5bdEYbgpQa z$-jq{rt;FGvG7)wzpPF33sEOG!HAeWe(D;0&_U!+w_W*-?0)_e^M8iu?4Y>Yko|-4 z>ZTEhhVOwZl;BD#ySbmlm7Up#K;!In65_-db%qUGL*_tRp#nE*_hjo-&8m0)6?Obs z6Q|DG^s^}O2GxmKRF)ijPf}U)Zs-c~_#{#XSIgV@!2=0Rb3=(9jmTz)t+Lgfftv8! z>tWytnZ}~8UP;f*^G3+w$4O>z@+GkMJ??qW!U`}>-F{oca5PBZyH0rAt^801zekwU zAGT0EW!QMPr|UYev#t#su=XL?Jqy;aU*xuDQQ2uO)pSFben<%NP@0&{Eeid_)9&I+ z(I}tvQ&RkXbww#AZ9{_S06qT+pbVfoufBkjhNE0Q!)Hu6+}Y4c$3~u`B3+(2eyxl^ z)V})m@ArNgfuQG8Gn}ghMfzM*BN9kg-!%)uYW43i(*2#Fh_#~iPInYluOR`%QUIH| zEco?Chlr)(nXjY@a9LiGBM-)NKV~oTH?9yr=-BE%nk)ur&B27la_E6RvH6)_SOFI@ zaE=R%Zt*(h!`DSm9 zeU^DY!g>DZP{8R_jz?pJdwQm4hLe z2C~$Gi0q`Q<(k}jGnw$*J%daA$_uGLWN0YAMIRQU7-utR89}9^@BpN3E|i6lh~Vtg zuNBdE`6lbcHPyl1-B=I#h(!Io$$nOyTdJ`O?SN^-@AlHH7Zk2U^auf@04*zfWcW<> zwSXw1jcf{C(sh&4at&mo=R{~wkL1=r?Kt<@m2#z{AUifkQZ1iD#l0f8A09;NpCHE> zmC%7Vh@`Se3q|o5BMl+qI({dz!kJu9M}pJbQp6Kxk0z_V1D9`P)&WEY`-)7X!YB#F zCU(ZQI%{cCkb-LjfH{CnhxYi5!Wvdb*HW?W<+yZ_LFBu)RHYRDx~o%lQPhm0P;j({ z{5|P)rZ$S~se27lacIvA28tgxV|x zBzq+;M&;_#l44BbU-b4Ave9P|*(5mjlJ22&bd{ zsL7`CD6ZV*pYT1xtJLw)&1Iz0tMV5%Y-ka9kn9F4@KCm}6uf!*O7m@hkQ)r7`L7GN zlB4wlV8vSCGN$cr7H$KfjgAF*2%307E)jWG+pG=1DBlq_^>{y=4XZN*I}~AMM!nJ_ zx7{aJDN}E_MThEpp>R^k>vEqy9-b-`s*yPZrrf_3kkJxuM6r*X`JZdlj{r_Y$C+HN zO;f>V032&5{ualKl7IkBCy>>Q(q>3Rs5vE4vi@3GH+2rQRQW^F)Xt|} zB|^9f*e4rT{@$cbfq@)Rls&ys`)Q~tYfU%iMkQXg zUve+Ed-bEb%_|%`1Io*OPK3P4gXAJIcx@>QGQ6TGu@`y-g&jutl}hh$Se~={&d4g? zo=16IG0oS-?3fT#LQnGw){6cQTGZoA^vpv)k|4Q5b?be3Cx9W-I}AthQYL?5DS&z$ zs#L#Jyiv|g`(%rv=Q_LY9F61lee()JX$RKH8{y4t#8)Q1-UVs-CN_~BN6KP_G%eVB z34y;o1+$--FvZE`8%ok4tL(zg~Gc@Jxev%`>*WJmS+{RyajB%Flvh=E(fIn|= z6HS_z!7ST2<*`Xo(NP#ev17LaGJ+fluf>a?hu@}iB0i|?D1Ph*lZvKNH&FlxH+0&R zTNEvHZPQyy?AO2#Sp0FnxZpR^G6$P9#f)`29kcrc9>b{s9k}!0gXCF4LMF+&>PH5T z(yQoqpLx7CyW-R_0Tsv+`KdQiJ$#F3^go6DjO0i3(G|++_eLSroadK^!P80c|8-B{ zq_3o4S%H|r;O`^y!B=5V-<_^_cT>{fOP=;9QyPX^#=N6sxLq;M2wDTQ-*Se69EOT< zJvxqvwonP*s9UkNnfdkq)`bo1JxVmO=|3X^{oVG4N1@(ZTTJa^J9prB%fs^Jc$g)C zz%Ji;v*x0WLdrErGhuT?T8PG_)fCP9rYAG(RntcwT&6_IN}xPp%zzcQXPT_o&m%;( zP=k$0<5=3rUuDVpdhW&vzNKO9Xdy?rd6YnJviT;*($nk>@uY* z;h5^wax?y@jkw%3_`$a?CYW1D;iMzK302}DC#1$no;#fl8SB7Lv0pAj2k+Qq^l#|S zOA+P$51;=_QgHV4R=X{z^~ zE+Z+{qp9MtVmMst_$L>#`==xG{ia0whNtE|MjWLhE@nE3?Nom@qDyYj&#q{2KGQhs zQW)K;Nl9mvtq|0}4ql3(-}i)3=V{N#c=Ld0RV;iyk#W#{?jZ12J|*gA zq2B{0&A*qF$(0&S=vNksgL)z5yT4w_uyi!Zd&_mOH?^?$;ldCxaoJs$e0%X|=^E<7 zXmDR*iV|72wW{b?zC%B+2<=9(n_EnWjj{gmE6sxIlVv%y%83P}DJB#ZaBhuUeTU8p zwuu!2VB#KbIs3*lZ}Y#r6|LEOsUFRGa55lU7W1<7iBW@9SySFjkvDY1nA+XPxSY}Y zuP{3$G4xx4--5cR3iG!tI)`@bruJjGyI;fMSMhDwg{aK(8#E6(*HOsicB4fNmAbPc zO|@Xo4(8bW5J~uew8XGnvC|;{ke@%JJ=n#a5twA8&I>!N@H8YMt7(mp7S57k{(6p6 zd_~A;P;Ul95<}`R^jM<4DwR-l+sN@qXn#+v$UHo|wTPr?oQvx@p#ec&3wK z2RVAiR5OeXzqfm3t{73?DPq37w^0b3As|FXfIL z^xD!(o^Br%Rvf2^1k2%EFh6#y)EnGu;53X8W~Ez*6vVP8@POHRv~uvT-TQhZnaNEv zWwmSl*JTuWL~T(7xE%LNcpE+Jr<^T5$LwQa>O!(XaaL`* z&#`*lay?op;zVy!+&(Z+E ziJi$4e<%8gspjJ5-W~Kcd|K*9LXMvseGz6N9ihVbk1inZ>=Ba&<_+x z=(XQ$^w?bv5}U&e5q+ET%-GSdF~eq$oh|x@E@U+GJS6BPp`PXll!rVYS%UjRE(o?a zc4(amhuL?gwXw&qh&EAIsMP%l<#7Kp=6da?5gAO9VO_$CC8?yJNT>@@tI(BGHj*~I zhm=x4g^`>bs*b4Gmg$M?+E58`GR71U@+mBKbaT;%%4!Z0htW4C~zw3p6G zDHY{t2=e*dAI^1ZMnixMG6a=at@6E9mT!>Zm$7NR zw$#rmk{~ZQ**1r8ia_^W&ddn>R6zidD=HCH_o)@HBBcn$i?zX!I}pIq(2~;alPPXB zN$5hS>^+*Qs!N5R(8p6Z&N4s~G7qh}8zRmYOoq3NQ^@1-=?Q=OAW{H5Qa$x#vK&j^ zt#dDD5F>%`GDomc9OY+YNSiHvLexy13v^LezD;o-=m>%qb{er{aPnn>MTNQ%d$=;s zWawduDKm8e;ITNzCF+;Vr3Qf#UF!IYJv8r*-3OqNNoSvsk%QNG1^NXA0l(JwJDnVh zt)5xfXa2g}WeS4MU0(9BKxAD(5GB7#%d9Ith}|TlXak)}P{m62IB)d^hNCojsj5qJ z1>A3dl2Nm?){xy76bOPWw&-@z5xLIt_&VA$3Um_ymET9k)CCI)SM{iea#u*yNV(fE z!yIg4JB`gfT~+=Nsw=Yyf6@p+UFJh(<)$LXCIfB19Dlr z_mYOh{Q2RnY4N)q5nASbM@T3B3v#ck z7_S6(mi=t6ZBAfB+SVG;)qcFF8%Ze#))E5VOHnun*f_tvv=74iKAs-6rV7C!>AuKv$csW z>o)gXyk;+Zu!PVl(A)X-&7({(O*lZ^fy}2&)H)(8H7APu%*MjWlh93skB~OlZzBr< zB!5CxwE-B!Di=jGraO}6c}f+^29YV6&j}f5i_61&nlq~NF{iZ-2~r0u%=&$E(ur2T z_61I~SF`ozB#(Fu5>j3h&i_*47_L}5+A5>15imA`RJ)L8Z=5x|r=ocp#qo_aLL9QL z3S3{NaJnmb)-7ooHNuSSHz$wrSf!v{A%OYr`~W zVdFawpc}J9YV;Ey-~)`0OVId4Ke~E&*a!<3&S_OB`95}k8OZYF3BC>_w%N!2`?lpm ze|{?JPJkOmbtvBvK0!#GDjN8|z1PCxZ=NUbFZg>JNS*x%#YEKtkrYJC_3tjjF}u*k zAa=M^KLckQ1_D0Ra!Vq#m(=Lj6OxL&myLnx6^Ppf2Xqm^Ub6rKE3=R*5+d&inrKFh zrHB}DmRTJ?!}Bw%3HU^I7O-Vbw8*7dn*}>VC9;zC9KS7f#?$w=|9>R~4f`cGVywvz zLh>U~-oI4+#(d`DVZF{zfba-}Q!?v6ex|QydW`cNvUa+(`i~pN@Ucb1#!@-wTr5&e z$o*0dyECia%FAhbqJFbQ5_ax_MVUqrQkhxe3F#^0r#X1Q3kz&1+|&qS5rkO?{f;C(yrt^=l0;V>nTOEat{9f0qxcYgU z|9XUcH&2eHb_SHW7AF_$0SamJeJE>(rf99QxC^C52yL|Eg$$E^^dHokDFjM9Fds}G zE_#=xiMkIV-37Y~D+Y7x&8akgPkxsnB}t93OG**?C*zgeh=0M(Cq|?f0^NQUm_btf z!>4;xcqy}*h+motVq1!ifn!PDns2JL(ZR^%fo_Ufg{Fv;R3=g6Rh0p+V#Z7yN?lhA zK+Es)PLO(0|48m#0Qt#?Vt9hvd{G!TpIjEpHTa()D2vI+O(grw^M3((0darsPZu~L z!l)O?3NQB(8r%)e(1bC&&Tq_nxJ$ zWIK8Q^Fccno9~@6uz!VbaJY9S5U_%nXez>Oc=dh+ix$u!ZFtYOKJ47vb#2Thz87s0 zEImV6kp-Dc#_Im2;x_{p(2}k1-$Ct}5$l1B4}S#>Hp#8#JP7W&mGlYv2=@|}Oo@-u zTczDd>P_q})xE}yCPT*NwQ&1v&kPlcy+(60dsT;)CpPt`6Q04m86^A;ruU99ri29K z`romwQg$MzY`?QY8EwdUo8jvX{g!y^Xy^ue%QgAQ9c|zj6{`+x@M&B4GPm}HERbw# zw0%{xFU#C45A!+o7Lka2tPg^B(+RRtkIxa4l{qrF|N0#ybO-~-s=QP2Y3*)#cU%^l zTxy-$^H3KS<_pQj%9n^_Tj<2&5{Rv|41T!Ru*6ONN>)i__J97H+GmP|8!=4Qg(Z&X zAKnAa#}BTCazF5_m06kohUKaO3*BjjmbTn6nySZd?`r=NCC&wxf+?SHZ8&a(l+VX9 zaHJ3(V!?5is6fK2#n1W=Ibl(opJv9E7_qM;^Lzdn3Fj+0NdGW|ekSK^Ru3nODvcs+ zkw{(iLK?XYZhmR49ylsYViNxhvkb!R0^HQvy;qQL^^+zwq4ya)VU))AA3hg(dGDr% zC@3AKK}W)z+yTDY?EKUtub7ThQT?ygV6%%1O%+#wTx@&Ma}F}J&pF_k0I5qqui)HB z8&-z@=t=1QR@|!FVzknX^lhw4fn=J5-Y24)xQ2?fI#IP2@xc2ZV3c=rOinxIW<+y| z>k}WzpTnHw%o{J7MzzEY2W|NkJZi{n6oA7!bN9!tm>!F)SjA|kW;0z)HL_`XS#ERZPG7l_$yE}-cRnx zGz`l({O|qb3an=?`tMfA3*!(c-VI$$;2%oxcZ}UMN!SMhjfsz za%^p-jZJm-AE`!8VDIDN7&hZ#=3XAxLk>@9hDVnr#w8cmglKoLcxp8k5*%I(I!Six zk*)m_wpLn^yT0v|ln`7s7t^1vk+N=ie@MhtIxTs4O`mpmw%8{YKZ)LxjVGgQhdmNS zM)>!j27=jz4gVoatB)xJhW&pFCXM&Vz*Gx^CA_Uf1tB2GNSucq+5m;}uJ^OSO&ybI z{K%Qv6F0h`y_G|NZ(^6^ z#KcFuzy3;~C{SyPRu`rHza=|?1~K;XP(ih} z;swh(2gSspPEb=y>=7Cw2D(a^W>MZuPe^wSChoi+a^CGN<*&%UO|RGii8v`;ZO;~= zoUOV&2LOJHj_?V?fw^YV6Orniux=pIrUPZv+{8F;O-%R|wUMP8(Zb39_@9_!2hyxx zW^x37MW)}P*a5C5_{+r?&z^cx&su{@Dg{<`S^shr_8S#~bQY_073)i9)!|k6cu$9m zJ0i4^eswP-Dthjn1}eib6m#3%_`Q=X9Gs;u>x`}amt^86WV81$%U>3bl3#Gw5}5V8;npDQhaKCuNuEut@uYYHN~Mm zV=KaGjA*bQHw1$;+D+^8ri2ue*%u_nKJISxa8V{yQA_ByL<_}ycxM4g|Inc4X?18H0~uTABe5XsBo+z=DM%V|96q44oU0QZFZRL!TvLF)HKHbRX6 z;&Nf6S}R2)YaMy*;L+l0ot1FR9hBZI@t0!?eJoddapVhS{CjEtb!|i)3|7tIoL!*#qJd!D5Bhtnuf+koJu}OgfM5WJby*(ftV1wtb z`0`*~kplmnN&IIyCzj1Zjddy8Md5JEWuNj1z??ZJBlIumwp|Jyh#72#jHY&IJAgY3 z2c~)4#=dzveTJ0{!^1+lp6V(2 zGG>#a6h-uGmUhJAuf|guQxq3}F4uF`sl!8}L;kon?9lGnwTdZ~__&>-H`&b$Fio@lguv#~LD3?9l(>$0!I8q1=taHAWC7m&ZC6)EJNI1Y) z05V>z(1?A`^3)cNK{4++k=mqHSfL1NGJN+IhP zV`R*io8u*X8~R)l5S8FSdZpV@`Al&oQU@2mk%2JIYFXl$ec&i%b~igcIys}4Tnivh zY-Jr9+GVq|MvgKk_pdPdUR(Z_xV0^Lms4_!uQmZv2N&>80Ic#6)@ca${rdod*AOVJ zP2{al52?sNdwP%%ko-sA%0oRU5U5H+z^BbAIyw-U4Np{N?8%nII47>J2xN8a!uW~J z|0X=OI}nSUZE57-DoFI%-%D zmybmYJx5s5TwPJ6o47bRPBtP;QfNPL2B?&>EVQfOdSV%(u*UN@3R;d2!)TX$?u9ta z3aH%_J|$J2Lz^e+UirwAp9?JowAObl+rt3jQsUNHKxF?buu|AH6f*A4| zr}v6;>pNb#Dv>SVi6YnF5G6ijZME}tU6bwQk|qe{h{t&L=;1rojz`JvI3g1SdUzUs z?c-Grg{io+{9P~Hq1^sX2{7#p$aCsPSZ--ZA}PDP)9RA~3e{uXAq&I+pn;=WOIw#L zJ`*L&syF;=`~PA>t#Ct(gvbI*52yKnIoz!$hS;WxDi=1G**u-zh=(nE97YUNo4l`x z;?5x6ol9G;LkUrv&dipY@fS9l0I!X$!IdrTBEXv|cSLcf1rP9L6qpp!vNU2rzQ11- zTaz27(7D0J^FaJq%Ya7o)J0+Apo2LYMWDZZ#?kofM_93jTpVee79CNrdTtwW8UzoZuG7b7 z;90_>B9G7u1ca?H?K7h+>p}ip>fMhV8K-67L>>^PGeUyVV4{Q`Pi?SD^=42jEZP0o zsnxJQ36b>JebF$}PgMnPY?%Fl4eSL|!&iqQw_EP|e5!OKU~-V7;f_Z^aX_tf>L|3G z?wjWod4Vi>rvDwHOCxNsN!&H6hwoC}7u@=i7@TRO{!NPZ$z|F* z$Ps0Gu=}h6JQe`o8Dz_3}s#>={h?sdU%<-lwWP*_9dt zH}$2YUkg~+q-Qm{Rc_zUV=i=W;0=syEDCmGA0&Kbs%d%GA9j-i;QeOj zRn_chlS>T3+&fOE+#Ez#`yR5O)Z7)+`awK2s>L5x-e$=@Z>>7JeBo)mfW4XI`sMqS zH-Rw($E<#5329IK%;?Un!_tzx#}ysy6qXfwI$o*UXt88A|I^XbC?7&&)vJj}H&v%; zN#mxE8-o>7$7MxNm~r!1SFh)3-gy(eOdXmZrKhrTA!F!7tfjBSoUpGL17G90>7|@o zMT?@mTFnyo6WecI@yTuW#F{@rD&6N$T)EcrEl#MGW~6_vr02n*r{y04j{4BEY~}Y> z8WrLN>QJwSCsOR!mG`<~&Xb1sa#)5H43$ZVIHlt^RLhSsyeowD9KTJgG8-($HLQPo z?(DgaTP?#$u~eL=*JW+xy}CGxAGTdn)*Hd_6{~tYiJL*(Jbg3sLjf%39NNJ6uFRyp zFzq%2K4^NW-l#?J=A;#>Igy#(Q?OpS-%usMPbpLnx5N=^U1uTz&k&CLY`+$2Ztyw1 zM~tUt=HVJ^wY{|17ux-AYsH_~c0Q4y4f;>!i%nR`j6q^y>ld`A$sUV~CHu%$2l-ek zSIxT@KArHU4UHUbikFZUI?JRf97vqLmJ8ZNS>?c#Hy20gWd(~x(2YjFN!yT zef(lw*iOHsj>$Z7_2}!43H$f2`mf)&+>U=X)@aCBm|HWG38}WYuB+sYueT%j`^BW|4kzfD>DO8$i<}mY#JxS!kE zN5~>Nuh(YS?%x(RVDs^)P;{WvI^uV#>XU*c`>e*v5WZ3Fh9Rr9(eiAZuG}zvz(Vbg zN~>kz@GBo(v+J z=~OwZeKbokV2CfSNS1QGjWWl^5@YAB2^ZGvVXlz4GCDGTw7JDWM_;^pZl}DURLs(a z>CK}+!H?^fPiRiJYJRLxjvj) z2y5hhP%ETbYT%G!(apsAoU#lNQ=(x}!-v=GXE6Nk2I=+u=>`r%aV{uA+TnWWDfaC9 z7tfUvGSlD1>ul&~t$G|1 z!Qk0GD-uyrH(4+hH6Tc-E2o@N6#5wD zK0rC0LTP`q}J6vYfb{w`BW2fh5hU$R5nA_NQ^(H>}wBicZyOx{hU9P{juV=HRNIP3UK6yP1b6< z05$mw!2F{G*xjK>P?5)gyTB0!28P27M-Cr8!p8U)BinJ7BS%<{bF#A^XJ_YRJM!cB zb^BTP?^h}&Mn)!PCRS!<)?>`f%*PHc%*TF;u>B_r$n^jl1MnPpPD3RGP_t3duu+jG zD8BrQ+)SlHL3xPk$MMrdO1w}!aEOkc;qYIKl#S^BYa_|PRo7`xD|ASt?IPtr?Ng-;#7)?h0w;~w0rMt?fm=;OT-wcfAN zr))pE2S=+J9fxCN)=twM0H7CvH1<(IWN_GNn8^Y+v(s7%qO}z5d!hlhvqCDy8;%;kWD;apEI%oZu2Mn;k_9ATW⊀z+Y|& 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 Vn(2ab(Zz!IVKHiWDe7#kzX9k;KDht@ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_user_3.webp b/app/src/main/res/drawable/img_user_3.webp new file mode 100644 index 0000000000000000000000000000000000000000..a5f1877ac432daa69650abab17cde7a0363865b5 GIT binary patch literal 17044 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 Dj!T0l literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/img_user_4.webp b/app/src/main/res/drawable/img_user_4.webp new file mode 100644 index 0000000000000000000000000000000000000000..d9dc169a38f763e8cc25531e56ebdc5870f876ad GIT binary patch literal 20162 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 z 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 Kc<0}d4ftQ+k3@t3 literal 0 HcmV?d00001 From ed3c78f1982dff3630192a843a874809f51ec9cb Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Wed, 14 Jun 2023 22:45:35 +0700 Subject: [PATCH 62/73] combining forum on home --- .../remote/apiService/TechwasPredictionApi.kt | 2 +- .../ui/screen/home/HomeScreen.kt | 61 +++++++++++++++++-- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt index 550d242..4d139fc 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasPredictionApi.kt @@ -16,7 +16,7 @@ interface TechwasPredictionApi { ) : DetectionsResultResponse companion object { - const val BASE_URL = "http://35.202.94.119/" + const val BASE_URL = "http://35.222.88.99/" // const val BASE_URL = "https://e-waste-model-deployment-1gb-fwd5gpydiq-uc.a.run.app/" } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index a8e2e74..d99d6e4 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -197,7 +197,7 @@ fun HomeContent( ) ) .background(Color.White) - .padding(bottom = 90.dp) + .padding(bottom = 80.dp) ) { Spacer(modifier = Modifier.height(18.dp)) @@ -399,11 +399,64 @@ fun HomeContent( LazyColumn( modifier = Modifier - .fillMaxSize(), + .fillMaxSize() + .padding(horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(10.dp), + contentPadding = PaddingValues( bottom = 16.dp) ) { - items(count = 10) { - ForumBox(modifier = Modifier.fillMaxWidth()) + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Jual Laptop Mati Total", + desc = "\"Saya mempunyai laptop yang baru saja mati, pada saat tombol power tekan tidak ada respon apapun, kemungkinan masalah berada di battery. Selain itu kondisi masih bagus dan tidak ada kerusakan luar\\nBagi yang berminat dapat mencoba menghubungi saya +6281396774583\"", + place = "Yogyakarta", + photoUrl = R.drawable.img_forum_laptop_bekas + ) + } + + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Cara Hidupkan Hape Xiomi Lama", + desc = "Tiga belas hari yang lalu jatuh dari motor dan hp saya ikut jatuh dan terbentur", + place = "Merauke" + ) + } + + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Bagaiamana Cara Menyambung Kabel", + desc = "Saya akan memberikan langkah-langkah mudah untuk menyambung kabel elektronik", + place = "Solo" + ) + } + + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Dijual Kulkas Potable", + desc = "Dijual kulkas Samsung berumur dua tahun tetapi masih layak pakai, fungsi masih lengkap", + place = "Jakarta" + ) + } + + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Membuka Service Laptop di Daerah Pogung", + desc = "Membuka jasa service laptop dengan jaminan uang kembali apabila tidak berhasil", + place = "Yogyakarta" + ) + } + + item { + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = "Membuat Kursus Membenarkan Laptop", + desc = "Membuka kursus untuk mengajarkan cara membenarkan laptop lama", + place = "Bali" + ) } } } From 21233c184989e340442ea98dad418c9f252fcb04 Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Wed, 14 Jun 2023 23:19:16 +0700 Subject: [PATCH 63/73] fixing signIn --- .../ui/screen/signIn/SignInScreen.kt | 21 ++++++++++++------- .../ui/screen/signIn/SignInScreenViewModel.kt | 3 ++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt index b7d98ea..5152d96 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt @@ -47,6 +47,7 @@ fun SignInScreen( ) { val userToSignInState by viewModel.userToSignInState.collectAsState() val userToSignInInfo by viewModel.userToSignInInfo.collectAsState() + val savedUsername by viewModel.savedUsername.collectAsState() // val userSessionState by viewModel.userSessionState.collectAsState() SignInContent( @@ -55,8 +56,9 @@ fun SignInScreen( userToSignInState = userToSignInState, signInUser = { viewModel.signInUser() }, saveUserSession = { viewModel.saveUserSession() }, - navigateToMain = { navController.navigate(Screen.Main.route) } -// userSessionState = userSessionState + navigateToMain = { navController.navigate(Screen.Main.route) }, + savedUsername = savedUsername +// userSessionState = userSessionState, ) } @@ -67,7 +69,8 @@ fun SignInContent( userToSignInState: UiState?, signInUser: () -> Unit, saveUserSession: () -> Unit, - navigateToMain: () -> Unit + navigateToMain: () -> Unit, + savedUsername: String? // userSessionState: UserSession? ) { @@ -177,11 +180,12 @@ fun SignInContent( is UiState.Success -> { saveUserSession() - val username = userToSignInState.data?.loginResult?.userId?.username - Toast.makeText(context, "Welcome $username", Toast.LENGTH_SHORT).show() + if (savedUsername != null && savedUsername != "") { + Toast.makeText(context, "Welcome $savedUsername", Toast.LENGTH_SHORT).show() - LaunchedEffect(Unit) { - navigateToMain() + LaunchedEffect(Unit) { + navigateToMain() + } } } } @@ -237,7 +241,8 @@ fun SingInContentPreview() { updateUserLoginInfo = {}, signInUser = {}, saveUserSession = {}, - navigateToMain = {} + navigateToMain = {}, + savedUsername = null // userSessionState = null ) } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt index 1c19c4f..089f7cd 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt @@ -49,9 +49,10 @@ class SignInScreenViewModel @Inject constructor( val result = preferencesRepository.saveSession(userSession) when(result) { is Resource.Error -> { - result.data + _savedUsername.value = "" } is Resource.Success -> { + _savedUsername.value = result.data?.userNameId?.username } } } From 7c9c283a447e79002abc25deb9e213a69593750b Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Thu, 15 Jun 2023 22:36:40 +0700 Subject: [PATCH 64/73] finishing navigation --- .idea/deploymentTargetDropDown.xml | 4 +- .../com/capstone/techwasmark02/TechwasApp.kt | 17 +++++-- .../ui/screen/catalog/CatalogScreen.kt | 8 +++- .../detectionResult/DetectionResultScreen.kt | 33 +++++++++----- .../screen/forumSingle/ForumSingleScreen.kt | 3 +- .../ui/screen/main/MainScreen.kt | 21 ++++++++- .../ui/screen/maps/MapsScreen.kt | 7 +++ .../ui/screen/onBoarding/OnBoardingScreen.kt | 2 +- .../screen/profileUser/ProfileUserScreen.kt | 2 +- .../ui/screen/setting/SettingScreen.kt | 45 ++++++++++--------- .../screen/setting/SettingScreenViewModel.kt | 17 +++++++ .../ui/screen/signIn/SignInScreen.kt | 4 +- .../singleArticle/SingleArticleScreen.kt | 9 +++- .../ui/screen/splashScreen/SplashScreen.kt | 2 +- 14 files changed, 128 insertions(+), 46 deletions(-) diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index c6ba9c3..475c42d 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -7,11 +7,11 @@ - + - + \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt index f6ecba2..9b3b5fa 100644 --- a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt +++ b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt @@ -74,11 +74,20 @@ fun TechwasApp() { } composable( - route = Main.route, + route = Main.route + "/{page}", enterTransition = Main.enterTransition, - exitTransition = Main.exitTransition - ) { - MainScreen(navController = navController) + exitTransition = Main.exitTransition, + arguments = listOf( + navArgument("page") { + type = NavType.IntType + defaultValue = 0 + } + ) + ) { navBackStackEntry -> + val page = navBackStackEntry.arguments?.getInt("page") + if (page != null) { + MainScreen(navController = navController, page = page) + } } composable( diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt index dfca3a6..7abcf4a 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt @@ -1,6 +1,7 @@ package com.capstone.techwasmark02.ui.screen.catalog import android.net.Uri +import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -54,7 +55,7 @@ fun CatalogScreen( navigateToSingleComponent = { navController.navigate("${Screen.SingleCatalog.route}/$it") }, searchBoxValue = searchBoxValue, onSearchBoxValueChange = { viewModel.updateSearchBoxValue(it) }, - navigateBackToMain = { navController.popBackStack() } + navigateBackToMain = { navController.navigate("${Screen.Main.route}/0") } ) } @@ -66,6 +67,11 @@ fun CatalogContent( onSearchBoxValueChange: (String) -> Unit, navigateBackToMain: () -> Unit ) { + + BackHandler(true) { + navigateBackToMain() + } + val moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) .build() diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt index 75efa1d..84248d3 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/detectionResult/DetectionResultScreen.kt @@ -99,7 +99,9 @@ fun DetectionResultScreen( updateCurrentlySelectedUsableComponentList = { viewModel.updateCurrentlySelectedUsableComponentList(it) }, relatedArticleListState = relatedArticleListState, navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") }, - navigateToMain = { navController.navigate(Screen.Main.route) } + navigateToMain = { navController.navigate("${Screen.Main.route}/0") }, + navigateToForum = { navController.navigate("${Screen.Main.route}/1")}, + navigateToMaps = { navController.navigate(Screen.Maps.route) } ) } @@ -116,7 +118,9 @@ fun DetectionResultContent( updateCurrentlySelectedUsableComponentList: (List) -> Unit, relatedArticleListState: List>?, navigateToSingleArticle: (idArticle: Int) -> Unit, - navigateToMain: () -> Unit + navigateToMain: () -> Unit, + navigateToForum: () -> Unit, + navigateToMaps: () -> Unit, ) { val coroutineScope = rememberCoroutineScope() val modalSheetState = rememberModalBottomSheetState( @@ -352,7 +356,7 @@ fun DetectionResultContent( is UiState.Loading -> { Box( modifier = Modifier - .height(100.dp) + .height(175.dp) .fillMaxWidth(), contentAlignment = Alignment.Center ) { @@ -362,7 +366,7 @@ fun DetectionResultContent( is UiState.Error -> { Box( modifier = Modifier - .height(100.dp) + .height(175.dp) .fillMaxWidth(), contentAlignment = Alignment.Center ) { @@ -407,7 +411,7 @@ fun DetectionResultContent( Box( modifier = Modifier .fillMaxWidth() - .height(100.dp), + .height(175.dp), contentAlignment = Alignment.Center ) { Box( @@ -452,7 +456,10 @@ fun DetectionResultContent( ) { Spacer(modifier = Modifier.weight(1f)) - ThrowNSellButton() + ThrowNSellButton( + navigateToMaps = navigateToMaps, + navigateToForum = navigateToForum + ) } } } @@ -461,7 +468,10 @@ fun DetectionResultContent( } @Composable -fun ThrowNSellButton() { +fun ThrowNSellButton( + navigateToMaps: () -> Unit, + navigateToForum: () -> Unit +) { Row( modifier = Modifier .fillMaxWidth(), @@ -469,7 +479,7 @@ fun ThrowNSellButton() { horizontalArrangement = Arrangement.Center ) { Button( - onClick = { /*TODO*/ }, + onClick = navigateToMaps, modifier = Modifier .weight(1f) .padding(vertical = 18.dp) @@ -514,7 +524,7 @@ fun ThrowNSellButton() { Spacer(modifier = Modifier.width(8.dp)) Button( - onClick = { /*TODO*/ }, + onClick = navigateToForum, modifier = Modifier .weight(1f) .padding(vertical = 18.dp) @@ -587,7 +597,10 @@ fun ThrowNSellButtonPreview() { modifier = Modifier .padding(20.dp) ) { - ThrowNSellButton() + ThrowNSellButton( + navigateToForum = {}, + navigateToMaps = {} + ) } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt index 150a668..e4d8c8e 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt @@ -58,6 +58,7 @@ import com.capstone.techwasmark02.data.remote.response.Token import com.capstone.techwasmark02.data.remote.response.UserId import com.capstone.techwasmark02.ui.component.DefaultTopBar import com.capstone.techwasmark02.ui.component.TransparentTopBar +import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.screen.forum.ForumContent import com.capstone.techwasmark02.ui.theme.Mist97 import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @@ -73,7 +74,7 @@ fun ForumSingleScreen( ForumSingleContent( userSession = userSession, - navigateBackToForum = { navController.popBackStack() } + navigateBackToForum = { navController.navigate("${Screen.Main.route}/1") } ) } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreen.kt index 61337fe..9814eeb 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/main/MainScreen.kt @@ -5,6 +5,7 @@ import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment @@ -22,7 +23,8 @@ import com.capstone.techwasmark02.ui.screen.profileUser.ProfileUserScreen @Composable fun MainScreen( navController: NavHostController, - viewModel: MainScreenViewModel = viewModel() + viewModel: MainScreenViewModel = viewModel(), + page: Int ) { val selectedBottomBarType by viewModel.selectedBottomBarType.collectAsState() @@ -46,6 +48,23 @@ fun MainScreen( contentAlignment = Alignment.BottomCenter ) { + LaunchedEffect(Unit) { + when(page) { + 0 -> { + viewModel.updateSelectedBottomBartype(BottomBarItemType.Home) + } + 1 -> { + viewModel.updateSelectedBottomBartype(BottomBarItemType.Forum) + } + 2 -> { + viewModel.updateSelectedBottomBartype(BottomBarItemType.Article) + } + 3 -> { + viewModel.updateSelectedBottomBartype(BottomBarItemType.Profile) + } + } + } + when(selectedBottomBarType) { is BottomBarItemType.Home -> { HomeScreen(navController = navController) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt index 22b812b..b630213 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/maps/MapsScreen.kt @@ -3,6 +3,7 @@ package com.capstone.techwasmark02.ui.screen.maps import android.Manifest import android.content.pm.PackageManager import android.location.Location +import androidx.activity.compose.BackHandler import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.material3.AlertDialog @@ -18,6 +19,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext import androidx.core.content.ContextCompat import androidx.navigation.NavHostController +import com.capstone.techwasmark02.ui.navigation.Screen import com.google.android.gms.location.LocationServices import com.google.android.gms.maps.model.BitmapDescriptorFactory import com.google.android.gms.maps.model.CameraPosition @@ -35,6 +37,11 @@ data class MapMarkerInfo( ) @Composable fun MapsScreen(navController: NavHostController) { + + BackHandler(true) { + navController.navigate("${Screen.Main.route}/0") + } + val diy = LatLng(-7.782275587997325, 110.36709993087182) // posisi camera diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt index 674a0ef..31e24e7 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt @@ -66,7 +66,7 @@ fun OnBoardingScreen( navigateToHome = { navController.navigate(Screen.Home.route) }, navigateToSignUp = { navController.navigate(Screen.SignUp.route) }, navigateToSignIn = { navController.navigate(Screen.SignIn.route) }, - navigateToMain = { navController.navigate(Screen.Main.route) } + navigateToMain = { navController.navigate("${Screen.Main.route}/0") } ) } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt index dd51bc3..3b910e0 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt @@ -80,7 +80,7 @@ fun ProfileUserScreen( fun ProfileUserContent( navigateToSetting: () -> Unit, userSession: UserSession?, - bookmarkedArticleState: UiState? + bookmarkedArticleState: UiState?, ) { Scaffold( diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreen.kt index bd2f549..fde3b63 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreen.kt @@ -1,11 +1,11 @@ package com.capstone.techwasmark02.ui.screen.setting +import androidx.activity.compose.BackHandler import androidx.compose.foundation.Image 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.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight @@ -15,24 +15,17 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Edit -import androidx.compose.material.icons.filled.ShoppingCart import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment @@ -50,15 +43,12 @@ import com.capstone.techwasmark02.R import com.capstone.techwasmark02.data.model.UserSession import com.capstone.techwasmark02.data.remote.response.Token import com.capstone.techwasmark02.data.remote.response.UserId -import com.capstone.techwasmark02.ui.component.ArticleCardSmall -import com.capstone.techwasmark02.ui.component.DefaultTopBar -import com.capstone.techwasmark02.ui.component.ForumBox import com.capstone.techwasmark02.ui.component.InverseTopBar import com.capstone.techwasmark02.ui.component.SettingItem import com.capstone.techwasmark02.ui.componentType.SettingItemType +import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import com.capstone.techwasmark02.ui.theme.red -import kotlin.random.Random @Composable fun SettingScreen( @@ -70,16 +60,24 @@ fun SettingScreen( SettingContent( navigateToProfile = { navController.popBackStack() }, - userSession = userSession + userSession = userSession, + navigateToOnBoarding = { navController.navigate(Screen.OnBoarding.route)}, + logOutUser = { viewModel.clearUserSession() }, + navigateBackToMain = { navController.navigate("${Screen.Main.route}/3") } ) } -@OptIn(ExperimentalMaterial3Api::class) @Composable fun SettingContent( navigateToProfile: () -> Unit, - userSession: UserSession? + userSession: UserSession?, + navigateToOnBoarding: () -> Unit, + logOutUser: () -> Unit, + navigateBackToMain: () -> Unit ) { + BackHandler(true) { + navigateBackToMain() + } val settingItemList = listOf( SettingItemType.Password, @@ -88,7 +86,11 @@ fun SettingContent( SettingItemType.Language ) - val scrollState = rememberScrollState() + LaunchedEffect(userSession) { + if (userSession?.userNameId?.username == "-") { + navigateToOnBoarding() + } + } Box( modifier = Modifier @@ -229,7 +231,7 @@ fun SettingContent( Spacer(modifier = Modifier.height(10.dp)) Button( - onClick = { }, + onClick = logOutUser, modifier = Modifier .width(122.dp) .height(41.dp) @@ -252,7 +254,7 @@ fun SettingContent( InverseTopBar( onClickNavigationIcon = { - navigateToProfile() + navigateBackToMain() } ) } @@ -272,7 +274,10 @@ fun SettingScreenPreview() { userLoginToken = Token( accessToken = "" ) - ) + ), + navigateToOnBoarding = {}, + logOutUser = {}, + navigateBackToMain = {} ) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreenViewModel.kt index 8b69145..a1eb95f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/setting/SettingScreenViewModel.kt @@ -38,4 +38,21 @@ class SettingScreenViewModel @Inject constructor( } } + fun clearUserSession() { + viewModelScope.launch { + val result = preferencesRepository.clearSession() + when(result) { + is Resource.Error -> { + // do nothing + } + is Resource.Success -> { + _userSessionState.value = UserSession( + userLoginToken = Token(accessToken = ""), + userNameId = UserId(username = "-", id = 0) + ) + } + } + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt index 5152d96..afd0b10 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt @@ -56,7 +56,7 @@ fun SignInScreen( userToSignInState = userToSignInState, signInUser = { viewModel.signInUser() }, saveUserSession = { viewModel.saveUserSession() }, - navigateToMain = { navController.navigate(Screen.Main.route) }, + navigateToMain = { navController.navigate("${Screen.Main.route}/0") }, savedUsername = savedUsername // userSessionState = userSessionState, ) @@ -181,9 +181,9 @@ fun SignInContent( saveUserSession() if (savedUsername != null && savedUsername != "") { - Toast.makeText(context, "Welcome $savedUsername", Toast.LENGTH_SHORT).show() LaunchedEffect(Unit) { + Toast.makeText(context, "Welcome $savedUsername", Toast.LENGTH_SHORT).show() navigateToMain() } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt index d642967..4a93d2f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt @@ -1,5 +1,6 @@ package com.capstone.techwasmark02.ui.screen.singleArticle +import androidx.activity.compose.BackHandler import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box @@ -74,7 +75,7 @@ fun SingleArticleScreen( SingleArticleContent( articleResult = articleResult, - navigateToArticle = { navController.popBackStack() } + navigateToArticle = { navController.navigate("${Screen.Main.route}/2") } ) } @@ -85,6 +86,10 @@ fun SingleArticleContent( navigateToArticle: () -> Unit ) { + BackHandler(true) { + navigateToArticle() + } + val result = articleResult?.data?.article Scaffold { innerPadding -> @@ -153,7 +158,7 @@ fun SingleArticleContent( ) } Text( - text = result?.get(0)?.id.toString(), + text = "source: techwaste", style = MaterialTheme.typography.bodyMedium ) } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt index 0ca3227..51d08f8 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/splashScreen/SplashScreen.kt @@ -69,7 +69,7 @@ fun SplashScreen( if (userSession!!.userLoginToken.accessToken == "") { navController.navigate(Screen.OnBoarding.route) } else { - navController.navigate(Screen.Main.route) + navController.navigate("${Screen.Main.route}/0") } } } From 3b49e50b52a1076dd6e44818717ebbb57a8cc626 Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Fri, 16 Jun 2023 09:26:17 +0700 Subject: [PATCH 65/73] adding add to favorite article feature on single article --- app/build.gradle | 5 + .../local/database/FavoriteArticleDatabase.kt | 14 + .../database/dao/FavoriteArticleEntityDao.kt | 28 ++ .../database/entity/FavoriteArticleEntity.kt | 14 + .../techwasmark02/data/mappers/Mappers.kt | 25 +- .../data/model/FavoriteArticle.kt | 9 + .../capstone/techwasmark02/di/AppModule.kt | 18 ++ .../repository/FavoriteArticleRepository.kt | 20 ++ .../singleArticle/SingleArticleScreen.kt | 276 +++++++++++------- .../SingleArticleScreenViewModel.kt | 40 ++- 10 files changed, 331 insertions(+), 118 deletions(-) create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/local/database/FavoriteArticleDatabase.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/local/database/dao/FavoriteArticleEntityDao.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/local/database/entity/FavoriteArticleEntity.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/model/FavoriteArticle.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/repository/FavoriteArticleRepository.kt diff --git a/app/build.gradle b/app/build.gradle index 8af9832..c67caad 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -119,6 +119,11 @@ dependencies { implementation "androidx.camera:camera-lifecycle:1.2.3" implementation "androidx.camera:camera-view:1.3.0-alpha07" + // Room + implementation "androidx.room:room-ktx:2.5.1" + kapt "androidx.room:room-compiler:2.5.1" + implementation "androidx.room:room-paging:2.5.1" + testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/app/src/main/java/com/capstone/techwasmark02/data/local/database/FavoriteArticleDatabase.kt b/app/src/main/java/com/capstone/techwasmark02/data/local/database/FavoriteArticleDatabase.kt new file mode 100644 index 0000000..a50a4f4 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/local/database/FavoriteArticleDatabase.kt @@ -0,0 +1,14 @@ +package com.capstone.techwasmark02.data.local.database + +import androidx.room.Database +import androidx.room.RoomDatabase +import com.capstone.techwasmark02.data.local.database.dao.FavoriteArticleEntityDao +import com.capstone.techwasmark02.data.local.database.entity.FavoriteArticleEntity + +@Database( + entities = [FavoriteArticleEntity::class], + version = 1 +) +abstract class FavoriteArticleDatabase: RoomDatabase() { + abstract val favoriteArticleDao: FavoriteArticleEntityDao +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/local/database/dao/FavoriteArticleEntityDao.kt b/app/src/main/java/com/capstone/techwasmark02/data/local/database/dao/FavoriteArticleEntityDao.kt new file mode 100644 index 0000000..4ec782d --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/local/database/dao/FavoriteArticleEntityDao.kt @@ -0,0 +1,28 @@ +package com.capstone.techwasmark02.data.local.database.dao + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Query +import androidx.room.Upsert +import com.capstone.techwasmark02.data.local.database.entity.FavoriteArticleEntity +import kotlinx.coroutines.flow.Flow + + +@Dao +interface FavoriteArticleEntityDao { + + @Upsert + suspend fun upsertFavoriteArticle(favoriteArticle: FavoriteArticleEntity) + + @Delete + suspend fun deleteFavoriteArticle( + favoriteArticle: FavoriteArticleEntity + ) + + @Query("SELECT * FROM fav_article_entity") + fun getFavoriteArticles(): Flow> + + @Query("SELECT * FROM fav_article_entity WHERE id = :id") + fun getFavoriteArticleById(id: Int): Flow + +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/local/database/entity/FavoriteArticleEntity.kt b/app/src/main/java/com/capstone/techwasmark02/data/local/database/entity/FavoriteArticleEntity.kt new file mode 100644 index 0000000..daa2776 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/local/database/entity/FavoriteArticleEntity.kt @@ -0,0 +1,14 @@ +package com.capstone.techwasmark02.data.local.database.entity + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity( tableName = "fav_article_entity" ) +data class FavoriteArticleEntity( + @PrimaryKey + val id: Int, + val name: String, + val desc: String, + val articleImageURL: String, + val componentId: Int +) diff --git a/app/src/main/java/com/capstone/techwasmark02/data/mappers/Mappers.kt b/app/src/main/java/com/capstone/techwasmark02/data/mappers/Mappers.kt index 3f292d3..453ba1e 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/mappers/Mappers.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/mappers/Mappers.kt @@ -1,6 +1,9 @@ package com.capstone.techwasmark02.data.mappers +import com.capstone.techwasmark02.data.local.database.entity.FavoriteArticleEntity +import com.capstone.techwasmark02.data.model.FavoriteArticle import com.capstone.techwasmark02.data.model.UserSession +import com.capstone.techwasmark02.data.remote.response.ArticleItem import com.capstone.techwasmark02.data.remote.response.LoginResult fun LoginResult.toUserSession(): UserSession { @@ -8,4 +11,24 @@ fun LoginResult.toUserSession(): UserSession { userLoginToken = token, userNameId = userId ) -} \ No newline at end of file +} + +fun FavoriteArticleEntity.toFavoriteArticle(): FavoriteArticle { + return FavoriteArticle( + id = id, + name = name, + desc = desc, + imageURL = articleImageURL, + compId = componentId + ) +} + +fun FavoriteArticle.toFavoriteArticleEntity(): FavoriteArticleEntity { + return FavoriteArticleEntity( + id = id, + name = name, + componentId = compId, + articleImageURL = imageURL, + desc = desc + ) +} diff --git a/app/src/main/java/com/capstone/techwasmark02/data/model/FavoriteArticle.kt b/app/src/main/java/com/capstone/techwasmark02/data/model/FavoriteArticle.kt new file mode 100644 index 0000000..3ab5a23 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/model/FavoriteArticle.kt @@ -0,0 +1,9 @@ +package com.capstone.techwasmark02.data.model + +data class FavoriteArticle( + val id: Int, + val name: String, + val imageURL: String, + val compId: Int, + val desc: String +) \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt b/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt index b520047..6a0d8e2 100644 --- a/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt +++ b/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt @@ -4,10 +4,13 @@ import android.content.Context import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.preferencesDataStore +import androidx.room.Room +import com.capstone.techwasmark02.data.local.database.FavoriteArticleDatabase import com.capstone.techwasmark02.data.remote.apiService.TechwasArticleApi import com.capstone.techwasmark02.data.remote.apiService.TechwasComponentApi import com.capstone.techwasmark02.data.remote.apiService.TechwasPredictionApi import com.capstone.techwasmark02.data.remote.apiService.TechwasUserApi +import com.capstone.techwasmark02.repository.FavoriteArticleRepository import com.capstone.techwasmark02.repository.TechwasArticleRepository import com.capstone.techwasmark02.repository.TechwasComponentApiRepository import com.capstone.techwasmark02.repository.TechwasUserApiRepository @@ -122,4 +125,19 @@ object AppModule { api: TechwasComponentApi ) = TechwasComponentApiRepository(api) + @Provides + @Singleton + fun provideFavoriteArticleDatabase(@ApplicationContext context: Context): FavoriteArticleDatabase { + return Room.databaseBuilder( + context, + FavoriteArticleDatabase::class.java, + "fav_article_database" + ).build() + } + + @Provides + fun provideFavoriteArticleRepository( + favoriteArticleDatabase: FavoriteArticleDatabase + ) = FavoriteArticleRepository(favArticleDatabase = favoriteArticleDatabase) + } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/FavoriteArticleRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/FavoriteArticleRepository.kt new file mode 100644 index 0000000..6b8f83c --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/repository/FavoriteArticleRepository.kt @@ -0,0 +1,20 @@ +package com.capstone.techwasmark02.repository + +import com.capstone.techwasmark02.data.local.database.FavoriteArticleDatabase +import com.capstone.techwasmark02.data.mappers.toFavoriteArticleEntity +import com.capstone.techwasmark02.data.model.FavoriteArticle +import javax.inject.Inject + +class FavoriteArticleRepository @Inject constructor(private val favArticleDatabase: FavoriteArticleDatabase) { + + fun getFavArticles() = favArticleDatabase.favoriteArticleDao.getFavoriteArticles() + + fun getFavArticleById(id: Int) = favArticleDatabase.favoriteArticleDao.getFavoriteArticleById(id = id) + + suspend fun upsertFavoriteArticle(favoriteArticle: FavoriteArticle) = favArticleDatabase.favoriteArticleDao.upsertFavoriteArticle(favoriteArticle.toFavoriteArticleEntity()) + + suspend fun deleteFavoriteArticle( + favoriteArticle: FavoriteArticle + ) = favArticleDatabase.favoriteArticleDao.deleteFavoriteArticle(favoriteArticle.toFavoriteArticleEntity()) + +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt index 4a93d2f..ae17a19 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt @@ -18,6 +18,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Favorite +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -46,6 +47,8 @@ import androidx.navigation.NavController import androidx.navigation.NavHostController import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.local.database.entity.FavoriteArticleEntity +import com.capstone.techwasmark02.data.model.FavoriteArticle import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.SingleArticleResponse import com.capstone.techwasmark02.ui.common.UiState @@ -55,6 +58,7 @@ import com.capstone.techwasmark02.ui.component.TransparentTopBar import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.Mist97 import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch import kotlin.random.Random @@ -68,14 +72,19 @@ fun SingleArticleScreen( LaunchedEffect(Unit) { viewModel.viewModelScope.launch { viewModel.getArticleById(idArticle) + viewModel.getFavArticleById(idArticle) } } val articleResult by viewModel.articleResult.collectAsState() + val isArticleFavorited by viewModel.isArticleFavorited.collectAsState(initial = null) + SingleArticleContent( articleResult = articleResult, - navigateToArticle = { navController.navigate("${Screen.Main.route}/2") } + navigateToArticle = { navController.navigate("${Screen.Main.route}/2") }, + isArticleFavorited = isArticleFavorited, + updateArticleFavorited = { articleGetFavorited, favoriteArticle -> viewModel.updateArticleFavorited(articleGetFavorited, favoriteArticle)} ) } @@ -83,7 +92,9 @@ fun SingleArticleScreen( @Composable fun SingleArticleContent( articleResult: UiState?, - navigateToArticle: () -> Unit + navigateToArticle: () -> Unit, + isArticleFavorited: FavoriteArticleEntity?, + updateArticleFavorited: ((articleGetFavorited: Boolean, favoriteArticle: FavoriteArticle) -> Unit) ) { BackHandler(true) { @@ -100,120 +111,172 @@ fun SingleArticleContent( .fillMaxSize() .padding(innerPadding) ) { - Column( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - .verticalScroll(scrollState) - ) { - - Box( - modifier = Modifier - .fillMaxWidth() - .background(Mist97) - ) { - Column( - modifier = Modifier - .fillMaxSize() - ) { + if (articleResult != null) { + when(articleResult) { + is UiState.Loading -> { Box( modifier = Modifier - .fillMaxWidth() - .height(300.dp) - .clip( - RoundedCornerShape( - topStart = 0.dp, - topEnd = 0.dp, - bottomEnd = 16.dp, - bottomStart = 16.dp - ) - ) + .fillMaxSize(), + contentAlignment = Alignment.Center ) { - Image( - modifier = Modifier.matchParentSize(), - painter = rememberAsyncImagePainter( - model = result?.get(0)?.articleImageURL, - placeholder = painterResource(id = R.drawable.place_holder), - ), - contentScale = ContentScale.Crop, - contentDescription = null - ) - } - - Column(modifier = Modifier - .padding(bottom = 10.dp, top = 10.dp) - .padding(horizontal = 16.dp) - ) { - result?.get(0)?.componentName?.let { - Text( - text = it, - style = MaterialTheme.typography.bodyMedium - ) - } - result?.get(0)?.name?.let { - Text( - text = it, - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold, - ) - } - Text( - text = "source: techwaste", - style = MaterialTheme.typography.bodyMedium - ) + CircularProgressIndicator() } } + is UiState.Error -> { + Box( + modifier = Modifier + .fillMaxSize() + ) + } + is UiState.Success -> { + val currentArticle = articleResult.data?.article?.get(0) + val isArticleFavorite = currentArticle?.id == isArticleFavorited?.id - Box( - modifier = Modifier - .fillMaxWidth() - .padding(end = 16.dp, top = 270.dp), - contentAlignment = Alignment.CenterEnd - ) { - IconButton( - onClick = {}, + Column( modifier = Modifier - .clip(CircleShape) - .shadow(elevation = 4.dp, clip = true) + .fillMaxSize() .background(Color.White) - .size(50.dp) + .verticalScroll(scrollState) ) { - Icon( - Icons.Default.Favorite, - tint = Color.Red, - contentDescription = null - ) - } - } - } - Spacer(modifier = Modifier.height(16.dp)) - - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) - .padding(bottom = 20.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - result?.get(0)?.description?.let { - HtmlText( - html = it, - textStyle = MaterialTheme.typography.bodyMedium.copy( - color = Color.Black, - fontWeight = FontWeight.Normal, - fontSize = 14.sp - ) - ) - } + Box( + modifier = Modifier + .fillMaxWidth() + .background(Mist97) + ) { + Column( + modifier = Modifier + .fillMaxSize() + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(300.dp) + .clip( + RoundedCornerShape( + topStart = 0.dp, + topEnd = 0.dp, + bottomEnd = 16.dp, + bottomStart = 16.dp + ) + ) + ) { + Image( + modifier = Modifier.matchParentSize(), + painter = rememberAsyncImagePainter( + model = result?.get(0)?.articleImageURL, + placeholder = painterResource(id = R.drawable.place_holder), + ), + contentScale = ContentScale.Crop, + contentDescription = null + ) + } - Spacer(modifier = Modifier.height(36.dp)) + Column(modifier = Modifier + .padding(bottom = 10.dp, top = 10.dp) + .padding(horizontal = 16.dp) + ) { + result?.get(0)?.componentName?.let { + Text( + text = it, + style = MaterialTheme.typography.bodyMedium + ) + } + result?.get(0)?.name?.let { + Text( + text = it, + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold, + ) + } + Text( + text = "source: techwaste", + style = MaterialTheme.typography.bodyMedium + ) + } + } - DefaultButton( - contentText = "Share", - onClick = {}, - modifier = Modifier.width(150.dp) - ) + Box( + modifier = Modifier + .fillMaxWidth() + .padding(end = 16.dp, top = 270.dp), + contentAlignment = Alignment.CenterEnd + ) { + + IconButton( + onClick = { + val favoritedArticle = currentArticle?.id?.let { + currentArticle.name?.let { it1 -> + currentArticle.articleImageURL?.let { it2 -> + currentArticle.componentID?.let { it3 -> + currentArticle.description?.let { it4 -> + FavoriteArticle( + id = it, + name = it1, + imageURL = it2, + compId = it3, + desc = it4 + ) + } + } + } + } + } + if (isArticleFavorite) { + if (favoritedArticle != null) { + updateArticleFavorited(false, favoritedArticle) + } + } else { + if (favoritedArticle != null) { + updateArticleFavorited(true, favoritedArticle) + } + } + }, + modifier = Modifier + .clip(CircleShape) + .shadow(elevation = 4.dp, clip = true) + .background(Color.White) + .size(50.dp) + ) { + Icon( + Icons.Default.Favorite, + tint = if (isArticleFavorite) Color.Red else Color.LightGray, + contentDescription = null + ) + } + } + } + + Spacer(modifier = Modifier.height(16.dp)) + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + .padding(bottom = 20.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + result?.get(0)?.description?.let { + HtmlText( + html = it, + textStyle = MaterialTheme.typography.bodyMedium.copy( + color = Color.Black, + fontWeight = FontWeight.Normal, + fontSize = 14.sp + ) + ) + } + + Spacer(modifier = Modifier.height(36.dp)) + + DefaultButton( + contentText = "Share", + onClick = {}, + modifier = Modifier.width(150.dp) + ) + } + } + } } } @@ -243,7 +306,10 @@ fun SingleArticleScreenPreview() { TechwasMark02Theme { SingleArticleContent( articleResult = UiState.Loading(), - navigateToArticle = {} + navigateToArticle = {}, + isArticleFavorited = null, + updateArticleFavorited = fun(articleGetFavorited: Boolean, + favoriteArticle: FavoriteArticle) {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt index 070c5c0..d87e79f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt @@ -2,11 +2,16 @@ package com.capstone.techwasmark02.ui.screen.singleArticle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.data.local.database.entity.FavoriteArticleEntity +import com.capstone.techwasmark02.data.mappers.toFavoriteArticleEntity +import com.capstone.techwasmark02.data.model.FavoriteArticle import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.SingleArticleResponse +import com.capstone.techwasmark02.repository.FavoriteArticleRepository import com.capstone.techwasmark02.repository.TechwasArticleRepository import com.capstone.techwasmark02.ui.common.UiState import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch @@ -14,7 +19,8 @@ import javax.inject.Inject @HiltViewModel class SingleArticleScreenViewModel @Inject constructor( - private val articleRepository: TechwasArticleRepository + private val articleRepository: TechwasArticleRepository, + private val favoriteArticleRepository: FavoriteArticleRepository ): ViewModel() { private val _articleResult: MutableStateFlow?> = MutableStateFlow(null) @@ -23,17 +29,27 @@ class SingleArticleScreenViewModel @Inject constructor( fun getArticleById(id: Int) { _articleResult.value = UiState.Loading() viewModelScope.launch { - val result = articleRepository.getArticleById(id) - when(result) { - is UiState.Success -> { - _articleResult.value = result - } - is UiState.Error -> { - _articleResult.value = result - } - else -> { - // do nothing - } + _articleResult.value = articleRepository.getArticleById(id) + } + } + + var isArticleFavorited: Flow = favoriteArticleRepository.getFavArticleById(id = 0) + + fun getFavArticleById(id: Int) { + isArticleFavorited = favoriteArticleRepository.getFavArticleById(id = id) + } + + fun updateArticleFavorited( + articleGetFavorited: Boolean, + favoriteArticle: FavoriteArticle + ) { + if (articleGetFavorited) { + viewModelScope.launch { + favoriteArticleRepository.upsertFavoriteArticle(favoriteArticle) + } + } else { + viewModelScope.launch { + favoriteArticleRepository.deleteFavoriteArticle(favoriteArticle) } } } From 470b059e45a52363a26759259ee1d5d18cd02372 Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Fri, 16 Jun 2023 09:42:45 +0700 Subject: [PATCH 66/73] showing favorite article on profile --- .../screen/profileUser/ProfileUserScreen.kt | 142 +++++++++++++----- .../profileUser/ProfileUserScreenViewModel.kt | 6 +- 2 files changed, 106 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt index 3b910e0..1eeb120 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt @@ -2,6 +2,8 @@ package com.capstone.techwasmark02.ui.screen.profileUser import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -44,6 +46,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.local.database.entity.FavoriteArticleEntity import com.capstone.techwasmark02.data.model.UserSession import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.Token @@ -67,11 +70,14 @@ fun ProfileUserScreen( ) { val userSession by viewModel.userSessionState.collectAsState() val bookmarkedArticleState by viewModel.bookmarkedArticleState.collectAsState() + val favoriteArticlesList by viewModel.favoriteArticlesFlow.collectAsState(initial = null) ProfileUserContent( navigateToSetting = { navController.navigate(Screen.Setting.route) }, userSession = userSession, - bookmarkedArticleState = bookmarkedArticleState + bookmarkedArticleState = bookmarkedArticleState, + favoriteArticleList = favoriteArticlesList, + navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") } ) } @@ -81,6 +87,8 @@ fun ProfileUserContent( navigateToSetting: () -> Unit, userSession: UserSession?, bookmarkedArticleState: UiState?, + favoriteArticleList: List?, + navigateToSingleArticle: (idArticle: Int) -> Unit ) { Scaffold( @@ -197,52 +205,102 @@ fun ProfileUserContent( Spacer(modifier = Modifier.height(8.dp)) - if (bookmarkedArticleState != null) { - when(bookmarkedArticleState) { - is UiState.Loading -> { - Box( - modifier = Modifier - .fillMaxWidth() - .height(100.dp), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() - } - } - is UiState.Error -> { - Box( - modifier = Modifier - .fillMaxWidth() - .height(100.dp), - contentAlignment = Alignment.Center - ) { - Text(text = "No article to view") + if (!favoriteArticleList.isNullOrEmpty() && favoriteArticleList.isNotEmpty()) { + favoriteArticleList.let { + LazyRow( + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + items( + count = favoriteArticleList.size, + ) { index -> + val article = favoriteArticleList[index] + + ArticleCardSmall( + modifier = Modifier + .width(150.dp) + .clickable { + navigateToSingleArticle(article.id) + }, + imgUrl = article.articleImageURL, + title = article.name, + description = article.desc + ) } } - is UiState.Success -> { - bookmarkedArticleState.data?.articleList?.size?.let { - LazyRow( - contentPadding = PaddingValues(horizontal = 16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - items( - count = it, - ) { page -> - val article = bookmarkedArticleState.data.articleList[page] + } + } else { + Box( + modifier = Modifier + .fillMaxWidth() + .height(175.dp), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) - ArticleCardSmall( - modifier = Modifier.width(150.dp), - imgUrl = article?.articleImageURL, - title = article?.name, - description = article?.desc - ) - } - } - } + ) { + Text( + text = "There's no related article", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) } } } +// if (bookmarkedArticleState != null) { +// when(bookmarkedArticleState) { +// is UiState.Loading -> { +// Box( +// modifier = Modifier +// .fillMaxWidth() +// .height(100.dp), +// contentAlignment = Alignment.Center +// ) { +// CircularProgressIndicator() +// } +// } +// is UiState.Error -> { +// Box( +// modifier = Modifier +// .fillMaxWidth() +// .height(100.dp), +// contentAlignment = Alignment.Center +// ) { +// Text(text = "No article to view") +// } +// } +// is UiState.Success -> { +// bookmarkedArticleState.data?.articleList?.size?.let { +// LazyRow( +// contentPadding = PaddingValues(horizontal = 16.dp), +// horizontalArrangement = Arrangement.spacedBy(16.dp) +// ) { +// items( +// count = it, +// ) { page -> +// val article = bookmarkedArticleState.data.articleList[page] +// +// ArticleCardSmall( +// modifier = Modifier.width(150.dp), +// imgUrl = article?.articleImageURL, +// title = article?.name, +// description = article?.desc +// ) +// } +// } +// } +// } +// } +// } + Spacer(modifier = Modifier.height(16.dp)) Text( @@ -337,7 +395,9 @@ fun ProfileUserScreenPreview() { accessToken = "" ) ), - bookmarkedArticleState = null + bookmarkedArticleState = null, + favoriteArticleList = null, + navigateToSingleArticle = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreenViewModel.kt index 092a5c3..79d8408 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreenViewModel.kt @@ -7,6 +7,7 @@ import com.capstone.techwasmark02.data.model.UserSession import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.Token import com.capstone.techwasmark02.data.remote.response.UserId +import com.capstone.techwasmark02.repository.FavoriteArticleRepository import com.capstone.techwasmark02.repository.PreferencesRepository import com.capstone.techwasmark02.repository.TechwasArticleRepository import com.capstone.techwasmark02.ui.common.UiState @@ -19,7 +20,8 @@ import javax.inject.Inject @HiltViewModel class ProfileUserScreenViewModel @Inject constructor( private val preferencesRepository: PreferencesRepository, - private val articleApiRepository: TechwasArticleRepository + private val articleApiRepository: TechwasArticleRepository, + private val favoriteArticleRepository: FavoriteArticleRepository ): ViewModel() { private val _userSessionState: MutableStateFlow = MutableStateFlow(null) @@ -28,6 +30,8 @@ class ProfileUserScreenViewModel @Inject constructor( private val _bookmarkedArticleState: MutableStateFlow?> = MutableStateFlow(null) val bookmarkedArticleState = _bookmarkedArticleState.asStateFlow() + val favoriteArticlesFlow = favoriteArticleRepository.getFavArticles() + init { _bookmarkedArticleState.value = UiState.Loading() From b946ba1f592468c1db5d54c7e4ca05ceb766b333 Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Fri, 16 Jun 2023 10:44:47 +0700 Subject: [PATCH 67/73] fetch all forum to forum screen --- .../data/remote/apiService/TechwasForumApi.kt | 25 +++ .../data/remote/response/ForumResponse.kt | 21 +++ .../capstone/techwasmark02/di/AppModule.kt | 26 ++- .../repository/TechwasForumApiRepository.kt | 39 +++++ .../ui/screen/forum/ForumScreen.kt | 151 ++++++++++++++---- .../ui/screen/forum/ForumScreenViewModel.kt | 27 ++++ 6 files changed, 261 insertions(+), 28 deletions(-) create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasForumApi.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/remote/response/ForumResponse.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasForumApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasForumApi.kt new file mode 100644 index 0000000..642776f --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasForumApi.kt @@ -0,0 +1,25 @@ +package com.capstone.techwasmark02.data.remote.apiService + +import com.capstone.techwasmark02.data.remote.response.ForumResponse +import retrofit2.http.GET +import retrofit2.http.Path + +interface TechwasForumApi { + + @GET("/forum/getall") + suspend fun fetchAllForum(): ForumResponse + + @GET("/forum/id/{id}") + suspend fun fetchForumById( + @Path("id") id: Int + ): ForumResponse + + @GET("/forum/category/{category}") + suspend fun fetchForumByCategory( + @Path("category") category: String + ): ForumResponse + + companion object { + const val BASE_URL = "https://backend-api-56g32wdmqa-uc.a.run.app/" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ForumResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ForumResponse.kt new file mode 100644 index 0000000..62973aa --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ForumResponse.kt @@ -0,0 +1,21 @@ +package com.capstone.techwasmark02.data.remote.response + +import com.google.gson.annotations.SerializedName + +data class ForumResponse( + val error: String, + val forum: List, + val message: String +) + +data class Forum( + @SerializedName("Postedby") + val postedBy: String, + val category: String, + val content: String, + val id: Int, + val imageURL: String, + val likes: Any, + val location: String, + val title: String +) \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt b/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt index 6a0d8e2..58585ec 100644 --- a/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt +++ b/app/src/main/java/com/capstone/techwasmark02/di/AppModule.kt @@ -8,11 +8,13 @@ import androidx.room.Room import com.capstone.techwasmark02.data.local.database.FavoriteArticleDatabase import com.capstone.techwasmark02.data.remote.apiService.TechwasArticleApi import com.capstone.techwasmark02.data.remote.apiService.TechwasComponentApi +import com.capstone.techwasmark02.data.remote.apiService.TechwasForumApi import com.capstone.techwasmark02.data.remote.apiService.TechwasPredictionApi import com.capstone.techwasmark02.data.remote.apiService.TechwasUserApi import com.capstone.techwasmark02.repository.FavoriteArticleRepository import com.capstone.techwasmark02.repository.TechwasArticleRepository import com.capstone.techwasmark02.repository.TechwasComponentApiRepository +import com.capstone.techwasmark02.repository.TechwasForumApiRepository import com.capstone.techwasmark02.repository.TechwasUserApiRepository import dagger.Module import dagger.Provides @@ -94,7 +96,7 @@ object AppModule { .addInterceptor(loggingInterceptor) .build() val retrofit = Retrofit.Builder() - .baseUrl(TechwasArticleApi.BASE_URL) + .baseUrl(TechwasComponentApi.BASE_URL) .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .client(client) @@ -102,6 +104,23 @@ object AppModule { return retrofit.create(TechwasComponentApi::class.java) } + @Provides + @Singleton + fun provideTechwasForumApi(): TechwasForumApi { + val loggingInterceptor = + HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY) + val client = OkHttpClient.Builder() + .addInterceptor(loggingInterceptor) + .build() + val retrofit = Retrofit.Builder() + .baseUrl(TechwasForumApi.BASE_URL) + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(GsonConverterFactory.create()) + .client(client) + .build() + return retrofit.create(TechwasForumApi::class.java) + } + @Provides @Singleton fun provideDataStorePreferences( @@ -125,6 +144,11 @@ object AppModule { api: TechwasComponentApi ) = TechwasComponentApiRepository(api) + @Provides + fun provideTechwasForumApiRepository( + api: TechwasForumApi + ) = TechwasForumApiRepository(api) + @Provides @Singleton fun provideFavoriteArticleDatabase(@ApplicationContext context: Context): FavoriteArticleDatabase { diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt new file mode 100644 index 0000000..74ca2b1 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt @@ -0,0 +1,39 @@ +package com.capstone.techwasmark02.repository + +import com.capstone.techwasmark02.data.remote.apiService.TechwasForumApi +import com.capstone.techwasmark02.data.remote.response.ForumResponse +import com.capstone.techwasmark02.ui.common.UiState +import java.lang.Exception +import javax.inject.Inject + +class TechwasForumApiRepository @Inject constructor( + private val forumApi: TechwasForumApi +) { + + suspend fun fetchAllForum(): UiState { + val response = try { + forumApi.fetchAllForum() + } catch (e: Exception) { + return UiState.Error(message = "fail to fetch forum, ${e.message}") + } + return UiState.Success(data = response, message = "Success to fetch forum") + } + + suspend fun fetchForumById(id: Int): UiState { + val response = try { + forumApi.fetchForumById(id) + } catch (e: Exception) { + return UiState.Error(message = "fail to fetch forum, ${e.message}") + } + return UiState.Success(data = response, message = response.message) + } + + suspend fun fetchForumByCategory(category: String): UiState { + val response = try { + forumApi.fetchForumByCategory(category) + } catch (e: Exception) { + return UiState.Error(message = "fail to fetch forum, ${e.message}") + } + return UiState.Success(data = response, message = response.message) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt index 2a718e9..95b59d6 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt @@ -1,6 +1,7 @@ package com.capstone.techwasmark02.ui.screen.forum import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -20,11 +21,14 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Icon +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -32,12 +36,16 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.remote.response.ForumResponse +import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.ForumBox import com.capstone.techwasmark02.ui.component.SearchBox import com.capstone.techwasmark02.ui.component.SelectableText @@ -47,16 +55,21 @@ import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme @Composable fun ForumScreen( - navController: NavHostController + navController: NavHostController, + viewModel: ForumScreenViewModel = hiltViewModel() ) { + val forumListState by viewModel.forumList.collectAsState() + ForumContent( - navigateToSingleForum = { navController.navigate(Screen.SingleForum.route)} + navigateToSingleForum = { navController.navigate(Screen.SingleForum.route)}, + forumListState = forumListState ) } @Composable fun ForumContent( - navigateToSingleForum: () -> Unit + navigateToSingleForum: () -> Unit, + forumListState: UiState? ) { var inputValue by remember { mutableStateOf("") @@ -177,31 +190,114 @@ fun ForumContent( } } + if (forumListState != null) { + when(forumListState) { + is UiState.Loading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is UiState.Error -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(175.dp), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) - LazyColumn( - modifier = Modifier, - contentPadding = PaddingValues(vertical = 20.dp, horizontal = 16.dp), - verticalArrangement = Arrangement.spacedBy(10.dp) - ) { - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Cara Hidupkan HP Masuk Toilet", - desc = "Jadi kemarin saya tidak sengaja menjatuhkan HP saya ke toilet", - place = "Malang", - photoUrl = R.drawable.img_forum_hp_nyala - ) - } + ) { + Text( + text = "Fail to fetch forum", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + } + is UiState.Success -> { + val currentForumList = forumListState.data?.forum - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - photoUrl = R.drawable.img_forum_laptop_bekas, - onClick = navigateToSingleForum, - title = "Jual Laptop Mati Total", - desc = "Saya mempunyai laptop yang baru saja mati, pada saat tombol power tekan tidak ada respon apapun, kemungkinan masalah berada di battery. Selain itu kondisi masih bagus dan tidak ada kerusakan luar\nBagi yang berminat dapat mencoba menghubungi saya +6281396774583", - place = "Yogyakarta" - ) + if (!currentForumList.isNullOrEmpty() && currentForumList.isNotEmpty()) { + LazyColumn( + modifier = Modifier, + contentPadding = PaddingValues(vertical = 20.dp, horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + items(currentForumList) { forum -> + ForumBox( + modifier = Modifier + .fillMaxWidth(), + title = forum.title, + place = forum.location, + desc = forum.content + ) + } + } + +// LazyColumn( +// modifier = Modifier, +// contentPadding = PaddingValues(vertical = 20.dp, horizontal = 16.dp), +// verticalArrangement = Arrangement.spacedBy(10.dp) +// ) { +// item { +// ForumBox( +// modifier = Modifier.fillMaxWidth(), +// title = "Cara Hidupkan HP Masuk Toilet", +// desc = "Jadi kemarin saya tidak sengaja menjatuhkan HP saya ke toilet", +// place = "Malang", +// photoUrl = R.drawable.img_forum_hp_nyala +// ) +// } +// +// item { +// ForumBox( +// modifier = Modifier.fillMaxWidth(), +// photoUrl = R.drawable.img_forum_laptop_bekas, +// onClick = navigateToSingleForum, +// title = "Jual Laptop Mati Total", +// desc = "Saya mempunyai laptop yang baru saja mati, pada saat tombol power tekan tidak ada respon apapun, kemungkinan masalah berada di battery. Selain itu kondisi masih bagus dan tidak ada kerusakan luar\nBagi yang berminat dapat mencoba menghubungi saya +6281396774583", +// place = "Yogyakarta" +// ) +// } +// } + } else { + Box( + modifier = Modifier + .fillMaxWidth() + .height(175.dp), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) + + ) { + Text( + text = "No forum to view", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + } + } } } @@ -214,7 +310,8 @@ fun ForumContent( fun ForumScreenPreview() { TechwasMark02Theme { ForumContent( - navigateToSingleForum = {} + navigateToSingleForum = {}, + forumListState = null ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreenViewModel.kt index 672d9b4..75f5abd 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreenViewModel.kt @@ -1,2 +1,29 @@ package com.capstone.techwasmark02.ui.screen.forum +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.data.remote.response.ForumResponse +import com.capstone.techwasmark02.repository.TechwasForumApiRepository +import com.capstone.techwasmark02.ui.common.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class ForumScreenViewModel @Inject constructor( + private val forumApiRepository: TechwasForumApiRepository +): ViewModel() { + + + private val _forumList: MutableStateFlow?> = MutableStateFlow(null) + val forumList = _forumList.asStateFlow() + + init { + viewModelScope.launch { + _forumList.value = forumApiRepository.fetchAllForum() + } + } + +} \ No newline at end of file From c498f4c58648b4f417d2783f16470c96346c437a Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Fri, 16 Jun 2023 17:14:00 +0700 Subject: [PATCH 68/73] Create single forum, search forum, filter forum --- app/src/main/AndroidManifest.xml | 1 + .../com/capstone/techwasmark02/TechwasApp.kt | 23 +- .../data/model/ForumCommentInfo.kt | 6 + .../data/model/ForumToCreateInfo.kt | 9 + .../data/remote/apiService/TechwasForumApi.kt | 26 + .../data/remote/response/ForumResponse.kt | 33 + .../repository/TechwasForumApiRepository.kt | 51 +- .../techwasmark02/ui/component/ForumBox.kt | 2 +- .../techwasmark02/ui/navigation/Screen.kt | 16 +- .../ui/screen/forum/ForumScreen.kt | 102 +-- .../ui/screen/forum/ForumScreenViewModel.kt | 9 +- .../screen/forumCreate/ForumCreateScreen.kt | 321 +++++++++ .../forumCreate/ForumCreateScreenViewModel.kt | 76 +++ .../screen/forumSingle/ForumSingleScreen.kt | 632 +++++++++++------- .../forumSingle/ForumSingleScreenViewModel.kt | 57 +- .../ui/screen/home/HomeScreen.kt | 162 ++--- .../ui/screen/home/HomeScreenViewModel.kt | 11 +- .../screen/profileUser/ProfileUserScreen.kt | 134 ++-- .../profileUser/ProfileUserScreenViewModel.kt | 10 +- 19 files changed, 1258 insertions(+), 423 deletions(-) create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/model/ForumCommentInfo.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/data/model/ForumToCreateInfo.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreen.kt create mode 100644 app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreenViewModel.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 28c17e6..3194540 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -28,6 +28,7 @@ tools:targetApi="31"> diff --git a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt index 9b3b5fa..d2255fc 100644 --- a/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt +++ b/app/src/main/java/com/capstone/techwasmark02/TechwasApp.kt @@ -1,6 +1,5 @@ package com.capstone.techwasmark02 -import androidx.activity.compose.BackHandler import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.core.tween @@ -12,6 +11,7 @@ import androidx.compose.ui.Modifier import androidx.navigation.NavType import androidx.navigation.navArgument import com.capstone.techwasmark02.ui.navigation.Screen.* +import com.capstone.techwasmark02.ui.screen.forumCreate.ForumCreateScreen import com.capstone.techwasmark02.ui.screen.article.ArticleScreen import com.capstone.techwasmark02.ui.screen.camera.CameraScreen import com.capstone.techwasmark02.ui.screen.catalog.CatalogScreen @@ -126,8 +126,25 @@ fun TechwasApp() { ForumScreen(navController = navController) } - composable(SingleForum.route) { - ForumSingleScreen(navController = navController) + composable( + route = SingleForum.route + "/{forumId}", + arguments = listOf( + navArgument("forumId") { + type = NavType.IntType + defaultValue = 1 + } + ) + ) { navBackStackEntry -> + val forumId = navBackStackEntry.arguments?.getInt("forumId") + if (forumId != null) { + ForumSingleScreen(navController = navController, forumId = forumId) + } + } + + composable( + route = CreateForum.route + ) { + ForumCreateScreen(navController = navController) } composable(Profile.route) { diff --git a/app/src/main/java/com/capstone/techwasmark02/data/model/ForumCommentInfo.kt b/app/src/main/java/com/capstone/techwasmark02/data/model/ForumCommentInfo.kt new file mode 100644 index 0000000..b6704a9 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/model/ForumCommentInfo.kt @@ -0,0 +1,6 @@ +package com.capstone.techwasmark02.data.model + +data class ForumCommentInfo( + val comment: String, + val forumID: Int +) \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/model/ForumToCreateInfo.kt b/app/src/main/java/com/capstone/techwasmark02/data/model/ForumToCreateInfo.kt new file mode 100644 index 0000000..e7f209a --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/data/model/ForumToCreateInfo.kt @@ -0,0 +1,9 @@ +package com.capstone.techwasmark02.data.model + +data class ForumToCreateInfo( + val category: String, + val content: String, + val imageUrl: String, + val location: String, + val title: String +) \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasForumApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasForumApi.kt index 642776f..d63b866 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasForumApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasForumApi.kt @@ -1,7 +1,15 @@ package com.capstone.techwasmark02.data.remote.apiService +import com.capstone.techwasmark02.data.model.ForumCommentInfo +import com.capstone.techwasmark02.data.model.ForumToCreateInfo +import com.capstone.techwasmark02.data.remote.response.CreateForumResponse +import com.capstone.techwasmark02.data.remote.response.ForumCommentResponse import com.capstone.techwasmark02.data.remote.response.ForumResponse +import com.capstone.techwasmark02.data.remote.response.PostForumCommentResponse +import retrofit2.http.Body import retrofit2.http.GET +import retrofit2.http.Header +import retrofit2.http.POST import retrofit2.http.Path interface TechwasForumApi { @@ -11,6 +19,7 @@ interface TechwasForumApi { @GET("/forum/id/{id}") suspend fun fetchForumById( + @Header("Authorization") token: String, @Path("id") id: Int ): ForumResponse @@ -19,6 +28,23 @@ interface TechwasForumApi { @Path("category") category: String ): ForumResponse + @POST("/forum/post") + suspend fun createNewForum( + @Header("Authorization") token: String, + @Body forumToCreateInfo: ForumToCreateInfo + ): CreateForumResponse + + @GET("/comments/byforumid/{forumid}") + suspend fun fetchForumComment( + @Path("forumid") forumid: Int + ): ForumCommentResponse + + @POST("/comments/post") + suspend fun postForumComment( + @Header("Authorization") token: String, + @Body forumCommentInfo: ForumCommentInfo + ): PostForumCommentResponse + companion object { const val BASE_URL = "https://backend-api-56g32wdmqa-uc.a.run.app/" } diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ForumResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ForumResponse.kt index 62973aa..2d914f2 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ForumResponse.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ForumResponse.kt @@ -18,4 +18,37 @@ data class Forum( val likes: Any, val location: String, val title: String +) + +data class ForumCommentResponse( + val article: List

, + val error: String, + val message: String +) + +data class Article( + val comment: String, + val forumID: Int, + val id: Int, + val replyFrom: Int, + val userID: String, + val username: String +) + +data class PostForumCommentResponse( + val commentInfo: CommentInfo, + val error: String, + val message: String +) + +data class CommentInfo( + val Poster: String, + val PosterID: Int, + val comment: String, + val forumID: Int +) + +data class CreateForumResponse( + val error: String, + val message: String ) \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt index 74ca2b1..ff110a4 100644 --- a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt @@ -1,10 +1,15 @@ package com.capstone.techwasmark02.repository +import com.capstone.techwasmark02.data.model.ForumCommentInfo +import com.capstone.techwasmark02.data.model.ForumToCreateInfo import com.capstone.techwasmark02.data.remote.apiService.TechwasForumApi +import com.capstone.techwasmark02.data.remote.response.CreateForumResponse +import com.capstone.techwasmark02.data.remote.response.ForumCommentResponse import com.capstone.techwasmark02.data.remote.response.ForumResponse +import com.capstone.techwasmark02.data.remote.response.PostForumCommentResponse import com.capstone.techwasmark02.ui.common.UiState -import java.lang.Exception import javax.inject.Inject +import kotlin.Exception class TechwasForumApiRepository @Inject constructor( private val forumApi: TechwasForumApi @@ -19,9 +24,14 @@ class TechwasForumApiRepository @Inject constructor( return UiState.Success(data = response, message = "Success to fetch forum") } - suspend fun fetchForumById(id: Int): UiState { + suspend fun fetchForumById(id: Int, userToken: String): UiState { + val token = "Bearer $userToken" + val response = try { - forumApi.fetchForumById(id) + forumApi.fetchForumById( + id = id, + token = token + ) } catch (e: Exception) { return UiState.Error(message = "fail to fetch forum, ${e.message}") } @@ -36,4 +46,39 @@ class TechwasForumApiRepository @Inject constructor( } return UiState.Success(data = response, message = response.message) } + + suspend fun fetchForumCommentByForumId(forumId: Int): UiState { + val response = try { + forumApi.fetchForumComment(forumid = forumId) + } catch (e: Exception) { + return UiState.Error(message = "fail to fetch comment, ${e.message}") + } + return UiState.Success(data = response, message = response.message) + } + + suspend fun postForumComment(forumCommentInfo: ForumCommentInfo, userToken: String): UiState { + val token = "Bearer $userToken" + + val response = try { + forumApi.postForumComment( + token, + forumCommentInfo, + ) + } catch (e: Exception) { + return UiState.Error(message = "fail to post comment, ${e.message}") + } + return UiState.Success(data = response, message = response.message) + } + + suspend fun createNewForum(forumToCreateInfo: ForumToCreateInfo, userToken: String): UiState { + val token = "Bearer $userToken" + + val response = try { + forumApi.createNewForum(forumToCreateInfo = forumToCreateInfo, token = token) + } catch (e: Exception) { + return UiState.Error(message = e.message ?: "Fail to create new forum") + } + return UiState.Success(data = response, message = response.message) + } + } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt index 0f480a1..3e87a7a 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ForumBox.kt @@ -38,7 +38,7 @@ import kotlin.random.Random @Composable fun ForumBox( modifier: Modifier = Modifier, - photoUrl: Int? = null, + photoUrl: String? = null, onClick: () -> Unit = {}, title: String, place: String, diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt index caa872d..9312814 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/navigation/Screen.kt @@ -107,7 +107,7 @@ sealed class Screen constructor(val route: String, val enterTransition: (Animat slideOutOfContainer( AnimatedContentScope.SlideDirection.Left, animationSpec = tween( durationMillis = 700, - ) + ) ) } ) @@ -129,6 +129,20 @@ sealed class Screen constructor(val route: String, val enterTransition: (Animat } ) + object CreateForum: Screen( + route = "CreateForum", + enterTransition = { + fadeIn( + animationSpec = tween(700) + ) + }, + exitTransition = { + fadeOut( + animationSpec = tween(700) + ) + } + ) + object Profile: Screen( route = "profile", enterTransition = { diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt index 95b59d6..0d7f3f6 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt @@ -1,5 +1,6 @@ package com.capstone.techwasmark02.ui.screen.forum +import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable @@ -28,6 +29,7 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -44,6 +46,7 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import com.capstone.techwasmark02.R +import com.capstone.techwasmark02.data.remote.response.Forum import com.capstone.techwasmark02.data.remote.response.ForumResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.ForumBox @@ -59,21 +62,25 @@ fun ForumScreen( viewModel: ForumScreenViewModel = hiltViewModel() ) { val forumListState by viewModel.forumList.collectAsState() + val searchBoxValue by viewModel.searchBoxValue.collectAsState() ForumContent( - navigateToSingleForum = { navController.navigate(Screen.SingleForum.route)}, - forumListState = forumListState + navigateToSingleForum = { navController.navigate("${Screen.SingleForum.route}/$it")}, + forumListState = forumListState, + navigateToCreateForum = { navController.navigate(Screen.CreateForum.route)}, + searchBoxValue = searchBoxValue, + onSearchBoxValueChange = { viewModel.updateSearchBoxValue(it)} ) } @Composable fun ForumContent( - navigateToSingleForum: () -> Unit, - forumListState: UiState? + navigateToSingleForum: (Int) -> Unit, + forumListState: UiState?, + navigateToCreateForum: () -> Unit, + searchBoxValue: String, + onSearchBoxValueChange: (String) -> Unit ) { - var inputValue by remember { - mutableStateOf("") - } val filterTypeList = listOf( ArticleFilterType.General, @@ -145,7 +152,7 @@ fun ForumContent( .padding(top = 8.dp, end = 8.dp) ) { IconButton( - onClick = { /*TODO*/ }, + onClick = navigateToCreateForum, modifier = Modifier .size(36.dp) .clip(CircleShape) @@ -163,8 +170,8 @@ fun ForumContent( Spacer(modifier = Modifier.height(16.dp)) SearchBox( - value = inputValue, - onValueChange = {}, + value = searchBoxValue, + onValueChange = onSearchBoxValueChange, ) Spacer(modifier = Modifier.height(16.dp)) @@ -195,7 +202,8 @@ fun ForumContent( is UiState.Loading -> { Box( modifier = Modifier - .fillMaxSize(), + .fillMaxWidth() + .weight(1f), contentAlignment = Alignment.Center ) { CircularProgressIndicator() @@ -229,49 +237,40 @@ fun ForumContent( is UiState.Success -> { val currentForumList = forumListState.data?.forum - if (!currentForumList.isNullOrEmpty() && currentForumList.isNotEmpty()) { + var filteredForumList by remember { + mutableStateOf(currentForumList) + } + + LaunchedEffect(key1 = searchBoxValue, key2 = selectedFilter) { + if (currentForumList != null) { + filteredForumList = selectedFilter?.type?.let { + searchForum( + forumList = currentForumList, + searchBoxValue = searchBoxValue, + selectedFilter = it + ) + } + } + } + + if (!filteredForumList.isNullOrEmpty() && filteredForumList!!.isNotEmpty()) { LazyColumn( modifier = Modifier, contentPadding = PaddingValues(vertical = 20.dp, horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(10.dp) ) { - items(currentForumList) { forum -> + items(filteredForumList!!) { forum -> ForumBox( modifier = Modifier .fillMaxWidth(), title = forum.title, place = forum.location, - desc = forum.content + desc = forum.content, + onClick = { navigateToSingleForum(forum.id) }, + photoUrl = forum.imageURL ) } } - -// LazyColumn( -// modifier = Modifier, -// contentPadding = PaddingValues(vertical = 20.dp, horizontal = 16.dp), -// verticalArrangement = Arrangement.spacedBy(10.dp) -// ) { -// item { -// ForumBox( -// modifier = Modifier.fillMaxWidth(), -// title = "Cara Hidupkan HP Masuk Toilet", -// desc = "Jadi kemarin saya tidak sengaja menjatuhkan HP saya ke toilet", -// place = "Malang", -// photoUrl = R.drawable.img_forum_hp_nyala -// ) -// } -// -// item { -// ForumBox( -// modifier = Modifier.fillMaxWidth(), -// photoUrl = R.drawable.img_forum_laptop_bekas, -// onClick = navigateToSingleForum, -// title = "Jual Laptop Mati Total", -// desc = "Saya mempunyai laptop yang baru saja mati, pada saat tombol power tekan tidak ada respon apapun, kemungkinan masalah berada di battery. Selain itu kondisi masih bagus dan tidak ada kerusakan luar\nBagi yang berminat dapat mencoba menghubungi saya +6281396774583", -// place = "Yogyakarta" -// ) -// } -// } } else { Box( modifier = Modifier @@ -305,13 +304,32 @@ fun ForumContent( } } +private fun searchForum(forumList: List, searchBoxValue: String, selectedFilter: String): List { + if (searchBoxValue == "" && selectedFilter == "General") { + return forumList + } + + val searchBoxFilter = forumList.filter { forum -> + forum.title.contains(searchBoxValue, ignoreCase = true) + } + + val selectedFilterList = searchBoxFilter.filter { forum -> + forum.category == selectedFilter + } + + return selectedFilterList +} + @Preview @Composable fun ForumScreenPreview() { TechwasMark02Theme { ForumContent( navigateToSingleForum = {}, - forumListState = null + forumListState = null, + navigateToCreateForum = {}, + searchBoxValue = "", + onSearchBoxValueChange = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreenViewModel.kt index 75f5abd..6afb7dc 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreenViewModel.kt @@ -16,11 +16,18 @@ class ForumScreenViewModel @Inject constructor( private val forumApiRepository: TechwasForumApiRepository ): ViewModel() { - private val _forumList: MutableStateFlow?> = MutableStateFlow(null) val forumList = _forumList.asStateFlow() + private val _searchBoxValue: MutableStateFlow = MutableStateFlow("") + val searchBoxValue = _searchBoxValue.asStateFlow() + + fun updateSearchBoxValue(newValue: String) { + _searchBoxValue.value = newValue + } + init { + _forumList.value = UiState.Loading() viewModelScope.launch { _forumList.value = forumApiRepository.fetchAllForum() } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreen.kt new file mode 100644 index 0000000..34685a7 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreen.kt @@ -0,0 +1,321 @@ +package com.capstone.techwasmark02.ui.screen.forumCreate + +import android.widget.Toast +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.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ElevatedButton +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavHostController +import com.capstone.techwasmark02.data.model.ForumToCreateInfo +import com.capstone.techwasmark02.data.remote.response.CreateForumResponse +import com.capstone.techwasmark02.ui.common.UiState +import com.capstone.techwasmark02.ui.component.DefaultTopBar +import com.capstone.techwasmark02.ui.component.SelectableText +import com.capstone.techwasmark02.ui.componentType.ArticleFilterType +import com.capstone.techwasmark02.ui.navigation.Screen +import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme + +@Composable +fun ForumCreateScreen( + navController: NavHostController, + viewModel: ForumCreateScreenViewModel = hiltViewModel() +) { + + val forumToCreateInfo by viewModel.forumToCreateInfo.collectAsState() + val createForumState by viewModel.createForumState.collectAsState() + + ForumCreateContent( + navigateBackToForum = {navController.navigate("${Screen.Main.route}/1")}, + forumToCreateInfo = forumToCreateInfo, + updateForumToCreateInfo = { viewModel.updateForumToCreateInfo(it) }, + createForumState = createForumState, + createNewForum = { viewModel.createNewForum() } + ) +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ForumCreateContent( + navigateBackToForum: () -> Unit, + forumToCreateInfo: ForumToCreateInfo, + updateForumToCreateInfo: (ForumToCreateInfo) -> Unit, + createForumState: UiState?, + createNewForum: () -> Unit +) { + + val filterTypeList = listOf( + ArticleFilterType.Battery, + ArticleFilterType.Cable, + ArticleFilterType.CrtTv, + ArticleFilterType.EKettle, + ArticleFilterType.Refrigerator, + ArticleFilterType.Keyboard, + ArticleFilterType.Laptop, + ArticleFilterType.LightBulb, + ArticleFilterType.Monitor, + ArticleFilterType.Mouse, + ArticleFilterType.PCB, + ArticleFilterType.Printer, + ArticleFilterType.RiceCooker, + ArticleFilterType.WashingMachine, + ArticleFilterType.Phone + ) + + var selectedFilter by remember { + mutableStateOf(filterTypeList.first()) + } + + val scrollState = rememberScrollState() + + LaunchedEffect(key1 = selectedFilter) { + selectedFilter.type.let { + forumToCreateInfo.copy( + category = it + ) + }.let { updateForumToCreateInfo(it) } + } + + + Box( + modifier = Modifier + .fillMaxSize() + ) { + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(scrollState) + ) { + Column( + modifier = Modifier + .padding(top = 88.dp) + .padding(horizontal = 16.dp) + ) { + Text( + text = "E-waste picture", + style = MaterialTheme.typography.labelLarge.copy( + fontWeight = FontWeight.SemiBold + ) + ) + + Spacer(modifier = Modifier.height(8.dp)) + + Box( + modifier = Modifier + .fillMaxWidth() + .height(240.dp) + .padding(8.dp) + .clip(RoundedCornerShape(20.dp)) + .background(Color.LightGray) + ) { + + } + + Spacer(modifier = Modifier.height(16.dp)) + + Text( + text = "E-waste category", + style = MaterialTheme.typography.labelLarge.copy( + fontWeight = FontWeight.SemiBold + ), + ) + } + + LazyRow( + modifier = Modifier.height(48.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + contentPadding = PaddingValues(horizontal = 16.dp) + ) { + items( + items = filterTypeList, + ) { item -> + SelectableText( + filterType = item, + selected = item == selectedFilter, + modifier = Modifier, + onClick = { + selectedFilter = item + } + ) + } + } + + Column( + modifier = Modifier + .padding(horizontal = 16.dp) + .padding(bottom = 80.dp) + ) { + Spacer(modifier = Modifier.height(16.dp)) + + Text( + text = "Forum title", + style = MaterialTheme.typography.labelLarge.copy( + fontWeight = FontWeight.SemiBold + ) + ) + + TextField( + value = forumToCreateInfo.title, + onValueChange = { newValue -> + updateForumToCreateInfo(forumToCreateInfo.copy( + title = newValue + )) + }, + modifier = Modifier + .fillMaxWidth(), + colors = TextFieldDefaults.textFieldColors( + containerColor = Color.Transparent, + ) + ) + + Spacer(modifier = Modifier.height(16.dp)) + + Text( + text = "Location", + style = MaterialTheme.typography.labelLarge.copy( + fontWeight = FontWeight.SemiBold + ) + ) + + TextField( + value = forumToCreateInfo.location, + onValueChange = { newValue -> + updateForumToCreateInfo(forumToCreateInfo.copy( + location = newValue + )) + }, + modifier = Modifier + .fillMaxWidth(), + colors = TextFieldDefaults.textFieldColors( + containerColor = Color.Transparent, + ) + ) + + Spacer(modifier = Modifier.height(16.dp)) + + Text( + text = "Forum Description", + style = MaterialTheme.typography.labelLarge.copy( + fontWeight = FontWeight.SemiBold + ) + ) + + TextField( + value = forumToCreateInfo.content, + onValueChange = { newValue -> + updateForumToCreateInfo(forumToCreateInfo.copy( + content = newValue + )) + }, + modifier = Modifier + .fillMaxWidth(), + colors = TextFieldDefaults.textFieldColors( + containerColor = Color.Transparent, + ) + ) + } + } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(bottom = 8.dp), + verticalArrangement = Arrangement.SpaceBetween + ) { + DefaultTopBar(onClickNavigationIcon = navigateBackToForum, pageTitle = "Create New Forum") + + Column( + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + ) { + ElevatedButton( + onClick = createNewForum , + modifier = Modifier + .fillMaxWidth() + .height(56.dp), + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primary, + contentColor = MaterialTheme.colorScheme.onPrimary + ), + ) { + val context = LocalContext.current + + if (createForumState != null) { + when(createForumState) { + is UiState.Error -> { + Toast.makeText(context, "Fail to create new forum", Toast.LENGTH_SHORT).show() + } + is UiState.Loading -> { + CircularProgressIndicator() + } + is UiState.Success -> { + navigateBackToForum() + } + } + } else { + Text( + text = "Create Forum", + style = MaterialTheme.typography.labelLarge + ) + } + } + } + } + } +} + +@Preview (showBackground = true) +@Composable +fun ForumCreateScreenPreview() { + TechwasMark02Theme { + ForumCreateContent( + navigateBackToForum = {}, + forumToCreateInfo = ForumToCreateInfo( + category = "", + content = "", + imageUrl = "", + location = "", + title = "" + ), + updateForumToCreateInfo = {}, + createForumState = null, + createNewForum = {} + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreenViewModel.kt new file mode 100644 index 0000000..e9d7995 --- /dev/null +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreenViewModel.kt @@ -0,0 +1,76 @@ +package com.capstone.techwasmark02.ui.screen.forumCreate + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.capstone.techwasmark02.common.Resource +import com.capstone.techwasmark02.data.model.ForumToCreateInfo +import com.capstone.techwasmark02.data.model.UserSession +import com.capstone.techwasmark02.data.remote.response.CreateForumResponse +import com.capstone.techwasmark02.data.remote.response.Token +import com.capstone.techwasmark02.data.remote.response.UserId +import com.capstone.techwasmark02.repository.PreferencesRepository +import com.capstone.techwasmark02.repository.TechwasForumApiRepository +import com.capstone.techwasmark02.ui.common.UiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class ForumCreateScreenViewModel @Inject constructor( + private val forumApiRepository: TechwasForumApiRepository, + private val preferencesRepository: PreferencesRepository +): ViewModel() { + + private val _userSessionState: MutableStateFlow = MutableStateFlow(null) + val userSessionState = _userSessionState.asStateFlow() + + private val _createForumState: MutableStateFlow?> = MutableStateFlow(null) + val createForumState = _createForumState.asStateFlow() + + private val _forumToCreateInfo: MutableStateFlow = MutableStateFlow( + ForumToCreateInfo( + category = "Mouse", + content = "", + imageUrl = "", + location = "", + title = "" + ) + ) + val forumToCreateInfo = _forumToCreateInfo.asStateFlow() + + fun updateForumToCreateInfo(forumToCreateInfo: ForumToCreateInfo) { + _forumToCreateInfo.value = forumToCreateInfo + } + + fun createNewForum() { + _createForumState.value = UiState.Loading() + viewModelScope.launch { + _createForumState.value = _userSessionState.value?.userLoginToken?.accessToken?.let { + forumApiRepository.createNewForum( + forumToCreateInfo = _forumToCreateInfo.value, + userToken = it + ) + } + } + } + + init { + viewModelScope.launch { + val result = preferencesRepository.getActiveSession() + when(result) { + is Resource.Error -> { + _userSessionState.value = UserSession( + userLoginToken = Token(accessToken = ""), + userNameId = UserId(username = "", id = 0) + ) + } + is Resource.Success -> { + _userSessionState.value = result.data + } + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt index e4d8c8e..e0ff6f0 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt @@ -1,5 +1,7 @@ package com.capstone.techwasmark02.ui.screen.forumSingle +import android.widget.Toast +import androidx.activity.compose.BackHandler import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -13,10 +15,14 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape @@ -46,16 +52,23 @@ import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.DefaultShadowColor import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.min import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController +import coil.compose.AsyncImage import com.capstone.techwasmark02.R import com.capstone.techwasmark02.data.model.UserSession +import com.capstone.techwasmark02.data.remote.response.ForumCommentResponse +import com.capstone.techwasmark02.data.remote.response.ForumResponse +import com.capstone.techwasmark02.data.remote.response.PostForumCommentResponse import com.capstone.techwasmark02.data.remote.response.Token import com.capstone.techwasmark02.data.remote.response.UserId +import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.DefaultTopBar import com.capstone.techwasmark02.ui.component.TransparentTopBar import com.capstone.techwasmark02.ui.navigation.Screen @@ -64,24 +77,52 @@ import com.capstone.techwasmark02.ui.theme.Mist97 import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import kotlin.io.path.fileVisitor @Composable fun ForumSingleScreen( viewModel: ForumSingleScreenViewModel = hiltViewModel(), - navController: NavHostController + navController: NavHostController, + forumId: Int ) { val userSession by viewModel.userSessionState.collectAsState() + val forumState by viewModel.forumState.collectAsState() + val forumCommentState by viewModel.forumCommentState.collectAsState() + val postingCommentState by viewModel.postingCommentState.collectAsState() + + LaunchedEffect(Unit) { + viewModel.fetchForumById(id = forumId,) + viewModel.fetchForumCommentByForumId(forumId) + } + + BackHandler(true) { + navController.navigate("${Screen.Main.route}/1") + } ForumSingleContent( userSession = userSession, - navigateBackToForum = { navController.navigate("${Screen.Main.route}/1") } + navigateBackToForum = { navController.navigate("${Screen.Main.route}/1") }, + forumState = forumState, + forumCommentState = forumCommentState, + fetchForumComment = { viewModel.fetchForumCommentByForumId(it)}, + forumId = forumId, + postForumComment = { comment, currentForumId -> viewModel.postForumComment(comment, currentForumId)}, + postingCommentState = postingCommentState, + clearPostingCommentState = { viewModel.clearPostingCommentState()} ) } @Composable fun ForumSingleContent( userSession: UserSession?, - navigateBackToForum: () -> Unit + navigateBackToForum: () -> Unit, + forumState: UiState?, + forumCommentState: UiState?, + fetchForumComment: (Int) -> Unit, + forumId: Int, + postForumComment: (comment: String, currentForumId: Int) -> Unit, + postingCommentState: UiState?, + clearPostingCommentState: () -> Unit ) { Box( modifier = Modifier @@ -97,263 +138,387 @@ fun ForumSingleContent( mutableStateOf("") } - var commentPosted by remember { - mutableStateOf(false) + var firstRender by remember { + mutableStateOf(true) } - var showLastComment by remember { - mutableStateOf(false) - } - - var lastCommentText by remember { - mutableStateOf("") - } - - fun postLastComment() { - coroutineScope.launch { - commentPosted = true - delay(2000) - lastCommentText = commentText - commentPosted = false - commentText = "" - showLastComment = true - } - } - - LaunchedEffect(key1 = showLastComment) { - if (showLastComment) { +// var commentPosted by remember { +// mutableStateOf(false) +// } +// +// var showLastComment by remember { +// mutableStateOf(false) +// } +// +// var lastCommentText by remember { +// mutableStateOf("") +// } +// +//// fun postLastComment() { +//// coroutineScope.launch { +//// +//// +//// commentPosted = true +//// delay(2000) +//// lastCommentText = commentText +//// commentPosted = false +//// commentText = "" +//// showLastComment = true +//// } +//// } + + LaunchedEffect(key1 = forumCommentState) { + if (!firstRender) { scrollState.animateScrollTo(scrollState.maxValue) } } - Column( - modifier = Modifier - .fillMaxSize() - .verticalScroll(scrollState) - ) { - Box( - modifier = Modifier - .fillMaxWidth() - .height(360.dp) -// .height(100.dp) - .clip(RoundedCornerShape(bottomEnd = 20.dp, bottomStart = 20.dp)) - .background(MaterialTheme.colorScheme.primary) - ) { - Image( - painter = painterResource(id = R.drawable.img_forum_laptop_bekas), - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier - .fillMaxSize() - ) - } - - Column( - modifier = Modifier - .padding(horizontal = 16.dp, vertical = 24.dp) - ) { - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = "Yogyakarta", - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.8f) - ) - Text( - text = "Laptop", - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.8f) - ) + if (forumState != null) { + when(forumState) { + is UiState.Loading -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(360.dp), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } } + is UiState.Error -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(360.dp), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) - Spacer(modifier = Modifier.height(4.dp)) - - Text( - text = "Jual Laptop Mati Total", - style = MaterialTheme.typography.titleMedium - ) - - Spacer(modifier = Modifier.height(10.dp)) - - Text( - text = "Saya mempunyai laptop yang baru saja mati, pada saat tombol power tekan tidak ada respon apapun, kemungkinan masalah berada di battery. Selain itu kondisi masih bagus dan tidak ada kerusakan luar\nBagi yang berminat dapat mencoba menghubungi saya +6281396774583", - style = MaterialTheme.typography.bodyMedium.copy( - fontWeight = FontWeight.Medium - ) - ) - - } - - Column( - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.tertiary) - .padding(top = 24.dp, bottom = 72.dp) - ) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 16.dp) - ) { - Text( - text = "Comment", - style = MaterialTheme.typography.labelLarge - ) - - Spacer(modifier = Modifier.height(10.dp)) - - UserInComment( - username = "Sesar Dito", - comment = "Ga minat beli, tapi pengen kenalan", - photoUrl = R.drawable.img_user_2 - ) - - Spacer(modifier = Modifier.height(8.dp)) + ) { + Text( + text = "Failed to fetch forum", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + } + is UiState.Success -> { + val currentForum = forumState.data?.forum?.get(0) - Row( + Column( modifier = Modifier - .fillMaxWidth() - .height(IntrinsicSize.Max) + .fillMaxSize() + .verticalScroll(scrollState) ) { Box( modifier = Modifier - .width(60.dp) - .fillMaxHeight(), - contentAlignment = Alignment.Center + .fillMaxWidth() + .height(360.dp) +// .height(100.dp) + .clip(RoundedCornerShape(bottomEnd = 20.dp, bottomStart = 20.dp)) + .background(MaterialTheme.colorScheme.primary) ) { - Box( + AsyncImage( + model = currentForum?.imageURL, + contentDescription = null, + contentScale = ContentScale.Crop, modifier = Modifier - .fillMaxHeight() - .width(2.dp) + .fillMaxSize() .background(Color.LightGray) ) +// Image( +// painter = painterResource(id = R.drawable.img_forum_laptop_bekas), +// contentDescription = null, +// contentScale = ContentScale.Crop, +// modifier = Modifier +// .fillMaxSize() +// ) } - Spacer(modifier = Modifier.width(16.dp)) - - Column { - UserInComment( - username = "Ong Gabriel", - comment = "Sama aku saja", - photoUrl = R.drawable.img_user_3 - ) - - Spacer(modifier = Modifier.height(8.dp)) + Column( + modifier = Modifier + .padding(horizontal = 16.dp) + .padding(top = 24.dp, bottom = 8.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + currentForum?.location?.let { + Text( + text = it, + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.8f) + ) + } + currentForum?.category?.let { + Text( + text = it, + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.8f) + ) + } + } + + Spacer(modifier = Modifier.height(4.dp)) + + currentForum?.title?.let { + Text( + text = it, + style = MaterialTheme.typography.titleMedium + ) + } + + Spacer(modifier = Modifier.height(10.dp)) + + currentForum?.content?.let { + Text( + text = it, + style = MaterialTheme.typography.bodyMedium.copy( + fontWeight = FontWeight.Medium + ) + ) + } - UserInComment( - username = "Dwi Nugroho", - comment = "Tolong jaga sikap", - photoUrl = R.drawable.img_user_4 - ) } - } - Spacer(modifier = Modifier.height(10.dp)) - - Text( - text = "Reply", - style = MaterialTheme.typography.bodySmall.copy( - fontWeight = FontWeight.Bold - ), - color = MaterialTheme.colorScheme.primary, - modifier = Modifier - .padding(start = 30.dp) - ) - - Spacer(modifier = Modifier.height(24.dp)) - - if (showLastComment && userSession != null) { - UserInComment( - username = userSession.userNameId.username, - comment = lastCommentText, - photoUrl = R.drawable.img_user_1 - ) - - Spacer(modifier = Modifier.height(10.dp)) + if (forumCommentState != null) { + when(forumCommentState) { + is UiState.Loading -> { + Box( + modifier = Modifier + .fillMaxWidth() + .weight(1f), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is UiState.Error -> { + Box( + modifier = Modifier + .fillMaxWidth() + .weight(1f), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) + + ) { + Text( + text = "Failed to fetch comment", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + } + is UiState.Success -> { + val commentList = forumCommentState.data?.article + + if (commentList != null) { + Column( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.tertiary) + .padding(top = 8.dp, bottom = 72.dp) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + ) { + Text( + text = "Comment", + style = MaterialTheme.typography.labelLarge + ) + + Spacer(modifier = Modifier.height(10.dp)) + + if (commentList != null) { + Column( + modifier = Modifier + .padding(bottom = 16.dp) + .widthIn(), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + if (commentList.isNotEmpty()) { + commentList.forEach { comment -> + UserInComment( + username = comment.username, + comment = comment.comment, + photoUrl = R.drawable.img_user_2 + ) + + Text( + text = "Reply", + style = MaterialTheme.typography.bodySmall.copy( + fontWeight = FontWeight.Bold + ), + color = MaterialTheme.colorScheme.primary, + modifier = Modifier + .padding(start = 30.dp) + ) + } + } + } + } + } + } + } else { + Column( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(MaterialTheme.colorScheme.tertiary) + ) { + Text( + text = "Comment", + style = MaterialTheme.typography.labelLarge, + modifier = Modifier + .padding(top = 8.dp) + .padding(horizontal = 16.dp) + ) + } + } + } + } + } - Text( - text = "Reply", - style = MaterialTheme.typography.bodySmall.copy( - fontWeight = FontWeight.Bold - ), - color = MaterialTheme.colorScheme.primary, - modifier = Modifier - .padding(start = 30.dp) - ) - Spacer(modifier = Modifier.height(24.dp)) } - } - } - } - - Column( - modifier = Modifier - .fillMaxSize(), - verticalArrangement = Arrangement.Bottom - ) { - Box( - modifier = Modifier - .fillMaxWidth() - .height(2.dp) - .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.5f)) - ) - - Row( - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.tertiary) - .padding(top = 10.dp, bottom = 10.dp, start = 16.dp, end = 20.dp), - verticalAlignment = Alignment.CenterVertically - ) { - - if (commentPosted) { - Box( + Column( modifier = Modifier - .weight(1f) - .height(56.dp) - .border( - width = 2.dp, - color = MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.6f), - shape = RoundedCornerShape(20.dp) - ), - contentAlignment = Alignment.Center + .fillMaxSize(), + verticalArrangement = Arrangement.Bottom ) { - CircularProgressIndicator( + + Box( modifier = Modifier - .size(24.dp) + .fillMaxWidth() + .height(2.dp) + .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.5f)) ) - } - } else { - CommentTextField( - value = commentText, - onValueChange = { newValue -> - commentText = newValue - }, - modifier = Modifier - .weight(1f) - ) - } - Spacer(modifier = Modifier.width(10.dp)) - - IconButton( - onClick = { postLastComment() }, - modifier = Modifier - .size(36.dp) - .clip(CircleShape) - .background(MaterialTheme.colorScheme.primary) - ) { - Icon( - painter = painterResource(id = R.drawable.ic_create), - contentDescription = null, - tint = MaterialTheme.colorScheme.onPrimary - ) + Row( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.tertiary) + .padding(top = 10.dp, bottom = 10.dp, start = 16.dp, end = 20.dp), + verticalAlignment = Alignment.CenterVertically + ) { + + if (postingCommentState != null) { + when(postingCommentState) { + is UiState.Success -> { + clearPostingCommentState() + firstRender = false + LaunchedEffect(Unit) { + fetchForumComment(forumId) + } + } + is UiState.Loading -> { + Box( + modifier = Modifier + .weight(1f) + .height(56.dp) + .border( + width = 2.dp, + color = MaterialTheme.colorScheme.onTertiary.copy( + alpha = 0.6f + ), + shape = RoundedCornerShape(20.dp) + ), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + modifier = Modifier + .size(24.dp) + ) + } + } + is UiState.Error -> { + val context = LocalContext.current + Toast.makeText(context, "Fail to post comment", Toast.LENGTH_SHORT).show() + clearPostingCommentState() + } + } + } else { + CommentTextField( + value = commentText, + onValueChange = { newValue -> + commentText = newValue + }, + modifier = Modifier + .weight(1f) + ) + } + +// if (commentPosted) { +// Box( +// modifier = Modifier +// .weight(1f) +// .height(56.dp) +// .border( +// width = 2.dp, +// color = MaterialTheme.colorScheme.onTertiary.copy(alpha = 0.6f), +// shape = RoundedCornerShape(20.dp) +// ), +// contentAlignment = Alignment.Center +// ) { +// CircularProgressIndicator( +// modifier = Modifier +// .size(24.dp) +// ) +// } +// } else { +// CommentTextField( +// value = commentText, +// onValueChange = { newValue -> +// commentText = newValue +// }, +// modifier = Modifier +// .weight(1f) +// ) +// } + + Spacer(modifier = Modifier.width(10.dp)) + + IconButton( + onClick = { + postForumComment( commentText, forumId) + commentText = "" + }, + modifier = Modifier + .size(36.dp) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.primary) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_create), + contentDescription = null, + tint = MaterialTheme.colorScheme.onPrimary + ) + } + } + } } } } @@ -391,7 +556,14 @@ fun ForumSingleScreenPreview() { accessToken = "" ) ), - navigateBackToForum = {} + navigateBackToForum = {}, + forumState = null, + forumCommentState = null, + fetchForumComment = {}, + forumId = 0, + postingCommentState = null, + postForumComment = {comment: String, currentForumId: Int -> {}}, + clearPostingCommentState = {} ) } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreenViewModel.kt index a4931e7..2c79914 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreenViewModel.kt @@ -3,10 +3,16 @@ package com.capstone.techwasmark02.ui.screen.forumSingle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.capstone.techwasmark02.common.Resource +import com.capstone.techwasmark02.data.model.ForumCommentInfo import com.capstone.techwasmark02.data.model.UserSession +import com.capstone.techwasmark02.data.remote.response.ForumCommentResponse +import com.capstone.techwasmark02.data.remote.response.ForumResponse +import com.capstone.techwasmark02.data.remote.response.PostForumCommentResponse import com.capstone.techwasmark02.data.remote.response.Token import com.capstone.techwasmark02.data.remote.response.UserId import com.capstone.techwasmark02.repository.PreferencesRepository +import com.capstone.techwasmark02.repository.TechwasForumApiRepository +import com.capstone.techwasmark02.ui.common.UiState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -15,12 +21,61 @@ import javax.inject.Inject @HiltViewModel class ForumSingleScreenViewModel @Inject constructor( - private val preferencesRepository: PreferencesRepository + private val preferencesRepository: PreferencesRepository, + private val forumApiRepository: TechwasForumApiRepository ): ViewModel() { private val _userSessionState: MutableStateFlow = MutableStateFlow(null) val userSessionState = _userSessionState.asStateFlow() + private val _forumState: MutableStateFlow?> = MutableStateFlow(null) + val forumState = _forumState.asStateFlow() + + private val _forumCommentState: MutableStateFlow?> = MutableStateFlow(null) + val forumCommentState = _forumCommentState.asStateFlow() + + private val _postingCommentState: MutableStateFlow?> = MutableStateFlow(null) + val postingCommentState = _postingCommentState.asStateFlow() + + fun fetchForumById(id: Int) { + _forumState.value = UiState.Loading() + viewModelScope.launch { + _forumState.value = _userSessionState.value?.userLoginToken?.accessToken?.let { + forumApiRepository.fetchForumById( + id = id, + userToken = it + ) + } + } + } + + fun fetchForumCommentByForumId(forumId: Int) { + _forumCommentState.value = UiState.Loading() + viewModelScope.launch { + _forumCommentState.value = forumApiRepository.fetchForumCommentByForumId(forumId) + } + } + + fun postForumComment(comment: String, forumId: Int) { + _postingCommentState.value = UiState.Loading() + val forumCommentInfo = ForumCommentInfo( + comment = comment, + forumID = forumId + ) + viewModelScope.launch { + _userSessionState.value?.userLoginToken?.accessToken?.let { + _postingCommentState.value = forumApiRepository.postForumComment( + forumCommentInfo = forumCommentInfo, + userToken = it + ) + } + } + } + + fun clearPostingCommentState() { + _postingCommentState.value = null + } + init { viewModelScope.launch { val result = preferencesRepository.getActiveSession() diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index d99d6e4..3906167 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -10,6 +10,7 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -26,6 +27,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState @@ -58,6 +60,7 @@ import androidx.navigation.NavHostController import com.capstone.techwasmark02.R import com.capstone.techwasmark02.data.remote.response.ArticleList import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.data.remote.response.ForumResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.ArticleCardBig import com.capstone.techwasmark02.ui.component.FeatureBox @@ -83,17 +86,21 @@ fun HomeScreen( ) { val latestArticleState by viewModel.latestArticleState.collectAsState() + val forumList by viewModel.forumList.collectAsState() HomeContent( navigateToCamera = { navController.navigate(Camera.route) }, navigateToHome = { navController.navigate(Home.route) }, - navigateToArticle = { navController.navigate(Article.route) }, + navigateToArticle = { navController.navigate("${Screen.Main.route}/2") }, navigateToForum = { navController.navigate(Forum.route) }, navigateToProfile = { navController.navigate(Profile.route) }, navigateToCatalog = { navController.navigate(Catalog.route) }, navigateToMaps = { navController.navigate(Maps.route) }, navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") }, - latestArticleState = latestArticleState + latestArticleState = latestArticleState, + forumList = forumList, + navigateToSingleForum = { navController.navigate("${Screen.SingleForum.route}/$it")}, + navigateToMain = { navController.navigate("${Screen.Main.route}/1") } ) } @@ -108,7 +115,10 @@ fun HomeContent( navigateToCatalog: () -> Unit, navigateToMaps: () -> Unit, navigateToSingleArticle: (idArticle: Int) -> Unit, - latestArticleState: UiState? + latestArticleState: UiState?, + forumList: UiState?, + navigateToSingleForum: (Int) -> Unit, + navigateToMain: () -> Unit ) { val context = LocalContext.current @@ -271,7 +281,7 @@ fun HomeContent( color = yellow, modifier = Modifier .clickable { - navigateToArticle() + navigateToForum() } ) } @@ -391,91 +401,84 @@ fun HomeContent( text = "See all", style = MaterialTheme.typography.labelMedium, fontWeight = FontWeight.Bold, - color = yellow + color = yellow, + modifier = Modifier + .clickable { + navigateToArticle() + } ) } Spacer(modifier = Modifier.height(titlePaddingBottom)) - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 16.dp), - verticalArrangement = Arrangement.spacedBy(10.dp), - contentPadding = PaddingValues( bottom = 16.dp) - ) { - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Jual Laptop Mati Total", - desc = "\"Saya mempunyai laptop yang baru saja mati, pada saat tombol power tekan tidak ada respon apapun, kemungkinan masalah berada di battery. Selain itu kondisi masih bagus dan tidak ada kerusakan luar\\nBagi yang berminat dapat mencoba menghubungi saya +6281396774583\"", - place = "Yogyakarta", - photoUrl = R.drawable.img_forum_laptop_bekas - ) - } - - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Cara Hidupkan Hape Xiomi Lama", - desc = "Tiga belas hari yang lalu jatuh dari motor dan hp saya ikut jatuh dan terbentur", - place = "Merauke" - ) - } - - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Bagaiamana Cara Menyambung Kabel", - desc = "Saya akan memberikan langkah-langkah mudah untuk menyambung kabel elektronik", - place = "Solo" - ) - } - - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Dijual Kulkas Potable", - desc = "Dijual kulkas Samsung berumur dua tahun tetapi masih layak pakai, fungsi masih lengkap", - place = "Jakarta" - ) - } + if (forumList != null) { + when(forumList) { + is UiState.Loading -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(200.dp), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is UiState.Error -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(200.dp), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) + + ) { + Text( + text = "Fail to fetch forum", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + } + is UiState.Success -> { + val latestForumList = forumList.data?.forum - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Membuka Service Laptop di Daerah Pogung", - desc = "Membuka jasa service laptop dengan jaminan uang kembali apabila tidak berhasil", - place = "Yogyakarta" - ) - } + LazyColumn( + modifier = Modifier + .fillMaxSize() + .height(400.dp) + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(10.dp), + contentPadding = PaddingValues( bottom = 16.dp) + ) { + if (latestForumList != null) { + items(latestForumList) { forum -> + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = forum.title, + desc = forum.content, + place = forum.location, + photoUrl = forum.imageURL, + onClick = { navigateToSingleForum(forum.id) } + ) - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Membuat Kursus Membenarkan Laptop", - desc = "Membuka kursus untuk mengajarkan cara membenarkan laptop lama", - place = "Bali" - ) + } + } + } + } } } } } } - -// Column( -// modifier = Modifier -// .fillMaxSize() -// ) { -// Spacer(modifier = Modifier.weight(1f)) -// DefaultBottomBar( -// selectedType = BottomBarItemType.Home, -// navigateToProfile = navigateToProfile, -// navigateToForum = navigateToForum, -// navigateToArticle = navigateToArticle, -// navigateToHome = navigateToHome -// ) -// } } } } @@ -508,7 +511,10 @@ fun HomeContentPreview() { navigateToCatalog = {}, navigateToMaps = {}, navigateToSingleArticle = {}, - latestArticleState = UiState.Loading() + latestArticleState = UiState.Loading(), + forumList = null, + navigateToSingleForum = {}, + navigateToMain = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreenViewModel.kt index 506271d..9fe4eac 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreenViewModel.kt @@ -3,7 +3,9 @@ package com.capstone.techwasmark02.ui.screen.home import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.data.remote.response.ForumResponse import com.capstone.techwasmark02.repository.TechwasArticleRepository +import com.capstone.techwasmark02.repository.TechwasForumApiRepository import com.capstone.techwasmark02.ui.common.UiState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -13,16 +15,23 @@ import javax.inject.Inject @HiltViewModel class HomeScreenViewModel @Inject constructor( - private val articleApiRepository: TechwasArticleRepository + private val articleApiRepository: TechwasArticleRepository, + private val forumApiRepository: TechwasForumApiRepository ): ViewModel() { private val _latestArticleState: MutableStateFlow?> = MutableStateFlow(null) val latestArticleState = _latestArticleState.asStateFlow() + private val _forumList: MutableStateFlow?> = MutableStateFlow(null) + val forumList = _forumList.asStateFlow() + init { _latestArticleState.value = UiState.Loading() + _forumList.value = UiState.Loading() + viewModelScope.launch { _latestArticleState.value = articleApiRepository.getAllArticle() + _forumList.value = forumApiRepository.fetchAllForum() } } diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt index 1eeb120..9cab988 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -17,6 +18,7 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape @@ -49,6 +51,7 @@ import com.capstone.techwasmark02.R import com.capstone.techwasmark02.data.local.database.entity.FavoriteArticleEntity import com.capstone.techwasmark02.data.model.UserSession import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.data.remote.response.ForumResponse import com.capstone.techwasmark02.data.remote.response.Token import com.capstone.techwasmark02.data.remote.response.UserId import com.capstone.techwasmark02.ui.common.UiState @@ -71,13 +74,16 @@ fun ProfileUserScreen( val userSession by viewModel.userSessionState.collectAsState() val bookmarkedArticleState by viewModel.bookmarkedArticleState.collectAsState() val favoriteArticlesList by viewModel.favoriteArticlesFlow.collectAsState(initial = null) + val forumList by viewModel.forumList.collectAsState() ProfileUserContent( navigateToSetting = { navController.navigate(Screen.Setting.route) }, userSession = userSession, bookmarkedArticleState = bookmarkedArticleState, favoriteArticleList = favoriteArticlesList, - navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") } + navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") }, + forumList = forumList, + navigateToSingleForum = { navController.navigate("${Screen.SingleForum.route}/$it")} ) } @@ -88,7 +94,9 @@ fun ProfileUserContent( userSession: UserSession?, bookmarkedArticleState: UiState?, favoriteArticleList: List?, - navigateToSingleArticle: (idArticle: Int) -> Unit + navigateToSingleArticle: (idArticle: Int) -> Unit, + forumList: UiState?, + navigateToSingleForum: (Int) -> Unit ) { Scaffold( @@ -312,67 +320,69 @@ fun ProfileUserContent( Spacer(modifier = Modifier.height(8.dp)) - LazyColumn( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - verticalArrangement = Arrangement.spacedBy(10.dp), - horizontalAlignment = Alignment.CenterHorizontally, - contentPadding = PaddingValues(vertical = 10.dp) - ) { - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Jual Laptop Mati Total", - desc = "\"Saya mempunyai laptop yang baru saja mati, pada saat tombol power tekan tidak ada respon apapun, kemungkinan masalah berada di battery. Selain itu kondisi masih bagus dan tidak ada kerusakan luar\\nBagi yang berminat dapat mencoba menghubungi saya +6281396774583\"", - place = "Yogyakarta", - photoUrl = R.drawable.img_forum_laptop_bekas - ) - } - - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Cara Hidupkan Hape Xiomi Lama", - desc = "Tiga belas hari yang lalu jatuh dari motor dan hp saya ikut jatuh dan terbentur", - place = "Merauke" - ) - } - - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Bagaiamana Cara Menyambung Kabel", - desc = "Saya akan memberikan langkah-langkah mudah untuk menyambung kabel elektronik", - place = "Solo" - ) - } + if (forumList != null) { + when(forumList) { + is UiState.Loading -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(200.dp), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is UiState.Error -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(200.dp), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Dijual Kulkas Potable", - desc = "Dijual kulkas Samsung berumur dua tahun tetapi masih layak pakai, fungsi masih lengkap", - place = "Jakarta" - ) - } + ) { + Text( + text = "Fail to fetch forum", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + } + is UiState.Success -> { + val latestForumList = forumList.data?.forum - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Membuka Service Laptop di Daerah Pogung", - desc = "Membuka jasa service laptop dengan jaminan uang kembali apabila tidak berhasil", - place = "Yogyakarta" - ) - } + LazyColumn( + modifier = Modifier + .fillMaxSize() + .height(400.dp) + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(10.dp), + contentPadding = PaddingValues( vertical = 10.dp) + ) { + if (latestForumList != null) { + items(latestForumList) { forum -> + ForumBox( + modifier = Modifier.fillMaxWidth(), + title = forum.title, + desc = forum.content, + place = forum.location, + photoUrl = forum.imageURL, + onClick = { navigateToSingleForum(forum.id) } + ) - item { - ForumBox( - modifier = Modifier.fillMaxWidth(), - title = "Membuat Kursus Membenarkan Laptop", - desc = "Membuka kursus untuk mengajarkan cara membenarkan laptop lama", - place = "Bali" - ) + } + } + } + } } } } @@ -397,7 +407,9 @@ fun ProfileUserScreenPreview() { ), bookmarkedArticleState = null, favoriteArticleList = null, - navigateToSingleArticle = {} + navigateToSingleArticle = {}, + forumList = null, + navigateToSingleForum = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreenViewModel.kt index 79d8408..f67791f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreenViewModel.kt @@ -5,11 +5,13 @@ import androidx.lifecycle.viewModelScope import com.capstone.techwasmark02.common.Resource import com.capstone.techwasmark02.data.model.UserSession import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse +import com.capstone.techwasmark02.data.remote.response.ForumResponse import com.capstone.techwasmark02.data.remote.response.Token import com.capstone.techwasmark02.data.remote.response.UserId import com.capstone.techwasmark02.repository.FavoriteArticleRepository import com.capstone.techwasmark02.repository.PreferencesRepository import com.capstone.techwasmark02.repository.TechwasArticleRepository +import com.capstone.techwasmark02.repository.TechwasForumApiRepository import com.capstone.techwasmark02.ui.common.UiState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -21,7 +23,8 @@ import javax.inject.Inject class ProfileUserScreenViewModel @Inject constructor( private val preferencesRepository: PreferencesRepository, private val articleApiRepository: TechwasArticleRepository, - private val favoriteArticleRepository: FavoriteArticleRepository + private val favoriteArticleRepository: FavoriteArticleRepository, + private val forumApiRepository: TechwasForumApiRepository ): ViewModel() { private val _userSessionState: MutableStateFlow = MutableStateFlow(null) @@ -32,11 +35,16 @@ class ProfileUserScreenViewModel @Inject constructor( val favoriteArticlesFlow = favoriteArticleRepository.getFavArticles() + private val _forumList: MutableStateFlow?> = MutableStateFlow(null) + val forumList = _forumList.asStateFlow() + init { _bookmarkedArticleState.value = UiState.Loading() + _forumList.value = UiState.Loading() viewModelScope.launch { _bookmarkedArticleState.value = articleApiRepository.getAllArticle() + _forumList.value = forumApiRepository.fetchAllForum() val result = preferencesRepository.getActiveSession() when(result) { From 92ef0362d626c0dded222498e542852f05e24b82 Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Fri, 16 Jun 2023 17:23:16 +0700 Subject: [PATCH 69/73] cleaning code --- .../capstone/techwasmark02/MainActivity.kt | 1 - .../techwasmark02/data/mappers/Mappers.kt | 1 - .../repository/PreferencesRepository.kt | 1 - .../repository/TechwasForumApiRepository.kt | 1 - .../techwasmark02/ui/component/ProfileBox.kt | 3 -- .../ui/component/SelectableText.kt | 4 --- .../techwasmark02/ui/component/SettingItem.kt | 2 -- .../ui/screen/article/ArticleScreen.kt | 2 -- .../screen/article/ArticleScreenViewModel.kt | 1 - .../ui/screen/catalog/CatalogScreen.kt | 1 - .../CatalogSingleComponentScreenViewModel.kt | 3 -- .../ui/screen/forum/ForumScreen.kt | 4 --- .../screen/forumSingle/ForumSingleScreen.kt | 36 ------------------- .../ui/screen/home/HomeScreen.kt | 15 +------- .../ui/screen/onBoarding/OnBoardingScreen.kt | 7 ---- .../screen/profileUser/ProfileUserScreen.kt | 7 ---- .../ui/screen/signIn/SignInScreen.kt | 6 ++-- .../ui/screen/signIn/SignInScreenViewModel.kt | 1 - .../singleArticle/SingleArticleScreen.kt | 4 --- .../SingleArticleScreenViewModel.kt | 2 -- 20 files changed, 5 insertions(+), 97 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt b/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt index deb2e82..7ae9a08 100644 --- a/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt +++ b/app/src/main/java/com/capstone/techwasmark02/MainActivity.kt @@ -26,7 +26,6 @@ class MainActivity : ComponentActivity() { color = MaterialTheme.colorScheme.background ) { TechwasApp() -// CatalogScreen() } } } diff --git a/app/src/main/java/com/capstone/techwasmark02/data/mappers/Mappers.kt b/app/src/main/java/com/capstone/techwasmark02/data/mappers/Mappers.kt index 453ba1e..307683f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/mappers/Mappers.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/mappers/Mappers.kt @@ -3,7 +3,6 @@ package com.capstone.techwasmark02.data.mappers import com.capstone.techwasmark02.data.local.database.entity.FavoriteArticleEntity import com.capstone.techwasmark02.data.model.FavoriteArticle import com.capstone.techwasmark02.data.model.UserSession -import com.capstone.techwasmark02.data.remote.response.ArticleItem import com.capstone.techwasmark02.data.remote.response.LoginResult fun LoginResult.toUserSession(): UserSession { diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/PreferencesRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/PreferencesRepository.kt index e8e1800..f0c3ddc 100644 --- a/app/src/main/java/com/capstone/techwasmark02/repository/PreferencesRepository.kt +++ b/app/src/main/java/com/capstone/techwasmark02/repository/PreferencesRepository.kt @@ -8,7 +8,6 @@ import com.capstone.techwasmark02.common.Resource import com.capstone.techwasmark02.data.model.UserSession import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import javax.inject.Inject diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt index ff110a4..5cca8cd 100644 --- a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt @@ -9,7 +9,6 @@ import com.capstone.techwasmark02.data.remote.response.ForumResponse import com.capstone.techwasmark02.data.remote.response.PostForumCommentResponse import com.capstone.techwasmark02.ui.common.UiState import javax.inject.Inject -import kotlin.Exception class TechwasForumApiRepository @Inject constructor( private val forumApi: TechwasForumApi diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt index d936d85..e1a8f2b 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/ProfileBox.kt @@ -12,8 +12,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Warning import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -21,7 +19,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt index b0ffd89..bceaa2d 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SelectableText.kt @@ -3,15 +3,11 @@ package com.capstone.techwasmark02.ui.component import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/component/SettingItem.kt b/app/src/main/java/com/capstone/techwasmark02/ui/component/SettingItem.kt index 64bc530..3bab856 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/component/SettingItem.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/component/SettingItem.kt @@ -11,8 +11,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.AccountCircle -import androidx.compose.material.icons.filled.ArrowForward import androidx.compose.material.icons.filled.KeyboardArrowRight import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt index 2dbce09..66f9b5a 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreen.kt @@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.requiredWidthIn import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.grid.GridCells @@ -22,7 +21,6 @@ import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt index 9ace97b..e9ca610 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/article/ArticleScreenViewModel.kt @@ -2,7 +2,6 @@ package com.capstone.techwasmark02.ui.screen.article import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.capstone.techwasmark02.data.mappers.toUserSession import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.repository.TechwasArticleRepository import com.capstone.techwasmark02.ui.common.UiState diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt index 7abcf4a..b9be8ee 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalog/CatalogScreen.kt @@ -34,7 +34,6 @@ import com.capstone.techwasmark02.data.remote.response.Component import com.capstone.techwasmark02.data.remote.response.ComponentsResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.CatalogCard -import com.capstone.techwasmark02.ui.component.DefaultTopBar import com.capstone.techwasmark02.ui.component.InverseTopBar import com.capstone.techwasmark02.ui.component.SearchBox import com.capstone.techwasmark02.ui.navigation.Screen diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreenViewModel.kt index 8d58241..1050175 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/catalogSingleComponent/CatalogSingleComponentScreenViewModel.kt @@ -2,10 +2,7 @@ package com.capstone.techwasmark02.ui.screen.catalogSingleComponent import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.capstone.techwasmark02.data.remote.apiService.TechwasComponentApi import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse -import com.capstone.techwasmark02.data.remote.response.Component -import com.capstone.techwasmark02.data.remote.response.ComponentResponse import com.capstone.techwasmark02.data.remote.response.SmallPart import com.capstone.techwasmark02.data.remote.response.UsableComponentsResponse import com.capstone.techwasmark02.repository.TechwasArticleRepository diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt index 0d7f3f6..ce0abda 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forum/ForumScreen.kt @@ -1,9 +1,7 @@ package com.capstone.techwasmark02.ui.screen.forum -import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.border -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -14,10 +12,8 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.requiredWidthIn import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt index e0ff6f0..d43fd99 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumSingle/ForumSingleScreen.kt @@ -15,14 +15,10 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape @@ -46,18 +42,15 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.draw.shadow import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.DefaultShadowColor import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.min import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import coil.compose.AsyncImage @@ -69,15 +62,10 @@ import com.capstone.techwasmark02.data.remote.response.PostForumCommentResponse import com.capstone.techwasmark02.data.remote.response.Token import com.capstone.techwasmark02.data.remote.response.UserId import com.capstone.techwasmark02.ui.common.UiState -import com.capstone.techwasmark02.ui.component.DefaultTopBar import com.capstone.techwasmark02.ui.component.TransparentTopBar import com.capstone.techwasmark02.ui.navigation.Screen -import com.capstone.techwasmark02.ui.screen.forum.ForumContent import com.capstone.techwasmark02.ui.theme.Mist97 import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlin.io.path.fileVisitor @Composable fun ForumSingleScreen( @@ -142,30 +130,6 @@ fun ForumSingleContent( mutableStateOf(true) } -// var commentPosted by remember { -// mutableStateOf(false) -// } -// -// var showLastComment by remember { -// mutableStateOf(false) -// } -// -// var lastCommentText by remember { -// mutableStateOf("") -// } -// -//// fun postLastComment() { -//// coroutineScope.launch { -//// -//// -//// commentPosted = true -//// delay(2000) -//// lastCommentText = commentText -//// commentPosted = false -//// commentText = "" -//// showLastComment = true -//// } -//// } LaunchedEffect(key1 = forumCommentState) { if (!firstRender) { diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index 3906167..f127b0f 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -58,7 +58,6 @@ import androidx.core.content.ContextCompat import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import com.capstone.techwasmark02.R -import com.capstone.techwasmark02.data.remote.response.ArticleList import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.ForumResponse import com.capstone.techwasmark02.ui.common.UiState @@ -68,13 +67,10 @@ import com.capstone.techwasmark02.ui.component.FeatureBoxLarge import com.capstone.techwasmark02.ui.component.ForumBox import com.capstone.techwasmark02.ui.componentType.FeatureBoxType import com.capstone.techwasmark02.ui.navigation.Screen -import com.capstone.techwasmark02.ui.navigation.Screen.Article import com.capstone.techwasmark02.ui.navigation.Screen.Camera import com.capstone.techwasmark02.ui.navigation.Screen.Catalog import com.capstone.techwasmark02.ui.navigation.Screen.Forum -import com.capstone.techwasmark02.ui.navigation.Screen.Home import com.capstone.techwasmark02.ui.navigation.Screen.Maps -import com.capstone.techwasmark02.ui.navigation.Screen.Profile import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme import com.capstone.techwasmark02.ui.theme.yellow import kotlin.math.absoluteValue @@ -90,17 +86,14 @@ fun HomeScreen( HomeContent( navigateToCamera = { navController.navigate(Camera.route) }, - navigateToHome = { navController.navigate(Home.route) }, navigateToArticle = { navController.navigate("${Screen.Main.route}/2") }, navigateToForum = { navController.navigate(Forum.route) }, - navigateToProfile = { navController.navigate(Profile.route) }, navigateToCatalog = { navController.navigate(Catalog.route) }, navigateToMaps = { navController.navigate(Maps.route) }, navigateToSingleArticle = { navController.navigate("${Screen.SingleArticle.route}/$it") }, latestArticleState = latestArticleState, forumList = forumList, navigateToSingleForum = { navController.navigate("${Screen.SingleForum.route}/$it")}, - navigateToMain = { navController.navigate("${Screen.Main.route}/1") } ) } @@ -108,17 +101,14 @@ fun HomeScreen( @Composable fun HomeContent( navigateToCamera: () -> Unit, - navigateToHome: () -> Unit, navigateToForum: () -> Unit, navigateToArticle: () -> Unit, - navigateToProfile: () -> Unit, navigateToCatalog: () -> Unit, navigateToMaps: () -> Unit, navigateToSingleArticle: (idArticle: Int) -> Unit, latestArticleState: UiState?, forumList: UiState?, navigateToSingleForum: (Int) -> Unit, - navigateToMain: () -> Unit ) { val context = LocalContext.current @@ -172,7 +162,7 @@ fun HomeContent( ) } Text( - text = "Techwas", + text = "Techwaste", modifier = Modifier .padding(start = 4.dp) .offset(y = 5.dp), @@ -504,17 +494,14 @@ fun HomeContentPreview() { TechwasMark02Theme { HomeContent( navigateToCamera = {}, - navigateToHome = {}, navigateToArticle = {}, navigateToForum = {}, - navigateToProfile = {}, navigateToCatalog = {}, navigateToMaps = {}, navigateToSingleArticle = {}, latestArticleState = UiState.Loading(), forumList = null, navigateToSingleForum = {}, - navigateToMain = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt index 31e24e7..8bfb589 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/onBoarding/OnBoardingScreen.kt @@ -1,10 +1,7 @@ package com.capstone.techwasmark02.ui.screen.onBoarding import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.EnterTransition import androidx.compose.animation.core.animateDpAsState -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.animateSizeAsState import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -31,14 +28,10 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontFamily diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt index 9cab988..a4b3365 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/profileUser/ProfileUserScreen.kt @@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -55,16 +54,10 @@ import com.capstone.techwasmark02.data.remote.response.ForumResponse import com.capstone.techwasmark02.data.remote.response.Token import com.capstone.techwasmark02.data.remote.response.UserId import com.capstone.techwasmark02.ui.common.UiState -import com.capstone.techwasmark02.ui.component.ArticleCardBig import com.capstone.techwasmark02.ui.component.ArticleCardSmall -import com.capstone.techwasmark02.ui.component.DefaultBottomBar -import com.capstone.techwasmark02.ui.component.DefaultTopBar import com.capstone.techwasmark02.ui.component.ForumBox -import com.capstone.techwasmark02.ui.component.ProfileBox -import com.capstone.techwasmark02.ui.componentType.BottomBarItemType import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme -import kotlin.random.Random @Composable fun ProfileUserScreen( diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt index afd0b10..34f8375 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreen.kt @@ -16,9 +16,12 @@ import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.* +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -30,7 +33,6 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import com.capstone.techwasmark02.data.model.UserLoginInfo -import com.capstone.techwasmark02.data.model.UserSession import com.capstone.techwasmark02.data.remote.response.UserLoginResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.DefaultButton diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt index 089f7cd..c4722d5 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/signIn/SignInScreenViewModel.kt @@ -5,7 +5,6 @@ import androidx.lifecycle.viewModelScope import com.capstone.techwasmark02.common.Resource import com.capstone.techwasmark02.data.mappers.toUserSession import com.capstone.techwasmark02.data.model.UserLoginInfo -import com.capstone.techwasmark02.data.model.UserSession import com.capstone.techwasmark02.data.remote.response.UserLoginResponse import com.capstone.techwasmark02.repository.PreferencesRepository import com.capstone.techwasmark02.repository.TechwasUserApiRepository diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt index ae17a19..12c50f5 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreen.kt @@ -43,13 +43,11 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.viewModelScope -import androidx.navigation.NavController import androidx.navigation.NavHostController import coil.compose.rememberAsyncImagePainter import com.capstone.techwasmark02.R import com.capstone.techwasmark02.data.local.database.entity.FavoriteArticleEntity import com.capstone.techwasmark02.data.model.FavoriteArticle -import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.SingleArticleResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.DefaultButton @@ -58,9 +56,7 @@ import com.capstone.techwasmark02.ui.component.TransparentTopBar import com.capstone.techwasmark02.ui.navigation.Screen import com.capstone.techwasmark02.ui.theme.Mist97 import com.capstone.techwasmark02.ui.theme.TechwasMark02Theme -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch -import kotlin.random.Random @Composable fun SingleArticleScreen( diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt index d87e79f..546742b 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/singleArticle/SingleArticleScreenViewModel.kt @@ -3,9 +3,7 @@ package com.capstone.techwasmark02.ui.screen.singleArticle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.capstone.techwasmark02.data.local.database.entity.FavoriteArticleEntity -import com.capstone.techwasmark02.data.mappers.toFavoriteArticleEntity import com.capstone.techwasmark02.data.model.FavoriteArticle -import com.capstone.techwasmark02.data.remote.response.ArticleResultResponse import com.capstone.techwasmark02.data.remote.response.SingleArticleResponse import com.capstone.techwasmark02.repository.FavoriteArticleRepository import com.capstone.techwasmark02.repository.TechwasArticleRepository From 05834a12765660616f3294263191f4de6eab7189 Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Fri, 16 Jun 2023 19:37:16 +0700 Subject: [PATCH 70/73] correcting see all forum & article --- .../com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt index f127b0f..9f28007 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/home/HomeScreen.kt @@ -271,7 +271,7 @@ fun HomeContent( color = yellow, modifier = Modifier .clickable { - navigateToForum() + navigateToArticle() } ) } @@ -394,7 +394,7 @@ fun HomeContent( color = yellow, modifier = Modifier .clickable { - navigateToArticle() + navigateToForum() } ) } From 9f4a4c1d56b6861a81445f838633e9d0bce8c3ba Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Fri, 16 Jun 2023 20:15:32 +0700 Subject: [PATCH 71/73] app icon and logo in bitmap --- app/src/main/ic_launcher-playstore.png | Bin 0 -> 40461 bytes .../main/res/mipmap-anydpi-v26/ic_launcher.xml | 5 ++--- .../res/mipmap-anydpi-v26/ic_launcher_round.xml | 5 ++--- app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2511 bytes app/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 4901 bytes .../main/res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4611 bytes .../main/res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 0 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1566 bytes app/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 2908 bytes .../main/res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2775 bytes .../main/res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 0 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 3657 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 7365 bytes .../main/res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6837 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 0 bytes app/src/main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6219 bytes app/src/main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 13669 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 11514 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 0 bytes app/src/main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9177 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 19103 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 17325 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 0 bytes .../main/res/values/ic_launcher_background.xml | 4 ++++ 29 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 app/src/main/ic_launcher-playstore.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/values/ic_launcher_background.xml diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..0b563a354d90357ce0e4feeb4b899711028d3032 GIT binary patch literal 40461 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 - - - + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index 6f3b755..036d09b 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,6 +1,5 @@ - - - + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7181e1500c405c6267d122af45bfd810ba15906a GIT binary patch literal 2511 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 Z{{xdU>v&Ji6#D=G002ovPDHLkV1gTY$DRNH literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index c209e78ecd372343283f4157dcfd918ec5165bb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1404 zcmV-?1%vuhNk&F=1pok7MM6+kP&il$0000G0000-002h-06|PpNX!5L00Dqw+t%{r zzW2vH!KF=w&cMnnN@{whkTw+#mAh0SV?YL=)3MimFYCWp#fpdtz~8$hD5VPuQgtcN zXl<@<#Cme5f5yr2h%@8TWh?)bSK`O z^Z@d={gn7J{iyxL_y_%J|L>ep{dUxUP8a{byupH&!UNR*OutO~0{*T4q5R6@ApLF! z5{w?Z150gC7#>(VHFJZ-^6O@PYp{t!jH(_Z*nzTK4 zkc{fLE4Q3|mA2`CWQ3{8;gxGizgM!zccbdQoOLZc8hThi-IhN90RFT|zlxh3Ty&VG z?Fe{#9RrRnxzsu|Lg2ddugg7k%>0JeD+{XZ7>Z~{=|M+sh1MF7~ zz>To~`~LVQe1nNoR-gEzkpe{Ak^7{{ZBk2i_<+`Bq<^GB!RYG+z)h;Y3+<{zlMUYd zrd*W4w&jZ0%kBuDZ1EW&KLpyR7r2=}fF2%0VwHM4pUs}ZI2egi#DRMYZPek*^H9YK zay4Iy3WXFG(F14xYsoDA|KXgGc5%2DhmQ1gFCkrgHBm!lXG8I5h*uf{rn48Z!_@ z4Bk6TJAB2CKYqPjiX&mWoW>OPFGd$wqroa($ne7EUK;#3VYkXaew%Kh^3OrMhtjYN?XEoY`tRPQsAkH-DSL^QqyN0>^ zmC>{#F14jz4GeW{pJoRpLFa_*GI{?T93^rX7SPQgT@LbLqpNA}<@2wH;q493)G=1Y z#-sCiRNX~qf3KgiFzB3I>4Z%AfS(3$`-aMIBU+6?gbgDb!)L~A)je+;fR0jWLL-Fu z4)P{c7{B4Hp91&%??2$v9iRSFnuckHUm}or9seH6 z>%NbT+5*@L5(I9j@06@(!{ZI?U0=pKn8uwIg&L{JV14+8s2hnvbRrU|hZCd}IJu7*;;ECgO%8_*W Kmw_-CKmY()leWbG diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..b7c208b0f68027f3bfe0100eb1b439593b283722 GIT binary patch literal 4901 zcmd^D_dA?z)0T);SBqX&uo8Ln5?v%%B6>(d1grNJ-4c>Th)#4KB@*#q^=`Ed(QC3; zo!Ah&N<=UF#d_ZFc>jm@IPUVpJ@+-&oHKLI%oS~*rwOFupduk50ct%^fAr^FcyUtz z{ye*Wv2c=*Fyge-?;8hL;Bx~59)Dx*KC78BHLH78US9qL?^sulM#noclN;x37+>o) zH8$olU@|n=P%2m+WU^PyAkSos6j!65e67W%7M7S84lefRZj?O`ou{5AFFc4m+if9) z?><>RK+pWZh3w03<-?gEhW~x-GrSi(q1;cSU@>BPI%URZqGR~n$|D*o0r84J3cT)S z>Sq3*`nU{19xMzuJD+(ba;g@CyjviRHzmLT;8;Rs;rNeLqfQsAR>E z6FO=)C;LxJ7bbDL$E_!a0{@YX2{LN7$z5+KYiP1-I2zt0>~#b$IZVBsJnH^e1WOvN zxjOv9$e?~yDbG7bK6H^6mVxjkz=!0|+8K_fTYaya{*_kQpkA3Vu7vwkEgSKc6VYV>^p?MBF1wWfq=UyHeYk_TkA%+OE2yP?|| zDoy}x4@LEf4$2MA%Iw)3NVt!S0r8>*|`PhUhx2KHEL46?*M8nQ%;2(!)xOs(m`Q3SxM~g zd%H^|tl2|~=-tXo^!n#-&sCvkPCYRxCioyyl_g zP#wQMO`+8fO2Vv5AlU@omtUWj2JMXn`o(3wy)s})(POT>98d#A8G{&IE?8GMzE!5e zdmGS6@`LuUzA0ckss8B}VkcB;uGrFzQ=7rCe$sU{eT%jKADIkRdw(jl=L3VR7lYSr zhUd(eo#xt8&*(p#EdK6qyM0J#4Vldw>aQkK0;4aY(}at?sak&<@FA!&+v_}EO{b;c z%hc-^3y`^1S+BML2Y%%}`@Wt`3yqmkX74YDHRBxpDq`W?bNFSR3ARGuM^_neAw#pZ_{$;ms$S%C%PI^g;Mbk4JRijLv%2Uv z5R)wd6Z7I);9bE_bn&KpymZuuK7CUA@QA84O|FKYHXueA5o<(;V;jTY8Gav>XRe5! zm1C+u>zGST1-E{8n!wi#jQ^dyvCJ-5vxuBCELopk+dh@$SCDfUH>vG%-~2WsF5d9ee&>&`)ISx!_Y4)YS5Vy^%?uf6-?UhO$G$}$X9O)=__pW{{d zU%G!;-s)zW{|f4n>m-IR*`5L+4zdwqvCaiz48xd3q${(!n|{|_(8qv#LPbEft>Wvr zI-8>pFcQ=<3xH79cy0q5Vga#)m7NXEiYD1pymK8FkP)99@ZO}M{bqxYp~zAH7Z&NI z&*0K+crAHi*NsA6)4(1nwV7CcS4x2>G(v^=~~3(UVi8m_{t%ihumXow?>g{Lt32^%omj` zc%%4g?)Zud;q!bUy`D2Y-m@A}<~-uclC(7+T@K&7$pM{o)m`}XtQt8AV&1EpvFCCR zb!eueInVo3XS~EgiZbx0tz9TaQes{*gV~m3@yCYk(u#iW4HM!VhFjSI^-Y~8?ERp1 z4(jb)0Zxa^&4~)CES7C3@J;WRn~{k23YwHw$pb{KkucS~2`o}Kf|Jv8#Okj^+i6F| z$|bci-i_MYl@t=9f>drrAwIX?CPvI@BGpD)VRj?r<;Q|4`GNToiEF1G`))~t9D8?X zo0(<2dVZzjeBwhjAEQMc?29FQ>77pLbQKMN4$2`Up2CY6@# zD0_*H`+oEB>+l5?d`y9#%CxLsOMzy#)saULzPeAe?-x4aR`^SQpdh^;PWb~!t43mdmzU$D@MN0jBZ{%-xu#Wt78u9xa1m*y&nN-V+WWBhJrLrgV+2|W zLzeJNII*o&Oesyyt{{8#i^Nykak@(-#}roX>dHC?ZB7i+JF-k$AMzw9iIkIbUke*I zdqTQ$W1|~S8Ko4$s_ZVx=Cg*7oixi+zO$ktV>X}7K4wCqcB0X>*>g+#Zwc>KVQx*; z9jUSdivvCuIIh0foK;3=M^I;126PUnO*J8ZRdq^?L^&)9?QF6Yd^?MMdY>&2Uu z->6gOVwPyQl0+X@acZg>n$c8HGElbYHT5F+&8RNQHH-f!VbX3qu#+>$8@+B1Sw}d@ zwb=UD>a*G7Sv=I_ZS_!9O?BHD!H}+ zdb+oZB*%>-9Lfo8O_eW$z4r0@*8Aq|?c;-@>?;D|gxbmRqm|0{-h10CZqXFEig6;W z$y67qArKMUn$9;dcYUHl(q(`eh%Kw@Op(Nf3n>q}9 zR@J3nf!p^}uxNHl({(+~Lxl^*+cbrZQ%kNDf3&R8RK$?M+dM#7FACfcZqb0>L_RGF z!(M$J{JnizeATRp?i!%9e8x$Ca%td27pwhpXVB)iz+8N@*z7P_%^a7);--qDm|7|O z@r^TEilj|ZkNz*41Iuv}Lo?LP806aaM&jHGYI|uJbbscVcH~8mo_q~cY!L1qrL<6E zm$UuE+%T|B8S5iN>`b3L4wfpoM zVy8_Bb-A-ATfM5S#QlO_Rm9#K664x2c+r^!T;<{^-b##{p?ed4alN;-mt$Pdc3ex-lwz5d{UUej9l0UnOdO}s+njhXnEQfWwE3p$ z0{9ySHUa20hATd``M0k^?0o8PltKp16{&fufQ+YgHc_7(CS+AUz@YXSES6v4yHaNR zFXBIZAO@-ynW+%XoAqQMskg-vq_x=oxy`W%-Y(nB&`|>~_MGmW5^GSV_|FuR6uu;_ z$soTQ#A2ld$dpw0drUnn4JMO7fO2R?&hT#dTl3d*2Zygq9x1s5;iigQf|ThmT?|*? z&SDs4kE_Uq@bKoXc?Uu}ZXu%-{Jv?{bDrMo3l|`Ai}n?b`>Zfzebs)8h+@Qt5F!k|sb4Q8uWiWwzG~gxSk&54A77xx!Mz}tI;q$KSN5L`RCN*i zbth*^4cr|M{Fy8gsA(HY+%x%K;vAA2o^TO#(gWv5cwHeFaULM&i%L603&O0%H%mAv zfe%$n_KPmnOuYicMz*jRk{tN!Lp8YgyDe(<`gGr1L=`RgNl>&-0{i4Ncao<)e&K3C zbTrL{KU~)Ht5_6;9c?=@(>?h~{Y*z)qTD%RjchOX-3@~NgR#9?!EP%yO%v(?D&&2J z8pYN%lt!ig{@1dbpRIzW?}XEdFWr}=t^YY%mLJ{MMl?VK=-O$=>VOf_>f%-i@U%Mq zGy2s)wt6-djk5s6e9d(GX6Hx8WEo)HrLlE@lGObX2LEz)f^li@m_ zRwo|XEaPfHRIJrulKoeV?mV`s9uDaF>_3Oc-075_>rZn=a0ezUKP{9NyCC;8V^2SJ zS;>4`c*O&hd*Ag5MCHMBe#}RkZ~#u^3Mx_KJPYYA zoo7;>6$>fF(sabtY&~Tl3H~pAFC3In*myZbE)yB@_FEz1@F$4)pZoaezYm)jQG_es Y*aU=<3Qqs}bNof31<_MSs6t==A7`C~oB#j- literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..ffe582ddd44315440aff6393b73c6bc451fdf30a GIT binary patch literal 4611 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp deleted file mode 100644 index b2dfe3d1ba5cf3ee31b3ecc1ced89044a1f3b7a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2898 zcmV-Y3$650Nk&FW3jhFDMM6+kP&il$0000G0000-002h-06|PpNWB9900E$G+qN-D z+81ABX7q?;bwx%xBg?kcwr$(C-Tex-ZCkHUw(Y9#+`E5-zuONG5fgw~E2WDng@Bc@ z24xy+R1n%~6xI#u9vJ8zREI)sb<&Il(016}Z~V1n^PU3-_H17A*Bf^o)&{_uBv}Py zulRfeE8g(g6HFhk_?o_;0@tz?1I+l+Y#Q*;RVC?(ud`_cU-~n|AX-b`JHrOIqn(-t&rOg-o`#C zh0LPxmbOAEb;zHTu!R3LDh1QO zZTf-|lJNUxi-PpcbRjw3n~n-pG;$+dIF6eqM5+L();B2O2tQ~|p{PlpNcvDbd1l%c zLtXn%lu(3!aNK!V#+HNn_D3lp z2%l+hK-nsj|Bi9;V*WIcQRTt5j90A<=am+cc`J zTYIN|PsYAhJ|=&h*4wI4ebv-C=Be#u>}%m;a{IGmJDU`0snWS&$9zdrT(z8#{OZ_Y zxwJx!ZClUi%YJjD6Xz@OP8{ieyJB=tn?>zaI-4JN;rr`JQbb%y5h2O-?_V@7pG_+y z(lqAsqYr!NyVb0C^|uclHaeecG)Sz;WV?rtoqOdAAN{j%?Uo%owya(F&qps@Id|Of zo@~Y-(YmfB+chv^%*3g4k3R0WqvuYUIA+8^SGJ{2Bl$X&X&v02>+0$4?di(34{pt* zG=f#yMs@Y|b&=HyH3k4yP&goF2LJ#tBLJNNDo6lG06r}ghC-pC4Q*=x3;|+W04zte zAl>l4kzUBQFYF(E`KJy?ZXd1tnfbH+Z~SMmA21KokJNs#eqcXWKUIC>{TuoKe^vhF z);H)o`t9j~`$h1D`#bxe@E`oE`cM9w(@)5Bp8BNukIwM>wZHfd0S;5bcXA*5KT3bj zc&_~`&{z7u{Et!Z_k78H75gXf4g8<_ul!H$eVspPeU3j&&Au=2R*Zp#M9$9s;fqwgzfiX=E_?BwVcfx3tG9Q-+<5fw z%Hs64z)@Q*%s3_Xd5>S4dg$s>@rN^ixeVj*tqu3ZV)biDcFf&l?lGwsa zWj3rvK}?43c{IruV2L`hUU0t^MemAn3U~x3$4mFDxj=Byowu^Q+#wKRPrWywLjIAp z9*n}eQ9-gZmnd9Y0WHtwi2sn6n~?i#n9VN1B*074_VbZZ=WrpkMYr{RsI ztM_8X1)J*DZejxkjOTRJ&a*lrvMKBQURNP#K)a5wIitfu(CFYV4FT?LUB$jVwJSZz zNBFTWg->Yk0j&h3e*a5>B=-xM7dE`IuOQna!u$OoxLlE;WdrNlN)1 z7**de7-hZ!(%_ZllHBLg`Ir#|t>2$*xVOZ-ADZKTN?{(NUeLU9GbuG-+Axf*AZ-P1 z0ZZ*fx+ck4{XtFsbcc%GRStht@q!m*ImssGwuK+P@%gEK!f5dHymg<9nSCXsB6 zQ*{<`%^bxB($Z@5286^-A(tR;r+p7B%^%$N5h%lb*Vlz-?DL9x;!j<5>~kmXP$E}m zQV|7uv4SwFs0jUervsxVUm>&9Y3DBIzc1XW|CUZrUdb<&{@D5yuLe%Xniw^x&{A2s z0q1+owDSfc3Gs?ht;3jw49c#mmrViUfX-yvc_B*wY|Lo7; zGh!t2R#BHx{1wFXReX*~`NS-LpSX z#TV*miO^~B9PF%O0huw!1Zv>^d0G3$^8dsC6VI!$oKDKiXdJt{mGkyA`+Gwd4D-^1qtNTUK)`N*=NTG-6}=5k6suNfdLt*dt8D| z%H#$k)z#ZRcf|zDWB|pn<3+7Nz>?WW9WdkO5(a^m+D4WRJ9{wc>Y}IN)2Kbgn;_O? zGqdr&9~|$Y0tP=N(k7^Eu;iO*w+f%W`20BNo)=Xa@M_)+o$4LXJyiw{F?a633SC{B zl~9FH%?^Rm*LVz`lkULs)%idDX^O)SxQol(3jDRyBVR!7d`;ar+D7do)jQ}m`g$TevUD5@?*P8)voa?kEe@_hl{_h8j&5eB-5FrYW&*FHVt$ z$kRF9Nstj%KRzpjdd_9wO=4zO8ritN*NPk_9avYrsF(!4))tm{Ga#OY z(r{0buexOzu7+rw8E08Gxd`LTOID{*AC1m*6Nw@osfB%0oBF5sf<~wH1kL;sd zo)k6^VyRFU`)dt*iX^9&QtWbo6yE8XXH?`ztvpiOLgI3R+=MOBQ9=rMVgi<*CU%+d1PQQ0a1U=&b0vkF207%xU0ssI2 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..acf1a2dcaaaac8c0a9c212069fe3b6ac00c981a3 GIT binary patch literal 1566 zcmV+(2I2XMP)3$g6h=WqC1OlTaAOgL5Wt`Yjimk&s00;*KuK8&fy$!%VNnD`4K6ea=nnxwFvePG zi*%*56zMw95@u-Gx-hg9%F<=_Zqr%H=Q)>ob>_{CP@LBp6HfBw&AZFH-*@jh_ntSe zPoMi1!Umu(pMx7pH$jgIeJ>uiukbZ{~h7yJZ2|RYVFK#|fYCzXV2)l0G zy4Bd#)ny1KTpV^WCwGoMO{#P{ox7;AeQvMsI>SxCEHf)6>VebM-K( zP^D6hA^}FJv;2X*4R-}?+PAuFJhh-+@<;Y-zA%u0P4(~<{bvnm=kht;E9ND8=S(PGPq zg?KOJ34DEgKF%~2Vr^a|emcF*t8K^$I9{KLn9R{weQYu=G?#Syd~EhhNUh%C)jnhd zFwtX|6A_(00y{NpVYceJ>#X*6M5PTw;guBcexV|utRWxsGe?O)ZMB&_>U3>4Fe7C! zxl)l=zmO1M>S)Hw+}9CzVi7D>gD7jWSzveC#P3?;c})K^99PX%UVQ^Dz~QvxlHm+4 z)1dnH2HG_`y#|#d@xpgla`;7DF;$9tvsI7nCzs=FW3jkDb>k>z(oQ6ab4S1hu)lt# znuoa=&tb)p*Ju}6fTOj)qoK7ourDb^lXQ4uXXv;1pLL4A_6#HVHZlS*iHx1 zBz#-4q&tV<9p}@+8N#P|rRJm$7dwujqmfqU4SZfS8>}yayKt^aC0v4u?kQW3yt*VrCWT>n&Z~I)z~fk)H69Bo zcvt2|AeXk?)=tmU*dG)Vz~CK-U5QD5Oo5nqVJmI1t0~KTO3X5^z?8)Pn40{kh#6ij zUOD+o%fCTU0Sw+fIM3Nux=b8w>`Jp!hfse17$Ql)hcx3^+P!FMtrxK)?|&yKE-EOc($dU{6DP9!@ONwf0@z#)!U)esMn+DKjg6fi6B82@ z@YqwxmVr_nD860_bo*1Z+i$LyQm1d Q9RL6T07*qoM6N<$f+36VTL1t6 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 4f0f1d64e58ba64d180ce43ee13bf9a17835fbca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 982 zcmV;{11bDcNk&G_0{{S5MM6+kP&il$0000G0000l001ul06|PpNU8t;00Dqo+t#w^ z^1csucXz7-Qrhzl9HuHB%l>&>1tG2^vb*E&k^T3$FG1eQZ51g$uv4V+kI`0<^1Z@N zk?Jjh$olyC%l>)Xq;7!>{iBj&BjJ`P&$fsCfpve_epJOBkTF?nu-B7D!hO=2ZR}

C%4 zc_9eOXvPbC4kzU8YowIA8cW~Uv|eB&yYwAObSwL2vY~UYI7NXPvf3b+c^?wcs~_t{ ze_m66-0)^{JdOMKPwjpQ@Sna!*?$wTZ~su*tNv7o!gXT!GRgivP}ec?5>l1!7<(rT zds|8x(qGc673zrvYIz;J23FG{9nHMnAuP}NpAED^laz3mAN1sy+NXK)!6v1FxQ;lh zOBLA>$~P3r4b*NcqR;y6pwyhZ3_PiDb|%n1gGjl3ZU}ujInlP{eks-#oA6>rh&g+!f`hv#_%JrgYPu z(U^&XLW^QX7F9Z*SRPpQl{B%x)_AMp^}_v~?j7 zapvHMKxSf*Mtyx8I}-<*UGn3)oHd(nn=)BZ`d$lDBwq_GL($_TPaS{UeevT(AJ`p0 z9%+hQb6z)U9qjbuXjg|dExCLjpS8$VKQ55VsIC%@{N5t{NsW)=hNGI`J=x97_kbz@ E0Of=7!T)7 zvNVyM7`w00`wx77dCzs7bFOop&*wS!^W67&o;%j?{yipoK6(lY3MOqWO{3Gh8~Hp> zb9zm5GVi0HV7REQdE3Mvx{?*}WcVv*_Yu35rL=p+BexZw--}Z@^*eQM(Ok6nU~|}83do&+L%0C zsHQq7=)8jz9OLHXy1CqrDXIPfquqf-M>8u|gQTRNj79usTVS5W*aPDUBgYr-cTg$l z=t%)HGOC@sd{(Y~gTGa3XMfBQ^Yz%W?=6=CZUT3y%^Dtm@Jns#r_~#HL4f%J+tDS_Wi1|B}s7&y<)&4E1 z;>ny{m#z8!7QIkN@pP8?7Exrj7;y@~zvOGmZvuCxg8Uz1#f zktyIXsdPDZ2)<9W0elpqJ6kNqT3pqW>lxD(q8HyNbIdMYylz1VEJd}@*Va!-9p&^i zr(||ApOV&@b1tpPd`HdBBX%$8jn~@#8g6rRMkX;|{p7$XOfn>$*gs3G#*!-}5#C`F zYMaA5*<=HYRfZzI*!H`aTu(){jD!-F!rsQpSpU-pL!J^1^P{EgYPPS!ZPL~j2ZBcy zo3WD>3=*#N_{Og`@=gUWhT+sdUD^gP(-HUHYEvEB=i!VF`X$3~K)Zv^@7O#Fj|g**1WI z_Sh|@`dn@4W29zmM4g|t{N67G4KukB!65y3q3k~a#)JMD|3>y28Z(3cwk&I&S36

k#HSQWY9&E~Na=UZmgmj-QX-0`m1B{E%xPPHy z-bH-D_Z0l+PB=c|#R@S0dc*aMhPc@&X0dME)-NcOo?UIOuRw4TBH9hGU@sb2u87jN zcYS1dFsB?U;m-1og(*l;^G(f-Zgn`2;in(eTZQP&dhwwnb=bA z;q_@1pN_ZQ1}|={9d<{i=^h4?#yxc>h9z;dGRJ z0>EOfuVc$X9x=sqg&~Jc=FXmi@4Y6Aok~c{iDXDj*S6v>J_7*y!uwmomdjxi1`+@? zgr2PG8EWv*`m^_rKcLF%C8aL6KvB`y&L)&SUeFa|m(*AwX!>VQc~usW+R{wT5@BLf zE}KH2c}|0FH>|xJ9l$F{<2IVIpFN`HKW`KCb7n7b(f2_Nu++SIo%#I4EBf98T4x$b2=a#4}HE zZe1liB(b3_6=9B&^KaXLKA|O`im0a18NyuqGM|j zg<{;iG%ek!hut)ru)gdbgu8))ZREZVhxxfYPGXKyb0oYh;BVQFBd$khWPatN3u4lkMwlW>?Fy?yI%$8s%~}*mCuotIqb#so`k`c0EXtH9 zqgxX_&?~f+xqIxiGH9-GH`-T*+rc7=nN1AnA+U#Cuz-p#6NG{Ks+h^3szhCW(eCze zKrN!9pKkM@+Ee69`_N;4vbJ7P;MmX6&)aT5Kw3@oBucq}InC2er4mM(pu@He@%# z%qTL(`rme}FFHr^+>O0G`?5#&qZrg_G3P^FUR*)XCsvGoZk#xomb>)SKnB0>SE8QN zH+%9*m&&ARv38tuVi9c}Wx=nM%RTK`4h|h~XoJleW5gY$Z8o^zmOV4;d&O3ZRorHNDXTgvox4KKH*T>IfRs=)zeUB7KceWbtNdc9>$0y zW~76=!oCrYnbd9=IJ``clt1RLDm3^!Xx=;z8>Bv~S){?uG-*vFk99B|rDAq4+*B(| z4iQ`o+fiAB_y=%KIMD3t5rjAbAJo=)3-3Y6-*%=FXo|=7p#;K2!|!<0h_ws(G%Mm%tQsam(xrDKbFFe}IhFfBOu0Qk@(hZb8+oun)kL782f6cVNO}5sMqH8qFZQ9|582O!h zI2BI2R4v(cQt5J6jh3f8!(ZkqX#~n9FWY=xsvtlAmqzaYc9`Bu0%Vi=oacmUmtr){ Ub3W_&scWXthTPYzyki^rKSso&D*ylh literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..81943f12ba9e16cdac3b26e493eabf9994eb1414 GIT binary patch literal 2775 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp deleted file mode 100644 index 62b611da081676d42f6c3f78a2c91e7bcedddedb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1772 zcmVQj4N+cqN`nQhxvX7dAV-`K|Ub$-q+H-5I?Tx0g9jWxd@A|?POE8`3b8fO$T))xP* z(X?&brZw({`)WU&rdAs1iTa0x6F@PIxJ&&L|dpySV!ID|iUhjCcKz(@mE z!x@~W#3H<)4Ae(4eQJRk`Iz3<1)6^m)0b_4_TRZ+cz#eD3f8V;2r-1fE!F}W zEi0MEkTTx}8i1{`l_6vo0(Vuh0HD$I4SjZ=?^?k82R51bC)2D_{y8mi_?X^=U?2|F{Vr7s!k(AZC$O#ZMyavHhlQ7 zUR~QXuH~#o#>(b$u4?s~HLF*3IcF7023AlwAYudn0FV~|odGH^05AYPEfR)8p`i{n zwg3zPVp{+wOsxKc>)(pMupKF!Y2HoUqQ3|Yu|8lwR=?5zZuhG6J?H`bSNk_wPoM{u zSL{c@pY7+c2kck>`^q1^^gR0QB7Y?KUD{vz-uVX~;V-rW)PDcI)$_UjgVV?S?=oLR zf4}zz{#*R_{LkiJ#0RdQLNC^2Vp%JPEUvG9ra2BVZ92(p9h7Ka@!yf9(lj#}>+|u* z;^_?KWdzkM`6gqPo9;;r6&JEa)}R3X{(CWv?NvgLeOTq$cZXqf7|sPImi-7cS8DCN zGf;DVt3Am`>hH3{4-WzH43Ftx)SofNe^-#|0HdCo<+8Qs!}TZP{HH8~z5n`ExcHuT zDL1m&|DVpIy=xsLO>8k92HcmfSKhflQ0H~9=^-{#!I1g(;+44xw~=* zxvNz35vfsQE)@)Zsp*6_GjYD};Squ83<_?^SbALb{a`j<0Gn%6JY!zhp=Fg}Ga2|8 z52e1WU%^L1}15Ex0fF$e@eCT(()_P zvV?CA%#Sy08_U6VPt4EtmVQraWJX` zh=N|WQ>LgrvF~R&qOfB$!%D3cGv?;Xh_z$z7k&s4N)$WYf*k=|*jCEkO19{h_(%W4 zPuOqbCw`SeAX*R}UUsbVsgtuG?xs(#Ikx9`JZoQFz0n*7ZG@Fv@kZk`gzO$HoA9kN z8U5{-yY zvV{`&WKU2$mZeoBmiJrEdzUZAv1sRxpePdg1)F*X^Y)zp^Y*R;;z~vOv-z&)&G)JQ{m!C9cmziu1^nHA z`#`0c>@PnQ9CJKgC5NjJD8HM3|KC(g5nnCq$n0Gsu_DXk36@ql%npEye|?%RmG)

UmY2RIYtNPVDpE$%vda+HD#3m z&VuXJ{BK&Qe+rBa7eq}Q(bq|tn(RrJAk|ztj2(i{d>nmQnM?;HF2k&9sA6up5tmjl z7lySlzMbifH17-m-Lwa_F&e7nOH?ESi3#ckR3tsM+jsck3`oG!uMS}|eAwVXv>}qxwq?QY%QJ0}r@^;fhuUA9W z*BVl>TGo&N004@xSiwDUXUvp51sVmqO3m)=B55aPwf@0=e}cN+$-BdKxY`YrT_4)0 z_d10#i44Q*rFr8MC>*)v$EJvz``(pb{e&*6k+b zsMz%($|1+8hn8c2?P(l@;Rb&CsZeYoCI3?2!LqjbwPXW3z4G$Qfj=cT5Yb%vY0(AX oeb?AaKtwrnc|$|zzw9vfvn^aJJ!zd)XFXqqy0000001=f@-~a#s diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file From c6ec8d8013acbc0e6145183bb5f2e7784eb25f3d Mon Sep 17 00:00:00 2001 From: Arif Dwi Nugroho Date: Fri, 16 Jun 2023 21:27:47 +0700 Subject: [PATCH 72/73] modif: add share and change logo app --- app/src/main/ic_launcher-playstore.png | Bin 0 -> 48545 bytes .../repository/PreferencesRepository.kt | 3 + .../ui/screen/home/HomeScreen.kt | 2 +- .../ui/screen/setting/SettingScreen.kt | 15 ++ .../singleArticle/SingleArticleScreen.kt | 18 +- .../res/drawable/ic_launcher_background.xml | 236 ++++++------------ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 +- .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 +- app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2806 bytes app/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 6267 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4780 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 0 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1921 bytes app/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 3728 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2936 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 0 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 3983 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 9080 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6840 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6487 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 16474 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10931 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9265 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 25253 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 16225 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 0 bytes app/src/main/res/values/strings.xml | 3 +- 34 files changed, 112 insertions(+), 175 deletions(-) create mode 100644 app/src/main/ic_launcher-playstore.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..18cd0a229ff607430e4346c7ace067727f975732 GIT binary patch literal 48545 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 `Q^u`-+ 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�RgcCUm6t}ritO^tlAP9E+#s<|pt zx{w7A2`8k931NDRN>6|d`f##qB#nYQE4n~KU*2_*!WI*~+IhXWW4->_Yz1K`=H+Fs zejiR7mjt)oU}~Cxf|!#hi|23mnO2$D!FM4naGDszf~*g6R%^e$6XJHt3b1qUoE2gT zjF_W4PMF(9srrp9d+ri9prY`AZxg~5be42}>@4Lh?fk?UE(xLVFi&ayZ7{$vN`jbY z2^MJ!KMpVYZ>wvBf7EPJQ8(RGN5%##xJWzSiW7GfUN^7&+EI5mxyHUQICpV}Wnz-B z5Xf--XB3}1B7+U~j=!tz#k85Ys-{;oF^a*XuwHxg8h_)qik%}n&Yhz;_ovxBO)9vS z`)?^cExIfREypZpEtlgrA#=$W74H6XR_;C<>hAF2qGCme|9=Z2+bOU3C%za+z#eLw z5Px#5-{mIUiQCbDdV>rnDUg;~RFr zdq9K|a11$vHGO})#&k`FN(DP#FEO3?{Yo^Zmp`b(ZZ_?f|bKAiYQqlbo zbj~an?IhqV;4J8T1S6a!q$4tMc?G}Pg``VkIIX-YBk(Lfs5&rN#i;gJkrlfG!ZV8o zP7{^bxp^etZIopadK&R}FOXvx0^c546>Va7KPe}Ieuen5@Iui?CGM$9C5AIU_<}>e zNcBjUrshed0&`+W8$luUZK|ZXIdul4kXb9L2CjuR1VgAZpYuc3;3d3&Meskg89Z{ZFtN01oL#K>R`cC<2JVvxC;C7i;wmJ-`c~}tuw2f1;7xe9Ea+*`L)nh{IL%U!qR!<5SF~ailoz$l z@b7)H#1J8jwLJ(gO9y9uq8TjDSpe9_Z-Y6FL}1Aiv2BI}c8a&sjW<{C!@z(&eL93p z<)clzkykJB<2t&c{%6bSbI2Tp_mSW9_F}&3x=td3jgT*M3Z~|sEEz(XDKbJDTf)v$ z8+!gbO`3oAV?W7phiIS;(cRO64gN)pqDeRHlDg^7i_KX$Vlgs|A%xB7izJ2*NKcU$ zW}Ix_`E&pK_{(@pI;A%`b_%ytUxvbW8wNI*-cc}sb(}zCCHf2kw~+#s*4W=8un+@& z0Pz~CbGc|R>+5sC)aV&h#}@RxbCVeIo2r>ZE%k9eQ=!UguaDM(6EPK&pP5auX{5?XgwL9My463}L%A z3AR%30(^~Go84%{Ypt>5ifTMk8NoF^c>5C Unit) ) { + val context = LocalContext.current BackHandler(true) { navigateToArticle() @@ -265,9 +271,19 @@ fun SingleArticleContent( Spacer(modifier = Modifier.height(36.dp)) + val plainText = Html.fromHtml(result?.get(0)?.description).toString() + DefaultButton( contentText = "Share", - onClick = {}, + onClick = { + val intent = Intent(Intent.ACTION_SEND) + intent.type = "text/plain" + intent.putExtra(Intent.EXTRA_SUBJECT, result?.get(0)?.name) + intent.putExtra(Intent.EXTRA_TEXT, + "$plainText\nSource: Techwaste" + ) + context.startActivity(intent) + }, modifier = Modifier.width(150.dp) ) } diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml index 07d5da9..ca3826a 100644 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -1,170 +1,74 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xmlns:android="http://schemas.android.com/apk/res/android"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 6f3b755..c4a603d 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,6 +1,5 @@ - - - + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index 6f3b755..c4a603d 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,6 +1,5 @@ - - - + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4b41879d3ca82bbe62a587d1e724e28c211c5480 GIT binary patch literal 2806 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 IM6N<$f)`3@zW@LL literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index c209e78ecd372343283f4157dcfd918ec5165bb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1404 zcmV-?1%vuhNk&F=1pok7MM6+kP&il$0000G0000-002h-06|PpNX!5L00Dqw+t%{r zzW2vH!KF=w&cMnnN@{whkTw+#mAh0SV?YL=)3MimFYCWp#fpdtz~8$hD5VPuQgtcN zXl<@<#Cme5f5yr2h%@8TWh?)bSK`O z^Z@d={gn7J{iyxL_y_%J|L>ep{dUxUP8a{byupH&!UNR*OutO~0{*T4q5R6@ApLF! z5{w?Z150gC7#>(VHFJZ-^6O@PYp{t!jH(_Z*nzTK4 zkc{fLE4Q3|mA2`CWQ3{8;gxGizgM!zccbdQoOLZc8hThi-IhN90RFT|zlxh3Ty&VG z?Fe{#9RrRnxzsu|Lg2ddugg7k%>0JeD+{XZ7>Z~{=|M+sh1MF7~ zz>To~`~LVQe1nNoR-gEzkpe{Ak^7{{ZBk2i_<+`Bq<^GB!RYG+z)h;Y3+<{zlMUYd zrd*W4w&jZ0%kBuDZ1EW&KLpyR7r2=}fF2%0VwHM4pUs}ZI2egi#DRMYZPek*^H9YK zay4Iy3WXFG(F14xYsoDA|KXgGc5%2DhmQ1gFCkrgHBm!lXG8I5h*uf{rn48Z!_@ z4Bk6TJAB2CKYqPjiX&mWoW>OPFGd$wqroa($ne7EUK;#3VYkXaew%Kh^3OrMhtjYN?XEoY`tRPQsAkH-DSL^QqyN0>^ zmC>{#F14jz4GeW{pJoRpLFa_*GI{?T93^rX7SPQgT@LbLqpNA}<@2wH;q493)G=1Y z#-sCiRNX~qf3KgiFzB3I>4Z%AfS(3$`-aMIBU+6?gbgDb!)L~A)je+;fR0jWLL-Fu z4)P{c7{B4Hp91&%??2$v9iRSFnuckHUm}or9seH6 z>%NbT+5*@L5(I9j@06@(!{ZI?U0=pKn8uwIg&L{JV14+8s2hnvbRrU|hZCd}IJu7*;;ECgO%8_*W Kmw_-CKmY()leWbG diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..ec560b01847f7916ddf160ec4e3f03311323fba9 GIT binary patch literal 6267 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 QQvpFqUJY0!Ya0Cj0NDH_1poj5 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..427b3606ae7563d335a964340391ddc380aef20a GIT binary patch literal 4780 zcmV;d5>xGoP)HYnl-@Tl7eg5a!&$%c{O*X02 z0nM7FSX`0TZ=CkqZNzNg8bx?*R;>6mb{E&2=KR(GgCu}CmIxPZV5D-_$c;+V5iv@e z;gL#v5WeFY`i$ezN?Y^4qG@+se{D#d^827@t9MYe<&~fqu_7>9>=+&;l7phf<-jO$ zGbl>rf$*LBE~5`)cx;qqI_6>x{hH;K#u{%7icSqi#wqs^!{dqZ4Fp6weM(SZIZ2zx zYeb7MtckT98`GY~8&azp?xJ4g1EZ{u5F=j^UD1OQ6e$V=BSZmHq$miA5QTg#O8lxP zTtgqmIL6!iiU7mfvjaG9u2%v5s_wymtCG4FXEC0y+S|naicR|-7;TwCz}!-S z(GFdez!=GCPdZC3&gAN>)zY*L12-v+=|JI{!~{f&d>4nWR?^O(N>c>Rs6TU+H*KTg zF?G8Pj}~Wf5FDy9>`P@4&Y}TDp~Bg~h`L?%XRorR8NQ$>>i~$c29EK7wS{zN%MA>( z`sjJ6^yW~jND%--%p2|Jn@B z$e6q3`1s~>_Fi8Zmi(dIpB}+~bBKX45kd|Q5rgzR-Eq@Ia(H;%F6zAP*(_{g0lv3O6l=7!|2BqD|N!*A{Td z4$5Z}TFQk-#>wNCx5yiL*JObTj7A62BjsOX>KDyZK^ht+e)e6c+^grYLd_8bM%Z0> zZ86BBVt*$;*gsevy_6tt<=UT0XKSu>7Po`WuD3_ghSx(yAjt%q8yeyWc z6(?WiImUIs3#pp)U1gc3=e5jDOZJ{xuecF7IefSpj&nxGHk9)Zjgc3!Ps)PAdEcuPmNK>+aIq<+SAK%5AZvl+TxbJt@$=6c>0IeVXm!x1nLyzN$;F&Ya3baMN)=FJ`6-3Jb_Hog|MnkU(<=Mx&1pj^wddZl%fB zcRXV1*Awyg>#z+%`Yf^z(DPnm(;4R2n)X_-Cor^mq%JVR@K&$w=xvf3JuNvN%m8KF z{8>)f`k<-biB#VFzYz&aSq!!&W`P@Ry&M5y4N1_*n0oU2q<=V!@xkHBGz*u2KF#6H!F3G0*kJ&Ogc2 z>xse%-#0Ox2FE$2q3{&_giS0tjEHs zsk&DuV1xL+rqm1We97?_*^S?(IOp5bZ#t(6>X_vxrm-r$u=$Tpea~-pCy6`C0EH&a zF|A)Lsl56v6_JF2i=w~!m}bB~l_sQ*X&79bdLbx#Z|?y4|2zLo2Wl^$-gGZ9(ZCU? z-3h^{BKQM?XGpbN*&TpzjU+2C|CapX*mHEPC{lj;hwd^n=NF#8=-4FF+~P=6GfF?w zJtrzH^q6qd5c3bQdb9MD;JId#$Rjbdhxy2VE^h@k7W7q??d=B2U?>V=#*}cY}`-;mC&%`x#nG3n1$(udc^I)w5=}~fQ+#gJ1 zAYmsnckq}~nLF7i>-(XS=u5wmB466t*)+c-A}K0Bel}pC1{)VpX%yL; zgLH?rJFUeUf7{fAr6&H|5|W}sM{NcS?M_=Sr*G@QDq>s@gt!N>4#p>4-RDwzAQ9)X zf8;UnRL{n@bn1V7$N$PJIjP(qlK57cCD%b}t?0>RVi#diw+I*27`eGA^#V4EpD?&2 z7Y`=GQ$FE?K$1{m(DwttsXug)tH_?D-biAApoTEM^AC^VJ8fKZ>ejAgcdoK+S)2Hd zsfGia7IXG9yYx_G{n3FyCjf@i_|T-eJRgzw^zELeJxU{f1Wtzf$yJu*rcITG4&l*) zqCZVjnvsa5^Wb7Um`49TGL`{?fu6auZ_y?O2|+Ftd1is5s0ADK^^Y$xh>khLsAhPx z^D@~xI`3y?gA2w1^v=|E>^1dcg12;%nYZlHb0{OmbdIu+BVb%3GP;e@1&kU%UUL*T zLNQAlY+OK3|3~ih*6kZylUaOxGAEB<@?_?AIb-LeQtx^pF?071R@I|`?aa5QXF5Pa zn6Ni3jG6oC>RywCy+qQ8f*ATy3xX@x_ait2Xy``nD?m$!A7X=Il$?pkg-tKd6(`f-SGEB}W4 z$NnLXv9LQUPrk<2F&_JkiM_|s59a`T1#lplM=r%v7|_PFXF13L&_m;t?k0eGzNWZS z9FUE{rKuR`!vg{A%HeWheBU73af#!j0`f?kwC8YPLylm*Nh_)v6;8i-R=&Oa3BC^CrctmQvlko>rflsk+via^8Vq%>331t2j>rb7!&+lceFgv)i7swG&6&7^4xQ zZ;V5(m3U=0UxVwPe|R*{!85RLPQAgN6MX;(PdAKVMny?;^L{HVDM}-yi8DZUkQxjP z72A1234x-Xrcm&vkE&nT(t%YW;>@RNzE;4AC5&hAmIoX;8f;it@;oPiR-Bm5sl=|- zPzUI%Pt9PvGIyUpON!mz6w1pv=jEEjw_OI56(%)M9JEC2AuJl{aB-v>cMtwntkMRX z7H~mGA&@mg)S*_}e+gkJf)_)k4RAC70OTUNhEgi#A{@{Igj54|#lF^Ux$VMgF3!V+ z!-HWA)ECnA_MRtrALDuMh}2Z0{{pcNSU8nD)Woc=&tl7r(vnpp!NqSrzl@_?Fag60 zX+a;-1Gs4igT(xa%xzo|fD4Dm)2^SUOyP@4FbzAc08)dp01Kyr8Jdb%<0n^(jq0Q_tC>b4N!>m>`YZvn+u_L|4fqZqc&CN>Ob*`B^Z;+>gtVzyA9@0yFucJ;1M1T%o|@% z(Fl@+I0%OQ`2_b89}HFnky$B3HSv+xEw2Fs&o5lPTxAz2Tid=$Co)zUJh7Z=W+X@e zRPP;1AmPDK@q>GhNcn`~rIoBo00@z{<3*?HCQZFoip#BfDtNKVW>PP$b)KcvrH>|q zzAC-4SbnmyWB@cIs6SlzhQUEF`0=3;Rc~jCA+6N<_&l)|ysH?vZmKt{-(#}y!=%y* z_~j);%6JI4_u>Y7A&pcHk+(7XuQrNQ6V$arJ~&DQfOnVnN8daK@^7@7`z;soyhtTU zQ81+!sQPJM48|Mal;Qb#)sf2EU*?N##B&Rk_mZ26U_;MIA~0a%ol6nk(D>r$M0qaj zxa!sm$Z((I7Zb+DH8qW|HqxYLjgVc&h%wCbL|4YyMRW5~>d{9_pG6`J?ysURP$7{_ zpd_^Db-CMeKLwPCi7Gu+C?{#J;gRjZ)6|wK&t+?YfozK!-tVRKK?#zd)tBPY?C%eD zld)$%=PY~8=~-$y#Qw|-sRL?AWqAZt<)mfq%SCpp-ikMP_3|pk_86PnGmL2SKC>*d zkfRVtCEB9#@%OQG6va1o7k-lh#MrZ+$;sroYRXeN5z-3cWyp6z_MB>&10GukDt8eqedx`KUuZB=ZSdYt-Z>l>$s=1 zri$IY4Vo$4eV1F3v565RNX5H*`ms7?knz2$mQyuCmC3n2T#IpH%A8$9?X9QGETsA$vr+t9Si~ZBSQEyt;>fBY~$3sP+LIJmkYOG~+>Q zgisKJ-B~8CyLl^v!IR3{oi~aP8qr7V?$6l9Jr!a%aC(qX*+WTm=B~%&#TzLc>)@^T zE$3Ir3Gpq=hplc>!SP=y3cHT9{hfGeqw-WS)pF75kQ=;*KHWV3ZhLX?YCA~UyT&*K zp3QGQznr}l9_1imeOmXJrbb8&Q8aM6kF`w&5BK-s-)U4DI9jtb?#c_hcYE44fs#9Z z3QNQw!F?lIMxIq$ycK=2&GB6-vQ^1(Z`7F!^5%CCE2&vp_2U10(5{WQ@b~%BlA=c2 z_^Eb@aZe;Id9IaVeKf-sRt*yS&^YM>FECrKXvQ$;B z!fDAJ6YZ_36wc)Jfrzu+t@OfK)iYN)I9jW7uP6VSxD`>CUQ?~_`z{yPxB^fUKA$Gol7vsSvzDXrCM*;1)b@dRFa?9ifzb%57g5k5FXK*Sj+)LN=k z_3Z!Ff;|*$4)*RlTSTMXb-t&q)!XxV>rBdhVg`L}xq#{&3go!+kO~KA#Zi=f?65F? zHAP|#?+-;Z*2LP_1AAdl?2R)xov4;Jfh4d&JC>+6M0jJXYr_`SM>_@BCiI?Wo%h&W z@m;?KV%NY$mPEg0mQ=r0BGZ4h$O7TJ-*QXpz{QqCjPa(iy{B8}VJ_BC?9zfY@5df$ z!uekTjImi159KZdn5z2W-M{uk4-j>+*=!FH^#s$+x>)-+e@F}j;XAHT-@_P#vFaSm zZH=`!X!YO{X|=iTs%{oihPt@hh-QD+UTM~#fzq6=LmdGejC@;_@EzA$U<}4$4ogaB ze(La>0i~qIkGmC=R6G@%2T6mQn^F&i@3_W&b}(wp;Qj|w6D3QLz}e0K0000` literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp deleted file mode 100644 index b2dfe3d1ba5cf3ee31b3ecc1ced89044a1f3b7a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2898 zcmV-Y3$650Nk&FW3jhFDMM6+kP&il$0000G0000-002h-06|PpNWB9900E$G+qN-D z+81ABX7q?;bwx%xBg?kcwr$(C-Tex-ZCkHUw(Y9#+`E5-zuONG5fgw~E2WDng@Bc@ z24xy+R1n%~6xI#u9vJ8zREI)sb<&Il(016}Z~V1n^PU3-_H17A*Bf^o)&{_uBv}Py zulRfeE8g(g6HFhk_?o_;0@tz?1I+l+Y#Q*;RVC?(ud`_cU-~n|AX-b`JHrOIqn(-t&rOg-o`#C zh0LPxmbOAEb;zHTu!R3LDh1QO zZTf-|lJNUxi-PpcbRjw3n~n-pG;$+dIF6eqM5+L();B2O2tQ~|p{PlpNcvDbd1l%c zLtXn%lu(3!aNK!V#+HNn_D3lp z2%l+hK-nsj|Bi9;V*WIcQRTt5j90A<=am+cc`J zTYIN|PsYAhJ|=&h*4wI4ebv-C=Be#u>}%m;a{IGmJDU`0snWS&$9zdrT(z8#{OZ_Y zxwJx!ZClUi%YJjD6Xz@OP8{ieyJB=tn?>zaI-4JN;rr`JQbb%y5h2O-?_V@7pG_+y z(lqAsqYr!NyVb0C^|uclHaeecG)Sz;WV?rtoqOdAAN{j%?Uo%owya(F&qps@Id|Of zo@~Y-(YmfB+chv^%*3g4k3R0WqvuYUIA+8^SGJ{2Bl$X&X&v02>+0$4?di(34{pt* zG=f#yMs@Y|b&=HyH3k4yP&goF2LJ#tBLJNNDo6lG06r}ghC-pC4Q*=x3;|+W04zte zAl>l4kzUBQFYF(E`KJy?ZXd1tnfbH+Z~SMmA21KokJNs#eqcXWKUIC>{TuoKe^vhF z);H)o`t9j~`$h1D`#bxe@E`oE`cM9w(@)5Bp8BNukIwM>wZHfd0S;5bcXA*5KT3bj zc&_~`&{z7u{Et!Z_k78H75gXf4g8<_ul!H$eVspPeU3j&&Au=2R*Zp#M9$9s;fqwgzfiX=E_?BwVcfx3tG9Q-+<5fw z%Hs64z)@Q*%s3_Xd5>S4dg$s>@rN^ixeVj*tqu3ZV)biDcFf&l?lGwsa zWj3rvK}?43c{IruV2L`hUU0t^MemAn3U~x3$4mFDxj=Byowu^Q+#wKRPrWywLjIAp z9*n}eQ9-gZmnd9Y0WHtwi2sn6n~?i#n9VN1B*074_VbZZ=WrpkMYr{RsI ztM_8X1)J*DZejxkjOTRJ&a*lrvMKBQURNP#K)a5wIitfu(CFYV4FT?LUB$jVwJSZz zNBFTWg->Yk0j&h3e*a5>B=-xM7dE`IuOQna!u$OoxLlE;WdrNlN)1 z7**de7-hZ!(%_ZllHBLg`Ir#|t>2$*xVOZ-ADZKTN?{(NUeLU9GbuG-+Axf*AZ-P1 z0ZZ*fx+ck4{XtFsbcc%GRStht@q!m*ImssGwuK+P@%gEK!f5dHymg<9nSCXsB6 zQ*{<`%^bxB($Z@5286^-A(tR;r+p7B%^%$N5h%lb*Vlz-?DL9x;!j<5>~kmXP$E}m zQV|7uv4SwFs0jUervsxVUm>&9Y3DBIzc1XW|CUZrUdb<&{@D5yuLe%Xniw^x&{A2s z0q1+owDSfc3Gs?ht;3jw49c#mmrViUfX-yvc_B*wY|Lo7; zGh!t2R#BHx{1wFXReX*~`NS-LpSX z#TV*miO^~B9PF%O0huw!1Zv>^d0G3$^8dsC6VI!$oKDKiXdJt{mGkyA`+Gwd4D-^1qtNTUK)`N*=NTG-6}=5k6suNfdLt*dt8D| z%H#$k)z#ZRcf|zDWB|pn<3+7Nz>?WW9WdkO5(a^m+D4WRJ9{wc>Y}IN)2Kbgn;_O? zGqdr&9~|$Y0tP=N(k7^Eu;iO*w+f%W`20BNo)=Xa@M_)+o$4LXJyiw{F?a633SC{B zl~9FH%?^Rm*LVz`lkULs)%idDX^O)SxQol(3jDRyBVR!7d`;ar+D7do)jQ}m`g$TevUD5@?*P8)voa?kEe@_hl{_h8j&5eB-5FrYW&*FHVt$ z$kRF9Nstj%KRzpjdd_9wO=4zO8ritN*NPk_9avYrsF(!4))tm{Ga#OY z(r{0buexOzu7+rw8E08Gxd`LTOID{*AC1m*6Nw@osfB%0oBF5sf<~wH1kL;sd zo)k6^VyRFU`)dt*iX^9&QtWbo6yE8XXH?`ztvpiOLgI3R+=MOBQ9=rMVgi<*CU%+d1PQQ0a1U=&b0vkF207%xU0ssI2 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..860be820fe48c561000fbfc9b5932fc6429c6a8c GIT binary patch literal 1921 zcmV-{2Y&d8P)uF&EGoY>Yr1&w`qvT#T#DU|}s0eO?YyQ4=-(+nMaFlN@aFqKhoa3DpVo5uN z=S87e;eNH3!tvpX0w?*F0OG{wXwbMHT{8Ulx@P)=Q<@LB$BqE8#1h1pge?M(2rF>8 zy9g%U+Z2e@-fB<)mn@>2-d!BiHWfOh`haW9;A+oHmTJ#XVawp6P%RD>R(phZfQfOl ziyV$D?#Ab;Wt8#scS!hh+i|Hr&)jh3Juh0SbyvjPU_$V(`-P6Gp*x-X^SNpnH#qpj zB0J~n&PuVQ6}wpXhUNw*U~;ffHO$M(p3hawxWUg3e{DBK((V~|vF;5`1*2nO)EY8f{;ZdVUGj}W0*1Q6-@(ys9PjR_Ezy%(f82VgeFyVe|o0z@wn z;4d(_03yCn+8qu)SP2==5}=}{1YXqEz_t7!m>$+vd#*tNf|e6N1pN~|A-g1r5s%F~ z1%3%GP*jlv7c#dqas2ts5TJ33DFw`lcn>aR{RPioltbcE3H%)UIgVSvjIj1lSyKl8 zJY21JO)~^&22CYk-sKM!X2n(biY6v0ekjx#Bro6!f(f42!_oQ47voO?j?_o3n%OgLA z;>ujC7Nt;HRSfxMX%Lfl0=C?A!vyW3_h7>MYonp2wiIU|mV*6f^3^rmM^D7IjzBK0`N)OdO%545gbifr?&?fRRD!c999w{OAjJ~v%=p&54c0J zA_l#pfRiYSBfC)A4HT7mn83dE#K7-+6AT63P>!J7~HsYVN?MGsz#~G zI9A&!@dEEJg{Ku+tlCiMP&iPsQ~A6g-^OA*OLYg%quBhibSSLIhNH>ru=KvKN7fLG zE`WAV+Fc9EGeM3b{vyXrbc-Yop&5kl-DpXUa;IC;%XG3Ko1acY8`Z6R+<8n2;eXW-(jh{ zq>@VI@kx0G3lZvTs<5`7lW)biAFTJD+Z>ow03TFNDL?$;T`;`laJw+9(O#)3Fq;7K z29--9-<0y$RG3A;FR>#bMG?!wCMx$>eMvP2njt{cECE!*sj-X9J<95Qs`5Iv*vtYV5T{~X){Xdb;{-TLhy*_0HmI7&?2aNwnvBshz{5W zBe%BvLr6WVJAV>d4eM(^`s~VcPEj+JZf84|xCIGS?m@y5bAo&3q>~m((O%p0og8{n z_y`+3Bjc=YLR&=d&ZF(d*-Wu_wHe#awf9(o`QapV?K-^Uc;Z5w8YRyeO|%!=x5AI@ z5gl3>?FGoC$>jM)$>OkYvE~18KnTnLdXDCq4JYgydp+zw&oBla$;4>^00000NkvXX Hu0mjfKueV~ literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 4f0f1d64e58ba64d180ce43ee13bf9a17835fbca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 982 zcmV;{11bDcNk&G_0{{S5MM6+kP&il$0000G0000l001ul06|PpNU8t;00Dqo+t#w^ z^1csucXz7-Qrhzl9HuHB%l>&>1tG2^vb*E&k^T3$FG1eQZ51g$uv4V+kI`0<^1Z@N zk?Jjh$olyC%l>)Xq;7!>{iBj&BjJ`P&$fsCfpve_epJOBkTF?nu-B7D!hO=2ZR}

C%4 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

FJ$wK}0tWNB{uH;AM~i diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d86a7cd5e9488cf2061f4ea73644a19076c0e1be GIT binary patch literal 3983 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 phY&9pxyVH>a*>N%o6o6Gy zRq6Ap5(_{XLdXcL-MzlN`ugSdZY_`jXhcENAu)N_0?GhF))9R;E`!bo9p?g?SRgw_ zEXHhFG$0{qYOqhdX<(wE4N@es3VIo$%il%6xP9gjiBri+2pI6aY4 zJbgh-Ud|V%3O!IcHKQx1FQH(_*TK;1>FQWbt^$K1zNn^cczkBs=QHCYZ8b&l!UV{K z{L0$KCf_&KR^}&2Fe|L&?1I7~pBENnCtCuH3sjcx6$c zwqkNkru);ie``q+_QI;IYLD9OV0ZxkuyBz|5<$1BH|vtey$> z5oto4=l-R-Aaq`Dk0}o9N0VrkqW_#;!u{!bJLDq%0092{Ghe=F;(kn} z+sQ@1=UlX30+2nWjkL$B^b!H2^QYO@iFc0{(-~yXj2TWz?VG{v`Jg zg}WyYnwGgn>{HFaG7E~pt=)sOO}*yd(UU-D(E&x{xKEl6OcU?pl)K%#U$dn1mDF19 zSw@l8G!GNFB3c3VVK0?uyqN&utT-D5%NM4g-3@Sii9tSXKtwce~uF zS&Jn746EW^wV~8zdQ1XC28~kXu8+Yo9p!<8h&(Q({J*4DBglPdpe4M_mD8AguZFn~ ztiuO~{6Bx?SfO~_ZV(GIboeR9~hAym{{fV|VM=77MxDrbW6`ujX z<3HF(>Zr;#*uCvC*bpoSr~C$h?_%nXps@A)=l_;({Fo#6Y1+Zv`!T5HB+)#^-Ud_; zBwftPN=d8Vx)*O1Mj+0oO=mZ+NVH*ptNDC-&zZ7Hwho6UQ#l-yNvc0Cm+2$$6YUk2D2t#vdZX-u3>-Be1u9gtTBiMB^xwWQ_rgvGpZ6(C@e23c!^K=>ai-Rqu zhqT`ZQof;9Bu!AD(i^PCbYV%yha9zuoKMp`U^z;3!+&d@Hud&_iy!O-$b9ZLcSRh? z)R|826w}TU!J#X6P%@Zh=La$I6zXa#h!B;{qfug}O%z@K{EZECu6zl)7CiNi%xti0 zB{OKfAj83~iJvmpTU|&q1^?^cIMn2RQ?jeSB95l}{DrEPTW{_gmU_pqTc)h@4T>~& zluq3)GM=xa(#^VU5}@FNqpc$?#SbVsX!~RH*5p0p@w z;~v{QMX0^bFT1!cXGM8K9FP+=9~-d~#TK#ZE{4umGT=;dfvWi?rYj;^l_Zxywze`W z^Cr{55U@*BalS}K%Czii_80e0#0#Zkhlij4-~I@}`-JFJ7$5{>LnoJSs??J8kWVl6|8A}RCGAu9^rAsfCE=2}tHwl93t0C?#+jMpvr7O3`2=tr{Hg$=HlnjVG^ewm|Js0J*kfPa6*GhtB>`fN!m#9J(sU!?(OSfzY*zS(FJ<-Vb zfAIg+`U)YaXv#sY(c--|X zEB+TVyZ%Ie4L$gi#Fc++`h6%vzsS$pjz9aLt+ZL(g;n$Dzy5=m=_TV(3H8^C{r0xd zp#a%}ht55dOq?yhwYPrtp-m1xXp;4X;)NhxxUpgP%XTLmO zcjaFva^}dP3$&sfFTIR_jC=2pHh9kpI@2(6V*GQo7Ws)`j)hd+tr@P~gR*2gO@+1? zG<`_tB+LJuF|SZ9tIec;h%}}6WClT`L>HSW?E{Hp1h^+mlbf_$9zA>!ug>NALJsO{ mU%z=YwVD?}XMya)Bp;vlyE5&E_6!fzx9pwrdz474!~g(M6R?N? diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..9fce78585f7a699737ce700a800d632816720f8e GIT binary patch literal 9080 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 ausd5~AEiQLvA2mDIOX>m3UzXppZ^CE>tfsh literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..373dc13f52aa757f32f408ea98890c19a4214e76 GIT binary patch literal 6840 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

?j}V2FUyS!5>xz_?QUpw!32#BS!{*Q14{AWJ;e> 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index 28d4b77f9f036a47549d47db79c16788749dca10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2884 zcmV-K3%m4ENk&FI3jhFDMM6+kP&il$0000G0001w0055w06|PpNY()W00EFA*|uso z=UmW3;Ri7@GcyiBW{ey$jes55b5S`|ZVZ{(x$xch{z?D+^{yErVgleVwa9qvGt40r z42;MG=7<0QySlzE=Ig6%01!FBK^$Fsxe@Hfe6aCy?Wh2r0~}@_lQAF90oTUi0FhEr z#(*;kTC(r!tQk6;gxj4h%FdHAt(^M3YvYj(!tOeN)+Hvj6+< zzyJRG?^lZfWuR#t!tUKP&(?%3v&Zd$R2YN>lB(Lq`OInY48%4%yTv2 zYe1{G`3)(PDEio5Y@-I5tUf`c%%OCJMtSW56g3iEg%3`$7XSJJHyA z<|7&N)5Xrlgv~%BO24eFd;Hd;uiK%D`EdK|quUeRZDqbh9l)%j%J#0lfrZumvA<_w zu&=AVvdChf6}eqh(bUz`(`Ue*p01{fBAcTgKyDYLs_I+YyJEk+rM@avU~>fB$n)HS zM7pfJydu`i%gfS<{PF94kZDv$t>06sAkheDzu40NJ$5CMW%n^Lls?8^p^QGWURbKu3ZduZQZ((s2? zzE`}<{;Zt7<$C|9R8A~DJ~@%x>TfP zF>TX8)@v|t)q4GjRt<}5s6hLHwRel7>V@&r-O|Av(yh;Q1A{E>Ir>p+%dHD|=l+lT zpr(Dg&>#Nu=!)6bCLr-ZS%|;h)Ij$+e@r8_{qO19QvDe=&1tmpY*0lcA^Cc-#{9fQ z<~$*<&P$Q<_jy#<$40PMofM7aQ}C=jphI`4kLg}Z7CIN#26D{-4v-_CA-LiE@(%{y!BzsU%gG`Q?sjLUf%qFSl0y)2#ae*+EI>s|i`d^V$Dn)qmzqRq6VJRY|{4ujsIU%#bnqU6MR&-1I_43=|5(6Jr;Jvert) zE?S|Tmn}Tv<-??sxV5@9t}3D=>YZ0JrQe$CO~|EY=Lj9RM&4svQHPQL6%pV5fPFiH zfXDx;l@~et{*{U*#c#Dvzu)|znDO7$#CRx)Z&yp-}SrD{&|(MQtfUz~n35@RLfUy=aqrhCX0M}J_r5QsK~NmRCR|Nm&L z41UdsLjWxSUlL41r^0K&nCCK>fdR-!MYjFg(z9_mF^C|#ZQw?`)f6uVzF^`bRnVY& zo}@M06J&_+>w9@jpaO4snmU;0t-(zYW1qVBHtuD!d?%?AtN7Plp><-1Y8Rqb20ZaP zTCgn*-Sri4Q8Xn>=gNaWQ57%!D35UkA@ksOlPB*Dvw}t02ENAqw|kFhn%ZyyW%+t{ zNdM!uqEM^;2}f+tECHbwLmH*!nZVrb$-az%t50Y2pg(HqhvY-^-lb}>^6l{$jOI6} zo_kBzj%8aX|6H5M0Y<)7pzz_wLkIpRm!;PzY)9+24wk2&TT{w--phDGDCOz{cN_ca zpnm7`$oDy=HX%0i-`769*0M6(e5j-?(?24%)<)&46y0e&6@HCDZAm9W6Ib#Y#BF6- z=30crHGg+RRTe%VBC>T00OV6F+gQDAK38Ne3N9bm|62tPccBJi)5{B z4zc^Db72XiBd}v$CF|yU{Z=M|DZ%-(XarYNclODlb1Kz1_EKLy(NSLCN`eUl(rBCL zT*jx@wNvze0|TSqgE(QArOZU)_?qH(sj#TwzElLs9q)(0u!_P|R%Cy_0JFQxgGV>1 zz4?_uq<8_gM0`c*Hh|;UMz~vrg1gQXp{ufg`hM_qU;U>+zmvc5blCLSq@PrEBSGR# z&8=2Z4uXN`F3p73ueD1l{s{k$WipAvSh5W7ABe?4)t;r@V?y`bNB5FvBuE|0VRTb< zM1Hn^?DSsJY+sX@T5xW=#>T9VEV|?<(=6|ge$X6Sb05!LFdjDcoq*gM(Zq=t;_)Le&jyt(&9jzR73noru`a# zN*<`KwGa^gZU3-)MSLF0aFag#f0<>E(bYTeHmtdbns#|I)-$)mJ`q9ctQ8g0=ET?| zdO}eZ*b_p>ygRTtR^5Ggdam=Zb5wmd{}np+Jn1d_=M`~P=M67jj})fH4ztb5yQqQW z^C|C&^LHAK-u+ooIK)yM)QM?t;|<{P;;{`p=BclzAN#JzL4jCwXkQB1Dy{=^KR`=~ zTrr)y7eiYBzSNs_DvO=4A6#EgGS-zY%Vi)N*Yb`U;6o}KR}dq{r9pT5wqZ@3NOE8- z9-(}D|Nc5732CSYQbL)!gPQ#RbD8BhK3dl{sUuPvei0tkvnJBxDEAYTesU8H$)g(Plra{VH(v3u^CO1~(+ zU0O7#)jaS4{NcwA+LuSm&VBcX2#Im3xg)W}ySNw%->orn1taZ&+d)}8gJTqA!u|5P z{yv?zol_3|(1(%M(EVU=cp?L`{Pi|ixk{U)*guFML3P!OSlz;zGA#T+E@8@cgQ_mv1o7RSU=Zo_82F?&&2r;WE z@wk}JHYEZ9nYUc(Vv~iTCa3u8e4q(yq<29VoNbKk|`mq%I6u)My=gPIDuUb&lzf4`MEA9^g8u z)vp8|$$HE9m_BTV?lOosIGa4jud=jIbw)O2eCMfyw2*S8?hjWw^nqws$O*M$3I1)x zR0PWFb3$ySOcGTe1dz%N0l;RPc`x%05FtT^f^j{YZg*j8g}V%xTDH*Rd(PVVHKd;Wua*P49E+I!x;U;OZ3 z!sKPeV4<*}zJ2=!D>1wcf(!Cd>D4E z5~`DUA|N5Gfoxw6jPg4>q&J9%t$`$2CXuQ`S#>=agOz4v&*gGrU?pW|1_>)AOu-Nw z*0rd3D2YW z|M8)^B#D$w9*T@_OT;SHARW@+(ax7rn0V4{D7cNG8Ge%)V5|-si0W-Z#;IoJ- zV)N8jV&pXV*z>-eFQ&=>67M&yb|t&6+OpDe98VLF*;iOc&QD_Sqgo*%a)jH z3TBtG*X>}u#Lu&!*TC1pO`-5S2leC_)~?^^*yy8vyy|dwa#qeQ1{cZm&lsSJ(}d31 z+KvfthXmuWpFgx9UpfmZsM4JcDc9=f*>MBZ;f|7N*&6uat}+2s*?w~Vy)i=yqg5ry zx?%lkc-L3eZCpc`>YDJFhJklt{0hq8r@?BGQ+8Ymo_^O?3@mP)0qMq}FR$1>L`ZDy zTK2nKPS?35Gzi*;M6yrAP1r+SOHS=RlxLVd1(Q9cugZ?4mol1}Q8=c_E%rD2askI7VI?bRn-}eh*Dip$OhraaLe_+SO7Z z?zDYS_hwQG%7D5dOudMF0@i$k_GUHQv!Bm})&1+0DniLI7|)FfQvQukYhW*aujd_pT9n z4wC8*|7?!no(-!X+_xbmk`_vcg$`|~$b(*R<94p-_aol2_EM&yWyQ;IlDz(PvU?$( z_RDkRZ!qo}8}rqkTDtFPLHW$q;;89D-n{pD7Ik}~B(eyKt157Ng`u(?K6Q))8l!ZW zA$HipfELurtPf*;lK8gb*Xp3!3=1L8;%)J)ek;BpT6zlpkX2L;fgm3#RqR>gjGdu=?KYr z0v*#+x(@1@cWikl!j13VH7V~G-M%p{8(l1YHgV~7M{J-IH;d|;Q>EL}k0i#N6=`ps z-P;i_8od@3)>{<7*#Y|v-I(vgAtiI7J)slTNg!T*YGUvn+AA?IDoE3cng~{52Y+WpZgofVcmb|^wjqQ-8)mFvD95fzcb6C$bc zkG>&%a(q9cVeoLDh=fhReI7W!*FLA0+#=7CgG9qZ%`5jJSsnDKgsqcc)Oc8K`@*{@ z@9V`S2Y_+NRalxJ`~uP=S_pL6fx$B;L_q~l^sX*Mql<| z4(vt+ve83gz4rA781?G3chfUy6(!e2F^e^#pAq}7#QhXaS~EoraE^=us0ez=q0QrI z$RqRQBDo2JChW(LnXz{Ly23#zxbJ|Gwei#lU=9OWiVrT!#zFTR1zP%vbfCXk<1#R| zNS~Wsnq7+mNwoNdM~E&S()@d)m#Swt_wP~LZRSab{`{-I-nu^p#d#RQ@q1qd@r9JL zN_hJlp8=CC#)3$@X<|gt92q|0&lDsUc7pKBcT6NCsBog|SMqe3x8kA8!YP1B2o%BD zT(s?q3Xn{2MGecHTt8Mrwodpo1OQHZ>{XzKgM)@c8a^%D=d9@>mf){mFlrm!seMN{ zsOUnMT6@Hs?q_awL2(Z&fmvfto5Pe?I$TVDZ#)XZ0#x-Xj{1<>)Z05oF_Y30Xu(us zt3=lISAIys${#G6qIGsEa1f;E=Wb7w+|1eF5)h*>vlPMjyM$6`&?2q-0Vnj!m$%;_ z2~!KpLM(M7?2BVWsGtKUH;@Ng@4>|&%&}E9uCG8})C)M(d35q4CY5yq8`y>`TaFFi zj*S2(1f`l3(a(8a>@2+SkqEO*^Xd+7j0YT2#$37Ir9b7w!Sjane*fWREpV7ltsmT?9ruZSP3M^MV%-iUW*v32cZ_u#-JE8WXrdID|J?xq@5Hty_HvLfn3X zRY*Sn>(UsFGFTN9cs;{*=@ov5_>I9&0-JP?XpF9!Y>d_&I(z41%B=2D16JX^r}<%; z1yMm=R%)B6IJT~-LjweWitzf>*cNPxQxb;agVOcG*sF-Ui8KzoDrH$TKHBa6XP4<) zGS9g~3TLF;ft(e%4i=Ma-TGhs>=1tOMR}5_E$7{Cs*Ch%Ar@$wji>N`cKUwIf5ZZ- zke)ZIs5q7#qcX&zl_J%=VU#cvba1*xT>7ZF*|KA4az@@GG1%|hcNPY_QI(pzDkHaM zcEO#o|CQ`Iv+S&^z?YIX_*8Q1TNkjuNqyZ7P%+FPwY>>p%~udl`m=9$xicNHDf3d4 z2AQPBnRjy}YF}X5T~f(awaOO*hr3F=s#6J5>T}MW!@84liHeGCc4CxjQD~E5>C}|@ zcfE;o@Mg_Ta3xW9FdLaoj#rDDqdPs+7K6?Of1Tz;xYFhl$>K21*-(6WntN%QIC`}3 z7FYUPoWXrGrd~3eYvVL5dBOV8zK`k}%e&{!IqGACNc&KP_rhv?8e~&J$k5s9yf?p5ndU;~JOv-r)c`KMZfjfaXAXN$TrE?>cFQ$vHDT3Czu zP4|+__tqmDTT*=J&+9~v#wVpDYiFKm;4zk9%Nh=Q zlN8N5lZaQxL5$(ZS#~(M*}Hn{ZbQMkiq`z*@h0UbB<$=kXCgm^{cnz3(2aBnanlx` zzNG=|aqzO=fL-TdC(p!&2Q{^D$aFpQX_Y&aW|?E67ZhJzozLyMZ0hEWq=xe=D*N$- zdY(<{PsnP0$T^gP2e?xu&)NivQFd?1E{YF^!zIJijLC(Ng+f;90V{-aRy=K*4IK{g zHJ*1bXT=KqXzuQuW=*u_f`!*H;qF;__b$Ef@=odYDO&XH9PnmQMb#E=r{M2{r) zuk(%zfQPNx^)_!w3Yy}Xs=QfLUyU0r`^l#{?(CTawxo5uqiS~BLySh_rBzh0+?$fQ z)^gqlN||>utn8=(p~qTLs8JH02tMj8%I1Ncb!3nzWvRYMyTyl?`HIVf(anbmFy}pe z^!&v)f%$pW(`1YJfl1M**G8+&SaCzS79f<#Jw{P$ZlWRDCk zqlihI86rG?KgbQ7o#RIsHHtZVqLdJ`fEN&E5Cp6I+c}w4;#ra%fJOdPm{?}y{QIrD zY0ovwB`A155P#A7o3mg^KZ5hb{fi7SiHb*SHgf-1zTvwc=m`P|YUQdP-G-)pHSjbv z|MWt+wX-*9z|nbx|`N;2eoIzH=A(Hl_p z@e;0?`S4X*=ATNptugIx4z_{pzlbrHY0?c|ra$9<-G5zz-6qlu3R;aks)v~y z7;v)hVyxyLh%ImGqa{6*HKUi&UHF?}K}&54hs8cC_t0O zWA%q=x(ZI0I`DDG=QV3~a}9XeLSy;$VM32}I!byZwgA2?^WCQgvz4c`6xR z=B?CBaf@|wS<6QWi_m?HZIRp_3~I2Ft=86A*NxFG%DN~@LPZMZbt_|F1B7gRHr-{e zX|OYFKXr}lHeUJN1Q5i8n#+j;-25yb5_Is zV>zX_9a2dkO_c)*8MPa$rJEVM1Z&-dGYFD2x>dCt-UFGG-yEgBnh|NnbfS>(BEJ27&U#|L`=W1&Nvmy zxt*Am&M%I<)$(?;^I_x47J~CjICqeM4K;$c8Xo0q zwM&?cENIIs%_f)3XIoUC`SW;$?NtMDmolN75OBzRU85)^>m?kMCGx;|E;%S1cE#aE zzG^@-7^H;0p2jc!NwRxOC+3o-=HtIe@6>D-diQXQ6+|cIVsEuLx5)os*OT^wXojD1 zGYIKsxnv-c(!}pP8V+)7gwl@HtrLHxZ9FXZ_LOd-dX_hz>a{Cy#Z(}}C%>=FMK=il zMm!6)k-8C_U3mm#a_^lpQ##qCz0n)aR9zF5;6WwL>?cN3krXyhqs4|D+D-brm$N}h zc?;Jaor_1DHSd~ccSL9^%uw1KDP+UN{{Sz&1C|jvC7eFu&G?hb?oI)24nED1Lllp+ z&;DOI{8!SHuX-zOG}xWdeb=vj#e!yHT17LC?cp0bi^7tB>`GGz#ZOKtD9i>dDT`zb@-Czrfl$)4`kdEQ%_Kr|z zAvQ`5nmplA_0~A~ufVUOgJ=}m2^NO?H$wkUZ))%E;rI^)B8t0zyps~4+;+?Tba|P( zN4ha)yNx$X>DQ`anO_7T4|mp=O~2Q!Kf9Yx2<5l{vAa~SGQ5;n@UZvCzjggO zXIG^%JOme>l$U$T~zm2$DDDvo#m33dj|=6#6bn}VcEcnz1krqQcV?T<_LI@PZU2=}>7 zu=QMtD=0a`Ws+UAmXaL{523HQUHe1`ljhTTm5z|A1>5d6V!{{ruoE1DF?U@+tF_p) z+P3jhAZ5oTF^gxY842}&>3=cX=S;!n)0$Cw*Z*mLeIc>acAe^|(2L~VSA>|=pHL)d zKIc?tZ4~jd729AyYZmW0<2vieT0#*ge4s!1sEL#u)n2f9)m>K_Di~TM3d!WRgs9zW zPfteex%c(U>}rD6m`r?kB3r=m3uN(l;T25h>f}!~jHkO}YpwoHCLe;RS=IOaG|1A{ zJD1UK#GDqByM6{C6tRWCv4MyH=7Sy`JxlX&&i{Zba(#IQQC+kZ^0KPh%0^)|Jh<+ot)ir3{Px@W)kP<&?H zKJ7bTlG$QX9=IQw8*7N$tVcQi)8^?oX2^lx!r^3{vDeAsgJUAUtv;yOs(HpSL_bcy z#W^TX75X1CIMg@C%(gE|zm`)k06614%h;s3m8|$WL_bSR`(map$$aPLSTSu<9h%fz zZIgUPO~>vco4?sRbcJ^AV{9hjQr;eGZ}=(gIlpT0_D(cdSd=T9Pc^HqmqDm34SI~yoqw= zN2EwR!a&G_7HLWb%LNeF`b#BlH`wZ^sV28-+#919d-dEb&AU1mT`)ie1f12I897MD zS@P?M6L~Yoxe$U?n~WNG(N<(ekVAh$)HnH3WTkD&VCBT~Y}OLH>o1BJ?)DD8EZG!= zOS0vAhNN5@xL`QFK!coHxe0t&zg+N`aPiL2uL?WoIn9-0o~!xQah;@fI%CIkA&HWg zvop)P6buzRx{n?;%7G5lL9xWYI;}Gq&L+iKw6>pLNwQEwNkYVy+1dS>v%x@T4|&YC zGZi({KK`Th4_=M0DAGmB-$0NRyVKgT#cT+E-~|NwKE|SGT_t^C^Vm9mf8|>5EBGHL zTcfO%%ZJg&d**>k!k$S?75xwz%MvWFVe>NJQ*eH(;U&Wgx|3s*eiCD0uQ_!6YHX0M z*AoK@;@;A=9pn_JI#YkeGDOZbcampixE4xA|5XUS2KFat)Q@2JoE6J_a@uU$PI9YG ze#EReTLC^fIgF=SGM<+R+>D>${6aAStT-*l=i(>AyW6?!B@5OvvJj=+w8J>Lu2k9X zb_XJUqfo5)nk#}7n(8X){XXcwsPd;6U@%STD^VXXTyfV)$ZYTkFEXEnvZrl4?JOcG zVv_}L3C=55$SyMDK6nIBWUhyjLDt<7eB5sLY~5D?^I@C^BVR>$ zTjeO^7o$;!OzKg5lZw4}gA!0dy4`IcTGDJOt3IjD5HR5I2rS74<|{8lX+zW~LiTfn z!UznC0`DH!zwsYwd(v)SafCgn);7B>-CcUF6pb$w7Kc-6eOCEOGa0Cc(89eT9G}OV zY&Betk-7)@9E-A?$)S0ic@)JWS1A5NU0>V_^k@-9UxlTe=SrNuqx|SlZ};uurNaVM zOKnzLOTL*!6$KTAksyvWgz}7AFsCcGJSkiF*sp=&s$^(XZZ%qQ@4fE7dG%_$D2>GZ zVNm)uwu3#GYvg$sW0A*cK7tksZmM%+o=p=fD@dXsRXRZM*3382IX{g#WxrjoCV2HNJ;9)Q<4mGEjDk*hJP!vM^ZPusoJ5S=nM1L#n>X?RrxAT zQVT3{;z5^0aCdU{e;ImZQ(b1&Uj7l3lX{ef(;gziJo79EYo@|+=ozpL<*+zdy*aev zY)}SvqT^XjB-Tx+gPgu{%`6cYXezDNNkKh4+hlu0 z7h7`@tl4f?DZUe@K{72YukxvO1$ewF^G^*32cv^ajGW~+lU54JHdM|0=ludN7P*ul z2mS@mN<%Lov&Y{W&d z|9%SPhg~w|`W?D=Br`JAWaAJfyGBh&$Oy)Sx|02pMy+kpjfU0aA0Pb#P^xEZDM6?j zbTr*v;4-tHi;$)2h_RjE&q#|E#(8+|zgKc<44Z#SMN}z`Vre4z{E5ZH)&1__34j#r zch-tW2BMPb8&i9H3{LDCu;IG@ob1fYW!aT-W8QG~2r{~v$jV~KnfAw+2RH3_?=+oafQR)CB%WB;o16468GyLH*T(YRbuo}c7G)_*XY^~Y&rhn}5 ze4WZOw_-VO&iF@tj)(cT3q#u;UZOR5c{@qlRTSk=q2HV9OjGDfa_spkQdSr&^S3>a zR(U2S0W}SJt+q`L*E7}0F!#avCI&IE(T5)G^AP1%+zG}IvopIPvNVZvuIIhCJz2l= zDvm}n=3ac_l4`UaGi)p!1XZ)tR-k_rj|jYmBFF~ayL@Ac5IcO6#ErzM*eHC+cfrvu zmqgK4T4|ft#h3?fpHkVj0Mi=Sz8l-QUecY%xewYxO!$Xoe>i7-<=7yw;$075QhOAb zmy<6c3H0fEtXHEBSJ@su8hutHvwNs=HF}xz@5*{0aRipkWnT}Fgq&9GS|s0NemQZD z4>f?;TmYFa_GEJbpD;8`AB@S=IVz@RYn=OfJWI0zeE|TO>XYQ(d7QOCfR!_7ag_}E7uYs9>CuNE`)^EDL~9jF zr4~Y&)fbn(S7l1R)0kU2+l56iiSVee7$_mtwNT6i+MkW~fEw~+c5L_OLmbEFLIrGJ z2bwb4sqYE}4ZNQ2{N}C3@sEJF?Gv#db1!TVO!MYin~3jw4(i>qO8Q5t=hSoQY*4`_ z6Kw`3PU^PlFzQs@v}R*r4>$TW3ja#w>|ct<-0-riJUJN(u>*O=9@XH@7a&^ljYOS)L?^ZhPnYx})u-$5Ruej@ z@3I;z?_mH5lChWK??wX;oX*zY^}3V!kL-`uus^xpzNlW`0v>@&7Z;0)$oawo_%4b9 zcJa41DO)4pN@u9bH>r3G_s`d<@gRpnoM=P4u;JMLmNbdX_9^px&eG7Uco(n`1Gf01 zG_jr;r3`9iTnZh=E)We&B$fZ^5~9j$Za9f-+5b>2u9gdu_cwS0H7C`1-Ux^zMT%I?Mi;o{~i zaKR?&8K7X0^%y9P77=%M&C(oNG%DM6wDjwQ>~5bvE1xRX`WPXJVj#o@O?aAdd8_j3 z3!=SU=0w{*+>Dn{*_I?=KKc2J+*vhXQot%ro5UvFK~_`Bch^Zc5%h5Lnv_4=THkJgHiH8HVghQ+a>-(+@v>wK${v*W1s@5$wQAzrP&q;p-d(eu&qae{9k$r>rlJ;>*6JJk!RJgmCey=joL` zTbi5(UtAG1 z1X-!6qtMrw$zYM$eLTJFhtB>C?2E4r3LJOMfShS6WbrxMekA=245nt6Yg&u5WO6~( zDu1WeB&@|~_V0(~9GQ@$42Iy;%&7Q;Q5C*{zG!9hv7BW-G%fh*`C;{Z28v=U?{Q?% z+4jBLv12xcN))S`>NPeglbxx%GtlEk7jip+-mcuSXk3JiV1_p1UqSs_1OkHcg?=+56|CnFWEvx za^$H4iIW1hM+mr`lzmd{AEA;V>`odr&;k{?^T>Ks|KU*+9LFc+yt0}Ru_$hY^4Ek?_34Yl1M$doN)>^688!m zww^CVj)!+u7LXagMI#IEfNc_4hc1ZS$%oy&QCT2=o+TS<-4X%5Ngb2?>;pkW($`wv zjLR)>DUEFXHJAhTW+|3rfsH&gX2c#^B(Q(_861eoh-ugi7-9oev+avOObtp90n#wF z+45X3yDTx_bcfsE>}JE{kdJrz+GaMd{A($~O*q1tTRu}Oyi}#{BVY#5-;P%iVzR?>SpQM(s%2H9fSO z-UKcfi2d!Akn-e%ywQHRWNg6$UTXBpk0=8}ChEILvgLyi;$OjBo zRh+f^f1$3uL@pyuk%=(L@H~{h%67rZHuRsS?!-y!gwcx)+)@Jo1kpLZpR^Sg?|pwr z(#%;=KhTz}DuwL%I4q$YD$OMrm`8qA>A{aHU{t?L2#5Bx;?_^(EYksTi&SdGR8mL( zH3FJBYO09At>xsaE0WXEnKI9k?2~gCAW-D1P@kOhJt7rWGWBE>8LKC20~-1@j7N+O zTvu$Vwv8%r^fkKlut>+~r+J^eATw$%RaTZa7$4lU>YX&zCIOLxu9iprrK%wP^XEE8 zWjRzQv}C~yU`sI&^G>BO1N8tbxBaWK4Cg#x*_c9j>gz@L$zdVHj^U>zAw`~HSLrUR zYqr0UN=Xa5E$M%!!yYEf8d*hILJv5hL7ZBj>}qEoQWwm}u_W4lB`S}6oad&oNqKVK zM`|$r>BECm?n|rF(`;=%lyw8b~4CF`ghkeCq$X zdw}hs$a|Wbu*MH>YuhsmM;ODFUVd>!^^ObQB!c6=axXm!P>Eq~3h^7B#Wk=ClT9#a zkcYACDX35L1|RSsJ~8nzp(#~1X=B)Z10n|&nA4;VHi-5U)L&6FJjv-J?mSKG4ld3E zFU39AVMw-M-?OMR@)vEZZ%W;^NChp(&skPtW{R?_nMg{Ofi&iZ&1$8>#a$#`>@Y7#6fpbg7 z0+jX%e&wog!=XoG@TO;{aQ1s%hsz2t27`~z-Ns?z<%bxRgXE;7>71Ajyq#QyX^v&_ z$WN6_D7k=Kp?%aWOHzdk~cbK5GF^n$-JOX zv!p3r`Ywq?YJFz>%NC}op~E-~mlOl0!kZo_hY^|p7~au|zp<5ILpYn3Lrw6;dS!Qf z*ARoPc#wa>e4r_pj!_;0{Q!-rg#(dL?%-_tfq4rhj_iQBx>@(=J0Un4SeCZf>?nmn;pE z=j<*dl?^p;iszVER%#R(G>X}L)9ed?_hL=DN-517Vysi_M=&(cEm>{sy{D;xvCeC;R*tH2U926O+sP?btaO`Nl|JKxbDpS|s@eCe$49CXwu#7J8m| zT>{oWWFRUtzZaPY6zRDbH_IJ{!jH(GTVYfsMUO(+Pv$T2=9*f01Jp(P84Ov&m3EYg zWpiM`(aK19yQtyxIc1$Kd=W#qLf=KZggUE9s!JNQnaWmEG61MdbV;}x`*R$#KSEVR ze=Q3`YNSJjz=iS(fXH7*$~xWZk!phx%B{ioJSQ`;pWpkT@|)C@!*mFmc_^kQ-C zf!~Gn#~37(Ef`w5ECdGj)#4w$a4447i%t592qym-8>_Q`d8kvbS#JtinZwdX-!U`Q zC+!B00FXuGY*a3WmifMuwreL}4t#B;c^17m+_HP8SP}tsppqh4z01`@5WkC{7ZYo_ zEzWp5GZ8*?JL07jlca8-M+~04PTiDP=cCv%Tb1w+ZZ)T~MI`bC5G#mRC4vI5&G$wB z4|^YnQ+ag)kbKX`u?KLwkB_Kg4ubXKBa+W2iY=DYFtR7`4|X#;kUcjsCtYy~D@#+= zj-{fl1;q0IDBht6_yZ&G;!OxD;!J|prqfKzQ7R6UIiCF`%$5a^^dccj9ldDwp$|V`+sHVwQDcWKXo3Pi@?2LF_TNbFqGD6}=ehB*OMSBfjTII8U_MQ18 zj%)1K_=7bLQqn7LY_&j+Uqy&RE0Xwuq#0M2l+5}$eax`mgi!)=sYAM%lB3cC+}g3c zIGXz5z#J&ynGK08=%2zH99jnQ zMCM;|EX`<+!Q%RYD1Lts<6;3}@L$@*QJ+W7a%B$bBY089H4K201PusQS8MH`O)2Y+Vbs>O?)%|8M z4ycrhQReM4@hl2Wd^HVYc|9D{*ys?&`ruKZ^3C|On>I39;>$}Yu^Wtk&NlN@0b~ZX z`i_i;Cwc1vUU_iIG`=U*g~Eys;Y`rPIlrdO&Ix})nw9)c0=v2tAC5uZ$y$=l0g+tMF!$YrvTX6DMtu zMKAswX5Te-znH2eI=Nv^Z3xeI2xb@m;-=f#z2eS}WV5H@X}~m^_|)HPBt??Mzxdpk zsprH)tiXa1I-n?A5O{6jxEQux!`j~;Ul;!jq50BC9h~Fj=jr>yDG*HHZR&7@-p5Fk zhXHy0k${}l*pB$~H2Tv_@?}uj4EwaV*`1HF0<&NKa=TBHzWV}DqcF8sb8Y7%QU+LO z$K0b>u@2BC+{HHDVrP{bRjZw7jZTloUqUFJC1Mg>kAeQ~S!*%fGP6>9&Z7PoSOQ$B zI8Q)}^O)ZT_5P zBp`mIjh{vX0v}=vy0RkbWb_+665I@@L_-wuFi1W`pLt4}NO`I!^_vV9g#pKW+tMo4 z#vfBDB@&FwG!~r16PJD(=(89A={jU?j6BiD=m{iUc7T+IX(uwkyhsx$fNz@|v0T3jpTQJZWzB3@MWuH}+BzQLhcAH*0E?ft`lzL=ksZm*p?q;{`uWo`gx25cEc3(H z)4UyL%Le_=Sm&C$h`;!(3{*f#tomX5)c9Y8!Yn&ZQXwfCH$wnXwiYI3A0MQre69SGkEXtJw!sJk=}DJR9%CIQPDT znFz$y2H(qxw-Y3fCnsYSpR(rVIE@MupD+5^^A z5kTxhe$?Rp6lqpfcxT(72D~kbf*nW~8@dZM9kYcpgOd-0B6qn0nJFgJq#Jy%CL$`l z4EMM%MSwC9Sm1i@&~#DpV__Z-`Sd|8l#lj^7+6imoN&GzBF_e&(f#X3(E*CR z%Wr}^tm`+z=^13N9zDI6t;@0?B|TW3ll`_=o$SKgET21pd^pHJk&skcN}GOf6xb*> z)&u1IG+6;Izx&QoJJ8H>3=~j-#yE{LzK*3U9y``UWqrYD`-%3g89aHb^`?Sn_Ri-s z1>Vrtk4#OS^gsni(2>rY`}85wtn68n&h3hSxU@t;mQf`AI5t!Np(!e}de=^13+tdb zKp3bRYA?qFEb%D`F^;sl{uQKb+R*B&MGLGqo#J zwK=n>0cLuAPeuUPd7!+C3aEQiTx8$1yaBVmYBdLi6x>C-pj)s8(qcoWK(I4Bo!mDf zgp7nbl=I-l-(^6SWE_&OVzWUIG}ndtL3Zg}Q11AEb@Y?VhGtVX z1FGWIlqpDGUXOKnvL(dD5bP&T?`vgA3CCHwC~fsqeS~h~fP7cpDq~^UZpdJ$iEF4& zVR0$xy(22mzSZ@g4>P|N4>!6P)f+B-MsW+n0O}E_0Q#?SG zz#@JLg7Yi_5y<2$PyFCt_fKNjEk5Q~t|u}eCR%M8JqiIy_`!bpYx)pzc8Y-HQ7F>P zJ5s4s93ykDT9S=xnrWLLnGlY51Blc;ozA8YS}RQ}Jj17d$aK#tiHr^<55}dvx2@lz z!kL*~KB;RnWrgWVgw!(u=`j>zmd;42je$^XpN&JZLtJ&dQwj7MSGUKz+rc$lqxmyN zOoLG!h2!w{BHw989>En{w!0ru24E(GypB~JwdFi)ZQn4oUBc8GJUgmwiJ*pv(?G#$ z1Q^mrve|zx$_Xdz3rY;vr-4&qqFKepJAoHn230c}_;bqCL9olAMqT8# z4wchU(^4DSKFPzF*q#BeWv-#{syumPkvo?);LFW>5qWZ>=-i$$!2NYX5HzZ{D*qpk zjEwH7?*4+itJ_3?3- z+p`UG1|Lf#tUw*!|Exlgo9b4ag3$m8GUjl|Fzh%nN*Sy9stPMxIEJSjHwQfA?LM$~ zfFu+O2wB!3DdVWi2?H;q?0v0NV_f*owv<&8HUSCtGD6(05`MihHk32Q-q|st`z`z{ zH-ez}upNKlgJEXEgW9A05T8c0h6Vb-Y-(&p@uCA~6s1Fy?U7NU1-S+z2;3^D(2x+M8xRx=2fAyk{U1vLTI;_LO}JynZk6!UGUyIip2)44n<~=B}LWfdDO;28x{vjYv_V15ZK}8gxzmG5i z7k=FWo!{C_a3z+X&SNrfmN8f7~-rnY#|N3|PB?Qu{v;>s}=DkN$zGK4r!J z#OZI*Up)PRj3bpFJ#!zZuqPddzyim~vA)-mv+MjF3jTdSI&R!d@uR0^azB{eRP5K4yxj$D2A+vBQ{J@aHDdp|E{N+iH7uiA1TMw z%1{LCpOQyD4}hf^AV084eQ;=hLQ|-at~H|uXord=RPT}&>!e2~P8~O< zvd$doc+V^`imo|M5^{*An#T~-fPKMG#6*NT0Tu=`8U zhy&30kFO2gD6TYPrjT)$gc|Qd?)k=tg5&Jg5E(#K@_DQKWqRq*d*KpO(4hYUh+G6+ z$I;yzzifJS6-_{s)K@}y;SyEgDEu<|?cW@nI;7tEd)2zGXp6@0_2f#J48Zc)0%I;+ zW<}{6fPqs4=N78n2XivzH_`yz=x=Hp7b6!eDqm7P8ye5Ohz+@}D-&K2zu0BOrL)SU zVdh|E!V!;6hB&{0=+t*w@`fH$i(0|rvJGlN<`N2M5v_srZ9e*_q#P9@ipjM^E{ zV2_Pl2X5b@qr4L2zDR--rwgpGkc)Vbf<7iYaXh55p4%bE!^qe?uX)?N>*cRb5ZJyw z32%rLVT{vn8Pt3SIxR7$wS2)T!f)av#j)9{c@d#nUjOUG^htP)G!~tQT{nzk>MG*1 z49^23I9x=hE{%P^Z_}~Gxc@Fzmu&4|{?@dg;_dmR%jeSy&znUE2XUrmk*#05nzkZ; ztHAlKE_wsixovs|XS%l#~EYrsxH!Z^x$e5=2wqfBjy?uvnO|UxeSLd> z@JK&f#o?}mctNt~1Ms8XTjU%#-ohjwu%Y#wo`3H~{KxkjvS3+ZU$&3ImjKe443wES z?i`@B^OC08pg_Ssx!DZ9*JNB7xvZT9{Lfi@Bd@MWoDW4rwl{HI2eeZwV+FOkyx(9k ziDzgZYPqZ2fxioWQkirYkKzXp*P>(KT4v<`LbRupR!|Q3LN2KBx(JX?y*%e(JBgx( z*xPwkFi+%&cZk&bAg_7sPr4-Od=E!`Ie`Z1pdIOdl7C-i6;MzqRPcuwyL6OsK3ezF z6o7I!gb)^oWgbDSR3xARs$n}|Ng=q7SLiRR7yNUkWPUUUQoWAXbcy9dli_v*<7>VY zjEF)iy0+I|o#MGz5{6mtImrozPQ=<(&N!?nNxVWw~kV4okw|qYB5|><7Bg t1%zX$`UXtsMHGOR@&C6U_xw-z1alCRVQPCl;BN+elMs;=t`gMu|38zrM0@}M literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..596144b1f8b5b749b00bd660b6240781861be1a2 GIT binary patch literal 10931 zcmV;kDooXhP)lR3L*vs6)cE_8VD`)BE1*s zEp!MqK*B%&yt6Zxz1h3VU2>Ot^E~f!DZ8_~Gw*$UW;HF?f-TsBE!cuB*s^S+TF9V5 znhr!x)rcp^<8Y4JO|WI>CP)GjG+(S40Devr5!ktEe?f9(mnI0~Ad08Pj_oo-E6{tP zRxCVPD-|(MtJEtdv<5?Mfg1Q5{)c05Y)T}N#0nBBD>Wez+z}>nj#e}>CbVA9x#Y2) zbB#g0V#p7XF=S!S7=1JQ`B2Xoa-Jc9A(7!00~Nr}_#6Ir-aJ;{jC0Wk`a+-R8`n^; zi{`kmAek~*b3+<@^G!)Yo?w$cw&y&unth(KkRlm#(*U(E^BSwzb-%^6aSvPySz3@x znV?DaWc?dd3zG)z7)G*5TrVVsE27+roJ$fp=8zXf|06dH1 zLB*HE@q4hPt*ON6Ip1i+Y>P>309jt37CDQ!(v zRZQf!W&=InN!lb!8rwu=2?)ugsJZz}CAV=m4#AdEW8XX{+hDHIfO$~SHsWLs_2e&b zwd+JA_RJ5@GaAZq;A0ZBk32UkaUPzll@_W>4ytL}*attm!L*gcb7KrJ7Ouu9*krRx z9rkmNIr_V7@Gd&YV|r5RKxc0_dvF&qCQ*eETxb*!^ZlZGB6PhnA3 z5mZ_JgF~hDh$d?~M`=Z@W1i)k{5Eu(hQOe)OOWTLi-8Ct4Pa8}CN~FW8N0)N)XG`M zKFc=w01-2_s_fz7g5*gH4B9Iu7kzYoe)`Ii`|0QFI@2c?6mmL7lBmaQ64&J?t-5s% zvRrehtvOm1_E2Yn z^XStHi@G@9LZay;E-WgGsWa(DcATvhVy^m*AbGsUsq0)2T9t$2FI97v#ZB2ZMwb^oj|keV10IzwP;e#$Dc<0&$XVHTmQpJ0ySsaMajn z9}3z%$-u<+i7id%9{h%@Bb78j(yc^#>gqu{WB)Mv&hpwkaH#eJz)k;Q#~U{9Z07#q zwqtz&w}+T2qpe39%`u0~2cPES=PRacMM`s+c}Wdc%U z?AGV#kxM)HB&)MjLqf8zOAS`UGF@i~e(Bx>H}5Z=9zeu4!RA)>p{gM7sV;E;Jpe-H$m=Pzw>KN6sPBa=P?+Y<@wW$8r@IguMgX1%+SgdA{JS z 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9287f5083623b375139afb391af71cc533a7dd37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5914 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�(p-{x$&=IACIfoAR!za)F-^da-t3#0Dycnp zwO~NVXwXCl;jE<}>%@xz|=8fIJAB?>+E{7)|4l${4ngA3G|=r z2Dyv;VVWSgZx9Wj>qUjleGl3Ei9K4>h!(lPS%8VOG>Xu0%6VDz^O=bjJmuP7>DeUv zrbI}MlHB^^d?{zv6d=@_ZD2lg1&G7UjnVN{1}9WkaM3H~btX0GtSzB+tZ^qRgWo4m z!GmimlG$=wgXCnr6j@m<1gAL46#T~5Bnm=2{^@>|t&`9mkEPddj zAvG~@Tv~TAm2i%VW}R-g(Z0)z-Y|szHr@rk>4MAyG*Ma*7Yh#H7(!-5>DZ@8r;_dx z{prSe<>~099F8vsYd2xff7uAS%7{S)f(|@me3t2$iy&NEc7OUEchp@9A|X;;IA>8!oX+y(BKJ$EzV* znR$z;!L$s7uy@{OT~nG#B!NRraT8(X##Ho!0r_o@gg0CA-9H^;-uE&?$2$nHv_00o z%cbuUc-tCx$Uh&EZ4Nf4Zgqv)Y6>usG3>GeQnxx_Z6+PcbX-+ysbt1hQ`K1LDpOE? zrAhIZhSN9yVIAOa22gn577tbc&i3|3V8NWy&!tw##`}9*x}gtI^h1DzZRA>UuaJG) zaZ7j)dq!O}{?#8Y7~7i6fHh4{`pL?>-18|p!S75Y#^DM>-S3)vuZG+Q7l@ek zQP~#cBpWgg#mApc_sPYjpw8odQuRokmTkzcNl`^CcKB7e&;zViV;{Y{o^Y$%7i0m# z62%#1Lq!RC?}lK>%mp}T!3Xv;L*0v*>USLm``N%>w>@fwC+#T&Tx2bN4w(20JB}oU zuSa6v^kXi0xPs?pbaOHnyiqq6By1EZY9OZ^^QA>{q-Hsd&m`pbQ%8121aWG-F5xf zlZ%;B{;C>X19|`^_?dVyCq>n+41w7|!tUS!{9rHlbhX=SZO5CQ^;!Du_E7*`GiR^Q w)2!4MKjfSAeN5a6!yNdhX%MZg2 z&#RHXKr%j?*%GyUndtxDmjT|vlM8d(Uw224OFPnz(Q;&@`7aV^@5h&V70-?B>LO%5`&6RY27|3v%573zYqJ6k z3L5KUyWw@vmzXnyZJ{A|Y)lvinNJdmB*e`B#tR^6n@aXL(NsD^?3nkv2yA(t)9jrv zxa+<=BRt`*ch_!6y9*Hjtn+ocWp4-L40&PzWtEi#oPu)^UYpX)cT zUIg3EY5lOkK?~a_Hq_g18%WfMaa0s`?Vz_IzE<@3G~`P6<@>C{dPDGxS%&l9qN6%P zm8{0@SD%?cYt}p$?HZQPyII_Ut`U^oopMPAci*~1{2(U_PXkkpBDkZ!nNaJnxI}brCPR7skb67) znchjc6O-ZU%A?JT3$2BVSA4uYN}o)cOku%}!ko%}@GSP;oe{GoOzN7mkPCW>@f4EyEQru+)&#nCS(h32l5%g+#zLt#S> zhPSRe*EsWZE3~49K_R(?RI>YZd*mV2A%pr8nA7g^B#)kr@>st)pfoP&RT@V$WdHE^ zLB}*E5YV4w;n>DopAW1H+UDOIVZ;#-()DLHU!R+wO|Jsp_Wsat2;RZ(Q1Ve<8bVG19CpR>5~JVg zJ0#k*A98Y7JnpyI9bmSuNZu^sUebly@5ZbE$%cmWbY z8xJ?{K=#QDMN;^t#T&1Q(#4c@W>SFh$0+cmxpZs5ULQ+4TIC$sZ_Fv0R8IKAA#y_q z@PoC$YCR>w${`8-?=jBV;CrL4q~1Z_clOB>2TIjYDBO{R8)PNeka9=@`}N(#IRNnm zq5!hGwr{nc)aCJueKVP@5Lq~V!b1jIrcrS~_`fCx%`NKz=$k-|c;RJc0CVE5xbsmz zFTQ!Ph97(GF(FVmGm7xi^75Pd9^A&o;)nL7gMKvDgQJ(ljGb7{?^`}i` zcBA7mN5A@fSs8q|6kEN+48}z!&c8J47>ZYMB42&|56h9H1L|Aw*rqwV2(gw=$b-Z0)j0()sksCBg`O0S4zB!lo@qB+w ziC^%5aIBF66TyYRqr{sUHKBw0GgEOu9L6FQ zIca{kkN8cmU9s96d9wbZWAGwz#Izhi_-QVU#~LaB!{Tvt9Xz)0>8bGcaGe>nUbKiAgh(y(p1_Uy+AqjQ!0vp3y(l*hXE56>4*tv@M<4xJ&) zv^IXq9C<{1-l-ZdT&Y(oW?7r-S$=Xp5p22{eTR#toAp-BMajMg^IG|l`RBeM6@o)L zPK~xde`vV0$5>h_acjw>d=fa0EyWm>aqaQOPsfJPZ4*SNC?b2#ML}y45typl~ z->F&7qkrFut|D?&>PWWfiNWT4@m3IS7(j66d zc9t+OEX~Ylk^bngkA0mzLvad4j0|SjAS_OAh8W$r9Hkt&14-)Xs}i<7XKcjMr>m=|ZcaRolPP`r zyJ^EIy^>gWuo*xKccTuO^3QOLMd-Jzj=6{1hs6Zbz$GDLJ~njYn6)L<0tteSlo;up z^--|Xwi@++t%M2PhH6oj$6D9;mI`;QZ(+lMX&zc+O}%7q*|gexYY<1al(H(g8#E3*sCF{Ka7E~y75@wO&d zMy3aL^;L=Vv>=)whv%W6FJ#W{4ZWzT&J(qbuZn7EaU1#e^^lN7h3?r>$}=E+{flKm zXBpdBD5UUjJPhqb%T6|g#9M69f5d_AYSZjPVQ)ox(+)1!PzH*L`mrWkv;;1yYo%q^ zrzlQYhXE^T-*H_R$2H28Bd8trpZ57{u<3I+Y9j-brjpU9twceBQuX;Sm4a(Jaln?> zj^=cAT4_<2urx?uC-IrPMdt7uv@mw#jf&??mgX0;oTH2R{|$?C`-m8bnw3X#GI0|C z)Q=jp<=%VrF@P%3NE^54S(r75wD|#L>})&$+C2sv7XjCw1FK`q*WV3vMpK*Kta$Gr z(FPPeD~)0p{VcfmuoMSx$k2R2bLu-*#lSUNAH~y2f1;?_C$k7w(SMhFr^GOdiEp2B zO@WA^4JI1&z@EKUa%(c&fXL?YcS?_dQmpik+q^mCKE{y-25h#pAV+-BFgvD^xZyg% zO{}N5x9O4VPUKi%DSmUy>S8NVa$0RaR9|~1M5lpiyQ@BXmew+sohSUuarfzRfvP!{ zDn&=1`<(5w*w2^J@E0>h*WDO3S6|UI1<8{{4+-r7-LO}_S zqH!EaT%U*r^?$^Vyk!>gIGZP}ylrJk`r=fry;UMQv}T0&+0gEjo1%G88eGrm(FZ|L z5HuGWIBDuV{=RfQ_Eu;*`?|H z)brgRBq7QadqOTY2rChouBq72Ff_(PJJxdIL7!=uyil z?Gq!o(dS1slbF?-%{q@vqr$v3s}PAg!P&GZCdqe`;CodfH;m}=f3A_>95#Te62J6rPB$nYPmyXgnPKFsAg6s;xU#hPQs6(m&pJ>zKp()SvhM+ zi;xWc;6uUkJmkqpC{=(+gDYXU-@c(LdUAX35YOC6)Nlh5JstrjU}-gfVz zu?Z=gkmU&Q|A7dhttRkf&O=R@e}3;$F!?KKb*(pkzbMDBOxs#wqh?nbWl`(9pI!)L z@;Ht@eDD8y7K6;?_f*F6Ipr0%a3J=VhWlqO`9{NpL4?bSl4&k^FZragG~B^mPC1{O zIO=Lq?QH?ts|_Ni>AX@UF9GQNX;aBo?A5YaBByVllm71)UAEaM zxiQ6TrC5C}4+)-vx-KG8j-nCwp?e;DzO;sRnp+-R+ZDpp?6Y;IeHHw2UfWGzxR~(B zb*bshfd6)FjnLDG8c{-Ln2%FSsw0cSQ{;}rODmU1L3!JTZ`Arsg3eYIv%iN}?Ah)~ z?6m_yYDZsQk~PD^=LzjHLF&lU;*%T1{I^?~2Xwd7KPj=I*Fsx>e`s-ZdQ4(9p)o-zr;X+D>8Yqki(vo#ndlz-eLYTN$rx>!`mo z3yc_+?>{M;oSu4Wxx_%Bxm<@8oid}rm4$U|Wn|6#0K1=w^gk2*(>C{pSHict$%zA1 zcRKTDAxzQt_SI!~c3w#9zAWxTW>?<)IhmFkm^q02xY+4($hXk9zIT)ONryz?%Iw$H z+DwocSEsHQU5%6`(^0SzU|?FzhEz@ zcEkc!2A4ur(RzP8I3wGC26*uND*7{ZoF6&VjW?C;-fJ7d3m2Sn2){I__#BMG>B~td zt&WsKT3>Rg9V5PkG+2;TgsEC@}#Z{^nza?_<~zMCk0Z_mNu=5h6@8Y_?4F01Ykbxqm3-GVW@zH&!1ck+WC$R2yhxWv5X3}lad&g^oko8|9|+q?#IGUUbZ zs$slX{9S%O);%d3RD*kv*ovo6wKi@c#^}R(9yh!28jB(Qr-k)YpSGSIdZM9XEM|O2 z@agz(-D`>Nb=IXtfwCjpHMaj{O*KRN`X`L_2w% zyg+bORYLLOs*U5|lGu9>TP};NDwTA``MnG>>TcMi>7RU+0dnA4UW>z(9+4=23Uyhm z0IHj%KX4?9V4$u-UI&&yTlaqM2BjGq>~`jLC0H1a@KL+Qry!?aa|&&$tj*{4UJkeW z=nd2KeUSDZlQE3UJ2z1dBQBUVSnhV2Xd6{6x;5<#HBT&@IG=X`78A`U#NG?*3a4iK zD~~Si2q68I@`JTyzj`}FQD9<_wY79u*Lv$33}8C?8t%SCn!$l-@*(8V2)angxYtXB zd*A;SSO{i|ZtPo()1^$Pl{>HnkpMlB2oluEa}wm$s^v7IVqI>A&MQ<@_`f>X{$(IL zp=Y;5C9loT-Vqkmwhp<&`s|SL%9A82dUijF-wdD^f2pZ)&o9j&D~JV~-;Wn-CU!FA z43qBf!)qRZ%nw&7K{%6GrhZ7}8BVlb<%O!{VEof5$9om_<@4@WN8@=WRGSz96ucYG zXSL8bK^GILRny#p*LOu4CgUX(v9`4lFqT*Oe=W*%zv>di7SI$M15F0qfPLTai?W&Ud-W zxb*tOnnY&yfoj5H4DV-Kv~O7pjLKuhzV3#Rke7(bVm>}|n0RB7ZxMEY_Xw~um-|C> zZiRhXxlE>2Q{INH0YD~t&;0-GtpM|tBZI)d=xVe+;#%8OOF425HRf8xg96(|#MTo? zjw*5#8ZoGo_@${Ly`LlA)z8y?w0k^BnN}DB=oOe)EaSPOZ0A!aGAUY2Um5X}z1~k* z(XbW=8v$JH%`Sjnf9TV`-A)bT(7$f#dk5ddO~EEfhOM}m{BT*2Bo_fP8(UFeZ-`E^ zSY4z#FWsPR^DbzCQV+WCl+~Ltz6zy5>lqFLf3jDUBtEeL230O%E(y~M4_pk;xB;Lv zv?nItg1t!Ou0kK$LA1A6Gq>C~pl6Pl`o>OC&)8ij`hmeO2ey(cT{(~HEfP3}JAZT1 zew+8^-IP9z4jnoFRFP{RFu*@Ao97Ahr-YyS+xq(E5?1NqYDOpBb4=|@;^17^s7dyN@_At%WLC)C+k13=r0D@D z2fRIyqmEpGkUF}Wk?R;aMocoNh$5zLpt6R8ev7h;>2qJ5!_Og7#8!1_r)1t@pYq?4 zKdK@A#OL>qhZ+_?%-Yup%mC;#@PVPVWZ#~teSv!SUYm$*nvm+4%M^562aO>9R0?wM zq0e<#QU&)BYf?U+D?UgXsJOP^-b4nU{}Vpp>7O^PKoWB^@n&$jHj;EfiW7)K*qzo+61glA zU>aZtpx3*OgZj+ZRheS8Ma8}RqcDDoFd{vzq3XA7;<_%8os1Y+{Jzwqu9{KCMGNrypg&($E(tb5GBX`PSKcLD zvGB{xEY_jn4(Refn@@^-kF6iyAL-RELFDQg2n{2X;Nkm+jPs_9m;6=cq|o=2E;}4d zBh_JXb(zwQH?)itgKXbIRRebO|J|Sl>of_#{|8$sidIMInkmSbMz;XVm9G4Y^7PQO z^53K|Or|=mh(A$xmuLhjWEO4!bmIMoAZ+N3zTwdzv*KSsT2^qEJv8-t^%{V&S4B#v zFTg1HsIU=1`76d~=DN$`LO2vbjS+YUV2s1;5?u550?JO+C=~dZ*2=Xyz%7@4Mk4+O z)LYoaph6h`>dG~$dn``6Fsl1)+~QvIoMOdFg60>1M?Jl!Zr6*rCeg3~O_IN?ig8tF z&nc(hKaF#ORAwYQhhabj@Fa+J&7tDp-_K4rGBFYnkd|w(8S5U>%*jk4a<9@462_5w zBkR0(x2q^xnHr8^YDE#kAx1+>b`wG9du zF)f|A{)Zn=zOz|U&jDQ9l2hz9(iDo{dF_3RQVSX#&yF~Boa$whkRx<(+PwwXWAgvt z=j)as!Nb>aRGCF{2Jj5aKCduAp=yjRvIA(;_Jr!~h=o+sX0GbLe{~cZ=RoejI*)h# z7{unZ#6KzwMWLpnRhCN*)}JC2#_9+)WN4HiWRYsB?xxDygJR)_J*n6YQ>{Fi@ew654@w~% z2CyRA0~E5pk*}B>!_Etz=$r#bl`8cLsI}>j$+l57?4zkj<^k{kUqlM`3DXr`33JL;5Tm|3`DIYSk1}ki&_7%&dcXOC{ zhLi39zsH7U1HnLQa&R!OWrv>Gn&#`*IHGwn%!lXZQ8{`T>kv|Sw9zTc&hKIV__%!h z`kE3xWIxO6FmJlEzTv>v8XZ*xQKRp1@V7QpkSU(#2snaUv7WfZ;~EBPNxtY{5Id6 ze|qN)uI@142x?)krh?DXaGiOVp4Aag*P9i?4Q>&Xn+p?t30+)t2uo}2Xx2!|LL-Iu z{X?uE?cwn%LH-;jcXD}>zXR7a-=wP z1?RDt_#7sEkN9?d0r`dC!Bu$R zHwgM6zUZjyNjx4HK>&dV3zqz--~&)bzHOYYoF<|GlEN`&{JdOiqtsKv(YvV0?Mr5g z(GF=qj%qbKc#Mi>$t#?>GNpJKlWzpg0PGNpbV;6+bba*jN7@e_S~;@X*a!gsmZvC5 z11N^o4$m*fg)5`mJ5R~4bqZj|nop3wNQrR!01I@g}r%$~9KauWj%{zBDHfi;-i zaCKxSFM@dqGL+uzqP6=$ftSHqK|9rwt3o2Q8AQPYPn#rgj2VwzCc^XHre|GxsLsKn zjvDV(Inb5ABvWV)Bsc*D&d6 zTO?Ii@9BX=A(;Y`G<(*}>k5;Dd=Q;PO54R0os36R6gZkLY0BOj?GX=DU9vP;<^76} z1HL6G;PWOIQy|Dwk2F9_*hbVj%-1QYZ8d=gd1i>X0De&J0}z7rcFtk#fMnVx3s!>i z&e?#j$j-}+qJ~zxqpE%8e8u*Rm6f)qDFnHCN)CLad=?!he=7eZ>B z-%>u~@?M5T11yEeq;O@AI`}Y?#BJ+}IIDpuQCzY z2-8SFes+mhGiH*4Gm5fU3k}5mi7d+zQ6lAsb2C}mF@JF7x~W)%kv%|4s^ycg{`<}r zf63?FK$n_tT3pQ-?%HeKIC|TGP6|(^;qT(6?XL09)cxaJ!|eNYMQ&u{i}*000$}{U zVzO6D(kA{J2oa-b+pn8W1LA<%5R-coeBps}srDrQ>Y8R z;i9gq^$O>hYxp!Gc#v>z*1gm!^a z@8On(Mgc3AI@}S};T1AOb-wbymkh6NfK5CQ2TRf(z-KT7u)+K+4~D&krUPd$9rhH! zlgbVN9+m_kj$3gU5L#};36H6=1aOQwY#z5&3jZH<=WF3d@qGAwl`TNI>ty?>dUax- zzBn5p4H0{S{+S&6`8MUQ^~bQ=0azY8eDH<{Z%=Hx9eyVw3@{`V<1uy0V0l>Z)i zf>no_T^XP24_tmdG=Bbum$}Sh&3#Czg^+=2Fgp5diSHSG`gQHSUak}Ig*p&o(g70^ zN0l+a74`nZj##FN{mW%k*6YL&lu86<{2b5_}H4_S{{K|OZed}*q(KM<1bWa#`t)IKeBuwqw`W*OZ8J&9bUVHA9DehrTZNcO#bMPU~ zOyX6pw^y%1ZaUV~YWhU@-(JAlySI^iy0iNNR-?ImDuLGu9cUnrl3k6t+X*t|&g+{S z#jJ^YOE%LLz_ZOaiec&xl6lZ~q7t8*jX7nADCY(+u9zH-o~zF%Ok~xcZwBdzPcpkTK`rI3ZateRFjXp4*F% zF$X|@y^x$kA%dRG`;|gl4vBdBe-bH1f7oRXXG9;q1OF~lKdsG}%n)~BHwO@klxcbm zZ*MB7{Cn};Yt+o|bm*`ZwoN3sB#r`L7r2N1nCVWN1SlJ|L!wCr*7v0Ted2iHkLb9+ zgEt}+WFlU0WosNTw})7g;ZM&4pXh+~wD%o+T`$p9Nga!(QM;})qHh}(CliP$;KDoe` zyUf(og$w1uPQj|x2;A^2eiajg`~dBn+lh3C1L1idC%i+_r8wFN(9iclLYo6!50+^T z(+qpx_;ar0ZUbDGhdKh+U)6m~g(`cxNrj?KV)2?yPH%%hw`M+=+Km`);J(i~$4+wC zQ7iP;5Qgj*{-9r0vA+yHy&nAaq>=IT@BKK&H<`VThT5*G)sYYs$`lX6FZ$kMo8XPM zLHFnBLEyV8|3`!tybr^V-n)kQI0sD-R3&RkJn9QcNa`zsm0Nd~5z1u;z~T?p#_Wdh zrrLK2Q1yYP(NE3*qD*385fMGHmFsk>#`^{`{Wg_yfjt`v5j#T-os-1m+xFOe_|+t8k4r z0)|x$u!HJ^g~`rP?a)pCm1*6fRLhn(?zDTPj&NxC&PHyFC%ta(ch|dY+glgmg*S^V z1Wkq*(*MsiV;(qFkEhm9wnqL_$7vh7$j0;&XV5c2V?xql(?k1@3W=*$D$pBJl!0!~QosO!6k_ zHd%Rze8af^2N1i%Jl|GQ8zWp<=HEZ5CE2?y$^UCTB62e?F!v8ILIuPQQ6-|nTP5$7 z#6Jl=dk7`UMYEE;8|>O2sJ2s(%Rzn7|#Fbeoz`+t-m literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index aa7d6427e6fa1074b79ccd52ef67ac15c5637e85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3844 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 Sm1gkYA?1+Dh|h47fd2v8g`kW8 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..b5f51ff45361f80170a8b700faa5f23fec762210 GIT binary patch literal 16225 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 LNkvXXu0mjfO88&Y literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9126ae37cbc3587421d6889eadd1d91fbf1994d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7778 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

UmY2RIYtNPVDpE$%vda+HD#3m z&VuXJ{BK&Qe+rBa7eq}Q(bq|tn(RrJAk|ztj2(i{d>nmQnM?;HF2k&9sA6up5tmjl z7lySlzMbifH17-m-Lwa_F&e7nOH?ESi3#ckR3tsM+jsck3`oG!uMS}|eAwVXv>}qxwq?QY%QJ0}r@^;fhuUA9W z*BVl>TGo&N004@xSiwDUXUvp51sVmqO3m)=B55aPwf@0=e}cN+$-BdKxY`YrT_4)0 z_d10#i44Q*rFr8MC>*)v$EJvz``(pb{e&*6k+b zsMz%($|1+8hn8c2?P(l@;Rb&CsZeYoCI3?2!LqjbwPXW3z4G$Qfj=cT5Yb%vY0(AX oeb?AaKtwrnc|$|zzw9vfvn^aJJ!zd)XFXqqy0000001=f@-~a#s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 42d30f5..1826127 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,4 @@ + - Techwas Mark02 + Techwaste \ No newline at end of file From 0b67d881ec925d0b3ea49992b7f1aee2bc78c6ea Mon Sep 17 00:00:00 2001 From: Zhahrany Date: Fri, 16 Jun 2023 21:48:05 +0700 Subject: [PATCH 73/73] Adding image to make forum --- .idea/deploymentTargetDropDown.xml | 4 +- .../data/remote/apiService/TechwasForumApi.kt | 12 ++ .../data/remote/response/ForumResponse.kt | 6 + .../repository/TechwasForumApiRepository.kt | 27 +++ .../screen/forumCreate/ForumCreateScreen.kt | 180 +++++++++++++++--- .../forumCreate/ForumCreateScreenViewModel.kt | 55 ++++++ app/src/main/res/drawable/ic_gallery_big.xml | 5 + 7 files changed, 262 insertions(+), 27 deletions(-) create mode 100644 app/src/main/res/drawable/ic_gallery_big.xml diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 475c42d..bbc02b5 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -7,11 +7,11 @@ - + - + \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasForumApi.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasForumApi.kt index d63b866..707dc36 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasForumApi.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/apiService/TechwasForumApi.kt @@ -5,11 +5,15 @@ import com.capstone.techwasmark02.data.model.ForumToCreateInfo import com.capstone.techwasmark02.data.remote.response.CreateForumResponse import com.capstone.techwasmark02.data.remote.response.ForumCommentResponse import com.capstone.techwasmark02.data.remote.response.ForumResponse +import com.capstone.techwasmark02.data.remote.response.ImageUrlResponse import com.capstone.techwasmark02.data.remote.response.PostForumCommentResponse +import okhttp3.MultipartBody import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.Header +import retrofit2.http.Multipart import retrofit2.http.POST +import retrofit2.http.Part import retrofit2.http.Path interface TechwasForumApi { @@ -45,6 +49,14 @@ interface TechwasForumApi { @Body forumCommentInfo: ForumCommentInfo ): PostForumCommentResponse + + @Multipart + @POST("/forum/upimagepost") + suspend fun uploadAndGetImage( + @Header("Authorization") token: String, + @Part imageFile: MultipartBody.Part + ): ImageUrlResponse + companion object { const val BASE_URL = "https://backend-api-56g32wdmqa-uc.a.run.app/" } diff --git a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ForumResponse.kt b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ForumResponse.kt index 2d914f2..74fcf28 100644 --- a/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ForumResponse.kt +++ b/app/src/main/java/com/capstone/techwasmark02/data/remote/response/ForumResponse.kt @@ -51,4 +51,10 @@ data class CommentInfo( data class CreateForumResponse( val error: String, val message: String +) + +data class ImageUrlResponse( + val error: String, + val imgURL: String, + val message: String ) \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt index 5cca8cd..080f55d 100644 --- a/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt +++ b/app/src/main/java/com/capstone/techwasmark02/repository/TechwasForumApiRepository.kt @@ -6,8 +6,13 @@ import com.capstone.techwasmark02.data.remote.apiService.TechwasForumApi import com.capstone.techwasmark02.data.remote.response.CreateForumResponse import com.capstone.techwasmark02.data.remote.response.ForumCommentResponse import com.capstone.techwasmark02.data.remote.response.ForumResponse +import com.capstone.techwasmark02.data.remote.response.ImageUrlResponse import com.capstone.techwasmark02.data.remote.response.PostForumCommentResponse import com.capstone.techwasmark02.ui.common.UiState +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody.Companion.asRequestBody +import java.io.File import javax.inject.Inject class TechwasForumApiRepository @Inject constructor( @@ -80,4 +85,26 @@ class TechwasForumApiRepository @Inject constructor( return UiState.Success(data = response, message = response.message) } + suspend fun uploadAndGetImageUrl(file: File, userToken: String): UiState { + val token = "Bearer ${userToken}" + + val imageFile = file.asRequestBody("image/jpeg".toMediaTypeOrNull()) + val imageMultiPart: MultipartBody.Part = MultipartBody.Part + .createFormData( + name = "file", + filename = file.name, + body = imageFile + ) + + val response = try { + forumApi.uploadAndGetImage( + token, + imageMultiPart + ) + } catch (e: Exception) { + return UiState.Error(message = "fail to get image url, ${e.message}") + } + return UiState.Success(data = response, message = response.message) + } + } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreen.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreen.kt index 34685a7..4594bb7 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreen.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreen.kt @@ -1,7 +1,13 @@ package com.capstone.techwasmark02.ui.screen.forumCreate +import android.content.Context +import android.net.Uri import android.widget.Toast +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -11,15 +17,18 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ElevatedButton import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextField @@ -35,14 +44,19 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController +import coil.compose.AsyncImage +import com.capstone.techwasmark02.R import com.capstone.techwasmark02.data.model.ForumToCreateInfo import com.capstone.techwasmark02.data.remote.response.CreateForumResponse +import com.capstone.techwasmark02.data.remote.response.ImageUrlResponse import com.capstone.techwasmark02.ui.common.UiState import com.capstone.techwasmark02.ui.component.DefaultTopBar import com.capstone.techwasmark02.ui.component.SelectableText @@ -58,13 +72,19 @@ fun ForumCreateScreen( val forumToCreateInfo by viewModel.forumToCreateInfo.collectAsState() val createForumState by viewModel.createForumState.collectAsState() + val imageUri by viewModel.imageUri.collectAsState() + val uploadAndGetImageUrlState by viewModel.uploadAndGetImageUrlState.collectAsState() ForumCreateContent( navigateBackToForum = {navController.navigate("${Screen.Main.route}/1")}, forumToCreateInfo = forumToCreateInfo, updateForumToCreateInfo = { viewModel.updateForumToCreateInfo(it) }, createForumState = createForumState, - createNewForum = { viewModel.createNewForum() } + createNewForum = { viewModel.createNewForum() }, + imageUri = imageUri, + updateImageUri = { viewModel.updateImageUri(it) }, + uploadAndGetImageUrl = { viewModel.uploadAndGetImageUrl(it)}, + uploadAndGetImageUrlState = uploadAndGetImageUrlState ) } @@ -75,9 +95,15 @@ fun ForumCreateContent( forumToCreateInfo: ForumToCreateInfo, updateForumToCreateInfo: (ForumToCreateInfo) -> Unit, createForumState: UiState?, - createNewForum: () -> Unit + createNewForum: () -> Unit, + imageUri: Uri?, + updateImageUri: (Uri) -> Unit, + uploadAndGetImageUrl: (Context) -> Unit, + uploadAndGetImageUrlState: UiState? ) { + val context = LocalContext.current + val filterTypeList = listOf( ArticleFilterType.Battery, ArticleFilterType.Cable, @@ -102,6 +128,16 @@ fun ForumCreateContent( val scrollState = rememberScrollState() + val galleryLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.GetContent(), + onResult = { storageImageUri -> + if (storageImageUri != null) { + updateImageUri(storageImageUri) + } + } + ) + + LaunchedEffect(key1 = selectedFilter) { selectedFilter.type.let { forumToCreateInfo.copy( @@ -110,6 +146,12 @@ fun ForumCreateContent( }.let { updateForumToCreateInfo(it) } } + LaunchedEffect(key1 = imageUri) { + if (imageUri != null) { + uploadAndGetImageUrl(context) + } + } + Box( modifier = Modifier @@ -140,9 +182,85 @@ fun ForumCreateContent( .height(240.dp) .padding(8.dp) .clip(RoundedCornerShape(20.dp)) - .background(Color.LightGray) + .background(Color.LightGray), + contentAlignment = Alignment.Center ) { + if (uploadAndGetImageUrlState != null) { + when(uploadAndGetImageUrlState) { + is UiState.Error -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = Color.Red, + shape = RoundedCornerShape(20.dp) + ) + .padding(8.dp) + ) { + Text( + text = "Fail to fetch forum", + style = MaterialTheme.typography.labelSmall, + color = Color.Red + ) + } + } + } + is UiState.Loading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is UiState.Success -> { + if (imageUri != null) { + AsyncImage( + model = imageUri, + contentDescription = null, + modifier = Modifier + .fillMaxSize(), + contentScale = ContentScale.Crop + ) + } + uploadAndGetImageUrlState.data?.imgURL?.let { + forumToCreateInfo.copy( + imageUrl = it + ) + }?.let { updateForumToCreateInfo(it) } + } + } + } + Box( + modifier = Modifier + .fillMaxSize() + .padding(end = 10.dp, bottom = 10.dp), + contentAlignment = Alignment.BottomEnd + ) { + Box( + modifier = Modifier + .size(40.dp) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.tertiary) + .clickable { + galleryLauncher.launch("image/*") + } + .padding(8.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_gallery_big), + contentDescription = null, + tint = Color.Black.copy(alpha = 0.7f) + ) + } + } } Spacer(modifier = Modifier.height(16.dp)) @@ -264,31 +382,39 @@ fun ForumCreateContent( .padding(horizontal = 16.dp) .fillMaxWidth() ) { - ElevatedButton( - onClick = createNewForum , - modifier = Modifier - .fillMaxWidth() - .height(56.dp), - colors = ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary - ), - ) { - val context = LocalContext.current + val context = LocalContext.current - if (createForumState != null) { - when(createForumState) { - is UiState.Error -> { - Toast.makeText(context, "Fail to create new forum", Toast.LENGTH_SHORT).show() - } - is UiState.Loading -> { + if (createForumState != null) { + + when(createForumState) { + is UiState.Error -> { + Toast.makeText(context, "Fail to create new forum", Toast.LENGTH_SHORT).show() + } + is UiState.Loading -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(56.dp), + contentAlignment = Alignment.Center + ) { CircularProgressIndicator() } - is UiState.Success -> { - navigateBackToForum() - } } - } else { + is UiState.Success -> { + navigateBackToForum() + } + } + } else { + ElevatedButton( + onClick = createNewForum , + modifier = Modifier + .fillMaxWidth() + .height(56.dp), + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primary, + contentColor = MaterialTheme.colorScheme.onPrimary + ), + ) { Text( text = "Create Forum", style = MaterialTheme.typography.labelLarge @@ -315,7 +441,11 @@ fun ForumCreateScreenPreview() { ), updateForumToCreateInfo = {}, createForumState = null, - createNewForum = {} + createNewForum = {}, + imageUri = null, + updateImageUri = {}, + uploadAndGetImageUrlState = null, + uploadAndGetImageUrl = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreenViewModel.kt b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreenViewModel.kt index e9d7995..dcb797e 100644 --- a/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreenViewModel.kt +++ b/app/src/main/java/com/capstone/techwasmark02/ui/screen/forumCreate/ForumCreateScreenViewModel.kt @@ -1,11 +1,15 @@ package com.capstone.techwasmark02.ui.screen.forumCreate +import android.content.Context +import android.net.Uri +import android.webkit.MimeTypeMap import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.capstone.techwasmark02.common.Resource import com.capstone.techwasmark02.data.model.ForumToCreateInfo import com.capstone.techwasmark02.data.model.UserSession import com.capstone.techwasmark02.data.remote.response.CreateForumResponse +import com.capstone.techwasmark02.data.remote.response.ImageUrlResponse import com.capstone.techwasmark02.data.remote.response.Token import com.capstone.techwasmark02.data.remote.response.UserId import com.capstone.techwasmark02.repository.PreferencesRepository @@ -15,6 +19,8 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch +import java.io.File +import java.io.FileOutputStream import javax.inject.Inject @HiltViewModel @@ -40,10 +46,20 @@ class ForumCreateScreenViewModel @Inject constructor( ) val forumToCreateInfo = _forumToCreateInfo.asStateFlow() + private val _imageUri: MutableStateFlow = MutableStateFlow(null) + val imageUri = _imageUri.asStateFlow() + + private val _uploadAndGetImageUrlState: MutableStateFlow?> = MutableStateFlow(null) + val uploadAndGetImageUrlState = _uploadAndGetImageUrlState.asStateFlow() + fun updateForumToCreateInfo(forumToCreateInfo: ForumToCreateInfo) { _forumToCreateInfo.value = forumToCreateInfo } + fun updateImageUri(newUri: Uri) { + _imageUri.value = newUri + } + fun createNewForum() { _createForumState.value = UiState.Loading() viewModelScope.launch { @@ -56,6 +72,22 @@ class ForumCreateScreenViewModel @Inject constructor( } } + fun uploadAndGetImageUrl(context: Context) { + val fileToUpload = _imageUri.value?.let { convertUriToFile(context, it) } + + _uploadAndGetImageUrlState.value = UiState.Loading() + viewModelScope.launch { + _uploadAndGetImageUrlState.value = fileToUpload?.let { + _userSessionState.value?.userLoginToken?.accessToken?.let { it1 -> + forumApiRepository.uploadAndGetImageUrl( + file = it, + userToken = it1 + ) + } + } + } + } + init { viewModelScope.launch { val result = preferencesRepository.getActiveSession() @@ -73,4 +105,27 @@ class ForumCreateScreenViewModel @Inject constructor( } } + private fun convertUriToFile(context: Context, uri: Uri): File? { + val inputStream = context.contentResolver.openInputStream(uri) + inputStream?.let { + val file = createTempFile(context, getFileExtension(uri)) + val outputStream = FileOutputStream(file) + inputStream.copyTo(outputStream) + outputStream.close() + inputStream.close() + return file + } + return null + } + + private fun createTempFile(context: Context, fileExtension: String): File { + val directory = context.cacheDir + return File.createTempFile("temp", ".$fileExtension", directory) + } + + private fun getFileExtension(uri: Uri): String { + val extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(uri.toString()) + return extension ?: "jpg" // Default to "jpg" if extension is null + } + } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_gallery_big.xml b/app/src/main/res/drawable/ic_gallery_big.xml new file mode 100644 index 0000000..6b87b62 --- /dev/null +++ b/app/src/main/res/drawable/ic_gallery_big.xml @@ -0,0 +1,5 @@ + + +

FJ$wK}0tWNB{uH;AM~i diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..3d52ca284d10869ff592eceb0821a7697484dc54 GIT binary patch literal 3657 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index 948a3070fe34c611c42c0d3ad3013a0dce358be0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1900 zcmV-y2b1_xNk&Fw2LJ$9MM6+kP&il$0000G0001A003VA06|PpNH75a00DqwTbm-~ zullQTcXxO9ki!OCRx^i?oR|n!<8G0=kI^!JSjFi-LL*`V;ET0H2IXfU0*i>o6o6Gy zRq6Ap5(_{XLdXcL-MzlN`ugSdZY_`jXhcENAu)N_0?GhF))9R;E`!bo9p?g?SRgw_ zEXHhFG$0{qYOqhdX<(wE4N@es3VIo$%il%6xP9gjiBri+2pI6aY4 zJbgh-Ud|V%3O!IcHKQx1FQH(_*TK;1>FQWbt^$K1zNn^cczkBs=QHCYZ8b&l!UV{K z{L0$KCf_&KR^}&2Fe|L&?1I7~pBENnCtCuH3sjcx6$c zwqkNkru);ie``q+_QI;IYLD9OV0ZxkuyBz|5<$1BH|vtey$> z5oto4=l-R-Aaq`Dk0}o9N0VrkqW_#;!u{!bJLDq%0092{Ghe=F;(kn} z+sQ@1=UlX30+2nWjkL$B^b!H2^QYO@iFc0{(-~yXj2TWz?VG{v`Jg zg}WyYnwGgn>{HFaG7E~pt=)sOO}*yd(UU-D(E&x{xKEl6OcU?pl)K%#U$dn1mDF19 zSw@l8G!GNFB3c3VVK0?uyqN&utT-D5%NM4g-3@Sii9tSXKtwce~uF zS&Jn746EW^wV~8zdQ1XC28~kXu8+Yo9p!<8h&(Q({J*4DBglPdpe4M_mD8AguZFn~ ztiuO~{6Bx?SfO~_ZV(GIboeR9~hAym{{fV|VM=77MxDrbW6`ujX z<3HF(>Zr;#*uCvC*bpoSr~C$h?_%nXps@A)=l_;({Fo#6Y1+Zv`!T5HB+)#^-Ud_; zBwftPN=d8Vx)*O1Mj+0oO=mZ+NVH*ptNDC-&zZ7Hwho6UQ#l-yNvc0Cm+2$$6YUk2D2t#vdZX-u3>-Be1u9gtTBiMB^xwWQ_rgvGpZ6(C@e23c!^K=>ai-Rqu zhqT`ZQof;9Bu!AD(i^PCbYV%yha9zuoKMp`U^z;3!+&d@Hud&_iy!O-$b9ZLcSRh? z)R|826w}TU!J#X6P%@Zh=La$I6zXa#h!B;{qfug}O%z@K{EZECu6zl)7CiNi%xti0 zB{OKfAj83~iJvmpTU|&q1^?^cIMn2RQ?jeSB95l}{DrEPTW{_gmU_pqTc)h@4T>~& zluq3)GM=xa(#^VU5}@FNqpc$?#SbVsX!~RH*5p0p@w z;~v{QMX0^bFT1!cXGM8K9FP+=9~-d~#TK#ZE{4umGT=;dfvWi?rYj;^l_Zxywze`W z^Cr{55U@*BalS}K%Czii_80e0#0#Zkhlij4-~I@}`-JFJ7$5{>LnoJSs??J8kWVl6|8A}RCGAu9^rAsfCE=2}tHwl93t0C?#+jMpvr7O3`2=tr{Hg$=HlnjVG^ewm|Js0J*kfPa6*GhtB>`fN!m#9J(sU!?(OSfzY*zS(FJ<-Vb zfAIg+`U)YaXv#sY(c--|X zEB+TVyZ%Ie4L$gi#Fc++`h6%vzsS$pjz9aLt+ZL(g;n$Dzy5=m=_TV(3H8^C{r0xd zp#a%}ht55dOq?yhwYPrtp-m1xXp;4X;)NhxxUpgP%XTLmO zcjaFva^}dP3$&sfFTIR_jC=2pHh9kpI@2(6V*GQo7Ws)`j)hd+tr@P~gR*2gO@+1? zG<`_tB+LJuF|SZ9tIec;h%}}6WClT`L>HSW?E{Hp1h^+mlbf_$9zA>!ug>NALJsO{ mU%z=YwVD?}XMya)Bp;vlyE5&E_6!fzx9pwrdz474!~g(M6R?N? diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..57ce6d5e37e9771461cfd03f3e801ae09688fd30 GIT binary patch literal 7365 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 AWB>pF literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..19b11f56249dc87262b032dfb0ebf3e8014c2ebb GIT binary patch literal 6837 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..a01fa89f468ba9b3ec28a2774ea93aaa8e771cc5 GIT binary patch literal 11514 zcmVuAcQczIF;X6G2FcFMnT94-=*QwAN`@!?x_hzLSORSR9jMH?^LZCQ3}8k4!bGArLJb%l~=u z(Hc)l{2~!5ks_S56DLko7)~1JST8YF*v`#0oNl=`ADODVAry)Fmj7W|dP$6y*eq-s z!`@7SFP5#)K#>96_^~YLruWmwDRx0Du7PXenz*(`mTOjK&ip@L^HLK|w2dKv|C9Jh zVviD;(F|c~A#0LA0^ucSg4xgML`!jvT!@rx5>rUPS~0z zj5o>RF1Q9oDC649m&>(t53No2r5+Ofx35*Q(V29r>F*vAe@J9&DHxhYnGq)ftZAS@ zCbOyIUbv?oru*~}sWOeuGk2i;euuj<^xaR`)Vglkx3PBqsRrdMneLlD z@N?EjzGgIG(mH&Xo%pW&%+x)2!WKzcJNi_IIfBb9w)Kh9K=hUVUgw)|^mA?&ww#G- zr=Y1SFRZ3*3w`9Q@9Jce9dM@U`!L;0velM|s;WSelA#pchB@oQI@5$HM3tXyB-ZGj zsUv<)MPb%P^jRCD59>|>Qkc^AMMXuA$-gs<4yo(r%3Y{n!sxS%{9JupPGJ=D2cMpk~coDgga{Z$l5tRxCbINn#j-3pTB$e z?z7E(eabXpIC`0xnT>_5tU^6F#Xghe3D`|qK|#TWn3$L*=030WO+O8Jd3k>Fdz3+* z0w*2eL*-CF$4Z|lIxa4*ow@I8ZPPa(Z>ppGp5!Bs*P%(26dxbo*(`%v*My-$<;`3z zzaQqtq^k9i$NNwuk{Um4-@bia%(AF8O|xF!L~Hpy(MO&thayoN?u;k;e-tC^{~(^D{+J zQDLdyH1va;o}RvG^ytwI%rdHRO_Ze4>&XkB<0Fq}QB+(cj^$^F*dtrTy7(nxPShB& zboV5YnRlerwq`)0!oot4l9IAe%0`jLB&(X!4E0DU#+L?peA(qn0@CCZWQn~;w~3Ir zMdFWbUy9FzpAavt=q~!sZX!Mmx?dbRcCgfbR*)yk&(9Z0NlBxSks+&^(}dyW7Znvf zXpn~s_azA{h}?o~aUgxC2u)Zf=1NU7GW1#T@`@Wo@0sU|J7=6L?(}aU?wx(H7`5Rg zaX2Tb)c#JO#ypN4J0@adWBZw9R_#r*S=w1Y`TYnNdZKO?fK>|e;S*W;M@5V@Q7iUL z5#NM9FP>l4O_Jt3afkmorEve8W@2*WXCgf}wbZd(KozJRl`S|pxPw`C)z*Zg-=j)0 zP?t_F-Uk;bEGiJG*$HAxQh=DXYqa?9-w%lg=e8(C7%Lv0*Gepo{Z*1Kz0@&X0ofE3 z6o|yc#Pw2Ux}2u^{2^h>E!2}v+ULq{`TQQYLG*MqH$_CI1dD0gM~F99-74;reoe0# z=P46qCJX<&XVygy|9gBv8xaz}SemYJhd>gDF<-e8c2 z3-tLtCjpLeX8sWoowiwNoYz*~qI?^xhPi7-L-Bw#Q_n8#D&7vbOAJ~4e-6L*U)Vt% z<9K0ysdJnJ${#v%l+B;pU#SL7L&vcy}`31RRU-}N^7{4Jk z&fT*vEJYmtH*nFF;=RCo#JH{RiH!*>#Quz3Vx}Zp$#xCIpru_z%CR`*J6X?jGH6ql zkdUxN%1}AeCYgG_8EUVdyoe!&^6`9svJ+Yvj=rz;PRP~v8f#|oe zy?7_ExA5Qbt=MxUQXD&;AvH{%NX*(RCPjSWpq+-SzFlO*I+VV6@#4#osUchMHevI9 zPM4~4BINOzF4rJJiafMde7fdQao?P#4#Yu=JUag}@qXaFVoB^oaX2Tj)czW~k3@*i z);@0E_uko!#jjgG6xqi!OKn>oAUo;9is^i(r5rJ^tdJK)I!<)oAQbXze$wJTAIZEUl zFJA=a1j?aKO-(Hh3JSUn*#>#jp*B<;+GoB``#48YaiKCT3uDHq2#OF~3m%{6zB!kO zkN$o@te50E*3X@ z^mG^S zN%Mq{qXmwmj03$e<`=c|Joqs`Z+=TW=0x-0zl0^NQdwgXiPrtg0t2hdcK_z! zgrnUE?aT6;$_eEQB_}6~6)RTUj;w<`sf7#zonBB-Fu|vN904H+y(dR}rc8^OJZOzC zL!J^*X<-#MH`M$1@AyVK&KKK{+izhzN!W~Xld&u?0G^YRBO)UsJsXi3>a3o0vReA` zKBbX!JWI@v{#iV?w3|iqoUdwk!jpqk2HLuxyEu}QEGC41ph9ScT1f6{Bp!hcQ1^ciEpKq?Z&6DO!fgusuie!)^LPJA8L*|<|Z?0U;kg$!9 zfck}ng=*cNVxRd^AcT%SyjeQO6nZtXlZTwoCu<&2$v;mxxpA4Xs>B0disRou=MwSh z+Q&RjAb@h9{53i{dYhE_Imq7NK*gH&eNt0Xdm7q@6ZxEH>3bw)?HAu~eAS`M0xk4b zz#Sqqep#i=mKhAb4q0`(oum)VYbi#Bz9b2B^88T+pq%MLhYpFQOPBUW_Cb|#rVSN# zMs9BID4+Q%!Lj^wF=g9uRg)M@-rl@r?9&w26FtL0j=##HT7@ zY2DTnz>HD)8Wt8d4%t`OjA`@r^Upt@Cl9RVcNN=Osgu?vV3xKd1xiP@vpvgvmvo*V zlo40p{+Y%s3C~4GJ5ocX)+veZ1}wTl4a|CrKoZ6HL%VnHj(P66=NiL-3Yjr&zLJxZ zRp!|+Uv(OU&6H()weD#L(?yPEROpLpK-8U~33mZWwj>8S_*gjXtM^U!Xb5iwjhxWJ zg$wV413?urW5!PPW%Tuxp?&JS`O3^cDgqD8R5i=GmZz5#?gxQ=rKVW#mSY=xBwU%G zAHoKU%}D`e?vp3|D55;GnS6fPwTe{UBoM9&wLGfvER0dodk<~|k-*5LvAW^@Cm#d+Mla*F*Ux}G}#Sa??i$~^PChnixOojS5 z$*xSEZBX_XJ9#+Y>nm>&aT(F2w)G?+5EY9%cI*g~9AHLk`OKIw#=XMB!!MTy%k*aS zMWT#KyyqHdZkKP-GPx*EKW^L z70Z_|e-SQ70-a^$iOUvbvw3GqJIG7YIG|U|7eM>G_E(QmnOq!Go_3ztw*&4JUxW-) zq@vD-D!(H+hg7+!tEbnKAZ(u(^`jD?_I)0icd612xyQ3hZSM?}U%avMR{K2?xsBWU zZkc3=P1`Eoln<8P=izxR#q=E`)%94n^)xVJg!Ajxt@{-&1i9-6Ve1}!^ikB++4=eT z0p2DMPUXjI9(E|aat6X!1jtiQ;rX{R>RAx|iwbkmPTnFCPh&#n9yNIS#8Vt!$+7{B!cRfeJOhlhiSfv%ir?kD`v-)iJt??cgj;DK4?o(on%C_hNLG3z83 z8o&v+{2=ZBj2bnniR`>M!~daKPv8+GX6+L{Y#Qtks=5P&NKWKEY4$J;f9?50`B2Pa zu%4qbpfr_8$ZUEZnA2Phpl0NymD=7JFw@NILhI;bFgyVPt=nqgbN#jV4+qUWXh|2f z&;pv*y1f^m23KQaW0M997|;q%7~Ckk1=&>98Ih5ZyzW{pQpB;GoWLVM2vfIzrADuH zN1Tz;GpzS2{r20f zaAN%U@h8tp8xC~+g9i^jVmQ!VBM-m3JSi5%j2HWkZm)11j=r{a@r%_^f<6azIa4BsoiuC*5Db6q z^}lX$DD}Ynk&{~09R$$7Q~Q#bwMRMJ%O%++hW}R#4<4XqXX>cPih=TYWQ+s$ z&#;BrZulxz5IOy_B3YL|W!f{z-Pc zbvq3PD=|}q_-yx1U@tXO!Tgll1b(h~VcE5+$Q@_9JkBR(VvqDUo?rG)yMs?D#pi3E z5P1bBkGyb>|JwVfcuwwbz9#ZGW%)h;v-$P{_qltjvqfRHf`EOvHiIQH_C3e-F6!rotu}Jw-E=r zDoohnoCN9TeC;4~o?Hel-R(349+tFP66s^*s;KS5Fl^B_G>=(kD4JJ6??4 z;^@S(N(N*vYhQk2!XIYV9D?61qc|3gLUUU8F@tGAV>Z3vaP0&Lm~QK~-UhPAltsuU zInl`AhU-vXGK?^-e*5~@5fl`ZQOnFQ4ig3k zNKIElybHvz;Qk^mBevA`-UhOV13Px?*wegubCwFOZ*atUGsZjEsCi*wVZ66C#9ivqCWQsCx&3E}5N{h;QJS@$ttGx;Ls(VHVo z`egZ@-^)C&7olo9Vq#*Fo_zAjHU>9bn=ykxXO0~^wyk7eT2&DUkRZcn&>eTrtj1#W z##f~ov#kLLc?j)aS#gsXy87Q@#?Eic^d$ggr4)IQY(#_TV*|_!`58=xb-(1S{c8O| zy)EYNz|W^-c@RQ4IUuQIZj4=edm; zyS`VNs)TqA#Y<8HZk0}cS&lcO?u7OXZ`kXMts%N&*pLuioeHkdelDWEcUz0iiy_sJI829Ruf%6c`) z&zzHih%YR=PDNI_ju|p+NLX&1tHcCRm*a}8_&pH(xnmp^RSu$$mUnFKOY)x`TkTL+!3Sdw7rw@l*kA3*LqPb>>{4gu zi~lkIi%Ep$AOQ38?S>bm2Bl!E^tAwnB`8m&OvHRW_s9s6B&e;}tn_|W1x=v%`1nFe zpdN5T63BHfNE684-@jXR5QwQV=1Fw;50rWwmL}$CZmKHfF#9rSp+B~LVO!O!jL_N) z%pS==vy;pDFma4OvG@UV+=+hpt=9~$p{LU%BU=qEHKwXRAm(= z!9LQ?C%zTF3t_qS{2YfWOa^^lls*n?C7K@y!u_BFb39&EP!VVX9Xxn2 z?}HCMz=WOs;)^f39#GW;8aHm-)$#yYRT+h85T+Ap>8Fw>a-`G_ns40!*A?M-DG zwrsQi&TpKSdf;dijS+2G=aiuZi7u)4v7W2CKpx15!j8TD_S@IP4Yvq1eE9Io<<5tz zgFu+EN#UQ^g@Sf?a?w>vGoU?K+Mlo($5uxyXcArv5Fj-R(VSIVI0NSD`;D(Tm@EEku0<(58E=9hgN~?)@lL9)-ZQe z6L2riBE0H`9?FP}jNBtR@ejCRaKvRh-OtaDRT&!R1=F_Vm_O$FIx6=^SfMQnb2n!1fmz-#7aKrUj zm~8c=iejUSjvhU_0QFU5W03X0UIkhM9|aQVa2gXqrk2E_ZFSNj-vQ+cR#>7U_$4PNyxMJjVKyuJ<`bk=vqM3-lw&FVmrts+rP?OC>L z8Oz>XXmG=IIfrcZh7KLdRMrb(Vq!it2vlr6cvS!)CuQvulOsNL$O>Z)&^Q~VZ-L2R zJ4_mW3a<*F-WZc+o&f==h_F78&gyFEI72wIqe~XrHf_hTqLFftmHVbD^JEU~0VefB z>DxeNR+?u~DSR6BRzVXH`J0fPwS)-!Gn6?j+rh61FbGu4TYYBEocS%BC=Y?o4-S@I ztf=1ASkV^IX<_2k6-+!V$+bWbA|A(Cp@hn*GD2IYX0|>cwSbun03tHJHh$~-%5l|^ z6}cHoNUd|zAkdU;!<4^bo%l!slZlQW$!Lsaea({&HQ0ykNE%Y6S_7jjmw-UBok&Vb z5_E+&ooejmY4*dezo?pe5%n# zJl#Cym_IZGn!>C(5Hh7A45Cim{w7^~Bo(t2+-89EESckkZ(_uhN27o2$JnP=3pcNWe#G@NMS{DwE*d~<8* zK<%%tNKAu{$B8A6f>5lQ0Aew-6=#})EgWo28p8-^mYKW06R)heS!o|LkqF%}IgC58 z=)vq=-#g@W$_wQaNn$>`w40jGg(g&as~Ya>xPlJhBO)RaI(P0&4yfU^*Ir8!u}lKd z&S=)GSws2REImDal|i6tailfWprzC@Om$Ji7!FUo&6y<>$E2)L(am88--uFDA}vPu zt%7IY7nWbAM)u7)rSbr+Lufy0!^`R&7`7R*&PzXP5p)E`)aHM*Xwd@mRb~!Ix6>be z^wIO=XOsQ=_kUlVk(e2ffmcNa?w_ruxHy}wiUwg|lb5mmy7dE9jmQ8jgrbl>aQ`gj zNMphr2p}~Rn$7CNlm)g$15zH#5-*gyLh_n02wGX_2#h6v=gph<8(c6rQDz9Q+v$D# z_JwVY0|Nt}s%}Tx44XO2uxpf(aM@At2o_C6Z4pBeKBVPWBs z>KGF%3q&)_yCShit&a7L##SKozH^$YDnD{Xe7A1n4$yj-yWb-}Q^aA=v<7F9D+4tK zwsYssjDZ6O-U1hlB;rZ^A6h+}rN)gLpD(|+lxl2Ebvx3|QKYiN46G7~eH8S7s(H5N zaw-c<6{F=ubR-HR)Y?SJwIY{O2^8c11O)}L#NB0Z!CePhw=;V5=+Q`iHs7^t*NB=) zARBbV6_d7A%_Jq`JS?QY8lS?%5pAJ?Y&ci>I|`B*8dlP1;;2QvH@v7O^)XPYR>r8= zLl2dPP9UbGrHSd&r%#X^Xm-O5H=s=1a-elP{jR(2A`)vddGh4G^1wyaoey#cm=g-v z5jK7jbLSa47{B#BRVqui_?^H$;>}gJDj(*VC7ngT1?|cFywQA_W6EK^vsZ*y;LiRV^ zbQ7!9mpv!mMbm!JCEtJleIFT(RrxFpZ-R_9Q;C`VYF-2ZpNU)%uavazbE-p|ub7ya z0vUlnj_fPq|LBIzJG)V%Mi|9In6GmAKf0l^&NNh5%fP_E52#M#B-Rtx7T^q{btXl8qO#eJj&lPs zU{MDd#f|jps;@N_M)I(j{n1_PhwaGjYQ45ZGD`cYLDTKBID z&|_bR4<9D?GZR^N?%eqjWN&bw!c9eEEI1`UTfG1N`@N4HJ9fM#jgPqkJ`8j1c`+Oz zxpgs4h(wJwvp*PQr4as98Otg!wDTMp8CmfB^UptotlPG2djYaHI8dpE3Tx1&O`B%& zvu#vV)WVvsg{Z@!pp2EhtZOC$>Yu4Hq@FoCZS$#6dQoARN8abppHK08TSL}VrdG;) z>86}%=?mdZw;Dct_ybv4S%oz*q{r8x!jM@KEVaV4XESkZ^S3&xHK%!Zg*$6K*8wQ) zvwi#aqQQd)lX-4+<&{@f+IcoN4gwR;ZQZ&xlgrwNhlkH&_0HmI&_YB4ur4T7SE02Jh4Zs!&02wM4H@g=F^>?4 zh9h-Wt5&VhLYKY%`s;nt($aFOLkkg#GfM*V^yqv)(RX%J@z{bkYFS{+lKE|dK-ccD zCL-p_R`OameH|xI+Gp$5t+@jS4tyBdwrtrF?ZXl-m2#e~O>3cs9XfPqDL>l>2M7O_ zo2!<5t1>M_;e7PrFf|Lpy85aWILQysyHtF(_A&J)<+?N=>JGH_;T7Lgrc5F7lCe^I zUaG<%x<{O6Yf~Y;!O+XDmn|+XE|CkVs_ZmVo>`W~HVLpaY0Mb3w6k=QKUZ_h>RM9J zO{i(hAt51$x_0f#;!&5iXwjkxGB#xG@uot0iG~JK+xh$Ze~9;Pi|R{VphrOg7prbC z-`rZ$Y{gwO&Qosy;#E?oc;Q!tptH_<_UsX(MveLsS$bRh=%#!ji3=MvXmF|gyfQK} za;;&?3auCFDL?`iHXypP`Z&(OOpCC@)jrMR1cvD<bHgQo7@D-^beQ z5t*N#Uvv4{_JtQ-xHmpNKG$$eX{9c@GJrf3t@Bbjy;uP=A#AJAyMD_d5gKp#u^!I{ z)p-9!UcY|*aGcwEEAn#HU?@3)^CgM=d}i(%t!ALI0K%rkRcZ%*Q6LX-81GWAREiz%bdk%t3QeB8ygU&U6qIz;RagBBnMv8TK!%1atBgFlX@~j( zZOT6X{PRIFv{$bPDz>#!H&YQnq8u5*Q#4OL2lHin5nMw>8j8YL=zs+irbG@`1gqf- zH&r#%Jg(Q zatciztih~VvqGdySm*ij1`Qf86h)6OmRCo6nnXT0hbGU_qeodBb8p+WZF?dMLnegm)$aGWYT6$nquIo8)UN8$qsQ%% zMEkTRvfi){o`ab@D^{#Hc>VR)-+>IIEO09rC`C3k!tZg_xG*xBIA~3EWCn>sLPBCZ z?-Ti;p?#jz)KoOj9)mnO;$l(+GVxfIp*Ncz>QK{x4EA5$u3ftxt5>hyLj8$BB9Dgn zbs2=}^eJ*#Bv&nb>a2AVuIUi;{#BQq7=OEhoN zqzN~4wY}3Erk7CQqI`U-oS``q=1eswK?fdaWUkZdMXC zGm=afDX!iv88?z=JcDSd17vDQ4bmOQ$dNrWA4 zdd@lLv}xS9aYy;R^N=A!o(~QVjw5SLg`Cf%l?{{0D#n*wxpHN~%P+tD3gn?rW#1C2 z<1o|LH6~H$iKcxbwd$F~WzCy6heX$qrXSm~S?3-keSL6sJ&j znok=QJ37jwK|(@8vcLJ}o6+7 zP{R*C_~88u7cLBmiHQ-|cf(1nlSI0uA5;3%cU;qzB-^f0?lD;zfOgqbUiaffR z{UX#aqr~Jc%-X1HpFVvam^N+NqODuE<`a3)*@i|^M5@hXGF`tiRS*XsaLbl0`G5TJ z$CBQ?dq3zz>(EE^6@7L}`#bJ7t&P-s%1*OI60OcY`|J*vTyjZg`MoopIAFkl{{H^{ z%cP^7gIdQgz_F~2=FM!T2+1+iiHV8ibaJLnow~eVzkUM^;&i4D=nMM9=o|WozN(X2 z$5pdxBWiWA@0X#nWhas(>q4jEL{6MI@y|7D)+CV4&dSPyML^||5KK)Zlc8;F7bve2 z_LD?q2!eZ=Fk!;fyYIgHVS_kbxM#y$QNu%D&?i2vbCPEEjmT#ZU7)gCpLgDQR}p!f zW@seY!9BkI`s*)b)V4{QH>H(wa&nN1CX+UE)j}u>VN^89wJ|dSZ4(|Ip2M|&@x>Qk zHf`Fpr`9;!BlpTZ8~08h&=+;q*C}t)+K7-8RgI%aAr#Yx{0xnxO!1gh4x^X&}wEZQJs=My~athaT$B zwQ~>L3-@Gb96#e;xo7U3KG5O0k38jQu85>G5`KYnEU%G~38qb%H;L=|_wWDY4?q0y z^Zfbq*R5Z_K82hTb-@q{U&GY2pcN221kfbV-<|!>X!dBl`Sukm{0T8XNVM$dh4w>e);8>33KMm36gD(G`u6SH(<37zk4WOBZrr#rAvidAUtnP1&c%xtht8NW zV=2cNIdbF(j>)m>*ROw*aV|v|t!Yf8X=hw3*UYu!9CI(+laDx6&@_>7D2Yh4RzeV( zOpFb+k*47a>6CUtc=A*GO;%C?G{p4?zh%pow@aFDYmVGo)I2Om`*qnoN zaZb){Hcvj%)WT*al$lhTSZD?Wj+Q|90IlH+`ggWvANJKmF_Xndm{YuI;abUM24pb9 g`n#DVb(Spu55RnV+Y<#?-v9sr07*qoM6N<$f+CP}*Q=lvp4$ZXrTZQHhO+w%wJn3c8j%+5C3UAFD&%8dBl_qi9D5g8fry}6Ev z2_Q~)5^N$!IU`BPh1O|=BxQ#*C5*}`lluC515$lxc-vNC)IgW=K|=z7o%cWFpndn= zX}f{`!VK02_kU+Q5a3m37J;c} zTzbxteE{GNf?yLt5X=Bzc-mio^Up0nunMCgp*ZJ;%MJvPM3QK)BryP(_v@ei4UvHr z6+sbCifQaOkL6-;5fL8$W($zZ_;CZp305C;~$hhRquZr-r)jjd1z z31%ZK{-(`P#|Um_Sivn@p$-vz46uqT>QG0B1w9znfS9A8PB2LaHdzA|_)yjXVR*l{ zkcu3@vEf7bxH0nkh`q?8FmoO_Ucui*>_a~P?qQrlZ9@+D7%MTpSnztpylXrt5!-k8_QPB?YL8Kx_On8WD zgT+111d(Op$^$&KLAN5+@?>f7F4~wFi(8TL8+szgVmcMDTp5l&k6~=rA{Dt}!gb^r zSWY<)M7D|Z2P0cEodj6E42PV>&>DFmQpgt)E-|#sSUU@uKed+F680H@<;-x{p|nuH4!_mn85rx>wz;0mPi2ZkL#k6;sznu?cXh!T0S>{w6 zL^gvR05NY64l*<+_L>On$rjx9!US;l;LX6@z}yi#2XHh)F@Oo+l)h%fq$v}DNmF2> zfs^_t0)3N-W<9-N?uedVv{)-J0W5mh#29QM5R5h&KuiRM=0Zvnf#lF=K#WlCgc#9c zS;qvh(P$!_a8JwyhI^ZJV2k+B6Z^64?w|1?5gyo6y{}923CRZfYVe1#?F% z7h2SUiNO3;T#JUOyovSs@@C1GtwipycA=*x5{BpIZ_#GCMuV8XK=x;qCNy{d7?wA~ zC+=vjls;ci&zW=6$H~4^K%v{p}Ab?U%C6Z4p%eC<3ExqU$XR<}LLF67A$Sr20DR_pJ3yeBa~ z^sw{V0FI5;UpwXsScYuhbqGQ`YQ25;6p6W^+tgL&;Ml;>S3CGpSZ>VrTn0m1$y$HU z&65)I!c?oREz};c=nLCliriqQX->4uivHTgd${GqeAlf*!P^B|jkU|*IdNP(&6C>4 zqOW$)Nw9nvjy^&`?E|gotDV{JmJ9Q~vuhy<`^C4XIUDt|j4o6rK^e8_(=YqC zuaR6TRVf@tUFHB079o4MBIh{M~4>WwnGgesQH*3?w(RA%hCZ*7)b!aNV=yOQ%o_Y=Lt0Sl*(9^jfRnC210Om$=y>*o|3z} zAR&vAdrB#mWoaB0fJSw9xw|Am$fzK>rx-~R#7IFSAwdu_EI|SRfB*yl0w8oX09H^q zAjl2?0I)v*odGJ40FVGaF&2qJq9Gv`>V>2r0|c`GX8h>CX8eHcOy>S0@<;M3<_6UM z7yCEpug5NZL!H_0>Hg_HasQGxR`rY&Z{geOy?N92Z z{lER^um|$*?*G63*njwc(R?NT)Bei*3jVzR>FWUDb^gKhtL4A=kE_1p-%Fo2`!8M} z(0AjuCiS;G{?*^1tB-uY%=)SRx&D)pK4u@>f6@KPe3}2j_har$>HqzH;UCR^ssFD0 z7h+VLO4o@_Yt>>AeaZKUxqyvxWCAjKB>qjQ30UA)#w z&=RmdwlT`7a8J8Yae=7*c8XL|{@%wA8uvCqfsNX^?UZsS>wX}QD{K}ad4y~iO*p%4 z_cS{u7Ek%?WV6em2(U9#d8(&JDirb^u~7wK4+xP$iiI6IlD|a&S)6o=kG;59N|>K1 zn(0mUqbG3YIY7dQd+*4~)`!S9m7H6HP6YcKHhBc#b%1L}VIisp%;TckEkcu0>lo@u995$<*Em;XNodjTiCdC%R+TX|_ZR#|1`RR|`^@Teh zl#w@8fI1FTx2Dy+{blUT{`^kY*V-AZUd?ZZqCS4gW(kY5?retkLbF=>p=59Nl|=sf zo1Pc|{{N4>5nt#627ylGF`3n>X%`w%bw-Y~zWM_{Si$dc82|=YhISal{N7OY?O`C4 zD|qb}6nLWJ`hUyL+E>-;ricg9J@ZNYP(x(Sct&OI$Y!QWr*=^VN;G3#i>^1n4e#Je zOVhbFbLpXVu*16enDM+ic;97@R~u&kh__kgP#!R`*rQEnA+_dLkNP~L`0alC|J;c; zeiK=s8;BsLE)KbG3BD&Br@(Ha@SBT&$?xX`=$;eeel=|R_dIr6-Ro?=HEjnsJ_b`1 zK6Yg^-6;^2aW!xeTK)A~3Rm|L^FCHB_I>jIju7ZGo&N_1*QHkxH2!!%@o4iZ?vntS;&zJdPe1dH#04YD93A44o-MpfD zP{rn_aq>U%RDvC2+bp;xPlsOzauIi3*Lf42`jVKKZCRuKdYhi>FDuL2l=v{$BCN#Q6796s%r-AG$Q^t(3c@ zD?w0UhYr11@feiyl9kY_@H8~|xlmO<8PfQmj1!$@WieW@VxR@Psxfe-v9WCi1+f>F4VL?0O~K7T?m4-u|pSkBpUJZZe*16_wAp zSYZ@;k`3;W3UHKUWc8QeI}0jH5Ly=cGWQPw(Kr2fm=-5L(d`lcXofy8tJY3@Tuadz zYWXR{mW7XT!RF#RVCe%}=tM*O6!AD3^(!8un~opNI%Uko7$5t@<8+?; zTxDys(MyyGsUjtSu9$+|_-t!U3fVb1dkK?l`17<+jfl=hrBHnDSV>^R1=TnQeyqbW z>ov#l%!1|S!1>8UUxIdhQq`_klcHVx0{?#>K3#$4GlXncwldt!g17TcvKq-jo_996 z>oA=tH9CqRl6Yw?Uc`am!V?lHJbizOJaVaScf1UP5e7Dbgabq=b!B~T&_F6?ooU>w%x0A zH~&MHJ=q`fCH{U<7MDXE4SD32cDZA)WJeWkllJ`UspWaS#eDe^kg^oU_A14UE9zG-a^g{xaXf$})Wik>gT zl#dkzGr(;h0JZDuFn(+k8wNq?PZ5grQ<+sM?wBGt@JnH6v0#or-5wBQWKU~(S_> zkE!tc*ZJ1Y&*p(xX84POb3cClRMd!^qJ#CAZfIepEj-<`VURS_yCz0(?*Ixcj4 z-!zV1_QZhpm=0<;*(nm+F>T=)o?ep@CK5I%g^VAA+RB25ab?7)A~z~egru=I1S|@v zH7tXV!0wmGS^qj#e+MY;C5eUjEAp$Y?LDkS^QPZ}8WN85?r$u<-Epi;yZ1|J2J`se z$D6DpH~2F=eI0B&=UFAUnJvZAmClJlK)sutJ?M>xpZiWV&0=G4MZP+x+p>EX=HbCz zxls%Mw?*u^;LbHWIWCyq+yi)`GmFn9J112CZda_u@YIP%i;srFg_paU02Ifij*7}l z&CF-(3|>*a|+vbNR`^RP=9G?ymEJ0Z~)d&c*UE$UMepZ zcITr{0WqhxkjUnM15js_gW=e3Uh|y6ZReaXHIz-=p`x5VvB&rH9y>Amv@^WmXFEw) zQXYrk3feir=a{jMQ+wDIkkFnZ$k{sJakHn*?u za%4b!00ev8NVLM1TY=cl?KB&55BY_MU-sg?c>=Dbz_W{(Z~c?HJi*XpYL)C6Bd8WH zt+v-#0&o~@t4qESi*)+eW%@VD0|o^yF)n0hME$UtXF$*Lvh}7sso{`|pn*JDIy5^Fm3s$5*zEE=?u5<=l8FJc3r%+H} zdfoNl2J0^~!-*mOL5o-x32|e0Im*E!yY7F7E5N)W3>+v_LBydlEx?4$RL5f2oYRD# zaR0wv(-p~wO0eLDl3K=%`{5+0Gd$ktO=W)gWlGZJ0`K z$_RNA=ckrfa;H0KA~dR^p�(p-{x$&=IACIfoAR!za)F-^da-t3#0Dycnp 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 U&YEK6FFOEv8D;4TN#lV30&Xm*MgRZ+ literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index aa7d6427e6fa1074b79ccd52ef67ac15c5637e85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3844 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