[Feat] 루틴/등록 수정 페이지 user interaction 추가#50
Conversation
Walkthrough도메인 RepeatType에 Equatable 및 주간 연관값(weeks) 추가. 프레젠테이션 계층 전반에서 Dependencies→Dependency로 API 일괄 변경 및 UI/레이아웃/상태 업데이트 로직 재구성. 뷰컨은 퍼블리셔 바인딩과 캘린더/타임피커 흐름 추가. 뷰모델은 입력/출력/내부 상태를 대폭 개편하고 실행시간/기간/반복 주간 처리 로직을 변경. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant VC as RoutineCreationViewController
participant PeriodView as RoutinePeriodContentView
participant Calendar as BitnagilCalendarView
participant VM as RoutineCreationViewModel
User->>PeriodView: 시작/종료 날짜 버튼 탭
PeriodView-->>VC: onAction(.startDateTapped / .endDateTapped)
VC->>Calendar: 바텀시트 표시
User->>Calendar: 날짜 선택
Calendar-->>VC: didSelectDate(date)
VC->>VM: action(.configureStartDate/.configureEndDate)
VM-->>VC: periodPublisher (start,end)
VC->>PeriodView: configure(dependency: (start,end))
sequenceDiagram
actor User
participant VC as RoutineCreationViewController
participant RepeatView as RoutineRepeatContentView
participant VM as RoutineCreationViewModel
User->>RepeatView: 일/주간 버튼/요일들 탭
RepeatView-->>VC: onAction(.repeatDaily / .repeatWeekly / .setWeeks)
VC->>VM: action(.configureRepeatType / .configureWeeks)
VM-->>VC: repeatTypePublisher (nil/daily/weekly(weeks))
VC->>RepeatView: configure(dependency: updated)
sequenceDiagram
actor User
participant VC as RoutineCreationViewController
participant TimeView as RoutineTimeContentView
participant TimePicker as TimePickerView
participant VM as RoutineCreationViewModel
User->>TimeView: 전체/시간 설정 탭
TimeView-->>VC: onAction(.toggleAllDay / .timeSetTapped)
VC->>VM: action(.toggleAllDay) note right of VC: 전체 선택 시
VC->>TimePicker: 표시 note right of VC: 시간 설정 시
User->>TimePicker: 시간 선택
TimePicker-->>VC: didSelectTime(time)
VC->>VM: action(.configureExecution(type: ExecutionTime(startAt: time)))
VM-->>VC: executionTimePublisher(Date?)
VC->>TimeView: configure(dependency: startTime?)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60–90 minutes Possibly related PRs
Suggested reviewers
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (12)
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutinePeriodContentView.swift (1)
32-34: Dependency에 튜플 대신 명시적 프로퍼티 사용 제안튜플(dates: (start:end:))은 확장성/가독성이 떨어집니다. start/end가 별도 의미를 가지므로 명시적 프로퍼티가 더 적합합니다. 아래처럼 변경하면 호출부도 더 명확해집니다.
- struct Dependency { - let dates: (start: Date, end: Date) - } + struct Dependency { + let startDate: Date + let endDate: Date + }- let startString = dependency - .dates - .start + let startString = dependency + .startDate .convertToString(dateType: .yearMonthDate) - let endString = dependency - .dates - .end + let endString = dependency + .endDate .convertToString(dateType: .yearMonthDate)Also applies to: 67-75
Projects/Presentation/Sources/RoutineCreation/View/Protocol/RoutineCreationExpandable.swift (1)
11-21: 중복된 확장/축소(setExpanded) 로직 프로토콜 익스텐션으로 공통화 제안여러 ContentView에서 동일한 토글 패턴을 반복합니다. 프로토콜 기본 구현으로 중복 제거하면 유지보수성이 좋아집니다.
다음 익스텐션을 추가하고, 특수 처리가 필요한 뷰(예: 주간 버튼 표시 갱신)는 setExpanded 호출 후 별도 메서드로 후처리하세요.
extension RoutineCreationExpandable where Self: UIView { func setExpanded(expanded: Bool) { guard heightConstraint?.isActive == expanded else { return } subviews.forEach { $0.alpha = 0 } defer { subviews.forEach { $0.alpha = 1 } } heightConstraint?.isActive = !expanded subviews.forEach { $0.isHidden = !expanded } } }Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineTimeContentView.swift (1)
65-70: 체크 아이콘 상태 일관성 유지nil(미선택)일 때는 unchecked 아이콘을 쓰면서, 특정 시간 선택 시에는 빈 이미지(UIImage())를 설정합니다. 동일한 미체크 표현(예: uncheckedIcon)으로 통일하는 편이 UI 일관성에 좋습니다. 또한 configureTime(time:)도 동일 규칙을 반영하도록 갱신을 권장합니다.
if time.isMidnight { timeButton.setTitle("하루종일", for: .normal) checkButtonImageView.image = BitnagilIcon.checkedIcon } else { timeButton.setTitle(time.convertToString(dateType: .amPmTimeShort), for: .normal) - checkButtonImageView.image = UIImage() + checkButtonImageView.image = BitnagilIcon.uncheckedIcon }- func configureTime(time: Date) { - let timeString = time.convertToString(dateType: .amPmTimeShort) - timeButton.setTitle(timeString, for: .normal) - } + func configureTime(time: Date) { + if time.isMidnight { + timeButton.setTitle("하루종일", for: .normal) + checkButtonImageView.image = BitnagilIcon.checkedIcon + } else { + timeButton.setTitle(time.convertToString(dateType: .amPmTimeShort), for: .normal) + checkButtonImageView.image = BitnagilIcon.uncheckedIcon + } + }Also applies to: 72-78, 157-160
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineNameContentView.swift (1)
51-51: 미사용 프로퍼티 정리isExpanded가 사용되지 않습니다. 불필요한 상태는 제거해 주세요.
- private var isExpanded = true // 초기 상태 추적Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineCreationCardView.swift (2)
179-204: 서브타이틀 업데이트 로직 개선 필요
configure(subTitles:)메서드에서 서브타이틀을 추가한 후updateHeaderVisibility()를 호출하는데, 이미titleLabel의 높이를 Line 198-200에서 업데이트하고 있습니다. 이로 인해updateHeaderVisibility()내부에서 Line 279-281에서 동일한 constraint를 다시 업데이트하게 되어 중복 작업이 발생합니다.func configure(subTitles: [String]) { labelStackView.arrangedSubviews.dropFirst(2).forEach { subview in labelStackView.removeArrangedSubview(subview) subview.removeFromSuperview() } for text in subTitles { let label = UILabel() label.text = text label.font = BitnagilFont(style: .body1, weight: .semiBold).font label.textColor = BitnagilColor.gray10 label.numberOfLines = 1 labelStackView.addArrangedSubview(label) label.snp.makeConstraints { make in make.height.equalTo(Layout.subTitleLabelHeight) } } - titleLabel.snp.updateConstraints { make in - make.height.equalTo(subTitles.isEmpty ? Layout.titleLabelLargeHeight : Layout.titleLabelSmallHeight) - } - updateHeaderVisibility() setNeedsLayout() }
266-290: 폰트 설정 로직 간소화 가능
updateHeaderVisibility()메서드의 Line 283-289에서 titleHeight 값에 따라 폰트를 설정하는 로직이 복잡합니다. 더 간결하게 표현할 수 있습니다.private func updateHeaderVisibility() { let arranged = labelStackView.arrangedSubviews let subtitles = arranged.dropFirst(2) let hasSubtitles = !subtitles.isEmpty let isExpanded = !contentView.isHidden let titleHeight: CGFloat = { if isExpanded { return Layout.titleLabelLargeHeight } return hasSubtitles ? Layout.titleLabelSmallHeight : Layout.titleLabelLargeHeight }() placeHolderLabel.isHidden = isExpanded || hasSubtitles subtitles.forEach { $0.isHidden = isExpanded } titleLabel.snp.updateConstraints { make in make.height.equalTo(titleHeight) } - if titleHeight == Layout.titleLabelLargeHeight { - titleLabel.font = isExpanded ? BitnagilFont.init(style: .body2, weight: .semiBold).font : BitnagilFont.init(style: .body1, weight: .semiBold).font - titleLabel.textColor = BitnagilColor.gray10 - } else { - titleLabel.font = BitnagilFont.init(style: .body2, weight: .medium).font - titleLabel.textColor = BitnagilColor.gray50 - } + let isLargeTitle = titleHeight == Layout.titleLabelLargeHeight + + if isLargeTitle { + let style: BitnagilFont.Style = isExpanded ? .body2 : .body1 + titleLabel.font = BitnagilFont(style: style, weight: .semiBold).font + titleLabel.textColor = BitnagilColor.gray10 + } else { + titleLabel.font = BitnagilFont(style: .body2, weight: .medium).font + titleLabel.textColor = BitnagilColor.gray50 + } }Projects/Presentation/Sources/RoutineCreation/View/RoutineCreationViewController.swift (2)
14-17: DateSelectionType enum을 더 직관적인 위치로 이동 고려
DateSelectionTypeenum이 ViewController 내부에 private으로 선언되어 있는데, 날짜 선택 관련 로직이 복잡해질 경우 별도 타입으로 분리하는 것을 고려해보세요.
203-208: 서브루틴 configure 중복 호출 최적화서브루틴 업데이트 시
configure(dependencies:)와configure(subTitles:)를 연속으로 호출하는데, 이는 뷰 업데이트를 두 번 트리거할 수 있습니다.단일 configure 메서드로 통합하거나, 내부적으로 한 번의 레이아웃 패스로 처리하도록 개선하면 성능이 향상될 수 있습니다.
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineRepeatContentView.swift (2)
169-179: 불필요한 self 캡처 간소화 가능버튼 액션 클로저에서
self를 weak 캡처한 후 guard let으로 언래핑하는데, 더 간결하게 작성할 수 있습니다.button.addAction( - UIAction { [weak self] action in - guard - let self, - let sender = action.sender as? UIButton - else { return } + UIAction { [weak self] action in + guard let sender = action.sender as? UIButton else { return } sender.isSelected.toggle() - configureWeekButton(weekButton: sender) - self.emitSelectedWeeks() + self?.configureWeekButton(weekButton: sender) + self?.emitSelectedWeeks() }, for: .touchUpInside )
249-263: emitSelectedWeeks 메서드 성능 개선 가능주간 버튼 선택 시마다 전체 버튼을 순회하여 선택된 주를 찾는데, 이미
buttonToWeek딕셔너리가 있으므로 더 효율적으로 처리할 수 있습니다.private func emitSelectedWeeks() { guard weeklyButton.isSelected else { return } - let weeks: [Week] = weekStackView - .arrangedSubviews - .compactMap { subview in - guard - let button = subview as? UIButton, - button.isSelected, - let week = buttonToWeek[button] - else { return nil } - - return week - } - .sorted { $0.id < $1.id } + let weeks = buttonToWeek + .filter { $0.key.isSelected } + .compactMap { $0.value } + .sorted { $0.id < $1.id } action?(.setWeeks(weeks)) }Projects/Presentation/Sources/RoutineCreation/ViewModel/RoutineCreationViewModel.swift (2)
86-86: deleteAllSubRoutines 초기화 값 검토
deleteAllSubRoutines액션이 서브루틴을["", "", ""]로 초기화하는데, 이는 UI에서 빈 텍스트필드 3개를 보여주기 위한 것으로 보입니다. 더 명확한 상수로 정의하면 좋겠습니다.+private let emptySubRoutines = ["", "", ""] case .deleteAllSubRoutines: - subRoutinesSubject.send(["", "", ""]) + subRoutinesSubject.send(emptySubRoutines)
203-214: 시간 설정 로직 복잡도 개선
configureExecutionTime메서드에서 midnight 체크 로직이 복잡합니다. 토글 동작이 명확하게 드러나도록 개선할 수 있습니다.private func configureExecutionTime(time: ExecutionTime) { - if - let time = time.startAt, - let curTime = executionTimeSubject.value.startAt, - time.isMidnight, - curTime.isMidnight - { - executionTimeSubject.send(.init(startAt: nil)) - return - } - - executionTimeSubject.send(time) + let newTime = time.startAt + let currentTime = executionTimeSubject.value.startAt + + // Toggle off if both times are midnight (all-day selection) + let shouldClearTime = newTime?.isMidnight == true && + currentTime?.isMidnight == true + + executionTimeSubject.send( + shouldClearTime ? .init(startAt: nil) : time + ) }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (9)
Projects/Domain/Sources/Entity/Enum/RepeatType.swift(1 hunks)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineCreationCardView.swift(6 hunks)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineNameContentView.swift(9 hunks)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutinePeriodContentView.swift(2 hunks)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineRepeatContentView.swift(5 hunks)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineTimeContentView.swift(2 hunks)Projects/Presentation/Sources/RoutineCreation/View/Protocol/RoutineCreationExpandable.swift(1 hunks)Projects/Presentation/Sources/RoutineCreation/View/RoutineCreationViewController.swift(5 hunks)Projects/Presentation/Sources/RoutineCreation/ViewModel/RoutineCreationViewModel.swift(8 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (7)
Projects/Presentation/Sources/RoutineCreation/View/Protocol/RoutineCreationExpandable.swift (4)
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutinePeriodContentView.swift (2)
setExpanded(57-65)configure(67-79)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineNameContentView.swift (2)
setExpanded(63-71)configure(73-92)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineRepeatContentView.swift (2)
setExpanded(52-61)configure(63-67)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineTimeContentView.swift (2)
setExpanded(55-63)configure(65-79)
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineTimeContentView.swift (3)
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutinePeriodContentView.swift (1)
configure(67-79)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineNameContentView.swift (1)
configure(73-92)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineRepeatContentView.swift (1)
configure(63-67)
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutinePeriodContentView.swift (5)
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineNameContentView.swift (1)
configure(73-92)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineCreationCardView.swift (3)
configure(69-76)configure(179-204)configure(206-208)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineRepeatContentView.swift (1)
configure(63-67)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineTimeContentView.swift (1)
configure(65-79)Projects/Shared/Sources/Extension/Date+.swift (1)
convertToString(16-22)
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineRepeatContentView.swift (2)
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineTimeContentView.swift (2)
configure(65-79)configureAttribute(81-112)Projects/Presentation/Sources/RoutineCreation/ViewModel/RoutineCreationViewModel.swift (1)
action(77-107)
Projects/Presentation/Sources/RoutineCreation/View/RoutineCreationViewController.swift (6)
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineNameContentView.swift (2)
textFieldEditingChanged(242-244)configure(73-92)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutinePeriodContentView.swift (1)
configure(67-79)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineRepeatContentView.swift (1)
configure(63-67)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineTimeContentView.swift (1)
configure(65-79)Projects/Shared/Sources/Extension/Date+.swift (1)
convertToString(16-22)Projects/Presentation/Sources/Common/Extension/UIViewController+.swift (1)
presentCustomBottomSheet(97-100)
Projects/Presentation/Sources/RoutineCreation/ViewModel/RoutineCreationViewModel.swift (5)
Projects/Domain/Sources/UseCase/Routine/RoutineUseCase.swift (1)
fetchRoutine(18-21)Projects/DataSource/Sources/Repository/RoutineRepository.swift (1)
fetchRoutine(26-31)Projects/DataSource/Sources/Repository/RecommendedRoutineRepository.swift (1)
fetchRecommendedRoutine(13-20)Projects/Domain/Sources/UseCase/RecommendedRoutine/RecommendedRoutineUseCase.swift (1)
fetchRecommendedRoutine(15-18)Projects/Shared/Sources/Extension/Date+.swift (2)
convertToDate(24-30)convertToString(16-22)
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineCreationCardView.swift (4)
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutinePeriodContentView.swift (1)
configure(67-79)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineNameContentView.swift (1)
configure(73-92)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineRepeatContentView.swift (1)
configure(63-67)Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineTimeContentView.swift (1)
configure(65-79)
🪛 SwiftLint (0.57.0)
Projects/Presentation/Sources/RoutineCreation/ViewModel/RoutineCreationViewModel.swift
[Warning] 256-256: TODOs should be resolved (- 수정 필요)
(todo)
🔇 Additional comments (5)
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutinePeriodContentView.swift (1)
67-79: 기간 값 유효성(시작 ≤ 종료) 보장에 대한 책임 위치 확인 필요UI 단에서는 문자열로만 표기하므로 무방하지만, 시작일이 종료일보다 이후인 입력이 들어올 가능성(예: 사용자 선택 순서)을 ViewModel/도메인에서 방지·정규화하는지 확인이 필요합니다. 이 뷰는 그대로 표시만 하되, 상위 계층에서 보장하는 흐름이면 OK입니다.
Projects/Domain/Sources/Entity/Enum/RepeatType.swift (1)
8-11: Equatable 추가와 주간 weeks 데이터 도입 방향 👍Set로 유일성 유지가 보장되고, Equatable 합성도 자동으로 되어 비교 로직 단순화에 도움이 됩니다.
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineNameContentView.swift (2)
87-91: 체크 아이콘 갱신 로직은 명확하고 직관적입니다모든 입력이 빈 문자열일 때 checked, 그 외에는 unchecked로 표현하는 규칙이 명확합니다. 위 가드 제거 후에도 정상 동작합니다.
109-127: 텍스트필드 태깅/델리게이트 설정 방식 적절index 태그로 액션 라우팅하고, editingChanged로 상위로 이벤트 전달하는 구조가 깔끔합니다. placeholder 스타일링도 일관적입니다.
Projects/Presentation/Sources/RoutineCreation/View/RoutineCreationViewController.swift (1)
319-328: dateSelectionType 초기화 시점 개선
dateSelectionType을 날짜 선택 완료 후에 nil로 초기화하는데, 사용자가 캘린더를 취소하는 경우에도 초기화가 필요할 수 있습니다.캘린더 뷰가 dismiss될 때 dateSelectionType이 제대로 초기화되는지 확인이 필요합니다. CustomBottomSheet이 취소되는 경우를 처리하는 delegate 메서드가 있는지 확인해보세요.
| public enum RepeatType: Equatable { | ||
| case daily | ||
| case weekly | ||
| case weekly(weeks: Set<Week>) | ||
| } |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
케이스 시그니처 변경(.weekly → .weekly(weeks:))에 따른 사용처 점검 필요
연관값 추가로 기존 .weekly 패턴 매칭/생성이 컴파일 에러가 될 수 있습니다. 아래 스크립트로 레거시 사용을 찾아 점검해 주세요.
🏁 Script executed:
#!/bin/bash
# .weekly 연관값 없이 사용된 곳 탐지
rg -nP --type=swift -C2 '\.weekly(?!\s*\()'Length of output: 2098
.weekly 케이스 연관값 처리 누락으로 인한 컴파일 에러 수정 필요
RepeatType에 weekly(weeks: Set<Week>)가 추가되면서, 기존의 .weekly 패턴 매칭/생성 코드는 모두 컴파일 에러가 발생합니다. 아래 위치들을 확인해 패턴 매칭 시 연관값 처리를 추가하거나 와일드카드로 무시하도록 수정하세요.
- Projects/Presentation/Sources/RoutineCreation/ViewModel/RoutineCreationViewModel.swift
• 186줄: - case .weekly:
- case .weekly(let weeks):
• 187줄:
```diff
- if case .weekly = current {
- if case .weekly(_) = current {
• 198줄:
```diff
- guard case .weekly = repeatTypeSubject.value else { return }
- guard case .weekly(_) = repeatTypeSubject.value else { return }
- Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineRepeatContentView.swift
• 190줄: - case .weekly:
- case .weekly(_):
필요하다면 let weeks로 바인딩하여 UI 업데이트에 활용할 수 있습니다.
| func configure(dependency: Dependency) { | ||
| guard !dependency.subRoutines.isEmpty else { return } | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
빈 배열 입력 시에도 UI가 정상 초기화되도록 가드 제거 및 나머지 필드 초기화
빈 배열이면 return 되어 체크 아이콘/텍스트필드 초기화가 누락될 수 있습니다. 가드를 제거하고, 전달된 subRoutines 수보다 많은 텍스트필드는 비워 주세요.
- func configure(dependency: Dependency) {
- guard !dependency.subRoutines.isEmpty else { return }
+ func configure(dependency: Dependency) {
let subRoutines = dependency.subRoutines
let subRoutineTextFields = [
subRoutineTextField1,
subRoutineTextField2,
subRoutineTextField3]
let minCount = min(subRoutines.count, subRoutineTextFields.count)
- zip(subRoutines, subRoutineTextFields).prefix(minCount).forEach {
- $1.text = $0
- }
+ zip(subRoutines, subRoutineTextFields).prefix(minCount).forEach { $1.text = $0 }
+ // 남은 필드는 초기화
+ subRoutineTextFields.dropFirst(minCount).forEach { $0.text = "" }Also applies to: 83-86
🤖 Prompt for AI Agents
In
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineNameContentView.swift
around lines 73–75 (and similarly 83–86), remove the early guard that returns on
empty dependency.subRoutines so UI always initializes; always set the check-icon
state and configure each text field up to dependency.subRoutines.count with the
provided subRoutine values, and explicitly clear any remaining text fields and
reset their check-icons when dependency.subRoutines.count is less than the total
fields so no stale text or checked state remains.
| associatedtype Dependency | ||
|
|
||
| /// RoutineCreationExpandableContentView 에서 일어날 수 있는 action을 전달합니다. | ||
| var action: ((Action) -> Void)? { get set } | ||
| var heightConstraint: Constraint? { get set } | ||
|
|
||
| func setExpanded(expanded: Bool) | ||
| func configure(dependencies: Dependencies) | ||
| func configure(dependency: Dependency) | ||
| } |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Dependencies → Dependency 리네이밍에 따른 전역 사용처 확인
프로토콜 시그니처가 바뀌었으므로 구현체/호출부에 잔존 레퍼런스가 없는지 확인해 주세요.
🏁 Script executed:
#!/bin/bash
# 남아있는 기존 표기 탐지
rg -nP --type=swift -C2 '\bassociatedtype\s+Dependencies\b|\bconfigure\s*\(\s*dependencies\s*:'Length of output: 5069
Dependencies → Dependency 리네이밍에 따른 호출부 및 구현체 수정 요청
프로토콜 시그니처를 associatedtype Dependency 및 func configure(dependency:)로 변경했으므로, 아직 남아 있는 configure(dependencies:) 호출부와 구현체 시그니처를 모두 dependency 파라미터로 교체해야 합니다. 아래 위치를 확인해 주세요:
-
Projects/Presentation/Sources/RoutineCreation/View/RoutineCreationViewController.swift
- 205행:
self?.subRoutineNameView.configure(dependencies: .init(subRoutines: subroutines)) - 214행:
self?.repeatView.configure(dependencies: .init(repeatType: .none)) - 224행:
self?.repeatView.configure(dependencies: .init(repeatType: .daily)) - 231행:
self?.repeatView.configure(dependencies: .init(repeatType: .weekly(weeks: weeks))) - 240행:
self?.periodView.configure(dependencies: .init(dates: (start, end))) - 247행:
self?.timeView.configure(dependencies: .init(startTime: startAt))
- 205행:
-
Projects/Presentation/Sources/RoutineCreation/View/Component/RoutineCreationCardView.swift
- 206행:
func configure(dependencies: ContentView.Dependency)
- 206행:
위 모든 호출과 시그니처에서
- 파라미터 이름
dependencies→dependency - 메소드 호출
configure(dependencies:)→configure(dependency:)
로 수정하고, 전달하는 인스턴스가Dependency타입으로 올바르게 초기화되는지 확인해 주세요.
| try await routineUseCase.saveRoutine( | ||
| routineSummary: routineSummary, | ||
| subRoutineSummaries: subRoutinesSubject.value, | ||
| subRoutineSummaries: [], // TODO: - 수정 필요 |
There was a problem hiding this comment.
TODO 주석 해결 필요
서브루틴 저장 로직이 빈 배열로 하드코딩되어 있습니다. 실제 서브루틴 데이터를 저장하도록 구현이 필요합니다.
try await routineUseCase.saveRoutine(
routineSummary: routineSummary,
- subRoutineSummaries: [], // TODO: - 수정 필요
+ subRoutineSummaries: subRoutinesSubject.value
+ .enumerated()
+ .filter { !$0.element.isEmpty }
+ .map { index, name in
+ SubRoutineSummaryEntity(
+ subRoutineId: nil,
+ subRoutineName: name,
+ orderNumber: index
+ )
+ },
deletedSubRoutineSummaries: Array(deletedSubroutines))이 구현을 완성하기 위해 새로운 이슈를 생성할까요?
📝 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.
| subRoutineSummaries: [], // TODO: - 수정 필요 | |
| try await routineUseCase.saveRoutine( | |
| routineSummary: routineSummary, | |
| subRoutineSummaries: subRoutinesSubject.value | |
| .enumerated() | |
| .filter { !$0.element.isEmpty } | |
| .map { index, name in | |
| SubRoutineSummaryEntity( | |
| subRoutineId: nil, | |
| subRoutineName: name, | |
| orderNumber: index | |
| ) | |
| }, | |
| deletedSubRoutineSummaries: Array(deletedSubroutines) | |
| ) |
🧰 Tools
🪛 SwiftLint (0.57.0)
[Warning] 256-256: TODOs should be resolved (- 수정 필요)
(todo)
🤖 Prompt for AI Agents
In
Projects/Presentation/Sources/RoutineCreation/ViewModel/RoutineCreationViewModel.swift
around line 256, the code currently hardcodes subRoutineSummaries: [] — replace
this placeholder with the actual conversion from your in-memory sub-routine view
models to the domain summary models (e.g., map subRoutineViewModels or
subRoutines into an array of SubRoutineSummary by pulling required fields like
id/title/duration/order, handling optionals/defaults, and preserving
order/identifiers). Ensure you call the builder/initializer used elsewhere for
summaries, remove the TODO comment, and keep validation/error handling so the
save path stores real sub-routine data instead of an empty array.
choijungp
left a comment
There was a problem hiding this comment.
딩 .......................
너무너무너무 잘해주셔가주구 ... 어푸루부 드립니다 ㅠ ㅠ
저의 지능 이슈로 .. 혹시 이따 회의할 때 간략 브리핑 부탁드려두 될깝쇼 ?????? ?????
하지만 띵이 다 옳게 하고 있다고 생각함 ..
| case .startDateSetTapped: | ||
| self?.dateSelectionType = .start | ||
| case .endDateSetTapped: | ||
| self?.dateSelectionType = .end |
There was a problem hiding this comment.
이건 단순 궁굼한 점인데요
start <= end 여야 하는거잖아요 .. 만일 start가 end 보다 이후면 어떻게 되나요 ?? ㅠㅠ !!!!!
서버에서 이를 막아놨는지 .. 아니라면 클라라도 막아놔야한다고 생각함 .. 하지만 이것보단 빨리 구현이 우선이라구 생각해요 ㅠㅠ !!
🌁 Background
👩💻 Contents
📝 Review Note
분명히 2~300 줄 수준인줄 알았는데,, 송구하옵니다 ㅜㅜ
인터렉션 처리 흐름 View -> ViewModel (RoutineNameContentView를 예시로 들어서)
RoutineCreationExpandable를 채택한 UI 컴포넌트입니다.enum Action이 정의되어 있습니다.action이라는 클로저 프로퍼티를 가지고 있으며, **해당 클로저의 파라미터 타입은 위에서 정의한Action**입니다.Action타입으로 정의Action을 클로저(action)로 외부에 전달view 업데이트 흐름
cardView자체를 설정한느 함수, 두번째는cardView내의RoutineCreationExpandable를 설정하는 함수입니다. 일단 이렇게 이원화하는 자체가 좋은 구조는 아닌것 같습니다. 외부인 VC에서 봤을때는, 단순히configure를 통해CardView를 설정할 수 있구나~ 라고만 생각할 수 있는 구조가 더 좋다 생각하기 때문입니다.RoutineCreationExpandable은 associatedType으로 모두Dependency라는 구조체를 가지게 됩니다.func configure(dependency: Dependency)를 통해, 외부에서 의존성을 주입받아 view를 재구성하는 방식입니다.Summary by CodeRabbit