2rabs/nito-app

View on GitHub
app/ios/Modules/Sources/Top/TopStateMachine.swift

Summary

Maintainability
A
0 mins
Test Coverage
import Common
import Dependencies
import Foundation
import KmpContainer
import NitoKmp

struct TopViewUIState: UIState {
    var recentScheduleUIState: LoadingState<RecentScheduleUIState> = .initial
}

struct RecentScheduleUIState: UIState {
    var data: ParticipantSchedule
    var formatter: DateFormatter
}

@MainActor
final class TopStateMachine: ObservableObject {
    @Dependency(\.dateTimeFormatter) var dateTimeFormatterProvider
    @Dependency(\.getRecentScheduleUseCase) var getRecentScheduleUseCase

    @Published var state: TopViewUIState = .init()

    private var cachedRecentSchedule: FetchSingleContentResult? {
        didSet {
            applyRecentScheduleToState()
        }
    }
    private var loadTask: Task<Void, Error>?

    deinit {
        loadTask?.cancel()
    }

    func load() async {
        state.recentScheduleUIState = .loading

        loadTask = Task.detached { @MainActor in
            do {
                for try await recentSchedule in self.getRecentScheduleUseCase.execute() {
                    self.cachedRecentSchedule = recentSchedule
                }
            } catch let error {
                self.state.recentScheduleUIState = .failed(error)
            }
        }
    }

    private func applyRecentScheduleToState() {
        guard let cachedRecentSchedule = cachedRecentSchedule else {
            return
        }

        switch cachedRecentSchedule {
        case is FetchSingleContentResultLoading, is FetchSingleContentResultNoContent:
            state.recentScheduleUIState = .loading
        case let result as FetchSingleContentResultSuccess<ParticipantSchedule>:
            state.recentScheduleUIState = .loaded(
                RecentScheduleUIState(
                    data: result.data!,
                    formatter: dateTimeFormatterProvider.dateTimeFormatter
                )
            )
        case let result as FetchSingleContentResultFailure:
            state.recentScheduleUIState = .failed(

                iOSNitoError.error(result.error)
            )
        default: break
        }
    }
}

enum iOSNitoError: Error {
    case error(NitoError?)
}