feat(checkout): replace dual payment group cards with single toggle switch
Toggle ON = Pagar Pelo App (default), shows in-app methods (PIX, Credit Card) Toggle OFF = Pagar Na Maquininha, shows store machine methods Automatically resets paymentMethod on toggle switch Removes paymentGroupCard helper, saves vertical space
This commit is contained in:
@@ -301,51 +301,32 @@ struct CheckoutView: View {
|
|||||||
.font(AppTypography.overline)
|
.font(AppTypography.overline)
|
||||||
.foregroundStyle(sectionTitleColor)
|
.foregroundStyle(sectionTitleColor)
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 12) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
paymentGroupCard(
|
// Toggle row
|
||||||
title: "Pagar Pelo App",
|
HStack(spacing: 12) {
|
||||||
subtitle: "Mais rápido e seguro",
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
isSelected: useInAppPayment
|
Text(useInAppPayment ? "Pagar Pelo App" : "Pagar Na Maquininha")
|
||||||
) {
|
.font(AppTypography.heading3)
|
||||||
VStack(spacing: 0) {
|
.foregroundStyle(AppColors.textPrimary)
|
||||||
ForEach(availableInAppPaymentMethods, id: \.rawValue) { method in
|
Text(useInAppPayment ? "Mais rápido e seguro" : "Na entrega/retirada com a loja")
|
||||||
paymentRow(method, isInAppGroup: true)
|
.font(.caption)
|
||||||
if method != availableInAppPaymentMethods.last {
|
.foregroundStyle(AppColors.textMuted)
|
||||||
Divider()
|
|
||||||
}
|
}
|
||||||
}
|
Spacer()
|
||||||
}
|
Toggle("", isOn: Binding(
|
||||||
} onTap: {
|
get: { useInAppPayment },
|
||||||
useInAppPayment = true
|
set: { newValue in
|
||||||
|
withAnimation(.easeInOut(duration: 0.2)) {
|
||||||
|
useInAppPayment = newValue
|
||||||
|
if newValue {
|
||||||
if availableInAppPaymentMethods.contains(paymentMethod) == false {
|
if availableInAppPaymentMethods.contains(paymentMethod) == false {
|
||||||
paymentMethod = .pix
|
paymentMethod = .pix
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
paymentGroupCard(
|
|
||||||
title: "Pagar Na Maquininha Da Loja",
|
|
||||||
subtitle: "Pague na entrega/retirada com os métodos aceitos pela loja",
|
|
||||||
isSelected: useInAppPayment == false
|
|
||||||
) {
|
|
||||||
if availableStoreMachineMethods.isEmpty {
|
|
||||||
Text("Loja não informou métodos presenciais.")
|
|
||||||
.font(AppTypography.body)
|
|
||||||
.foregroundStyle(AppColors.textMuted)
|
|
||||||
.padding(.horizontal, 14)
|
|
||||||
.padding(.bottom, 14)
|
|
||||||
} else {
|
} else {
|
||||||
VStack(spacing: 0) {
|
guard availableStoreMachineMethods.isEmpty == false else {
|
||||||
ForEach(availableStoreMachineMethods, id: \.rawValue) { method in
|
useInAppPayment = true
|
||||||
paymentRow(method, isInAppGroup: false)
|
return
|
||||||
if method != availableStoreMachineMethods.last {
|
|
||||||
Divider()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} onTap: {
|
|
||||||
guard availableStoreMachineMethods.isEmpty == false else { return }
|
|
||||||
useInAppPayment = false
|
|
||||||
if availableStoreMachineMethods.contains(paymentMethod) == false,
|
if availableStoreMachineMethods.contains(paymentMethod) == false,
|
||||||
let first = availableStoreMachineMethods.first {
|
let first = availableStoreMachineMethods.first {
|
||||||
paymentMethod = first
|
paymentMethod = first
|
||||||
@@ -353,6 +334,42 @@ struct CheckoutView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
))
|
||||||
|
.labelsHidden()
|
||||||
|
.tint(AppColors.primary)
|
||||||
|
}
|
||||||
|
.padding(14)
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
.padding(.horizontal, 14)
|
||||||
|
|
||||||
|
// Methods list
|
||||||
|
if useInAppPayment {
|
||||||
|
ForEach(availableInAppPaymentMethods, id: \.rawValue) { method in
|
||||||
|
paymentRow(method, isInAppGroup: true)
|
||||||
|
if method != availableInAppPaymentMethods.last {
|
||||||
|
Divider().padding(.horizontal, 14)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if availableStoreMachineMethods.isEmpty {
|
||||||
|
Text("Loja não informou métodos presenciais.")
|
||||||
|
.font(AppTypography.body)
|
||||||
|
.foregroundStyle(AppColors.textMuted)
|
||||||
|
.padding(14)
|
||||||
|
} else {
|
||||||
|
ForEach(availableStoreMachineMethods, id: \.rawValue) { method in
|
||||||
|
paymentRow(method, isInAppGroup: false)
|
||||||
|
if method != availableStoreMachineMethods.last {
|
||||||
|
Divider().padding(.horizontal, 14)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.background(AppColors.surface)
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func paymentRow(_ method: CheckoutPaymentMethod, isInAppGroup: Bool) -> some View {
|
private func paymentRow(_ method: CheckoutPaymentMethod, isInAppGroup: Bool) -> some View {
|
||||||
@@ -405,44 +422,6 @@ struct CheckoutView: View {
|
|||||||
return method.subtitle
|
return method.subtitle
|
||||||
}
|
}
|
||||||
|
|
||||||
private func paymentGroupCard<Content: View>(
|
|
||||||
title: String,
|
|
||||||
subtitle: String,
|
|
||||||
isSelected: Bool,
|
|
||||||
@ViewBuilder content: () -> Content,
|
|
||||||
onTap: @escaping () -> Void
|
|
||||||
) -> some View {
|
|
||||||
VStack(alignment: .leading, spacing: 10) {
|
|
||||||
HStack(spacing: 10) {
|
|
||||||
VStack(alignment: .leading, spacing: 2) {
|
|
||||||
Text(title)
|
|
||||||
.font(AppTypography.heading3)
|
|
||||||
.foregroundStyle(AppColors.textPrimary)
|
|
||||||
Text(subtitle)
|
|
||||||
.font(.caption)
|
|
||||||
.foregroundStyle(AppColors.textMuted)
|
|
||||||
}
|
|
||||||
Spacer()
|
|
||||||
Circle()
|
|
||||||
.stroke(isSelected ? AppColors.tertiary : AppColors.textMuted.opacity(0.45), lineWidth: 2)
|
|
||||||
.frame(width: 22, height: 22)
|
|
||||||
.background(
|
|
||||||
Circle()
|
|
||||||
.fill(isSelected ? AppColors.tertiary : Color.clear)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.padding(.horizontal, 14)
|
|
||||||
.padding(.top, 14)
|
|
||||||
.appContentShape(Rectangle())
|
|
||||||
.onTapGesture(perform: onTap)
|
|
||||||
|
|
||||||
content()
|
|
||||||
.allowsHitTesting(isSelected)
|
|
||||||
.opacity(isSelected ? 1 : 0.82)
|
|
||||||
}
|
|
||||||
.background(AppColors.surface)
|
|
||||||
.clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous))
|
|
||||||
}
|
|
||||||
|
|
||||||
private var bottomBar: some View {
|
private var bottomBar: some View {
|
||||||
VStack(spacing: 12) {
|
VStack(spacing: 12) {
|
||||||
|
|||||||
Reference in New Issue
Block a user