Add basic app structure with Dashboard, Transactions and Profile views. Create TransactionModel and TransactionRowView
This commit is contained in:
parent
800494f34e
commit
2ec0711bde
10 changed files with 270 additions and 24 deletions
|
|
@ -9,9 +9,12 @@ import SwiftUI
|
|||
|
||||
@main
|
||||
struct CoinlyApp: App {
|
||||
let persistenceController = PersistenceController.shared
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Coinly/App/ContentView.swift
Normal file
35
Coinly/App/ContentView.swift
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ContentView.swift
|
||||
// Coinly
|
||||
//
|
||||
// Created by Vadym Samoilenko on 02/03/2025.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
var body: some View {
|
||||
TabView {
|
||||
DashboardView()
|
||||
.tabItem {
|
||||
Label("Dashboard", systemImage: "chart.pie.fill")
|
||||
}
|
||||
|
||||
TransactionsView()
|
||||
.tabItem {
|
||||
Label("Transactions", systemImage: "list.bullet")
|
||||
}
|
||||
|
||||
ProfileView()
|
||||
.tabItem {
|
||||
Label("Profile", systemImage: "person.fill")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView()
|
||||
}
|
||||
}
|
||||
29
Coinly/App/Persistence.swift
Normal file
29
Coinly/App/Persistence.swift
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// Persistence.swift
|
||||
// Coinly
|
||||
//
|
||||
// Created by Vadym Samoilenko on 02/03/2025.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
|
||||
struct PersistenceController {
|
||||
static let shared = PersistenceController()
|
||||
|
||||
let container: NSPersistentContainer
|
||||
|
||||
init(inMemory: Bool = false) {
|
||||
container = NSPersistentContainer(name: "Coinly")
|
||||
|
||||
if inMemory {
|
||||
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
|
||||
}
|
||||
|
||||
container.loadPersistentStores { (storeDescription, error) in
|
||||
if let error = error as NSError? {
|
||||
fatalError("Unresolved error \(error), \(error.userInfo)")
|
||||
}
|
||||
}
|
||||
container.viewContext.automaticallyMergesChangesFromParent = true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
//
|
||||
// ContentView.swift
|
||||
// Coinly
|
||||
//
|
||||
// Created by Vadym Samoilenko on 02/03/2025.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
var body: some View {
|
||||
VStack {
|
||||
Image(systemName: "globe")
|
||||
.imageScale(.large)
|
||||
.foregroundStyle(.tint)
|
||||
Text("Hello, world!")
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ContentView()
|
||||
}
|
||||
35
Coinly/Features/Dashboard/DashboardView.swift
Normal file
35
Coinly/Features/Dashboard/DashboardView.swift
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// DashboardView.swift
|
||||
// Coinly
|
||||
//
|
||||
// Created by Vadym Samoilenko on 02/03/2025.
|
||||
//
|
||||
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct DashboardView: View {
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
VStack {
|
||||
Text("Total Balance")
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.gray)
|
||||
|
||||
Text("$1,234.56")
|
||||
.font(.title)
|
||||
.fontWeight(.bold)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding()
|
||||
.navigationTitle("Dashboard")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DashboardView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
DashboardView()
|
||||
}
|
||||
}
|
||||
40
Coinly/Features/Models/TransactionModel.swift
Normal file
40
Coinly/Features/Models/TransactionModel.swift
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// TransactionType.swift
|
||||
// Coinly
|
||||
//
|
||||
// Created by Vadym Samoilenko on 02/03/2025.
|
||||
//
|
||||
|
||||
|
||||
import Foundation
|
||||
|
||||
enum TransactionType: String {
|
||||
case income = "Income"
|
||||
case expense = "Expense"
|
||||
}
|
||||
|
||||
struct TransactionModel: Identifiable {
|
||||
let id = UUID()
|
||||
var amount: Double
|
||||
var date: Date
|
||||
var type: TransactionType
|
||||
var category: String
|
||||
var note: String?
|
||||
|
||||
var isExpense: Bool {
|
||||
type == .expense
|
||||
}
|
||||
|
||||
var signedAmount: Double {
|
||||
isExpense ? -amount : amount
|
||||
}
|
||||
}
|
||||
|
||||
// Sample Data
|
||||
extension TransactionModel {
|
||||
static let sampleData = [
|
||||
TransactionModel(amount: 100, date: Date(), type: .income, category: "Salary", note: "Monthly salary"),
|
||||
TransactionModel(amount: 25.99, date: Date(), type: .expense, category: "Food", note: "Lunch"),
|
||||
TransactionModel(amount: 50, date: Date(), type: .expense, category: "Transport", note: "Fuel")
|
||||
]
|
||||
}
|
||||
36
Coinly/Features/Profile/ProfileView.swift
Normal file
36
Coinly/Features/Profile/ProfileView.swift
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// ProfileView.swift
|
||||
// Coinly
|
||||
//
|
||||
// Created by Vadym Samoilenko on 02/03/2025.
|
||||
//
|
||||
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ProfileView: View {
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
List {
|
||||
Section("Settings") {
|
||||
Text("Categories")
|
||||
Text("Currency")
|
||||
Text("Notifications")
|
||||
}
|
||||
|
||||
Section("About") {
|
||||
Text("Help")
|
||||
Text("Privacy Policy")
|
||||
Text("Version 1.0")
|
||||
}
|
||||
}
|
||||
.navigationTitle("Profile")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ProfileView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ProfileView()
|
||||
}
|
||||
}
|
||||
35
Coinly/Features/Transactions/TransactionsView.swift
Normal file
35
Coinly/Features/Transactions/TransactionsView.swift
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// TransactionsView.swift
|
||||
// Coinly
|
||||
//
|
||||
// Created by Vadym Samoilenko on 02/03/2025.
|
||||
//
|
||||
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct TransactionsView: View {
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
List {
|
||||
Text("Transaction 1")
|
||||
Text("Transaction 2")
|
||||
Text("Transaction 3")
|
||||
}
|
||||
.navigationTitle("Transactions")
|
||||
.toolbar {
|
||||
Button(action: {
|
||||
// Add transaction action
|
||||
}) {
|
||||
Image(systemName: "plus")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TransactionsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
TransactionsView()
|
||||
}
|
||||
}
|
||||
47
Coinly/UI/Components/TransactionRowView.swift
Normal file
47
Coinly/UI/Components/TransactionRowView.swift
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// TransactionRowView.swift
|
||||
// Coinly
|
||||
//
|
||||
// Created by Vadym Samoilenko on 02/03/2025.
|
||||
//
|
||||
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct TransactionRowView: View {
|
||||
let transaction: TransactionModel
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
VStack(alignment: .leading) {
|
||||
Text(transaction.category)
|
||||
.font(.headline)
|
||||
if let note = transaction.note {
|
||||
Text(note)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
VStack(alignment: .trailing) {
|
||||
Text(String(format: "%.2f", transaction.amount))
|
||||
.font(.headline)
|
||||
.foregroundColor(transaction.isExpense ? .red : .green)
|
||||
Text(transaction.date, style: .date)
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
}
|
||||
|
||||
struct TransactionRowView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
TransactionRowView(transaction: TransactionModel.sampleData[0])
|
||||
.previewLayout(.sizeThatFits)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="23605" systemVersion="24D70" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithSwiftData="YES" userDefinedModelVersionIdentifier="">
|
||||
<entity name="Transaction" representedClassName="Transaction" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="amount" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="category" optional="YES" attributeType="String"/>
|
||||
<attribute name="date" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="note" optional="YES" attributeType="String"/>
|
||||
<attribute name="type" optional="YES" attributeType="String"/>
|
||||
</entity>
|
||||
</model>
|
||||
Loading…
Add table
Reference in a new issue