Implemented Task Pause and Resume
This commit is contained in:
@@ -54,6 +54,12 @@ String _uiFingerprint(TaskActivityLog log) {
|
||||
return '${log.taskId}|${log.actionType}';
|
||||
}
|
||||
|
||||
// Pause/resume events are sequence-sensitive for execution-time calculations.
|
||||
// Keep each row distinct to avoid collapsing multiple toggles in the same minute.
|
||||
if (log.actionType == 'paused' || log.actionType == 'resumed') {
|
||||
return '${log.taskId}|${log.id}';
|
||||
}
|
||||
|
||||
// The UI displays time as "MMM dd, yyyy hh:mm AA". Grouping by year, month,
|
||||
// day, hour, and minute ensures we collapse duplicates that look identical on screen.
|
||||
final visualMinute =
|
||||
@@ -610,6 +616,92 @@ class TasksController {
|
||||
// SupabaseClient instance.
|
||||
final dynamic _client;
|
||||
|
||||
Future<bool> _isTaskCurrentlyPaused(String taskId) async {
|
||||
try {
|
||||
final rows = await _client
|
||||
.from('task_activity_logs')
|
||||
.select('action_type, created_at')
|
||||
.eq('task_id', taskId)
|
||||
.inFilter('action_type', [
|
||||
'started',
|
||||
'paused',
|
||||
'resumed',
|
||||
'completed',
|
||||
'cancelled',
|
||||
])
|
||||
.order('created_at', ascending: false)
|
||||
.limit(1);
|
||||
if (rows is List && rows.isNotEmpty) {
|
||||
final latest = rows.first;
|
||||
final action = latest['action_type']?.toString() ?? '';
|
||||
return action == 'paused';
|
||||
}
|
||||
} catch (_) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> pauseTask({required String taskId}) async {
|
||||
final row = await _client
|
||||
.from('tasks')
|
||||
.select('status')
|
||||
.eq('id', taskId)
|
||||
.maybeSingle();
|
||||
if (row is! Map<String, dynamic>) {
|
||||
throw Exception('Task not found');
|
||||
}
|
||||
|
||||
final status = (row['status'] as String?)?.trim() ?? '';
|
||||
if (status == 'completed' || status == 'cancelled' || status == 'closed') {
|
||||
throw Exception('Cannot pause a terminal task.');
|
||||
}
|
||||
if (status != 'in_progress') {
|
||||
throw Exception('Only in-progress tasks can be paused.');
|
||||
}
|
||||
|
||||
final alreadyPaused = await _isTaskCurrentlyPaused(taskId);
|
||||
if (alreadyPaused) {
|
||||
return;
|
||||
}
|
||||
|
||||
final actorId = _client.auth.currentUser?.id;
|
||||
await _insertActivityRows(_client, {
|
||||
'task_id': taskId,
|
||||
'actor_id': actorId,
|
||||
'action_type': 'paused',
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> resumeTask({required String taskId}) async {
|
||||
final row = await _client
|
||||
.from('tasks')
|
||||
.select('status')
|
||||
.eq('id', taskId)
|
||||
.maybeSingle();
|
||||
if (row is! Map<String, dynamic>) {
|
||||
throw Exception('Task not found');
|
||||
}
|
||||
|
||||
final status = (row['status'] as String?)?.trim() ?? '';
|
||||
if (status == 'completed' || status == 'cancelled' || status == 'closed') {
|
||||
throw Exception('Cannot resume a terminal task.');
|
||||
}
|
||||
if (status != 'in_progress') {
|
||||
throw Exception('Only in-progress tasks can be resumed.');
|
||||
}
|
||||
|
||||
final isPaused = await _isTaskCurrentlyPaused(taskId);
|
||||
if (!isPaused) {
|
||||
return;
|
||||
}
|
||||
|
||||
final actorId = _client.auth.currentUser?.id;
|
||||
await _insertActivityRows(_client, {
|
||||
'task_id': taskId,
|
||||
'actor_id': actorId,
|
||||
'action_type': 'resumed',
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> createTask({
|
||||
required String title,
|
||||
required String description,
|
||||
|
||||
Reference in New Issue
Block a user