diff --git a/Shopping List.xcodeproj/project.pbxproj b/Shopping List.xcodeproj/project.pbxproj index 9970ba97..c9d8f245 100644 --- a/Shopping List.xcodeproj/project.pbxproj +++ b/Shopping List.xcodeproj/project.pbxproj @@ -8,20 +8,30 @@ /* Begin PBXBuildFile section */ 4613E91221143BFC00E7FF73 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4613E91121143BFC00E7FF73 /* AppDelegate.swift */; }; - 4613E91421143BFC00E7FF73 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4613E91321143BFC00E7FF73 /* ViewController.swift */; }; 4613E91721143BFC00E7FF73 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4613E91521143BFC00E7FF73 /* Main.storyboard */; }; 4613E91921143BFD00E7FF73 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4613E91821143BFD00E7FF73 /* Assets.xcassets */; }; 4613E91C21143BFD00E7FF73 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4613E91A21143BFD00E7FF73 /* LaunchScreen.storyboard */; }; + B483F7002478236C004C8620 /* ShoppingItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B483F6FF2478236C004C8620 /* ShoppingItem.swift */; }; + B483F70224782578004C8620 /* ShoppingList.swift in Sources */ = {isa = PBXBuildFile; fileRef = B483F70124782578004C8620 /* ShoppingList.swift */; }; + B483F70524782DA3004C8620 /* DefaultsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B483F70424782DA3004C8620 /* DefaultsHelper.swift */; }; + B483F7072478321B004C8620 /* ShoppingItemsCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B483F7062478321B004C8620 /* ShoppingItemsCollectionViewController.swift */; }; + B483F70924783248004C8620 /* OrderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B483F70824783248004C8620 /* OrderViewController.swift */; }; + B483F70B24783262004C8620 /* ShoppingItemsCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B483F70A24783262004C8620 /* ShoppingItemsCollectionViewCell.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 4613E90E21143BFC00E7FF73 /* Shopping List.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Shopping List.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 4613E91121143BFC00E7FF73 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 4613E91321143BFC00E7FF73 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 4613E91621143BFC00E7FF73 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 4613E91821143BFD00E7FF73 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 4613E91B21143BFD00E7FF73 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 4613E91D21143BFD00E7FF73 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B483F6FF2478236C004C8620 /* ShoppingItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingItem.swift; sourceTree = ""; }; + B483F70124782578004C8620 /* ShoppingList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingList.swift; sourceTree = ""; }; + B483F70424782DA3004C8620 /* DefaultsHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultsHelper.swift; sourceTree = ""; }; + B483F7062478321B004C8620 /* ShoppingItemsCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingItemsCollectionViewController.swift; sourceTree = ""; }; + B483F70824783248004C8620 /* OrderViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderViewController.swift; sourceTree = ""; }; + B483F70A24783262004C8620 /* ShoppingItemsCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingItemsCollectionViewCell.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -54,16 +64,53 @@ 4613E91021143BFC00E7FF73 /* Shopping List */ = { isa = PBXGroup; children = ( - 4613E91121143BFC00E7FF73 /* AppDelegate.swift */, - 4613E91321143BFC00E7FF73 /* ViewController.swift */, + B483F70E2478328D004C8620 /* Resources */, 4613E91521143BFC00E7FF73 /* Main.storyboard */, - 4613E91821143BFD00E7FF73 /* Assets.xcassets */, - 4613E91A21143BFD00E7FF73 /* LaunchScreen.storyboard */, + B483F70D2478326F004C8620 /* View Controllers */, + B483F70C24783266004C8620 /* Views */, 4613E91D21143BFD00E7FF73 /* Info.plist */, + B483F70324782D44004C8620 /* Models */, ); path = "Shopping List"; sourceTree = ""; }; + B483F70324782D44004C8620 /* Models */ = { + isa = PBXGroup; + children = ( + B483F6FF2478236C004C8620 /* ShoppingItem.swift */, + B483F70124782578004C8620 /* ShoppingList.swift */, + B483F70424782DA3004C8620 /* DefaultsHelper.swift */, + ); + path = Models; + sourceTree = ""; + }; + B483F70C24783266004C8620 /* Views */ = { + isa = PBXGroup; + children = ( + B483F70A24783262004C8620 /* ShoppingItemsCollectionViewCell.swift */, + ); + path = Views; + sourceTree = ""; + }; + B483F70D2478326F004C8620 /* View Controllers */ = { + isa = PBXGroup; + children = ( + B483F7062478321B004C8620 /* ShoppingItemsCollectionViewController.swift */, + B483F70824783248004C8620 /* OrderViewController.swift */, + ); + path = "View Controllers"; + sourceTree = ""; + }; + B483F70E2478328D004C8620 /* Resources */ = { + isa = PBXGroup; + children = ( + 4613E91121143BFC00E7FF73 /* AppDelegate.swift */, + 4613E91821143BFD00E7FF73 /* Assets.xcassets */, + 4613E91A21143BFD00E7FF73 /* LaunchScreen.storyboard */, + ); + path = Resources; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -135,8 +182,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4613E91421143BFC00E7FF73 /* ViewController.swift in Sources */, + B483F7072478321B004C8620 /* ShoppingItemsCollectionViewController.swift in Sources */, + B483F70524782DA3004C8620 /* DefaultsHelper.swift in Sources */, + B483F7002478236C004C8620 /* ShoppingItem.swift in Sources */, + B483F70224782578004C8620 /* ShoppingList.swift in Sources */, 4613E91221143BFC00E7FF73 /* AppDelegate.swift in Sources */, + B483F70B24783262004C8620 /* ShoppingItemsCollectionViewCell.swift in Sources */, + B483F70924783248004C8620 /* OrderViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Shopping List/Base.lproj/Main.storyboard b/Shopping List/Base.lproj/Main.storyboard index 03c13c22..ae6d5274 100644 --- a/Shopping List/Base.lproj/Main.storyboard +++ b/Shopping List/Base.lproj/Main.storyboard @@ -1,24 +1,159 @@ - + + - + + + - - + + - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + diff --git a/Shopping List/Models/DefaultsHelper.swift b/Shopping List/Models/DefaultsHelper.swift new file mode 100644 index 00000000..73df6898 --- /dev/null +++ b/Shopping List/Models/DefaultsHelper.swift @@ -0,0 +1,14 @@ +// +// DefaultsHelper.swift +// Shopping List +// +// Created by Mike Nichols on 5/22/20. +// Copyright © 2020 Lambda School. All rights reserved. +// + +import Foundation + +extension String { + static var isNewUser = "isNewUser" +} + diff --git a/Shopping List/Models/ShoppingItem.swift b/Shopping List/Models/ShoppingItem.swift new file mode 100644 index 00000000..ca24b364 --- /dev/null +++ b/Shopping List/Models/ShoppingItem.swift @@ -0,0 +1,25 @@ +// +// ShoppingItem.swift +// Shopping List +// +// Created by Mike Nichols on 5/22/20. +// Copyright © 2020 Lambda School. All rights reserved. +// + +import Foundation +import UIKit + +struct ShoppingItem: Codable { + var itemName: String + var isOnList: Bool + var itemImage: UIImage? { + let itemImageName = "\(itemName).png" + guard let itemImage = UIImage(named: itemImageName) else { + return nil + } + return itemImage + } +} + + + diff --git a/Shopping List/Models/ShoppingList.swift b/Shopping List/Models/ShoppingList.swift new file mode 100644 index 00000000..d4776418 --- /dev/null +++ b/Shopping List/Models/ShoppingList.swift @@ -0,0 +1,76 @@ +// +// ShoppingList.swift +// Shopping List +// +// Created by Mike Nichols on 5/22/20. +// Copyright © 2020 Lambda School. All rights reserved. +// + +import Foundation + +protocol ShoppingListDelegate { + func saveToPersistentStore() + + func loadFromPersistentStore() +} + + +class ShoppingList: Codable { + + var delegate: ShoppingListDelegate? + + var shoppingList: [ShoppingItem] = [] + var persistentFileURL: URL? { + let fileManager = FileManager.default + let documentsDir = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first + let url = documentsDir?.appendingPathComponent("shoppingList.plist") + + return url + } + + init() { + let isNewUser = UserDefaults.standard.bool(forKey: "isNewUser") + if isNewUser == true { + let itemNames = ["Apple", "Grapes", "Milk", "Muffin", "Popcorn", "Soda", "Strawberries"] + for item in itemNames { + let item = ShoppingItem(itemName: item, isOnList: false) + shoppingList.append(item) + } + saveToPersistentStore() + let defaults = UserDefaults.standard + defaults.set(false, forKey: "isNewUser") + } else { + loadFromPersistentStore() + } + } + + func loadFromPersistentStore() { + do { + guard let persistentFileURL = persistentFileURL else { return } + + let shoppingListPList = try Data(contentsOf: persistentFileURL) + let decoder = PropertyListDecoder() + let decodedShoppingList = try decoder.decode([ShoppingItem].self, from: shoppingListPList) + self.shoppingList = decodedShoppingList + + } catch { + fatalError("Failed to load list") + } + } + + func saveToPersistentStore() { + do { + guard let persistentFileURL = persistentFileURL else { return } + + let encoder = PropertyListEncoder() + let encodedShoppingList = try encoder.encode(shoppingList) + try encodedShoppingList.write(to: persistentFileURL) + + } catch { + + fatalError("Failed to save list") + + } +} +} + diff --git a/Shopping List/AppDelegate.swift b/Shopping List/Resources/AppDelegate.swift similarity index 100% rename from Shopping List/AppDelegate.swift rename to Shopping List/Resources/AppDelegate.swift diff --git a/Shopping List/Assets.xcassets/AppIcon.appiconset/Contents.json b/Shopping List/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Shopping List/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Shopping List/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Shopping List/Assets.xcassets/Apple.imageset/Contents.json b/Shopping List/Resources/Assets.xcassets/Apple.imageset/Contents.json similarity index 100% rename from Shopping List/Assets.xcassets/Apple.imageset/Contents.json rename to Shopping List/Resources/Assets.xcassets/Apple.imageset/Contents.json diff --git a/Shopping List/Assets.xcassets/Apple.imageset/apple.png b/Shopping List/Resources/Assets.xcassets/Apple.imageset/apple.png similarity index 100% rename from Shopping List/Assets.xcassets/Apple.imageset/apple.png rename to Shopping List/Resources/Assets.xcassets/Apple.imageset/apple.png diff --git a/Shopping List/Assets.xcassets/Contents.json b/Shopping List/Resources/Assets.xcassets/Contents.json similarity index 100% rename from Shopping List/Assets.xcassets/Contents.json rename to Shopping List/Resources/Assets.xcassets/Contents.json diff --git a/Shopping List/Assets.xcassets/Grapes.imageset/Contents.json b/Shopping List/Resources/Assets.xcassets/Grapes.imageset/Contents.json similarity index 100% rename from Shopping List/Assets.xcassets/Grapes.imageset/Contents.json rename to Shopping List/Resources/Assets.xcassets/Grapes.imageset/Contents.json diff --git a/Shopping List/Assets.xcassets/Grapes.imageset/grapes.png b/Shopping List/Resources/Assets.xcassets/Grapes.imageset/grapes.png similarity index 100% rename from Shopping List/Assets.xcassets/Grapes.imageset/grapes.png rename to Shopping List/Resources/Assets.xcassets/Grapes.imageset/grapes.png diff --git a/Shopping List/Assets.xcassets/Milk.imageset/Contents.json b/Shopping List/Resources/Assets.xcassets/Milk.imageset/Contents.json similarity index 100% rename from Shopping List/Assets.xcassets/Milk.imageset/Contents.json rename to Shopping List/Resources/Assets.xcassets/Milk.imageset/Contents.json diff --git a/Shopping List/Assets.xcassets/Milk.imageset/milk.png b/Shopping List/Resources/Assets.xcassets/Milk.imageset/milk.png similarity index 100% rename from Shopping List/Assets.xcassets/Milk.imageset/milk.png rename to Shopping List/Resources/Assets.xcassets/Milk.imageset/milk.png diff --git a/Shopping List/Assets.xcassets/Muffin.imageset/Contents.json b/Shopping List/Resources/Assets.xcassets/Muffin.imageset/Contents.json similarity index 100% rename from Shopping List/Assets.xcassets/Muffin.imageset/Contents.json rename to Shopping List/Resources/Assets.xcassets/Muffin.imageset/Contents.json diff --git a/Shopping List/Assets.xcassets/Muffin.imageset/muffin.png b/Shopping List/Resources/Assets.xcassets/Muffin.imageset/muffin.png similarity index 100% rename from Shopping List/Assets.xcassets/Muffin.imageset/muffin.png rename to Shopping List/Resources/Assets.xcassets/Muffin.imageset/muffin.png diff --git a/Shopping List/Assets.xcassets/Popcorn.imageset/Contents.json b/Shopping List/Resources/Assets.xcassets/Popcorn.imageset/Contents.json similarity index 100% rename from Shopping List/Assets.xcassets/Popcorn.imageset/Contents.json rename to Shopping List/Resources/Assets.xcassets/Popcorn.imageset/Contents.json diff --git a/Shopping List/Assets.xcassets/Popcorn.imageset/popcorn.png b/Shopping List/Resources/Assets.xcassets/Popcorn.imageset/popcorn.png similarity index 100% rename from Shopping List/Assets.xcassets/Popcorn.imageset/popcorn.png rename to Shopping List/Resources/Assets.xcassets/Popcorn.imageset/popcorn.png diff --git a/Shopping List/Assets.xcassets/Soda.imageset/Contents.json b/Shopping List/Resources/Assets.xcassets/Soda.imageset/Contents.json similarity index 100% rename from Shopping List/Assets.xcassets/Soda.imageset/Contents.json rename to Shopping List/Resources/Assets.xcassets/Soda.imageset/Contents.json diff --git a/Shopping List/Assets.xcassets/Soda.imageset/soda.png b/Shopping List/Resources/Assets.xcassets/Soda.imageset/soda.png similarity index 100% rename from Shopping List/Assets.xcassets/Soda.imageset/soda.png rename to Shopping List/Resources/Assets.xcassets/Soda.imageset/soda.png diff --git a/Shopping List/Assets.xcassets/Strawberries.imageset/Contents.json b/Shopping List/Resources/Assets.xcassets/Strawberries.imageset/Contents.json similarity index 100% rename from Shopping List/Assets.xcassets/Strawberries.imageset/Contents.json rename to Shopping List/Resources/Assets.xcassets/Strawberries.imageset/Contents.json diff --git a/Shopping List/Assets.xcassets/Strawberries.imageset/strawberries.png b/Shopping List/Resources/Assets.xcassets/Strawberries.imageset/strawberries.png similarity index 100% rename from Shopping List/Assets.xcassets/Strawberries.imageset/strawberries.png rename to Shopping List/Resources/Assets.xcassets/Strawberries.imageset/strawberries.png diff --git a/Shopping List/Base.lproj/LaunchScreen.storyboard b/Shopping List/Resources/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from Shopping List/Base.lproj/LaunchScreen.storyboard rename to Shopping List/Resources/Base.lproj/LaunchScreen.storyboard diff --git a/Shopping List/View Controllers/OrderViewController.swift b/Shopping List/View Controllers/OrderViewController.swift new file mode 100644 index 00000000..90eb7b89 --- /dev/null +++ b/Shopping List/View Controllers/OrderViewController.swift @@ -0,0 +1,29 @@ +// +// OrderViewController.swift +// Shopping List +// +// Created by Mike Nichols on 5/22/20. +// Copyright © 2020 Lambda School. All rights reserved. +// + +import UIKit + +class OrderViewController: UIViewController { + + @IBOutlet weak var nameTextField: UITextField! + @IBOutlet weak var addressTextField: UITextField! + @IBOutlet weak var itemCountLabel: UILabel! + + override func viewDidLoad() { + super.viewDidLoad() + + } + + + + @IBAction func submitWasTapped(_ sender: UIButton) { + let alert = UIAlertController(title: "Thank you, \(String(describing: nameTextField.text))!", message: "Your items will be delivered to \(String(describing: addressTextField.text)) in the next 15 minutes.", preferredStyle: .alert) + present(alert, animated: true, completion: nil) + + } +} diff --git a/Shopping List/View Controllers/ShoppingItemsCollectionViewController.swift b/Shopping List/View Controllers/ShoppingItemsCollectionViewController.swift new file mode 100644 index 00000000..0b27185e --- /dev/null +++ b/Shopping List/View Controllers/ShoppingItemsCollectionViewController.swift @@ -0,0 +1,69 @@ +// +// ShoppingItemsCollectionViewController.swift +// Shopping List +// +// Created by Mike Nichols on 5/22/20. +// Copyright © 2020 Lambda School. All rights reserved. +// + +import UIKit + +class ShoppingItemsCollectionViewController: UICollectionViewController { + + var myList = ShoppingList() + + var delegate: ShoppingListCellDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + collectionView?.dataSource = self + collectionView?.delegate = self + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + guard let destinationVC = segue.destination as? OrderViewController else { return } + + var itemsOnList: Int = 0 + for item in myList.shoppingList { + if item.isOnList == true { + itemsOnList += 1 + } + } + destinationVC.itemCountLabel.text = String(itemsOnList) + } + + + + override func numberOfSections(in collectionView: UICollectionView) -> Int { + // #warning Incomplete implementation, return the number of sections + return 1 + } + + override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of items + return myList.shoppingList.count + } + + override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ItemCell", for: indexPath) as? ShoppingItemsCollectionViewCell else { + fatalError("Collection view cell identifier is wrong or cell is not of type ShoppingItemsCollectionViewCell" ) + } + + let item = myList.shoppingList[indexPath.item] + cell.itemImageView.image = item.itemImage + cell.itemNameLabel.text = item.itemName + + + return cell + +} + + override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + guard let cell = collectionView.cellForItem(at: indexPath) else { return } + + delegate?.itemSelected(cell as! ShoppingItemsCollectionViewCell) + } + +} + diff --git a/Shopping List/ViewController.swift b/Shopping List/ViewController.swift deleted file mode 100644 index eecb48b5..00000000 --- a/Shopping List/ViewController.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// ViewController.swift -// Shopping List -// -// Created by Spencer Curtis on 8/3/18. -// Copyright © 2018 Lambda School. All rights reserved. -// - -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - -} - diff --git a/Shopping List/Views/ShoppingItemsCollectionViewCell.swift b/Shopping List/Views/ShoppingItemsCollectionViewCell.swift new file mode 100644 index 00000000..22c599f7 --- /dev/null +++ b/Shopping List/Views/ShoppingItemsCollectionViewCell.swift @@ -0,0 +1,33 @@ +// +// ShoppingItemsCollectionViewCell.swift +// Shopping List +// +// Created by Mike Nichols on 5/22/20. +// Copyright © 2020 Lambda School. All rights reserved. +// + +import UIKit + +protocol ShoppingListCellDelegate: class { + func itemSelected(_ cell: ShoppingItemsCollectionViewCell) + +} + +class ShoppingItemsCollectionViewCell: UICollectionViewCell, ShoppingListCellDelegate { + + var delegate: ShoppingListDelegate? + + @IBOutlet weak var itemImageView: UIImageView! + @IBOutlet weak var itemNameLabel: UILabel! + @IBOutlet weak var isOnListButton: UIButton! + + func itemSelected(_ cell: ShoppingItemsCollectionViewCell) { + if cell.isOnListButton.isSelected == true { + cell.isOnListButton.isSelected = false + + } else { + cell.isOnListButton.isSelected = true + } + delegate?.saveToPersistentStore() + } +}