From 2774be91d7c564ef85b36b08588edccb7d7faab7 Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Wed, 10 Apr 2024 00:40:25 +0900 Subject: [PATCH 01/18] =?UTF-8?q?[feat]=20UnifestTopAppBar=20=EA=B7=B8?= =?UTF-8?q?=EB=A6=BC=EC=9E=90=20=EC=86=8D=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit b2b19163c6d01d4b970cf4821dfe48d1f7fc8069) (cherry picked from commit 455d9f19568cfb8a453aaa48316aaae607f2df5a) --- .../unifest/android/core/designsystem/component/TopAppBar.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/TopAppBar.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/TopAppBar.kt index b5cb3f6c..0f8ab497 100644 --- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/TopAppBar.kt +++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/TopAppBar.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LocalContentColor @@ -21,12 +22,14 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.rememberCoroutineScope 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.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.skydoves.balloon.ArrowOrientation import com.skydoves.balloon.BalloonAnimation @@ -55,6 +58,7 @@ fun UnifestTopAppBar( contentColor: Color = Color.Black, onNavigationClick: () -> Unit = {}, onTitleClick: (Boolean) -> Unit = {}, + elevation: Dp = 0.dp, ) { CompositionLocalProvider(LocalContentColor provides contentColor) { val icon: @Composable (Modifier, imageVector: ImageVector) -> Unit = @@ -72,6 +76,7 @@ fun UnifestTopAppBar( Box( modifier = Modifier .fillMaxWidth() + .shadow(elevation, RoundedCornerShape(bottomEnd = 20.dp, bottomStart = 20.dp)) .background(containerColor) .then(modifier), ) { From c586f33ecebf0a2078c81d0751c21e33831e5c1c Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Thu, 11 Apr 2024 01:48:30 +0900 Subject: [PATCH 02/18] =?UTF-8?q?[add]=20=ED=8F=B0=ED=8A=B8=20=EB=A6=AC?= =?UTF-8?q?=EC=86=8C=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit bd69a5d6bac477ad56175a6b55f02c389ed8ed89) (cherry picked from commit 26c17707925206bc71972f3d5a2cb3805c3404d4) --- .../unifest/android/core/designsystem/theme/Font.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Font.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Font.kt index 7181fe33..c9ba24e3 100644 --- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Font.kt +++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Font.kt @@ -134,6 +134,18 @@ val Content6 = TextStyle( fontSize = 12.sp, ) +val Content7 = TextStyle( + fontFamily = pretendardFamily, + fontWeight = FontWeight.SemiBold, + fontSize = 11.sp, +) + +val Content8 = TextStyle( + fontFamily = pretendardFamily, + fontWeight = FontWeight.Medium, + fontSize = 15.sp, +) + val WaitingTeam = TextStyle( fontFamily = pretendardFamily, fontWeight = FontWeight.Bold, From 903cf1ed6ca28e4080f87e3be150f890d221abda Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Thu, 11 Apr 2024 01:48:50 +0900 Subject: [PATCH 03/18] =?UTF-8?q?[add]=20=EB=B6=80=EC=8A=A4=20=EB=A9=94?= =?UTF-8?q?=EB=89=B4=20=EC=95=84=EC=9D=B4=EC=BD=98=20=EB=A6=AC=EC=86=8C?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit b1af7e9caed3523b40f72c68b8220be63b6972dc) (cherry picked from commit d47ff9a77df4dd154132a94ada754e9cc39de483) --- .../src/main/res/drawable/ic_admin_mode.xml | 20 +++++++++++++++++++ .../src/main/res/drawable/ic_inquiry.xml | 14 +++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 core/designsystem/src/main/res/drawable/ic_admin_mode.xml create mode 100644 core/designsystem/src/main/res/drawable/ic_inquiry.xml diff --git a/core/designsystem/src/main/res/drawable/ic_admin_mode.xml b/core/designsystem/src/main/res/drawable/ic_admin_mode.xml new file mode 100644 index 00000000..f30ab67a --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_admin_mode.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_inquiry.xml b/core/designsystem/src/main/res/drawable/ic_inquiry.xml new file mode 100644 index 00000000..7ff3a4a4 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_inquiry.xml @@ -0,0 +1,14 @@ + + + + From 2688bc42e4ed480c93b0ed6b6ee71d99060a1aac Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Thu, 11 Apr 2024 01:49:48 +0900 Subject: [PATCH 04/18] =?UTF-8?q?[feat]=20Menu=20Screen=20=EC=95=B1=20?= =?UTF-8?q?=EB=B2=84=EC=A0=BC=20=EC=96=BB=EC=96=B4=EC=98=A4=EB=8A=94=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 11d57deb61b4bdf840358ca2aeedecfa7959052d) (cherry picked from commit 779f9605840ea25de74b308569ec78ad459b0d76) --- .../feature/menu/viewmodel/MenuUiState.kt | 12 +++ .../feature/menu/viewmodel/MenuViewModel.kt | 75 ++++++++++++++++++- 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuUiState.kt diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuUiState.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuUiState.kt new file mode 100644 index 00000000..cd94386e --- /dev/null +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuUiState.kt @@ -0,0 +1,12 @@ +package com.unifest.android.feature.menu.viewmodel + +import com.unifest.android.core.domain.entity.BoothDetailEntity +import com.unifest.android.core.domain.entity.Festival +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf + +data class MenuUiState( + val festivals: ImmutableList = persistentListOf(), + val interestedBooths: ImmutableList = persistentListOf(), + val appVersion: String = "" +) diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt index b8c84732..9b14f19b 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt @@ -1,8 +1,81 @@ package com.unifest.android.feature.menu.viewmodel +import android.app.Application +import android.content.pm.PackageManager import androidx.lifecycle.ViewModel +import com.unifest.android.core.domain.entity.BoothDetailEntity +import com.unifest.android.core.domain.entity.MenuEntity +import com.unifest.android.core.domain.entity.Festival import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update import javax.inject.Inject @HiltViewModel -class MenuViewModel @Inject constructor() : ViewModel() +class MenuViewModel @Inject constructor(private val application: Application) : ViewModel() { + private val _uiState = MutableStateFlow(MenuUiState()) + val uiState: StateFlow = _uiState.asStateFlow() + + init { + + val appVersion = try { + application.packageManager.getPackageInfo(application.packageName, 0).versionName + } catch (e: PackageManager.NameNotFoundException) { + "Unknown" + } + + _uiState.update {currentState -> + currentState.copy( + appVersion = appVersion, + // 임시 데이터 + festivals = persistentListOf( + Festival("school_image_url_1", "서울대학교", "설대축제", "05.06-05.08"), + Festival("school_image_url_2", "연세대학교", "연대축제", "05.06-05.08"), + Festival("school_image_url_3", "고려대학교", "고대축제", "05.06-05.08"), + Festival("school_image_url_4", "건국대학교", "녹색지대", "05.06-05.08"), + Festival("school_image_url_5", "성균관대", "성대축제", "05.06-05.08"), + ), + + interestedBooths = persistentListOf( + BoothDetailEntity( + id = 1, + name = "부스1", + category = "카페", + description = "부스1 설명", + warning = "부스1 주의사항", + location = "부스1 위치", + latitude = 37.5665f, + longitude = 126.9780f, + menus = listOf(), + ), + BoothDetailEntity( + id = 2, + name = "부스2", + category = "카페", + description = "부스2 설명", + warning = "부스2 주의사항", + location = "부스2 위치", + latitude = 37.5665f, + longitude = 126.9780f, + menus = listOf(), + ), + BoothDetailEntity( + id = 3, + name = "부스3", + category = "카페", + description = "부스3 설명", + warning = "부스3 주의사항", + location = "부스3 위치", + latitude = 37.5665f, + longitude = 126.9780f, + menus = listOf(), + ), + ), + ) + } + } + +} From 105dfdf70e761f23feb4716731d91690abf8d6fd Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Thu, 11 Apr 2024 02:01:23 +0900 Subject: [PATCH 05/18] =?UTF-8?q?[feat]=20Menu=20Ui=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit cbacf80863164c9ed3fed3497d662bbc9474ca29) (cherry picked from commit d1602d76fed02f005a2c42124b0f43fbd00e4905) --- .../android/feature/menu/MenuScreen.kt | 406 +++++++++++++++++- 1 file changed, 398 insertions(+), 8 deletions(-) diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt index b2374626..d95b6d65 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt @@ -1,28 +1,333 @@ package com.unifest.android.feature.menu +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 com.unifest.android.core.designsystem.theme.UnifestTheme +import com.unifest.android.core.domain.entity.MenuEntity +import com.unifest.android.core.ui.DevicePreview +import kotlinx.collections.immutable.persistentListOf +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.LazyColumn +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Help +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material.icons.outlined.CheckBoxOutlineBlank +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon import androidx.compose.material3.Text +import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import com.unifest.android.core.designsystem.theme.UnifestTheme -import com.unifest.android.core.ui.DevicePreview +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.unifest.android.core.designsystem.R +import com.unifest.android.core.designsystem.component.TopAppBarNavigationType +import com.unifest.android.core.designsystem.component.UnifestTopAppBar +import com.unifest.android.core.designsystem.theme.Content2 +import com.unifest.android.core.designsystem.theme.Content4 +import com.unifest.android.core.designsystem.theme.Content6 +import com.unifest.android.core.designsystem.theme.Content7 +import com.unifest.android.core.designsystem.theme.Content8 +import com.unifest.android.core.designsystem.theme.MenuTitle +import com.unifest.android.core.designsystem.theme.Title2 +import com.unifest.android.core.designsystem.theme.Title3 +import com.unifest.android.core.designsystem.theme.Title5 +import com.unifest.android.core.domain.entity.BoothDetailEntity +import com.unifest.android.core.domain.entity.Festival +import com.unifest.android.feature.menu.viewmodel.MenuUiState +import com.unifest.android.feature.menu.viewmodel.MenuViewModel @Composable -internal fun MenuRoute() { - MenuScreen() +internal fun MenuRoute( + viewModel: MenuViewModel = hiltViewModel(), +) { + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + MenuScreen( + uiState = uiState, + ) + } @Composable -fun MenuScreen() { +fun MenuScreen( + uiState: MenuUiState, +) { + + Box { + Column { + UnifestTopAppBar( + navigationType = TopAppBarNavigationType.None, + title = "메뉴", + elevation = 8.dp, + modifier = Modifier.background(Color.White, shape = RoundedCornerShape(bottomEnd = 20.dp, bottomStart = 20.dp)), + ) + LazyColumn { + item { Spacer(modifier = Modifier.height(5.dp)) } + item { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .padding(20.dp), + ) { + Text(text = "나의 관심학교", style = Title3) + Text(text = "추가하기>", style = Content7, color = Color(0xFF545454)) + } + } + item { + LazyVerticalGrid( + columns = GridCells.Fixed(4), + modifier = Modifier + + .height( + when { + uiState.festivals.isEmpty() -> 0.dp + else -> { + val rows = ((uiState.festivals.size - 1) / 4 + 1) * 130 + rows.dp + } + }, + ), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + items(uiState.festivals.size) { index -> + val school = uiState.festivals[index] + SchoolItem( + festival = school, + ) + } + } + } + item { + VerticalDivider( + modifier = Modifier + .fillMaxWidth() + .height(8.dp) + .background(Color(0xFFF1F3F7)), + ) + } + item { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .padding(start = 20.dp, end = 20.dp, top = 20.dp), + ) { + Text(text = "관심부스", style = Title3) + Text(text = "더보기>", style = Content7, color = Color(0xFF545454)) + } + } + + itemsIndexed(uiState.interestedBooths) { index, booth -> + Column { + Spacer(modifier = Modifier.height(16.dp)) + IncomingFestivalCard(booth) + } + if (index < uiState.interestedBooths.size - 1) { + Spacer(modifier = Modifier.height(16.dp)) + HorizontalDivider( + color = Color(0xFFDFDFDF), + modifier = Modifier.padding(horizontal = 20.dp), + thickness = 1.dp, + ) + } + } + item { Spacer(modifier = Modifier.height(16.dp)) } + item { + VerticalDivider( + modifier = Modifier + .fillMaxWidth() + .height(8.dp) + .background(Color(0xFFF1F3F7)), + ) + } + item { + MenuItem( + ImageVector.vectorResource(R.drawable.ic_inquiry), + title = "이용 문의", + onClick = { /* 구현 */ }, + ) + } + item { + VerticalDivider( + modifier = Modifier + .fillMaxWidth() + .height(1.dp) + .background(Color(0xFFE0E0E0)), + ) + } + item { + MenuItem( + ImageVector.vectorResource(R.drawable.ic_admin_mode), + title = "운영자 모드 진입", + onClick = { /* 구현 */ }, + ) + } + item { + VerticalDivider( + modifier = Modifier + .fillMaxWidth() + .height(1.dp) + .background(Color(0xFFE0E0E0)), + ) + } + item { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 13.dp), + ) { + Text("UniFest ${uiState.appVersion}", textAlign = TextAlign.Center, color = Color(0xFFC5C5C5)) + } + } + } + + } + } + +} + +@Composable +fun MenuItem(icon: ImageVector, title: String, onClick: () -> Unit) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .padding(25.dp), + ) { + Icon(icon, contentDescription = null, tint = Color(0xFF7A7A7C)) + Spacer(modifier = Modifier.width(16.dp)) + Text(title, style = Content8) + } +} + +@Composable +fun SchoolItem( + festival: Festival, +) { Column( - modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxSize() + .padding(16.dp), ) { - Text("Menu Screen") + Box( + modifier = Modifier + .size(50.dp) + .shadow( + elevation = 4.dp, + shape = CircleShape, + clip = false, + ) + .background(Color.White, CircleShape) + .padding(5.dp), + contentAlignment = Alignment.Center, + ) { + Image( + painter = painterResource(id = R.drawable.ic_waiting), + contentDescription = null, + modifier = Modifier.size(50.dp), + ) + } + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = festival.schoolName, + color = Color(0xFF545454), + style = Content6, + ) + Spacer(modifier = Modifier.height(2.dp)) + Text( + text = festival.festivalName, + color = Color.Black, + style = MenuTitle, + ) + } + +} + +@Composable +fun IncomingFestivalCard(booth: BoothDetailEntity) { + val isBookmarked = true + val bookMarkColor = if (isBookmarked) Color(0xFFF5687E) else Color(0xFF4B4B4B) + Row( + modifier = Modifier + .padding(horizontal = 20.dp) + .fillMaxSize(), + + ) { + Icon( + imageVector = Icons.Outlined.CheckBoxOutlineBlank, + contentDescription = "Example Image Icon", + modifier = Modifier.size(86.dp), + ) + Spacer(modifier = Modifier.width(14.dp)) + Column( + modifier = Modifier + .weight(1f) + .fillMaxWidth(), + ) { + Text( + text = booth.name, + style = Title2, + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = booth.description, + style = Title5, + color = Color(0xFF545454), + ) + Spacer(modifier = Modifier.height(13.dp))//todo:23dp 너무 멀음 + Row { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_location_green), + contentDescription = "Location Icon", + tint = Color.Unspecified, + ) + Spacer(modifier = Modifier.width(3.dp)) + Text( + text = booth.location, + style = Title5, + color = Color(0xFF545454), + modifier = Modifier.align(Alignment.CenterVertically), + ) + } + } + Icon( + imageVector = ImageVector.vectorResource(if (isBookmarked) R.drawable.ic_bookmarked else R.drawable.ic_bookmark), + contentDescription = if (isBookmarked) "북마크됨" else "북마크하기", + tint = bookMarkColor, + ) } } @@ -30,6 +335,91 @@ fun MenuScreen() { @Composable fun MenuScreenPreview() { UnifestTheme { - MenuScreen() + MenuScreen( + uiState = MenuUiState( + festivals = persistentListOf( + Festival( + schoolName = "건국대", + festivalName = "녹색지대", + festivalDate = "2021.11.11", + imgUrl = "", + ), + Festival( + schoolName = "건국대", + festivalName = "녹색지대", + festivalDate = "2021.11.11", + imgUrl = "", + ), + Festival( + schoolName = "건국대", + festivalName = "녹색지대", + festivalDate = "2021.11.11", + imgUrl = "", + ), + Festival( + schoolName = "건국대", + festivalName = "녹색지대", + festivalDate = "2021.11.11", + imgUrl = "", + ), + ), + interestedBooths = persistentListOf( + BoothDetailEntity( + id = 1, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), + BoothDetailEntity( + id = 2, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), +// BoothDetailEntity( +// id = 3, +// name = "부스 이름", +// category = "음식", +// description = "부스 설명", +// warning = "주의사항", +// location = "부스 위치", +// latitude = 0.0f, +// longitude = 0.0f, +// menus = listOf( +// MenuEntity( +// id = 1, +// name = "메뉴 이름", +// price = 1000, +// imgUrl = "", +// ), +// ), +// ), + ), + ), + ) } } From 9ec0855643a12bf4e69caba35692b4a6800fa05f Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Thu, 11 Apr 2024 23:51:46 +0900 Subject: [PATCH 06/18] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EC=8B=9C=EC=95=88?= =?UTF-8?q?=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 0f5c3d6cb1d1c8440753bcd790faf403f2957308) --- .../android/feature/menu/MenuScreen.kt | 248 +++++++++--------- .../feature/menu/viewmodel/MenuUiState.kt | 2 +- .../feature/menu/viewmodel/MenuViewModel.kt | 10 +- 3 files changed, 125 insertions(+), 135 deletions(-) diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt index d95b6d65..d2e04dd9 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt @@ -25,15 +25,17 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Help -import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.outlined.CheckBoxOutlineBlank import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.material3.VerticalDivider 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.shadow @@ -48,8 +50,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.unifest.android.core.designsystem.R import com.unifest.android.core.designsystem.component.TopAppBarNavigationType import com.unifest.android.core.designsystem.component.UnifestTopAppBar -import com.unifest.android.core.designsystem.theme.Content2 -import com.unifest.android.core.designsystem.theme.Content4 import com.unifest.android.core.designsystem.theme.Content6 import com.unifest.android.core.designsystem.theme.Content7 import com.unifest.android.core.designsystem.theme.Content8 @@ -70,21 +70,24 @@ internal fun MenuRoute( MenuScreen( uiState = uiState, ) - } @Composable fun MenuScreen( uiState: MenuUiState, ) { - Box { Column { UnifestTopAppBar( navigationType = TopAppBarNavigationType.None, title = "메뉴", elevation = 8.dp, - modifier = Modifier.background(Color.White, shape = RoundedCornerShape(bottomEnd = 20.dp, bottomStart = 20.dp)), + modifier = Modifier + .background( + Color.White, + shape = RoundedCornerShape(bottomEnd = 20.dp, bottomStart = 20.dp), + ) + .padding(top = 5.dp, bottom = 5.dp), ) LazyColumn { item { Spacer(modifier = Modifier.height(5.dp)) } @@ -94,33 +97,45 @@ fun MenuScreen( verticalAlignment = Alignment.CenterVertically, modifier = Modifier .fillMaxWidth() - .padding(20.dp), + .padding(top = 10.dp, start = 20.dp), ) { - Text(text = "나의 관심학교", style = Title3) - Text(text = "추가하기>", style = Content7, color = Color(0xFF545454)) + Text( + text = "나의 관심학교", + style = Title3, + ) + TextButton( + onClick = { /*TODO*/ }, + modifier = Modifier.padding(end = 8.dp), + ) { + Text( + text = "추가하기>", + style = Content7, + color = Color(0xFF545454), + ) + } } } item { LazyVerticalGrid( columns = GridCells.Fixed(4), modifier = Modifier - + .padding(horizontal = 20.dp) .height( when { uiState.festivals.isEmpty() -> 0.dp else -> { - val rows = ((uiState.festivals.size - 1) / 4 + 1) * 130 + val rows = ((uiState.festivals.size - 1) / 4 + 1) * 140 rows.dp } }, ), - horizontalArrangement = Arrangement.spacedBy(8.dp), + horizontalArrangement = Arrangement.spacedBy(20.dp), verticalArrangement = Arrangement.spacedBy(8.dp), ) { items(uiState.festivals.size) { index -> - val school = uiState.festivals[index] - SchoolItem( - festival = school, + val festival = uiState.festivals[index] + FestivalItem( + festival = festival, ) } } @@ -139,28 +154,24 @@ fun MenuScreen( verticalAlignment = Alignment.CenterVertically, modifier = Modifier .fillMaxWidth() - .padding(start = 20.dp, end = 20.dp, top = 20.dp), + .padding(start = 20.dp, top = 10.dp), ) { Text(text = "관심부스", style = Title3) - Text(text = "더보기>", style = Content7, color = Color(0xFF545454)) + TextButton( + onClick = { /*TODO*/ }, + modifier = Modifier.padding(end = 8.dp), + ) { + Text( + text = "더보기>", + style = Content7, + color = Color(0xFF545454), + ) + } } } - - itemsIndexed(uiState.interestedBooths) { index, booth -> - Column { - Spacer(modifier = Modifier.height(16.dp)) - IncomingFestivalCard(booth) - } - if (index < uiState.interestedBooths.size - 1) { - Spacer(modifier = Modifier.height(16.dp)) - HorizontalDivider( - color = Color(0xFFDFDFDF), - modifier = Modifier.padding(horizontal = 20.dp), - thickness = 1.dp, - ) - } + itemsIndexed(uiState.interestedBooths.take(3)) { index, booth -> + InterestedBoothsItems(booth, index, uiState.interestedBooths.size) } - item { Spacer(modifier = Modifier.height(16.dp)) } item { VerticalDivider( modifier = Modifier @@ -210,45 +221,25 @@ fun MenuScreen( } } } - } } - } @Composable -fun MenuItem(icon: ImageVector, title: String, onClick: () -> Unit) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .clickable(onClick = onClick) - .padding(25.dp), - ) { - Icon(icon, contentDescription = null, tint = Color(0xFF7A7A7C)) - Spacer(modifier = Modifier.width(16.dp)) - Text(title, style = Content8) - } -} - -@Composable -fun SchoolItem( +fun FestivalItem( festival: Festival, ) { Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, - modifier = Modifier - .fillMaxSize() - .padding(16.dp), + modifier = Modifier.padding(vertical = 10.dp), ) { Box( modifier = Modifier - .size(50.dp) + .size(65.dp) .shadow( - elevation = 4.dp, + elevation = 6.dp, shape = CircleShape, - clip = false, ) .background(Color.White, CircleShape) .padding(5.dp), @@ -257,7 +248,7 @@ fun SchoolItem( Image( painter = painterResource(id = R.drawable.ic_waiting), contentDescription = null, - modifier = Modifier.size(50.dp), + modifier = Modifier.size(60.dp), ) } Spacer(modifier = Modifier.height(8.dp)) @@ -273,61 +264,94 @@ fun SchoolItem( style = MenuTitle, ) } - } @Composable -fun IncomingFestivalCard(booth: BoothDetailEntity) { - val isBookmarked = true +fun InterestedBoothsItems(booth: BoothDetailEntity, index: Int, total: Int) { + var isBookmarked by remember { mutableStateOf(true) } val bookMarkColor = if (isBookmarked) Color(0xFFF5687E) else Color(0xFF4B4B4B) - Row( + Column( modifier = Modifier - .padding(horizontal = 20.dp) - .fillMaxSize(), - - ) { - Icon( - imageVector = Icons.Outlined.CheckBoxOutlineBlank, - contentDescription = "Example Image Icon", - modifier = Modifier.size(86.dp), - ) - Spacer(modifier = Modifier.width(14.dp)) - Column( - modifier = Modifier - .weight(1f) - .fillMaxWidth(), + .clickable { /* 클릭 이벤트 처리 */ } + .padding(horizontal = 20.dp), + ) { + Spacer(modifier = Modifier.height(16.dp)) + Row( + modifier = Modifier.fillMaxSize(), ) { - Text( - text = booth.name, - style = Title2, - ) - Spacer(modifier = Modifier.height(4.dp)) - Text( - text = booth.description, - style = Title5, - color = Color(0xFF545454), + Icon( + imageVector = Icons.Outlined.CheckBoxOutlineBlank, + contentDescription = "Example Image Icon", + modifier = Modifier.size(86.dp), ) - Spacer(modifier = Modifier.height(13.dp))//todo:23dp 너무 멀음 - Row { - Icon( - imageVector = ImageVector.vectorResource(id = R.drawable.ic_location_green), - contentDescription = "Location Icon", - tint = Color.Unspecified, + Spacer(modifier = Modifier.width(14.dp)) + Column( + modifier = Modifier + .weight(1f) + .fillMaxWidth(), + ) { + Text( + text = booth.name, + style = Title2, ) - Spacer(modifier = Modifier.width(3.dp)) + Spacer(modifier = Modifier.height(4.dp)) Text( - text = booth.location, + text = booth.description, style = Title5, color = Color(0xFF545454), - modifier = Modifier.align(Alignment.CenterVertically), ) + Spacer(modifier = Modifier.height(13.dp)) + Row { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_location_green), + contentDescription = "Location Icon", + tint = Color.Unspecified, + ) + Spacer(modifier = Modifier.width(3.dp)) + Text( + text = booth.location, + style = Title5, + color = Color(0xFF545454), + modifier = Modifier.align(Alignment.CenterVertically), + ) + } } + Icon( + imageVector = ImageVector.vectorResource(if (isBookmarked) R.drawable.ic_bookmarked else R.drawable.ic_bookmark), + contentDescription = if (isBookmarked) "북마크됨" else "북마크하기", + tint = bookMarkColor, + modifier = Modifier + .size(24.dp) + .clickable(onClick = { isBookmarked = !isBookmarked }), + ) + } + Spacer(modifier = Modifier.height(16.dp)) + if (index < total - 1) { + HorizontalDivider( + color = Color(0xFFDFDFDF), + thickness = 1.dp, + modifier = Modifier.fillMaxWidth(), + ) } + } +} + +@Composable +fun MenuItem(icon: ImageVector, title: String, onClick: () -> Unit) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .padding(25.dp), + ) { Icon( - imageVector = ImageVector.vectorResource(if (isBookmarked) R.drawable.ic_bookmarked else R.drawable.ic_bookmark), - contentDescription = if (isBookmarked) "북마크됨" else "북마크하기", - tint = bookMarkColor, + icon, + contentDescription = null, + tint = Color(0xFF7A7A7C), ) + Spacer(modifier = Modifier.width(16.dp)) + Text(title, style = Content8) } } @@ -350,18 +374,6 @@ fun MenuScreenPreview() { festivalDate = "2021.11.11", imgUrl = "", ), - Festival( - schoolName = "건국대", - festivalName = "녹색지대", - festivalDate = "2021.11.11", - imgUrl = "", - ), - Festival( - schoolName = "건국대", - festivalName = "녹색지대", - festivalDate = "2021.11.11", - imgUrl = "", - ), ), interestedBooths = persistentListOf( BoothDetailEntity( @@ -400,24 +412,6 @@ fun MenuScreenPreview() { ), ), ), -// BoothDetailEntity( -// id = 3, -// name = "부스 이름", -// category = "음식", -// description = "부스 설명", -// warning = "주의사항", -// location = "부스 위치", -// latitude = 0.0f, -// longitude = 0.0f, -// menus = listOf( -// MenuEntity( -// id = 1, -// name = "메뉴 이름", -// price = 1000, -// imgUrl = "", -// ), -// ), -// ), ), ), ) diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuUiState.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuUiState.kt index cd94386e..ef8c8b51 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuUiState.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuUiState.kt @@ -8,5 +8,5 @@ import kotlinx.collections.immutable.persistentListOf data class MenuUiState( val festivals: ImmutableList = persistentListOf(), val interestedBooths: ImmutableList = persistentListOf(), - val appVersion: String = "" + val appVersion: String = "", ) diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt index 9b14f19b..37a93f92 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt @@ -4,7 +4,6 @@ import android.app.Application import android.content.pm.PackageManager import androidx.lifecycle.ViewModel import com.unifest.android.core.domain.entity.BoothDetailEntity -import com.unifest.android.core.domain.entity.MenuEntity import com.unifest.android.core.domain.entity.Festival import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.persistentListOf @@ -12,22 +11,21 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update +import timber.log.Timber import javax.inject.Inject @HiltViewModel class MenuViewModel @Inject constructor(private val application: Application) : ViewModel() { private val _uiState = MutableStateFlow(MenuUiState()) val uiState: StateFlow = _uiState.asStateFlow() - init { - val appVersion = try { application.packageManager.getPackageInfo(application.packageName, 0).versionName } catch (e: PackageManager.NameNotFoundException) { + Timber.tag("AppVersion").e(e, "Failed to get package info") "Unknown" } - - _uiState.update {currentState -> + _uiState.update { currentState -> currentState.copy( appVersion = appVersion, // 임시 데이터 @@ -38,7 +36,6 @@ class MenuViewModel @Inject constructor(private val application: Application) : Festival("school_image_url_4", "건국대학교", "녹색지대", "05.06-05.08"), Festival("school_image_url_5", "성균관대", "성대축제", "05.06-05.08"), ), - interestedBooths = persistentListOf( BoothDetailEntity( id = 1, @@ -77,5 +74,4 @@ class MenuViewModel @Inject constructor(private val application: Application) : ) } } - } From 231449d8bf31cf7c038781b582a1537f7315575c Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Fri, 12 Apr 2024 00:03:11 +0900 Subject: [PATCH 07/18] =?UTF-8?q?[feat]=20=EA=B4=80=EC=8B=AC=ED=95=99?= =?UTF-8?q?=EA=B5=90=20=EC=B6=94=EA=B0=80=20=ED=81=B4=EB=A6=AD=EC=8B=9C=20?= =?UTF-8?q?Intro=ED=99=94=EB=A9=B4=EC=97=90=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 7da62be9d93520bed5017338d66ea54eff020986) --- .../kotlin/com/unifest/android/feature/main/MainScreen.kt | 4 +++- .../kotlin/com/unifest/android/feature/menu/MenuScreen.kt | 6 +++++- .../android/feature/menu/navigation/MenuNavigation.kt | 6 ++++-- gradle/libs.versions.toml | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt index 386bb5f3..5667849f 100644 --- a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt +++ b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt @@ -82,7 +82,9 @@ internal fun MainScreen( onShowSnackBar = onShowSnackBar, ) waitingNavGraph() - menuNavGraph() + menuNavGraph( + onNavigateToIntro = onNavigateToIntro, + ) } }, bottomBar = { diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt index d2e04dd9..7213cc1a 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt @@ -64,17 +64,20 @@ import com.unifest.android.feature.menu.viewmodel.MenuViewModel @Composable internal fun MenuRoute( + onNavigateToIntro: () -> Unit, viewModel: MenuViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() MenuScreen( uiState = uiState, + onNavigateToIntro = onNavigateToIntro, ) } @Composable fun MenuScreen( uiState: MenuUiState, + onNavigateToIntro: () -> Unit, ) { Box { Column { @@ -104,7 +107,7 @@ fun MenuScreen( style = Title3, ) TextButton( - onClick = { /*TODO*/ }, + onClick = { onNavigateToIntro() }, modifier = Modifier.padding(end = 8.dp), ) { Text( @@ -360,6 +363,7 @@ fun MenuItem(icon: ImageVector, title: String, onClick: () -> Unit) { fun MenuScreenPreview() { UnifestTheme { MenuScreen( + onNavigateToIntro = { }, uiState = MenuUiState( festivals = persistentListOf( Festival( diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt index 1f9ef1fa..0a5fa60d 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt @@ -12,8 +12,10 @@ fun NavController.navigateToMenu(navOptions: NavOptions) { navigate(MENU_ROUTE, navOptions) } -fun NavGraphBuilder.menuNavGraph() { +fun NavGraphBuilder.menuNavGraph( + onNavigateToIntro: () -> Unit, +) { composable(route = MENU_ROUTE) { - MenuRoute() + MenuRoute(onNavigateToIntro = onNavigateToIntro) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1a112b8d..5df9532d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,7 +20,7 @@ kotlinx-serialization-converter = "1.0.0" kotlinx-collections-immutable = "0.3.7" androidx-core = "1.12.0" -androidx-lifecycle = "2.8.0-alpha04" +androidx-lifecycle = "2.8.0-alpha02" androidx-splash = "1.0.1" androidx-startup = "1.1.1" androidx-navigation = "2.7.7" From ce54c08967322dfe4d97a772734d2dad211bfd8f Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Fri, 12 Apr 2024 00:13:36 +0900 Subject: [PATCH 08/18] =?UTF-8?q?[feat]=20MenuScreen=EA=B3=BC=20Interested?= =?UTF-8?q?Booth=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 5324d61661e43dee367ddfa5e7a353338c6b16b0) --- .../kotlin/com/unifest/android/feature/main/MainScreen.kt | 3 +++ .../kotlin/com/unifest/android/feature/menu/MenuScreen.kt | 6 +++++- .../android/feature/menu/navigation/MenuNavigation.kt | 6 +++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt index 5667849f..62b1cdb9 100644 --- a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt +++ b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt @@ -37,6 +37,7 @@ import com.unifest.android.core.designsystem.theme.BottomMenuBar import com.unifest.android.core.designsystem.theme.UnifestTheme import com.unifest.android.feature.booth.navigation.boothNavGraph import com.unifest.android.feature.home.navigation.homeNavGraph +import com.unifest.android.feature.interested_booth.navigation.interestedBoothNavGraph import com.unifest.android.feature.map.navigation.mapNavGraph import com.unifest.android.feature.menu.navigation.menuNavGraph import com.unifest.android.feature.waiting.navigation.waitingNavGraph @@ -84,7 +85,9 @@ internal fun MainScreen( waitingNavGraph() menuNavGraph( onNavigateToIntro = onNavigateToIntro, + onNavigateToInterestedBooths = navigator::navigateToInterestedBooth, ) + interestedBoothNavGraph() } }, bottomBar = { diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt index 7213cc1a..fa23804d 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt @@ -65,12 +65,14 @@ import com.unifest.android.feature.menu.viewmodel.MenuViewModel @Composable internal fun MenuRoute( onNavigateToIntro: () -> Unit, + onNavigateToInterestedBooths: () -> Unit, viewModel: MenuViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() MenuScreen( uiState = uiState, onNavigateToIntro = onNavigateToIntro, + onNavigateToInterestedBooths = onNavigateToInterestedBooths, ) } @@ -78,6 +80,7 @@ internal fun MenuRoute( fun MenuScreen( uiState: MenuUiState, onNavigateToIntro: () -> Unit, + onNavigateToInterestedBooths: () -> Unit, ) { Box { Column { @@ -161,7 +164,7 @@ fun MenuScreen( ) { Text(text = "관심부스", style = Title3) TextButton( - onClick = { /*TODO*/ }, + onClick = { onNavigateToInterestedBooths() }, modifier = Modifier.padding(end = 8.dp), ) { Text( @@ -364,6 +367,7 @@ fun MenuScreenPreview() { UnifestTheme { MenuScreen( onNavigateToIntro = { }, + onNavigateToInterestedBooths = { }, uiState = MenuUiState( festivals = persistentListOf( Festival( diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt index 0a5fa60d..12d0ab7c 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt @@ -14,8 +14,12 @@ fun NavController.navigateToMenu(navOptions: NavOptions) { fun NavGraphBuilder.menuNavGraph( onNavigateToIntro: () -> Unit, + onNavigateToInterestedBooths: () -> Unit, ) { composable(route = MENU_ROUTE) { - MenuRoute(onNavigateToIntro = onNavigateToIntro) + MenuRoute( + onNavigateToIntro = onNavigateToIntro, + onNavigateToInterestedBooths = onNavigateToInterestedBooths + ) } } From 1c0a545b4a14ef9ed6d68ff6322177fc0140fac7 Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Fri, 12 Apr 2024 00:26:33 +0900 Subject: [PATCH 09/18] =?UTF-8?q?[feat]=20=EA=B4=80=EC=8B=AC=20=EB=B6=80?= =?UTF-8?q?=EC=8A=A4=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 73cf90426f57975a19bf5feef03d6230b5200a86) --- .../interested_booth/InterestedBoothScreen.kt | 235 +++++++++++++++++- .../viewmodel/InterestedBoothViewModel.kt | 116 ++++++++- .../android/feature/menu/MenuScreen.kt | 2 +- 3 files changed, 336 insertions(+), 17 deletions(-) diff --git a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt index fed2552b..f4ae804a 100644 --- a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt +++ b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt @@ -1,17 +1,47 @@ package com.unifest.android.feature.interested_booth +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.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.itemsIndexed +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.CheckBoxOutlineBlank +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon 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.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.unifest.android.core.designsystem.R +import com.unifest.android.core.designsystem.component.TopAppBarNavigationType +import com.unifest.android.core.designsystem.component.UnifestTopAppBar +import com.unifest.android.core.designsystem.theme.Title2 +import com.unifest.android.core.designsystem.theme.Title5 import com.unifest.android.core.designsystem.theme.UnifestTheme import com.unifest.android.core.domain.entity.BoothDetailEntity +import com.unifest.android.core.domain.entity.MenuEntity import com.unifest.android.core.ui.DevicePreview import com.unifest.android.feature.interested_booth.viewmodel.InterestedBoothUiState import com.unifest.android.feature.interested_booth.viewmodel.InterestedBoothViewModel @@ -22,7 +52,6 @@ internal fun InterestedBoothRoute( viewModel: InterestedBoothViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() - InterestedBoothScreen(uiState = uiState) } @@ -30,12 +59,95 @@ internal fun InterestedBoothRoute( internal fun InterestedBoothScreen( uiState: InterestedBoothUiState, ) { + Box { + Column { + UnifestTopAppBar( + navigationType = TopAppBarNavigationType.Back, + title = "관심 부스", + elevation = 8.dp, + modifier = Modifier + .background( + Color.White, + shape = RoundedCornerShape(bottomEnd = 20.dp, bottomStart = 20.dp), + ) + .padding(top = 13.dp, bottom = 5.dp), + ) + LazyColumn { + itemsIndexed(uiState.interestedBooths) { index, booth -> + InterestedBoothsItems(booth, index, uiState.interestedBooths.size) + } + } + } + } +} + +@Composable +fun InterestedBoothsItems(booth: BoothDetailEntity, index: Int, total: Int) { + var isBookmarked by remember { mutableStateOf(true) } + val bookMarkColor = if (isBookmarked) Color(0xFFF5687E) else Color(0xFF4B4B4B) Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, + modifier = Modifier + .clickable { /* 클릭 이벤트 처리 */ } + .padding(horizontal = 20.dp), ) { - Text(uiState.interestedBooths.toString()) + Spacer(modifier = Modifier.height(16.dp)) + Row( + modifier = Modifier.fillMaxSize(), + ) { + Icon( + imageVector = Icons.Outlined.CheckBoxOutlineBlank, + contentDescription = "Example Image Icon", + modifier = Modifier.size(86.dp), + ) + Spacer(modifier = Modifier.width(14.dp)) + Column( + modifier = Modifier + .weight(1f) + .fillMaxWidth(), + ) { + Text( + text = booth.name, + style = Title2, + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = booth.description, + style = Title5, + color = Color(0xFF545454), + ) + Spacer(modifier = Modifier.height(13.dp)) + Row { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_location_green), + contentDescription = "Location Icon", + tint = Color.Unspecified, + ) + Spacer(modifier = Modifier.width(3.dp)) + Text( + text = booth.location, + style = Title5, + color = Color(0xFF545454), + modifier = Modifier.align(Alignment.CenterVertically), + ) + } + } + Icon( + imageVector = ImageVector.vectorResource(if (isBookmarked) R.drawable.ic_bookmarked else R.drawable.ic_bookmark), + contentDescription = if (isBookmarked) "북마크됨" else "북마크하기", + tint = bookMarkColor, + modifier = Modifier + .size(24.dp) + .clickable(onClick = { isBookmarked = !isBookmarked }), + ) + } + Spacer(modifier = Modifier.height(16.dp)) + if (index < total - 1) { + HorizontalDivider( + color = Color(0xFFDFDFDF), + thickness = 1.dp, + modifier = Modifier.fillMaxWidth(), + ) + } } } @@ -46,11 +158,114 @@ fun InterestedBoothScreenPreview() { InterestedBoothScreen( uiState = InterestedBoothUiState( interestedBooths = persistentListOf( - BoothDetailEntity(1L, "컴공 주점", "컴퓨터공학부 전용 부스"), - BoothDetailEntity(2L, "학생회 부스", "건국대학교 학생회 부스"), - BoothDetailEntity(3L, "컴공 주점", "컴퓨터공학부 전용 부스"), - BoothDetailEntity(4L, "학생회 부스", "건국대학교 학생회 부스"), - BoothDetailEntity(5L, "컴공 주점", "컴퓨터공학부 전용 부스"), + BoothDetailEntity( + id = 1, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), + BoothDetailEntity( + id = 2, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), + BoothDetailEntity( + id = 3, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), + BoothDetailEntity( + id = 4, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), + BoothDetailEntity( + id = 5, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), + BoothDetailEntity( + id = 6, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), ), ), ) diff --git a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/viewmodel/InterestedBoothViewModel.kt b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/viewmodel/InterestedBoothViewModel.kt index b7b8a9f9..39583583 100644 --- a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/viewmodel/InterestedBoothViewModel.kt +++ b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/viewmodel/InterestedBoothViewModel.kt @@ -2,6 +2,7 @@ package com.unifest.android.feature.interested_booth.viewmodel import androidx.lifecycle.ViewModel import com.unifest.android.core.domain.entity.BoothDetailEntity +import com.unifest.android.core.domain.entity.MenuEntity import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.flow.MutableStateFlow @@ -19,12 +20,115 @@ class InterestedBoothViewModel @Inject constructor() : ViewModel() { _uiState.update { it.copy( interestedBooths = persistentListOf( - BoothDetailEntity(1L, "컴공 주점", "컴퓨터공학부 전용 부스"), - BoothDetailEntity(2L, "학생회 부스", "건국대학교 학생회 부스"), - BoothDetailEntity(3L, "컴공 주점", "컴퓨터공학부 전용 부스"), - BoothDetailEntity(4L, "학생회 부스", "건국대학교 학생회 부스"), - BoothDetailEntity(5L, "컴공 주점", "컴퓨터공학부 전용 부스"), - ), + BoothDetailEntity( + id = 1, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), + BoothDetailEntity( + id = 2, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), + BoothDetailEntity( + id = 3, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), + BoothDetailEntity( + id = 4, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), + BoothDetailEntity( + id = 5, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), + BoothDetailEntity( + id = 6, + name = "부스 이름", + category = "음식", + description = "부스 설명", + warning = "주의사항", + location = "부스 위치", + latitude = 0.0f, + longitude = 0.0f, + menus = listOf( + MenuEntity( + id = 1, + name = "메뉴 이름", + price = 1000, + imgUrl = "", + ), + ), + ), + ) ) } } diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt index fa23804d..8507ba31 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt @@ -93,7 +93,7 @@ fun MenuScreen( Color.White, shape = RoundedCornerShape(bottomEnd = 20.dp, bottomStart = 20.dp), ) - .padding(top = 5.dp, bottom = 5.dp), + .padding(top = 13.dp, bottom = 5.dp), ) LazyColumn { item { Spacer(modifier = Modifier.height(5.dp)) } From 4071f25ccad3d6986d9008f6a1c45102517601fa Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Fri, 12 Apr 2024 00:40:36 +0900 Subject: [PATCH 10/18] [chore] style check success --- .../android/feature/interested_booth/InterestedBoothScreen.kt | 1 - .../interested_booth/viewmodel/InterestedBoothViewModel.kt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt index f4ae804a..ec2aa57f 100644 --- a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt +++ b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt @@ -2,7 +2,6 @@ package com.unifest.android.feature.interested_booth 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 diff --git a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/viewmodel/InterestedBoothViewModel.kt b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/viewmodel/InterestedBoothViewModel.kt index 39583583..1f1c06e2 100644 --- a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/viewmodel/InterestedBoothViewModel.kt +++ b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/viewmodel/InterestedBoothViewModel.kt @@ -128,7 +128,7 @@ class InterestedBoothViewModel @Inject constructor() : ViewModel() { ), ), ), - ) + ), ) } } From 3344783b69ba041a63d08417ff654266318a86fa Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Fri, 12 Apr 2024 00:40:59 +0900 Subject: [PATCH 11/18] [chore] style check success --- .../unifest/android/feature/menu/navigation/MenuNavigation.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt index 12d0ab7c..0036bf60 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt @@ -19,7 +19,7 @@ fun NavGraphBuilder.menuNavGraph( composable(route = MENU_ROUTE) { MenuRoute( onNavigateToIntro = onNavigateToIntro, - onNavigateToInterestedBooths = onNavigateToInterestedBooths + onNavigateToInterestedBooths = onNavigateToInterestedBooths, ) } } From a22b7c0d344e74aa21a871bf3c3558d34d6f70e7 Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Fri, 12 Apr 2024 01:06:06 +0900 Subject: [PATCH 12/18] =?UTF-8?q?[feat]=20Network=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../interested_booth/InterestedBoothScreen.kt | 11 +++++---- .../android/feature/menu/MenuScreen.kt | 23 ++++++++++--------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt index ec2aa57f..2658cd0d 100644 --- a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt +++ b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt @@ -27,6 +27,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.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.vectorResource @@ -34,6 +35,7 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.unifest.android.core.designsystem.R +import com.unifest.android.core.designsystem.component.NetworkImage import com.unifest.android.core.designsystem.component.TopAppBarNavigationType import com.unifest.android.core.designsystem.component.UnifestTopAppBar import com.unifest.android.core.designsystem.theme.Title2 @@ -93,10 +95,11 @@ fun InterestedBoothsItems(booth: BoothDetailEntity, index: Int, total: Int) { Row( modifier = Modifier.fillMaxSize(), ) { - Icon( - imageVector = Icons.Outlined.CheckBoxOutlineBlank, - contentDescription = "Example Image Icon", - modifier = Modifier.size(86.dp), + NetworkImage( + imageUrl = "https://picsum.photos/86", + modifier = Modifier + .size(86.dp) + .clip(RoundedCornerShape(16.dp)), ) Spacer(modifier = Modifier.width(14.dp)) Column( diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt index 8507ba31..f666cded 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt @@ -24,8 +24,6 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.CheckBoxOutlineBlank import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.Text @@ -38,16 +36,17 @@ 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.graphics.vector.ImageVector -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.unifest.android.core.designsystem.R +import com.unifest.android.core.designsystem.component.NetworkImage import com.unifest.android.core.designsystem.component.TopAppBarNavigationType import com.unifest.android.core.designsystem.component.UnifestTopAppBar import com.unifest.android.core.designsystem.theme.Content6 @@ -251,10 +250,11 @@ fun FestivalItem( .padding(5.dp), contentAlignment = Alignment.Center, ) { - Image( - painter = painterResource(id = R.drawable.ic_waiting), - contentDescription = null, - modifier = Modifier.size(60.dp), + NetworkImage( + imageUrl = "https://picsum.photos/86", + modifier = Modifier + .size(60.dp) + .clip(CircleShape), ) } Spacer(modifier = Modifier.height(8.dp)) @@ -285,10 +285,11 @@ fun InterestedBoothsItems(booth: BoothDetailEntity, index: Int, total: Int) { Row( modifier = Modifier.fillMaxSize(), ) { - Icon( - imageVector = Icons.Outlined.CheckBoxOutlineBlank, - contentDescription = "Example Image Icon", - modifier = Modifier.size(86.dp), + NetworkImage( + imageUrl = "https://picsum.photos/86", + modifier = Modifier + .size(86.dp) + .clip(RoundedCornerShape(16.dp)), ) Spacer(modifier = Modifier.width(14.dp)) Column( From d6249bff727d9eb39eb644ab139088e77facaf8e Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Fri, 12 Apr 2024 01:14:47 +0900 Subject: [PATCH 13/18] =?UTF-8?q?[chore]=20Text=20=EB=A6=AC=EC=86=8C?= =?UTF-8?q?=EC=8A=A4=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../designsystem/src/main/res/values/strings.xml | 13 +++++++++++++ .../interested_booth/InterestedBoothScreen.kt | 5 ++--- .../unifest/android/feature/menu/MenuScreen.kt | 16 ++++++++-------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/core/designsystem/src/main/res/values/strings.xml b/core/designsystem/src/main/res/values/strings.xml index 1d9e3e61..d4858f15 100644 --- a/core/designsystem/src/main/res/values/strings.xml +++ b/core/designsystem/src/main/res/values/strings.xml @@ -45,6 +45,19 @@ 부스 / 주점을 검색해보세요. 여기를 눌러서 학교를 검색해보세요. + + 메뉴 + 나의 관심 학교 + 추가하기> + 관심 부스 + 더보기> + 이용 문의 + 운영자 모드 진입 + + + 관심 부스 + + 학교 / 축제 이름을 검색해보세요. 나의 관심 축제 diff --git a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt index 2658cd0d..06aa7793 100644 --- a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt +++ b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt @@ -15,8 +15,6 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.CheckBoxOutlineBlank import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.Text @@ -30,6 +28,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel @@ -64,7 +63,7 @@ internal fun InterestedBoothScreen( Column { UnifestTopAppBar( navigationType = TopAppBarNavigationType.Back, - title = "관심 부스", + title = stringResource(id = R.string.interested_booths_title), elevation = 8.dp, modifier = Modifier .background( diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt index f666cded..52fb600f 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt @@ -1,6 +1,5 @@ package com.unifest.android.feature.menu -import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -40,6 +39,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -85,7 +85,7 @@ fun MenuScreen( Column { UnifestTopAppBar( navigationType = TopAppBarNavigationType.None, - title = "메뉴", + title = stringResource(id = R.string.menu_title), elevation = 8.dp, modifier = Modifier .background( @@ -105,7 +105,7 @@ fun MenuScreen( .padding(top = 10.dp, start = 20.dp), ) { Text( - text = "나의 관심학교", + text = stringResource(id = R.string.menu_my_interested_festival), style = Title3, ) TextButton( @@ -113,7 +113,7 @@ fun MenuScreen( modifier = Modifier.padding(end = 8.dp), ) { Text( - text = "추가하기>", + text = stringResource(id = R.string.menu_add), style = Content7, color = Color(0xFF545454), ) @@ -161,13 +161,13 @@ fun MenuScreen( .fillMaxWidth() .padding(start = 20.dp, top = 10.dp), ) { - Text(text = "관심부스", style = Title3) + Text(text = stringResource(id = R.string.menu_interested_booths)) TextButton( onClick = { onNavigateToInterestedBooths() }, modifier = Modifier.padding(end = 8.dp), ) { Text( - text = "더보기>", + text = stringResource(id = R.string.menu_watch_more), style = Content7, color = Color(0xFF545454), ) @@ -188,7 +188,7 @@ fun MenuScreen( item { MenuItem( ImageVector.vectorResource(R.drawable.ic_inquiry), - title = "이용 문의", + title = stringResource(id = R.string.menu_questions), onClick = { /* 구현 */ }, ) } @@ -203,7 +203,7 @@ fun MenuScreen( item { MenuItem( ImageVector.vectorResource(R.drawable.ic_admin_mode), - title = "운영자 모드 진입", + title = stringResource(id = R.string.menu_admin_mode), onClick = { /* 구현 */ }, ) } From f21732b43f49277db6d4749f37f63726dd1e8487 Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Fri, 12 Apr 2024 17:28:46 +0900 Subject: [PATCH 14/18] [fix] merge conflict fix --- .../interested_booth/InterestedBoothScreen.kt | 12 ++++++++++-- .../navigation/InterestedBoothNavigation.kt | 5 +++-- .../com/unifest/android/feature/main/MainScreen.kt | 5 +++++ .../com/unifest/android/feature/menu/MenuScreen.kt | 11 ++++++++++- .../feature/menu/navigation/MenuNavigation.kt | 2 ++ 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt index 06aa7793..225bde14 100644 --- a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt +++ b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt @@ -4,6 +4,7 @@ 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.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -49,17 +50,23 @@ import kotlinx.collections.immutable.persistentListOf @Composable internal fun InterestedBoothRoute( + padding: PaddingValues, viewModel: InterestedBoothViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() - InterestedBoothScreen(uiState = uiState) + InterestedBoothScreen(padding = padding, uiState = uiState) } @Composable internal fun InterestedBoothScreen( + padding: PaddingValues, uiState: InterestedBoothUiState, ) { - Box { + Box( + modifier = Modifier + .fillMaxSize() + .padding(padding), + ) { Column { UnifestTopAppBar( navigationType = TopAppBarNavigationType.Back, @@ -157,6 +164,7 @@ fun InterestedBoothsItems(booth: BoothDetailEntity, index: Int, total: Int) { fun InterestedBoothScreenPreview() { UnifestTheme { InterestedBoothScreen( + padding = PaddingValues(), uiState = InterestedBoothUiState( interestedBooths = persistentListOf( BoothDetailEntity( diff --git a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/navigation/InterestedBoothNavigation.kt b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/navigation/InterestedBoothNavigation.kt index dfd2476d..5e57f832 100644 --- a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/navigation/InterestedBoothNavigation.kt +++ b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/navigation/InterestedBoothNavigation.kt @@ -1,5 +1,6 @@ package com.unifest.android.feature.interested_booth.navigation +import androidx.compose.foundation.layout.PaddingValues import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable @@ -11,8 +12,8 @@ fun NavController.navigateToInterestedBooth() { navigate(INTERESTED_BOOTH_ROUTE) } -fun NavGraphBuilder.interestedBoothNavGraph() { +fun NavGraphBuilder.interestedBoothNavGraph(padding: PaddingValues) { composable(route = INTERESTED_BOOTH_ROUTE) { - InterestedBoothRoute() + InterestedBoothRoute(padding = padding) } } diff --git a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt index d23e4799..2ae889ba 100644 --- a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt +++ b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt @@ -107,6 +107,11 @@ internal fun MainScreen( ) menuNavGraph( padding = innerPadding, + onNavigateToIntro = onNavigateToIntro, + onNavigateToInterestedBooths = navigator::navigateToInterestedBooth, + ) + interestedBoothNavGraph( + padding = innerPadding, ) } } diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt index 52fb600f..bbff4485 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt @@ -5,6 +5,7 @@ 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 com.unifest.android.core.designsystem.theme.UnifestTheme import com.unifest.android.core.domain.entity.MenuEntity import com.unifest.android.core.ui.DevicePreview @@ -63,12 +64,14 @@ import com.unifest.android.feature.menu.viewmodel.MenuViewModel @Composable internal fun MenuRoute( + padding: PaddingValues, onNavigateToIntro: () -> Unit, onNavigateToInterestedBooths: () -> Unit, viewModel: MenuViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() MenuScreen( + padding = padding, uiState = uiState, onNavigateToIntro = onNavigateToIntro, onNavigateToInterestedBooths = onNavigateToInterestedBooths, @@ -77,11 +80,16 @@ internal fun MenuRoute( @Composable fun MenuScreen( + padding: PaddingValues, uiState: MenuUiState, onNavigateToIntro: () -> Unit, onNavigateToInterestedBooths: () -> Unit, ) { - Box { + Box( + modifier = Modifier + .fillMaxSize() + .padding(padding), + ) { Column { UnifestTopAppBar( navigationType = TopAppBarNavigationType.None, @@ -367,6 +375,7 @@ fun MenuItem(icon: ImageVector, title: String, onClick: () -> Unit) { fun MenuScreenPreview() { UnifestTheme { MenuScreen( + padding = PaddingValues(0.dp), onNavigateToIntro = { }, onNavigateToInterestedBooths = { }, uiState = MenuUiState( diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt index 45b9e7b2..38ed636a 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt @@ -14,11 +14,13 @@ fun NavController.navigateToMenu(navOptions: NavOptions) { } fun NavGraphBuilder.menuNavGraph( + padding: PaddingValues, onNavigateToIntro: () -> Unit, onNavigateToInterestedBooths: () -> Unit, ) { composable(route = MENU_ROUTE) { MenuRoute( + padding = padding, onNavigateToIntro = onNavigateToIntro, onNavigateToInterestedBooths = onNavigateToInterestedBooths, ) From 0af50b3d9e6fb71bd3417b9d4814aee3b1d2ee94 Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Fri, 12 Apr 2024 19:26:45 +0900 Subject: [PATCH 15/18] =?UTF-8?q?[feat]=20=EA=B4=80=EC=8B=AC=EB=B6=80?= =?UTF-8?q?=EC=8A=A4=20=EC=95=B1=EB=B0=94=20=EB=92=A4=EB=A1=9C=EA=B0=80?= =?UTF-8?q?=EA=B8=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../interested_booth/InterestedBoothScreen.kt | 15 +++++++++++++-- .../navigation/InterestedBoothNavigation.kt | 10 ++++++++-- .../unifest/android/feature/main/MainScreen.kt | 1 + 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt index 225bde14..4bf87204 100644 --- a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt +++ b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/InterestedBoothScreen.kt @@ -51,16 +51,22 @@ import kotlinx.collections.immutable.persistentListOf @Composable internal fun InterestedBoothRoute( padding: PaddingValues, + onBackClick: () -> Unit, viewModel: InterestedBoothViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() - InterestedBoothScreen(padding = padding, uiState = uiState) + InterestedBoothScreen( + padding = padding, + uiState = uiState, + onBackClick = onBackClick, + ) } @Composable internal fun InterestedBoothScreen( padding: PaddingValues, uiState: InterestedBoothUiState, + onBackClick: () -> Unit, ) { Box( modifier = Modifier @@ -70,6 +76,7 @@ internal fun InterestedBoothScreen( Column { UnifestTopAppBar( navigationType = TopAppBarNavigationType.Back, + onNavigationClick = onBackClick, title = stringResource(id = R.string.interested_booths_title), elevation = 8.dp, modifier = Modifier @@ -80,7 +87,10 @@ internal fun InterestedBoothScreen( .padding(top = 13.dp, bottom = 5.dp), ) LazyColumn { - itemsIndexed(uiState.interestedBooths) { index, booth -> + itemsIndexed( + uiState.interestedBooths, + key = { _, booth -> booth.id }, + ) { index, booth -> InterestedBoothsItems(booth, index, uiState.interestedBooths.size) } } @@ -165,6 +175,7 @@ fun InterestedBoothScreenPreview() { UnifestTheme { InterestedBoothScreen( padding = PaddingValues(), + onBackClick = {}, uiState = InterestedBoothUiState( interestedBooths = persistentListOf( BoothDetailEntity( diff --git a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/navigation/InterestedBoothNavigation.kt b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/navigation/InterestedBoothNavigation.kt index 5e57f832..a4437a5b 100644 --- a/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/navigation/InterestedBoothNavigation.kt +++ b/feature/interested-booth/src/main/kotlin/com/unifest/android/feature/interested_booth/navigation/InterestedBoothNavigation.kt @@ -12,8 +12,14 @@ fun NavController.navigateToInterestedBooth() { navigate(INTERESTED_BOOTH_ROUTE) } -fun NavGraphBuilder.interestedBoothNavGraph(padding: PaddingValues) { +fun NavGraphBuilder.interestedBoothNavGraph( + padding: PaddingValues, + onBackClick: () -> Unit, +) { composable(route = INTERESTED_BOOTH_ROUTE) { - InterestedBoothRoute(padding = padding) + InterestedBoothRoute( + padding = padding, + onBackClick = onBackClick, + ) } } diff --git a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt index 2ae889ba..37c76ef2 100644 --- a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt +++ b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt @@ -112,6 +112,7 @@ internal fun MainScreen( ) interestedBoothNavGraph( padding = innerPadding, + onBackClick = navigator::popBackStackIfNotHome, ) } } From 50c2fecb324e84a6da53c4030b49c3c493ef0166 Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Fri, 12 Apr 2024 19:27:12 +0900 Subject: [PATCH 16/18] =?UTF-8?q?[add]=20=EB=A9=94=EB=89=B4=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=EC=95=84=EC=9D=B4=EC=BD=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/res/drawable/ic_selected_menu.xml | 24 +++++++++++++++++++ .../unifest/android/feature/main/MainTab.kt | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 core/designsystem/src/main/res/drawable/ic_selected_menu.xml diff --git a/core/designsystem/src/main/res/drawable/ic_selected_menu.xml b/core/designsystem/src/main/res/drawable/ic_selected_menu.xml new file mode 100644 index 00000000..02eca978 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_selected_menu.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainTab.kt b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainTab.kt index 0d9920fe..a6403819 100644 --- a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainTab.kt +++ b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainTab.kt @@ -32,7 +32,7 @@ internal enum class MainTab( ), MENU( iconResId = R.drawable.ic_menu, - selectedIconResId = R.drawable.ic_menu, + selectedIconResId = R.drawable.ic_selected_menu, contentDescription = "Menu Icon", label = "메뉴", route = "menu_route", From e59773faec73b92e24e24d072150e6230512a111 Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Fri, 12 Apr 2024 19:27:35 +0900 Subject: [PATCH 17/18] =?UTF-8?q?[feat]=20=EC=95=B1=20=EB=B2=84=EC=A0=BC?= =?UTF-8?q?=20=EB=B7=B0=EB=AA=A8=EB=8D=B8=EC=97=90=EC=84=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0,=20=EB=B3=80=EA=B2=BD=EA=B0=80=EB=8A=A5=ED=95=9C=20La?= =?UTF-8?q?zyColumn=20=EC=95=84=EC=9D=B4=ED=85=9C=EC=97=90=20key=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/menu/MenuScreen.kt | 24 +++++++++++++++---- .../feature/menu/viewmodel/MenuViewModel.kt | 12 +--------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt index bbff4485..f44753a6 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt @@ -1,5 +1,6 @@ package com.unifest.android.feature.menu +import android.content.pm.PackageManager import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -40,6 +41,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextAlign @@ -61,6 +63,7 @@ import com.unifest.android.core.domain.entity.BoothDetailEntity import com.unifest.android.core.domain.entity.Festival import com.unifest.android.feature.menu.viewmodel.MenuUiState import com.unifest.android.feature.menu.viewmodel.MenuViewModel +import timber.log.Timber @Composable internal fun MenuRoute( @@ -85,6 +88,15 @@ fun MenuScreen( onNavigateToIntro: () -> Unit, onNavigateToInterestedBooths: () -> Unit, ) { + val context = LocalContext.current + val appVersion = remember { + try { + context.packageManager.getPackageInfo(context.packageName, 0).versionName + } catch (e: PackageManager.NameNotFoundException) { + Timber.tag("AppVersion").e(e, "Failed to get package info") + "Unknown" + } + } Box( modifier = Modifier .fillMaxSize() @@ -145,10 +157,12 @@ fun MenuScreen( horizontalArrangement = Arrangement.spacedBy(20.dp), verticalArrangement = Arrangement.spacedBy(8.dp), ) { - items(uiState.festivals.size) { index -> - val festival = uiState.festivals[index] + items( + uiState.festivals.size, + key = { index -> uiState.festivals[index].schoolName }, + ) { index -> FestivalItem( - festival = festival, + festival = uiState.festivals[index], ) } } @@ -182,7 +196,7 @@ fun MenuScreen( } } } - itemsIndexed(uiState.interestedBooths.take(3)) { index, booth -> + itemsIndexed(uiState.interestedBooths.take(3), key = { _, booth -> booth.id }) { index, booth -> InterestedBoothsItems(booth, index, uiState.interestedBooths.size) } item { @@ -230,7 +244,7 @@ fun MenuScreen( .fillMaxWidth() .padding(vertical = 13.dp), ) { - Text("UniFest ${uiState.appVersion}", textAlign = TextAlign.Center, color = Color(0xFFC5C5C5)) + Text("UniFest v$appVersion", textAlign = TextAlign.Center, color = Color(0xFFC5C5C5)) } } } diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt index 37a93f92..a3f5e540 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt @@ -1,7 +1,5 @@ package com.unifest.android.feature.menu.viewmodel -import android.app.Application -import android.content.pm.PackageManager import androidx.lifecycle.ViewModel import com.unifest.android.core.domain.entity.BoothDetailEntity import com.unifest.android.core.domain.entity.Festival @@ -11,23 +9,15 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update -import timber.log.Timber import javax.inject.Inject @HiltViewModel -class MenuViewModel @Inject constructor(private val application: Application) : ViewModel() { +class MenuViewModel @Inject constructor() : ViewModel() { private val _uiState = MutableStateFlow(MenuUiState()) val uiState: StateFlow = _uiState.asStateFlow() init { - val appVersion = try { - application.packageManager.getPackageInfo(application.packageName, 0).versionName - } catch (e: PackageManager.NameNotFoundException) { - Timber.tag("AppVersion").e(e, "Failed to get package info") - "Unknown" - } _uiState.update { currentState -> currentState.copy( - appVersion = appVersion, // 임시 데이터 festivals = persistentListOf( Festival("school_image_url_1", "서울대학교", "설대축제", "05.06-05.08"), From e2d6e99dea6068b73ce2ec296f75a8338a5b7ca2 Mon Sep 17 00:00:00 2001 From: Jeong Sang Hoon Date: Sat, 13 Apr 2024 00:03:00 +0900 Subject: [PATCH 18/18] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=20=EA=B4=80?= =?UTF-8?q?=EC=8B=AC=20=ED=95=99=EA=B5=90=20=EC=B6=94=EA=B0=80=20=EB=B0=94?= =?UTF-8?q?=ED=85=80=EC=8B=9C=ED=8A=B8=EB=A1=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/main/MainScreen.kt | 1 - .../android/feature/menu/MenuScreen.kt | 43 ++++++++++++++-- .../feature/menu/navigation/MenuNavigation.kt | 2 - .../feature/menu/viewmodel/MenuUiState.kt | 9 +++- .../feature/menu/viewmodel/MenuViewModel.kt | 51 +++++++++++++++++++ 5 files changed, 97 insertions(+), 9 deletions(-) diff --git a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt index 37c76ef2..0032ba79 100644 --- a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt +++ b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt @@ -107,7 +107,6 @@ internal fun MainScreen( ) menuNavGraph( padding = innerPadding, - onNavigateToIntro = onNavigateToIntro, onNavigateToInterestedBooths = navigator::navigateToInterestedBooth, ) interestedBoothNavGraph( diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt index f44753a6..832d2931 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/MenuScreen.kt @@ -44,6 +44,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel @@ -61,6 +62,7 @@ import com.unifest.android.core.designsystem.theme.Title3 import com.unifest.android.core.designsystem.theme.Title5 import com.unifest.android.core.domain.entity.BoothDetailEntity import com.unifest.android.core.domain.entity.Festival +import com.unifest.android.core.ui.component.FestivalSearchBottomSheet import com.unifest.android.feature.menu.viewmodel.MenuUiState import com.unifest.android.feature.menu.viewmodel.MenuViewModel import timber.log.Timber @@ -68,7 +70,6 @@ import timber.log.Timber @Composable internal fun MenuRoute( padding: PaddingValues, - onNavigateToIntro: () -> Unit, onNavigateToInterestedBooths: () -> Unit, viewModel: MenuViewModel = hiltViewModel(), ) { @@ -76,8 +77,13 @@ internal fun MenuRoute( MenuScreen( padding = padding, uiState = uiState, - onNavigateToIntro = onNavigateToIntro, + setFestivalSearchBottomSheetVisible = viewModel::setFestivalSearchBottomSheetVisible, onNavigateToInterestedBooths = onNavigateToInterestedBooths, + updateFestivalSearchText = viewModel::updateFestivalSearchText, + initSearchText = viewModel::initSearchText, + setEnableSearchMode = viewModel::setEnableSearchMode, + setEnableEditMode = viewModel::setEnableEditMode, + setInterestedFestivalDeleteDialogVisible = viewModel::setInterestedFestivalDeleteDialogVisible, ) } @@ -85,8 +91,13 @@ internal fun MenuRoute( fun MenuScreen( padding: PaddingValues, uiState: MenuUiState, - onNavigateToIntro: () -> Unit, + setFestivalSearchBottomSheetVisible: (Boolean) -> Unit, onNavigateToInterestedBooths: () -> Unit, + updateFestivalSearchText: (TextFieldValue) -> Unit, + initSearchText: () -> Unit, + setEnableSearchMode: (Boolean) -> Unit, + setEnableEditMode: () -> Unit, + setInterestedFestivalDeleteDialogVisible: (Boolean) -> Unit, ) { val context = LocalContext.current val appVersion = remember { @@ -129,7 +140,7 @@ fun MenuScreen( style = Title3, ) TextButton( - onClick = { onNavigateToIntro() }, + onClick = { setFestivalSearchBottomSheetVisible(true) }, modifier = Modifier.padding(end = 8.dp), ) { Text( @@ -249,6 +260,23 @@ fun MenuScreen( } } } + if (uiState.isFestivalSearchBottomSheetVisible) { + FestivalSearchBottomSheet( + searchText = uiState.festivalSearchText, + updateSearchText = updateFestivalSearchText, + searchTextHintRes = R.string.festival_search_text_field_hint, + setFestivalSearchBottomSheetVisible = setFestivalSearchBottomSheetVisible, + interestedFestivals = uiState.interestedFestivals, + festivalSearchResults = uiState.festivalSearchResults, + initSearchText = initSearchText, + setEnableSearchMode = setEnableSearchMode, + isSearchMode = uiState.isSearchMode, + setEnableEditMode = setEnableEditMode, + isInterestedFestivalDeleteDialogVisible = uiState.isInterestedFestivalDeleteDialogVisible, + setInterestedFestivalDeleteDialogVisible = setInterestedFestivalDeleteDialogVisible, + isEditMode = uiState.isEditMode, + ) + } } } @@ -390,7 +418,12 @@ fun MenuScreenPreview() { UnifestTheme { MenuScreen( padding = PaddingValues(0.dp), - onNavigateToIntro = { }, + setFestivalSearchBottomSheetVisible = { }, + updateFestivalSearchText = { }, + initSearchText = { }, + setEnableSearchMode = { }, + setEnableEditMode = { }, + setInterestedFestivalDeleteDialogVisible = { }, onNavigateToInterestedBooths = { }, uiState = MenuUiState( festivals = persistentListOf( diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt index 38ed636a..b4a908dc 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/navigation/MenuNavigation.kt @@ -15,13 +15,11 @@ fun NavController.navigateToMenu(navOptions: NavOptions) { fun NavGraphBuilder.menuNavGraph( padding: PaddingValues, - onNavigateToIntro: () -> Unit, onNavigateToInterestedBooths: () -> Unit, ) { composable(route = MENU_ROUTE) { MenuRoute( padding = padding, - onNavigateToIntro = onNavigateToIntro, onNavigateToInterestedBooths = onNavigateToInterestedBooths, ) } diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuUiState.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuUiState.kt index ef8c8b51..59b6184d 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuUiState.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuUiState.kt @@ -1,5 +1,6 @@ package com.unifest.android.feature.menu.viewmodel +import androidx.compose.ui.text.input.TextFieldValue import com.unifest.android.core.domain.entity.BoothDetailEntity import com.unifest.android.core.domain.entity.Festival import kotlinx.collections.immutable.ImmutableList @@ -8,5 +9,11 @@ import kotlinx.collections.immutable.persistentListOf data class MenuUiState( val festivals: ImmutableList = persistentListOf(), val interestedBooths: ImmutableList = persistentListOf(), - val appVersion: String = "", + val festivalSearchText: TextFieldValue = TextFieldValue(), + val interestedFestivals: MutableList = mutableListOf(), + val festivalSearchResults: ImmutableList = persistentListOf(), + val isSearchMode: Boolean = false, + val isEditMode: Boolean = false, + val isFestivalSearchBottomSheetVisible: Boolean = false, + val isInterestedFestivalDeleteDialogVisible: Boolean = false, ) diff --git a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt index a3f5e540..25000722 100644 --- a/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt +++ b/feature/menu/src/main/kotlin/com/unifest/android/feature/menu/viewmodel/MenuViewModel.kt @@ -1,5 +1,6 @@ package com.unifest.android.feature.menu.viewmodel +import androidx.compose.ui.text.input.TextFieldValue import androidx.lifecycle.ViewModel import com.unifest.android.core.domain.entity.BoothDetailEntity import com.unifest.android.core.domain.entity.Festival @@ -18,6 +19,20 @@ class MenuViewModel @Inject constructor() : ViewModel() { init { _uiState.update { currentState -> currentState.copy( + interestedFestivals = mutableListOf( + Festival("https://picsum.photos/36", "서울대학교", "설대축제", "05.06-05.08"), + Festival("https://picsum.photos/36", "연세대학교", "연대축제", "05.06-05.08"), + Festival("https://picsum.photos/36", "고려대학교", "고대축제", "05.06-05.08"), + Festival("https://picsum.photos/36", "건국대학교", "녹색지대", "05.06-05.08"), + Festival("https://picsum.photos/36", "성균관대학교", "성대축제", "05.06-05.08"), + ), + festivalSearchResults = persistentListOf( + Festival("https://picsum.photos/36", "서울대학교", "설대축제", "05.06-05.08"), + Festival("https://picsum.photos/36", "연세대학교", "연대축제", "05.06-05.08"), + Festival("https://picsum.photos/36", "고려대학교", "고대축제", "05.06-05.08"), + Festival("https://picsum.photos/36", "건국대학교", "녹색지대", "05.06-05.08"), + Festival("https://picsum.photos/36", "성균관대학교", "성대축제", "05.06-05.08"), + ), // 임시 데이터 festivals = persistentListOf( Festival("school_image_url_1", "서울대학교", "설대축제", "05.06-05.08"), @@ -64,4 +79,40 @@ class MenuViewModel @Inject constructor() : ViewModel() { ) } } + + fun updateFestivalSearchText(text: TextFieldValue) { + _uiState.update { + it.copy(festivalSearchText = text) + } + } + + fun initSearchText() { + _uiState.update { + it.copy(festivalSearchText = TextFieldValue()) + } + } + + fun setFestivalSearchBottomSheetVisible(flag: Boolean) { + _uiState.update { + it.copy(isFestivalSearchBottomSheetVisible = flag) + } + } + + fun setEnableSearchMode(flag: Boolean) { + _uiState.update { + it.copy(isSearchMode = flag) + } + } + + fun setEnableEditMode() { + _uiState.update { + it.copy(isEditMode = !_uiState.value.isEditMode) + } + } + + fun setInterestedFestivalDeleteDialogVisible(flag: Boolean) { + _uiState.update { + it.copy(isInterestedFestivalDeleteDialogVisible = flag) + } + } }