From 2c06d297aa53932446b690ddfd4818b9bcc87734 Mon Sep 17 00:00:00 2001 From: Sadturtleman Date: Tue, 25 Aug 2026 09:43:07 +0900 Subject: [PATCH] =?UTF-8?q?fix(home):=20=EA=B8=B0=EB=A1=9D=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=B9=B4=EB=93=9C=EA=B0=80=20?= =?UTF-8?q?=C2=AB=EB=AA=A8=EB=A6=84=C2=BB=20=EC=9D=84=200=20=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=91=EC=A7=80=20=EC=95=8A=EA=B2=8C=20=ED=95=9C?= =?UTF-8?q?=EB=8B=A4=20(#700=20=EC=9D=BC=EB=B6=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HomeTabViewModel 이 MindRecordCategory.entries 를 돌며 데일리질문·주간 리포트에 0 을 박아 넣고 있었다. 지금은 화면이 일기 카드만 그려 안 보일 뿐, 카드가 늘면 그 0 이 그대로 «기록 0건» 으로 노출된다. 목업 숫자는 눈에 띄지만 0 은 그럴듯한 거짓이라 사용자가 그대로 믿는다. - ViewModel·로딩 분기 모두 **값을 아는 카테고리만** map 에 담는다. - RecordCategoryCard.totalCount 를 Int? 로 열고, 모르면 대시로 그린다 — 수신자 홈(#952)·주간 요약(#562)과 같은 표기다. 시안 정본 확정이 필요한 카드 구성 자체는 이 커밋 범위 밖이다. Co-Authored-By: Claude Opus 5 (1M context) --- .../home/presentation/HomeTabScreen.kt | 3 +- .../home/presentation/HomeTabViewModel.kt | 13 ++-- .../home/presentation/HomeTabViewModelTest.kt | 9 +-- .../component/hometab/RecordCategoryCard.kt | 11 ++- .../hometab/HomeTabMindRecordLazyItems.kt | 3 +- .../src/main/res/values/strings.xml | 2 + .../component/RecordCategoryCountTest.kt | 68 +++++++++++++++++++ 7 files changed, 90 insertions(+), 19 deletions(-) create mode 100644 feature/mindrecord/presentation/src/test/kotlin/com/afternote/feature/mindrecord/presentation/component/RecordCategoryCountTest.kt diff --git a/feature/home/presentation/src/main/kotlin/com/afternote/feature/home/presentation/HomeTabScreen.kt b/feature/home/presentation/src/main/kotlin/com/afternote/feature/home/presentation/HomeTabScreen.kt index 63e8d05af6..724d8ee4be 100644 --- a/feature/home/presentation/src/main/kotlin/com/afternote/feature/home/presentation/HomeTabScreen.kt +++ b/feature/home/presentation/src/main/kotlin/com/afternote/feature/home/presentation/HomeTabScreen.kt @@ -148,7 +148,8 @@ fun HomeTabScreen( userName = uiState.cachedUserName ?: "\u2026", // 조회 전이다 — 지정 여부를 결과로 확정하지 않는다 (#698). recipientBadgeState = RecipientDesignationBadgeState.Unknown, - categoryCounts = MindRecordCategory.entries.associateWith { 0 }, + // 조회 전에는 아는 값이 없다 — 0 을 채워 넣지 않는다 (#700). + categoryCounts = emptyMap(), categoryCountsLoading = true, todayDateText = todayDateText, todayQuestionContent = null, diff --git a/feature/home/presentation/src/main/kotlin/com/afternote/feature/home/presentation/HomeTabViewModel.kt b/feature/home/presentation/src/main/kotlin/com/afternote/feature/home/presentation/HomeTabViewModel.kt index bf2abcc3ef..6006d172f4 100644 --- a/feature/home/presentation/src/main/kotlin/com/afternote/feature/home/presentation/HomeTabViewModel.kt +++ b/feature/home/presentation/src/main/kotlin/com/afternote/feature/home/presentation/HomeTabViewModel.kt @@ -132,12 +132,9 @@ private fun HomeSummary.toHomeTabSuccess(): HomeTabUiState.Success = userName = userName, isRecipientDesignated = isRecipientDesignated, todayQuestionContent = todayQuestionContent, - categoryCounts = - MindRecordCategory.entries.associateWith { category -> - when (category) { - MindRecordCategory.DIARY -> diaryCategoryCount - MindRecordCategory.DAILY_QUESTION -> 0 - MindRecordCategory.WEEKLY_REPORT -> 0 - } - }, + // **실제로 값을 아는 카테고리만 담는다.** 종전에는 enum 전체를 돌며 데일리질문·주간 + // 리포트에 0 을 박아 넣었다. 지금은 화면이 일기 카드만 그려 안 보일 뿐, 카드가 늘면 + // 그 0 이 그대로 «기록 0건» 으로 노출된다 — 목업이면 눈에 띄지만 0 은 그럴듯한 + // 거짓이라 사용자가 그대로 믿는다 (#700). + categoryCounts = mapOf(MindRecordCategory.DIARY to diaryCategoryCount), ) diff --git a/feature/home/presentation/src/test/kotlin/com/afternote/feature/home/presentation/HomeTabViewModelTest.kt b/feature/home/presentation/src/test/kotlin/com/afternote/feature/home/presentation/HomeTabViewModelTest.kt index bc1e219bb8..2bcc8919b3 100644 --- a/feature/home/presentation/src/test/kotlin/com/afternote/feature/home/presentation/HomeTabViewModelTest.kt +++ b/feature/home/presentation/src/test/kotlin/com/afternote/feature/home/presentation/HomeTabViewModelTest.kt @@ -520,12 +520,9 @@ private fun successState( HomeTabUiState.Success( userName = userName, isRecipientDesignated = isRecipientDesignated, - categoryCounts = - mapOf( - MindRecordCategory.DAILY_QUESTION to 0, - MindRecordCategory.DIARY to diaryCount, - MindRecordCategory.WEEKLY_REPORT to 0, - ), + // 값을 아는 카테고리만 담는다 — 데일리질문·주간 리포트는 아직 카드를 그리지 않고, + // 0 을 넣어 두면 카드가 늘 때 그대로 «기록 0건» 이 된다 (#700). + categoryCounts = mapOf(MindRecordCategory.DIARY to diaryCount), todayQuestionContent = questionContent, ) diff --git a/feature/mindrecord/presentation/src/main/kotlin/com/afternote/feature/mindrecord/presentation/component/hometab/RecordCategoryCard.kt b/feature/mindrecord/presentation/src/main/kotlin/com/afternote/feature/mindrecord/presentation/component/hometab/RecordCategoryCard.kt index fe9685967b..181a7f3be5 100644 --- a/feature/mindrecord/presentation/src/main/kotlin/com/afternote/feature/mindrecord/presentation/component/hometab/RecordCategoryCard.kt +++ b/feature/mindrecord/presentation/src/main/kotlin/com/afternote/feature/mindrecord/presentation/component/hometab/RecordCategoryCard.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.unit.sp import com.afternote.core.ui.modifierextention.shimmerLoadingPlaceholder import com.afternote.core.ui.theme.AfternoteDesign import com.afternote.core.ui.theme.AfternoteTheme +import com.afternote.feature.mindrecord.presentation.R.string.mindrecord_home_category_count_unavailable import com.afternote.feature.mindrecord.presentation.R.string.mindrecord_total_label import java.text.NumberFormat import java.util.Locale @@ -44,7 +45,11 @@ fun RecordCategoryCard( iconResId: Int, title: String, subtitle: String, - totalCount: Int, + /** + * 이 카테고리의 총 기록 수. **null 은 «아직 모름»** — 0 으로 접으면 조회 실패나 미연결이 + * «기록 없음» 으로 확정된다. 수신자 홈(#952)·주간 요약(#562)과 같은 규칙이다 (#700). + */ + totalCount: Int?, onClick: () -> Unit, modifier: Modifier = Modifier, // TODO: Vector Asset(xml)의 viewport 여백을 맞추면 이 플래그를 제거할 수 있습니다. @@ -53,7 +58,7 @@ fun RecordCategoryCard( ) { val formattedCount = remember(totalCount) { - NumberFormat.getNumberInstance(Locale.getDefault()).format(totalCount) + totalCount?.let { NumberFormat.getNumberInstance(Locale.getDefault()).format(it) } } Column( @@ -141,7 +146,7 @@ fun RecordCategoryCard( ) } else { Text( - text = formattedCount, + text = formattedCount ?: stringResource(mindrecord_home_category_count_unavailable), style = AfternoteDesign.typography.h3, color = AfternoteDesign.colors.gray9, ) diff --git a/feature/mindrecord/presentation/src/main/kotlin/com/afternote/feature/mindrecord/presentation/hometab/HomeTabMindRecordLazyItems.kt b/feature/mindrecord/presentation/src/main/kotlin/com/afternote/feature/mindrecord/presentation/hometab/HomeTabMindRecordLazyItems.kt index ca9f33b806..69bdc3e888 100644 --- a/feature/mindrecord/presentation/src/main/kotlin/com/afternote/feature/mindrecord/presentation/hometab/HomeTabMindRecordLazyItems.kt +++ b/feature/mindrecord/presentation/src/main/kotlin/com/afternote/feature/mindrecord/presentation/hometab/HomeTabMindRecordLazyItems.kt @@ -72,7 +72,8 @@ fun LazyListScope.homeTabMindRecordQuestionAndCategories( iconResId = CoreUiR.drawable.core_ui_ic_diary, title = stringResource(MindRecordCategoryUi.Diary.titleRes), subtitle = stringResource(MindRecordCategoryUi.Diary.descriptionRes), - totalCount = categoryCounts[MindRecordCategory.DIARY] ?: 0, + // 키가 없으면 «모름» 이다 — 0 으로 접지 않는다 (#700). + totalCount = categoryCounts[MindRecordCategory.DIARY], onClick = { onRecordCategoryClick(MindRecordCategory.DIARY) }, useDiaryIconLayout = true, isCountLoading = isCategoryCountLoading, diff --git a/feature/mindrecord/presentation/src/main/res/values/strings.xml b/feature/mindrecord/presentation/src/main/res/values/strings.xml index 64fe008626..1cfe725122 100644 --- a/feature/mindrecord/presentation/src/main/res/values/strings.xml +++ b/feature/mindrecord/presentation/src/main/res/values/strings.xml @@ -203,4 +203,6 @@ 마음의 기록을 불러오지 못했어요. 다시 시도 마음의 기록 + + – diff --git a/feature/mindrecord/presentation/src/test/kotlin/com/afternote/feature/mindrecord/presentation/component/RecordCategoryCountTest.kt b/feature/mindrecord/presentation/src/test/kotlin/com/afternote/feature/mindrecord/presentation/component/RecordCategoryCountTest.kt new file mode 100644 index 0000000000..d7e38b84fd --- /dev/null +++ b/feature/mindrecord/presentation/src/test/kotlin/com/afternote/feature/mindrecord/presentation/component/RecordCategoryCountTest.kt @@ -0,0 +1,68 @@ +package com.afternote.feature.mindrecord.presentation.component + +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithText +import com.afternote.core.ui.theme.AfternoteTheme +import com.afternote.feature.mindrecord.presentation.component.hometab.RecordCategoryCard +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import com.afternote.core.ui.R as CoreUiR + +/** + * 기록 카테고리 카드가 «모름» 을 0 으로 접지 않는지 (#700). + * + * 홈 ViewModel 이 enum 전체를 돌며 데일리질문·주간 리포트에 0 을 박아 넣고 있었다. 화면이 + * 일기 카드만 그려 안 보였을 뿐, 카드가 늘면 그 0 이 그대로 «기록 0건» 으로 노출된다. + * 목업 숫자는 눈에 띄지만 0 은 그럴듯한 거짓이라 사용자가 그대로 믿는다 — 수신자 홈(#952)· + * 주간 요약(#562)에서 같은 이유로 대시 표기를 택했다. + */ +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [35]) +class RecordCategoryCountTest { + @get:Rule + val composeRule = createAndroidComposeRule() + + @Test + fun `기록 수를 모르면 0 이 아니라 대시를 그린다`() { + composeRule.setContent { + AfternoteTheme { card(totalCount = null) } + } + + composeRule.onNodeWithText("–").assertIsDisplayed() + composeRule.onNodeWithText("0").assertDoesNotExist() + } + + @Test + fun `0건은 확정값이라 그대로 그린다`() { + composeRule.setContent { + AfternoteTheme { card(totalCount = 0) } + } + + composeRule.onNodeWithText("0").assertIsDisplayed() + } + + @Test + fun `실제 기록 수는 천 단위로 끊어 그린다`() { + composeRule.setContent { + AfternoteTheme { card(totalCount = 1234) } + } + + composeRule.onNodeWithText("1,234").assertIsDisplayed() + } + + @androidx.compose.runtime.Composable + private fun card(totalCount: Int?) { + RecordCategoryCard( + iconResId = CoreUiR.drawable.core_ui_ic_diary, + title = "일기", + subtitle = "나의 매일을 기록하세요", + totalCount = totalCount, + onClick = {}, + ) + } +}