VcfImportScreen.swift 99 lignes · 3623 octets
import SwiftUI
import UniformTypeIdentifiers

// Port of ui/importvcf/VcfImportScreen.kt — .vcf file picker, progress,
// import summary (imported / skipped duplicates / errors).

struct VcfImportScreen: View {
    @StateObject private var viewModel = VcfImportViewModel()
    let onBack: () -> Void

    @State private var showPicker = false

    var body: some View {
        VStack(spacing: 0) {
            ScreenTopBar(title: "Import VCF", onBack: onBack)
            content
        }
        .background(C2VColor.fond)
        .toolbar(.hidden, for: .navigationBar)
        .fileImporter(
            isPresented: $showPicker,
            allowedContentTypes: [.vCard, .plainText, .data]
        ) { result in
            if case .success(let url) = result {
                viewModel.importFrom(url: url)
            }
        }
    }

    @ViewBuilder
    private var content: some View {
        switch viewModel.state {
        case .idle:
            VStack(spacing: 14) {
                Spacer()
                Text("Choisissez un fichier vCard (.vcf). Les doublons (e-mail ou téléphone) sont ignorés.")
                    .font(C2VFont.bodyMedium)
                    .foregroundColor(C2VColor.texteFaible)
                    .multilineTextAlignment(.center)
                Button("Choisir un fichier") { showPicker = true }
                    .buttonStyle(C2VPrimaryButtonStyle())
                Spacer()
            }
            .padding(18)
        case .loading:
            VStack(spacing: 16) {
                Spacer()
                ProgressView().tint(C2VColor.ink)
                Text("Import en cours…")
                    .font(C2VFont.bodyMedium)
                    .foregroundColor(C2VColor.texteFaible)
                Spacer()
            }
            .frame(maxWidth: .infinity)
        case .done(let result):
            VStack(spacing: 12) {
                Spacer()
                Text("Résumé")
                    .font(C2VFont.titleLarge)
                    .foregroundColor(C2VColor.encre)
                Text(String(format: "Importés : %d", result.imported))
                    .font(C2VFont.bodyLarge)
                    .foregroundColor(C2VColor.encre)
                Text(String(format: "Doublons ignorés : %d", result.skippedDuplicates))
                    .font(C2VFont.bodyMedium)
                    .foregroundColor(C2VColor.texteFaible)
                Text(String(format: "Erreurs : %d", result.errors))
                    .font(C2VFont.bodyMedium)
                    .foregroundColor(C2VColor.texteFaible)
                Button("Retour au carnet", action: onBack)
                    .buttonStyle(C2VPrimaryButtonStyle())
                Button("Importer un autre fichier") {
                    viewModel.reset()
                    showPicker = true
                }
                .buttonStyle(C2VOutlineButtonStyle())
                Spacer()
            }
            .padding(18)
        case .error(let message):
            VStack(spacing: 12) {
                Spacer()
                Text(message)
                    .font(C2VFont.bodyLarge)
                    .foregroundColor(C2VColor.encre)
                    .multilineTextAlignment(.center)
                Button("Réessayer") {
                    viewModel.reset()
                    showPicker = true
                }
                .buttonStyle(C2VPrimaryButtonStyle())
                Button("Retour", action: onBack)
                    .buttonStyle(C2VOutlineButtonStyle())
                Spacer()
            }
            .padding(18)
        }
    }
}