diff options
author | Christian Cleberg <hello@cleberg.net> | 2024-01-04 14:26:57 -0600 |
---|---|---|
committer | Christian Cleberg <hello@cleberg.net> | 2024-01-04 14:26:57 -0600 |
commit | cf13000e6fb6af629d7659dd3e99ccb9496e6462 (patch) | |
tree | b7333053afe1878d223d35d9d1fff2cd37d8cf77 | |
parent | 72028eb2a2f3c55fbf4f7f8f421f5414f8745ea8 (diff) | |
download | libre-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.swift | 142 | ||||
-rw-r--r-- | LibreTasks/DataModel.xcdatamodeld/DataModel.xcdatamodel/contents | 12 | ||||
-rw-r--r-- | LibreTasks/DataStore.swift | 8 |
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 { |