144 lines
4.3 KiB
Swift
144 lines
4.3 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 {
|
|
ZStack {
|
|
Color.appBackgroundLight.opacity(0.22).ignoresSafeArea()
|
|
|
|
VStack(spacing: 0) {
|
|
Spacer(minLength: 0)
|
|
|
|
VStack(spacing: 20) {
|
|
header
|
|
content
|
|
}
|
|
.padding(20)
|
|
.background(.white)
|
|
.clipShape(RoundedRectangle(cornerRadius: 22))
|
|
.shadow(color: .black.opacity(0.18), radius: 15, y: 8)
|
|
.padding(.horizontal, 32)
|
|
|
|
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: 94)
|
|
|
|
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: 32)
|
|
}
|
|
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)
|
|
}
|
|
} |