import 'task_statistics.dart'; /// Scheduling behavior category. enum TaskType { /// Movable planned work. flexible, /// Required visible block that should not be moved automatically. inflexible, /// Required visible task that remains actionable if missed. critical, /// Hidden scheduling constraint, not a task card. locked, /// Unplanned completed/logged task. surprise, /// Intentional rest time. freeSlot, } /// Current lifecycle state of a task. enum TaskStatus { /// Scheduled or queued work that has not started. planned, /// Work currently in progress. active, /// Work finished by the user. completed, /// Work that was not completed in its intended time. missed, /// Work intentionally removed from the plan. cancelled, /// Work intentionally dismissed because it no longer applies. noLongerRelevant, /// Unscheduled work kept for later planning. backlog, } /// User-facing importance level. enum PriorityLevel { /// Lowest priority. veryLow, /// Low priority. low, /// Default middle priority. medium, /// High priority. high, /// Highest priority. veryHigh, } /// Expected reward or payoff from completing a task. enum RewardLevel { /// No reward level has been captured; this is not equivalent to low reward. notSet, /// Very low expected reward. veryLow, /// Low expected reward. low, /// Medium expected reward. medium, /// High expected reward. high, /// Very high expected reward. veryHigh, } /// Expected effort or activation difficulty for a task. enum DifficultyLevel { /// No difficulty has been captured yet. notSet, /// Very easy to start or complete. veryEasy, /// Easy to start or complete. easy, /// Medium effort. medium, /// Hard to start or complete. hard, /// Very hard to start or complete. veryHard, } /// Reminder intensity preference. enum ReminderProfile { /// No reminder nudges. silent, /// Low-friction reminder nudges. gentle, /// Repeated reminder nudges. persistent, /// Strong reminder behavior for required items. strict, } /// Lightweight backlog-only metadata. enum BacklogTag { /// Task is intentionally saved as a someday/wishlist item. wishlist, } /// Starter task model for the scheduling core. /// /// This is a public placeholder API for early V1 chunks. Keep behavior changes /// explicit and covered by tests as the model becomes more complete. class Task { const Task({ required this.id, required this.title, required this.projectId, required this.type, required this.status, required this.createdAt, required this.updatedAt, this.priority, this.reward = RewardLevel.notSet, this.difficulty = DifficultyLevel.notSet, this.durationMinutes, this.scheduledStart, this.scheduledEnd, this.parentTaskId, this.backlogTags = const {}, this.stats = const TaskStatistics(), }); /// Create a minimal captured task without requiring planning details. factory Task.quickCapture({ required String id, required String title, required DateTime createdAt, String projectId = 'inbox', TaskType type = TaskType.flexible, TaskStatus status = TaskStatus.backlog, PriorityLevel priority = PriorityLevel.medium, RewardLevel reward = RewardLevel.notSet, DifficultyLevel difficulty = DifficultyLevel.notSet, Set backlogTags = const {}, DateTime? updatedAt, }) { if (title.trim().isEmpty) { throw ArgumentError.value(title, 'title', 'Title is required.'); } return Task( id: id, title: title.trim(), projectId: projectId, type: type, status: status, priority: priority, reward: reward, difficulty: difficulty, createdAt: createdAt, updatedAt: updatedAt ?? createdAt, backlogTags: backlogTags, ); } final String id; final String title; final String projectId; final TaskType type; final TaskStatus status; final PriorityLevel? priority; final RewardLevel reward; final DifficultyLevel difficulty; final int? durationMinutes; final DateTime? scheduledStart; final DateTime? scheduledEnd; final String? parentTaskId; final Set backlogTags; final DateTime createdAt; final DateTime updatedAt; final TaskStatistics stats; bool get isFlexible => type == TaskType.flexible; bool get isRequiredVisible => type == TaskType.critical || type == TaskType.inflexible; bool get isLocked => type == TaskType.locked; bool get isBacklog => status == TaskStatus.backlog; Task copyWith({ String? id, String? title, String? projectId, TaskType? type, TaskStatus? status, PriorityLevel? priority, RewardLevel? reward, DifficultyLevel? difficulty, int? durationMinutes, DateTime? scheduledStart, DateTime? scheduledEnd, String? parentTaskId, Set? backlogTags, DateTime? createdAt, DateTime? updatedAt, TaskStatistics? stats, bool clearSchedule = false, }) { return Task( id: id ?? this.id, title: title ?? this.title, projectId: projectId ?? this.projectId, type: type ?? this.type, status: status ?? this.status, priority: priority ?? this.priority, reward: reward ?? this.reward, difficulty: difficulty ?? this.difficulty, durationMinutes: durationMinutes ?? this.durationMinutes, scheduledStart: clearSchedule ? null : (scheduledStart ?? this.scheduledStart), scheduledEnd: clearSchedule ? null : (scheduledEnd ?? this.scheduledEnd), parentTaskId: parentTaskId ?? this.parentTaskId, backlogTags: backlogTags ?? this.backlogTags, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt, stats: stats ?? this.stats, ); } } /// Starter project defaults used when creating or scheduling tasks. class ProjectProfile { const ProjectProfile({ required this.id, required this.name, required this.colorKey, this.defaultPriority = PriorityLevel.medium, this.defaultReward = RewardLevel.notSet, this.defaultDifficulty = DifficultyLevel.notSet, this.defaultReminderProfile = ReminderProfile.gentle, this.defaultDurationMinutes, }); final String id; final String name; final String colorKey; final PriorityLevel defaultPriority; final RewardLevel defaultReward; final DifficultyLevel defaultDifficulty; final ReminderProfile defaultReminderProfile; final int? defaultDurationMinutes; /// Create a task using project defaults while allowing explicit overrides. Task createTask({ required String id, required String title, required DateTime createdAt, TaskType type = TaskType.flexible, TaskStatus status = TaskStatus.backlog, PriorityLevel? priority, RewardLevel? reward, DifficultyLevel? difficulty, int? durationMinutes, DateTime? scheduledStart, DateTime? scheduledEnd, String? parentTaskId, Set backlogTags = const {}, DateTime? updatedAt, }) { return Task( id: id, title: title, projectId: this.id, type: type, status: status, priority: priority ?? defaultPriority, reward: reward ?? defaultReward, difficulty: difficulty ?? defaultDifficulty, durationMinutes: durationMinutes ?? defaultDurationMinutes, scheduledStart: scheduledStart, scheduledEnd: scheduledEnd, parentTaskId: parentTaskId, backlogTags: backlogTags, createdAt: createdAt, updatedAt: updatedAt ?? createdAt, ); } } /// Starter time range value used by scheduling helpers. class TimeInterval { const TimeInterval({ required this.start, required this.end, this.label, }); final DateTime start; final DateTime end; final String? label; Duration get duration => end.difference(start); bool overlaps(TimeInterval other) { return start.isBefore(other.end) && end.isAfter(other.start); } }