feat: Refine badge and status indicator styling across various client features, including updated colors, borders, and typography, and remove unused action buttons.

This commit is contained in:
Achintha Isuru
2026-02-23 12:14:28 -05:00
parent 7136aa7686
commit f453f8aadd
6 changed files with 218 additions and 258 deletions

View File

@@ -77,10 +77,11 @@ class _StatCard extends StatelessWidget {
return Container(
padding: const EdgeInsets.all(UiConstants.space3),
decoration: BoxDecoration(
color: UiColors.bgMenu,
color: color.withAlpha(10),
borderRadius: UiConstants.radiusLg,
border: Border.all(
color: UiColors.border,
color: color,
width: 0.75,
),
),
child: Column(

View File

@@ -1,11 +1,8 @@
import 'package:core_localization/core_localization.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:krow_domain/krow_domain.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../blocs/coverage_bloc.dart';
import '../blocs/coverage_event.dart';
import 'package:core_localization/core_localization.dart';
/// List of shifts with their workers.
///
@@ -235,19 +232,6 @@ class _ShiftHeader extends StatelessWidget {
total: total,
coveragePercent: coveragePercent,
),
if (current < total)
Padding(
padding: const EdgeInsets.only(left: UiConstants.space2),
child: UiButton.primary(
text: 'Repost',
size: UiButtonSize.small,
onPressed: () {
ReadContext(context).read<CoverageBloc>().add(
CoverageRepostShiftRequested(shiftId: shiftId),
);
},
),
),
],
),
);
@@ -278,14 +262,14 @@ class _CoverageBadge extends StatelessWidget {
Color text;
if (coveragePercent >= 100) {
bg = UiColors.textSuccess;
text = UiColors.primaryForeground;
bg = UiColors.textSuccess.withAlpha(40);
text = UiColors.textSuccess;
} else if (coveragePercent >= 80) {
bg = UiColors.textWarning;
text = UiColors.primaryForeground;
bg = UiColors.textWarning.withAlpha(40);
text = UiColors.textWarning;
} else {
bg = UiColors.destructive;
text = UiColors.destructiveForeground;
bg = UiColors.destructive.withAlpha(40);
text = UiColors.destructive;
}
return Container(
@@ -295,11 +279,12 @@ class _CoverageBadge extends StatelessWidget {
),
decoration: BoxDecoration(
color: bg,
borderRadius: UiConstants.radiusFull,
border: Border.all(color: text, width: 0.75),
borderRadius: UiConstants.radiusMd,
),
child: Text(
'$current/$total',
style: UiTypography.body3m.copyWith(
style: UiTypography.body3b.copyWith(
color: text,
),
),
@@ -335,92 +320,101 @@ class _WorkerRow extends StatelessWidget {
String statusText;
Color badgeBg;
Color badgeText;
Color badgeBorder;
String badgeLabel;
switch (worker.status) {
case CoverageWorkerStatus.checkedIn:
bg = UiColors.textSuccess.withOpacity(0.1);
bg = UiColors.textSuccess.withAlpha(26);
border = UiColors.textSuccess;
textBg = UiColors.textSuccess.withOpacity(0.2);
textBg = UiColors.textSuccess.withAlpha(51);
textColor = UiColors.textSuccess;
icon = UiIcons.success;
statusText = '✓ Checked In at ${formatTime(worker.checkInTime)}';
badgeBg = UiColors.textSuccess;
badgeText = UiColors.primaryForeground;
badgeBg = UiColors.textSuccess.withAlpha(40);
badgeText = UiColors.textSuccess;
badgeBorder = badgeText;
badgeLabel = 'On Site';
case CoverageWorkerStatus.confirmed:
if (worker.checkInTime == null) {
bg = UiColors.textWarning.withOpacity(0.1);
bg = UiColors.textWarning.withAlpha(26);
border = UiColors.textWarning;
textBg = UiColors.textWarning.withOpacity(0.2);
textBg = UiColors.textWarning.withAlpha(51);
textColor = UiColors.textWarning;
icon = UiIcons.clock;
statusText = 'En Route - Expected $shiftStartTime';
badgeBg = UiColors.textWarning;
badgeText = UiColors.primaryForeground;
badgeBg = UiColors.textWarning.withAlpha(40);
badgeText = UiColors.textWarning;
badgeBorder = badgeText;
badgeLabel = 'En Route';
} else {
bg = UiColors.muted.withOpacity(0.1);
bg = UiColors.muted.withAlpha(26);
border = UiColors.border;
textBg = UiColors.muted.withOpacity(0.2);
textBg = UiColors.muted.withAlpha(51);
textColor = UiColors.textSecondary;
icon = UiIcons.success;
statusText = 'Confirmed';
badgeBg = UiColors.muted;
badgeText = UiColors.textPrimary;
badgeBg = UiColors.textSecondary.withAlpha(40);
badgeText = UiColors.textSecondary;
badgeBorder = badgeText;
badgeLabel = 'Confirmed';
}
case CoverageWorkerStatus.late:
bg = UiColors.destructive.withOpacity(0.1);
bg = UiColors.destructive.withAlpha(26);
border = UiColors.destructive;
textBg = UiColors.destructive.withOpacity(0.2);
textBg = UiColors.destructive.withAlpha(51);
textColor = UiColors.destructive;
icon = UiIcons.warning;
statusText = '⚠ Running Late';
badgeBg = UiColors.destructive;
badgeText = UiColors.destructiveForeground;
badgeBg = UiColors.destructive.withAlpha(40);
badgeText = UiColors.destructive;
badgeBorder = badgeText;
badgeLabel = 'Late';
case CoverageWorkerStatus.checkedOut:
bg = UiColors.muted.withOpacity(0.1);
bg = UiColors.muted.withAlpha(26);
border = UiColors.border;
textBg = UiColors.muted.withOpacity(0.2);
textBg = UiColors.muted.withAlpha(51);
textColor = UiColors.textSecondary;
icon = UiIcons.success;
statusText = 'Checked Out';
badgeBg = UiColors.muted;
badgeText = UiColors.textPrimary;
badgeBg = UiColors.textSecondary.withAlpha(40);
badgeText = UiColors.textSecondary;
badgeBorder = badgeText;
badgeLabel = 'Done';
case CoverageWorkerStatus.noShow:
bg = UiColors.destructive.withOpacity(0.1);
bg = UiColors.destructive.withAlpha(26);
border = UiColors.destructive;
textBg = UiColors.destructive.withOpacity(0.2);
textBg = UiColors.destructive.withAlpha(51);
textColor = UiColors.destructive;
icon = UiIcons.warning;
statusText = 'No Show';
badgeBg = UiColors.destructive;
badgeText = UiColors.destructiveForeground;
badgeBg = UiColors.destructive.withAlpha(40);
badgeText = UiColors.destructive;
badgeBorder = badgeText;
badgeLabel = 'No Show';
case CoverageWorkerStatus.completed:
bg = UiColors.textSuccess.withOpacity(0.1);
border = UiColors.textSuccess;
textBg = UiColors.textSuccess.withOpacity(0.2);
bg = UiColors.iconSuccess.withAlpha(26);
border = UiColors.iconSuccess;
textBg = UiColors.iconSuccess.withAlpha(51);
textColor = UiColors.textSuccess;
icon = UiIcons.success;
statusText = 'Completed';
badgeBg = UiColors.textSuccess;
badgeText = UiColors.primaryForeground;
badgeBg = UiColors.textSuccess.withAlpha(40);
badgeText = UiColors.textSuccess;
badgeBorder = badgeText;
badgeLabel = 'Completed';
case CoverageWorkerStatus.pending:
case CoverageWorkerStatus.accepted:
case CoverageWorkerStatus.rejected:
bg = UiColors.muted.withOpacity(0.1);
bg = UiColors.muted.withAlpha(26);
border = UiColors.border;
textBg = UiColors.muted.withOpacity(0.2);
textBg = UiColors.muted.withAlpha(51);
textColor = UiColors.textSecondary;
icon = UiIcons.clock;
statusText = worker.status.name.toUpperCase();
badgeBg = UiColors.muted;
badgeText = UiColors.textPrimary;
badgeBg = UiColors.textSecondary.withAlpha(40);
badgeText = UiColors.textSecondary;
badgeBorder = badgeText;
badgeLabel = worker.status.name[0].toUpperCase() +
worker.status.name.substring(1);
}
@@ -493,40 +487,42 @@ class _WorkerRow extends StatelessWidget {
),
),
Column(
spacing: UiConstants.space2,
children: [
Container(
padding: const EdgeInsets.symmetric(
horizontal: UiConstants.space2,
vertical: UiConstants.space1 / 2,
),
decoration: BoxDecoration(
color: badgeBg,
borderRadius: UiConstants.radiusFull,
),
child: Text(
badgeLabel,
style: UiTypography.footnote2b.copyWith(
color: badgeText,
),
spacing: UiConstants.space2,
children: <Widget>[
Container(
padding: const EdgeInsets.symmetric(
horizontal: UiConstants.space2,
vertical: UiConstants.space1 / 2,
),
decoration: BoxDecoration(
color: badgeBg,
borderRadius: UiConstants.radiusMd,
border: Border.all(color: badgeBorder, width: 0.5),
),
child: Text(
badgeLabel,
style: UiTypography.footnote2b.copyWith(
color: badgeText,
),
),
if (worker.status == CoverageWorkerStatus.checkedIn)
UiButton.primary(
text: context.t.client_coverage.worker_row.verify,
size: UiButtonSize.small,
onPressed: () {
UiSnackbar.show(
context,
message: context.t.client_coverage.worker_row.verified_message(
name: worker.name,
),
type: UiSnackbarType.success,
);
},
),
],
),
),
if (worker.status == CoverageWorkerStatus.checkedIn)
UiButton.primary(
text: context.t.client_coverage.worker_row.verify,
size: UiButtonSize.small,
onPressed: () {
UiSnackbar.show(
context,
message:
context.t.client_coverage.worker_row.verified_message(
name: worker.name,
),
type: UiSnackbarType.success,
);
},
),
],
),
],
),
);