focus-flow/lib/src/task_actions.dart

86 lines
2.3 KiB
Dart

import 'models.dart';
import 'scheduling_engine.dart';
/// Quick actions available from a flexible task card.
enum FlexibleTaskQuickAction {
done,
push,
backlog,
breakUp,
}
/// Explicit push destinations shown after choosing the push quick action.
enum PushDestination {
nextAvailableSlot,
tomorrowTopOfQueue,
backlog,
}
/// Domain result for a flexible task quick action.
class FlexibleTaskActionResult {
const FlexibleTaskActionResult({
required this.action,
required this.task,
this.pushDestinations = const <PushDestination>[],
this.startsChildTaskFlow = false,
});
final FlexibleTaskQuickAction action;
final Task task;
final List<PushDestination> pushDestinations;
final bool startsChildTaskFlow;
bool get changedTask => !startsChildTaskFlow && pushDestinations.isEmpty;
}
/// Applies low-friction quick actions for flexible task cards.
class FlexibleTaskActionService {
const FlexibleTaskActionService({
this.schedulingEngine = const SchedulingEngine(),
});
final SchedulingEngine schedulingEngine;
FlexibleTaskActionResult apply({
required Task task,
required FlexibleTaskQuickAction action,
DateTime? updatedAt,
}) {
if (!task.isFlexible) {
throw ArgumentError.value(
task.type, 'task.type', 'Task must be flexible.');
}
switch (action) {
case FlexibleTaskQuickAction.done:
return FlexibleTaskActionResult(
action: action,
task: task.copyWith(
status: TaskStatus.completed,
updatedAt: updatedAt ?? DateTime.now(),
),
);
case FlexibleTaskQuickAction.push:
return FlexibleTaskActionResult(
action: action,
task: task,
pushDestinations: const [
PushDestination.nextAvailableSlot,
PushDestination.tomorrowTopOfQueue,
PushDestination.backlog,
],
);
case FlexibleTaskQuickAction.backlog:
return FlexibleTaskActionResult(
action: action,
task: schedulingEngine.moveToBacklog(task, updatedAt: updatedAt),
);
case FlexibleTaskQuickAction.breakUp:
return FlexibleTaskActionResult(
action: action,
task: task,
startsChildTaskFlow: true,
);
}
}
}