From b3c187911f9eda4a3a4bca8403bd59121b6519df Mon Sep 17 00:00:00 2001 From: HELLOHIDI Date: Sat, 23 Nov 2024 11:45:05 +0900 Subject: [PATCH] =?UTF-8?q?[Feat/#118]=20Point=20Demo=20App=20=EC=A0=9C?= =?UTF-8?q?=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Extension/Combine+/Mapper.swift | 1 - .../PointServiceView.swift} | 104 +++++++-------- .../PointServiceViewModel.swift | 120 ++++++++++++++++++ .../Networks/Demo/Sources/ServiceType.swift | 38 +++++- .../Sources/DTO/Point/UserPointDTO.swift | 6 + .../Foundation/Base/NetworkLogHandler.swift | 2 +- .../Error/Foundation/HMHNetworkError.swift | 4 +- 7 files changed, 210 insertions(+), 65 deletions(-) rename HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/{ServiceTestView.swift => PointServiceTest/PointServiceView.swift} (61%) create mode 100644 HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/PointServiceTest/PointServiceViewModel.swift diff --git a/HMH_Tuist_iOS/Projects/Core/Sources/Extension/Combine+/Mapper.swift b/HMH_Tuist_iOS/Projects/Core/Sources/Extension/Combine+/Mapper.swift index 0182d983..435cbe37 100644 --- a/HMH_Tuist_iOS/Projects/Core/Sources/Extension/Combine+/Mapper.swift +++ b/HMH_Tuist_iOS/Projects/Core/Sources/Extension/Combine+/Mapper.swift @@ -29,4 +29,3 @@ public extension Publisher { .eraseToAnyPublisher() } } - diff --git a/HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/ServiceTestView.swift b/HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/PointServiceTest/PointServiceView.swift similarity index 61% rename from HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/ServiceTestView.swift rename to HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/PointServiceTest/PointServiceView.swift index 5beaf3c4..0f6bbb49 100644 --- a/HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/ServiceTestView.swift +++ b/HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/PointServiceTest/PointServiceView.swift @@ -1,5 +1,5 @@ // -// ServiceTestView.swift +// PointServiceView.swift // NetworksDemo // // Created by 류희재 on 11/22/24. @@ -9,8 +9,11 @@ import SwiftUI import Networks import Core +import Combine -struct ServiceTestView: View { +struct PointServiceView: View { + + @StateObject var viewModel: PointServiceViewModel var body: some View { VStack { @@ -24,9 +27,9 @@ struct ServiceTestView: View { .frame(width: 12, height: 24) } .padding(.leading, 14) - + Spacer() - + Text("PointService") .foregroundStyle(Color( red: 165 / 255.0, @@ -36,12 +39,12 @@ struct ServiceTestView: View { .font(.title) .bold() .multilineTextAlignment(.center) - + Spacer() } .padding(.vertical, 18) - ServiceListView() + ServiceListView(viewModel: viewModel) .padding(.horizontal, 20) .padding(.bottom, 25) .frame(height: 360) @@ -52,7 +55,7 @@ struct ServiceTestView: View { .padding(.horizontal, 20) .padding(.bottom, 25) - Text("결과창") + Text(viewModel.state.networkLoggingText) .padding(.top, 25) .padding(.horizontal, 20) .frame(width: 335, height: 240) @@ -64,67 +67,54 @@ struct ServiceTestView: View { } } -//ForEach($viewModel.missionList) { $mission in -// Service(viewModel: viewModel, mission: $mission) -// .padding(.bottom, 16) -//} fileprivate struct ServiceListView: View { + private let viewModel: PointServiceViewModel + + init(viewModel: PointServiceViewModel) { + self.viewModel = viewModel + } + + let apiList: [String] = [ + "PatchPointUse", + "GetEarnPoint", + "GetUsagePoint", + "PatchEarnPoint", + "GetPointList" + + ] var body: some View { VStack { Spacer() .frame(height: 24) ScrollView(.vertical, showsIndicators: true) { - ServiceCellView() - Rectangle() - .foregroundColor(.gray) - .frame(width: .infinity, height: 1) - ServiceCellView() - Rectangle() - .foregroundColor(.gray) - .frame(width: .infinity, height: 1) - ServiceCellView() - Rectangle() - .foregroundColor(.gray) - .frame(width: .infinity, height: 1) - ServiceCellView() - Rectangle() - .foregroundColor(.gray) - .frame(width: .infinity, height: 1) - ServiceCellView() - Rectangle() - .foregroundColor(.gray) - .frame(width: .infinity, height: 1) - ServiceCellView() - Rectangle() - .foregroundColor(.gray) - .frame(width: .infinity, height: 1) - ServiceCellView() - Rectangle() - .foregroundColor(.gray) - .frame(width: .infinity, height: 1) - ServiceCellView() - Rectangle() - .foregroundColor(.gray) - .frame(width: .infinity, height: 1) - ServiceCellView() - Rectangle() - .foregroundColor(.gray) - .frame(width: .infinity, height: 1) - ServiceCellView() - Rectangle() - .foregroundColor(.gray) - .frame(width: .infinity, height: 1) + ForEach(Array(apiList.enumerated()), id: \.element) { index, api in + ServiceCellView(apiTitle: api, index: index, viewModel: viewModel) + Rectangle() + .foregroundColor(.gray) + .frame(width: .infinity, height: 1) + } } } } } fileprivate struct ServiceCellView: View { + private let apiTitle: String + private let index: Int + @ObservedObject private var viewModel: PointServiceViewModel + + init(apiTitle: String, index: Int, viewModel: PointServiceViewModel) { + self.apiTitle = apiTitle + self.index = index + self.viewModel = viewModel + } + + var body: some View { HStack { VStack(alignment: .leading) { - Text("PatchPointUse") + Text(apiTitle) .foregroundStyle(Color( red: 219 / 255.0, green: 218 / 255.0, @@ -135,7 +125,7 @@ fileprivate struct ServiceCellView: View { .frame(height: 2) .padding(.bottom, 10) - Text("✅ 성공 or ❌ 실패") + Text("테스트 결과: \(viewModel.state.resultText[index])") .foregroundColor(.white) .font(.body) .bold() @@ -145,7 +135,7 @@ fileprivate struct ServiceCellView: View { Spacer() Button { - + viewModel.send(action: .serviceButtonDidTap(index)) } label: { Text("Test") .foregroundColor(.white) @@ -166,7 +156,11 @@ fileprivate struct ServiceCellView: View { } #Preview { - return ServiceTestView() + return PointServiceView( + viewModel: PointServiceViewModel( + service: PointService() + ) + ) } diff --git a/HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/PointServiceTest/PointServiceViewModel.swift b/HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/PointServiceTest/PointServiceViewModel.swift new file mode 100644 index 00000000..f76db109 --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/PointServiceTest/PointServiceViewModel.swift @@ -0,0 +1,120 @@ +// +// PointServiceViewModel.swift +// NetworksDemo +// +// Created by 류희재 on 11/23/24. +// Copyright © 2024 HMH-iOS. All rights reserved. + + +import Foundation +import Combine +import Core +import Networks + +class PointServiceViewModel: ObservableObject { + + //MARK: Action, State + + enum Action { + case serviceButtonDidTap(Int) + } + + struct State { + var resultText: [String] = Array(repeating: "", count: 5) + var networkLoggingText: String = "네트워크 결과창입니다!" + } + + //MARK: Dependency + + let service: PointServiceType + + //MARK: Init + + + + // MARK: - Init + init(service: PointServiceType) { + self.service = service + self.state = State() + } + + //MARK: Properties + + @Published private(set) var state: State + private let cancelBag = CancelBag() + + //MARK: Methods + + func send(action: Action) { + switch action { + case .serviceButtonDidTap(let index): + let requestPublisher: AnyPublisher + switch index { + case 0: + service.patchPointUse() + .sink(receiveCompletion: { [weak self] completion in + if case let .failure(error) = completion { + self?.state.networkLoggingText = error.description + self?.state.resultText[index] = "❌ 실패" + } + }) { [weak self] result in + self?.state.networkLoggingText = "\(result)" + self?.state.resultText[index] = "✅ 성공" + } + .store(in: cancelBag) + case 1: + service.getEarnPoint() + .sink(receiveCompletion: { [weak self] completion in + if case let .failure(error) = completion { + self?.state.networkLoggingText = error.description + self?.state.resultText[index] = "❌ 실패" + } + }) { [weak self] result in + self?.state.networkLoggingText = "\(result)" + self?.state.resultText[index] = "✅ 성공" + } + .store(in: cancelBag) + case 2: + service.getUsagePoint() + .sink(receiveCompletion: { [weak self] completion in + if case let .failure(error) = completion { + self?.state.networkLoggingText = error.description + self?.state.resultText[index] = "❌ 실패" + } + }) { [weak self] result in + self?.state.networkLoggingText = "\(result)" + self?.state.resultText[index] = "✅ 성공" + } + .store(in: cancelBag) + case 3: + service.patchEarnPoint(request: .stub) + .sink(receiveCompletion: { [weak self] completion in + if case let .failure(error) = completion { + self?.state.networkLoggingText = error.description + self?.state.resultText[index] = "❌ 실패" + } + }) { [weak self] result in + self?.state.networkLoggingText = "\(result)" + self?.state.resultText[index] = "✅ 성공" + } + .store(in: cancelBag) + case 4: + service.getPointList() + .sink(receiveCompletion: { [weak self] completion in + if case let .failure(error) = completion { + self?.state.networkLoggingText = error.description + self?.state.resultText[index] = "❌ 실패" + } + }) { [weak self] result in + self?.state.networkLoggingText = "\(result)" + self?.state.resultText[index] = "✅ 성공" + } + .store(in: cancelBag) + default: + break + } + } + } +} + + diff --git a/HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/ServiceType.swift b/HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/ServiceType.swift index ab6c0864..2a8a3ea6 100644 --- a/HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/ServiceType.swift +++ b/HMH_Tuist_iOS/Projects/Modules/Networks/Demo/Sources/ServiceType.swift @@ -10,10 +10,23 @@ import Foundation import Networks enum ServiceType { - case auth - case point - case challenge - case user + case auth(AuthService) + case point(PointService) + case challenge(ChallengeService) + case user(UserService) + + var title: String { + switch self { + case .auth: + return "AuthService" + case .point: + return "PointService" + case .challenge: + return "ChallengeService" + case .user: + return "UserService" + } + } var apiList: [String] { switch self { @@ -31,9 +44,22 @@ enum ServiceType { "PatchEarnPoint" ] case .challenge: - <#code#> + return [ + "GetDailyChallenge", + "GetSuccesChallenge", + "CreateChallenge", + "PostLockChallenge", + "DeleteApp", + "AddApp", + "GetChallenge" + ] case .user: - <#code#> + return [ + "Logout", + "DeleteAccount", + "GetUserData", + "GetCurrentPoint" + ] } } } diff --git a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Point/UserPointDTO.swift b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Point/UserPointDTO.swift index 4cff8f45..63f9018c 100644 --- a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Point/UserPointDTO.swift +++ b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Point/UserPointDTO.swift @@ -24,6 +24,12 @@ public struct UserPointResult: Decodable { } } +public extension UserPointRequest { + static var stub: Self { + return .init(challengeDate: "2024/12/1") + } +} + public extension UserPointResult { static var stub: Self { return .init(userPoint: 100) diff --git a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/Foundation/Base/NetworkLogHandler.swift b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/Foundation/Base/NetworkLogHandler.swift index 34e40d01..1a1eb445 100644 --- a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/Foundation/Base/NetworkLogHandler.swift +++ b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/Foundation/Base/NetworkLogHandler.swift @@ -8,7 +8,7 @@ import Foundation -struct NetworkLogHandler { +public struct NetworkLogHandler { // 디코딩 로깅 함수 static func responseDecodingError( data: Data, diff --git a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/Foundation/Response/Error/Foundation/HMHNetworkError.swift b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/Foundation/Response/Error/Foundation/HMHNetworkError.swift index 2e935bbf..b62ee759 100644 --- a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/Foundation/Response/Error/Foundation/HMHNetworkError.swift +++ b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/Foundation/Response/Error/Foundation/HMHNetworkError.swift @@ -8,7 +8,7 @@ import Foundation -@frozen public enum HMHNetworkError: Error, Equatable { +@frozen public enum HMHNetworkError: Error, Equatable, LocalizedError { case invalidRequest(RequestError) case invalidResponse(ResponseError) case decodingFailed(DecodeError) @@ -16,7 +16,7 @@ import Foundation case retryLimitExceeded case unknownError - var description: String { + public var description: String { switch self { case .invalidRequest(let requestError): return "요청 시 발생된" + requestError.description