diff --git a/core/designsystem/src/main/java/com/susu/core/designsystem/component/searchbar/SusuSearchBar.kt b/core/designsystem/src/main/java/com/susu/core/designsystem/component/searchbar/SusuSearchBar.kt index 9a74dd2e..15d2bad1 100644 --- a/core/designsystem/src/main/java/com/susu/core/designsystem/component/searchbar/SusuSearchBar.kt +++ b/core/designsystem/src/main/java/com/susu/core/designsystem/component/searchbar/SusuSearchBar.kt @@ -30,6 +30,7 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.susu.core.designsystem.R +import com.susu.core.designsystem.component.button.ClearIconButton import com.susu.core.designsystem.theme.Gray100 import com.susu.core.designsystem.theme.Gray20 import com.susu.core.designsystem.theme.Gray60 @@ -40,6 +41,7 @@ fun SusuSearchBar( modifier: Modifier = Modifier, value: String, onValueChange: (String) -> Unit = {}, + onClickClearIcon: () -> Unit = {}, maxLines: Int = 1, minLines: Int = 1, textColor: Color = Gray100, @@ -94,6 +96,13 @@ fun SusuSearchBar( ) } } + + if (value.isNotEmpty()) { + ClearIconButton( + iconSize = 24.dp, + onClick = onClickClearIcon, + ) + } } }, ) @@ -104,7 +113,7 @@ fun SusuSearchBar( fun SusuSearchBarPreview() { SusuTheme { var text by remember { - mutableStateOf("") + mutableStateOf("zzzz") } SusuSearchBar( diff --git a/core/model/src/main/java/com/susu/core/model/Category.kt b/core/model/src/main/java/com/susu/core/model/Category.kt new file mode 100644 index 00000000..e35d01ed --- /dev/null +++ b/core/model/src/main/java/com/susu/core/model/Category.kt @@ -0,0 +1,8 @@ +package com.susu.core.model + +data class Category( + val id: Int, + val seq: Int, + val category: String, + val customCategory: String? = null, +) diff --git a/core/model/src/main/java/com/susu/core/model/Ledger.kt b/core/model/src/main/java/com/susu/core/model/Ledger.kt new file mode 100644 index 00000000..fced05c1 --- /dev/null +++ b/core/model/src/main/java/com/susu/core/model/Ledger.kt @@ -0,0 +1,15 @@ +package com.susu.core.model + +import androidx.compose.runtime.Stable +import java.time.LocalDateTime + +@Stable +data class Ledger( + val id: Int, + val title: String, + val description: String, + val startAt: LocalDateTime, + val endAt: LocalDateTime, + val category: Category, + val totalAmounts: Int, +) diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/main/res/values/strings.xml index 19e91fa6..2d9826d0 100644 --- a/core/ui/src/main/res/values/strings.xml +++ b/core/ui/src/main/res/values/strings.xml @@ -5,6 +5,7 @@ 금액 높은 순 금액 낮은 순 최근 검색 + 검색 결과 편집 저장 삭제 diff --git a/data/src/main/java/com/susu/data/data/di/RepositoryModule.kt b/data/src/main/java/com/susu/data/data/di/RepositoryModule.kt index a9b67d77..34902eb2 100644 --- a/data/src/main/java/com/susu/data/data/di/RepositoryModule.kt +++ b/data/src/main/java/com/susu/data/data/di/RepositoryModule.kt @@ -1,11 +1,13 @@ package com.susu.data.data.di import com.susu.data.data.repository.LedgerRecentSearchRepositoryImpl +import com.susu.data.data.repository.LedgerRepositoryImpl import com.susu.data.data.repository.LoginRepositoryImpl import com.susu.data.data.repository.SignUpRepositoryImpl import com.susu.data.data.repository.TermRepositoryImpl import com.susu.data.data.repository.TokenRepositoryImpl import com.susu.domain.repository.LedgerRecentSearchRepository +import com.susu.domain.repository.LedgerRepository import com.susu.domain.repository.LoginRepository import com.susu.domain.repository.SignUpRepository import com.susu.domain.repository.TermRepository @@ -43,4 +45,9 @@ abstract class RepositoryModule { abstract fun bindTermRepository( termRepositoryImpl: TermRepositoryImpl, ): TermRepository + + @Binds + abstract fun bindLedgerRepository( + ledgerRepositoryImpl: LedgerRepositoryImpl, + ): LedgerRepository } diff --git a/data/src/main/java/com/susu/data/data/repository/LedgerRepositoryImpl.kt b/data/src/main/java/com/susu/data/data/repository/LedgerRepositoryImpl.kt new file mode 100644 index 00000000..4f0e75df --- /dev/null +++ b/data/src/main/java/com/susu/data/data/repository/LedgerRepositoryImpl.kt @@ -0,0 +1,31 @@ +package com.susu.data.data.repository + +import com.susu.core.model.Ledger +import com.susu.data.remote.api.LedgerService +import com.susu.data.remote.model.response.toModel +import com.susu.domain.repository.LedgerRepository +import kotlinx.datetime.toKotlinLocalDateTime +import java.time.LocalDateTime +import javax.inject.Inject + +class LedgerRepositoryImpl @Inject constructor( + private val ledgerService: LedgerService, +) : LedgerRepository { + override suspend fun getLedgerList( + title: String?, + categoryId: Long?, + fromStartAt: LocalDateTime, + toEndAt: LocalDateTime, + page: Int?, + sort: String?, + ): List { + return ledgerService.getLedgerList( + title = title, + categoryId = categoryId, + fromStartAt = fromStartAt.toKotlinLocalDateTime(), + toEndAt = toEndAt.toKotlinLocalDateTime(), + page = page, + sort = sort, + ).getOrThrow().toModel() + } +} diff --git a/data/src/main/java/com/susu/data/remote/api/LedgerService.kt b/data/src/main/java/com/susu/data/remote/api/LedgerService.kt new file mode 100644 index 00000000..e24872b9 --- /dev/null +++ b/data/src/main/java/com/susu/data/remote/api/LedgerService.kt @@ -0,0 +1,19 @@ +package com.susu.data.remote.api + +import com.susu.data.remote.model.response.LedgerListResponse +import com.susu.data.remote.retrofit.ApiResult +import kotlinx.datetime.LocalDateTime +import retrofit2.http.GET +import retrofit2.http.Query + +interface LedgerService { + @GET("ledgers") + suspend fun getLedgerList( + @Query("title") title: String?, + @Query("categoryId") categoryId: Long?, + @Query("fromStartAt") fromStartAt: LocalDateTime, + @Query("toEndAt") toEndAt: LocalDateTime, + @Query("page") page: Int?, + @Query("sort") sort: String?, + ): ApiResult +} diff --git a/data/src/main/java/com/susu/data/remote/di/ApiServiceModule.kt b/data/src/main/java/com/susu/data/remote/di/ApiServiceModule.kt index 7ddec6cc..aa41241f 100644 --- a/data/src/main/java/com/susu/data/remote/di/ApiServiceModule.kt +++ b/data/src/main/java/com/susu/data/remote/di/ApiServiceModule.kt @@ -1,5 +1,6 @@ package com.susu.data.remote.di +import com.susu.data.remote.api.LedgerService import com.susu.data.remote.api.SignUpService import com.susu.data.remote.api.TermService import com.susu.data.remote.api.TokenService @@ -39,4 +40,10 @@ object ApiServiceModule { fun providesTermService(retrofit: Retrofit): TermService { return retrofit.create(TermService::class.java) } + + @Singleton + @Provides + fun providesLedgerService(retrofit: Retrofit): LedgerService { + return retrofit.create(LedgerService::class.java) + } } diff --git a/data/src/main/java/com/susu/data/remote/model/response/LedgerListResponse.kt b/data/src/main/java/com/susu/data/remote/model/response/LedgerListResponse.kt new file mode 100644 index 00000000..71eeb782 --- /dev/null +++ b/data/src/main/java/com/susu/data/remote/model/response/LedgerListResponse.kt @@ -0,0 +1,72 @@ +package com.susu.data.remote.model.response + +import com.susu.core.model.Category +import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.toJavaLocalDateTime +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class LedgerListResponse( + @SerialName("data") + val ledgerList: List, + val page: Int, + val size: Int, + val totalPage: Int, + val totalCount: Int, + val sort: SortInfo, +) + +@Serializable +data class Ledger( + @SerialName("ledger") + val info: LedgerInfo, + val category: CategoryInfo, + val totalAmounts: Int, + val totalCounts: Int, +) + +@Serializable +data class LedgerInfo( + val id: Int, + val title: String, + val description: String, + val startAt: LocalDateTime, + val endAt: LocalDateTime, +) + +@Serializable +data class CategoryInfo( + val id: Int, + val seq: Int, + val category: String, + val customCategory: String? = null, +) + +@Serializable +data class SortInfo( + val empty: Boolean, + val unsorted: Boolean, + val sorted: Boolean, +) + +internal fun LedgerListResponse.toModel() = this.ledgerList.map { ledger -> + with(ledger) { + com.susu.core.model.Ledger( + id = info.id, + title = info.title, + description = info.description, + startAt = info.startAt.toJavaLocalDateTime(), + endAt = info.endAt.toJavaLocalDateTime(), + category = category.toModel(), + totalAmounts = totalAmounts, + ) + } +} + +internal fun CategoryInfo.toModel() = Category( + id = id, + seq = seq, + category = category, + customCategory = customCategory, +) diff --git a/domain/src/main/java/com/susu/domain/repository/LedgerRepository.kt b/domain/src/main/java/com/susu/domain/repository/LedgerRepository.kt new file mode 100644 index 00000000..97602be5 --- /dev/null +++ b/domain/src/main/java/com/susu/domain/repository/LedgerRepository.kt @@ -0,0 +1,15 @@ +package com.susu.domain.repository + +import com.susu.core.model.Ledger +import java.time.LocalDateTime + +interface LedgerRepository { + suspend fun getLedgerList( + title: String?, + categoryId: Long?, + fromStartAt: LocalDateTime, + toEndAt: LocalDateTime, + page: Int?, + sort: String?, + ): List +} diff --git a/domain/src/main/java/com/susu/domain/usecase/ledger/GetLedgerListUseCase.kt b/domain/src/main/java/com/susu/domain/usecase/ledger/GetLedgerListUseCase.kt new file mode 100644 index 00000000..edb20111 --- /dev/null +++ b/domain/src/main/java/com/susu/domain/usecase/ledger/GetLedgerListUseCase.kt @@ -0,0 +1,32 @@ +package com.susu.domain.usecase.ledger + +import com.susu.core.common.runCatchingIgnoreCancelled +import com.susu.domain.repository.LedgerRepository +import java.time.LocalDateTime +import javax.inject.Inject + +class GetLedgerListUseCase @Inject constructor( + private val ledgerRepository: LedgerRepository, +) { + suspend operator fun invoke(param: Param) = runCatchingIgnoreCancelled { + with(param) { + ledgerRepository.getLedgerList( + title = title, + categoryId = categoryId, + fromStartAt = fromStartAt, + toEndAt = toEndAt, + page = page, + sort = sort, + ) + } + } + + data class Param( + val title: String? = null, + val categoryId: Long? = null, + val fromStartAt: LocalDateTime = LocalDateTime.now().minusYears(10), + val toEndAt: LocalDateTime = LocalDateTime.now(), + val page: Int? = null, + val sort: String? = null, + ) +} diff --git a/feature/received/src/main/java/com/susu/feature/received/navigation/ReceivedNavigation.kt b/feature/received/src/main/java/com/susu/feature/received/navigation/ReceivedNavigation.kt index b83df67b..867246b8 100644 --- a/feature/received/src/main/java/com/susu/feature/received/navigation/ReceivedNavigation.kt +++ b/feature/received/src/main/java/com/susu/feature/received/navigation/ReceivedNavigation.kt @@ -74,6 +74,7 @@ fun NavGraphBuilder.receivedNavGraph( composable(route = ReceivedRoute.ledgerSearchRoute) { LedgerSearchRoute( popBackStack = popBackStack, + navigateLedgerDetail = navigateLedgerDetail, ) } composable( diff --git a/feature/received/src/main/java/com/susu/feature/received/search/LedgerSearchContract.kt b/feature/received/src/main/java/com/susu/feature/received/search/LedgerSearchContract.kt index 8033b589..f7a2e55d 100644 --- a/feature/received/src/main/java/com/susu/feature/received/search/LedgerSearchContract.kt +++ b/feature/received/src/main/java/com/susu/feature/received/search/LedgerSearchContract.kt @@ -1,5 +1,6 @@ package com.susu.feature.received.search +import com.susu.core.model.Ledger import com.susu.core.ui.base.SideEffect import com.susu.core.ui.base.UiState import kotlinx.collections.immutable.PersistentList @@ -7,10 +8,13 @@ import kotlinx.collections.immutable.persistentListOf data class LedgerSearchState( val searchKeyword: String = "", - val searchKeywordList: PersistentList = persistentListOf(), + val recentSearchKeywordList: PersistentList = persistentListOf(), + val ledgerList: PersistentList = persistentListOf(), val isLoading: Boolean = false, + val showSearchResultEmpty: Boolean = false, ) : UiState sealed interface LedgerSearchSideEffect : SideEffect { data object PopBackStack : LedgerSearchSideEffect + data class NavigateLedgerDetail(val id: Int) : LedgerSearchSideEffect } diff --git a/feature/received/src/main/java/com/susu/feature/received/search/LedgerSearchScreen.kt b/feature/received/src/main/java/com/susu/feature/received/search/LedgerSearchScreen.kt index c1a4e465..2d968a6e 100644 --- a/feature/received/src/main/java/com/susu/feature/received/search/LedgerSearchScreen.kt +++ b/feature/received/src/main/java/com/susu/feature/received/search/LedgerSearchScreen.kt @@ -1,5 +1,6 @@ package com.susu.feature.received.search +import androidx.compose.animation.Crossfade import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -7,10 +8,10 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -26,19 +27,25 @@ import com.susu.core.designsystem.component.searchbar.SusuSearchBar import com.susu.core.designsystem.theme.Gray60 import com.susu.core.designsystem.theme.Gray80 import com.susu.core.designsystem.theme.SusuTheme +import com.susu.core.model.Ledger import com.susu.core.ui.extension.collectWithLifecycle import com.susu.feature.received.R import kotlinx.collections.immutable.PersistentList +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.flow.debounce +@OptIn(FlowPreview::class) @Composable fun LedgerSearchRoute( viewModel: LedgerSearchViewModel = hiltViewModel(), popBackStack: () -> Unit, + navigateLedgerDetail: (Int) -> Unit, ) { val uiState = viewModel.uiState.collectAsStateWithLifecycle().value viewModel.sideEffect.collectWithLifecycle { sideEffect -> when (sideEffect) { LedgerSearchSideEffect.PopBackStack -> popBackStack() + is LedgerSearchSideEffect.NavigateLedgerDetail -> navigateLedgerDetail(sideEffect.id) } } @@ -46,15 +53,25 @@ fun LedgerSearchRoute( viewModel.getLedgerRecentSearchList() } + LaunchedEffect(key1 = uiState.searchKeyword) { + snapshotFlow { uiState.searchKeyword } + .debounce(100L) + .collect(viewModel::getLedgerList) + } + LedgerSearchScreen( uiState = uiState, onClickBackIcon = viewModel::popBackStack, onValueChangeSearchBar = viewModel::updateSearch, - onClickRecentSearchContainer = viewModel::upsertLedgerRecentSearch, + onClickSearchClearIcon = { viewModel.updateSearch("") }, + onClickRecentSearchContainer = { search -> + viewModel.updateSearch(search) + viewModel.upsertLedgerRecentSearch(search) + }, onClickRecentSearchContainerCloseIcon = viewModel::deleteLedgerRecentSearch, - onSearchDone = { - viewModel.upsertLedgerRecentSearch(it) - viewModel.updateSearch("") + onClickSearchResultContainer = { + viewModel.upsertLedgerRecentSearch(it.title) + viewModel.navigateLedgerDetail(it.id) }, ) } @@ -63,10 +80,11 @@ fun LedgerSearchRoute( fun LedgerSearchScreen( uiState: LedgerSearchState = LedgerSearchState(), onClickBackIcon: () -> Unit = {}, + onClickSearchClearIcon: () -> Unit = {}, onValueChangeSearchBar: (String) -> Unit = {}, onClickRecentSearchContainer: (String) -> Unit = {}, onClickRecentSearchContainerCloseIcon: (String) -> Unit = {}, - onSearchDone: (String) -> Unit = {}, // TODO REMOVE -> 테스트 용 + onClickSearchResultContainer: (Ledger) -> Unit = {}, ) { Box( modifier = Modifier @@ -90,23 +108,24 @@ fun LedgerSearchScreen( SusuSearchBar( value = uiState.searchKeyword, onValueChange = onValueChangeSearchBar, + onClickClearIcon = onClickSearchClearIcon, placeholder = stringResource(R.string.ledger_search_screen_search_placeholder), - keyboardActions = KeyboardActions( - onDone = { - // TODO REMOVE -> 테스트 용 - onSearchDone(uiState.searchKeyword) - }, - ), ) - if (uiState.searchKeywordList.isEmpty()) { - RecentSearchEmptyScreen() - } else { - RecentSearchScreen( - recentSearchList = uiState.searchKeywordList, - onClickItem = onClickRecentSearchContainer, - onClickCloseIcon = onClickRecentSearchContainerCloseIcon, - ) + Crossfade(targetState = uiState.searchKeyword.isEmpty(), label = "SearchColumn") { showRecentSearch -> + if (showRecentSearch) { + RecentSearchColumn( + recentSearchList = uiState.recentSearchKeywordList, + onClickItem = onClickRecentSearchContainer, + onClickCloseIcon = onClickRecentSearchContainerCloseIcon, + ) + } else { + SearchResultColumn( + showSearchResultEmpty = uiState.showSearchResultEmpty, + ledgerList = uiState.ledgerList, + onClickItem = onClickSearchResultContainer, + ) + } } } } @@ -114,19 +133,21 @@ fun LedgerSearchScreen( } @Composable -private fun RecentSearchEmptyScreen() { +private fun ResultEmptyColumn( + title: String, +) { Column( modifier = Modifier.fillMaxWidth().padding(top = 136.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(SusuTheme.spacing.spacing_xxxxs), ) { Text( - text = stringResource(R.string.ledger_search_screen_empty_recent_search_title), + text = title, style = SusuTheme.typography.title_xs, color = Gray80, ) Text( - text = stringResource(R.string.ledger_search_screen_empty_recent_search_description), + text = stringResource(R.string.ledger_search_screen_empty_search_description), style = SusuTheme.typography.text_xxs, textAlign = TextAlign.Center, color = Gray80, @@ -135,26 +156,63 @@ private fun RecentSearchEmptyScreen() { } @Composable -private fun RecentSearchScreen( +private fun RecentSearchColumn( recentSearchList: PersistentList, onClickItem: (String) -> Unit, onClickCloseIcon: (String) -> Unit, ) { - Column( - modifier = Modifier.padding(top = SusuTheme.spacing.spacing_xxl), - verticalArrangement = Arrangement.spacedBy(SusuTheme.spacing.spacing_m), - ) { - Text( - text = stringResource(com.susu.core.ui.R.string.word_recent_search), - style = SusuTheme.typography.title_xxs, - color = Gray60, + if (recentSearchList.isEmpty()) { + ResultEmptyColumn( + title = stringResource(R.string.ledger_search_screen_empty_recent_search_title), ) - recentSearchList.forEach { name -> - SusuRecentSearchContainer( - text = name, - onClick = { onClickItem(name) }, - onClickCloseIcon = { onClickCloseIcon(name) }, + } else { + Column( + modifier = Modifier.padding(top = SusuTheme.spacing.spacing_xxl), + verticalArrangement = Arrangement.spacedBy(SusuTheme.spacing.spacing_m), + ) { + Text( + text = stringResource(com.susu.core.ui.R.string.word_recent_search), + style = SusuTheme.typography.title_xxs, + color = Gray60, ) + recentSearchList.forEach { name -> + SusuRecentSearchContainer( + text = name, + onClick = { onClickItem(name) }, + onClickCloseIcon = { onClickCloseIcon(name) }, + ) + } + } + } +} + +@Composable +private fun SearchResultColumn( + showSearchResultEmpty: Boolean, + ledgerList: PersistentList, + onClickItem: (Ledger) -> Unit, +) { + if (showSearchResultEmpty) { + ResultEmptyColumn( + title = stringResource(R.string.ledger_search_screen_empty_search_result_title), + ) + } else { + Column( + modifier = Modifier.padding(top = SusuTheme.spacing.spacing_xxl), + verticalArrangement = Arrangement.spacedBy(SusuTheme.spacing.spacing_m), + ) { + Text( + text = stringResource(com.susu.core.ui.R.string.word_search_result), + style = SusuTheme.typography.title_xxs, + color = Gray60, + ) + ledgerList.forEach { ledger -> + SusuRecentSearchContainer( + typeIconId = R.drawable.ic_ledger, + text = ledger.title, + onClick = { onClickItem(ledger) }, + ) + } } } } diff --git a/feature/received/src/main/java/com/susu/feature/received/search/LedgerSearchViewModel.kt b/feature/received/src/main/java/com/susu/feature/received/search/LedgerSearchViewModel.kt index 59ad5003..d8210429 100644 --- a/feature/received/src/main/java/com/susu/feature/received/search/LedgerSearchViewModel.kt +++ b/feature/received/src/main/java/com/susu/feature/received/search/LedgerSearchViewModel.kt @@ -2,6 +2,7 @@ package com.susu.feature.received.search import androidx.lifecycle.viewModelScope import com.susu.core.ui.base.BaseViewModel +import com.susu.domain.usecase.ledger.GetLedgerListUseCase import com.susu.domain.usecase.ledgerrecentsearch.DeleteLedgerRecentSearchUseCase import com.susu.domain.usecase.ledgerrecentsearch.GetLedgerRecentSearchListUseCase import com.susu.domain.usecase.ledgerrecentsearch.UpsertLedgerRecentSearchUseCase @@ -15,9 +16,12 @@ class LedgerSearchViewModel @Inject constructor( private val upsertLedgerRecentSearchUseCase: UpsertLedgerRecentSearchUseCase, private val getLedgerRecentSearchListUseCase: GetLedgerRecentSearchListUseCase, private val deleteLedgerRecentSearchUseCase: DeleteLedgerRecentSearchUseCase, + private val getLedgerListUseCase: GetLedgerListUseCase, ) : BaseViewModel( LedgerSearchState(), ) { + fun navigateLedgerDetail(id: Int) = postSideEffect(LedgerSearchSideEffect.NavigateLedgerDetail(id)) + fun getLedgerRecentSearchList() = viewModelScope.launch { getLedgerRecentSearchListUseCase() .onSuccess(::updateRecentSearchList) @@ -38,7 +42,17 @@ class LedgerSearchViewModel @Inject constructor( fun updateSearch(search: String) = intent { copy(searchKeyword = search) } + fun getLedgerList(search: String) = viewModelScope.launch { + getLedgerListUseCase(GetLedgerListUseCase.Param(title = search)) + .onSuccess { intent { copy(ledgerList = it.toPersistentList()) } } + } + fun popBackStack() = postSideEffect(LedgerSearchSideEffect.PopBackStack) - private fun updateRecentSearchList(searchList: List) = intent { copy(searchKeywordList = searchList.toPersistentList()) } + private fun updateRecentSearchList(searchList: List) = intent { + copy( + recentSearchKeywordList = searchList.toPersistentList(), + showSearchResultEmpty = searchList.isEmpty(), + ) + } } diff --git a/feature/received/src/main/res/drawable/ic_ledger.xml b/feature/received/src/main/res/drawable/ic_ledger.xml new file mode 100644 index 00000000..c58956bd --- /dev/null +++ b/feature/received/src/main/res/drawable/ic_ledger.xml @@ -0,0 +1,9 @@ + + + diff --git a/feature/received/src/main/res/values/strings.xml b/feature/received/src/main/res/values/strings.xml index 953a889e..cfdcf105 100644 --- a/feature/received/src/main/res/values/strings.xml +++ b/feature/received/src/main/res/values/strings.xml @@ -4,8 +4,9 @@ 필터 아이콘 아직 받은 장부가 없어요 받아요 - 장부 이름, 경조사 카테고리 등을\n검색해볼 수 있어요 + 장부 이름, 경조사 카테고리 등을\n검색해볼 수 있어요 어떤 장부를 찾아드릴까요? + 원하는 검색 결과가 없나요? 찾고 싶은 장부를 검색해보세요 아직 보낸 봉투가 없어요 받은 봉투 추가하기