diff --git a/KisaniCal/Models/TaskItem.swift b/KisaniCal/Models/TaskItem.swift index 4fa208b..f141beb 100644 --- a/KisaniCal/Models/TaskItem.swift +++ b/KisaniCal/Models/TaskItem.swift @@ -23,9 +23,9 @@ struct TaskItem: Identifiable, Codable, Equatable { // Recurrence: optional so existing saved tasks decode safely (missing key → nil). var recurrenceEnd: Date? = nil // "repeat until" (nil = open-ended) var completedOccurrences: [String]? = nil // "yyyy-MM-dd" of completed occurrences - // Matrix: a manual drag pins the task to a quadrant (overrides auto-placement). - // nil = auto-place from Priority × deadline. Optional so old saves decode safely. - var matrixOverride: Quadrant? = nil + // Matrix: horizontal manual moves override urgency only. + // nil = auto from deadline, true = force urgent, false = force not-urgent. + var urgencyOverride: Bool? = nil } enum Priority: String, Codable, CaseIterable, Identifiable { @@ -351,19 +351,20 @@ class TaskViewModel: ObservableObject { return nil } - // MARK: - Eisenhower Matrix (TickTick-style: Priority × deadline, with manual override) + // MARK: - Eisenhower Matrix (TickTick-style: Priority × deadline, with urgency override) // // The Matrix is a VIEW of tasks, not a separate system. A task is auto-placed: // • Importance (top row) = Priority is High; Medium/Low/None = bottom row. // • Urgency (left column) = its (next active) due date is today/overdue/within // `urgentWindowDays`; undated or far-out = right column. // So Q1 = High + urgent, Q2 = High + not urgent, Q3 = not-High + urgent, Q4 = the rest. - // A manual drag (`moveToQuadrant`) pins the task via `matrixOverride` and syncs its - // Priority to the target row — the move sticks and is never forced back. Editing the - // Priority or due date in the task view clears the override so it re-places live. + // Vertical drag changes Priority directly. Horizontal drag sets `urgencyOverride` + // because we should not fabricate/destroy a real deadline just to move columns. + // Editing the due date clears urgency override so the task re-places live. // Recurring tasks roll forward (a completed occurrence is replaced by the next). - static let urgentWindowDays = 7 + static let urgentWindowDays = 3 + static let categoryUrgentWindowDays = 14 private func isImportant(_ t: TaskItem) -> Bool { t.priority == .high } @@ -374,11 +375,32 @@ class TaskViewModel: ObservableObject { } private func isUrgent(_ t: TaskItem, on today: Date) -> Bool { + t.urgencyOverride ?? urgentByDeadline(t, on: today) + } + + /// Date-derived urgency, ignoring any manual override (overdue/today/within window). + private func urgentByDeadline(_ t: TaskItem, on today: Date = Date()) -> Bool { guard let due = effectiveDue(t, on: today) else { return false } // undated → never urgent let days = Calendar.current.dateComponents([.day], from: Calendar.current.startOfDay(for: today), to: Calendar.current.startOfDay(for: due)).day ?? 0 - return days <= Self.urgentWindowDays // due soon / overdue + return days <= urgentWindow(for: t) // due soon / overdue + } + + private func urgentWindow(for t: TaskItem) -> Int { + switch t.category { + case .birthday, .domain, .annual: + return Self.categoryUrgentWindowDays + case .reminder, .custom: + let title = t.title.lowercased() + if title.contains("domain") || title.contains("subscription") + || title.contains("annual") || title.contains("renewal") + || title.contains("renew") || title.contains("exam") + || title.contains("deadline") { + return Self.categoryUrgentWindowDays + } + return Self.urgentWindowDays + } } /// Auto-placement from Priority (importance) × deadline (urgency). @@ -391,9 +413,9 @@ class TaskViewModel: ObservableObject { } } - /// Where a task appears in the Matrix now: a manual override wins, else auto-placement. + /// Where a task appears in the Matrix now. func displayQuadrant(_ t: TaskItem, on today: Date = Date()) -> Quadrant { - t.matrixOverride ?? autoQuadrant(t, on: today) + autoQuadrant(t, on: today) } /// Matrix rows for a quadrant, grouped by the *displayed* (computed) quadrant. @@ -436,36 +458,47 @@ class TaskViewModel: ObservableObject { func setDate(_ task: TaskItem, date: Date?) { guard let idx = tasks.firstIndex(where: { $0.id == task.id }) else { return } tasks[idx].dueDate = date - tasks[idx].matrixOverride = nil // deadline changed → re-place from urgency + tasks[idx].urgencyOverride = nil // deadline changed → re-place from urgency + tasks[idx].quadrant = displayQuadrant(tasks[idx]) save() } func setCategory(_ task: TaskItem, category: TaskCategory) { guard let idx = tasks.firstIndex(where: { $0.id == task.id }) else { return } tasks[idx].category = category + tasks[idx].quadrant = displayQuadrant(tasks[idx]) save() } func setPriority(_ task: TaskItem, priority: Priority) { guard let idx = tasks.firstIndex(where: { $0.id == task.id }) else { return } tasks[idx].priority = priority - tasks[idx].matrixOverride = nil // priority changed → re-place from importance + tasks[idx].quadrant = displayQuadrant(tasks[idx]) // color follows placement save() } - /// Manual drag/move in the Matrix. Pins the task to the target quadrant and syncs - /// its Priority to that row — top row (Q1/Q2) becomes High; moving down out of the - /// top demotes High→Medium so it reads as unimportant. TickTick-style: it sticks. + /// Manual drag/move in the Matrix. Vertical movement updates Priority directly. + /// Horizontal movement sets an urgency override instead of mutating due dates — + /// but only when the target column disagrees with the date-derived urgency, so a + /// drag into a task's natural column leaves it on Auto (no false "Manual" flag). func moveToQuadrant(taskID: UUID, quadrant: Quadrant) { guard let idx = tasks.firstIndex(where: { $0.id == taskID }) else { return } - tasks[idx].matrixOverride = quadrant - tasks[idx].quadrant = quadrant // keep stored quadrant in sync (widget accent) let importantRow = (quadrant == .urgent || quadrant == .schedule) + let urgentColumn = (quadrant == .urgent || quadrant == .delegate_) if importantRow { tasks[idx].priority = .high } else if tasks[idx].priority == .high { tasks[idx].priority = .medium } + tasks[idx].urgencyOverride = urgentByDeadline(tasks[idx]) == urgentColumn ? nil : urgentColumn + tasks[idx].quadrant = quadrant // keep stored quadrant in sync (color + widget accent) + save() + } + + func resetMatrixUrgencyOverride(_ task: TaskItem) { + guard let idx = tasks.firstIndex(where: { $0.id == task.id }) else { return } + tasks[idx].urgencyOverride = nil + tasks[idx].quadrant = displayQuadrant(tasks[idx]) save() } @@ -500,6 +533,7 @@ class TaskViewModel: ObservableObject { priority: resolvedPriority, reminderDate: reminderDate, constantReminder: constantReminder) item.recurrenceEnd = recurrenceEnd + item.quadrant = displayQuadrant(item) // color/widget identity follows placement tasks.append(item) save() } @@ -519,7 +553,8 @@ class TaskViewModel: ObservableObject { tasks[idx].reminderDate = reminderDate tasks[idx].constantReminder = constantReminder tasks[idx].recurrenceEnd = recurrenceEnd - tasks[idx].matrixOverride = nil // editor saved a new deadline → re-place + tasks[idx].urgencyOverride = nil // editor saved a new deadline → re-place + tasks[idx].quadrant = displayQuadrant(tasks[idx]) save() } diff --git a/KisaniCal/Views/CalendarView.swift b/KisaniCal/Views/CalendarView.swift index 831e5e1..e997b71 100644 --- a/KisaniCal/Views/CalendarView.swift +++ b/KisaniCal/Views/CalendarView.swift @@ -607,6 +607,7 @@ struct CalendarView: View { onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, onSetCategory: { taskVM.setCategory($0, category: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) }, onEditEvent: { editingEvent = EditableEvent(event: $0) }, onDeleteEvent: { calStore.deleteEvent($0) } ) @@ -1585,6 +1586,7 @@ struct DayTimelineView: View { var onMove: ((TaskItem, Quadrant) -> Void)? = nil var onSetPriority: ((TaskItem, Priority) -> Void)? = nil var onSetCategory: ((TaskItem, TaskCategory) -> Void)? = nil + var onResetMatrixUrgency: ((TaskItem) -> Void)? = nil // Calendar events (non-subscription only): edit/delete in the real calendar. var onEditEvent: ((EKEvent) -> Void)? = nil var onDeleteEvent: ((EKEvent) -> Void)? = nil @@ -1747,6 +1749,7 @@ struct DayTimelineView: View { onMove: { onMove?($0, $1) }, onSetPriority: { onSetPriority?($0, $1) }, onSetCategory: { onSetCategory?($0, $1) }, + onResetMatrixUrgency: onResetMatrixUrgency, onLiveActivity:{ LiveActivityManager.toggle(for: $0) }, onEdit: onEdit, onDelete: { onDelete?($0) } diff --git a/KisaniCal/Views/MatrixView.swift b/KisaniCal/Views/MatrixView.swift index d9f0bad..353f434 100644 --- a/KisaniCal/Views/MatrixView.swift +++ b/KisaniCal/Views/MatrixView.swift @@ -5,7 +5,7 @@ struct MatrixView: View { @EnvironmentObject var taskVM: TaskViewModel @State private var showAddTask = false @State private var dropTarget: Quadrant? = nil - @State private var hideCompleted = false + @State private var hideCompleted = true @State private var showUserGuide = false @State private var drillQuadrant: Quadrant? = nil @State private var showDrill = false @@ -67,6 +67,7 @@ struct MatrixView: View { onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetCategory: { taskVM.setCategory($0, category: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) }, onDelete: { taskVM.delete($0) }, onTapHeader: { drillQuadrant = .urgent; showDrill = true } ) @@ -85,6 +86,7 @@ struct MatrixView: View { onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetCategory: { taskVM.setCategory($0, category: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) }, onDelete: { taskVM.delete($0) }, onTapHeader: { drillQuadrant = .schedule; showDrill = true } ) @@ -107,6 +109,7 @@ struct MatrixView: View { onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetCategory: { taskVM.setCategory($0, category: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) }, onDelete: { taskVM.delete($0) }, onTapHeader: { drillQuadrant = .delegate_; showDrill = true } ) @@ -125,6 +128,7 @@ struct MatrixView: View { onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetCategory: { taskVM.setCategory($0, category: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) }, onDelete: { taskVM.delete($0) }, onTapHeader: { drillQuadrant = .eliminate; showDrill = true } ) @@ -188,6 +192,7 @@ struct QuadrantCard: View { var onMove: ((TaskItem, Quadrant) -> Void)? = nil var onSetCategory: ((TaskItem, TaskCategory) -> Void)? = nil var onSetPriority: ((TaskItem, Priority) -> Void)? = nil + var onResetMatrixUrgency: ((TaskItem) -> Void)? = nil var onDelete: ((TaskItem) -> Void)? = nil var onTapHeader: (() -> Void)? = nil @@ -265,6 +270,15 @@ struct QuadrantCard: View { .font(.system(size: 7, weight: .bold)) .foregroundColor(badgeColor.opacity(0.7)) } + if task.urgencyOverride != nil { + Text("Manual") + .font(AppFonts.mono(7, weight: .bold)) + .foregroundColor(badgeColor) + .padding(.horizontal, 4) + .padding(.vertical, 2) + .background(badgeBg) + .clipShape(Capsule()) + } Text(task.title) .font(AppFonts.sans(12, weight: .medium)) .foregroundColor(task.isComplete ? AppColors.text3(cs) : AppColors.text(cs)) @@ -291,6 +305,7 @@ struct QuadrantCard: View { onMove: { t, q in withAnimation(KisaniSpring.snappy) { onMove?(t, q) } }, onSetPriority: { onSetPriority?($0, $1) }, onSetCategory: { onSetCategory?($0, $1) }, + onResetMatrixUrgency: { t in withAnimation(KisaniSpring.snappy) { onResetMatrixUrgency?(t) } }, onLiveActivity:{ LiveActivityManager.toggle(for: $0) }, onDelete: { t in withAnimation(KisaniSpring.snappy) { onDelete?(t) } } ) @@ -449,6 +464,7 @@ struct QuadrantDetailView: View { onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, onSetCategory: { taskVM.setCategory($0, category: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) }, onLiveActivity:{ LiveActivityManager.toggle(for: $0) }, onEdit: { editingTask = $0 }, onDelete: { taskVM.delete($0) } @@ -474,6 +490,7 @@ struct QuadrantDetailView: View { onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, onSetCategory: { taskVM.setCategory($0, category: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) }, onLiveActivity:{ LiveActivityManager.toggle(for: $0) }, onEdit: { editingTask = $0 }, onDelete: { taskVM.delete($0) } @@ -500,6 +517,7 @@ struct QuadrantDetailView: View { onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, onSetCategory: { taskVM.setCategory($0, category: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) }, onLiveActivity:{ LiveActivityManager.toggle(for: $0) }, onEdit: { editingTask = $0 }, onDelete: { taskVM.delete($0) } @@ -622,12 +640,23 @@ private struct QDTaskRow: View { Button(action: onTap) { HStack(alignment: .top) { - Text(task.title) - .font(AppFonts.sans(14, weight: task.isComplete ? .regular : .medium)) - .foregroundColor(task.isComplete ? AppColors.text3(cs) : AppColors.text(cs)) - .strikethrough(task.isComplete, color: AppColors.text3(cs)) - .lineLimit(2) - .frame(maxWidth: .infinity, alignment: .leading) + VStack(alignment: .leading, spacing: 4) { + if task.urgencyOverride != nil { + Text("Manual") + .font(AppFonts.mono(8, weight: .bold)) + .foregroundColor(quadrant.color) + .padding(.horizontal, 5) + .padding(.vertical, 2) + .background(quadrant.softColor) + .clipShape(Capsule()) + } + Text(task.title) + .font(AppFonts.sans(14, weight: task.isComplete ? .regular : .medium)) + .foregroundColor(task.isComplete ? AppColors.text3(cs) : AppColors.text(cs)) + .strikethrough(task.isComplete, color: AppColors.text3(cs)) + .lineLimit(2) + } + .frame(maxWidth: .infinity, alignment: .leading) VStack(alignment: .trailing, spacing: 3) { if let d = task.dueDate { diff --git a/KisaniCal/Views/SettingsView.swift b/KisaniCal/Views/SettingsView.swift index 1d7aad2..ec6c658 100644 --- a/KisaniCal/Views/SettingsView.swift +++ b/KisaniCal/Views/SettingsView.swift @@ -1051,7 +1051,7 @@ private struct ProfileStatsSheet: View { return taskVM.tasks.filter { $0.isComplete && ($0.completedAt ?? .distantPast) >= start }.count } private var urgentOpen: Int { - taskVM.tasks.filter { !$0.isComplete && $0.quadrant == .urgent }.count + taskVM.tasks.filter { !$0.isComplete && taskVM.displayQuadrant($0) == .urgent }.count } // ── 7-day task activity ── @@ -1140,10 +1140,10 @@ private struct ProfileStatsSheet: View { // Quadrant breakdown HStack(spacing: 8) { - QuadStat(label: "Urgent", count: taskVM.tasks.filter { $0.quadrant == .urgent && !$0.isComplete }.count, color: AppColors.accent) - QuadStat(label: "Schedule", count: taskVM.tasks.filter { $0.quadrant == .schedule && !$0.isComplete }.count, color: AppColors.yellow) - QuadStat(label: "Delegate", count: taskVM.tasks.filter { $0.quadrant == .delegate_ && !$0.isComplete }.count, color: AppColors.blue) - QuadStat(label: "Eliminate",count: taskVM.tasks.filter { $0.quadrant == .eliminate && !$0.isComplete }.count, color: AppColors.green) + QuadStat(label: "Urgent", count: taskVM.tasks.filter { !$0.isComplete && taskVM.displayQuadrant($0) == .urgent }.count, color: AppColors.accent) + QuadStat(label: "Schedule", count: taskVM.tasks.filter { !$0.isComplete && taskVM.displayQuadrant($0) == .schedule }.count, color: AppColors.yellow) + QuadStat(label: "Delegate", count: taskVM.tasks.filter { !$0.isComplete && taskVM.displayQuadrant($0) == .delegate_ }.count, color: AppColors.blue) + QuadStat(label: "Eliminate",count: taskVM.tasks.filter { !$0.isComplete && taskVM.displayQuadrant($0) == .eliminate }.count, color: AppColors.green) } } .padding(14).background(AppColors.surface(cs)) diff --git a/KisaniCal/Views/TaskContextMenu.swift b/KisaniCal/Views/TaskContextMenu.swift index f39e128..581e8f5 100644 --- a/KisaniCal/Views/TaskContextMenu.swift +++ b/KisaniCal/Views/TaskContextMenu.swift @@ -35,6 +35,7 @@ struct TaskMenuItems: View { var onMove: (TaskItem, Quadrant) -> Void = { _, _ in } var onSetPriority: (TaskItem, Priority) -> Void = { _, _ in } var onSetCategory: (TaskItem, TaskCategory) -> Void = { _, _ in } + var onResetMatrixUrgency: ((TaskItem) -> Void)? = nil var onLiveActivity:(TaskItem) -> Void = { LiveActivityManager.toggle(for: $0) } var onEdit: ((TaskItem) -> Void)? = nil var onDelete: (TaskItem) -> Void = { _ in } @@ -73,6 +74,12 @@ struct TaskMenuItems: View { } } label: { Label("Move", systemImage: "arrow.right.square") } + if task.urgencyOverride != nil, let onResetMatrixUrgency { + Button { onResetMatrixUrgency(task) } label: { + Label("Reset Matrix Urgency", systemImage: "arrow.counterclockwise") + } + } + Menu { ForEach(Priority.allCases) { p in Button { onSetPriority(task, p) } label: { diff --git a/KisaniCal/Views/TodayView.swift b/KisaniCal/Views/TodayView.swift index f4f06de..bf6e5e1 100644 --- a/KisaniCal/Views/TodayView.swift +++ b/KisaniCal/Views/TodayView.swift @@ -113,7 +113,8 @@ struct TodayView: View { onSetDate: { taskVM.setDate($0, date: $1) }, onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, - onSetCategory: { taskVM.setCategory($0, category: $1) } + onSetCategory: { taskVM.setCategory($0, category: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) } ) .padding(.horizontal, 18) @@ -130,7 +131,8 @@ struct TodayView: View { onSetDate: { taskVM.setDate($0, date: $1) }, onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, - onSetCategory: { taskVM.setCategory($0, category: $1) } + onSetCategory: { taskVM.setCategory($0, category: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) } ) .padding(.horizontal, 18) .padding(.top, 10) @@ -149,7 +151,8 @@ struct TodayView: View { onSetDate: { taskVM.setDate($0, date: $1) }, onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, - onSetCategory: { taskVM.setCategory($0, category: $1) } + onSetCategory: { taskVM.setCategory($0, category: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) } ) } @@ -166,7 +169,8 @@ struct TodayView: View { onSetDate: { taskVM.setDate($0, date: $1) }, onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, - onSetCategory: { taskVM.setCategory($0, category: $1) } + onSetCategory: { taskVM.setCategory($0, category: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) } ) } @@ -183,7 +187,8 @@ struct TodayView: View { onSetDate: { taskVM.setDate($0, date: $1) }, onMove: { taskVM.moveToQuadrant(taskID: $0.id, quadrant: $1) }, onSetPriority: { taskVM.setPriority($0, priority: $1) }, - onSetCategory: { taskVM.setCategory($0, category: $1) } + onSetCategory: { taskVM.setCategory($0, category: $1) }, + onResetMatrixUrgency: { taskVM.resetMatrixUrgencyOverride($0) } ) } @@ -538,6 +543,7 @@ struct OverdueCard: View { var onMove: (TaskItem, Quadrant) -> Void = { _, _ in } var onSetPriority: (TaskItem, Priority) -> Void = { _, _ in } var onSetCategory: (TaskItem, TaskCategory) -> Void = { _, _ in } + var onResetMatrixUrgency: (TaskItem) -> Void = { _ in } @State private var expanded = true @@ -639,6 +645,7 @@ struct OverdueCard: View { onMove: onMove, onSetPriority: onSetPriority, onSetCategory: onSetCategory, + onResetMatrixUrgency: onResetMatrixUrgency, onLiveActivity: { LiveActivityManager.toggle(for: $0) }, onEdit: onEdit, onDelete: onDelete @@ -951,6 +958,7 @@ struct UpcomingSection: View { var onMove: (TaskItem, Quadrant) -> Void = { _, _ in } var onSetPriority: (TaskItem, Priority) -> Void = { _, _ in } var onSetCategory: (TaskItem, TaskCategory) -> Void = { _, _ in } + var onResetMatrixUrgency: (TaskItem) -> Void = { _ in } @State private var collapsed = false @State private var showAll = false @@ -1014,6 +1022,7 @@ struct UpcomingSection: View { onMove: onMove, onSetPriority: onSetPriority, onSetCategory: onSetCategory, + onResetMatrixUrgency: onResetMatrixUrgency, onLiveActivity: { LiveActivityManager.toggle(for: $0) }, onEdit: onEdit, onDelete: { task in withAnimation(KisaniSpring.snappy) { onDelete(task) } } @@ -1737,7 +1746,7 @@ struct AddTaskSheet: View { let importantRow = (prefilledQuadrant == .urgent || prefilledQuadrant == .schedule) _selectedPriority = State(initialValue: importantRow ? .high : .none) var p = NLParsed() - p.date = prefilledDate ?? Calendar.current.startOfDay(for: Date()) + p.date = prefilledDate _parsed = State(initialValue: p) } @@ -1755,7 +1764,7 @@ struct AddTaskSheet: View { .frame(minHeight: 36, maxHeight: 72) .onChange(of: rawText) { _ in var p = NLTaskParser.parse(rawText) - if p.date == nil { p.date = Calendar.current.startOfDay(for: Date()) } + if p.date == nil { p.date = prefilledDate } withAnimation(KisaniSpring.micro) { parsed = p if p.isBirthday { selectedCategory = .birthday }