Przejdź do treści

Jak zrobić formularz zapytania ofertowego na iOS w SwiftUI

Formularz zapytania ofertowego w SwiftUI z wyborem usługi i budżetu oraz terminem, który wysyła Ci każde zapytanie e-mailem, a klientowi automatyczne potwierdzenie – bez backendu.

Zaktualizowano:

Film jest po angielsku; poniżej znajdziesz pełny samouczek krok po kroku.

W tym samouczku zbudujesz w SwiftUI formularz zapytania ofertowego z natywnymi pickerami: usługa, budżet i termin, do tego opis. Ty dostajesz uporządkowany e-mail, a klient automatyczne potwierdzenie.

Potrzebujesz: darmowego konta Frontmail, projektu w Xcode ze SwiftUI i około dwudziestu minut.

1. Podłącz skrzynkę i utwórz szablony

  1. Usługi e-mail → Dodaj usługę: podłącz swoją skrzynkę lub dostawcę, Ustaw jako domyślną, Zweryfikuj i zapisz.
  2. Szablony → Z galerii → Zapytanie ofertowe (kategoria Biznes) → Użyj szablonu.
  3. Z galerii → Automatyczna odpowiedź: dziękujemy za wiadomość → Użyj szablonu; ustaw wartości domyślne company_name i response_time, a potem wybierz go w szablonie zapytania w Ustawienia → Doręczanie → Szablon automatycznej odpowiedzi.

Szablon zapytania wymaga name, email, service i details; phone, company, budget i deadline (YYYY-MM-DD) są opcjonalne. service i budget przyjmują tylko wartości z zakładki Parametry. Przykładowy kod używa wartości z angielskiej wersji szablonu; szablon utworzony po polsku ma Strona internetowa, Sklep internetowy, Aplikacja mobilna, Konsultacje, Inne oraz Do 20 tys. zł, 20–100 tys. zł, 100–200 tys. zł, Powyżej 200 tys. zł – aplikacja musi wysyłać dokładnie te same wartości.

2. Zezwól na aplikacje mobilne i włącz CAPTCHA

  • Bezpieczeństwo → Aplikacje mobilne → Zezwól na aplikacje mobilne → Zapisz.
  • Szablon zapytania → Ustawienia → Ochrona → Wymagaj CAPTCHA (Turnstile) – wspólny mobilny widżet Frontmail, klucze nie są potrzebne.

3. Dodaj pakiet

File → Add Package Dependencies… → https://github.com/frontmail-dev/frontmail-swift → dodaj Frontmail do swojego targetu i skopiuj TurnstileView z sekcji o Turnstile w dokumentacji iOS SDK.

4. Zbuduj formularz

import SwiftUI
import Frontmail

let frontmail = try! Frontmail(publicKey: "pk_…")

let services = ["Website", "E-shop", "Mobile app", "Consulting", "Other"]
let budgets = ["Under $5k", "$5k–20k", "$20k–50k", "Over $50k"]

struct QuoteRequest: Encodable {
    let name: String
    let email: String
    let service: String
    let budget: String?   // nil is left out of the email
    let deadline: String? // YYYY-MM-DD
    let details: String
}

struct QuoteView: View {
    @State private var name = ""
    @State private var email = ""
    @State private var service = services[0]
    @State private var budget = ""
    @State private var hasDeadline = false
    @State private var deadline = Date()
    @State private var details = ""
    @State private var widget: Turnstile.Widget?
    @State private var token: String?
    @State private var resetID = 0
    @State private var info = ""

    var body: some View {
        Form {
            Section {
                TextField("Name", text: $name)
                TextField("Email", text: $email)
                    .keyboardType(.emailAddress)
                    .textInputAutocapitalization(.never)
            }
            Section {
                Picker("What do you need?", selection: $service) {
                    ForEach(services, id: \.self) { Text($0) }
                }
                Picker("Budget", selection: $budget) {
                    Text("Not sure yet").tag("")
                    ForEach(budgets, id: \.self) { Text($0) }
                }
                Toggle("I have a deadline", isOn: $hasDeadline)
                if hasDeadline {
                    DatePicker("Deadline", selection: $deadline, in: Date()..., displayedComponents: .date)
                }
                TextField("Project details", text: $details, axis: .vertical)
                    .lineLimit(4...8)
            }
            if let widget {
                TurnstileView(widget: widget, size: .flexible, resetID: resetID) { event in
                    if case let .token(t) = event { token = t } else { token = nil }
                }
                .frame(height: Turnstile.Size.flexible.recommendedHeight)
            }
            Button("Request a quote") { Task { await send() } }
                .disabled(token == nil)
            Text(info)
        }
        .task { widget = try? await Turnstile.widget(client: frontmail) }
    }

    private func send() async {
        guard let widget, let token else { return }
        defer { self.token = nil; resetID += 1 } // a token works only once
        let request = QuoteRequest(
            name: name,
            email: email,
            service: service,
            budget: budget.isEmpty ? nil : budget,
            deadline: hasDeadline ? deadline.formatted(Date.ISO8601FormatStyle(timeZone: .current).year().month().day()) : nil,
            details: details
        )
        do {
            _ = try await frontmail.send(
                templateID: "tpl_…",
                params: request,
                options: SendOptions(turnstileToken: token, turnstileKey: widget.turnstileKey)
            )
            info = "Thanks! We’ve emailed you a confirmation."
        } catch let error as FrontmailError {
            info = error.message
        } catch {
            info = error.localizedDescription
        }
    }
}

Opcjonalne właściwości równe nil w ogóle nie są kodowane, więc puste wiersze nigdy nie pojawią się w e-mailu.

5. Przetestuj

Wyślij zapytanie, podając jako e-mail klienta swój adres: dostaniesz zapytanie i potwierdzenie, a oba pojawią się w Historii.

Zapytanie z potwierdzeniem zużywa dwa kredyty. Jeśli kredyty się skończą, zapytania są przyjmowane jako .held i wychodzą automatycznie po doładowaniu.

Co dalej

  • Włącz Zbieranie kontaktów w ustawieniach szablonu, żeby budować listę wszystkich, którzy prosili o wycenę.
  • Dołączaj brief lub zdjęcia przez SendOptions(attachments: [.data(…)]) – szczegóły w dokumentacji SDK.
Wszystkie samouczki
  • Film, 42 s

    iOS (Swift)Formularz kontaktowy

    Jak zrobić formularz kontaktowy na iOS w Swifcie i SwiftUI

    Formularz kontaktowy w SwiftUI, który wysyła Ci każdą wiadomość e-mailem przez Twoją własną skrzynkę – bez backendu i bez hasła SMTP w aplikacji. Korzysta z pakietu Frontmail dla Swifta.

  • Film, 42 s

    Strona internetowaFormularz zapytania ofertowego

    Jak zrobić formularz zapytania ofertowego na stronę internetową

    Formularz zapytania ofertowego z usługą, budżetem i terminem, który trafia do Twojej skrzynki jako przejrzysty e-mail – i automatycznie wysyła klientowi potwierdzenie. Bez backendu, w czystym HTML.

  • Film, 42 s

    FlutterFormularz zapytania ofertowego

    Jak zrobić formularz zapytania ofertowego we Flutterze

    Formularz zapytania ofertowego we Flutterze z wyborem usługi, budżetem i terminem, który wysyła Ci każde zapytanie e-mailem, a klientowi automatyczne potwierdzenie – bez backendu.