From c44ed7e6d3192ec86d8cccacff94dc7e4c4df5d2 Mon Sep 17 00:00:00 2001 From: yeonee Date: Fri, 23 Jan 2026 17:11:04 +0900 Subject: [PATCH 1/4] =?UTF-8?q?refactor:=20#172=20=EB=A1=9C=EB=94=A9?= =?UTF-8?q?=EB=B7=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xcshareddata/swiftpm/Package.resolved | 11 ++- .../Calendar/CalendarMain/CalendarView.swift | 77 ++++++++++++------- .../CalendarMain/CalendarViewModel.swift | 33 ++++++-- .../View/ChallengeProgressView.swift | 30 ++++++-- .../View/ChallengeSelectMissionView.swift | 1 - .../Presentation/Feature/Home/HomeView.swift | 20 ++++- .../Feature/MyPage/MyPageView.swift | 22 ++++-- .../Feature/MyPage/MyPageViewModel.swift | 14 +++- .../Components/CherrishLoadingView.swift | 15 ++++ 9 files changed, 166 insertions(+), 57 deletions(-) create mode 100644 Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/CherrishLoadingView.swift diff --git a/Cherrish-iOS/Cherrish-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Cherrish-iOS/Cherrish-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 017b43ad..cded0138 100644 --- a/Cherrish-iOS/Cherrish-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Cherrish-iOS/Cherrish-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "11b78eba97192d19796cff581fdf69b3e65b441188b1448a1b67e5d7b825a354", + "originHash" : "aceca0c973d8efe8d069cb81bf522ace08d6a1258b48197a08fc849f34cd8f80", "pins" : [ { "identity" : "alamofire", @@ -9,6 +9,15 @@ "revision" : "7be73f6c2b5cd90e40798b06ebd5da8f9f79cf88", "version" : "5.11.0" } + }, + { + "identity" : "lottie-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/airbnb/lottie-ios", + "state" : { + "revision" : "0cb03fd7564d27345bcd96144b811e56212949c6", + "version" : "4.6.0" + } } ], "version" : 3 diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift index d39e9824..b344f0ea 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift @@ -22,14 +22,59 @@ enum CalendarMode { } struct CalendarView: View { + @EnvironmentObject private var calendarCoordinator: CalendarCoordinator + @StateObject var viewModel: CalendarViewModel + @StateObject var homeCalendarFlowState: HomeCalendarFlowState + @State var calendarMode: CalendarMode = .none + @State var selectedProcedureID: Int? = nil + + var body: some View { + ZStack { + if viewModel.isLoading { + CherrishLoadingView() + } else { + CalendarContentView( + viewModel: viewModel, + homeCalendarFlowState: homeCalendarFlowState, + calendarMode: $calendarMode, + selectedProcedureID: $selectedProcedureID + ) + } + } + .task (id: viewModel.currentMonth){ + if calendarMode == .none { + do { + try await viewModel.fetchProcedureCountsOfMonth() + try await viewModel.fetchTodayProcedureList() + } catch { + CherrishLogger.error(error) + } + } + } + .onChange(of: homeCalendarFlowState.treatmentDate) { _, date in + if let date = date { + viewModel.updateDate(date: date) + homeCalendarFlowState.treatmentDate = nil + } + } + .onAppear { + if let date = homeCalendarFlowState.treatmentDate { + viewModel.updateDate(date: date) + homeCalendarFlowState.treatmentDate = nil + } + } + } +} + +private struct CalendarContentView: View { @EnvironmentObject private var calendarCoordinator: CalendarCoordinator @StateObject var viewModel: CalendarViewModel @StateObject var homeCalendarFlowState: HomeCalendarFlowState @State private var topGlobalY: CGFloat = .zero @State private var initialTopGlobalY: CGFloat? = nil @State private var bottomOffsetY: CGFloat = .zero - @State private var calendarMode: CalendarMode = .none - @State private var selectedProcedureID: Int? = nil + @Binding var calendarMode: CalendarMode + @Binding var selectedProcedureID: Int? @State private var buttonState: ButtonState = .active private let scrollAreaHeight: CGFloat = 184.adjustedH @@ -40,6 +85,7 @@ struct CalendarView: View { let weekdays: [String] = ["일", "월", "화", "수", "목", "금", "토"] let columns = Array(repeating: GridItem(.fixed(40.adjustedW), spacing: 8), count: 7) + var body: some View { VStack { Spacer() @@ -56,33 +102,10 @@ struct CalendarView: View { } Spacer() } - .task (id: viewModel.currentMonth){ - if calendarMode == .none { - do { - try await viewModel.fetchProcedureCountsOfMonth() - try await viewModel.fetchTodayProcedureList() - } catch { - CherrishLogger.error(error) - } - } - } - .onChange(of: homeCalendarFlowState.treatmentDate) { _, date in - if let date = date { - viewModel.updateDate(date: date) - homeCalendarFlowState.treatmentDate = nil - } - } - .onAppear { - if let date = homeCalendarFlowState.treatmentDate { - viewModel.updateDate(date: date) - homeCalendarFlowState.treatmentDate = nil - } - } .background(.gray0) } } - -extension CalendarView { +extension CalendarContentView { private var calendarHeader: some View { VStack { HStack { @@ -330,7 +353,7 @@ extension CalendarView { } -extension CalendarView { +extension CalendarContentView { private var scrollViewTopMarkerView: some View { GeometryReader { proxy in Color.clear diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift index 3f4e308a..e126681f 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift @@ -22,6 +22,7 @@ final class CalendarViewModel: ObservableObject { @Published private(set) var treatmentDate: String = "" @Published private(set) var downtimeByDay: [String : DowntimeDayState] = [:] @Published private(set) var selectedDowntime: ProcedureDowntimeEntity? + @Published private(set) var isLoading: Bool = true private let fetchProcedureCountOfMonthUseCase: FetchProcedureCountOfMonth private let fetchTodayProcedureListUseCase: FetchTodayProcedureListUseCase @@ -103,26 +104,46 @@ final class CalendarViewModel: ObservableObject { @MainActor func fetchProcedureCountsOfMonth() async throws { + isLoading = true let calendar = Calendar.current let targetDate = getCurrentMonth(addingMonth: currentMonth) let year = calendar.component(.year, from: targetDate) let month = calendar.component(.month, from: targetDate) - let response = try await fetchProcedureCountOfMonthUseCase.execute(year: year, month: month) - procedureCountOfMonth = response.dailyProcedureCounts + do { + let response = try await fetchProcedureCountOfMonthUseCase.execute(year: year, month: month) + isLoading = false + procedureCountOfMonth = response.dailyProcedureCounts + } catch { + CherrishLogger.error(error) + } } @MainActor func fetchTodayProcedureList() async throws { + isLoading = true treatmentDate = selectedDate.toDateString() - procedureList = try await fetchTodayProcedureListUseCase.execute(date: treatmentDate) + + do { + procedureList = try await fetchTodayProcedureListUseCase.execute(date: treatmentDate) + isLoading = false + } catch { + CherrishLogger.error(error) + } } @MainActor func fetchDowntimeByDay(procedureId: Int) async throws { - let downtimeList = try await fetchProcedureDowntimeUseCase.execute(id: procedureId) - selectedDowntime = downtimeList - mapToDowntimeDays(procedure: downtimeList) + isLoading = true + + do { + let downtimeList = try await fetchProcedureDowntimeUseCase.execute(id: procedureId) + isLoading = false + selectedDowntime = downtimeList + mapToDowntimeDays(procedure: downtimeList) + } catch { + CherrishLogger.error(error) + } } func updateDate(date: Date) { diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/View/ChallengeProgressView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/View/ChallengeProgressView.swift index 48fc6cdb..51b50f57 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/View/ChallengeProgressView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/View/ChallengeProgressView.swift @@ -11,6 +11,26 @@ struct ChallengeProgressView: View { @EnvironmentObject private var challengeCoordinator: ChallengeCoordinator @StateObject var viewModel: ChallengeProgressViewModel + var body: some View { + ZStack { + if viewModel.isLoading { + CherrishLoadingView() + } + else { + ChallengeProgressContentView(viewModel: viewModel) + } + } + .task { + await viewModel.loadChallenge() + } + } +} + + +private struct ChallengeProgressContentView: View { + @EnvironmentObject private var challengeCoordinator: ChallengeCoordinator + @StateObject var viewModel: ChallengeProgressViewModel + let buttonState: ButtonState = .active var body: some View { @@ -37,13 +57,9 @@ struct ChallengeProgressView: View { .padding(.vertical, 24.adjustedH) } .scrollIndicators(.hidden) - .task { - await viewModel.loadChallenge() - } } } - -extension ChallengeProgressView { +extension ChallengeProgressContentView { private var CherryGrowthView: some View { VStack(spacing: 0) { VStack(spacing: 0) { @@ -98,9 +114,7 @@ extension ChallengeProgressView { ) .cherrishShadow() } -} - -extension ChallengeProgressView { + private var CherryTodoView: some View { VStack { HStack { diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/View/ChallengeSelectMissionView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/View/ChallengeSelectMissionView.swift index d7b67b1b..5e75052e 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/View/ChallengeSelectMissionView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/View/ChallengeSelectMissionView.swift @@ -12,7 +12,6 @@ struct ChallengeSelectMissionView: View { @EnvironmentObject private var challengeCoordinator: ChallengeCoordinator @ObservedObject var viewModel: CreateChallengeViewModel - var body: some View { VStack { VStack { diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Home/HomeView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Home/HomeView.swift index 66f7dc57..8c806f85 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Home/HomeView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Home/HomeView.swift @@ -10,6 +10,23 @@ import SwiftUI struct HomeView: View { @StateObject var viewModel: HomeViewModel + var body: some View { + ZStack { + if viewModel.isLoading { + CherrishLoadingView() + } else { + HomeContentView(viewModel: viewModel) + } + } + .task { + await viewModel.loadDashboard() + } + } +} + +private struct HomeContentView: View { + @StateObject var viewModel: HomeViewModel + var body: some View { ZStack { BackgroundGradientView() @@ -44,9 +61,6 @@ struct HomeView: View { .padding(.bottom, 20.adjustedH) } } - .task { - await viewModel.loadDashboard() - } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift index c87ff9ba..8a444fca 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift @@ -11,14 +11,20 @@ struct MyPageView: View { @StateObject var viewModel: MyPageViewModel var body: some View { - VStack { - Spacer() - .frame(height: 52.adjustedH) - headerView - grayEmptyBar - prepareView - .padding(.horizontal, 35) - grayEmptyBar + ZStack { + if viewModel.isLoading { + CherrishLoadingView() + } else { + VStack { + Spacer() + .frame(height: 52.adjustedH) + headerView + grayEmptyBar + prepareView + .padding(.horizontal, 35) + grayEmptyBar + } + } } .task { do { diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageViewModel.swift index 003b8a1a..f87187b8 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageViewModel.swift @@ -10,6 +10,7 @@ import Foundation final class MyPageViewModel: ObservableObject { @Published private(set) var name: String = "" @Published private(set) var day: Int = 1 + @Published private(set) var isLoading: Bool = false private let fetchUserInfoUseCase: FetchUserInfoUseCase @@ -19,8 +20,15 @@ final class MyPageViewModel: ObservableObject { @MainActor func fetchUserInfo() async throws { - let response = try await fetchUserInfoUseCase.execute() - name = response.name - day = response.daysSinceSignup + isLoading = true + + do { + let response = try await fetchUserInfoUseCase.execute() + isLoading = false + name = response.name + day = response.daysSinceSignup + } catch { + CherrishLogger.error(error) + } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/CherrishLoadingView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/CherrishLoadingView.swift new file mode 100644 index 00000000..540143de --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Components/CherrishLoadingView.swift @@ -0,0 +1,15 @@ +// +// CherrishLoadingView.swift +// Cherrish-iOS +// +// Created by 이나연 on 1/23/26. +// + +import SwiftUI + +struct CherrishLoadingView: View { + var body: some View { + ProgressView() + .progressViewStyle(.circular) + } +} From 4a5048702c7b9190335b583d63455ca78f4fa73c Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Fri, 23 Jan 2026 17:45:26 +0900 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20#172=20=EC=8B=9C=EC=88=A0=20?= =?UTF-8?q?=ED=94=8C=EB=A1=9C=EC=9A=B0=20=EB=A1=9C=EB=94=A9=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NoTreatment/NoTreatmentFilterView.swift | 51 ++++----- .../View/NoTreatment/NoTreatmentView.swift | 106 +++++++++--------- .../View/Treatment/TreatmentFilterView.swift | 49 ++++---- .../NoTreatment/NoTreatmentViewModel.swift | 5 + .../Treatment/TreatmentViewModel.swift | 4 + 5 files changed, 113 insertions(+), 102 deletions(-) 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 84fa5e28..e40803f5 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 @@ -25,35 +25,36 @@ struct NoTreatmentFilterView: View { var body: some View { VStack(spacing: 0) { TitleHeaderView(title: viewModel.selectedCategory?.title ?? "") - - ScrollView(.vertical, showsIndicators: false){ - Spacer() - .frame(height: 18.adjustedH) - - ForEach(viewModel.treatments, id: \.id) { treatment in - TreatmentRowView( - displayMode: .checkBoxView, - treatmentEntity: treatment, - isSelected: .constant(viewModel.isSelected(treatment)), - action: { - if viewModel.isSelected(treatment) { - viewModel.removeTreatment(treatment) - } else { - viewModel.addTreatment(treatment) - - } - } - ) - .padding(.horizontal, 25.adjustedW) + if viewModel.isLoading { + CherrishLoadingView() + } else { + ScrollView(.vertical, showsIndicators: false) { + Spacer() + .frame(height: 18.adjustedH) + ForEach(viewModel.treatments, id: \.id) { treatment in + TreatmentRowView( + displayMode: .checkBoxView, + treatmentEntity: treatment, + isSelected: .constant(viewModel.isSelected(treatment)), + action: { + if viewModel.isSelected(treatment) { + viewModel.removeTreatment(treatment) + } else { + viewModel.addTreatment(treatment) + + } + } + ) + .padding(.horizontal, 25.adjustedW) + + } + Spacer() + .frame(height: 198.adjustedH) } - Spacer() - .frame( - height: viewModel.selectedTreatments.isEmpty ? - 24.adjustedH : scrollViewHeight.adjustedH + 24.adjustedH - ) } + } .task { await viewModel.fetchNoTreatments() 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 e4d13735..cd28361d 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 @@ -151,63 +151,67 @@ private struct TreatmentSelectedCategory: View { ] var body: some View { - VStack(spacing: 0) { - Spacer() - .frame(height: 50.adjustedH) - - HStack(spacing: 0) { - VStack(alignment: .leading, spacing: 0) { - TypographyText( - "요즘 가장 신경 쓰이는 ", - style: .title1_sb_18, - color: .gray1000 - ) - .frame(height: 27.adjustedH) + if viewModel.isLoading { + CherrishLoadingView() + } else { + VStack(spacing: 0) { + Spacer() + .frame(height: 50.adjustedH) + + 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_m_14, + color: .gray700 + ) + .frame(height: 20.adjustedH) + + } + .frame(height: 78.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) + .padding(.horizontal, 34.adjustedW) - Spacer() - } - .padding(.horizontal, 34.adjustedW) - - ScrollView(.vertical, showsIndicators:false) { - Spacer() - .frame(height: 40.adjustedH) - LazyVGrid(columns: columns, spacing: 12.adjustedH) { - ForEach(viewModel.categories, id: \.id) { category in - SelectionChip( - title: category.title, - isSelected: Binding( - get: { - viewModel.selectedCategory == category - }, - set: { - isSelected in - guard isSelected else { - return + ScrollView(.vertical, showsIndicators:false) { + Spacer() + .frame(height: 40.adjustedH) + LazyVGrid(columns: columns, spacing: 12.adjustedH) { + ForEach(viewModel.categories, id: \.id) { category in + SelectionChip( + title: category.title, + isSelected: Binding( + get: { + viewModel.selectedCategory == category + }, + set: { + isSelected in + guard isSelected else { + return + } + viewModel.selectCategory(category) } - viewModel.selectCategory(category) - } + ) ) - ) - } - } .padding(.horizontal, 34.adjustedW) + } + } .padding(.horizontal, 34.adjustedW) + } } } } 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 093b052b..8153387c 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 @@ -50,35 +50,32 @@ struct TreatmentFilterView: View { } .frame(height: 34.adjustedH) .padding(.horizontal, 25.adjustedW) - - Spacer() - .frame(height: 20.adjustedH) - - if viewModel.treatments.isEmpty { - Spacer() - .frame(height: 148.adjustedH) - filterEmptyView + if viewModel.isLoading { + CherrishLoadingView() } else { - ForEach(viewModel.treatments, id: \.id) { treatment in - TreatmentRowView( - displayMode: .checkBoxView, - treatmentEntity: treatment, - isSelected: .constant(viewModel.isSelected(treatment)), - action: { if viewModel.isSelected(treatment) { - viewModel.removeTreatment(treatment) - } else { - viewModel.addTreatment(treatment) - - } } - ) + if viewModel.treatments.isEmpty { + Spacer() + .frame(height: 148.adjustedH) + filterEmptyView + } else { + ForEach(viewModel.treatments, id: \.id) { treatment in + TreatmentRowView( + displayMode: .checkBoxView, + treatmentEntity: treatment, + isSelected: .constant(viewModel.isSelected(treatment)), + action: { if viewModel.isSelected(treatment) { + viewModel.removeTreatment(treatment) + } else { + viewModel.addTreatment(treatment) + + } } + ) + } + .padding(.horizontal, 24.adjustedW) } - .padding(.horizontal, 24.adjustedW) + Spacer() + .frame(height: 198.adjustedH) } - Spacer() - .frame( - height: viewModel.selectedTreatments.isEmpty ? - 24.adjustedH : scrollViewHeight.adjustedH + 24.adjustedH - ) } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift index 57aa331e..99aff4ab 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift @@ -18,6 +18,7 @@ final class NoTreatmentViewModel: ObservableObject{ @Published var month: String = "" @Published var day: String = "" @Published private(set) var warning: TreatmentInputWarning = .none + @Published private(set) var isLoading: Bool = false private let fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase private let fetchTreatmentsUseCase: FetchTreatmentsUseCase @@ -71,8 +72,10 @@ final class NoTreatmentViewModel: ObservableObject{ @MainActor func fetchCategories() async { + isLoading = true do { categories = try await fetchCategoriesUseCase.execute() + isLoading = false } catch { CherrishLogger.debug(error) } @@ -80,8 +83,10 @@ final class NoTreatmentViewModel: ObservableObject{ @MainActor func fetchNoTreatments() async { + isLoading = true do { treatments = try await fetchTreatmentsUseCase.execute(id: selectedCategory?.id, keyword: "") + isLoading = false } catch { treatments = [] CherrishLogger.debug(error) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift index 14af68ac..07b90861 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift @@ -18,6 +18,7 @@ final class TreatmentViewModel: ObservableObject{ @Published var day: String = "" @Published var searchText = "" @Published private(set) var warning: TreatmentInputWarning = .none + @Published private(set) var isLoading: Bool = false private let fetchTreatmentsUseCase: FetchTreatmentsUseCase private let createUserProcedureUseCase: CreateUserProcedureUseCase @@ -63,10 +64,13 @@ final class TreatmentViewModel: ObservableObject{ @MainActor func fetchTreatments() async throws { + isLoading = true do { treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: searchText) + isLoading = false } catch { treatments = [] + CherrishLogger.network(error) } } From dd446712ffe1946eab6490b5736294bcc3daf350 Mon Sep 17 00:00:00 2001 From: yeonee Date: Fri, 23 Jan 2026 19:27:06 +0900 Subject: [PATCH 3/4] =?UTF-8?q?refactor:=20#172=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=9E=98=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Feature/Calendar/CalendarMain/CalendarView.swift | 4 ++-- .../Treatment/View/Treatment/TreatmentFilterView.swift | 1 + .../Feature/ChallengeView/View/ChallengeProgressView.swift | 2 +- .../Cherrish-iOS/Presentation/Feature/Home/HomeView.swift | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift index b344f0ea..39bff2a5 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift @@ -68,8 +68,8 @@ struct CalendarView: View { private struct CalendarContentView: View { @EnvironmentObject private var calendarCoordinator: CalendarCoordinator - @StateObject var viewModel: CalendarViewModel - @StateObject var homeCalendarFlowState: HomeCalendarFlowState + @ObservedObject var viewModel: CalendarViewModel + @ObservedObject var homeCalendarFlowState: HomeCalendarFlowState @State private var topGlobalY: CGFloat = .zero @State private var initialTopGlobalY: CGFloat? = nil @State private var bottomOffsetY: CGFloat = .zero 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 8153387c..0e1dbffa 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 @@ -28,6 +28,7 @@ struct TreatmentFilterView: View { Task { try await viewModel.fetchTreatments() } + self.hideKeyboard() }, isDisabled: false ) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/View/ChallengeProgressView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/View/ChallengeProgressView.swift index 51b50f57..04c0e615 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/View/ChallengeProgressView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/ChallengeView/View/ChallengeProgressView.swift @@ -29,7 +29,7 @@ struct ChallengeProgressView: View { private struct ChallengeProgressContentView: View { @EnvironmentObject private var challengeCoordinator: ChallengeCoordinator - @StateObject var viewModel: ChallengeProgressViewModel + @ObservedObject var viewModel: ChallengeProgressViewModel let buttonState: ButtonState = .active diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Home/HomeView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Home/HomeView.swift index 8c806f85..7d49b5c5 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Home/HomeView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Home/HomeView.swift @@ -25,7 +25,7 @@ struct HomeView: View { } private struct HomeContentView: View { - @StateObject var viewModel: HomeViewModel + @ObservedObject var viewModel: HomeViewModel var body: some View { ZStack { From 3a585cac67e9572b16d5e4bd1136110d3ea658d1 Mon Sep 17 00:00:00 2001 From: yeonee Date: Fri, 23 Jan 2026 19:37:07 +0900 Subject: [PATCH 4/4] =?UTF-8?q?refactor:=20#172=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift index 8a444fca..bb760867 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift @@ -21,7 +21,7 @@ struct MyPageView: View { headerView grayEmptyBar prepareView - .padding(.horizontal, 35) + .padding(.horizontal, 35.adjustedW) grayEmptyBar } }