Skip to content

Commit

Permalink
161
Browse files Browse the repository at this point in the history
  • Loading branch information
stephencelis committed Sep 28, 2021
1 parent ac48542 commit 28c7f2a
Show file tree
Hide file tree
Showing 12 changed files with 952 additions and 0 deletions.

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import SwiftUI

enum Tab {
case one, inventory, three
}

class AppViewModel: ObservableObject {
@Published var inventoryViewModel: InventoryViewModel
@Published var selectedTab: Tab

init(
inventoryViewModel: InventoryViewModel = .init(),
selectedTab: Tab = .one
) {
self.inventoryViewModel = inventoryViewModel
self.selectedTab = selectedTab
}
}

struct ContentView: View {
@ObservedObject var viewModel: AppViewModel

var body: some View {
TabView(selection: self.$viewModel.selectedTab) {
Button("Go to 2nd tab") {
self.viewModel.selectedTab = .inventory
}
.tabItem { Text("One") }
.tag(Tab.one)

InventoryView(viewModel: self.viewModel.inventoryViewModel)
.tabItem { Text("Inventory") }
.tag(Tab.inventory)

Text("Three")
.tabItem { Text("Three") }
.tag(Tab.three)
}
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(viewModel: .init(selectedTab: .inventory))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import IdentifiedCollections
import SwiftUI

struct Item: Equatable, Identifiable {
let id = UUID()
var name: String
var color: Color?
var status: Status
// var quantity: Int
// var isOnBackOrder: Bool

enum Status: Equatable {
case inStock(quantity: Int)
case outOfStock(isOnBackOrder: Bool)

var isInStock: Bool {
guard case .inStock = self else { return false }
return true
}
}

struct Color: Equatable, Hashable {
var name: String
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0

static var defaults: [Self] = [
.red,
.green,
.blue,
.black,
.yellow,
.white,
]

static let red = Self(name: "Red", red: 1)
static let green = Self(name: "Green", green: 1)
static let blue = Self(name: "Blue", blue: 1)
static let black = Self(name: "Black")
static let yellow = Self(name: "Yellow", red: 1, green: 1)
static let white = Self(name: "White", red: 1, green: 1, blue: 1)

var swiftUIColor: SwiftUI.Color {
.init(red: self.red, green: self.green, blue: self.blue)
}
}
}

class InventoryViewModel: ObservableObject {
@Published var inventory: IdentifiedArrayOf<Item>
@Published var itemToDelete: Item?

init(
inventory: IdentifiedArrayOf<Item> = [],
itemToDelete: Item? = nil
) {
self.itemToDelete = itemToDelete
self.inventory = inventory
}

func delete(item: Item) {
withAnimation {
_ = self.inventory.remove(id: item.id)
//self.inventory.removeAll(where: { $0.id == item.id })
}
}

func deleteButtonTapped(item: Item) {
self.itemToDelete = item
}
}

struct InventoryView: View {
@ObservedObject var viewModel: InventoryViewModel
// @State var deleteItemAlertIsPresented = false
// @State var itemToDelete: Item?

var body: some View {
List {
ForEach(self.viewModel.inventory) { item in
HStack {
VStack(alignment: .leading) {
Text(item.name)

switch item.status {
case let .inStock(quantity):
Text("In stock: \(quantity)")
case let .outOfStock(isOnBackOrder):
Text("Out of stock" + (isOnBackOrder ? ": on back order" : ""))
}
}

Spacer()

if let color = item.color {
Rectangle()
.frame(width: 30, height: 30)
.foregroundColor(color.swiftUIColor)
.border(Color.black, width: 1)
}

Button(action: { self.viewModel.deleteButtonTapped(item: item) }) {
Image(systemName: "trash.fill")
}
.padding(.leading)
}
.buttonStyle(.plain)
.foregroundColor(item.status.isInStock ? nil : Color.gray)
}
}
.alert(
title: { Text($0.name) },
presenting: self.$viewModel.itemToDelete,
actions: { item in
Button("Delete", role: .destructive) {
self.viewModel.delete(item: item)
}
},
message: { _ in
Text("Are you sure you want to delete this item?")
}
)
// .alert(item: self.$viewModel.itemToDelete) { item in
// Alert(
// title: Text(item.name),
// message: Text("Are you sure you want to delete this item?"),
// primaryButton: .destructive(Text("Delete")) {
// self.viewModel.delete(item: item)
// },
// secondaryButton: .cancel()
// )
// }
}
}

struct InventoryView_Previews: PreviewProvider {
static var previews: some View {
let keyboard = Item(name: "Keyboard", color: .blue, status: .inStock(quantity: 100))

InventoryView(
viewModel: .init(
inventory: [
keyboard,
Item(name: "Charger", color: .yellow, status: .inStock(quantity: 20)),
Item(name: "Phone", color: .green, status: .outOfStock(isOnBackOrder: true)),
Item(name: "Headphones", color: .green, status: .outOfStock(isOnBackOrder: false)),
],
itemToDelete: keyboard
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import SwiftUI

extension Binding {
func isPresent<Wrapped>() -> Binding<Bool>
where Value == Wrapped? {
.init(
get: { self.wrappedValue != nil },
set: { isPresented in
if !isPresented {
self.wrappedValue = nil
}
}
)
}
}

extension View {
func alert<A: View, M: View, T>(
title: (T) -> Text,
presenting data: Binding<T?>,
@ViewBuilder actions: @escaping (T) -> A,
@ViewBuilder message: @escaping (T) -> M
) -> some View {
self.alert(
data.wrappedValue.map(title) ?? Text(""),
isPresented: data.isPresent(),
presenting: data.wrappedValue,
actions: actions,
message: message
)
}

func confirmationDialog<A: View, M: View, T>(
title: (T) -> Text,
titleVisibility: Visibility = .automatic,
presenting data: Binding<T?>,
@ViewBuilder actions: @escaping (T) -> A,
@ViewBuilder message: @escaping (T) -> M
) -> some View {
self.confirmationDialog(
data.wrappedValue.map(title) ?? Text(""),
isPresented: data.isPresent(),
titleVisibility: titleVisibility,
presenting: data.wrappedValue,
actions: actions,
message: message
)
}
}
Loading

0 comments on commit 28c7f2a

Please sign in to comment.