diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9f767ef2f715c553dccf9688aa34f8c8ac8c1c0b Binary files /dev/null and b/.DS_Store differ diff --git a/HailMoney.xcodeproj/project.pbxproj b/HailMoney.xcodeproj/project.pbxproj index c730d62c4e51a67392597fe3920e7f3358aec14b..2d3615403eb6cc009a63e58014721c4c72174ace 100644 --- a/HailMoney.xcodeproj/project.pbxproj +++ b/HailMoney.xcodeproj/project.pbxproj @@ -3,18 +3,41 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ + 143130AF266F1C1400BC449D /* Item+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 143130AB266F1C1400BC449D /* Item+CoreDataClass.swift */; }; + 143130B0266F1C1400BC449D /* Item+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 143130AC266F1C1400BC449D /* Item+CoreDataProperties.swift */; }; + 143130B1266F1C1400BC449D /* Simulation+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 143130AD266F1C1400BC449D /* Simulation+CoreDataClass.swift */; }; + 143130B2266F1C1400BC449D /* Simulation+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 143130AE266F1C1400BC449D /* Simulation+CoreDataProperties.swift */; }; + 143130B5266F5C6800BC449D /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 143130B4266F5C6800BC449D /* Constants.swift */; }; + 147E1AF2266DEA260097AA22 /* Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 147E1AF1266DEA260097AA22 /* Helper.swift */; }; 14AC89982664DE5A0013CF32 /* HailMoneyApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14AC89972664DE5A0013CF32 /* HailMoneyApp.swift */; }; 14AC899A2664DE5A0013CF32 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14AC89992664DE5A0013CF32 /* ContentView.swift */; }; 14AC899C2664DE5C0013CF32 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 14AC899B2664DE5C0013CF32 /* Assets.xcassets */; }; 14AC899F2664DE5C0013CF32 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 14AC899E2664DE5C0013CF32 /* Preview Assets.xcassets */; }; 14AC89A72664DF4E0013CF32 /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = 14AC89A62664DF4E0013CF32 /* .swiftlint.yml */; }; + 14FABE54266A190D00C0851A /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14FABE53266A190D00C0851A /* PersistenceController.swift */; }; + 14FABE58266A19A800C0851A /* HailMoney.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 14FABE56266A19A800C0851A /* HailMoney.xcdatamodeld */; }; + 14FABE5F266A1D0200C0851A /* NewSimulationModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14FABE5E266A1D0200C0851A /* NewSimulationModal.swift */; }; + 14FABE61266A1D3300C0851A /* FinanceGoal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14FABE60266A1D3300C0851A /* FinanceGoal.swift */; }; + 14FABE64266A1F5400C0851A /* SimulationCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14FABE63266A1F5400C0851A /* SimulationCardView.swift */; }; + 14FABE68266A209800C0851A /* MutualFund.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14FABE67266A209800C0851A /* MutualFund.swift */; }; + 5025E8E7266A090900DED6C3 /* OnboardingPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5025E8E6266A090900DED6C3 /* OnboardingPage.swift */; }; + 5025E8EB266A0A2200DED6C3 /* ConcentricOnboarding in Frameworks */ = {isa = PBXBuildFile; productRef = 5025E8EA266A0A2200DED6C3 /* ConcentricOnboarding */; }; + 5025E911266A330F00DED6C3 /* SimulationPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5025E910266A330F00DED6C3 /* SimulationPage.swift */; }; + 5025E915266A334900DED6C3 /* SwiftUICharts in Frameworks */ = {isa = PBXBuildFile; productRef = 5025E914266A334900DED6C3 /* SwiftUICharts */; }; + 50F846DF266BA2D000ECD771 /* TransactionPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50F846DE266BA2D000ECD771 /* TransactionPage.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 143130AB266F1C1400BC449D /* Item+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Item+CoreDataClass.swift"; sourceTree = ""; }; + 143130AC266F1C1400BC449D /* Item+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Item+CoreDataProperties.swift"; sourceTree = ""; }; + 143130AD266F1C1400BC449D /* Simulation+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Simulation+CoreDataClass.swift"; sourceTree = ""; }; + 143130AE266F1C1400BC449D /* Simulation+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Simulation+CoreDataProperties.swift"; sourceTree = ""; }; + 143130B4266F5C6800BC449D /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; + 147E1AF1266DEA260097AA22 /* Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helper.swift; sourceTree = ""; }; 14AC89942664DE5A0013CF32 /* HailMoney.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HailMoney.app; sourceTree = BUILT_PRODUCTS_DIR; }; 14AC89972664DE5A0013CF32 /* HailMoneyApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HailMoneyApp.swift; sourceTree = ""; }; 14AC89992664DE5A0013CF32 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -22,6 +45,15 @@ 14AC899E2664DE5C0013CF32 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 14AC89A02664DE5C0013CF32 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 14AC89A62664DF4E0013CF32 /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = ""; }; + 14FABE53266A190D00C0851A /* PersistenceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceController.swift; sourceTree = ""; }; + 14FABE57266A19A800C0851A /* HailMoney.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = HailMoney.xcdatamodel; sourceTree = ""; }; + 14FABE5E266A1D0200C0851A /* NewSimulationModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewSimulationModal.swift; sourceTree = ""; }; + 14FABE60266A1D3300C0851A /* FinanceGoal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FinanceGoal.swift; sourceTree = ""; }; + 14FABE63266A1F5400C0851A /* SimulationCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimulationCardView.swift; sourceTree = ""; }; + 14FABE67266A209800C0851A /* MutualFund.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MutualFund.swift; sourceTree = ""; }; + 5025E8E6266A090900DED6C3 /* OnboardingPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingPage.swift; sourceTree = ""; }; + 5025E910266A330F00DED6C3 /* SimulationPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimulationPage.swift; sourceTree = ""; }; + 50F846DE266BA2D000ECD771 /* TransactionPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionPage.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -29,12 +61,25 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 5025E8EB266A0A2200DED6C3 /* ConcentricOnboarding in Frameworks */, + 5025E915266A334900DED6C3 /* SwiftUICharts in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 143130B3266F1E4A00BC449D /* CoreData */ = { + isa = PBXGroup; + children = ( + 143130AB266F1C1400BC449D /* Item+CoreDataClass.swift */, + 143130AC266F1C1400BC449D /* Item+CoreDataProperties.swift */, + 143130AD266F1C1400BC449D /* Simulation+CoreDataClass.swift */, + 143130AE266F1C1400BC449D /* Simulation+CoreDataProperties.swift */, + ); + path = CoreData; + sourceTree = ""; + }; 14AC898B2664DE5A0013CF32 = { isa = PBXGroup; children = ( @@ -55,9 +100,13 @@ 14AC89962664DE5A0013CF32 /* HailMoney */ = { isa = PBXGroup; children = ( - 14AC89972664DE5A0013CF32 /* HailMoneyApp.swift */, - 14AC89992664DE5A0013CF32 /* ContentView.swift */, + 143130B3266F1E4A00BC449D /* CoreData */, + 14FABE59266A1C7D00C0851A /* Models */, + 14FABE55266A191100C0851A /* Utils */, + 14FABE5A266A1C8C00C0851A /* Views */, 14AC899B2664DE5C0013CF32 /* Assets.xcassets */, + 14FABE56266A19A800C0851A /* HailMoney.xcdatamodeld */, + 14AC89972664DE5A0013CF32 /* HailMoneyApp.swift */, 14AC89A02664DE5C0013CF32 /* Info.plist */, 14AC899D2664DE5C0013CF32 /* Preview Content */, ); @@ -72,6 +121,54 @@ path = "Preview Content"; sourceTree = ""; }; + 14FABE55266A191100C0851A /* Utils */ = { + isa = PBXGroup; + children = ( + 14FABE53266A190D00C0851A /* PersistenceController.swift */, + 147E1AF1266DEA260097AA22 /* Helper.swift */, + 143130B4266F5C6800BC449D /* Constants.swift */, + ); + path = Utils; + sourceTree = ""; + }; + 14FABE59266A1C7D00C0851A /* Models */ = { + isa = PBXGroup; + children = ( + 14FABE60266A1D3300C0851A /* FinanceGoal.swift */, + 14FABE67266A209800C0851A /* MutualFund.swift */, + ); + path = Models; + sourceTree = ""; + }; + 14FABE5A266A1C8C00C0851A /* Views */ = { + isa = PBXGroup; + children = ( + 5025E8E6266A090900DED6C3 /* OnboardingPage.swift */, + 50F846DE266BA2D000ECD771 /* TransactionPage.swift */, + 5025E910266A330F00DED6C3 /* SimulationPage.swift */, + 14FABE62266A1EFA00C0851A /* SimulationList */, + 14FABE5B266A1CBF00C0851A /* Modals */, + ); + path = Views; + sourceTree = ""; + }; + 14FABE5B266A1CBF00C0851A /* Modals */ = { + isa = PBXGroup; + children = ( + 14FABE5E266A1D0200C0851A /* NewSimulationModal.swift */, + ); + path = Modals; + sourceTree = ""; + }; + 14FABE62266A1EFA00C0851A /* SimulationList */ = { + isa = PBXGroup; + children = ( + 14AC89992664DE5A0013CF32 /* ContentView.swift */, + 14FABE63266A1F5400C0851A /* SimulationCardView.swift */, + ); + path = SimulationList; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -89,6 +186,10 @@ dependencies = ( ); name = HailMoney; + packageProductDependencies = ( + 5025E8EA266A0A2200DED6C3 /* ConcentricOnboarding */, + 5025E914266A334900DED6C3 /* SwiftUICharts */, + ); productName = HailMoney; productReference = 14AC89942664DE5A0013CF32 /* HailMoney.app */; productType = "com.apple.product-type.application"; @@ -116,6 +217,10 @@ Base, ); mainGroup = 14AC898B2664DE5A0013CF32; + packageReferences = ( + 5025E8E9266A0A2200DED6C3 /* XCRemoteSwiftPackageReference "ConcentricOnboarding" */, + 5025E913266A334900DED6C3 /* XCRemoteSwiftPackageReference "ChartView" */, + ); productRefGroup = 14AC89952664DE5A0013CF32 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -163,8 +268,23 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 143130B0266F1C1400BC449D /* Item+CoreDataProperties.swift in Sources */, + 147E1AF2266DEA260097AA22 /* Helper.swift in Sources */, + 14FABE58266A19A800C0851A /* HailMoney.xcdatamodeld in Sources */, + 143130B1266F1C1400BC449D /* Simulation+CoreDataClass.swift in Sources */, + 14FABE68266A209800C0851A /* MutualFund.swift in Sources */, + 14FABE64266A1F5400C0851A /* SimulationCardView.swift in Sources */, + 143130AF266F1C1400BC449D /* Item+CoreDataClass.swift in Sources */, + 14FABE61266A1D3300C0851A /* FinanceGoal.swift in Sources */, + 14FABE54266A190D00C0851A /* PersistenceController.swift in Sources */, 14AC899A2664DE5A0013CF32 /* ContentView.swift in Sources */, + 14FABE5F266A1D0200C0851A /* NewSimulationModal.swift in Sources */, + 50F846DF266BA2D000ECD771 /* TransactionPage.swift in Sources */, 14AC89982664DE5A0013CF32 /* HailMoneyApp.swift in Sources */, + 5025E911266A330F00DED6C3 /* SimulationPage.swift in Sources */, + 143130B2266F1C1400BC449D /* Simulation+CoreDataProperties.swift in Sources */, + 143130B5266F5C6800BC449D /* Constants.swift in Sources */, + 5025E8E7266A090900DED6C3 /* OnboardingPage.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -353,6 +473,51 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 5025E8E9266A0A2200DED6C3 /* XCRemoteSwiftPackageReference "ConcentricOnboarding" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/exyte/ConcentricOnboarding"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.0.6; + }; + }; + 5025E913266A334900DED6C3 /* XCRemoteSwiftPackageReference "ChartView" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/AppPear/ChartView"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.5.5; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 5025E8EA266A0A2200DED6C3 /* ConcentricOnboarding */ = { + isa = XCSwiftPackageProductDependency; + package = 5025E8E9266A0A2200DED6C3 /* XCRemoteSwiftPackageReference "ConcentricOnboarding" */; + productName = ConcentricOnboarding; + }; + 5025E914266A334900DED6C3 /* SwiftUICharts */ = { + isa = XCSwiftPackageProductDependency; + package = 5025E913266A334900DED6C3 /* XCRemoteSwiftPackageReference "ChartView" */; + productName = SwiftUICharts; + }; +/* End XCSwiftPackageProductDependency section */ + +/* Begin XCVersionGroup section */ + 14FABE56266A19A800C0851A /* HailMoney.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + 14FABE57266A19A800C0851A /* HailMoney.xcdatamodel */, + ); + currentVersion = 14FABE57266A19A800C0851A /* HailMoney.xcdatamodel */; + path = HailMoney.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ }; rootObject = 14AC898C2664DE5A0013CF32 /* Project object */; } diff --git a/HailMoney.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/HailMoney.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000000000000000000000000000000000000..adbcc3ca7e553f4e0f7aa26f5684e5b76c17178c --- /dev/null +++ b/HailMoney.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,25 @@ +{ + "object": { + "pins": [ + { + "package": "SwiftUICharts", + "repositoryURL": "https://github.com/AppPear/ChartView", + "state": { + "branch": null, + "revision": "9115a992c91fa19cbb4f2241084240d38654a1fc", + "version": "1.5.5" + } + }, + { + "package": "ConcentricOnboarding", + "repositoryURL": "https://github.com/exyte/ConcentricOnboarding", + "state": { + "branch": null, + "revision": "8ec6051f638f7de72c629368014777ad1346d653", + "version": "0.0.6" + } + } + ] + }, + "version": 1 +} diff --git a/HailMoney/.DS_Store b/HailMoney/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..dcbfa92eedac43f409f56bf4e14b5c15bf652264 Binary files /dev/null and b/HailMoney/.DS_Store differ diff --git a/HailMoney/Assets.xcassets/onboard1.imageset/Contents.json b/HailMoney/Assets.xcassets/onboard1.imageset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..0b4ac3007bc847510facef87d3181dc9fbf8fd88 --- /dev/null +++ b/HailMoney/Assets.xcassets/onboard1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "crossway_confused.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/HailMoney/Assets.xcassets/onboard1.imageset/crossway_confused.jpg b/HailMoney/Assets.xcassets/onboard1.imageset/crossway_confused.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5363f0d1978ef9e3520418ad9d830bd79ce0f2b1 Binary files /dev/null and b/HailMoney/Assets.xcassets/onboard1.imageset/crossway_confused.jpg differ diff --git a/HailMoney/Assets.xcassets/onboard2.imageset/Contents.json b/HailMoney/Assets.xcassets/onboard2.imageset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..df28ed2b787d90c5c05728de5ea836f21e1fbbd8 --- /dev/null +++ b/HailMoney/Assets.xcassets/onboard2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "—Pngtree—hand drawn online learning reading_5341172.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/HailMoney/Assets.xcassets/onboard2.imageset/\303\242\302\200\302\224Pngtree\303\242\302\200\302\224hand drawn online learning reading_5341172.png" "b/HailMoney/Assets.xcassets/onboard2.imageset/\303\242\302\200\302\224Pngtree\303\242\302\200\302\224hand drawn online learning reading_5341172.png" new file mode 100644 index 0000000000000000000000000000000000000000..3322db8517a667d524b8b7e72ca8de2fd4530b83 Binary files /dev/null and "b/HailMoney/Assets.xcassets/onboard2.imageset/\303\242\302\200\302\224Pngtree\303\242\302\200\302\224hand drawn online learning reading_5341172.png" differ diff --git a/HailMoney/Assets.xcassets/onboard3.imageset/2650149.jpg b/HailMoney/Assets.xcassets/onboard3.imageset/2650149.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cb623a4392bcc7d394c4c1a51801b089c21d6f70 Binary files /dev/null and b/HailMoney/Assets.xcassets/onboard3.imageset/2650149.jpg differ diff --git a/HailMoney/Assets.xcassets/onboard3.imageset/Contents.json b/HailMoney/Assets.xcassets/onboard3.imageset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..c9bced85e3787b99ae8b64a58bd15916c42f3c00 --- /dev/null +++ b/HailMoney/Assets.xcassets/onboard3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "2650149.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/HailMoney/ContentView.swift b/HailMoney/ContentView.swift deleted file mode 100644 index bf273e2ddbf5922a157ebdaee3e893a724755ca9..0000000000000000000000000000000000000000 --- a/HailMoney/ContentView.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// ContentView.swift -// HailMoney -// -// Created by Henry David Lie on 31/05/21. -// - -import SwiftUI - -struct ContentView: View { - var body: some View { - Text("Hello, world!") - .padding() - } -} - -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView() - } -} diff --git a/HailMoney/CoreData/Item+CoreDataClass.swift b/HailMoney/CoreData/Item+CoreDataClass.swift new file mode 100644 index 0000000000000000000000000000000000000000..bb400c2b0934132ec8884f9485598d8d7c6c3ec4 --- /dev/null +++ b/HailMoney/CoreData/Item+CoreDataClass.swift @@ -0,0 +1,15 @@ +// +// Item+CoreDataClass.swift +// HailMoney +// +// Created by Henry David Lie on 08/06/21. +// +// + +import Foundation +import CoreData + +@objc(Item) +public class Item: NSManagedObject { + +} diff --git a/HailMoney/CoreData/Item+CoreDataProperties.swift b/HailMoney/CoreData/Item+CoreDataProperties.swift new file mode 100644 index 0000000000000000000000000000000000000000..6f7f2fff6bcff36a9d5a43dcf3845bb3bddd46e6 --- /dev/null +++ b/HailMoney/CoreData/Item+CoreDataProperties.swift @@ -0,0 +1,31 @@ +// +// Item+CoreDataProperties.swift +// HailMoney +// +// Created by Henry David Lie on 08/06/21. +// +// + +import Foundation +import CoreData + +extension Item { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Item") + } + + @NSManaged public var timestamp: Date? + @NSManaged public var id: UUID? + @NSManaged public var name: String? + @NSManaged public var type: String? + @NSManaged public var origin: Simulation? + + public var wrappedName: String { + name ?? "No name" + } +} + +extension Item: Identifiable { + +} diff --git a/HailMoney/CoreData/Simulation+CoreDataClass.swift b/HailMoney/CoreData/Simulation+CoreDataClass.swift new file mode 100644 index 0000000000000000000000000000000000000000..5476091d2120e557212d0d17ed2c6d996a5dac2b --- /dev/null +++ b/HailMoney/CoreData/Simulation+CoreDataClass.swift @@ -0,0 +1,15 @@ +// +// Simulation+CoreDataClass.swift +// HailMoney +// +// Created by Henry David Lie on 08/06/21. +// +// + +import Foundation +import CoreData + +@objc(Simulation) +public class Simulation: NSManagedObject { + +} diff --git a/HailMoney/CoreData/Simulation+CoreDataProperties.swift b/HailMoney/CoreData/Simulation+CoreDataProperties.swift new file mode 100644 index 0000000000000000000000000000000000000000..c9398df85a4ff1f2422cdac3253eeef761bb58b7 --- /dev/null +++ b/HailMoney/CoreData/Simulation+CoreDataProperties.swift @@ -0,0 +1,59 @@ +// +// Simulation+CoreDataProperties.swift +// HailMoney +// +// Created by Henry David Lie on 08/06/21. +// +// + +import Foundation +import CoreData + +extension Simulation { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Simulation") + } + + @NSManaged public var id: UUID? + @NSManaged public var status: String? + @NSManaged public var title: String? + @NSManaged public var goalAmount: String? + @NSManaged public var monthlyAllocation: String? + @NSManaged public var achieveIn: String? + @NSManaged public var riskProfile: String? + @NSManaged public var item: NSSet? + + public var wrappedTitle: String { + title ?? "No title" + } + + public var itemArray: [Item] { + let set = item as? Set ?? [] + + return set.sorted { + $0.wrappedName < $1.wrappedName + } + } +} + +// MARK: Generated accessors for item +extension Simulation { + + @objc(addItemObject:) + @NSManaged public func addToItem(_ value: Item) + + @objc(removeItemObject:) + @NSManaged public func removeFromItem(_ value: Item) + + @objc(addItem:) + @NSManaged public func addToItem(_ values: NSSet) + + @objc(removeItem:) + @NSManaged public func removeFromItem(_ values: NSSet) + +} + +extension Simulation: Identifiable { + +} diff --git a/HailMoney/HailMoney.xcdatamodeld/HailMoney.xcdatamodel/contents b/HailMoney/HailMoney.xcdatamodeld/HailMoney.xcdatamodel/contents new file mode 100644 index 0000000000000000000000000000000000000000..a3089fdc323e2209b2a137c2ab28a00ae2edf1c6 --- /dev/null +++ b/HailMoney/HailMoney.xcdatamodeld/HailMoney.xcdatamodel/contents @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HailMoney/HailMoneyApp.swift b/HailMoney/HailMoneyApp.swift index dffc7328e6f7837e0f709f74dfb7b650077f239b..cd9a116ca3736c533a19d67765cade127304869c 100644 --- a/HailMoney/HailMoneyApp.swift +++ b/HailMoney/HailMoneyApp.swift @@ -9,9 +9,12 @@ import SwiftUI @main struct HailMoneyApp: App { + let persistenceController = PersistenceController.shared + var body: some Scene { WindowGroup { - ContentView() + OnboardingPage() + .environment(\.managedObjectContext, persistenceController.container.viewContext) } } } diff --git a/HailMoney/Models/FinanceGoal.swift b/HailMoney/Models/FinanceGoal.swift new file mode 100644 index 0000000000000000000000000000000000000000..c723a9dd97d9a2d3256f174369aff2809d5f14fa --- /dev/null +++ b/HailMoney/Models/FinanceGoal.swift @@ -0,0 +1,18 @@ +// +// FinanceGoal.swift +// HailMoney +// +// Created by Henry David Lie on 04/06/21. +// + +import Foundation + +struct FinanceGoal { + let ids: UUID + let title: String + let goalAmount: String + let monthlyAllocation: String + let achieveIn: String + let riskProfile: RiskProfile + var status: String = SimulationStatus.new.rawValue +} diff --git a/HailMoney/Models/MutualFund.swift b/HailMoney/Models/MutualFund.swift new file mode 100644 index 0000000000000000000000000000000000000000..580124c31595524d6270363f33891aa599f08077 --- /dev/null +++ b/HailMoney/Models/MutualFund.swift @@ -0,0 +1,20 @@ +// +// MutualFund.swift +// HailMoney +// +// Created by Henry David Lie on 04/06/21. +// + +import Foundation + +public class MutualFund: NSObject { + let type: String + let riskRate: RiskProfile + + init(type: String, riskRate: RiskProfile) { + self.type = type + self.riskRate = riskRate + } + + // id, nama, type, filter json based on data from coredata +} diff --git a/HailMoney/Utils/Constants.swift b/HailMoney/Utils/Constants.swift new file mode 100644 index 0000000000000000000000000000000000000000..9c105e6a00d5812a913a03fa41bd8204df36cbec --- /dev/null +++ b/HailMoney/Utils/Constants.swift @@ -0,0 +1,23 @@ +// +// Constants.swift +// HailMoney +// +// Created by Henry David Lie on 08/06/21. +// + +enum RiskProfile: String, CaseIterable { + case conservative = "Conservative" + case moderat = "Moderate" + case agresive = "Agresive" +} + +enum SimulationStatus: String, CaseIterable { + case new = "New" + case ongoing = "Ongoing" + case done = "Done" +} + +enum GetDateFormat: String, CaseIterable { + case short = "MMM dd, yyyy" + case long = "MMMM dd, yyyy" +} diff --git a/HailMoney/Utils/Helper.swift b/HailMoney/Utils/Helper.swift new file mode 100644 index 0000000000000000000000000000000000000000..b0e5f45b4cdeee60951937a3b10d448e81fc3aa4 --- /dev/null +++ b/HailMoney/Utils/Helper.swift @@ -0,0 +1,40 @@ +// +// Helper.swift +// HailMoney +// +// Created by Henry David Lie on 07/06/21. +// + +import UIKit + +extension Bundle { + func decode(_ type: T.Type, from file: String) -> T { + guard let url = self.url(forResource: file, withExtension: nil) else { + fatalError("Failed to locate \(file) in bundle.") + } + + guard let data = try? Data(contentsOf: url) else { + fatalError("Failed to load \(file) from bundle.") + } + + let decoder = JSONDecoder() + + guard let loaded = try? decoder.decode(T.self, from: data) else { + fatalError("Failed to decode \(file) from bundle.") + } + + return loaded + } +} + +func getDateString(format: GetDateFormat, target: Date) -> String { + let fromDate = DateFormatter() + + if format == GetDateFormat.short { + fromDate.dateFormat = GetDateFormat.short.rawValue + } else { + fromDate.dateFormat = GetDateFormat.long.rawValue + } + + return fromDate.string(from: target) +} diff --git a/HailMoney/Utils/PersistenceController.swift b/HailMoney/Utils/PersistenceController.swift new file mode 100644 index 0000000000000000000000000000000000000000..a1fdbde0c9992733f3a09b0b6ea171f5e21659db --- /dev/null +++ b/HailMoney/Utils/PersistenceController.swift @@ -0,0 +1,85 @@ +// +// PersistenceController.swift +// HailMoney +// +// Created by Henry David Lie on 04/06/21. +// + +import CoreData + +struct PersistenceController { + static let shared = PersistenceController() + + static var preview: PersistenceController = { + let result = PersistenceController(inMemory: true) + let viewContext = result.container.viewContext + for _ in 0..<10 { + let newItem = Item(context: viewContext) + newItem.timestamp = Date() + } + do { + try viewContext.save() + } catch { + let nsError = error as NSError + fatalError("Unresolved error \(nsError), \(nsError.userInfo)") + } + return result + }() + + let container: NSPersistentContainer + + init(inMemory: Bool = false) { + container = NSPersistentContainer(name: "HailMoney") + if inMemory { + container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") + } + container.loadPersistentStores(completionHandler: { (_, error) in + if let error = error as NSError? { + fatalError("Unresolved error \(error), \(error.userInfo)") + } + }) + } + + func getContext() -> NSManagedObjectContext? { + let result = PersistenceController(inMemory: true) + let viewContext = result.container.viewContext + return viewContext + } + + func retrieveSimulation(id: Int) -> NSManagedObject? { + guard let managedContext = getContext() else { return nil } + let fetchRequest = NSFetchRequest(entityName: "Simulations") + + do { + let result = try managedContext.fetch(fetchRequest) as? [NSManagedObject] + if result!.count > 0 { + // Assuming there will only ever be one User in the app. + return result![0] + } else { + return nil + } + } catch let error as NSError { + print("Retrieving user failed. \(error): \(error.userInfo)") + return nil + } + } + + func saveItems(_ mutualFund: MutualFund, simId: Int) { + guard let managedContext = getContext() else { return } + guard let simulation = retrieveSimulation(id: simId) else { return } + + var items: [MutualFund] = [] + if let pastItems = simulation.value(forKey: "items") as? [MutualFund] { + items += pastItems + } + items.append(mutualFund) + simulation.setValue(items, forKey: "items") + + do { + print("Saving session...") + try managedContext.save() + } catch let error as NSError { + print("Failed to save session data! \(error): \(error.userInfo)") + } + } +} diff --git a/HailMoney/Views/.DS_Store b/HailMoney/Views/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5cbcd4f30b420ce0c6b6b5cd260f3778a7fed950 Binary files /dev/null and b/HailMoney/Views/.DS_Store differ diff --git a/HailMoney/Views/Modals/NewSimulationModal.swift b/HailMoney/Views/Modals/NewSimulationModal.swift new file mode 100644 index 0000000000000000000000000000000000000000..56977dddeaec4b7c0d652aedba94017834f0e60c --- /dev/null +++ b/HailMoney/Views/Modals/NewSimulationModal.swift @@ -0,0 +1,90 @@ +// +// FinanceGoalModal.swift +// HailMoney +// +// Created by Henry David Lie on 04/06/21. +// + +import SwiftUI +import CoreData + +struct NewSimulationModal: View { + + @Environment(\.presentationMode) private var presentationMode + @Environment(\.managedObjectContext) private var viewContext + @State var goal: String = "" + @State var amount: String = "" + @State var allocation: String = "" + @State var target = Date() + @State private var selectedRisk: RiskProfile = .conservative + + var body: some View { + NavigationView { + Form { + Section(header: Text("")) { + TextField("What's your goal?", text: $goal) + TextField("Money needed", text: $amount) + TextField("Monthly allocation", text: $allocation) + DatePicker("Achieved in ", selection: $target, displayedComponents: .date) + Picker("Risk Profile", selection: $selectedRisk) { + ForEach(RiskProfile.allCases, id: \.self) { + Text($0.rawValue) + } + } + } + } + .navigationBarTitle("New Investment Plan") + .navigationBarItems( + leading: + Button("Cancel") { + presentationMode.wrappedValue.dismiss() + }, + trailing: + Button("Save") { + let newGoal = + FinanceGoal(ids: UUID(), + title: goal, + goalAmount: amount, + monthlyAllocation: allocation, + achieveIn: getDateString(format: GetDateFormat.short, target: target), + riskProfile: selectedRisk) + if newSimulation(financeGoal: newGoal) { + presentationMode.wrappedValue.dismiss() + } + } + ) + .navigationBarTitleDisplayMode(.inline) + } + } + + private func newSimulation(financeGoal: FinanceGoal) -> Bool { + withAnimation { + let newSim = Simulation(context: viewContext) + newSim.id = financeGoal.ids + newSim.title = financeGoal.title + newSim.goalAmount = financeGoal.goalAmount + newSim.monthlyAllocation = financeGoal.monthlyAllocation + newSim.achieveIn = financeGoal.achieveIn + newSim.riskProfile = financeGoal.riskProfile.rawValue + newSim.status = financeGoal.status + return saveContext() + } + } + + private func saveContext() -> Bool { + do { + try viewContext.save() + return true + } catch { + let error = error as NSError + print("Error when creating new simulation: \(error)") + return false + } + } + } + +struct NewSimulationModal_Previews: PreviewProvider { + static var previews: some View { + NewSimulationModal() + } +} diff --git a/HailMoney/Views/OnboardingPage.swift b/HailMoney/Views/OnboardingPage.swift new file mode 100644 index 0000000000000000000000000000000000000000..080fcf223a1a762d5421d634e945f69f34de07d1 --- /dev/null +++ b/HailMoney/Views/OnboardingPage.swift @@ -0,0 +1,67 @@ +// +// OnboardingPage.swift +// HailMoney +// +// Created by bevan christian on 04/06/21. +// + +import SwiftUI +import ConcentricOnboarding + +struct OnboardingPage: View { + @State private var selesai = UserDefaults.standard.bool(forKey: "onboard") + var body: some View { + if selesai { + ContentView() + } else { + onboardingView() + } + } + + func onboardingView() -> ConcentricOnboardingView { + var onboard = ConcentricOnboardingView(pages: + [AnyView(Page(title: "SIMPLE LEARN TO INVEST", + subtitle: "Mau belajar reksadana namun tidak paham harus mulai", + image: "onboard1")), + AnyView(Page(title: "FREE SIMULATION AND SUMMARY", + subtitle: "simulasi gratis dan saran dari pakar", image: "onboard2")), + AnyView(Page(title: "NO HIDDEN CHARGES OR FEES", + subtitle: "Tidak ada charge tersembunyi maupun pembayaran", + image: "onboard3"))], + bgColors: [.white, .blue, .white], + duration: 1.0) + onboard.insteadOfCyclingToFirstPage = { + selesai = true + UserDefaults.standard.set(true, forKey: "onboard") + } + return onboard + } + +} + +struct Page: View { + var title: String + var subtitle: String + var image: String + var body: some View { + VStack(alignment: .center) { + Image(image).resizable().frame(width: 200, height: 190, alignment: .center) + Text(title) + .font(.title) + .multilineTextAlignment(.center) + .padding(.bottom, 20) + Text(subtitle) + .font(.body) + .lineLimit(/*@START_MENU_TOKEN@*/2/*@END_MENU_TOKEN@*/) + .lineSpacing(5.0) + .multilineTextAlignment(.center) + } + + } +} + +struct OnboardingPage_Previews: PreviewProvider { + static var previews: some View { + OnboardingPage() + } +} diff --git a/HailMoney/Views/SimulationList/ContentView.swift b/HailMoney/Views/SimulationList/ContentView.swift new file mode 100644 index 0000000000000000000000000000000000000000..862f11178512379d89c40d398352f33539134a78 --- /dev/null +++ b/HailMoney/Views/SimulationList/ContentView.swift @@ -0,0 +1,63 @@ +// +// ContentView.swift +// HailMoney +// +// Created by Henry David Lie on 31/05/21. +// + +import SwiftUI +import CoreData + +struct ContentView: View { + + @Environment(\.managedObjectContext) private var viewContext + @State var showNewSimulationModal = false + + @FetchRequest(sortDescriptors: []) + var sims: FetchedResults + + var body: some View { + NavigationView { + List { + ForEach(sims, id: \.id) { sim in + SimulationCardView(simulation: sim) + }.onDelete(perform: deleteSim) + } + .listStyle(PlainListStyle()) + .navigationTitle("Simulator") + .navigationBarItems( + trailing: + Button(action: { + self.showNewSimulationModal.toggle() + }, label: { + Image(systemName: "plus") + }) + ) + .sheet(isPresented: $showNewSimulationModal, content: { + NewSimulationModal() + }) + } + } + + private func deleteSim(offsets: IndexSet) { + withAnimation { + offsets.map { sims[$0] }.forEach(viewContext.delete) + saveContext() + } + } + + private func saveContext() { + do { + try viewContext.save() + } catch { + let error = error as NSError + print("Error when creating new simulation: \(error)") + } + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} diff --git a/HailMoney/Views/SimulationList/SimulationCardView.swift b/HailMoney/Views/SimulationList/SimulationCardView.swift new file mode 100644 index 0000000000000000000000000000000000000000..7f0659cd174b16fa8af69fe79a316bd19c7774c1 --- /dev/null +++ b/HailMoney/Views/SimulationList/SimulationCardView.swift @@ -0,0 +1,37 @@ +// +// SimulationCardView.swift +// HailMoney +// +// Created by Henry David Lie on 04/06/21. +// + +import SwiftUI + +struct SimulationCardView: View { + + @State var simulation: Simulation + + var body: some View { + ZStack { + RoundedRectangle(cornerRadius: 5) + .fill(Color.gray) + .opacity(0.15) + + HStack { + VStack(alignment: .leading) { + Text(simulation.title ?? "") + .font(.headline) + + Text("Budget \(simulation.goalAmount ?? "0")") + .font(.subheadline) + } + Spacer() + Text(simulation.status ?? "") + .font(.subheadline) + .foregroundColor(Color.gray) + } + .padding(.horizontal) + } + .frame(width: 357, height: 78) + } +} diff --git a/HailMoney/Views/SimulationPage.swift b/HailMoney/Views/SimulationPage.swift new file mode 100644 index 0000000000000000000000000000000000000000..38e4aa475a0cd0717c6b89b5d68a20a93882f4ab --- /dev/null +++ b/HailMoney/Views/SimulationPage.swift @@ -0,0 +1,112 @@ +// +// SimulationPage.swift +// HailMoney +// +// Created by bevan christian on 04/06/21. +// + +import SwiftUI +import SwiftUICharts + +struct SimulationPage: View { + @State private var listData = [200.0, 400.0, 500.0, 300.0, 700.0, 900.0] + @State private var harga = 3000.0 + @State private var profit = 0.0 + @State private var nilaiAhkir = 900.0 + var body: some View { + VStack { + Grafik(listData: listData) + Harga(nilaiPorto: "\(harga)", profit: "900.000") + .frame(width: 220, height: 80, alignment: .center) + .background(Color.white) + .cornerRadius(10.0) + .shadow(radius: 5).padding() + HStack { + Text("Manajer Investasi").font(.title2) + Spacer() + } + ListMi() + .ignoresSafeArea(.container) + .frame(height: 220, alignment: .center).padding(5) + // untuk sementara untuk ujicoba simulasi + Button("Start Simulation") { + simulasi() + + }.frame(width: 330, height: 50) + .background(Color.blue) + .foregroundColor(.white) + .cornerRadius(10.0) + Spacer() + }.padding(10).animation(.easeIn) + } + + // untuk simulasi + func simulasi() { + Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {_ in + let dataRandom = Double.random(in: 100...1000) + if dataRandom < nilaiAhkir { + harga -= dataRandom + } else { + harga += dataRandom + } + nilaiAhkir = dataRandom + listData.append(dataRandom) + + } + + } +} + +struct Harga: View { + var nilaiPorto: String + var profit: String + var body: some View { + VStack { + Text("Rp \(nilaiPorto)").font(.title) + Text("+ \(profit) (12.25)%").font(.subheadline).foregroundColor(.green) + } + + } +} +struct Grafik: View { + var listData: [Double] + var body: some View { + LineView(data: listData, title: "Portofolio", + style: .init(backgroundColor: .white, + accentColor: .blue, + gradientColor: GradientColor(start: Color.red, end: Color.blue), + textColor: Color.black, + legendTextColor: Color.black, + dropShadowColor: Color.gray)).frame(height: 290, + alignment: .center) + + } + +} +struct ListMi: View { + var namaMi = ["Succorinvest", "Manulife", "bibit", "bareksa", "aa"] + var body: some View { + + List(namaMi, id: \.self) { data in + ScrollView { + VStack { + HStack { + Image("onboard1").resizable().frame(width: 60, height: 60) + Text(data) + Spacer() + VStack { + Text("+12%") + } + } + } + } + + }.ignoresSafeArea(.container) + + } +} +struct SimulationPage_Previews: PreviewProvider { + static var previews: some View { + SimulationPage() + } +} diff --git a/HailMoney/Views/TransactionPage.swift b/HailMoney/Views/TransactionPage.swift new file mode 100644 index 0000000000000000000000000000000000000000..27eca3fdb2d6cfd2acd4f1a1ea2d5fd5f43109a9 --- /dev/null +++ b/HailMoney/Views/TransactionPage.swift @@ -0,0 +1,84 @@ +// +// TransactionPage.swift +// HailMoney +// +// Created by bevan christian on 05/06/21. +// + +import SwiftUI + +struct TransactionPage: View { + @State private var topUp = "" + + var body: some View { + VStack { + Text("Jarvis Balanced Fund").font(.title2) + Text("Total AUM: 204.888B").font(.subheadline).foregroundColor(.gray) + KeteranganMI(nilaiTopUp: $topUp, expenseRatio2: "0.2", returnPerTahun2: "12", drawdown2: "40") + PenjelasanTransaksi(expenseRatio: "0.2", returnPerTahun: "12", drawdown: "42") + Button("Buy") { + print("dismis modal") + }.frame(width: 300, + height: 40).background(Color.blue) + .foregroundColor(.white) + .cornerRadius(10.0).padding() + } + } +} +struct KeteranganMI: View { + @Binding var nilaiTopUp: String + var expenseRatio2: String + var returnPerTahun2: String + var drawdown2: String + var body: some View { + VStack { + List { + Text("Keterangan MI").font(.headline) + HStack { + Text("Return Per Tahun") + Spacer() + Text("12%") + } + HStack { + Text("Expense Ratio") + Spacer() + Text("0.2%") + } + HStack { + Text("Drawdown Maksimum") + Spacer() + Text("42%") + } + HStack { + Text("TopUp/Bulan") + Spacer() + TextField("Rp.10000,0000", text: $nilaiTopUp).offset(x: 120.0).keyboardType(.numberPad) + } + + }.frame(height: 220, alignment: .center) + } + } +} +struct PenjelasanTransaksi: View { + var expenseRatio: String + var returnPerTahun: String + var drawdown: String + var body: some View { + VStack(alignment: .leading) { + Text("Penjelasan").font(.headline).padding(.bottom, 10) + Text(""" +Dengan membeli reksa dana ini maka anda harus siap untuk resiko terburuknya. +Dalam kasus ini Jarvis Balanced Fund memiliki +Resiko penurunan \(drawdown)% dalam setahun dan keuntungan \(returnPerTahun)% dalam setahun, selain itu ada +hal yang harus dipahami yaitu biaya untuk manajer investasi sebesar \(expenseRatio) persen +""").font(.callout) + Spacer() + }.padding() + } +} + +struct TransactionPage_Previews: PreviewProvider { + static var previews: some View { + TransactionPage() + } +}