Skip to content

Commit

Permalink
feat(Crypto List): Refreshable crypto list (#4)
Browse files Browse the repository at this point in the history
* feat(Crypto list): Retrieve top list cryptos

* Add tests

* feat(Crypto List): Add loading, error and refresh to view

* Create codecov.yml

* Update codecov.yml
  • Loading branch information
josetorronteras authored Jun 8, 2024
1 parent 2ea3ba6 commit 904d37a
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
21 changes: 21 additions & 0 deletions CryptoWidgetKitApp/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct ContentView: View {
@Environment(CryptoViewModel.self) var cryptoViewModel

var body: some View {
@Bindable var cryptoViewModel = cryptoViewModel
NavigationStack {
List(cryptoViewModel.cryptos, id: \.coinInfo.id) { crypto in
HStack {
Expand All @@ -20,7 +21,27 @@ struct ContentView: View {
Text(crypto.display?.usd.price ?? "0")
}
}
.redacted(reason: cryptoViewModel.isLoading ? .placeholder : [])
.task { await cryptoViewModel.fetch() }
.refreshable { await cryptoViewModel.fetch() }
.alert(isPresented: $cryptoViewModel.showError, content: {
Alert(title: Text("An error occurred, try again later"),
dismissButton: .default(
Text("Retry"),
action: {
Task {
await cryptoViewModel.fetch()
}
}))
})
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
Text("API Cache 120 seconds")
.font(.footnote)
.foregroundColor(.secondary)
.frame(maxWidth: .infinity)
}
}
}
}
}
Expand Down
21 changes: 20 additions & 1 deletion CryptoWidgetKitApp/ViewModels/CryptoViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ final class CryptoViewModel {

// MARK: - Properties
private(set) var cryptos: [Crypto] = []
private(set) var isLoading: Bool = true
var showError: Bool = false

// MARK: - Dependencies
private let apiService: CryptoAPIService

// MARK: - Init
init(apiService: CryptoAPIService = CryptoAPIService()) {
init(apiService: CryptoAPIService = CryptoAPIService(),
initialState: [Crypto] = .mock) {
self.apiService = apiService
self.cryptos = initialState
}
}

Expand All @@ -28,10 +32,25 @@ extension CryptoViewModel {

/// Fetch the cryptos from API and update the cryptos array
func fetch() async {
isLoading = true
do {
sleep(3)
cryptos = try await apiService.fetchRetrieveFullList().data
isLoading = false
} catch {
print(error)
showError = true
}
}
}

// MARK: - Crypto Extension
extension [Crypto] {

/// Mock Crypto
static var mock: [Crypto] {
(0..<5).map {
Crypto(coinInfo: CoinInfo(id: $0.description, name: "name", fullName: "fullName", imageURL: "imageURL"), display: nil)
}
}
}
16 changes: 16 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Refs:
# - https://docs.codecov.com/docs/common-recipe-list
# - https://docs.codecov.com/docs/codecovyml-reference
#
# After making changes, run below command to validate
# curl --data-binary @codecov.yml https://codecov.io/validate
coverage:
status:
project:
default:
target: 80%
threshold: 1%
patch:
default:
target: 60%
threshold: 1%

0 comments on commit 904d37a

Please sign in to comment.