Search code examples
iosswiftswiftuishopping-cartmodifier

How to update the text values based on button click in Swift


I have shopping cart app in swiftUI . Currently when I click the add to cart button that time , it is able to add the product record into view . But here is the problem . When I click the button twice that time same product record get again , to be more straight forward having duplicate record and seconds problem is , I am expecting to update the quantities of the product as well but I'm not sure how to do it Please suggest me to do it batter way.

Here is my code for List view ..

 import SwiftUI

struct ProductListView: View {
    
    var body: some View {

        NavigationStack {
            VStack {
                    if viewModel.productLists.count > 0 && !viewModel.refreshing {
 List(viewModel.productList, id: \.self) { product in
                    ProductListViewCell(productData: product)

                        } .listStyle(.grouped)
                    }
                }
            }
            .navigationTitle(Text("Product List"))
        }
    }
}

Here is the code for cell..

struct ProductListViewCell: View {

    let productData: Product
    @EnvironmentObject var order: Order

    var body: some View {
        HStack {
            if let url = URL(string: productData.thumbnail) {
                ProductAsyncImageView(url: url)
                    .frame(width: 150, height: 150)
                    .mask(RoundedRectangle(cornerRadius: 16))
            }
            VStack(alignment: .leading,spacing: 5) {
                Text("Name: " +  (productData.title))
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .font(.headline)

                Text("Description: " + (productData.description))
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .multilineTextAlignment(.leading)

                Text("Price: £" + String(productData.price))
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .font(.subheadline)

                Button {
                    order.add(item: productData)

                } label: {
                    HStack {
                        Image(systemName: "cart.badge.plus")

                        Text("Add to Cart")
                            .fontWeight(.semibold)
                    }
                    .foregroundColor(.white)
                    .frame(width: 150 , height: 40)

                }
                .background(Color(.systemBlue))
                .cornerRadius(10)
            }
        }
    }
}

Here is my order class ..

import SwiftUI

class Order: ObservableObject {

    @Published var product = [Product]()

    func add(item: Product) {
        product.append(item)
    }
    func remove(item: Product) {
        if let index = product.firstIndex(of: item) {
            product.remove(at: index)
        }
    }
}

Here is the code for order view..

struct OrderView: View {

    @EnvironmentObject var order: Order

    var body: some View {
           NavigationStack {
               List {
                   Section {
                       ForEach(order.product) { item in
                           HStack(spacing: 20) {
                               if let url = URL(string: item.thumbnail) {
                                   ProductAsyncImageView(url: url)
                                       .frame(width: 90, height: 90)
                                        .padding(.bottom, -10)
                                       .clipShape(Circle())
                               }
                               VStack(alignment: .leading) {
                                   Text("Name: \(item.title)")
                                   Text("Price :£\(item.price)")
                                   Button("Show details") {

                                   }.foregroundColor(.gray)
                               }
                               HStack {
                                   Image(systemName: "multiply")
                                   Text("1")
                               }
                           }
                       }
                   }
                   Section {
                       NavigationLink("Place Order") {
                       }
                   }
               }
               .navigationTitle("Order")
           }
       }
   }

Here is the screenshot for product list view ..

enter image description here

Here is the screenshot having duplicate record when I click the add to button three time but I want only single record with Quantity 3.

enter image description here


Solution

    • In Product class you should have a quantity variable.

    • In Order.add(item:) you should check if Product exists in products array, and increase its quantity, as the following:

    class Order: ObservableObject {
    
        @Published var products = [Product]()
    
        func add(item: Product) {
            var exists = false
            products.forEach { product in
                if product.id == item.id {
                    exists = true
                    product.quantity += 1
                }
            }
            
            if !exists {
                product.append(item)
            }
        }
    
        //The rest of your code...
    }
    
    • Finally, you need to display the quantity in OrderView, as the following:
    ...
        HStack {
            Image(systemName: "multiply")
            Text(item.quantity)
        }
    ...
    

    Fixed your typo in Order class: product:[Product] -> products:[Product]