-
Notifications
You must be signed in to change notification settings - Fork 0
Hotfix/#126 쿼리파라미터 수정 및 자체QA 조금 #130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The head ref may contain hidden characters: "hotfix/#126-\uCFFC\uB9AC\uD30C\uB77C\uBBF8\uD130-\uC218\uC815"
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -23,7 +23,7 @@ enum CalendarMode { | |||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| struct CalendarView: View { | ||||||||||||||||||||||||||||
| @EnvironmentObject private var calendarCoordinator: CalendarCoordinator | ||||||||||||||||||||||||||||
| @ObservedObject var viewModel: CalendarViewModel | ||||||||||||||||||||||||||||
| @StateObject var viewModel: CalendarViewModel | ||||||||||||||||||||||||||||
| @State private var topGlobalY: CGFloat = .zero | ||||||||||||||||||||||||||||
| @State private var initialTopGlobalY: CGFloat? = nil | ||||||||||||||||||||||||||||
| @State private var bottomOffsetY: CGFloat = .zero | ||||||||||||||||||||||||||||
|
|
@@ -32,20 +32,28 @@ struct CalendarView: View { | |||||||||||||||||||||||||||
| @State private var buttonState: ButtonState = .active | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| private let scrollAreaHeight: CGFloat = 184.adjustedH | ||||||||||||||||||||||||||||
| private let calendarCellWidth: CGFloat = 40.adjustedW | ||||||||||||||||||||||||||||
| private let calendarCellHeight: CGFloat = 40.adjustedH | ||||||||||||||||||||||||||||
| private let calendarRowSpacing: CGFloat = 8.adjustedH | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| let weekdays: [String] = ["일", "월", "화", "수", "목", "금", "토"] | ||||||||||||||||||||||||||||
| let columns = Array(repeating: GridItem(.fixed(40), spacing: 8), count: 7) | ||||||||||||||||||||||||||||
| let columns = Array(repeating: GridItem(.fixed(40.adjustedW), spacing: 8), count: 7) | ||||||||||||||||||||||||||||
|
Comment on lines
+35
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial 상수 일관성 개선 권장
♻️ 상수 사용 권장- let columns = Array(repeating: GridItem(.fixed(40.adjustedW), spacing: 8), count: 7)
+ let columns = Array(repeating: GridItem(.fixed(calendarCellWidth), spacing: calendarRowSpacing), count: 7)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 요기 spacing에도 기기대응 해야하나요? |
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| var body: some View { | ||||||||||||||||||||||||||||
| VStack { | ||||||||||||||||||||||||||||
| Spacer() | ||||||||||||||||||||||||||||
| .frame(height: 38.adjustedH) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| calendarHeader | ||||||||||||||||||||||||||||
| dateGridsView | ||||||||||||||||||||||||||||
| Spacer() | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if viewModel.isEmptyProcedureList() { | ||||||||||||||||||||||||||||
| emptyScheduleView | ||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||
| scheduleListContainerView | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Spacer() | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| .task (id: viewModel.currentMonth){ | ||||||||||||||||||||||||||||
| if calendarMode == .none { | ||||||||||||||||||||||||||||
|
|
@@ -66,7 +74,7 @@ extension CalendarView { | |||||||||||||||||||||||||||
| VStack { | ||||||||||||||||||||||||||||
| HStack { | ||||||||||||||||||||||||||||
| Image(.chevronLeft) | ||||||||||||||||||||||||||||
| .frame(width: 40, height: 40) | ||||||||||||||||||||||||||||
| .frame(width: 40.adjustedW, height: 40.adjustedH) | ||||||||||||||||||||||||||||
| .scaledToFit() | ||||||||||||||||||||||||||||
| .onTapGesture { | ||||||||||||||||||||||||||||
| viewModel.currentMonth -= 1 | ||||||||||||||||||||||||||||
|
|
@@ -80,30 +88,32 @@ extension CalendarView { | |||||||||||||||||||||||||||
| Spacer() | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Image(.chevronRight) | ||||||||||||||||||||||||||||
| .frame(width: 40, height: 40) | ||||||||||||||||||||||||||||
| .frame(width: 40.adjustedW, height: 40.adjustedH) | ||||||||||||||||||||||||||||
| .scaledToFit() | ||||||||||||||||||||||||||||
| .onTapGesture { | ||||||||||||||||||||||||||||
| viewModel.currentMonth += 1 | ||||||||||||||||||||||||||||
| viewModel.selectedDate = viewModel.firstDateOfCurrentMonth() | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| .padding(.horizontal, 11) | ||||||||||||||||||||||||||||
| .padding(.top, 38) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| .padding(.horizontal, 11.adjustedW) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| HStack(spacing: 8) { | ||||||||||||||||||||||||||||
| ForEach(weekdays, id: \.self) { weekday in | ||||||||||||||||||||||||||||
| TypographyText(weekday, style: .body1_r_14, color: .gray800) | ||||||||||||||||||||||||||||
| .frame(width: 40, height: 40) | ||||||||||||||||||||||||||||
| .frame(width: 40.adjustedW, height: 40.adjustedH) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| .padding(.horizontal, 23) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 23.adjustedH) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| private var dateGridsView: some View { | ||||||||||||||||||||||||||||
| LazyVGrid(columns: columns) { | ||||||||||||||||||||||||||||
| ForEach(viewModel.getDatesArray()) { value in | ||||||||||||||||||||||||||||
| let dates = viewModel.getDatesArray() | ||||||||||||||||||||||||||||
| let rowCount = dates.count / 7 | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| return VStack(spacing: 0) { | ||||||||||||||||||||||||||||
| LazyVGrid(columns: columns, spacing: calendarRowSpacing) { | ||||||||||||||||||||||||||||
| ForEach(dates) { value in | ||||||||||||||||||||||||||||
| if value.day != -1 { | ||||||||||||||||||||||||||||
| CalendarCellView( | ||||||||||||||||||||||||||||
| value: value, | ||||||||||||||||||||||||||||
|
|
@@ -127,11 +137,18 @@ extension CalendarView { | |||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||
| Text("").hidden() | ||||||||||||||||||||||||||||
| Color.clear | ||||||||||||||||||||||||||||
| .frame(width: calendarCellWidth, height: calendarCellHeight) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if rowCount == 4 { | ||||||||||||||||||||||||||||
| Spacer() | ||||||||||||||||||||||||||||
| .frame(height: calendarCellHeight + calendarRowSpacing) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| .padding(.horizontal, 23) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 23.adjustedW) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| private var scheduleListContainerView: some View { | ||||||||||||||||||||||||||||
|
|
@@ -157,7 +174,7 @@ extension CalendarView { | |||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| .frame(height: 40.adjustedH) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 20) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 20.adjustedW) | ||||||||||||||||||||||||||||
| .padding(.top, 8) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ZStack { | ||||||||||||||||||||||||||||
|
|
@@ -203,31 +220,31 @@ extension CalendarView { | |||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| GradientBox(isTop: true) | ||||||||||||||||||||||||||||
| .frame(height: 56) | ||||||||||||||||||||||||||||
| .frame(height: 56.adjustedH) | ||||||||||||||||||||||||||||
| .allowsHitTesting(false) | ||||||||||||||||||||||||||||
| .opacity(shouldShowGradientTop ? 1 : 0) | ||||||||||||||||||||||||||||
| .frame(maxHeight: .infinity, alignment: .top) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| GradientBox(isTop: false) | ||||||||||||||||||||||||||||
| .frame(height: 92) | ||||||||||||||||||||||||||||
| .frame(height: 92.adjustedH) | ||||||||||||||||||||||||||||
| .allowsHitTesting(false) | ||||||||||||||||||||||||||||
| .opacity(shouldShowGradientBottom ? 1 : 0) | ||||||||||||||||||||||||||||
| .frame(maxHeight: .infinity, alignment: .bottom) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| .frame(height: scrollAreaHeight.adjustedH) | ||||||||||||||||||||||||||||
| .padding(.top, 6) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 19) | ||||||||||||||||||||||||||||
| .padding(.bottom, 12) | ||||||||||||||||||||||||||||
| .padding(.top, 6.adjustedW) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 19.adjustedW) | ||||||||||||||||||||||||||||
| .padding(.bottom, 12.adjustedH) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| .background( | ||||||||||||||||||||||||||||
| RoundedRectangle(cornerRadius: 10) | ||||||||||||||||||||||||||||
| .fill(.gray0) | ||||||||||||||||||||||||||||
| .cherrishShadow() | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| .padding(.top, 20) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 25) | ||||||||||||||||||||||||||||
| .padding(.bottom, 18) | ||||||||||||||||||||||||||||
| .padding(.top, 20.adjustedH) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 25.adjustedW) | ||||||||||||||||||||||||||||
| .padding(.bottom, 18.adjustedH) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| private var emptyScheduleView: some View { | ||||||||||||||||||||||||||||
|
|
@@ -239,8 +256,8 @@ extension CalendarView { | |||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| TypographyText("오늘 예정된 일정이 없어요.", style: .body1_r_14, color: .gray600) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| .padding(.top, 50) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 65) | ||||||||||||||||||||||||||||
| .padding(.top, 50.adjustedH) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 65.adjustedW) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Spacer() | ||||||||||||||||||||||||||||
| .frame(height: 38.adjustedH) | ||||||||||||||||||||||||||||
|
|
@@ -257,7 +274,7 @@ extension CalendarView { | |||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 24) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 24.adjustedW) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Spacer() | ||||||||||||||||||||||||||||
| .frame(height: 24.adjustedH) | ||||||||||||||||||||||||||||
|
|
@@ -268,9 +285,9 @@ extension CalendarView { | |||||||||||||||||||||||||||
| .cherrishShadow() | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| .frame(width: 326.adjustedW, height: 264.adjustedH) | ||||||||||||||||||||||||||||
| .padding(.top, 20) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 25) | ||||||||||||||||||||||||||||
| .padding(.bottom, 30) | ||||||||||||||||||||||||||||
| .padding(.top, 20.adjustedH) | ||||||||||||||||||||||||||||
| .padding(.horizontal, 25.adjustedW) | ||||||||||||||||||||||||||||
| .padding(.bottom, 30.adjustedH) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| private var downTimeRangeIcons: some View { | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -136,21 +136,29 @@ extension CalendarViewModel { | |
| } | ||
|
|
||
| private func extractDate(currentMonth: Int) -> [DateValue] { | ||
| let calendar = Calendar.current | ||
| var calendar = Calendar(identifier: .gregorian) | ||
| calendar.timeZone = TimeZone(identifier: "Asia/Seoul")! | ||
|
|
||
| let currentMonth = getCurrentMonth(addingMonth: currentMonth) | ||
| var days = currentMonth.getAllDates().compactMap { date -> DateValue in | ||
| let day = calendar.component(.day, from: date) | ||
| return DateValue(day: day, date: date) | ||
| } | ||
| let targetMonthDate = getCurrentMonth(addingMonth: currentMonth) | ||
| let startOfMonth = calendar.date(from: calendar.dateComponents([.year, .month], from: targetMonthDate))! | ||
| let daysInMonth = calendar.range(of: .day, in: .month, for: startOfMonth)?.count ?? 0 | ||
|
|
||
| let firstWeekday = calendar.component(.weekday, from: days.first?.date ?? Date()) | ||
| let firstWeekday = calendar.component(.weekday, from: startOfMonth) | ||
| let leading = firstWeekday - 1 | ||
| let totalCells = leading + daysInMonth | ||
| let rows = Int(ceil(Double(totalCells) / 7.0)) | ||
|
|
||
| for _ in 0 ..< firstWeekday - 1 { | ||
| days.insert(DateValue(day: -1, date: Date()), at: 0) | ||
| } | ||
| let gridStart = calendar.date(byAdding: .day, value: -leading, to: startOfMonth)! | ||
|
|
||
| return days | ||
| return (0..<(rows * 7)).map { i in | ||
| let raw = calendar.date(byAdding: .day, value: i, to: gridStart)! | ||
| let date = calendar.startOfDay(for: raw) | ||
|
|
||
| let isInTargetMonth = calendar.isDate(date, equalTo: targetMonthDate, toGranularity: .month) | ||
| let day = isInTargetMonth ? calendar.component(.day, from: date) : -1 | ||
|
|
||
| return DateValue(day: day, date: date) | ||
| } | ||
| } | ||
|
Comment on lines
138
to
162
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial 캘린더 그리드 생성 로직 개선 승인 단일 패스로 캘린더 그리드를 생성하는 깔끔한 리팩토링입니다. 타임존 처리가 일관성 있게 참고: Line 140, 143, 151, 154에서 force unwrap( ♻️ 방어적 코딩 예시 (선택사항) private func extractDate(currentMonth: Int) -> [DateValue] {
var calendar = Calendar(identifier: .gregorian)
- calendar.timeZone = TimeZone(identifier: "Asia/Seoul")!
+ calendar.timeZone = TimeZone(identifier: "Asia/Seoul") ?? .current
let targetMonthDate = getCurrentMonth(addingMonth: currentMonth)
- let startOfMonth = calendar.date(from: calendar.dateComponents([.year, .month], from: targetMonthDate))!
+ guard let startOfMonth = calendar.date(from: calendar.dateComponents([.year, .month], from: targetMonthDate)) else {
+ return []
+ }🤖 Prompt for AI Agents |
||
|
|
||
| private func mapToDowntimeDays(procedure: ProcedureDowntimeEntity) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 2872
🏁 Script executed:
Repository: TEAM-Cherrish/Cherrish-iOS
Length of output: 3866
@StateObject대신@ObservedObject사용 필요CalendarViewModel이 외부의DIContainer에서 생성되어 의존성 주입으로 전달되고 있습니다 (ViewFactory라인 53-57,makeCalendarView(viewModel:)호출). 이 경우@StateObject사용은 부적절합니다.@StateObject: 뷰가 객체를 생성하고 소유할 때만 사용@ObservedObject: 외부에서 주입된 객체를 관찰할 때 사용현재
@StateObject로 선언하면 뷰 재생성 시 예기치 않게 새 인스턴스가 생성될 수 있습니다.@ObservedObject로 변경하세요.🤖 Prompt for AI Agents