Skip to content

Commit cb97b91

Browse files
authored
Merge pull request #31 from casper-jr/feat/mypageupdate
[Feat] 내 정보 조회/수정 화면 기능 구현
2 parents e6fb514 + 9028f91 commit cb97b91

File tree

11 files changed

+332
-183
lines changed

11 files changed

+332
-183
lines changed

composeApp/src/commonMain/kotlin/org/whosin/client/core/navigation/Route.kt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ sealed interface Route {
2929
data object NicknameInput: Route
3030

3131
@Serializable
32-
data object ClubCodeInput: Route
32+
data class ClubCodeInput(val returnToMyPage: Boolean = false): Route
3333

3434
/* 메인 화면 */
3535
@Serializable
@@ -38,8 +38,4 @@ sealed interface Route {
3838
/* 마이 페이지 */
3939
@Serializable
4040
data object MyPage: Route
41-
42-
/* 내 정보 수정하기 */
43-
@Serializable
44-
data object UpdateMyInfo: Route
4541
}

composeApp/src/commonMain/kotlin/org/whosin/client/core/navigation/WhosInNavGraph.kt

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import androidx.navigation.NavHostController
66
import androidx.navigation.compose.NavHost
77
import androidx.navigation.compose.composable
88
import androidx.navigation.navigation
9+
import androidx.navigation.toRoute
910
import org.whosin.client.presentation.auth.clubcode.ClubCodeInputScreen
1011
import org.whosin.client.presentation.auth.login.EmailVerificationScreen
1112
import org.whosin.client.presentation.auth.login.LoginScreen
@@ -15,7 +16,6 @@ import org.whosin.client.presentation.auth.login.PasswordInputScreen
1516
import org.whosin.client.presentation.auth.login.SignupScreen
1617
import org.whosin.client.presentation.auth.login.SplashScreen
1718
import org.whosin.client.presentation.home.HomeScreen
18-
import org.whosin.client.presentation.mypage.EditMyInfoScreen
1919
import org.whosin.client.presentation.mypage.MyPageScreen
2020

2121
@Composable
@@ -105,18 +105,25 @@ fun WhosInNavGraph(
105105
modifier = modifier,
106106
onNavigateBack = { navController.navigateUp() },
107107
onNavigateToClubCode = {
108-
navController.navigate(Route.ClubCodeInput)
108+
navController.navigate(Route.ClubCodeInput(returnToMyPage = false))
109109
}
110110
)
111111
}
112112

113-
composable<Route.ClubCodeInput> {
113+
composable<Route.ClubCodeInput> { backStackEntry ->
114+
val route = backStackEntry.toRoute<Route.ClubCodeInput>()
114115
ClubCodeInputScreen(
115116
modifier = modifier,
116117
onNavigateBack = { navController.navigateUp() },
117118
onNavigateToHome = {
118-
navController.navigate(Route.Home) {
119-
popUpTo(Route.AuthGraph) { inclusive = true }
119+
if (route.returnToMyPage) {
120+
// MyPage에서 온 경우 단순히 뒤로가기
121+
navController.navigateUp()
122+
} else {
123+
// 회원가입 플로우에서 온 경우 Home으로 이동
124+
navController.navigate(Route.Home) {
125+
popUpTo(Route.AuthGraph) { inclusive = true }
126+
}
120127
}
121128
}
122129
)
@@ -139,23 +146,7 @@ fun WhosInNavGraph(
139146
modifier = modifier,
140147
onNavigateBack = { navController.navigateUp() },
141148
onNavigateToAddClub = {
142-
143-
},
144-
onNavigateToEdit = {
145-
navController.navigate(Route.UpdateMyInfo)
146-
},
147-
)
148-
}
149-
150-
composable<Route.UpdateMyInfo> {
151-
EditMyInfoScreen(
152-
modifier = modifier,
153-
onNavigateBack = { navController.navigateUp() },
154-
onNavigateToMyPage = {
155-
navController.navigate(Route.MyPage) {
156-
popUpTo(Route.UpdateMyInfo) { inclusive = true }
157-
launchSingleTop = true
158-
}
149+
navController.navigate(Route.ClubCodeInput(returnToMyPage = true))
159150
}
160151
)
161152
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.whosin.client.data.dto.request
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
6+
@Serializable
7+
data class UpdateMyInfoRequestDto(
8+
@SerialName("nickName")
9+
val nickName: String,
10+
@SerialName("clubList")
11+
val clubList: List<Int>?
12+
)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.whosin.client.data.dto.response
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
6+
@Serializable
7+
data class MyInfoResponseDto(
8+
@SerialName("success")
9+
val success: Boolean,
10+
@SerialName("status")
11+
val status: Int,
12+
@SerialName("message")
13+
val message: String,
14+
@SerialName("data")
15+
val data: MyInfoData
16+
)
17+
18+
@Serializable
19+
data class MyInfoData(
20+
@SerialName("nickName")
21+
val nickName: String,
22+
@SerialName("clubList")
23+
val clubList: List<MyClubData>
24+
)
25+
26+
@Serializable
27+
data class MyClubData(
28+
@SerialName("id")
29+
val id: Int,
30+
@SerialName("name")
31+
val name: String
32+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.whosin.client.data.dto.response
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
6+
@Serializable
7+
data class UpdateMyInfoResponseDto(
8+
@SerialName("success")
9+
val success: Boolean,
10+
@SerialName("status")
11+
val status: Int,
12+
@SerialName("message")
13+
val message: String,
14+
@SerialName("data")
15+
val data: MyInfoData
16+
)

composeApp/src/commonMain/kotlin/org/whosin/client/data/remote/RemoteMemberDataSource.kt

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@ package org.whosin.client.data.remote
33
import io.ktor.client.HttpClient
44
import io.ktor.client.call.body
55
import io.ktor.client.request.get
6+
import io.ktor.client.request.patch
67
import io.ktor.client.request.post
78
import io.ktor.client.request.setBody
89
import io.ktor.client.statement.HttpResponse
910
import io.ktor.http.isSuccess
1011
import org.whosin.client.core.network.ApiResult
1112
import org.whosin.client.data.dto.request.LoginRequestDto
13+
import org.whosin.client.data.dto.request.UpdateMyInfoRequestDto
14+
import org.whosin.client.data.dto.response.ErrorResponseDto
1215
import org.whosin.client.data.dto.response.LoginResponseDto
16+
import org.whosin.client.data.dto.response.MyInfoResponseDto
17+
import org.whosin.client.data.dto.response.UpdateMyInfoResponseDto
1318

1419
class RemoteMemberDataSource(
1520
private val client: HttpClient
@@ -38,4 +43,73 @@ class RemoteMemberDataSource(
3843
ApiResult.Error(message = t.message, cause = t)
3944
}
4045
}
46+
47+
// 내 정보 조회
48+
suspend fun getMyInfo(): ApiResult<MyInfoResponseDto> {
49+
return try {
50+
val response: HttpResponse = client.get(urlString = "users/myPage")
51+
52+
if (response.status.isSuccess()) {
53+
ApiResult.Success(
54+
data = response.body(),
55+
statusCode = response.status.value
56+
)
57+
} else {
58+
// 에러 응답 파싱 시도
59+
try {
60+
val errorResponse: ErrorResponseDto = response.body()
61+
ApiResult.Error(
62+
code = response.status.value,
63+
message = errorResponse.message
64+
)
65+
} catch (e: Exception) {
66+
// 파싱 실패 시 기본 에러 메시지
67+
ApiResult.Error(
68+
code = response.status.value,
69+
message = "HTTP Error: ${response.status.value}"
70+
)
71+
}
72+
}
73+
} catch (t: Throwable) {
74+
ApiResult.Error(message = t.message, cause = t)
75+
}
76+
}
77+
78+
// 내 정보 수정
79+
suspend fun updateMyInfo(
80+
newNickName: String,
81+
clubList: List<Int>?
82+
): ApiResult<UpdateMyInfoResponseDto> {
83+
return try {
84+
val response: HttpResponse = client.patch(urlString = "users/myPage/update") {
85+
setBody(
86+
UpdateMyInfoRequestDto(nickName = newNickName, clubList = clubList)
87+
)
88+
}
89+
90+
if (response.status.isSuccess()) {
91+
ApiResult.Success(
92+
data = response.body(),
93+
statusCode = response.status.value
94+
)
95+
} else {
96+
// 에러 응답 파싱 시도
97+
try {
98+
val errorResponse: ErrorResponseDto = response.body()
99+
ApiResult.Error(
100+
code = response.status.value,
101+
message = errorResponse.message
102+
)
103+
} catch (e: Exception) {
104+
// 파싱 실패 시 기본 에러 메시지
105+
ApiResult.Error(
106+
code = response.status.value,
107+
message = "HTTP Error: ${response.status.value}"
108+
)
109+
}
110+
}
111+
} catch (t: Throwable) {
112+
ApiResult.Error(message = t.message, cause = t)
113+
}
114+
}
41115
}

composeApp/src/commonMain/kotlin/org/whosin/client/data/repository/MemberRepository.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@ package org.whosin.client.data.repository
33
import org.whosin.client.data.remote.RemoteMemberDataSource
44
import org.whosin.client.core.network.ApiResult
55
import org.whosin.client.data.dto.response.LoginResponseDto
6+
import org.whosin.client.data.dto.response.MyInfoResponseDto
7+
import org.whosin.client.data.dto.response.UpdateMyInfoResponseDto
68

79
class MemberRepository(
810
private val dataSource: RemoteMemberDataSource
911
) {
1012
suspend fun login(email: String, password: String): ApiResult<LoginResponseDto> =
1113
dataSource.login(email, password)
1214

15+
suspend fun getMyInfo(): ApiResult<MyInfoResponseDto> =
16+
dataSource.getMyInfo()
17+
18+
suspend fun updateMyInfo(newNickName: String, clubList: List<Int>?): ApiResult<UpdateMyInfoResponseDto> =
19+
dataSource.updateMyInfo(newNickName = newNickName, clubList = clubList)
20+
1321
}

composeApp/src/commonMain/kotlin/org/whosin/client/presentation/mypage/EditMyInfoScreen.kt

Lines changed: 0 additions & 99 deletions
This file was deleted.

0 commit comments

Comments
 (0)