Feat/#125 Flowstate, 시술 일정 추가 API 연결#128
Conversation
📝 WalkthroughWalkthrough캘린더 기반 시술 일정 생성 기능을 추가합니다. DTO/응답 모델, TreatmentAPI 엔드포인트, 저장소·도메인 유스케이스, 캘린더-시술 흐름 상태 및 뷰/뷰모델 연동을 포함해 전체 워크플로우를 구현합니다. Changes
Sequence DiagramsequenceDiagram
participant User as User
participant CalView as CalendarView
participant CalVM as CalendarViewModel
participant FlowState as CalendarTreatmentFlowState
participant TreatView as TreatmentView
participant TreatVM as TreatmentViewModel
participant UseCase as CreateUserProcedureUseCase
participant Repo as TreatmentRepository
participant API as TreatmentAPI
participant Server as API_Server
User->>CalView: 날짜 선택
CalView->>CalVM: sendDateToTreatmentView()
CalVM->>FlowState: selectedDate = Date
User->>TreatView: 시술 선택 후 다음
TreatView->>TreatVM: createUserProcedure()
TreatVM->>FlowState: selectedDate 조회
FlowState-->>TreatVM: selectedDate
TreatVM->>UseCase: execute(scheduledDate, recoveryDate, treatments)
UseCase->>Repo: createUserProcedure(...)
Repo->>API: createUserProcedure(userId, requestDTO)
API->>Server: POST /api/user-procedures (JSON body)
Server-->>API: 200 OK (프로시저 생성 응답)
API-->>Repo: 응답 전달
Repo-->>UseCase: 완료
UseCase-->>TreatVM: 완료
TreatVM->>TreatView: 탭바 노출 및 루트로 네비게이션
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 19
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift (1)
36-38: 중복된homeRepositoryguard 문 발견Lines 24-26에서 이미
homeRepository를 resolve하고 있습니다. 이 중복된 guard 문은 불필요하며 제거해야 합니다.🧹 중복 guard 제거
DIContainer.shared.register(type: FetchTodayProcedureListUseCase.self) { return DefaultFetchTodayProcedureUseCase(repository: calendarRepository) } - - guard let homeRepository = DIContainer.shared.resolve(type: HomeInterface.self) else { - return - } DIContainer.shared.register(type: FetchProcedureDowntimeUseCase.self) {
🤖 Fix all issues with AI agents
In `@Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureRequestDTO.swift`:
- Around line 10-18: Replace the repeated Encodable, Decodable declarations with
the Codable typealias on the DTOs: update both UserProcedureItemRequestDTO and
CreateUserProcedureRequestDTO to conform to Codable instead of listing Encodable
and Decodable separately, keeping existing property names and types unchanged.
- Around line 1-6: 파일 헤더 주석의 파일명이 실제 파일명과 일치하지 않습니다: 현재 상단 주석에
`UserProcedureItemRequestDTO.swift`가 적혀 있으나 파일명은
`CreateUserProcedureRequestDTO.swift`입니다; 파일 상단의 주석 블록(헤더 코멘트)을 찾아
`UserProcedureItemRequestDTO.swift`를 `CreateUserProcedureRequestDTO.swift`로 수정하여
헤더와 실제 파일명이 일치하도록 고치세요.
In `@Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift`:
- Around line 98-108: The manual dictionary construction in the TreatmentAPI
case .createUserProcedure should be replaced by encoding the existing
CreateUserProcedureRequestDTO to a Parameters-style dictionary to avoid
duplication; add an extension on CreateUserProcedureRequestDTO (or a helper)
that encodes self with JSONEncoder and converts to [String: Any] (e.g.,
asParameters) and then return request.asParameters from the createUserProcedure
case, or alternatively use Alamofire's JSONParameterEncoder when building the
request so the body is derived from the DTO rather than hand-constructed.
In `@Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift`:
- Around line 51-53: MockTreatmentRepository.createUserProcedure has a different
signature than the protocol and DefaultTreatmentRepository; update
MockTreatmentRepository.createUserProcedure to match the protocol's declaration
by adding async throws to its signature (so it matches TreatmentInterface and
DefaultTreatmentRepository), and ensure its implementation returns/throws
appropriately for the mock behavior.
- Around line 38-46: createUserProcedure currently uses treatments.compactMap {
$0.toRequestDTO() } which drops any treatments whose setDowntime is nil and can
produce an empty procedures array; add validation in createUserProcedure to
check the resulting procedures array and throw (or return) a clear error before
calling networkService.request when procedures.isEmpty, and surface that error
to callers; replace the incorrect decodingType UserProcedureItemRequestDTO with
a dedicated response DTO (e.g., UserProcedureItemResponseDTO) that matches the
server response and update the request call (TreatmentAPI.createUserProcedure)
to decode that response type; finally, make
MockTreatmentRepository.createUserProcedure conform by adding the missing async
throws signature so it matches the TreatmentInterface protocol.
In `@Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift`:
- Around line 76-78: Remove the stray whitespace between DIContainer.shared and
.register in the registration call so it reads as
DIContainer.shared.register(...); locate the registration for
CreateUserProcedureUseCase that returns
DefaultCreateUserProcedureUseCase(repository: treatmentRepository) and fix the
spacing around the dot to match surrounding calls.
In `@Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift`:
- Around line 22-24: Rename the misspelled method excute to execute in
CreateUserProcedureUseCase by changing the function signature func excute(...)
to func execute(...), and update any conformance/overrides (e.g., protocol
requirements or callers that expect execute) so the implementation in
CreateUserProcedureUseCase and its references call
repository.createUserProcedure(...) the same way; ensure the method name change
is propagated to any protocol/interface that declared excute to avoid
mismatches.
- Around line 10-12: Rename the misspelled protocol method excute to execute in
CreateUserProcedureUseCase and update all call sites to the new name;
specifically change the protocol declaration (CreateUserProcedureUseCase) and
adjust any invocations in NoTreatmentViewModel and TreatmentViewModel to call
execute(scheduledDate:recoveryDate:treatments:) so signatures stay consistent
and compilation errors are resolved.
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift`:
- Around line 256-260: 해당 블록에서 viewModel.confirmDate() 호출 후
calendarCoordinator.push(.selectTreatment) 호출 다음에 있는 불필요한 공백 라인(현재 빈 줄)을 제거하세요;
즉 CalendarView.swift의 해당 코드 블록에서 calendarCoordinator.push(.selectTreatment) 뒤에
있는 빈 줄을 삭제하여 불필요한 공백을 없애면 됩니다.
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift`:
- Around line 104-106: Two methods, sendDateToTreatmentView() and confirmDate(),
perform the same action (assigning selectedDate to
calendarTreatmentFlowState.selectedDaet); remove the duplication by keeping one
method (pick a clear name like sendDateToTreatmentView or confirmDate), delete
the other, and update all callers to invoke the retained method (search for
sendDateToTreatmentView and confirmDate usages). Also ensure the retained method
is accessible where needed and run tests/build to confirm no references remain
to the removed symbol.
- Around line 43-45: Rename the typo property selectedDaet to selectedDate in
CalendarTreatmentFlowState and update all references to the new name (search for
selectedDaet usages), then in CalendarViewModel change the assignment in
confirmDate() to use calendarTreatmentFlowState.selectedDate = selectedDate;
finally remove the duplicate method sendDateToTreatmentView() (or make it call
confirmDate()) so only one implementation remains (update any call sites to the
single method name to avoid breakage).
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarTreatmentFlowState.swift`:
- Around line 10-12: Rename the mistyped property selectedDaet to selectedDate
in CalendarTreatmentFlowState and update every reference to it across the
codebase (e.g., NoTreatmentViewModel, TreatmentViewModel and any other
consumers) to use CalendarTreatmentFlowState.selectedDate; ensure you update
both declaration and all usages (getters, setters, bindings, initializers) and
run the build to catch any remaining references.
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentView.swift`:
- Around line 114-122: The Task block around viewModel.createUserProcedure()
lacks error handling so API failures give no user feedback; wrap the await call
in a do/catch inside the Task, handle errors by updating the view state (e.g.,
set an `@State` error/message or call a viewModel.showError method) and present an
alert/toast to the user, and only set tabBarCoordinator.isTabbarHidden = false
and call calendarCoordinator.popToRoot() on successful completion of
createUserProcedure(); reference viewModel.createUserProcedure(),
tabBarCoordinator.isTabbarHidden, and calendarCoordinator.popToRoot when
implementing the changes.
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift`:
- Around line 113-121: The code calls try await viewModel.createUserProcedure()
inside a Task without error handling, so wrap that call in a do-catch inside the
Task and only run tabBarCoordinator.isTabbarHidden = false and
calendarCoordinator.popToRoot() after a successful createUserProcedure(); on
error catch and handle appropriately (e.g., call viewModel.handleError(_:) or
present an error alert and keep UI state unchanged), referencing
createUserProcedure() and the viewModel/state check in TreatmentView so failures
don't trigger the navigation changes.
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift`:
- Around line 90-104: The createUserProcedure() implementation silently returns
on nil dates and swallows errors; fix it by correcting the typos and surfacing
errors: rename calendarTreatmentFlowState.selectedDaet to selectedDate and call
createUserProcedureUseCase.execute(...) (fix excute→execute in the use
case/protocol), validate and throw a clear error when scheduledDate or
recoverDate is nil instead of returning, and in the do/catch rethrow the caught
error (or remove internal catch since the method is async throws) while logging
the actual error via CherrishLogger.network(error) rather than the generic
CherrishError.networkRequestFailed so callers can handle failures.
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift`:
- Around line 71-85: The function createUserProcedure is declared async throws
but swallows errors and uses misspelled identifiers; change
calendarTreatmentFlowState.selectedDaet to selectedDate, rename
createUserProcedureUseCase.excute to execute, and propagate errors instead of
swallowing them: either remove the do-catch and call try await
createUserProcedureUseCase.execute(...) so failures bubble up, or if you need
logging, catch the error, log with CherrishLogger.network(error), then rethrow
the caught error; ensure you still pass scheduledDate.toScheduledAtFormat,
recoveryDate.toRecoveryDateFormat, and selectedTreatments unchanged.
In `@Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date`+.swift:
- Around line 49-60: The two computed properties toScheduledAtFormat and
toRecoveryDateFormat create new DateFormatter instances on each access which is
expensive; replace these per-access allocations by reusing static DateFormatter
singletons (e.g., static let scheduledAtFormatter and static let
recoveryDateFormatter) configured with the same formats ("yyyy-MM-dd'T'HH:mm:ss"
and "yyyy-MM-dd") and any needed locale/timeZone, and have the computed
properties call formatter.string(from: self) on those static formatters (or
reuse the existing shared dateFormatter already defined elsewhere if
appropriate) to improve performance and avoid duplication.
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift`:
- Around line 76-80: The guard that resolves CreateUserProcedureUseCase via
DIContainer.shared.resolve currently returns silently on failure; update this
guard to log the same DI failure as other guards by calling
CherrishLogger.error(CherrishError.DIFailedError) before returning so failures
are consistently reported — locate the guard that checks
CreateUserProcedureUseCase and insert the error logging call above the return.
- Around line 91-97: The TreatmentViewModel registration closure contains an
unnecessary trailing comma after the last initializer argument
(`createUserProcedureUseCase:`) which can cause compile errors on some Swift
versions; edit the DIContainer.shared.register block and remove the trailing
comma following the `createUserProcedureUseCase` parameter in the
TreatmentViewModel(...) call so the final argument is not followed by a comma.
| // | ||
| // UserProcedureItemRequestDTO.swift | ||
| // Cherrish-iOS | ||
| // | ||
| // Created by 어재선 on 1/21/26. | ||
| // |
There was a problem hiding this comment.
파일 헤더 주석의 파일명이 실제 파일명과 불일치합니다.
주석에는 UserProcedureItemRequestDTO.swift로 되어 있으나, 실제 파일명은 CreateUserProcedureRequestDTO.swift입니다.
✏️ 수정 제안
//
-// UserProcedureItemRequestDTO.swift
+// CreateUserProcedureRequestDTO.swift
// Cherrish-iOS
//📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // | |
| // UserProcedureItemRequestDTO.swift | |
| // Cherrish-iOS | |
| // | |
| // Created by 어재선 on 1/21/26. | |
| // | |
| // | |
| // CreateUserProcedureRequestDTO.swift | |
| // Cherrish-iOS | |
| // | |
| // Created by 어재선 on 1/21/26. | |
| // |
🤖 Prompt for AI Agents
In `@Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureRequestDTO.swift`
around lines 1 - 6, 파일 헤더 주석의 파일명이 실제 파일명과 일치하지 않습니다: 현재 상단 주석에
`UserProcedureItemRequestDTO.swift`가 적혀 있으나 파일명은
`CreateUserProcedureRequestDTO.swift`입니다; 파일 상단의 주석 블록(헤더 코멘트)을 찾아
`UserProcedureItemRequestDTO.swift`를 `CreateUserProcedureRequestDTO.swift`로 수정하여
헤더와 실제 파일명이 일치하도록 고치세요.
| struct UserProcedureItemRequestDTO: Encodable, Decodable { | ||
| let procedureId: Int | ||
| let downtimeDays: Int | ||
| } | ||
|
|
||
| struct CreateUserProcedureRequestDTO: Encodable, Decodable { | ||
| let scheduledAt: String | ||
| let recoveryTargetDate: String | ||
| let procedures: [UserProcedureItemRequestDTO] |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Codable 타입 별칭 사용을 권장합니다.
Encodable, Decodable을 명시적으로 나열하는 대신 Codable을 사용하면 더 간결합니다.
♻️ 리팩토링 제안
-struct UserProcedureItemRequestDTO: Encodable, Decodable {
+struct UserProcedureItemRequestDTO: Codable {
let procedureId: Int
let downtimeDays: Int
}
-struct CreateUserProcedureRequestDTO: Encodable, Decodable {
+struct CreateUserProcedureRequestDTO: Codable {
let scheduledAt: String
let recoveryTargetDate: String
let procedures: [UserProcedureItemRequestDTO]
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| struct UserProcedureItemRequestDTO: Encodable, Decodable { | |
| let procedureId: Int | |
| let downtimeDays: Int | |
| } | |
| struct CreateUserProcedureRequestDTO: Encodable, Decodable { | |
| let scheduledAt: String | |
| let recoveryTargetDate: String | |
| let procedures: [UserProcedureItemRequestDTO] | |
| struct UserProcedureItemRequestDTO: Codable { | |
| let procedureId: Int | |
| let downtimeDays: Int | |
| } | |
| struct CreateUserProcedureRequestDTO: Codable { | |
| let scheduledAt: String | |
| let recoveryTargetDate: String | |
| let procedures: [UserProcedureItemRequestDTO] |
🤖 Prompt for AI Agents
In `@Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureRequestDTO.swift`
around lines 10 - 18, Replace the repeated Encodable, Decodable declarations
with the Codable typealias on the DTOs: update both UserProcedureItemRequestDTO
and CreateUserProcedureRequestDTO to conform to Codable instead of listing
Encodable and Decodable separately, keeping existing property names and types
unchanged.
| case .createUserProcedure(_, let request): | ||
| return [ | ||
| "scheduledAt": request.scheduledAt, | ||
| "recoveryTargetDate": request.recoveryTargetDate, | ||
| "procedures": request.procedures.map { | ||
| [ | ||
| "procedureId": $0.procedureId, | ||
| "downtimeDays": $0.downtimeDays | ||
| ] | ||
| } | ||
| ] |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
DTO의 Encodable 준수를 활용하는 것을 고려하세요
CreateUserProcedureRequestDTO가 이미 Encodable을 준수하므로, 수동으로 딕셔너리를 생성하는 대신 직접 인코딩하는 것이 더 안전하고 유지보수하기 쉽습니다. 현재 방식은 DTO 구조가 변경될 때 두 곳을 수정해야 합니다.
♻️ 대안 제안
Alamofire와 함께 사용할 수 있도록 DTO를 Parameters로 변환하는 헬퍼를 만들거나, JSONParameterEncoder를 사용하는 것을 고려하세요:
// 옵션 1: DTO에 extension 추가
extension CreateUserProcedureRequestDTO {
var asParameters: Parameters {
guard let data = try? JSONEncoder().encode(self),
let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
return [:]
}
return dict
}
}
// 옵션 2: bodyParameters에서 사용
case .createUserProcedure(_, let request):
return request.asParameters🤖 Prompt for AI Agents
In `@Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift` around
lines 98 - 108, The manual dictionary construction in the TreatmentAPI case
.createUserProcedure should be replaced by encoding the existing
CreateUserProcedureRequestDTO to a Parameters-style dictionary to avoid
duplication; add an extension on CreateUserProcedureRequestDTO (or a helper)
that encodes self with JSONEncoder and converts to [String: Any] (e.g.,
asParameters) and then return request.asParameters from the createUserProcedure
case, or alternatively use Alamofire's JSONParameterEncoder when building the
request so the body is derived from the DTO rather than hand-constructed.
| func createUserProcedure(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws { | ||
| let userId: Int = userDefaultService.load(key: .userID) ?? 1 | ||
| let request = CreateUserProcedureRequestDTO( | ||
| scheduledAt: scheduledDate, | ||
| recoveryTargetDate: recoveryDate, | ||
| procedures: treatments.compactMap { $0.toRequestDTO() } | ||
| ) | ||
| let _ = try await networkService.request(TreatmentAPI.createUserProcedure(userId: userId, request: request), decodingType: UserProcedureItemRequestDTO.self) | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, find and read the TreatmentRepository.swift file to understand the full context
find . -name "TreatmentRepository.swift" -type fRepository: TEAM-Cherrish/Cherrish-iOS
Length of output: 139
🏁 Script executed:
# Search for TreatmentInterface protocol definition
rg -n "protocol TreatmentInterface" --type swift -A 20Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 729
🏁 Script executed:
# Search for UserProcedureItemRequestDTO definition
rg -n "struct UserProcedureItemRequestDTO\|class UserProcedureItemRequestDTO" --type swift -A 5Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 52
🏁 Script executed:
# Search for response DTOs related to user procedures
rg -n "UserProcedure.*ResponseDTO\|UserProcedure.*Response\|.*ProcedureResponse" --type swift -A 5Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 52
🏁 Script executed:
# Search for TreatmentEntity and its toRequestDTO method
rg -n "func toRequestDTO" --type swift -B 2 -A 10Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 1048
🏁 Script executed:
# Search for MockTreatmentRepository
rg -n "class MockTreatmentRepository\|struct MockTreatmentRepository" --type swift -A 30Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 52
🏁 Script executed:
# Find UserProcedureItemRequestDTO definition with broader search
rg -n "UserProcedureItemRequestDTO" --type swift -B 2 -A 5Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 3706
🏁 Script executed:
# Read the full TreatmentRepository.swift file
cat -n ./Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swiftRepository: TEAM-Cherrish/Cherrish-iOS
Length of output: 3175
🏁 Script executed:
# Search for MockTreatmentRepository without exact class/struct syntax
rg -n "MockTreatmentRepository" --type swift -B 2 -A 20Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 2471
🏁 Script executed:
# Search for any DTO that contains "Procedure" in name
rg -n "struct.*Procedure.*DTO\|class.*Procedure.*DTO" --type swift -A 3Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 52
procedures 배열이 비어서 전송될 수 있습니다.
compactMap { $0.toRequestDTO() }는 setDowntime이 nil인 모든 treatment를 필터링합니다. 모든 treatment의 setDowntime이 nil이면 빈 procedures 배열이 생성되어 API 요청이 전송됩니다. 이에 대한 유효성 검사 또는 에러 처리를 추가해야 합니다.
또한 Line 45의 응답 타입으로 UserProcedureItemRequestDTO를 사용하고 있는데, 이는 요청용 DTO입니다. 서버 응답에 맞는 별도의 Response DTO를 정의하고 사용해야 합니다.
추가로 MockTreatmentRepository의 createUserProcedure 메서드(Line 51)에 async throws 키워드가 누락되어 있습니다. TreatmentInterface 프로토콜 요구사항과 일치시켜주세요.
🤖 Prompt for AI Agents
In `@Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift` around
lines 38 - 46, createUserProcedure currently uses treatments.compactMap {
$0.toRequestDTO() } which drops any treatments whose setDowntime is nil and can
produce an empty procedures array; add validation in createUserProcedure to
check the resulting procedures array and throw (or return) a clear error before
calling networkService.request when procedures.isEmpty, and surface that error
to callers; replace the incorrect decodingType UserProcedureItemRequestDTO with
a dedicated response DTO (e.g., UserProcedureItemResponseDTO) that matches the
server response and update the request call (TreatmentAPI.createUserProcedure)
to decode that response type; finally, make
MockTreatmentRepository.createUserProcedure conform by adding the missing async
throws signature so it matches the TreatmentInterface protocol.
| func createUserProcedure(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) { | ||
|
|
||
| } |
There was a problem hiding this comment.
MockTreatmentRepository.createUserProcedure 메서드 시그니처가 프로토콜과 불일치합니다.
DefaultTreatmentRepository의 createUserProcedure는 async throws로 선언되어 있으나, Mock 구현체는 이를 누락하고 있습니다. 프로토콜 TreatmentInterface의 요구사항과 일치시켜야 합니다.
🐛 수정 제안
- func createUserProcedure(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) {
-
+ func createUserProcedure(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws {
+ // Mock implementation - no-op
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| func createUserProcedure(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) { | |
| } | |
| func createUserProcedure(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws { | |
| // Mock implementation - no-op | |
| } |
🤖 Prompt for AI Agents
In `@Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift` around
lines 51 - 53, MockTreatmentRepository.createUserProcedure has a different
signature than the protocol and DefaultTreatmentRepository; update
MockTreatmentRepository.createUserProcedure to match the protocol's declaration
by adding async throws to its signature (so it matches TreatmentInterface and
DefaultTreatmentRepository), and ensure its implementation returns/throws
appropriately for the mock behavior.
| func createUserProcedure() async throws { | ||
| guard let scheduledDate = calendarTreatmentFlowState.selectedDaet else { | ||
| return | ||
| } | ||
|
|
||
| guard let recoverDate = Date.from(year: year, month: month, day: day) else { | ||
| return | ||
| } | ||
|
|
||
| do { | ||
| try await createUserProcedureUseCase.excute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) | ||
| } catch { | ||
| CherrishLogger.network(CherrishError.networkRequestFailed) | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find the NoTreatmentViewModel file and check its content
find . -name "NoTreatmentViewModel.swift" -type fRepository: TEAM-Cherrish/Cherrish-iOS
Length of output: 196
🏁 Script executed:
#!/bin/bash
# Find CreateUserProcedureUseCase to check the method name (excute vs execute)
find . -name "*CreateUserProcedureUseCase*" -type fRepository: TEAM-Cherrish/Cherrish-iOS
Length of output: 145
🏁 Script executed:
#!/bin/bash
# Search for the excute method across the codebase
rg "func excute" --type swiftRepository: TEAM-Cherrish/Cherrish-iOS
Length of output: 429
🏁 Script executed:
#!/bin/bash
# Search for the execute method across the codebase
rg "func execute" --type swiftRepository: TEAM-Cherrish/Cherrish-iOS
Length of output: 2267
🏁 Script executed:
#!/bin/bash
# Search for selectedDaet or selectedDate property
rg "selectedDa" --type swift -A 2 -B 2Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 6880
에러 처리 개선 및 오타 수정 필요
이 메서드에서 여러 문제가 있습니다:
async throws로 선언되었지만 에러를 throw하지 않고 내부에서 모두 catch합니다.scheduledDate나recoverDate가 nil일 때 조용히 반환하여 호출자에게 피드백이 없습니다.- 실제 에러를 무시하고 generic
networkRequestFailed에러만 로깅합니다. selectedDaet는 CalendarTreatmentFlowState의 프로퍼티명 오타입니다 (올바른 철자:selectedDate).excute메서드는 CreateUserProcedureUseCase의 오타입니다 (올바른 철자:execute).
🔧 수정 제안
func createUserProcedure() async throws {
- guard let scheduledDate = calendarTreatmentFlowState.selectedDaet else {
- return
+ guard let scheduledDate = calendarTreatmentFlowState.selectedDate else {
+ CherrishLogger.debug("scheduledDate is nil")
+ throw CherrishError.invalidInput
}
guard let recoverDate = Date.from(year: year, month: month, day: day) else {
+ CherrishLogger.debug("Invalid recovery date")
+ throw CherrishError.invalidInput
- return
}
- do {
- try await createUserProcedureUseCase.excute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments)
- } catch {
- CherrishLogger.network(CherrishError.networkRequestFailed)
- }
+ try await createUserProcedureUseCase.execute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments)
}주의: selectedDaet → selectedDate 변경 시 CalendarTreatmentFlowState.swift와 이를 참조하는 다른 파일들도 함께 수정해야 합니다. excute → execute 변경은 CreateUserProcedureUseCase.swift에서 메서드명과 프로토콜 정의를 모두 수정해야 합니다.
🤖 Prompt for AI Agents
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift`
around lines 90 - 104, The createUserProcedure() implementation silently returns
on nil dates and swallows errors; fix it by correcting the typos and surfacing
errors: rename calendarTreatmentFlowState.selectedDaet to selectedDate and call
createUserProcedureUseCase.execute(...) (fix excute→execute in the use
case/protocol), validate and throw a clear error when scheduledDate or
recoverDate is nil instead of returning, and in the do/catch rethrow the caught
error (or remove internal catch since the method is async throws) while logging
the actual error via CherrishLogger.network(error) rather than the generic
CherrishError.networkRequestFailed so callers can handle failures.
| func createUserProcedure() async throws { | ||
| guard let scheduledDate = calendarTreatmentFlowState.selectedDaet else { | ||
| return | ||
| } | ||
|
|
||
| guard let recoverDate = Date.from(year: year, month: month, day: day) else { | ||
| return | ||
| } | ||
|
|
||
| do { | ||
| try await createUserProcedureUseCase.excute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) | ||
| } catch { | ||
| CherrishLogger.network(CherrishError.networkRequestFailed) | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
rg -n "selectedDa" --type swiftRepository: TEAM-Cherrish/Cherrish-iOS
Length of output: 1889
🏁 Script executed:
rg -n "excute|execute" --type swift -B 2 -A 2Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 17254
🏁 Script executed:
rg -n "CalendarTreatmentFlowState" --type swift -A 5 | head -50Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 6320
🏁 Script executed:
fd "CalendarTreatmentFlowState" --type swiftRepository: TEAM-Cherrish/Cherrish-iOS
Length of output: 242
throws 선언과 에러 처리 로직이 불일치합니다.
함수가 async throws로 선언되어 있지만, 내부에서 에러를 catch하고 로깅만 수행합니다. 이로 인해 호출자가 실패 여부를 알 수 없습니다. 에러를 re-throw하거나 함수 시그니처에서 throws를 제거해 주세요.
또한 Line 72의 selectedDaet는 오타입니다 (selectedDate가 올바른 표기). CreateUserProcedureUseCase의 메서드명도 excute에서 execute로 수정이 필요합니다.
♻️ 에러 전파 방식 수정 제안
func createUserProcedure() async throws {
- guard let scheduledDate = calendarTreatmentFlowState.selectedDaet else {
+ guard let scheduledDate = calendarTreatmentFlowState.selectedDate else {
return
}
guard let recoverDate = Date.from(year: year, month: month, day: day) else {
return
}
- do {
- try await createUserProcedureUseCase.excute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments)
- } catch {
- CherrishLogger.network(CherrishError.networkRequestFailed)
- }
+ try await createUserProcedureUseCase.execute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments)
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| func createUserProcedure() async throws { | |
| guard let scheduledDate = calendarTreatmentFlowState.selectedDaet else { | |
| return | |
| } | |
| guard let recoverDate = Date.from(year: year, month: month, day: day) else { | |
| return | |
| } | |
| do { | |
| try await createUserProcedureUseCase.excute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) | |
| } catch { | |
| CherrishLogger.network(CherrishError.networkRequestFailed) | |
| } | |
| } | |
| func createUserProcedure() async throws { | |
| guard let scheduledDate = calendarTreatmentFlowState.selectedDate else { | |
| return | |
| } | |
| guard let recoverDate = Date.from(year: year, month: month, day: day) else { | |
| return | |
| } | |
| try await createUserProcedureUseCase.execute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) | |
| } |
🤖 Prompt for AI Agents
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift`
around lines 71 - 85, The function createUserProcedure is declared async throws
but swallows errors and uses misspelled identifiers; change
calendarTreatmentFlowState.selectedDaet to selectedDate, rename
createUserProcedureUseCase.excute to execute, and propagate errors instead of
swallowing them: either remove the do-catch and call try await
createUserProcedureUseCase.execute(...) so failures bubble up, or if you need
logging, catch the error, log with CherrishLogger.network(error), then rethrow
the caught error; ensure you still pass scheduledDate.toScheduledAtFormat,
recoveryDate.toRecoveryDateFormat, and selectedTreatments unchanged.
|
|
||
|
|
||
| guard let createUserProcedureUseCase = DIContainer.shared.resolve(type: CreateUserProcedureUseCase.self) else { | ||
| return | ||
| } |
There was a problem hiding this comment.
에러 로깅이 누락되었습니다.
다른 guard 문들은 실패 시 CherrishLogger.error(CherrishError.DIFailedError)를 호출하지만, 이 블록은 로깅 없이 return만 합니다. 일관성을 위해 에러 로깅을 추가해 주세요.
✏️ 수정 제안
guard let createUserProcedureUseCase = DIContainer.shared.resolve(type: CreateUserProcedureUseCase.self) else {
+ CherrishLogger.error(CherrishError.DIFailedError)
return
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| guard let createUserProcedureUseCase = DIContainer.shared.resolve(type: CreateUserProcedureUseCase.self) else { | |
| return | |
| } | |
| guard let createUserProcedureUseCase = DIContainer.shared.resolve(type: CreateUserProcedureUseCase.self) else { | |
| CherrishLogger.error(CherrishError.DIFailedError) | |
| return | |
| } |
🤖 Prompt for AI Agents
In `@Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift`
around lines 76 - 80, The guard that resolves CreateUserProcedureUseCase via
DIContainer.shared.resolve currently returns silently on failure; update this
guard to log the same DI failure as other guards by calling
CherrishLogger.error(CherrishError.DIFailedError) before returning so failures
are consistently reported — locate the guard that checks
CreateUserProcedureUseCase and insert the error logging call above the return.
Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift
Show resolved
Hide resolved
| // | ||
| // UserProcedureItemRequestDTO.swift | ||
| // Cherrish-iOS | ||
| // | ||
| // Created by 어재선 on 1/21/26. | ||
| // |
| struct UserProcedureItemRequestDTO: Encodable, Decodable { | ||
| let procedureId: Int | ||
| let downtimeDays: Int | ||
| } | ||
|
|
||
| struct CreateUserProcedureRequestDTO: Encodable, Decodable { |
There was a problem hiding this comment.
리퀘스트니까 encodable만 쓰면 되겟져 ~~ ?
| protocol CreateUserProcedureUseCase { | ||
| func excute(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws | ||
| } |
| func excute(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws { | ||
| return try await repository.createUserProcedure(scheduledDate: scheduledDate, recoveryDate: recoveryDate, treatments: treatments) | ||
| } |
| func confirmDate() { | ||
| calendarTreatmentFlowState.selectedDaet = selectedDate | ||
| } |
| if viewModel.state == .downTimeSetting { | ||
| Task { | ||
| try await viewModel.createUserProcedure() | ||
| tabBarCoordinator.isTabbarHidden = false | ||
| calendarCoordinator.popToRoot() | ||
| } | ||
| } else { | ||
| viewModel.next() | ||
| } |
There was a problem hiding this comment.
do {
try await ~
} catch {
CherrishLogger.error(error)
} 이렇게 써주면 조을것 같아요
| if viewModel.state == .downTimeSetting { | ||
| Task { | ||
| try await viewModel.createUserProcedure() | ||
| tabBarCoordinator.isTabbarHidden = false | ||
| calendarCoordinator.popToRoot() | ||
| } | ||
| } else { | ||
| viewModel.next() | ||
| } |
| try await createUserProcedureUseCase.excute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) | ||
| } catch { | ||
| CherrishLogger.network(CherrishError.networkRequestFailed) |
There was a problem hiding this comment.
- 개행
- network 말고 CherrishLogger.error(error)로 찍어주세여
| func createUserProcedure() async throws { | ||
| guard let scheduledDate = calendarTreatmentFlowState.selectedDaet else { | ||
| return | ||
| } | ||
|
|
||
| guard let recoverDate = Date.from(year: year, month: month, day: day) else { | ||
| return | ||
| } | ||
|
|
||
| do { | ||
| try await createUserProcedureUseCase.excute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) | ||
| } catch { | ||
| CherrishLogger.network(CherrishError.networkRequestFailed) | ||
| } | ||
| } |
|
|
||
| private let userDefaultService: UserDefaultService | ||
|
|
||
| init(userDefaultService: UserDefaultService = DefaultUserDefaultService()) { | ||
| self.userDefaultService = userDefaultService | ||
| } | ||
|
|
| final class CalendarTreatmentFlowState: ObservableObject { | ||
| @Published var selectedDaet: Date? | ||
| } |
| let monthInt = Int(month), monthInt >= 1, monthInt <= 12, | ||
| let dayInt = Int(day), dayInt >= 1, dayInt <= 31 else { | ||
| let monthInt = Int(month), (1...12).contains(monthInt), | ||
| let dayInt = Int(day), (1...31).contains(dayInt) else { |
Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentView.swift`:
- Around line 117-130: The navigation lines run regardless of API success; wrap
tabBarCoordinator.isTabbarHidden = false and calendarCoordinator.popToRoot() so
they only execute on successful createUserProcedure(): inside the Task's do
block, after await viewModel.createUserProcedure(), perform the two navigation
calls; in the catch block log the error (CherrishLogger.error(error)) and
present or propagate an error UI/state instead of allowing the function to
continue to navigation; ensure viewModel.next() remains in the else branch for
non-.downTimeSetting flows.
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift`:
- Around line 113-126: The screen transition is executed even when the API call
fails because tabBarCoordinator.isTabbarHidden = false and
calendarCoordinator.popToRoot() are outside the do block; update the Task in
TreatmentView so that those two calls are moved inside the do block immediately
after successful await viewModel.createUserProcedure(), and keep the catch block
to call CherrishLogger.error(error) without performing the transitions; ensure
the else branch still calls viewModel.next() as before.
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift`:
- Around line 61-68: fetchTreatments() is declared async throws but swallows
errors internally; either remove throws from the signature or rethrow the caught
error so callers can handle it. To fix: in TreatmentViewModel.update the
function fetchTreatments() adjust the error handling around
fetchTreatmentsUseCase.execute(id:keyword:)—option A: remove throws from func
signature and keep the do/catch that sets treatments = [] on error (handling
locally); option B: if you want callers to observe failures, rethrow the error
in the catch (i.e., catch { treatments = []; throw error } or simply remove the
do/catch and let try await propagate). Ensure the signature and internal
behavior for fetchTreatments() are consistent.
In `@Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date`+.swift:
- Around line 69-79: Date.from(year:month:day:) uses Calendar.current which can
vary by user settings; change it to create and use a dedicated Calendar (e.g.,
Calendar(identifier: .gregorian)) configured with TimeZone(identifier:
"Asia/Seoul") and a consistent Locale (matching
scheduledAtFormatter/dateFormatter) before calling date(from:), so the date
construction is timezone/locale deterministic; update the method to build
components with that calendar instead of Calendar.current.
♻️ Duplicate comments (7)
Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureRequestDTO.swift (1)
1-6: 파일 헤더 주석의 파일명이 실제 파일명과 불일치합니다.주석에는
UserProcedureItemRequestDTO.swift로 되어 있으나, 실제 파일명은CreateUserProcedureRequestDTO.swift입니다.Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift (1)
256-260: 네비게이션 전 상태 동기화가 잘 적용되었습니다.
sendDateToTreatmentView()호출이 일관되게 적용되었습니다. Line 260의 불필요한 공백은 제거하는 것이 좋습니다.Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift (2)
64-66:MockTreatmentRepository.createUserProcedure메서드 시그니처가 프로토콜과 불일치합니다.
DefaultTreatmentRepository의createUserProcedure는async throws로 선언되어 있으나, Mock 구현체는 이를 누락하고 있습니다. 프로토콜TreatmentInterface의 요구사항과 일치시켜야 컴파일 에러가 발생하지 않습니다.🐛 수정 제안
- func createUserProcedure(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) { - + func createUserProcedure(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws { + // Mock implementation - no-op }
45-59:procedures배열이 비어있을 때의 검증이 필요합니다.
treatments.compactMap { $0.toRequestDTO() }는setDowntime이 nil인 모든 treatment를 필터링합니다. 모든 treatment의 downtime이 설정되지 않았다면 빈procedures배열로 API 요청이 전송됩니다.🔧 수정 제안
func createUserProcedure(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws { let userId: Int = userDefaultService.load(key: .userID) ?? 1 + let procedures = treatments.compactMap { $0.toRequestDTO() } + guard !procedures.isEmpty else { + throw CherrishError.invalidInput + } let request = CreateUserProcedureRequestDTO( scheduledAt: scheduledDate, recoveryTargetDate: recoveryDate, - procedures: treatments.compactMap { $0.toRequestDTO() } + procedures: procedures )Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift (1)
76-79: 에러 로깅이 누락되었습니다.다른
guard문들은 실패 시CherrishLogger.error(CherrishError.DIFailedError)를 호출하지만, 이 블록은 로깅 없이return만 합니다.✏️ 수정 제안
guard let createUserProcedureUseCase = DIContainer.shared.resolve(type: CreateUserProcedureUseCase.self) else { + CherrishLogger.error(CherrishError.DIFailedError) return }Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift (1)
90-103:async throws로 선언되었지만 에러를 throw하지 않습니다.메서드가
async throws로 선언되었지만, 내부에서 모든 에러를 catch하여 로깅만 하고 있습니다. 호출자(NoTreatmentView)에서 에러 처리를 할 수 있도록 에러를 전파하거나,throws를 제거하는 것이 좋습니다.또한 이전 리뷰 피드백에 따라
CherrishLogger.network(error)대신CherrishLogger.error(error)를 사용해 주세요.🔧 수정 제안
func createUserProcedure() async throws { guard let scheduledDate = calendarTreatmentFlowState.selectedDate else { + CherrishLogger.debug("scheduledDate is nil") return } guard let recoverDate = Date.from(year: year, month: month, day: day) else { + CherrishLogger.debug("Invalid recovery date") return } - do { - try await createUserProcedureUseCase.execute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) - } catch { - CherrishLogger.network(error) - } + try await createUserProcedureUseCase.execute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) }Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift (1)
71-85:throws선언과 에러 처리 로직이 여전히 불일치합니다.이전 리뷰에서 지적된 오타(
selectedDaet,excute)는 수정되었으나, 함수가async throws로 선언되어 있으면서 에러를 catch 후 로깅만 수행하고 re-throw하지 않는 문제가 그대로 남아 있습니다. 호출자가 실패 여부를 알 수 없습니다.♻️ 에러 전파 방식 수정 제안
옵션 1: 에러를 전파 (권장)
func createUserProcedure() async throws { guard let scheduledDate = calendarTreatmentFlowState.selectedDate else { return } guard let recoverDate = Date.from(year: year, month: month, day: day) else { return } - do { - try await createUserProcedureUseCase.execute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) - } catch { - CherrishLogger.network(error) - } + try await createUserProcedureUseCase.execute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) }옵션 2: 로깅 후 re-throw
do { try await createUserProcedureUseCase.execute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) } catch { CherrishLogger.network(error) + throw error }옵션 3: throws 제거 (에러 무시가 의도적인 경우)
- func createUserProcedure() async throws { + func createUserProcedure() async {
| if viewModel.state == .downTimeSetting { | ||
| Task { | ||
| do { | ||
| try await viewModel.createUserProcedure() | ||
| } catch { | ||
| CherrishLogger.error(error) | ||
| } | ||
|
|
||
| tabBarCoordinator.isTabbarHidden = false | ||
| calendarCoordinator.popToRoot() | ||
| } | ||
| } else { | ||
| viewModel.next() | ||
| } |
There was a problem hiding this comment.
API 실패 시에도 화면이 전환됩니다.
do/catch 블록이 추가되었지만, tabBarCoordinator.isTabbarHidden = false와 calendarCoordinator.popToRoot()가 do 블록 외부에 있어 API 호출 실패 시에도 화면이 전환됩니다. 사용자에게 에러 피드백 없이 화면이 닫히면 혼란을 줄 수 있습니다.
🔧 수정 제안
if viewModel.state == .downTimeSetting {
Task {
do {
try await viewModel.createUserProcedure()
+ tabBarCoordinator.isTabbarHidden = false
+ calendarCoordinator.popToRoot()
} catch {
CherrishLogger.error(error)
+ // TODO: 사용자에게 에러 표시 (예: Alert, Toast 등)
}
-
- tabBarCoordinator.isTabbarHidden = false
- calendarCoordinator.popToRoot()
}
} else {
viewModel.next()
}🤖 Prompt for AI Agents
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentView.swift`
around lines 117 - 130, The navigation lines run regardless of API success; wrap
tabBarCoordinator.isTabbarHidden = false and calendarCoordinator.popToRoot() so
they only execute on successful createUserProcedure(): inside the Task's do
block, after await viewModel.createUserProcedure(), perform the two navigation
calls; in the catch block log the error (CherrishLogger.error(error)) and
present or propagate an error UI/state instead of allowing the function to
continue to navigation; ensure viewModel.next() remains in the else branch for
non-.downTimeSetting flows.
| if viewModel.state == .downTimeSetting { | ||
| Task { | ||
| do { | ||
| try await viewModel.createUserProcedure() | ||
| } catch { | ||
| CherrishLogger.error(error) | ||
| } | ||
|
|
||
| tabBarCoordinator.isTabbarHidden = false | ||
| calendarCoordinator.popToRoot() | ||
| } | ||
| } else { | ||
| viewModel.next() | ||
| } |
There was a problem hiding this comment.
API 호출 성공 시에만 화면 전환이 실행되어야 합니다.
do-catch 블록이 추가되었지만, tabBarCoordinator.isTabbarHidden = false와 calendarCoordinator.popToRoot()가 do 블록 외부에 있어서 API 호출 실패 시에도 화면 전환이 실행됩니다.
🐛 수정 제안
if viewModel.state == .downTimeSetting {
Task {
do {
try await viewModel.createUserProcedure()
+ tabBarCoordinator.isTabbarHidden = false
+ calendarCoordinator.popToRoot()
} catch {
CherrishLogger.error(error)
+ // TODO: 사용자에게 에러 상태 표시
}
-
- tabBarCoordinator.isTabbarHidden = false
- calendarCoordinator.popToRoot()
}
} else {
viewModel.next()
}🤖 Prompt for AI Agents
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift`
around lines 113 - 126, The screen transition is executed even when the API call
fails because tabBarCoordinator.isTabbarHidden = false and
calendarCoordinator.popToRoot() are outside the do block; update the Task in
TreatmentView so that those two calls are moved inside the do block immediately
after successful await viewModel.createUserProcedure(), and keep the catch block
to call CherrishLogger.error(error) without performing the transitions; ensure
the else branch still calls viewModel.next() as before.
| @MainActor | ||
| func fetchTreatments() async throws { | ||
| do { | ||
| treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: searchText) | ||
| treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: searchText) | ||
| } catch { | ||
| treatments = [] | ||
| } | ||
| } |
There was a problem hiding this comment.
함수 시그니처와 에러 처리의 불일치
fetchTreatments()가 async throws로 선언되어 있지만, 내부에서 에러를 catch하고 빈 배열로 대체합니다. 호출자에게 에러가 전파되지 않으므로 throws를 제거하거나, 에러를 re-throw하는 것이 좋습니다.
♻️ 제안
`@MainActor`
- func fetchTreatments() async throws {
+ func fetchTreatments() async {
do {
treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: searchText)
} catch {
treatments = []
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @MainActor | |
| func fetchTreatments() async throws { | |
| do { | |
| treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: searchText) | |
| treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: searchText) | |
| } catch { | |
| treatments = [] | |
| } | |
| } | |
| `@MainActor` | |
| func fetchTreatments() async { | |
| do { | |
| treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: searchText) | |
| } catch { | |
| treatments = [] | |
| } | |
| } |
🤖 Prompt for AI Agents
In
`@Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift`
around lines 61 - 68, fetchTreatments() is declared async throws but swallows
errors internally; either remove throws from the signature or rethrow the caught
error so callers can handle it. To fix: in TreatmentViewModel.update the
function fetchTreatments() adjust the error handling around
fetchTreatmentsUseCase.execute(id:keyword:)—option A: remove throws from func
signature and keep the do/catch that sets treatments = [] on error (handling
locally); option B: if you want callers to observe failures, rethrow the error
in the catch (i.e., catch { treatments = []; throw error } or simply remove the
do/catch and let try await propagate). Ensure the signature and internal
behavior for fetchTreatments() are consistent.
| static func from(year: String, month: String, day: String) -> Date? { | ||
| guard let y = Int(year), | ||
| let m = Int(month), | ||
| let d = Int(day) else { return nil } | ||
|
|
||
| var components = DateComponents() | ||
| components.year = y | ||
| components.month = m | ||
| components.day = d | ||
| return Calendar.current.date(from: components) | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Calendar의 locale/timeZone 설정 누락 가능성
Date.from(year:month:day:)에서 Calendar.current를 사용하면 사용자 기기 설정에 따라 다른 결과가 나올 수 있습니다. scheduledAtFormatter와 dateFormatter에서 Asia/Seoul 타임존을 명시한 것과 일관성을 유지하려면 Calendar도 동일하게 설정하는 것이 좋습니다.
♻️ 타임존 일관성 적용 제안
static func from(year: String, month: String, day: String) -> Date? {
guard let y = Int(year),
let m = Int(month),
let d = Int(day) else { return nil }
+ var calendar = Calendar.current
+ calendar.timeZone = TimeZone(identifier: "Asia/Seoul") ?? .current
+
var components = DateComponents()
components.year = y
components.month = m
components.day = d
- return Calendar.current.date(from: components)
+ return calendar.date(from: components)
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| static func from(year: String, month: String, day: String) -> Date? { | |
| guard let y = Int(year), | |
| let m = Int(month), | |
| let d = Int(day) else { return nil } | |
| var components = DateComponents() | |
| components.year = y | |
| components.month = m | |
| components.day = d | |
| return Calendar.current.date(from: components) | |
| } | |
| static func from(year: String, month: String, day: String) -> Date? { | |
| guard let y = Int(year), | |
| let m = Int(month), | |
| let d = Int(day) else { return nil } | |
| var calendar = Calendar.current | |
| calendar.timeZone = TimeZone(identifier: "Asia/Seoul") ?? .current | |
| var components = DateComponents() | |
| components.year = y | |
| components.month = m | |
| components.day = d | |
| return calendar.date(from: components) | |
| } |
🤖 Prompt for AI Agents
In `@Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date`+.swift around
lines 69 - 79, Date.from(year:month:day:) uses Calendar.current which can vary
by user settings; change it to create and use a dedicated Calendar (e.g.,
Calendar(identifier: .gregorian)) configured with TimeZone(identifier:
"Asia/Seoul") and a consistent Locale (matching
scheduledAtFormatter/dateFormatter) before calling date(from:), so the date
construction is timezone/locale deterministic; update the method to build
components with that calendar instead of Calendar.current.

🔗 연결된 이슈
📄 작업 내용
💻 주요 코드 설명
CalendarTreatmentFlowState.swiftPresentationDependencyAssembler.swift