Skip to content

Commit 0a87542

Browse files
committed
[Feat] TraineeHomeFeature ์ž‘์„ฑ
1 parent 538f8a3 commit 0a87542

File tree

5 files changed

+174
-3
lines changed

5 files changed

+174
-3
lines changed

โ€ŽTnT/Projects/Domain/Sources/Entity/RecordListItemEntity.swiftโ€Ž

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import Foundation
1010

1111
/// ํŠธ๋ ˆ์ด๋‹ˆ ๊ธฐ๋ก ๋ชฉ๋ก ์•„์ดํ…œ ๋ชจ๋ธ
12-
public struct RecordListItemEntity {
12+
public struct RecordListItemEntity: Equatable {
13+
/// ๊ธฐ๋ก id
14+
public let id: Int
1315
/// ๊ธฐ๋ก ํƒ€์ž…
1416
public let type: RecordType
1517
/// ๊ธฐ๋ก ์‹œ๊ฐ„
@@ -22,12 +24,14 @@ public struct RecordListItemEntity {
2224
public let imageUrl: String?
2325

2426
public init(
27+
id: Int,
2528
type: RecordType,
2629
date: Date,
2730
title: String,
2831
hasFeedBack: Bool,
2932
imageUrl: String?
3033
) {
34+
self.id = id
3135
self.type = type
3236
self.date = date
3337
self.title = title

โ€ŽTnT/Projects/Domain/Sources/Entity/RecordType.swiftโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//
88

99
/// ์•ฑ์—์„œ ์กด์žฌํ•˜๋Š” ๊ธฐ๋ก ์œ ํ˜•์„ ์ •์˜ํ•œ ์—ด๊ฑฐํ˜•
10-
public enum RecordType: Sendable {
10+
public enum RecordType: Sendable, Equatable {
1111
/// nํšŒ์ฐจ ์ˆ˜์—…
1212
case session(count: Int)
1313
/// ์šด๋™

โ€ŽTnT/Projects/Domain/Sources/Entity/WorkoutListItemEntity.swiftโ€Ž

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import Foundation
1010

1111
/// ํŠธ๋ ˆ์ด๋‹ˆ PT ์šด๋™ ๋ชฉ๋ก ์•„์ดํ…œ ๋ชจ๋ธ
12-
public struct WorkoutListItemEntity {
12+
public struct WorkoutListItemEntity: Equatable {
13+
/// ์ˆ˜์—… Id
14+
public let id: Int
1315
/// ํ˜„์žฌ ์ˆ˜์—… ์ฐจ์ˆ˜
1416
public let currentCount: Int
1517
/// ์ˆ˜์—… ์‹œ์ž‘ ์‹œ๊ฐ„
@@ -24,13 +26,15 @@ public struct WorkoutListItemEntity {
2426
public let hasRecord: Bool
2527

2628
public init(
29+
id: Int,
2730
currentCount: Int,
2831
startDate: Date,
2932
endDate: Date,
3033
trainerProfileImageUrl: String?,
3134
trainerName: String,
3235
hasRecord: Bool
3336
) {
37+
self.id = id
3438
self.currentCount = currentCount
3539
self.startDate = startDate
3640
self.endDate = endDate
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// CGFloat+.swift
3+
// Presentation
4+
//
5+
// Created by ๋ฐ•๋ฏผ์„œ on 2/3/25.
6+
// Copyright ยฉ 2025 yapp25thTeamTnT. All rights reserved.
7+
//
8+
9+
import SwiftUI
10+
11+
public extension CGFloat {
12+
/// ์ƒ๋‹จ safeArea
13+
static var safeAreaTop: CGFloat {
14+
guard let window = UIApplication.shared.connectedScenes
15+
.compactMap({ ($0 as? UIWindowScene)?.keyWindow })
16+
.first else { return 44 }
17+
18+
let topInset = window.safeAreaInsets.top
19+
return topInset > 0 ? topInset : 0
20+
}
21+
22+
/// ํ•˜๋‹จ safeArea
23+
static var safeAreaBottom: CGFloat {
24+
guard let window = UIApplication.shared.connectedScenes
25+
.compactMap({ ($0 as? UIWindowScene)?.keyWindow })
26+
.first else { return 34 }
27+
28+
let bottomInset = window.safeAreaInsets.bottom
29+
return bottomInset > 0 ? bottomInset : 34
30+
}
31+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
//
2+
// TraineeHomeFeature.swift
3+
// Presentation
4+
//
5+
// Created by ๋ฐ•๋ฏผ์„œ on 2/2/25.
6+
// Copyright ยฉ 2025 yapp25thTeamTnT. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import ComposableArchitecture
11+
12+
import Domain
13+
14+
@Reducer
15+
public struct TraineeHomeFeature {
16+
17+
@ObservableState
18+
public struct State: Equatable {
19+
// MARK: Data related state
20+
/// ์„ ํƒ๋œ ๋‚ ์งœ
21+
var selectedDate: Date
22+
/// ์บ˜๋ฆฐ๋” ์ด๋ฒคํŠธ
23+
var events: [Date: Int]
24+
/// ์ˆ˜์—… ์ •๋ณด
25+
var sessionInfo: WorkoutListItemEntity?
26+
/// ๊ธฐ๋ก ์ •๋ณด ๋ชฉ๋ก
27+
var records: [RecordListItemEntity]
28+
29+
// MARK: UI related state
30+
/// ์บ˜๋ฆฐ๋” ํ‘œ์‹œ ํŽ˜์ด์ง€
31+
var view_currentPage: Date
32+
/// ์ˆ˜์—… ์นด๋“œ ์‹œ๊ฐ„ ํ‘œ์‹œ
33+
var view_sessionCardTimeString: String {
34+
guard let sessionInfo else { return "" }
35+
return "\(TDateFormatUtility.formatter(for: .a_HHmm).string(from: sessionInfo.startDate)) ~ \(TDateFormatUtility.formatter(for: .a_HHmm).string(from: sessionInfo.endDate))"
36+
}
37+
/// ๊ธฐ๋ก ์ œ๋ชฉ ํ‘œ์‹œ
38+
var view_recordTitleString: String {
39+
return TDateFormatUtility.formatter(for: .MM์›”_dd์ผ_EEEE).string(from: selectedDate)
40+
}
41+
/// ์„ ํƒ ๋ฐ”ํ…€ ์‹œํŠธ ํ‘œ์‹œ
42+
var view_isBottomSheetPresented: Bool
43+
44+
public init(
45+
selectedDate: Date = .now,
46+
events: [Date: Int] = [:],
47+
sessionInfo: WorkoutListItemEntity? = nil,
48+
records: [RecordListItemEntity] = [],
49+
view_currentPage: Date = .now,
50+
view_isBottomSheetPresented: Bool = false
51+
) {
52+
self.selectedDate = selectedDate
53+
self.events = events
54+
self.sessionInfo = sessionInfo
55+
self.records = records
56+
self.view_currentPage = view_currentPage
57+
self.view_isBottomSheetPresented = view_isBottomSheetPresented
58+
}
59+
}
60+
61+
@Dependency(\.traineeUseCase) private var traineeUseCase: TraineeUseCase
62+
63+
public enum Action: Sendable, ViewAction {
64+
/// ๋ทฐ์—์„œ ๋ฐœ์ƒํ•œ ์•ก์…˜์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
65+
case view(View)
66+
/// ๋„ค๋น„๊ฒŒ์ด์…˜ ์—ฌ๋ถ€ ์„ค์ •
67+
case setNavigating
68+
69+
@CasePathable
70+
public enum View: Sendable, BindableAction {
71+
/// ๋ฐ”์ธ๋”ฉํ•  ์•ก์…˜์„ ์ฒ˜๋ฆฌ
72+
case binding(BindingAction<State>)
73+
/// ์šฐ์ธก ์ƒ๋‹จ ์•Œ๋ฆผ ํŽ˜์ด์ง€ ๋ณด๊ธฐ ๋ฒ„ํŠผ ํƒญ
74+
case tapAlarmPageButton
75+
/// ์ƒ๋‹จ ์ˆ˜์—… ๊ธฐ๋ก ๋ณด๊ธฐ ๋ฒ„ํŠผ ํƒญ
76+
case tapShowSessionRecordButton(id: Int)
77+
/// ๊ธฐ๋ก ๋ชฉ๋ก ํ”ผ๋“œ๋ฐฑ ๋ณด๊ธฐ ๋ฒ„ํŠผ ํƒญ
78+
case tapShowRecordFeedbackButton(id: Int)
79+
/// ์šฐ์ธก ํ•˜๋‹จ ๊ธฐ๋ก ์ถ”๊ฐ€ ๋ฒ„ํŠผ ํƒญ
80+
case tapAddRecordButton
81+
/// ๊ฐœ์ธ ์šด๋™ ๊ธฐ๋ก ์ถ”๊ฐ€ ๋ฒ„ํŠผ ํƒญ
82+
case tapAddWorkoutRecordButton
83+
/// ์‹๋‹จ ๊ธฐ๋ก ์ถ”๊ฐ€ ๋ฒ„ํŠผ ํƒญ
84+
case tapAddMealRecordButton
85+
}
86+
}
87+
88+
public init() {}
89+
90+
public var body: some ReducerOf<Self> {
91+
BindingReducer(action: \.view)
92+
93+
Reduce { state, action in
94+
switch action {
95+
96+
case .view(let action):
97+
switch action {
98+
case .binding(\.selectedDate):
99+
print(state.events[state.selectedDate])
100+
return .none
101+
case .binding:
102+
return .none
103+
case .tapAlarmPageButton:
104+
// TODO: ๋„ค๋น„๊ฒŒ์ด์…˜ ์—ฐ๊ฒฐ ์‹œ ์ถ”๊ฐ€
105+
print("tapAlarmPageButton")
106+
return .none
107+
case .tapShowSessionRecordButton(let id):
108+
// TODO: ๋„ค๋น„๊ฒŒ์ด์…˜ ์—ฐ๊ฒฐ ์‹œ ์ถ”๊ฐ€
109+
print("tapShowSessionRecordButton \(id)")
110+
return .none
111+
case .tapShowRecordFeedbackButton(let id):
112+
// TODO: ๋„ค๋น„๊ฒŒ์ด์…˜ ์—ฐ๊ฒฐ ์‹œ ์ถ”๊ฐ€
113+
print("tapShowRecordFeedbackButton \(id)")
114+
return .none
115+
case .tapAddRecordButton:
116+
state.view_isBottomSheetPresented = true
117+
return .none
118+
case .tapAddWorkoutRecordButton:
119+
// TODO: ๋„ค๋น„๊ฒŒ์ด์…˜ ์—ฐ๊ฒฐ ์‹œ ์ถ”๊ฐ€
120+
print("tapAddWorkoutRecordButton")
121+
return .none
122+
case .tapAddMealRecordButton:
123+
// TODO: ๋„ค๋น„๊ฒŒ์ด์…˜ ์—ฐ๊ฒฐ ์‹œ ์ถ”๊ฐ€
124+
print("tapAddMealRecordButton")
125+
return .none
126+
}
127+
case .setNavigating:
128+
return .none
129+
}
130+
}
131+
}
132+
}

0 commit comments

Comments
ย (0)