Skip to content

Commit 5a78836

Browse files
committed
conflict 해결
2 parents fe2dc9b + fd06558 commit 5a78836

29 files changed

+1003
-30
lines changed

app/src/main/java/com/wafflestudio/siksha2/models/Review.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ data class Review(
1010
@Json(name = "user_id") val userId: Long,
1111
@Json(name = "score") val score: Double,
1212
@Json(name = "comment") val comment: String?,
13+
@Json(name = "keyword_reviews") val keywordReviews: List<String?>?,
14+
@Json(name = "is_liked") val isLiked: Boolean?,
15+
@Json(name = "name_kr") val nameKr: String?,
16+
@Json(name = "name_en") val nameEn: String?,
1317
@Json(name = "created_at") val createdAt: String,
18+
@Json(name = "updated_at") val updatedAt: String,
1419
@Json(name = "etc") val etc: Etc?
1520
)
1621

app/src/main/java/com/wafflestudio/siksha2/network/SikshaApi.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,24 @@ interface SikshaApi {
7373
@POST("/reviews/")
7474
suspend fun leaveMenuReview(@Body req: LeaveReviewParam): NetworkResult<LeaveReviewResult>
7575

76+
@PATCH("/reviews")
77+
suspend fun updateReviews(
78+
@Query("menu_id") menuId: Long,
79+
@Query("page") page: Long,
80+
@Query("per_page") perPage: Long
81+
): NetworkResult<FetchReviewsResult>
82+
83+
@DELETE("/reviews/{review_id}")
84+
suspend fun deleteReviews(
85+
@Path("review_id") reviewId: Long
86+
): Response<Unit?>
87+
88+
@GET("/reviews/me")
89+
suspend fun fetchMyReviews(
90+
@Query("page") page: Long,
91+
@Query("perPage") perPage: Long
92+
): NetworkResult<FetchMyReviewsResult>
93+
7694
@Multipart
7795
@POST("/reviews/images")
7896
suspend fun leaveMenuReviewImages(
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.wafflestudio.siksha2.network.dto
2+
3+
import com.squareup.moshi.Json
4+
import com.squareup.moshi.JsonClass
5+
import com.wafflestudio.siksha2.models.Review
6+
7+
@JsonClass(generateAdapter = true)
8+
data class ReviewRestaurant(
9+
@Json(name = "restaurant_id") val restaurantId: Long,
10+
@Json(name = "name_kr") val nameKr: String?,
11+
@Json(name = "name_en") val nameEn: String?,
12+
@Json(name = "reviews") val reviews: List<Review>
13+
)
14+
15+
@JsonClass(generateAdapter = true)
16+
data class FetchMyReviewsResult(
17+
@Json(name = "total_count") val totalCount: Int,
18+
@Json(name = "has_next") val hasNext: Boolean,
19+
@Json(name = "result") val result: List<ReviewRestaurant>
20+
)

app/src/main/java/com/wafflestudio/siksha2/repositories/MenuRepository.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ import com.wafflestudio.siksha2.network.dto.FetchReviewDistributionResult
1313
import com.wafflestudio.siksha2.network.dto.FetchReviewsResult
1414
import com.wafflestudio.siksha2.network.dto.LeaveReviewParam
1515
import com.wafflestudio.siksha2.network.dto.LeaveReviewResult
16+
import com.wafflestudio.siksha2.network.dto.ReviewRestaurant
1617
import com.wafflestudio.siksha2.network.result.NetworkResult
18+
import com.wafflestudio.siksha2.ui.menuDetail.MenuMyReviewPagingSource
1719
import com.wafflestudio.siksha2.ui.menuDetail.MenuReviewPagingSource
1820
import com.wafflestudio.siksha2.ui.menuDetail.MenuReviewWithImagePagingSource
1921
import com.wafflestudio.siksha2.utils.toLocalDate
@@ -80,6 +82,18 @@ class MenuRepository @Inject constructor(
8082
).flow
8183
}
8284

85+
fun getMyPagedReviewsByMenuIdFlow(): Flow<PagingData<ReviewRestaurant>> {
86+
return Pager(
87+
config = MenuMyReviewPagingSource.Config,
88+
pagingSourceFactory = { MenuMyReviewPagingSource(sikshaApi) }
89+
).flow
90+
}
91+
92+
suspend fun deleteReview(reviewId: Long): Boolean {
93+
val response = sikshaApi.deleteReviews(reviewId)
94+
return response.isSuccessful
95+
}
96+
8397
fun getPagedReviewsOnlyHaveImagesByMenuIdFlow(menuId: Long): Flow<PagingData<Review>> {
8498
return Pager(
8599
config = MenuReviewWithImagePagingSource.Config,

app/src/main/java/com/wafflestudio/siksha2/ui/main/setting/SettingFragment.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ class SettingFragment : Fragment() {
7676
findNavController().navigate(action)
7777
}
7878

79+
binding.myReviewRow.setOnClickListener {
80+
val action =
81+
MainFragmentDirections.actionMainFragmentToMyReviewFragment()
82+
findNavController().navigate(action)
83+
}
84+
7985
binding.orderRestaurantRow.setOnClickListener {
8086
val action =
8187
MainFragmentDirections.actionMainFragmentToReorderRestaurantFragment()

app/src/main/java/com/wafflestudio/siksha2/ui/menuDetail/LeaveReviewFragment.kt

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package com.wafflestudio.siksha2.ui.menuDetail
22

33
import android.Manifest
44
import android.app.Activity.RESULT_OK
5+
import android.content.Context
56
import android.content.Intent
67
import android.content.pm.PackageManager
8+
import android.net.Uri
79
import android.os.Build
810
import android.os.Bundle
911
import android.provider.MediaStore
@@ -30,7 +32,12 @@ import com.wafflestudio.siksha2.network.result.NetworkResult
3032
import com.wafflestudio.siksha2.utils.hasFinalConsInKr
3133
import com.wafflestudio.siksha2.utils.setVisibleOrGone
3234
import com.wafflestudio.siksha2.utils.showToast
35+
import kotlinx.coroutines.Dispatchers
3336
import kotlinx.coroutines.launch
37+
import kotlinx.coroutines.withContext
38+
import java.io.File
39+
import java.net.HttpURLConnection
40+
import java.net.URL
3441

3542
class LeaveReviewFragment : Fragment() {
3643
private lateinit var binding: FragmentLeaveReviewBinding
@@ -93,6 +100,32 @@ class LeaveReviewFragment : Fragment() {
93100
}
94101
}
95102

103+
vm.editingReview.observe(viewLifecycleOwner) { review ->
104+
review ?: return@observe
105+
106+
// 평점
107+
vm.setReviewRating(review.score.toFloat())
108+
binding.rateText.text = review.score.toInt().toString()
109+
110+
// 코멘트 세팅
111+
binding.commentEdit.setText(review.comment ?: "")
112+
113+
// Todo : keyword 세팅, patch api 연결
114+
115+
// 이미지(url) → Uri 로 변환
116+
review.etc?.images?.let { urls ->
117+
lifecycleScope.launch {
118+
urls.forEach { url: String ->
119+
val file = downloadImageToFile(requireContext(), url)
120+
file?.let {
121+
val uri = Uri.fromFile(it)
122+
vm.addImageUri(uri, onFailure = {})
123+
}
124+
}
125+
}
126+
}
127+
}
128+
96129
vm.commentHint.observe(viewLifecycleOwner) { hint ->
97130
binding.commentEdit.hint = hint
98131
}
@@ -193,6 +226,32 @@ class LeaveReviewFragment : Fragment() {
193226
}
194227
}
195228

229+
suspend fun downloadImageToFile(
230+
context: Context,
231+
imageUrl: String
232+
): File? = withContext(Dispatchers.IO) {
233+
return@withContext try {
234+
val url = URL(imageUrl)
235+
val connection = url.openConnection() as HttpURLConnection
236+
connection.connect()
237+
238+
if (connection.responseCode != HttpURLConnection.HTTP_OK) {
239+
return@withContext null
240+
}
241+
242+
val input = connection.inputStream
243+
val tempFile = File.createTempFile("review_img_", ".jpg", context.cacheDir)
244+
245+
tempFile.outputStream().use { output ->
246+
input.copyTo(output)
247+
}
248+
249+
tempFile
250+
} catch (e: Exception) {
251+
null
252+
}
253+
}
254+
196255
private fun requestPermission(onGranted: () -> Unit) {
197256
if (Build.VERSION.SDK_INT >= 33) {
198257
onGranted()

app/src/main/java/com/wafflestudio/siksha2/ui/menuDetail/MenuDetailViewModel.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import androidx.paging.PagingData
1212
import com.wafflestudio.siksha2.models.Menu
1313
import com.wafflestudio.siksha2.models.Review
1414
import com.wafflestudio.siksha2.network.dto.LeaveReviewResult
15+
import com.wafflestudio.siksha2.network.dto.ReviewRestaurant
1516
import com.wafflestudio.siksha2.network.result.NetworkResult
1617
import com.wafflestudio.siksha2.repositories.MenuRepository
1718
import com.wafflestudio.siksha2.utils.ImageUtil
@@ -65,6 +66,18 @@ class MenuDetailViewModel @Inject constructor(
6566
val reviewRating: FloatState
6667
get() = _reviewRating
6768

69+
private val _deleteResult = MutableLiveData<Boolean>()
70+
val deleteResult: LiveData<Boolean>
71+
get() = _deleteResult
72+
73+
private val _editingReview = MutableLiveData<Review?>()
74+
val editingReview: LiveData<Review?>
75+
get() = _editingReview
76+
77+
fun setEditingReview(review: Review?) {
78+
_editingReview.value = review
79+
}
80+
6881
fun refreshMenu(menuId: Long) {
6982
_networkResultState.value = State.LOADING
7083
viewModelScope.launch {
@@ -103,10 +116,21 @@ class MenuDetailViewModel @Inject constructor(
103116
}
104117
}
105118

119+
fun deleteReview(id: Long) {
120+
viewModelScope.launch {
121+
val success = menuRepository.deleteReview(id)
122+
_deleteResult.postValue(success)
123+
}
124+
}
125+
106126
fun getReviews(menuId: Long): Flow<PagingData<Review>> {
107127
return menuRepository.getPagedReviewsByMenuIdFlow(menuId)
108128
}
109129

130+
fun getMyReviews(): Flow<PagingData<ReviewRestaurant>> {
131+
return menuRepository.getMyPagedReviewsByMenuIdFlow()
132+
}
133+
110134
fun getReviewsWithImages(menuId: Long): Flow<PagingData<Review>> {
111135
return menuRepository.getPagedReviewsOnlyHaveImagesByMenuIdFlow(menuId)
112136
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.wafflestudio.siksha2.ui.menuDetail
2+
3+
import android.view.LayoutInflater
4+
import android.view.ViewGroup
5+
import androidx.core.view.isVisible
6+
import androidx.paging.PagingDataAdapter
7+
import androidx.recyclerview.widget.DiffUtil
8+
import androidx.recyclerview.widget.LinearLayoutManager
9+
import androidx.recyclerview.widget.RecyclerView
10+
import com.wafflestudio.siksha2.databinding.ItemMyReviewRestaurantBinding
11+
import com.wafflestudio.siksha2.models.Review
12+
import com.wafflestudio.siksha2.network.dto.ReviewRestaurant
13+
14+
class MenuMyReviewAdapter(
15+
private val onMenuClick: (Review) -> Unit,
16+
private val onEditClick: (Review) -> Unit,
17+
private val onDeleteClick: (Review) -> Unit
18+
) :
19+
PagingDataAdapter<ReviewRestaurant, MenuMyReviewAdapter.RestaurantViewHolder>(DiffCallback) {
20+
21+
companion object {
22+
private val DiffCallback = object : DiffUtil.ItemCallback<ReviewRestaurant>() {
23+
override fun areItemsTheSame(oldItem: ReviewRestaurant, newItem: ReviewRestaurant): Boolean {
24+
return oldItem.restaurantId == newItem.restaurantId
25+
}
26+
27+
override fun areContentsTheSame(oldItem: ReviewRestaurant, newItem: ReviewRestaurant): Boolean {
28+
return oldItem == newItem
29+
}
30+
}
31+
}
32+
33+
inner class RestaurantViewHolder(private val binding: ItemMyReviewRestaurantBinding) :
34+
RecyclerView.ViewHolder(binding.root) {
35+
36+
private var isExpanded = false
37+
38+
fun bind(item: ReviewRestaurant) {
39+
if (bindingAdapterPosition == 0) {
40+
isExpanded = true
41+
binding.topDivider.isVisible = true
42+
}
43+
44+
binding.restaurantName.text = item.nameKr
45+
binding.arrowIcon.rotation = if (isExpanded) 180f else 0f
46+
47+
// 리뷰 어댑터 (Nested RecyclerView)
48+
binding.reviewRecycler.layoutManager = LinearLayoutManager(binding.root.context)
49+
50+
val reviewAdapter = MenuMyReviewChildAdapter(onMenuClick, onEditClick, onDeleteClick)
51+
binding.reviewRecycler.adapter = reviewAdapter
52+
53+
reviewAdapter.submitList(item.reviews)
54+
55+
// 펼치기/접기
56+
binding.root.setOnClickListener {
57+
isExpanded = !isExpanded
58+
binding.arrowIcon.animate().rotation(if (isExpanded) 180f else 0f).start()
59+
binding.reviewRecycler.isVisible = isExpanded
60+
binding.topDivider.isVisible = isExpanded
61+
}
62+
63+
// 초기에는 접혀있게
64+
binding.reviewRecycler.isVisible = isExpanded
65+
}
66+
}
67+
68+
override fun onBindViewHolder(holder: RestaurantViewHolder, position: Int) {
69+
getItem(position)?.let { holder.bind(it) }
70+
}
71+
72+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RestaurantViewHolder {
73+
val binding = ItemMyReviewRestaurantBinding.inflate(LayoutInflater.from(parent.context), parent, false)
74+
return RestaurantViewHolder(binding)
75+
}
76+
}

0 commit comments

Comments
 (0)