Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
86dc37c
Feat: 리플효과 제거 modifier 확장함수 정의
wjdrjs00 Jul 26, 2025
db583bf
Feat: 색상 추가 및 수정
wjdrjs00 Jul 27, 2025
55cd8e5
Feat: 리플효과 제거 modifier 확장함수 정의
wjdrjs00 Jul 26, 2025
b1ded46
Feat: 색상 추가 및 수정
wjdrjs00 Jul 27, 2025
bedd17e
Feat: BitnagilTextButton 공통 컴포넌트 추가
wjdrjs00 Jul 27, 2025
02e78eb
Feat: BitnagilSelectButton 공통 컴포넌트 추가
wjdrjs00 Jul 27, 2025
840f903
Feat: BitnagilIcon 공통 컴포넌트 추가
wjdrjs00 Jul 27, 2025
5db6ea8
Feat: BitnagilProgressBar 공통 컴포넌트 구현
wjdrjs00 Jul 27, 2025
f312261
Feat: BitnagilProgressTopBar 공통 컴포넌트 구현
wjdrjs00 Jul 27, 2025
c1b5fe9
Ui: 온보딩화면 공통컴포넌트 적용 및 ui 고도화
wjdrjs00 Jul 27, 2025
8047a3a
Ui: 아이콘 에셋 추가
wjdrjs00 Jul 27, 2025
4d1cbfe
Feat: BitnagilCheckBox 컴포넌트 추가
wjdrjs00 Jul 27, 2025
f06fbef
Merge branch 'ui/#45-common-component' of https://github.com/YAPP-Git…
wjdrjs00 Jul 27, 2025
d99c5e8
Feat: BitnagilOptionButton 공통 컴포넌트 추가
wjdrjs00 Jul 27, 2025
1ef8328
Ui: 마이페이지 및 설정 BitnagilOptionButton 컴포넌트 적용
wjdrjs00 Jul 27, 2025
906ea0e
Add: 해상도별 감정구슬 추가
wjdrjs00 Jul 27, 2025
be44f99
Feat: 감정 선택 화면 퍼브리싱 및 감정 아이콘 적용
wjdrjs00 Jul 27, 2025
dc53e98
Refactor: BitnagilIcon 컴포넌트 onClick 로직 제거
wjdrjs00 Jul 27, 2025
675f25c
Feat: 루틴 등록 화면 퍼블리싱
wjdrjs00 Jul 28, 2025
5df4bc0
Feat: BitnagilTopBar 공통 컴포넌트 추가
wjdrjs00 Jul 28, 2025
c965421
Feat: 약관동의 화면 퍼블리싱
wjdrjs00 Jul 28, 2025
c3b45c3
Feat: 추천루틴 화면 퍼블리싱
wjdrjs00 Jul 28, 2025
433f801
Feat: BitnagilFloatingButton 컴포넌트 추가
wjdrjs00 Jul 28, 2025
3044a5e
Feat: 쉐도우가 있는 감정구슬 컴포넌트 구현
wjdrjs00 Jul 28, 2025
33e01d6
Feat: 홈 화면 퍼블리싱
wjdrjs00 Jul 28, 2025
f5c77c8
Chore: ktlintFormat 적용
wjdrjs00 Jul 28, 2025
c5aea0f
Chore: clickable을 clickableWithoutRipple로 변경
wjdrjs00 Jul 28, 2025
ed0893d
Refactor: BitnagilOptionButton 컴포넌트 패딩 위치 변경
wjdrjs00 Jul 28, 2025
538e738
Chore: ktlintFormat 적용
wjdrjs00 Jul 28, 2025
30982d0
Feat: 추천 루틴 관련 응답 dto 모델 정의
wjdrjs00 Jul 29, 2025
c3c6f6c
Feat: 인트로 화면 캐릭터 그래픽 추가
wjdrjs00 Jul 29, 2025
9b61c0a
Feat: 온보딩 화면 캐릭터 그래픽 추가
wjdrjs00 Jul 29, 2025
f2900eb
Feat: BitnagilCheckBox 컴포저블 기능 추가
wjdrjs00 Jul 29, 2025
f3f1f14
Feat: BitnagilIconButton 컴포넌트 추가
wjdrjs00 Jul 29, 2025
78758dc
Feat: 추천 루틴 도메인 모델 정의
wjdrjs00 Jul 29, 2025
268ae06
Feat: dto -> domain 매핑 로직 추가
wjdrjs00 Jul 29, 2025
92b5515
Feat: 추천 루틴 조회 API 연동
wjdrjs00 Jul 29, 2025
902f368
Feat: 추천 루틴 UI 모델 및 매퍼 추가
wjdrjs00 Jul 29, 2025
e3771b7
Refactor: 추천루틴 도메인 모델 적용 및 관련 UI 로직 수정
wjdrjs00 Jul 29, 2025
9dac88f
Refactor: 추천 루틴 API 연동 및 ViewModel 로직 수정
wjdrjs00 Jul 29, 2025
11ecdba
Chore: ktlintFormat 적용
wjdrjs00 Jul 29, 2025
d2b73a4
Chore: 추천 루틴 설명 한 줄 초과 시 Ellipsis 처리
wjdrjs00 Jul 29, 2025
97cd2cb
Merge pull request #48 from YAPP-Github/ui/#45-common-component
wjdrjs00 Jul 29, 2025
b8dbc2c
Chore: ktlintFormat 적용
wjdrjs00 Jul 29, 2025
77a5a60
Fix: 추천 루틴 등록 시 루틴 id 타입 변경
wjdrjs00 Jul 29, 2025
01c02b6
Feat: 추천 루틴 관련 응답 dto 모델 정의
wjdrjs00 Jul 29, 2025
5751d46
Feat: 추천 루틴 도메인 모델 정의
wjdrjs00 Jul 29, 2025
31c555d
Feat: dto -> domain 매핑 로직 추가
wjdrjs00 Jul 29, 2025
378fa6b
Feat: 추천 루틴 조회 API 연동
wjdrjs00 Jul 29, 2025
f39cdd3
Feat: 추천 루틴 UI 모델 및 매퍼 추가
wjdrjs00 Jul 29, 2025
26b55d2
Refactor: 추천루틴 도메인 모델 적용 및 관련 UI 로직 수정
wjdrjs00 Jul 29, 2025
a15cdce
Refactor: 추천 루틴 API 연동 및 ViewModel 로직 수정
wjdrjs00 Jul 29, 2025
0e7a982
Chore: ktlintFormat 적용
wjdrjs00 Jul 29, 2025
3b8223b
Chore: 추천 루틴 설명 한 줄 초과 시 Ellipsis 처리
wjdrjs00 Jul 29, 2025
d8872c2
Chore: ktlintFormat 적용
wjdrjs00 Jul 29, 2025
443b720
Fix: 추천 루틴 등록 시 루틴 id 타입 변경
wjdrjs00 Jul 29, 2025
4d773ea
Chore: ktlintFormat 적용
wjdrjs00 Jul 29, 2025
1ed24bf
Merge branch 'feature/#50-recommend-routine-api' of https://github.co…
wjdrjs00 Jul 29, 2025
7d0f361
Chore: import문 제거
wjdrjs00 Jul 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import com.threegap.bitnagil.data.emotion.datasource.EmotionDataSource
import com.threegap.bitnagil.data.emotion.datasourceImpl.EmotionDataSourceImpl
import com.threegap.bitnagil.data.onboarding.datasource.OnBoardingDataSource
import com.threegap.bitnagil.data.onboarding.datasourceImpl.OnBoardingDataSourceImpl
import com.threegap.bitnagil.data.recommendroutine.datasource.RecommendRoutineDataSource
import com.threegap.bitnagil.data.recommendroutine.datasourceImpl.RecommendRoutineDataSourceImpl
import com.threegap.bitnagil.data.routine.datasource.RoutineRemoteDataSource
import com.threegap.bitnagil.data.routine.datasourceImpl.RoutineRemoteDataSourceImpl
import com.threegap.bitnagil.data.writeroutine.datasource.WriteRoutineDataSource
Expand Down Expand Up @@ -45,4 +47,8 @@ abstract class DataSourceModule {
@Binds
@Singleton
abstract fun bindWriteRoutineDataSource(writeRoutineDataSourceImpl: WriteRoutineDataSourceImpl): WriteRoutineDataSource

@Binds
@Singleton
abstract fun bindRecommendRoutineDataSource(recommendRoutineDataSourceImpl: RecommendRoutineDataSourceImpl): RecommendRoutineDataSource
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package com.threegap.bitnagil.di.data
import com.threegap.bitnagil.data.auth.repositoryimpl.AuthRepositoryImpl
import com.threegap.bitnagil.data.emotion.repositoryImpl.EmotionRepositoryImpl
import com.threegap.bitnagil.data.onboarding.repositoryImpl.OnBoardingRepositoryImpl
import com.threegap.bitnagil.data.recommendroutine.repositoryImpl.RecommendRoutineRepositoryImpl
import com.threegap.bitnagil.data.routine.repositoryImpl.RoutineRepositoryImpl
import com.threegap.bitnagil.data.writeroutine.repositoryImpl.WriteRoutineRepositoryImpl
import com.threegap.bitnagil.domain.auth.repository.AuthRepository
import com.threegap.bitnagil.domain.emotion.repository.EmotionRepository
import com.threegap.bitnagil.domain.onboarding.repository.OnBoardingRepository
import com.threegap.bitnagil.domain.recommendroutine.repository.RecommendRoutineRepository
import com.threegap.bitnagil.domain.routine.repository.RoutineRepository
import com.threegap.bitnagil.domain.writeroutine.repository.WriteRoutineRepository
import dagger.Binds
Expand Down Expand Up @@ -39,4 +41,8 @@ abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindWriteRoutineRepository(writeRoutineRepositoryImpl: WriteRoutineRepositoryImpl): WriteRoutineRepository

@Binds
@Singleton
abstract fun bindRecommendRoutineRepository(recommendRoutineRepositoryImpl: RecommendRoutineRepositoryImpl): RecommendRoutineRepository
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.threegap.bitnagil.di.data
import com.threegap.bitnagil.data.auth.service.AuthService
import com.threegap.bitnagil.data.emotion.service.EmotionService
import com.threegap.bitnagil.data.onboarding.service.OnBoardingService
import com.threegap.bitnagil.data.recommendroutine.service.RecommendRoutineService
import com.threegap.bitnagil.data.routine.service.RoutineService
import com.threegap.bitnagil.data.writeroutine.service.WriteRoutineService
import com.threegap.bitnagil.di.core.Auth
Expand Down Expand Up @@ -48,4 +49,9 @@ object ServiceModule {
@Singleton
fun provideReissueService(@NoneAuth retrofit: Retrofit): ReissueService =
retrofit.create(ReissueService::class.java)

@Provides
@Singleton
fun provideRecommendRoutineService(@Auth retrofit: Retrofit): RecommendRoutineService =
retrofit.create(RecommendRoutineService::class.java)
}
116 changes: 81 additions & 35 deletions app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,28 @@ package com.threegap.bitnagil.navigation.home
import android.annotation.SuppressLint
import android.app.Activity
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import com.threegap.bitnagil.designsystem.BitnagilTheme
import com.threegap.bitnagil.designsystem.R
import com.threegap.bitnagil.designsystem.component.atom.BitnagilFloatingActionMenu
import com.threegap.bitnagil.designsystem.component.atom.FloatingActionItem
import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple
import com.threegap.bitnagil.presentation.home.HomeScreenContainer
import com.threegap.bitnagil.presentation.mypage.MyPageScreenContainer
import com.threegap.bitnagil.presentation.recommendroutine.RecommendRoutineScreenContainer
Expand All @@ -31,48 +42,83 @@ fun HomeNavHost(
navigateToEmotion: () -> Unit,
) {
val navigator = rememberHomeNavigator()
var showFloatingOverlay by remember { mutableStateOf(false) }

DoubleBackButtonPressedHandler()

Scaffold(
modifier = Modifier.fillMaxSize(),
bottomBar = {
HomeBottomNavigationBar(navController = navigator.navController)
},
content = { _ ->
NavHost(
navController = navigator.navController,
startDestination = navigator.startDestination,
modifier = modifier,
) {
composable(HomeRoute.Home.route) {
HomeScreenContainer(
navigateToRegisterRoutine = {
navigateToRegisterRoutine(null)
},
navigateToEditRoutine = navigateToEditRoutine,
navigateToEmotion = navigateToEmotion,
)
}
Box(modifier = Modifier.fillMaxSize()) {
Scaffold(
modifier = Modifier.fillMaxSize(),
bottomBar = {
HomeBottomNavigationBar(navController = navigator.navController)
},
content = { _ ->
NavHost(
navController = navigator.navController,
startDestination = navigator.startDestination,
modifier = modifier,
) {
composable(HomeRoute.Home.route) {
HomeScreenContainer(
navigateToRegisterRoutine = {
navigateToRegisterRoutine(null)
},
navigateToEditRoutine = navigateToEditRoutine,
navigateToEmotion = navigateToEmotion,
)
}

composable(HomeRoute.RecommendRoutine.route) {
RecommendRoutineScreenContainer(
navigateToEmotion = navigateToEmotion,
navigateToRegisterRoutine = navigateToRegisterRoutine,
)
}
composable(HomeRoute.RecommendRoutine.route) {
RecommendRoutineScreenContainer(
navigateToEmotion = navigateToEmotion,
navigateToRegisterRoutine = navigateToRegisterRoutine,
)
}

composable(HomeRoute.MyPage.route) {
MyPageScreenContainer(
navigateToSetting = navigateToSetting,
navigateToOnBoarding = navigateToOnBoarding,
navigateToNotice = navigateToNotice,
navigateToQnA = navigateToQnA,
)
composable(HomeRoute.MyPage.route) {
MyPageScreenContainer(
navigateToSetting = navigateToSetting,
navigateToOnBoarding = navigateToOnBoarding,
navigateToNotice = navigateToNotice,
navigateToQnA = navigateToQnA,
)
}
}
},
)

if (navigator.shouldShowFloatingAction()) {
if (showFloatingOverlay) {
Box(
modifier = Modifier
.fillMaxSize()
.background(BitnagilTheme.colors.black.copy(alpha = 0.7f))
.clickableWithoutRipple { showFloatingOverlay = false },
)
}
},
)

BitnagilFloatingActionMenu(
actions = listOf(
FloatingActionItem(
icon = R.drawable.ic_report,
text = "제보하기",
onClick = {},
),
FloatingActionItem(
icon = R.drawable.ic_add_routine,
text = "루틴 등록",
onClick = { navigateToRegisterRoutine(null) },
),
),
isExpanded = showFloatingOverlay,
onToggle = { expanded -> showFloatingOverlay = expanded },
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(16.dp)
.padding(bottom = 80.dp),
)
}
}
}

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,24 @@ package com.threegap.bitnagil.navigation.home
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController

class HomeNavigator(
val navController: NavHostController,
) {
val startDestination = HomeRoute.Home.route

@Composable
fun getCurrentRoute(): String? {
return navController.currentBackStackEntryAsState().value?.destination?.route
}

@Composable
fun shouldShowFloatingAction(): Boolean {
val currentRoute = getCurrentRoute()
return currentRoute == HomeRoute.Home.route || currentRoute == HomeRoute.RecommendRoutine.route
}
}

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ data class BitnagilColors(
val emotionLonely: Color = EmotionLonely,
val emotionSad: Color = EmotionSad,
val emotionAnxiety: Color = EmotionAnxiety,
val progressBarGradientStartColor: Color = ProgressBarGradientStartColor,
val progressBarGradientEndColor: Color = ProgressBarGradientEndColor,
val homeGradientStartColor: Color = HomeGradientStartColor,
val homeGradientEndColor: Color = HomeGradientEndColor,
val coolGray99: Color = CoolGray99,
val coolGray98: Color = CoolGray98,
val coolGray97: Color = CoolGray97,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ val EmotionLethargy = Color(0xFFFFC0A1)
val EmotionLonely = Color(0xFFC8C1DE)
val EmotionSad = Color(0xFFA9B9FF)
val EmotionAnxiety = Color(0xFF96D8AD)
val ProgressBarGradientStartColor = Color(0xFFA9CFFF)
val ProgressBarGradientEndColor = Color(0xFFFFCDB3)
val HomeGradientStartColor = Color(0xFFFFEADF)
val HomeGradientEndColor = Color(0xFFF0F7FF)

val CoolGray99 = Color(0xFFF7F7F8)
val CoolGray98 = Color(0xFFF4F4F5)
Expand All @@ -26,7 +30,7 @@ val CoolGray40 = Color(0xFF5A5C63)
val CoolGray30 = Color(0xFF46474C)
val CoolGray20 = Color(0xFF292A2D)
val CoolGray10 = Color(0xFF171719)
val CoolGray7 = Color(0xFF0F0F10)
val CoolGray7 = Color(0xFF141415)
val CoolGray5 = Color(0xFF0F0F10)

val Navy900 = Color(0xFF050B1B)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.threegap.bitnagil.designsystem.component.atom

import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.threegap.bitnagil.designsystem.BitnagilTheme
import com.threegap.bitnagil.designsystem.R
import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple

@Composable
fun BitnagilCheckBox(
checked: Boolean,
modifier: Modifier = Modifier,
onCheckedChange: ((Boolean) -> Unit)? = null,
colors: BitnagilCheckBoxColor = BitnagilCheckBoxColor.terms(),
) {
val iconColor = if (checked) colors.checkedColor else colors.uncheckedColor

Box(
modifier = modifier
.let {
if (onCheckedChange != null) {
it.clickableWithoutRipple { onCheckedChange(!checked) }
} else {
it
}
}
.background(
color = BitnagilTheme.colors.white,
shape = RoundedCornerShape(6.dp),
),
contentAlignment = Alignment.Center,
) {
Image(
imageVector = ImageVector.vectorResource(R.drawable.ic_check),
contentDescription = null,
colorFilter = ColorFilter.tint(iconColor),
modifier = modifier.size(24.dp),
)
}
}

data class BitnagilCheckBoxColor(
val uncheckedColor: Color,
val checkedColor: Color,
) {
companion object {
@Composable
fun terms(): BitnagilCheckBoxColor = BitnagilCheckBoxColor(
uncheckedColor = BitnagilTheme.colors.navy50,
checkedColor = BitnagilTheme.colors.navy500,
)
}
}

@Preview
@Composable
private fun BitnagilCheckBoxPreview() {
var checked by remember { mutableStateOf(false) }
BitnagilCheckBox(
checked = checked,
onCheckedChange = { checked = !checked },
)
}
Loading