Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TNT-254] commonQA 완료 #90

Merged
merged 24 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ff13469
[Feat] 상세뷰 중 스크롤뷰 상단 Stroke 처리
FpRaArNkK Feb 14, 2025
7648a6c
[Feat] TraineeBasicInfoInput 최신 기획 반영
FpRaArNkK Feb 14, 2025
ec79d30
[Feat] TrainneTrainingPurpose 최신 기획 반영
FpRaArNkK Feb 14, 2025
893f2e1
[Feat] TrianeeInvitationCodeInput 진입시 팝업 해제
FpRaArNkK Feb 14, 2025
0733e95
[Feat] CreateProfile 제약문구 업데이트
FpRaArNkK Feb 14, 2025
590e1b4
[Fix] 포커스 전환 텍스트 필드 간 status UI 표시 수정
FpRaArNkK Feb 14, 2025
5261e34
[Fix] 초대코드 텍스트필드 distinguished 추가
FpRaArNkK Feb 14, 2025
aa97b60
[Feat] TDatePicker 기본 캘린더 추가, TraineeBasicInfoInput 화면 반영
FpRaArNkK Feb 14, 2025
80762a7
[Fix] TrainingInfoInput 날짜 수정
FpRaArNkK Feb 14, 2025
3521229
[Feat] TraineeBasicInfo 기획 수정사항 반영
FpRaArNkK Feb 14, 2025
bbb7f09
[Feat] TraineeTrainingInfoInput 기획 추가사항 반영
FpRaArNkK Feb 14, 2025
251dd57
[Feat] TraineeAddDietRecord 현재 날짜/시간 반영
FpRaArNkK Feb 14, 2025
d4e349b
[Feat] TrainerAddPTSessionView DatePicker/TimePicker 기획 반영
FpRaArNkK Feb 14, 2025
ee21d11
[Feat] AppLinks 업데이트
FpRaArNkK Feb 14, 2025
470b004
[Feat] 토스트 표시 위치 수정
FpRaArNkK Feb 14, 2025
e432954
[Feat] TermView AppLink 반영, UI 수정
FpRaArNkK Feb 14, 2025
e5e045e
[Feat] 트레이너/트레이니 연결 화면 수정 사항 반영
FpRaArNkK Feb 14, 2025
115f7b9
[Feat] Debouncer 추가
FpRaArNkK Feb 14, 2025
98065d4
[Feat] post 관련 버튼 debounce 적용
FpRaArNkK Feb 14, 2025
4e0d864
[Feat] BottomButton 탭 영역 수정, 개별 화면 버튼 disable 분기처리 추가
FpRaArNkK Feb 14, 2025
f7d8c63
[Feat] UI 사이즈 반영용 비율 Modifier 추가
FpRaArNkK Feb 14, 2025
56fcafb
[Fix] CGFloat - SafeArea 미반영 오류 수정
FpRaArNkK Feb 14, 2025
b191387
[Feat] SE, ProMax 사이즈 맞춰 화면 조정
FpRaArNkK Feb 14, 2025
4766ef8
[Fix] Coordinator popToRoot 로직 수정
FpRaArNkK Feb 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions TnT/Projects/DesignSystem/Sources/Button/TBottomButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ public struct TBottomButton: View {
}

public var body: some View {
Button(title) {
action()
Button(action: { action() }) {
Text(title)
.typographyStyle(.heading4, with: isEnable ? ButtonState.true.textColor : ButtonState.false.textColor)
.padding(.vertical, 20)
.frame(maxWidth: .infinity)
.background(isEnable ? ButtonState.true.background : ButtonState.false.background)
}
.typographyStyle(.heading4, with: isEnable ? ButtonState.true.textColor : ButtonState.false.textColor)
.padding(.vertical, 20)
.frame(maxWidth: .infinity)
.background(isEnable ? ButtonState.true.background : ButtonState.false.background)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import SwiftUI
/// - 날짜 선택할 수 있는 DatePicker View
public struct TDatePickerView: View {

/// 커스텀/시스템 캘린더 선택
private let calendarType: CalendarType
/// picker 제목
private let title: String
/// 버튼 실행 action
Expand All @@ -20,25 +22,29 @@ public struct TDatePickerView: View {
/// 선택 날짜
@State private var selectedDate: Date = .now
/// 표시 날짜
@State private var currentDate: Date = .now
@State private var currentPageDate: Date = .now

@Environment(\.dismiss) var dismiss

/// `TDatePickerView` 생성자
/// - Parameters:
/// - calendarType: 시스템 캘린더 / 커스텀 캘린더 선택 (기본값: 커스텀)
/// - selectedDate: 초기 선택 날짜 (기본값: 현재 날짜)
/// - title: DatePicker의 제목
/// - buttonAction: 날짜 선택 후 실행할 액션
public init(
calendarType: CalendarType = .custom,
selectedDate: Date = .now,
title: String,
monthFormatter: @escaping (Date) -> String,
buttonAction: @escaping (Date) -> Void
) {
self.calendarType = calendarType
self.selectedDate = selectedDate
self.title = title
self.monthFormatter = monthFormatter
self.buttonAction = buttonAction
currentPageDate = selectedDate
}

public var body: some View {
Expand All @@ -59,28 +65,59 @@ public struct TDatePickerView: View {
}
.padding(20)

Calendar(calendarType)

TButton(
title: "확인",
config: .large,
state: .default(.primary(isEnabled: true)),
action: {
buttonAction(selectedDate)
}
)
.padding(20)
}
}

@ViewBuilder
private func Calendar(_ calendarType: CalendarType) -> some View {
switch calendarType {
case .custom:
TCalendarHeader<EmptyView>(
currentPage: $currentDate,
currentPage: $currentPageDate,
formatter: monthFormatter
)
.padding(.top, 20)

TCalendarView(
selectedDate: $selectedDate,
currentPage: $currentDate,
currentPage: $currentPageDate,
mode: .compactMonth
)
.padding(.horizontal, 16)

TButton(
title: "확인",
config: .large,
state: .default(.primary(isEnabled: true)),
action: {
buttonAction(selectedDate)
case let .system(range):
Group {
if let range {
DatePicker(title, selection: $selectedDate, in: range, displayedComponents: .date)
.datePickerStyle(GraphicalDatePickerStyle())
.environment(\.locale, Locale(identifier: "ko_KR"))

} else {
DatePicker(title, selection: $selectedDate, displayedComponents: .date)
.datePickerStyle(GraphicalDatePickerStyle())
.environment(\.locale, Locale(identifier: "ko_KR"))
}
)
.padding(20)
}
.tint(.red400)
.padding(.top, 20)
.padding(.horizontal, 16)
}
}
}

public extension TDatePickerView {
enum CalendarType {
case system(in: PartialRangeThrough<Date>? = nil)
case custom
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ public struct ConnectedTraineeProfileEntity: Equatable, Sendable {
/// 나이
public let age: Int?
/// 키
public let height: Double
public let height: Double?
/// 몸무게
public let weight: Double
public let weight: Double?
/// PT 목표
public let ptGoal: String
/// 주의 사항
Expand All @@ -29,8 +29,8 @@ public struct ConnectedTraineeProfileEntity: Equatable, Sendable {
traineeName: String,
imageUrl: String,
age: Int?,
height: Double,
weight: Double,
height: Double?,
weight: Double?,
ptGoal: String,
cautionNote: String?
) {
Expand Down
6 changes: 4 additions & 2 deletions TnT/Projects/Domain/Sources/Mapper/TrainerMapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import Foundation

public extension ConnectTraineeInfoDTO {
func toEntity() -> ConnectedTraineeProfileEntity {
let height = self.height == 0 ? nil : self.height
let weight = self.weight == 0 ? nil : self.weight
return .init(
traineeName: self.traineeName,
imageUrl: self.traineeProfileImageUrl,
age: self.age,
height: self.height,
weight: self.weight,
height: height,
weight: weight,
ptGoal: self.ptGoal,
cautionNote: self.cautionNote
)
Expand Down
6 changes: 3 additions & 3 deletions TnT/Projects/Domain/Sources/Policy/AppLinks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import Foundation

public enum AppLinks {
public static let termsOfService: String = "https://yapp25thteam.com/terms"
public static let privacyPolicy: String = "https://yapp25thteam.com/privacy"
public static let openSourceLicense: String = "https://yapp25thteam.com/license"
public static let termsOfService: String = "https://www.notion.so/f1ee7a43b6d941068723163fda127699?pvs=4"
public static let privacyPolicy: String = "https://www.notion.so/775bc037dd1b4e8ba56679e51a7321e5?pvs=4"
public static let openSourceLicense: String = "https://www.notion.so/197cabde9e4b800d8e8ec6c22d343b32?pvs=4"
}
8 changes: 4 additions & 4 deletions TnT/Projects/Domain/Sources/Policy/UserPolicy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ struct UserPolicy {
isRequired: false
)

/// 키 입력 검증 (정수 3자리, 필수)
/// 키 입력 검증 (정수 3자리)
static let heightInput: PolicyInputInfo = .init(
textValidation: { TextValidator.isValidInput($0, maxLength: 3, regexPattern: #"^\d{3}$"#) },
isRequired: true
isRequired: false
)

/// 몸무게 입력 검증 (정수 3자리 + 소수점 1자리, 필수)
/// 몸무게 입력 검증 (정수 3자리 + 소수점 1자리)
/// 정수 최소 2자리 이상, 소수점 1자리까지만
static let weightInput: PolicyInputInfo = .init(
textValidation: { TextValidator.isValidInput($0, maxLength: 5, regexPattern: #"^\d{2,3}(\.\d{1})?$"#) },
isRequired: true
isRequired: false
)

/// 주의사항 최대 길이 제한 (공백 포함)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public struct TraineeAddDietRecordView: View {
),
leftAction: { send(.tapNavBackButton) }
)
TDivider(color: .neutral200)

ScrollView {
VStack(alignment: .leading, spacing: 8) {
DietPhotoSection()
Expand All @@ -57,22 +59,24 @@ public struct TraineeAddDietRecordView: View {
.onTapGesture { focusedField = nil }
.navigationBarBackButtonHidden()
.keyboardDismissOnTap()
.safeAreaInset(edge: .bottom) {
if store.view_focusField == nil {
TButton(
title: "저장",
config: .xLarge,
state: .default(.primary(isEnabled: store.view_isSubmitButtonEnabled))
) {
send(.tapSubmitButton)
}
.padding(.horizontal, 16)
.bottomFixWith {
TButton(
title: "저장",
config: .xLarge,
state: .default(.primary(isEnabled: store.view_isSubmitButtonEnabled))
) {
send(.tapSubmitButton)
}
.padding(.bottom, .safeAreaBottom)
.disabled(!store.view_isSubmitButtonEnabled)
.debounce()
.padding(.horizontal, 16)
}
.sheet(item: $store.view_bottomSheetItem) { item in
switch item {
case .datePicker(let field):
TDatePickerView(
selectedDate: store.dietDate ?? .now,
title: field.title,
monthFormatter: { TDateFormatUtility.formatter(for: .yyyy년_MM월).string(from: $0) },
buttonAction: {
Expand All @@ -82,9 +86,9 @@ public struct TraineeAddDietRecordView: View {
.autoSizingBottomSheet(presentationDragIndicator: .hidden)
case .timePicker(let field):
TTimePickerView(
selectedTime: store.dietDate ?? .now,
selectedTime: store.dietTime ?? .now,
title: field.title,
minuteStep: 10,
minuteStep: 1,
buttonAction: {
send(.tapBottomSheetSubmitButton(field, $0))
}
Expand Down Expand Up @@ -163,7 +167,7 @@ public struct TraineeAddDietRecordView: View {
@ViewBuilder
private func DietDateSection() -> some View {
TTextField(
placeholder: "2025/11/19",
placeholder: Date().toString(format: .yyyyMMddSlash),
text: Binding(get: {
store.dietDate?.toString(format: .yyyyMMddSlash) ?? ""
}, set: { _ in }),
Expand All @@ -185,7 +189,7 @@ public struct TraineeAddDietRecordView: View {
@ViewBuilder
private func DietTimeSection() -> some View {
TTextField(
placeholder: "09:00",
placeholder: Date().toString(format: .HHmm),
text: Binding(get: {
store.dietTime?.toString(format: .HHmm) ?? ""
}, set: { _ in }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public struct TrainerAddPTSessionView: View {
leftAction: { send(.tapNavBackButton) }
)
TDivider(height: 1, color: .neutral200)

ScrollView {
VStack(alignment: .leading, spacing: 0) {
Header()
Expand All @@ -62,19 +63,20 @@ public struct TrainerAddPTSessionView: View {
.padding(.bottom, .safeAreaBottom + 20)
}
}
.bottomFixWith {
TBottomButton(
title: "완료",
isEnable: store.view_isSubmitButtonEnabled
) {
send(.tapSubmitButton)
}
.padding(.bottom, .safeAreaBottom)
.disabled(!store.view_isSubmitButtonEnabled)
.debounce()
}
.onTapGesture { focusedField = nil }
.navigationBarBackButtonHidden()
.keyboardDismissOnTap()
.safeAreaInset(edge: .bottom) {
if store.view_focusField == nil {
TBottomButton(
title: "완료",
isEnable: store.view_isSubmitButtonEnabled
) {
send(.tapSubmitButton)
}
}
}
.sheet(item: $store.view_bottomSheetItem) { item in
switch item {
case .traineeList:
Expand All @@ -86,6 +88,7 @@ public struct TrainerAddPTSessionView: View {
)
case .datePicker(let field):
TDatePickerView(
selectedDate: store.ptDate ?? .now,
title: field.title,
monthFormatter: { TDateFormatUtility.formatter(for: .yyyy년_MM월).string(from: $0) },
buttonAction: {
Expand Down Expand Up @@ -196,7 +199,7 @@ public struct TrainerAddPTSessionView: View {
HStack(alignment: .bottom, spacing: 12) {
// StartTime
TTextField(
placeholder: "09:00",
placeholder: Date().toString(format: .HHmm),
text: Binding(get: {
store.startTime?.toString(format: .HHmm) ?? ""
}, set: { _ in }),
Expand Down Expand Up @@ -227,7 +230,7 @@ public struct TrainerAddPTSessionView: View {

// EndTime
TTextField(
placeholder: "10:00",
placeholder: Date().addingTimeInterval(3600).toString(format: .HHmm),
text: Binding(get: {
store.endTime?.toString(format: .HHmm) ?? ""
}, set: { _ in }),
Expand Down
3 changes: 2 additions & 1 deletion TnT/Projects/Presentation/Sources/Alarm/AlarmCheckView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import ComposableArchitecture
import Domain
import DesignSystem

/// 알람 목록을 입력하는 화면
/// 알람 목록을 확인하는 화면
/// 유저에게 도착한 알람을 표시 - 유저 타입에 따라 분류
@ViewAction(for: AlarmCheckFeature.self)
public struct AlarmCheckView: View {
Expand All @@ -30,6 +30,7 @@ public struct AlarmCheckView: View {
type: .LButtonWithTitle(leftImage: .icnArrowLeft, centerTitle: "알림"),
leftAction: { send(.tapNavBackButton) }
)
TDivider(color: .neutral200)

ScrollView(showsIndicators: false) {
AlarmList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public struct OnboardingFlowFeature {

/// 트레이니 회원가입 완료 화면 -> 트레이너 초대코드 입력 화면 이동
case .element(id: _, action: .traineeProfileCompletion(.setNavigating)):
state.path.append(.traineeInvitationCodeInput(.init(view_popUp: .invitePopUp, view_isPopupPresented: true)))
state.path.append(.traineeInvitationCodeInput(.init()))
return .none

/// 트레이니 초대코드 입력 화면 -> 트레이니 홈화면/PT 정보 입력 화면
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ public struct TraineeMainFlowFeature {

/// 식단 기록 화면 등록 -> 홈화면으로 이동
case .element(id: _, action: .addDietRecordPage(.setNavigating)):
state.path.removeLast()
state.path.removeSubrange(1...)
return .none

/// 마이페이지 초대코드 입력화면 다음 버튼 탭 - > PT 정보 입력 화면 or 홈 이동
case .element(_, action: .traineeInvitationCodeInput(.setNavigating(let screen))):
switch screen {
case .traineeHome:
state.path.removeLast()
state.path.removeSubrange(1...)
case let .trainingInfoInput(trainerName, invitationCode):
state.path.append(.traineeTrainingInfoInput(.init(trainerName: trainerName, invitationCode: invitationCode)))
}
Expand All @@ -119,7 +119,7 @@ public struct TraineeMainFlowFeature {

/// 연결 완료 화면 -> 홈으로 이동
case .element(id: _, action: .traineeConnectionComplete(.setNavigating)):
state.path.removeLast(2)
state.path.removeSubrange(1...)
return .none

default:
Expand Down
Loading