diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/SelectTreatment/SelectTreatmentView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/SelectTreatment/SelectTreatmentView.swift index a3da3a84..ae70bc4f 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/SelectTreatment/SelectTreatmentView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/SelectTreatment/SelectTreatmentView.swift @@ -69,15 +69,22 @@ extension SelectTreatmentView { @ViewBuilder private var titleView: some View { - HStack { - VStack(alignment: .leading){ - TypographyText("시술 일정을 추가해볼게요.", style: .title1_sb_18, color: .gray1000) - - TypographyText("이미 생각해둔 시술이 있나요?", style: .title1_sb_18, color: .gray1000) + HStack(spacing: 0) { + VStack(alignment: .leading, spacing: 0){ + + TypographyText("시술 일정을 추가해볼게요.", style: .title1_sb_18, color: .gray1000) + .frame(height: 27.adjustedH) + TypographyText("이미 생각해둔 시술이 있나요?", style: .title1_sb_18, color: .gray1000) + .frame(height: 27.adjustedH) + + + Spacer() + .frame(height: 4.adjustedH) TypographyText("시술을 선택하셨는지 확인할게요.", style: .body1_r_14, color: .gray700) - + .frame(height: 20.adjustedH) } + .frame(height: 78.adjustedH) Spacer() } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/SelectTreatment/SelectTreatmentViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/SelectTreatment/SelectTreatmentViewModel.swift index 1f56165a..36801fc2 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/SelectTreatment/SelectTreatmentViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/SelectTreatment/SelectTreatmentViewModel.swift @@ -8,8 +8,8 @@ import SwiftUI enum TreatmentSelectionState: CaseIterable { - case notSelected case available + case notSelected var title: String { switch self { diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DownTimeSettingView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DownTimeSettingView.swift index da3ad424..e66d2877 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DownTimeSettingView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DownTimeSettingView.swift @@ -14,7 +14,7 @@ struct DownTimeSettingView: View { let today: (year: Int, month: Int, day: Int) var body: some View { - VStack { + VStack(spacing: 0) { Spacer() .frame(height: 30.adjustedH) @@ -30,9 +30,10 @@ struct DownTimeSettingView: View { } .padding(.horizontal, 25.adjustedW) ScrollView(.vertical, showsIndicators: false) { - VStack { - Spacer() - .frame(height: 24.adjustedH) + Spacer() + .frame(height: 24.adjustedH) + VStack(spacing: 10) { + ForEach(treatments, id: \.self) { treatment in TreatmentRowView( displayMode: .completeBoxView, @@ -48,42 +49,43 @@ struct DownTimeSettingView: View { selectedTreatment = treatment }) } + } + .padding(.horizontal, 25.adjustedW) + Spacer() + .frame(height: 14.adjustedH) + + HStack(alignment: .top, spacing: 0) { + TypographyText( + "◎", + style: .body3_r_12, + color: .gray600 + ) - Spacer() - .frame(height: 14.adjustedH) - - HStack(alignment: .top, spacing: 0) { + VStack(alignment: .leading, spacing: 0) { TypographyText( - "◎", + "본 정보는 의료 상담이나 진단을 대체하지 않으며,", style: .body3_r_12, color: .gray600 ) - VStack(alignment: .leading, spacing: 0) { - TypographyText( - "본 정보는 의료 상담이나 진단을 대체하지 않으며,", - style: .body3_r_12, - color: .gray600 - ) - - TypographyText( - "실제 다운타임 및 회복 과정은 개인에 따라 다를 수 있습니다.", - style: .body3_r_12, - color: .gray600 - ) - - TypographyText( - "정확한 내용은 의료진 상담을 통해 확인하세요.", - style: .body3_r_12, - color: .gray600 - ) - - } + TypographyText( + "실제 다운타임 및 회복 과정은 개인에 따라 다를 수 있습니다.", + style: .body3_r_12, + color: .gray600 + ) + + TypographyText( + "정확한 내용은 의료진 상담을 통해 확인하세요.", + style: .body3_r_12, + color: .gray600 + ) - Spacer() } + + Spacer() } .padding(.horizontal, 25.adjustedW) + } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentFilterView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentFilterView.swift index 5b343f66..036cfffd 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentFilterView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentFilterView.swift @@ -14,24 +14,31 @@ struct NoTreatmentFilterView: View { VStack(spacing: 0) { TitleHeaderView(title: viewModel.selectedCategory?.title ?? "") - Spacer() - .frame(height: 10.adjustedH) - ScrollView(.vertical, showsIndicators: false){ Spacer() - .frame(height: 10.adjustedH) + .frame(height: 18.adjustedH) ForEach(viewModel.treatments, id: \.id) { treatment in TreatmentRowView( displayMode: .checkBoxView, treatmentEntity: treatment, isSelected: .constant(viewModel.isSelected(treatment)), - action: { viewModel.addTreatment(treatment) } + action: { + if viewModel.isSelected(treatment) { + viewModel.removeTreatment(treatment) + } else { + viewModel.addTreatment(treatment) + + } + } ) - .padding(.horizontal, 34.adjustedW) + .padding(.horizontal, 25.adjustedW) } + Spacer() + .frame(height: 198.adjustedH) } + } .task { await viewModel.fetchNoTreatments() @@ -44,16 +51,16 @@ private struct TitleHeaderView: View { var body: some View { VStack(spacing: 4.adjustedH) { - VStack(alignment: .leading) { + VStack(alignment: .leading, spacing: 0) { HStack(spacing: 6.adjustedW) { TypographyText(title, style: .title1_sb_18, color: .gray1000) - + .frame(height: 27.adjustedH) TypographyText("관련 시술 리스트", style: .title1_sb_18, color: .gray1000) - + .frame(height: 27.adjustedH) Spacer() } - .frame(height: 27.adjustedH) + HStack(spacing: 4.adjustedW) { VStack { @@ -62,20 +69,17 @@ private struct TitleHeaderView: View { Spacer() } - VStack(alignment: .leading) { + VStack(alignment: .leading, spacing: 0) { TypographyText("본 정보는 인터넷 빅테이터 검색 및 분석을 통해 수집된 정보이며, ", style: .body3_r_12, color: .gray600) - - TypographyText("관련 시술 리스트", style: .body3_r_12, color: .gray600) - + .frame(height: 17.adjustedH) + TypographyText("공식적인 의료 정보가 아닙니다.", style: .body3_r_12, color: .gray600) + .frame(height: 17.adjustedH) } - .frame(height: 34.adjustedH) } } .padding(.horizontal, 25.adjustedW) .padding(.vertical, 20.adjustedH) - Spacer() - } .background(Color.gray100) .overlay(alignment: .top) { @@ -88,7 +92,7 @@ private struct TitleHeaderView: View { .frame(height: 1.adjustedH) .gray500() } - .frame(height: 105) + .frame(height: 105.adjustedH ) } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentView.swift index a0331911..f5db3ccb 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentView.swift @@ -79,6 +79,15 @@ struct NoTreatmentView: View { case .treatmentFilter: NoTreatmentFilterView(viewModel: viewModel) + .overlay(alignment: .bottom) { + if viewModel.state == .treatmentFilter, !viewModel.selectedTreatments.isEmpty { + SelectedTreatmentSheetView( + selectedTreatments: viewModel.selectedTreatments, + removeTreatment: viewModel.removeTreatment(_:) + ) + + } + } case .downTimeSetting: DownTimeSettingView( @@ -101,13 +110,6 @@ struct NoTreatmentView: View { @ViewBuilder private func bottomView() -> some View { VStack(spacing: 0) { - if viewModel.state == .treatmentFilter, !viewModel.selectedTreatments.isEmpty { - SelectedTreatmentSheetView( - selectedTreatments: viewModel.selectedTreatments, - removeTreatment: viewModel.removeTreatment(_:) - ) - } - CherrishButton( title: "다음", type: .large, @@ -157,18 +159,22 @@ private struct TreatmentSelectedCategory: View { style: .title1_sb_18, color: .gray1000 ) + .frame(height: 27.adjustedH) TypographyText( "외모 고민은 무엇인가요?", style: .title1_sb_18, color: .gray1000 ) - + .frame(height: 27.adjustedH) + Spacer() + .frame(height: 4.adjustedH) TypographyText( "선택한 고민을 기준으로 시술 정보를 정리해줘요.", style: .body1_m_14, color: .gray700 ) + .frame(height: 20.adjustedH) } .frame(height: 78.adjustedH) @@ -176,9 +182,10 @@ private struct TreatmentSelectedCategory: View { Spacer() } .padding(.horizontal, 34.adjustedW) - Spacer() - .frame(height: 40.adjustedH) + ScrollView(.vertical, showsIndicators:false) { + Spacer() + .frame(height: 40.adjustedH) LazyVGrid(columns: columns, spacing: 12.adjustedH) { ForEach(viewModel.categories, id: \.id) { category in SelectionChip( diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/SelectedTreatmentSheetView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/SelectedTreatmentSheetView.swift index e0f573ce..ca3bdd93 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/SelectedTreatmentSheetView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/SelectedTreatmentSheetView.swift @@ -51,28 +51,45 @@ struct SelectedTreatmentSheetView: View { y: -5 ) ZStack { - ScrollView(.vertical, showsIndicators: false) { - VStack(spacing: spacing) { - if selectedTreatments.count > 3 { - scrollViewTopMarkerView - .allowsHitTesting(false) - } - ForEach(selectedTreatments, id: \.id) { treatment in - TreatmentRowView( - displayMode: .summary, - treatmentEntity: treatment, - isSelected: .constant(true), - action: { removeTreatment(treatment) } - ) - .frame(height: itemHeight) + ScrollViewReader { proxy in + ScrollView(.vertical, showsIndicators: false) { + VStack(spacing: spacing) { + if selectedTreatments.count > 3 { + scrollViewTopMarkerView + .allowsHitTesting(false) + } + ForEach(selectedTreatments, id: \.id) { treatment in + TreatmentRowView( + displayMode: .summary, + treatmentEntity: treatment, + isSelected: .constant(true), + action: { removeTreatment(treatment) } + ) + .id(treatment.id) + .frame(height: itemHeight) + } + .padding(.horizontal, 24.5.adjustedW) + + if selectedTreatments.count > 3 { + scrollViewBottomMarkerView + .allowsHitTesting(false) + } + + Color.clear + .frame(height: 1) + .id("scrollBottom") } - if selectedTreatments.count > 3 { - scrollViewBottomMarkerView - .allowsHitTesting(false) + .padding(.vertical, 14.adjustedH) + } + .onChange(of: selectedTreatments.count) { oldCount, newCount in + if newCount > oldCount { + withAnimation { + proxy.scrollTo("scrollBottom", anchor: .bottom) + } } } - .padding(.vertical, 14.adjustedH) } + if selectedTreatments.count > 3 { GradientBox(isTop: true) .frame(height: 42.adjustedH) @@ -86,12 +103,10 @@ struct SelectedTreatmentSheetView: View { .opacity(shouldShowGradientBottom ? 1 : 0) .frame(maxHeight: .infinity, alignment: .bottom) } - - - } + .background(.gray0) .frame(height: scrollViewHeight) - .padding(.horizontal, 24.5.adjustedW) + .coordinateSpace(name: "SelectedTreatmentScroll") .onPreferenceChange(ScrollTopPreferenceKey.self) { minY in if initialTopGlobalY == nil { initialTopGlobalY = minY } @@ -100,7 +115,9 @@ struct SelectedTreatmentSheetView: View { .onPreferenceChange(ScrollBottomPreferenceKey.self) { height in bottomOffsetY = height } + } + } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/TargetDdaySettingView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/TargetDdaySettingView.swift index 1d4f0871..649975f9 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/TargetDdaySettingView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/TargetDdaySettingView.swift @@ -8,8 +8,8 @@ import SwiftUI enum DdayState: CaseIterable { - case yes case no + case yes var id: Self { self } var title: String { @@ -38,17 +38,14 @@ struct TargetDdaySettingView: View { HStack(spacing:0){ VStack(alignment: .leading, spacing: 0) { TypographyText("회복을 계획할 때 고려해야 할", style: .title1_sb_18, color: .gray1000) - + .frame(height: 27.adjustedH) TypographyText("중요한 일정이 있나요?", style: .title1_sb_18, color: .gray1000) - + .frame(height: 27.adjustedH) } - Spacer() } - .frame(height: 54.adjustedH) - Spacer() - .frame(height: 40) + .frame(height: 40.adjustedH) HStack(spacing: 12.adjustedW) { ForEach(DdayState.allCases, id: \.self) { state in diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift index da2233c1..0fdc7d20 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift @@ -10,7 +10,7 @@ import SwiftUI struct TreatmentFilterView: View { @ObservedObject var viewModel: TreatmentViewModel var body: some View { - VStack { + VStack(spacing: 0) { TreatmentSearchBarTextField( text: $viewModel.searchText, onTap: { @@ -21,7 +21,7 @@ struct TreatmentFilterView: View { isDisabled: false ) .padding(.horizontal, 25.adjustedW) - + .padding(.bottom, 8.adjustedH) ScrollView(.vertical, showsIndicators: false) { HStack(alignment: .top,spacing: 4) { TypographyText("◎", style: .body3_r_12, color: .gray600) @@ -51,11 +51,18 @@ struct TreatmentFilterView: View { displayMode: .checkBoxView, treatmentEntity: treatment, isSelected: .constant(viewModel.isSelected(treatment)), - action: { viewModel.addTreatment(treatment) } + action: { if viewModel.isSelected(treatment) { + viewModel.removeTreatment(treatment) + } else { + viewModel.addTreatment(treatment) + + } } ) } .padding(.horizontal, 24.adjustedW) } + Spacer() + .frame(height: 198.adjustedH) } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift index 79d8c920..aeba478d 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift @@ -74,7 +74,15 @@ struct TreatmentView: View { case .treatmentFilter: TreatmentFilterView(viewModel: viewModel) - + .overlay(alignment: .bottom) { + if viewModel.state == .treatmentFilter, !viewModel.selectedTreatments.isEmpty { + SelectedTreatmentSheetView( + selectedTreatments: viewModel.selectedTreatments, + removeTreatment: viewModel.removeTreatment(_:) + ) + + } + } case .downTimeSetting: DownTimeSettingView( treatments: $viewModel.selectedTreatments, @@ -97,13 +105,6 @@ struct TreatmentView: View { @ViewBuilder private func bottomView() -> some View { VStack(spacing: 0) { - if viewModel.state == .treatmentFilter, !viewModel.selectedTreatments.isEmpty { - SelectedTreatmentSheetView( - selectedTreatments: viewModel.selectedTreatments, - removeTreatment: viewModel.removeTreatment(_:) - ) - } - CherrishButton( title: "다음", type: .large, diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/CherrishTextBox/CherrishTextBox.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/CherrishTextBox/CherrishTextBox.swift index 5bcc4a2c..0bf0770d 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/CherrishTextBox/CherrishTextBox.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/CherrishTextBox/CherrishTextBox.swift @@ -17,6 +17,7 @@ struct CherrishTextBox: View { VStack(spacing: 0) { HStack(spacing: 0) { TypographyText(title, style: .body1_sb_14,color: .gray1000) + .frame(height: 20.adjustedH) Spacer() } Spacer() diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/CherrishTextBox/DateTextBox.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/CherrishTextBox/DateTextBox.swift index 6f211851..e700cc44 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/CherrishTextBox/DateTextBox.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/CherrishTextBox/DateTextBox.swift @@ -16,6 +16,7 @@ struct DateTextBox: View { VStack(spacing: 8) { HStack(spacing: 0) { TypographyText("날짜", style: .body1_sb_14, color: .gray1000) + .frame(height: 20.adjustedH) Spacer() } HStack(spacing: 14){ diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/Treatment/TreatmentRowView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/Treatment/TreatmentRowView.swift index 242f2a01..c72a0e80 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/Treatment/TreatmentRowView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/Treatment/TreatmentRowView.swift @@ -71,11 +71,14 @@ private struct TreatmentSummaryView: View { Spacer() .frame(width: 12.adjustedW) TypographyText( - "다운타임*\(treatmentEntity.downtimeMin)-\(treatmentEntity.downtimeMax)일", + treatmentEntity.downtimeMin == 0 && treatmentEntity.downtimeMax == 0 ? + "다운타임* 0일" : + "다운타임* \(treatmentEntity.downtimeMin)-\(treatmentEntity.downtimeMax)일", style: .body1_r_14, color: .gray700 ) + Spacer() Image(.deletebox) .onTapGesture { @@ -118,8 +121,7 @@ private struct TreatmentCheckBoxView: View { var body: some View { VStack(spacing: 0) { HStack { - Text(treatmentEntity.name) - .typography(.title1_sb_18) + TypographyText(treatmentEntity.name, style: .title1_sb_18, color: .gray1000) .frame(height: 24.adjustedH) Spacer() if isCompletedView{ @@ -127,19 +129,21 @@ private struct TreatmentCheckBoxView: View { } } HStack(spacing: 0) { - Text(treatmentEntity.benefits.joinedWithSeparator()) - .typography(.body3_r_12) - .foregroundStyle(.gray700) - .frame(height: 18.adjustedH) + TypographyText( + treatmentEntity.benefits.joinedWithSeparator(), + style: .body3_r_12, + color: .gray700 + ) + .frame(height: 18.adjustedH) Spacer() } Spacer() DownTimeLabel(downtimeMin: treatmentEntity.downtimeMin, downtimeMax: treatmentEntity.downtimeMax) } - .padding(.vertical, 12) - .padding(.horizontal, 14) - .frame(height: 100) + .padding(.vertical, 12.adjustedH) + .padding(.horizontal, 14.adjustedW) + .frame(height: 100.adjustedH) .background { if isCompleted { RoundedRectangle(cornerRadius: 10) @@ -175,12 +179,15 @@ private struct DownTimeLabel: View { let downtimeMin: Int let downtimeMax: Int var body: some View { - HStack(spacing: 0){ + HStack(alignment: .center, spacing: 0){ Spacer() Image(.clock) .gray700() + .frame(width: 24.adjustedH, height: 24.adjustedH) TypographyText( - "다운타임*\(downtimeMin)-\(downtimeMax)일", + downtimeMin == 0 && downtimeMax == 0 ? + "다운타임* 0일" : + "다운타임* \(downtimeMin)-\(downtimeMax)일", style: .body2_r_13, color: .gray700 )