163 lines
5.6 KiB
Swift
163 lines
5.6 KiB
Swift
//
|
|
// ContentView.swift
|
|
// Shared
|
|
//
|
|
// Created by Trey Tartt on 1/5/22.
|
|
//
|
|
|
|
import SwiftUI
|
|
import CoreData
|
|
import Charts
|
|
|
|
struct ContentView: View {
|
|
@Environment(\.managedObjectContext) private var viewContext
|
|
|
|
@State private var showingSheet = false
|
|
@State private var showTodayInput = true
|
|
|
|
@FetchRequest(
|
|
sortDescriptors: [NSSortDescriptor(keyPath: \MoodEntry.forDate, ascending: false)],
|
|
animation: .spring())
|
|
private var items: FetchedResults<MoodEntry>
|
|
|
|
init(){ }
|
|
|
|
var body: some View {
|
|
TabView {
|
|
mainView
|
|
.tabItem {
|
|
Label("Main", systemImage: "list.dash")
|
|
}
|
|
|
|
FilterView()
|
|
.tabItem {
|
|
Label("Filter", systemImage: "calendar.circle")
|
|
}
|
|
|
|
GraphView()
|
|
.tabItem {
|
|
Label("Stats", systemImage: "chart.line.uptrend.xyaxis")
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
private var settingsButtonView: some View {
|
|
HStack {
|
|
Spacer()
|
|
Button(action: {
|
|
showingSheet.toggle()
|
|
}, label: {
|
|
Image(systemName: "gear")
|
|
.foregroundColor(Color(UIColor.systemGray))
|
|
.font(.system(size: 20))
|
|
}).sheet(isPresented: $showingSheet) {
|
|
SettingsView()
|
|
}.padding(.trailing)
|
|
}
|
|
}
|
|
|
|
private var listView: some View {
|
|
List {
|
|
ForEach(items) { item in
|
|
HStack {
|
|
item.mood.icon
|
|
.resizable()
|
|
.frame(width: 50, height: 50, alignment: .center)
|
|
.foregroundColor(item.mood.color)
|
|
VStack {
|
|
Text("\(item.moodString)")
|
|
.font(.title)
|
|
.foregroundColor(Color(UIColor.systemGray))
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
Text(item.forDate ?? Date(), style: .date)
|
|
.font(.body)
|
|
.foregroundColor(Color(UIColor.label))
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
}
|
|
.padding(.leading)
|
|
}
|
|
}
|
|
.onDelete(perform: deleteItems)
|
|
}
|
|
}
|
|
|
|
private var mainView: some View {
|
|
VStack{
|
|
settingsButtonView
|
|
if shouldShowTodayInput() {
|
|
AddMoodHeaderView()
|
|
.frame(minHeight: 85, maxHeight: 180)
|
|
.frame(minWidth: 0, maxWidth: .infinity)
|
|
} else {
|
|
HeaderStatsView(entries: [
|
|
//x - position of a bar, y - height of a bar
|
|
BarChartDataEntry(x: 1, y: 1),
|
|
BarChartDataEntry(x: 2, y: 5),
|
|
BarChartDataEntry(x: 3, y: 2),
|
|
BarChartDataEntry(x: 4, y: 4),
|
|
BarChartDataEntry(x: 5, y: 1)
|
|
])
|
|
.frame(minHeight: 85, maxHeight: 180)
|
|
}
|
|
listView
|
|
}
|
|
}
|
|
|
|
private func deleteItems(offsets: IndexSet) {
|
|
withAnimation {
|
|
offsets.map { items[$0] }.forEach(viewContext.delete)
|
|
|
|
do {
|
|
try viewContext.save()
|
|
} catch {
|
|
// Replace this implementation with code to handle the error appropriately.
|
|
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
|
let nsError = error as NSError
|
|
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
|
|
}
|
|
}
|
|
}
|
|
|
|
private func shouldShowTodayInput() -> Bool {
|
|
let fetchRequest = NSFetchRequest<MoodEntry>(entityName: "MoodEntry")
|
|
|
|
var calendar = Calendar.current
|
|
calendar.timeZone = NSTimeZone.local
|
|
|
|
// Get today's beginning & end
|
|
let dateFrom = calendar.startOfDay(for: Date()) // eg. 2016-10-10 00:00:00
|
|
let dateTo = calendar.date(byAdding: .day, value: 1, to: dateFrom)!
|
|
// Note: Times are printed in UTC. Depending on where you live it won't print 00:00:00 but it will work with UTC times which can be converted to local time
|
|
|
|
// Set predicate as date being today's date
|
|
let fromPredicate = NSPredicate(format: "%@ <= %K", dateFrom as NSDate, #keyPath(MoodEntry.forDate))
|
|
let toPredicate = NSPredicate(format: "%K < %@", #keyPath(MoodEntry.forDate), dateTo as NSDate)
|
|
let datePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [fromPredicate, toPredicate])
|
|
fetchRequest.predicate = datePredicate
|
|
let entries = try! self.viewContext.count(for: fetchRequest)
|
|
|
|
return entries == 0
|
|
}
|
|
}
|
|
|
|
private let itemFormatter: DateFormatter = {
|
|
let formatter = DateFormatter()
|
|
formatter.dateStyle = .short
|
|
formatter.timeStyle = .medium
|
|
return formatter
|
|
}()
|
|
|
|
struct ContentView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
ContentView().environment(\.managedObjectContext, PersistenceController.shared.container.viewContext)
|
|
.onAppear(perform: {
|
|
PersistenceController.shared.populateMemory()
|
|
})
|
|
|
|
ContentView()
|
|
.preferredColorScheme(.dark)
|
|
.environment(\.managedObjectContext, PersistenceController.shared.container.viewContext)
|
|
}
|
|
}
|