Skip to content

Commit 4958478

Browse files
authored
Merge pull request #82 from YAPP-Github/TNT-232-myPage
[TNT-232] ํŠธ๋ ˆ์ด๋‹ˆ, ํŠธ๋ ˆ์ด๋„ˆ ๋งˆ์ดํŽ˜์ด์ง€ + ์•ฑ ๋‚ด ํŠธ๋ ˆ์ด๋„ˆ/ํŠธ๋ ˆ์ด๋‹ˆ ์—ฐ๊ฒฐ ์—ฌ๋ถ€ ๋ฐ˜์˜
2 parents 3ea855f + 519f767 commit 4958478

File tree

15 files changed

+224
-29
lines changed

15 files changed

+224
-29
lines changed

โ€ŽTnT/Projects/Data/Sources/Network/Service/User/UserRepositoryImpl.swiftโ€Ž

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,9 @@ public struct UserRepositoryImpl: UserRepository {
5050
public func postWithdrawal() async throws -> PostWithdrawalResDTO {
5151
return try await networkService.request(UserTargetType.postWithdrawal, decodingType: PostWithdrawalResDTO.self)
5252
}
53+
54+
/// ๋งˆ์ดํŽ˜์ด์ง€ ์š”์ฒญ์„ ์ˆ˜ํ–‰
55+
public func getMyPageInfo() async throws -> GetMyPageInfoResDTO {
56+
return try await networkService.request(UserTargetType.getMyPageInfo, decodingType: GetMyPageInfoResDTO.self)
57+
}
5358
}

โ€ŽTnT/Projects/Data/Sources/Network/Service/User/UserTargetType.swiftโ€Ž

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public enum UserTargetType {
2222
case postLogout
2323
/// ํšŒ์› ํƒˆํ‡ด ์š”์ฒญ
2424
case postWithdrawal
25+
/// ๋งˆ์ดํŽ˜์ด์ง€ ์ •๋ณด ์š”์ฒญ
26+
case getMyPageInfo
2527
}
2628

2729
extension UserTargetType: TargetType {
@@ -45,12 +47,15 @@ extension UserTargetType: TargetType {
4547

4648
case .postWithdrawal:
4749
return "/members/withdraw"
50+
51+
case .getMyPageInfo:
52+
return "/members"
4853
}
4954
}
5055

5156
var method: HTTPMethod {
5257
switch self {
53-
case .getSessionCheck:
58+
case .getSessionCheck, .getMyPageInfo:
5459
return .get
5560

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

6166
var task: RequestTask {
6267
switch self {
63-
case .getSessionCheck, .postLogout, .postWithdrawal:
68+
case .getSessionCheck, .postLogout, .postWithdrawal, .getMyPageInfo:
6469
return .requestPlain
6570

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

8186
var headers: [String: String]? {
8287
switch self {
83-
case .getSessionCheck, .postLogout, .postWithdrawal:
88+
case .getSessionCheck, .postLogout, .postWithdrawal, .getMyPageInfo:
8489
return nil
8590

8691
case .postSocialLogin:
@@ -96,7 +101,7 @@ extension UserTargetType: TargetType {
96101

97102
var interceptors: [any Interceptor] {
98103
switch self {
99-
case .getSessionCheck, .postLogout, .postWithdrawal:
104+
case .getSessionCheck, .postLogout, .postWithdrawal, .getMyPageInfo:
100105
return [
101106
LoggingInterceptor(),
102107
AuthTokenInterceptor(),

โ€ŽTnT/Projects/Domain/Sources/DTO/User/UserResponseDTO.swiftโ€Ž

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import Foundation
1010

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

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

110+
/// ๋งˆ์ดํŽ˜์ด์ง€ ์ •๋ณด ์‘๋‹ต DTO
111+
public struct GetMyPageInfoResDTO: Decodable {
112+
/// ํšŒ์› ์ด๋ฆ„
113+
public let name: String
114+
/// ์ด๋ฉ”์ผ
115+
public let email: String
116+
/// ํ”„๋กœํ•„ ์‚ฌ์ง„ URL
117+
public let profileImageUrl: String
118+
/// ํšŒ์› ํƒ€์ž…
119+
public let memberType: MemberTypeResDTO
120+
/// ์†Œ์…œ ํƒ€์ž…
121+
public let socialType: String
122+
/// ํŠธ๋ ˆ์ด๋„ˆ DTO
123+
public let trainer: TrainerInfoResDTO?
124+
/// ํŠธ๋ ˆ์ด๋‹ˆ DTO
125+
public let trainee: TraineeInfoResDTO?
126+
}
127+
128+
/// ํŠธ๋ ˆ์ด๋„ˆ ์ •๋ณด ํ‘œ์‹œ์— ์‚ฌ์šฉ๋˜๋Š” TrainerInfoDTO
129+
public struct TrainerInfoResDTO: Decodable {
130+
/// ๊ด€๋ฆฌ ์ค‘์ธ ํšŒ์›
131+
public let activeTraineeCount: Int?
132+
/// ํ•จ๊ป˜ํ–ˆ๋˜ ํšŒ์›
133+
public let totalTraineeCount: Int?
134+
}
135+
136+
/// ํŠธ๋ ˆ์ด๋‹ˆ ์ •๋ณด ํ‘œ์‹œ์— ์‚ฌ์šฉ๋˜๋Š” TraineeInfoDTO
137+
public struct TraineeInfoResDTO: Decodable {
138+
/// ํŠธ๋ ˆ์ด๋„ˆ ์—ฐ๊ฒฐ ์—ฌ๋ถ€
139+
public let isConnected: Bool
140+
/// ์ƒ๋…„์›”์ผ
141+
public let birthday: String?
142+
/// ๋‚˜์ด
143+
public let age: Int?
144+
/// ์ง„ํ–‰ํ•œ PT ํšŸ์ˆ˜
145+
public let height: Double?
146+
/// ์ด PT ํšŸ์ˆ˜
147+
public let weight: Double?
148+
/// ์ฃผ์˜์‚ฌํ•ญ
149+
public let cautionNote: String?
150+
/// PT ๋ชฉํ‘œ
151+
public let ptGoals: [String]
152+
}
153+
107154
public extension PostSignUpResDTO {
108155
func toEntity() -> PostSignUpResEntity {
109156
return .init(
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//
2+
// MyPageEntity.swift
3+
// Domain
4+
//
5+
// Created by ๋ฐ•๋ฏผ์„œ on 2/12/25.
6+
// Copyright ยฉ 2025 yapp25thTeamTnT. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
public struct TraineeMyPageEntity: Equatable, Sendable {
12+
/// ํŠธ๋ ˆ์ด๋‹ˆ ์—ฐ๊ฒฐ ์—ฌ๋ถ€
13+
public let isConnected: Bool
14+
/// ํŠธ๋ ˆ์ด๋‹ˆ ์ด๋ฆ„
15+
public let name: String
16+
/// ํŠธ๋ ˆ์ด๋‹ˆ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL
17+
public let profileImageUrl: String
18+
/// ์†Œ์…œ ํƒ€์ž…
19+
public let socialType: String
20+
}
21+
22+
public struct TrainerMyPageEntity: Equatable, Sendable {
23+
/// ํŠธ๋ ˆ์ด๋„ˆ ์ด๋ฆ„
24+
public let name: String
25+
/// ํŠธ๋ ˆ์ด๋„ˆ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL
26+
public let profileImageUrl: String
27+
/// ์†Œ์…œ ํƒ€์ž…
28+
public let socialType: String
29+
/// ๊ด€๋ฆฌ ์ค‘์ธ ํšŒ์› ์ˆ˜
30+
public let activeTraineeCount: Int?
31+
/// ํ•จ๊ป˜ํ–ˆ๋˜ ํšŒ์› ์ˆ˜
32+
public let totalTraineeCount: Int?
33+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//
2+
// UserMapper.swift
3+
// Domain
4+
//
5+
// Created by ๋ฐ•๋ฏผ์„œ on 2/12/25.
6+
// Copyright ยฉ 2025 yapp25thTeamTnT. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
public extension GetMyPageInfoResDTO {
12+
func toEntity() -> TraineeMyPageEntity {
13+
return .init(
14+
isConnected: self.trainee?.isConnected ?? false,
15+
name: self.name,
16+
profileImageUrl: self.profileImageUrl,
17+
socialType: self.socialType
18+
)
19+
}
20+
21+
func toEntity() -> TrainerMyPageEntity {
22+
return .init(
23+
name: self.name,
24+
profileImageUrl: self.profileImageUrl,
25+
socialType: self.socialType,
26+
activeTraineeCount: self.trainer?.activeTraineeCount,
27+
totalTraineeCount: self.trainer?.totalTraineeCount
28+
)
29+
}
30+
}

โ€ŽTnT/Projects/Domain/Sources/Policy/AppStorage.swiftโ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ import Foundation
1010

1111
public enum AppStorage {
1212
public static let hideHomePopupUntil: String = "hideHomePopupUntil"
13+
public static let isConnected: String = "isConnected"
1314
}

โ€ŽTnT/Projects/Domain/Sources/Repository/UserRepository.swiftโ€Ž

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,9 @@ public protocol UserRepository {
3939
/// - Returns: ํšŒ์› ํƒˆํ‡ด ์™„๋ฃŒ ์‹œ ์‘๋‹ต DTO (`PostWithdrawalResDTO`)
4040
/// - Throws: ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ๋˜๋Š” ์„œ๋ฒ„์—์„œ ๋ฐ˜ํ™˜ํ•œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Œ
4141
func postWithdrawal() async throws -> PostWithdrawalResDTO
42+
43+
/// ๋งˆ์ดํŽ˜์ด์ง€ ์ •๋ณด ์š”์ฒญ
44+
/// - Returns: ๋งˆ์ดํŽ˜์ด์ง€ ํ‘œ์‹œ์— ํ•„์š”ํ•œ ์‘๋‹ต DTO (`GetMyPageInfoResDTO`)
45+
/// - Throws: ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ๋˜๋Š” ์„œ๋ฒ„์—์„œ ๋ฐ˜ํ™˜ํ•œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Œ
46+
func getMyPageInfo() async throws -> GetMyPageInfoResDTO
4247
}

โ€ŽTnT/Projects/Domain/Sources/UseCase/UserUseCase.swiftโ€Ž

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public protocol UserUseCase {
2828
}
2929

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

3333
public let userRepostiory: UserRepository
3434

@@ -67,7 +67,7 @@ public struct DefaultUserUseCase: UserRepository, UserUseCase {
6767
}
6868

6969
// MARK: - Repository
70-
extension DefaultUserUseCase {
70+
extension DefaultUserUseCase: UserRepository {
7171
public func getSessionCheck() async throws -> GetSessionCheckResDTO {
7272
return try await userRepostiory.getSessionCheck()
7373
}
@@ -87,4 +87,8 @@ extension DefaultUserUseCase {
8787
public func postWithdrawal() async throws -> PostWithdrawalResDTO {
8888
return try await userRepostiory.postWithdrawal()
8989
}
90+
91+
public func getMyPageInfo() async throws -> GetMyPageInfoResDTO {
92+
return try await userRepostiory.getMyPageInfo()
93+
}
9094
}

โ€ŽTnT/Projects/Presentation/Sources/Coordinator/AppFlow/AppFlowCoordinatorFeature.swiftโ€Ž

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,14 @@ public struct AppFlowCoordinatorFeature {
2323
@ObservableState
2424
public struct State: Equatable {
2525
// MARK: Data related state
26+
/// ํŠธ๋ ˆ์ด๋„ˆ/ํŠธ๋ ˆ์ด๋‹ˆ ์—ฐ๊ฒฐ ์—ฌ๋ถ€
27+
@Shared(.appStorage(AppStorage.isConnected)) var isConnected: Bool = false
28+
/// ์œ ์ € ๋ฉค๋ฒ„ ์œ ํ˜•
2629
var userType: UserType?
2730
// MARK: UI related state
31+
/// ์Šคํ”Œ๋ž˜์‹œ ํ‘œ์‹œ ์—ฌ๋ถ€
2832
var view_isSplashActive: Bool
33+
/// ํŒ์—… ํ‘œ์‹œ ์—ฌ๋ถ€
2934
var view_isPopUpPresented: Bool
3035

3136
// MARK: SubFeature state
@@ -59,7 +64,7 @@ public struct AppFlowCoordinatorFeature {
5964
/// ์ €์žฅ ์„ธ์…˜ ์ •๋ณด ํ™•์ธ
6065
case checkSessionInfo
6166
/// ํ˜„์žฌ ์œ ์ € ์ •๋ณด ์—…๋ฐ์ดํŠธ
62-
case updateUserInfo(UserType?)
67+
case updateUserInfo(type: UserType?, isConnected: Bool)
6368
/// ์Šคํ”Œ๋ž˜์‹œ ํ‘œ์‹œ ์ข…๋ฃŒ ์‹œ
6469
case splashFinished
6570
/// ์„ธ์…˜ ๋งŒ๋ฃŒ ํŒ์—… ํ‘œ์‹œ
@@ -139,15 +144,20 @@ public struct AppFlowCoordinatorFeature {
139144
switch action {
140145
case .checkSession:
141146
return .run { send in
142-
let result = try? await userUseCaseRepo.getSessionCheck()
143-
switch result?.memberType {
147+
guard let result = try? await userUseCaseRepo.getSessionCheck() else {
148+
try keyChainManager.delete(.sessionId)
149+
await send(.updateUserInfo(type: nil, isConnected: false))
150+
return
151+
}
152+
153+
switch result.memberType {
144154
case .trainer:
145-
await send(.updateUserInfo(.trainer))
155+
await send(.updateUserInfo(type: .trainer, isConnected: result.isConnected))
146156
case .trainee:
147-
await send(.updateUserInfo(.trainee))
157+
await send(.updateUserInfo(type: .trainee, isConnected: result.isConnected))
148158
default:
149159
try keyChainManager.delete(.sessionId)
150-
await send(.updateUserInfo(nil))
160+
await send(.updateUserInfo(type: nil, isConnected: false))
151161
}
152162
}
153163
}
@@ -156,9 +166,11 @@ public struct AppFlowCoordinatorFeature {
156166
let session: String? = try? keyChainManager.read(for: .sessionId)
157167
return session != nil
158168
? .send(.api(.checkSession))
159-
: .send(.updateUserInfo(nil))
169+
: .send(.updateUserInfo(type: nil, isConnected: false))
170+
171+
case let .updateUserInfo(userType, isConnected):
172+
state.$isConnected.withLock { $0 = isConnected }
160173

161-
case .updateUserInfo(let userType):
162174
switch userType {
163175
case .trainee:
164176
return self.setFlow(.traineeMainFlow, state: &state)

โ€ŽTnT/Projects/Presentation/Sources/Coordinator/TraineeMainFlow/TraineeMainFlowFeature.swiftโ€Ž

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ public struct TraineeMainFlowFeature {
114114
)
115115
return .none
116116

117+
/// ์—ฐ๊ฒฐ ์™„๋ฃŒ ํ™”๋ฉด -> ํ™ˆ์œผ๋กœ ์ด๋™
118+
case .element(id: _, action: .traineeConnectionComplete(.setNavigating)):
119+
state.path.removeLast(2)
120+
return .none
121+
117122
default:
118123
return .none
119124
}

0 commit comments

Comments
ย (0)