WWDC24 SALE: Save 50% on all my Swift books and bundles! >>

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      

Save 50% in my WWDC sale.

SAVE 50% To celebrate WWDC24, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

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.