chore: wire in initial viewmodel and view
Signed-off-by: Alan Brault <alan.brault@visus.io>
This commit is contained in:
-2
@@ -1,2 +0,0 @@
|
|||||||
// The Swift Programming Language
|
|
||||||
// https://docs.swift.org/swift-book
|
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
import Foundation
|
||||||
|
import Observation
|
||||||
|
import TempestasDomain
|
||||||
|
|
||||||
|
@Observable
|
||||||
|
@MainActor
|
||||||
|
public final class MainViewModel {
|
||||||
|
public private(set) var isLoading: Bool = false
|
||||||
|
|
||||||
|
private let forecastRepository: ForecastRepository
|
||||||
|
|
||||||
|
public init(
|
||||||
|
forecastRepository: ForecastRepository
|
||||||
|
) {
|
||||||
|
self.forecastRepository = forecastRepository
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
public struct MainView: View {
|
||||||
|
let viewModel: MainViewModel
|
||||||
|
|
||||||
|
public init (
|
||||||
|
viewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
self.viewModel = viewModel
|
||||||
|
}
|
||||||
|
|
||||||
|
public var body: some View {
|
||||||
|
NavigationStack {
|
||||||
|
|
||||||
|
}.frame(width: 320, height: 400)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,4 +13,10 @@ final class AppComposition {
|
|||||||
|
|
||||||
self.forecastRepository = forecastRepository
|
self.forecastRepository = forecastRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeMainViewModel() -> MainViewModel {
|
||||||
|
MainViewModel(
|
||||||
|
forecastRepository: forecastRepository
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
//
|
|
||||||
// ContentView.swift
|
|
||||||
// Tempestas
|
|
||||||
//
|
|
||||||
// Created by Alan Brault on 8/4/26.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
import SwiftData
|
|
||||||
|
|
||||||
struct ContentView: View {
|
|
||||||
@Environment(\.modelContext) private var modelContext
|
|
||||||
@Query private var items: [Item]
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
NavigationSplitView {
|
|
||||||
List {
|
|
||||||
ForEach(items) { item in
|
|
||||||
NavigationLink {
|
|
||||||
Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))")
|
|
||||||
} label: {
|
|
||||||
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onDelete(perform: deleteItems)
|
|
||||||
}
|
|
||||||
.navigationSplitViewColumnWidth(min: 180, ideal: 200)
|
|
||||||
.toolbar {
|
|
||||||
ToolbarItem {
|
|
||||||
Button(action: addItem) {
|
|
||||||
Label("Add Item", systemImage: "plus")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} detail: {
|
|
||||||
Text("Select an item")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func addItem() {
|
|
||||||
withAnimation {
|
|
||||||
let newItem = Item(timestamp: Date())
|
|
||||||
modelContext.insert(newItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func deleteItems(offsets: IndexSet) {
|
|
||||||
withAnimation {
|
|
||||||
for index in offsets {
|
|
||||||
modelContext.delete(items[index])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#Preview {
|
|
||||||
ContentView()
|
|
||||||
.modelContainer(for: Item.self, inMemory: true)
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
//
|
|
||||||
// Item.swift
|
|
||||||
// Tempestas
|
|
||||||
//
|
|
||||||
// Created by Alan Brault on 8/4/26.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import SwiftData
|
|
||||||
|
|
||||||
@Model
|
|
||||||
final class Item {
|
|
||||||
var timestamp: Date
|
|
||||||
|
|
||||||
init(timestamp: Date) {
|
|
||||||
self.timestamp = timestamp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +1,24 @@
|
|||||||
//
|
|
||||||
// TempestasApp.swift
|
|
||||||
// Tempestas
|
|
||||||
//
|
|
||||||
// Created by Alan Brault on 8/4/26.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import SwiftData
|
import SwiftData
|
||||||
|
import TempestasPresentation
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct TempestasApp: App {
|
struct TempestasApp: App {
|
||||||
private let composition: AppComposition
|
private let composition: AppComposition
|
||||||
|
@State private var mainViewModel: MainViewModel
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
self.composition = AppComposition()
|
self.composition = AppComposition()
|
||||||
|
|
||||||
|
_mainViewModel = State(initialValue: composition.makeMainViewModel())
|
||||||
}
|
}
|
||||||
|
|
||||||
var sharedModelContainer: ModelContainer = {
|
|
||||||
let schema = Schema([
|
|
||||||
Item.self,
|
|
||||||
])
|
|
||||||
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
|
|
||||||
|
|
||||||
do {
|
|
||||||
return try ModelContainer(for: schema, configurations: [modelConfiguration])
|
|
||||||
} catch {
|
|
||||||
fatalError("Could not create ModelContainer: \(error)")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
MenuBarExtra("Tempestas", systemImage: "cloud.sun") {
|
||||||
ContentView()
|
MainView(
|
||||||
|
viewModel: mainViewModel
|
||||||
|
)
|
||||||
}
|
}
|
||||||
.modelContainer(sharedModelContainer)
|
.menuBarExtraStyle(.window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user