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}