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:
@@ -12,6 +12,7 @@ import '../../providers/profile_provider.dart';
|
||||
import '../../providers/whereabouts_provider.dart';
|
||||
import '../../providers/workforce_provider.dart';
|
||||
import '../../theme/app_surfaces.dart';
|
||||
import '../../theme/app_status_colors.dart';
|
||||
import '../../widgets/app_page_header.dart';
|
||||
import '../../widgets/responsive_body.dart';
|
||||
import '../../utils/app_time.dart';
|
||||
@@ -232,8 +233,10 @@ class _WhereaboutsMap extends StatelessWidget {
|
||||
polygons: [
|
||||
Polygon(
|
||||
points: points,
|
||||
color: Colors.blue.withValues(alpha: 0.1),
|
||||
borderColor: Colors.blue,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.primary.withValues(alpha: 0.12),
|
||||
borderColor: Theme.of(context).colorScheme.primary,
|
||||
borderStrokeWidth: 2.0,
|
||||
),
|
||||
],
|
||||
@@ -313,11 +316,20 @@ class _StaffLegendPanel extends StatelessWidget {
|
||||
).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w700),
|
||||
),
|
||||
const Spacer(),
|
||||
_RoleBadge(color: Colors.blue.shade700, label: 'Admin'),
|
||||
_RoleBadge(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
label: 'Admin',
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
_RoleBadge(color: Colors.green.shade700, label: 'IT Staff'),
|
||||
_RoleBadge(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
label: 'IT Staff',
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
_RoleBadge(color: Colors.orange.shade700, label: 'Dispatcher'),
|
||||
_RoleBadge(
|
||||
color: Theme.of(context).colorScheme.tertiary,
|
||||
label: 'Dispatcher',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -416,6 +428,7 @@ class _StaffLegendTile extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
final status = AppStatusColors.of(context);
|
||||
final roleColor = _roleColor(profile.role, cs);
|
||||
|
||||
final hasPosition = position != null;
|
||||
@@ -445,30 +458,30 @@ class _StaffLegendTile extends StatelessWidget {
|
||||
? 'In premise (Tracking off) \u00b7 $timeLabel'
|
||||
: 'Outside premise (Tracking off) \u00b7 $timeLabel';
|
||||
statusColor = isStale
|
||||
? Colors.grey
|
||||
: (isInPremise ? Colors.green : Colors.grey);
|
||||
? status.neutral.color
|
||||
: (isInPremise ? status.success.color : status.neutral.color);
|
||||
} else if (inferredInPremise) {
|
||||
statusText = 'In premise (Checked in)';
|
||||
statusColor = Colors.green;
|
||||
statusColor = status.success.color;
|
||||
} else {
|
||||
statusText = 'Tracking off';
|
||||
statusColor = Colors.grey;
|
||||
statusColor = status.neutral.color;
|
||||
}
|
||||
} else if (isStale && hasPosition) {
|
||||
final timeLabel = _timeAgo(position!.updatedAt);
|
||||
statusText = isInPremise
|
||||
? 'Last seen in premise \u00b7 $timeLabel'
|
||||
: 'Last seen outside premise \u00b7 $timeLabel';
|
||||
statusColor = Colors.grey;
|
||||
statusColor = status.neutral.color;
|
||||
} else if (isActive) {
|
||||
statusText = 'In premise \u00b7 ${_timeAgo(position!.updatedAt)}';
|
||||
statusColor = Colors.green;
|
||||
statusColor = status.success.color;
|
||||
} else if (hasPosition) {
|
||||
statusText = 'Outside premise \u00b7 ${_timeAgo(position!.updatedAt)}';
|
||||
statusColor = Colors.grey;
|
||||
statusColor = status.neutral.color;
|
||||
} else {
|
||||
statusText = 'No location data';
|
||||
statusColor = Colors.grey;
|
||||
statusColor = status.neutral.color;
|
||||
}
|
||||
|
||||
final IconData statusIcon;
|
||||
|
||||
Reference in New Issue
Block a user