Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
1080590fde
commit
4145f73bc9
@ -81,6 +81,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Add Contact Fields" : {
|
||||||
|
|
||||||
},
|
},
|
||||||
"Add note" : {
|
"Add note" : {
|
||||||
|
|
||||||
@ -176,9 +179,6 @@
|
|||||||
},
|
},
|
||||||
"Contact" : {
|
"Contact" : {
|
||||||
|
|
||||||
},
|
|
||||||
"Contact Fields" : {
|
|
||||||
|
|
||||||
},
|
},
|
||||||
"Country" : {
|
"Country" : {
|
||||||
|
|
||||||
@ -249,6 +249,9 @@
|
|||||||
},
|
},
|
||||||
"Developer" : {
|
"Developer" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Drag to reorder. Swipe to delete." : {
|
||||||
|
|
||||||
},
|
},
|
||||||
"e.g. MBA, CPA, PhD" : {
|
"e.g. MBA, CPA, PhD" : {
|
||||||
|
|
||||||
@ -733,6 +736,9 @@
|
|||||||
},
|
},
|
||||||
"Write down a memorable reminder about your contact" : {
|
"Write down a memorable reminder about your contact" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Your Contact Fields" : {
|
||||||
|
|
||||||
},
|
},
|
||||||
"ZIP Code" : {
|
"ZIP Code" : {
|
||||||
|
|
||||||
|
|||||||
@ -50,6 +50,10 @@ struct CardEditorView: View {
|
|||||||
// Photo editor state - just one variable!
|
// Photo editor state - just one variable!
|
||||||
@State private var editingImageType: ImageType?
|
@State private var editingImageType: ImageType?
|
||||||
|
|
||||||
|
// Contact field editor state
|
||||||
|
@State private var selectedFieldTypeForAdd: ContactFieldType?
|
||||||
|
@State private var fieldToEdit: AddedContactField?
|
||||||
|
|
||||||
@State private var showingPreview = false
|
@State private var showingPreview = false
|
||||||
|
|
||||||
enum ImageType: String, Identifiable {
|
enum ImageType: String, Identifiable {
|
||||||
@ -196,11 +200,34 @@ struct CardEditorView: View {
|
|||||||
Text("Card Label")
|
Text("Card Label")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contact & social fields manager
|
// Current contact fields (reorderable list)
|
||||||
|
if !contactFields.isEmpty {
|
||||||
Section {
|
Section {
|
||||||
ContactFieldsManagerView(fields: $contactFields)
|
ForEach(contactFields) { field in
|
||||||
|
ContactFieldRowView(field: field) {
|
||||||
|
fieldToEdit = field
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onMove { from, to in
|
||||||
|
contactFields.move(fromOffsets: from, toOffset: to)
|
||||||
|
}
|
||||||
|
.onDelete { indexSet in
|
||||||
|
contactFields.remove(atOffsets: indexSet)
|
||||||
|
}
|
||||||
} header: {
|
} header: {
|
||||||
Text("Contact Fields")
|
Text("Your Contact Fields")
|
||||||
|
} footer: {
|
||||||
|
Text("Drag to reorder. Swipe to delete.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new contact fields
|
||||||
|
Section {
|
||||||
|
ContactFieldPickerView { fieldType in
|
||||||
|
selectedFieldTypeForAdd = fieldType
|
||||||
|
}
|
||||||
|
} header: {
|
||||||
|
Text("Add Contact Fields")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bio section
|
// Bio section
|
||||||
@ -244,6 +271,29 @@ struct CardEditorView: View {
|
|||||||
editingImageType = nil
|
editingImageType = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.sheet(item: $selectedFieldTypeForAdd) { fieldType in
|
||||||
|
ContactFieldEditorSheet(
|
||||||
|
fieldType: fieldType,
|
||||||
|
initialValue: "",
|
||||||
|
initialTitle: fieldType.titleSuggestions.first ?? "",
|
||||||
|
onSave: { value, title in
|
||||||
|
addContactField(fieldType: fieldType, value: value, title: title)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.sheet(item: $fieldToEdit) { field in
|
||||||
|
ContactFieldEditorSheet(
|
||||||
|
fieldType: field.fieldType,
|
||||||
|
initialValue: field.value,
|
||||||
|
initialTitle: field.title,
|
||||||
|
onSave: { value, title in
|
||||||
|
updateContactField(id: field.id, value: value, title: title)
|
||||||
|
},
|
||||||
|
onDelete: {
|
||||||
|
deleteContactField(id: field.id)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
.onAppear { loadCardData() }
|
.onAppear { loadCardData() }
|
||||||
.sheet(isPresented: $showingPreview) {
|
.sheet(isPresented: $showingPreview) {
|
||||||
CardPreviewSheet(card: buildPreviewCard())
|
CardPreviewSheet(card: buildPreviewCard())
|
||||||
@ -524,6 +574,54 @@ private struct ProfilePhotoView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Contact Field Row View
|
||||||
|
|
||||||
|
private struct ContactFieldRowView: View {
|
||||||
|
let field: AddedContactField
|
||||||
|
let onTap: () -> Void
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Button(action: onTap) {
|
||||||
|
HStack(spacing: Design.Spacing.medium) {
|
||||||
|
// Drag handle
|
||||||
|
Image(systemName: "line.3.horizontal")
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundStyle(Color.Text.tertiary)
|
||||||
|
.accessibilityHidden(true)
|
||||||
|
|
||||||
|
// Icon
|
||||||
|
Circle()
|
||||||
|
.fill(field.fieldType.iconColor)
|
||||||
|
.frame(width: Design.CardSize.avatarSize, height: Design.CardSize.avatarSize)
|
||||||
|
.overlay(
|
||||||
|
field.fieldType.iconImage()
|
||||||
|
.font(.title3)
|
||||||
|
.foregroundStyle(.white)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Content
|
||||||
|
VStack(alignment: .leading, spacing: Design.Spacing.xxSmall) {
|
||||||
|
Text(field.value.isEmpty ? field.fieldType.valuePlaceholder : field.shortDisplayValue)
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundStyle(field.value.isEmpty ? Color.Text.secondary : Color.Text.primary)
|
||||||
|
.lineLimit(1)
|
||||||
|
|
||||||
|
Text(field.title.isEmpty ? field.fieldType.displayName : field.title)
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundStyle(Color.Text.secondary)
|
||||||
|
.lineLimit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.contentShape(.rect)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.accessibilityLabel("\(field.fieldType.displayName): \(field.shortDisplayValue)")
|
||||||
|
.accessibilityHint(String.localized("Tap to edit, drag to reorder"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Accreditations Row
|
// MARK: - Accreditations Row
|
||||||
|
|
||||||
private struct AccreditationsRow: View {
|
private struct AccreditationsRow: View {
|
||||||
@ -828,6 +926,35 @@ private extension CardEditorView {
|
|||||||
return previewCard
|
return previewCard
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Contact Field Operations
|
||||||
|
|
||||||
|
func addContactField(fieldType: ContactFieldType, value: String, title: String) {
|
||||||
|
guard !value.isEmpty else { return }
|
||||||
|
withAnimation {
|
||||||
|
let newField = AddedContactField(
|
||||||
|
fieldType: fieldType,
|
||||||
|
value: value,
|
||||||
|
title: title
|
||||||
|
)
|
||||||
|
contactFields.append(newField)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateContactField(id: UUID, value: String, title: String) {
|
||||||
|
if let index = contactFields.firstIndex(where: { $0.id == id }) {
|
||||||
|
withAnimation {
|
||||||
|
contactFields[index].value = value
|
||||||
|
contactFields[index].title = title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteContactField(id: UUID) {
|
||||||
|
withAnimation {
|
||||||
|
contactFields.removeAll { $0.id == id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Contact Fields Sync
|
// MARK: - Contact Fields Sync
|
||||||
|
|
||||||
/// Saves the contactFields array to the BusinessCard model
|
/// Saves the contactFields array to the BusinessCard model
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user