From 06959be239582bab83846209fd9ebadbd4ba11fa Mon Sep 17 00:00:00 2001 From: Park Seo Yeon Date: Sat, 8 Feb 2025 01:49:13 +0900 Subject: [PATCH 1/3] =?UTF-8?q?[Feat]=20=ED=8A=B8=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=84=88=20=ED=9A=8C=EC=9B=90=20=EB=AA=A9=EB=A1=9D=20usecase,?= =?UTF-8?q?=20dto=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 화면 작성 (네비게이션 추가) - 회원이 없는 경우의 EmptyView 화면 작성 --- .../DIContainer/Sources/DIContainer.swift | 9 + .../Trainer/TrainerRepositoryImpl.swift | 7 + .../Service/Trainer/TrainerTargetType.swift | 10 + .../Sources/Navigation/TNavigation.swift | 22 +- .../DTO/Trainer/GetMembersListDTO.swift | 39 ++++ .../Sources/Entity/GetMembersListEntity.swift | 92 ++++++++ .../Repository/TrainerRepository.swift | 3 + .../Sources/UseCase/TrainerUseCase.swift | 39 ++++ .../Trainer/TrainerManagementView.swift | 205 ++++++++++++++++++ 9 files changed, 425 insertions(+), 1 deletion(-) create mode 100644 TnT/Projects/Domain/Sources/DTO/Trainer/GetMembersListDTO.swift create mode 100644 TnT/Projects/Domain/Sources/Entity/GetMembersListEntity.swift create mode 100644 TnT/Projects/Domain/Sources/UseCase/TrainerUseCase.swift create mode 100644 TnT/Projects/Presentation/Sources/MyPage/Trainer/TrainerManagementView.swift diff --git a/TnT/Projects/DIContainer/Sources/DIContainer.swift b/TnT/Projects/DIContainer/Sources/DIContainer.swift index e0c12763..3ea94209 100644 --- a/TnT/Projects/DIContainer/Sources/DIContainer.swift +++ b/TnT/Projects/DIContainer/Sources/DIContainer.swift @@ -30,6 +30,10 @@ private enum SocialUseCaseKey: DependencyKey { static let liveValue: SocialLoginUseCase = SocialLoginUseCase(socialLoginRepository: SocialLogInRepositoryImpl(loginManager: SNSLoginManager())) } +private enum TrainerUseCaseKey: DependencyKey { + static let liveValue: TrainerRepository = DefaultTrainerUseCase(trainerRepository: TrainerRepositoryImpl()) +} + // MARK: - DependencyValues public extension DependencyValues { var userUseCase: UserUseCase { @@ -51,4 +55,9 @@ public extension DependencyValues { get { self[SocialUseCaseKey.self] } set { self[SocialUseCaseKey.self] = newValue } } + + var trainerRepoUseCase: TrainerRepository { + get { self[TrainerUseCaseKey.self] } + set { self[TrainerUseCaseKey.self] = newValue } + } } diff --git a/TnT/Projects/Data/Sources/Network/Service/Trainer/TrainerRepositoryImpl.swift b/TnT/Projects/Data/Sources/Network/Service/Trainer/TrainerRepositoryImpl.swift index eae6b117..dc6339a1 100644 --- a/TnT/Projects/Data/Sources/Network/Service/Trainer/TrainerRepositoryImpl.swift +++ b/TnT/Projects/Data/Sources/Network/Service/Trainer/TrainerRepositoryImpl.swift @@ -45,4 +45,11 @@ public struct TrainerRepositoryImpl: TrainerRepository { decodingType: GetDateSessionListDTO.self ) } + + public func getMembersList() async throws -> GetMembersListDTO { + return try await networkService.request( + TrainerTargetType.getMemebersList, + decodingType: GetMembersListDTO.self + ) + } } diff --git a/TnT/Projects/Data/Sources/Network/Service/Trainer/TrainerTargetType.swift b/TnT/Projects/Data/Sources/Network/Service/Trainer/TrainerTargetType.swift index 90b1715c..e6d19681 100644 --- a/TnT/Projects/Data/Sources/Network/Service/Trainer/TrainerTargetType.swift +++ b/TnT/Projects/Data/Sources/Network/Service/Trainer/TrainerTargetType.swift @@ -20,6 +20,8 @@ public enum TrainerTargetType { case getDateLessionList(date: String) /// 트레이너 초대코드 재발급 case getReissuanceInvitationCode + /// 회원 조희 + case getMemebersList } extension TrainerTargetType: TargetType { @@ -38,6 +40,8 @@ extension TrainerTargetType: TargetType { return "/lessions/\(date)" case .getReissuanceInvitationCode: return "/invitation-code/reissue" + case .getMemebersList: + return "/members" } } @@ -51,6 +55,8 @@ extension TrainerTargetType: TargetType { return .get case .getReissuanceInvitationCode: return .put + case .getMemebersList: + return .get } } @@ -64,6 +70,8 @@ extension TrainerTargetType: TargetType { return .requestPlain case .getReissuanceInvitationCode: return .requestPlain + case .getMemebersList: + return .requestPlain } } @@ -77,6 +85,8 @@ extension TrainerTargetType: TargetType { return ["Content-Type": "application/json"] case .getReissuanceInvitationCode: return ["Content-Type": "application/json"] + case .getMemebersList: + return ["Content-Type": "application/json"] } } diff --git a/TnT/Projects/DesignSystem/Sources/Navigation/TNavigation.swift b/TnT/Projects/DesignSystem/Sources/Navigation/TNavigation.swift index e300dbbf..3ffbbbfd 100644 --- a/TnT/Projects/DesignSystem/Sources/Navigation/TNavigation.swift +++ b/TnT/Projects/DesignSystem/Sources/Navigation/TNavigation.swift @@ -64,6 +64,16 @@ public struct TNavigation: View { Rectangle() .fill(Color.clear) .frame(width: 32, height: 32) + + case .LTextRButtonTitle(let leftTitle, let pointText, _): + HStack(spacing: 6){ + Text(leftTitle) + .typographyStyle(.heading2, with: .neutral900) + if let pointText = pointText { + Text(pointText) + .typographyStyle(.heading2, with: .red500) + } else { EmptyView() } + } } } @@ -78,7 +88,7 @@ public struct TNavigation: View { Text(centerTitle) .typographyStyle(.heading4, with: .neutral900) .frame(maxWidth: .infinity, alignment: .center) - case .LButton: + case .LButton, .LTextRButtonTitle(_, _, _): EmptyView() } } @@ -105,6 +115,14 @@ public struct TNavigation: View { Rectangle() .fill(Color.clear) .frame(width: 32, height: 32) + + case .LTextRButtonTitle(_, _, let rightButton): + TButton( + title: rightButton, + config: .small, + state: .disable(.gray(isEnabled: true))) { + rightAction?() + } } } } @@ -143,4 +161,6 @@ public enum TNavigationCase { case Title(centerTitle: String) /// 왼쪽 이미지 case LButton(leftImage: ImageResource) + /// 왼쪽 텍스트, 오른쪽 버튼 + case LTextRButtonTitle(leftTitle: String, pointText: String?, rightButton: String) } diff --git a/TnT/Projects/Domain/Sources/DTO/Trainer/GetMembersListDTO.swift b/TnT/Projects/Domain/Sources/DTO/Trainer/GetMembersListDTO.swift new file mode 100644 index 00000000..99bffdf9 --- /dev/null +++ b/TnT/Projects/Domain/Sources/DTO/Trainer/GetMembersListDTO.swift @@ -0,0 +1,39 @@ +// +// GetMembersListDTO.swift +// Domain +// +// Created by 박서연 on 2/8/25. +// Copyright © 2025 yapp25thTeamTnT. All rights reserved. +// + +import Foundation + +/// 트레이너 회원 조회 DTO +public struct GetMembersListDTO: Decodable { + /// 이름 + public let name: String + /// 이메일 + public let email: String + /// 프로필 사진 + public let profileImageUrl: String + /// 생년월일 + public let birthday: String + /// 유저 타입 (트레이너/트레이니) + public let memberType: String + /// 소셜 로그인 타입 + public let socialType: String + /// 관리중인 회원의 수 + public let managementMember: Int + /// 함께했던 회원의 수 + public let fellowMember: Int + /// 트레이너 ID + public let trainerId: String + /// 트레이니 키 + public let height: Double + /// 트레이니 무게 + public let weight: Double + /// 주의사항 + public let cautionNote: String + /// PT 목표 + public let goalContents: [String] +} diff --git a/TnT/Projects/Domain/Sources/Entity/GetMembersListEntity.swift b/TnT/Projects/Domain/Sources/Entity/GetMembersListEntity.swift new file mode 100644 index 00000000..86dbfcc4 --- /dev/null +++ b/TnT/Projects/Domain/Sources/Entity/GetMembersListEntity.swift @@ -0,0 +1,92 @@ +// +// GetMembersListEntity.swift +// Domain +// +// Created by 박서연 on 2/8/25. +// Copyright © 2025 yapp25thTeamTnT. All rights reserved. +// + +import Foundation + +/// 트레이너 회원 조회 DTO +public struct GetMembersListEntity: Encodable, Equatable { + /// ID 값 활용을 위한 추가 + public let id: String + /// 이름 + public let name: String + /// 이메일 + public let email: String + /// 프로필 사진 + public let profileImageUrl: String + /// 생년월일 + public let birthday: String? + /// 유저 타입 (트레이너/트레이니) + public let memberType: String + /// 소셜 로그인 타입 + public let socialType: String + /// 관리중인 회원의 수 + public let managementMember: Int + /// 함께했던 회원의 수 + public let fellowMember: Int + /// 트레이너 ID + public let trainerId: String + /// 트레이니 키 + public let height: Double? + /// 트레이니 무게 + public let weight: Double? + /// 주의사항 + public let cautionNote: String? + /// PT 목표 + public let goalContents: [String] + + public init( + id: String = UUID().uuidString, + name: String, + email: String, + profileImageUrl: String, + birthday: String?, + memberType: String, + socialType: String, + managementMember: Int, + fellowMember: Int, + trainerId: String, + height: Double?, + weight: Double?, + cautionNote: String?, + goalContents: [String] + ) { + self.id = id + self.name = name + self.email = email + self.profileImageUrl = profileImageUrl + self.birthday = birthday + self.memberType = memberType + self.socialType = socialType + self.managementMember = managementMember + self.fellowMember = fellowMember + self.trainerId = trainerId + self.height = height + self.weight = weight + self.cautionNote = cautionNote + self.goalContents = goalContents + } +} + +extension GetMembersListEntity { + static func toDTO(entity: GetMembersListEntity) -> GetMembersListDTO { + return GetMembersListDTO( + name: entity.name, + email: entity.email, + profileImageUrl: entity.profileImageUrl, + birthday: entity.birthday ?? "", + memberType: entity.memberType, + socialType: entity.socialType, + managementMember: entity.managementMember, + fellowMember: entity.fellowMember, + trainerId: entity.trainerId, + height: entity.height ?? 0.0, + weight: entity.weight ?? 0.0, + cautionNote: entity.cautionNote ?? "", + goalContents: entity.goalContents) + } +} diff --git a/TnT/Projects/Domain/Sources/Repository/TrainerRepository.swift b/TnT/Projects/Domain/Sources/Repository/TrainerRepository.swift index 6c7ae2f1..c6f27016 100644 --- a/TnT/Projects/Domain/Sources/Repository/TrainerRepository.swift +++ b/TnT/Projects/Domain/Sources/Repository/TrainerRepository.swift @@ -25,4 +25,7 @@ public protocol TrainerRepository { /// 트레이너 캘린더에 특정 날짜의 수업 정보 가져오기 func getDateSessionList(date: String) async throws -> GetDateSessionListDTO + + /// 회원 조희 + func getMembersList() async throws -> GetMembersListDTO } diff --git a/TnT/Projects/Domain/Sources/UseCase/TrainerUseCase.swift b/TnT/Projects/Domain/Sources/UseCase/TrainerUseCase.swift new file mode 100644 index 00000000..2b906ff3 --- /dev/null +++ b/TnT/Projects/Domain/Sources/UseCase/TrainerUseCase.swift @@ -0,0 +1,39 @@ +// +// TrainerUseCase.swift +// Domain +// +// Created by 박서연 on 2/8/25. +// Copyright © 2025 yapp25thTeamTnT. All rights reserved. +// + +import Foundation + +// MARK: - TrainerUseCase Default 구현체 +public struct DefaultTrainerUseCase: TrainerRepository { + + private let trainerRepository: TrainerRepository + + public init (trainerRepository: TrainerRepository) { + self.trainerRepository = trainerRepository + } + + public func getVerifyInvitationCode(code: String) async throws -> GetVerifyInvitationCodeResDTO { + return try await trainerRepository.getVerifyInvitationCode(code: code) + } + + public func getTheFirstInvitationCode() async throws -> GetTheFirstInvitationCodeDTO { + return try await trainerRepository.getTheFirstInvitationCode() + } + + public func getReissuanceInvitationCode() async throws -> GetReissuanceInvitationCodeDTO { + return try await trainerRepository.getReissuanceInvitationCode() + } + + public func getDateSessionList(date: String) async throws -> GetDateSessionListDTO { + return try await trainerRepository.getDateSessionList(date: date) + } + + public func getMembersList() async throws -> GetMembersListDTO { + return try await trainerRepository.getMembersList() + } +} diff --git a/TnT/Projects/Presentation/Sources/MyPage/Trainer/TrainerManagementView.swift b/TnT/Projects/Presentation/Sources/MyPage/Trainer/TrainerManagementView.swift new file mode 100644 index 00000000..fa5a0576 --- /dev/null +++ b/TnT/Projects/Presentation/Sources/MyPage/Trainer/TrainerManagementView.swift @@ -0,0 +1,205 @@ +// +// TrainerManagementView.swift +// Presentation +// +// Created by 박서연 on 2/7/25. +// Copyright © 2025 yapp25thTeamTnT. All rights reserved. +// + +import SwiftUI +import ComposableArchitecture + +import DesignSystem + +/* + @Reducer + public struct TrainerMypageFeature { + + @ObservableState + public struct State: Equatable { + /// 사용자 이름 + var userName: String + /// 사용자 이미지 URL + var userImageUrl: String? + /// 관리 중인 회원 + var studentCount: Int + /// 함께 했던 회원 + var oldStudentCount: Int + /// 앱 푸시 알림 허용 여부 + var appPushNotificationAllowed: Bool + /// 버전 정보 + var versionInfo: String + /// 팝업 + var view_popUp: PopUp? + /// 팝업 표시 유무 + var view_isPopUpPresented: Bool = false + + public init( + userName: String = "", + userImageUrl: String? = nil, + studentCount: Int = 0, + oldStudentCount: Int = 0, + appPushNotificationAllowed: Bool = false, + versionInfo: String = "", + view_popUp: PopUp? = nil, + view_isPopUpPresented: Bool = false + ) { + self.userName = userName + self.userImageUrl = userImageUrl + self.studentCount = studentCount + self.oldStudentCount = oldStudentCount + self.appPushNotificationAllowed = appPushNotificationAllowed + self.versionInfo = versionInfo + self.view_popUp = view_popUp + self.view_isPopUpPresented = view_isPopUpPresented + } + } + + @Dependency(\.userUseCase) private var userUseCase: UserUseCase + + public enum Action: Sendable, ViewAction { + /// 뷰에서 발생한 액션을 처리합니다. + case view(View) + /// 네비게이션 여부 설정 + case setNavigating + + @CasePathable + public enum View: Sendable, BindableAction { + /// 바인딩할 액션을 처리 (알람) + case binding(BindingAction) + /// 서비스 이용약관 버튼 탭 + case tapTOSButton + /// 개인정보 처리방침 버튼 탭 + case tapPrivacyPolicyButton + /// 오픈소스 라이선스 버튼 탭 + case tapOpenSourceLicenseButton + /// 로그아웃 버튼 탭 + case tapLogoutButton + /// 계정 탈퇴 버튼 탭 + case tapWithdrawButton + /// 팝업 왼쪽 탭 + case tapPupUpSecondaryButton(popUp: PopUp?) + /// 팝옵 오른쪽 탭 + case tapPopUpPrimaryButton(popUp: PopUp?) + } + } + + public init() { } + + public var body: some ReducerOf { + BindingReducer(action: \.view) + + Reduce { state, action in + switch action { + case .view(let action): + */ + +@Reducer +struct TrainerManagementFeature { + @ObservableState + struct State { + + } +} + +struct TrainerManagementView: View { + var body: some View { + VStack(spacing: 0) { + TNavigation(type: .LTextRButtonTitle( + leftTitle: "내 회원", + pointText: "0", + rightButton: "회원 초대하기") + ) + + VStack(spacing: 12) { + HStack { + ProfileImageView(imageURL: "") + + VStack(spacing: 12) { + Text("") + .typographyStyle(.body1Bold, with: Color.neutral900) + Text("") + .typographyStyle(.label2Medium, with: Color.neutral500) + } + } + + VStack(spacing: 5) { + Text("메모") + .typographyStyle(.label2Bold, with: Color.neutral600) + Text("") + .typographyStyle(.label2Medium, with: Color.neutral500) + } + } + .padding(12) + .background(Color.white) + .clipShape(RoundedRectangle(cornerRadius: 12)) + } + } + + /// 연결된 회원이 없는 경우 + @ViewBuilder + func EmptyListView() -> some View { + VStack(spacing: 0) { + TNavigation(type: .LTextRButtonTitle( + leftTitle: "내 회원", + pointText: "0", + rightButton: "회원 초대하기") + ) + + Spacer() + VStack(spacing: 4) { + Text("아직 연결된 회원이 없어요") + .typographyStyle(.body2Bold, with: Color.neutral600) + Text("추가 버튼을 눌러 회원을 추가해 보세요") + .typographyStyle(.label1Medium, with: Color.neutral400) + } + Spacer() + } + } +} + +extension TrainerManagementView { + struct ProfileImageView: View { + let imageURL: String? + + var body: some View { + if let urlString = imageURL, let url = URL(string: urlString) { + AsyncImage(url: url) { phase in + switch phase { + case .empty: + ProgressView() + .tint(.red500) + .frame(width: 60, height: 60) + + case .success(let image): + image + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 60, height: 60) + .clipShape(RoundedRectangle(cornerRadius: 16)) + + case .failure: + Image(.imgDefaultTrainerImage) + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 60, height: 60) + .clipShape(RoundedRectangle(cornerRadius: 16)) + + @unknown default: + EmptyView() + } + } + } else { + Image(.imgDefaultTrainerImage) + .resizable() + .scaledToFill() + .frame(width: 132, height: 132) + .clipShape(Circle()) + } + } + } +} + +#Preview { + TrainerManagementView() +} From f14e28cd8af23a91ee0eb648fe48286af1b14f55 Mon Sep 17 00:00:00 2001 From: Park Seo Yeon Date: Sun, 9 Feb 2025 04:09:40 +0900 Subject: [PATCH 2/3] =?UTF-8?q?[Feat]=20=ED=8A=B8=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=84=88=20=EB=A7=88=EC=9D=B4=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EB=AA=A9=EB=A1=9D=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DTO/Trainer/GetMembersListDTO.swift | 28 +++- .../{ => Policy}/Extension/Date+.swift | 0 .../{ => Policy}/Extension/String+.swift | 0 .../Trainer/TrainerManagementView.swift | 145 ++++-------------- .../Trainer/TrainerManagmentFeature.swift | 47 ++++++ 5 files changed, 102 insertions(+), 118 deletions(-) rename TnT/Projects/Domain/Sources/{ => Policy}/Extension/Date+.swift (100%) rename TnT/Projects/Domain/Sources/{ => Policy}/Extension/String+.swift (100%) create mode 100644 TnT/Projects/Presentation/Sources/MyPage/Trainer/TrainerManagmentFeature.swift diff --git a/TnT/Projects/Domain/Sources/DTO/Trainer/GetMembersListDTO.swift b/TnT/Projects/Domain/Sources/DTO/Trainer/GetMembersListDTO.swift index 99bffdf9..6d4b6584 100644 --- a/TnT/Projects/Domain/Sources/DTO/Trainer/GetMembersListDTO.swift +++ b/TnT/Projects/Domain/Sources/DTO/Trainer/GetMembersListDTO.swift @@ -17,7 +17,7 @@ public struct GetMembersListDTO: Decodable { /// 프로필 사진 public let profileImageUrl: String /// 생년월일 - public let birthday: String + public let birthday: String? /// 유저 타입 (트레이너/트레이니) public let memberType: String /// 소셜 로그인 타입 @@ -29,11 +29,31 @@ public struct GetMembersListDTO: Decodable { /// 트레이너 ID public let trainerId: String /// 트레이니 키 - public let height: Double + public let height: Double? /// 트레이니 무게 - public let weight: Double + public let weight: Double? /// 주의사항 - public let cautionNote: String + public let cautionNote: String? /// PT 목표 public let goalContents: [String] } + +public extension GetMembersListDTO { + public static func toEntity(resEntity: GetMembersListDTO) -> GetMembersListEntity { + return GetMembersListEntity( + name: resEntity.name, + email: resEntity.email, + profileImageUrl: resEntity.profileImageUrl, + birthday: resEntity.birthday ?? "", + memberType: resEntity.memberType, + socialType: resEntity.socialType, + managementMember: resEntity.managementMember, + fellowMember: resEntity.fellowMember, + trainerId: resEntity.trainerId, + height: resEntity.height ?? 0.0, + weight: resEntity.weight ?? 0.0, + cautionNote: resEntity.cautionNote ?? "", + goalContents: resEntity.goalContents + ) + } +} diff --git a/TnT/Projects/Domain/Sources/Extension/Date+.swift b/TnT/Projects/Domain/Sources/Policy/Extension/Date+.swift similarity index 100% rename from TnT/Projects/Domain/Sources/Extension/Date+.swift rename to TnT/Projects/Domain/Sources/Policy/Extension/Date+.swift diff --git a/TnT/Projects/Domain/Sources/Extension/String+.swift b/TnT/Projects/Domain/Sources/Policy/Extension/String+.swift similarity index 100% rename from TnT/Projects/Domain/Sources/Extension/String+.swift rename to TnT/Projects/Domain/Sources/Policy/Extension/String+.swift diff --git a/TnT/Projects/Presentation/Sources/MyPage/Trainer/TrainerManagementView.swift b/TnT/Projects/Presentation/Sources/MyPage/Trainer/TrainerManagementView.swift index fa5a0576..3ab2aeb2 100644 --- a/TnT/Projects/Presentation/Sources/MyPage/Trainer/TrainerManagementView.swift +++ b/TnT/Projects/Presentation/Sources/MyPage/Trainer/TrainerManagementView.swift @@ -11,97 +11,6 @@ import ComposableArchitecture import DesignSystem -/* - @Reducer - public struct TrainerMypageFeature { - - @ObservableState - public struct State: Equatable { - /// 사용자 이름 - var userName: String - /// 사용자 이미지 URL - var userImageUrl: String? - /// 관리 중인 회원 - var studentCount: Int - /// 함께 했던 회원 - var oldStudentCount: Int - /// 앱 푸시 알림 허용 여부 - var appPushNotificationAllowed: Bool - /// 버전 정보 - var versionInfo: String - /// 팝업 - var view_popUp: PopUp? - /// 팝업 표시 유무 - var view_isPopUpPresented: Bool = false - - public init( - userName: String = "", - userImageUrl: String? = nil, - studentCount: Int = 0, - oldStudentCount: Int = 0, - appPushNotificationAllowed: Bool = false, - versionInfo: String = "", - view_popUp: PopUp? = nil, - view_isPopUpPresented: Bool = false - ) { - self.userName = userName - self.userImageUrl = userImageUrl - self.studentCount = studentCount - self.oldStudentCount = oldStudentCount - self.appPushNotificationAllowed = appPushNotificationAllowed - self.versionInfo = versionInfo - self.view_popUp = view_popUp - self.view_isPopUpPresented = view_isPopUpPresented - } - } - - @Dependency(\.userUseCase) private var userUseCase: UserUseCase - - public enum Action: Sendable, ViewAction { - /// 뷰에서 발생한 액션을 처리합니다. - case view(View) - /// 네비게이션 여부 설정 - case setNavigating - - @CasePathable - public enum View: Sendable, BindableAction { - /// 바인딩할 액션을 처리 (알람) - case binding(BindingAction) - /// 서비스 이용약관 버튼 탭 - case tapTOSButton - /// 개인정보 처리방침 버튼 탭 - case tapPrivacyPolicyButton - /// 오픈소스 라이선스 버튼 탭 - case tapOpenSourceLicenseButton - /// 로그아웃 버튼 탭 - case tapLogoutButton - /// 계정 탈퇴 버튼 탭 - case tapWithdrawButton - /// 팝업 왼쪽 탭 - case tapPupUpSecondaryButton(popUp: PopUp?) - /// 팝옵 오른쪽 탭 - case tapPopUpPrimaryButton(popUp: PopUp?) - } - } - - public init() { } - - public var body: some ReducerOf { - BindingReducer(action: \.view) - - Reduce { state, action in - switch action { - case .view(let action): - */ - -@Reducer -struct TrainerManagementFeature { - @ObservableState - struct State { - - } -} - struct TrainerManagementView: View { var body: some View { VStack(spacing: 0) { @@ -110,29 +19,6 @@ struct TrainerManagementView: View { pointText: "0", rightButton: "회원 초대하기") ) - - VStack(spacing: 12) { - HStack { - ProfileImageView(imageURL: "") - - VStack(spacing: 12) { - Text("") - .typographyStyle(.body1Bold, with: Color.neutral900) - Text("") - .typographyStyle(.label2Medium, with: Color.neutral500) - } - } - - VStack(spacing: 5) { - Text("메모") - .typographyStyle(.label2Bold, with: Color.neutral600) - Text("") - .typographyStyle(.label2Medium, with: Color.neutral500) - } - } - .padding(12) - .background(Color.white) - .clipShape(RoundedRectangle(cornerRadius: 12)) } } @@ -156,6 +42,37 @@ struct TrainerManagementView: View { Spacer() } } + + @ViewBuilder + func ListCellView() -> some View { + VStack(spacing: 12) { + HStack { + HStack { + ProfileImageView(imageURL: "") + + VStack(spacing: 12) { + Text("") + .typographyStyle(.body1Bold, with: Color.neutral900) + Text("") + .typographyStyle(.label2Medium, with: Color.neutral500) + } + } + + Spacer() + TChip(leadingEmoji: "💪", title: "", style: .blue) + } + + VStack(spacing: 5) { + Text("메모") + .typographyStyle(.label2Bold, with: Color.neutral600) + Text("") + .typographyStyle(.label2Medium, with: Color.neutral500) + } + } + .padding(12) + .background(Color.white) + .clipShape(RoundedRectangle(cornerRadius: 12)) + } } extension TrainerManagementView { diff --git a/TnT/Projects/Presentation/Sources/MyPage/Trainer/TrainerManagmentFeature.swift b/TnT/Projects/Presentation/Sources/MyPage/Trainer/TrainerManagmentFeature.swift new file mode 100644 index 00000000..4778c084 --- /dev/null +++ b/TnT/Projects/Presentation/Sources/MyPage/Trainer/TrainerManagmentFeature.swift @@ -0,0 +1,47 @@ +// +// TrainerManagmentFeature.swift +// Presentation +// +// Created by 박서연 on 2/9/25. +// Copyright © 2025 yapp25thTeamTnT. All rights reserved. +// + +import ComposableArchitecture + +import Domain + +@Reducer +struct TrainerManagementFeature { + @ObservableState + struct State { + var memberList: GetMembersListEntity + } + + @Dependency(\.trainerRepoUseCase) private var trainerRepoUseCase: TrainerRepository + + public enum Action: Sendable, ViewAction { + /// 뷰에서 발생한 에러를 처리합니다. + case view(View) + /// 네비게이션 여부 설정 + case setNavigating + + @CasePathable + public enum View: Sendable { + case getMembersList + } + } + + public init() { } + + public var body: some ReducerOf { + Reduce { state, action in + switch action { + case .setNavigating: + return .none + case .view(.getMembersList): + return .none + } + } + } +} + From eaa38481f076456abb478ff9c9c2f4ca97c18007 Mon Sep 17 00:00:00 2001 From: Park Seo Yeon Date: Mon, 10 Feb 2025 23:11:12 +0900 Subject: [PATCH 3/3] =?UTF-8?q?[Refactor]=20TrainerUseCase=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TnT/Projects/DIContainer/Sources/DIContainer.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TnT/Projects/DIContainer/Sources/DIContainer.swift b/TnT/Projects/DIContainer/Sources/DIContainer.swift index 3ea94209..de10e23d 100644 --- a/TnT/Projects/DIContainer/Sources/DIContainer.swift +++ b/TnT/Projects/DIContainer/Sources/DIContainer.swift @@ -30,7 +30,7 @@ private enum SocialUseCaseKey: DependencyKey { static let liveValue: SocialLoginUseCase = SocialLoginUseCase(socialLoginRepository: SocialLogInRepositoryImpl(loginManager: SNSLoginManager())) } -private enum TrainerUseCaseKey: DependencyKey { +private enum TrainerUseCaseRepoKey: DependencyKey { static let liveValue: TrainerRepository = DefaultTrainerUseCase(trainerRepository: TrainerRepositoryImpl()) } @@ -57,7 +57,7 @@ public extension DependencyValues { } var trainerRepoUseCase: TrainerRepository { - get { self[TrainerUseCaseKey.self] } - set { self[TrainerUseCaseKey.self] = newValue } + get { self[TrainerUseCaseRepoKey.self] } + set { self[TrainerUseCaseRepoKey.self] = newValue } } }