From 7318d7fcda7a1e42bbf4abfd8453fae5b5f242ad Mon Sep 17 00:00:00 2001 From: Yu Sung Date: Mon, 21 Jul 2025 23:10:24 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=A9=94=EC=9D=B8=20=ED=99=88=20-=20?= =?UTF-8?q?=EC=9D=B8=EA=B8=B0=20=ED=81=AC=EB=A6=AC=EC=97=90=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20-=20=ED=8C=94=EB=A1=9C=EC=9A=B0=20=EC=88=98=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20-=20=ED=8C=94=EB=A1=9C=EC=9A=B0=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EC=B6=94=EA=B0=80=20-=20=EB=B0=B0?= =?UTF-8?q?=EA=B2=BD:=20=EA=B7=B8=EB=9D=BC=EB=8D=B0=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0,=20=ED=95=98=EB=82=98=EC=9D=98=20=EC=83=89?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ContentMainTabHomeRankCreatorView.swift | 8 +-- .../Explorer/GetExplorerResponse.swift | 2 +- .../Home/HomeCreatorRankingItemView.swift | 70 ++++++++++--------- SodaLive/Sources/Home/HomeTabView.swift | 17 ++++- SodaLive/Sources/Home/HomeTabViewModel.swift | 37 ++++++++++ 5 files changed, 94 insertions(+), 40 deletions(-) diff --git a/SodaLive/Sources/Content/Main/V2/Home/Rank/ContentMainTabHomeRankCreatorView.swift b/SodaLive/Sources/Content/Main/V2/Home/Rank/ContentMainTabHomeRankCreatorView.swift index 15de9bf..098ac68 100644 --- a/SodaLive/Sources/Content/Main/V2/Home/Rank/ContentMainTabHomeRankCreatorView.swift +++ b/SodaLive/Sources/Content/Main/V2/Home/Rank/ContentMainTabHomeRankCreatorView.swift @@ -151,28 +151,28 @@ struct ContentMainTabHomeRankCreatorView: View { nickname: "User1", tags: "", profileImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png", - followerCount: 1000 + follow: false ), GetExplorerSectionCreatorResponse( id: 2, nickname: "User2", tags: "", profileImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png", - followerCount: 1000 + follow: false ), GetExplorerSectionCreatorResponse( id: 3, nickname: "User3", tags: "", profileImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png", - followerCount: 1000 + follow: false ), GetExplorerSectionCreatorResponse( id: 4, nickname: "User4", tags: "", profileImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png", - followerCount: 1000 + follow: false ) ] ) diff --git a/SodaLive/Sources/Explorer/GetExplorerResponse.swift b/SodaLive/Sources/Explorer/GetExplorerResponse.swift index 81b2048..f06876d 100644 --- a/SodaLive/Sources/Explorer/GetExplorerResponse.swift +++ b/SodaLive/Sources/Explorer/GetExplorerResponse.swift @@ -24,6 +24,6 @@ struct GetExplorerSectionCreatorResponse: Decodable, Hashable { let nickname: String let tags: String let profileImageUrl: String - let followerCount: Int + var follow: Bool } diff --git a/SodaLive/Sources/Home/HomeCreatorRankingItemView.swift b/SodaLive/Sources/Home/HomeCreatorRankingItemView.swift index 4544c90..1658a37 100644 --- a/SodaLive/Sources/Home/HomeCreatorRankingItemView.swift +++ b/SodaLive/Sources/Home/HomeCreatorRankingItemView.swift @@ -11,54 +11,55 @@ import Kingfisher struct HomeCreatorRankingItemView: View { let rank: Int - let item: GetExplorerSectionCreatorResponse + @State var item: GetExplorerSectionCreatorResponse + + let onClickFollow: (Int, Bool) -> Void let crowns = ["rank_1", "rank_2", "rank_3"] + @AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token) + var body: some View { ZStack(alignment: .topLeading) { VStack(spacing: 0) { KFImage(URL(string: item.profileImageUrl)) .cancelOnDisappear(true) .resizable() - .frame(width: 70, height: 70) + .frame(width: 84, height: 84) .clipShape(Circle()) - + Text(item.nickname) - .font(.custom(Font.preRegular.rawValue, size: 18)) + .font(.custom(Font.preRegular.rawValue, size: 16)) .foregroundColor(.white) - .padding(.top, 8) + .padding(.top, 20) - Text("팔로워") - .font(.custom(Font.preBold.rawValue, size: 14)) - .foregroundColor(Color(hex: "78909C")) - .padding(.top, 12) + Spacer() - Text("\(item.followerCount)") - .font(.custom(Font.preRegular.rawValue, size: 14)) - .foregroundColor(Color(hex: "78909C")) - .padding(.top, 4) + if item.id != UserDefaults.int(forKey: .userId) { + Text(item.follow ? "팔로잉" : "팔로우") + .font(.custom(Font.preRegular.rawValue, size: 14)) + .padding(.vertical, 4) + .frame(maxWidth: .infinity) + .background( + item.follow ? Color(hex: "455a64") : Color.white + ) + .cornerRadius(999) + .foregroundColor( + item.follow ? .white : Color(hex: "263238") + ) + .onTapGesture { + if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { + item.follow = !item.follow + } + + onClickFollow(item.id, item.follow) + } + } } - .frame(width: 133, height: 188) - .background( - LinearGradient( - gradient: Gradient(colors: [Color(hex: "5ACDE1"), Color(hex: "2A339D")]), - startPoint: .topLeading, - endPoint: .bottom - ) - ) + .padding(16) + .frame(width: 144, height: 204) + .background(Color(hex: "263238")) .cornerRadius(16) - .overlay { - RoundedRectangle(cornerRadius: 16) - .strokeBorder( - LinearGradient( - gradient: Gradient(colors: [Color(hex: "9AE2F6"), .white.opacity(0)]), - startPoint: .top, - endPoint: .bottom - ), - lineWidth: 1 - ) - } .padding(.top, 20) if rank <= 3 { @@ -79,7 +80,8 @@ struct HomeCreatorRankingItemView: View { nickname: "유빈ASMR", tags: "", profileImageUrl: "https://cf.sodalive.net/profile/34806/34806-profile-49db6b45-bb1e-4dc7-917e-1a614a853f5f-4232-1752158072656", - followerCount: 1000 - ) + follow: true + ), + onClickFollow: { _, _ in } ) } diff --git a/SodaLive/Sources/Home/HomeTabView.swift b/SodaLive/Sources/Home/HomeTabView.swift index 3d29ced..028f33b 100644 --- a/SodaLive/Sources/Home/HomeTabView.swift +++ b/SodaLive/Sources/Home/HomeTabView.swift @@ -109,7 +109,22 @@ struct HomeTabView: View { HStack(spacing: 16) { ForEach(0..() @Published var errorMessage = "" @@ -160,4 +161,40 @@ final class HomeTabViewModel: ObservableObject { } .store(in: &subscription) } + + func creatorFollow(creatorId: Int, follow: Bool = true, notify: Bool = true) { + isLoading = true + + userRepository.creatorFollow(creatorId: creatorId, follow: follow, notify: notify) + .sink { result in + switch result { + case .finished: + DEBUG_LOG("finish") + case .failure(let error): + ERROR_LOG(error.localizedDescription) + } + } receiveValue: { [unowned self] response in + self.isLoading = false + let responseData = response.data + + do { + let jsonDecoder = JSONDecoder() + let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData) + + if !decoded.success { + if let message = decoded.message { + self.errorMessage = message + } else { + self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + } + + self.isShowPopup = true + } + } catch { + self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + self.isShowPopup = true + } + } + .store(in: &subscription) + } }