Almost done

This commit is contained in:
Daniel Arantes Loverde
2026-06-08 10:46:52 -03:00
parent aec1193944
commit 23d9752bfd
25 changed files with 476 additions and 257 deletions

View File

@@ -12,6 +12,7 @@ struct AddressesView: View {
@State var editingAddress: CustomerAddress? = nil
@State var openSwipeRowId: String? = nil
@State var deletingRowId: String? = nil
@State var settingDefaultRowId: String? = nil
let tabBarClearance: CGFloat = 96
@@ -54,7 +55,9 @@ struct AddressesView: View {
} else {
ForEach(Array(addresses.enumerated()), id: \.offset) { index, address in
let rowId = addressRowId(for: address, index: index)
let isSelected: Bool = {
let isPrimary: Bool = {
if address.isDefault == true { return true }
if addresses.contains(where: { $0.isDefault == true }) { return false }
if let selectedId = appState.address.selectedId {
return address.id == selectedId
}
@@ -65,10 +68,10 @@ struct AddressesView: View {
Button {
selectAddress(address)
} label: {
AddressCard(item: addressToListItem(address, isPrimary: isSelected))
AddressCard(item: addressToListItem(address, isPrimary: isPrimary))
}
.buttonStyle(.plain)
} else {
} else if addresses.count > 1 {
SwipeToDeleteAddressRow(
rowId: rowId,
openRowId: $openSwipeRowId,
@@ -76,19 +79,30 @@ struct AddressesView: View {
onDelete: { deleteAddress(address, rowId: rowId) }
) {
AddressCard(
item: addressToListItem(address, isPrimary: isSelected),
onEdit: { beginEditing(address) }
item: addressToListItem(address, isPrimary: isPrimary),
onEdit: { beginEditing(address) },
onSetDefault: { setDefaultAddress(address, rowId: rowId) }
)
.appContentShape(Rectangle())
.onTapGesture {
if openSwipeRowId == rowId {
openSwipeRowId = nil
}
}
.simultaneousGesture(TapGesture().onEnded {
if openSwipeRowId == rowId { openSwipeRowId = nil }
})
.opacity(settingDefaultRowId == rowId ? 0.6 : 1.0)
}
.id(rowId)
.opacity(deletingRowId == rowId ? 0.6 : 1.0)
.disabled(deletingRowId != nil)
.disabled(deletingRowId != nil || settingDefaultRowId != nil)
} else {
AddressCard(
item: addressToListItem(address, isPrimary: isPrimary),
onEdit: { beginEditing(address) }
)
.overlay(alignment: .bottom) {
Text("Ao menos um endereço deve permanecer")
.font(AppTypography.caption)
.foregroundStyle(AppColors.textMuted.opacity(0.7))
.padding(.bottom, 8)
}
}
}
}
@@ -230,8 +244,65 @@ struct AddressesView: View {
return "idx:\(index):\(address.label ?? ""):\(address.address ?? ""):\(address.number ?? "")"
}
private func setDefaultAddress(_ address: CustomerAddress, rowId: String) {
guard settingDefaultRowId == nil else { return }
settingDefaultRowId = rowId
openSwipeRowId = nil
Task {
var resolvedId = address.id?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
if resolvedId.isEmpty {
if let book = try? await ApiService().profile(forceRefresh: true).result?.addressBook {
await MainActor.run { addresses = book }
resolvedId = book.first {
$0.address == address.address &&
$0.number == address.number &&
$0.zipCode == address.zipCode
}?.id?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
}
}
guard resolvedId.isEmpty == false else {
await MainActor.run {
settingDefaultRowId = nil
SnackbarCenter.shared.show(title: "Não foi possível identificar o endereço.", style: .error, icon: "xmark.octagon.fill", duration: 3.5)
}
return
}
do {
let response = try await ApiService().setDefaultAddress(addressId: resolvedId)
await MainActor.run {
settingDefaultRowId = nil
if response.error == false {
addresses = addresses.map { addr in
let isTarget = (addr.id ?? "") == resolvedId
return CustomerAddress(
id: addr.id, label: addr.label, address: addr.address,
number: addr.number, complement: addr.complement,
neighborhood: addr.neighborhood, city: addr.city,
state: addr.state, zipCode: addr.zipCode,
latLong: addr.latLong, isDefault: isTarget
)
}
selectAddress(address)
SnackbarCenter.shared.show(title: "Endereço principal atualizado.", style: .success, icon: "star.fill", duration: 2.5)
} else {
SnackbarCenter.shared.show(title: response.message ?? "Não foi possível definir endereço principal.", style: .error, icon: "xmark.octagon.fill", duration: 3.0)
}
}
} catch {
await MainActor.run {
settingDefaultRowId = nil
SnackbarCenter.shared.show(title: "Erro ao atualizar endereço principal.", style: .error, icon: "xmark.octagon.fill", duration: 3.0)
}
}
}
}
private func deleteAddress(_ address: CustomerAddress, rowId: String) {
guard deletingRowId == nil else { return }
guard addresses.count > 1, deletingRowId == nil else { return }
deletingRowId = rowId
openSwipeRowId = nil
@@ -302,7 +373,7 @@ struct AddressesView: View {
do {
let service = ApiService()
let response = try await service.profile()
let response = try await service.profile(forceRefresh: true)
guard response.error == false else {
errorMessage = response.message ?? "Não foi possível carregar os endereços."
isLoading = false