diff --git a/app/src/main/java/com/no5ing/bbibbi/data/model/view/MainPageModel.kt b/app/src/main/java/com/no5ing/bbibbi/data/model/view/MainPageModel.kt index 61f2a76..85a8da0 100644 --- a/app/src/main/java/com/no5ing/bbibbi/data/model/view/MainPageModel.kt +++ b/app/src/main/java/com/no5ing/bbibbi/data/model/view/MainPageModel.kt @@ -20,6 +20,7 @@ data class MainPageModel( @Parcelize data class NightMainPageModel( val topBarElements: List, + val familyMemberMonthlyRanking: MainPageMonthlyRankingModel, ) : Parcelable, BaseModel() @Parcelize @@ -46,4 +47,23 @@ data class MainPageTopBarModel( val displayRank: Int?, val shouldShowBirthdayMark: Boolean, val shouldShowPickIcon: Boolean, +) : Parcelable + +@Parcelize +data class MainPageMonthlyRankingModel( + val month: Int, + val firstRanker: MainPageMonthlyRankerModel?, + val secondRanker: MainPageMonthlyRankerModel?, + val thirdRanker: MainPageMonthlyRankerModel?, +) : Parcelable { + fun isAllRankersNull(): Boolean { + return firstRanker == null && secondRanker == null && thirdRanker == null + } +} + +@Parcelize +data class MainPageMonthlyRankerModel( + val profileImageUrl: String?, + val name: String, + val survivalCount: Int, ) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/no5ing/bbibbi/presentation/component/button/FlatButton.kt b/app/src/main/java/com/no5ing/bbibbi/presentation/component/button/FlatButton.kt new file mode 100644 index 0000000..7af3b16 --- /dev/null +++ b/app/src/main/java/com/no5ing/bbibbi/presentation/component/button/FlatButton.kt @@ -0,0 +1,60 @@ +package com.no5ing.bbibbi.presentation.component.button + +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import com.no5ing.bbibbi.presentation.theme.bbibbiScheme +import com.no5ing.bbibbi.presentation.theme.bbibbiTypo + +@Composable +fun FlatButton( + text: String, + modifier: Modifier = Modifier, + buttonColor: Color = MaterialTheme.bbibbiScheme.mainYellow, + textColor: Color = MaterialTheme.bbibbiScheme.backgroundPrimary, + contentPadding: PaddingValues = PaddingValues( + start = 24.dp, + top = 12.dp, + end = 24.dp, + bottom = 12.dp, + ), + onClick: () -> Unit = {}, + isActive: Boolean = true, + byPassCtaIgnore: Boolean = false, +) { + val opacityAlpha: Float by animateFloatAsState( + targetValue = if (isActive) 1f else 0.2f, + animationSpec = tween( + durationMillis = 130, + easing = LinearEasing, + ), label = "" + ) + Button( + shape = RoundedCornerShape(8.dp), + onClick = { if (isActive || byPassCtaIgnore) onClick() }, + colors = ButtonDefaults.buttonColors( + containerColor = buttonColor.copy( + alpha = opacityAlpha + ) + ), + modifier = modifier, + contentPadding = contentPadding, + ) { + Text( + text = text, + color = textColor, + style = MaterialTheme.bbibbiTypo.bodyOneBold, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/calendar/MainCalendarPage.kt b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/calendar/MainCalendarPage.kt index df6bba3..5c0aacd 100644 --- a/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/calendar/MainCalendarPage.kt +++ b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/calendar/MainCalendarPage.kt @@ -312,7 +312,6 @@ fun MainCalendarYearMonthBar( .size(20.dp) .clickable { it.showAlignBottom() } ) - } } if (statistics.isReady()) { diff --git a/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/HomePage.kt b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/HomePage.kt index 8c25e89..edfe02f 100644 --- a/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/HomePage.kt +++ b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/HomePage.kt @@ -28,14 +28,17 @@ import com.no5ing.bbibbi.presentation.component.BBiBBiPreviewSurface import com.no5ing.bbibbi.presentation.component.BBiBBiSurface import com.no5ing.bbibbi.presentation.component.BackToExitHandler import com.no5ing.bbibbi.presentation.feature.view.common.CustomAlertDialog +import com.no5ing.bbibbi.presentation.feature.view_model.MainPageNightViewModel import com.no5ing.bbibbi.presentation.feature.view_model.MainPageViewModel import com.no5ing.bbibbi.presentation.theme.bbibbiScheme import com.no5ing.bbibbi.util.gapUntilNext import kotlinx.coroutines.flow.MutableStateFlow +import java.time.LocalDate @Composable fun HomePage( mainPageViewModel: MainPageViewModel = hiltViewModel(), + mainPageNightViewModel: MainPageNightViewModel = hiltViewModel(), postViewTypeState: MutableState = remember { mutableStateOf(PostType.SURVIVAL) }, onTapLeft: () -> Unit = {}, onTapRight: () -> Unit = {}, @@ -44,12 +47,14 @@ fun HomePage( onTapUpload: () -> Unit = {}, onTapInvite: () -> Unit = {}, onUnsavedPost: (Uri) -> Unit = {}, + onTapViewPost: (LocalDate) -> Unit = {}, onTapPick: (MainPageTopBarModel) -> Unit = {}, ) { val postViewType by postViewTypeState val mainPageState = mainPageViewModel.uiState.collectAsState() val unsavedDialogUri = remember { mutableStateOf(null) } val unsavedDialogEnabled = remember { mutableStateOf(false) } + val isDayTime = gapUntilNext() > 0 CustomAlertDialog( enabledState = unsavedDialogEnabled, title = stringResource(id = R.string.unsaved_post_dialog_title), @@ -71,7 +76,11 @@ fun HomePage( unsavedDialogUri.value = tempUri unsavedDialogEnabled.value = true } - mainPageViewModel.invoke(Arguments()) + if(isDayTime) { + mainPageViewModel.invoke(Arguments()) + } else { + mainPageNightViewModel.invoke(Arguments()) + } } BBiBBiSurface( @@ -89,18 +98,34 @@ fun HomePage( onTapLeft = onTapLeft, onTapRight = onTapRight ) - HomePageContent( - mainPageState = mainPageViewModel.uiState, - postViewTypeState = postViewTypeState, - onTapContent = onTapContent, - onTapProfile = onTapProfile, - onTapInvite = onTapInvite, - onTapPick = onTapPick, - onRefresh = { - mainPageViewModel.invoke(Arguments()) - }, - deferredPickStateSet = mainPageViewModel.deferredPickMembersSet - ) + if (isDayTime) { + HomePageContent( + mainPageState = mainPageViewModel.uiState, + postViewTypeState = postViewTypeState, + onTapContent = onTapContent, + onTapProfile = onTapProfile, + onTapInvite = onTapInvite, + onTapPick = onTapPick, + onRefresh = { + mainPageViewModel.invoke(Arguments()) + }, + deferredPickStateSet = mainPageViewModel.deferredPickMembersSet + ) + } else { + NightHomePageContent( + mainPageState = mainPageNightViewModel.uiState, + postViewTypeState = postViewTypeState, + onTapViewPost = onTapViewPost, + onTapProfile = onTapProfile, + onTapInvite = onTapInvite, + onTapPick = onTapPick, + onRefresh = { + mainPageNightViewModel.invoke(Arguments()) + }, + deferredPickStateSet = mainPageViewModel.deferredPickMembersSet + ) + } + } if (postViewType == PostType.SURVIVAL) { HomePageSurvivalUploadButton( diff --git a/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/HomePageContent.kt b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/HomePageContent.kt index 82e2e5b..c935a29 100644 --- a/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/HomePageContent.kt +++ b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/HomePageContent.kt @@ -111,7 +111,7 @@ fun HomePageContent( .verticalScroll(state = scrollState) ) { HomePageStoryBar( - mainPageState = mainPageState, + items = if (mainPageModel.isReady()) mainPageModel.data.topBarElements else emptyList(), onTapProfile = onTapProfile, onTapInvite = onTapInvite, onTapPick = onTapPick, diff --git a/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/HomePageStoryBar.kt b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/HomePageStoryBar.kt index 6861cc8..e3db64a 100644 --- a/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/HomePageStoryBar.kt +++ b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/HomePageStoryBar.kt @@ -45,16 +45,17 @@ import kotlinx.coroutines.flow.StateFlow @Composable fun HomePageStoryBar( - mainPageState: StateFlow>, + //mainPageState: StateFlow>, + items: List, deferredPickStateSet: StateFlow>, onTapProfile: (String) -> Unit = {}, onTapPick: (MainPageTopBarModel) -> Unit = {}, onTapInvite: () -> Unit = {}, ) { val meId = LocalSessionState.current.memberId - val mainPageModel by mainPageState.collectAsState() + // val mainPageModel by mainPageState.collectAsState() val deferredPickSet = deferredPickStateSet.collectAsState() - val items = if (mainPageModel.isReady()) mainPageModel.data.topBarElements else emptyList() + // val items = if (mainPageModel.isReady()) mainPageModel.data.topBarElements else emptyList() if (items.size == 1) { HomePageNoFamilyBar( @@ -206,7 +207,7 @@ fun StoryBarIcon( } @Composable -private fun getRankColor(rank: Int) = when (rank) { +fun getRankColor(rank: Int) = when (rank) { 0 -> MaterialTheme.bbibbiScheme.mainYellow 1 -> Color(0xff7FEC93) 2 -> Color(0xffFFC98D) diff --git a/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/NightHomePageContent.kt b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/NightHomePageContent.kt new file mode 100644 index 0000000..2ddd34f --- /dev/null +++ b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view/main/home/NightHomePageContent.kt @@ -0,0 +1,403 @@ +package com.no5ing.bbibbi.presentation.feature.view.main.home + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.Image +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.BoxWithConstraints +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.Icon +import androidx.compose.material.pullrefresh.PullRefreshIndicator +import androidx.compose.material.pullrefresh.pullRefresh +import androidx.compose.material.pullrefresh.rememberPullRefreshState +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +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.painter.Painter +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.no5ing.bbibbi.R +import com.no5ing.bbibbi.data.model.APIResponse +import com.no5ing.bbibbi.data.model.post.PostType +import com.no5ing.bbibbi.data.model.view.MainPageMonthlyRankerModel +import com.no5ing.bbibbi.data.model.view.MainPageTopBarModel +import com.no5ing.bbibbi.data.model.view.NightMainPageModel +import com.no5ing.bbibbi.presentation.component.CircleProfileImage +import com.no5ing.bbibbi.presentation.component.button.FlatButton +import com.no5ing.bbibbi.presentation.theme.bbibbiScheme +import com.no5ing.bbibbi.presentation.theme.bbibbiTypo +import com.skydoves.balloon.ArrowPositionRules +import com.skydoves.balloon.BalloonAnimation +import com.skydoves.balloon.BalloonSizeSpec +import com.skydoves.balloon.compose.Balloon +import com.skydoves.balloon.compose.rememberBalloonBuilder +import com.skydoves.balloon.compose.setBackgroundColor +import kotlinx.coroutines.flow.StateFlow +import java.time.LocalDate + +@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterialApi::class) +@Composable +fun NightHomePageContent( + mainPageState: StateFlow>, + deferredPickStateSet: StateFlow>, + postViewTypeState: MutableState = remember { mutableStateOf(PostType.SURVIVAL) }, + onTapViewPost: (LocalDate) -> Unit = {}, + onTapProfile: (String) -> Unit = {}, + onTapPick: (MainPageTopBarModel) -> Unit = {}, + onTapInvite: () -> Unit = {}, + onRefresh: () -> Unit = {}, +) { + val warningState = remember { + mutableIntStateOf(0) + } + val balloonColor = MaterialTheme.bbibbiScheme.button + val balloonText = "생존신고 횟수가 동일한 경우\n이모지, 댓글 수를 합산해서 등수를 정해요" + val builder = rememberBalloonBuilder { + setArrowSize(10) + setArrowPosition(0.5f) + setArrowPositionRules(ArrowPositionRules.ALIGN_ANCHOR) + setWidth(BalloonSizeSpec.WRAP) + setHeight(BalloonSizeSpec.WRAP) + setMarginTop(12) + setPaddingVertical(10) + setPaddingHorizontal(16) + setMarginHorizontal(12) + setCornerRadius(12f) + setBackgroundColor(balloonColor) + // setBackgroundColorResource(balloonColor) + setBalloonAnimation(BalloonAnimation.ELASTIC) + } + + val mainPageModel by mainPageState.collectAsState() + var isRefreshing by remember { mutableStateOf(true) } + val pagerState = rememberPagerState(pageCount = { 2 }) + val pullRefreshStyle = rememberPullRefreshState( + refreshing = isRefreshing, + onRefresh = { + if (isRefreshing) return@rememberPullRefreshState + isRefreshing = true + onRefresh() + } + ) + LaunchedEffect(mainPageModel) { + if (mainPageModel.isReady()) { + isRefreshing = false + } + } + LaunchedEffect(postViewTypeState.value) { + val page = if (postViewTypeState.value == PostType.SURVIVAL) 0 else 1 + pagerState.animateScrollToPage(page) + } + LaunchedEffect(pagerState.currentPage) { + val type = if (pagerState.currentPage == 0) PostType.SURVIVAL else PostType.MISSION + if (type != postViewTypeState.value) { + postViewTypeState.value = type + } + } + BoxWithConstraints { + val scrollState = rememberScrollState() + + Column( + modifier = Modifier + // .fillMaxSize() + .pullRefresh(pullRefreshStyle) + .verticalScroll(state = scrollState) + ) { + HomePageStoryBar( + items = if (mainPageModel.isReady()) mainPageModel.data.topBarElements else emptyList(), + onTapProfile = onTapProfile, + onTapInvite = onTapInvite, + onTapPick = onTapPick, + deferredPickStateSet = deferredPickStateSet, + ) + Spacer(modifier = Modifier.height(24.dp)) + HorizontalDivider( + thickness = 1.dp, + color = MaterialTheme.bbibbiScheme.backgroundSecondary + ) + Spacer(modifier = Modifier.height(24.dp)) + UploadCountDownBar(warningState = warningState) + SurvivalTextDescription(warningState = warningState) + Spacer(modifier = Modifier.height(24.dp)) + if(mainPageModel.isReady()) { + val ranking = mainPageModel.data.familyMemberMonthlyRanking + Box( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + .background( + MaterialTheme.bbibbiScheme.backgroundSecondary, + RoundedCornerShape(24.dp) + ) + ){ + Column( + modifier = Modifier.padding(vertical = 20.dp, horizontal = 20.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier + .fillMaxWidth() + // .padding(horizontal = 20.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = "이번달 최고 기여자", + style = MaterialTheme.bbibbiTypo.headTwoBold, + color = MaterialTheme.bbibbiScheme.textPrimary, + ) + Balloon( + builder = builder, + balloonContent = { + Text( + text = balloonText, + textAlign = TextAlign.Center, + color = MaterialTheme.bbibbiScheme.white, + style = MaterialTheme.bbibbiTypo.bodyTwoRegular, + ) + } + ) { + Icon( + painter = painterResource(id = R.drawable.warning_circle_icon), + tint = MaterialTheme.bbibbiScheme.textSecondary, + contentDescription = null, + modifier = Modifier + .size(20.dp) + .clickable { it.showAlignBottom() } + ) + } + } + + Text( + text = "${ranking.month}월 생존신고 횟수", + style = MaterialTheme.bbibbiTypo.bodyTwoRegular, + color = MaterialTheme.bbibbiScheme.textSecondary, + ) + } + Spacer(modifier = Modifier.height(24.dp)) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 4.dp), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + Box( + Modifier.padding(top = 36.dp) + ) { + RankIcon( + model = ranking.secondRanker, + outerCircleSize = 72.dp, + innerCircleSize = 64.dp, + borderColor = getRankColor(rank = 1)!!, + noRankImage = painterResource(id = R.drawable.second_ranking_empty), + rankImage = painterResource(id = R.drawable.second_ranking), + badgeHeight = 27.dp + ) + } + + RankIcon( + model = ranking.firstRanker, + outerCircleSize = 90.dp, + innerCircleSize = 82.dp, + borderColor = getRankColor(rank = 0)!!, + noRankImage = painterResource(id = R.drawable.first_ranking_empty), + rankImage = painterResource(id = R.drawable.first_ranking), + badgeHeight = 32.dp + ) + Box( + Modifier.padding(top = 36.dp) + ) { + RankIcon( + model = ranking.thirdRanker, + outerCircleSize = 72.dp, + innerCircleSize = 64.dp, + borderColor = getRankColor(rank = 2)!!, + noRankImage = painterResource(id = R.drawable.third_ranking_empty), + rankImage = painterResource(id = R.drawable.third_ranking), + badgeHeight = 27.dp + ) + } + } + Spacer(modifier = Modifier.height(36.dp)) + if(ranking.isAllRankersNull()) { + Text( + text = "아직 활동한 가족이 없어요", + style = MaterialTheme.bbibbiTypo.bodyOneBold, + color = MaterialTheme.bbibbiScheme.textSecondary, + ) + Spacer(modifier = Modifier.height(8.dp)) + } else { + FlatButton( + text = "지난 날 생존신고 보기", + modifier = Modifier.fillMaxWidth(), + onClick = { + onTapViewPost(LocalDate.now()) + }, + ) + } + } + } + } + } + PullRefreshIndicator( + refreshing = isRefreshing, + state = pullRefreshStyle, + modifier = Modifier.align(Alignment.TopCenter), + backgroundColor = MaterialTheme.bbibbiScheme.backgroundSecondary, + contentColor = MaterialTheme.bbibbiScheme.iconSelected, + ) + } +} + +@Composable +fun RankIcon( + model: MainPageMonthlyRankerModel?, + outerCircleSize: Dp, + innerCircleSize: Dp, + borderColor: Color, + noRankImage: Painter, + rankImage: Painter, + badgeHeight: Dp, +) { + if(model == null) { + Column( + verticalArrangement = Arrangement.spacedBy(9.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Box(contentAlignment = Alignment.Center, modifier = Modifier.padding(bottom = 12.dp)) { + Box( + Modifier + .size(outerCircleSize) + .background(MaterialTheme.bbibbiScheme.gray600, CircleShape) + ) + Box( + Modifier + .size(innerCircleSize) + .background(MaterialTheme.bbibbiScheme.backgroundHover, CircleShape), + contentAlignment = Alignment.Center, + ) { + Text(text = "?", style = TextStyle( + fontSize = 33.75.sp, + fontWeight = FontWeight.SemiBold + ), color = MaterialTheme.colorScheme.onSurface) + } + Image( + painter = noRankImage, + contentDescription = null, + modifier = Modifier + .height(badgeHeight) + .align(Alignment.BottomCenter) + .offset(y = 12.dp) + ) + } + CommonEmptyBlock() + } + } else { + Column( + verticalArrangement = Arrangement.spacedBy(9.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Box(contentAlignment = Alignment.Center, modifier = Modifier.padding(bottom = 12.dp)) { + Box( + Modifier + .size(outerCircleSize) + .background(borderColor, CircleShape) + ) + CircleProfileImage( + size = innerCircleSize, + noImageLetter = model.name.first().toString(), + imageUrl = model.profileImageUrl + ) + Image( + painter = rankImage, + contentDescription = null, + modifier = Modifier + .height(badgeHeight) + .align(Alignment.BottomCenter) + .offset(y = 12.dp) + ) + } + CommonTextBlock( + name = model.name, + count = model.survivalCount + ) + } + } + + +} + +@Composable +fun CommonEmptyBlock() { + Column( + verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Box(modifier = Modifier + .size(width = 53.dp, height = 16.dp) + .background(MaterialTheme.bbibbiScheme.gray600, RoundedCornerShape(4.dp)) + ) + Box(modifier = Modifier + .size(width = 29.dp, height = 12.dp) + .background(MaterialTheme.bbibbiScheme.button, RoundedCornerShape(4.dp)) + ) + } +} + +@Composable +private fun CommonTextBlock( + name: String, + count: Int, +) { + Column( + verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + text = name, + style = MaterialTheme.bbibbiTypo.bodyTwoBold, + color = MaterialTheme.bbibbiScheme.textPrimary, + ) + Text( + text = "${count}회", + style = MaterialTheme.bbibbiTypo.bodyTwoRegular, + color = MaterialTheme.bbibbiScheme.textSecondary, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view_controller/main/HomePageController.kt b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view_controller/main/HomePageController.kt index 8297374..b4c09e6 100644 --- a/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view_controller/main/HomePageController.kt +++ b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view_controller/main/HomePageController.kt @@ -18,6 +18,7 @@ import com.no5ing.bbibbi.presentation.feature.view.main.home.HomePage import com.no5ing.bbibbi.presentation.feature.view.main.home.TryPickPopup import com.no5ing.bbibbi.presentation.feature.view_controller.CameraViewPageController.goCameraViewPage import com.no5ing.bbibbi.presentation.feature.view_controller.NavigationDestination +import com.no5ing.bbibbi.presentation.feature.view_controller.main.CalendarDetailPageController.goCalendarDetailPage import com.no5ing.bbibbi.presentation.feature.view_controller.main.CalendarPageController.goCalendarPage import com.no5ing.bbibbi.presentation.feature.view_controller.main.FamilyListPageController.goFamilyListPage import com.no5ing.bbibbi.presentation.feature.view_controller.main.PostReUploadPageController.goPostReUploadPage @@ -94,6 +95,9 @@ object HomePageController : NavigationDestination( isPickDialogVisible = true }, mainPageViewModel = mainPageViewModel, + onTapViewPost = { date -> + navController.goCalendarDetailPage(date) + } ) } diff --git a/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view_model/MainPageNightViewModel.kt b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view_model/MainPageNightViewModel.kt new file mode 100644 index 0000000..a9cd409 --- /dev/null +++ b/app/src/main/java/com/no5ing/bbibbi/presentation/feature/view_model/MainPageNightViewModel.kt @@ -0,0 +1,30 @@ +package com.no5ing.bbibbi.presentation.feature.view_model + +import com.no5ing.bbibbi.data.datasource.local.LocalDataStorage +import com.no5ing.bbibbi.data.datasource.network.RestAPI +import com.no5ing.bbibbi.data.model.APIResponse +import com.no5ing.bbibbi.data.model.APIResponse.Companion.wrapToAPIResponse +import com.no5ing.bbibbi.data.model.view.NightMainPageModel +import com.no5ing.bbibbi.data.repository.Arguments +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import javax.inject.Inject + +@HiltViewModel +class MainPageNightViewModel @Inject constructor( + private val restAPI: RestAPI, + private val localDataStorage: LocalDataStorage, +) : BaseViewModel>() { + + override fun initState(): APIResponse { + return APIResponse.idle() + } + + override fun invoke(arguments: Arguments) { + withMutexScope(Dispatchers.IO) { + val mainResult = restAPI.getViewApi().getNightMainView() + val apiResult = mainResult.wrapToAPIResponse() + setState(apiResult) + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/first_ranking.png b/app/src/main/res/drawable/first_ranking.png new file mode 100644 index 0000000..763cdb1 Binary files /dev/null and b/app/src/main/res/drawable/first_ranking.png differ diff --git a/app/src/main/res/drawable/first_ranking_empty.png b/app/src/main/res/drawable/first_ranking_empty.png new file mode 100644 index 0000000..98f3d5f Binary files /dev/null and b/app/src/main/res/drawable/first_ranking_empty.png differ diff --git a/app/src/main/res/drawable/second_ranking.png b/app/src/main/res/drawable/second_ranking.png new file mode 100644 index 0000000..ac84ae2 Binary files /dev/null and b/app/src/main/res/drawable/second_ranking.png differ diff --git a/app/src/main/res/drawable/second_ranking_empty.png b/app/src/main/res/drawable/second_ranking_empty.png new file mode 100644 index 0000000..e69e763 Binary files /dev/null and b/app/src/main/res/drawable/second_ranking_empty.png differ diff --git a/app/src/main/res/drawable/third_ranking.png b/app/src/main/res/drawable/third_ranking.png new file mode 100644 index 0000000..4f9a875 Binary files /dev/null and b/app/src/main/res/drawable/third_ranking.png differ diff --git a/app/src/main/res/drawable/third_ranking_empty.png b/app/src/main/res/drawable/third_ranking_empty.png new file mode 100644 index 0000000..469ca46 Binary files /dev/null and b/app/src/main/res/drawable/third_ranking_empty.png differ