From 8f041c69f3afb037e7c7bd4b80263869ddebe158 Mon Sep 17 00:00:00 2001 From: Robin Kutesa Date: Mon, 1 Jun 2026 03:57:48 +0300 Subject: [PATCH] Add task priority (High/Medium/Low/None) with colored flag picker Priority stored on TaskItem, shown as colored flag in add sheet toolbar and as a small flag indicator on each task row. Co-Authored-By: Kutesir --- KisaniCal/Models/TaskItem.swift | 33 +++++++++++++++++++++++++++++++-- KisaniCal/Views/TodayView.swift | 26 ++++++++++++++++++++------ 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/KisaniCal/Models/TaskItem.swift b/KisaniCal/Models/TaskItem.swift index 081285a..b8f8bda 100644 --- a/KisaniCal/Models/TaskItem.swift +++ b/KisaniCal/Models/TaskItem.swift @@ -15,6 +15,33 @@ struct TaskItem: Identifiable, Codable, Equatable { var isPinned: Bool = false var endDate: Date? = nil var isAllDay: Bool = false + var priority: Priority = .none +} + +enum Priority: String, Codable, CaseIterable, Identifiable { + var id: String { rawValue } + case high = "High" + case medium = "Medium" + case low = "Low" + case none = "None" + + var color: Color { + switch self { + case .high: return .red + case .medium: return .yellow + case .low: return .blue + case .none: return Color(.systemGray3) + } + } + + var label: String { + switch self { + case .high: return "High Priority" + case .medium: return "Medium Priority" + case .low: return "Low Priority" + case .none: return "No Priority" + } + } } enum Quadrant: String, CaseIterable, Identifiable, Codable { @@ -162,11 +189,13 @@ class TaskViewModel: ObservableObject { func addTask(title: String, dueDate: Date?, hasTime: Bool = false, quadrant: Quadrant = .urgent, category: TaskCategory = .reminder, taskColor: TaskColor = .orange, isRecurring: Bool = false, - endDate: Date? = nil, isAllDay: Bool = false) { + endDate: Date? = nil, isAllDay: Bool = false, + priority: Priority = .none) { tasks.append(TaskItem(title: title, dueDate: dueDate, hasTime: hasTime, quadrant: quadrant, category: category, taskColor: taskColor, isRecurring: isRecurring, - endDate: endDate, isAllDay: isAllDay)) + endDate: endDate, isAllDay: isAllDay, + priority: priority)) save() } diff --git a/KisaniCal/Views/TodayView.swift b/KisaniCal/Views/TodayView.swift index 9fe299f..3d62451 100644 --- a/KisaniCal/Views/TodayView.swift +++ b/KisaniCal/Views/TodayView.swift @@ -1015,6 +1015,13 @@ struct TaskRowView: View { Spacer() + if task.priority != .none { + Image(systemName: "flag.fill") + .font(.system(size: 11, weight: .semibold)) + .foregroundColor(task.priority.color) + .padding(.trailing, 4) + } + TagChip( text: task.category.rawValue, color: task.taskColor.color(), @@ -1459,6 +1466,7 @@ struct AddTaskSheet: View { @State private var parsed = NLParsed() @State private var selectedQuadrant: Quadrant @State private var selectedCategory: TaskCategory = .reminder + @State private var selectedPriority: Priority = .none @State private var showDatePicker = false var prefilledDate: Date? @@ -1534,15 +1542,20 @@ struct AddTaskSheet: View { // Priority Menu { - ForEach(Quadrant.allCases) { q in - Button { withAnimation(KisaniSpring.micro) { selectedQuadrant = q } } label: { - Label(q.rawValue, systemImage: selectedQuadrant == q ? "checkmark" : "") + ForEach(Priority.allCases) { p in + Button { withAnimation(KisaniSpring.micro) { selectedPriority = p } } label: { + Label { + Text(p.label) + } icon: { + Image(systemName: p == .none ? "flag" : "flag.fill") + .foregroundStyle(p.color) + } } } } label: { - Image(systemName: selectedQuadrant == .urgent ? "flag.fill" : "flag") + Image(systemName: selectedPriority == .none ? "flag" : "flag.fill") .font(.system(size: 16)) - .foregroundColor(selectedQuadrant == .urgent ? AppColors.accent : AppColors.text3(cs)) + .foregroundColor(selectedPriority == .none ? AppColors.text3(cs) : selectedPriority.color) .frame(width: 42, height: 44) } .buttonStyle(.plain) @@ -1618,7 +1631,8 @@ struct AddTaskSheet: View { taskVM.addTask(title: cleanTitle, dueDate: parsed.date, hasTime: parsed.hasTime, quadrant: selectedQuadrant, category: selectedCategory, isRecurring: parsed.isRecurring, - endDate: parsed.endDate, isAllDay: parsed.isAllDay) + endDate: parsed.endDate, isAllDay: parsed.isAllDay, + priority: selectedPriority) dismiss() } }