diff --git a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSaleCardPresentPaymentSuccessMessageView.swift b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSaleCardPresentPaymentSuccessMessageView.swift index c9ddc1cc390..db2d13af643 100644 --- a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSaleCardPresentPaymentSuccessMessageView.swift +++ b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSaleCardPresentPaymentSuccessMessageView.swift @@ -68,7 +68,7 @@ struct PointOfSaleCardPresentPaymentSuccessMessageView: View { .frame(width: Constants.imageSize.width, height: Constants.imageSize.height) .shadow(color: Color(.wooCommerceEmerald(.shade80)).opacity(Constants.shadowOpacity), radius: Constants.shadowRadius, x: Constants.shadowSize.width, y: Constants.shadowSize.height) - .foregroundColor(circleBackgroundColor) + .foregroundColor(.posSuccessColor) Image(PointOfSaleAssets.successCheck.imageName) .renderingMode(.template) .foregroundColor(checkmarkColor) @@ -77,10 +77,6 @@ struct PointOfSaleCardPresentPaymentSuccessMessageView: View { } } - private var circleBackgroundColor: Color { - Color(red: 8/255, green: 251/255, blue: 135/255) - } - private var checkmarkColor: Color { Color.primary } diff --git a/WooCommerce/Classes/POS/Presentation/PointOfSaleCollectCashView.swift b/WooCommerce/Classes/POS/Presentation/PointOfSaleCollectCashView.swift index a334c0a8270..0207801398f 100644 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleCollectCashView.swift +++ b/WooCommerce/Classes/POS/Presentation/PointOfSaleCollectCashView.swift @@ -25,81 +25,84 @@ struct PointOfSaleCollectCashView: View { allowNegativeNumber: false) var body: some View { - VStack(alignment: .center, spacing: conditionalPadding(8)) { - HStack { + ScrollView { + VStack(alignment: .center, spacing: conditionalPadding(8)) { + HStack { + Button(action: { + Task { @MainActor in + await posModel.cancelCashPayment() + isTextFieldFocused = false + } + }, label: { + navigationHeader + }) + .disabled(isLoading) + Spacer() + .renderedIf(!dynamicTypeSize.isAccessibilitySize) + } + + FormattableAmountTextField(viewModel: textFieldViewModel, style: .pos) + .focused($isTextFieldFocused) + .dynamicTypeSize(...DynamicTypeSize.accessibility1) + .onSubmit { + Task { @MainActor in + await submitCashAmount() + } + } + .onChange(of: textFieldViewModel.amount) { newValue in + textFieldAmountInput = newValue + updateChangeDueMessage() + } + + if let changeDue = changeDueMessage { + Text(changeDue) + .font(.posBodyRegular) + .foregroundColor(.posSecondaryText) + } + + if let errorMessage = errorMessage { + Text(errorMessage) + .font(POSFontStyle.posBodyRegular) + .foregroundColor(.red) + .padding(.bottom, Constants.errorMessagePadding) + } + Button(action: { Task { @MainActor in - await posModel.cancelCashPayment() - isTextFieldFocused = false + await submitCashAmount() } }, label: { - navigationHeader + ZStack { + if isLoading { + ProgressView() + .progressViewStyle(CircularProgressViewStyle()) + .tint(Color.posPrimaryTextInverted) + } else { + Text(Localization.markPaymentCompletedButtonTitle) + .font(Constants.buttonFont) + } + } + .frame(maxWidth: .infinity, minHeight: Constants.buttonMinHeight) }) - .disabled(isLoading) - Spacer() - .renderedIf(!dynamicTypeSize.isAccessibilitySize) - } - - FormattableAmountTextField(viewModel: textFieldViewModel, style: .pos) - .focused($isTextFieldFocused) + .adaptiveButtonPadding(Constants.buttonPadding) + .frame(maxWidth: .infinity) + .foregroundColor(colorScheme == .light ? Color.white : Color.black) + .background(Color.posPrimaryButtonBackground) + .cornerRadius(Constants.buttonCornerRadius) + .contentShape(Rectangle()) .dynamicTypeSize(...DynamicTypeSize.accessibility1) - .onSubmit { - Task { @MainActor in - await submitCashAmount() - } - } - .onChange(of: textFieldViewModel.amount) { newValue in - textFieldAmountInput = newValue - updateChangeDueMessage() - } + .disabled(isLoading) - if let changeDue = changeDueMessage { - Text(changeDue) - .font(.posBodyRegular) - .foregroundColor(.posTextSuccess) + Spacer() } - - if let errorMessage = errorMessage { - Text(errorMessage) - .font(POSFontStyle.posBodyRegular) - .foregroundColor(.red) + .background(backgroundColor) + .padding(.top, conditionalPadding(Constants.navigationHeaderTopPadding)) + .padding([.horizontal, .bottom]) + .animation(.easeInOut, value: errorMessage) + .animation(.easeInOut, value: changeDueMessage) + .onChange(of: textFieldAmountInput) { _ in + errorMessage = nil } - - Button(action: { - Task { @MainActor in - await submitCashAmount() - } - }, label: { - ZStack { - if isLoading { - ProgressView() - .progressViewStyle(CircularProgressViewStyle()) - .tint(Color.posPrimaryTextInverted) - } else { - Text(Localization.markPaymentCompletedButtonTitle) - .font(Constants.buttonFont) - } - } - .frame(maxWidth: .infinity, minHeight: Constants.buttonMinHeight) - }) - .padding(conditionalPadding(Constants.buttonPadding)) - .frame(maxWidth: .infinity) - .foregroundColor(colorScheme == .light ? Color.white : Color.black) - .background(Color.posPrimaryButtonBackground) - .cornerRadius(Constants.buttonCornerRadius) - .contentShape(Rectangle()) - .dynamicTypeSize(...DynamicTypeSize.accessibility1) - .disabled(isLoading) - - Spacer() - } - .background(backgroundColor) - .padding(.top, conditionalPadding(Constants.navigationHeaderTopPadding)) - .padding([.horizontal, .bottom]) - .animation(.easeInOut, value: errorMessage) - .animation(.easeInOut, value: changeDueMessage) - .onChange(of: textFieldAmountInput) { _ in - errorMessage = nil } } @@ -170,6 +173,7 @@ private extension PointOfSaleCollectCashView { static let navigationHeaderTopPadding: CGFloat = 8 static let buttonFont: POSFontStyle = .posBodyEmphasized static let buttonCornerRadius: CGFloat = 8 + static let errorMessagePadding: CGFloat = 8 } private func conditionalPadding(_ padding: CGFloat) -> CGFloat { diff --git a/WooCommerce/Classes/POS/Presentation/Reusable Views/POSSendReceiptView.swift b/WooCommerce/Classes/POS/Presentation/Reusable Views/POSSendReceiptView.swift index b0b8487e03f..7373169c114 100644 --- a/WooCommerce/Classes/POS/Presentation/Reusable Views/POSSendReceiptView.swift +++ b/WooCommerce/Classes/POS/Presentation/Reusable Views/POSSendReceiptView.swift @@ -56,6 +56,7 @@ struct POSSendReceiptView: View { Text(errorMessage) .font(POSFontStyle.posBodyRegular) .foregroundColor(.red) + .padding(.bottom, Constants.errorMessagePadding) } Button(action: { @@ -119,13 +120,14 @@ private extension POSSendReceiptView { static let buttonPadding: CGFloat = 32 static let buttonFont: POSFontStyle = .posBodyEmphasized static let buttonCornerRadius: CGFloat = 8 + static let errorMessagePadding: CGFloat = 8 } private func conditionalPadding(_ padding: CGFloat) -> CGFloat { if dynamicTypeSize.isAccessibilitySize { return 0 } else if dynamicTypeSize >= .xLarge { - return padding * 0.5 + return padding * 0.8 } else { return padding } diff --git a/WooCommerce/Classes/POS/Utils/AdaptiveButtonPaddingModifier.swift b/WooCommerce/Classes/POS/Utils/AdaptiveButtonPaddingModifier.swift new file mode 100644 index 00000000000..1e9325abc9d --- /dev/null +++ b/WooCommerce/Classes/POS/Utils/AdaptiveButtonPaddingModifier.swift @@ -0,0 +1,41 @@ +import SwiftUI + +struct AdaptiveButtonPaddingModifier: ViewModifier { + @Environment(\.dynamicTypeSize) private var dynamicTypeSize + let defaultButtonPadding: CGFloat + + func body(content: Content) -> some View { + content + .padding(adjustablePadding(for: dynamicTypeSize, + defaultButtonPadding: defaultButtonPadding)) + } + + private func adjustablePadding(for size: DynamicTypeSize, defaultButtonPadding: CGFloat) -> CGFloat { + switch size { + case .xxxLarge: + return defaultButtonPadding * 0.7 + case .xxLarge: + return defaultButtonPadding * 0.8 + case .xLarge: + return defaultButtonPadding * 0.9 + case .accessibility1: + return defaultButtonPadding * 0.6 + case .accessibility2: + return defaultButtonPadding * 0.5 + case .accessibility3: + return defaultButtonPadding * 0.4 + case .accessibility4: + return defaultButtonPadding * 0.3 + case .accessibility5: + return defaultButtonPadding * 0.2 + default: + return defaultButtonPadding + } + } +} + +extension View { + func adaptiveButtonPadding(_ defaultButtonPadding: CGFloat) -> some View { + modifier(AdaptiveButtonPaddingModifier(defaultButtonPadding: defaultButtonPadding)) + } +} diff --git a/WooCommerce/Classes/POS/Utils/Color+WooCommercePOS.swift b/WooCommerce/Classes/POS/Utils/Color+WooCommercePOS.swift index 48df6dbc1da..f1c8aa3c5e3 100644 --- a/WooCommerce/Classes/POS/Utils/Color+WooCommercePOS.swift +++ b/WooCommerce/Classes/POS/Utils/Color+WooCommercePOS.swift @@ -95,11 +95,11 @@ extension Color { ) } - static var posTextSuccess: Color { + static var posSuccessColor: Color { Color( UIColor( - light: UIColor(red: 10.0/255.0, green: 148.0/255.0, blue: 0.0/255.0, alpha: 1.0), - dark: UIColor(red: 10.0/255.0, green: 148.0/255.0, blue: 0.0/255.0, alpha: 1.0) + light: UIColor(red: 8.0/255.0, green: 251.0/255.0, blue: 135.0/255.0, alpha: 1.0), + dark: UIColor(red: 2.0/255.0, green: 140.0/255.0, blue: 89.0/255.0, alpha: 1.0) ) ) } diff --git a/WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/FormattableAmountTextField.swift b/WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/FormattableAmountTextField.swift index d6f6f87b07a..ebc81a0d00c 100644 --- a/WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/FormattableAmountTextField.swift +++ b/WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/FormattableAmountTextField.swift @@ -74,3 +74,11 @@ private extension FormattableAmountTextField { } } } + +#Preview { + let viewModel = FormattableAmountTextFieldViewModel(size: .extraLarge, + locale: .current, + storeCurrencySettings: .init(), + allowNegativeNumber: false) + FormattableAmountTextField(viewModel: viewModel, style: .pos) +} diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index 22b46620bfc..93d9ee59122 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -1613,6 +1613,7 @@ 68E674AB2A4DAB8C0034BA1E /* CompletedUpgradeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68E674AA2A4DAB8C0034BA1E /* CompletedUpgradeView.swift */; }; 68E674AD2A4DAC010034BA1E /* CurrentPlanDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68E674AC2A4DAC010034BA1E /* CurrentPlanDetailsView.swift */; }; 68E674AF2A4DACD50034BA1E /* UpgradeTopBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68E674AE2A4DACD50034BA1E /* UpgradeTopBarView.swift */; }; + 68E8C04C2D4285C50094FCAC /* AdaptiveButtonPaddingModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68E8C04B2D4285C30094FCAC /* AdaptiveButtonPaddingModifier.swift */; }; 68E952CC287536010095A23D /* SafariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68E952CB287536010095A23D /* SafariView.swift */; }; 68E952D0287587BF0095A23D /* CardReaderManualRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68E952CF287587BF0095A23D /* CardReaderManualRowView.swift */; }; 68E952D22875A44B0095A23D /* CardReaderType+Manual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68E952D12875A44B0095A23D /* CardReaderType+Manual.swift */; }; @@ -4729,6 +4730,7 @@ 68E674AA2A4DAB8C0034BA1E /* CompletedUpgradeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletedUpgradeView.swift; sourceTree = ""; }; 68E674AC2A4DAC010034BA1E /* CurrentPlanDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentPlanDetailsView.swift; sourceTree = ""; }; 68E674AE2A4DACD50034BA1E /* UpgradeTopBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpgradeTopBarView.swift; sourceTree = ""; }; + 68E8C04B2D4285C30094FCAC /* AdaptiveButtonPaddingModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptiveButtonPaddingModifier.swift; sourceTree = ""; }; 68E952CB287536010095A23D /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = ""; }; 68E952CF287587BF0095A23D /* CardReaderManualRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardReaderManualRowView.swift; sourceTree = ""; }; 68E952D12875A44B0095A23D /* CardReaderType+Manual.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CardReaderType+Manual.swift"; sourceTree = ""; }; @@ -7010,6 +7012,7 @@ 026826972BF59D9E0036F959 /* Utils */ = { isa = PBXGroup; children = ( + 68E8C04B2D4285C30094FCAC /* AdaptiveButtonPaddingModifier.swift */, 026826982BF59DA80036F959 /* Color+WooCommercePOS.swift */, 68E4E8B42C0EF39D00CFA0C3 /* PreviewHelpers.swift */, DA4104392C247B6900E8456A /* PointOfSalePreviewOrderController.swift */, @@ -15453,6 +15456,7 @@ 01BB6C072D09DC560094D55B /* CardPresentModalLocationPreAlert.swift in Sources */, 74B5713621CD7604008F9B8E /* SharingHelper.swift in Sources */, 261F1A7929C2AB2E001D9861 /* FreeTrialBannerViewModel.swift in Sources */, + 68E8C04C2D4285C50094FCAC /* AdaptiveButtonPaddingModifier.swift in Sources */, DEF657A82C895B0500ACD61E /* BlazeCampaignObjectivePickerViewModel.swift in Sources */, 0313651328ABCB2D00EEE571 /* InPersonPaymentsOnboardingErrorMainContentView.swift in Sources */, B9F148962AD55326008FC795 /* FormattableAmountTextField.swift in Sources */,