diff --git a/app/src/main/java/com/zion830/threedollars/repository/model/v2/response/HomeStoreEmptyResponse.kt b/app/src/main/java/com/zion830/threedollars/repository/model/v2/response/HomeStoreEmptyResponse.kt new file mode 100644 index 00000000..da27bcc7 --- /dev/null +++ b/app/src/main/java/com/zion830/threedollars/repository/model/v2/response/HomeStoreEmptyResponse.kt @@ -0,0 +1,9 @@ +package com.zion830.threedollars.repository.model.v2.response + +import com.zion830.threedollars.R + +data class HomeStoreEmptyResponse( + val emptyImage: Int = R.drawable.ic_no_store, + val emptyTitle: Int = R.string.empty_store, + val emptyBody: Int = R.string.empty_store_msg +) : AdAndStoreItem \ No newline at end of file diff --git a/app/src/main/java/com/zion830/threedollars/repository/model/v2/response/PopupsResponse.kt b/app/src/main/java/com/zion830/threedollars/repository/model/v2/response/PopupsResponse.kt index 75ce24bd..91d30d4d 100644 --- a/app/src/main/java/com/zion830/threedollars/repository/model/v2/response/PopupsResponse.kt +++ b/app/src/main/java/com/zion830/threedollars/repository/model/v2/response/PopupsResponse.kt @@ -2,6 +2,7 @@ package com.zion830.threedollars.repository.model.v2.response import com.google.gson.annotations.SerializedName +interface AdAndStoreItem data class PopupsResponse( @SerializedName("data") @@ -14,9 +15,9 @@ data class PopupsResponse( data class Popups( @SerializedName("bgColor") - val bgColor: String = "", + val bgColor: String? = "", @SerializedName("fontColor") - val fontColor: String = "", + val fontColor: String? = "", @SerializedName("imageUrl") val imageUrl: String = "", @SerializedName("linkUrl") @@ -25,4 +26,4 @@ data class Popups( val subTitle: String = "", @SerializedName("title") val title: String = "" -) \ No newline at end of file +) : AdAndStoreItem \ No newline at end of file diff --git a/app/src/main/java/com/zion830/threedollars/repository/model/v2/response/store/StoreInfo.kt b/app/src/main/java/com/zion830/threedollars/repository/model/v2/response/store/StoreInfo.kt index bc6c8c4f..174d0c0a 100644 --- a/app/src/main/java/com/zion830/threedollars/repository/model/v2/response/store/StoreInfo.kt +++ b/app/src/main/java/com/zion830/threedollars/repository/model/v2/response/store/StoreInfo.kt @@ -1,6 +1,9 @@ package com.zion830.threedollars.repository.model.v2.response.store import com.google.gson.annotations.SerializedName +import com.zion830.threedollars.repository.model.v2.response.AdAndStoreItem + +interface StoreByMenuItem data class StoreInfo( @SerializedName("categories") @@ -25,4 +28,4 @@ data class StoreInfo( val visitHistory: VisitHistory = VisitHistory(), @SerializedName("isDeleted") val isDeleted: Boolean = false -) \ No newline at end of file +) : AdAndStoreItem \ No newline at end of file diff --git a/app/src/main/java/com/zion830/threedollars/ui/addstore/view/NearStoreNaverMapFragment.kt b/app/src/main/java/com/zion830/threedollars/ui/addstore/view/NearStoreNaverMapFragment.kt index 1f8765db..fa808c8e 100644 --- a/app/src/main/java/com/zion830/threedollars/ui/addstore/view/NearStoreNaverMapFragment.kt +++ b/app/src/main/java/com/zion830/threedollars/ui/addstore/view/NearStoreNaverMapFragment.kt @@ -36,7 +36,7 @@ class NearStoreNaverMapFragment(private val cameraMoved: () -> Unit = {}) : Nave } override fun onMyLocationLoaded(position: LatLng) { - viewModel.requestStoreInfo(position) + viewModel.requestHomeItem(position) viewModel.updateCurrentLocation(position) } diff --git a/app/src/main/java/com/zion830/threedollars/ui/category/SelectCategoryFragment.kt b/app/src/main/java/com/zion830/threedollars/ui/category/SelectCategoryFragment.kt index 65e1a1cf..7c6ca5d0 100644 --- a/app/src/main/java/com/zion830/threedollars/ui/category/SelectCategoryFragment.kt +++ b/app/src/main/java/com/zion830/threedollars/ui/category/SelectCategoryFragment.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import android.content.Intent import android.graphics.Color import android.net.Uri +import androidx.core.graphics.toColorInt import androidx.core.text.bold import androidx.core.text.buildSpannedString import androidx.core.view.isVisible @@ -19,6 +20,7 @@ import com.zion830.threedollars.repository.model.v2.response.store.CategoryInfo import com.zion830.threedollars.ui.category.adapter.SelectCategoryRecyclerAdapter import com.zion830.threedollars.ui.popup.PopupViewModel import zion830.com.common.base.BaseFragment +import zion830.com.common.base.loadUrlImg import zion830.com.common.listener.OnItemClickListener class SelectCategoryFragment : @@ -65,17 +67,16 @@ class SelectCategoryFragment : if (popups.isNotEmpty()) { val popup = popups[0] binding.tvAdTitle.text = popup.title - binding.tvAdTitle.setTextColor(Color.parseColor(popup.fontColor)) binding.tvAdBody.text = popup.subTitle - binding.tvAdBody.setTextColor(Color.parseColor(popup.fontColor)) - binding.cdAdCategory.setCardBackgroundColor(Color.parseColor(popup.bgColor)) + popup.fontColor?.let { + binding.tvAdTitle.setTextColor(it.toColorInt()) + binding.tvAdBody.setTextColor(it.toColorInt()) + } + popup.bgColor?.let { binding.cdAdCategory.setCardBackgroundColor(it.toColorInt()) } - Glide.with(requireContext()) - .load(popup.imageUrl) - .transition(DrawableTransitionOptions.withCrossFade()) - .into(binding.ivAdImage) + binding.ivAdImage.loadUrlImg(popup.imageUrl) binding.cdAdCategory.setOnClickListener { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(popup.linkUrl))) diff --git a/app/src/main/java/com/zion830/threedollars/ui/category/StoreByMenuActivity.kt b/app/src/main/java/com/zion830/threedollars/ui/category/StoreByMenuActivity.kt index c10a000e..0ab7f871 100644 --- a/app/src/main/java/com/zion830/threedollars/ui/category/StoreByMenuActivity.kt +++ b/app/src/main/java/com/zion830/threedollars/ui/category/StoreByMenuActivity.kt @@ -2,26 +2,36 @@ package com.zion830.threedollars.ui.category import android.content.Context import android.content.Intent +import android.net.Uri import androidx.activity.viewModels +import androidx.core.graphics.toColorInt +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.google.android.gms.ads.AdRequest import com.zion830.threedollars.R import com.zion830.threedollars.databinding.ActivityStoreByMenuBinding +import com.zion830.threedollars.repository.model.v2.response.Popups import com.zion830.threedollars.repository.model.v2.response.store.CategoryInfo import com.zion830.threedollars.repository.model.v2.response.store.StoreInfo import com.zion830.threedollars.ui.category.adapter.SearchByDistanceRecyclerAdapter import com.zion830.threedollars.ui.category.adapter.SearchByRatingRecyclerAdapter +import com.zion830.threedollars.ui.popup.PopupViewModel import com.zion830.threedollars.ui.store_detail.StoreDetailActivity import com.zion830.threedollars.ui.store_detail.map.StoreByMenuNaverMapFragment import com.zion830.threedollars.ui.store_detail.vm.StoreByMenuViewModel import com.zion830.threedollars.utils.* import zion830.com.common.base.BaseActivity +import zion830.com.common.base.loadUrlImg import zion830.com.common.listener.OnItemClickListener class StoreByMenuActivity : - BaseActivity(R.layout.activity_store_by_menu), OnMapTouchListener { + BaseActivity(R.layout.activity_store_by_menu), + OnMapTouchListener { override val viewModel: StoreByMenuViewModel by viewModels() + private val popupViewModel: PopupViewModel by viewModels() + private lateinit var menuType: CategoryInfo private val listener = object : OnItemClickListener { @@ -30,12 +40,17 @@ class StoreByMenuActivity : startActivity(intent) } } + private val adListener = object : OnItemClickListener { + override fun onClick(item: Popups) { + startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(item.linkUrl))) + } + } private val storeByDistanceAdapters by lazy { - SearchByDistanceRecyclerAdapter(listener) + SearchByDistanceRecyclerAdapter(listener, adListener) } private val storeByRatingAdapters by lazy { - SearchByRatingRecyclerAdapter(listener) + SearchByRatingRecyclerAdapter(listener, adListener) } override fun onTouch() { @@ -73,6 +88,28 @@ class StoreByMenuActivity : viewModel.changeSortType(SortType.RATING, currentPosition) } } + popupViewModel.popups.observe(this, { popups -> + if (popups.isNotEmpty()) { + binding.itemStoreListAd.run { + tvAdTitle.text = popups[0].title + popups[0].fontColor?.let { + tvAdTitle.setTextColor(it.toColorInt()) + tvAdBody.setTextColor(it.toColorInt()) + } + tvAdBody.text = popups[0].subTitle + + popups[0].bgColor?.let { layoutItem.setBackgroundColor(it.toColorInt()) } + + ivAdImage.loadUrlImg(popups[0].imageUrl) + + tvDetail.setOnClickListener { + startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(popups[0].linkUrl))) + } + } + storeByDistanceAdapters.submitAdList(popups) + storeByRatingAdapters.submitAdList(popups) + } + }) viewModel.storeByRating.observe(this) { val storeInfoList = if (binding.cbCertification.isChecked) { it.filter { storeInfo -> storeInfo.visitHistory.isCertified } @@ -80,6 +117,7 @@ class StoreByMenuActivity : it } storeByRatingAdapters.submitList(storeInfoList) + popupViewModel.getPopups("STORE_CATEGORY_LIST") } viewModel.storeByDistance.observe(this) { val storeInfoList = if (binding.cbCertification.isChecked) { @@ -88,6 +126,7 @@ class StoreByMenuActivity : it } storeByDistanceAdapters.submitList(storeInfoList) + popupViewModel.getPopups("STORE_CATEGORY_LIST") } binding.btnBack.setOnClickListener { finish() diff --git a/app/src/main/java/com/zion830/threedollars/ui/category/adapter/SearchByAdViewHolder.kt b/app/src/main/java/com/zion830/threedollars/ui/category/adapter/SearchByAdViewHolder.kt new file mode 100644 index 00000000..f58a5c52 --- /dev/null +++ b/app/src/main/java/com/zion830/threedollars/ui/category/adapter/SearchByAdViewHolder.kt @@ -0,0 +1,30 @@ +package com.zion830.threedollars.ui.category.adapter + +import android.annotation.SuppressLint +import android.view.ViewGroup +import androidx.core.graphics.toColorInt +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions +import com.zion830.threedollars.R +import com.zion830.threedollars.databinding.ItemStoreListAdBinding +import com.zion830.threedollars.repository.model.v2.response.Popups +import zion830.com.common.base.BaseViewHolder +import zion830.com.common.base.loadUrlImg +import zion830.com.common.listener.OnItemClickListener + +class SearchByAdViewHolder(parent: ViewGroup) : + BaseViewHolder(R.layout.item_store_list_ad, parent) { + + @SuppressLint("Range") + override fun bind(item: Popups, listener: OnItemClickListener?) { + super.bind(item, listener) + if (!item.fontColor.isNullOrEmpty()) { + binding.tvAdTitle.setTextColor(item.fontColor.toColorInt()) + binding.tvAdBody.setTextColor(item.fontColor.toColorInt()) + } + if (!item.bgColor.isNullOrEmpty()) { + binding.layoutItem.setBackgroundColor(item.bgColor.toColorInt()) + } + binding.ivAdImage.loadUrlImg(item.imageUrl) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/zion830/threedollars/ui/category/adapter/SearchByDistanceRecyclerAdapter.kt b/app/src/main/java/com/zion830/threedollars/ui/category/adapter/SearchByDistanceRecyclerAdapter.kt index 2bb2a368..fa490113 100644 --- a/app/src/main/java/com/zion830/threedollars/ui/category/adapter/SearchByDistanceRecyclerAdapter.kt +++ b/app/src/main/java/com/zion830/threedollars/ui/category/adapter/SearchByDistanceRecyclerAdapter.kt @@ -4,6 +4,8 @@ import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.zion830.threedollars.R import com.zion830.threedollars.databinding.ItemStoreByDistanceBinding +import com.zion830.threedollars.repository.model.v2.response.AdAndStoreItem +import com.zion830.threedollars.repository.model.v2.response.Popups import com.zion830.threedollars.repository.model.v2.response.store.StoreInfo import com.zion830.threedollars.utils.SharedPrefUtils import zion830.com.common.base.BaseViewHolder @@ -11,36 +13,88 @@ import zion830.com.common.ext.toFormattedNumber import zion830.com.common.listener.OnItemClickListener class SearchByDistanceRecyclerAdapter( - private val listener: OnItemClickListener -) : RecyclerView.Adapter() { - private val items = arrayListOf() + private val listener: OnItemClickListener, + private val adListener: OnItemClickListener +) : RecyclerView.Adapter() { + private val items = arrayListOf() - override fun getItemCount(): Int = items.size + override fun getItemCount(): Int { + return items.size + } + + override fun getItemViewType(position: Int): Int { + return when (items[position]) { + is Popups -> { + VIEW_TYPE_AD + } + is StoreInfo -> { + VIEW_TYPE_STORE + } + else -> { + throw IllegalStateException("Not Found ViewHolder Type") + } + } + } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchByDistanceViewHolder { - return SearchByDistanceViewHolder(parent) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when (viewType) { + VIEW_TYPE_AD -> { + SearchByAdViewHolder(parent) + } + VIEW_TYPE_STORE -> { + SearchByDistanceViewHolder(parent) + } + else -> { + throw IllegalStateException("Not Found ViewHolder Type $viewType") + } } - override fun onBindViewHolder(holder: SearchByDistanceViewHolder, position: Int) { - holder.bind(items[position], listener) + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when (holder) { + is SearchByDistanceViewHolder -> { + holder.bind(items[position] as StoreInfo, listener) + } + is SearchByAdViewHolder -> { + holder.bind(items[position] as Popups, adListener) + } + } } - fun submitList(newItems: List) { + fun submitList(newItems: List) { items.clear() items.addAll(newItems) notifyDataSetChanged() } + + fun submitAdList(newItems: List) { + if (items.isEmpty()) { + return + } + val list = items.filterIsInstance() + items.clear() + items.addAll(list) + items.add(1, newItems[0]) + notifyDataSetChanged() + } + + + companion object { + private const val VIEW_TYPE_AD = 1 + private const val VIEW_TYPE_STORE = 2 + } } -class SearchByDistanceViewHolder(parent: ViewGroup) : BaseViewHolder(R.layout.item_store_by_distance, parent) { + +class SearchByDistanceViewHolder(parent: ViewGroup) : + BaseViewHolder(R.layout.item_store_by_distance, parent) { override fun bind(item: StoreInfo, listener: OnItemClickListener?) { super.bind(item, listener) val categoryInfo = SharedPrefUtils.getCategories() - val categories = item.categories.joinToString(" ") { "#${categoryInfo.find { categoryInfo -> categoryInfo.category == it }?.name}" } + val categories = + item.categories.joinToString(" ") { "#${categoryInfo.find { categoryInfo -> categoryInfo.category == it }?.name}" } val distanceString = "${item.distance.toString().toFormattedNumber()}m" binding.tvCategory.text = categories binding.tvDistance.text = distanceString } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/zion830/threedollars/ui/category/adapter/SearchByRatingRecyclerAdapter.kt b/app/src/main/java/com/zion830/threedollars/ui/category/adapter/SearchByRatingRecyclerAdapter.kt index a2b223f3..e2ad109d 100644 --- a/app/src/main/java/com/zion830/threedollars/ui/category/adapter/SearchByRatingRecyclerAdapter.kt +++ b/app/src/main/java/com/zion830/threedollars/ui/category/adapter/SearchByRatingRecyclerAdapter.kt @@ -4,24 +4,56 @@ import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.zion830.threedollars.R import com.zion830.threedollars.databinding.ItemStoreByRatingBinding +import com.zion830.threedollars.repository.model.v2.response.AdAndStoreItem +import com.zion830.threedollars.repository.model.v2.response.Popups import com.zion830.threedollars.repository.model.v2.response.store.StoreInfo import com.zion830.threedollars.utils.SharedPrefUtils import zion830.com.common.base.BaseViewHolder import zion830.com.common.listener.OnItemClickListener class SearchByRatingRecyclerAdapter( - private val listener: OnItemClickListener -) : RecyclerView.Adapter() { - private val items = arrayListOf() + private val listener: OnItemClickListener, + private val adListener: OnItemClickListener +) : RecyclerView.Adapter() { + private val items = arrayListOf() override fun getItemCount(): Int = items.size - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchByRatingViewHolder { - return SearchByRatingViewHolder(parent) + override fun getItemViewType(position: Int): Int { + return when (items[position]) { + is Popups -> { + VIEW_TYPE_AD + } + is StoreInfo -> { + VIEW_TYPE_STORE + } + else -> { + throw IllegalStateException("Not Found ViewHolder Type") + } + } } - override fun onBindViewHolder(holder: SearchByRatingViewHolder, position: Int) { - holder.bind(items[position], listener) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when (viewType) { + VIEW_TYPE_AD -> { + SearchByAdViewHolder(parent) + } + VIEW_TYPE_STORE -> { + SearchByRatingViewHolder(parent) + } + else -> { + throw IllegalStateException("Not Found ViewHolder Type $viewType") + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when (holder) { + is SearchByRatingViewHolder -> { + holder.bind(items[position] as StoreInfo, listener) + } + is SearchByAdViewHolder -> { + holder.bind(items[position] as Popups, adListener) + } + } } fun submitList(newItems: List) { @@ -29,15 +61,33 @@ class SearchByRatingRecyclerAdapter( items.addAll(newItems) notifyDataSetChanged() } + + fun submitAdList(newItems: List) { + if (items.isEmpty()) { + return + } + val list = items.filterIsInstance() + items.clear() + items.addAll(list) + items.add(1, newItems[0]) + notifyDataSetChanged() + } + + companion object { + private const val VIEW_TYPE_AD = 1 + private const val VIEW_TYPE_STORE = 2 + } } -class SearchByRatingViewHolder(parent: ViewGroup) : BaseViewHolder(R.layout.item_store_by_rating, parent) { +class SearchByRatingViewHolder(parent: ViewGroup) : + BaseViewHolder(R.layout.item_store_by_rating, parent) { override fun bind(item: StoreInfo, listener: OnItemClickListener?) { super.bind(item, listener) val categoryInfo = SharedPrefUtils.getCategories() - val categories = item.categories.joinToString(" ") { "#${categoryInfo.find { categoryInfo -> categoryInfo.category == it }?.name}" } + val categories = + item.categories.joinToString(" ") { "#${categoryInfo.find { categoryInfo -> categoryInfo.category == it }?.name}" } binding.tvCategory.text = categories } } \ No newline at end of file diff --git a/app/src/main/java/com/zion830/threedollars/ui/home/HomeFragment.kt b/app/src/main/java/com/zion830/threedollars/ui/home/HomeFragment.kt index ea49fae8..423a7781 100644 --- a/app/src/main/java/com/zion830/threedollars/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/zion830/threedollars/ui/home/HomeFragment.kt @@ -2,16 +2,20 @@ package com.zion830.threedollars.ui.home import android.content.Intent import android.net.Uri +import androidx.activity.viewModels import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels +import androidx.fragment.app.viewModels import androidx.recyclerview.widget.LinearSnapHelper import com.naver.maps.geometry.LatLng import com.zion830.threedollars.Constants import com.zion830.threedollars.R import com.zion830.threedollars.databinding.FragmentHomeBinding +import com.zion830.threedollars.repository.model.v2.response.Popups import com.zion830.threedollars.repository.model.v2.response.store.StoreInfo import com.zion830.threedollars.ui.addstore.view.NearStoreNaverMapFragment import com.zion830.threedollars.ui.home.adapter.NearStoreRecyclerAdapter +import com.zion830.threedollars.ui.popup.PopupViewModel import com.zion830.threedollars.ui.store_detail.StoreDetailActivity import com.zion830.threedollars.utils.getCurrentLocationName import com.zion830.threedollars.utils.showToast @@ -53,7 +57,6 @@ class HomeFragment : BaseFragment(R.layout.f getCurrentLocationName(it) ?: getString(R.string.location_no_address) } viewModel.nearStoreInfo.observe(viewLifecycleOwner) { store -> - binding.layoutEmpty.isVisible = store.isNullOrEmpty() adapter.submitList(store) } binding.layoutAddress.setOnClickListener { @@ -74,6 +77,11 @@ class HomeFragment : BaseFragment(R.layout.f showToast(R.string.exist_store_error) } } + }, object : OnItemClickListener { + override fun onClick(item: Popups) { + startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(item.linkUrl))) + } + }) { item -> if (item != null) { val intent = StoreDetailActivity.getIntent(requireContext(), item.storeId, true) @@ -81,7 +89,8 @@ class HomeFragment : BaseFragment(R.layout.f } } viewModel.nearStoreInfo.observe(viewLifecycleOwner) { res -> - naverMapFragment.addStoreMarkers(R.drawable.ic_store_off, res ?: listOf()) { + val list = res?.filterIsInstance() + naverMapFragment.addStoreMarkers(R.drawable.ic_store_off, list ?: listOf()) { onStoreClicked(it) } } @@ -105,13 +114,14 @@ class HomeFragment : BaseFragment(R.layout.f adapter.focusedIndex ) adapter.notifyDataSetChanged() - naverMapFragment.moveCameraWithAnim(adapter.getItemLocation(position)) + adapter.getItemLocation(position) + ?.let { naverMapFragment.moveCameraWithAnim(it) } } } }) ) binding.tvRetrySearch.setOnClickListener { - viewModel.requestStoreInfo(naverMapFragment.getMapCenterLatLng()) + viewModel.requestHomeItem(naverMapFragment.getMapCenterLatLng()) binding.tvRetrySearch.isVisible = false } binding.ibToss.setOnClickListener { @@ -147,6 +157,6 @@ class HomeFragment : BaseFragment(R.layout.f override fun onResume() { super.onResume() - naverMapFragment.getMapCenterLatLng().let { viewModel.requestStoreInfo(it) } + naverMapFragment.getMapCenterLatLng().let { viewModel.requestHomeItem(it) } } } \ No newline at end of file diff --git a/app/src/main/java/com/zion830/threedollars/ui/home/HomeViewModel.kt b/app/src/main/java/com/zion830/threedollars/ui/home/HomeViewModel.kt index 875127c4..0f7d60cc 100644 --- a/app/src/main/java/com/zion830/threedollars/ui/home/HomeViewModel.kt +++ b/app/src/main/java/com/zion830/threedollars/ui/home/HomeViewModel.kt @@ -3,8 +3,10 @@ package com.zion830.threedollars.ui.home import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.naver.maps.geometry.LatLng +import com.zion830.threedollars.repository.PopupRepository import com.zion830.threedollars.repository.StoreRepository -import com.zion830.threedollars.repository.model.v2.response.store.StoreInfo +import com.zion830.threedollars.repository.model.v2.response.AdAndStoreItem +import com.zion830.threedollars.repository.model.v2.response.HomeStoreEmptyResponse import com.zion830.threedollars.utils.getCurrentLocationName import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -13,8 +15,9 @@ import zion830.com.common.base.BaseViewModel class HomeViewModel : BaseViewModel() { private val repository = StoreRepository() + private val popupRepository = PopupRepository() - val nearStoreInfo: MutableLiveData?> = MutableLiveData() + val nearStoreInfo: MutableLiveData?> = MutableLiveData() val searchResultLocation: MutableLiveData = MutableLiveData() @@ -28,12 +31,21 @@ class HomeViewModel : BaseViewModel() { addressText.value = getCurrentLocationName(latlng) ?: "위치를 찾는 중..." } - fun requestStoreInfo(location: LatLng) { + fun requestHomeItem(location: LatLng) { viewModelScope.launch(Dispatchers.IO + coroutineExceptionHandler) { - val data = repository.getAllStore(location.latitude, location.longitude) - if (data.isSuccessful) { - nearStoreInfo.postValue(data.body()?.data) + val storeData = repository.getAllStore(location.latitude, location.longitude) + val adData = popupRepository.getPopups("MAIN_PAGE_CARD").body()?.data + + val resultList: ArrayList = arrayListOf() + storeData.body()?.data?.let { resultList.addAll(it) } + + if (resultList.isEmpty()) { + resultList.add(HomeStoreEmptyResponse()) + } + if (adData != null) { + adData.firstOrNull()?.let { resultList.add(1, it) } } + nearStoreInfo.postValue(resultList.toList()) } } } \ No newline at end of file diff --git a/app/src/main/java/com/zion830/threedollars/ui/home/SearchAddressFragment.kt b/app/src/main/java/com/zion830/threedollars/ui/home/SearchAddressFragment.kt index bbc7412f..17724345 100644 --- a/app/src/main/java/com/zion830/threedollars/ui/home/SearchAddressFragment.kt +++ b/app/src/main/java/com/zion830/threedollars/ui/home/SearchAddressFragment.kt @@ -28,7 +28,7 @@ class SearchAddressFragment : BaseFragment { override fun onClick(item: Document) { val location = LatLng(item.y.toDouble(), item.x.toDouble()) - viewModel.requestStoreInfo(location) + viewModel.requestHomeItem(location) searchViewModel.updateLatLng(location) activity?.supportFragmentManager?.popBackStack() searchViewModel.clear() diff --git a/app/src/main/java/com/zion830/threedollars/ui/home/adapter/NearStoreRecyclerAdapter.kt b/app/src/main/java/com/zion830/threedollars/ui/home/adapter/NearStoreRecyclerAdapter.kt index 1d2514d4..10fa00c7 100644 --- a/app/src/main/java/com/zion830/threedollars/ui/home/adapter/NearStoreRecyclerAdapter.kt +++ b/app/src/main/java/com/zion830/threedollars/ui/home/adapter/NearStoreRecyclerAdapter.kt @@ -1,35 +1,134 @@ package com.zion830.threedollars.ui.home.adapter +import android.annotation.SuppressLint +import android.graphics.Color import android.view.ViewGroup +import androidx.core.graphics.toColorInt import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.naver.maps.geometry.LatLng import com.zion830.threedollars.R +import com.zion830.threedollars.databinding.ItemHomeEmptyBinding +import com.zion830.threedollars.databinding.ItemNearStoreAdBinding +import com.zion830.threedollars.databinding.ItemStoreListAdBinding import com.zion830.threedollars.databinding.ItemStoreLocationBinding +import com.zion830.threedollars.repository.model.v2.response.AdAndStoreItem +import com.zion830.threedollars.repository.model.v2.response.HomeStoreEmptyResponse +import com.zion830.threedollars.repository.model.v2.response.Popups import com.zion830.threedollars.repository.model.v2.response.store.StoreInfo +import com.zion830.threedollars.ui.category.adapter.SearchByAdViewHolder +import com.zion830.threedollars.ui.category.adapter.SearchByDistanceRecyclerAdapter +import com.zion830.threedollars.ui.category.adapter.SearchByDistanceViewHolder import com.zion830.threedollars.ui.mypage.adapter.bindMenuIcons import com.zion830.threedollars.utils.SharedPrefUtils import zion830.com.common.base.BaseDiffUtilCallback import zion830.com.common.base.BaseViewHolder +import zion830.com.common.base.loadUrlImg import zion830.com.common.listener.OnItemClickListener class NearStoreRecyclerAdapter( private val clickListener: OnItemClickListener, + private val adClickListener: OnItemClickListener, private val certificationClick: (StoreInfo?) -> Unit -) : ListAdapter(BaseDiffUtilCallback()) { +) : ListAdapter(BaseDiffUtilCallback()) { var focusedIndex = 0 - fun getItemLocation(position: Int) = - LatLng(getItem(position)?.latitude ?: 0.0, getItem(position)?.longitude ?: 0.0) + fun getItemLocation(position: Int) = when (getItem(position)) { + is StoreInfo -> { + LatLng( + (getItem(position) as StoreInfo).latitude, + (getItem(position) as StoreInfo).longitude + ) + } + else -> { + null + } + } + + fun getItemPosition(item: StoreInfo) = + currentList.indexOfFirst { + if (it is StoreInfo) { + it.storeId == item.storeId + } else { + false + } + } + + override fun getItemViewType(position: Int): Int = when (getItem(position)) { + is StoreInfo -> { + VIEW_TYPE_STORE + } + is Popups -> { + VIEW_TYPE_AD + } + else -> { + VIEW_TYPE_EMPTY + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when (viewType) { + VIEW_TYPE_AD -> { + NearStoreAdViewHolder(parent) + } + VIEW_TYPE_STORE -> { + NearStoreViewHolder(parent, certificationClick) + } + else -> { + NearStoreEmptyViewHolder(parent) + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when (holder) { + is NearStoreViewHolder -> { + holder.bind(getItem(position) as StoreInfo, listener = clickListener) + holder.bindPosition(focusedIndex == position) + } + is NearStoreAdViewHolder -> { + holder.bind(getItem(position) as Popups, adClickListener) + } + is NearStoreEmptyViewHolder -> { + holder.bind(getItem(position) as HomeStoreEmptyResponse, null) + } + } + } + + companion object { + private const val VIEW_TYPE_EMPTY = 0 + private const val VIEW_TYPE_AD = 1 + private const val VIEW_TYPE_STORE = 2 + } +} - fun getItemPosition(item: StoreInfo) = currentList.indexOfFirst { it?.storeId == item.storeId } +class NearStoreEmptyViewHolder(parent: ViewGroup) : + BaseViewHolder(R.layout.item_home_empty, parent) { - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NearStoreViewHolder { - return NearStoreViewHolder(parent, certificationClick) + @SuppressLint("Range") + override fun bind( + item: HomeStoreEmptyResponse, + listener: OnItemClickListener? + ) { + super.bind(item, listener) } +} - override fun onBindViewHolder(holder: NearStoreViewHolder, position: Int) { - holder.bind(getItem(position), listener = clickListener) - holder.bindPosition(focusedIndex == position) +class NearStoreAdViewHolder(parent: ViewGroup) : + BaseViewHolder(R.layout.item_near_store_ad, parent) { + + @SuppressLint("Range") + override fun bind(item: Popups, listener: OnItemClickListener?) { + super.bind(item, listener) + if (!item.fontColor.isNullOrEmpty()) { + binding.tvAdTitle.setTextColor(item.fontColor.toColorInt()) + binding.tvAdBody.setTextColor(item.fontColor.toColorInt()) + } + + if (!item.bgColor.isNullOrEmpty()) { + binding.layoutItem.setBackgroundColor(item.bgColor.toColorInt()) + } + binding.ivAdImage.loadUrlImg(item.imageUrl) } } diff --git a/app/src/main/res/drawable/rect_ff5c43_opacity_radius16.xml b/app/src/main/res/drawable/rect_ff5c43_opacity_radius16.xml new file mode 100644 index 00000000..4f7eeaa3 --- /dev/null +++ b/app/src/main/res/drawable/rect_ff5c43_opacity_radius16.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_store_by_menu.xml b/app/src/main/res/layout/activity_store_by_menu.xml index cdde8594..1387ba71 100644 --- a/app/src/main/res/layout/activity_store_by_menu.xml +++ b/app/src/main/res/layout/activity_store_by_menu.xml @@ -9,6 +9,10 @@ name="viewModel" type="com.zion830.threedollars.ui.store_detail.vm.StoreByMenuViewModel" /> + + @@ -216,6 +220,16 @@ android:textColor="@color/color_gray1" android:visibility="gone" /> + + - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_empty.xml b/app/src/main/res/layout/item_home_empty.xml new file mode 100644 index 00000000..b4757e49 --- /dev/null +++ b/app/src/main/res/layout/item_home_empty.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + > + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_near_store_ad.xml b/app/src/main/res/layout/item_near_store_ad.xml new file mode 100644 index 00000000..d11a7287 --- /dev/null +++ b/app/src/main/res/layout/item_near_store_ad.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_store_list_ad.xml b/app/src/main/res/layout/item_store_list_ad.xml new file mode 100644 index 00000000..8ed001e8 --- /dev/null +++ b/app/src/main/res/layout/item_store_list_ad.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_store_location.xml b/app/src/main/res/layout/item_store_location.xml index 1dd2701a..2881a799 100644 --- a/app/src/main/res/layout/item_store_location.xml +++ b/app/src/main/res/layout/item_store_location.xml @@ -141,44 +141,5 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@id/ll_distance_rating" /> - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 524e5ae2..7f5f301a 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -30,6 +30,8 @@ #999999 #99FFFFFF #FFA1AA + #FF5C43 + #33FF5C43 #4f4f4f #E2E2E2 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 68386485..0f9b331f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -192,8 +192,8 @@ 4점 이상 가게형태 - 주변 2km 이내에 가게가 없어요 - 다른 주소로 검색하거나 직접 제보해보세요! + 2km 이내에 가게가 없어요 + 다른 주소로 검색하거나\n직접 제보해보세요! 아직 등록된 정보가 없어요. 검색 결과가 없어요. 출몰시기 @@ -267,4 +267,6 @@ 10m이내에 이미 제보된\n가게가 있어요! 중복된 가게 제보인지 확인해 주세요 이 위치가 맞아요! + 광고 + ]]> diff --git a/common.gradle b/common.gradle index 0dfb9b03..39a46c18 100644 --- a/common.gradle +++ b/common.gradle @@ -16,8 +16,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 31 - versionCode 33 - versionName "2.4.5" + versionCode 34 + versionName "2.4.6" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"