11import SwiftUI
22import struct Yosemite. Booking
33
4- struct BookingListView < Header : View > : View {
4+ struct BookingListView : View {
55 @ObservedObject private var viewModel : BookingListViewModel
66
7- @Namespace var topID
8-
9- private let headerView : Header
10-
11- private let viewPadding : CGFloat = 16
12- private let defaultBadgeColor = Color ( uiColor: . init( light: . systemGray6, dark: . systemGray5) )
13-
14- init ( viewModel: BookingListViewModel ,
15- @ViewBuilder header: ( ) -> Header ) {
7+ init ( viewModel: BookingListViewModel ) {
168 self . viewModel = viewModel
17- self . headerView = header ( )
189 }
1910
2011 var body : some View {
2112 VStack {
2213 switch viewModel. syncState {
2314 case . empty:
24- headerView
2515 Spacer ( )
2616 Text ( " No bookings found " ) // TODO: update this in WOOMOB-1394
2717 Spacer ( )
2818 case . syncingFirstPage:
29- headerView
3019 Spacer ( )
3120 ProgressView ( ) . progressViewStyle ( . circular)
3221 Spacer ( )
@@ -35,38 +24,32 @@ struct BookingListView<Header: View>: View {
3524 }
3625 }
3726 . task {
38- viewModel. loadBookings ( )
27+ // Only load first page if no content is available.
28+ if viewModel. bookings. isEmpty {
29+ viewModel. loadBookings ( )
30+ }
3931 }
4032 }
4133}
4234
4335private extension BookingListView {
4436 var bookingList : some View {
45- ScrollViewReader { proxy in
46- ScrollView {
47- LazyVStack ( spacing: 0 , pinnedViews: . sectionHeaders) {
48- Section {
49- ForEach ( viewModel. bookings) { item in
50- bookingItem ( item)
51- }
52- } header: {
53- headerView
54- }
55- . id ( topID)
56-
57- InfiniteScrollIndicator ( showContent: viewModel. shouldShowBottomActivityIndicator)
58- . padding ( . top, viewPadding)
59- . onAppear {
60- viewModel. onLoadNextPageAction ( )
61- }
37+ ScrollView {
38+ LazyVStack ( spacing: 0 ) {
39+ ForEach ( viewModel. bookings) { item in
40+ bookingItem ( item)
6241 }
63- }
64- . refreshable {
65- await viewModel. onRefreshAction ( )
66- // workaround as navigation bar is not snapped back after refreshing
67- proxy. scrollTo ( topID, anchor: . top)
42+
43+ InfiniteScrollIndicator ( showContent: viewModel. shouldShowBottomActivityIndicator)
44+ . padding ( . top, Layout . viewPadding)
45+ . onAppear {
46+ viewModel. onLoadNextPageAction ( )
47+ }
6848 }
6949 }
50+ . refreshable {
51+ await viewModel. onRefreshAction ( )
52+ }
7053 }
7154
7255 func bookingItem( _ booking: Booking ) -> some View {
@@ -86,15 +69,15 @@ private extension BookingListView {
8669 HStack {
8770 // TODO: update this when attendance status is available
8871 // Update badge colors if design changes as statuses are not clarified now.
89- statusBadge ( text: " Booked " , color: defaultBadgeColor)
90- statusBadge ( text: booking. bookingStatus. localizedTitle, color: defaultBadgeColor)
72+ statusBadge ( text: " Booked " , color: Layout . defaultBadgeColor)
73+ statusBadge ( text: booking. bookingStatus. localizedTitle, color: Layout . defaultBadgeColor)
9174 Spacer ( )
9275 }
9376 }
94- . padding ( viewPadding)
77+ . padding ( Layout . viewPadding)
9578
9679 Divider ( )
97- . padding ( . leading, viewPadding)
80+ . padding ( . leading, Layout . viewPadding)
9881 }
9982 . background ( Color ( . listForeground( modal: false ) ) ) // TODO: update selected background color as part of selection handling
10083 }
@@ -107,3 +90,10 @@ private extension BookingListView {
10790 . background ( color. clipShape ( RoundedRectangle ( cornerRadius: 4 ) ) )
10891 }
10992}
93+
94+ private extension BookingListView {
95+ enum Layout {
96+ static let viewPadding : CGFloat = 16
97+ static let defaultBadgeColor = Color ( uiColor: . init( light: . systemGray6, dark: . systemGray5) )
98+ }
99+ }
0 commit comments