Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#176 [ui] 루틴 추가하기 - 리스트 뷰 #177

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
3 changes: 3 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ dependencies {

// Coroutine
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3")

// Tool Tip
implementation("com.github.skydoves:balloon:1.6.5")
}

fun getApiKey(propertyKey: String): String {
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@
</intent-filter>
</activity>

<activity
android:name=".ui.addroutine.list.AddRoutineActivity"
android:exported="false"
android:screenOrientation="portrait" />

<activity
android:name=".ui.happyroutine.list.HappyAddListActivity"
android:exported="false"
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/java/com/sopetit/softie/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import com.sopetit.softie.data.repositoryImpl.MemberHappinessRoutineRepositoryIm
import com.sopetit.softie.data.repositoryImpl.MemberRepositoryImpl
import com.sopetit.softie.data.repositoryImpl.RefreshTokenRepositoryImpl
import com.sopetit.softie.data.repositoryImpl.VersionRepositoryImpl
import com.sopetit.softie.domain.repository.AddRoutineRepository
import com.sopetit.softie.domain.repository.AuthRepository
import com.sopetit.softie.domain.repository.DailyRoutineRepository
import com.sopetit.softie.domain.repository.DollRepository
import com.sopetit.softie.domain.repository.HappinessRoutineRepository
import com.sopetit.softie.domain.repository.MemberHappinessRoutineRepository
import com.sopetit.softie.domain.repository.MemberRepository
import com.sopetit.softie.domain.repository.MockAddRoutineRepository
import com.sopetit.softie.domain.repository.RefreshTokenRepository
import com.sopetit.softie.domain.repository.VersionRepository
import dagger.Binds
Expand Down Expand Up @@ -55,6 +57,12 @@ abstract class RepositoryModule {
memberHappinessRoutineRepositoryImpl: MemberHappinessRoutineRepositoryImpl
): MemberHappinessRoutineRepository

@Binds
@Singleton
abstract fun bindAddRoutineRepository(
mockAddRoutineRepository: MockAddRoutineRepository
): AddRoutineRepository

@Binds
@Singleton
abstract fun bindToAuthRepository(
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/com/sopetit/softie/domain/entity/MakerCard.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.sopetit.softie.domain.entity

data class MakerCard(
val artistId: Int,
val artistImageUrl: String,
val subTitle: String,
val title: String,
val hashtag: List<Hashtag>
) {
data class Hashtag(
val hashtagId: Int,
val content: String,
)
}
12 changes: 12 additions & 0 deletions app/src/main/java/com/sopetit/softie/domain/entity/RoutineTheme.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.sopetit.softie.domain.entity

data class RoutineTheme(
val themes: List<Themes>
) {
data class Themes(
val themeId: Int,
val modifier: String,
val name: String,
val description: String,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.sopetit.softie.domain.repository

import com.sopetit.softie.domain.entity.MakerCard
import com.sopetit.softie.domain.entity.RoutineTheme

interface AddRoutineRepository {
suspend fun getMakerCard(): Result<List<MakerCard>>
suspend fun getRoutineTheme(): Result<RoutineTheme>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.sopetit.softie.domain.repository

import com.sopetit.softie.domain.entity.MakerCard
import com.sopetit.softie.domain.entity.RoutineTheme
import javax.inject.Inject

class MockAddRoutineRepository @Inject constructor() : AddRoutineRepository {
override suspend fun getMakerCard(): Result<List<MakerCard>> {
return Result.success(
listOf(
MakerCard(
artistId = 1,
artistImageUrl = "https://img.etoday.co.kr/pto_db/2024/04/600/20240426132100_2017673_647_863.jpeg",
subTitle = "하이브의 주인은 누구?",
title = "뉴진스가 돌아왔다",
hashtag = listOf(
MakerCard.Hashtag(hashtagId = 1, content = "#민희진"),
MakerCard.Hashtag(hashtagId = 2, content = "#방시혁"),
MakerCard.Hashtag(hashtagId = 2, content = "#하이브")
)
),
MakerCard(
artistId = 2,
artistImageUrl = "https://cdn.hankyung.com/photo/202211/BF.23427209.1.jpg",
subTitle = "더이상 웹툰작가로는 못산다",
title = "침착맨의 시크릿",
hashtag = listOf(
MakerCard.Hashtag(hashtagId = 3, content = "#침착침착"),
MakerCard.Hashtag(hashtagId = 4, content = "#이말년")
)
),
MakerCard(
artistId = 3,
artistImageUrl = "https://res.heraldm.com/content/image/2024/05/06/20240506050023_0.jpg",
subTitle = "선재업고 얼마나 뛸 수 있어?",
title = "변우석의 성공담",
hashtag = listOf(
MakerCard.Hashtag(hashtagId = 5, content = "#류선재"),
MakerCard.Hashtag(hashtagId = 6, content = "#드라마")
)
)
)
)
}

override suspend fun getRoutineTheme(): Result<RoutineTheme> {
return Result.success(
RoutineTheme(
themes = listOf(
RoutineTheme.Themes(
themeId = 1,
modifier = "사람들과 어울리는",
name = "관계 쌓기",
description = "설명"
),
RoutineTheme.Themes(
themeId = 2,
modifier = "나를 돌보는",
name = "마음 챙김",
description = "설명2"
),
RoutineTheme.Themes(
themeId = 3,
modifier = "경제적으로 살아가는",
name = "통통한 통장",
description = "설명2"
),
RoutineTheme.Themes(
themeId = 4,
modifier = "하루를 상쾌하게",
name = "산뜻한 일상",
description = "설명2"
),
RoutineTheme.Themes(
themeId = 5,
modifier = "더 나은 나를 위해",
name = "한 걸음 성장",
description = "설명2"
),
RoutineTheme.Themes(
themeId = 6,
modifier = "튼튼하게 건강하게",
name = "건강한 몸",
description = "설명2"
),
RoutineTheme.Themes(
themeId = 7,
modifier = "튼튼하게 건강하게",
name = "나와 친해지기",
description = "설명2"
)
)
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.sopetit.softie.domain.usecase.addroutine

import com.sopetit.softie.domain.entity.MakerCard
import com.sopetit.softie.domain.repository.AddRoutineRepository
import javax.inject.Inject

class GetMakerCardUseCase @Inject constructor(
private val addRoutineRepository: AddRoutineRepository
) {
suspend operator fun invoke(): Result<List<MakerCard>> {
return addRoutineRepository.getMakerCard()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.sopetit.softie.domain.usecase.addroutine

import com.sopetit.softie.domain.entity.RoutineTheme
import com.sopetit.softie.domain.repository.AddRoutineRepository
import javax.inject.Inject

class GetRoutineThemeListUseCase @Inject constructor(
private val addRoutineRepository: AddRoutineRepository
) {
suspend operator fun invoke(): Result<RoutineTheme> {
return try {
val result = addRoutineRepository.getRoutineTheme()
result
} catch (e: Exception) {
Result.failure(e)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.sopetit.softie.ui.addroutine.list

import android.os.Bundle
import android.view.View
import android.widget.ImageView
import androidx.activity.viewModels
import com.skydoves.balloon.createBalloon
import com.skydoves.balloon.overlay.BalloonOverlayAnimation
import com.skydoves.balloon.overlay.BalloonOverlayCircle
import com.sopetit.softie.R
import com.sopetit.softie.databinding.ActivityAddRoutineListBinding
import com.sopetit.softie.util.HorizontalItemDecoration
import com.sopetit.softie.util.VerticalItemDecoration
import com.sopetit.softie.util.binding.BindingActivity
import com.sopetit.softie.util.setSingleOnClickListener
import com.sopetit.softie.util.setStatusBarColorFromResource
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class AddRoutineActivity : BindingActivity<ActivityAddRoutineListBinding>(R.layout.activity_add_routine_list) {
private val makerCardPagerAdapter = MakerCardAdapter()
private val viewModel by viewModels<AddRoutineViewModel>()
private var routineThemeListAdapter: RoutineThemeListAdapter? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.viewModel = viewModel
setStatusBarColorFromResource(R.color.background)

startMakerTooltipModal()
setBackEnter()
setInitBinding()
setAddRoutineListCardPagerAdapter()
setRoutineThemeListAdapter()
setItemDeco()
setupUI()
setupObservers()
}

private fun startMakerTooltipModal() {
binding.ivAddRoutineListMakerHelp.setSingleOnClickListener { view ->
showTooltip(view)
}
}

private fun showTooltip(anchor: View) {
val balloon =
createBalloon(this) {
setLayout(R.layout.tooltip_maker_help)
setBackgroundDrawableResource(R.drawable.shape_gray0_fill_10_rect)
setIsVisibleArrow(false)
setDismissWhenClicked(false)
setIsVisibleOverlay(true)
setOverlayShape(BalloonOverlayCircle(radius = 0f))
setOverlayColorResource(R.color.gray950)
setBalloonOverlayAnimation(BalloonOverlayAnimation.FADE)
setDismissWhenOverlayClicked(false)
setLifecycleOwner(lifecycleOwner)
}

balloon.setOnBalloonInitializedListener { view ->
view.findViewById<ImageView>(R.id.iv_maker_help_tooltip_exit)?.setOnClickListener {
balloon.dismiss()
}
}

balloon.showAlignBottom(anchor)
}

private fun setBackEnter() {
binding.ivAddRoutineListBackArrow.setSingleOnClickListener {
finish()
}
}

private fun setInitBinding() {
viewModel.getMakerCard()
viewModel.getRoutineTheme()
}

private fun setAddRoutineListCardPagerAdapter() {
with(binding) {
rvAddRoutineListMakerCard.adapter = makerCardPagerAdapter
}
}

private fun setRoutineThemeListAdapter() {
with(binding) {
routineThemeListAdapter = RoutineThemeListAdapter()
rvAddList.adapter = routineThemeListAdapter
}
}

private fun setItemDeco() {
val horizontalDecoration =
HorizontalItemDecoration(
context = this,
firstItemMargin = R.dimen.maker_recycler_view_first_margin,
itemMargin = R.dimen.maker_recycler_view_margin
)
val verticalDecoration =
VerticalItemDecoration(
context = this,
firstItemMargin = R.dimen.add_routine_recycler_view_first_margin,
itemMargin = R.dimen.add_routine_recycler_view_margin
)
binding.rvAddRoutineListMakerCard.addItemDecoration(horizontalDecoration)
binding.rvAddList.addItemDecoration(verticalDecoration)
}

private fun setupUI() {
binding.ivAddRoutineListMakerHelp.setOnClickListener {
showTooltip(it)
}
}

private fun setupObservers() {
viewModel.addRoutineThemeListResponse.observe(this) { routineTheme ->
routineTheme?.let {
routineThemeListAdapter?.submitList(routineTheme.themes)
}
}

viewModel.addMakerCardResponse.observe(this) { makerCards ->
makerCards?.let {
makerCardPagerAdapter.submitList(makerCards)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.sopetit.softie.ui.addroutine.list

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sopetit.softie.domain.entity.MakerCard
import com.sopetit.softie.domain.entity.RoutineTheme
import com.sopetit.softie.domain.usecase.addroutine.GetMakerCardUseCase
import com.sopetit.softie.domain.usecase.addroutine.GetRoutineThemeListUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject

@HiltViewModel
class AddRoutineViewModel @Inject constructor(
private val getMakerCardUseCase: GetMakerCardUseCase,
private val getRoutineThemeListUseCase: GetRoutineThemeListUseCase
) : ViewModel() {
private val _addMakerCardResponse = MutableLiveData<List<MakerCard>>()
val addMakerCardResponse: LiveData<List<MakerCard>> get() = _addMakerCardResponse

private val _addRoutineThemeListResponse = MutableLiveData<RoutineTheme>()
val addRoutineThemeListResponse: LiveData<RoutineTheme> get() = _addRoutineThemeListResponse

fun getMakerCard() {
viewModelScope.launch {
getMakerCardUseCase()
.onSuccess { response ->
_addMakerCardResponse.value = response
}
.onFailure { throwable ->
Timber.e("$throwable")
}
}
}

fun getRoutineTheme() {
viewModelScope.launch {
val result = getRoutineThemeListUseCase()

result.onSuccess { response ->
_addRoutineThemeListResponse.value = response
}.onFailure { throwable ->
Timber.e("$throwable")
}
}
}
}
Loading
Loading