Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
874908398a
commit
5e2ff8b990
@ -500,9 +500,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Share your card and track recipients, or scan someone else's QR code to save their card." : {
|
||||
|
||||
},
|
||||
"Shared With" : {
|
||||
|
||||
@ -512,6 +509,9 @@
|
||||
},
|
||||
"Support & Funding" : {
|
||||
|
||||
},
|
||||
"Tap + to add a contact, scan a QR code, or track who you share your card with." : {
|
||||
|
||||
},
|
||||
"Tap a field below to add it" : {
|
||||
|
||||
|
||||
@ -75,6 +75,33 @@ final class ContactsStore: ContactTracking {
|
||||
fetchContacts()
|
||||
}
|
||||
|
||||
/// Creates a new contact manually
|
||||
func createContact(
|
||||
name: String,
|
||||
role: String = "",
|
||||
company: String = "",
|
||||
email: String = "",
|
||||
phone: String = "",
|
||||
notes: String = "",
|
||||
tags: String = "",
|
||||
metAt: String = ""
|
||||
) {
|
||||
let contact = Contact(
|
||||
name: name,
|
||||
role: role,
|
||||
company: company,
|
||||
cardLabel: "Manual",
|
||||
notes: notes,
|
||||
tags: tags,
|
||||
email: email,
|
||||
phone: phone,
|
||||
metAt: metAt
|
||||
)
|
||||
modelContext.insert(contact)
|
||||
saveContext()
|
||||
fetchContacts()
|
||||
}
|
||||
|
||||
/// Updates a contact's notes
|
||||
func updateNotes(for contact: Contact, notes: String) {
|
||||
contact.notes = notes
|
||||
|
||||
@ -5,6 +5,7 @@ import SwiftData
|
||||
struct ContactsView: View {
|
||||
@Environment(AppState.self) private var appState
|
||||
@State private var showingScanner = false
|
||||
@State private var showingAddContact = false
|
||||
|
||||
var body: some View {
|
||||
@Bindable var contactsStore = appState.contactsStore
|
||||
@ -20,12 +21,19 @@ struct ContactsView: View {
|
||||
.navigationTitle(String.localized("Contacts"))
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
HStack(spacing: Design.Spacing.small) {
|
||||
Button(String.localized("Add Contact"), systemImage: "plus") {
|
||||
showingAddContact = true
|
||||
}
|
||||
.accessibilityHint(String.localized("Manually add a new contact"))
|
||||
|
||||
Button(String.localized("Scan Card"), systemImage: "qrcode.viewfinder") {
|
||||
showingScanner = true
|
||||
}
|
||||
.accessibilityHint(String.localized("Scan someone else's QR code to save their card"))
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showingScanner) {
|
||||
QRScannerView { scannedData in
|
||||
if !scannedData.isEmpty {
|
||||
@ -34,6 +42,9 @@ struct ContactsView: View {
|
||||
showingScanner = false
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showingAddContact) {
|
||||
AddContactSheet()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -49,7 +60,7 @@ private struct EmptyContactsView: View {
|
||||
.font(.headline)
|
||||
.foregroundStyle(Color.Text.primary)
|
||||
|
||||
Text("Share your card and track recipients, or scan someone else's QR code to save their card.")
|
||||
Text("Tap + to add a contact, scan a QR code, or track who you share your card with.")
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Color.Text.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
85
BusinessCard/Views/Sheets/AddContactSheet.swift
Normal file
85
BusinessCard/Views/Sheets/AddContactSheet.swift
Normal file
@ -0,0 +1,85 @@
|
||||
import SwiftUI
|
||||
import SwiftData
|
||||
import Bedrock
|
||||
|
||||
struct AddContactSheet: View {
|
||||
@Environment(AppState.self) private var appState
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
@State private var name = ""
|
||||
@State private var role = ""
|
||||
@State private var company = ""
|
||||
@State private var email = ""
|
||||
@State private var phone = ""
|
||||
@State private var metAt = ""
|
||||
|
||||
private var canSave: Bool {
|
||||
!name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
Form {
|
||||
Section(String.localized("Name")) {
|
||||
TextField(String.localized("Full name"), text: $name)
|
||||
.textContentType(.name)
|
||||
.accessibilityLabel(String.localized("Contact name"))
|
||||
}
|
||||
|
||||
Section(String.localized("Role")) {
|
||||
TextField(String.localized("Job title"), text: $role)
|
||||
.textContentType(.jobTitle)
|
||||
TextField(String.localized("Company"), text: $company)
|
||||
.textContentType(.organizationName)
|
||||
}
|
||||
|
||||
Section(String.localized("Contact")) {
|
||||
TextField(String.localized("Email"), text: $email)
|
||||
.keyboardType(.emailAddress)
|
||||
.textContentType(.emailAddress)
|
||||
.textInputAutocapitalization(.never)
|
||||
TextField(String.localized("Phone"), text: $phone)
|
||||
.keyboardType(.phonePad)
|
||||
.textContentType(.telephoneNumber)
|
||||
}
|
||||
|
||||
Section(String.localized("Where You Met")) {
|
||||
TextField(String.localized("Event, location, or how you connected..."), text: $metAt)
|
||||
}
|
||||
}
|
||||
.navigationTitle(String.localized("Add Contact"))
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button(String.localized("Cancel")) {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
Button(String.localized("Save")) {
|
||||
saveContact()
|
||||
}
|
||||
.bold()
|
||||
.disabled(!canSave)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func saveContact() {
|
||||
appState.contactsStore.createContact(
|
||||
name: name.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
role: role.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
company: company.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
email: email.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
phone: phone.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
metAt: metAt.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
AddContactSheet()
|
||||
.environment(AppState(modelContext: try! ModelContainer(for: BusinessCard.self, Contact.self).mainContext))
|
||||
}
|
||||
@ -67,6 +67,7 @@ Each field has:
|
||||
|
||||
### Contacts
|
||||
|
||||
- **Add contacts manually**: Tap + to create contacts with name, role, company, email, phone
|
||||
- Track who you've shared your card with
|
||||
- **Scan QR codes** to save someone else's business card
|
||||
- **Notes & annotations**: Add notes about each contact
|
||||
|
||||
@ -129,6 +129,7 @@ Reusable components (in `Views/Components/`):
|
||||
Sheets (in `Views/Sheets/`):
|
||||
- `RecordContactSheet.swift` — track share recipient
|
||||
- `ContactFieldEditorSheet.swift` — add/edit contact field with type-specific UI
|
||||
- `AddContactSheet.swift` — manually add a new contact
|
||||
|
||||
Small utilities:
|
||||
- `Views/EmptyStateView.swift` — empty state placeholder
|
||||
|
||||
Loading…
Reference in New Issue
Block a user