Added validation when task type, category, signatories and action taken are empty upon completing a task
This commit is contained in:
@@ -556,22 +556,56 @@ class TasksController {
|
||||
required String status,
|
||||
}) async {
|
||||
if (status == 'completed') {
|
||||
// fetch current metadata to validate
|
||||
// fetch current metadata to validate several required fields
|
||||
try {
|
||||
final row = await _client
|
||||
.from('tasks')
|
||||
.select('request_type, request_category')
|
||||
// include all columns that must be non-null/empty before completing
|
||||
.select(
|
||||
'request_type, request_category, requested_by, noted_by, received_by, action_taken',
|
||||
)
|
||||
.eq('id', taskId)
|
||||
.maybeSingle();
|
||||
final rt = row is Map ? row['request_type'] : null;
|
||||
final rc = row is Map ? row['request_category'] : null;
|
||||
if (rt == null || rc == null) {
|
||||
if (row is! Map<String, dynamic>) {
|
||||
throw Exception('Task not found');
|
||||
}
|
||||
|
||||
final rt = row['request_type'];
|
||||
final rc = row['request_category'];
|
||||
final requested = row['requested_by'];
|
||||
final noted = row['noted_by'];
|
||||
final received = row['received_by'];
|
||||
final action = row['action_taken'];
|
||||
|
||||
final missing = <String>[];
|
||||
if (rt == null || (rt is String && rt.trim().isEmpty)) {
|
||||
missing.add('request type');
|
||||
}
|
||||
if (rc == null || (rc is String && rc.trim().isEmpty)) {
|
||||
missing.add('request category');
|
||||
}
|
||||
if (requested == null ||
|
||||
(requested is String && requested.trim().isEmpty)) {
|
||||
missing.add('requested by');
|
||||
}
|
||||
if (noted == null || (noted is String && noted.trim().isEmpty)) {
|
||||
missing.add('noted by');
|
||||
}
|
||||
if (received == null ||
|
||||
(received is String && received.trim().isEmpty)) {
|
||||
missing.add('received by');
|
||||
}
|
||||
if (action == null || (action is String && action.trim().isEmpty)) {
|
||||
missing.add('action taken');
|
||||
}
|
||||
|
||||
if (missing.isNotEmpty) {
|
||||
throw Exception(
|
||||
'Request type and category must be set before completing a task.',
|
||||
'The following fields must be set before completing a task: ${missing.join(', ')}.',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
// rethrow so callers can handle
|
||||
// rethrow so callers can handle (UI will display message)
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2731,9 +2731,16 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
|
||||
// Update DB only — Supabase realtime stream will emit the
|
||||
// updated task list, so explicit invalidation here causes a
|
||||
// visible loading/refresh and is unnecessary.
|
||||
await ref
|
||||
.read(tasksControllerProvider)
|
||||
.updateTaskStatus(taskId: task.id, status: value);
|
||||
try {
|
||||
await ref
|
||||
.read(tasksControllerProvider)
|
||||
.updateTaskStatus(taskId: task.id, status: value);
|
||||
} catch (e) {
|
||||
// surface validation or other errors to user
|
||||
if (mounted) {
|
||||
showErrorSnackBar(context, e.toString());
|
||||
}
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => _statusOptions
|
||||
.map(
|
||||
|
||||
Reference in New Issue
Block a user