ContactEditScreen.swift
145 lignes · 5368 octets
import SwiftUI // Port of ui/contact/ContactEditScreen.kt (+ ManualContactScreen). struct ContactEditScreen: View { @StateObject private var viewModel: ContactEditViewModel let onBack: () -> Void let onSaved: () -> Void let onRescan: (Int64) -> Void @State private var showCamera = false @State private var showPhotoPicker = false init( contactId: Int64, onBack: @escaping () -> Void, onSaved: @escaping () -> Void, onRescan: @escaping (Int64) -> Void ) { _viewModel = StateObject(wrappedValue: ContactEditViewModel(contactId: contactId)) self.onBack = onBack self.onSaved = onSaved self.onRescan = onRescan } var body: some View { VStack(spacing: 0) { ScreenTopBar(title: "Modifier le contact", centered: false, onBack: onBack) if !viewModel.loaded { Spacer() ProgressView().tint(C2VColor.ink) Spacer() } else { ScrollView { VStack(alignment: .leading, spacing: 14) { Text("Photo de profil") .font(C2VFont.bodyMedium) .foregroundColor(C2VColor.encre) profilePreview HStack(spacing: 10) { Button("Prendre une photo") { showCamera = true } .buttonStyle(C2VOutlineButtonStyle()) .disabled(!CameraPickerView.isAvailable) Button("Choisir une photo") { showPhotoPicker = true } .buttonStyle(C2VOutlineButtonStyle()) } ContactDraftFieldsView(card: $viewModel.card, phonesAsList: true) Button("Rescanner la carte") { onRescan(viewModel.contactId) } .buttonStyle(C2VOutlineButtonStyle()) } .padding(.horizontal, 18) .padding(.vertical, 12) } Button("Enregistrer") { viewModel.save() } .buttonStyle(C2VPrimaryButtonStyle()) .padding(.horizontal, 18) .padding(.vertical, 12) } } .background(C2VColor.fond) .toolbar(.hidden, for: .navigationBar) .task { await viewModel.load() } .onChange(of: viewModel.saveDone) { done in if done { onSaved() } } .fullScreenCover(isPresented: $showCamera) { CameraPickerView { image in showCamera = false if let image { viewModel.setProfileImage(ImageOrientation.orient(image).bitmap) } } .ignoresSafeArea() } .sheet(isPresented: $showPhotoPicker) { PhotoPickerView { image in showPhotoPicker = false if let image { viewModel.setProfileImage(ImageOrientation.orient(image).bitmap) } } } } @ViewBuilder private var profilePreview: some View { if let preview = viewModel.profilePreview { Image(uiImage: preview) .resizable() .aspectRatio(contentMode: .fill) .frame(width: 96, height: 96) .clipped() .overlay(Rectangle().stroke(C2VColor.bordure, lineWidth: 1)) } else { Rectangle() .fill(C2VColor.surface) .frame(width: 96, height: 96) .overlay(Rectangle().stroke(C2VColor.bordure, lineWidth: 1)) } } } /// Kotlin `ManualContactScreen` — blank draft saved straight to the carnet. struct ManualContactScreen: View { let onBack: () -> Void let onSaved: (Int64) -> Void @State private var card = ContactCard() @State private var saving = false private let repository = ContactRepository( dao: Card2vcfDatabase.shared.crmContactDao, images: ContactImageStore() ) var body: some View { VStack(spacing: 0) { ScreenTopBar(title: "Nouveau contact", centered: false, onBack: onBack) ScrollView { VStack(alignment: .leading, spacing: 14) { Text("Saisissez les champs, puis enregistrez dans le carnet.") .font(C2VFont.bodyMedium) .foregroundColor(C2VColor.texteFaible) ContactDraftFieldsView(card: $card) Spacer().frame(height: 8) } .padding(.horizontal, 18) .padding(.vertical, 12) } Button("Enregistrer") { guard !saving else { return } saving = true Task { do { let id = try await repository.insertFromCard(card) onSaved(id) } catch { saving = false } } } .buttonStyle(C2VPrimaryButtonStyle()) .padding(.horizontal, 18) .padding(.vertical, 12) } .background(C2VColor.fond) .toolbar(.hidden, for: .navigationBar) } }
GitRust