A better state and alerts

This commit is contained in:
2026-02-23 20:19:07 +08:00
parent 0b900d3480
commit 1074572905
17 changed files with 673 additions and 428 deletions
+45 -23
View File
@@ -13,6 +13,7 @@ import '../../providers/profile_provider.dart';
import '../../providers/workforce_provider.dart';
import '../../widgets/responsive_body.dart';
import '../../theme/app_surfaces.dart';
import '../../utils/snackbar.dart';
class WorkforceScreen extends ConsumerWidget {
const WorkforceScreen({super.key});
@@ -438,7 +439,11 @@ class _ScheduleTile extends ConsumerWidget {
.where((profile) => profile.id != currentUserId)
.toList();
if (staff.isEmpty) {
_showMessage(context, 'No IT staff available for swaps.');
_showMessage(
context,
'No IT staff available for swaps.',
type: SnackType.warning,
);
return;
}
@@ -572,17 +577,36 @@ class _ScheduleTile extends ConsumerWidget {
);
ref.invalidate(swapRequestsProvider);
if (!context.mounted) return;
_showMessage(context, 'Swap request sent.');
_showMessage(context, 'Swap request sent.', type: SnackType.success);
} catch (error) {
if (!context.mounted) return;
_showMessage(context, 'Swap request failed: $error');
_showMessage(
context,
'Swap request failed: $error',
type: SnackType.error,
);
}
}
void _showMessage(BuildContext context, String message) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(message)));
void _showMessage(
BuildContext context,
String message, {
SnackType type = SnackType.warning,
}) {
switch (type) {
case SnackType.success:
showSuccessSnackBar(context, message);
break;
case SnackType.error:
showErrorSnackBar(context, message);
break;
case SnackType.info:
showInfoSnackBar(context, message);
break;
case SnackType.warning:
showWarningSnackBar(context, message);
break;
}
}
Future<void> _showAlert(
@@ -647,7 +671,11 @@ class _ScheduleTile extends ConsumerWidget {
controller.animateTo(1);
return;
}
_showMessage(context, 'Swap request already sent. See Swaps panel.');
_showMessage(
context,
'Swap request already sent. See Swaps panel.',
type: SnackType.info,
);
}
String _statusLabel(String status) {
@@ -884,11 +912,11 @@ class _ScheduleGeneratorPanelState
final start = _startDate;
final end = _endDate;
if (start == null || end == null) {
_showMessage('Select a date range.');
showWarningSnackBar(context, 'Select a date range.');
return;
}
if (end.isBefore(start)) {
_showMessage('End date must be after start date.');
showWarningSnackBar(context, 'End date must be after start date.');
return;
}
setState(() => _isGenerating = true);
@@ -896,7 +924,7 @@ class _ScheduleGeneratorPanelState
final staff = _sortedStaff();
if (staff.isEmpty) {
if (!mounted) return;
_showMessage('No IT staff available for scheduling.');
showWarningSnackBar(context, 'No IT staff available for scheduling.');
return;
}
@@ -919,7 +947,7 @@ class _ScheduleGeneratorPanelState
});
if (generated.isEmpty) {
_showMessage('No shifts could be generated.');
showInfoSnackBar(context, 'No shifts could be generated.');
}
} finally {
if (mounted) {
@@ -1099,7 +1127,7 @@ class _ScheduleGeneratorPanelState
Future<void> _openDraftEditor({_DraftSchedule? existing}) async {
final staff = _sortedStaff();
if (staff.isEmpty) {
_showMessage('No IT staff available.');
showWarningSnackBar(context, 'No IT staff available.');
return;
}
@@ -1305,14 +1333,14 @@ class _ScheduleGeneratorPanelState
final start = _startDate;
final end = _endDate;
if (start == null || end == null) {
_showMessage('Select a date range.');
showWarningSnackBar(context, 'Select a date range.');
return;
}
final schedules = ref.read(dutySchedulesProvider).valueOrNull ?? [];
final conflict = _findConflict(_draftSchedules, schedules);
if (conflict != null) {
_showMessage(conflict);
showInfoSnackBar(context, conflict);
return;
}
@@ -1334,14 +1362,14 @@ class _ScheduleGeneratorPanelState
await ref.read(workforceControllerProvider).insertSchedules(payload);
ref.invalidate(dutySchedulesProvider);
if (!mounted) return;
_showMessage('Schedule committed.');
showSuccessSnackBar(context, 'Schedule committed.');
setState(() {
_draftSchedules = [];
_warnings = [];
});
} catch (error) {
if (!mounted) return;
_showMessage('Commit failed: $error');
showErrorSnackBar(context, 'Commit failed: $error');
} finally {
if (mounted) {
setState(() => _isSaving = false);
@@ -1762,12 +1790,6 @@ class _ScheduleGeneratorPanelState
return value;
}
}
void _showMessage(String message) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(message)));
}
}
class _SwapRequestsPanel extends ConsumerWidget {