krz/libre-tasks
A free and private task manager for iOS.
clone: git clone https://gitbay.org/krz/libre-tasks.git
main: LibreTasks/ContentView.swift · raw
1//
2// ContentView.swift
3// LibreTasks
4//
5//
6
7import SwiftUI
8import Combine
9
10struct ContentView: View {
11 @ObservedObject var taskStore = TaskDataStore()
12 @State private var newTask : String = ""
13 @State private var taskPriority : String = ""
14 @State private var query = ""
15 @State private var newTaskDate: Date = Date()
16 @State private var showingPopover = false
17 @State private var recurringReminder = false
18 @State private var recurrenceInteger : Int = 1
19 @State private var showAlert: Bool = false
20
21 enum Priority: String, CaseIterable, Identifiable {
22 case A, B, C
23 var id: Self { self }
24 }
25 @State private var selectedPriority: Priority = .A
26
27 enum Recurrence: String, CaseIterable, Identifiable {
28 case hours, days, weeks, months
29 var id: Self { self }
30 }
31 @State private var selectedRecurrence: Recurrence = .hours
32
33 var filteredTasks: [Task] {
34 if query.isEmpty {
35 return self.taskStore.tasks
36 } else {
37 return taskStore.tasks.filter {
38 $0.taskItem.localizedCaseInsensitiveContains(query)
39 }
40 }
41 }
42
43 func addNewTask() {
44 if newTask.isEmpty {
45 showAlert = true
46 } else {
47 taskStore.tasks.append(Task(
48 id: (taskStore.tasks.count + 1),
49 taskItem: newTask,
50 taskDate: newTaskDate,
51 taskPriority: selectedPriority.rawValue,
52 taskRecurrence: recurringReminder,
53 taskRecurrenceInt: recurrenceInteger,
54 taskRecurrencePeriod: selectedRecurrence.rawValue
55 ))
56 self.newTask = ""
57 self.showingPopover = false
58 }
59 }
60
61 var body: some View {
62 NavigationView {
63 VStack {
64 List {
65 ForEach(filteredTasks) { task in
66 HStack {
67 VStack(alignment: .leading) {
68 Text(task.taskItem)
69 if (Date() > task.taskDate) {
70 HStack {
71 Text(task.taskDate, style: .date)
72 .foregroundColor(.red)
73 .font(.caption)
74 Text(task.taskDate, style: .time)
75 .foregroundColor(.red)
76 .font(.caption)
77 if (task.taskRecurrence == true) {
78 (Text("[+") + Text(String(task.taskRecurrenceInt)) + Text(" ") + Text(task.taskRecurrencePeriod) + Text("]"))
79 .foregroundColor(.red)
80 .font(.caption)
81 }
82 }
83 } else {
84 HStack {
85 Text(task.taskDate, style: .date)
86 .font(.caption)
87 Text(task.taskDate, style: .time)
88 .font(.caption)
89 if (task.taskRecurrence == true) {
90 (Text("[+") + Text(String(task.taskRecurrenceInt)) + Text(" ") + Text(task.taskRecurrencePeriod) + Text("]"))
91 .font(.caption)
92 }
93 }
94 }
95 }
96 Spacer()
97 (Text("[#") + Text(task.taskPriority) + Text("]"))
98 }
99 .swipeActions(edge: .leading) {
100 Button() {
101 print("\(task.taskItem) is being edited.")
102 // TODO: Add method to edit message in the DataStore
103 } label: {
104 Label("Edit", systemImage: "pencil")
105 }
106 }
107 .swipeActions(edge: .trailing) {
108 Button() {
109 print("\(task.taskItem) is being marked as complete.")
110 // TODO: Add method to complete message in the DataStore & move to Archive list
111 } label: {
112 Label("Complete", systemImage: "checkmark")
113 }
114 .tint(.green)
115 Button(role: .destructive) {
116 print("\(task.taskItem) is being deleted.")
117 } label: {
118 Label("Delete", systemImage: "trash")
119 }
120 }
121 }
122 .onDelete(perform: self.deleteTask)
123 }
124 .navigationBarTitle("LibreTasks")
125 .toolbar {
126 ToolbarItemGroup(placement: .navigationBarTrailing) {
127 EditButton()
128 Button {
129 showingPopover = true
130 } label: {
131 Image(systemName: "square.and.pencil")
132 }.popover(isPresented: $showingPopover) {
133 HStack {
134 Button {
135 showingPopover = false
136 } label: {
137 Text("Close")
138 }
139 Spacer()
140 Text("Add New Task")
141 Spacer()
142 Button(action: self.addNewTask, label: {
143 Text("Save")
144 })
145 }
146 .padding()
147 Form {
148 Section(header: Text("Task Details")) {
149 TextField("Task Title", text: self.$newTask)
150 .onSubmit {
151 if newTask.isEmpty {
152 showAlert = true
153 }
154 }
155 .alert(isPresented: $showAlert) {
156 Alert(title: Text("Required Field"),
157 message: Text("You must enter a task title"),
158 dismissButton: .default(Text("OK")))
159 }
160 Picker("Priority:", selection: $selectedPriority) {
161 Text("A").tag(Priority.A)
162 Text("B").tag(Priority.B)
163 Text("C").tag(Priority.C)
164 }
165 DatePicker("Scheduled:", selection: $newTaskDate)
166 .datePickerStyle(CompactDatePickerStyle())
167 }
168 Section(header: Text("Repeating")) {
169 Toggle("Repeating", isOn: $recurringReminder)
170 if (recurringReminder == true) {
171 HStack {
172 TextField("", value: $recurrenceInteger, formatter: NumberFormatter())
173 Stepper(value: $recurrenceInteger, in: 1...100) {
174 EmptyView()
175 }
176 Picker("", selection: $selectedRecurrence) {
177 Text("Hours").tag(Recurrence.hours)
178 Text("Days").tag(Recurrence.days)
179 Text("Weeks").tag(Recurrence.weeks)
180 Text("Months").tag(Recurrence.months)
181 }
182 }
183 }
184 }
185 }
186 .padding()
187 Spacer()
188 }
189 }
190 }
191 }
192 }
193 .searchable(text: $query, prompt: "Search tasks")
194 }
195
196 func deleteTask(at offsets: IndexSet) {
197 taskStore.tasks.remove(atOffsets: offsets)
198 }
199
200}
201
202struct ContentView_Previews: PreviewProvider {
203 static var previews: some View {
204 ContentView()
205 }
206}