@@ -4,13 +4,12 @@ import SwiftUI
44
55struct DateRangeSelectorSheetItem : SheetItem {
66 let id : SheetID = . dateRangeSelector
7- let size : SheetSize = . medium
7+ let size : SheetSize = . calendar
88}
99
1010// MARK: - DateRangeSelectorSheet
1111
1212struct DateRangeSelectorSheet : View {
13- @EnvironmentObject private var sheets : SheetViewModel
1413 @Environment ( \. calendar) var calendar
1514 @ObservedObject var viewModel : ActivityListViewModel
1615 @Binding var isPresented : Bool
@@ -41,14 +40,25 @@ struct DateRangeSelectorSheet: View {
4140 }
4241
4342 private var daysInMonth : [ Date ? ] {
44- guard let monthInterval = calendar. dateInterval ( of: . month, for: displayedMonth) ,
45- let monthFirstWeek = calendar. dateInterval ( of: . weekOfMonth, for: monthInterval. start)
46- else {
43+ guard let monthInterval = calendar. dateInterval ( of: . month, for: displayedMonth) else {
44+ return [ ]
45+ }
46+
47+ // Get the first day of the month
48+ let firstDayOfMonth = monthInterval. start
49+
50+ // Find the first day of the week that contains the first day of the month
51+ // This ensures alignment with the weekday headers
52+ let firstWeekday = calendar. component ( . weekday, from: firstDayOfMonth)
53+ let firstDayOfWeek = calendar. firstWeekday
54+ let daysToSubtract = ( firstWeekday - firstDayOfWeek + 7 ) % 7
55+
56+ guard let calendarStartDate = calendar. date ( byAdding: . day, value: - daysToSubtract, to: firstDayOfMonth) else {
4757 return [ ]
4858 }
4959
5060 var days : [ Date ? ] = [ ]
51- var currentDate = monthFirstWeek . start
61+ var currentDate = calendarStartDate
5262
5363 while days. count < 42 { // 6 weeks max
5464 if calendar. isDate ( currentDate, equalTo: displayedMonth, toGranularity: . month) {
@@ -74,37 +84,39 @@ struct DateRangeSelectorSheet: View {
7484 VStack ( alignment: . leading, spacing: 16 ) {
7585 // Month navigation
7686 HStack {
77- Text ( monthYearString)
78- . font ( . custom( Fonts . semiBold, size: 17 ) )
79- . foregroundColor ( . white)
87+ BodyMSBText ( monthYearString)
8088 Spacer ( )
8189
8290 Button ( action: previousMonth) {
83- Image ( systemName: " chevron.left " )
91+ Image ( " chevron " )
92+ . resizable ( )
8493 . foregroundColor ( . brandAccent)
85- . frame ( width: 44 , height: 44 )
94+ . frame ( width: 24 , height: 24 )
95+ . rotationEffect ( . degrees( 180 ) )
96+ . frame ( width: 44 , height: 44 ) // Increase hit area
8697 }
8798 . padding ( . leading, 8 )
8899 . accessibilityIdentifier ( " PrevMonth " )
89100
90101 Button ( action: nextMonth) {
91- Image ( systemName: " chevron.right " )
102+ Image ( " chevron " )
103+ . resizable ( )
92104 . foregroundColor ( . brandAccent)
93- . frame ( width: 44 , height: 44 )
105+ . frame ( width: 24 , height: 24 )
106+ . frame ( width: 44 , height: 44 ) // Increase hit area
94107 }
95108 . accessibilityIdentifier ( " NextMonth " )
96109 }
97110 . padding ( . horizontal, 16 )
98111
99112 // Weekday headers
100113 HStack ( spacing: 0 ) {
101- ForEach ( calendar . shortWeekdaySymbols , id: \. self) { symbol in
102- CaptionText ( symbol . uppercased ( ) )
103- . foregroundColor ( . white64 )
114+ ForEach ( 0 ..< 7 , id: \. self) { index in
115+ let weekdayIndex = ( index + calendar . firstWeekday - 1 ) % 7
116+ CaptionMText ( calendar . shortWeekdaySymbols [ weekdayIndex ] )
104117 . frame ( maxWidth: . infinity)
105118 }
106119 }
107- . padding ( . horizontal, 16 )
108120
109121 // Calendar grid
110122 LazyVGrid ( columns: Array ( repeating: GridItem ( . flexible( ) , spacing: 0 ) , count: 7 ) , spacing: 8 ) {
@@ -122,11 +134,10 @@ struct DateRangeSelectorSheet: View {
122134 . accessibilityIdentifier ( calendar. isDateInToday ( date) ? " Today " : " Day- \( calendar. component ( . day, from: date) ) " )
123135 } else {
124136 Color . clear
125- . frame ( height: 40 )
137+ . frame ( height: 48 )
126138 }
127139 }
128140 }
129- . padding ( . horizontal, 16 )
130141
131142 // Display selected range (fixed height to prevent layout jump)
132143 VStack {
@@ -172,7 +183,6 @@ struct DateRangeSelectorSheet: View {
172183 startDate = nil
173184 endDate = nil
174185 viewModel. clearDateRange ( )
175- isPresented = false
176186 }
177187 . accessibilityIdentifier ( " CalendarClearButton " )
178188
@@ -278,9 +288,23 @@ struct CalendarDayView: View {
278288 } else if isStartDate {
279289 Circle ( )
280290 . fill ( Color . brand16)
291+ UnevenRoundedRectangle (
292+ topLeadingRadius: 44 ,
293+ bottomLeadingRadius: 44 ,
294+ bottomTrailingRadius: 0 ,
295+ topTrailingRadius: 0
296+ )
297+ . fill ( Color . brand16)
281298 } else if isEndDate {
282299 Circle ( )
283300 . fill ( Color . brand16)
301+ UnevenRoundedRectangle (
302+ topLeadingRadius: 0 ,
303+ bottomLeadingRadius: 0 ,
304+ bottomTrailingRadius: 44 ,
305+ topTrailingRadius: 44
306+ )
307+ . fill ( Color . brand16)
284308 } else {
285309 // Middle of range
286310 Rectangle ( )
@@ -289,18 +313,16 @@ struct CalendarDayView: View {
289313 }
290314
291315 // Day number
292- Text ( dayNumber)
293- . font ( . custom( Fonts . regular, size: 16 ) )
294- . foregroundColor ( isStartDate || isEndDate ? Color . brandAccent : Color . white)
316+ BodyMSBText ( dayNumber, textColor: isStartDate || isEndDate ? Color . brandAccent : Color . white)
295317
296318 // Today indicator
297319 if isToday && !isSelected {
298320 Circle ( )
299- . stroke ( Color . brandAccent , lineWidth : 1 )
321+ . fill ( Color . white10 )
300322 }
301323 }
302324 }
303- . frame ( height: 40 )
325+ . frame ( height: 48 )
304326 }
305327}
306328
0 commit comments