diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0d799397..a86b06f7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -170,7 +170,7 @@ android:value="" /> + activity?.showToast(App.appContext.getString(R.string.delete_undo)) + } + setPositiveButton("삭제") { _, _ -> + viewModel.deleteReview(reviewId) + lifecycleScope.launch { + viewModel.uiState.collectLatest { + if (it.isDeleted) { + onReviewDeletedListener?.onReviewDeleted() // 콜백 호출 + dismiss() + } + } + } + } + }.create().show() + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/presentation/common/OthersBottomSheetFragment.kt b/app/src/main/java/com/eatssu/android/presentation/common/OthersBottomSheetFragment.kt new file mode 100644 index 00000000..b117e81b --- /dev/null +++ b/app/src/main/java/com/eatssu/android/presentation/common/OthersBottomSheetFragment.kt @@ -0,0 +1,50 @@ +package com.eatssu.android.presentation.common + +import android.content.Intent +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.eatssu.android.databinding.FragmentBottomsheetOthersBinding +import com.eatssu.android.presentation.review.report.ReportActivity +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import dagger.hilt.android.AndroidEntryPoint +import timber.log.Timber + +@AndroidEntryPoint +class OthersBottomSheetFragment : BottomSheetDialogFragment() { + private var _binding: FragmentBottomsheetOthersBinding? = null + private val binding get() = _binding!! + + var reviewId = -1L + var menu = "" + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentBottomsheetOthersBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + arguments?.let { + reviewId = it.getLong("reviewId") + menu = it.getString("menu").toString() + } + + Timber.d("넘겨받은 리뷰 정보: $reviewId $menu") + + binding.llReport.setOnClickListener { + + val intent = Intent(requireContext(), ReportActivity::class.java) + intent.putExtra("reviewId", reviewId) + Timber.d("reviewId $reviewId") + startActivity(intent) + dismiss() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/presentation/mypage/myreview/MyReviewAdapter.kt b/app/src/main/java/com/eatssu/android/presentation/mypage/myreview/MyReviewAdapter.kt index 5649cf96..7368874d 100644 --- a/app/src/main/java/com/eatssu/android/presentation/mypage/myreview/MyReviewAdapter.kt +++ b/app/src/main/java/com/eatssu/android/presentation/mypage/myreview/MyReviewAdapter.kt @@ -1,69 +1,61 @@ package com.eatssu.android.presentation.mypage.myreview -import android.content.Intent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.content.ContextCompat -import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter import com.bumptech.glide.Glide import com.eatssu.android.data.MySharedPreferences import com.eatssu.android.databinding.ItemReviewBinding import com.eatssu.android.domain.model.Review -import com.eatssu.android.presentation.review.delete.MyReviewDialogActivity import timber.log.Timber +class MyReviewAdapter : + ListAdapter(ReviewDiffCallback()) { -class MyReviewAdapter(private val dataList: List) : - RecyclerView.Adapter() { + interface OnItemClickListener { + fun onMyReviewClicked(view: View, reviewData: Review) + } - inner class ViewHolder(private val binding: ItemReviewBinding) : - RecyclerView.ViewHolder(binding.root) { + // 객체 저장 변수 + private lateinit var mOnItemClickListener: OnItemClickListener - fun bind(position: Int) { - binding.tvReviewItemComment.text = dataList[position].content - binding.tvReviewItemDate.text = dataList[position].writeDate - binding.tvMenuName.text = dataList[position].menu + // 객체 전달 메서드 + fun setOnItemClickListener(onItemClickListener: OnItemClickListener) { + mOnItemClickListener = onItemClickListener + } - binding.rbRate.rating = dataList[position].mainGrade.toFloat() + inner class ViewHolder(private val binding: ItemReviewBinding) : + androidx.recyclerview.widget.RecyclerView.ViewHolder(binding.root) { + + fun bind(data: Review) { binding.tvWriterNickname.text = MySharedPreferences.getUserName(binding.root.context) + binding.tvReviewItemComment.text = data.content + binding.tvReviewItemDate.text = data.writeDate + binding.tvMenuName.text = data.menu + binding.rbRate.rating = data.mainGrade.toFloat() val imageView: ImageView = binding.ivReviewPhoto - - if (dataList[position].imgUrl?.isEmpty() == true) { + if (data.imgUrl?.isEmpty() == true || data.imgUrl?.get(0).isNullOrEmpty()) { imageView.visibility = View.GONE } else { - Timber.d("사진 있다") Glide.with(itemView) - .load(dataList[position].imgUrl?.get(0)) + .load(data.imgUrl?.get(0)) .into(imageView) imageView.visibility = View.VISIBLE - - if (dataList[position].imgUrl?.get(0) == "" || dataList[position].imgUrl?.get(0) == null) { - binding.ivReviewPhoto.visibility = View.GONE - } } - binding.btnDetail.setOnClickListener { - val intent = Intent(binding.btnDetail.context, MyReviewDialogActivity::class.java) - intent.putExtra("reviewId", dataList[position].reviewId) - intent.putExtra("menu", dataList[position].menu) - - intent.putExtra("content", dataList[position].content) - - intent.putExtra("mainGrade", dataList[position].mainGrade) - intent.putExtra("amountGrade", dataList[position].amountGrade) - intent.putExtra("tasteGrade", dataList[position].tasteGrade) + binding.btnDetail.setOnClickListener { v: View -> + mOnItemClickListener.onMyReviewClicked(v, data) Timber.d( "리뷰 상세 정보 - ID: %d, 메뉴: %s, 내용: %s", - dataList[position].reviewId, - dataList[position].menu, - dataList[position].content + data.reviewId, + data.menu, + data.content ) - - ContextCompat.startActivity(binding.btnDetail.context, intent, null) } } } @@ -75,8 +67,17 @@ class MyReviewAdapter(private val dataList: List) : } override fun onBindViewHolder(holder: ViewHolder, position: Int) { - holder.bind(position) + val item = getItem(position) + holder.bind(item) } +} - override fun getItemCount(): Int = dataList.size -} \ No newline at end of file +class ReviewDiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: Review, newItem: Review): Boolean { + return oldItem.reviewId == newItem.reviewId + } + + override fun areContentsTheSame(oldItem: Review, newItem: Review): Boolean { + return oldItem == newItem + } +} diff --git a/app/src/main/java/com/eatssu/android/presentation/mypage/myreview/MyReviewListActivity.kt b/app/src/main/java/com/eatssu/android/presentation/mypage/myreview/MyReviewListActivity.kt index 2beee9a1..39fa59f6 100644 --- a/app/src/main/java/com/eatssu/android/presentation/mypage/myreview/MyReviewListActivity.kt +++ b/app/src/main/java/com/eatssu/android/presentation/mypage/myreview/MyReviewListActivity.kt @@ -3,18 +3,22 @@ package com.eatssu.android.presentation.mypage.myreview import android.os.Bundle import android.view.View import androidx.activity.viewModels +import androidx.fragment.app.DialogFragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager +import com.eatssu.android.R import com.eatssu.android.databinding.ActivityMyReviewListBinding import com.eatssu.android.domain.model.Review import com.eatssu.android.presentation.base.BaseActivity +import com.eatssu.android.presentation.common.MyReviewBottomSheetFragment import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @AndroidEntryPoint class MyReviewListActivity : - BaseActivity(ActivityMyReviewListBinding::inflate) { + BaseActivity(ActivityMyReviewListBinding::inflate), + MyReviewBottomSheetFragment.OnReviewDeletedListener { private val myReviewViewModel: MyReviewViewModel by viewModels() @@ -28,10 +32,21 @@ class MyReviewListActivity : } private fun setAdapter(reviewList: List) { - val listAdapter = MyReviewAdapter(reviewList) + + val adapter = MyReviewAdapter() + adapter.submitList(reviewList) + val linearLayoutManager = LinearLayoutManager(this) - binding.rvReview.adapter = listAdapter + adapter.setOnItemClickListener(object : + MyReviewAdapter.OnItemClickListener { + + override fun onMyReviewClicked(view: View, reviewData: Review) { + onMyReviewClicked(review = reviewData) + } + }) + + binding.rvReview.adapter = adapter binding.rvReview.layoutManager = linearLayoutManager binding.rvReview.setHasFixedSize(true) } @@ -62,4 +77,29 @@ class MyReviewListActivity : super.onResume() lodeReview() } + + fun onMyReviewClicked(review: Review) { + + val modalBottomSheet = MyReviewBottomSheetFragment().apply { + arguments = Bundle().apply { + putLong("reviewId", review.reviewId) + putString("menu", review.menu) + putString("content", review.content) + putInt("mainGrade", review.mainGrade) + putInt("amountGrade", review.amountGrade) + putInt("tasteGrade", review.tasteGrade) + } + onReviewDeletedListener = this@MyReviewListActivity + } + modalBottomSheet.setStyle( + DialogFragment.STYLE_NORMAL, + R.style.RoundCornerBottomSheetDialogTheme + ) + modalBottomSheet.show(supportFragmentManager, "Open Bottom Sheet") + } + + override fun onReviewDeleted() { + lodeReview() + } + } \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/presentation/mypage/myreview/MyReviewViewModel.kt b/app/src/main/java/com/eatssu/android/presentation/mypage/myreview/MyReviewViewModel.kt index b65be4bf..29fe8b12 100644 --- a/app/src/main/java/com/eatssu/android/presentation/mypage/myreview/MyReviewViewModel.kt +++ b/app/src/main/java/com/eatssu/android/presentation/mypage/myreview/MyReviewViewModel.kt @@ -1,11 +1,15 @@ package com.eatssu.android.presentation.mypage.myreview +import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.eatssu.android.R import com.eatssu.android.data.dto.response.toReviewList import com.eatssu.android.domain.model.Review import com.eatssu.android.domain.usecase.auth.GetMyReviewsUseCase +import com.eatssu.android.domain.usecase.review.DeleteReviewUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -21,6 +25,8 @@ import javax.inject.Inject @HiltViewModel class MyReviewViewModel @Inject constructor( private val getMyReviewsUseCase: GetMyReviewsUseCase, + private val deleteReviewUseCase: DeleteReviewUseCase, + @ApplicationContext private val context: Context ) : ViewModel() { private val _uiState: MutableStateFlow = MutableStateFlow(MyReviewState()) @@ -55,6 +61,33 @@ class MyReviewViewModel @Inject constructor( } } } + + fun deleteReview(reviewId: Long) { + viewModelScope.launch { + deleteReviewUseCase(reviewId).onStart { + _uiState.update { it.copy(loading = true) } + }.onCompletion { + _uiState.update { it.copy(loading = false, error = true) } + }.catch { e -> + _uiState.update { + it.copy( + error = true, + toastMessage = context.getString(R.string.delete_not) + ) + } + Timber.e(e.toString()) + }.collectLatest { result -> + Timber.d(result.toString()) + + _uiState.update { + it.copy( + isDeleted = true, + toastMessage = context.getString(R.string.delete_done) + ) + } + } + } + } } @@ -67,5 +100,6 @@ data class MyReviewState( var isEmpty: Boolean = false, var myReviews: List? = null, + var isDeleted: Boolean = false, ) \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/presentation/review/delete/DeleteViewModel.kt b/app/src/main/java/com/eatssu/android/presentation/review/delete/DeleteViewModel.kt deleted file mode 100644 index ef9fb66d..00000000 --- a/app/src/main/java/com/eatssu/android/presentation/review/delete/DeleteViewModel.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.eatssu.android.presentation.review.delete - -import android.content.Context -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.eatssu.android.R -import com.eatssu.android.domain.usecase.review.DeleteReviewUseCase -import dagger.hilt.android.lifecycle.HiltViewModel -import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.onCompletion -import kotlinx.coroutines.flow.onStart -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import timber.log.Timber -import javax.inject.Inject - -@HiltViewModel -class DeleteViewModel @Inject constructor( - private val deleteReviewUseCase: DeleteReviewUseCase, - @ApplicationContext private val context: Context -) : ViewModel() { - - private val _uiState: MutableStateFlow = MutableStateFlow(DeleteState()) - val uiState: StateFlow = _uiState.asStateFlow() - - - fun deleteReview(reviewId: Long) { - viewModelScope.launch { - deleteReviewUseCase(reviewId).onStart { - _uiState.update { it.copy(loading = true) } - }.onCompletion { - _uiState.update { it.copy(loading = false, error = true) } - }.catch { e -> - _uiState.update { - it.copy( - error = true, - toastMessage = context.getString(R.string.delete_not) - ) - } - Timber.e(e.toString()) - }.collectLatest { result -> - Timber.d(result.toString()) - - _uiState.update { - it.copy( - isDeleted = true, - toastMessage = context.getString(R.string.delete_done) - ) - } - } - } - } -} - -data class DeleteState( - var loading: Boolean = true, - var error: Boolean = false, - - var toastMessage: String = "", - - var isDeleted: Boolean = false, - - ) \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/presentation/review/delete/MyReviewDialogActivity.kt b/app/src/main/java/com/eatssu/android/presentation/review/delete/MyReviewDialogActivity.kt deleted file mode 100644 index 57313a79..00000000 --- a/app/src/main/java/com/eatssu/android/presentation/review/delete/MyReviewDialogActivity.kt +++ /dev/null @@ -1,84 +0,0 @@ -package com.eatssu.android.presentation.review.delete - -import android.content.Intent -import android.os.Bundle -import androidx.activity.viewModels -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.lifecycleScope -import com.eatssu.android.App -import com.eatssu.android.R -import com.eatssu.android.databinding.ActivityMyReviewDialogBinding -import com.eatssu.android.presentation.review.modify.ModifyReviewActivity -import com.eatssu.android.presentation.util.showToast -import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.launch -import timber.log.Timber - -@AndroidEntryPoint -class MyReviewDialogActivity : AppCompatActivity() { - private lateinit var binding: ActivityMyReviewDialogBinding - - private val deleteViewModel: DeleteViewModel by viewModels() - - var reviewId = -1L - var menu = "" - var content = "" - var mainGrade = -1 - var amountGrade = -1 - var tasteGrade = -1 - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - binding = ActivityMyReviewDialogBinding.inflate(layoutInflater) - setContentView(binding.root) - - reviewId = intent.getLongExtra("reviewId", -1L) - menu = intent.getStringExtra("menu").toString() - content = intent.getStringExtra("content").toString() - mainGrade = intent.getIntExtra("mainGrade", -1) - amountGrade = intent.getIntExtra("amountGrade", -1) - tasteGrade = intent.getIntExtra("tasteGrade", -1) - - Timber.d("전:" + reviewId.toString()) - Timber.d("전:" + menu.toString()) - Timber.d("전:" + content.toString()) - Timber.d(reviewId.toString()) - - binding.btnReviewFix.setOnClickListener { - val intent = Intent(this, ModifyReviewActivity::class.java) - intent.putExtra("reviewId", reviewId) - intent.putExtra("menu", menu) - intent.putExtra("content", content) - intent.putExtra("mainGrade", mainGrade) - intent.putExtra("amountGrade", amountGrade) - intent.putExtra("tasteGrade", tasteGrade) - - startActivity(intent) - finish() - } - - binding.btnReviewDelete.setOnClickListener { - AlertDialog.Builder(this).apply { - setTitle(R.string.delete) - setMessage(R.string.delete_description) - setNegativeButton("취소") { _, _ -> - showToast(App.appContext.getString(R.string.delete_undo)) - } - setPositiveButton("삭제") { _, _ -> - deleteViewModel.deleteReview(reviewId) - lifecycleScope.launch { - deleteViewModel.uiState.collectLatest { - if (it.isDeleted) { - finish() - } - } - } - } - }.create().show() - - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/presentation/review/list/ReviewActivity.kt b/app/src/main/java/com/eatssu/android/presentation/review/list/ReviewActivity.kt index feb396e7..670664e8 100644 --- a/app/src/main/java/com/eatssu/android/presentation/review/list/ReviewActivity.kt +++ b/app/src/main/java/com/eatssu/android/presentation/review/list/ReviewActivity.kt @@ -4,12 +4,16 @@ import android.content.Intent import android.os.Bundle import android.view.View import androidx.activity.viewModels +import androidx.fragment.app.DialogFragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager +import com.eatssu.android.R import com.eatssu.android.data.enums.MenuType import com.eatssu.android.databinding.ActivityReviewBinding +import com.eatssu.android.domain.model.Review import com.eatssu.android.presentation.base.BaseActivity -import com.eatssu.android.presentation.review.delete.DeleteViewModel +import com.eatssu.android.presentation.common.MyReviewBottomSheetFragment +import com.eatssu.android.presentation.common.OthersBottomSheetFragment import com.eatssu.android.presentation.review.write.ReviewWriteRateActivity import com.eatssu.android.presentation.review.write.menu.ReviewWriteMenuActivity import dagger.hilt.android.AndroidEntryPoint @@ -20,17 +24,15 @@ import kotlin.properties.Delegates @AndroidEntryPoint class ReviewActivity : - BaseActivity(ActivityReviewBinding::inflate) { + BaseActivity(ActivityReviewBinding::inflate), + MyReviewBottomSheetFragment.OnReviewDeletedListener { - private val deleteViewModel: DeleteViewModel by viewModels() private val reviewViewModel: ReviewViewModel by viewModels() private lateinit var menuType: String private var itemId by Delegates.notNull() private lateinit var itemName: String - private var reviewAdapter: ReviewAdapter? = null - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -68,7 +70,6 @@ class ReviewActivity : } - private fun bindData() { lifecycleScope.launch { reviewViewModel.uiState.collectLatest { @@ -88,19 +89,7 @@ class ReviewActivity : binding.llNonReview.visibility = View.INVISIBLE binding.rvReview.visibility = View.VISIBLE - reviewAdapter = it.reviewList?.let { review -> - ReviewAdapter(review) { reviewId -> - deleteViewModel.deleteReview( - reviewId - ) - } - } - - binding.rvReview.apply { - adapter = reviewAdapter - layoutManager = LinearLayoutManager(applicationContext) - setHasFixedSize(true) - } + it.reviewList?.let { reviewList -> setAdapter(reviewList = reviewList) } it.reviewInfo?.apply { @@ -129,6 +118,32 @@ class ReviewActivity : } } + + private fun setAdapter(reviewList: List) { + + val adapter = ReviewAdapter() + adapter.submitList(reviewList) + + val linearLayoutManager = LinearLayoutManager(this) + + adapter.setOnItemClickListener(object : + ReviewAdapter.OnItemClickListener { + + override fun onMyReviewClicked(view: View, reviewData: Review) { + onMyReviewClicked(review = reviewData) + } + + override fun onOthersReviewClicked(view: View, reviewData: Review) { + onOthersReviewClicked(reviewData = reviewData) + } + }) + + binding.rvReview.adapter = adapter + binding.rvReview.layoutManager = linearLayoutManager + binding.rvReview.setHasFixedSize(true) + } + + private fun setClickListener() { when (menuType) { MenuType.FIXED.name -> { @@ -155,4 +170,47 @@ class ReviewActivity : } } } + + + fun onMyReviewClicked(review: Review) { + val modalBottomSheet = MyReviewBottomSheetFragment().apply { + arguments = Bundle().apply { + putLong("reviewId", review.reviewId) + putString("menu", review.menu) + putString("content", review.content) + putInt("mainGrade", review.mainGrade) + putInt("amountGrade", review.amountGrade) + putInt("tasteGrade", review.tasteGrade) + } + onReviewDeletedListener = this@ReviewActivity + } + modalBottomSheet.setStyle( + DialogFragment.STYLE_NORMAL, + R.style.RoundCornerBottomSheetDialogTheme + ) + modalBottomSheet.show(supportFragmentManager, "Open Bottom Sheet") + } + + fun onOthersReviewClicked(reviewData: Review) { + val modalBottomSheet = OthersBottomSheetFragment() + modalBottomSheet.setStyle( + DialogFragment.STYLE_NORMAL, + R.style.RoundCornerBottomSheetDialogTheme + ) + + val bundle = Bundle() + bundle.let { + it.putLong("reviewId", reviewData.reviewId) + it.putString("menu", reviewData.menu) + } + + modalBottomSheet.arguments = bundle + modalBottomSheet.show(supportFragmentManager, "Open Bottom Sheet") + } + + + override fun onReviewDeleted() { + lodeData() + bindData() + } } diff --git a/app/src/main/java/com/eatssu/android/presentation/review/list/ReviewAdapter.kt b/app/src/main/java/com/eatssu/android/presentation/review/list/ReviewAdapter.kt index 112b122b..f6948f8a 100644 --- a/app/src/main/java/com/eatssu/android/presentation/review/list/ReviewAdapter.kt +++ b/app/src/main/java/com/eatssu/android/presentation/review/list/ReviewAdapter.kt @@ -1,53 +1,48 @@ package com.eatssu.android.presentation.review.list -import android.content.Context -import android.content.Intent -import android.util.Log import android.view.LayoutInflater -import android.view.MenuItem import android.view.View import android.view.ViewGroup -import androidx.annotation.MenuRes -import androidx.appcompat.widget.PopupMenu -import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide -import com.eatssu.android.R import com.eatssu.android.databinding.ItemReviewBinding import com.eatssu.android.domain.model.Review -import com.eatssu.android.presentation.review.modify.ModifyReviewActivity -import com.eatssu.android.presentation.review.report.ReportActivity -class ReviewAdapter( - private val dataList: List, - private val callBackReviewId: (Long) -> Unit -) : - RecyclerView.Adapter() { +class ReviewAdapter : + ListAdapter(ReviewDiffCallback()) { + + interface OnItemClickListener { + fun onMyReviewClicked(view: View, reviewData: Review) + fun onOthersReviewClicked(view: View, reviewData: Review) + } + + private lateinit var mOnItemClickListener: OnItemClickListener + + fun setOnItemClickListener(onItemClickListener: OnItemClickListener) { + mOnItemClickListener = onItemClickListener + } inner class ViewHolder(private val binding: ItemReviewBinding) : RecyclerView.ViewHolder(binding.root) { - fun bind(position: Int) { - val data = dataList[position].apply { - binding.tvWriterNickname.text = writerNickname - binding.tvReviewItemComment.text = content - binding.tvReviewItemDate.text = writeDate - binding.tvMenuName.text = menu //TODO 리사이클러뷰로 변경 - binding.rbRate.rating = mainGrade.toFloat() - } + fun bind(data: Review) { + binding.tvWriterNickname.text = data.writerNickname + binding.tvReviewItemComment.text = data.content + binding.tvReviewItemDate.text = data.writeDate + binding.tvMenuName.text = data.menu + binding.rbRate.rating = data.mainGrade.toFloat() if (!data.imgUrl.isNullOrEmpty()) { - Log.d("ReviewAdapter", data.content + data.imgUrl?.size.toString()) - data.imgUrl?.toString()?.let { Log.d("ReviewAdapter", it) } - Glide.with(itemView) .load(data.imgUrl[0]) .into(binding.ivReviewPhoto) binding.ivReviewPhoto.visibility = View.VISIBLE binding.cvPhotoReview.visibility = View.VISIBLE - if (data.imgUrl[0] == "") { + if (data.imgUrl[0].isEmpty()) { binding.ivReviewPhoto.visibility = View.GONE binding.cvPhotoReview.visibility = View.GONE } @@ -58,81 +53,34 @@ class ReviewAdapter( binding.btnDetail.setOnClickListener { v: View -> if (data.isWriter) { - showMenu(binding.root.context, v, R.menu.menu_my_review, data) + mOnItemClickListener.onMyReviewClicked(v, data) } else { - showMenu(binding.root.context, v, R.menu.menu_other_review, data) + mOnItemClickListener.onOthersReviewClicked(v, data) } } } } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val binding = ItemReviewBinding.inflate(LayoutInflater.from(parent.context), parent, false) - return ViewHolder(binding) - } - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is ViewHolder -> holder.bind(position) - } + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val review = getItem(position) // `ListAdapter`에서 제공 + holder.bind(review) } +} - - private fun showMenu(holdercontext: Context, v: View, @MenuRes menuRes: Int, data: Review) { - val popup = PopupMenu(holdercontext, v) - popup.menuInflater.inflate(menuRes, popup.menu) - - popup.setOnMenuItemClickListener { menuItem: MenuItem -> - // Respond to menu item click. - when (menuItem.itemId) { - R.id.report -> { - val intent = - Intent(holdercontext, ReportActivity::class.java) - intent.putExtra("reviewId", data.reviewId) - intent.putExtra("menu", data.menu) - ContextCompat.startActivity(holdercontext, intent, null) - - true - } - - R.id.fix -> { - val intent = - Intent(holdercontext, ModifyReviewActivity::class.java) - intent.putExtra("reviewId", data.reviewId) - intent.putExtra("menu", data.menu) - intent.putExtra("content", data.content) - intent.putExtra("mainGrade", data.mainGrade) - intent.putExtra("amountGrade", data.amountGrade) - intent.putExtra("tasteGrade", data.tasteGrade) - - Log.d("ReviewFixedActivity", "전전:" + data.reviewId) - Log.d("ReviewFixedActivity", "전전:" + data.menu) - Log.d("ReviewFixedActivity", "전전:" + data.content) -//// Timber.d("내용: "+data.content) - ContextCompat.startActivity(holdercontext, intent, null) - true - } - - R.id.delete -> { - callBackReviewId(data.reviewId) - true - } - - else -> { - true - } - } - } - popup.setOnDismissListener { - // Respond to popup being dismissed. - } -// Show the popup menu. - popup.show() +class ReviewDiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: Review, newItem: Review): Boolean { + // 고유 식별자를 비교 (예: id) + return oldItem.reviewId == newItem.reviewId } - override fun getItemCount(): Int = dataList.size - + override fun areContentsTheSame(oldItem: Review, newItem: Review): Boolean { + // 객체의 내용 전체를 비교 + return oldItem == newItem + } } diff --git a/app/src/main/java/com/eatssu/android/presentation/review/list/ReviewViewModel.kt b/app/src/main/java/com/eatssu/android/presentation/review/list/ReviewViewModel.kt index b49b83bf..86e42362 100644 --- a/app/src/main/java/com/eatssu/android/presentation/review/list/ReviewViewModel.kt +++ b/app/src/main/java/com/eatssu/android/presentation/review/list/ReviewViewModel.kt @@ -7,6 +7,7 @@ import com.eatssu.android.data.dto.response.toReviewList import com.eatssu.android.data.enums.MenuType import com.eatssu.android.domain.model.Review import com.eatssu.android.domain.model.ReviewInfo +import com.eatssu.android.domain.usecase.review.DeleteReviewUseCase import com.eatssu.android.domain.usecase.review.GetMealReviewInfoUseCase import com.eatssu.android.domain.usecase.review.GetMealReviewListUseCase import com.eatssu.android.domain.usecase.review.GetMenuReviewInfoUseCase @@ -31,6 +32,7 @@ class ReviewViewModel @Inject constructor( private val getMenuReviewListUseCase: GetMenuReviewListUseCase, private val getMealReviewInfoUseCase: GetMealReviewInfoUseCase, private val getMealReviewListUseCase: GetMealReviewListUseCase, + private val deleteReviewUseCase: DeleteReviewUseCase, ) : ViewModel() { private val _uiState: MutableStateFlow = MutableStateFlow(ReviewState()) @@ -224,6 +226,33 @@ class ReviewViewModel @Inject constructor( } } } + + fun deleteReview(reviewId: Long) { + viewModelScope.launch { + deleteReviewUseCase(reviewId).onStart { + _uiState.update { it.copy(loading = true) } + }.onCompletion { + _uiState.update { it.copy(loading = false, error = true) } + }.catch { e -> + _uiState.update { + it.copy( + error = true, +// toastMessage = context.getString(R.string.delete_not) + ) + } + Timber.e(e.toString()) + }.collectLatest { result -> + Timber.d(result.toString()) + + _uiState.update { + it.copy( +// isDeleted = true, +// toastMessage = context.getString(R.string.delete_done) + ) + } + } + } + } } data class ReviewState( diff --git a/app/src/main/java/com/eatssu/android/presentation/review/report/OthersReviewDialogActivity.kt b/app/src/main/java/com/eatssu/android/presentation/review/report/OthersReviewDialogActivity.kt deleted file mode 100644 index 88b4609f..00000000 --- a/app/src/main/java/com/eatssu/android/presentation/review/report/OthersReviewDialogActivity.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.eatssu.android.presentation.review.report - -import android.content.Intent -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.eatssu.android.databinding.ActivityOthersReviewDialogBinding -import timber.log.Timber - -class OthersReviewDialogActivity : AppCompatActivity() { - - private lateinit var binding: ActivityOthersReviewDialogBinding - var reviewId = -1L - var menuId = -1L - var menu = "" - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - binding = ActivityOthersReviewDialogBinding.inflate(layoutInflater) - - setContentView(binding.root) - - reviewId = intent.getLongExtra("reviewId", -1L) - menu = intent.getStringExtra("menu").toString() - - - binding.btnReviewReport.setOnClickListener { - val intent = Intent(this, ReportActivity::class.java) - intent.putExtra( - "reviewId", reviewId - ) - Timber.d("reviewId $reviewId") - startActivity(intent) - finish() - } - - - } -} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_pencil.xml b/app/src/main/res/drawable/ic_pencil.xml new file mode 100644 index 00000000..c04bdf61 --- /dev/null +++ b/app/src/main/res/drawable/ic_pencil.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/drawable/ic_remove.xml b/app/src/main/res/drawable/ic_remove.xml new file mode 100644 index 00000000..3fe37ca3 --- /dev/null +++ b/app/src/main/res/drawable/ic_remove.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/layout/activity_fix_menu.xml b/app/src/main/res/layout/activity_fix_menu.xml index efe9e40a..32397c14 100644 --- a/app/src/main/res/layout/activity_fix_menu.xml +++ b/app/src/main/res/layout/activity_fix_menu.xml @@ -47,7 +47,10 @@ android:layout_height="wrap_content" android:isIndicator="false" android:numStars="5" + android:progressBackgroundTint="@color/gray300" + android:progressTint="@color/star" android:rating="0" + android:secondaryProgressTint="@color/star" android:stepSize="1" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" @@ -102,7 +105,10 @@ android:layout_gravity="center" android:isIndicator="false" android:numStars="5" + android:progressBackgroundTint="@color/gray300" + android:progressTint="@color/star" android:rating="0" + android:secondaryProgressTint="@color/star" android:stepSize="1" /> @@ -131,9 +137,13 @@ style="@style/Widget.AppCompat.RatingBar.Indicator" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_gravity="center" android:isIndicator="false" android:numStars="5" + android:progressBackgroundTint="@color/gray300" + android:progressTint="@color/star" android:rating="0" + android:secondaryProgressTint="@color/star" android:stepSize="1" /> diff --git a/app/src/main/res/layout/activity_my_review_dialog.xml b/app/src/main/res/layout/activity_my_review_dialog.xml deleted file mode 100644 index 1f8a10c4..00000000 --- a/app/src/main/res/layout/activity_my_review_dialog.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_bottomsheet_my_review.xml b/app/src/main/res/layout/fragment_bottomsheet_my_review.xml new file mode 100644 index 00000000..29984fa0 --- /dev/null +++ b/app/src/main/res/layout/fragment_bottomsheet_my_review.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_bottomsheet_others.xml b/app/src/main/res/layout/fragment_bottomsheet_others.xml new file mode 100644 index 00000000..245979d8 --- /dev/null +++ b/app/src/main/res/layout/fragment_bottomsheet_others.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file