2 Commits 46ff6a9c41 ... 79ae5275e3

Autor SHA1 Mensagem Data
  Sam Jaffe 79ae5275e3 refactor: move Category picker into Project popover, relocate color icon 2 semanas atrás
  Sam Jaffe 21abee85ca feat: add popover to Task w/ Category picker and new Priority enum 2 semanas atrás

+ 33 - 0
Todos/Model/Priority.swift

@@ -0,0 +1,33 @@
+//
+//  Priority.swift
+//  Todos
+//
+//  Created by Sam Jaffe on 3/7/26.
+//
+
+import Foundation
+import SwiftUI
+
+enum Priority : String, CaseIterable, Identifiable, Codable {
+  case low = "Low"
+  case medium = "Medium"
+  case high = "High"
+
+  var id: String { self.rawValue }
+  
+  var label: String {
+    switch self {
+    case .low: return "chevron.down"
+    case .medium: return "chevron.up"
+    case .high: return "chevron.up.2"
+    }
+  }
+  
+  var style: some ShapeStyle {
+    switch self {
+    case .low: return .green
+    case .medium: return .blue
+    case .high: return .red
+    }
+  }
+}

+ 1 - 0
Todos/Model/Task.swift

@@ -21,6 +21,7 @@ final class Task: Codable {
   var subtasks: [SubTask] = []
   var notes: String = ""
   var status: Status = Status.todo
+  var priority: Priority? = nil
 
   init(parent: Project? = nil) {
     self.project = parent

+ 12 - 14
Todos/View/ProjectPanelView.swift

@@ -22,9 +22,12 @@ struct ProjectPanelView: View {
 
   var body: some View {
     HStack {
-      TextField("", text: $item.name)
+      TextField("Project Name", text: $item.name)
         .font(.title)
         .padding(.leading, 10)
+      if let grp = $allGroups.first(where: { $0.name.wrappedValue == item.category }) {
+        ColorPicker("", selection: grp.color).disabled(true).scaledToFit()
+      }
       Spacer()
       Button(action: addItem) {
         Image(systemName: "plus")
@@ -59,6 +62,12 @@ struct ProjectPanelView: View {
       .buttonStyle(.borderless)
       .popover(isPresented: $showDialogue) {
         List{
+          Picker("Default Category", selection: $item.category) {
+            Text(empty.name).tag("")
+            ForEach(allGroups) { group in
+              Text(group.name)
+            }
+          }
           HStack {
             Label("", systemImage: "arrow.up.arrow.down")
             Toggle("Move Tasks", isOn: $move)
@@ -72,19 +81,8 @@ struct ProjectPanelView: View {
       }
       Text("")
     }
-    HStack(alignment: .top) {
-      TextField("Project Notes", text: $item.notes, axis: .vertical)
-        .padding(.leading, 20)
-      if let grp = $allGroups.first(where: { $0.name.wrappedValue == item.category }) {
-        ColorPicker("", selection: grp.color).disabled(true).scaledToFit()
-      }
-      Picker("", selection: $item.category) {
-        Text(empty.name).tag("")
-        ForEach(allGroups) { group in
-          Text(group.name)
-        }
-      }.help("Default category for new Tasks")
-    }
+    TextField("Project Notes", text: $item.notes, axis: .vertical)
+      .padding(.leading, 20)
     List {
       ForEach(selected($item.tasks), id: \.id) { task in
         TaskView(task: task)

+ 37 - 9
Todos/View/TaskView.swift

@@ -13,15 +13,25 @@ struct TaskView: View {
   @AppStorage(UserDefaultsKeys.Category) var allGroups = CodableArray<Category>()
   @Binding var task: Task
 
+  @State private var showDialogue: Bool = false
   @State private var hideTags: Bool = false
   @State private var hideNotes: Bool = false
   @State private var empty = Category()
+  let unset: Priority? = nil
 
   @FocusState private var isFocused: Bool
 
   var body: some View {
     VStack {
       HStack {
+        if let priority = task.priority {
+          Image(systemName: priority.label)
+            .foregroundStyle(priority.style)
+            .bold()
+            .frame(width: 20)
+            .padding(.trailing, -10)
+        }
+
         StatusPicker(status: $task.status)
           .onChange(of: task.status) {
             if task.status.isStrong {
@@ -42,22 +52,40 @@ struct TaskView: View {
           Image(systemName: "plus")
             .help("Add a Subtask")
         }
-      }
-
-      if isFocused || !(hideTags || task.tags.isEmpty) {
-        HStack {
-          TagBarView(task: $task)
-            .font(.footnote)
-            .padding(.leading, 30)
-          if isFocused {
-            Picker("", selection: $task.category) {
+        Button {
+          showDialogue = !showDialogue
+        } label: {
+          Label("", systemImage: "ellipsis.circle")
+            .foregroundStyle(.gray)
+            .font(.title2)
+        }
+        .buttonStyle(.borderless)
+        .popover(isPresented: $showDialogue) {
+          List{
+            Picker("Task Category", selection: $task.category) {
               Text(empty.name).tag("")
               ForEach(allGroups) { group in
                 Text(group.name)
               }
             }
             .fixedSize(horizontal: true, vertical: false)
+
+            Picker("Priority", selection: $task.priority) {
+              Text("").tag(unset)
+              ForEach(Priority.allCases) { unit in
+                Text(unit.id).tag(unit)
+              }
+            }
           }
+        }
+        Text("")
+      }
+
+      if isFocused || !(hideTags || task.tags.isEmpty) {
+        HStack {
+          TagBarView(task: $task)
+            .font(.footnote)
+            .padding(.leading, 30)
           VisibilityTapper(hideToggle: $hideTags)
         }.focused($isFocused)
       }