From d01363f236c63adc08bd5a9a5e7fc11db52426b2 Mon Sep 17 00:00:00 2001 From: k3y0708 Date: Fri, 28 Jun 2024 14:10:19 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=84=20UI=20Enhancements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AboTracker/ContentView.swift | 119 +++++++++++++++++++++++++--------- AboTracker/Subscription.swift | 63 ++++++++++++------ 2 files changed, 134 insertions(+), 48 deletions(-) diff --git a/AboTracker/ContentView.swift b/AboTracker/ContentView.swift index 7e03c64..133e91a 100644 --- a/AboTracker/ContentView.swift +++ b/AboTracker/ContentView.swift @@ -1,49 +1,66 @@ import SwiftUI struct ContentView: View { - var subs: [Subscription] = [ - Subscription(name: "Test", amount: 9.99, intervall: .monthly), - Subscription(name: "Fitness First", amount: 8, intervall: .weekly) + @State private var showAddSubscriptionSheet = false + @State private var subs: [Subscription] = [ + Subscription(name: "Test", payments: [Payment(amount: 9.99, intervall: .monthly)]), + Subscription(name: "Fitness First", payments: [Payment(amount: 8, intervall: .weekly), Payment(amount: 30, intervall: .quarter)]) ] var body: some View { NavigationView { - List { - ForEach(subs) { sub in - HStack { + Form { + Section(header: Text("Subscriptions")) { + ForEach(subs) { sub in VStack(alignment: .leading, spacing: 8) { - HStack { - Image(systemName: "arrow.left") - Text(sub.name) - Spacer() - Text("\(sub.amount, specifier: "%.2f")€/\(sub.intervall.description)") + Text(sub.name) + .font(.headline) + ForEach(sub.payments) { payment in + HStack { + Text("\(payment.amount, specifier: "%.2f")\(Currency.euro.description)") + Spacer() + Text("/\(payment.intervall.description)") + .foregroundColor(.gray) + } + .font(.subheadline) } } - .frame(maxWidth: .infinity, alignment: .leading) - .padding(7) - .background(Color.gray.opacity(0.15)) - .cornerRadius(10) - .padding(5) + .padding(.vertical, 8) } - .frame(maxWidth: .infinity) - .padding(.vertical, 4) + .onDelete(perform: deleteSubscription) } - .listRowInsets(EdgeInsets()) - .listRowSeparator(.hidden) - HStack { - Text("Monthly Total: ") - Spacer() - Text("\(getMonthlyTotal(subs: subs), specifier: "%.2f€")") + Section { + HStack { + Text("Monthly Total") + Spacer() + Text("\(getMonthlyTotal(subs: subs), specifier: "%.2f")\(Currency.euro.description)") + .foregroundColor(.gray) + } + } + + Section { + Button("Add a Subscription") { + showAddSubscriptionSheet.toggle() + } } - .padding(.vertical, 4) - Button("Add a Subscription", action: addSub) } - .listStyle(PlainListStyle()) .navigationTitle("Subscriptions") + .navigationBarItems(leading: EditButton(), trailing: Button(action: { + showAddSubscriptionSheet.toggle() + }) { + Image(systemName: "plus") + }) + .sheet(isPresented: $showAddSubscriptionSheet) { + AddSubscriptionView(subs: $subs) + } } } + func deleteSubscription(at offsets: IndexSet) { + subs.remove(atOffsets: offsets) + } + func getMonthlyTotal(subs: [Subscription]) -> Float { var monthlyTotal: Float = 0.0 for sub in subs { @@ -51,9 +68,53 @@ struct ContentView: View { } return monthlyTotal } +} + +struct AddSubscriptionView: View { + @Environment(\.presentationMode) var presentationMode + @Binding var subs: [Subscription] - func addSub() -> Void { - + @State private var name: String = "" + @State private var amount: String = "" + @State private var intervall: PaymentIntervall = .monthly + + var body: some View { + NavigationView { + Form { + Section(header: Text("Subscription Name")) { + TextField("Name", text: $name) + } + + Section(header: Text("Amount")) { + TextField("Amount", text: $amount) + .keyboardType(.decimalPad) + } + + Section(header: Text("Intervall")) { + Picker("Intervall", selection: $intervall) { + Text("Weekly").tag(PaymentIntervall.weekly) + Text("Monthly").tag(PaymentIntervall.monthly) + Text("Quarter").tag(PaymentIntervall.quarter) + Text("Yearly").tag(PaymentIntervall.yearly) + } + .pickerStyle(SegmentedPickerStyle()) + } + + Section { + Button("Add Subscription") { + if let amount = Float(amount) { + let newSubscription = Subscription(name: name, payments: [Payment(amount: amount, intervall: intervall)]) + subs.append(newSubscription) + presentationMode.wrappedValue.dismiss() + } + } + } + } + .navigationTitle("Add Subscription") + .navigationBarItems(trailing: Button("Cancel") { + presentationMode.wrappedValue.dismiss() + }) + } } } diff --git a/AboTracker/Subscription.swift b/AboTracker/Subscription.swift index 2c1c60a..4e1785d 100644 --- a/AboTracker/Subscription.swift +++ b/AboTracker/Subscription.swift @@ -1,33 +1,55 @@ -// -// Subscription.swift -// AboTracker -// -// Created by Keyvan Atashfaraz on 27.06.24. -// - import Foundation import SwiftUI final class Subscription: Identifiable { public let id = UUID() var name: String - var amount: Float - var intervall: PaymentIntervall + var payments: [Payment] - init(name: String, amount: Float, intervall: PaymentIntervall) { + init(name: String, payments: [Payment]) { self.name = name - self.amount = amount - self.intervall = intervall + self.payments = payments } func getMonthlyAmount() -> Float { - switch intervall { - case .weekly: - return amount/7*30; - case .monthly: - return amount; - case .yearly: - return amount/12; + var sum: Float = 0.0 + for payment in payments { + switch payment.intervall { + case .weekly: + sum += payment.amount / 7 * 30 + case .monthly: + sum += payment.amount + case .quarter: + sum += payment.amount / 3 + case .yearly: + sum += payment.amount / 12 + } + } + return sum + } +} + +final class Payment: Identifiable { + public let id = UUID() + var amount: Float + var intervall: PaymentIntervall + + init(amount: Float, intervall: PaymentIntervall) { + self.amount = amount + self.intervall = intervall + } +} + +enum Currency: CustomStringConvertible { + case euro + case dollar + + var description: String { + switch self { + case .euro: + return "€" + case .dollar: + return "$" } } } @@ -35,6 +57,7 @@ final class Subscription: Identifiable { enum PaymentIntervall: CustomStringConvertible { case weekly case monthly + case quarter case yearly var description: String { @@ -43,6 +66,8 @@ enum PaymentIntervall: CustomStringConvertible { return "week" case .monthly: return "month" + case .quarter: + return "quarter" case .yearly: return "year" }