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:
@@ -13,6 +13,8 @@ import '../../providers/teams_provider.dart';
|
||||
import '../../utils/app_time.dart';
|
||||
import '../../utils/snackbar.dart';
|
||||
import '../../widgets/app_breakpoints.dart';
|
||||
import '../../theme/app_status_colors.dart';
|
||||
import '../../theme/app_surfaces.dart';
|
||||
import '../../widgets/m3_card.dart';
|
||||
import '../../widgets/mono_text.dart';
|
||||
import '../../widgets/profile_avatar.dart';
|
||||
@@ -231,24 +233,25 @@ class _ItJobChecklistTabState extends ConsumerState<ItJobChecklistTab> {
|
||||
}
|
||||
|
||||
Widget _buildSkeletonTile(BuildContext context, bool isWide) {
|
||||
final bone = Theme.of(context).colorScheme.surfaceContainerHighest;
|
||||
return M3Card.outlined(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(width: 60, height: 14, color: Colors.grey),
|
||||
Container(width: 60, height: 14, color: bone),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Container(height: 14, color: Colors.grey),
|
||||
child: Container(height: 14, color: bone),
|
||||
),
|
||||
if (isWide) ...[
|
||||
const SizedBox(width: 12),
|
||||
Container(width: 80, height: 22, color: Colors.grey),
|
||||
Container(width: 80, height: 22, color: bone),
|
||||
const SizedBox(width: 12),
|
||||
Container(width: 120, height: 14, color: Colors.grey),
|
||||
Container(width: 120, height: 14, color: bone),
|
||||
],
|
||||
const SizedBox(width: 12),
|
||||
Container(width: 24, height: 24, color: Colors.grey),
|
||||
Container(width: 24, height: 24, color: bone),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -292,20 +295,21 @@ class _StatsCard extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
|
||||
final status = AppStatusColors.of(context);
|
||||
final submittedChip = _StatChip(
|
||||
icon: Icons.check_circle_outline,
|
||||
label: 'Submitted',
|
||||
count: submitted,
|
||||
color: cs.primary,
|
||||
bgColor: cs.primaryContainer,
|
||||
color: status.success.onContainer,
|
||||
bgColor: status.success.container,
|
||||
);
|
||||
|
||||
final pendingChip = _StatChip(
|
||||
icon: Icons.pending_outlined,
|
||||
label: 'Pending',
|
||||
count: pending,
|
||||
color: cs.tertiary,
|
||||
bgColor: cs.tertiaryContainer,
|
||||
color: status.warning.onContainer,
|
||||
bgColor: status.warning.container,
|
||||
);
|
||||
|
||||
return M3Card.filled(
|
||||
@@ -399,7 +403,7 @@ class _StatChip extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: bgColor,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
borderRadius: BorderRadius.circular(AppSurfaces.of(context).chipRadius),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -878,11 +882,14 @@ class _ItJobTileState extends ConsumerState<_ItJobTile> {
|
||||
_isChecked ? cs.primaryContainer.withValues(alpha: 0.18) : null;
|
||||
|
||||
// Status badge
|
||||
final statusSwatch = _isChecked
|
||||
? AppStatusColors.of(context).success
|
||||
: AppStatusColors.of(context).warning;
|
||||
final statusBadge = Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: _isChecked ? cs.primaryContainer : cs.tertiaryContainer,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: statusSwatch.container,
|
||||
borderRadius: BorderRadius.circular(AppSurfaces.of(context).chipRadius),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -892,13 +899,13 @@ class _ItJobTileState extends ConsumerState<_ItJobTile> {
|
||||
? Icons.check_circle_outline
|
||||
: Icons.hourglass_empty_outlined,
|
||||
size: 12,
|
||||
color: _isChecked ? cs.primary : cs.tertiary,
|
||||
color: statusSwatch.onContainer,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
_isChecked ? 'Submitted' : 'Pending',
|
||||
style: tt.labelSmall?.copyWith(
|
||||
color: _isChecked ? cs.primary : cs.tertiary,
|
||||
color: statusSwatch.onContainer,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user