-
Notifications
You must be signed in to change notification settings - Fork 0
/
BrowseBreedsView.swift
98 lines (86 loc) · 2.7 KB
/
BrowseBreedsView.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Created by Josh Adams, who holds the copyright and reserves all rights, on 1/6/23.
import SwiftUI
struct BrowseBreedsView: View {
@StateObject var viewModel = BrowseBreedsViewModel()
@State private var images: [Breed: UIImage] = [:]
private let mockedState: BrowseBreedsViewModel.State?
private let photoHeightWidth: CGFloat = 150
init(mockedState: BrowseBreedsViewModel.State? = nil) {
self.mockedState = mockedState
}
var body: some View {
NavigationStack {
Group {
switch viewModel.state {
case .loading:
ProgressView()
case .error:
ErrorRetryView(message: "An error occurred during breed fetching.", viewModel: viewModel)
case .loaded(let breeds):
if !breeds.isEmpty {
list(of: breeds, viewModel: viewModel, mockedState: mockedState)
} else {
ErrorRetryView(message: "The endpoint returned an empty array of beeds.", viewModel: viewModel)
}
}
}
.navigationTitle("Cat Breeds")
}
.task {
await viewModel.loadBreeds(mockedState: mockedState)
}
}
@ViewBuilder
func list(of breeds: [Breed], viewModel: BrowseBreedsViewModel, mockedState: BrowseBreedsViewModel.State? = nil) -> some View {
if !breeds.isEmpty {
List(breeds) { breed in
NavigationLink {
BreedDetailsView(breed: breed)
} label: {
HStack {
VStack(alignment: .leading) {
Text(breed.name)
.font(.headline)
Text(breed.knownFor)
Text("Popularity: \(breed.popularity)")
}
Spacer()
Group {
if let image = images[breed] {
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fit)
.padding()
} else {
ProgressView()
}
}
.frame(width: photoHeightWidth)
.task {
await images[breed] = Current.imageLoader.fetch(breed.photoUrl)
}
}
.padding()
}
}
} else {
EmptyView()
}
}
}
struct BrowseBreedsView_Previews: PreviewProvider {
static var previews: some View {
Group {
BrowseBreedsView(mockedState: .loaded(breeds: [Breed].mock))
.previewDisplayName("Mocked Data")
BrowseBreedsView()
.previewDisplayName("Actual Data")
BrowseBreedsView(mockedState: .loaded(breeds: []))
.previewDisplayName("No Data")
BrowseBreedsView(mockedState: .loading)
.previewDisplayName("Loading")
BrowseBreedsView(mockedState: .error)
.previewDisplayName("Error")
}
}
}