UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Challenge iExpense Day 37 – Project 7

Forums > 100 Days of SwiftUI

//
//  AddView.swift
//  iExpense
//

import SwiftUI

struct AddView: View {
    @State private var name = ""
    @State private var type = "Personal"
    @State private var amount = ""
@Environment(\.presentationMode) var presentationMode
    static let types = ["Business", "Personal"]
    @ObservedObject var expenses: Expenses
    @State private var showAlert = false

    var body: some View {
        NavigationView {
            Form {
                TextField("Name", text: $name)
                Picker("Type", selection: $type) {
                    ForEach(Self.types, id: \.self) {
                        Text($0)
                    }
                }
                TextField("Amount", text: $amount)
                    .keyboardType(.numberPad)
            }
            .navigationBarTitle("Add new expense")
            .navigationBarItems(trailing: Button("Save") {
                if let actualAmount = Int(self.amount) {
                    let item = ExpenseItem(name: self.name, type: self.type, amount: actualAmount)
                    self.expenses.items.append(item)
                    self.presentationMode.wrappedValue.dismiss()
                }
                else {
                    self.showAlert = true
                }

            })
                .alert(isPresented: $showAlert){
                    Alert(title: Text("Warning!"), message: Text("Something went wrong"), dismissButton: .default(Text("OK")))
            }
        }
    }
}

struct AddView_Previews: PreviewProvider {
    static var previews: some View {
        AddView(expenses: Expenses())
    }
}
//
//  ContentView.swift
//  iExpense
//

import SwiftUI

struct ExpenseItem: Identifiable,Codable {
    let id = UUID()
    let name: String
    let type: String
    let amount: Int
}

class Expenses: ObservableObject {
    @Published var items: [ExpenseItem] {
        didSet {
            let encoder = JSONEncoder()
            if let encoded = try? encoder.encode(items) {
                UserDefaults.standard.set(encoded, forKey: "Items")
            }
        }
    }
    init() {
        if let items = UserDefaults.standard.data(forKey: "Items") {
            let decoder = JSONDecoder()
            if let decoded = try? decoder.decode([ExpenseItem].self, from: items) {
                self.items = decoded
                return
            }
        }

        self.items = []
    }
}

struct style: ViewModifier{
    var amount: Int

    func body(content: Content) -> some View {
        if amount < 10 {
            return content.foregroundColor(.red)
        }

        else if amount < 100 {
            return content.foregroundColor(.green)
        }

        else if amount > 100{
            return content.foregroundColor(.blue)
        }

        else {
            return content.foregroundColor(.black)
        }
    }
}

struct ContentView: View {
    @State private var showingAddExpense = false
    @ObservedObject var expenses = Expenses()

    var body: some View {
        NavigationView {
            List {
                ForEach(expenses.items) { item in
                    HStack {
                        VStack(alignment: .leading) {
                            Text(item.name)
                                .font(.headline)
                            Text(item.type)
                        }

                        Spacer()
                        Text("$\(item.amount)")
                            .modifier(style(amount: item.amount))
                    }
                }
                .onDelete(perform: removeItems)
            }
            .navigationBarItems(leading: EditButton(), trailing: Button(action: {
                self.showingAddExpense = true
            }) {
                Image(systemName: "plus")
            })
                .sheet(isPresented: $showingAddExpense) {
                    AddView(expenses: self.expenses)
            }
            .navigationBarTitle("iExpense")
        }
    }

    func removeItems(at offsets: IndexSet) {
        expenses.items.remove(atOffsets: offsets)
    }

}

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

3      

do you have a question about your code? btw I had a read on your code as I am doing the same project. Thanks for the code on ViewModifier, I was stuck in a challenge on changing $ color!

3      

Text("$\(item.cost)")
                            .foregroundColor(item.cost <= 100 ? .green : item.cost > 100 && item.cost < 1000 ? .orange : .red)

Hey guys this replaces your multiple line code to only two :)

6      

Thanks for posting some code everyone, seeing other approaches after a while of trying myself and not being sure how to approach it myself, is a great learning tool. Only after I bang my head against the wall a bit first :).

3      

How would you remove Amount alltogether?

3      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.