From 26218bc762b627c66b8912ad593850c74cb55a14 Mon Sep 17 00:00:00 2001 From: JiWoo1261 Date: Mon, 14 Jul 2025 19:56:28 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat/#63:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20viewmodel=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/mypage/MyPageScreen.kt | 42 ++++++++++++++----- .../ui/mypage/UserProfileScreen.kt | 3 +- .../ui/mypage/state/MyPageContract.kt | 17 ++++++++ .../ui/mypage/viewmodel/MyPageViewModel.kt | 24 +++++++++++ 4 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/state/MyPageContract.kt create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/MyPageViewModel.kt diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/MyPageScreen.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/MyPageScreen.kt index 8ce97a2d..6eeb6e16 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/MyPageScreen.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/MyPageScreen.kt @@ -19,9 +19,13 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.paw.key.R import com.paw.key.core.designsystem.component.SubChip import com.paw.key.core.designsystem.theme.PawKeyTheme +import com.paw.key.presentation.ui.mypage.state.MyPageContract +import com.paw.key.presentation.ui.mypage.viewmodel.MyPageViewModel @Composable fun MyPageRoute( @@ -32,9 +36,13 @@ fun MyPageRoute( navigateArchivedCourse: () -> Unit, navigateSavedCourse: () -> Unit, snackBarHostState: SnackbarHostState, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + viewModel: MyPageViewModel = hiltViewModel() ) { + val state = viewModel.state.collectAsStateWithLifecycle() + MyPageScreen( + state = state.value, paddingValues = paddingValues, navigateUp = navigateUp, navigateUserProfile = navigateUserProfile, @@ -49,6 +57,7 @@ fun MyPageRoute( @Composable fun MyPageScreen( + state: MyPageContract.MyPageState, paddingValues: PaddingValues, navigateUp: () -> Unit, navigateUserProfile: () -> Unit, @@ -70,19 +79,23 @@ fun MyPageScreen( style = PawKeyTheme.typography.head22B, modifier = Modifier.padding(start = 16.dp, top = 16.dp, bottom = 12.dp) ) - OwnerCard(ownerName = "김도기님", role = "견주", navigateUserProfile = navigateUserProfile) - + OwnerCard( + ownerName = state.ownerName, + role = state.role, + navigateUserProfile = navigateUserProfile + ) Spacer(modifier = Modifier.height(19.dp)) PetCard( - name = "포비", - age = "12세", - gender = "여아", - tags = listOf("조금 느긋해요", "#오토바이소리", "#대형견"), - walkCount = "7회", - totalDistance = "14km", + name = state.petName, + age = state.petAge, + gender = state.petGender, + tags = state.petTags, + walkCount = state.walkCount, + totalDistance = state.totalDistance, navigatePetProfile = navigatePetProfile ) + Spacer(modifier = Modifier.height(12.dp)) WalkRouteList( @@ -290,7 +303,16 @@ fun WalkRouteList( @Composable private fun MyPageScreenPreview() { PawKeyTheme { - MyPageScreen( + MyPageScreen(state = MyPageContract.MyPageState( + ownerName = "김도기님", + role = "견주", + petName = "포비", + petAge = "12세", + petGender = "여아", + petTags = listOf("조금 느긋해요", "#오토바이소리", "#대형견"), + walkCount = "7회", + totalDistance = "14km" + ), paddingValues = PaddingValues(), navigateUp = {}, navigateUserProfile = {}, diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/UserProfileScreen.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/UserProfileScreen.kt index 77c54317..622dbd2a 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/UserProfileScreen.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/UserProfileScreen.kt @@ -26,6 +26,7 @@ fun UserProfileRoute( fun UserProfileScreen( navigateUp: () -> Unit, modifier: Modifier = Modifier, + id: String = "sgh1261", name: String = "김도기", gender: String = "여성", age: String = "24세", @@ -46,12 +47,12 @@ fun UserProfileScreen( Column( verticalArrangement = Arrangement.spacedBy(16.dp) ) { + ProfileItem(label = "아이디", value = id) ProfileItem(label = "이름", value = name) ProfileItem(label = "성별", value = gender) ProfileItem(label = "나이", value = age) ProfileItem(label = "활동지역", value = region) } - Spacer(modifier = Modifier.weight(1f)) } } diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/state/MyPageContract.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/MyPageContract.kt new file mode 100644 index 00000000..05c5f341 --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/MyPageContract.kt @@ -0,0 +1,17 @@ +package com.paw.key.presentation.ui.mypage.state + +import androidx.compose.runtime.Immutable + +class MyPageContract { + @Immutable + data class MyPageState( + val ownerName: String = "김도기님", + val role: String = "견주", + val petName: String = "포비", + val petAge: String = "12세", + val petGender: String = "여아", + val petTags: List = listOf("조금 느긋해요", "#오토바이소리", "#대형견"), + val walkCount: String = "7회", + val totalDistance: String = "14km" + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/MyPageViewModel.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/MyPageViewModel.kt new file mode 100644 index 00000000..4c7b6d20 --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/MyPageViewModel.kt @@ -0,0 +1,24 @@ +package com.paw.key.presentation.ui.mypage.viewmodel + +import androidx.lifecycle.ViewModel +import com.paw.key.presentation.ui.mypage.state.MyPageContract +import com.paw.key.presentation.ui.mypage.state.MyPageContract.MyPageState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject + +@HiltViewModel +class MyPageViewModel @Inject constructor() : ViewModel() { + private val _state = MutableStateFlow(MyPageState()) + val state: StateFlow + get() = _state.asStateFlow() //get할때마다 업데이트 + + fun updateWalkInfo(walkCount: String, totalDistance: String) { + _state.value = _state.value.copy( + walkCount = walkCount, + totalDistance = totalDistance + ) + } +} \ No newline at end of file From 98dd2c193254184c910f18f30b8229c63de1da6a Mon Sep 17 00:00:00 2001 From: JiWoo1261 Date: Tue, 15 Jul 2025 01:56:39 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat/#63:=20=EC=A0=80=EC=9E=A5=ED=95=9C=20?= =?UTF-8?q?=EC=82=B0=EC=B1=85=20=EB=A3=A8=ED=8A=B8=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=B0=8F=20=EC=83=81=EC=84=B8=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=20=EC=83=81=ED=83=9C=20=EA=B4=80=EB=A6=AC(ViewModel=20+=20Stat?= =?UTF-8?q?eFlow)=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/mypage/MyPageScreen.kt | 3 +- .../ui/mypage/PetProfileScreen.kt | 30 ++++++++++++--- .../ui/mypage/SavedCourseDetailScreen.kt | 25 +++++++++++-- .../ui/mypage/SavedCourseListScreen.kt | 37 ++++++++++++++----- .../ui/mypage/UserProfileScreen.kt | 18 ++++++++- .../ui/mypage/state/ArchivedDetailContract.kt | 4 ++ .../ui/mypage/state/ArchivedListContract.kt | 20 ++++++++++ .../ui/mypage/state/PetProfileContract.kt | 16 ++++++++ .../ui/mypage/state/SavedDetailContract.kt | 17 +++++++++ .../ui/mypage/state/SavedListContract.kt | 20 ++++++++++ .../ui/mypage/state/UserProfileContract.kt | 14 +++++++ .../viewmodel/ArchivedDetailViewModel.kt | 4 ++ .../mypage/viewmodel/ArchivedListViewModel.kt | 18 +++++++++ .../ui/mypage/viewmodel/MyPageViewModel.kt | 1 - .../mypage/viewmodel/PetProfileViewModel.kt | 17 +++++++++ .../mypage/viewmodel/SavedDetailViewModel.kt | 26 +++++++++++++ .../ui/mypage/viewmodel/SavedListViewModel.kt | 20 ++++++++++ .../mypage/viewmodel/UserProfileViewModel.kt | 16 ++++++++ 18 files changed, 283 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/state/ArchivedDetailContract.kt create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/state/ArchivedListContract.kt create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/state/PetProfileContract.kt create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/state/SavedDetailContract.kt create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/state/SavedListContract.kt create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/state/UserProfileContract.kt create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/ArchivedDetailViewModel.kt create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/ArchivedListViewModel.kt create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/PetProfileViewModel.kt create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/SavedDetailViewModel.kt create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/SavedListViewModel.kt create mode 100644 app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/UserProfileViewModel.kt diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/MyPageScreen.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/MyPageScreen.kt index 6eeb6e16..449e08de 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/MyPageScreen.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/MyPageScreen.kt @@ -51,7 +51,6 @@ fun MyPageRoute( navigateSavedCourse = navigateSavedCourse, snackBarHostState = snackBarHostState, modifier = modifier - ) } @@ -172,7 +171,7 @@ fun PetCard( ) Text( text = "반려견 프로필", - style = PawKeyTheme.typography.caption12Sb1, + style = PawKeyTheme.typography.body16Sb, color = Color.White ) Spacer(modifier = Modifier.weight(1f)) diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/PetProfileScreen.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/PetProfileScreen.kt index 4c679310..7912770d 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/PetProfileScreen.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/PetProfileScreen.kt @@ -16,16 +16,24 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.paw.key.R import com.paw.key.core.designsystem.component.TopBar import com.paw.key.core.designsystem.theme.PawKeyTheme +import com.paw.key.presentation.ui.mypage.state.PetProfileContract +import com.paw.key.presentation.ui.mypage.viewmodel.PetProfileViewModel @Composable fun PetProfileRoute( navigateUp : () -> Unit, modifier: Modifier = Modifier, + viewModel: PetProfileViewModel = hiltViewModel() ) { + val state = viewModel.state.collectAsStateWithLifecycle() + PetProfileScreen( + state = state.value, navigateUp = navigateUp, modifier = modifier ) @@ -33,13 +41,16 @@ fun PetProfileRoute( @Composable fun PetProfileScreen( + state: PetProfileContract.PetProfileState, navigateUp: () -> Unit, + modifier: Modifier = Modifier, + imageUrl: String? = null, name: String = "까루", gender: String = "남아", breed: String = "코리안 숏헤어", age: String = "4세", - personality: String = "활동적", - modifier: Modifier = Modifier + energyLevel: String = "활동적이에요", + socialLevel: String = "불편해해요" ) { Column( modifier = modifier @@ -58,6 +69,7 @@ fun PetProfileScreen( .clip(CircleShape) .border(2.dp, PawKeyTheme.colors.green500, CircleShape) ) { + // TODO: imageUrl AsyncImage로 URL 로딩 Image( painter = painterResource(id = R.drawable.profile), contentDescription = null, @@ -106,7 +118,7 @@ fun PetProfileScreen( color = PawKeyTheme.colors.gray600 ) Text( - text = "활동적이에요", + text = energyLevel, style = PawKeyTheme.typography.head18Sb, color = PawKeyTheme.colors.green500 ) @@ -124,7 +136,7 @@ fun PetProfileScreen( color = PawKeyTheme.colors.gray600 ) Text( - text = "불편해해요", + text = socialLevel, style = PawKeyTheme.typography.head18Sb, color = PawKeyTheme.colors.green500 ) @@ -164,7 +176,15 @@ fun PetProfileItem( fun PetProfileScreenPreview() { PawKeyTheme { PetProfileScreen( - navigateUp = {}, + state = PetProfileContract.PetProfileState( + name = "까루", + gender = "남아", + breed = "코리안 숏헤어", + age = "4세", + energyLevel = "활동적이에요", + socialLevel = "불편해해요" + ), + navigateUp = {} ) } } \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseDetailScreen.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseDetailScreen.kt index c366b26e..4759478f 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseDetailScreen.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseDetailScreen.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -20,20 +19,30 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.paw.key.core.designsystem.component.CourseDetail import com.paw.key.core.designsystem.component.ImageModal import com.paw.key.core.designsystem.component.PawkeyButton import com.paw.key.core.designsystem.component.TopBar import com.paw.key.core.designsystem.theme.PawKeyTheme import com.paw.key.core.designsystem.theme.White1 +import com.paw.key.presentation.ui.mypage.state.MyPageContract +import com.paw.key.presentation.ui.mypage.state.SavedDetailContract +import com.paw.key.presentation.ui.mypage.viewmodel.MyPageViewModel +import com.paw.key.presentation.ui.mypage.viewmodel.SavedDetailViewModel @Composable fun SavedDetailRoute( navigateUp: () -> Unit, navigateToWalk: () -> Unit, modifier: Modifier = Modifier, + viewModel: SavedDetailViewModel = hiltViewModel() ) { + val state = viewModel.state.collectAsStateWithLifecycle() + SavedCourseDetailScreen( + state = state.value, navigateUp = navigateUp, navigateToWalk = navigateToWalk, modifier = modifier @@ -42,6 +51,7 @@ fun SavedDetailRoute( @Composable fun SavedCourseDetailScreen( + state: SavedDetailContract.SavedDetailState, navigateUp: () -> Unit, navigateToWalk: () -> Unit, modifier: Modifier = Modifier @@ -111,7 +121,7 @@ fun SavedCourseDetailScreen( if (isImageExpanded) { ImageModal( - imageUrl = "https://pawkey-server.com/image.jpg", + imageUrl = state.imageUrl, onDismiss = { isImageExpanded = false } ) } @@ -123,7 +133,16 @@ fun SavedCourseDetailScreen( @Composable fun SavedCourseDetailPreview(){ PawKeyTheme { - SavedCourseDetailScreen( + SavedCourseDetailScreen(state = SavedDetailContract.SavedDetailState( + title = "한강 산책로", + petName = "후추", + date = "2025/06/02", + location = "뚝섬유원지", + distance = "4.5km", + time = "1시간 30분 소요", + option = listOf("풍경이 좋아요", "조용해요", "길이 깨끗해요"), + imageUrl = "https://pawkey-server.com/image.jpg" + ), navigateUp = {}, navigateToWalk = {} ) diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseListScreen.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseListScreen.kt index 6a10275c..bf41d443 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseListScreen.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseListScreen.kt @@ -9,27 +9,29 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.paw.key.core.designsystem.component.CourseCard import com.paw.key.core.designsystem.component.TopBar import com.paw.key.core.designsystem.theme.PawKeyTheme +import com.paw.key.presentation.ui.mypage.state.MyPageContract +import com.paw.key.presentation.ui.mypage.state.SavedListContract +import com.paw.key.presentation.ui.mypage.state.SavedListContract.CourseCardData +import com.paw.key.presentation.ui.mypage.viewmodel.MyPageViewModel +import com.paw.key.presentation.ui.mypage.viewmodel.SavedListViewModel -// 코스 카드에서 사용할 데이터 모델 -data class CourseCardData( - val title: String, - val petName: String, - val date: String, - val location: String, - val distance: String, - val time: String -) @Composable fun SavedCourseRoute( navigateUp: () -> Unit, navigateNext: () -> Unit, modifier: Modifier = Modifier, + viewModel: SavedListViewModel = hiltViewModel() ) { + val state = viewModel.state.collectAsStateWithLifecycle() + SavedCourseListScreen( + state = state.value, navigateUp = navigateUp, navigateNext = navigateNext, modifier = modifier @@ -38,6 +40,7 @@ fun SavedCourseRoute( @Composable fun SavedCourseListScreen( + state: SavedListContract.SavedListState, navigateUp: () -> Unit, navigateNext: () -> Unit, modifier: Modifier = Modifier @@ -91,6 +94,20 @@ fun SavedCourseListScreen( @Composable fun SavedCourseListScreenPreview() { PawKeyTheme { - SavedCourseListScreen(navigateUp = {}, navigateNext = {}) + SavedCourseListScreen(state = SavedListContract.SavedListState( + courseList = listOf( + CourseCardData( + title = "예시 산책로", + petName = "하루", + date = "2025/01/01", + location = "강남", + distance = "2.3km", + time = "45분" + ) + ) + ), + navigateUp = {}, + navigateNext = {} + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/UserProfileScreen.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/UserProfileScreen.kt index 622dbd2a..5c23c5b4 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/UserProfileScreen.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/UserProfileScreen.kt @@ -1,22 +1,28 @@ package com.paw.key.presentation.ui.mypage import androidx.compose.foundation.layout.* -import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import androidx.compose.ui.Alignment import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.paw.key.core.designsystem.component.TopBar import com.paw.key.core.designsystem.theme.PawKeyTheme +import com.paw.key.presentation.ui.mypage.state.UserProfileContract +import com.paw.key.presentation.ui.mypage.viewmodel.UserProfileViewModel @Composable fun UserProfileRoute( navigateUp: () -> Unit, modifier: Modifier = Modifier, + viewModel: UserProfileViewModel = hiltViewModel() ) { + val state = viewModel.state.collectAsStateWithLifecycle() + UserProfileScreen( + state = state.value, navigateUp = navigateUp, modifier = modifier ) @@ -24,6 +30,7 @@ fun UserProfileRoute( @Composable fun UserProfileScreen( + state: UserProfileContract.UserProfileState, navigateUp: () -> Unit, modifier: Modifier = Modifier, id: String = "sgh1261", @@ -78,6 +85,13 @@ fun ProfileItem(label: String, value: String) { fun UserProfileScreenPreview() { PawKeyTheme { UserProfileScreen( + state = UserProfileContract.UserProfileState( + id = "sgh1261", + name = "김도기", + gender = "여성", + age = "24세", + region = "강남구 역삼동" + ), navigateUp = {} ) } diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/state/ArchivedDetailContract.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/ArchivedDetailContract.kt new file mode 100644 index 00000000..7468ac76 --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/ArchivedDetailContract.kt @@ -0,0 +1,4 @@ +package com.paw.key.presentation.ui.mypage.state + +class ArchivedDetailContract { +} diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/state/ArchivedListContract.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/ArchivedListContract.kt new file mode 100644 index 00000000..ecbf4fb4 --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/ArchivedListContract.kt @@ -0,0 +1,20 @@ +package com.paw.key.presentation.ui.mypage.state + +import androidx.compose.runtime.Immutable + +object ArchivedListContract { + @Immutable + data class ArchivedListState( + val courseList: List = emptyList() + ) + + @Immutable + data class CourseCardData( + val title: String, + val petName: String, + val date: String, + val location: String, + val distance: String, + val time: String + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/state/PetProfileContract.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/PetProfileContract.kt new file mode 100644 index 00000000..bee053b7 --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/PetProfileContract.kt @@ -0,0 +1,16 @@ +package com.paw.key.presentation.ui.mypage.state + +import androidx.compose.runtime.Immutable + +object PetProfileContract { + @Immutable + data class PetProfileState( + val imageUrl: String? = null, + val name: String = "까루", + val gender: String = "남아", + val breed: String = "코리안 숏헤어", + val age: String = "4세", + val energyLevel: String = "활동적이에요", + val socialLevel: String = "불편해해요" + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/state/SavedDetailContract.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/SavedDetailContract.kt new file mode 100644 index 00000000..3507094c --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/SavedDetailContract.kt @@ -0,0 +1,17 @@ +package com.paw.key.presentation.ui.mypage.state + +import androidx.compose.runtime.Immutable + +object SavedDetailContract { + @Immutable + data class SavedDetailState( + val title: String, + val petName: String, + val date: String, + val location: String, + val distance: String, + val time: String, + val option: List = emptyList(), + val imageUrl: String + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/state/SavedListContract.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/SavedListContract.kt new file mode 100644 index 00000000..51ed94ee --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/SavedListContract.kt @@ -0,0 +1,20 @@ +package com.paw.key.presentation.ui.mypage.state + +import androidx.compose.runtime.Immutable + +object SavedListContract { + @Immutable + data class SavedListState( + val courseList: List = emptyList() + ) + + @Immutable + data class CourseCardData( + val title: String, + val petName: String, + val date: String, + val location: String, + val distance: String, + val time: String + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/state/UserProfileContract.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/UserProfileContract.kt new file mode 100644 index 00000000..c7d3a08a --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/UserProfileContract.kt @@ -0,0 +1,14 @@ +package com.paw.key.presentation.ui.mypage.state + +import androidx.compose.runtime.Immutable + +object UserProfileContract { + @Immutable + data class UserProfileState( + val id: String = "sgh1261", + val name: String = "김도기", + val gender: String = "여성", + val age: String = "24세", + val region: String = "강남구 역삼동" + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/ArchivedDetailViewModel.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/ArchivedDetailViewModel.kt new file mode 100644 index 00000000..65328f67 --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/ArchivedDetailViewModel.kt @@ -0,0 +1,4 @@ +package com.paw.key.presentation.ui.mypage.viewmodel + +class ArchivedDetailViewModel { +} \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/ArchivedListViewModel.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/ArchivedListViewModel.kt new file mode 100644 index 00000000..132ed3bc --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/ArchivedListViewModel.kt @@ -0,0 +1,18 @@ +package com.paw.key.presentation.ui.mypage.viewmodel + +import androidx.lifecycle.ViewModel +import com.paw.key.presentation.ui.mypage.state.ArchivedListContract +import com.paw.key.presentation.ui.mypage.state.ArchivedListContract.ArchivedListState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject + +@HiltViewModel +class ArchivedListViewModel @Inject constructor() : ViewModel() { + private val _state = MutableStateFlow(ArchivedListContract.ArchivedListState()) + val state: StateFlow + get() = _state.asStateFlow() //get할때마다 업데이트 + +} \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/MyPageViewModel.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/MyPageViewModel.kt index 4c7b6d20..f9ac4617 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/MyPageViewModel.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/MyPageViewModel.kt @@ -1,7 +1,6 @@ package com.paw.key.presentation.ui.mypage.viewmodel import androidx.lifecycle.ViewModel -import com.paw.key.presentation.ui.mypage.state.MyPageContract import com.paw.key.presentation.ui.mypage.state.MyPageContract.MyPageState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/PetProfileViewModel.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/PetProfileViewModel.kt new file mode 100644 index 00000000..69ee6ef9 --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/PetProfileViewModel.kt @@ -0,0 +1,17 @@ +package com.paw.key.presentation.ui.mypage.viewmodel + +import androidx.lifecycle.ViewModel +import com.paw.key.presentation.ui.mypage.state.PetProfileContract +import com.paw.key.presentation.ui.mypage.state.PetProfileContract.PetProfileState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject + +@HiltViewModel +class PetProfileViewModel @Inject constructor() : ViewModel() { + private val _state = MutableStateFlow(PetProfileState()) + val state: StateFlow + get() = _state.asStateFlow() // get할 때마다 업데이트 +} \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/SavedDetailViewModel.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/SavedDetailViewModel.kt new file mode 100644 index 00000000..950f4b7f --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/SavedDetailViewModel.kt @@ -0,0 +1,26 @@ +package com.paw.key.presentation.ui.mypage.viewmodel + +import androidx.lifecycle.ViewModel +import com.paw.key.presentation.ui.mypage.state.SavedDetailContract.SavedDetailState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject + +@HiltViewModel +class SavedDetailViewModel @Inject constructor() : ViewModel() { + private val _state = MutableStateFlow( + SavedDetailState( + title = "한강 산책로", + petName = "후추", + date = "2025/06/02", + location = "뚝섬유원지", + distance = "4.5km", + time = "1시간 30분 소요", + option = listOf("풍경이 좋아요", "조용해요", "길이 깨끗해요"), + imageUrl = "https://pawkey-server.com/image.jpg" + ) + ) + val state: StateFlow get() = _state.asStateFlow() +} \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/SavedListViewModel.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/SavedListViewModel.kt new file mode 100644 index 00000000..bb464787 --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/SavedListViewModel.kt @@ -0,0 +1,20 @@ +package com.paw.key.presentation.ui.mypage.viewmodel + +import androidx.lifecycle.ViewModel +import com.paw.key.presentation.ui.mypage.state.MyPageContract +import com.paw.key.presentation.ui.mypage.state.MyPageContract.MyPageState +import com.paw.key.presentation.ui.mypage.state.SavedListContract +import com.paw.key.presentation.ui.mypage.state.SavedListContract.SavedListState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject + +@HiltViewModel +class SavedListViewModel @Inject constructor() : ViewModel() { + private val _state = MutableStateFlow(SavedListContract.SavedListState()) + val state: StateFlow + get() = _state.asStateFlow() //get할때마다 업데이트 + +} \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/UserProfileViewModel.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/UserProfileViewModel.kt new file mode 100644 index 00000000..da8cb1f2 --- /dev/null +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/UserProfileViewModel.kt @@ -0,0 +1,16 @@ +package com.paw.key.presentation.ui.mypage.viewmodel + +import androidx.lifecycle.ViewModel +import com.paw.key.presentation.ui.mypage.state.UserProfileContract.UserProfileState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject + +@HiltViewModel +class UserProfileViewModel @Inject constructor() : ViewModel() { + private val _state = MutableStateFlow(UserProfileState()) + val state: StateFlow + get() = _state.asStateFlow() +} From 81c532c0f277f4d3e18d60ba11f08e317100b843 Mon Sep 17 00:00:00 2001 From: JiWoo1261 Date: Tue, 15 Jul 2025 02:48:15 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat/#63:=20=EA=B8=B0=EB=A1=9D=ED=95=9C=20?= =?UTF-8?q?=EC=82=B0=EC=B1=85=20=EB=A3=A8=ED=8A=B8=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=B0=8F=20=EC=83=81=EC=84=B8=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=20=EC=83=81=ED=83=9C=20=EA=B4=80=EB=A6=AC(ViewModel=20+=20Stat?= =?UTF-8?q?eFlow)=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/mypage/ArchivedCourseDetailScreen.kt | 30 ++++++++++++++++--- .../ui/mypage/ArchivedCourseListScreen.kt | 29 ++++++++++++++++-- .../ui/mypage/SavedCourseDetailScreen.kt | 2 -- .../ui/mypage/SavedCourseListScreen.kt | 3 -- .../ui/mypage/state/ArchivedDetailContract.kt | 17 +++++++++-- .../viewmodel/ArchivedDetailViewModel.kt | 24 ++++++++++++++- 6 files changed, 91 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/ArchivedCourseDetailScreen.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/ArchivedCourseDetailScreen.kt index 5d5db9b8..a9d34bb2 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/ArchivedCourseDetailScreen.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/ArchivedCourseDetailScreen.kt @@ -2,12 +2,10 @@ package com.paw.key.presentation.ui.mypage import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -16,27 +14,39 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.paw.key.core.designsystem.component.CourseDetail import com.paw.key.core.designsystem.component.ImageModal import com.paw.key.core.designsystem.component.PawkeyButton import com.paw.key.core.designsystem.component.TopBar import com.paw.key.core.designsystem.theme.PawKeyTheme import com.paw.key.core.designsystem.theme.White1 +import com.paw.key.presentation.ui.mypage.state.ArchivedDetailContract +import com.paw.key.presentation.ui.mypage.viewmodel.ArchivedDetailViewModel @Composable fun ArchivedDetailRoute( navigateUp: () -> Unit, + navigateToWalk: () -> Unit, modifier: Modifier = Modifier, + viewModel: ArchivedDetailViewModel = hiltViewModel() ) { + val state = viewModel.state.collectAsStateWithLifecycle() + ArchivedCourseDetailScreen( + state = state.value, navigateUp = navigateUp, + navigateToWalk = navigateToWalk, modifier = modifier ) } @Composable fun ArchivedCourseDetailScreen( + state: ArchivedDetailContract.ArchivedDetailState, navigateUp: () -> Unit, + navigateToWalk: () -> Unit, modifier: Modifier = Modifier ){ var isImageExpanded by remember { mutableStateOf(false) } @@ -76,7 +86,7 @@ fun ArchivedCourseDetailScreen( if (isImageExpanded) { ImageModal( - imageUrl = "https://pawkey-server.com/image.jpg", + imageUrl = state.imageUrl, onDismiss = { isImageExpanded = false } ) } @@ -87,6 +97,18 @@ fun ArchivedCourseDetailScreen( @Composable fun ArchivedCourseDetailPreview(){ PawKeyTheme { - ArchivedCourseDetailScreen(navigateUp = {}) + ArchivedCourseDetailScreen(state = ArchivedDetailContract.ArchivedDetailState( + title = "한강 산책로", + petName = "후추", + date = "2025/06/02", + location = "뚝섬유원지", + distance = "4.5km", + time = "1시간 30분 소요", + option = listOf("풍경이 좋아요", "조용해요", "길이 깨끗해요"), + imageUrl = "https://pawkey-server.com/image.jpg" + ), + navigateUp = {}, + navigateToWalk = {} + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/ArchivedCourseListScreen.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/ArchivedCourseListScreen.kt index 45f99d08..fbec5976 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/ArchivedCourseListScreen.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/ArchivedCourseListScreen.kt @@ -7,26 +7,36 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.paw.key.core.designsystem.component.CourseCard import com.paw.key.core.designsystem.component.TopBar import com.paw.key.core.designsystem.theme.PawKeyTheme import com.paw.key.core.designsystem.theme.White1 +import com.paw.key.presentation.ui.mypage.state.ArchivedListContract +import com.paw.key.presentation.ui.mypage.state.SavedListContract.CourseCardData +import com.paw.key.presentation.ui.mypage.viewmodel.ArchivedListViewModel @Composable fun ArchivedCourseRoute( navigateUp: () -> Unit, navigateNext: () -> Unit, modifier: Modifier = Modifier, + viewModel: ArchivedListViewModel = hiltViewModel() ) { + val state = viewModel.state.collectAsStateWithLifecycle() + ArchivedCourseListScreen( + state = state.value, navigateUp = navigateUp, navigateNext = navigateNext, - modifier = modifier + modifier = modifier ) } @Composable fun ArchivedCourseListScreen( + state: ArchivedListContract.ArchivedListState, navigateUp: () -> Unit, navigateNext: () -> Unit, modifier: Modifier = Modifier @@ -81,6 +91,21 @@ fun ArchivedCourseListScreen( @Composable fun ArchivedCourseListScreenPreview() { PawKeyTheme { - ArchivedCourseListScreen(navigateUp = {}, navigateNext = {}) + ArchivedCourseListScreen( + state = ArchivedListContract.ArchivedListState( + courseList = listOf( + ArchivedListContract.CourseCardData( + title = "예시 산책로", + petName = "하루", + date = "2025/01/01", + location = "강남", + distance = "2.3km", + time = "45분" + ) + ) + ), + navigateUp = {}, + navigateNext = {} + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseDetailScreen.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseDetailScreen.kt index 4759478f..859405ff 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseDetailScreen.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseDetailScreen.kt @@ -27,9 +27,7 @@ import com.paw.key.core.designsystem.component.PawkeyButton import com.paw.key.core.designsystem.component.TopBar import com.paw.key.core.designsystem.theme.PawKeyTheme import com.paw.key.core.designsystem.theme.White1 -import com.paw.key.presentation.ui.mypage.state.MyPageContract import com.paw.key.presentation.ui.mypage.state.SavedDetailContract -import com.paw.key.presentation.ui.mypage.viewmodel.MyPageViewModel import com.paw.key.presentation.ui.mypage.viewmodel.SavedDetailViewModel @Composable diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseListScreen.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseListScreen.kt index bf41d443..04895ab7 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseListScreen.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/SavedCourseListScreen.kt @@ -14,13 +14,10 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.paw.key.core.designsystem.component.CourseCard import com.paw.key.core.designsystem.component.TopBar import com.paw.key.core.designsystem.theme.PawKeyTheme -import com.paw.key.presentation.ui.mypage.state.MyPageContract import com.paw.key.presentation.ui.mypage.state.SavedListContract import com.paw.key.presentation.ui.mypage.state.SavedListContract.CourseCardData -import com.paw.key.presentation.ui.mypage.viewmodel.MyPageViewModel import com.paw.key.presentation.ui.mypage.viewmodel.SavedListViewModel - @Composable fun SavedCourseRoute( navigateUp: () -> Unit, diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/state/ArchivedDetailContract.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/ArchivedDetailContract.kt index 7468ac76..b123b52a 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/state/ArchivedDetailContract.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/state/ArchivedDetailContract.kt @@ -1,4 +1,17 @@ package com.paw.key.presentation.ui.mypage.state -class ArchivedDetailContract { -} +import androidx.compose.runtime.Immutable + +object ArchivedDetailContract { + @Immutable + data class ArchivedDetailState( + val title: String, + val petName: String, + val date: String, + val location: String, + val distance: String, + val time: String, + val option: List = emptyList(), + val imageUrl: String + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/ArchivedDetailViewModel.kt b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/ArchivedDetailViewModel.kt index 65328f67..047afa82 100644 --- a/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/ArchivedDetailViewModel.kt +++ b/app/src/main/java/com/paw/key/presentation/ui/mypage/viewmodel/ArchivedDetailViewModel.kt @@ -1,4 +1,26 @@ package com.paw.key.presentation.ui.mypage.viewmodel -class ArchivedDetailViewModel { +import androidx.lifecycle.ViewModel +import com.paw.key.presentation.ui.mypage.state.ArchivedDetailContract.ArchivedDetailState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject + +@HiltViewModel +class ArchivedDetailViewModel @Inject constructor() : ViewModel() { + private val _state = MutableStateFlow( + ArchivedDetailState( + title = "한강 산책로", + petName = "후추", + date = "2025/06/02", + location = "뚝섬유원지", + distance = "4.5km", + time = "1시간 30분 소요", + option = listOf("풍경이 좋아요", "조용해요", "길이 깨끗해요"), + imageUrl = "https://pawkey-server.com/image.jpg" + ) + ) + val state: StateFlow get() = _state.asStateFlow() } \ No newline at end of file