aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Cleberg <hello@cleberg.net>2024-01-04 14:26:57 -0600
committerChristian Cleberg <hello@cleberg.net>2024-01-04 14:26:57 -0600
commitcf13000e6fb6af629d7659dd3e99ccb9496e6462 (patch)
treeb7333053afe1878d223d35d9d1fff2cd37d8cf77
parent72028eb2a2f3c55fbf4f7f8f421f5414f8745ea8 (diff)
downloadlibre-tasks-cf13000e6fb6af629d7659dd3e99ccb9496e6462.tar.gz
libre-tasks-cf13000e6fb6af629d7659dd3e99ccb9496e6462.tar.bz2
libre-tasks-cf13000e6fb6af629d7659dd3e99ccb9496e6462.zip
feat: improve new task form and swipe actions
-rw-r--r--LibreTasks/ContentView.swift142
-rw-r--r--LibreTasks/DataModel.xcdatamodeld/DataModel.xcdatamodel/contents12
-rw-r--r--LibreTasks/DataStore.swift8
3 files changed, 131 insertions, 31 deletions
diff --git a/LibreTasks/ContentView.swift b/LibreTasks/ContentView.swift
index 226db4d..2ea9013 100644
--- a/LibreTasks/ContentView.swift
+++ b/LibreTasks/ContentView.swift
@@ -9,10 +9,26 @@ import Combine
struct ContentView: View {
@ObservedObject var taskStore = TaskDataStore()
- @State var newTask : String = ""
+ @State private var newTask : String = ""
+ @State private var taskPriority : String = ""
@State private var query = ""
- @State var newTaskDate: Date = Date()
+ @State private var newTaskDate: Date = Date()
@State private var showingPopover = false
+ @State private var recurringReminder = false
+ @State private var recurrenceInteger : Int = 1
+ @State private var showAlert: Bool = false
+
+ enum Priority: String, CaseIterable, Identifiable {
+ case A, B, C
+ var id: Self { self }
+ }
+ @State private var selectedPriority: Priority = .A
+
+ enum Recurrence: String, CaseIterable, Identifiable {
+ case hours, days, weeks, months
+ var id: Self { self }
+ }
+ @State private var selectedRecurrence: Recurrence = .hours
var filteredTasks: [Task] {
if query.isEmpty {
@@ -25,13 +41,21 @@ struct ContentView: View {
}
func addNewTask() {
- taskStore.tasks.append(Task(
- id: String(taskStore.tasks.count + 1),
- taskItem: newTask,
- taskDate: newTaskDate
- ))
- self.newTask = ""
- self.showingPopover = false
+ if newTask.isEmpty {
+ showAlert = true
+ } else {
+ taskStore.tasks.append(Task(
+ id: (taskStore.tasks.count + 1),
+ taskItem: newTask,
+ taskDate: newTaskDate,
+ taskPriority: selectedPriority.rawValue,
+ taskRecurrence: recurringReminder,
+ taskRecurrenceInt: recurrenceInteger,
+ taskRecurrencePeriod: selectedRecurrence.rawValue
+ ))
+ self.newTask = ""
+ self.showingPopover = false
+ }
}
var body: some View {
@@ -39,25 +63,51 @@ struct ContentView: View {
VStack {
List {
ForEach(filteredTasks) { task in
- VStack(alignment: .leading) {
- Text(task.taskItem)
- if (Date() > task.taskDate) {
- HStack {
- Text(task.taskDate, style: .date)
- .foregroundColor(.red)
- .font(.caption)
- Text(task.taskDate, style: .time)
- .foregroundColor(.red)
- .font(.caption)
- }
- } else {
- HStack {
- Text(task.taskDate, style: .date)
- .font(.caption)
- Text(task.taskDate, style: .time)
- .font(.caption)
+ HStack {
+ VStack(alignment: .leading) {
+ Text(task.taskItem)
+ if (Date() > task.taskDate) {
+ HStack {
+ Text(task.taskDate, style: .date)
+ .foregroundColor(.red)
+ .font(.caption)
+ Text(task.taskDate, style: .time)
+ .foregroundColor(.red)
+ .font(.caption)
+ if (task.taskRecurrence == true) {
+ (Text("[+") + Text(String(task.taskRecurrenceInt)) + Text(" ") + Text(task.taskRecurrencePeriod) + Text("]"))
+ .foregroundColor(.red)
+ .font(.caption)
+ }
+ }
+ } else {
+ HStack {
+ Text(task.taskDate, style: .date)
+ .font(.caption)
+ Text(task.taskDate, style: .time)
+ .font(.caption)
+ if (task.taskRecurrence == true) {
+ (Text("[+") + Text(String(task.taskRecurrenceInt)) + Text(" ") + Text(task.taskRecurrencePeriod) + Text("]"))
+ .font(.caption)
+ }
+ }
}
}
+ Spacer()
+ (Text("[#") + Text(task.taskPriority) + Text("]"))
+ }
+ .swipeActions(edge: .trailing) {
+ Button(role: .destructive) {
+ print("\(task.taskItem) is being deleted.")
+ } label: {
+ Label("Delete", systemImage: "trash")
+ }
+ Button() {
+ print("\(task.taskItem) is being edited.")
+ // TODO: Add method to edit message in the DataStore
+ } label: {
+ Label("Edit", systemImage: "pencil")
+ }
}
}
.onDelete(perform: self.deleteTask)
@@ -85,12 +135,44 @@ struct ContentView: View {
})
}
.padding()
- HStack {
- VStack {
- TextField("Add Task: ", text: self.$newTask)
- DatePicker("Scheduled: ", selection: $newTaskDate)
+ Form {
+ Section(header: Text("Task Details")) {
+ TextField("Task Title", text: self.$newTask)
+ .onSubmit {
+ if newTask.isEmpty {
+ showAlert = true
+ }
+ }
+ .alert(isPresented: $showAlert) {
+ Alert(title: Text("Required Field"),
+ message: Text("You must enter a task title"),
+ dismissButton: .default(Text("OK")))
+ }
+ Picker("Priority:", selection: $selectedPriority) {
+ Text("A").tag(Priority.A)
+ Text("B").tag(Priority.B)
+ Text("C").tag(Priority.C)
+ }
+ DatePicker("Scheduled:", selection: $newTaskDate)
.datePickerStyle(CompactDatePickerStyle())
}
+ Section(header: Text("Repeating")) {
+ Toggle("Repeating", isOn: $recurringReminder)
+ if (recurringReminder == true) {
+ HStack {
+ TextField("", value: $recurrenceInteger, formatter: NumberFormatter())
+ Stepper(value: $recurrenceInteger, in: 1...100) {
+ EmptyView()
+ }
+ Picker("", selection: $selectedRecurrence) {
+ Text("Hours").tag(Recurrence.hours)
+ Text("Days").tag(Recurrence.days)
+ Text("Weeks").tag(Recurrence.weeks)
+ Text("Months").tag(Recurrence.months)
+ }
+ }
+ }
+ }
}
.padding()
Spacer()
diff --git a/LibreTasks/DataModel.xcdatamodeld/DataModel.xcdatamodel/contents b/LibreTasks/DataModel.xcdatamodeld/DataModel.xcdatamodel/contents
new file mode 100644
index 0000000..5287d8e
--- /dev/null
+++ b/LibreTasks/DataModel.xcdatamodeld/DataModel.xcdatamodel/contents
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22522" systemVersion="23C71" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithSwiftData="YES" userDefinedModelVersionIdentifier="">
+ <entity name="Tasks" representedClassName="Tasks" syncable="YES" codeGenerationType="class">
+ <attribute name="id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
+ <attribute name="taskDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
+ <attribute name="taskItem" optional="YES" attributeType="String"/>
+ <attribute name="taskPriority" optional="YES" attributeType="String"/>
+ <attribute name="taskRecurrence" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
+ <attribute name="taskRecurrenceInt" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
+ <attribute name="taskRecurrencePeriod" optional="YES" attributeType="String"/>
+ </entity>
+</model> \ No newline at end of file
diff --git a/LibreTasks/DataStore.swift b/LibreTasks/DataStore.swift
index 1628979..76733de 100644
--- a/LibreTasks/DataStore.swift
+++ b/LibreTasks/DataStore.swift
@@ -8,10 +8,16 @@ import Foundation
import SwiftUI
import Combine
+// TODO: Persist data storage across sessions
+
struct Task: Identifiable {
- var id = String()
+ var id = Int()
var taskItem = String()
var taskDate = Date()
+ var taskPriority = String()
+ var taskRecurrence = Bool()
+ var taskRecurrenceInt = Int()
+ var taskRecurrencePeriod = String()
}
class TaskDataStore: ObservableObject {