@@ -3,101 +3,110 @@ import SwiftUI
33/// Represents the Customer section
44///
55struct OrderCustomerSection : View {
6- let geometry : GeometryProxy
76
8- /// View model to drive the view content
9- let viewModel : NewOrderViewModel . CustomerDataViewModel
7+ /// Parent view model to access all data
8+ @ ObservedObject var viewModel : NewOrderViewModel
109
11- /// View model for Address Form
12- let addressFormViewModel : CreateOrderAddressFormViewModel
10+ /// View model to drive the view content
11+ private var customerDataViewModel : NewOrderViewModel . CustomerDataViewModel {
12+ viewModel. customerDataViewModel
13+ }
1314
1415 @State private var showAddressForm : Bool = false
1516
1617 var body : some View {
17- Group {
18- Divider ( )
18+ OrderCustomerSectionContent ( viewModel: viewModel. customerDataViewModel, showAddressForm: $showAddressForm)
19+ . sheet ( isPresented: $showAddressForm) {
20+ NavigationView {
21+ EditOrderAddressForm ( dismiss: {
22+ showAddressForm. toggle ( )
23+ } , viewModel: viewModel. createOrderAddressFormViewModel ( ) )
24+ }
25+ }
26+ }
27+ }
1928
20- VStack ( alignment: . leading) {
21- HStack ( alignment: . top) {
22- Text ( Localization . customer)
23- . headlineStyle ( )
24-
25- Spacer ( )
26-
27- if viewModel. isDataAvailable {
28- Button ( Localization . editButton) {
29- showAddressForm. toggle ( )
30- }
31- . buttonStyle ( LinkButtonStyle ( ) )
32- . fixedSize ( horizontal: true , vertical: true )
33- . padding ( . top, - Layout. linkButtonTopPadding) // remove padding to align button title to the top
34- . padding ( . trailing, - Layout. linkButtonTrailingPadding) // remove padding to align button title to the side
35- }
36- }
29+ private struct OrderCustomerSectionContent : View {
30+
31+ /// View model to drive the view content
32+ var viewModel : NewOrderViewModel . CustomerDataViewModel
33+
34+ @Binding var showAddressForm : Bool
35+
36+ @Environment ( \. safeAreaInsets) var safeAreaInsets : EdgeInsets
37+
38+ var body : some View {
39+ Divider ( )
3740
38- if !viewModel. isDataAvailable {
39- createCustomerView
40- } else {
41- customerDataView
41+ VStack ( alignment: . leading, spacing: . zero) {
42+ HStack ( alignment: . top) {
43+ Text ( Localization . customer)
44+ . headlineStyle ( )
45+
46+ Spacer ( )
47+
48+ if viewModel. isDataAvailable {
49+ Button ( Localization . editButton) {
50+ showAddressForm. toggle ( )
51+ }
52+ . buttonStyle ( LinkButtonStyle ( ) )
53+ . fixedSize ( horizontal: true , vertical: true )
54+ . padding ( . top, - Layout. linkButtonTopPadding) // remove padding to align button title to the top
55+ . padding ( . trailing, - Layout. linkButtonTrailingPadding) // remove padding to align button title to the side
4256 }
4357 }
44- . padding ( . horizontal, insets: geometry. safeAreaInsets)
45- . padding ( )
46- . background ( Color ( . listForeground) )
58+ . padding ( [ . leading, . top, . trailing] )
4759
48- Divider ( )
49- }
50- . sheet ( isPresented: $showAddressForm) {
51- NavigationView {
52- EditOrderAddressForm ( dismiss: {
53- showAddressForm. toggle ( )
54- } , viewModel: addressFormViewModel)
60+ if !viewModel. isDataAvailable {
61+ Spacer ( minLength: Layout . verticalHeadlineSpacing)
62+ createCustomerView
63+ } else {
64+ customerDataView
5565 }
5666 }
67+ . padding ( . horizontal, insets: safeAreaInsets)
68+ . background ( Color ( . listForeground) )
69+
70+ Divider ( )
5771 }
5872
5973 private var createCustomerView : some View {
6074 Button ( Localization . addCustomer) {
6175 showAddressForm. toggle ( )
6276 }
6377 . buttonStyle ( PlusButtonStyle ( ) )
78+ . padding ( [ . leading, . bottom, . trailing] )
6479 }
6580
6681 private var customerDataView : some View {
6782 Group {
68- VStack ( alignment: . leading, spacing: Layout . verticalEmailSpacing) {
69- if let fullName = viewModel. fullName {
70- Text ( fullName)
71- . bodyStyle ( )
72- }
73- if let email = viewModel. email {
74- Text ( email)
75- . footnoteStyle ( )
76- }
77- }
78- if let billingAddressFormatted = viewModel. billingAddressFormatted {
79- addressDetails ( title: Localization . billingTitle, formattedAddress: billingAddressFormatted)
80- }
81- if let shippingAddressFormatted = viewModel. shippingAddressFormatted {
82- addressDetails ( title: Localization . shippingTitle, formattedAddress: shippingAddressFormatted)
83- }
83+ addressDetails ( title: Localization . shippingTitle, formattedAddress: viewModel. shippingAddressFormatted)
84+ Divider ( )
85+ . padding ( . leading)
86+ addressDetails ( title: Localization . billingTitle, formattedAddress: viewModel. billingAddressFormatted)
8487 }
8588 }
8689
87- @ViewBuilder private func addressDetails( title: String , formattedAddress: String ) -> some View {
88- Divider ( )
90+ @ViewBuilder private func addressDetails( title: String , formattedAddress: String ? ) -> some View {
8991 VStack ( alignment: . leading, spacing: Layout . verticalAddressSpacing) {
9092 Text ( title)
9193 . headlineStyle ( )
92- Text ( formattedAddress)
93- . bodyStyle ( )
94+ if let formattedAddress = formattedAddress, formattedAddress. isNotEmpty {
95+ Text ( formattedAddress)
96+ . bodyStyle ( )
97+ } else {
98+ Text ( Localization . noAddress)
99+ . bodyStyle ( )
100+ }
94101 }
102+ . padding ( )
95103 }
96104}
97105
98106// MARK: Constants
99- private extension OrderCustomerSection {
107+ private extension OrderCustomerSectionContent {
100108 enum Layout {
109+ static let verticalHeadlineSpacing : CGFloat = 22.0
101110 static let verticalEmailSpacing : CGFloat = 4.0
102111 static let verticalAddressSpacing : CGFloat = 6.0
103112 static let linkButtonTopPadding : CGFloat = 12.0
@@ -111,28 +120,28 @@ private extension OrderCustomerSection {
111120
112121 static let billingTitle = NSLocalizedString ( " Billing Address " , comment: " Title for the Billing Address section in order customer data " )
113122 static let shippingTitle = NSLocalizedString ( " Shipping Address " , comment: " Title for the Edit Shipping Address section in order customer data " )
123+
124+ static let noAddress = NSLocalizedString ( " No address specified. " , comment: " Placeholder for empty address in order customer data " )
114125 }
115126}
116127
128+ @available ( iOS 15 . 0 , * )
117129struct OrderCustomerSection_Previews : PreviewProvider {
118130 static var previews : some View {
119- let orderAdressFormViewModel = NewOrderViewModel ( siteID: 123 ) . createOrderAddressFormViewModel ( )
120131 let emptyViewModel = NewOrderViewModel . CustomerDataViewModel ( billingAddress: nil , shippingAddress: nil )
121132 let addressViewModel = NewOrderViewModel . CustomerDataViewModel ( fullName: " Johnny Appleseed " ,
122133123- billingAddressFormatted: """
134+ billingAddressFormatted: nil ,
135+ shippingAddressFormatted: """
124136 Johnny Appleseed
125137 234 70th Street
126138 Niagara Falls NY 14304
127139 US
128- """ ,
129- shippingAddressFormatted: nil )
140+ """ )
130141
131- GeometryReader { geometry in
132- ScrollView {
133- OrderCustomerSection ( geometry: geometry, viewModel: emptyViewModel, addressFormViewModel: orderAdressFormViewModel)
134- OrderCustomerSection ( geometry: geometry, viewModel: addressViewModel, addressFormViewModel: orderAdressFormViewModel)
135- }
142+ ScrollView {
143+ OrderCustomerSectionContent ( viewModel: emptyViewModel, showAddressForm: . constant( false ) )
144+ OrderCustomerSectionContent ( viewModel: addressViewModel, showAddressForm: . constant( false ) )
136145 }
137146 }
138147}
0 commit comments