Files
haptika/ios/HaptikaWatch/Views/WatchRootView.swift
T
2026-07-31 16:20:10 +02:00

115 lines
4.1 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import SwiftUI
struct WatchRootView: View {
@EnvironmentObject private var model: WatchAppModel
var body: some View {
Group {
if model.hasCompletedOnboarding {
WatchHomeView()
} else {
WatchOnboardingView()
}
}
.preferredColorScheme(.dark)
}
}
struct WatchOnboardingView: View {
@EnvironmentObject private var model: WatchAppModel
@State private var page = 0
@State private var authorizationError: String?
var body: some View {
VStack(spacing: 8) {
TabView(selection: $page) {
onboardingPage(icon: "hand.raised.fill", title: "Vos données", text: "Les mesures restent sur vos appareils et se synchronisent avec votre iPhone appairé.").tag(0)
onboardingPage(icon: "heart.text.square.fill", title: "Bien-être, pas diagnostic", text: "Haptika n’est pas un dispositif médical. Consultez un professionnel en cas de symptôme.").tag(1)
onboardingPage(icon: "waveform.path.ecg", title: "Mesurer sans vibrer", text: "La Watch mesure le pouls optique. Les vibrations sont toujours arrêtées pendant cette phase.").tag(2)
}
.tabViewStyle(.verticalPage)
if let authorizationError {
Text(authorizationError).font(.caption2).foregroundStyle(.orange)
}
Button(page < 2 ? "Continuer" : "Autoriser Santé") {
if page < 2 {
withAnimation { page += 1 }
} else {
Task {
do {
try await model.measurement.requestAuthorization()
model.hasCompletedOnboarding = true
} catch {
authorizationError = error.localizedDescription
}
}
}
}
.buttonStyle(.borderedProminent)
}
.padding(.horizontal, 6)
.background(WatchTheme.background.ignoresSafeArea())
}
private func onboardingPage(icon: String, title: String, text: String) -> some View {
VStack(spacing: 10) {
Image(systemName: icon).font(.system(size: 34)).foregroundStyle(WatchTheme.accent)
Text(title).font(.headline).multilineTextAlignment(.center)
Text(text).font(.caption).foregroundStyle(WatchTheme.secondary).multilineTextAlignment(.center)
}
}
}
struct WatchHomeView: View {
@EnvironmentObject private var model: WatchAppModel
var body: some View {
NavigationStack {
List {
Section {
NavigationLink(value: WatchHomeDestination.measure) { homeRow("Mesurer", "waveform.path.ecg", WatchTheme.mint) }
NavigationLink(value: WatchHomeDestination.coherence) { homeRow("Ma Cohérence", "circle.dotted", WatchTheme.accent) }
NavigationLink(value: WatchHomeDestination.exercises) { homeRow("Exercices", "wind", .cyan) }
NavigationLink(value: WatchHomeDestination.cardiacMirror) { homeRow("Miroir cardiaque", "heart.circle", .pink) }
NavigationLink(value: WatchHomeDestination.history) { homeRow("Historique", "chart.xyaxis.line", .indigo) }
} header: {
VStack(alignment: .leading, spacing: 2) {
Text("HAPTIKA").font(.caption2).foregroundStyle(WatchTheme.accent)
Text("Prendre un temps").font(.headline).foregroundStyle(.white)
}
.textCase(nil)
}
Section {
HStack {
Circle().fill(model.connectivity.isReachable ? WatchTheme.mint : .gray).frame(width: 7, height: 7)
Text(model.connectivity.isReachable ? "iPhone joignable" : "Mode autonome")
}
.font(.caption2)
.foregroundStyle(WatchTheme.secondary)
}
}
.navigationDestination(for: WatchHomeDestination.self) { destination in
switch destination {
case .measure: WatchMeasurementView()
case .coherence: WatchCoherenceView()
case .exercises: WatchExerciseListView()
case .cardiacMirror: WatchCardiacMirrorView()
case .history: WatchHistoryView()
}
}
.haptikaScreen()
}
}
private func homeRow(_ title: String, _ icon: String, _ color: Color) -> some View {
Label {
Text(title).font(.subheadline.weight(.semibold))
} icon: {
Image(systemName: icon).foregroundStyle(color)
}
}
}