Skip to content

Commit 89dc2a7

Browse files
authored
[Woo POS] Coupons: Creation (with dummy entry point UI) (#15467)
2 parents 33c007b + 5efb9d0 commit 89dc2a7

File tree

4 files changed

+144
-2
lines changed

4 files changed

+144
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import SwiftUI
2+
import struct Yosemite.Coupon
3+
import enum Yosemite.POSItem
4+
import struct Yosemite.POSCoupon
5+
6+
extension View {
7+
func posCouponCreationSheet(
8+
isPresented: Binding<Bool>,
9+
onSuccess: @escaping (POSItem) -> Void
10+
) -> some View {
11+
modifier(POSCouponCreationSheetModifier(isPresented: isPresented, onSuccess: onSuccess))
12+
}
13+
}
14+
15+
private struct POSCouponCreationSheetModifier: ViewModifier {
16+
@Binding var isPresented: Bool
17+
let onSuccess: (POSItem) -> Void
18+
19+
@State private var selectedType: POSCouponDiscountType?
20+
@State private var showCouponSelectionSheet: Bool = false
21+
22+
func body(content: Content) -> some View {
23+
content
24+
.sheet(item: $selectedType) { (posDiscountType: POSCouponDiscountType) in
25+
var addedCouponItem: POSItem?
26+
let viewModel = AddEditCouponViewModel(discountType: posDiscountType.discountType, onSuccess: { coupon in
27+
addedCouponItem = .coupon(.init(id: UUID(), code: coupon.code))
28+
})
29+
var view = AddEditCoupon(viewModel)
30+
31+
view.dismissHandler = {
32+
selectedType = nil
33+
}
34+
35+
view.onDisappear = {
36+
if let couponItem = addedCouponItem {
37+
selectedType = nil
38+
onSuccess(couponItem)
39+
addedCouponItem = nil
40+
}
41+
}
42+
43+
view.discountTypeHandler = { _ in
44+
showCouponSelectionSheet = true
45+
}
46+
47+
return view
48+
.interactiveDismissDisabled()
49+
.discountTypeSelectionSheet(isPresented: $showCouponSelectionSheet) { type in
50+
showCouponSelectionSheet = false
51+
viewModel.discountType = type.discountType
52+
}
53+
}
54+
.discountTypeSelectionSheet(isPresented: $isPresented) { type in
55+
selectedType = type
56+
}
57+
}
58+
}
59+
60+
private extension View {
61+
func discountTypeSelectionSheet(
62+
isPresented: Binding<Bool>,
63+
onSelection: @escaping (POSCouponDiscountType) -> Void
64+
) -> some View {
65+
sheet(isPresented: isPresented) {
66+
let command = DiscountTypeBottomSheetListSelectorCommand(selected: nil) { type in
67+
onSelection(.init(discountType: type))
68+
}
69+
70+
NavigationView {
71+
BottomSheetListSelector(
72+
viewProperties: BottomSheetListSelectorViewProperties(),
73+
command: command,
74+
onDismiss: { _ in
75+
isPresented.wrappedValue = false
76+
}
77+
)
78+
.navigationBarTitleDisplayMode(.large)
79+
.navigationTitle(Localization.selectCouponTypeTitle)
80+
.toolbar {
81+
ToolbarItem(placement: .cancellationAction) {
82+
Button(Localization.selectCouponCancelButtonTitle) {
83+
isPresented.wrappedValue = false
84+
}
85+
}
86+
}
87+
}
88+
.navigationViewStyle(.stack)
89+
.interactiveDismissDisabled()
90+
}
91+
}
92+
}
93+
94+
private struct POSCouponDiscountType: Identifiable, Equatable {
95+
var id: String { discountType.rawValue }
96+
let discountType: Coupon.DiscountType
97+
}
98+
99+
private enum Localization {
100+
static let selectCouponTypeTitle = NSLocalizedString(
101+
"pos.couponCreationSheet.selectCoupon.title",
102+
value: "Create coupon",
103+
comment: "A title for the view that selects the type of coupon to create"
104+
)
105+
106+
static let selectCouponCancelButtonTitle = NSLocalizedString(
107+
"pos.couponCreationSheet.selectCoupon.cancel",
108+
value: "Cancel",
109+
comment: "A button that dismisses coupon creation sheet"
110+
)
111+
}

WooCommerce/Classes/POS/Presentation/ItemListView.swift

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import SwiftUI
22
import enum Yosemite.POSItem
33
import protocol Yosemite.POSOrderableItem
4-
import struct Yosemite.POSCoupon
54

65
@available(iOS 17.0, *)
76
struct ItemListView: View {
@@ -23,6 +22,8 @@ struct ItemListView: View {
2322

2423
@State private var selectedItemType: ItemType = .products
2524

25+
@State private var showCouponCreationModal: Bool = false
26+
2627
var body: some View {
2728
if #available(iOS 18.0, *) {
2829
NavigationStack {
@@ -52,7 +53,19 @@ struct ItemListView: View {
5253
}, label: {
5354
Text("Coupons")
5455
})
56+
57+
Spacer()
58+
59+
Button(action: {
60+
showCouponCreationModal = true
61+
}, label: {
62+
Text(Image(systemName: "plus.circle.fill"))
63+
})
64+
.font(.posButtonSymbolLarge)
65+
.foregroundStyle(Color.posOnSurface)
66+
.renderedIf(selectedItemType == .coupons)
5567
}
68+
.padding(POSPadding.medium)
5669
.renderedIf(shouldShowCoupons)
5770

5871
switch itemListState {
@@ -80,6 +93,12 @@ struct ItemListView: View {
8093
.posModal(isPresented: $showSimpleProductsModal) {
8194
SimpleProductsOnlyInformation(isPresented: $showSimpleProductsModal)
8295
}
96+
.posCouponCreationSheet(isPresented: $showCouponCreationModal, onSuccess: { couponItem in
97+
Task { @MainActor in
98+
posModel.addToCart(couponItem)
99+
await posModel.refreshItems(base: .root)
100+
}
101+
})
83102
}
84103
}
85104

WooCommerce/Classes/ViewRelated/Coupons/Add and Edit Coupons/AddEditCouponViewModel.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ final class AddEditCouponViewModel: ObservableObject {
213213

214214
/// Init method for coupon creation
215215
///
216-
init(siteID: Int64,
216+
init(siteID: Int64 = ServiceLocator.stores.sessionManager.defaultStoreID ?? 0,
217217
discountType: Coupon.DiscountType,
218218
stores: StoresManager = ServiceLocator.stores,
219219
storageManager: StorageManagerType = ServiceLocator.storageManager,

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

+12
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
015D99AA2C58C780001D7186 /* PointOfSaleCardPresentPaymentLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 015D99A92C58C780001D7186 /* PointOfSaleCardPresentPaymentLayout.swift */; };
3636
01620C4E2C5394B200D3EA2F /* POSProgressViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01620C4D2C5394B200D3EA2F /* POSProgressViewStyle.swift */; };
3737
01664F9E2C50E685007CB5DD /* POSFontStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01664F9D2C50E685007CB5DD /* POSFontStyle.swift */; };
38+
016A77692D9D24B00004FCD6 /* POSCouponCreationSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016A77682D9D24A70004FCD6 /* POSCouponCreationSheet.swift */; };
3839
016C6B972C74AB17000D86FD /* POSConnectivityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 016C6B962C74AB17000D86FD /* POSConnectivityView.swift */; };
3940
0174DDBB2CE5FD60005D20CA /* ReceiptEmailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0174DDBA2CE5FD5D005D20CA /* ReceiptEmailViewModel.swift */; };
4041
0174DDBF2CE600C5005D20CA /* ReceiptEmailViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0174DDBE2CE600C0005D20CA /* ReceiptEmailViewModelTests.swift */; };
@@ -3275,6 +3276,7 @@
32753276
015D99A92C58C780001D7186 /* PointOfSaleCardPresentPaymentLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleCardPresentPaymentLayout.swift; sourceTree = "<group>"; };
32763277
01620C4D2C5394B200D3EA2F /* POSProgressViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSProgressViewStyle.swift; sourceTree = "<group>"; };
32773278
01664F9D2C50E685007CB5DD /* POSFontStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSFontStyle.swift; sourceTree = "<group>"; };
3279+
016A77682D9D24A70004FCD6 /* POSCouponCreationSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSCouponCreationSheet.swift; sourceTree = "<group>"; };
32783280
016C6B962C74AB17000D86FD /* POSConnectivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSConnectivityView.swift; sourceTree = "<group>"; };
32793281
0174DDBA2CE5FD5D005D20CA /* ReceiptEmailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReceiptEmailViewModel.swift; sourceTree = "<group>"; };
32803282
0174DDBE2CE600C0005D20CA /* ReceiptEmailViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReceiptEmailViewModelTests.swift; sourceTree = "<group>"; };
@@ -6565,6 +6567,14 @@
65656567
path = "Reusable Views";
65666568
sourceTree = "<group>";
65676569
};
6570+
016A77672D9D24A30004FCD6 /* Coupons */ = {
6571+
isa = PBXGroup;
6572+
children = (
6573+
016A77682D9D24A70004FCD6 /* POSCouponCreationSheet.swift */,
6574+
);
6575+
path = Coupons;
6576+
sourceTree = "<group>";
6577+
};
65686578
0174DDB92CE5FD49005D20CA /* ReceiptEmail */ = {
65696579
isa = PBXGroup;
65706580
children = (
@@ -7241,6 +7251,7 @@
72417251
026826A12BF59DED0036F959 /* Presentation */ = {
72427252
isa = PBXGroup;
72437253
children = (
7254+
016A77672D9D24A30004FCD6 /* Coupons */,
72447255
026A50262D2F6BBF002C42C2 /* Infinite Scroll */,
72457256
029149792D2682DF00F7B3B3 /* Item Selector */,
72467257
01620C4C2C5394A400D3EA2F /* Reusable Views */,
@@ -15817,6 +15828,7 @@
1581715828
EE9D03122B89DF760077CED1 /* WooAnalyticsEvent+OrdersListFilter.swift in Sources */,
1581815829
683421642ACE9391009021D7 /* ProductDiscountView.swift in Sources */,
1581915830
B6E851F3276320C70041D1BA /* RefundCustomAmountsDetailsViewModel.swift in Sources */,
15831+
016A77692D9D24B00004FCD6 /* POSCouponCreationSheet.swift in Sources */,
1582015832
024DF31F23743045006658FE /* Header+AztecFormatting.swift in Sources */,
1582115833
B5A8F8AD20B88D9900D211DE /* LoginPrologueViewController.swift in Sources */,
1582215834
B5D1AFC620BC7B7300DB0E8C /* StorePickerViewController.swift in Sources */,

0 commit comments

Comments
 (0)