diff --git a/WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/RangedDatePicker.swift b/WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/RangedDatePicker.swift new file mode 100644 index 00000000000..c07107606fb --- /dev/null +++ b/WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/RangedDatePicker.swift @@ -0,0 +1,107 @@ +import Foundation +import SwiftUI + +/// View to select a custom date range. +/// Consists of two date pickers laid out vertically. +/// +struct RangedDatePicker: View { + + @Environment(\.presentationMode) var presentation + + /// Closure invoked when the custom date range has been confirmed. + /// + var datesSelected: ((_ start: Date, _ end: Date) -> Void)? + + /// Start date binding variable + /// + @State private var startDate = Date() + + /// End date binding variable + /// + @State private var endDate = Date() + + var body: some View { + NavigationView { + ScrollView { + VStack(alignment: .leading) { + + // Start Picker + Text(Localization.startDate) + .foregroundColor(Color(.accent)) + .headlineStyle() + + Divider() + + DatePicker("", selection: $startDate, in: ...Date(), displayedComponents: [.date]) + .datePickerStyle(.graphical) + .accentColor(Color(.brand)) + + // End Picker + Text(Localization.endDate) + .foregroundColor(Color(.accent)) + .headlineStyle() + + Divider() + + DatePicker("", selection: $endDate, in: ...Date(), displayedComponents: [.date]) + .datePickerStyle(.graphical) + .accentColor(Color(.brand)) + } + .padding() + } + .navigationBarTitleDisplayMode(.inline) + .toolbar(content: { + ToolbarItem(placement: .principal) { + // Navigation Bar title + VStack(spacing: Layout.titleSpacing) { + Text(Localization.title) + .headlineStyle() + + // TODO: Properly format date ranges outside the view + Text("\(DateFormatter.monthAndDayFormatter.string(from: startDate)) - \(DateFormatter.monthAndDayFormatter.string(from: endDate))") + .captionStyle() + } + } + ToolbarItem(placement: .confirmationAction) { + Button(action: { + presentation.wrappedValue.dismiss() + datesSelected?(startDate, endDate) + }, label: { + Text(Localization.apply) + }) + } + ToolbarItem(placement: .cancellationAction) { + Button(action: { + presentation.wrappedValue.dismiss() + }, label: { + Image(uiImage: .closeButton) + }) + } + }) + } + .navigationViewStyle(.stack) + .wooNavigationBarStyle() + } +} + +// MARK: Constant + +private extension RangedDatePicker { + enum Localization { + static let title = NSLocalizedString("Custom Date Range", comment: "Title in custom range date picker") + static let apply = NSLocalizedString("Apply", comment: "Apply navigation button in custom range date picker") + static let startDate = NSLocalizedString("Start Date", comment: "Start Date label in custom range date picker") + static let endDate = NSLocalizedString("End Date", comment: "End Date label in custom range date picker") + } + enum Layout { + static let titleSpacing: CGFloat = 4.0 + } +} + +// MARK: Previews + +struct RangedDatePickerPreview: PreviewProvider { + static var previews: some View { + RangedDatePicker() + } +} diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index b1d7c919ee5..7217a656731 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -635,6 +635,7 @@ 26B3D8A0252235C50054C319 /* RefundShippingDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B3D89F252235C50054C319 /* RefundShippingDetailsViewModel.swift */; }; 26B3EC622744772A0075EAE6 /* SimplePaymentsSummaryViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B3EC612744772A0075EAE6 /* SimplePaymentsSummaryViewModelTests.swift */; }; 26B3EC642745916F0075EAE6 /* BindableTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B3EC632745916F0075EAE6 /* BindableTextField.swift */; }; + 26B71DB6293FE490004D8052 /* RangedDatePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B71DB5293FE490004D8052 /* RangedDatePicker.swift */; }; 26B98758273C5BE30090E8CA /* EditCustomerNoteViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B98757273C5BE30090E8CA /* EditCustomerNoteViewModelProtocol.swift */; }; 26B9875D273C6A830090E8CA /* SimplePaymentsNoteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B9875C273C6A830090E8CA /* SimplePaymentsNoteViewModel.swift */; }; 26B9875F273CB6AA0090E8CA /* SimplePaymentsNoteViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B9875E273CB6AA0090E8CA /* SimplePaymentsNoteViewModelTests.swift */; }; @@ -2646,6 +2647,7 @@ 26B3D89F252235C50054C319 /* RefundShippingDetailsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefundShippingDetailsViewModel.swift; sourceTree = ""; }; 26B3EC612744772A0075EAE6 /* SimplePaymentsSummaryViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimplePaymentsSummaryViewModelTests.swift; sourceTree = ""; }; 26B3EC632745916F0075EAE6 /* BindableTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BindableTextField.swift; sourceTree = ""; }; + 26B71DB5293FE490004D8052 /* RangedDatePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RangedDatePicker.swift; sourceTree = ""; }; 26B98757273C5BE30090E8CA /* EditCustomerNoteViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditCustomerNoteViewModelProtocol.swift; sourceTree = ""; }; 26B9875C273C6A830090E8CA /* SimplePaymentsNoteViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimplePaymentsNoteViewModel.swift; sourceTree = ""; }; 26B9875E273CB6AA0090E8CA /* SimplePaymentsNoteViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimplePaymentsNoteViewModelTests.swift; sourceTree = ""; }; @@ -6209,6 +6211,7 @@ DE2FE5872925DD950018040A /* JetpackInstallHeaderView.swift */, 26E7EE6F29300F6200793045 /* DeltaTag.swift */, AEE9A87F293A3E5500227C92 /* RefreshablePlainList.swift */, + 26B71DB5293FE490004D8052 /* RangedDatePicker.swift */, ); path = "SwiftUI Components"; sourceTree = ""; @@ -9955,6 +9958,7 @@ 7459A6C621B0680300F83A78 /* RequirementsChecker.swift in Sources */, CE1D5A55228A0AD200DF3715 /* TwoColumnTableViewCell.swift in Sources */, 02759B9128FFA09600918176 /* StoreCreationWebViewModel.swift in Sources */, + 26B71DB6293FE490004D8052 /* RangedDatePicker.swift in Sources */, 74460D4222289C7A00D7316A /* StorePickerCoordinator.swift in Sources */, FEDD70AF26A7223500194C3A /* StorageEligibilityErrorInfo+Woo.swift in Sources */, AE9E04752776213E003FA09E /* OrderCustomerSection.swift in Sources */,