Adds a Reports tab to the Insights view with date range selection, two report types (Quick Summary / Detailed), Foundation Models AI generation with batched concurrent processing, and clinical PDF export via WKWebView HTML rendering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
87 lines
2.8 KiB
Swift
87 lines
2.8 KiB
Swift
//
|
|
// ReportGeneratingView.swift
|
|
// Reflect
|
|
//
|
|
// Overlay shown during AI report generation with progress and cancel.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct ReportGeneratingView: View {
|
|
let progress: Double
|
|
let message: String
|
|
let onCancel: () -> Void
|
|
|
|
@Environment(\.colorScheme) private var colorScheme
|
|
@State private var isPulsing = false
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
// Semi-transparent background
|
|
Color.black.opacity(0.4)
|
|
.ignoresSafeArea()
|
|
|
|
VStack(spacing: 24) {
|
|
// Sparkles icon
|
|
Image(systemName: "sparkles")
|
|
.font(.system(size: 44))
|
|
.foregroundStyle(
|
|
LinearGradient(
|
|
colors: [.purple, .blue],
|
|
startPoint: .topLeading,
|
|
endPoint: .bottomTrailing
|
|
)
|
|
)
|
|
.scaleEffect(isPulsing ? 1.1 : 1.0)
|
|
.opacity(isPulsing ? 0.8 : 1.0)
|
|
.animation(
|
|
UIAccessibility.isReduceMotionEnabled ? nil :
|
|
.easeInOut(duration: 1.2).repeatForever(autoreverses: true),
|
|
value: isPulsing
|
|
)
|
|
|
|
// Progress bar
|
|
VStack(spacing: 8) {
|
|
ProgressView(value: progress)
|
|
.progressViewStyle(.linear)
|
|
.tint(
|
|
LinearGradient(
|
|
colors: [.purple, .blue],
|
|
startPoint: .leading,
|
|
endPoint: .trailing
|
|
)
|
|
)
|
|
.accessibilityIdentifier(AccessibilityID.Reports.progressView)
|
|
|
|
Text(message)
|
|
.font(.subheadline)
|
|
.foregroundStyle(.secondary)
|
|
.multilineTextAlignment(.center)
|
|
}
|
|
|
|
// Cancel button
|
|
Button(role: .cancel) {
|
|
onCancel()
|
|
} label: {
|
|
Text("Cancel")
|
|
.font(.subheadline.weight(.medium))
|
|
.foregroundColor(.secondary)
|
|
}
|
|
.accessibilityIdentifier(AccessibilityID.Reports.cancelButton)
|
|
}
|
|
.padding(32)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 20)
|
|
.fill(colorScheme == .dark ? Color(.systemGray6) : .white)
|
|
.shadow(radius: 20)
|
|
)
|
|
.padding(.horizontal, 40)
|
|
}
|
|
.onAppear {
|
|
if !UIAccessibility.isReduceMotionEnabled {
|
|
isPulsing = true
|
|
}
|
|
}
|
|
}
|
|
}
|