From a83ad40ccc1141e716de37815126162268db3b5d Mon Sep 17 00:00:00 2001 From: JSPark <48265129+pknujsp@users.noreply.github.com> Date: Tue, 30 May 2023 00:50:11 +0900 Subject: [PATCH] =?UTF-8?q?#91=20=EC=88=98=EB=8F=99=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/data/remote/di/RepositoryModule.kt | 10 +++-- .../MedicineApprovalRepositoryImpl.kt | 10 ++++- .../data/search/SearchHistoryRepository.kt | 10 ++++- .../search/SearchHistoryRepositoryImpl.kt | 39 +++++++------------ .../searchhistory/SearchHistoryDao.kt | 14 ++++--- .../searchhistory/SearchHistoryDto.kt | 11 +++++- .../searchhistory/SearchHistoryMapper.kt | 7 +++- .../core/domain/SearchHistoryUseCase.kt | 3 +- .../core/ui/base/view/ButtonChip.kt | 2 + .../core/ui/base/view/SimpleListItemView.kt | 34 ++++++++-------- .../RecentCommentsAdapter.kt | 2 +- .../mediproject/feature/home/HomeFragment.kt | 13 +++---- .../home/src/main/res/navigation/home_nav.xml | 13 +++++-- .../mediproject/feature/news/NewsScreen.kt | 4 +- .../news/adminaction/AdminActionScreen.kt | 2 +- .../RecallSuspensionScreen.kt | 2 +- .../recentpenaltylist/PenaltyListAdapter.kt | 10 ++--- .../penalties/src/main/res/values/colors.xml | 4 ++ .../feature/search/SearchMedicinesFragment.kt | 14 ++++++- .../RecentSearchListFragment.kt | 1 + .../RecentSearchListViewModel.kt | 9 ++++- .../manual/ManualSearchResultFragment.kt | 8 ---- .../manual/ManualSearchResultViewModel.kt | 29 ++++++++++---- .../res/navigation/search_medicines_nav.xml | 14 ------- 24 files changed, 151 insertions(+), 114 deletions(-) create mode 100644 feature/penalties/src/main/res/values/colors.xml diff --git a/core/data/src/main/java/com/android/mediproject/core/data/remote/di/RepositoryModule.kt b/core/data/src/main/java/com/android/mediproject/core/data/remote/di/RepositoryModule.kt index ca6c9ec03..8da021b6d 100644 --- a/core/data/src/main/java/com/android/mediproject/core/data/remote/di/RepositoryModule.kt +++ b/core/data/src/main/java/com/android/mediproject/core/data/remote/di/RepositoryModule.kt @@ -46,9 +46,11 @@ object RepositoryModule { @Provides @Singleton fun provideMedicineApprovalRepository( - medicineApprovalDataSource: MedicineApprovalDataSource, searchHistoryRepository: SearchHistoryRepository + medicineApprovalDataSource: MedicineApprovalDataSource, + searchHistoryRepository: SearchHistoryRepository, + @Dispatcher(MediDispatchers.IO) ioDispatcher: CoroutineDispatcher ): MedicineApprovalRepository = MedicineApprovalRepositoryImpl( - medicineApprovalDataSource, searchHistoryRepository + medicineApprovalDataSource, searchHistoryRepository, ioDispatcher ) @Provides @@ -93,6 +95,6 @@ object RepositoryModule { @Provides @Singleton fun providesSearchHistoryRepository( - searchHistoryDao: SearchHistoryDao, @Dispatcher(MediDispatchers.IO) ioDispatcher: CoroutineDispatcher - ): SearchHistoryRepository = SearchHistoryRepositoryImpl(searchHistoryDao, ioDispatcher) + searchHistoryDao: SearchHistoryDao + ): SearchHistoryRepository = SearchHistoryRepositoryImpl(searchHistoryDao) } \ No newline at end of file diff --git a/core/data/src/main/java/com/android/mediproject/core/data/remote/medicineapproval/MedicineApprovalRepositoryImpl.kt b/core/data/src/main/java/com/android/mediproject/core/data/remote/medicineapproval/MedicineApprovalRepositoryImpl.kt index 548b69133..dd83457e9 100644 --- a/core/data/src/main/java/com/android/mediproject/core/data/remote/medicineapproval/MedicineApprovalRepositoryImpl.kt +++ b/core/data/src/main/java/com/android/mediproject/core/data/remote/medicineapproval/MedicineApprovalRepositoryImpl.kt @@ -4,11 +4,15 @@ import androidx.paging.Pager import androidx.paging.PagingConfig import androidx.paging.PagingData import com.android.mediproject.core.common.DATA_GO_KR_PAGE_SIZE +import com.android.mediproject.core.common.network.Dispatcher +import com.android.mediproject.core.common.network.MediDispatchers import com.android.mediproject.core.data.search.SearchHistoryRepository +import com.android.mediproject.core.database.searchhistory.SearchHistoryDto import com.android.mediproject.core.model.medicine.medicineapproval.Item import com.android.mediproject.core.model.medicine.medicinedetailinfo.MedicineDetailInfoResponse import com.android.mediproject.core.network.datasource.medicineapproval.MedicineApprovalDataSource import com.android.mediproject.core.network.datasource.medicineapproval.MedicineApprovalListDataSourceImpl +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.channelFlow import kotlinx.coroutines.flow.collectLatest @@ -17,7 +21,9 @@ import kotlinx.coroutines.flow.map import javax.inject.Inject class MedicineApprovalRepositoryImpl @Inject constructor( - private val medicineApprovalDataSource: MedicineApprovalDataSource, private val searchHistoryRepository: SearchHistoryRepository + private val medicineApprovalDataSource: MedicineApprovalDataSource, + private val searchHistoryRepository: SearchHistoryRepository, + @Dispatcher(MediDispatchers.IO) private val ioDispatcher: CoroutineDispatcher ) : MedicineApprovalRepository { /** @@ -35,7 +41,7 @@ class MedicineApprovalRepositoryImpl @Inject constructor( if (itemName == null && entpName == null) { emptyFlow() } else { - searchHistoryRepository.insertSearchHistory(itemName ?: entpName!!) + searchHistoryRepository.insertSearchHistory(SearchHistoryDto(itemName ?: entpName!!)) Pager(config = PagingConfig(pageSize = DATA_GO_KR_PAGE_SIZE, prefetchDistance = 5), pagingSourceFactory = { MedicineApprovalListDataSourceImpl( medicineApprovalDataSource, itemName, entpName, medicationType diff --git a/core/data/src/main/java/com/android/mediproject/core/data/search/SearchHistoryRepository.kt b/core/data/src/main/java/com/android/mediproject/core/data/search/SearchHistoryRepository.kt index 5ac9b1357..219a09511 100644 --- a/core/data/src/main/java/com/android/mediproject/core/data/search/SearchHistoryRepository.kt +++ b/core/data/src/main/java/com/android/mediproject/core/data/search/SearchHistoryRepository.kt @@ -1,14 +1,22 @@ package com.android.mediproject.core.data.search +import androidx.annotation.WorkerThread import com.android.mediproject.core.database.searchhistory.SearchHistoryDto import kotlinx.coroutines.flow.Flow interface SearchHistoryRepository { - suspend fun insertSearchHistory(query: String) + @WorkerThread + suspend fun insertSearchHistory(searchHistoryDto: SearchHistoryDto) + + @WorkerThread suspend fun getSearchHistoryList(count: Int = 5): Flow> + @WorkerThread + suspend fun deleteSearchHistory(id: Long) + @WorkerThread + suspend fun deleteAllSearchHistory() } \ No newline at end of file diff --git a/core/data/src/main/java/com/android/mediproject/core/data/search/SearchHistoryRepositoryImpl.kt b/core/data/src/main/java/com/android/mediproject/core/data/search/SearchHistoryRepositoryImpl.kt index 434698abc..cc462dfd7 100644 --- a/core/data/src/main/java/com/android/mediproject/core/data/search/SearchHistoryRepositoryImpl.kt +++ b/core/data/src/main/java/com/android/mediproject/core/data/search/SearchHistoryRepositoryImpl.kt @@ -1,44 +1,33 @@ package com.android.mediproject.core.data.search -import com.android.mediproject.core.common.network.Dispatcher -import com.android.mediproject.core.common.network.MediDispatchers import com.android.mediproject.core.database.searchhistory.SearchHistoryDao import com.android.mediproject.core.database.searchhistory.SearchHistoryDto -import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.withContext -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter +import kotlinx.coroutines.runBlocking import javax.inject.Inject class SearchHistoryRepositoryImpl @Inject constructor( - private val searchHistoryDao: SearchHistoryDao, @Dispatcher(MediDispatchers.IO) private val ioDispatcher: CoroutineDispatcher + private val searchHistoryDao: SearchHistoryDao, ) : SearchHistoryRepository { - override suspend fun insertSearchHistory(query: String) { - withContext(ioDispatcher) { - searchHistoryDao.insert( - SearchHistoryDto( - query = query, id = 0L, searchDateTime = LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME) - ) - ) + override suspend fun insertSearchHistory(searchHistoryDto: SearchHistoryDto) = runBlocking { + searchHistoryDto.apply { + query = query.trim() } + if (!searchHistoryDao.isExist(searchHistoryDto.query)) searchHistoryDao.insert(searchHistoryDto) } - override suspend fun getSearchHistoryList(count: Int): Flow> = withContext(ioDispatcher) { - searchHistoryDao.select(count) - } + override suspend fun getSearchHistoryList(count: Int): Flow> = searchHistoryDao.select(count) - override suspend fun deleteSearchHistory(id: Long) { - withContext(ioDispatcher) { - searchHistoryDao.delete(id) - } + + override suspend fun deleteSearchHistory(id: Long) = runBlocking { + searchHistoryDao.delete(id) } - override suspend fun deleteAllSearchHistory() { - withContext(ioDispatcher) { - searchHistoryDao.deleteAll() - } + + override suspend fun deleteAllSearchHistory() = runBlocking { + searchHistoryDao.deleteAll() } + } \ No newline at end of file diff --git a/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryDao.kt b/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryDao.kt index c595def4a..7702bf244 100644 --- a/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryDao.kt +++ b/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryDao.kt @@ -1,8 +1,9 @@ package com.android.mediproject.core.database.searchhistory import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy import androidx.room.Query -import androidx.room.Upsert import kotlinx.coroutines.flow.Flow @Dao @@ -12,15 +13,15 @@ interface SearchHistoryDao { * 검색 기록을 추가한다. * @param searchHistoryDto */ - @Upsert - fun insert(searchHistoryDto: SearchHistoryDto) + @Insert(entity = SearchHistoryDto::class, onConflict = OnConflictStrategy.IGNORE) + suspend fun insert(SearchHistoryDto: SearchHistoryDto) /** * id에 해당하는 검색 기록을 삭제한다. * @param id */ @Query("DELETE FROM search_history_table WHERE id = :id") - fun delete(id: Long) + suspend fun delete(id: Long) /** * 개수 만큼 검색 목록을 가져온다. @@ -33,5 +34,8 @@ interface SearchHistoryDao { * 모든 검색 기록을 삭제한다. */ @Query("DELETE FROM search_history_table") - fun deleteAll() + suspend fun deleteAll() + + @Query("SELECT EXISTS (SELECT * FROM search_history_table WHERE `query` = :query)") + suspend fun isExist(query: String): Boolean } \ No newline at end of file diff --git a/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryDto.kt b/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryDto.kt index 9c490ce70..da7282b06 100644 --- a/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryDto.kt +++ b/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryDto.kt @@ -8,5 +8,12 @@ import androidx.room.PrimaryKey data class SearchHistoryDto( @PrimaryKey(autoGenerate = true) val id: Long, - @ColumnInfo(name = "query") val query: String, @ColumnInfo(name = "search_date_time") val searchDateTime: String -) \ No newline at end of file + @ColumnInfo(name = "query") var query: String, + + @ColumnInfo( + name = "search_date_time", defaultValue = "CURRENT_TIMESTAMP" + ) val searchDateTime: String + +) { + constructor(query: String) : this(0, query, "") +} \ No newline at end of file diff --git a/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryMapper.kt b/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryMapper.kt index fa2ef8e01..cdf9d80c9 100644 --- a/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryMapper.kt +++ b/core/database/src/main/java/com/android/mediproject/core/database/searchhistory/SearchHistoryMapper.kt @@ -1,9 +1,12 @@ package com.android.mediproject.core.database.searchhistory import java.time.LocalDateTime +import java.time.format.DateTimeFormatter fun SearchHistoryDto.toSearchHistoryItemDto(): com.android.mediproject.core.model.search.local.SearchHistoryItemDto { return com.android.mediproject.core.model.search.local.SearchHistoryItemDto( - id = id, query = query, searchedAt = LocalDateTime.parse(this.searchDateTime) + id = id, query = query, searchedAt = LocalDateTime.parse(this.searchDateTime, dateTimeFormatter) ) -} \ No newline at end of file +} + +private val dateTimeFormatter by lazy { DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") } \ No newline at end of file diff --git a/core/domain/src/main/java/com/android/mediproject/core/domain/SearchHistoryUseCase.kt b/core/domain/src/main/java/com/android/mediproject/core/domain/SearchHistoryUseCase.kt index a047cc9d8..f45344a4a 100644 --- a/core/domain/src/main/java/com/android/mediproject/core/domain/SearchHistoryUseCase.kt +++ b/core/domain/src/main/java/com/android/mediproject/core/domain/SearchHistoryUseCase.kt @@ -1,6 +1,7 @@ package com.android.mediproject.core.domain import com.android.mediproject.core.data.search.SearchHistoryRepository +import com.android.mediproject.core.database.searchhistory.SearchHistoryDto import com.android.mediproject.core.database.searchhistory.toSearchHistoryItemDto import kotlinx.coroutines.flow.map import javax.inject.Inject @@ -10,7 +11,7 @@ import javax.inject.Singleton class SearchHistoryUseCase @Inject constructor( private val searchHistoryRepository: SearchHistoryRepository ) { - suspend fun insertSearchHistory(query: String) = searchHistoryRepository.insertSearchHistory(query) + suspend fun insertSearchHistory(query: String) = searchHistoryRepository.insertSearchHistory(SearchHistoryDto(query)) suspend fun getSearchHistoryList(count: Int) = searchHistoryRepository.getSearchHistoryList(count).map { it.map { diff --git a/core/ui/src/main/java/com/android/mediproject/core/ui/base/view/ButtonChip.kt b/core/ui/src/main/java/com/android/mediproject/core/ui/base/view/ButtonChip.kt index f5d23d2b4..cc9b60d5f 100644 --- a/core/ui/src/main/java/com/android/mediproject/core/ui/base/view/ButtonChip.kt +++ b/core/ui/src/main/java/com/android/mediproject/core/ui/base/view/ButtonChip.kt @@ -64,4 +64,6 @@ class ButtonChip : Chip { listener.onClick(data) } } + + } \ No newline at end of file diff --git a/core/ui/src/main/java/com/android/mediproject/core/ui/base/view/SimpleListItemView.kt b/core/ui/src/main/java/com/android/mediproject/core/ui/base/view/SimpleListItemView.kt index b5e06abd9..a6b752db7 100644 --- a/core/ui/src/main/java/com/android/mediproject/core/ui/base/view/SimpleListItemView.kt +++ b/core/ui/src/main/java/com/android/mediproject/core/ui/base/view/SimpleListItemView.kt @@ -18,8 +18,8 @@ import com.android.mediproject.core.ui.R */ class SimpleListItemView : ConstraintLayout { - constructor(context: Context) : super(context, null) { - init(context, null) + constructor(context: Context, midRatio: Float) : super(context, null) { + init(context, null, midRatio) } constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs) { @@ -42,25 +42,13 @@ class SimpleListItemView : ConstraintLayout { get() = _data @SuppressLint("ResourceType") private val chip = ButtonChip(context).apply { - layoutParams = ConstraintLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT).apply { - topToTop = LayoutParams.PARENT_ID - bottomToBottom = LayoutParams.PARENT_ID - leftToLeft = LayoutParams.PARENT_ID - } textSize = 13f isClickable = false id = 10 } @SuppressLint("ResourceType") private val textView = TextView(context).apply { - layoutParams = ConstraintLayout.LayoutParams(0, LayoutParams.WRAP_CONTENT).apply { - topToTop = LayoutParams.PARENT_ID - bottomToBottom = LayoutParams.PARENT_ID - leftToRight = chip.id - rightToRight = LayoutParams.PARENT_ID - leftMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f, resources.displayMetrics).toInt() - } - ellipsize = TextUtils.TruncateAt.MARQUEE + ellipsize = TextUtils.TruncateAt.END isClickable = false maxLines = 1 textAlignment = TEXT_ALIGNMENT_VIEW_START @@ -68,7 +56,7 @@ class SimpleListItemView : ConstraintLayout { id = 20 } - private fun init(context: Context, attrs: AttributeSet?) { + private fun init(context: Context, attrs: AttributeSet?, midRatio: Float = 0.6f) { context.theme.obtainStyledAttributes( attrs, R.styleable.SimpleCommentItemView, 0, 0 ).apply { @@ -81,8 +69,18 @@ class SimpleListItemView : ConstraintLayout { TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3f, resources.displayMetrics).toInt() .apply { setPadding(0, this, 0, this) } - addView(chip) - addView(textView) + addView(chip, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT).apply { + topToTop = LayoutParams.PARENT_ID + bottomToBottom = LayoutParams.PARENT_ID + leftToLeft = LayoutParams.PARENT_ID + }) + addView(textView, LayoutParams(0, LayoutParams.WRAP_CONTENT).apply { + topToTop = LayoutParams.PARENT_ID + bottomToBottom = LayoutParams.PARENT_ID + leftToRight = chip.id + rightToRight = LayoutParams.PARENT_ID + leftMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f, resources.displayMetrics).toInt() + }) isClickable = true diff --git a/feature/comments/src/main/java/com/android/mediproject/feature/comments/recentcommentlist/RecentCommentsAdapter.kt b/feature/comments/src/main/java/com/android/mediproject/feature/comments/recentcommentlist/RecentCommentsAdapter.kt index 6d8f63bad..273958cb7 100644 --- a/feature/comments/src/main/java/com/android/mediproject/feature/comments/recentcommentlist/RecentCommentsAdapter.kt +++ b/feature/comments/src/main/java/com/android/mediproject/feature/comments/recentcommentlist/RecentCommentsAdapter.kt @@ -32,7 +32,7 @@ class RecentCommentsAdapter : ListAdapter(FragmentHo } } setFragmentResultListener(RecentSearchListFragment.ResultKey.RESULT_KEY.name, viewLifecycleOwner) { _, bundle -> - bundle.apply { - findNavController().navigateByDeepLink( - "medilens://main/search/recentSearchListFragment", - SearchQueryArgs(getString(RecentSearchListFragment.ResultKey.WORD.name) ?: "") - ) - } + findNavController().navigate( + HomeFragmentDirections.actionHomeFragmentToSearchMedicinesFragment( + bundle.getString(RecentSearchListFragment.ResultKey.WORD.name) ?: "" + ) + ) } } } diff --git a/feature/home/src/main/res/navigation/home_nav.xml b/feature/home/src/main/res/navigation/home_nav.xml index 3383d2cfe..5fe40e180 100644 --- a/feature/home/src/main/res/navigation/home_nav.xml +++ b/feature/home/src/main/res/navigation/home_nav.xml @@ -16,10 +16,17 @@ - + + android:label="SearchMedicinesFragment" + tools:layout="@layout/fragment_search_medicines"> + + + + \ No newline at end of file diff --git a/feature/news/src/main/java/com/android/mediproject/feature/news/NewsScreen.kt b/feature/news/src/main/java/com/android/mediproject/feature/news/NewsScreen.kt index 6d717bafe..528d9ccb1 100644 --- a/feature/news/src/main/java/com/android/mediproject/feature/news/NewsScreen.kt +++ b/feature/news/src/main/java/com/android/mediproject/feature/news/NewsScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Divider import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FilterChip import androidx.compose.material3.FilterChipDefaults @@ -21,7 +22,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner @@ -49,7 +49,6 @@ enum class ChipType : Parcelable { /** * 뉴스 화면 */ -@Preview @Composable fun NewsNavHost( navController: NavHostController = rememberNavController(), startDestination: String = "news" @@ -89,6 +88,7 @@ fun NewsScreen(navController: NavController) { ChipGroup(selectedChip, onChipSelected = { chip -> selectedChip = chip }) + Divider(modifier = Modifier.padding(horizontal = 24.dp)) if (selectedChip == ChipType.RECALLS_SUSPENSION) RecallDisposalScreen(navController = navController) else { CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { diff --git a/feature/news/src/main/java/com/android/mediproject/feature/news/adminaction/AdminActionScreen.kt b/feature/news/src/main/java/com/android/mediproject/feature/news/adminaction/AdminActionScreen.kt index 91799819d..b3a7fe770 100644 --- a/feature/news/src/main/java/com/android/mediproject/feature/news/adminaction/AdminActionScreen.kt +++ b/feature/news/src/main/java/com/android/mediproject/feature/news/adminaction/AdminActionScreen.kt @@ -81,7 +81,7 @@ fun ListItem(adminActionListItemDto: AdminActionListItemDto) { Surface( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 24.dp, vertical = 9.dp), + .padding(horizontal = 24.dp, vertical = 20.dp), shape = RectangleShape, onClick = { adminActionListItemDto.onClick?.invoke() diff --git a/feature/news/src/main/java/com/android/mediproject/feature/news/recallsuspension/RecallSuspensionScreen.kt b/feature/news/src/main/java/com/android/mediproject/feature/news/recallsuspension/RecallSuspensionScreen.kt index f402debea..94faedf95 100644 --- a/feature/news/src/main/java/com/android/mediproject/feature/news/recallsuspension/RecallSuspensionScreen.kt +++ b/feature/news/src/main/java/com/android/mediproject/feature/news/recallsuspension/RecallSuspensionScreen.kt @@ -85,7 +85,7 @@ fun ListItem(recallSuspensionListItemDto: RecallSuspensionListItemDto) { Surface( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 24.dp, vertical = 9.dp), + .padding(horizontal = 24.dp, vertical = 20.dp), shape = RectangleShape, onClick = { recallSuspensionListItemDto.onClick?.invoke(recallSuspensionListItemDto) diff --git a/feature/penalties/src/main/java/com/android/mediproject/feature/penalties/recentpenaltylist/PenaltyListAdapter.kt b/feature/penalties/src/main/java/com/android/mediproject/feature/penalties/recentpenaltylist/PenaltyListAdapter.kt index 39a4fed78..87123aea9 100644 --- a/feature/penalties/src/main/java/com/android/mediproject/feature/penalties/recentpenaltylist/PenaltyListAdapter.kt +++ b/feature/penalties/src/main/java/com/android/mediproject/feature/penalties/recentpenaltylist/PenaltyListAdapter.kt @@ -1,12 +1,12 @@ package com.android.mediproject.feature.penalties.recentpenaltylist -import android.graphics.Color import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.android.mediproject.core.model.remote.recall.RecallSuspensionListItemDto import com.android.mediproject.core.ui.base.view.SimpleListItemView +import com.android.mediproject.feature.penalties.R class PenaltyListAdapter : ListAdapter(object : DiffUtil.ItemCallback() { @@ -21,9 +21,9 @@ class PenaltyListAdapter : ListAdapter(parent.context)) + PenaltyViewHolder(SimpleListItemView(parent.context, 0.6f)) override fun onBindViewHolder(holder: PenaltyViewHolder, position: Int) { holder.bind(getItem(position)) diff --git a/feature/penalties/src/main/res/values/colors.xml b/feature/penalties/src/main/res/values/colors.xml new file mode 100644 index 000000000..aa5e93fe2 --- /dev/null +++ b/feature/penalties/src/main/res/values/colors.xml @@ -0,0 +1,4 @@ + + + #32649F + \ No newline at end of file diff --git a/feature/search/src/main/java/com/android/mediproject/feature/search/SearchMedicinesFragment.kt b/feature/search/src/main/java/com/android/mediproject/feature/search/SearchMedicinesFragment.kt index b2491c568..3b29fda96 100644 --- a/feature/search/src/main/java/com/android/mediproject/feature/search/SearchMedicinesFragment.kt +++ b/feature/search/src/main/java/com/android/mediproject/feature/search/SearchMedicinesFragment.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.View import androidx.core.net.toUri import androidx.fragment.app.viewModels +import androidx.navigation.NavOptions import androidx.navigation.findNavController import androidx.navigation.fragment.findNavController import com.android.mediproject.core.common.uiutil.hideKeyboard @@ -21,7 +22,6 @@ class SearchMedicinesFragment : override val fragmentViewModel by viewModels() - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -61,9 +61,19 @@ class SearchMedicinesFragment : bundle.getString(RecentSearchListFragment.ResultKey.WORD.name)?.also { binding.searchView.searchWithQuery(it) } - } } + + // 검색어가 전달된 경우에는 검색어를 넣은 후 검색 + arguments?.getString("query")?.takeIf { + it.isNotEmpty() + }?.also { + binding.searchView.setText(it) + binding.contentsFragmentContainerView.findNavController().navigate( + RecentSearchListFragmentDirections.actionRecentSearchListFragmentToManualSearchResultFragment(), + NavOptions.Builder().setPopUpTo(R.id.manualSearchResultFragment, true).build() + ) + } } /** diff --git a/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListFragment.kt b/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListFragment.kt index a98e9e98c..8991d8974 100644 --- a/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListFragment.kt +++ b/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListFragment.kt @@ -58,6 +58,7 @@ class RecentSearchListFragment : } data = searchHistoryItemDto.query setChipText(data.toString()) + setOnChipClickListener { onClicked(searchHistoryItemDto.query) } diff --git a/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListViewModel.kt b/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListViewModel.kt index 49bfd9c0c..00d515d2f 100644 --- a/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListViewModel.kt +++ b/feature/search/src/main/java/com/android/mediproject/feature/search/recentsearchlist/RecentSearchListViewModel.kt @@ -1,20 +1,25 @@ package com.android.mediproject.feature.search.recentsearchlist import androidx.lifecycle.viewModelScope +import com.android.mediproject.core.common.network.Dispatcher +import com.android.mediproject.core.common.network.MediDispatchers import com.android.mediproject.core.domain.SearchHistoryUseCase import com.android.mediproject.core.ui.base.BaseViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.shareIn import javax.inject.Inject @HiltViewModel class RecentSearchListViewModel @Inject constructor( - private val searchHistoryUseCase: SearchHistoryUseCase + private val searchHistoryUseCase: SearchHistoryUseCase, + @Dispatcher(MediDispatchers.IO) private val ioDispatcher: CoroutineDispatcher, ) : BaseViewModel() { val searchHistoryList by lazy { suspend { - searchHistoryUseCase.getSearchHistoryList(6).shareIn( + searchHistoryUseCase.getSearchHistoryList(6).distinctUntilChanged().shareIn( viewModelScope, started = SharingStarted.Lazily, replay = 1 ) } diff --git a/feature/search/src/main/java/com/android/mediproject/feature/search/result/manual/ManualSearchResultFragment.kt b/feature/search/src/main/java/com/android/mediproject/feature/search/result/manual/ManualSearchResultFragment.kt index 25e2f62bd..7f41917ba 100644 --- a/feature/search/src/main/java/com/android/mediproject/feature/search/result/manual/ManualSearchResultFragment.kt +++ b/feature/search/src/main/java/com/android/mediproject/feature/search/result/manual/ManualSearchResultFragment.kt @@ -5,7 +5,6 @@ import android.view.View import androidx.core.content.ContextCompat import androidx.fragment.app.viewModels import androidx.navigation.findNavController -import androidx.navigation.fragment.navArgs import androidx.paging.map import androidx.recyclerview.widget.DividerItemDecoration import com.android.mediproject.core.common.paging.setOnStateChangedListener @@ -32,19 +31,12 @@ class ManualSearchResultFragment : override val fragmentViewModel: ManualSearchResultViewModel by viewModels() - private val searchQueryArgs: ManualSearchResultFragmentArgs by navArgs() - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.apply { viewModel = fragmentViewModel - - if (searchQueryArgs.query.isNotEmpty()) { - searchMedicinesViewModel.setQuery(searchQueryArgs.query) - } - val searchResultListAdapter = ApprovedMedicinesAdapter().also { it.withLoadStateHeaderAndFooter(header = PagingLoadStateAdapter { it.retry() }, footer = PagingLoadStateAdapter { it.retry() }) diff --git a/feature/search/src/main/java/com/android/mediproject/feature/search/result/manual/ManualSearchResultViewModel.kt b/feature/search/src/main/java/com/android/mediproject/feature/search/result/manual/ManualSearchResultViewModel.kt index 1b25463c8..18ea1e221 100644 --- a/feature/search/src/main/java/com/android/mediproject/feature/search/result/manual/ManualSearchResultViewModel.kt +++ b/feature/search/src/main/java/com/android/mediproject/feature/search/result/manual/ManualSearchResultViewModel.kt @@ -2,17 +2,23 @@ package com.android.mediproject.feature.search.result.manual import androidx.lifecycle.viewModelScope import androidx.paging.PagingData -import androidx.paging.cachedIn +import com.android.mediproject.core.common.network.Dispatcher +import com.android.mediproject.core.common.network.MediDispatchers +import com.android.mediproject.core.common.viewmodel.UiState import com.android.mediproject.core.domain.GetMedicineApprovalListUseCase import com.android.mediproject.core.model.constants.MedicationType -import com.android.mediproject.core.model.parameters.ApprovalListSearchParameter import com.android.mediproject.core.model.medicine.medicineapproval.ApprovedMedicineItemDto +import com.android.mediproject.core.model.parameters.ApprovalListSearchParameter import com.android.mediproject.core.ui.base.BaseViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.last import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @@ -27,6 +33,7 @@ import javax.inject.Inject @HiltViewModel class ManualSearchResultViewModel @Inject constructor( private val getMedicineApprovalListUseCase: GetMedicineApprovalListUseCase, + @Dispatcher(MediDispatchers.IO) private val ioDispatcher: CoroutineDispatcher, ) : BaseViewModel() { private val _searchParameter = MutableStateFlow( @@ -36,11 +43,19 @@ class ManualSearchResultViewModel @Inject constructor( ) val searchParameter = _searchParameter.asStateFlow() - val searchResultFlow: Flow> = searchParameter.flatMapLatest { parameter -> - getMedicineApprovalListUseCase.invoke( - parameter - ).cachedIn(viewModelScope) - } + val searchResultFlow: Flow>> = searchParameter.flatMapLatest { parameter -> + if (parameter.entpName.isNullOrEmpty() && parameter.itemName.isNullOrEmpty()) { + flowOf(UiState.Error("검색어를 입력해주세요")) + } else { + flowOf( + UiState.Success( + getMedicineApprovalListUseCase.invoke( + parameter + ).last() + ) + ) + } + }.flowOn(ioDispatcher) /** * 의약품명으로 검색 diff --git a/feature/search/src/main/res/navigation/search_medicines_nav.xml b/feature/search/src/main/res/navigation/search_medicines_nav.xml index e32b94d1e..8f0d553dd 100644 --- a/feature/search/src/main/res/navigation/search_medicines_nav.xml +++ b/feature/search/src/main/res/navigation/search_medicines_nav.xml @@ -11,13 +11,10 @@ android:label="RecentSearchListFragment" tools:layout="@layout/fragment_recent_search_list"> - - - - - - - - - -