Skip to content

Commit c0fbeff

Browse files
committed
[Feat] TrainerAddPTSession 기능 수정, 화면 수정본 반영
1 parent 7f12830 commit c0fbeff

File tree

3 files changed

+232
-159
lines changed

3 files changed

+232
-159
lines changed

TnT/Projects/DesignSystem/Sources/Components/TextField/TTextEditor.swift

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public struct TTextEditor: View {
2222
private let footer: Footer?
2323
/// Placeholder 텍스트
2424
private let placeholder: String
25+
/// 텍스트 에디터 사이즈
26+
private let size: Size
2527
/// 텍스트 필드 상태
2628
@Binding private var status: Status
2729
/// 입력된 텍스트
@@ -35,74 +37,58 @@ public struct TTextEditor: View {
3537
/// TTextEditor 생성자
3638
/// - Parameters:
3739
/// - placeholder: Placeholder 텍스트 (기본값: "내용을 입력해주세요").
40+
/// - size: 텍스트 에디터 사이즈.
3841
/// - text: 입력된 텍스트를 관리하는 바인딩.
3942
/// - textEditorStatus: 텍스트 에디터 상태를 관리하는 바인딩.
4043
/// - footer: Textfield 하단에 표시될 `TTextEditor.FooterView`를 정의하는 클로저.
4144
public init(
4245
placeholder: String = "내용을 입력해주세요",
46+
size: Size = .large,
4347
text: Binding<String>,
4448
textEditorStatus: Binding<Status>,
4549
footer: () -> Footer? = { nil }
4650
) {
4751
self.placeholder = placeholder
52+
self.size = size
4853
self._text = text
4954
self._status = textEditorStatus
5055
self.footer = footer()
5156
}
5257

5358
public var body: some View {
54-
GeometryReader { geometry in
55-
VStack(alignment: .leading, spacing: 8) {
56-
ZStack(alignment: .topLeading) {
57-
TextEditor(text: $text)
58-
.autocorrectionDisabled()
59-
.scrollDisabled(true)
60-
.focused($isFocused)
61-
.font(Typography.FontStyle.body1Medium.font)
62-
.lineSpacing(Typography.FontStyle.body1Medium.lineSpacing)
63-
.kerning(Typography.FontStyle.body1Medium.letterSpacing)
64-
.tint(Color.neutral800)
65-
.frame(minHeight: textHeight, maxHeight: .infinity)
66-
.padding(.vertical, TTextEditor.verticalPadding)
67-
.padding(.horizontal, TTextEditor.horizontalPadding)
68-
.background(Color.common0)
69-
.scrollContentBackground(.hidden)
70-
.cornerRadius(8)
71-
.overlay(
72-
RoundedRectangle(cornerRadius: 8)
73-
.stroke(status.borderColor(isFocused: isFocused), lineWidth: status.borderWidth(isFocused: isFocused))
74-
)
75-
.onChange(of: text) {
76-
withAnimation {
77-
textHeight = getNewHeight(geometry: geometry)
78-
}
79-
}
80-
.onAppear {
81-
textHeight = getNewHeight(geometry: geometry)
82-
}
83-
84-
if text.isEmpty {
85-
Text(placeholder)
86-
.typographyStyle(.body1Medium, with: .neutral400)
87-
.padding(.vertical, TTextEditor.verticalPadding + 8)
88-
.padding(.horizontal, TTextEditor.horizontalPadding + 4)
89-
}
90-
}
91-
if let footer {
92-
footer
59+
VStack(alignment: .leading, spacing: 8) {
60+
ZStack(alignment: .topLeading) {
61+
TextEditor(text: $text)
62+
.autocorrectionDisabled()
63+
.scrollDisabled(true)
64+
.focused($isFocused)
65+
.font(Typography.FontStyle.body1Medium.font)
66+
.lineSpacing(Typography.FontStyle.body1Medium.lineSpacing)
67+
.kerning(Typography.FontStyle.body1Medium.letterSpacing)
68+
.tint(Color.neutral800)
69+
.frame(minHeight: textHeight, maxHeight: .infinity)
70+
.padding(.vertical, TTextEditor.verticalPadding)
71+
.padding(.horizontal, TTextEditor.horizontalPadding)
72+
.background(Color.common0)
73+
.scrollContentBackground(.hidden)
74+
.cornerRadius(8)
75+
.overlay(
76+
RoundedRectangle(cornerRadius: 8)
77+
.stroke(status.borderColor(isFocused: isFocused), lineWidth: status.borderWidth(isFocused: isFocused))
78+
)
79+
.frame(height: size.height)
80+
81+
if text.isEmpty {
82+
Text(placeholder)
83+
.typographyStyle(.body1Medium, with: .neutral400)
84+
.padding(.vertical, TTextEditor.verticalPadding + 8)
85+
.padding(.horizontal, TTextEditor.horizontalPadding + 4)
9386
}
9487
}
88+
if let footer {
89+
footer
90+
}
9591
}
96-
.frame(height: TTextEditor.defaultHeight)
97-
}
98-
99-
private func getNewHeight(geometry: GeometryProxy) -> CGFloat {
100-
let newHeight: CGFloat = TextUtility.calculateTextHeight(
101-
boxWidth: geometry.size.width - TTextEditor.horizontalPadding * 2,
102-
text: text,
103-
style: .body1Medium
104-
) + TTextEditor.verticalPadding * 2
105-
return max(newHeight, TTextEditor.defaultHeight)
10692
}
10793
}
10894

@@ -198,4 +184,20 @@ public extension TTextEditor {
198184
}
199185
}
200186
}
187+
188+
/// TextEditor의 크기
189+
enum Size {
190+
case small
191+
case large
192+
193+
/// 높이
194+
var height: CGFloat {
195+
switch self {
196+
case .small:
197+
return 52
198+
case .large:
199+
return 130
200+
}
201+
}
202+
}
201203
}

TnT/Projects/Presentation/Sources/AddPTSession/TrainerAddPTSessionFeature.swift

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ public struct TrainerAddPTSessionFeature {
263263
let endDate = combinedDietDateTime(date: state.ptDate, time: state.endTime)?.toString(format: .ISO8601),
264264
let traineeId = state.trainee?.id
265265
else { return .none }
266-
266+
267267
return .run { send in
268268
let result = try await trainerRepoUseCase.postLesson(
269269
reqDTO: .init(
@@ -279,7 +279,7 @@ public struct TrainerAddPTSessionFeature {
279279
case .setTraineeList(let trainees):
280280
state.traineeList = trainees
281281
return .none
282-
282+
283283
case .setNavigating:
284284
return .none
285285
}
@@ -303,26 +303,29 @@ private extension TrainerAddPTSessionFeature {
303303

304304
/// 시작시간 종료시간 업데이트
305305
func updateTime(
306-
state: inout State,
307-
field: FocusField,
308-
with date: Date
306+
state: inout State,
307+
field: FocusField,
308+
with date: Date
309309
) {
310-
switch field {
311-
case .startTime:
312-
state.startTime = date
313-
state.view_startTimeStatus = .filled
314-
case .endTime:
315-
state.endTime = date
316-
state.view_endTimeStatus = .filled
317-
default:
318-
return
319-
}
320-
321-
if let start = state.startTime, let end = state.endTime,
322-
let status = self.validateTimes(startTime: start, endTime: end) {
323-
state.view_startTimeStatus = status
324-
state.view_endTimeStatus = status
325-
}
310+
switch field {
311+
case .startTime:
312+
state.startTime = date
313+
state.view_startTimeStatus = .filled
314+
// 시작 시간 선택시 종료시간 초기화
315+
state.endTime = nil
316+
state.view_endTimeStatus = .empty
317+
case .endTime:
318+
state.endTime = date
319+
state.view_endTimeStatus = .filled
320+
default:
321+
return
322+
}
323+
324+
if let start = state.startTime, let end = state.endTime,
325+
let status = self.validateTimes(startTime: start, endTime: end) {
326+
state.view_startTimeStatus = status
327+
state.view_endTimeStatus = status
328+
}
326329
}
327330

328331
/// 모든 필드의 상태를 검증하여 "다음" 버튼 활성화 여부를 결정

0 commit comments

Comments
 (0)