Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into feature/matching-ui
Browse files Browse the repository at this point in the history
  • Loading branch information
murjune committed Feb 8, 2024
2 parents 14bd808 + c24ad47 commit 56043f2
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 0 deletions.
94 changes: 94 additions & 0 deletions feature/match/src/main/java/com/moya/funch/MatchScreen.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.moya.funch

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.moya.funch.entity.SubwayStation
import com.moya.funch.entity.match.Chemistry
import com.moya.funch.entity.match.Recommend
import com.moya.funch.entity.profile.Profile

@Composable
internal fun MatchRoute(onClose: () -> Unit, code: String, matchViewModel: MatchViewModel = hiltViewModel()) {
val uiState by matchViewModel.uiState.collectAsStateWithLifecycle()
val matchCode by matchViewModel.matchCode.collectAsStateWithLifecycle()

LaunchedEffect(matchViewModel) {
matchViewModel.saveMatchCode(code)
}

MatchScreen(
onClose = onClose,
memberCode = matchCode,
matchUiState = uiState
)
}

@Composable
private fun MatchScreen(onClose: () -> Unit, memberCode: String, matchUiState: MatchUiState) {
CompositionLocalProvider(LocalContentColor provides Color.White) { // @murjune TODO Delete this line
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
when (matchUiState) {
is MatchUiState.Loading -> Loading()
is MatchUiState.Error -> ErrorMatchContent(code = memberCode)
is MatchUiState.Success -> {
val (profile, similarity, chemistrys, recommends, subways) = matchUiState.matching
MatchContent(
profile = profile,
similarity = similarity,
chemistrys = chemistrys,
recommends = recommends,
subways = subways
)
}
}
Button(onClick = onClose) {
Text("Close")
}
}
}
}

@Composable
internal fun MatchContent(
profile: Profile,
similarity: Int,
chemistrys: List<Chemistry>,
recommends: List<Recommend>,
subways: List<SubwayStation>
) {
Column {
Text("This is Match Screen")
Text(text = "Profile : $profile")
Text(text = "Similarity : $similarity")
Text(text = "Chemistrys : $chemistrys")
Text(text = "Recommends : $recommends")
Text(text = "Subways : $subways")
}
}

@Composable
internal fun ErrorMatchContent(code: String) {
Text("There is no match code $code. Please try again.")
}

@Composable
internal fun Loading() {
Text(text = "Loading...")
}
84 changes: 84 additions & 0 deletions feature/match/src/main/java/com/moya/funch/MatchViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.moya.funch

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.moya.funch.entity.Blood
import com.moya.funch.entity.Club
import com.moya.funch.entity.Job
import com.moya.funch.entity.Mbti
import com.moya.funch.entity.SubwayLine
import com.moya.funch.entity.SubwayStation
import com.moya.funch.entity.match.Chemistry
import com.moya.funch.entity.match.Matching
import com.moya.funch.entity.match.Recommend
import com.moya.funch.entity.profile.Profile
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn

@HiltViewModel
class MatchViewModel @Inject constructor(
// private val matchProfileUseCase : MatchProfileUseCase,
private val savedStateHandle: SavedStateHandle
) : ViewModel() {

val matchCode: StateFlow<String> = savedStateHandle.getStateFlow(MATCH_CODE, "")

val uiState: StateFlow<MatchUiState> = matchCode.mapLatest { code ->
if (code.isEmpty()) {
MatchUiState.Loading
} else {
// MatchUiState.Success(matchProfileUseCase("1", it))
// TODO : Remove 목 데이터, delay
delay(1000L)
MatchUiState.Success(MOCK_MATCHING)
}
}.catch {
emit(MatchUiState.Error)
}.stateIn(viewModelScope, started = SharingStarted.WhileSubscribed(5000), initialValue = MatchUiState.Loading)

fun saveMatchCode(code: String) {
savedStateHandle[MATCH_CODE] = code
}

companion object {
private const val MATCH_CODE = "matchCode"

// id: 65c27d3232e6054951260d3d, code: V3H5, device : bbb
// id: 65c27d8b32e6054951260d3e, code: 6V2Q, device: ccc
private val MOCK_MATCHING = Matching(
profile = Profile().copy(
name = "abc",
job = Job.DEVELOPER,
clubs = listOf(Club.NEXTERS),
mbti = Mbti.INFP,
blood = Blood.A,
subways = listOf(
SubwayStation("목동역", lines = listOf(SubwayLine.FIVE))
)
),
similarity = 80,
chemistrys = listOf(
Chemistry("대한민국 선수분들", "정말 고생 많으셨습니다...")
),
recommends = listOf(
Recommend("지금은"),
Recommend("새벽"),
Recommend("3시"),
Recommend("48뷴")
)
)
}
}

sealed class MatchUiState {
data object Loading : MatchUiState()
data object Error : MatchUiState()
data class Success(val matching: Matching) : MatchUiState()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.moya.funch.navigation

import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import com.moya.funch.MatchRoute

private const val MATCH_ROUTE = "match/{code}"
private const val MEMBER_CODE_KEY = "code"
private const val NO_MEMBER_CODE = "no member code"

fun NavController.navigateToMatching(memberCode: String, navOptions: NavOptions? = null) =
navigate(createMatchRoute(memberCode), navOptions)

fun NavGraphBuilder.matchingScreen(onClose: () -> Unit) {
composable(
route = MATCH_ROUTE,
arguments = listOf(
navArgument(MEMBER_CODE_KEY) {
type = NavType.StringType
defaultValue = NO_MEMBER_CODE
}
)
) { backStackEntry ->
val code = backStackEntry.arguments?.getString(MEMBER_CODE_KEY) ?: NO_MEMBER_CODE
MatchRoute(code = code, onClose = onClose)
}
}

private fun createMatchRoute(memberCode: String) = MATCH_ROUTE.replace("{$MEMBER_CODE_KEY}", memberCode)

0 comments on commit 56043f2

Please sign in to comment.