-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e1075bf
commit 4eb9946
Showing
22 changed files
with
644 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
20 changes: 20 additions & 0 deletions
20
Sources/Assets.xcassets/AccentColor.colorset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"colors" : [ | ||
{ | ||
"color" : { | ||
"color-space" : "display-p3", | ||
"components" : { | ||
"alpha" : "1.000", | ||
"blue" : "0.227", | ||
"green" : "0.160", | ||
"red" : "0.127" | ||
} | ||
}, | ||
"idiom" : "universal" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"filename" : "piggy_bank_icon_1024x1024.png", | ||
"idiom" : "universal", | ||
"platform" : "ios", | ||
"size" : "1024x1024" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
Binary file added
BIN
+313 KB
Sources/Assets.xcassets/AppIcon.appiconset/piggy_bank_icon_1024x1024.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,27 @@ | ||
import SwiftData | ||
import SwiftUI | ||
|
||
struct ContentView: View { | ||
init() { | ||
print("test") | ||
} | ||
@Environment(\.modelContext) var context: ModelContext | ||
|
||
var body: some View { | ||
return VStack { | ||
Text("Hello, World!") | ||
TabView { | ||
Reports() | ||
.tabItem { | ||
Label("Reports", systemImage: "chart.bar") | ||
} | ||
AccountList() | ||
.tabItem { | ||
Label("Accounts", systemImage: "building.columns") | ||
} | ||
SavingList() | ||
.tabItem { | ||
Label("Savings", systemImage: "dollarsign.circle") | ||
} | ||
GoalList() | ||
.tabItem { | ||
Label("Goals", systemImage: "target") | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import SwiftData | ||
|
||
@Model | ||
class Account { | ||
var name: String = "" | ||
var balance: Double = 0.0 | ||
var debt: Bool = false | ||
|
||
init(name: String, balance: Double, debt: Bool) { | ||
self.name = name | ||
self.balance = balance | ||
self.debt = debt | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import SwiftData | ||
import SwiftUI | ||
|
||
enum GoalRecurrence: Codable { | ||
case daily | ||
case weekly | ||
case monthly | ||
case yearly | ||
} | ||
|
||
@Model | ||
class Goal { | ||
var name: String = "" | ||
var amount: Double = 0.0 | ||
var recurrence: GoalRecurrence = GoalRecurrence.monthly | ||
var targetDate: Date = Date() | ||
|
||
init(name: String, amount: Double, recurrence: GoalRecurrence, targetDate: Date) { | ||
self.name = name | ||
self.amount = amount | ||
self.recurrence = recurrence | ||
self.targetDate = targetDate | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import SwiftData | ||
|
||
@Model | ||
class Saving { | ||
var name: String = "" | ||
var amount: Double = 0.0 | ||
|
||
init(name: String, amount: Double) { | ||
self.name = name | ||
self.amount = amount | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import SwiftUI | ||
|
||
struct DateService { | ||
enum DateServiceError: Error { | ||
case unexpectedDate | ||
} | ||
|
||
private let from: Date | ||
private let calendar: Calendar | ||
|
||
init() { | ||
self.from = Date() | ||
self.calendar = Calendar.current | ||
} | ||
|
||
init(_ from: Date) { | ||
self.from = from | ||
self.calendar = Calendar.current | ||
} | ||
|
||
func startOfMonth() throws -> Date { | ||
let components = self.calendar.dateComponents([.year, .month], from: self.from) | ||
guard let optDate = self.calendar.date(from: components) else { | ||
throw DateServiceError.unexpectedDate | ||
} | ||
return optDate | ||
} | ||
|
||
func endOfMonth() throws -> Date { | ||
let startOfMonth = try startOfMonth() | ||
let components = DateComponents(month: 1, second: -1) | ||
guard let endOfMonth = self.calendar.date(byAdding: components, to: startOfMonth) else { | ||
throw DateServiceError.unexpectedDate | ||
} | ||
return endOfMonth | ||
} | ||
|
||
func startOfNextMonth() throws -> Date { | ||
let addComponents = DateComponents(month: 1) | ||
|
||
guard let nextMonth = self.calendar.date(byAdding: addComponents, to: self.from) else { | ||
throw DateServiceError.unexpectedDate | ||
} | ||
|
||
let nextMonthComponents = self.calendar.dateComponents([.year, .month], from: nextMonth) | ||
|
||
guard let optDate = self.calendar.date(from: nextMonthComponents) else { | ||
throw DateServiceError.unexpectedDate | ||
} | ||
return optDate | ||
} | ||
|
||
func endOfNextMonth() throws -> Date { | ||
let startOfNextMonth = try startOfNextMonth() | ||
let components = DateComponents(month: 1, second: -1) | ||
guard let endOfNextMonth = self.calendar.date(byAdding: components, to: startOfNextMonth) else { | ||
throw DateServiceError.unexpectedDate | ||
} | ||
return endOfNextMonth | ||
} | ||
|
||
func isEndOfMonth() throws -> Bool { | ||
let dateComponents = self.calendar.dateComponents([.year, .month, .day], from: self.from) | ||
let endOfMonthComponents = try self.calendar.dateComponents( | ||
[.year, .month, .day], from: endOfMonth()) | ||
|
||
return dateComponents.year == endOfMonthComponents.year | ||
&& dateComponents.month == endOfMonthComponents.month | ||
&& dateComponents.day == endOfMonthComponents.day | ||
} | ||
|
||
func daysUntilEndOfMonth() throws -> Int { | ||
if try isEndOfMonth() { | ||
guard | ||
let days = try self.calendar.dateComponents( | ||
[.day], from: self.from, to: endOfNextMonth() | ||
).day | ||
else { | ||
throw DateServiceError.unexpectedDate | ||
} | ||
return days | ||
} | ||
|
||
guard | ||
let days = try self.calendar.dateComponents([.day], from: self.from, to: endOfMonth()) | ||
.day | ||
else { | ||
throw DateServiceError.unexpectedDate | ||
} | ||
return days | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import SwiftUI | ||
|
||
struct GoalService { | ||
private let goal: Goal | ||
private let day: Double = 60 * 60 * 24.0 | ||
|
||
init(goal: Goal) { | ||
self.goal = goal | ||
} | ||
|
||
func amortized() -> Decimal { | ||
if Date() >= self.goal.targetDate { | ||
return Decimal(self.goal.amount) | ||
} | ||
|
||
return dailyAmount() * Decimal(elapsedDays()) | ||
} | ||
|
||
func dailyAmount() -> Decimal { | ||
if Date() >= self.goal.targetDate { | ||
return Decimal(0) | ||
} | ||
|
||
if Date() < startDate() { | ||
return Decimal(0) | ||
} | ||
|
||
return Decimal(self.goal.amount) | ||
/ Decimal(DateInterval(start: startDate(), end: self.goal.targetDate).duration / day) | ||
} | ||
|
||
private func elapsedDays() -> Double { | ||
if Date() < startDate() { | ||
return 0 | ||
} | ||
|
||
return DateInterval(start: startDate(), end: Date()).duration / day | ||
} | ||
|
||
private func startDate() -> Date { | ||
switch self.goal.recurrence { | ||
case GoalRecurrence.daily: | ||
return Calendar.current.date(byAdding: .day, value: -1, to: self.goal.targetDate)! | ||
case GoalRecurrence.weekly: | ||
return Calendar.current.date(byAdding: .weekOfYear, value: -1, to: self.goal.targetDate)! | ||
case GoalRecurrence.monthly: | ||
return Calendar.current.date(byAdding: .month, value: -1, to: self.goal.targetDate)! | ||
case GoalRecurrence.yearly: | ||
return Calendar.current.date(byAdding: .year, value: -1, to: self.goal.targetDate)! | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,11 @@ | ||
import SwiftData | ||
import SwiftUI | ||
|
||
@main | ||
struct SimpleBudget: App { | ||
var body: some Scene { | ||
WindowGroup { | ||
ContentView() | ||
} | ||
var body: some Scene { | ||
WindowGroup { | ||
ContentView().modelContainer(for: [Account.self, Saving.self, Goal.self]) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import SwiftData | ||
import SwiftUI | ||
|
||
struct AccountForm: View { | ||
let account: Account? | ||
|
||
@State private var name: String = "" | ||
@State private var balance: Double = 0.0 | ||
@State private var debt: Bool = false | ||
|
||
@Environment(\.modelContext) var modelContext: ModelContext | ||
@Environment(\.dismiss) private var dismiss | ||
|
||
var body: some View { | ||
Form { | ||
TextField("Name", text: $name) | ||
TextField("Balance", value: $balance, format: .number) | ||
Picker("Debt", selection: $debt) { | ||
Text("No").tag(false) | ||
Text("Yes").tag(true) | ||
}.pickerStyle(.segmented) | ||
}.navigationBarTitle("New Account").toolbar { | ||
ToolbarItem(placement: .navigationBarTrailing) { | ||
Button("Save") { | ||
if let account { | ||
account.name = name | ||
account.balance = balance | ||
account.debt = debt | ||
} else { | ||
modelContext.insert(Account(name: name, balance: balance, debt: debt)) | ||
} | ||
dismiss() | ||
} | ||
} | ||
}.onAppear { | ||
if let account { | ||
name = account.name | ||
balance = account.balance | ||
debt = account.debt | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import SwiftData | ||
import SwiftUI | ||
|
||
struct AccountList: View { | ||
@Environment(\.modelContext) var modelContext: ModelContext | ||
@Query<Account> private var accounts: [Account] | ||
|
||
var body: some View { | ||
VStack { | ||
NavigationStack { | ||
List { | ||
ForEach(accounts, id: \.self) { account in | ||
NavigationLink(destination: AccountForm(account: account)) { | ||
Text(account.name) | ||
} | ||
}.onDelete(perform: deleteAccount) | ||
}.navigationBarTitle("Accounts").toolbar { | ||
ToolbarItem { | ||
NavigationLink(destination: AccountForm(account: nil)) { | ||
Image(systemName: "plus") | ||
} | ||
} | ||
} | ||
} | ||
Spacer() | ||
} | ||
} | ||
|
||
func deleteAccount(at offsets: IndexSet) { | ||
for offset in offsets { | ||
modelContext.delete(accounts[offset]) | ||
} | ||
} | ||
} |
Oops, something went wrong.