@@ -3,56 +3,99 @@ import WooFoundation
33import Networking
44
55struct BookingDetailsView : View {
6- @ObservedObject var viewModel : BookingDetailsViewModel
6+ @ObservedObject private var viewModel : BookingDetailsViewModel
77
8- enum Layout {
8+ private enum Layout {
99 static let contentSidePadding : CGFloat = 16
1010 static let headerContentVerticalPadding : CGFloat = 6
1111 static let headerBadgesAdditionalTopPadding : CGFloat = 4
12+ static let appointmentDetailsRowVerticalPadding : CGFloat = 6
1213 }
1314
14- enum TextFont {
15- static let headerBodyText = Font . body. weight ( . medium)
15+ fileprivate enum TextFont {
16+ static var bodyMedium : Font {
17+ Font . body. weight ( . medium)
18+ }
19+
20+ static var bodyRegular : Font {
21+ Font . body. weight ( . regular)
22+ }
23+ }
24+
25+ private enum ColorConstants {
26+ static var bookingStatusLabel : Color {
27+ return . gray
28+ }
1629 }
1730
18- enum ColorConstants {
19- static let bookingStatusLabel : Color = . gray
31+ init ( _ viewModel : BookingDetailsViewModel ) {
32+ self . viewModel = viewModel
2033 }
2134
35+ var body : some View {
36+ RefreshablePlainList ( action: {
37+ print ( " Refresh triggered " )
38+ } ) {
39+ VStack ( alignment: . leading, spacing: . zero) {
40+ ForEach ( viewModel. sections) { section in
41+ sectionView ( with: section)
42+ Divider ( )
43+ }
44+ }
45+ }
46+ . navigationBarTitleDisplayMode ( . inline)
47+ . background ( Color ( uiColor: . systemGroupedBackground) )
48+ }
49+ }
50+
51+ private extension BookingDetailsView {
2252 func sectionView( with section: BookingDetailsViewModel . Section ) -> some View {
23- VStack ( alignment: . leading, spacing: Layout . headerContentVerticalPadding ) {
53+ VStack ( alignment: . leading, spacing: 0 ) {
2454 if let headerText = section. headerText {
2555 Text ( headerText)
26- . font ( . caption )
56+ . font ( . footnote )
2757 . foregroundColor ( . gray)
58+ . padding ( . vertical)
59+ . padding ( . horizontal, Layout . contentSidePadding)
60+ Divider ( )
2861 }
2962
30- switch section. content {
31- case . header( let content) :
32- headerView ( with: content)
33- case . appointmentDetails( let content) :
34- appointmentDetailsView ( with: content)
35- default :
36- EmptyView ( )
37- }
63+ sectionContentView ( section. content)
64+ . padding ( . horizontal, Layout . contentSidePadding)
65+ . padding ( . vertical, 10 )
66+ . background ( Color ( uiColor: . listBackground) )
3867
3968 if let footerText = section. footerText {
69+ Divider ( )
4070 Text ( footerText)
41- . font ( . caption)
71+ . padding ( . horizontal, Layout . contentSidePadding)
72+ . font ( . footnote)
4273 . foregroundColor ( . gray)
4374 }
4475 }
4576 }
4677
78+ @ViewBuilder
79+ func sectionContentView( _ content: BookingDetailsViewModel . SectionContent ) -> some View {
80+ switch content {
81+ case . header( let content) :
82+ headerView ( with: content)
83+ case . appointmentDetails( let content) :
84+ appointmentDetailsView ( with: content)
85+ default :
86+ EmptyView ( )
87+ }
88+ }
89+
4790 func headerView( with headerContent: BookingDetailsViewModel . HeaderContent ) -> some View {
4891 VStack ( alignment: . leading, spacing: Layout . headerContentVerticalPadding) {
4992 Text ( headerContent. bookingDate)
5093 . font ( . caption)
5194 . foregroundColor ( . secondary)
5295 Text ( headerContent. serviceName)
53- . font ( TextFont . headerBodyText )
96+ . font ( TextFont . bodyMedium )
5497 Text ( headerContent. customerName)
55- . font ( TextFont . headerBodyText )
98+ . font ( TextFont . bodyMedium )
5699 . foregroundColor ( . secondary)
57100 HStack {
58101 ForEach ( headerContent. status, id: \. self) { status in
@@ -65,47 +108,36 @@ struct BookingDetailsView: View {
65108 }
66109 . padding ( . top, Layout . headerBadgesAdditionalTopPadding)
67110 }
111+ . frame ( maxWidth: . infinity, alignment: . leading)
112+ . padding ( . vertical, 6 )
68113 }
69114
70115 func appointmentDetailsView( with content: BookingDetailsViewModel . AppointmentDetailsContent ) -> some View {
71- VStack ( alignment: . leading, spacing : 16 ) {
116+ VStack ( alignment: . leading) {
72117 ForEach ( content. rows) { row in
73118 DetailRow ( title: row. title, value: row. value)
74- Divider ( )
75- }
76- }
77- }
78-
79- var body : some View {
80- RefreshablePlainList ( action: {
81- print ( " Refresh triggered " )
82- } ) {
83- VStack ( alignment: . leading) {
84- ForEach ( viewModel. sections) { section in
85- sectionView ( with: section)
86- . padding ( . horizontal)
119+ . padding ( . vertical, Layout . appointmentDetailsRowVerticalPadding)
87120
121+ if row. id != content. rows. last? . id {
88122 Divider ( )
123+ . padding ( . trailing, - Layout. contentSidePadding)
89124 }
90125 }
91- . padding ( . vertical)
92126 }
93- . navigationBarTitleDisplayMode ( . inline)
94- . background ( Color ( uiColor: . listBackground) )
95127 }
96128}
97129
98130struct DetailRow : View {
99131 let title : String
100132 let value : String
101- var isBold : Bool = false
102-
103133 var body : some View {
104134 HStack {
105135 Text ( title)
136+ . font ( BookingDetailsView . TextFont. bodyMedium)
106137 Spacer ( )
107138 Text ( value)
108- . fontWeight ( isBold ? . bold : . regular)
139+ . font ( BookingDetailsView . TextFont. bodyRegular)
140+ . foregroundColor ( . secondary)
109141 }
110142 }
111143}
@@ -135,7 +167,7 @@ struct BookingDetailsView_Previews: PreviewProvider {
135167 localTimezone: " America/New_York "
136168 )
137169 let viewModel = BookingDetailsViewModel ( booking: sampleBooking)
138- return BookingDetailsView ( viewModel: viewModel )
170+ return BookingDetailsView ( viewModel)
139171 }
140172}
141173#endif
0 commit comments