// // DayPickerSheet.swift // Workouts // // Copyright 2026 Rouslan Zenetl. All Rights Reserved. // import SwiftUI import UIKit /// The calendar toolbar button's sheet: jumps the Today board to any day. Days with /// at least one logged workout carry a small dot. Built on `UICalendarView` rather /// than the SwiftUI graphical `DatePicker` solely because only the UIKit calendar /// supports per-day decorations. Picking a day (or "Today") dismisses immediately — /// this is navigation, not a form, so there's nothing to confirm. struct DayPickerSheet: View { @Binding var selectedDate: Date /// Day-precision (year/month/day) components of the days to decorate. let workoutDays: Set @Environment(\.dismiss) private var dismiss var body: some View { NavigationStack { DayCalendarView(selectedDate: $selectedDate, workoutDays: workoutDays) { dismiss() } .padding(.horizontal) .navigationTitle("Go to Day") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .topBarLeading) { Button("Today") { selectedDate = Date() dismiss() } } ToolbarItem(placement: .topBarTrailing) { Button("Done") { dismiss() } } } } .presentationDetents([.medium, .large]) } } /// `UICalendarView` wrapper: single-date selection plus a dot decoration on each /// day in `workoutDays`. private struct DayCalendarView: UIViewRepresentable { @Binding var selectedDate: Date let workoutDays: Set /// Called after a day is picked — the sheet dismisses itself here. var onPick: () -> Void func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> UICalendarView { let view = UICalendarView() view.calendar = Calendar.current view.delegate = context.coordinator let selection = UICalendarSelectionSingleDate(delegate: context.coordinator) selection.setSelected( Calendar.current.dateComponents([.year, .month, .day], from: selectedDate), animated: false ) view.selectionBehavior = selection return view } func updateUIView(_ uiView: UICalendarView, context: Context) { context.coordinator.parent = self } @MainActor final class Coordinator: NSObject, UICalendarViewDelegate, UICalendarSelectionSingleDateDelegate { var parent: DayCalendarView init(_ parent: DayCalendarView) { self.parent = parent } func calendarView(_ calendarView: UICalendarView, decorationFor dateComponents: DateComponents) -> UICalendarView.Decoration? { // The view hands back components richer than year/month/day (era, calendar, // …) — reduce to day precision so set membership compares equal. var day = DateComponents() day.year = dateComponents.year day.month = dateComponents.month day.day = dateComponents.day return parent.workoutDays.contains(day) ? .default(color: .systemGreen, size: .small) : nil } func dateSelection(_ selection: UICalendarSelectionSingleDate, didSelectDate dateComponents: DateComponents?) { guard let dateComponents, let date = Calendar.current.date(from: dateComponents) else { return } parent.selectedDate = date parent.onPick() } } }