- Custom sheet header with warm canvas background (no white bar) - Tab picker styled as warm pills (not default segmented control) - AI Chat welcome state: sparkles icon + 'What did you eat?' prompt - All backgrounds use canvas color consistently Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
125 lines
3.8 KiB
Swift
125 lines
3.8 KiB
Swift
import SwiftUI
|
|
|
|
struct ContentView: View {
|
|
@Environment(AuthManager.self) private var auth
|
|
|
|
var body: some View {
|
|
Group {
|
|
if auth.isCheckingAuth {
|
|
ProgressView()
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.background(Color.canvas)
|
|
} else if auth.isLoggedIn {
|
|
MainTabView()
|
|
} else {
|
|
LoginView()
|
|
}
|
|
}
|
|
.task {
|
|
await auth.checkAuth()
|
|
}
|
|
}
|
|
}
|
|
|
|
struct MainTabView: View {
|
|
@State private var selectedTab = 0
|
|
@State private var showAssistant = false
|
|
|
|
var body: some View {
|
|
ZStack(alignment: .bottomTrailing) {
|
|
TabView(selection: $selectedTab) {
|
|
HomeView()
|
|
.tabItem {
|
|
Label("Home", systemImage: "house.fill")
|
|
}
|
|
.tag(0)
|
|
|
|
FitnessTabView()
|
|
.tabItem {
|
|
Label("Fitness", systemImage: "flame.fill")
|
|
}
|
|
.tag(1)
|
|
}
|
|
.tint(Color.accentWarm)
|
|
|
|
Button {
|
|
showAssistant = true
|
|
} label: {
|
|
Image(systemName: "plus")
|
|
.font(.title2.weight(.semibold))
|
|
.foregroundStyle(.white)
|
|
.frame(width: 56, height: 56)
|
|
.background(Color.accentWarm)
|
|
.clipShape(Circle())
|
|
.shadow(color: .black.opacity(0.2), radius: 8, y: 4)
|
|
}
|
|
.padding(.trailing, 20)
|
|
.padding(.bottom, 70)
|
|
}
|
|
.sheet(isPresented: $showAssistant) {
|
|
AssistantSheetView()
|
|
}
|
|
}
|
|
}
|
|
|
|
struct AssistantSheetView: View {
|
|
@Environment(\.dismiss) private var dismiss
|
|
@State private var selectedMode = 0
|
|
|
|
var body: some View {
|
|
VStack(spacing: 0) {
|
|
// Custom header — warm background
|
|
VStack(spacing: 12) {
|
|
// Drag handle
|
|
Capsule()
|
|
.fill(Color.textTertiary.opacity(0.3))
|
|
.frame(width: 36, height: 5)
|
|
.padding(.top, 8)
|
|
|
|
Text("Add Food")
|
|
.font(.headline)
|
|
.foregroundStyle(Color.textPrimary)
|
|
|
|
// Tab picker — warm styled
|
|
HStack(spacing: 4) {
|
|
tabButton("AI Chat", icon: "sparkles", index: 0)
|
|
tabButton("Quick Add", icon: "magnifyingglass", index: 1)
|
|
}
|
|
.padding(4)
|
|
.background(Color.textTertiary.opacity(0.08))
|
|
.clipShape(Capsule())
|
|
.padding(.horizontal, 40)
|
|
}
|
|
.padding(.bottom, 12)
|
|
.background(Color.canvas)
|
|
|
|
// Content
|
|
if selectedMode == 0 {
|
|
AssistantChatView()
|
|
} else {
|
|
FoodSearchView(isSheet: true)
|
|
}
|
|
}
|
|
.background(Color.canvas)
|
|
.presentationDetents([.large])
|
|
}
|
|
|
|
private func tabButton(_ title: String, icon: String, index: Int) -> some View {
|
|
Button {
|
|
withAnimation(.easeInOut(duration: 0.2)) { selectedMode = index }
|
|
} label: {
|
|
HStack(spacing: 5) {
|
|
Image(systemName: icon)
|
|
.font(.caption2)
|
|
Text(title)
|
|
.font(.subheadline.weight(selectedMode == index ? .semibold : .regular))
|
|
}
|
|
.foregroundStyle(selectedMode == index ? Color.textPrimary : Color.textTertiary)
|
|
.padding(.horizontal, 16)
|
|
.padding(.vertical, 8)
|
|
.background(selectedMode == index ? Color.surfaceCard : Color.clear)
|
|
.clipShape(Capsule())
|
|
}
|
|
}
|
|
}
|