import SwiftUI import MapKit import CoreLocation struct ConnectView: View { @Environment(ChurchDataService.self) private var dataService @Environment(\.horizontalSizeClass) private var horizontalSizeClass @State private var churchConfig: ChurchConfig? @State private var showingContactForm = false var body: some View { ScrollView { LazyVStack(spacing: 0) { // Hero Section VStack(spacing: 24) { VStack(spacing: 16) { Text(getChurchName()) .font(.system(size: horizontalSizeClass == .regular ? 42 : 32, weight: .bold, design: .serif)) .foregroundColor(.primary) Text("Proclaiming the Three Angels' Messages") .font(.system(size: horizontalSizeClass == .regular ? 18 : 16, weight: .medium)) .foregroundColor(Color(hex: getBrandColor())) .italic() } .padding(.top, 32) } .padding(.bottom, 40) // Three Angels Messages VStack(alignment: .leading, spacing: 24) { Text("The Three Angels' Messages") .font(.system(size: horizontalSizeClass == .regular ? 32 : 28, weight: .bold, design: .serif)) .padding(.horizontal, 20) Text("Our mission is centered on the prophetic messages of Revelation 14, calling people to worship God, proclaim His truth, and prepare for Christ's second coming.") .font(.system(size: horizontalSizeClass == .regular ? 18 : 16, weight: .regular)) .lineSpacing(4) .padding(.horizontal, 20) .foregroundColor(.secondary) if horizontalSizeClass == .regular { // iPad: Horizontal layout HStack(spacing: 16) { ThreeAngelsMessagesView() } .padding(.horizontal, 20) } else { // iPhone: Vertical layout VStack(spacing: 16) { ThreeAngelsMessagesView() } .padding(.horizontal, 20) } } .padding(.bottom, 40) // Worship With Us Section VStack(alignment: .leading, spacing: 16) { Text("Worship With Us") .font(.system(size: horizontalSizeClass == .regular ? 28 : 24, weight: .bold)) .padding(.horizontal, 20) ServiceTimesSection() .padding(20) .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16)) .padding(.horizontal, 20) } .padding(.bottom, 32) // Mission Statement VStack(alignment: .leading, spacing: 16) { Text("Our Mission") .font(.system(size: horizontalSizeClass == .regular ? 28 : 24, weight: .bold)) .padding(.horizontal, 20) Text(getAboutText()) .font(.system(size: horizontalSizeClass == .regular ? 18 : 16, weight: .regular)) .lineSpacing(4) .padding(24) .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16)) .padding(.horizontal, 20) NavigationLink { BeliefsView() } label: { HStack { Text("Our 28 Fundamental Beliefs") .font(.system(size: horizontalSizeClass == .regular ? 18 : 16, weight: .semibold)) Spacer() Image(systemName: "chevron.right") } .foregroundColor(.white) .padding(20) .background(Color(hex: getBrandColor()), in: RoundedRectangle(cornerRadius: 12)) } .padding(.horizontal, 20) } .padding(.bottom, 32) // Visit & Connect Section VStack(alignment: .leading, spacing: 16) { Text("Visit & Connect") .font(.system(size: horizontalSizeClass == .regular ? 28 : 24, weight: .bold)) .padding(.horizontal, 20) // Interactive Map ChurchMapView() .padding(.horizontal, 20) // Contact Information VStack(spacing: 12) { ContactActionRow( icon: "location.fill", title: "Visit Us", subtitle: getChurchAddress(), iconColor: .red, action: ContactActions.directionsAction(address: getChurchAddress().replacingOccurrences(of: " ", with: "+")) ) if UIDevice.current.userInterfaceIdiom == .phone { ContactActionRow( icon: "phone.fill", title: "Call Us", subtitle: getContactPhone(), iconColor: .green, action: ContactActions.callAction(phoneNumber: getContactPhone()) ) } ContactActionRow( icon: "envelope.fill", title: "Email Us", subtitle: getContactEmail(), iconColor: .blue, action: ContactActions.emailAction(email: getContactEmail()) ) } .padding(20) .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16)) .padding(.horizontal, 20) // Send Message Button Button { showingContactForm = true } label: { HStack { Image(systemName: "paperplane.fill") Text("Send Us a Message") .fontWeight(.semibold) } .foregroundColor(.white) .frame(maxWidth: .infinity) .padding(16) .background(Color(hex: getBrandColor()), in: RoundedRectangle(cornerRadius: 12)) } .padding(.horizontal, 20) } .padding(.bottom, 32) // Support Our Ministry Section VStack(alignment: .leading, spacing: 16) { Text("Support Our Ministry") .font(.system(size: horizontalSizeClass == .regular ? 28 : 24, weight: .bold)) .padding(.horizontal, 20) Text("Your generous gifts help us share the Three Angels' Messages and serve our community.") .font(.system(size: horizontalSizeClass == .regular ? 18 : 16, weight: .regular)) .lineSpacing(4) .padding(.horizontal, 20) .foregroundColor(.secondary) Link(destination: URL(string: getDonationUrl())!) { HStack { Image(systemName: "heart.fill") Text("Give Securely Online") .fontWeight(.semibold) } .foregroundColor(.white) .frame(maxWidth: .infinity) .padding(16) .background(.green, in: RoundedRectangle(cornerRadius: 12)) } .padding(.horizontal, 20) HStack { Image(systemName: "lock.shield.fill") .foregroundColor(.green) Text("Secure giving powered by Adventist Giving") .font(.caption) .foregroundColor(.secondary) } .padding(.horizontal, 20) } .padding(.bottom, 100) } } .navigationTitle("About Us") .navigationBarTitleDisplayMode(.inline) .onAppear { loadChurchConfig() } .sheet(isPresented: $showingContactForm) { ContactFormView(isModal: true) .environment(dataService) } } private func loadChurchConfig() { // Use Rust functions directly - NO JSON parsing in Swift! self.churchConfig = ChurchConfig( contactPhone: getContactPhone(), contactEmail: getContactEmail(), churchAddress: getChurchAddress(), churchName: getChurchName() ) } } struct ChurchMapView: View { @Environment(\.horizontalSizeClass) private var horizontalSizeClass // Church location coordinates from Rust private var churchLocation: CLLocationCoordinate2D { let coords = getCoordinates() return CLLocationCoordinate2D( latitude: coords[0], longitude: coords[1] ) } @State private var cameraPosition: MapCameraPosition = .region( MKCoordinateRegion( center: CLLocationCoordinate2D(latitude: 41.8703594, longitude: -72.4077036), span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01) ) ) var body: some View { Map(position: $cameraPosition) { Annotation("Rockville Tolland SDA Church", coordinate: churchLocation) { VStack { Image(systemName: "house.fill") .font(.title2) .foregroundColor(.white) .padding(8) .background(Color(hex: getBrandColor()), in: Circle()) .shadow(radius: 4) Text("RTSDA") .font(.caption) .fontWeight(.bold) .foregroundColor(.white) .padding(.horizontal, 8) .padding(.vertical, 4) .background(Color.black.opacity(0.8), in: Capsule()) .shadow(radius: 3) } } } .frame(height: horizontalSizeClass == .regular ? 250 : 200) .cornerRadius(16) .onTapGesture { // Open in Apple Maps let placemark = MKPlacemark(coordinate: churchLocation) let mapItem = MKMapItem(placemark: placemark) mapItem.name = "Rockville Tolland SDA Church" mapItem.openInMaps(launchOptions: [ MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving ]) } .onAppear { // Update camera position when config loads cameraPosition = .region( MKCoordinateRegion( center: churchLocation, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01) ) ) } } } struct AngelMessageCard: View { let number: Int let title: String let reference: String let description: String @Environment(\.horizontalSizeClass) private var horizontalSizeClass var body: some View { VStack(spacing: 12) { // Number circle Text("\(number)") .font(.system(size: horizontalSizeClass == .regular ? 28 : 24, weight: .bold)) .foregroundColor(.white) .frame(width: horizontalSizeClass == .regular ? 50 : 44, height: horizontalSizeClass == .regular ? 50 : 44) .background(Color(hex: getBrandColor()), in: Circle()) VStack(spacing: 8) { Text(title) .font(.system(size: horizontalSizeClass == .regular ? 18 : 16, weight: .semibold)) .multilineTextAlignment(.center) Text(reference) .font(.system(size: horizontalSizeClass == .regular ? 14 : 12, weight: .medium)) .foregroundColor(Color(hex: getBrandColor())) .padding(.horizontal, 8) .padding(.vertical, 4) .background(Color(hex: getBrandColor()).opacity(0.1), in: Capsule()) Text(description) .font(.system(size: horizontalSizeClass == .regular ? 15 : 13)) .foregroundColor(.secondary) .multilineTextAlignment(.center) .lineLimit(4) } } .padding(horizontalSizeClass == .regular ? 20 : 16) .frame(maxWidth: .infinity) .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16)) } } struct ThreeAngelsMessagesView: View { @Environment(\.horizontalSizeClass) private var horizontalSizeClass @State private var messages: [(title: String, reference: String, description: String)] = [ ("First Angel's Message", "Revelation 14:6-7", "Fear God and give glory to Him, for the hour of His judgment has come"), ("Second Angel's Message", "Revelation 14:8", "Babylon is fallen, is fallen, that great city"), ("Third Angel's Message", "Revelation 14:9-12", "Keep the commandments of God and the faith of Jesus") ] @State private var isLoading = true private let angelMessages = [ (title: "First Angel's Message", reference: "Revelation 14:6-7"), (title: "Second Angel's Message", reference: "Revelation 14:8"), (title: "Third Angel's Message", reference: "Revelation 14:9-12") ] var body: some View { ForEach(Array(messages.enumerated()), id: \.offset) { index, message in NavigationLink { AngelMessageDetailView( number: index + 1, title: message.title, reference: message.reference ) } label: { AngelMessageCard( number: index + 1, title: message.title, reference: message.reference, description: message.description ) } .buttonStyle(PlainButtonStyle()) } .task { await loadMessages() } } private func loadMessages() async { var loadedMessages: [(String, String, String)] = [] for angel in angelMessages { // Use church-core to fetch the actual Bible verse text (following BeliefsView pattern) let versesJson = fetchBibleVerseJson(query: angel.reference) // Use Rust function for JSON parsing and description generation - NO business logic in Swift! let description = generateVerseDescription(versesJson: versesJson) loadedMessages.append((angel.title, angel.reference, description)) } await MainActor.run { messages = loadedMessages isLoading = false } } } struct AngelMessageDetailView: View { let number: Int let title: String let reference: String @Environment(\.horizontalSizeClass) private var horizontalSizeClass @State private var verseText: String = "" @State private var isLoading: Bool = true var body: some View { ScrollView { VStack(spacing: 24) { // Header with number circle VStack(spacing: 16) { Text("\(number)") .font(.system(size: horizontalSizeClass == .regular ? 48 : 40, weight: .bold)) .foregroundColor(.white) .frame(width: horizontalSizeClass == .regular ? 80 : 70, height: horizontalSizeClass == .regular ? 80 : 70) .background(Color(hex: getBrandColor()), in: Circle()) Text(title) .font(.system(size: horizontalSizeClass == .regular ? 32 : 28, weight: .bold, design: .serif)) .multilineTextAlignment(.center) Text(reference) .font(.system(size: horizontalSizeClass == .regular ? 20 : 18, weight: .medium)) .foregroundColor(Color(hex: getBrandColor())) .padding(.horizontal, 12) .padding(.vertical, 6) .background(Color(hex: getBrandColor()).opacity(0.1), in: Capsule()) } // Verse content VStack(alignment: .leading, spacing: 16) { if isLoading { ProgressView("Loading verse...") } else if !verseText.isEmpty { Text(verseText) .font(.system(size: horizontalSizeClass == .regular ? 20 : 18, weight: .regular)) .lineSpacing(6) .padding(24) .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16)) } else { Text("Unable to load verse text") .font(.system(size: horizontalSizeClass == .regular ? 18 : 16)) .foregroundColor(.secondary) .padding(24) .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16)) } } } .padding(.horizontal, 20) .padding(.bottom, 100) } .navigationTitle("Angel's Message") .navigationBarTitleDisplayMode(.inline) .task { await loadVerse() } } private func loadVerse() async { let versesJson = fetchBibleVerseJson(query: reference) await MainActor.run { isLoading = false // Use Rust function for JSON parsing and text extraction - NO business logic in Swift! verseText = extractFullVerseText(versesJson: versesJson) } } }