How to swipe and delete

59 views Asked by At

I need help deleting a product I am able to swipe over and delete the product row but the product is not deleting the product is still there when the page refresh how do I fix this code to swipe and delete the product

**This is the full I use to delete the product **

import Foundation
import FirebaseStorage
import Firebase

class ProductViewModel: ObservableObject {
    @Published var products: [Product] = []
    let db = Firestore.firestore()
    let storageRef = Storage.storage().reference()
    
    func uploadImage(_ image: UIImage, completion: @escaping (Result<URL, Error>) -> Void) {
        guard let imageData = image.jpegData(compressionQuality: 0.5) else {
            completion(.failure(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to convert image to data"])))
            return
        }
        
        let imageName = UUID().uuidString
        let imageRef = storageRef.child("product_images/\(imageName)")
        
        imageRef.putData(imageData, metadata: nil) { metadata, error in
            guard let _ = metadata else {
                completion(.failure(error ?? NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to upload image"])))
                return
            }
            
            imageRef.downloadURL { url, error in
                if let url = url {
                    completion(.success(url))
                } else {
                    completion(.failure(error ?? NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to get download URL"])))
                }
            }
        }
    }
    
    func saveProduct(_ product: Product, imageURLs: [URL], completion: @escaping (Error?) -> Void) {
        guard let currentUser = Auth.auth().currentUser else {
            completion(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "No user signed in"]))
            return
        }
        
        let userId = currentUser.uid
        
        var productData: [String: Any] = [
            "name": product.name,
            "price": product.price,
            "description": product.description,
            "userId": userId // Save the userId along with the product data
        ]
        
        // Convert imageURLs to an array of string URLs
        let imageURLStrings = imageURLs.map { $0.absoluteString }
        productData["imageURLs"] = imageURLStrings
        
        db.collection("products").addDocument(data: productData) { error in
            completion(error)
        }
    }
    
    func fetchProducts() {
        db.collection("products").getDocuments { snapshot, error in
            if let error = error {
                print("Error fetching products: \(error.localizedDescription)")
                return
            }
            
            guard let snapshot = snapshot else {
                print("No data found")
                return
            }
            
            let products = snapshot.documents.compactMap { document -> Product? in
                let data = document.data()
                let name = data["name"] as? String ?? ""
                let price = data["price"] as? Double ?? 0.0
                let quantity = data["quantity"] as? Int ?? 0
                let imageName = data["imageURLs"] as? [String] ?? [] // Assuming imageURL is the correct field name
                let description = data["description"] as? String ?? ""
                
                return Product(name: name, price: price,  imageURLs: imageName, description: description)
            }
            
            DispatchQueue.main.async {
                self.products = products
            }
        }
    }
    func fetchCurrentUserProducts() {
        guard let currentUser = Auth.auth().currentUser else {
            print("No user signed in")
            return
        }
        
        let userId = currentUser.uid
        
        db.collection("products")
            .whereField("userId", isEqualTo: userId) // Assuming you save userId along with product data
            .getDocuments { snapshot, error in
                if let error = error {
                    print("Error fetching products: \(error.localizedDescription)")
                    return
                }
                
                guard let snapshot = snapshot else {
                    print("No data found")
                    return
                }
                
                let products = snapshot.documents.compactMap { document -> Product? in
                    let data = document.data()
                    let name = data["name"] as? String ?? ""
                    let price = data["price"] as? Double ?? 0.0
                    let quantity = data["quantity"] as? Int ?? 0
                    let imageName = data["imageURLs"] as? [String] ?? [] // Assuming imageURL is the correct field name
                    let description = data["description"] as? String ?? ""
                    
                    return Product(name: name, price: price,  imageURLs: imageName, description: description)
                }
                
                DispatchQueue.main.async {
                    self.products = products
                }
            }
    }
    func saveEditedProduct(_ editedProduct: Product, completion: @escaping (Error?) -> Void) {
        guard let currentUserID = Auth.auth().currentUser?.uid else {
            completion(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "No current user"]))
            return
        }
        
        // Ensure the edited product belongs to the current user
        let productID = editedProduct.id.uuidString
        
        let documentRef = db.collection("products").document(productID)
        documentRef.updateData([
            "name": editedProduct.name,
            "price": editedProduct.price,
            "description": editedProduct.description,
            // You can update other fields as needed
        ]) { error in
            if let error = error {
                print("Error updating product: \(error.localizedDescription)")
                completion(error)
            } else {
                print("Product updated successfully")
                completion(nil)
            }
        }
    }
    func deleteProduct(_ product: Product, completion: @escaping (Error?) -> Void) {
        
        let db = Firestore.firestore()
              
              
              let documentID = product.id.uuidString
              
              db.collection("products").document(documentID).delete { error in
                  if let error = error {
                      completion(error)
                  } else {
                      // Successfully deleted
                      completion(nil)
                  }
              }
          }
          
           }    


import SwiftUI

struct ProductNwRw: View {
    var product: Product
        var onDelete: () -> Void

        var body: some View {
            NavigationLink(destination: EditProduct(viewModel: ProductViewModel(), product: product)) {
                       Text(product.name)
                   }
                   .swipeActions {
                       Button {
                           onDelete()
                       } label: {
                           Label("Delete", systemImage: "trash")
                       }
                       .tint(.red)
                   }
               }
           }


#Preview {
    ProductNwRw(product: Product(name: "Sample Product", price: 19.99, imageURLs: ["19.99"], description: "This is a sample product description."
                                ), onDelete: {})
}

import SwiftUI
import Kingfisher
import StoreKit
struct ProductDetailContentView: View {
    
    @ObservedObject var viewModel = ProductViewModel()
    
    var body: some View {
        List {
                   ForEach(viewModel.products, id: \.id) { product in
                       ProductNwRw(product: product) {
                           viewModel.deleteProduct(product) { error in
                               if let error = error {
                                   print("Error deleting product: \(error.localizedDescription)")
                               } else {
                                   print("Product deleted successfully")
                                   // Optionally, you can remove the product from the list
                                   viewModel.products.removeAll { $0.id == product.id }
                               }
                           }
                       }
                   }
                   .onDelete { indexSet in
                       indexSet.forEach { index in
                           let product = viewModel.products[index]
                           viewModel.deleteProduct(product) { error in
                               if let error = error {
                                   print("Error deleting product: \(error.localizedDescription)")
                               } else {
                                   print("Product deleted successfully")
                                   
                               }
                           }
                       }
                   }
               }
               .onAppear {
                   viewModel.fetchCurrentUserProducts()
               }
           }
       }
    #Preview {
       ProductDetailContentView()
    }
1

There are 1 answers

2
NewbieiOS On

After deleting a product from Firestore, you should also update the products array in your view model to reflect the deletion. This ensures that the UI is updated when the data changes.

Modify your deleteProduct function in ProductViewModel to update the products array after successful deletion:

func deleteProduct(_ product: Product, completion: @escaping (Error?) -> Void) {
    let db = Firestore.firestore()
    let documentID = product.id.uuidString

    db.collection("products").document(documentID).delete { error in
        if let error = error {
            completion(error)
        } else {
            // Successfully deleted
            // Update the products array to reflect deletion
            self.products.removeAll { $0.id == product.id }
            completion(nil)
        }
    }
}

and refresh the UI.

struct ProductDetailContentView: View {
    @ObservedObject var viewModel = ProductViewModel()

    var body: some View {
        List {
            ForEach(viewModel.products, id: \.id) { product in
                ProductNwRw(product: product) {
                    viewModel.deleteProduct(product) { error in
                        if let error = error {
                            print("Error deleting product: \(error.localizedDescription)")
                        } else {
                            print("Product deleted successfully")
                            // Trigger fetching products again after deletion
                            viewModel.fetchCurrentUserProducts()
                        }
                    }
                }
            }
        }
        .onAppear {
            viewModel.fetchCurrentUserProducts()
        }
    }
}

By making these changes, the product deletion should be properly reflected in your UI when the page refreshes after deleting a product. The products array in your view model will be updated, and the UI will be refreshed accordingly. try like this..