diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 558dfb3a..9f450cfb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,9 +2,9 @@ + tools:targetApi="p"> @@ -23,52 +23,49 @@ android:supportsRtl="true" android:theme="@style/Theme.JJBAKSAAOS" tools:targetApi="33"> + + - - - - - - - - - @@ -83,57 +80,46 @@ android:name=".ui.setting.SettingActivity" android:exported="false" android:screenOrientation="portrait" /> - - - - - - - - - - - diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/di/DataSourceModule.kt b/app/src/main/java/com/jjbaksa/jjbaksa/di/DataSourceModule.kt index 9ea3cf70..c2cb433a 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/di/DataSourceModule.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/di/DataSourceModule.kt @@ -7,6 +7,7 @@ import com.jjbaksa.data.database.UserDao import com.jjbaksa.data.datasource.local.HomeLocalDataSource import com.jjbaksa.data.datasource.local.SearchLocalDataSource import com.jjbaksa.data.datasource.local.UserLocalDataSource +import com.jjbaksa.data.datasource.remote.FollowerRemoteDataSource import com.jjbaksa.data.datasource.remote.HomeRemoteDataSource import com.jjbaksa.data.datasource.remote.InquiryRemoteDataSource import com.jjbaksa.data.datasource.remote.ShopRemoteDataSource @@ -113,4 +114,10 @@ object DataSourceModule { ): SearchLocalDataSource { return SearchLocalDataSource(context) } + + @Provides + @Singleton + fun provideFollowerRemoteDataSource(authApi: AuthApi, noAuthApi: NoAuthApi): FollowerRemoteDataSource { + return FollowerRemoteDataSource(authApi, noAuthApi) + } } diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/di/RepositoryModule.kt b/app/src/main/java/com/jjbaksa/jjbaksa/di/RepositoryModule.kt index 1bcc0dbc..2243e198 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/di/RepositoryModule.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/di/RepositoryModule.kt @@ -11,6 +11,7 @@ import com.jjbaksa.data.repository.HomeRepositoryImpl import com.jjbaksa.domain.repository.UserRepository import com.jjbaksa.data.repository.UserRepositoryImpl import com.example.imageselector.repository.ImageRepository +import com.jjbaksa.data.datasource.remote.FollowerRemoteDataSource import com.jjbaksa.data.datasource.local.SearchLocalDataSource import com.jjbaksa.data.datasource.remote.InquiryRemoteDataSource import com.jjbaksa.data.datasource.remote.ShopRemoteDataSource @@ -22,10 +23,12 @@ import com.jjbaksa.domain.repository.InquiryRepository import com.jjbaksa.data.datasource.remote.PostRemoteDataSource import com.jjbaksa.data.datasource.remote.ReviewRemoteDataSource import com.jjbaksa.data.datasource.remote.ScrapRemoteDataSource +import com.jjbaksa.data.repository.FollowerRepositoryImpl import com.jjbaksa.data.repository.ShopRepositoryImpl import com.jjbaksa.data.repository.PostRepositoryImpl import com.jjbaksa.data.repository.ReviewRepositoryImpl import com.jjbaksa.data.repository.ScrapRepositoryImpl +import com.jjbaksa.domain.repository.FollowerRepository import com.jjbaksa.domain.repository.ShopRepository import com.jjbaksa.domain.repository.PostRepository import com.jjbaksa.domain.repository.ReviewRepository @@ -113,4 +116,12 @@ object RepositoryModule { ): ReviewRepository { return ReviewRepositoryImpl(reviewRemoteDataSource, userLocalDataSource) } + + @Singleton + @Provides + fun provideFollowerRepository( + followerRemoteDataSource: FollowerRemoteDataSource, + ): FollowerRepository { + return FollowerRepositoryImpl(followerRemoteDataSource) + } } diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/FollowerActivity.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/FollowerActivity.kt new file mode 100644 index 00000000..f8fc43ff --- /dev/null +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/FollowerActivity.kt @@ -0,0 +1,265 @@ +package com.jjbaksa.jjbaksa.ui.follower + +import android.content.Intent +import android.view.View +import com.jjbaksa.jjbaksa.R +import androidx.activity.viewModels +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.jjbaksa.domain.enums.UserCursor +import com.jjbaksa.domain.model.user.User +import com.jjbaksa.jjbaksa.base.BaseActivity +import com.jjbaksa.jjbaksa.databinding.ActivityFollowerBinding +import com.jjbaksa.jjbaksa.ui.follower.adapter.FollowRequestAdapter +import com.jjbaksa.jjbaksa.ui.follower.adapter.FollowerAdapter +import com.jjbaksa.jjbaksa.ui.follower.adapter.RecentlyActiveAdapter +import com.jjbaksa.jjbaksa.ui.follower.viewmodel.FollowerViewModel +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class FollowerActivity : BaseActivity() { + override val layoutId: Int + get() = R.layout.activity_follower + + private lateinit var followerAdapter: FollowerAdapter + private lateinit var followRequestAdapter: FollowRequestAdapter + private lateinit var userAdapter: FollowerAdapter + private lateinit var recentlyActiveAdapter: RecentlyActiveAdapter + private lateinit var linearLayoutManager: LinearLayoutManager + private lateinit var requestLinearLayoutManager: LinearLayoutManager + private lateinit var userLinearLayoutManager: LinearLayoutManager + private lateinit var followRequestLinearLayoutManager: LinearLayoutManager + private lateinit var recentlyActiveLinearLayoutManager: LinearLayoutManager + private val viewModel: FollowerViewModel by viewModels() + + override fun initView() { + binding.lifecycleOwner = this + viewModel.getFollower(null, 20) + viewModel.followRequestReceived(null, 20) + viewModel.followRequestSend(null, 20) + viewModel.getRecentlyActiveFollowers(20, null) + + followerAdapter = FollowerAdapter({ + toggleFollow(it) + }) { + goToFollowerActivity(it) + } + followRequestAdapter = FollowRequestAdapter({ + viewModel.followRequestAccept(it.id) + }) { + viewModel.followRequestReject(it.id) + } + + userAdapter = FollowerAdapter({ + toggleFollow(it) + }) { + goToFollowerActivity(it) + } + + recentlyActiveAdapter = RecentlyActiveAdapter() + + linearLayoutManager = LinearLayoutManager(this) + requestLinearLayoutManager = LinearLayoutManager(this) + userLinearLayoutManager = LinearLayoutManager(this) + followRequestLinearLayoutManager = LinearLayoutManager(this) + recentlyActiveLinearLayoutManager = LinearLayoutManager(this) + recentlyActiveLinearLayoutManager.orientation = LinearLayoutManager.HORIZONTAL + + binding.rvAllFollower.apply { + layoutManager = linearLayoutManager + adapter = followerAdapter + } + binding.rvRequestFollow.apply { + layoutManager = requestLinearLayoutManager + adapter = followRequestAdapter + } + + binding.rvSearchResult.apply { + layoutManager = userLinearLayoutManager + adapter = userAdapter + } + + binding.rvRecentlyActiveFollower.apply { + layoutManager = recentlyActiveLinearLayoutManager + adapter = recentlyActiveAdapter + } + } + + override fun subscribe() { + binding.rvAllFollower.addOnScrollListener( + object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + val itemCount = linearLayoutManager.itemCount + val lastPosition = + linearLayoutManager.findLastCompletelyVisibleItemPosition() + + if (lastPosition != -1 && lastPosition >= (itemCount - 1) && viewModel.followerHasMore.value == true) { + viewModel.followerHasMore.value = false + viewModel.getFollower( + null, + 20 + ) + binding.loadingView.setLoading(true) + } + } + }) + + binding.rvRequestFollow.addOnScrollListener( + object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + val itemCount = requestLinearLayoutManager.itemCount + val lastPosition = + requestLinearLayoutManager.findLastCompletelyVisibleItemPosition() + + if (lastPosition != -1 && lastPosition >= (itemCount - 1) && viewModel.receivedFollowRequestHasMore.value == true && viewModel.sendFollowRequestHasMore.value == true) { + viewModel.receivedFollowRequestHasMore.value = false + viewModel.sendFollowRequestHasMore.value = false + viewModel.followRequestReceived( + null, + 20 + ) + viewModel.followRequestSend( + null, + 20 + ) + binding.loadingView.setLoading(true) + } + } + }) + + binding.rvSearchResult.addOnScrollListener( + object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + val itemCount = userLinearLayoutManager.itemCount + val lastPosition = + userLinearLayoutManager.findLastCompletelyVisibleItemPosition() + + if (lastPosition != -1 && lastPosition >= (itemCount - 1)) { + viewModel.getUserSearch( + viewModel.searchKeyword.value!!, + 20, + userAdapter.currentList.last().id + ) + binding.loadingView.setLoading(true) + } + } + }) + + binding.rvRecentlyActiveFollower.addOnScrollListener( + object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + val itemCount = recentlyActiveLinearLayoutManager.itemCount + val lastPosition = + recentlyActiveLinearLayoutManager.findLastCompletelyVisibleItemPosition() + + if (lastPosition != -1 && lastPosition >= (itemCount - 1) && viewModel.recentlyActiveHasMore.value == true) { + viewModel.recentlyActiveHasMore.value = false + viewModel.getRecentlyActiveFollowers( + 20, + recentlyActiveAdapter.currentList.last().id + ) + binding.loadingView.setLoading(true) + } + } + }) + } + + override fun initEvent() { + binding.jjAppBar.setOnClickListener { finish() } + + binding.ivSearch.setOnClickListener { + + binding.etSearch.text?.let { + if (it.isEmpty()) { + showSnackBar(getString(R.string.main_page_search_edit_text_hint)) + viewModel.cursor.value = UserCursor.FOLLOWER + } else { + viewModel.getUserSearch(it.toString(), 20, null) + viewModel.cursor.value = UserCursor.ALL + } + } + } + + viewModel.followerList.observe(this) { + binding.loadingView.setLoading(false) + if (it.content.isEmpty() && followerAdapter.currentList.isEmpty()) { + followerAdapter.submitList(emptyList()) + } else { + followerAdapter.submitList(followerAdapter.currentList + it.content) + } + } + + viewModel.receivedFollowRequestList.observe(this) { + binding.loadingView.setLoading(false) + if (it.content.isEmpty() && followRequestAdapter.currentList.isEmpty()) { + followRequestAdapter.submitList(emptyList()) + } else { + followRequestAdapter.submitList(followRequestAdapter.currentList + it.content) + } + } + + viewModel.sendFollowRequestList.observe(this) { + binding.loadingView.setLoading(false) + if (it.content.isEmpty() && followRequestAdapter.currentList.isEmpty()) { + followRequestAdapter.submitList(emptyList()) + } else { + followRequestAdapter.submitList(followRequestAdapter.currentList + it.content) + } + } + + viewModel.userList.observe(this) { + binding.loadingView.setLoading(false) + if (it.content.isEmpty() && userAdapter.currentList.isEmpty()) { + userAdapter.submitList(emptyList()) + } else { + userAdapter.submitList(userAdapter.currentList + it.content) + } + } + + viewModel.recentlyActiveList.observe(this) { + binding.loadingView.setLoading(false) + if (it.content.isEmpty() && recentlyActiveAdapter.currentList.isEmpty()) { + recentlyActiveAdapter.submitList(emptyList()) + } else { + recentlyActiveAdapter.submitList(recentlyActiveAdapter.currentList + it.content) + } + } + + viewModel.cursor.observe(this) { + when (it) { + UserCursor.ALL -> { + binding.rvRecentlyActiveFollower.visibility = View.GONE + binding.clAllFollower.visibility = View.GONE + binding.clRequestFollow.visibility = View.GONE + binding.clSearchResult.visibility = View.VISIBLE + } + + UserCursor.FOLLOWER -> { + binding.rvRecentlyActiveFollower.visibility = View.VISIBLE + binding.clAllFollower.visibility = View.VISIBLE + binding.clRequestFollow.visibility = View.VISIBLE + binding.clSearchResult.visibility = View.GONE + } + } + } + } + + private fun toggleFollow(user: User) { + if (viewModel.unfollowedUsers.contains(user.account)) { + viewModel.followRequest(user.account) + } else { + viewModel.followerDelete(user.account) + } + } + + private fun goToFollowerActivity(user: User) { + val intent = Intent(this, FollowerProfileActivity::class.java).apply { + putExtra("nickname", user.nickname) + putExtra("account", user.account) + putExtra("fid", user.id) + putExtra("profileImage", user.profileImage.url) + putExtra("followerCount", user.userCountResponse.friendCount) + } + startActivity(intent) + } +} diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/FollowerProfileActivity.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/FollowerProfileActivity.kt new file mode 100644 index 00000000..efb2185c --- /dev/null +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/FollowerProfileActivity.kt @@ -0,0 +1,67 @@ +package com.jjbaksa.jjbaksa.ui.follower + +import androidx.activity.viewModels +import com.bumptech.glide.Glide +import com.google.android.material.tabs.TabLayoutMediator +import com.jjbaksa.jjbaksa.R +import com.jjbaksa.jjbaksa.base.BaseActivity +import com.jjbaksa.jjbaksa.databinding.ActivityFollowerProfileBinding +import com.jjbaksa.jjbaksa.ui.follower.adapter.PageAdapter +import com.jjbaksa.jjbaksa.ui.follower.viewmodel.FollowerProfileViewModel +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class FollowerProfileActivity : BaseActivity() { + override val layoutId: Int + get() = R.layout.activity_follower_profile + private val viewModel: FollowerProfileViewModel by viewModels() + + private val nickname: String by lazy { + intent.getStringExtra("nickname") ?: "" + } + private val account: String by lazy { + intent.getStringExtra("account") ?: "" + } + private val followerCount: Int by lazy { + intent.getIntExtra("followerCount", 0) + } + private val fid: Long by lazy { + intent.getLongExtra("fid", 0) + } + private val profileImage: String by lazy { + intent.getStringExtra("profileImage") ?: "" + } + + override fun initView() { + binding.lifecycleOwner = this + binding.run { + tvNickname.text = nickname + tvAccount.text = "@" + account + tvFollowerCount.text = followerCount.toString() + Glide.with(this@FollowerProfileActivity) + .load(profileImage) + .error(R.drawable.baseline_supervised_user_circle_24) + .circleCrop() + .into(ivProfile) + } + viewModel.fid = fid + initTabLayoutAndViewPager() + } + private fun initTabLayoutAndViewPager() { + binding.vpPage.adapter = PageAdapter(this) + + TabLayoutMediator( + binding.tlPage, + binding.vpPage + ) { tab, position -> + binding.vpPage.currentItem = tab.position + tab.text = resources.getStringArray(R.array.my_page_tab)[position] + }.attach() + } + + override fun subscribe() { + } + + override fun initEvent() { + } +} diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/FollowerReviewsFragment.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/FollowerReviewsFragment.kt new file mode 100644 index 00000000..ae3d0262 --- /dev/null +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/FollowerReviewsFragment.kt @@ -0,0 +1,50 @@ +package com.jjbaksa.jjbaksa.ui.follower + +import androidx.fragment.app.activityViewModels +import com.jjbaksa.domain.model.review.MyReviewShopsContent +import com.jjbaksa.jjbaksa.R +import com.jjbaksa.jjbaksa.base.BaseFragment +import com.jjbaksa.jjbaksa.databinding.FragmentFollowerReviewsBinding +import com.jjbaksa.jjbaksa.ui.follower.adapter.FollowerReviewedShopAdapter +import com.jjbaksa.jjbaksa.ui.follower.viewmodel.FollowerProfileViewModel +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class FollowerReviewsFragment : BaseFragment() { + override val layoutId: Int + get() = R.layout.fragment_follower_reviews + private val viewModel: FollowerProfileViewModel by activityViewModels() + private val followerReviewedShopAdapter: FollowerReviewedShopAdapter by lazy { + FollowerReviewedShopAdapter { shop, adapter -> + viewModel.getShopReview(viewModel.fid, shop.placeId) { + adapter.submitList( + it.content.map { + MyReviewShopsContent( + id = it.id, + content = it.content, + rate = it.rate, + createdAt = it.createdAt, + ) + } + ) + } + } + } + + override fun initView() { + binding.viewModel = viewModel + binding.lifecycleOwner = viewLifecycleOwner + binding.rvFollowerReviewShops.adapter = followerReviewedShopAdapter + viewModel.getFollowerReviewCount() + viewModel.getReviewedShops() + } + + override fun subscribe() { + viewModel.reviewedShops.observe(viewLifecycleOwner) { + followerReviewedShopAdapter.submitList(it.content) + } + } + + override fun initEvent() { + } +} diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/FollowRequestAdapter.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/FollowRequestAdapter.kt new file mode 100644 index 00000000..8c228717 --- /dev/null +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/FollowRequestAdapter.kt @@ -0,0 +1,72 @@ +package com.jjbaksa.jjbaksa.ui.follower.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import com.jjbaksa.domain.model.follower.FollowContent +import com.jjbaksa.jjbaksa.R +import com.jjbaksa.jjbaksa.databinding.ItemFollowBinding + +class FollowRequestAdapter( + private val onAcceptClicked: (FollowContent) -> Unit, + private val onDeleteClicked: (FollowContent) -> Unit, +) : ListAdapter(diffUtil) { + + inner class ViewHolder(private val binding: ItemFollowBinding) : + RecyclerView.ViewHolder(binding.root) { + fun bind(item: FollowContent) { + binding.followNameTextView.text = item.user?.nickname + binding.followAccountTextView.text = "@" + item.user?.account + Glide.with(binding.root.context) + .load(item.user.profileImage.url) + .error(R.drawable.baseline_supervised_user_circle_24) + .circleCrop() + .into(binding.ivProfile) + + binding.followButton.isVisible = false + binding.acceptButton.isVisible = true + binding.deleteButton.isVisible = true + + binding.acceptButton.setOnClickListener { + onAcceptClicked(item) + } + binding.deleteButton.setOnClickListener { + onDeleteClicked(item) + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder( + ItemFollowBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(currentList[position]) + } + + companion object { + val diffUtil = object : DiffUtil.ItemCallback() { + + override fun areItemsTheSame(oldItem: FollowContent, newItem: FollowContent): Boolean { + return oldItem.id == newItem.id + } + + override fun areContentsTheSame( + oldItem: FollowContent, + newItem: FollowContent + ): Boolean { + return oldItem == newItem + } + } + } +} diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/FollowerAdapter.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/FollowerAdapter.kt new file mode 100644 index 00000000..450c369a --- /dev/null +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/FollowerAdapter.kt @@ -0,0 +1,81 @@ +package com.jjbaksa.jjbaksa.ui.follower.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import com.jjbaksa.domain.model.user.User +import com.jjbaksa.jjbaksa.R +import com.jjbaksa.jjbaksa.databinding.ItemFollowBinding + +class FollowerAdapter( + private val onButtonClicked: (User) -> Unit, + private val onItemClicked: (User) -> Unit +) : ListAdapter(diffUtil) { + + inner class ViewHolder(private val binding: ItemFollowBinding) : + RecyclerView.ViewHolder(binding.root) { + fun bind(item: User) { + binding.followNameTextView.text = item.nickname + binding.followAccountTextView.text = "@" + item.account + + Glide.with(binding.root.context) + .load(item.profileImage.url) + .error(R.drawable.baseline_supervised_user_circle_24) + .circleCrop() + .into(binding.ivProfile) + + binding.followingButton.setOnClickListener { + onButtonClicked(item) + binding.followingButton.isVisible = false + binding.followButton.isVisible = true + binding.requestedButton.isVisible = false + } + binding.followButton.setOnClickListener { + onButtonClicked(item) + binding.followingButton.isVisible = false + binding.followButton.isVisible = false + binding.requestedButton.isVisible = true + } + binding.clItemFollower.setOnClickListener { + onItemClicked(item) + } + binding.requestedButton.setOnClickListener { + onButtonClicked(item) + binding.followingButton.isVisible = false + binding.followButton.isVisible = true + binding.requestedButton.isVisible = false + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder( + ItemFollowBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(currentList[position]) + } + + companion object { + val diffUtil = object : DiffUtil.ItemCallback() { + + override fun areItemsTheSame(oldItem: User, newItem: User): Boolean { + return oldItem.id == newItem.id + } + + override fun areContentsTheSame(oldItem: User, newItem: User): Boolean { + return oldItem == newItem + } + } + } +} diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/FollowerReviewedShopAdapter.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/FollowerReviewedShopAdapter.kt new file mode 100644 index 00000000..98c1fecc --- /dev/null +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/FollowerReviewedShopAdapter.kt @@ -0,0 +1,79 @@ +package com.jjbaksa.jjbaksa.ui.follower.adapter + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.jjbaksa.domain.model.review.ReviewShopContent +import com.jjbaksa.jjbaksa.R +import com.jjbaksa.jjbaksa.databinding.ItemShopTitleBinding +import com.jjbaksa.jjbaksa.ui.mainpage.mypage.adapter.ReviewDetailAdapter + +class FollowerReviewedShopAdapter( + private val onListChanged: (ReviewShopContent, ReviewDetailAdapter) -> Unit +) : ListAdapter(diffUtil) { + + private val reviewDetailAdapter: ReviewDetailAdapter by lazy { + ReviewDetailAdapter() + } + var isReviewVisible = false + inner class ViewHolder(private val binding: ItemShopTitleBinding) : + RecyclerView.ViewHolder(binding.root) { + fun bind(shop: ReviewShopContent) { + binding.run { + tvShopTitle.text = shop.name + tvShopCategory.text = shop.category + rvShopReviews.adapter = reviewDetailAdapter + root.setOnClickListener { + if (isReviewVisible) { + isReviewVisible = false + ivShopExpand.setImageResource(R.drawable.sel_jj_check_box_more_info_closed) + rvShopReviews.visibility = View.GONE + } else { + isReviewVisible = true + ivShopExpand.setImageResource(R.drawable.sel_jj_check_box_more_info_opened) + rvShopReviews.visibility = View.VISIBLE + } + } + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder( + ItemShopTitleBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) + } + + override fun onCurrentListChanged( + previousList: MutableList, + currentList: MutableList + ) { + currentList.forEach { shop -> + onListChanged(shop, reviewDetailAdapter) + } + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(currentList[position]) + } + + companion object { + val diffUtil = object : DiffUtil.ItemCallback() { + + override fun areItemsTheSame(oldItem: ReviewShopContent, newItem: ReviewShopContent): Boolean { + return oldItem.shopId == newItem.shopId + } + + override fun areContentsTheSame(oldItem: ReviewShopContent, newItem: ReviewShopContent): Boolean { + return oldItem == newItem + } + } + } +} diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/PageAdapter.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/PageAdapter.kt new file mode 100644 index 00000000..af88ca58 --- /dev/null +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/PageAdapter.kt @@ -0,0 +1,17 @@ +package com.jjbaksa.jjbaksa.ui.follower.adapter + +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import androidx.viewpager2.adapter.FragmentStateAdapter +import com.jjbaksa.jjbaksa.ui.follower.FollowerReviewsFragment +import com.jjbaksa.jjbaksa.ui.mainpage.mypage.BookmarkFragment + +class PageAdapter( + fragmentActivity: FragmentActivity +) : FragmentStateAdapter(fragmentActivity) { + override fun getItemCount(): Int = 2 + override fun createFragment(position: Int): Fragment = when (position) { + 0 -> FollowerReviewsFragment() + else -> BookmarkFragment() + } +} diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/RecentlyActiveAdapter.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/RecentlyActiveAdapter.kt new file mode 100644 index 00000000..bd70247b --- /dev/null +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/adapter/RecentlyActiveAdapter.kt @@ -0,0 +1,53 @@ +package com.jjbaksa.jjbaksa.ui.follower.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import com.jjbaksa.domain.model.user.User +import com.jjbaksa.jjbaksa.R +import com.jjbaksa.jjbaksa.databinding.ItemRecentlyActiveBinding + +class RecentlyActiveAdapter() : ListAdapter(diffUtil) { + inner class ViewHolder(private val binding: ItemRecentlyActiveBinding) : + RecyclerView.ViewHolder(binding.root) { + fun bind(item: User) { + binding.followNameTextView.text = item.nickname + + Glide.with(binding.root.context) + .load(item.profileImage.url) + .error(R.drawable.baseline_supervised_user_circle_24) + .circleCrop() + .into(binding.ivProfile) + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder( + ItemRecentlyActiveBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(currentList[position]) + } + + companion object { + val diffUtil = object : DiffUtil.ItemCallback() { + + override fun areItemsTheSame(oldItem: User, newItem: User): Boolean { + return oldItem.id == newItem.id + } + + override fun areContentsTheSame(oldItem: User, newItem: User): Boolean { + return oldItem == newItem + } + } + } +} diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/viewmodel/FollowerProfileViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/viewmodel/FollowerProfileViewModel.kt new file mode 100644 index 00000000..fb4c1c27 --- /dev/null +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/viewmodel/FollowerProfileViewModel.kt @@ -0,0 +1,55 @@ +package com.jjbaksa.jjbaksa.ui.follower.viewmodel + +import androidx.lifecycle.viewModelScope +import com.jjbaksa.domain.model.review.FollowerReviewShops +import com.jjbaksa.domain.model.review.ReviewShop +import com.jjbaksa.domain.usecase.follower.FollowerUseCase +import com.jjbaksa.jjbaksa.base.BaseViewModel +import com.jjbaksa.jjbaksa.util.SingleLiveEvent +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class FollowerProfileViewModel @Inject constructor( + private val followerUseCase: FollowerUseCase +) : BaseViewModel() { + + var fid = 0L + + private val _followerReviewCount = SingleLiveEvent() + val totalReviewCount: SingleLiveEvent get() = _followerReviewCount + + private val _reviewedShops = SingleLiveEvent() + val reviewedShops: SingleLiveEvent get() = _reviewedShops + + fun getFollowerReviewCount() { + viewModelScope.launch(ceh) { + followerUseCase.getFollowerReviewCount(fid).collect { + it.onSuccess { + _followerReviewCount.value = it + } + } + } + } + + fun getReviewedShops() { + viewModelScope.launch(ceh) { + followerUseCase.getReviewedShops(fid).collect { + it.onSuccess { + _reviewedShops.value = it + } + } + } + } + + fun getShopReview(id: Long, placeId: String, onComplete: (FollowerReviewShops) -> Unit) { + viewModelScope.launch(ceh) { + followerUseCase.getShopReview(id, placeId).collect { + it.onSuccess { + onComplete(it) + } + } + } + } +} diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/viewmodel/FollowerViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/viewmodel/FollowerViewModel.kt new file mode 100644 index 00000000..99aa5823 --- /dev/null +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/follower/viewmodel/FollowerViewModel.kt @@ -0,0 +1,149 @@ +package com.jjbaksa.jjbaksa.ui.follower.viewmodel + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import com.jjbaksa.domain.enums.UserCursor +import com.jjbaksa.domain.model.follower.FollowContent +import com.jjbaksa.domain.model.follower.Followers +import com.jjbaksa.domain.model.follower.FollowerList +import com.jjbaksa.domain.model.user.UserList +import com.jjbaksa.domain.usecase.follower.FollowerUseCase +import com.jjbaksa.domain.usecase.user.UserUseCase +import com.jjbaksa.jjbaksa.base.BaseViewModel +import com.jjbaksa.jjbaksa.util.SingleLiveEvent +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class FollowerViewModel @Inject constructor( + private val followerUseCase: FollowerUseCase, + private val userUseCase: UserUseCase +) : BaseViewModel() { + private val _followerList = SingleLiveEvent() + val followerList: SingleLiveEvent get() = _followerList + + private val _UserList = MutableLiveData() + val userList: MutableLiveData get() = _UserList + private val _receivedFollowRequestList = SingleLiveEvent() + val receivedFollowRequestList: LiveData get() = _receivedFollowRequestList + private val _sendFollowRequestList = SingleLiveEvent() + val sendFollowRequestList: LiveData get() = _sendFollowRequestList + private val _recentlyActiveList = SingleLiveEvent() + val recentlyActiveList: SingleLiveEvent get() = _recentlyActiveList + + val followerHasMore = SingleLiveEvent() + val receivedFollowRequestHasMore = SingleLiveEvent() + val sendFollowRequestHasMore = SingleLiveEvent() + val recentlyActiveHasMore = SingleLiveEvent() + val unfollowedUsers = mutableListOf() + val searchKeyword = SingleLiveEvent() + val cursor = SingleLiveEvent() + fun getFollower(cursor: String?, pageSize: Int) { + viewModelScope.launch(ceh) { + followerUseCase.getFollower(cursor, pageSize).collect { + it.onSuccess { + _followerList.value = it + followerHasMore.value = it.content.count() == 20 + } + } + } + } + + fun followerDelete(userAccount: String) { + viewModelScope.launch(ceh) { + followerUseCase.followerDelete(userAccount).collect { + it.onSuccess { + unfollowedUsers.add(userAccount) + } + } + } + } + + fun followRequest(userAccount: String) { + viewModelScope.launch(ceh) { + followerUseCase.followRequest(userAccount).collect { + it.onSuccess { + if (unfollowedUsers.contains(userAccount)) { + unfollowedUsers.remove(userAccount) + } + } + } + } + } + + fun followRequestReject(userId: Long) { + viewModelScope.launch(ceh) { + followerUseCase.followRequestReject(userId).collect { + it.onSuccess { + } + } + } + } + + fun followRequestAccept(userId: Long) { + viewModelScope.launch(ceh) { + followerUseCase.followRequestAccept(userId).collect { + it.onSuccess { + unfollowedUsers.remove(userId.toString()) + } + } + } + } + + fun followRequestReceived(page: Int?, pageSize: Int?) { + + viewModelScope.launch(ceh) { + followerUseCase.followRequestRecived(page, pageSize).collect { + it.onSuccess { + _receivedFollowRequestList.value = it + receivedFollowRequestHasMore.value = it.content.count() == 20 + } + } + } + } + + fun followRequestSend(page: Int?, pageSize: Int?) { + viewModelScope.launch(ceh) { + followerUseCase.followRequestSend(page, pageSize).collect { + it.onSuccess { + val list = mutableListOf() + it.content.forEach { item -> + list.add( + FollowContent( + follower = item.user, + id = item.id, + user = item.follower + ) + ) + } + _sendFollowRequestList.value = Followers(list) + sendFollowRequestHasMore.value = it.content.count() == 20 + } + } + } + } + + fun getUserSearch(keyword: String, pageSize: Int?, cursor: Long?) { + viewModelScope.launch(ceh) { + userUseCase.getUserSearch(keyword, pageSize, cursor).collect { + it.onSuccess { + _UserList.value = it + } + searchKeyword.value = keyword + } + } + } + + fun getRecentlyActiveFollowers(pageSize: Int?, cursor: Long?) { + viewModelScope.launch(ceh) { + followerUseCase.getRecentlyActiveFollowers(pageSize, cursor).collect { + it.onSuccess { + _recentlyActiveList.value = it + recentlyActiveHasMore.value = it.content.count() == 20 + } + } + } + } +} diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/NaviMyPageFragment.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/NaviMyPageFragment.kt index 8cb32832..7adcd527 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/NaviMyPageFragment.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/NaviMyPageFragment.kt @@ -11,6 +11,7 @@ import com.jjbaksa.jjbaksa.R import com.jjbaksa.jjbaksa.base.BaseFragment import com.jjbaksa.jjbaksa.databinding.FragmentNaviMyPageBinding import com.jjbaksa.jjbaksa.dialog.MyPageBottomSheetDialog +import com.jjbaksa.jjbaksa.ui.follower.FollowerActivity import com.jjbaksa.jjbaksa.ui.mainpage.MainPageActivity import com.jjbaksa.jjbaksa.ui.mainpage.home.NaviHomeFragment import com.jjbaksa.jjbaksa.ui.mainpage.mypage.adapter.MyPageAdapter @@ -72,6 +73,10 @@ class NaviMyPageFragment : BaseFragment() { binding.profileImageView.setOnClickListener { MyPageBottomSheetDialog().show(parentFragmentManager, MY_PAGE_DIALOG_TAG) } + + binding.followerTextView.setOnClickListener { + settingResult.launch(Intent(requireContext(), FollowerActivity::class.java)) + } } private fun onClickSettingImage() { diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/adapter/ReviewDetailAdapter.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/adapter/ReviewDetailAdapter.kt index 38660a75..e2d71fab 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/adapter/ReviewDetailAdapter.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/adapter/ReviewDetailAdapter.kt @@ -15,7 +15,7 @@ class ReviewDetailAdapter : fun bind(item: MyReviewShopsContent) { binding.myReviewContentTextView.text = item.content binding.myReviewCreatedDateTextView.text = item.createdAt - binding.reviewStarCountTextView.text = item.rate.toFloat().toString() + binding.tvReviewStarCount.text = item.rate.toFloat().toString() } } diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/pin/PinActivity.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/pin/PinActivity.kt index 2813ff36..f20b4b58 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/pin/PinActivity.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/pin/PinActivity.kt @@ -94,7 +94,7 @@ class PinActivity : BaseActivity() { viewModel.shopInfo.observe(this) { binding.shopTitleTextView.text = it.name binding.shopTypeTextView.text = it.category - binding.reviewStarCountTextView.text = + binding.tvReviewStarCount.text = round((it.totalRating / it.ratingCount.toDouble()) * 10).div(10).toString() binding.bookmarkImageView.isSelected = it.scrap != 0 diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/pin/adapter/PinFriendReviewAdapter.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/pin/adapter/PinFriendReviewAdapter.kt index 203d60eb..8f6462bd 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/pin/adapter/PinFriendReviewAdapter.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/pin/adapter/PinFriendReviewAdapter.kt @@ -21,7 +21,7 @@ class PinFriendReviewAdapter( binding.friendReviewAccountTextView.text = item.userReviewResponse.account binding.friendReviewContentTextView.text = item.content binding.friendReviewCreatedDateTextView.text = item.createdAt - binding.reviewStarCountTextView.text = item.rate.toFloat().toString() + binding.tvReviewStarCount.text = item.rate.toFloat().toString() Glide.with(binding.friendReviewProfileImageView) .load(item.userReviewResponse.profileImage.url) .override(40) diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/pin/adapter/PinMyReviewAdapter.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/pin/adapter/PinMyReviewAdapter.kt index ba027007..c1c97301 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/pin/adapter/PinMyReviewAdapter.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/pin/adapter/PinMyReviewAdapter.kt @@ -15,7 +15,7 @@ class PinMyReviewAdapter : fun bind(item: MyReviewShopsContent) { binding.myReviewContentTextView.text = item.content binding.myReviewCreatedDateTextView.text = item.createdAt - binding.reviewStarCountTextView.text = item.rate.toFloat().toString() + binding.tvReviewStarCount.text = item.rate.toFloat().toString() } } diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/shop/ShopActivity.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/shop/ShopActivity.kt index 0b0dd7d7..4387a09e 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/shop/ShopActivity.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/shop/ShopActivity.kt @@ -4,6 +4,7 @@ import android.content.Intent import android.view.View import androidx.activity.viewModels import androidx.core.view.isVisible +import com.bumptech.glide.Glide import com.google.android.material.tabs.TabLayoutMediator import com.jjbaksa.jjbaksa.R import com.jjbaksa.jjbaksa.base.BaseActivity @@ -18,7 +19,6 @@ import com.naver.maps.map.MapFragment import com.naver.maps.map.NaverMap import com.naver.maps.map.OnMapReadyCallback import dagger.hilt.android.AndroidEntryPoint -import kotlin.math.round @AndroidEntryPoint class ShopActivity : BaseActivity(), OnMapReadyCallback { @@ -32,7 +32,7 @@ class ShopActivity : BaseActivity(), OnMapReadyCallback { binding.lifecycleOwner = this intent.getStringExtra("place_id")?.let { viewModel.placeId.value = it - viewModel.getShopDetail(it) + viewModel.getShopInfo(it) } viewModel.getMyReview( placeId = viewModel.placeId.value.toString(), @@ -48,6 +48,9 @@ class ShopActivity : BaseActivity(), OnMapReadyCallback { viewModel.getMyLastReviewDate( placeId = viewModel.placeId.value.toString() ) + viewModel.getShopRates( + placeId = viewModel.placeId.value.toString() + ) initShopImageViewPagerWithTabLayout() initMap() } @@ -83,9 +86,7 @@ class ShopActivity : BaseActivity(), OnMapReadyCallback { binding.addressTextView.text = it.formattedAddress binding.phoneTextView.text = it.formattedPhoneNumber - binding.reviewStarCountTextView.text = if (it.ratingCount == 0) "0.0" else - round((it.totalRating / it.ratingCount.toDouble()) * 10).div(10).toString() - binding.bookmarkImageView.isSelected = it.scrap != 0 +// binding.bookmarkImageView.isSelected = it.scrap != 0 it.photos.forEach { binding.shopImagesTabLayout.addTab(binding.shopImagesTabLayout.newTab()) @@ -104,6 +105,9 @@ class ShopActivity : BaseActivity(), OnMapReadyCallback { setResult(RESULT_CANCELED, intent) finish() } + viewModel.shopAverageRate.observe(this) { + binding.tvReviewStarCount.text = String.format("%.1f", it) + } observeMyReview() observeFriendsReview() } @@ -146,8 +150,8 @@ class ShopActivity : BaseActivity(), OnMapReadyCallback { override fun onMapReady(naverMap: NaverMap) { val cameraUpdate = CameraUpdate.scrollTo( LatLng( - viewModel.shopInfo.value?.lat ?: 0.0, - viewModel.shopInfo.value?.lng ?: 0.0 + viewModel.shopInfo.value?.coordinate?.lat ?: 0.0, + viewModel.shopInfo.value?.coordinate?.lng ?: 0.0 ) ) naverMap.moveCamera(cameraUpdate) @@ -163,12 +167,12 @@ class ShopActivity : BaseActivity(), OnMapReadyCallback { if (it.content.isNotEmpty()) { binding.myReviewLayout1.myReviewContentTextView.text = it.content[0].content binding.myReviewLayout1.myReviewCreatedDateTextView.text = it.content[0].createdAt - binding.myReviewLayout1.reviewStarCountTextView.text = it.content[0].rate.toString() + binding.myReviewLayout1.tvReviewStarCount.text = it.content[0].rate.toString() if (it.content.size > 1) { binding.myReviewLayout2.myReviewContentTextView.text = it.content[1].content binding.myReviewLayout2.myReviewCreatedDateTextView.text = it.content[1].createdAt - binding.myReviewLayout2.reviewStarCountTextView.text = it.content[1].rate.toString() + binding.myReviewLayout2.tvReviewStarCount.text = it.content[1].rate.toString() } else { binding.myReviewLayout2.root.visibility = View.GONE } @@ -183,14 +187,28 @@ class ShopActivity : BaseActivity(), OnMapReadyCallback { private fun observeFriendsReview() { viewModel.friendReview.observe(this) { if (it.content.isNotEmpty()) { + binding.friendReviewLayout1.friendReviewNameTextView.text = it.content[0].userReviewResponse.nickname + binding.friendReviewLayout1.friendReviewAccountTextView.text = it.content[0].userReviewResponse.account binding.friendReviewLayout1.friendReviewContentTextView.text = it.content[0].content binding.friendReviewLayout1.friendReviewCreatedDateTextView.text = it.content[0].createdAt - binding.friendReviewLayout1.reviewStarCountTextView.text = it.content[0].rate.toString() + binding.friendReviewLayout1.tvReviewStarCount.text = it.content[0].rate.toString() + Glide.with(this) + .load(it.content[0].userReviewResponse.profileImage.url) + .placeholder(R.drawable.ic_profile) + .circleCrop() + .into(binding.friendReviewLayout1.friendReviewProfileImageView) if (it.content.size > 1) { + binding.friendReviewLayout2.friendReviewNameTextView.text = it.content[1].userReviewResponse.nickname + binding.friendReviewLayout2.friendReviewAccountTextView.text = it.content[1].userReviewResponse.account binding.friendReviewLayout2.friendReviewContentTextView.text = it.content[1].content binding.friendReviewLayout2.friendReviewCreatedDateTextView.text = it.content[1].createdAt - binding.friendReviewLayout2.reviewStarCountTextView.text = it.content[1].rate.toString() + binding.friendReviewLayout2.tvReviewStarCount.text = it.content[1].rate.toString() + Glide.with(this) + .load(it.content[1].userReviewResponse.profileImage.url) + .placeholder(R.drawable.ic_profile) + .circleCrop() + .into(binding.friendReviewLayout2.friendReviewProfileImageView) } else { binding.friendReviewLayout2.root.visibility = View.GONE } diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/shop/viewmodel/ShopViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/shop/viewmodel/ShopViewModel.kt index 42aac39e..240c53db 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/shop/viewmodel/ShopViewModel.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/shop/viewmodel/ShopViewModel.kt @@ -2,10 +2,10 @@ package com.jjbaksa.jjbaksa.ui.shop.viewmodel import androidx.lifecycle.viewModelScope import com.jjbaksa.domain.model.review.FollowerReviewShops -import com.jjbaksa.domain.model.shop.ShopDetail import com.jjbaksa.domain.model.review.MyReviewShops import com.jjbaksa.domain.model.review.ReviewShopLastDate import com.jjbaksa.domain.model.scrap.AddShopScrap +import com.jjbaksa.domain.model.shop.ShopInfo import com.jjbaksa.domain.usecase.shop.ShopUseCase import com.jjbaksa.domain.usecase.review.ReviewUseCase import com.jjbaksa.domain.usecase.scrap.GetShopScrapUseCase @@ -24,8 +24,8 @@ class ShopViewModel @Inject constructor( val placeId = SingleLiveEvent() val showProgress = SingleLiveEvent() - private val _shopInfo = SingleLiveEvent() - val shopInfo: SingleLiveEvent get() = _shopInfo + private val _shopInfo = SingleLiveEvent() + val shopInfo: SingleLiveEvent get() = _shopInfo private val _addScrapInfo = SingleLiveEvent() val addScrapInfo: SingleLiveEvent get() = _addScrapInfo @@ -42,10 +42,13 @@ class ShopViewModel @Inject constructor( private val _myLastReviewDate = SingleLiveEvent() val myLastReviewDate: SingleLiveEvent get() = _myLastReviewDate - fun getShopDetail(placeId: String) { + private val _shopAverageRate = SingleLiveEvent() + val shopAverageRate: SingleLiveEvent get() = _shopAverageRate + + fun getShopInfo(placeId: String) { showProgress.value = true viewModelScope.launch(ceh) { - shopUseCase.getShopDetail(placeId) { msg -> + shopUseCase.getShopInfo(placeId) { msg -> toastMsg.postValue(msg) }.collect { it.onSuccess { @@ -54,7 +57,7 @@ class ShopViewModel @Inject constructor( } it.onFailure { showProgress.value = false - _shopInfo.value = ShopDetail() + _shopInfo.value = ShopInfo() } } } @@ -150,4 +153,18 @@ class ShopViewModel @Inject constructor( } } } + + fun getShopRates(placeId: String) { + viewModelScope.launch(ceh) { + shopUseCase.getShopRates(placeId) { msg -> + toastMsg.postValue(msg) + }.collect { + it.onSuccess { + _shopAverageRate.value = it + }.onFailure { + _shopAverageRate.value = 0f + } + } + } + } } diff --git a/app/src/main/res/drawable/ic_follow_back.xml b/app/src/main/res/drawable/ic_follow_back.xml new file mode 100644 index 00000000..7e248f95 --- /dev/null +++ b/app/src/main/res/drawable/ic_follow_back.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_follow_request_back.xml b/app/src/main/res/drawable/ic_follow_request_back.xml new file mode 100644 index 00000000..da574da4 --- /dev/null +++ b/app/src/main/res/drawable/ic_follow_request_back.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_following_back.xml b/app/src/main/res/drawable/ic_following_back.xml new file mode 100644 index 00000000..e5cb6c2d --- /dev/null +++ b/app/src/main/res/drawable/ic_following_back.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_follower.xml b/app/src/main/res/layout/activity_follower.xml new file mode 100644 index 00000000..004db3f3 --- /dev/null +++ b/app/src/main/res/layout/activity_follower.xml @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_follower_profile.xml b/app/src/main/res/layout/activity_follower_profile.xml new file mode 100644 index 00000000..6701daf0 --- /dev/null +++ b/app/src/main/res/layout/activity_follower_profile.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + +