diff --git a/app/src/debug/res/drawable/rect27_white.xml b/app/src/debug/res/drawable/rect27_white.xml new file mode 100644 index 00000000..2d7cdba8 --- /dev/null +++ b/app/src/debug/res/drawable/rect27_white.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/teampome/pome/model/response/DeleteFriendRecord.kt b/app/src/main/java/com/teampome/pome/model/response/DeleteFriendRecord.kt new file mode 100644 index 00000000..f05b0f7b --- /dev/null +++ b/app/src/main/java/com/teampome/pome/model/response/DeleteFriendRecord.kt @@ -0,0 +1,6 @@ +package com.teampome.pome.model.response + +//친구 삭제 Response +data class DeleteFriendRecord( + val data : Boolean +) diff --git a/app/src/main/java/com/teampome/pome/model/response/GetFriendRecord.kt b/app/src/main/java/com/teampome/pome/model/response/GetFriendRecord.kt index 23b79df5..59742627 100644 --- a/app/src/main/java/com/teampome/pome/model/response/GetFriendRecord.kt +++ b/app/src/main/java/com/teampome/pome/model/response/GetFriendRecord.kt @@ -13,17 +13,31 @@ data class GetFriendRecord( val useComment: String, val oneLineMind: String, val createdAt: String, - val emotionResponse: FriendEmotion + val emotionResponse: EmotionResponse ) : Parcelable @Parcelize -data class FriendEmotion( +data class EmotionResponse( val firstEmotion : Int, val secondEmotion : Int, - val myEmotion : Int, - val friendEmotion : List + val myEmotion : Int?, + val friendEmotions : List ) : Parcelable +@Parcelize +data class FriendEmotionResponse( + val nickname : String, + val emotionId : Int, +) : Parcelable + +//@Parcelize +//data class FriendEmotion( +// val firstEmotion : Int, +// val secondEmotion : Int, +// val myEmotion : Int?, +// val friendEmotions : List? +//) : Parcelable + /* "id": 3, "nickname": "찬영짱121", diff --git a/app/src/main/java/com/teampome/pome/network/AddFriendsService.kt b/app/src/main/java/com/teampome/pome/network/AddFriendsService.kt index 581ffa2e..fec896c2 100644 --- a/app/src/main/java/com/teampome/pome/network/AddFriendsService.kt +++ b/app/src/main/java/com/teampome/pome/network/AddFriendsService.kt @@ -4,6 +4,7 @@ import com.teampome.pome.model.base.BaseAllData import com.teampome.pome.model.base.BasePomeResponse import com.teampome.pome.model.friend.FriendData import com.teampome.pome.model.response.DeleteFriend +import com.teampome.pome.model.response.DeleteFriendRecord import com.teampome.pome.model.response.GetFriendRecord import com.teampome.pome.model.response.GetFriends import retrofit2.Response @@ -37,8 +38,20 @@ interface AddFriendsService { @Path("userId") userId: String ) : Response>> + //친구 삭제 @DELETE("api/v1/users/friend/{friendId}") suspend fun deleteFriend( @Path("friendId") friendId: String ) : Response> + + //모든 친구 기록 조회 + @GET("api/v1/records/friends") + suspend fun getAllFriendRecord() : + Response>> + + //기록 숨기기 + @DELETE("api/v1/records/hide/{recordId}") + suspend fun deleteFriendRecord( + @Path("recordId") recordId: Int + ) : Response> } \ No newline at end of file diff --git a/app/src/main/java/com/teampome/pome/presentation/addfriends/AddFriendsFragment.kt b/app/src/main/java/com/teampome/pome/presentation/addfriends/AddFriendsFragment.kt index 418603f5..0cac7fe4 100644 --- a/app/src/main/java/com/teampome/pome/presentation/addfriends/AddFriendsFragment.kt +++ b/app/src/main/java/com/teampome/pome/presentation/addfriends/AddFriendsFragment.kt @@ -9,11 +9,14 @@ import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.fragment.app.viewModels +import androidx.navigation.NavArgs import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs import com.teampome.pome.R import com.teampome.pome.databinding.FragmentAddFriendsBinding import com.teampome.pome.presentation.addfriends.recyclerview.AddFriendsListAdapter import com.teampome.pome.presentation.addfriends.recyclerview.OnAddFriendClickListener +import com.teampome.pome.presentation.record.add.AddGoalContentsFragmentArgs import com.teampome.pome.util.common.CommonUtil import com.teampome.pome.util.base.ApiResponse import com.teampome.pome.util.base.BaseFragment @@ -23,6 +26,9 @@ import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class AddFriendsFragment : BaseFragment(R.layout.fragment_add_friends) { + + private val args: AddFriendsFragmentArgs by navArgs() + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -42,6 +48,12 @@ class AddFriendsFragment : BaseFragment(R.layout.frag } override fun initView() { + if(args.addFriendType) { + binding.addFriendsBackIv.visibility = View.VISIBLE + } else { + binding.addFriendsBackIv.visibility = View.GONE + } + binding.addFriendsListRv.adapter = AddFriendsListAdapter().apply { setOnAddFriendClickListener(object : OnAddFriendClickListener { override fun onAddFriendClick(friendId: String, position: Int) { @@ -170,6 +182,10 @@ class AddFriendsFragment : BaseFragment(R.layout.frag binding.addFriendsFindDeleteAtv.setOnClickListener { binding.addFriendsNameEt.setText("") } + + binding.addFriendsBackIv.setOnClickListener { + findNavController().popBackStack() + } } private fun bindEmptyFriendData() { diff --git a/app/src/main/java/com/teampome/pome/presentation/friend/BottomEmojiGridSpaceItemDecoration.kt b/app/src/main/java/com/teampome/pome/presentation/friend/BottomEmojiGridSpaceItemDecoration.kt new file mode 100644 index 00000000..fb9b3ff5 --- /dev/null +++ b/app/src/main/java/com/teampome/pome/presentation/friend/BottomEmojiGridSpaceItemDecoration.kt @@ -0,0 +1,37 @@ +package com.teampome.pome.presentation.friend + +import android.graphics.Rect +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import com.teampome.pome.util.common.CommonUtil + +class BottomEmojiGridSpaceItemDecoration(private val spanCount: Int) : + RecyclerView.ItemDecoration() { + // 3, 20 + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + val position = parent.getChildAdapterPosition(view) + + val column = position % spanCount + + val spaceInPx = CommonUtil.dpToPx(parent.context, 10) + + outRect.top = spaceInPx + + if (column == 0) { + outRect.left = spaceInPx + } else if (column == 1) { + outRect.left = spaceInPx + } else if (column == 2) { + outRect.left = spaceInPx + } + + if (position >= 3) { + outRect.top = CommonUtil.dpToPx(parent.context, 30) + } + } +} diff --git a/app/src/main/java/com/teampome/pome/presentation/friend/FriendDetailRecordClickListener.kt b/app/src/main/java/com/teampome/pome/presentation/friend/FriendDetailRecordClickListener.kt new file mode 100644 index 00000000..b2c0b06c --- /dev/null +++ b/app/src/main/java/com/teampome/pome/presentation/friend/FriendDetailRecordClickListener.kt @@ -0,0 +1,12 @@ +package com.teampome.pome.presentation.friend + +import com.teampome.pome.model.response.FriendEmotionResponse + +//친구 기록 클릭 리스너 +interface FriendDetailRecordClickListener { + + fun onFriendDetailMoreClick(recordId : Int) + + fun onFriendDetailEmojiClick(emojiList : List) + +} \ No newline at end of file diff --git a/app/src/main/java/com/teampome/pome/presentation/friend/FriendEmotionAdapter.kt b/app/src/main/java/com/teampome/pome/presentation/friend/FriendEmotionAdapter.kt new file mode 100644 index 00000000..7e87cce0 --- /dev/null +++ b/app/src/main/java/com/teampome/pome/presentation/friend/FriendEmotionAdapter.kt @@ -0,0 +1,50 @@ +package com.teampome.pome.presentation.friend + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.teampome.pome.R +import com.teampome.pome.databinding.ItemBottomEmojiBinding +import com.teampome.pome.model.response.FriendEmotionResponse + +class FriendEmotionAdapter( + private var friendEmotionList: List +) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FriendEmotionViewHolder { + val binding = ItemBottomEmojiBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return FriendEmotionViewHolder(binding) + } + + override fun onBindViewHolder(holder: FriendEmotionViewHolder, position: Int) { + holder.bind(friendEmotionList[position]) + } + + override fun getItemCount(): Int = friendEmotionList.size + + fun updateData(newData: List) { + this.friendEmotionList = newData + notifyDataSetChanged() + } + + inner class FriendEmotionViewHolder( + private val binding: ItemBottomEmojiBinding + ) : RecyclerView.ViewHolder(binding.root) { + fun bind(friendEmotion: FriendEmotionResponse) { + with(binding) { + friendEmotionHappyTv.text = friendEmotion.nickname + + val imageResource = when(friendEmotion.emotionId) { + 0 -> R.drawable.emotion_happy_54 + 1 -> R.drawable.emotion_what_54 + 2 -> R.drawable.emotion_sad_54 + 3 -> R.drawable.emotion_funny_54 + 4 -> R.drawable.emotion_smile_54 + else -> R.drawable.emotion_flex_54 + } + + friendEmotionHappyAiv.setImageResource(imageResource) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/teampome/pome/presentation/friend/FriendFragment.kt b/app/src/main/java/com/teampome/pome/presentation/friend/FriendFragment.kt index 9758e1e4..5d69cb79 100644 --- a/app/src/main/java/com/teampome/pome/presentation/friend/FriendFragment.kt +++ b/app/src/main/java/com/teampome/pome/presentation/friend/FriendFragment.kt @@ -1,12 +1,18 @@ package com.teampome.pome.presentation.friend import android.util.Log +import android.view.View import android.widget.Toast import androidx.fragment.app.viewModels -import androidx.recyclerview.widget.DividerItemDecoration +import androidx.navigation.fragment.findNavController +import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager +import com.google.android.material.bottomsheet.BottomSheetDialog import com.teampome.pome.R import com.teampome.pome.databinding.FragmentFriendBinding +import com.teampome.pome.databinding.PomeFriendEmotionBottomSheetDialogBinding +import com.teampome.pome.databinding.PomeFriendSettingBottomSheetDialogBinding +import com.teampome.pome.model.response.FriendEmotionResponse import com.teampome.pome.util.base.ApiResponse import com.teampome.pome.util.base.BaseFragment import com.teampome.pome.util.base.CoroutineErrorHandler @@ -14,16 +20,23 @@ import com.teampome.pome.viewmodel.AddFriendsViewModel import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint -class FriendFragment : BaseFragment(R.layout.fragment_friend) { +class FriendFragment : BaseFragment(R.layout.fragment_friend), FriendDetailRecordClickListener { private val viewModel: AddFriendsViewModel by viewModels() private lateinit var friendGetAdapter: FriendGetAdapter private lateinit var friendRecordGetAdapter: FriendRecordGetAdapter + private lateinit var pomeFriendSettingBottomSheetDialogBinding : PomeFriendSettingBottomSheetDialogBinding + private lateinit var friendSettingBottomSheetDialog: BottomSheetDialog + + private lateinit var pomeFriendEmojiBottomSheetDialogBinding : PomeFriendEmotionBottomSheetDialogBinding + private lateinit var pomeFriendEmojiBottomSheetDialog: BottomSheetDialog + override fun initView() { setUpRecyclerView() friendRecordSetUpRecyclerView() + getAllFriendRecord() //친구 조회 viewModel.getFriend(object : CoroutineErrorHandler{ @@ -40,16 +53,27 @@ class FriendFragment : BaseFragment(R.layout.fragment_fri viewModel.getFriendsResponse.observe(viewLifecycleOwner) { when(it) { is ApiResponse.Success -> { + hideLoading() it.data.data?.let { list -> - (binding.friendListRv.adapter as FriendGetAdapter).submitList( - list - ) + if(list.isEmpty()) { + binding.friendNotIv.visibility = View.VISIBLE + binding.friendNotTv.visibility = View.VISIBLE + } else { + binding.friendNotIv.visibility = View.GONE + binding.friendNotTv.visibility = View.GONE + (binding.friendListRv.adapter as FriendGetAdapter).submitList( + list + ) + friendRecordGetAdapter.updateFriendsMap(list) + } } } is ApiResponse.Failure -> { - + hideLoading() + } + is ApiResponse.Loading -> { + showLoading() } - is ApiResponse.Loading -> {} } } @@ -65,18 +89,67 @@ class FriendFragment : BaseFragment(R.layout.fragment_fri } } is ApiResponse.Failure -> { + hideLoading() + } + is ApiResponse.Loading -> { + showLoading() + } + } + } + viewModel.getAllFriendRecordResponse.observe(viewLifecycleOwner){ + when(it) { + is ApiResponse.Success -> { + hideLoading() + it.data.data?.content?.let { list -> + (binding.friendDetailRv.adapter as FriendRecordGetAdapter).submitList( + list + ) + } + } + is ApiResponse.Failure -> { + hideLoading() } is ApiResponse.Loading -> { showLoading() } } } + + viewModel.deleteFriendRecord.observe(viewLifecycleOwner) { + when(it) { + is ApiResponse.Success -> { + hideLoading() + Toast.makeText(requireContext(), "해당 게시글을 숨겼어요", Toast.LENGTH_SHORT).show() + viewModel.getAllRecordFriend(object : CoroutineErrorHandler{ + override fun onError(message: String) { + Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + hideLoading() + } + }) + } + is ApiResponse.Failure -> { + hideLoading() + } + is ApiResponse.Loading -> { + showLoading() + } + } + } + + binding.friendAllIv.setOnClickListener { + getAllFriendRecord() + } + + binding.friendAddIv.setOnClickListener { + val action = FriendFragmentDirections.actionFriendFragmentToAddFriendsFragment(true) + findNavController().navigate(action) + } } //친구 목록 조회 RV private fun setUpRecyclerView(){ - friendGetAdapter = FriendGetAdapter() + friendGetAdapter = FriendGetAdapter(context) binding.friendListRv.apply { // setHasFixedSize(true) layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false) @@ -96,21 +169,76 @@ class FriendFragment : BaseFragment(R.layout.fragment_fri //친구 기록 조회 RV private fun friendRecordSetUpRecyclerView(){ - friendRecordGetAdapter = FriendRecordGetAdapter() + friendRecordGetAdapter = FriendRecordGetAdapter(this) binding.friendDetailRv.apply { // setHasFixedSize(true) layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) adapter = friendRecordGetAdapter - addItemDecoration( - DividerItemDecoration( - requireContext(), DividerItemDecoration.VERTICAL - ) - ) } + } - // 클릭 리스너 - friendRecordGetAdapter.setOnItemClickListener { - Toast.makeText(requireContext(), "${it.nickname}", Toast.LENGTH_SHORT).show() + private fun getAllFriendRecord() { + viewModel.getAllRecordFriend(object : CoroutineErrorHandler{ + override fun onError(message: String) { + Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + hideLoading() + } + }) + } + + private fun makeFriendSettingBottomDialog(recordId: Int) { + friendSettingBottomSheetDialog = BottomSheetDialog(requireContext()) + pomeFriendSettingBottomSheetDialogBinding = PomeFriendSettingBottomSheetDialogBinding.inflate(layoutInflater, null, false) + + friendSettingBottomSheetDialog.setContentView(pomeFriendSettingBottomSheetDialogBinding.root) + + pomeFriendSettingBottomSheetDialogBinding.apply{ + //숨기기 + pomeFriendBottomSheetDialogHideTv.setOnClickListener { + viewModel.deleteFriendRecord(recordId, object : CoroutineErrorHandler{ + override fun onError(message: String) { + Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + hideLoading() + } + }) + friendSettingBottomSheetDialog.dismiss() + } + + //신고 + pomeFriendBottomSheetDialogReportTv.setOnClickListener { + friendSettingBottomSheetDialog.dismiss() + } } } + + private fun makeFriendEmojiBottomDialog(emojiList : List) { + pomeFriendEmojiBottomSheetDialog = BottomSheetDialog(requireContext()) + pomeFriendEmojiBottomSheetDialogBinding = PomeFriendEmotionBottomSheetDialogBinding.inflate(layoutInflater, null, false) + + pomeFriendEmojiBottomSheetDialog.setContentView(pomeFriendEmojiBottomSheetDialogBinding.root) + + with(pomeFriendEmojiBottomSheetDialogBinding) { + val emojiListSize = emojiList.size + friendDetailAllEmotionTv.text = "전체 ${emojiListSize}개" + + val gridLayoutManager = GridLayoutManager(context, 3) + val adapter = FriendEmotionAdapter(emojiList) + val decoration = BottomEmojiGridSpaceItemDecoration(3) + friendBottomEmojiRv.apply { + layoutManager = gridLayoutManager + this.adapter = adapter + addItemDecoration(decoration) + } + } + } + + override fun onFriendDetailMoreClick(recordId : Int) { + makeFriendSettingBottomDialog(recordId) + friendSettingBottomSheetDialog.show() + } + + override fun onFriendDetailEmojiClick(emojiList: List) { + makeFriendEmojiBottomDialog(emojiList) + pomeFriendEmojiBottomSheetDialog.show() + } } \ No newline at end of file diff --git a/app/src/main/java/com/teampome/pome/presentation/friend/FriendGetAdapter.kt b/app/src/main/java/com/teampome/pome/presentation/friend/FriendGetAdapter.kt index 74fe38da..faa08f77 100644 --- a/app/src/main/java/com/teampome/pome/presentation/friend/FriendGetAdapter.kt +++ b/app/src/main/java/com/teampome/pome/presentation/friend/FriendGetAdapter.kt @@ -1,15 +1,23 @@ package com.teampome.pome.presentation.friend +import android.content.Context +import android.graphics.Color +import android.util.Log 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.teampome.pome.databinding.ItemFriendsListBinding import com.teampome.pome.model.response.GetFriends // 친구 탭에서 친구 조회하는 친구 리스트 어댑터 -class FriendGetAdapter : ListAdapter(BookDiffCallback) { +class FriendGetAdapter( + private val context : Context? +) : ListAdapter(BookDiffCallback) { + + private var selectedPosition = -1 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FriendGetViewHolder { return FriendGetViewHolder( @@ -20,9 +28,7 @@ class FriendGetAdapter : ListAdapter Unit)? = null @@ -34,12 +40,29 @@ class FriendGetAdapter : ListAdapter= 3) { + fun bind(getFriends: GetFriends) = with(binding){ + friendAllTv.text = if (getFriends.friendNickName.length >= 3) { "${getFriends.friendNickName.substring(0, 3)}..." } else { getFriends.friendNickName } + + context?.let { context -> + Glide.with(context) + .load(getFriends.imageKey) + .circleCrop() + .into(friendListProfileIv) + } + + itemView.setOnClickListener { + selectedPosition = bindingAdapterPosition + notifyDataSetChanged() + onItemClickListener?.invoke(getFriends) + } + + friendAllTv.setTextColor( + if (bindingAdapterPosition == selectedPosition) Color.BLACK else Color.GRAY + ) } } diff --git a/app/src/main/java/com/teampome/pome/presentation/friend/FriendGetRecordViewHolder.kt b/app/src/main/java/com/teampome/pome/presentation/friend/FriendGetRecordViewHolder.kt new file mode 100644 index 00000000..c8072350 --- /dev/null +++ b/app/src/main/java/com/teampome/pome/presentation/friend/FriendGetRecordViewHolder.kt @@ -0,0 +1,96 @@ +package com.teampome.pome.presentation.friend + +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import com.teampome.pome.R +import com.teampome.pome.databinding.ItemFriendDetailCardBinding +import com.teampome.pome.model.response.GetFriendRecord +import com.teampome.pome.model.response.GetFriends +import java.time.Duration +import java.time.Instant +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter + +class FriendGetRecordViewHolder( + private val friendDetailRecordClickListener: FriendDetailRecordClickListener, + private val binding : ItemFriendDetailCardBinding, + private val friendsMap: HashMap +) : RecyclerView.ViewHolder(binding.root){ + + fun bind(getFriedRecord: GetFriendRecord){ + with(binding) { + getFriendRecord = getFriedRecord + + friendDetailMoreSettingIv.setOnClickListener { + friendDetailRecordClickListener.onFriendDetailMoreClick(getFriedRecord.id) + } + + val timeString = getTimeAgo(getFriedRecord.createdAt) + friendDetailContentNameTimeTv.text = " · ${getFriedRecord.oneLineMind} · $timeString" + + if(getFriedRecord.emotionResponse.friendEmotions.isEmpty()) { + friendDetailCardLastFriendEmotionCountTv.visibility = View.INVISIBLE + friendDetailCardLastFriendEmotionAiv.visibility = View.INVISIBLE + } else { + friendDetailCardLastFriendEmotionCountTv.visibility = View.VISIBLE + friendDetailCardLastFriendEmotionAiv.visibility = View.VISIBLE + + val count = getFriedRecord.emotionResponse.friendEmotions.size + + if(count >= 10) { + friendDetailCardLastFriendEmotionCountTv.text = "9+" + } else { + friendDetailCardLastFriendEmotionCountTv.text = "+$count" + } + } + + if(getFriedRecord.emotionResponse.myEmotion == null) { + itemView.context?.let{ context -> + Glide.with(context).load(R.drawable.emoji_mint_28).into(friendDetailCardFirstFriendEmotionAiv) + } + } + + friendDetailCardFirstFriendEmotionAiv.setOnClickListener { + val params = friendEmojiRegisterCl.layoutParams + if(friendEmojiRegisterCl.visibility == View.VISIBLE) { + friendEmojiRegisterCl.visibility = View.GONE + params.height = 0 + } else { + friendEmojiRegisterCl.visibility = View.VISIBLE + params.height = ViewGroup.LayoutParams.WRAP_CONTENT + } + friendEmojiRegisterCl.layoutParams = params + } + + val friends = friendsMap[getFriedRecord.nickname] + + friends?.let { friend -> + Glide.with(itemView.context) + .load(friend.imageKey) + .circleCrop() + .into(friendDetailProfileIv) + } + + friendDetailCardLastFriendEmotionAiv.setOnClickListener { + friendDetailRecordClickListener.onFriendDetailEmojiClick(getFriedRecord.emotionResponse.friendEmotions) + } + } + } + + private fun getTimeAgo(isoTime: String): String { + val modifiedIsoTime = isoTime.substring(0, isoTime.lastIndexOf(".") + 4) + "Z" + val time = Instant.parse(modifiedIsoTime) + val now = Instant.now() + val duration = Duration.between(time, now) + + return when { + duration.toMinutes() < 1 -> "방금 전" + duration.toMinutes() < 60 -> "${duration.toMinutes()}분 전" + duration.toHours() < 24 -> "${duration.toHours()}시간 전" + duration.toDays() < 2 -> "어제" + else -> ZonedDateTime.parse(modifiedIsoTime).format(DateTimeFormatter.ofPattern("M월 d일")) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/teampome/pome/presentation/friend/FriendRecordGetAdapter.kt b/app/src/main/java/com/teampome/pome/presentation/friend/FriendRecordGetAdapter.kt index 1d9b6772..67c50006 100644 --- a/app/src/main/java/com/teampome/pome/presentation/friend/FriendRecordGetAdapter.kt +++ b/app/src/main/java/com/teampome/pome/presentation/friend/FriendRecordGetAdapter.kt @@ -1,46 +1,51 @@ package com.teampome.pome.presentation.friend +import android.content.Context +import android.os.Build +import android.util.Log import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import androidx.annotation.RequiresApi import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import com.teampome.pome.R import com.teampome.pome.databinding.ItemFriendDetailCardBinding -import com.teampome.pome.databinding.ItemFriendsListBinding import com.teampome.pome.model.response.GetFriendRecord import com.teampome.pome.model.response.GetFriends +import java.time.Duration +import java.time.Instant +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter //친구 기록 조회 -class FriendRecordGetAdapter : ListAdapter(BookDiffCallback) { +class FriendRecordGetAdapter( + private val clickListener: FriendDetailRecordClickListener, +) : ListAdapter(BookDiffCallback) { + + private val friendsMap: HashMap = HashMap() + + fun updateFriendsMap(friends: List) { + for (friend in friends) { + friendsMap[friend.friendNickName] = friend + } + } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FriendGetRecordViewHolder { return FriendGetRecordViewHolder( + clickListener, ItemFriendDetailCardBinding.inflate(LayoutInflater.from(parent.context), parent, false), + friendsMap ) } override fun onBindViewHolder(holder: FriendGetRecordViewHolder, position: Int) { val friends = currentList[position] holder.bind(friends) - holder.itemView.setOnClickListener { - onItemClickListener?.let{ it(friends) } - } } - private var onItemClickListener : ((GetFriendRecord) -> Unit)? = null - fun setOnItemClickListener(listener : (GetFriendRecord) -> Unit){ - onItemClickListener = listener - } - - inner class FriendGetRecordViewHolder( - private val binding : ItemFriendDetailCardBinding, - ) : RecyclerView.ViewHolder(binding.root){ - - fun bind(getFriedRecord: GetFriendRecord){ - binding.getFriendRecord = getFriedRecord - } - - } companion object{ private val BookDiffCallback = object : DiffUtil.ItemCallback(){ override fun areItemsTheSame(oldItem: GetFriendRecord, newItem: GetFriendRecord): Boolean { diff --git a/app/src/main/java/com/teampome/pome/repository/friend/AddFriendsDataSource.kt b/app/src/main/java/com/teampome/pome/repository/friend/AddFriendsDataSource.kt index 58cf82cc..fa649971 100644 --- a/app/src/main/java/com/teampome/pome/repository/friend/AddFriendsDataSource.kt +++ b/app/src/main/java/com/teampome/pome/repository/friend/AddFriendsDataSource.kt @@ -4,6 +4,7 @@ import com.teampome.pome.model.base.BaseAllData import com.teampome.pome.model.base.BasePomeResponse import com.teampome.pome.model.friend.FriendData import com.teampome.pome.model.response.DeleteFriend +import com.teampome.pome.model.response.DeleteFriendRecord import com.teampome.pome.model.response.GetFriendRecord import com.teampome.pome.model.response.GetFriends import com.teampome.pome.util.base.ApiResponse @@ -21,7 +22,13 @@ interface AddFriendsDataSource { userId : String ) : Flow>>> + //친구 삭제 fun deleteFriend( friendId: String ) : Flow>> + + //모든 친구 기록 조회 + fun getAllFriendRecord() : Flow>>> + + fun deleteFriendRecord(recordId : Int) : Flow>> } \ No newline at end of file diff --git a/app/src/main/java/com/teampome/pome/repository/friend/AddFriendsRemoteDataSource.kt b/app/src/main/java/com/teampome/pome/repository/friend/AddFriendsRemoteDataSource.kt index 2c2fe781..d82ddce4 100644 --- a/app/src/main/java/com/teampome/pome/repository/friend/AddFriendsRemoteDataSource.kt +++ b/app/src/main/java/com/teampome/pome/repository/friend/AddFriendsRemoteDataSource.kt @@ -4,6 +4,7 @@ import com.teampome.pome.model.base.BaseAllData import com.teampome.pome.model.base.BasePomeResponse import com.teampome.pome.model.friend.FriendData import com.teampome.pome.model.response.DeleteFriend +import com.teampome.pome.model.response.DeleteFriendRecord import com.teampome.pome.model.response.GetFriendRecord import com.teampome.pome.model.response.GetFriends import com.teampome.pome.network.AddFriendsService @@ -34,4 +35,12 @@ class AddFriendsRemoteDataSource @Inject constructor( override fun deleteFriend(friendId: String): Flow>> = apiRequestFlow{ service.deleteFriend(friendId) } + + override fun getAllFriendRecord(): Flow>>> = apiRequestFlow { + service.getAllFriendRecord() + } + + override fun deleteFriendRecord(recordId : Int): Flow>> = apiRequestFlow { + service.deleteFriendRecord(recordId) + } } \ No newline at end of file diff --git a/app/src/main/java/com/teampome/pome/repository/friend/AddFriendsRepository.kt b/app/src/main/java/com/teampome/pome/repository/friend/AddFriendsRepository.kt index dd1b7cf8..d22a5859 100644 --- a/app/src/main/java/com/teampome/pome/repository/friend/AddFriendsRepository.kt +++ b/app/src/main/java/com/teampome/pome/repository/friend/AddFriendsRepository.kt @@ -13,4 +13,8 @@ class AddFriendsRepository @Inject constructor( fun getFriendRecord(userId : String) = dataSource.getFriendRecord(userId) fun deleteFriend(friendId: String) = dataSource.deleteFriend(friendId) + + fun getAllFriendRecord() = dataSource.getAllFriendRecord() + + fun deleteFriendRecord(recordId : Int) = dataSource.deleteFriendRecord(recordId) } \ No newline at end of file diff --git a/app/src/main/java/com/teampome/pome/viewmodel/AddFriendsViewModel.kt b/app/src/main/java/com/teampome/pome/viewmodel/AddFriendsViewModel.kt index 311cefe1..72b5340e 100644 --- a/app/src/main/java/com/teampome/pome/viewmodel/AddFriendsViewModel.kt +++ b/app/src/main/java/com/teampome/pome/viewmodel/AddFriendsViewModel.kt @@ -8,6 +8,7 @@ import com.teampome.pome.model.base.BasePomeResponse import com.teampome.pome.model.friend.FriendData import com.teampome.pome.model.goal.GoalData import com.teampome.pome.model.response.DeleteFriend +import com.teampome.pome.model.response.DeleteFriendRecord import com.teampome.pome.model.response.GetFriendRecord import com.teampome.pome.model.response.GetFriends import com.teampome.pome.repository.friend.AddFriendsRepository @@ -45,6 +46,13 @@ class AddFriendsViewModel @Inject constructor( private val _deleteFriendResponse = MutableLiveData>>() val deleteFriendResponse : LiveData>> = _deleteFriendResponse + //모든 친구 기록 조회 + private val _getAllFriendRecordResponse = MutableLiveData>>>() + val getAllFriendRecordResponse : LiveData>>> = _getAllFriendRecordResponse + + //친구 기록 숨기기 + private val _deleteFriendRecord = MutableLiveData>>() + val deleteFriendRecord : LiveData>> = _deleteFriendRecord fun findFriendsData(nickName: String, coroutineErrorHandler: CoroutineErrorHandler) = baseRequest( _findFriendsDataResponse, @@ -80,6 +88,7 @@ class AddFriendsViewModel @Inject constructor( repository.getFriendRecord(userId) } + //친구 삭제 fun deleteFriend(friendId : String, coroutineErrorHandler: CoroutineErrorHandler) = baseRequest( _deleteFriendResponse, coroutineErrorHandler @@ -87,6 +96,20 @@ class AddFriendsViewModel @Inject constructor( repository.deleteFriend(friendId) } + fun getAllRecordFriend(coroutineErrorHandler: CoroutineErrorHandler) = baseRequest( + _getAllFriendRecordResponse, + coroutineErrorHandler + ){ + repository.getAllFriendRecord() + } + + fun deleteFriendRecord(recordId : Int, coroutineErrorHandler: CoroutineErrorHandler) = baseRequest( + _deleteFriendRecord, + coroutineErrorHandler + ){ + repository.deleteFriendRecord(recordId) + } + //친구 조회 val friendGet: LiveData> = Transformations.map(_getFriendResponse) { when(it) { @@ -97,6 +120,4 @@ class AddFriendsViewModel @Inject constructor( is ApiResponse.Failure -> { null } } } - - } \ No newline at end of file diff --git a/app/src/main/res/drawable/emoji_mint_28.png b/app/src/main/res/drawable/emoji_mint_28.png new file mode 100644 index 00000000..f769b2af Binary files /dev/null and b/app/src/main/res/drawable/emoji_mint_28.png differ diff --git a/app/src/main/res/drawable/emoji_mint_38.png b/app/src/main/res/drawable/emoji_mint_38.png new file mode 100644 index 00000000..91cce585 Binary files /dev/null and b/app/src/main/res/drawable/emoji_mint_38.png differ diff --git a/app/src/main/res/drawable/emoji_mint_38_2.png b/app/src/main/res/drawable/emoji_mint_38_2.png new file mode 100644 index 00000000..9220bfab Binary files /dev/null and b/app/src/main/res/drawable/emoji_mint_38_2.png differ diff --git a/app/src/main/res/drawable/emoji_mint_38_3.png b/app/src/main/res/drawable/emoji_mint_38_3.png new file mode 100644 index 00000000..3a225f2b Binary files /dev/null and b/app/src/main/res/drawable/emoji_mint_38_3.png differ diff --git a/app/src/main/res/drawable/emoji_mint_38_4.png b/app/src/main/res/drawable/emoji_mint_38_4.png new file mode 100644 index 00000000..c8b67899 Binary files /dev/null and b/app/src/main/res/drawable/emoji_mint_38_4.png differ diff --git a/app/src/main/res/drawable/emoji_mint_38_5.png b/app/src/main/res/drawable/emoji_mint_38_5.png new file mode 100644 index 00000000..07c276d8 Binary files /dev/null and b/app/src/main/res/drawable/emoji_mint_38_5.png differ diff --git a/app/src/main/res/drawable/emoji_mint_38_6.png b/app/src/main/res/drawable/emoji_mint_38_6.png new file mode 100644 index 00000000..66d7872d Binary files /dev/null and b/app/src/main/res/drawable/emoji_mint_38_6.png differ diff --git a/app/src/main/res/drawable/emoji_mint_38_7.png b/app/src/main/res/drawable/emoji_mint_38_7.png new file mode 100644 index 00000000..91cce585 Binary files /dev/null and b/app/src/main/res/drawable/emoji_mint_38_7.png differ diff --git a/app/src/main/res/drawable/emotion_flex_54.png b/app/src/main/res/drawable/emotion_flex_54.png new file mode 100644 index 00000000..be38daa1 Binary files /dev/null and b/app/src/main/res/drawable/emotion_flex_54.png differ diff --git a/app/src/main/res/drawable/emotion_funny_54.png b/app/src/main/res/drawable/emotion_funny_54.png new file mode 100644 index 00000000..e85f994c Binary files /dev/null and b/app/src/main/res/drawable/emotion_funny_54.png differ diff --git a/app/src/main/res/drawable/emotion_happy_54.png b/app/src/main/res/drawable/emotion_happy_54.png new file mode 100644 index 00000000..1615be28 Binary files /dev/null and b/app/src/main/res/drawable/emotion_happy_54.png differ diff --git a/app/src/main/res/drawable/emotion_sad_54.png b/app/src/main/res/drawable/emotion_sad_54.png new file mode 100644 index 00000000..33928b8e Binary files /dev/null and b/app/src/main/res/drawable/emotion_sad_54.png differ diff --git a/app/src/main/res/drawable/emotion_smile_54.png b/app/src/main/res/drawable/emotion_smile_54.png new file mode 100644 index 00000000..21285a93 Binary files /dev/null and b/app/src/main/res/drawable/emotion_smile_54.png differ diff --git a/app/src/main/res/drawable/emotion_what_54.png b/app/src/main/res/drawable/emotion_what_54.png new file mode 100644 index 00000000..246e93ae Binary files /dev/null and b/app/src/main/res/drawable/emotion_what_54.png differ diff --git a/app/src/main/res/layout/fragment_add_friends.xml b/app/src/main/res/layout/fragment_add_friends.xml index baea09d8..ce3a1a90 100644 --- a/app/src/main/res/layout/fragment_add_friends.xml +++ b/app/src/main/res/layout/fragment_add_friends.xml @@ -18,6 +18,16 @@ android:layout_height="match_parent" android:background="@color/white"> + + + @@ -18,63 +19,68 @@ android:id="@+id/friend_add_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:layout_marginRight="20dp" android:src="@drawable/ic_friend_add" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintRight_toRightOf="parent" - android:layout_marginTop="16dp" - android:layout_marginRight="20dp"/> + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toBottomOf="@id/friend_add_iv" /> + app:layout_constraintTop_toBottomOf="@id/friend_all_iv" /> + app:layout_constraintTop_toBottomOf="@id/friend_add_iv" + tools:listitem="@layout/item_friends_list" /> + + + app:layout_constraintTop_toBottomOf="@id/friend_all_tv" + tools:listitem="@layout/item_friend_detail_card" /> + app:layout_constraintTop_toTopOf="@id/friend_list_rv" /> - + app:layout_constraintTop_toBottomOf="@id/friend_not_iv" /> \ No newline at end of file diff --git a/app/src/main/res/layout/item_bottom_emoji.xml b/app/src/main/res/layout/item_bottom_emoji.xml new file mode 100644 index 00000000..8cc5d374 --- /dev/null +++ b/app/src/main/res/layout/item_bottom_emoji.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_friend_detail_card.xml b/app/src/main/res/layout/item_friend_detail_card.xml index 5bc9071c..b3c7af84 100644 --- a/app/src/main/res/layout/item_friend_detail_card.xml +++ b/app/src/main/res/layout/item_friend_detail_card.xml @@ -1,15 +1,17 @@ + xmlns:bind="http://schemas.android.com/tools" + xmlns:tools="http://schemas.android.com/tools"> + + @@ -17,35 +19,32 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:cardBackgroundColor="@color/white" - app:cardPreventCornerOverlap="true" - > + app:cardPreventCornerOverlap="true"> + android:layout_height="wrap_content"> + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toTopOf="@id/friend_detail_profile_iv" + tools:text="성식" /> + app:layout_constraintTop_toTopOf="parent" + bind:remindFirstEmotionDrawable="@{CommonUtil.INSTANCE.numToEmotion(getFriendRecord.emotionResponse.firstEmotion)}" + tools:src="@drawable/emoji_mint_fiter_sad" /> + app:layout_constraintTop_toTopOf="@id/friend_detail_content_first_emotion_aiv" + tools:text="후회해요" /> + app:layout_constraintTop_toTopOf="parent" + bind:remindFirstEmotionDrawable="@{CommonUtil.INSTANCE.numToEmotion(getFriendRecord.emotionResponse.secondEmotion)}" + tools:src="@drawable/emoji_pink_fiter_happy" /> + app:layout_constraintTop_toTopOf="@id/friend_detail_card_last_emotion_aiv" + tools:text="행복해요" /> @@ -146,13 +145,13 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="12dp" - tools:text="16,000원" + android:layout_marginRight="24dp" android:text="@{@string/use_price_text(CommonUtil.INSTANCE.makePriceStyle(String.valueOf(getFriendRecord.usePrice)))}" android:textColor="@color/grey_8" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@id/friend_detail_content_first_emotion_cl" app:layout_constraintTop_toBottomOf="@id/friend_detail_content_first_emotion_cl" - android:layout_marginRight="24dp"/> + tools:text="16,000원" /> + app:layout_constraintTop_toBottomOf="@id/friend_detail_card_title_tv" + tools:text="아휴 힘빠져 이젠 진짜 포기다 포기 도대체 뭐가 문제일까 현실을 되돌아볼 필요를 느낀다ㅠ 이정도 노력했으면 된거 아닌가 진짜 개 힘빠지네 그래서 오늘은 물 대신 라떼 한잔을 마셨습니다 ㅋ 라뗴 존맛탱~~ 다들 나흐바 시그니쳐 커피를 마셔주세요 설탕 솔솔 뿌려서 개맛있음" /> + app:layout_constraintTop_toBottomOf="@id/friend_detail_card_content_tv"> @@ -221,15 +219,105 @@ + app:layout_constraintTop_toTopOf="@+id/friend_detail_friends_emotion_container_cl" /> + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/pome_friend_emotion_bottom_sheet_dialog.xml b/app/src/main/res/layout/pome_friend_emotion_bottom_sheet_dialog.xml index 8ec20185..6ad9d22b 100644 --- a/app/src/main/res/layout/pome_friend_emotion_bottom_sheet_dialog.xml +++ b/app/src/main/res/layout/pome_friend_emotion_bottom_sheet_dialog.xml @@ -11,6 +11,7 @@ android:id="@+id/pome_friend_emotion_bottom_sheet_dialog_cl" android:layout_width="match_parent" android:layout_height="match_parent" + android:paddingTop="20dp" app:behavior_draggable="true" app:behavior_hideable="true" app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"> @@ -19,70 +20,71 @@ android:id="@+id/friend_detail_profile_iv" android:layout_width="34dp" android:layout_height="34dp" - android:layout_marginLeft="19dp" + android:layout_marginStart="19dp" android:layout_marginBottom="20dp" android:src="@drawable/ic_friend_all_on" app:layout_constraintBottom_toTopOf="@+id/friend_detail_all_emotion_tv" - app:layout_constraintLeft_toLeftOf="parent" /> + app:layout_constraintStart_toStartOf="parent" /> + app:layout_constraintEnd_toStartOf="@+id/friend_detail_emoji_what_iv" + app:layout_constraintStart_toEndOf="@+id/friend_detail_profile_iv" /> + app:layout_constraintEnd_toStartOf="@+id/friend_detail_emoji_merong_iv" + app:layout_constraintStart_toEndOf="@+id/friend_detail_emoji_love_iv" /> + app:layout_constraintEnd_toStartOf="@+id/friend_detail_emoji_glass_iv" + app:layout_constraintStart_toEndOf="@+id/friend_detail_emoji_what_iv" /> + app:layout_constraintEnd_toStartOf="@+id/friend_detail_emoji_sad_iv" + app:layout_constraintStart_toEndOf="@+id/friend_detail_emoji_merong_iv" /> + app:layout_constraintEnd_toStartOf="@+id/friend_detail_emoji_happy_iv" + app:layout_constraintStart_toEndOf="@+id/friend_detail_emoji_glass_iv" /> - - - - - - - - - - - - - - - - - - - - - - - + app:layout_constraintHorizontal_bias="1.0" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/friend_detail_all_emotion_tv" + tools:listitem="@layout/item_bottom_emoji" /> \ No newline at end of file diff --git a/app/src/main/res/navigation/pome_navigation.xml b/app/src/main/res/navigation/pome_navigation.xml index 2993baec..7afcf759 100644 --- a/app/src/main/res/navigation/pome_navigation.xml +++ b/app/src/main/res/navigation/pome_navigation.xml @@ -78,6 +78,9 @@ + +