Skip to content

Commit

Permalink
Merge pull request #82 from YAPP-Github/TNT-232-myPage
Browse files Browse the repository at this point in the history
[TNT-232] ํŠธ๋ ˆ์ด๋‹ˆ, ํŠธ๋ ˆ์ด๋„ˆ ๋งˆ์ดํŽ˜์ด์ง€ + ์•ฑ ๋‚ด ํŠธ๋ ˆ์ด๋„ˆ/ํŠธ๋ ˆ์ด๋‹ˆ ์—ฐ๊ฒฐ ์—ฌ๋ถ€ ๋ฐ˜์˜
  • Loading branch information
FpRaArNkK authored Feb 12, 2025
2 parents 3ea855f + 519f767 commit 4958478
Show file tree
Hide file tree
Showing 15 changed files with 224 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,9 @@ public struct UserRepositoryImpl: UserRepository {
public func postWithdrawal() async throws -> PostWithdrawalResDTO {
return try await networkService.request(UserTargetType.postWithdrawal, decodingType: PostWithdrawalResDTO.self)
}

/// ๋งˆ์ดํŽ˜์ด์ง€ ์š”์ฒญ์„ ์ˆ˜ํ–‰
public func getMyPageInfo() async throws -> GetMyPageInfoResDTO {
return try await networkService.request(UserTargetType.getMyPageInfo, decodingType: GetMyPageInfoResDTO.self)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public enum UserTargetType {
case postLogout
/// ํšŒ์› ํƒˆํ‡ด ์š”์ฒญ
case postWithdrawal
/// ๋งˆ์ดํŽ˜์ด์ง€ ์ •๋ณด ์š”์ฒญ
case getMyPageInfo
}

extension UserTargetType: TargetType {
Expand All @@ -45,12 +47,15 @@ extension UserTargetType: TargetType {

case .postWithdrawal:
return "/members/withdraw"

case .getMyPageInfo:
return "/members"
}
}

var method: HTTPMethod {
switch self {
case .getSessionCheck:
case .getSessionCheck, .getMyPageInfo:
return .get

case .postSocialLogin, .postSignUp, .postLogout, .postWithdrawal:
Expand All @@ -60,7 +65,7 @@ extension UserTargetType: TargetType {

var task: RequestTask {
switch self {
case .getSessionCheck, .postLogout, .postWithdrawal:
case .getSessionCheck, .postLogout, .postWithdrawal, .getMyPageInfo:
return .requestPlain

case .postSocialLogin(let reqDto):
Expand All @@ -80,7 +85,7 @@ extension UserTargetType: TargetType {

var headers: [String: String]? {
switch self {
case .getSessionCheck, .postLogout, .postWithdrawal:
case .getSessionCheck, .postLogout, .postWithdrawal, .getMyPageInfo:
return nil

case .postSocialLogin:
Expand All @@ -96,7 +101,7 @@ extension UserTargetType: TargetType {

var interceptors: [any Interceptor] {
switch self {
case .getSessionCheck, .postLogout, .postWithdrawal:
case .getSessionCheck, .postLogout, .postWithdrawal, .getMyPageInfo:
return [
LoggingInterceptor(),
AuthTokenInterceptor(),
Expand Down
47 changes: 47 additions & 0 deletions TnT/Projects/Domain/Sources/DTO/User/UserResponseDTO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import Foundation

/// ๋กœ๊ทธ์ธ ์„ธ์…˜ ์œ ํšจ ํ™•์ธ ์‘๋‹ต DTO
public struct GetSessionCheckResDTO: Decodable {
/// ํŠธ๋ ˆ์ด๋„ˆ/ํŠธ๋ ˆ์ด๋‹ˆ ์—ฐ๊ฒฐ ์—ฌ๋ถ€
public let isConnected: Bool
/// ๋ฉค๋ฒ„ ์œ ํ˜•
public let memberType: MemberTypeResDTO
}

Expand Down Expand Up @@ -104,6 +107,50 @@ public struct PostLogoutResDTO: Decodable {
/// ํšŒ์›ํƒˆํ‡ด ์‘๋‹ต DTO
public typealias PostWithdrawalResDTO = EmptyResponse

/// ๋งˆ์ดํŽ˜์ด์ง€ ์ •๋ณด ์‘๋‹ต DTO
public struct GetMyPageInfoResDTO: Decodable {
/// ํšŒ์› ์ด๋ฆ„
public let name: String
/// ์ด๋ฉ”์ผ
public let email: String
/// ํ”„๋กœํ•„ ์‚ฌ์ง„ URL
public let profileImageUrl: String
/// ํšŒ์› ํƒ€์ž…
public let memberType: MemberTypeResDTO
/// ์†Œ์…œ ํƒ€์ž…
public let socialType: String
/// ํŠธ๋ ˆ์ด๋„ˆ DTO
public let trainer: TrainerInfoResDTO?
/// ํŠธ๋ ˆ์ด๋‹ˆ DTO
public let trainee: TraineeInfoResDTO?
}

/// ํŠธ๋ ˆ์ด๋„ˆ ์ •๋ณด ํ‘œ์‹œ์— ์‚ฌ์šฉ๋˜๋Š” TrainerInfoDTO
public struct TrainerInfoResDTO: Decodable {
/// ๊ด€๋ฆฌ ์ค‘์ธ ํšŒ์›
public let activeTraineeCount: Int?
/// ํ•จ๊ป˜ํ–ˆ๋˜ ํšŒ์›
public let totalTraineeCount: Int?
}

/// ํŠธ๋ ˆ์ด๋‹ˆ ์ •๋ณด ํ‘œ์‹œ์— ์‚ฌ์šฉ๋˜๋Š” TraineeInfoDTO
public struct TraineeInfoResDTO: Decodable {
/// ํŠธ๋ ˆ์ด๋„ˆ ์—ฐ๊ฒฐ ์—ฌ๋ถ€
public let isConnected: Bool
/// ์ƒ๋…„์›”์ผ
public let birthday: String?
/// ๋‚˜์ด
public let age: Int?
/// ์ง„ํ–‰ํ•œ PT ํšŸ์ˆ˜
public let height: Double?
/// ์ด PT ํšŸ์ˆ˜
public let weight: Double?
/// ์ฃผ์˜์‚ฌํ•ญ
public let cautionNote: String?
/// PT ๋ชฉํ‘œ
public let ptGoals: [String]
}

public extension PostSignUpResDTO {
func toEntity() -> PostSignUpResEntity {
return .init(
Expand Down
33 changes: 33 additions & 0 deletions TnT/Projects/Domain/Sources/Entity/MyPageEntity.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// MyPageEntity.swift
// Domain
//
// Created by ๋ฐ•๋ฏผ์„œ on 2/12/25.
// Copyright ยฉ 2025 yapp25thTeamTnT. All rights reserved.
//

import Foundation

public struct TraineeMyPageEntity: Equatable, Sendable {
/// ํŠธ๋ ˆ์ด๋‹ˆ ์—ฐ๊ฒฐ ์—ฌ๋ถ€
public let isConnected: Bool
/// ํŠธ๋ ˆ์ด๋‹ˆ ์ด๋ฆ„
public let name: String
/// ํŠธ๋ ˆ์ด๋‹ˆ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL
public let profileImageUrl: String
/// ์†Œ์…œ ํƒ€์ž…
public let socialType: String
}

public struct TrainerMyPageEntity: Equatable, Sendable {
/// ํŠธ๋ ˆ์ด๋„ˆ ์ด๋ฆ„
public let name: String
/// ํŠธ๋ ˆ์ด๋„ˆ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL
public let profileImageUrl: String
/// ์†Œ์…œ ํƒ€์ž…
public let socialType: String
/// ๊ด€๋ฆฌ ์ค‘์ธ ํšŒ์› ์ˆ˜
public let activeTraineeCount: Int?
/// ํ•จ๊ป˜ํ–ˆ๋˜ ํšŒ์› ์ˆ˜
public let totalTraineeCount: Int?
}
30 changes: 30 additions & 0 deletions TnT/Projects/Domain/Sources/Mapper/UserMapper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// UserMapper.swift
// Domain
//
// Created by ๋ฐ•๋ฏผ์„œ on 2/12/25.
// Copyright ยฉ 2025 yapp25thTeamTnT. All rights reserved.
//

import Foundation

public extension GetMyPageInfoResDTO {
func toEntity() -> TraineeMyPageEntity {
return .init(
isConnected: self.trainee?.isConnected ?? false,
name: self.name,
profileImageUrl: self.profileImageUrl,
socialType: self.socialType
)
}

func toEntity() -> TrainerMyPageEntity {
return .init(
name: self.name,
profileImageUrl: self.profileImageUrl,
socialType: self.socialType,
activeTraineeCount: self.trainer?.activeTraineeCount,
totalTraineeCount: self.trainer?.totalTraineeCount
)
}
}
1 change: 1 addition & 0 deletions TnT/Projects/Domain/Sources/Policy/AppStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ import Foundation

public enum AppStorage {
public static let hideHomePopupUntil: String = "hideHomePopupUntil"
public static let isConnected: String = "isConnected"
}
5 changes: 5 additions & 0 deletions TnT/Projects/Domain/Sources/Repository/UserRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,9 @@ public protocol UserRepository {
/// - Returns: ํšŒ์› ํƒˆํ‡ด ์™„๋ฃŒ ์‹œ ์‘๋‹ต DTO (`PostWithdrawalResDTO`)
/// - Throws: ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ๋˜๋Š” ์„œ๋ฒ„์—์„œ ๋ฐ˜ํ™˜ํ•œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Œ
func postWithdrawal() async throws -> PostWithdrawalResDTO

/// ๋งˆ์ดํŽ˜์ด์ง€ ์ •๋ณด ์š”์ฒญ
/// - Returns: ๋งˆ์ดํŽ˜์ด์ง€ ํ‘œ์‹œ์— ํ•„์š”ํ•œ ์‘๋‹ต DTO (`GetMyPageInfoResDTO`)
/// - Throws: ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ๋˜๋Š” ์„œ๋ฒ„์—์„œ ๋ฐ˜ํ™˜ํ•œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Œ
func getMyPageInfo() async throws -> GetMyPageInfoResDTO
}
8 changes: 6 additions & 2 deletions TnT/Projects/Domain/Sources/UseCase/UserUseCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public protocol UserUseCase {
}

// MARK: - Default ๊ตฌํ˜„์ฒด
public struct DefaultUserUseCase: UserRepository, UserUseCase {
public struct DefaultUserUseCase: UserUseCase {

public let userRepostiory: UserRepository

Expand Down Expand Up @@ -67,7 +67,7 @@ public struct DefaultUserUseCase: UserRepository, UserUseCase {
}

// MARK: - Repository
extension DefaultUserUseCase {
extension DefaultUserUseCase: UserRepository {
public func getSessionCheck() async throws -> GetSessionCheckResDTO {
return try await userRepostiory.getSessionCheck()
}
Expand All @@ -87,4 +87,8 @@ extension DefaultUserUseCase {
public func postWithdrawal() async throws -> PostWithdrawalResDTO {
return try await userRepostiory.postWithdrawal()
}

public func getMyPageInfo() async throws -> GetMyPageInfoResDTO {
return try await userRepostiory.getMyPageInfo()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ public struct AppFlowCoordinatorFeature {
@ObservableState
public struct State: Equatable {
// MARK: Data related state
/// ํŠธ๋ ˆ์ด๋„ˆ/ํŠธ๋ ˆ์ด๋‹ˆ ์—ฐ๊ฒฐ ์—ฌ๋ถ€
@Shared(.appStorage(AppStorage.isConnected)) var isConnected: Bool = false
/// ์œ ์ € ๋ฉค๋ฒ„ ์œ ํ˜•
var userType: UserType?
// MARK: UI related state
/// ์Šคํ”Œ๋ž˜์‹œ ํ‘œ์‹œ ์—ฌ๋ถ€
var view_isSplashActive: Bool
/// ํŒ์—… ํ‘œ์‹œ ์—ฌ๋ถ€
var view_isPopUpPresented: Bool

// MARK: SubFeature state
Expand Down Expand Up @@ -59,7 +64,7 @@ public struct AppFlowCoordinatorFeature {
/// ์ €์žฅ ์„ธ์…˜ ์ •๋ณด ํ™•์ธ
case checkSessionInfo
/// ํ˜„์žฌ ์œ ์ € ์ •๋ณด ์—…๋ฐ์ดํŠธ
case updateUserInfo(UserType?)
case updateUserInfo(type: UserType?, isConnected: Bool)
/// ์Šคํ”Œ๋ž˜์‹œ ํ‘œ์‹œ ์ข…๋ฃŒ ์‹œ
case splashFinished
/// ์„ธ์…˜ ๋งŒ๋ฃŒ ํŒ์—… ํ‘œ์‹œ
Expand Down Expand Up @@ -139,15 +144,20 @@ public struct AppFlowCoordinatorFeature {
switch action {
case .checkSession:
return .run { send in
let result = try? await userUseCaseRepo.getSessionCheck()
switch result?.memberType {
guard let result = try? await userUseCaseRepo.getSessionCheck() else {
try keyChainManager.delete(.sessionId)
await send(.updateUserInfo(type: nil, isConnected: false))
return
}

switch result.memberType {
case .trainer:
await send(.updateUserInfo(.trainer))
await send(.updateUserInfo(type: .trainer, isConnected: result.isConnected))
case .trainee:
await send(.updateUserInfo(.trainee))
await send(.updateUserInfo(type: .trainee, isConnected: result.isConnected))
default:
try keyChainManager.delete(.sessionId)
await send(.updateUserInfo(nil))
await send(.updateUserInfo(type: nil, isConnected: false))
}
}
}
Expand All @@ -156,9 +166,11 @@ public struct AppFlowCoordinatorFeature {
let session: String? = try? keyChainManager.read(for: .sessionId)
return session != nil
? .send(.api(.checkSession))
: .send(.updateUserInfo(nil))
: .send(.updateUserInfo(type: nil, isConnected: false))

case let .updateUserInfo(userType, isConnected):
state.$isConnected.withLock { $0 = isConnected }

case .updateUserInfo(let userType):
switch userType {
case .trainee:
return self.setFlow(.traineeMainFlow, state: &state)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ public struct TraineeMainFlowFeature {
)
return .none

/// ์—ฐ๊ฒฐ ์™„๋ฃŒ ํ™”๋ฉด -> ํ™ˆ์œผ๋กœ ์ด๋™
case .element(id: _, action: .traineeConnectionComplete(.setNavigating)):
state.path.removeLast(2)
return .none

default:
return .none
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,16 @@ public struct TrainerMainFlowFeature {
state.path.removeLast()
return .none

/// ์—ฐ๊ฒฐ ์™„๋ฃŒ -> ํŠธ๋ ˆ์ด๋‹ˆ ์ •๋ณด
case .element(id: _, action: .connectionComplete(.setNavigating(let profile))):
state.path.append(.connectedTraineeProfile(.init(traineeProfile: profile)))
return .none

/// ํŠธ๋ ˆ์ด๋‹ˆ ์ •๋ณด -> ํ™ˆ์œผ๋กœ
case .element(id: _, action: .connectedTraineeProfile(.setNavigating)):
state.path.removeLast(2)
return.none

/// ํŠธ๋ ˆ์ด๋„ˆ ์ˆ˜์—… ์ถ”๊ฐ€ -> ํ™ˆ์œผ๋กœ
case .element(id: _, action: .addPTSession(.setNavigating)):
state.path.removeLast()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public struct TraineeHomeFeature {
// MARK: Data related state
/// 3์ผ ๋™์•ˆ ๋ณด์ง€ ์•Š๊ธฐ ์‹œ์ž‘ ๋‚ ์งœ
@Shared(.appStorage(AppStorage.hideHomePopupUntil)) var hidePopupUntil: Date?
/// ํŠธ๋ ˆ์ด๋„ˆ ์—ฐ๊ฒฐ ์—ฌ๋ถ€
@Shared(.appStorage(AppStorage.isConnected)) var isConnected: Bool = false
/// ์„ ํƒ๋œ ๋‚ ์งœ
var selectedDate: Date
/// ์บ˜๋ฆฐ๋” ์ด๋ฒคํŠธ
Expand All @@ -29,8 +31,6 @@ public struct TraineeHomeFeature {
var records: [RecordListItemEntity]
/// 3์ผ ๋™์•ˆ ๋ณด์ง€ ์•Š๊ธฐ ์„ ํƒ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€
var isHideUntilSelected: Bool
/// ํŠธ๋ ˆ์ด๋„ˆ ์—ฐ๊ฒฐ ์—ฌ๋ถ€
var isConnected: Bool

// MARK: UI related state
/// ์บ˜๋ฆฐ๋” ํ‘œ์‹œ ํŽ˜์ด์ง€
Expand All @@ -55,7 +55,6 @@ public struct TraineeHomeFeature {
sessionInfo: WorkoutListItemEntity? = nil,
records: [RecordListItemEntity] = [],
isHideUntilSelected: Bool = false,
isConnected: Bool = false,
view_currentPage: Date = .now,
view_isBottomSheetPresented: Bool = false,
view_isPopUpPresented: Bool = false
Expand All @@ -65,7 +64,6 @@ public struct TraineeHomeFeature {
self.sessionInfo = sessionInfo
self.records = records
self.isHideUntilSelected = isHideUntilSelected
self.isConnected = isConnected
self.view_currentPage = view_currentPage
self.view_isBottomSheetPresented = view_isBottomSheetPresented
self.view_isPopUpPresented = view_isPopUpPresented
Expand Down Expand Up @@ -172,11 +170,9 @@ public struct TraineeHomeFeature {
return .send(.setNavigating(.traineeInvitationCodeInput))

case .onAppear:
if let hideUntil = state.hidePopupUntil, hideUntil > Date() {
state.view_isPopUpPresented = false
} else {
state.view_isPopUpPresented = true
}
let hideUntil = state.hidePopupUntil ?? Date()
let hidePopUp = state.isConnected || hideUntil > Date()
state.view_isPopUpPresented = !hidePopUp
return .none
}

Expand Down
Loading

0 comments on commit 4958478

Please sign in to comment.