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)
    }
}