Ako vytvoriť dopytový formulár pre iOS v SwiftUI
Dopytový formulár v SwiftUI s výberom služby, rozpočtu a termínu, ktorý vám každý dopyt pošle e-mailom a zákazníkovi automaticky pošle potvrdenie – bez backendu.
Aktualizované:
V tomto návode vytvoríte dopytový formulár v SwiftUI s natívnymi pickermi: služba, rozpočet a termín, k tomu popis. Vy dostanete štruktúrovaný e-mail, zákazník automatické potvrdenie.
Potrebujete: bezplatný účet Frontmail, projekt v Xcode so SwiftUI a zhruba dvadsať minút.
1. Pripojte schránku a vytvorte šablóny
- E-mailové služby → Pridať službu: pripojte svoju schránku alebo poskytovateľa, Nastaviť ako predvolenú, Overiť a uložiť.
- Šablóny → Z galérie → Dopyt (kategória Biznis) → Použiť šablónu.
- Z galérie → Automatická odpoveď: ďakujeme za správu → Použiť šablónu; nastavte
predvolené hodnoty pre
company_namearesponse_timea potom ju vyberte v šablóne dopytu v Nastavenia → Doručovanie → Šablóna automatickej odpovede.
Šablóna dopytu potrebuje name, email, service a details; phone, company, budget
a deadline (YYYY-MM-DD) sú nepovinné. service a budget prijímajú iba hodnoty z karty
Parametre. Príklad kódu používa hodnoty anglickej šablóny; keď šablónu vytvoríte
v slovenčine, hodnoty budú slovenské (Web, E-shop, Mobilná aplikácia, Konzultácie, Iné a Do
5 000 €, 5 000 – 20 000 €, 20 000 – 50 000 €, Nad 50 000 €) – v aplikácii posielajte presne tie
isté reťazce.
2. Povoľte mobilné aplikácie a zapnite CAPTCHA
- Zabezpečenie → Mobilné aplikácie → Povoliť mobilné aplikácie → Uložiť.
- Šablóna dopytu → Nastavenia → Ochrana → Vyžadovať CAPTCHA (Turnstile) – zdieľaný mobilný widget Frontmailu, žiadne kľúče nepotrebujete.
3. Pridajte balíček
File → Add Package Dependencies… → https://github.com/frontmail-dev/frontmail-swift →
pridajte Frontmail do svojho targetu a skopírujte TurnstileView z časti o Turnstile
v dokumentácii iOS SDK.
4. Vytvorte formulár
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
}
}
}
Nepovinné vlastnosti s hodnotou nil sa vôbec nezakódujú, takže prázdne riadky sa v e-maili nikdy
neobjavia.
5. Vyskúšajte to
Odošlite dopyt s vlastnou adresou ako e-mailom zákazníka: dostanete dopyt aj potvrdenie a oba e-maily sa zobrazia v História.
Dopyt s potvrdením stojí dva kredity. Ak kredity dôjdu, dopyty sa prijmú so stavom
.helda po dobití automaticky odídu.
Ďalšie kroky
- V nastaveniach šablóny zapnite Zber kontaktov a vytvorte si zoznam všetkých, ktorí žiadali o ponuku.
- Prikladajte zadanie alebo fotky cez
SendOptions(attachments: [.data(…)])– pozrite si dokumentáciu SDK.


