Skip to content

Commit

Permalink
fix: 마이페이지 데이터 보이지 않는 문제 해결
Browse files Browse the repository at this point in the history
- visibility로 인한 문제였음
  • Loading branch information
hyeonhh committed Nov 22, 2024
1 parent b7127df commit 90531d1
Show file tree
Hide file tree
Showing 17 changed files with 137 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@ import com.example.com_us.data.model.home.ResponseHomeDataDto
import com.example.com_us.data.repository.HomeRepository
import com.example.com_us.data.default_source.DefaultHomeDataSource
import com.example.com_us.data.model.BaseResponse
import com.example.com_us.data.model.toResult
import javax.inject.Inject

fun <T> BaseResponse<T>.toResult(): Result<T> {
return when {
status in 200..299 && data != null -> Result.success(data)
status in 200..299 && data == null -> Result.failure(NetworkError.NullDataError())
else -> Result.failure(NetworkError.ApiError(status, message))
}
}


sealed class NetworkError : Exception(){
data class ApiError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.example.com_us.data.default_repository
import com.example.com_us.data.model.question.response.question.ResponseProfileDto
import com.example.com_us.data.repository.ProfileRepository
import com.example.com_us.data.default_source.DefaultProfileDataSource
import com.example.com_us.data.model.toResult
import javax.inject.Inject

class DefaultProfileRepository @Inject constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.example.com_us.data.model.question.response.question.ResponseQuestion
import com.example.com_us.data.model.question.response.question.ResponseQuestionDto
import com.example.com_us.data.repository.QuestionRepository
import com.example.com_us.data.default_source.DefaultQuestionDataSource
import com.example.com_us.data.model.toResult
import javax.inject.Inject

class DefaultQuestionRepository @Inject constructor(
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/java/com/example/com_us/data/model/BaseResponse.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.com_us.data.model

import com.example.com_us.data.default_repository.NetworkError
import kotlinx.serialization.Serializable

@Serializable
Expand All @@ -14,3 +15,13 @@ data class BaseResponseNoData(
val status: Int,
val message: String,
)

fun <T> BaseResponse<T>.toResult(): Result<T> {
return when{
status == 200 && data != null -> Result.success(data)
status == 200 && data == null -> Result.failure(NetworkError.NullDataError())
status == 400 or 401 -> Result.failure(NetworkError.ApiError(status,message))
status == 500 -> Result.failure(NetworkError.ApiError(status,message))
else -> Result.failure(NetworkError.ApiError(status,message))
}
}
9 changes: 9 additions & 0 deletions app/src/main/java/com/example/com_us/ui/ApiResult.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.com_us.ui


// 성공 / 실패에 따른 UI 처리
sealed class ApiResult<out T> {
data object Initial : ApiResult<Nothing>()
data class Success<T>(val data : T) : ApiResult<T>()
data class Error(val message : String) : ApiResult<Nothing>()
}
9 changes: 0 additions & 9 deletions app/src/main/java/com/example/com_us/ui/UiState.kt

This file was deleted.

72 changes: 55 additions & 17 deletions app/src/main/java/com/example/com_us/ui/profile/ProfileFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,35 @@ package com.example.com_us.ui.profile
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout.LayoutParams
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import com.example.com_us.R
import com.example.com_us.databinding.FragmentProfileBinding
import com.example.com_us.ui.ApiResult
import com.example.com_us.util.ServerResponseHandler
import com.google.android.material.datepicker.OnSelectionChangedListener
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import java.time.LocalTime
import java.time.format.DateTimeFormatter


@AndroidEntryPoint
class ProfileFragment : Fragment(), ServerResponseHandler {
class ProfileFragment : Fragment() ,ServerResponseHandler{

private var _binding: FragmentProfileBinding? = null
private val profileViewModel: ProfileViewModel by viewModels()
Expand All @@ -38,31 +46,53 @@ class ProfileFragment : Fragment(), ServerResponseHandler {
_binding = FragmentProfileBinding.inflate(inflater, container, false)

profileViewModel.loadProfileData()
profileViewModel.serverResponseHandler = this

setProfile()

return binding.root
}

@RequiresApi(Build.VERSION_CODES.O)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
setProfile()
super.onViewCreated(view, savedInstanceState)
}

@RequiresApi(Build.VERSION_CODES.O)
private fun setProfile() {
profileViewModel.profileData.observe(viewLifecycleOwner) {
val themeGraphRatioList: List<Float> = listOf(
it.answerStatistic.dailyQuestionRatio.toFloat(),
it.answerStatistic.schoolQuestionRatio.toFloat(),
it.answerStatistic.friendQuestionRatio.toFloat(),
it.answerStatistic.familyQuestionRatio.toFloat(),
it.answerStatistic.hobbyQuestionRatio.toFloat(),
)
setProfile(it.userInfo.name, it.userInfo.imageUrl)
setStatic(it.userInfo.totalChatTime, it.userInfo.totalChatCount)
changeTypeGraph(it.answerStatistic.multipleChoiceRatio.toFloat(), it.answerStatistic.sentenceRatio.toFloat())
changeThemeGraph(themeGraphRatioList)
lifecycleScope.launch {
profileViewModel.profileUiState.collect {
when (it) {
is ApiResult.Success -> {
binding.constraintProfile.visibility = View.VISIBLE
val themeGraphRatioList: List<Float> = listOf(
it.data.answerStatistic.dailyQuestionRatio.toFloat(),
it.data.answerStatistic.schoolQuestionRatio.toFloat(),
it.data.answerStatistic.friendQuestionRatio.toFloat(),
it.data.answerStatistic.familyQuestionRatio.toFloat(),
it.data.answerStatistic.hobbyQuestionRatio.toFloat(),
)

setProfile(it.data.userInfo.name, it.data.userInfo.imageUrl)
setStatic(it.data.userInfo.totalChatTime, it.data.userInfo.totalChatCount)
changeTypeGraph(
it.data.answerStatistic.multipleChoiceRatio.toFloat(),
it.data.answerStatistic.sentenceRatio.toFloat()
)
changeThemeGraph(themeGraphRatioList)
}

is ApiResult.Error -> {
Toast.makeText(context,"잠시 후에 다시 시도해주세요!",Toast.LENGTH_SHORT).show()
}

else -> {}
}

}
}
}

private fun setProfile(username: String, profileImgUrl: String) {
Log.d("profile","setProfile")
binding.textviewProfileNickname.text = String.format(resources.getString(R.string.profile_username), username)
Glide.with(this)
.load(profileImgUrl)
Expand All @@ -72,12 +102,14 @@ class ProfileFragment : Fragment(), ServerResponseHandler {

@RequiresApi(Build.VERSION_CODES.O)
private fun setStatic(totalChatTime: String, totalChatCount: Int) {
Log.d("profile","setStatic")
val totalChatTime = stringToLocalTime(totalChatTime)
binding.textviewTimeTaken.text = String.format(resources.getString(R.string.profile_time_taken_minute), totalChatTime.toSecondOfDay() / 60)
binding.textviewConvCount.text = String.format(resources.getString(R.string.profile_conv_count_count), totalChatCount)
}

private fun changeTypeGraph(choiceRatio: Float, interactionRatio: Float) {
Log.d("profile","changeTypeGraph")
changeGraphShape(R.drawable.shape_type_graph_fill_stroke_rect34_blue, choiceRatio, GraphPosition.LEFT)
changeGraphShape(R.drawable.shape_type_graph_fill_stroke_rect34_pink, interactionRatio, GraphPosition.RIGHT)

Expand All @@ -89,6 +121,7 @@ class ProfileFragment : Fragment(), ServerResponseHandler {
}

private fun changeThemeGraph(themeGraphRatioList: List<Float>) {
Log.d("profile","changeThemeGraph")
val themeGraphBg: List<Int> = listOf(
R.drawable.shape_theme_graph_fill_rect_orange700,
R.drawable.shape_theme_graph_fill_rect_blue700,
Expand Down Expand Up @@ -123,6 +156,7 @@ class ProfileFragment : Fragment(), ServerResponseHandler {
changeGraphLayoutWeight(binding.viewProfileThemeGraphFamily, themeGraphRatioList[3])
changeGraphLayoutWeight(binding.viewProfileThemeGraphInterest, themeGraphRatioList[4])

print(binding)
binding.includeProfileGraphThemeDaily.textviewGraphPercent.text = String.format(resources.getString(R.string.percent), themeGraphRatioList[0].toInt())
binding.includeProfileGraphThemeSchool.textviewGraphPercent.text = String.format(resources.getString(R.string.percent), themeGraphRatioList[1].toInt())
binding.includeProfileGraphThemeFriend.textviewGraphPercent.text = String.format(resources.getString(R.string.percent), themeGraphRatioList[2].toInt())
Expand All @@ -131,6 +165,7 @@ class ProfileFragment : Fragment(), ServerResponseHandler {
}

private fun changeGraphLayoutWeight(view: View, ratio: Float) {
Log.d("profile","changeGraphLayoutWeight")
val marginInDp = resources.getDimensionPixelSize(R.dimen.profile_graph_margin)
view.layoutParams = LayoutParams(
LayoutParams.WRAP_CONTENT,
Expand All @@ -142,6 +177,7 @@ class ProfileFragment : Fragment(), ServerResponseHandler {
}

private fun changeGraphShape(graphDrawableId: Int, ratio: Float, position: GraphPosition) {
Log.d("profile","changeGraphShape")
val drawable = context?.let { ContextCompat.getDrawable(it, graphDrawableId) } as? GradientDrawable
if(ratio >= 100.0) {
drawable?.cornerRadius = 40f
Expand All @@ -160,6 +196,7 @@ class ProfileFragment : Fragment(), ServerResponseHandler {

@RequiresApi(Build.VERSION_CODES.O)
fun stringToLocalTime(timeString: String): LocalTime {
Log.d("profile","stringToLocalTime")
val formatter = DateTimeFormatter.ofPattern("HH:mm:ss")

return LocalTime.parse(timeString, formatter)
Expand All @@ -174,10 +211,11 @@ class ProfileFragment : Fragment(), ServerResponseHandler {
RIGHT, MIDDLE, LEFT
}

@RequiresApi(Build.VERSION_CODES.O)
override fun onServerSuccess() {
binding.constraintProfile.visibility = View.VISIBLE
}

override fun onServerFailure() {
TODO("Not yet implemented")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,45 @@ import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asFlow
import androidx.lifecycle.viewModelScope
import com.example.com_us.data.default_repository.NetworkError
import com.example.com_us.data.repository.ProfileRepository
import com.example.com_us.data.model.question.response.question.ResponseProfileDto
import com.example.com_us.ui.ApiResult
import com.example.com_us.util.ServerResponseHandler
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.serialization.builtins.UIntArraySerializer
import okhttp3.Response
import javax.inject.Inject

@HiltViewModel
class ProfileViewModel @Inject constructor(private val profileRepository: ProfileRepository) : ViewModel() {

var serverResponseHandler: ServerResponseHandler? = null
private val _profileUiState = MutableStateFlow<ApiResult<ResponseProfileDto>>(ApiResult.Initial)
val profileUiState = _profileUiState.asStateFlow()

private val _profileData = MutableLiveData<ResponseProfileDto>()
val profileData: LiveData<ResponseProfileDto> = _profileData

fun loadProfileData(){


fun loadProfileData() {
viewModelScope.launch {
profileRepository.getProfileData()
.onSuccess {
_profileData.value = it
serverResponseHandler?.onServerSuccess()
_profileUiState.value = ApiResult.Success(it)
}
.onFailure {
Log.d("GET: [PROFILE DATA]", it.toString())
serverResponseHandler?.onServerFailure()
val errorMessage = when (it) {
is NetworkError.NetworkException -> { it.message }
is NetworkError.NullDataError -> { "데이터가 준비중이에요!" }
else -> "알 수 없는 에러가 발생했습니다. 다시 시도해주세요!"
}
if (errorMessage != null) {
_profileUiState.value = ApiResult.Error(errorMessage)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.example.com_us.R
import com.example.com_us.databinding.FragmentQuestionBinding
import com.example.com_us.ui.UiState
import com.example.com_us.ui.ApiResult
import com.example.com_us.ui.compose.QuestionListItem
import com.example.com_us.ui.question.select.SelectAnswerActivity
import com.example.com_us.util.ThemeType
Expand Down Expand Up @@ -73,9 +73,9 @@ class AllQuestionListFragment : Fragment(), View.OnClickListener {
// 데이터 리스트
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED){
viewModel.uiState.collect {
viewModel.apiResult.collect {
when(it) {
is UiState.Success -> {
is ApiResult.Success -> {
if (it.data.isNotEmpty()) {
setThemeSelected()
binding.constraintQuestion.visibility = View.VISIBLE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.com_us.R
import com.example.com_us.data.default_repository.NetworkError
import com.example.com_us.data.model.home.ResponseHomeDataDto
import com.example.com_us.data.model.question.response.question.ResponseAnswerDetailWithDateDto
import com.example.com_us.data.model.question.response.question.ResponseQuestionDto
import com.example.com_us.data.repository.QuestionRepository
import com.example.com_us.ui.UiState
import com.example.com_us.ui.ApiResult
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
Expand All @@ -34,8 +31,8 @@ class AllQuestionListViewModel @Inject constructor(


// ui 상태 변수
private val _uiState = MutableStateFlow<UiState<List<ResponseQuestionDto>>>(UiState.Initial)
val uiState = _uiState.asStateFlow()
private val _apiResult = MutableStateFlow<ApiResult<List<ResponseQuestionDto>>>(ApiResult.Initial)
val apiResult = _apiResult.asStateFlow()


// 선택한 테마의 id
Expand All @@ -56,7 +53,7 @@ class AllQuestionListViewModel @Inject constructor(
viewModelScope.launch {
questionRepository.getQuestionListByCate(category)
.onSuccess {
_uiState.value = UiState.Success(it)
_apiResult.value = ApiResult.Success(it)
}
.onFailure {
val errorMessage = when(it){
Expand All @@ -65,7 +62,7 @@ class AllQuestionListViewModel @Inject constructor(
else -> "알 수 없는 에러가 발생했습니다. 다시 시도해주세요!"
}
if (errorMessage != null) {
_uiState.value = UiState.Error(errorMessage)
_apiResult.value = ApiResult.Error(errorMessage)
} }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import androidx.lifecycle.repeatOnLifecycle
import com.example.com_us.R
import com.example.com_us.data.model.question.response.question.Answer
import com.example.com_us.databinding.ActivityQuestionPreviousAnswerBinding
import com.example.com_us.ui.UiState
import com.example.com_us.ui.ApiResult
import com.example.com_us.ui.compose.AnswerHistoryItem
import com.example.com_us.ui.compose.AnswerTypeTag
import com.example.com_us.util.ColorMatch
Expand Down Expand Up @@ -48,7 +48,7 @@ class PreviousAnswerActivity : AppCompatActivity() {
repeatOnLifecycle(Lifecycle.State.STARTED){
viewModel.uiState.collect{
when(it){
is UiState.Success -> {
is ApiResult.Success -> {
setQuestion(it.data.question.questionCount, it.data.question.questionContent)
setQuestionTypeCompose(it.data.question.category, it.data.question.answerType)
setComposeList(it.data.answerList)
Expand Down
Loading

0 comments on commit 90531d1

Please sign in to comment.