diff --git a/data/src/main/java/com/whyranoid/data/model/challenge/ChallengeDetailResponse.kt b/data/src/main/java/com/whyranoid/data/model/challenge/ChallengeDetailResponse.kt index 57206753..877bcfa7 100644 --- a/data/src/main/java/com/whyranoid/data/model/challenge/ChallengeDetailResponse.kt +++ b/data/src/main/java/com/whyranoid/data/model/challenge/ChallengeDetailResponse.kt @@ -10,6 +10,7 @@ data class ChallengeDetailResponse( val participants = walkies.map { it.toUser() } return com.whyranoid.domain.model.challenge.Challenge( badge = challenge.badge.toBadge(), + calorie = challenge.calorie, challengeType = ChallengeType.getChallengeTypeByString(challenge.category), id = challenge.challengeId.toLong(), contents = challenge.content, @@ -18,6 +19,11 @@ data class ChallengeDetailResponse( process = challenge.progress, participants = participants, participantCount = participants.size, + period = challenge.period, + distance = challenge.distance, + endTime = challenge.endTime, + startTime = challenge.startTime, + status = challenge.status ) } } \ No newline at end of file diff --git a/data/src/main/java/com/whyranoid/data/model/challenge/ChallengeFromServer.kt b/data/src/main/java/com/whyranoid/data/model/challenge/ChallengeFromServer.kt index f2e79bc4..dcfd4fe7 100644 --- a/data/src/main/java/com/whyranoid/data/model/challenge/ChallengeFromServer.kt +++ b/data/src/main/java/com/whyranoid/data/model/challenge/ChallengeFromServer.kt @@ -2,11 +2,16 @@ package com.whyranoid.data.model.challenge data class ChallengeFromServer( val badge: BadgeResponse, + val calorie: Int?, val category: String, val challengeId: Int, val content: String, + val distance: Int?, + val endTime: String, val img: String, val name: String, - val progress: Int?, - val status: String? + val period: Int?, + val progress: Int, + val startTime: String, + val status: String ) \ No newline at end of file diff --git a/domain/src/main/java/com/whyranoid/domain/model/challenge/Challenge.kt b/domain/src/main/java/com/whyranoid/domain/model/challenge/Challenge.kt index 956625ec..b0eb667c 100644 --- a/domain/src/main/java/com/whyranoid/domain/model/challenge/Challenge.kt +++ b/domain/src/main/java/com/whyranoid/domain/model/challenge/Challenge.kt @@ -13,26 +13,9 @@ data class Challenge( val participantCount: Int, val participants: List, val process: Int? = null, -) { - companion object { - - val DUMMY = Challenge( - id = 1, - imageUrl = "https://picsum.photos/250/250", - title = "햄버거 세트 불태우기", - contents = "햄버거 세트의 평균 칼로리는 1110kcal 에요.\n" + - "일주일 동안 걷기로 햄버거 세트 태우기 도전!", - period = 7, - challengeType = ChallengeType.values().toList().shuffled().first(), - badge = Badge( - id = 1, - name = "햄버거", - imageUrl = "https://picsum.photos/250/250", - ), - - participantCount = 12, - participants = List(12) { User.DUMMY}, - process = (0..100).random(), - ) - } -} + val calorie: Int? = null, + val distance: Int? = null, + val endTime: String, + val startTime: String, + val status: String? = null +) diff --git a/presentation/src/main/java/com/whyranoid/presentation/component/ChallengeGoalContent.kt b/presentation/src/main/java/com/whyranoid/presentation/component/ChallengeGoalContent.kt index 21d394e7..0f2a3758 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/component/ChallengeGoalContent.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/component/ChallengeGoalContent.kt @@ -25,7 +25,6 @@ import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.ExperimentalTextApi import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.drawText import androidx.compose.ui.text.rememberTextMeasurer @@ -36,10 +35,10 @@ import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.whyranoid.domain.model.challenge.Challenge +import com.whyranoid.domain.model.challenge.ChallengeType import com.whyranoid.presentation.R import com.whyranoid.presentation.theme.ChallengeColor.getColor -@OptIn(ExperimentalTextApi::class) @Composable fun ChallengeGoalContent( challenge: Challenge @@ -153,10 +152,30 @@ fun ChallengeGoalContent( horizontalArrangement = Arrangement.SpaceEvenly, verticalAlignment = Alignment.CenterVertically ) { - ChallengeGoalItem( - modifier = Modifier.weight(1f), - goal = "기간", limit = "${challenge.period}일" - ) + when (challenge.challengeType) { + ChallengeType.LIFE -> { + ChallengeGoalItem( + modifier = Modifier.weight(1f), + // TODO : limit에 적합한 값 필요(새로운 필드) + // TODO : time 포멧 변경 + goal = "${challenge.startTime}~${challenge.endTime}시 사이", limit = challenge.period.toString() + ) + } + ChallengeType.CALORIE -> { + ChallengeGoalItem( + modifier = Modifier.weight(1f), + // TODO: 정확한 형식 필요, ex) 20일 + goal = "기간", limit = challenge.period.toString() + ) + } + ChallengeType.DISTANCE -> { + ChallengeGoalItem( + modifier = Modifier.weight(1f), + // TODO: 텍스트 꾸미기 적용 필요 + goal = "거리", limit = "0/${challenge.distance}km" + ) + } + } Divider( color = challengeColor.progressBarColor, @@ -165,10 +184,9 @@ fun ChallengeGoalContent( .width(1.dp) ) - // TODO: challenge type ChallengeGoalItem( modifier = Modifier.weight(1f), - goal = "칼로리", limit = "1110kcal" + goal = "칼로리", limit = if (challenge.challengeType == ChallengeType.CALORIE) "${challenge.calorie}kcal" else "0kcal" ) } diff --git a/presentation/src/main/java/com/whyranoid/presentation/component/ChallengeItem.kt b/presentation/src/main/java/com/whyranoid/presentation/component/ChallengeItem.kt index 68f77f73..441daa9a 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/component/ChallengeItem.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/component/ChallengeItem.kt @@ -17,6 +17,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.whyranoid.presentation.theme.ChallengeColor +import com.whyranoid.presentation.theme.WalkieTypography import com.whyranoid.presentation.util.bouncingClickable @Composable @@ -49,6 +50,7 @@ fun ChallengeItem( textAlign = TextAlign.Start, text = text, overflow = TextOverflow.Ellipsis, + style = WalkieTypography.Body1, maxLines = 2 ) } diff --git a/presentation/src/main/java/com/whyranoid/presentation/component/ChallengingItem.kt b/presentation/src/main/java/com/whyranoid/presentation/component/ChallengingItem.kt index a932e15d..a1087ddd 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/component/ChallengingItem.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/component/ChallengingItem.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp import com.whyranoid.presentation.theme.ChallengeColor +import com.whyranoid.presentation.theme.WalkieTypography import com.whyranoid.presentation.util.bouncingClickable // TODO: set Color System @@ -33,8 +34,7 @@ fun ChallengingItem( .fillMaxWidth() .height(105.dp) .clip(shape = RoundedCornerShape(20.dp)) - .background(color = challengeColor.backgroundColor) - , + .background(color = challengeColor.backgroundColor), ) { Box( @@ -43,7 +43,10 @@ fun ChallengingItem( .padding(start = 26.dp), contentAlignment = Alignment.CenterStart ) { - Text(text) + Text( + text = text, + style = WalkieTypography.Body1 + ) } diff --git a/presentation/src/main/java/com/whyranoid/presentation/component/bottomsheet/ChallengeExitModalBottomSheetContainer.kt b/presentation/src/main/java/com/whyranoid/presentation/component/bottomsheet/ChallengeExitModalBottomSheetContainer.kt index 2ef10a1d..869e0b6b 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/component/bottomsheet/ChallengeExitModalBottomSheetContainer.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/component/bottomsheet/ChallengeExitModalBottomSheetContainer.kt @@ -64,31 +64,29 @@ fun ChallengeExitModalBottomSheetContainer( style = WalkieTypography.Title ) - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(16.dp)) Text( text = "${challenge.badge.name} 뱃지가 코 앞이에요.", style = WalkieTypography.Body2.copy(color = SystemColor.Negative) ) - Spacer(modifier = Modifier.height(22.dp)) - - Text( - text = challenge.title, - style = WalkieTypography.SubTitle.copy(color = SystemColor.Negative) - ) - - Spacer(modifier = Modifier.height(22.dp)) + Spacer(modifier = Modifier.height(31.dp)) AsyncImage( model = challenge.badge.imageUrl, contentDescription = "", modifier = Modifier .size(100.dp) - .clip(CircleShape) .padding(bottom = 10.dp), - contentScale = ContentScale.Crop ) + Text( + text = "${challenge.badge.name} 뱃지", + style = WalkieTypography.Body2 + ) + + Spacer(modifier = Modifier.height(16.dp)) + Text( text = "진행률 ${challenge.process}%", style = WalkieTypography.Body2.copy( @@ -97,9 +95,9 @@ fun ChallengeExitModalBottomSheetContainer( ) ) - Spacer(modifier = Modifier.height(37.dp)) + Spacer(modifier = Modifier.height(50.dp)) - WalkiePositiveButton(text = "계속하기") { + WalkiePositiveButton(text = "도전하기") { coroutineScope.launch { modalSheetState.hide() onPositiveButtonClicked(challenge) diff --git a/presentation/src/main/java/com/whyranoid/presentation/screens/challenge/ChallengeDetailScreen.kt b/presentation/src/main/java/com/whyranoid/presentation/screens/challenge/ChallengeDetailScreen.kt index cd73490f..128152d7 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/screens/challenge/ChallengeDetailScreen.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/screens/challenge/ChallengeDetailScreen.kt @@ -133,8 +133,8 @@ fun ChallengeDetailContent( .verticalScroll(scrollState), ) { // TODO: Async Image - Image( - painter = painterResource(id = R.drawable.dummy_challenge_banner), + AsyncImage( + model = challenge.imageUrl, contentDescription = null, modifier = Modifier.fillMaxWidth(), contentScale = ContentScale.FillWidth @@ -208,7 +208,6 @@ fun ChallengeDetailContent( modifier = Modifier .size(100.dp) .clip(CircleShape), - contentScale = ContentScale.Crop ) Spacer(modifier = Modifier.height(8.dp)) diff --git a/presentation/src/main/java/com/whyranoid/presentation/screens/challenge/ChallengeMainScreen.kt b/presentation/src/main/java/com/whyranoid/presentation/screens/challenge/ChallengeMainScreen.kt index 203ec340..4af84e4f 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/screens/challenge/ChallengeMainScreen.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/screens/challenge/ChallengeMainScreen.kt @@ -1,8 +1,10 @@ package com.whyranoid.presentation.screens.challenge import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -10,31 +12,29 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Icon -import androidx.compose.material.IconButton import androidx.compose.material.Scaffold import androidx.compose.material.Text -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Menu -import androidx.compose.material.icons.filled.Search -import androidx.compose.material.icons.rounded.ExpandMore import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavController import com.whyranoid.domain.model.challenge.ChallengePreview import com.whyranoid.domain.model.challenge.ChallengeType +import com.whyranoid.presentation.R import com.whyranoid.presentation.component.ChallengeItem import com.whyranoid.presentation.component.ChallengingItem import com.whyranoid.presentation.component.bar.WalkieTopBar @@ -84,7 +84,7 @@ fun ChallengeMainContent( leftContent = { Text( text = "챌린지", - style = WalkieTypography.Title.copy(fontWeight = FontWeight(600)), + style = WalkieTypography.Title, ) }, rightContent = { @@ -94,17 +94,8 @@ fun ChallengeMainContent( .clickable { }, - imageVector = Icons.Filled.Search, contentDescription = "검색 버튼" - ) - - Spacer(modifier = Modifier.width(16.dp)) - - Icon( - modifier = Modifier - .clickable { - - }, - imageVector = Icons.Filled.Menu, contentDescription = "메뉴 버튼" + painter = painterResource(id = R.drawable.ic_menu), + contentDescription = "메뉴 버튼" ) } @@ -123,68 +114,29 @@ fun ChallengeMainContent( ) { item { - Spacer(modifier = Modifier.height(10.dp)) - - Text( - modifier = Modifier.padding(horizontal = 20.dp), - text = "신규", - fontSize = 16.sp, - color = Color.Black, - fontWeight = FontWeight(700) - ) - Spacer(modifier = Modifier.height(10.dp)) - } - - item { - LazyRow( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(13.dp), - contentPadding = PaddingValues(20.dp) - ) { + Spacer(modifier = Modifier.height(8.dp)) - state.newChallengePreviewsState.getDataOrNull()?.let { newChallengePreviews -> - newChallengePreviews.forEach { - item { - ChallengeItem( - Modifier.fillParentMaxWidth(0.9f), - it.type.getColor(), - text = it.title - ) { - onChallengeItemClicked(it, false) - } - } - } - } ?: run { - item { - WalkieCircularProgressIndicator(Modifier.fillParentMaxWidth()) - } - } - - } - Spacer(modifier = Modifier.height(44.dp)) - } - - item { Text( modifier = Modifier.padding(horizontal = 20.dp), text = "도전중인 챌린지", - fontSize = 20.sp, + fontSize = 18.sp, color = Color.Black, fontWeight = FontWeight(700) ) - Spacer(modifier = Modifier.height(10.dp)) + Spacer(modifier = Modifier.height(16.dp)) + } item { Column( modifier = Modifier.padding(horizontal = 20.dp), - horizontalAlignment = Alignment.CenterHorizontally) { + horizontalAlignment = Alignment.CenterHorizontally + ) { state.challengingPreviewsState.getDataOrNull()?.let { challengingPreviews -> if (challengingPreviews.isNotEmpty()) { - challengingPreviews.take(4).forEach { + challengingPreviews.take(3).forEach { ChallengingItem( text = it.title, progress = it.progress!!, @@ -195,18 +147,54 @@ fun ChallengeMainContent( Spacer(modifier = Modifier.height(10.dp)) } - IconButton( - onClick = { onExpandButtonClicked() }) { - Icon( - imageVector = Icons.Rounded.ExpandMore, - modifier = Modifier - .width(20.dp) - .height(20.dp), - contentDescription = "도전중인 챌린지 더보기" + Box( + modifier = Modifier + .fillMaxWidth() + .height(30.dp) + .clip(shape = RoundedCornerShape(7.dp)) + .background(Color(0xFFF7F7F7)) + .clickable { + + }, + contentAlignment = Alignment.Center + ) { + Text( + text = "더보기", + style = WalkieTypography.Body2, + color = Color(0xFF808080), + fontWeight = FontWeight(700) ) } - } else { + } else { + Box( + modifier = Modifier + .fillMaxWidth() + .height(105.dp) + .clip(shape = RoundedCornerShape(20.dp)) + .background(Color(0xFFF7F7F7)), + contentAlignment = Alignment.Center + ) { + + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "아직 시작한 챌린지가 없어요.", + style = WalkieTypography.Body1, + color = Color(0xFF808080) + ) + + Spacer(modifier = Modifier.height(8.dp)) + + Text( + text = "아래 목록에서 도전할 챌린지를 찾아보세요!", + style = WalkieTypography.Body2, + color = Color(0xFF808080) + ) + } + } } @@ -214,30 +202,42 @@ fun ChallengeMainContent( WalkieCircularProgressIndicator(Modifier.fillParentMaxWidth()) } - Spacer(modifier = Modifier.height(10.dp)) + Spacer(modifier = Modifier.height(30.dp)) } } + item { + Box( + modifier = Modifier + .fillMaxWidth() + .height(8.dp) + .background(Color(0xFFF7F7F7)) + ) + + Spacer(modifier = Modifier.height(30.dp)) + } + item { Text( modifier = Modifier.padding(horizontal = 20.dp), - text = "다른 챌린지도 도전해보세요!", - fontSize = 20.sp, + text = "챌린지에 도전해보세요!", + fontSize = 18.sp, color = Color.Black, fontWeight = FontWeight(700) ) - Spacer(modifier = Modifier.height(14.dp)) + + Spacer(modifier = Modifier.height(16.dp)) } item { Text( modifier = Modifier.padding(horizontal = 20.dp), - text = "인기 챌린지", + text = "많이 도전하는 챌린지", fontSize = 16.sp, color = Color.Black, fontWeight = FontWeight(700) ) - Spacer(modifier = Modifier.height(14.dp)) + Spacer(modifier = Modifier.height(11.dp)) } item { @@ -245,34 +245,76 @@ fun ChallengeMainContent( modifier = Modifier .fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(13.dp), - contentPadding = PaddingValues(20.dp) + contentPadding = PaddingValues(start = 20.dp) ) { - state.topRankChallengePreviewState.getDataOrNull()?.let { newChallengePreviews -> - newChallengePreviews.chunkedList(3).forEach { list -> - item { - Column() { - list.forEach { - ChallengeItem( - Modifier.fillParentMaxWidth(0.9f), - it.type.getColor(), - text = it.title - ) { - onChallengeItemClicked(it, false) + state.topRankChallengePreviewState.getDataOrNull() + ?.let { newChallengePreviews -> + newChallengePreviews.chunkedList(3).forEach { list -> + item { + Column() { + list.forEach { + ChallengeItem( + Modifier.fillParentMaxWidth(0.9f), + it.type.getColor(), + text = it.title + ) { + onChallengeItemClicked(it, false) + } + Spacer(modifier = Modifier.height(10.dp)) } - Spacer(modifier = Modifier.height(10.dp)) } } } - } - } ?: run { + } ?: run { item { WalkieCircularProgressIndicator(Modifier.fillParentMaxWidth()) } } } - Spacer(modifier = Modifier.height(28.dp)) + Spacer(modifier = Modifier.height(30.dp)) + } + + item { + Text( + modifier = Modifier.padding(horizontal = 20.dp), + text = "새로 나온 챌린지", + fontSize = 16.sp, + color = Color.Black, + fontWeight = FontWeight(700) + ) + Spacer(modifier = Modifier.height(16.dp)) + } + + item { + Column( + modifier = Modifier.padding(horizontal = 20.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + state.newChallengePreviewsState.getDataOrNull() + ?.let { challengingPreviews -> + + if (challengingPreviews.isNotEmpty()) { + challengingPreviews.take(3).forEach { + ChallengingItem( + text = it.title, + progress = it.progress!!, + challengeColor = it.type.getColor(), + ) { + onChallengeItemClicked(it, true) + } + Spacer(modifier = Modifier.height(10.dp)) + } + + } else { + + } + + } + } + + Spacer(modifier = Modifier.height(30.dp)) } item { @@ -332,7 +374,8 @@ fun ChallengeMainContent( Spacer(modifier = Modifier.height(10.dp)) } } - } ?: run { WalkieCircularProgressIndicator(Modifier.fillParentMaxWidth()) } + } + ?: run { WalkieCircularProgressIndicator(Modifier.fillParentMaxWidth()) } } } diff --git a/presentation/src/main/res/drawable/ic_menu.xml b/presentation/src/main/res/drawable/ic_menu.xml new file mode 100644 index 00000000..37755e6e --- /dev/null +++ b/presentation/src/main/res/drawable/ic_menu.xml @@ -0,0 +1,9 @@ + + +