UI: Cyber/IT design overhaul with semantic status tokens (Material 3)
Re-theme TasQ with a refined enterprise "Cyber/IT" identity on Material 3. Functionality is unchanged — only color/shape tokens and a few state widgets. Foundation: - Hand-tuned light + dark ColorSchemes (deep-slate surfaces, azure/teal/violet accents), tightened 12-16dp shape language, flat hairline-outlined cards. - New AppStatusColors theme extension (success/warning/danger/info/neutral, per-brightness) replacing scattered raw Colors.green/orange/red/grey so status color is consistent and legible in dark mode. - New TechChip mono primitive; StatusPill.kind; M3Card hairline variants; tightened AppSurfaces radii. Per-screen: - Tokenized status colors + radii across dashboard, tickets, tasks, IT service requests, attendance, whereabouts, network map, reports charts, auth, and shared/admin screens. Added _ticketStatusKind/_taskStatusKind/_isrStatusKind mappers so status carries meaning consistently. - Fixed white pie-slice borders for dark mode; dropped ad-hoc dialog radius overrides in favor of the theme default. Categorical palettes (leave-type icons, team color picker, distribution charts) intentionally preserved. Verified: flutter analyze lib clean; flutter build web green; visual QA in light and dark (dashboard, tickets, attendance). Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -35,6 +35,7 @@ import 'logbook_day_activity.dart';
|
||||
import 'work_log_tab.dart';
|
||||
import '../../theme/m3_motion.dart';
|
||||
import '../../theme/app_surfaces.dart';
|
||||
import '../../theme/app_status_colors.dart';
|
||||
import '../../utils/app_time.dart';
|
||||
import '../../utils/device_security.dart';
|
||||
import '../../utils/location_permission.dart';
|
||||
@@ -787,7 +788,7 @@ class _CheckInTabState extends ConsumerState<_CheckInTab> {
|
||||
} else if (diff.inMinutes <= 5) {
|
||||
timeColor = colors.error;
|
||||
} else if (diff.inMinutes <= 15) {
|
||||
timeColor = Colors.orange;
|
||||
timeColor = AppStatusColors.of(context).warning.color;
|
||||
} else if (diff.inMinutes <= 30) {
|
||||
timeColor = colors.tertiary;
|
||||
}
|
||||
@@ -847,7 +848,7 @@ class _CheckInTabState extends ConsumerState<_CheckInTab> {
|
||||
: Icons.cancel,
|
||||
size: 16,
|
||||
color: _insideGeofence || hasGeofenceOverride
|
||||
? Colors.green
|
||||
? AppStatusColors.of(context).success.color
|
||||
: colors.error,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
@@ -859,7 +860,7 @@ class _CheckInTabState extends ConsumerState<_CheckInTab> {
|
||||
: 'Outside geofence',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: _insideGeofence || hasGeofenceOverride
|
||||
? Colors.green
|
||||
? AppStatusColors.of(context).success.color
|
||||
: colors.error,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -1863,11 +1864,11 @@ class _CheckInTabState extends ConsumerState<_CheckInTab> {
|
||||
bg = colors.secondaryContainer;
|
||||
fg = colors.onSecondaryContainer;
|
||||
case 'Early Out':
|
||||
bg = Colors.orange.shade100;
|
||||
fg = Colors.orange.shade900;
|
||||
bg = AppStatusColors.of(context).warning.container;
|
||||
fg = AppStatusColors.of(context).warning.onContainer;
|
||||
case 'Noon Break':
|
||||
bg = Colors.blue.shade100;
|
||||
fg = Colors.blue.shade900;
|
||||
bg = AppStatusColors.of(context).info.container;
|
||||
fg = AppStatusColors.of(context).info.onContainer;
|
||||
case 'Absent':
|
||||
bg = colors.errorContainer;
|
||||
fg = colors.onErrorContainer;
|
||||
@@ -2841,13 +2842,14 @@ class _DateGroupTile extends StatelessWidget {
|
||||
final colors = Theme.of(context).colorScheme;
|
||||
final textTheme = Theme.of(context).textTheme;
|
||||
|
||||
final status = AppStatusColors.of(context);
|
||||
final statusColor = group.status == 'Absent'
|
||||
? Colors.red
|
||||
? status.danger.color
|
||||
: group.status == 'On duty'
|
||||
? Colors.orange
|
||||
? status.warning.color
|
||||
: group.status == 'On Leave'
|
||||
? Colors.teal
|
||||
: Colors.green;
|
||||
? status.info.color
|
||||
: status.success.color;
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.fromLTRB(12, 8, 12, 0),
|
||||
@@ -2960,10 +2962,10 @@ class _DateGroupTile extends StatelessWidget {
|
||||
String statusLabel;
|
||||
switch (slip.status) {
|
||||
case 'approved':
|
||||
statusColor = Colors.green;
|
||||
statusColor = AppStatusColors.of(context).success.color;
|
||||
statusLabel = 'Approved';
|
||||
case 'pending':
|
||||
statusColor = Colors.orange;
|
||||
statusColor = AppStatusColors.of(context).warning.color;
|
||||
statusLabel = 'Pending';
|
||||
case 'rejected':
|
||||
statusColor = colors.error;
|
||||
@@ -3081,7 +3083,7 @@ class _DateGroupTile extends StatelessWidget {
|
||||
? Chip(
|
||||
label: Text(entry.isLeave ? 'On Leave' : 'Absent'),
|
||||
backgroundColor: entry.isLeave
|
||||
? Colors.teal.withValues(alpha: 0.15)
|
||||
? AppStatusColors.of(context).info.container
|
||||
: colors.errorContainer,
|
||||
)
|
||||
: entry.status == 'On duty'
|
||||
@@ -3107,7 +3109,7 @@ class _DateGroupTile extends StatelessWidget {
|
||||
switch (entry.verificationStatus) {
|
||||
case 'verified':
|
||||
icon = Icons.verified;
|
||||
color = Colors.green;
|
||||
color = AppStatusColors.of(context).success.color;
|
||||
tooltip = 'Verified';
|
||||
case 'unverified' || 'skipped':
|
||||
icon = Icons.warning_amber_rounded;
|
||||
@@ -3115,7 +3117,7 @@ class _DateGroupTile extends StatelessWidget {
|
||||
tooltip = 'Unverified';
|
||||
default:
|
||||
icon = Icons.hourglass_bottom;
|
||||
color = Colors.orange;
|
||||
color = AppStatusColors.of(context).warning.color;
|
||||
tooltip = 'Pending';
|
||||
}
|
||||
final badge = Tooltip(
|
||||
@@ -3526,7 +3528,7 @@ class _CheckInOutMapTab extends StatelessWidget {
|
||||
title: 'Check In',
|
||||
lat: entry.checkInLat,
|
||||
lng: entry.checkInLng,
|
||||
markerColor: Colors.green,
|
||||
markerColor: AppStatusColors.of(context).success.color,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
@@ -3536,7 +3538,7 @@ class _CheckInOutMapTab extends StatelessWidget {
|
||||
title: 'Check Out',
|
||||
lat: entry.checkOutLat,
|
||||
lng: entry.checkOutLng,
|
||||
markerColor: Colors.red,
|
||||
markerColor: AppStatusColors.of(context).danger.color,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -5830,7 +5832,7 @@ class _PassSlipTabState extends ConsumerState<_PassSlipTab> {
|
||||
IconData statusIcon;
|
||||
switch (slip.status) {
|
||||
case 'approved':
|
||||
statusColor = Colors.green;
|
||||
statusColor = AppStatusColors.of(context).success.color;
|
||||
statusIcon = Icons.check_circle;
|
||||
case 'rejected':
|
||||
statusColor = colors.error;
|
||||
@@ -5839,7 +5841,7 @@ class _PassSlipTabState extends ConsumerState<_PassSlipTab> {
|
||||
statusColor = colors.primary;
|
||||
statusIcon = Icons.task_alt;
|
||||
default:
|
||||
statusColor = Colors.orange;
|
||||
statusColor = AppStatusColors.of(context).warning.color;
|
||||
statusIcon = Icons.hourglass_top;
|
||||
}
|
||||
|
||||
@@ -6248,7 +6250,7 @@ class _LeaveTabState extends ConsumerState<_LeaveTab> {
|
||||
IconData statusIcon;
|
||||
switch (leave.status) {
|
||||
case 'approved':
|
||||
statusColor = Colors.teal;
|
||||
statusColor = AppStatusColors.of(context).success.color;
|
||||
statusIcon = Icons.check_circle;
|
||||
case 'rejected':
|
||||
statusColor = colors.error;
|
||||
@@ -6257,7 +6259,7 @@ class _LeaveTabState extends ConsumerState<_LeaveTab> {
|
||||
statusColor = colors.onSurfaceVariant;
|
||||
statusIcon = Icons.remove_circle_outline;
|
||||
default:
|
||||
statusColor = Colors.orange;
|
||||
statusColor = AppStatusColors.of(context).warning.color;
|
||||
statusIcon = Icons.hourglass_top;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user