Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Foundation
import struct Networking.Booking
import class WooFoundationCore.CurrencyFormatter

extension BookingDetailsViewModel {
struct AppointmentDetailsContent {
Expand Down Expand Up @@ -34,7 +33,10 @@ extension BookingDetailsViewModel {
to: booking.endDate
)
),
Row(title: Localization.appointmentDetailsPriceTitle, value: Self.formatPrice(booking.cost))
Row(
title: Localization.appointmentDetailsPriceTitle,
value: BookingDetailsViewModel.formatPrice(for: booking, priceString: booking.cost)
)
]
}
}
Expand All @@ -51,15 +53,6 @@ private extension BookingDetailsViewModel.AppointmentDetailsContent {
static func formatDuration(from startDate: Date, to endDate: Date) -> String {
durationFormatter.string(from: startDate, to: endDate) ?? ""
}

static func formatPrice(_ price: String) -> String {
guard let decimalPrice = Decimal(string: price) else {
return price
}
return CurrencyFormatter(
currencySettings: ServiceLocator.currencySettings
).formatAmount(decimalPrice) ?? price
}
}

private extension BookingDetailsViewModel.AppointmentDetailsContent {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Foundation
import struct Networking.Booking
import class WooFoundationCore.CurrencyFormatter
import class WooFoundationCore.CurrencySettings
import enum WooFoundationCore.CurrencyCode

extension BookingDetailsViewModel {
static func formatPrice(for booking: Booking, priceString: String) -> String {
guard let decimalPrice = Decimal(string: priceString) else {
return priceString
}
return CurrencyFormatter(
currencySettings: Self.currencySettings(for: booking)
).formatAmount(decimalPrice) ?? priceString
}

private static func currencySettings(for booking: Booking) -> CurrencySettings {
let siteCurrencySettings = ServiceLocator.currencySettings
guard let currencyCode = CurrencyCode(rawValue: booking.currency) else {
return siteCurrencySettings
}

return CurrencySettings(
currencyCode: currencyCode,
currencyPosition: siteCurrencySettings.currencyPosition,
thousandSeparator: siteCurrencySettings.groupingSeparator,
decimalSeparator: siteCurrencySettings.decimalSeparator,
numberOfDecimals: siteCurrencySettings.fractionDigits
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ final class BookingDetailsViewModel: ObservableObject {
let sections: [Section]
let navigationTitle: String

private let booking: Booking

init(booking: Booking) {
self.booking = booking

navigationTitle = Self.navigationTitle(for: booking)

let headerSection = Section.init(
Expand Down Expand Up @@ -59,6 +63,27 @@ final class BookingDetailsViewModel: ObservableObject {
}
}

extension BookingDetailsViewModel {
var cancellationAlertMessage: String {
// Temporary hardcoded
//TODO: - replace with associated customer data
let productName = "Women's Haircut"
let customerName = "Margarita Nikolaevna"

let date = booking.startDate.formatted(
date: .long,
time: .shortened
)

return String(
format: Localization.cancelBookingAlertMessage,
customerName,
productName,
date
)
}
}

private extension BookingDetailsViewModel {
static func navigationTitle(for booking: Booking) -> String {
let titleFormat = NSLocalizedString(
Expand Down Expand Up @@ -107,5 +132,11 @@ private extension BookingDetailsViewModel {
value: "Booking notes",
comment: "Header title for the 'Booking notes' section in the booking details screen."
)

static let cancelBookingAlertMessage = NSLocalizedString(
"BookingDetailsView.cancelation.alert.message",
value: "%1$@ will no longer be able to attend “%2$@” on %3$@.",
comment: "Message for the booking cancellation confirmation alert. %1$@ is customer name, %2$@ is product name, %3$@ is booking date."
)
}
}
34 changes: 12 additions & 22 deletions WooCommerce/Classes/ViewModels/Booking Details/PaymentContent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,21 @@ extension BookingDetailsViewModel {

init(booking: Booking) {
amounts = [
.init(value: Self.formatPrice(booking.cost), type: .service),
.init(value: Self.formatPrice("0"), type: .tax),
.init(value: BookingDetailsViewModel.formatPrice(for: booking, priceString: booking.cost), type: .service),
.init(value: BookingDetailsViewModel.formatPrice(for: booking, priceString: "0"), type: .tax),
.init(value: "-", type: .discount),
.init(value: Self.formatPrice(booking.cost), type: .total, emphasized: true),
.init(value: BookingDetailsViewModel.formatPrice(for: booking, priceString: booking.cost), type: .total, emphasized: true),
]

actions = [
.markAsPaid,
.issueRefund,
.viewOrder
]
}
}
}

private extension BookingDetailsViewModel.PaymentContent {
static func formatPrice(_ price: String) -> String {
guard let decimalPrice = Decimal(string: price) else {
return price
}
return CurrencyFormatter(
currencySettings: ServiceLocator.currencySettings
).formatAmount(decimalPrice) ?? price
}
}

extension BookingDetailsViewModel.PaymentContent {
struct Amount {
enum AmountType {
Expand Down Expand Up @@ -83,7 +73,7 @@ extension BookingDetailsViewModel.PaymentContent.Amount.AmountType {
extension BookingDetailsViewModel.PaymentContent {
enum Action: String, Identifiable {
case markAsPaid
case markAsRefunded
case issueRefund
case viewOrder

var id: String {
Expand All @@ -97,8 +87,8 @@ extension BookingDetailsViewModel.PaymentContent.Action {
switch self {
case .markAsPaid:
return Localization.paymentMarkAsPaidButtonTitle
case .markAsRefunded:
return Localization.paymentMarkAsRefundedButtonTitle
case .issueRefund:
return Localization.paymentIssueRefundButtonTitle
case .viewOrder:
return Localization.paymentViewOrderButtonTitle
}
Expand All @@ -108,7 +98,7 @@ extension BookingDetailsViewModel.PaymentContent.Action {
switch self {
case .markAsPaid:
return true
case .markAsRefunded, .viewOrder:
case .issueRefund, .viewOrder:
return false
}
}
Expand Down Expand Up @@ -145,10 +135,10 @@ private enum Localization {
comment: "Title for 'Mark as paid' button in payment section in booking details view."
)

static let paymentMarkAsRefundedButtonTitle = NSLocalizedString(
"BookingDetailsView.payment.markAsRefunded.title",
value: "Mark as refunded",
comment: "Title for 'Mark as refunded' button in payment section in booking details view."
static let paymentIssueRefundButtonTitle = NSLocalizedString(
"BookingDetailsView.payment.issueRefund.title",
value: "Issue refund",
comment: "Title for 'Issue refund' button in payment section in booking details view."
)

static let paymentViewOrderButtonTitle = NSLocalizedString(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ struct BookingDetailsView: View {
@Environment(\.dismiss) private var dismiss
@State private var showingOptions = false
@State private var showingStatusSheet = false
@State private var showingCancelAlert = false

@ObservedObject private var viewModel: BookingDetailsViewModel

Expand Down Expand Up @@ -78,6 +79,17 @@ struct BookingDetailsView: View {
.presentationDetents([.medium, .large])
.presentationDragIndicator(.visible)
}
.alert(
Localization.cancelBookingAlertTitle,
isPresented: $showingCancelAlert
) {
Button(Localization.cancelBookingAlertCancelAction, role: .cancel) {}
Button(Localization.cancelBookingAlertConfirmAction, role: .destructive) {
print("On cancel booking confirmation tap")
}
} message: {
Text(viewModel.cancellationAlertMessage)
}
}
}

Expand Down Expand Up @@ -185,7 +197,7 @@ private extension BookingDetailsView {
}

Button {
/// On cancel booking button tap
showingCancelAlert = true
} label: {
Text(Localization.cancelBooking)
}
Expand Down Expand Up @@ -356,6 +368,24 @@ private extension BookingDetailsView {
comment: "'Cancel booking' button title in appointment details section in booking details view."
)

static let cancelBookingAlertTitle = NSLocalizedString(
"BookingDetailsView.cancelation.alert.title",
value: "Cancel booking",
comment: "Title for the booking cancellation confirmation alert."
)

static let cancelBookingAlertConfirmAction = NSLocalizedString(
"BookingDetailsView.cancelation.alert.confirmAction",
value: "Yes, cancel it",
comment: "Confirm button title for the booking cancellation confirmation alert."
)

static let cancelBookingAlertCancelAction = NSLocalizedString(
"BookingDetailsView.cancelation.alert.cancelAction",
value: "No, keep it",
comment: "Cancel button title for the booking cancellation confirmation alert."
)

/// Attendance section
static let statusRowTitle = NSLocalizedString(
"BookingDetailsView.customer.status.title",
Expand Down
4 changes: 4 additions & 0 deletions WooCommerce/WooCommerce.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,7 @@
26FE09E124DB8FA000B9BDF5 /* SurveyCoordinatorControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26FE09E024DB8FA000B9BDF5 /* SurveyCoordinatorControllerTests.swift */; };
26FFC50C2BED7C5A0067B3A4 /* WatchDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B249702BEC801400730730 /* WatchDependencies.swift */; };
26FFC50D2BED7C5B0067B3A4 /* WatchDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B249702BEC801400730730 /* WatchDependencies.swift */; };
2D05337E2E951A62004111FD /* BookingDetailsViewModel+PriceFormatting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D05337D2E951A62004111FD /* BookingDetailsViewModel+PriceFormatting.swift */; };
2D05D19F2E82D1A8004111FD /* BookingDetailsViewModel+Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D05D19E2E82D1A3004111FD /* BookingDetailsViewModel+Section.swift */; };
2D05D1A22E82D235004111FD /* HeaderContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D05D1A12E82D233004111FD /* HeaderContent.swift */; };
2D05D1A42E82D266004111FD /* AppointmentDetailsContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D05D1A32E82D25F004111FD /* AppointmentDetailsContent.swift */; };
Expand Down Expand Up @@ -3877,6 +3878,7 @@
26FE09E024DB8FA000B9BDF5 /* SurveyCoordinatorControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SurveyCoordinatorControllerTests.swift; sourceTree = "<group>"; };
26FFD32628C6A0A4002E5E5E /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
26FFD32928C6A0F4002E5E5E /* UIImage+Widgets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Widgets.swift"; sourceTree = "<group>"; };
2D05337D2E951A62004111FD /* BookingDetailsViewModel+PriceFormatting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BookingDetailsViewModel+PriceFormatting.swift"; sourceTree = "<group>"; };
2D05D19E2E82D1A3004111FD /* BookingDetailsViewModel+Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BookingDetailsViewModel+Section.swift"; sourceTree = "<group>"; };
2D05D1A02E82D1EF004111FD /* BookingDetailsViewModel+SectionContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BookingDetailsViewModel+SectionContent.swift"; sourceTree = "<group>"; };
2D05D1A12E82D233004111FD /* HeaderContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderContent.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -7944,6 +7946,7 @@
2D05D1A62E82D49D004111FD /* BookingDetailsViewModel+Status.swift */,
2D05D19E2E82D1A3004111FD /* BookingDetailsViewModel+Section.swift */,
2D05D1A02E82D1EF004111FD /* BookingDetailsViewModel+SectionContent.swift */,
2D05337D2E951A62004111FD /* BookingDetailsViewModel+PriceFormatting.swift */,
);
path = "Booking Details";
sourceTree = "<group>";
Expand Down Expand Up @@ -14919,6 +14922,7 @@
45CE2D322625AA9A00E3CA00 /* ShippingLabelPackageList.swift in Sources */,
AEFF77A42978389400667F7A /* PriceInputViewController.swift in Sources */,
02535CBB25823F7A00E137BB /* ShippingLabelPaperSize+UI.swift in Sources */,
2D05337E2E951A62004111FD /* BookingDetailsViewModel+PriceFormatting.swift in Sources */,
CCD2E67E25DD4DC900BD975D /* ProductVariationsViewModel.swift in Sources */,
02C2756824F4E77F00286C04 /* ProductShippingSettingsViewModel.swift in Sources */,
E12AF69926BA8ADC00C371C1 /* CardPresentPaymentsOnboardingUseCase.swift in Sources */,
Expand Down