article

Tuesday, November 9, 2021

SwiftUI Firebase Grocery Shopping List App

SwiftUI Firebase Grocery Shopping List App
ContentView.swift
 
//
//  ContentView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import Firebase
import FirebaseFirestoreSwift

struct ContentView: View {
    
    private var db: Firestore
    @State private var storeName: String = ""
    @State private var stores: [Store] = []
    
    init() {
        db = Firestore.firestore()
    }
    
    private func saveStore(store: Store) {
        _ = try? db.collection("stores")
            .addDocument(from: store) { error in
                if let error = error {
                    print(error.localizedDescription)
                } else {
                    print("Document has been saved!")
                    getAllStores()
                }
                
            }
    }
    
    private func getAllStores() {
        
        db.collection("stores")
            .getDocuments { (snapshot, error) in
                if let error = error {
                    print(error.localizedDescription)
                } else {
                    if let snapshot = snapshot {
                        stores = snapshot.documents.compactMap { doc in
                            var store = try? doc.data(as: Store.self)
                            if store != nil {
                                store!.id = doc.documentID
                            }
                            return store
                        }
                    }
                }
            }
        
    }
    
    private func deleteStore(at indexSet: IndexSet) {
        indexSet.forEach { index in
            
            let store = stores[index]
            // delete from the firestore database
            db.collection("stores")
                .document(store.id!)
                .delete { error in
                    if let error = error {
                        print(error.localizedDescription)
                    } else {
                        getAllStores()
                    }
                }
            
        }
    }
    
    var body: some View {
        
        NavigationView {
            
            VStack {
                TextField("Enter store name", text: $storeName)
                    .font(.title2)
                    .modifier(customViewModifier(roundedCornes: 6, startColor: .orange, endColor: .purple, textColor: .white))
                Button("Save Store") {
                    saveStore(store: Store(name: storeName))
                }
                .frame(width: 200)
                .padding()
                .foregroundColor(.white)
                .background(Color.orange)
                .cornerRadius(40)
                
                List {
                    
                    ForEach(stores, id: \.name) { store in
                        NavigationLink(
                            destination: StoreDetailsView(store: store))
                        {
                            Text(store.name)
                        }
                    }.onDelete(perform: deleteStore)
                }.listStyle(PlainListStyle())
                
                Spacer()
                    
                    .onAppear(perform: {
                        getAllStores()
                    })
                
            }.padding()
            
            .navigationTitle("Grocery")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


struct customViewModifier: ViewModifier {
    var roundedCornes: CGFloat
    var startColor: Color
    var endColor: Color
    var textColor: Color
    
    func body(content: Content) -> some View {
        content
            .padding()
            .background(LinearGradient(gradient: Gradient(colors: [startColor, endColor]), startPoint: .topLeading, endPoint: .bottomTrailing))
            .cornerRadius(roundedCornes)
            .padding(3)
            .foregroundColor(textColor)
            .overlay(RoundedRectangle(cornerRadius: roundedCornes)
                        .stroke(LinearGradient(gradient: Gradient(colors: [startColor, endColor]), startPoint: .topLeading, endPoint: .bottomTrailing), lineWidth: 2.5))
            .font(.custom("Open Sans", size: 18))
            
            .shadow(radius: 10)
    }
}
StoreDetailsView.swift
 
//
//  StoreDetailsView.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import Firebase
import FirebaseFirestoreSwift

struct StoreDetailsView: View {
    
    @State var store: Store
    @State private var storeName: String = ""
    @State private var groceryItemName: String = ""
    let db = Firestore.firestore()
    
    private func updateStore() {
        
        db.collection("stores")
            .document(store.id!)
            .updateData(["name": storeName]) { error in
                
                if let error = error {
                    print(error.localizedDescription)
                } else {
                    print("Store has been updated!")
                }
            }
        
    }
    
    private func loadGroceryItems() {
        let ref = db.collection("stores")
            .document(store.id!)
        
        ref.getDocument { doc, error in
            if let doc = doc, doc.exists {
                if let store = try? doc.data(as: Store.self) {
                    self.store = store
                    self.store.id = doc.documentID
                }
            } else {
                print("Document does not exists!")
            }
        }
        
    }
    
    private func saveGroceryItem() {
        
        db.collection("stores")
            .document(store.id!)
            .updateData([
                "items": FieldValue.arrayUnion([groceryItemName])
            ]) { error in
                if let error = error {
                    print(error.localizedDescription)
                } else {
                    // load the docs and populate the items
                    loadGroceryItems()
                }
            }
        
    }
    
    var body: some View {
       
        NavigationView {
            VStack {
                TextField("Enter item name", text: $groceryItemName)
                    .font(.title2)
                    .modifier(customViewModifier(roundedCornes: 6, startColor: .orange, endColor: .purple, textColor: .white))
                
                Button("Add Item") {
                    saveGroceryItem()
                }
                .frame(width: 200)
                .padding()
                .foregroundColor(.white)
                .background(Color.orange)
                .cornerRadius(40)
                
                if let items = store.items {
                    List(items, id: \.self) { item in
                        Text(item)
                    }.listStyle(GroupedListStyle())
                }
                
                Spacer()
                
            }.padding()
        }.navigationTitle(store.name)
    }
}

struct StoreDetailsView_Previews: PreviewProvider {
    static var previews: some View {
        StoreDetailsView(store: Store(id: "333", name: "HEB"))
    }
}
Store.swift
 
//
//  Store.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import Foundation

struct Store: Codable {
    var id: String?
    let name: String
    var items: [String]? = nil
}
DevSwiftUIApp.swift
 
//
//  DevSwiftUIApp.swift
//  DevSwiftUI
//
//  Created by Cairocoders
//

import SwiftUI
import Firebase

@main
struct DevSwiftUIApp: App {
       
    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
      
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
  
class AppDelegate: NSObject,UIApplicationDelegate{
        
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
            
        FirebaseApp.configure()
        return true
    }
}

Related Post