APP-iOS3rd / PJ3T2_Mymory

멋쟁이사자처럼 iOS 앱스쿨 3기 팀 프로젝트
11 stars 3 forks source link

Feat/memo like : 사용자 메모 좋아요 누르기, 좋아요 누른 메모 확인 구현 #125

Closed jeonguk29 closed 9 months ago

jeonguk29 commented 9 months ago

PR 가이드라인

PR Checklist

PR 날릴 때 체크 리스트

PR Type

어떤 종류의 PR인가요?

연관되는 issue 정보를 알려주세요

Issue Number: #63

PR 설명하기

이 PR에 대해 간략하게 소개해주세요!

사용자가 메모에 '좋아요'를 누를 수 있으며 좋아요. 누른 메모는 앱이 다시 실행되어도 기억되도록 구현 하였습니다.

어떻게 작동하나요? code 기반으로 설명해주세요

func likeMemo(memo: Memo, completion: @escaping (Error?) -> Void) {
        guard let uid = Auth.auth().currentUser?.uid, let memoID = memo.id else {
            completion(NSError(domain: "Auth Error", code: 401, userInfo: nil))
            return
        }

        if memo.didLike {
                COLLECTION_USER_LIKES.document(uid).updateData([String(memo.id ?? "") : FieldValue.delete()])
                COLLECTION_MEMO_LIKES.document(memo.id ?? "").updateData([uid : FieldValue.delete()])
            } else {
                COLLECTION_USER_LIKES.document(uid).setData([String(memo.id ?? "") : "LikeMemoUid"], merge: true)
                COLLECTION_MEMO_LIKES.document(memo.id ?? "").setData([uid : "LikeUserUid"], merge: true)
            }

    }

사용자가 좋아요를 누르면 해당 메서드가 실행되고 COLLECTION_MEMO_LIKES 컬렉션에 현재 메모의 uid를 문서로 저장 그리고 좋아요 누른 사용자의 uid를 하나씩 필드 값으로 추가합니다. COLLECTION_USER_LIKES 컬렉션에 현재 사용자 uid를 문서로 저장 그리고 좋아요 누른 메모의 uid를 하나씩 필드 값으로 추가합니다.

image

 func likeMemoCount(memo: Memo) async -> Int {
        let memoID = memo.id ?? ""
        var likeCount = 0

        do {
            let document = try await COLLECTION_MEMO_LIKES.document(memoID).getDocument()

            if document.exists {
                let fieldCount = document.data()?.count ?? 0
                likeCount = fieldCount
            }
        } catch {
            print("에러 발생: \(error)")
        }

        print(likeCount)
        return likeCount
    }

해당 메서드를 이용하면 현재 메모uid 밑에 필드가 좋아요. 누른 사용자의 uid 개수를 파악하여 좋아요. 누른 총개수를 알 수 있습니다.

func checkLikedMemo(_ memo: Memo, completion: @escaping (Bool) -> Void) {
        guard let uid = Auth.auth().currentUser?.uid else {
            completion(false)
            return
        }

        let memoID = memo.id ?? ""

        let userLikesRef = COLLECTION_USER_LIKES.document(uid)
        userLikesRef.getDocument { (document, error) in
            if let error = error {
                print("사용자 좋아요 문서를 가져오는 중 오류가 발생했습니다: \(error.localizedDescription)")
                completion(false)
                return
            }

            if let document = document, document.exists, let dataArray = document.data() as? [String: String] {
                print("데이터 \(dataArray)")
                print("메모 ID \(memoID)")
                if dataArray.keys.contains(memoID) {
                    completion(true)
                } else {
                    completion(false)
                }
            } else {
                completion(false)
            }
        }
    }

해당 메서드를 이용하면 fatch해서 가져온 MemoList에 각 Memo uid와 현재 사용자가 좋아요 눌러 저장했던 COLLECTION_USER_LIKES 컬렉션 => 현재 사용자 uid 문서 => 좋아요 누른 메모의 uid 필드를 비교하여 일치하면 이전에 좋아요 눌렀던 메모를 파악합니다 맞다면 참, 아니라면 거짓을 반환합니다.

UI 반영 코드 (멀다면 잠금 이미지, 볼 수 있다면 하트 버튼을 표시 '좋아요'를 눌렀다면 빨간색 하트로 만들고 누르지 않았다면 회색 색상으로)

 VStack{
                if isVisible {
                    Button(action: {
                        MemoService.shared.likeMemo(memo: memo) { err in
                            guard err == nil else {
                                return
                            }
                        }
                        self.memo.didLike.toggle()
                        Task {
                            await fetchlikeCount()
                        }
                        //print("\(memo.didLike)")
                        //memo.didLike.toggle()
                        //print("\(memo.didLike)")
                    }) {
                        Image(systemName: "heart.fill")
                            .foregroundColor(memo.didLike ? .red : .gray)
                            .frame(width: 46, height: 46)
                            .background(isDark ? .white : .lightGray)
                            .clipShape(Circle())
                    }
                }else {
                    Image(systemName: "lock")
                    .foregroundColor(.gray)
                    .frame(width: 46, height: 46)
                    .background(isDark ? .white : .lightGray)
                    .clipShape(Circle())
                }

                Spacer()
            }

가능하다면 추가해주세요

변경 사항 스크린샷 혹은 화면 녹화

https://github.com/APP-iOS3rd/PJ3T2_Mymory/assets/54401641/2e80f457-4754-4c98-8310-85a4ca3a3f66

스크린샷

Test 여부

Test 정보

Text("(String(item.didLike))") // 화면에 표시하여 좋아요. 누른 것을 잘 파악하고 있는지 확인 할 수 있습니다.

 ScrollView(.horizontal) {
                    HStack(spacing: 20) {
                        ForEach(mainMapViewModel.filterList.isEmpty ? mainMapViewModel.memoList : mainMapViewModel.filteredMemoList) { item  in
                            VStack{
                                Text("\(String(item.didLike))")
                                MemoCell(
                                    isVisible: true,
                                    isDark: true,
                                    location: $mainMapViewModel.location,
                                    memo: item)
                                .environmentObject(mainMapViewModel)
                                .onTapGesture {
                                    mainMapViewModel.memoDidSelect(memo: item)
                                }
                                .frame(width: UIScreen.main.bounds.size.width * 0.84)
                                .padding(.leading, 12)
                                .padding(.bottom, 12)
                            }
                        }
                    }
                }

기타 언급해야 할 사항들