medmap-ios/medmap/Views/PatientMonthlyHistorySheet.swift
Ricardo Araújo 7215cc263a dashboard
2026-09-16 14:15:51 +01:00

140 lines
4.2 KiB
Swift

//
// PatientMonthlyHistorySheet.swift
// medmap
//
import SwiftUI
struct PatientMonthlyHistorySheet: View {
@StateObject private var viewModel = PatientMonthlyHistoryViewModel()
@Environment(\.dismiss) private var dismiss
private let columns = Array(repeating: GridItem(.flexible(), spacing: 7), count: 7)
var body: some View {
VStack(spacing: 0) {
Spacer(minLength: 0)
VStack(spacing: 24) {
header
content
}
.padding(24)
.background(.white)
.clipShape(RoundedRectangle(cornerRadius: 22))
.shadow(color: .black.opacity(0.18), radius: 15, y: 8)
.padding(.horizontal, 20)
Spacer(minLength: 0)
Button(action: dismiss.callAsFunction) {
Image(systemName: "xmark")
.font(.system(size: 21, weight: .medium))
.foregroundStyle(Color.appAccent)
.frame(width: 44, height: 44)
}
.padding(.bottom, 48)
}
.task {
await viewModel.loadHistory()
}
}
private var header: some View {
HStack {
Label("Histórico", systemImage: "hand.tap")
.font(.jakartaRegular14)
.foregroundStyle(Color.appBackground)
Spacer()
Button {
Task { await viewModel.showPreviousMonth() }
} label: {
Image(systemName: "chevron.left")
}
.buttonStyle(.plain)
.foregroundStyle(Color.appAccent)
Text(viewModel.history?.periodLabel ?? "Histórico")
.font(.jakartaBold16)
.foregroundStyle(Color.appAccent)
.frame(minWidth: 124)
Button {
Task { await viewModel.showNextMonth() }
} label: {
Image(systemName: "chevron.right")
}
.buttonStyle(.plain)
.foregroundStyle(Color.appAccent)
Image(systemName: "calendar")
.foregroundStyle(.white)
.frame(width: 32, height: 32)
.background(Color.appAccent)
.clipShape(RoundedRectangle(cornerRadius: 7))
}
}
@ViewBuilder
private var content: some View {
if viewModel.isLoading && viewModel.history == nil {
ProgressView().frame(height: 185)
} else if let errorMessage = viewModel.errorMessage {
VStack(spacing: 12) {
Text(errorMessage)
.font(.jakartaRegular14)
.foregroundStyle(.red)
.multilineTextAlignment(.center)
Button("Tentar novamente") {
Task { await viewModel.loadHistory() }
}
.font(.jakartaBold14)
.foregroundStyle(Color.appAccent)
}
.frame(height: 185)
} else if let history = viewModel.history {
LazyVGrid(columns: columns, spacing: 11) {
ForEach(0..<history.leadingDays, id: \.self) { _ in
Color.clear.frame(height: 38)
}
ForEach(history.days) { day in
CalendarDayView(day: day)
}
}
}
}
}
private struct CalendarDayView: View {
let day: PatientHistoryDay
private var toneColor: Color {
switch day.tone {
case "good": return Color(hex: "#6DD655")
case "warning": return Color(hex: "#F3B84E")
case "bad": return Color(hex: "#F45A68")
default: return Color(hex: "#D7DCE5")
}
}
var body: some View {
ZStack {
Circle()
.stroke(toneColor, lineWidth: 3)
.frame(width: 30, height: 30)
VStack(spacing: 0) {
Text(day.number)
.font(.system(size: 9, weight: .bold))
Text(day.weekday)
.font(.system(size: 6, weight: .medium))
}
.foregroundStyle(Color.appAccent)
}
.frame(height: 32)
.accessibilityLabel(day.date)
}
}