109 lines
3.1 KiB
Swift
109 lines
3.1 KiB
Swift
import Foundation
|
|
import SwiftUI
|
|
import Combine
|
|
|
|
@MainActor
|
|
final class DashboardViewModel: ViewModel {
|
|
|
|
@Published private(set) var patient: PatientDTO?
|
|
@Published private(set) var prescriptions: [PrescriptionWithSchedulesResponse] = []
|
|
@Published private(set) var medications: [String: MedicationDTO] = [:]
|
|
@Published private(set) var errorMessage: String?
|
|
@Published private(set) var logoutErrorMessage: String?
|
|
|
|
private let api: MedMapAPI = DIContainer.shared.resolve()
|
|
|
|
var patientAge: Int? {
|
|
guard let dateOfBirth = patient?.dateOfBirth else { return nil }
|
|
let formatter = DateFormatter()
|
|
formatter.locale = Locale(identifier: "en_US_POSIX")
|
|
formatter.dateFormat = "yyyy-MM-dd"
|
|
guard let birthDate = formatter.date(from: dateOfBirth) else { return nil }
|
|
return Calendar.current.dateComponents([.year], from: birthDate, to: .now).year
|
|
}
|
|
|
|
var totalDosesToday: Int {
|
|
medicationCards.reduce(0) { $0 + $1.doseTimes.count }
|
|
}
|
|
|
|
var medicationCards: [MedicationCard] {
|
|
prescriptions.map { response in
|
|
let times = response.schedules
|
|
.flatMap(\.timesOfDay)
|
|
.sorted()
|
|
let medication = medications[response.medicationId]
|
|
|
|
return MedicationCard(
|
|
id: response.prescription.id,
|
|
medicationId: response.medicationId,
|
|
name: medication?.name ?? "Medicacao prescrita",
|
|
tag: medication?.activeIngredient ?? medication?.dosageForm ?? "Ativo",
|
|
photoBase64: medication?.medicationPhoto,
|
|
doseTimes: times,
|
|
nextDoseTime: times.first(where: { $0 >= currentTime }) ?? times.first
|
|
)
|
|
}
|
|
}
|
|
|
|
func loadDashboard() async {
|
|
guard !isLoading else { return }
|
|
|
|
isLoading = true
|
|
errorMessage = nil
|
|
defer { isLoading = false }
|
|
|
|
do {
|
|
async let myPatient = api.getMyPatientProfile()
|
|
async let activePrescriptions = api.listMyActivePrescriptions()
|
|
async let medicationsResponse = api.listMedications()
|
|
|
|
let (patient, prescriptions, medicationsResponseValue) = try await (myPatient, activePrescriptions, medicationsResponse)
|
|
self.patient = patient
|
|
self.prescriptions = prescriptions
|
|
medications = Dictionary(
|
|
uniqueKeysWithValues: medicationsResponseValue.medications.map { ($0.medicationId, $0) }
|
|
)
|
|
} catch {
|
|
errorMessage = "Nao foi possivel carregar a sua medicacao."
|
|
fluxlog("Patient dashboard load failed: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
func logout() async {
|
|
guard !isLoading else { return }
|
|
|
|
isLoading = true
|
|
logoutErrorMessage = nil
|
|
defer { isLoading = false }
|
|
|
|
do {
|
|
try await api.logout()
|
|
appStateManager.resetNavigation()
|
|
appStateManager.navigateTo(state: .login)
|
|
} catch {
|
|
logoutErrorMessage = "Nao foi possivel terminar a sessao. Tente novamente."
|
|
fluxlog("Patient logout failed: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
private var currentTime: String {
|
|
let formatter = DateFormatter()
|
|
formatter.locale = Locale(identifier: "en_US_POSIX")
|
|
formatter.dateFormat = "HH:mm"
|
|
return formatter.string(from: .now)
|
|
}
|
|
}
|
|
|
|
struct MedicationCard: Identifiable {
|
|
let id: String
|
|
let medicationId: String
|
|
let name: String
|
|
let tag: String
|
|
let photoBase64: String?
|
|
let doseTimes: [String]
|
|
let nextDoseTime: String?
|
|
}
|
|
// Created by RSA on 28/08/2026.
|
|
//
|
|
|