Added cancel details in activity logs as well as used icons

This commit is contained in:
Marc Rejohn Castillano 2026-02-28 18:08:45 +08:00
parent e99b87bd20
commit 97d9e83f17

View File

@ -2227,7 +2227,14 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
: (profileById[l.actorId]?.fullName ?? l.actorId!); : (profileById[l.actorId]?.fullName ?? l.actorId!);
switch (l.actionType) { switch (l.actionType) {
case 'created': case 'created':
timeline.add(_activityRow('Task created', actorName, l.createdAt)); timeline.add(
_activityRow(
'Task created',
actorName,
l.createdAt,
icon: Icons.add_task,
),
);
break; break;
case 'assigned': case 'assigned':
final meta = l.meta ?? {}; final meta = l.meta ?? {};
@ -2241,6 +2248,7 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
auto ? 'Auto-assigned to $name' : 'Assigned to $name', auto ? 'Auto-assigned to $name' : 'Assigned to $name',
actorName, actorName,
l.createdAt, l.createdAt,
icon: Icons.person_add,
), ),
); );
break; break;
@ -2252,7 +2260,12 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
.map((id) => profileById[id]?.fullName ?? id) .map((id) => profileById[id]?.fullName ?? id)
.join(', '); .join(', ');
timeline.add( timeline.add(
_activityRow('Reassigned to $toNames', actorName, l.createdAt), _activityRow(
'Reassigned to $toNames',
actorName,
l.createdAt,
icon: Icons.swap_horiz,
),
); );
break; break;
case 'started': case 'started':
@ -2268,7 +2281,14 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
label = label =
'Task started — Response: ${_formatDuration(responseDuration)} ($assigneeName responded at ${AppTime.formatDate(resp)} ${AppTime.formatTime(resp)})'; 'Task started — Response: ${_formatDuration(responseDuration)} ($assigneeName responded at ${AppTime.formatDate(resp)} ${AppTime.formatTime(resp)})';
} }
timeline.add(_activityRow(label, actorName, l.createdAt)); timeline.add(
_activityRow(
label,
actorName,
l.createdAt,
icon: Icons.play_arrow,
),
);
} }
break; break;
case 'completed': case 'completed':
@ -2283,15 +2303,69 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
'Task completed — Execution: ${_formatDuration(exec)} (${AppTime.formatDate(start)} ${AppTime.formatTime(start)}${AppTime.formatDate(end)} ${AppTime.formatTime(end)})'; 'Task completed — Execution: ${_formatDuration(exec)} (${AppTime.formatDate(start)} ${AppTime.formatTime(start)}${AppTime.formatDate(end)} ${AppTime.formatTime(end)})';
} }
} }
timeline.add(_activityRow(label, actorName, l.createdAt)); timeline.add(
_activityRow(
label,
actorName,
l.createdAt,
icon: Icons.check_circle,
),
);
} }
break; break;
case 'cancelled':
final meta = l.meta ?? {};
final reason = (meta['reason'] as String?) ?? '';
final base = reason.isNotEmpty
? 'Task cancelled — $reason'
: 'Task cancelled';
timeline.add(
_activityRow(base, actorName, l.createdAt, icon: Icons.cancel),
);
break;
default: default:
timeline.add(_activityRow(l.actionType, actorName, l.createdAt)); timeline.add(
_activityRow(
l.actionType,
actorName,
l.createdAt,
icon: Icons.info,
),
);
} }
} }
} }
// If the task is cancelled but no explicit cancelled activity row exists,
// show a fallback using the task's cancellation fields.
final hasCancelledLog = logs.any((e) => e.actionType == 'cancelled');
if (task.status == 'cancelled' && !hasCancelledLog) {
final reason = task.cancellationReason;
final at = task.cancelledAt ?? AppTime.now();
String inferredActor = 'System';
try {
final candidates = logs
.where((e) => e.actorId != null && e.createdAt.isBefore(at))
.toList();
if (candidates.isNotEmpty) {
candidates.sort((a, b) => a.createdAt.compareTo(b.createdAt));
final last = candidates.last;
inferredActor = profileById[last.actorId]?.fullName ?? last.actorId!;
}
} catch (_) {}
timeline.add(
_activityRow(
reason != null && reason.isNotEmpty
? 'Task cancelled — $reason'
: 'Task cancelled',
inferredActor,
at,
icon: Icons.cancel,
),
);
}
// Response and execution times are now merged into the related // Response and execution times are now merged into the related
// 'Task started' and 'Task completed' timeline entries above. // 'Task started' and 'Task completed' timeline entries above.
@ -2305,17 +2379,18 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
// TAT helpers removed; timings are shown inline in the activity timeline. // TAT helpers removed; timings are shown inline in the activity timeline.
Widget _activityRow(String title, String actor, DateTime at) { Widget _activityRow(
String title,
String actor,
DateTime at, {
IconData icon = Icons.circle,
}) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 8), padding: const EdgeInsets.symmetric(vertical: 8),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Icon( Icon(icon, size: 16, color: Theme.of(context).colorScheme.primary),
Icons.circle,
size: 12,
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(width: 8), const SizedBox(width: 8),
Expanded( Expanded(
child: Column( child: Column(