Skip to content

Commit

Permalink
Merge pull request #99 from Nexters/release/1.1.0
Browse files Browse the repository at this point in the history
[Release] 1.1.0 버전 업데이트 - master
  • Loading branch information
ham2174 authored Feb 26, 2024
2 parents ed11285 + 629e205 commit 8980b69
Show file tree
Hide file tree
Showing 26 changed files with 376 additions and 32 deletions.
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
android:name=".MainActivity"
android:exported="true"
android:windowSoftInputMode="adjustResize"
android:screenOrientation="portrait"
android:theme="@style/Theme.FunchAOS.Splash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/com/moya/funch/di/MemberModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import com.moya.funch.repository.MemberRepository
import com.moya.funch.repository.MemberRepositoryImpl
import com.moya.funch.usecase.CreateUserProfileUseCase
import com.moya.funch.usecase.CreateUserProfileUseCaseImpl
import com.moya.funch.usecase.DeleteUserProfileUseCase
import com.moya.funch.usecase.DeleteUserProfileUseCaseImpl
import com.moya.funch.usecase.LoadUserProfileUseCase
import com.moya.funch.usecase.LoadUserProfileUseCaseImpl
import com.moya.funch.usecase.LoadViewCountUseCase
Expand Down Expand Up @@ -32,6 +34,10 @@ object MemberModule {
@Binds
@Singleton
fun bindCreateUserProfileUseCase(useCase: CreateUserProfileUseCaseImpl): CreateUserProfileUseCase

@Binds
@Singleton
fun bindDeleteUserProfileUseCase(useCase: DeleteUserProfileUseCaseImpl): DeleteUserProfileUseCase
}

@Module
Expand Down
6 changes: 5 additions & 1 deletion app/src/main/java/com/moya/funch/navigation/FunchNavHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ fun FunchNavHost(hasProfile: Boolean, navController: NavHostController = remembe
with(navController) {
profileGraph(
onNavigateToHome = ::onNavigateToHome,
onCloseMyProfile = ::onCloseMyProfile
onCloseMyProfile = ::onCloseMyProfile,
onNavigateCreateProfile = ::onNavigateToCreateProfile
)
homeScreen(
onNavigateToMatching = ::onNavigateToMatching,
Expand All @@ -32,6 +33,9 @@ fun FunchNavHost(hasProfile: Boolean, navController: NavHostController = remembe
}
}

private fun NavController.onNavigateToCreateProfile() =
navigateToCreateProfile(navOptions { popUpTo(graph.id) { inclusive = true } })

private fun NavController.onNavigateToMyProfile() = navigateToMyProfile(singleTopNavOptions)

private fun NavController.onNavigateToMatching(route: String) = navigateToMatching(route, singleTopNavOptions)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.moya.funch.datasource.remote

import com.moya.funch.network.dto.response.match.MatchingResponse

fun interface RemoteMatchDataSource {
interface RemoteMatchDataSource {
suspend fun matchProfile(targetCode: String): Result<MatchingResponse>

suspend fun canMatchProfile(targetCode: String): Result<Boolean>
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,13 @@ class RemoteMatchDataSourceImpl @Inject constructor(
)
}.mapCatching { it.data }
}

override suspend fun canMatchProfile(targetCode: String): Result<Boolean> {
return runCatching { matchingService.canMatchProfile(targetCode).code == SUCCESS_CODE }
}

companion object {
private const val SUCCESS_CODE = 1000 // @murjune TODO 추후 : DTO 전면 개편 시 Enum 으로 가져갈지 논의
private const val FAILURE_CODE = 4001
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ import com.moya.funch.model.ProfileModel

interface RemoteUserDataSource : UserDataSource {
suspend fun createUserProfile(userModel: ProfileModel): Result<ProfileModel>

suspend fun deleteUserProfile(): Result<String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,12 @@ class RemoteUserDataSourceImpl @Inject constructor(
memberService.createMember(request).data
}.mapCatching { it.toModel() }
}

override suspend fun deleteUserProfile(): Result<String> {
return runCatching {
memberService.deleteMember(userDataStore.userId).message
}.onSuccess {
userDataStore.clear()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,12 @@ class MatchingRepositoryImpl @Inject constructor(
override suspend fun matchProfile(targetCode: String): Result<Matching> {
return remoteMatchDataSource.matchProfile(targetCode).mapCatching { it.toDomain() }
}

override suspend fun canMatchProfile(targetCode: String): Result<Unit> {
return remoteMatchDataSource.canMatchProfile(targetCode).mapCatching { isSuccess ->
require(isSuccess) {
"매칭에 실패하였습니다"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,8 @@ class MemberRepositoryImpl @Inject constructor(
it.toDomain()
}
}

override suspend fun deleteUserProfile(): Result<String> {
return remoteUserDataSource.deleteUserProfile()
}
}
79 changes: 79 additions & 0 deletions core/designsystem/src/main/java/com/moya/funch/ui/FunchDialog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.moya.funch.ui

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.moya.funch.theme.FunchTheme
import com.moya.funch.theme.LocalBackgroundTheme

@Composable
fun FunchDialog(
title: String,
text: String,
dismissText: String,
confirmText: String,
onDismiss: () -> Unit,
onConfirm: () -> Unit
) {
AlertDialog(
title = {
Text(text = title)
},
titleContentColor = Color(0xFFE6E0E9),
text = {
Text(text = text)
},
textContentColor = Color(0xFFCAC4D0),
containerColor = Color(0xFF2B2930),
confirmButton = {
Box(
modifier = Modifier
.clickable(onClick = onConfirm)
.padding(vertical = 10.dp, horizontal = 12.dp)
) {
Text(
text = confirmText,
color = Color(0xFFD0BCFF)
)
}
},
onDismissRequest = { onDismiss() },
dismissButton = {
Box(
modifier = Modifier
.clickable(onClick = onDismiss)
.padding(vertical = 10.dp, horizontal = 12.dp)
) {
Text(
text = dismissText,
color = Color(0xFFD0BCFF)
)
}
}
)
}

@Preview
@Composable
private fun Preview1() {
FunchTheme {
Surface(color = LocalBackgroundTheme.current.color) {
FunchDialog(
title = "프로필 삭제하기",
text = "기존 프로필이 삭제되고 복구가 불가능해요.\n정말 삭제하실 건가요?",
dismissText = "취소하기",
confirmText = "삭제하기",
onDismiss = {},
onConfirm = {}
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.moya.funch.repository

import com.moya.funch.entity.match.Matching

fun interface MatchingRepository {
interface MatchingRepository {
suspend fun matchProfile(targetCode: String): Result<Matching>

suspend fun canMatchProfile(targetCode: String): Result<Unit>
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ interface MemberRepository {
suspend fun fetchUserViewCount(): Result<Int>

suspend fun fetchMemberProfile(id: String): Result<Profile>

suspend fun deleteUserProfile(): Result<String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class CanMatchProfileUseCaseImpl @Inject constructor(
override suspend operator fun invoke(targetCode: String): Result<Unit> = runCatching {
val code = targetCode.uppercase()
validate(code)
matchingRepository.matchProfile(code).getOrThrow()
matchingRepository.canMatchProfile(code).getOrThrow()
}

private fun validate(targetCode: String) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.moya.funch.usecase

import com.moya.funch.repository.MemberRepository
import javax.inject.Inject

class DeleteUserProfileUseCaseImpl @Inject constructor(
private val memberRepository: MemberRepository
) : DeleteUserProfileUseCase {
override suspend operator fun invoke(): Result<String> {
return memberRepository.deleteUserProfile()
}
}

fun interface DeleteUserProfileUseCase {
suspend operator fun invoke(): Result<String>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.moya.funch.network.dto.response.match

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class CanMatchResponse(
@SerialName("status")
val status: Int,
@SerialName("message")
val message: String = "",
@SerialName("code")
val code: Int = 0,
@SerialName("data")
val data: Unit? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ package com.moya.funch.network.service

import com.moya.funch.network.dto.request.MatchingRequest
import com.moya.funch.network.dto.response.BaseResponse
import com.moya.funch.network.dto.response.match.CanMatchResponse
import com.moya.funch.network.dto.response.match.MatchingResponse
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path

interface MatchingService {
@POST("api/v1/matching")
suspend fun matchProfile(@Body body: MatchingRequest): BaseResponse<MatchingResponse>

@GET("api/v1/matching/{targetMemberCode}")
suspend fun canMatchProfile(@Path("targetMemberCode") code: String): CanMatchResponse
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.moya.funch.network.dto.request.MemberRequest
import com.moya.funch.network.dto.response.BaseResponse
import com.moya.funch.network.dto.response.member.MemberResponse
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path
Expand All @@ -19,4 +20,7 @@ interface MemberService {

@GET("api/v1/members")
suspend fun findMemberByDeviceNumber(@Query("deviceNumber") deviceNumber: String): BaseResponse<MemberResponse>

@DELETE("api/v1/members/{id}")
suspend fun deleteMember(@Path("id") id: String): BaseResponse<String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.google.common.truth.Truth.assertThat
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import com.moya.funch.network.dto.request.MatchingRequest
import com.moya.funch.network.dto.response.BaseResponse
import com.moya.funch.network.dto.response.match.CanMatchResponse
import com.moya.funch.network.dto.response.match.ChemistryResponse
import com.moya.funch.network.dto.response.match.MatchInfoResponse
import com.moya.funch.network.dto.response.match.MatchingResponse
Expand Down Expand Up @@ -39,7 +40,6 @@ internal class MatchingServiceTest {
matchingService =
Retrofit.Builder().addConverterFactory(
Json {
ignoreUnknownKeys = true
prettyPrint = true
coerceInputValues = true
}.asConverterFactory("application/json".toMediaType())
Expand Down Expand Up @@ -110,6 +110,43 @@ internal class MatchingServiceTest {
)
}

@Test
fun `상대방 code 로 매칭 성공 유부를 알 수 있다`() = runTest {
// given
val successJson = File("src/test/res/can_matching_success.json").readText()
val failJson = File("src/test/res/can_matching_fail.json").readText()
val fakeSuccessResponse = MockResponse().setBody(successJson).setResponseCode(200)
val fakeFailResponse = MockResponse().setBody(failJson).setResponseCode(200)
mockWebServer.enqueue(fakeSuccessResponse)
mockWebServer.enqueue(fakeFailResponse)
val expectedSuccessResponse = CanMatchResponse(
200,
"OK",
1000,
null
)
val expectedFailResponse = CanMatchResponse(
200,
"매칭상대 프로필 존재하지 않음",
4001,
null
)
// when
val actualSuccessResponse =
matchingService.canMatchProfile(
"1BD"
)
val actualFailResponse =
matchingService.canMatchProfile(
"1B3D"
)
// then
assertAll(
{ assertThat(actualSuccessResponse).isEqualTo(expectedSuccessResponse) },
{ assertThat(actualFailResponse).isEqualTo(expectedFailResponse) }
)
}

companion object {
@JvmField
@RegisterExtension
Expand Down
6 changes: 6 additions & 0 deletions core/network/src/test/res/can_matching_fail.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"status": "200",
"message": "매칭상대 프로필 존재하지 않음",
"code": "4001",
"data": null
}
6 changes: 6 additions & 0 deletions core/network/src/test/res/can_matching_success.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"status": "200",
"message": "OK",
"code": "1000",
"data": null
}
Loading

0 comments on commit 8980b69

Please sign in to comment.