UI Phase 2: dogfood follow-ups — section headers, role terms, status semantics

Address the remaining concrete items flagged by the dogfood pass.

Section headers (→ AppSectionHeader, azure accent bar + uppercase):
- Attendance: "Today's Schedule", "Pass Slip History", and two "Pending
  Approvals" rows (were plain bold text / a manual tertiary accent bar).

User Management:
- Roles now display human-friendly labels (it_staff → "IT Staff", standard →
  "Standard", …) in the table cell, mobile tile and edit dropdown, instead of
  raw snake_case (Content/terminology consistency).
- _StatusBadge is now semantic via AppStatusColors: Active → success (green),
  Locked → danger (red), else neutral — previously everything was teal, so a
  Locked account read the same as an Active one.

Verified: flutter analyze lib clean; flutter build web green; visual QA
(Attendance, User Management) in dark.

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-09-26 16:44:39 +08:00
parent 6bde8630d8
commit 4685430406
2 changed files with 39 additions and 69 deletions
+12 -58
View File
@@ -36,6 +36,7 @@ import 'work_log_tab.dart';
import '../../theme/m3_motion.dart';
import '../../theme/app_surfaces.dart';
import '../../theme/app_status_colors.dart';
import '../../widgets/app_section_header.dart';
import '../../utils/app_time.dart';
import '../../utils/device_security.dart';
import '../../utils/location_permission.dart';
@@ -885,11 +886,9 @@ class _CheckInTabState extends ConsumerState<_CheckInTab> {
const SizedBox(height: 24),
// Today's schedule
Text(
const AppSectionHeader(
"Today's Schedule",
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
),
padding: EdgeInsets.zero,
),
const SizedBox(height: 8),
@@ -5704,24 +5703,9 @@ class _PassSlipTabState extends ConsumerState<_PassSlipTab> {
// Pending slips for admin approval
if (isAdmin) ...[
Row(
children: [
Container(
width: 4,
height: 20,
decoration: BoxDecoration(
color: colors.tertiary,
borderRadius: BorderRadius.circular(2),
),
),
const SizedBox(width: 10),
Text(
'Pending Approvals',
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
),
),
],
const AppSectionHeader(
'Pending Approvals',
padding: EdgeInsets.zero,
),
const SizedBox(height: 8),
for (int i = 0; i < pendingSlipList.length; i++)
@@ -5755,24 +5739,9 @@ class _PassSlipTabState extends ConsumerState<_PassSlipTab> {
],
// History
Row(
children: [
Container(
width: 4,
height: 20,
decoration: BoxDecoration(
color: colors.outlineVariant,
borderRadius: BorderRadius.circular(2),
),
),
const SizedBox(width: 10),
Text(
'Pass Slip History',
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
),
),
],
const AppSectionHeader(
'Pass Slip History',
padding: EdgeInsets.zero,
),
const SizedBox(height: 8),
for (int i = 0; i < historySlipList.length; i++)
@@ -6069,24 +6038,9 @@ class _LeaveTabState extends ConsumerState<_LeaveTab> {
children: [
// ── Pending Approvals (admin only) ──
if (isAdmin) ...[
Row(
children: [
Container(
width: 4,
height: 20,
decoration: BoxDecoration(
color: colors.tertiary,
borderRadius: BorderRadius.circular(2),
),
),
const SizedBox(width: 10),
Text(
'Pending Approvals',
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
),
),
],
const AppSectionHeader(
'Pending Approvals',
padding: EdgeInsets.zero,
),
const SizedBox(height: 8),
if (pendingApprovals.isEmpty)