Skip to content

Commit

Permalink
[D83T-66] 메인 탭 예약 시간 UI 반영
Browse files Browse the repository at this point in the history
  • Loading branch information
YHKOO95 committed Mar 3, 2023
1 parent 227b53f commit b647a1d
Show file tree
Hide file tree
Showing 20 changed files with 242 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.d83t.bpm.data.model.response

import com.d83t.bpm.data.base.BaseResponse
import com.d83t.bpm.data.mapper.DataMapper
import com.d83t.bpm.domain.model.UserSchedule
import com.google.gson.annotations.SerializedName
import kotlinx.parcelize.Parcelize

@Parcelize
data class UserScheduleResponse(
@SerializedName("studioName")
val studioName: String?,
@SerializedName("date")
val date: String?,
@SerializedName("time")
val time: String?,
@SerializedName("memo")
val memo: String?,
) : BaseResponse {
companion object : DataMapper<UserScheduleResponse, UserSchedule> {
override fun UserScheduleResponse.toDataModel(): UserSchedule {
return UserSchedule(
studioName = studioName,
date = date,
time = time,
memo = memo
)
}
}
}
13 changes: 4 additions & 9 deletions data/src/main/java/com/d83t/bpm/data/network/MainApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,10 @@ import com.d83t.bpm.data.model.response.ScheduleResponse
import com.d83t.bpm.data.model.response.SignUpResponse
import com.d83t.bpm.data.model.response.StudioListResponse
import com.d83t.bpm.data.model.response.StudioResponse
import com.d83t.bpm.domain.model.StudioList
import com.d83t.bpm.data.model.response.UserScheduleResponse
import okhttp3.MultipartBody
import retrofit2.Response
import retrofit2.http.*
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Headers
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.Part
import retrofit2.http.Path
import retrofit2.http.Query

interface MainApi {
@Headers("shouldBeAuthorized: false")
Expand Down Expand Up @@ -77,6 +69,9 @@ interface MainApi {
@Query("offset") offset: Int,
): Response<StudioListResponse>

@GET("api/users/schedule")
suspend fun getUserSchedule(): Response<UserScheduleResponse>

@GET("api/studio")
suspend fun searchStudio(
@Query("q") query: String
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.d83t.bpm.data.repositoryImpl

import com.d83t.bpm.data.model.response.StudioListResponse.Companion.toDataModel
import com.d83t.bpm.data.model.response.UserScheduleResponse.Companion.toDataModel
import com.d83t.bpm.data.network.BPMResponse
import com.d83t.bpm.data.network.BPMResponseHandler
import com.d83t.bpm.data.network.ErrorResponse.Companion.toDataModel
import com.d83t.bpm.data.network.MainApi
import com.d83t.bpm.domain.model.ResponseState
import com.d83t.bpm.domain.model.StudioList
import com.d83t.bpm.domain.model.UserSchedule
import com.d83t.bpm.domain.repository.MainRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
Expand All @@ -30,4 +32,17 @@ class MainRepositoryImpl @Inject constructor(
}.collect()
}
}

override suspend fun getUserSchedule(): Flow<ResponseState<UserSchedule>> {
return flow {
BPMResponseHandler().handle {
mainApi.getUserSchedule()
}.onEach { result ->
when (result) {
is BPMResponse.Success -> emit(ResponseState.Success(result.data.toDataModel()))
is BPMResponse.Error -> emit(ResponseState.Error(result.error.toDataModel()))
}
}.collect()
}
}
}
3 changes: 3 additions & 0 deletions domain/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,7 @@ dependencies {
//timber log
implementation 'com.jakewharton.timber:timber:5.0.1'

// joda datetime
implementation "joda-time:joda-time:2.10.13"

}
7 changes: 6 additions & 1 deletion domain/src/main/java/com/d83t/bpm/domain/model/Studio.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.d83t.bpm.domain.model

import com.d83t.bpm.domain.base.BaseModel
import com.google.gson.annotations.SerializedName
import kotlin.math.round
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize

Expand All @@ -27,9 +27,14 @@ data class Studio(
val updatedAt: String?
) : BaseModel {

// TODO : 죄송합니다..

@IgnoredOnParcel
val tagList = listOf<String>(
"친절해요", "소통이 빨라요", "깨끗해요"
)

@IgnoredOnParcel
val ratingText: String = "${round((rating?.times(10) ?: 0) as Double) / 10}"

}
12 changes: 12 additions & 0 deletions domain/src/main/java/com/d83t/bpm/domain/model/UserSchedule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.d83t.bpm.domain.model

import com.d83t.bpm.domain.base.BaseModel
import kotlinx.parcelize.Parcelize

@Parcelize
data class UserSchedule(
val studioName: String? = "",
val date: String? = "",
val time: String? = "",
val memo: String? = "끝까지 화이팅!",
) : BaseModel
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ package com.d83t.bpm.domain.repository

import com.d83t.bpm.domain.model.ResponseState
import com.d83t.bpm.domain.model.StudioList
import com.d83t.bpm.domain.model.UserSchedule
import kotlinx.coroutines.flow.Flow

interface MainRepository {

// TODO : Move to HomeRepository
suspend fun getStudioList(limit: Int, offset: Int): Flow<ResponseState<StudioList>>

suspend fun getUserSchedule(): Flow<ResponseState<UserSchedule>>

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.d83t.bpm.domain.usecase.main

import com.d83t.bpm.domain.model.ResponseState
import com.d83t.bpm.domain.model.UserSchedule
import com.d83t.bpm.domain.repository.MainRepository
import dagger.Reusable
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow

@Reusable
class GetUserScheduleUseCase @Inject constructor(
private val mainRepository: MainRepository
) {
suspend operator fun invoke(): Flow<ResponseState<UserSchedule>> {
return mainRepository.getUserSchedule()
}
}
3 changes: 3 additions & 0 deletions presentation/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ dependencies {
// 카카오 로그인
implementation "com.kakao.sdk:v2-user:2.12.1"

// joda datetime
implementation "joda-time:joda-time:2.10.13"

// Flipper
debugImplementation 'com.facebook.flipper:flipper:0.182.0'
debugImplementation 'com.facebook.soloader:soloader:0.10.4'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,22 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::infl
viewModel.state.collect { state ->
when (state) {
HomeState.Init -> {
// TODO : 예약현황 가져오기
viewModel.getUserSchedule()
}
HomeState.StudioList -> Unit
HomeState.UserSchedule -> Unit
HomeState.Error -> {
// TODO : Error Handling
requireContext().showToast("예약 정보를 가져오는 중 에러가 발생했습니다.")
// requireContext().showToast("예약 정보를 가져오는 중 에러가 발생했습니다.")
}
}
}
}

repeatCallDefaultOnStarted {
viewModel.event.collect { event ->
when (event) {
HomeViewEvent.ClickSearch -> {
requireContext().showToast("검색페이지 이동")
}
}
}
Expand All @@ -54,7 +64,12 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::infl
private fun setUpPager() {
binding.pager.adapter = HomePagerAdapter(requireActivity(), fragmentList)

TabLayoutMediator(binding.tab, binding.pager, false, true) { tab: TabLayout.Tab?, position: Int ->
TabLayoutMediator(
binding.tab,
binding.pager,
false,
true
) { tab: TabLayout.Tab?, position: Int ->
val resId: Int = when (position) {
0 -> R.string.tab_hot
1 -> R.string.tab_review
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.d83t.bpm.presentation.ui.main.home

sealed interface HomeState {
object Init : HomeState
object StudioList : HomeState
object UserSchedule : HomeState

object Error : HomeState
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package com.d83t.bpm.presentation.ui.main.home

sealed interface HomeViewEvent
sealed interface HomeViewEvent {
object ClickSearch : HomeViewEvent
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package com.d83t.bpm.presentation.ui.main.home

import androidx.lifecycle.viewModelScope
import com.d83t.bpm.domain.model.ResponseState
import com.d83t.bpm.domain.model.Studio
import com.d83t.bpm.domain.usecase.main.GetStudioListUseCase
import com.d83t.bpm.domain.model.UserSchedule
import com.d83t.bpm.domain.usecase.main.GetUserScheduleUseCase
import com.d83t.bpm.presentation.base.BaseViewModel
import com.d83t.bpm.presentation.di.IoDispatcher
import com.d83t.bpm.presentation.di.MainDispatcher
Expand All @@ -21,7 +21,7 @@ import kotlinx.coroutines.launch

@HiltViewModel
class HomeViewModel @Inject constructor(
private val getStudioListUseCase: GetStudioListUseCase,
private val getUserScheduleUseCase: GetUserScheduleUseCase,
@MainDispatcher private val mainDispatcher: CoroutineDispatcher,
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
) : BaseViewModel() {
Expand All @@ -34,11 +34,36 @@ class HomeViewModel @Inject constructor(
val event: SharedFlow<HomeViewEvent>
get() = _event

private val _userScheduleInfo = MutableStateFlow(UserSchedule())
val userScheduleInfo: StateFlow<UserSchedule>
get() = _userScheduleInfo

private val exceptionHandler: CoroutineExceptionHandler by lazy {
CoroutineExceptionHandler { coroutineContext, throwable ->

}
}

fun getUserSchedule() {
viewModelScope.launch(ioDispatcher + exceptionHandler) {
getUserScheduleUseCase().onEach { state ->
when (state) {
is ResponseState.Success -> {
_userScheduleInfo.emit(state.data)
_state.emit(HomeState.UserSchedule)
}
is ResponseState.Error -> {
_state.emit(HomeState.Error)
}
}
}.launchIn(viewModelScope)
}
}

fun clickSearch(){
viewModelScope.launch {
_event.emit(HomeViewEvent.ClickSearch)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class HomeRecommendViewHolder(
this.item = item

list.adapter = HomeRecommendImageAdapter()
// list.addItemDecoration(HomeRecommendImageItemDecoration())
list.addItemDecoration(HomeRecommendImageItemDecoration())

root.setOnClickListener {
listener.invoke(item.id)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.d83t.bpm.presentation.util

import android.view.View
import android.widget.ImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.databinding.BindingAdapter
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
Expand All @@ -9,6 +11,28 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.d83t.bpm.presentation.R
import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup
import org.joda.time.DateTime
import org.joda.time.Days
import org.joda.time.format.DateTimeFormat

@BindingAdapter("bind:visibility")
fun View.bindVisibleOrGone(isVisibleOrGone: Boolean?) {
visibility = if (isVisibleOrGone == true) {
View.VISIBLE
} else {
View.GONE
}
}

@BindingAdapter("bind:visibility")
fun View.bindVisibleOrGone(text: String?) {
visibility = if (!text.isNullOrEmpty()) {
View.VISIBLE
} else {
View.GONE
}
}


@BindingAdapter("bind:list_item")
fun RecyclerView.bindListItems(list: List<Any>?) {
Expand Down Expand Up @@ -40,3 +64,23 @@ fun ImageView.bindImageUrl(url: String?) {
.transition(DrawableTransitionOptions.withCrossFade())
.into(this)
}

@BindingAdapter("bind:home_user_schedule_date", "bind:home_user_schedule_time")
fun AppCompatTextView.bindHomeUserSchedule(dateString: String?, timeString: String?) {
if (dateString.isNullOrEmpty() || timeString.isNullOrEmpty() || dateString == "-" || timeString == "-") return
else {
val date = DateTime.parse(dateString, DateTimeFormat.forPattern("yyyy-MM-dd"))
val time = DateTime.parse(timeString, DateTimeFormat.forPattern("HH:mm:ss"))

text = "${date.toString("yyyy년 MM월 dd일 ")} ${time.getKoreanHour()}"
}
}

@BindingAdapter("bind:home_user_schedule_dday")
fun AppCompatTextView.bindHomeUserScheduleDday(dateString: String?) {
if (dateString.isNullOrEmpty() || dateString == "-") return
else {
val date = DateTime.parse(dateString, DateTimeFormat.forPattern("yyyy-MM-dd"))
text = "D${Days.daysBetween(date, DateTime.now()).days}"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,21 @@ package com.d83t.bpm.presentation.util

import android.content.res.Resources
import android.util.TypedValue
import org.joda.time.DateTime

val Int.dp: Int
get() {
val metrics = Resources.getSystem().displayMetrics
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), metrics)
.toInt()
}

fun DateTime.getKoreanHour(): String {
val nowHour = this.hourOfDay
return if (nowHour < 12) "오전 ${nowHour}"
else "오후 ${nowHour - 12}"
}

fun DateTime.getUserScheduleDate(): String {
return toString("yyyy.MM.dd") + " ${getKoreanHour()}"
}
Loading

0 comments on commit b647a1d

Please sign in to comment.