Calendar: show the year (fix "can't navigate past 2026")

Navigation was unbounded, but headers only showed the month name so the
year change was invisible and future months felt unreachable.

- Main calendar header now shows "Month Year".
- Date-picker grid label shows the year.
- Year view gets a chevron year navigator (unbounded) + year label.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
kutesir
2026-06-09 00:48:17 +03:00
parent d09a6c1fe3
commit 7b2b61a228
2 changed files with 33 additions and 8 deletions

View File

@@ -326,9 +326,9 @@ struct CalendarView: View {
} }
.menuStyle(.automatic) .menuStyle(.automatic)
// Center: month name // Center: month + year
Spacer() Spacer()
Text(monthShortTitle) Text(monthTitle)
.font(AppFonts.sans(17, weight: .semibold)) .font(AppFonts.sans(17, weight: .semibold))
.foregroundColor(AppColors.text(cs)) .foregroundColor(AppColors.text(cs))
Spacer() Spacer()
@@ -673,13 +673,38 @@ struct CalendarView: View {
private var yearView: some View { private var yearView: some View {
let year = cal.component(.year, from: displayMonth) let year = cal.component(.year, from: displayMonth)
let months: [Date] = (1...12).compactMap { cal.date(from: DateComponents(year: year, month: $0, day: 1)) } let months: [Date] = (1...12).compactMap { cal.date(from: DateComponents(year: year, month: $0, day: 1)) }
return ScrollView(showsIndicators: false) { return VStack(spacing: 0) {
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())], spacing: 24) { // Year header with navigation (unbounded go as far forward/back as you like).
ForEach(months, id: \.self) { m in HStack {
cvMiniMonth(m) Button { navigateYear(-1) } label: {
Image(systemName: "chevron.left").font(.system(size: 14, weight: .semibold))
.foregroundColor(AppColors.text(cs)).frame(width: 40, height: 40)
}
Spacer()
Text(String(year))
.font(AppFonts.sans(20, weight: .bold)).foregroundColor(AppColors.text(cs))
Spacer()
Button { navigateYear(1) } label: {
Image(systemName: "chevron.right").font(.system(size: 14, weight: .semibold))
.foregroundColor(AppColors.text(cs)).frame(width: 40, height: 40)
} }
} }
.padding(16) .padding(.horizontal, 16).padding(.top, 4)
ScrollView(showsIndicators: false) {
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())], spacing: 24) {
ForEach(months, id: \.self) { m in
cvMiniMonth(m)
}
}
.padding(16)
}
}
}
private func navigateYear(_ offset: Int) {
withAnimation(KisaniSpring.snappy) {
displayMonth = cal.date(byAdding: .year, value: offset, to: displayMonth) ?? displayMonth
} }
} }

View File

@@ -2560,7 +2560,7 @@ struct CalendarGridView: View {
} }
private var monthLabel: String { private var monthLabel: String {
let f = DateFormatter(); f.dateFormat = "MMMM"; return f.string(from: displayMonth) let f = DateFormatter(); f.dateFormat = "MMMM yyyy"; return f.string(from: displayMonth)
} }
private func shift(_ d: Int) { private func shift(_ d: Int) {