TaskView.swift 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. //
  2. // TaskView.swift
  3. // Todos
  4. //
  5. // Created by Sam Jaffe on 2/28/26.
  6. //
  7. import SwiftUI
  8. import SwiftData
  9. struct TaskView: View {
  10. @Environment(\.modelContext) private var modelContext
  11. @Binding var task: Task
  12. @State private var showDialogue: Bool = false
  13. @State private var hideTags: Bool = false
  14. @State private var hideNotes: Bool = false
  15. let unset: Priority? = nil
  16. @FocusState private var isFocused: Bool
  17. var body: some View {
  18. VStack {
  19. HStack {
  20. if let priority = task.priority {
  21. Image(systemName: priority.label)
  22. .foregroundStyle(priority.style)
  23. .bold()
  24. .frame(width: 20)
  25. .padding(.trailing, -10)
  26. }
  27. StatusPicker(status: $task.status)
  28. .onChange(of: task.status) {
  29. if task.status.isStrong {
  30. task.subtasks
  31. .filter({ !$0.status.isStrong })
  32. .forEach({ subtask in subtask.status = task.status })
  33. }
  34. }
  35. TextField("Task Name", text: $task.name)
  36. .focused($isFocused)
  37. CategoryColorDisplay(category: $task.category)
  38. Button(action: addItem) {
  39. Image(systemName: "plus")
  40. .help("Add a Subtask")
  41. }
  42. Button {
  43. showDialogue = !showDialogue
  44. } label: {
  45. Label("", systemImage: "ellipsis.circle")
  46. .foregroundStyle(.gray)
  47. .font(.title2)
  48. }
  49. .buttonStyle(.borderless)
  50. .popover(isPresented: $showDialogue) {
  51. List {
  52. CategoryPicker(category: $task.category)
  53. .fixedSize(horizontal: true, vertical: false)
  54. Picker("Priority", selection: $task.priority) {
  55. Text("").tag(unset)
  56. ForEach(Priority.allCases) { unit in
  57. Text(unit.id).tag(unit)
  58. }
  59. }
  60. }
  61. }
  62. Text("")
  63. }
  64. if isFocused || !(hideTags || task.tags.isEmpty) {
  65. HStack {
  66. TagBarView(task: $task)
  67. .font(.footnote)
  68. .padding(.leading, 30)
  69. VisibilityTapper(hideToggle: $hideTags)
  70. }.focused($isFocused)
  71. }
  72. if isFocused || !(hideNotes || task.notes.isEmpty) {
  73. HStack {
  74. TextField("Notes", text: $task.notes, axis: .vertical)
  75. .font(.footnote)
  76. .padding(.leading, 30)
  77. VisibilityTapper(hideToggle: $hideNotes)
  78. }.focused($isFocused)
  79. }
  80. }
  81. }
  82. private func addItem() {
  83. withAnimation {
  84. let newSubtask = SubTask(parent: task)
  85. modelContext.insert(newSubtask)
  86. task.subtasks.append(newSubtask)
  87. }
  88. }
  89. }
  90. #Preview {
  91. @Previewable @State var task = Task()
  92. TaskView(task: $task)
  93. .frame(minHeight: 100) // Preview does not resize window properly
  94. }