Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.tooling.preview.Preview
Expand Down Expand Up @@ -59,11 +58,7 @@ fun BitnagilProgressBar(
if (animatedProgress > 0) {
val progressEndX = size.width * animatedProgress
drawLine(
brush = Brush.horizontalGradient(
colors = listOf(color.gradientStartColor, color.gradientEndColor),
startX = 0f,
endX = progressEndX,
),
color = color.progressColor,
start = Offset(0f, size.height / 2),
end = Offset(progressEndX, size.height / 2),
strokeWidth = strokeWidth,
Expand All @@ -75,16 +70,14 @@ fun BitnagilProgressBar(

@Immutable
data class BitnagilProgressBarColor(
val gradientStartColor: Color,
val gradientEndColor: Color,
val progressColor: Color,
val backgroundColor: Color,
) {
companion object {
@Composable
fun default(): BitnagilProgressBarColor = BitnagilProgressBarColor(
gradientStartColor = BitnagilTheme.colors.progressBarGradientStartColor,
gradientEndColor = BitnagilTheme.colors.progressBarGradientEndColor,
backgroundColor = BitnagilTheme.colors.white,
progressColor = BitnagilTheme.colors.orange500,
backgroundColor = BitnagilTheme.colors.coolGray97,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ fun BitnagilProgressTopBar(
progress: Float,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
showProgress: Boolean,
) {
Row(
modifier = modifier
Expand All @@ -35,10 +36,12 @@ fun BitnagilProgressTopBar(
tint = BitnagilTheme.colors.coolGray10,
)

BitnagilProgressBar(
progress = progress,
modifier = Modifier,
)
if (showProgress) {
BitnagilProgressBar(
progress = progress,
modifier = Modifier,
)
}
}
}

Expand All @@ -48,5 +51,6 @@ private fun BitnagilProgressTopBarPreview() {
BitnagilProgressTopBar(
progress = 1f,
onBackClick = {},
showProgress = true,
)
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import com.threegap.bitnagil.data.onboarding.model.dto.OnBoardingAbstractDto
import com.threegap.bitnagil.data.onboarding.model.dto.OnBoardingDto
import com.threegap.bitnagil.data.onboarding.model.request.GetOnBoardingRecommendRoutinesRequest
import com.threegap.bitnagil.data.onboarding.model.response.GetOnBoardingRecommendRoutinesResponse
import com.threegap.bitnagil.data.onboarding.model.response.GetUserOnBoardingResponse

interface OnBoardingDataSource {
suspend fun getOnBoardingList(): List<OnBoardingDto>
suspend fun getOnBoardingRecommendRoutines(request: GetOnBoardingRecommendRoutinesRequest): Result<GetOnBoardingRecommendRoutinesResponse>
suspend fun getOnBoardingAbstract(selectedOnBoardingItemIdList: List<Pair<String, List<String>>>): OnBoardingAbstractDto
suspend fun registerRecommendRoutineList(selectedRecommendRoutineIds: List<Int>): Result<Unit>
suspend fun getUserOnBoarding(): Result<GetUserOnBoardingResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.threegap.bitnagil.data.onboarding.model.dto.OnBoardingItemDto
import com.threegap.bitnagil.data.onboarding.model.request.GetOnBoardingRecommendRoutinesRequest
import com.threegap.bitnagil.data.onboarding.model.request.RegisterOnBoardingRecommendRoutinesRequest
import com.threegap.bitnagil.data.onboarding.model.response.GetOnBoardingRecommendRoutinesResponse
import com.threegap.bitnagil.data.onboarding.model.response.GetUserOnBoardingResponse
import com.threegap.bitnagil.data.onboarding.service.OnBoardingService
import javax.inject.Inject

Expand Down Expand Up @@ -57,6 +58,12 @@ class OnBoardingDataSourceImpl @Inject constructor(
}
}

override suspend fun getUserOnBoarding(): Result<GetUserOnBoardingResponse> {
return safeApiCall {
onBoardingService.getOnBoarding()
}
}

private fun getOnBoardingAbstractText(onBoardingId: String, selectedOnBoardingDetailIdList: List<String>): OnBoardingAbstractTextDto? {
if (selectedOnBoardingDetailIdList.isEmpty()) return null
val onBoarding = onBoardingDtoList.find { it.id == onBoardingId }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ data class GetOnBoardingRecommendRoutinesRequest(
@SerialName("timeSlot")
val timeSlot: String,
@SerialName("emotionType")
val emotionType: String,
val emotionType: List<String>,
@SerialName("realOutingFrequency")
val realOutingFrequency: String,
@SerialName("targetOutingFrequency")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.threegap.bitnagil.data.onboarding.model.response

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

@Serializable
data class GetUserOnBoardingResponse(
@SerialName("timeSlot")
val timeSlot: String,
@SerialName("emotionTypes")
val emotionTypes: List<String>,
@SerialName("targetOutingFrequency")
val targetOutingFrequency: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ class OnBoardingRepositoryImpl @Inject constructor(
selectedItemIdsWithOnBoardingId: List<Pair<String, List<String>>>,
): Result<List<OnBoardingRecommendRoutine>> {
val timeSlot = selectedItemIdsWithOnBoardingId.find { it.first == OnBoardingDto.TimeSlot.id }?.second?.first()
val emotionType = selectedItemIdsWithOnBoardingId.find { it.first == OnBoardingDto.EmotionType.id }?.second?.first()
val emotionType = selectedItemIdsWithOnBoardingId.find { it.first == OnBoardingDto.EmotionType.id }?.second
val realOutingFrequency = selectedItemIdsWithOnBoardingId.find { it.first == OnBoardingDto.RealOutingFrequency.id }?.second?.first()
val targetOutingFrequency = selectedItemIdsWithOnBoardingId.find { it.first == OnBoardingDto.TargetOutingFrequency.id }?.second?.first()

val request = GetOnBoardingRecommendRoutinesRequest(
timeSlot = timeSlot ?: "",
emotionType = emotionType ?: "",
emotionType = emotionType ?: listOf(),
realOutingFrequency = realOutingFrequency ?: "",
targetOutingFrequency = targetOutingFrequency ?: "",
)
Expand All @@ -64,6 +64,16 @@ class OnBoardingRepositoryImpl @Inject constructor(
}
}

override suspend fun getUserOnBoarding(): Result<List<Pair<String, List<String>>>> {
return onBoardingDataSource.getUserOnBoarding().map {
listOf(
OnBoardingDto.TimeSlot.id to listOf(it.timeSlot),
OnBoardingDto.EmotionType.id to it.emotionTypes,
OnBoardingDto.TargetOutingFrequency.id to listOf(it.targetOutingFrequency),
)
}
}

private val _onBoardingRecommendRoutineEventFlow = MutableSharedFlow<OnBoardingRecommendRoutineEvent>(
extraBufferCapacity = 1,
onBufferOverflow = BufferOverflow.DROP_OLDEST,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@ package com.threegap.bitnagil.data.onboarding.service
import com.threegap.bitnagil.data.onboarding.model.request.GetOnBoardingRecommendRoutinesRequest
import com.threegap.bitnagil.data.onboarding.model.request.RegisterOnBoardingRecommendRoutinesRequest
import com.threegap.bitnagil.data.onboarding.model.response.GetOnBoardingRecommendRoutinesResponse
import com.threegap.bitnagil.data.onboarding.model.response.GetUserOnBoardingResponse
import com.threegap.bitnagil.network.model.BaseResponse
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST

interface OnBoardingService {
@POST("/api/v1/onboardings")
@POST("/api/v2/onboardings")
suspend fun postOnBoarding(
@Body onBoardingRecommendRoutinesRequest: GetOnBoardingRecommendRoutinesRequest,
): BaseResponse<GetOnBoardingRecommendRoutinesResponse>

@POST("/api/v1/onboardings/routines")
@POST("/api/v2/onboardings/routines")
suspend fun postOnBoardingRoutines(
@Body registerOnBoardingRecommendRoutinesRequest: RegisterOnBoardingRecommendRoutinesRequest,
): BaseResponse<Unit>

@GET("/api/v2/onboardings")
suspend fun getOnBoarding(): BaseResponse<GetUserOnBoardingResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ interface OnBoardingRepository {
suspend fun getRecommendOnBoardingRouteList(selectedItemIdsWithOnBoardingId: List<Pair<String, List<String>>>): Result<List<OnBoardingRecommendRoutine>>
suspend fun registerRecommendRoutineList(selectedRecommendRoutineIds: List<String>): Result<Unit>
suspend fun getOnBoardingRecommendRoutineEventFlow(): Flow<OnBoardingRecommendRoutineEvent>
suspend fun getUserOnBoarding(): Result<List<Pair<String, List<String>>>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.threegap.bitnagil.domain.onboarding.usecase

import com.threegap.bitnagil.domain.onboarding.repository.OnBoardingRepository
import javax.inject.Inject

class GetUserOnBoardingUseCase @Inject constructor(
private val onBoardingRepository: OnBoardingRepository,
) {
suspend operator fun invoke(): Result<List<Pair<String, List<String>>>> {
return onBoardingRepository.getUserOnBoarding()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.threegap.bitnagil.presentation.common.ninepatch

import android.graphics.drawable.NinePatchDrawable
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.platform.LocalContext
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.updateBounds

@Composable
fun Modifier.ninePatchBackgroundNode(drawableResId: Int): Modifier {
val context = LocalContext.current
val ninePatchDrawable = remember(drawableResId) {
ContextCompat.getDrawable(context, drawableResId) as? NinePatchDrawable
}

return if (ninePatchDrawable != null) {
this.then(
Modifier.drawBehind {
ninePatchDrawable.updateBounds(0, 0, size.width.toInt(), size.height.toInt())
ninePatchDrawable.draw(drawContext.canvas.nativeCanvas)
},
)
} else {
this
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import androidx.hilt.navigation.compose.hiltViewModel
import com.threegap.bitnagil.designsystem.BitnagilTheme
import com.threegap.bitnagil.designsystem.component.block.BitnagilProgressTopBar
import com.threegap.bitnagil.presentation.common.flow.collectAsEffect
import com.threegap.bitnagil.presentation.common.toast.GlobalBitnagilToast
import com.threegap.bitnagil.presentation.onboarding.component.template.OnBoardingAbstractTemplate
import com.threegap.bitnagil.presentation.onboarding.component.template.OnBoardingIntroTemplate
import com.threegap.bitnagil.presentation.onboarding.component.template.OnBoardingSelectTemplate
import com.threegap.bitnagil.presentation.onboarding.model.OnBoardingItem
import com.threegap.bitnagil.presentation.onboarding.model.OnBoardingPageInfo
Expand All @@ -37,12 +39,17 @@ fun OnBoardingScreenContainer(
OnBoardingSideEffect.NavigateToHomeScreen -> {
navigateToHome()
}

is OnBoardingSideEffect.ShowToast -> {
GlobalBitnagilToast.showWarning(sideEffect.message)
}
}
}

OnBoardingScreen(
state = state,
onClickNext = onBoardingViewModel::selectNext,
onClickLoadOnBoarding = onBoardingViewModel::loadOnBoardingItems,
onClickPreviousInSelectOnBoarding = onBoardingViewModel::selectPrevious,
onClickItem = onBoardingViewModel::selectItem,
onClickRoutine = onBoardingViewModel::selectRoutine,
Expand All @@ -57,6 +64,7 @@ fun OnBoardingScreenContainer(
private fun OnBoardingScreen(
state: OnBoardingState,
onClickNext: () -> Unit,
onClickLoadOnBoarding: () -> Unit,
onClickPreviousInSelectOnBoarding: () -> Unit,
onClickItem: (String) -> Unit,
onClickRoutine: (String) -> Unit,
Expand All @@ -67,24 +75,36 @@ private fun OnBoardingScreen(
) {
Column(
modifier = Modifier
.background(BitnagilTheme.colors.coolGray99)
.background(BitnagilTheme.colors.white)
.statusBarsPadding(),
) {
BitnagilProgressTopBar(
onBackClick = onClickPreviousInSelectOnBoarding,
progress = state.progress,
)
if (!state.hideToolbar) {
BitnagilProgressTopBar(
modifier = Modifier,
onBackClick = onClickPreviousInSelectOnBoarding,
progress = state.progress,
showProgress = state.showProgress,
)
}

when (state) {
is OnBoardingState.Idle -> {
when (val currentOnBoardingPageInfo = state.currentOnBoardingPageInfo) {
OnBoardingPageInfo.Intro -> {
OnBoardingIntroTemplate(
userName = state.userName,
onClickNextButton = onClickLoadOnBoarding,
)
}
is OnBoardingPageInfo.Abstract -> {
OnBoardingAbstractTemplate(
modifier = Modifier.weight(1f),
title = "이제 당신에게\n꼭 맞는 루틴을 제안해드릴게요.",
onInit = loadRecommendRoutines,
title = "이제 포모가 당신에게\n꼭 맞는 루틴을 찾아줄거에요.",
onBoardingAbstractTexts = currentOnBoardingPageInfo.abstractTexts,
onDispose = cancelRecommendRoutines,
onClickNextButton = loadRecommendRoutines,
nextButtonEnable = state.nextButtonEnable,
userName = state.userName,
)
}
is OnBoardingPageInfo.RecommendRoutines -> {
Expand All @@ -95,11 +115,7 @@ private fun OnBoardingScreen(
items = currentOnBoardingPageInfo.routines,
nextButtonEnable = state.nextButtonEnable,
onClickNextButton = onClickRegister,
onClickItem = if (state.onBoardingSetType.canSelectRoutine) {
onClickRoutine
} else {
null
},
onClickItem = onClickRoutine,
onClickSkip = if (state.onBoardingSetType.canSkip) {
onClickSkip
} else {
Expand All @@ -118,6 +134,18 @@ private fun OnBoardingScreen(
onClickItem = onClickItem,
)
}

is OnBoardingPageInfo.ExistedOnBoardingAbstract -> {
OnBoardingAbstractTemplate(
modifier = Modifier.weight(1f),
title = "이전에 설정한 목표예요!\n변경하시겠어요?",
onBoardingAbstractTexts = currentOnBoardingPageInfo.abstractTexts,
onDispose = cancelRecommendRoutines,
onClickNextButton = onClickLoadOnBoarding,
nextButtonEnable = true,
userName = state.userName,
)
}
}
}
OnBoardingState.Loading -> {
Expand All @@ -141,8 +169,10 @@ fun OnBoardingScreenPreview() {
totalStep = 5,
currentStep = 1,
onBoardingSetType = OnBoardingSetType.RESET,
userName = "안드로이드",
),
onClickNext = {},
onClickLoadOnBoarding = {},
onClickPreviousInSelectOnBoarding = {},
onClickItem = {},
onClickRoutine = {},
Expand Down
Loading