Standardize UI to design system tokens
Refactor multiple UI components to use design system tokens and primitives. Added new UiIcons (coffee, wifi, xCircle, ban) and typography color getters (primary, accent). Replaced hardcoded paddings, spacings, radii, borderRadius, and icon imports (lucide_icons -> UiIcons) with UiConstants, UiColors, UiTypography and UiIcons, and switched to UiColors.withValues for opacity. Changes apply across authentication, availability, clock_in (and its widgets), commute tracker, lunch break modal, location map placeholder, attendance card, date selector, and related presentation files to improve visual consistency.
This commit is contained in:
@@ -1,22 +1,21 @@
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart' hide ReadContext;
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
|
||||
import '../blocs/profile_cubit.dart';
|
||||
import '../blocs/profile_state.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
import '../widgets/language_selector_bottom_sheet.dart';
|
||||
import '../widgets/logout_button.dart';
|
||||
import '../widgets/profile_header.dart';
|
||||
import '../widgets/profile_menu_grid.dart';
|
||||
import '../widgets/profile_menu_item.dart';
|
||||
import '../widgets/profile_header.dart';
|
||||
import '../widgets/reliability_score_bar.dart';
|
||||
import '../widgets/reliability_stats_card.dart';
|
||||
import '../widgets/reliability_stats_card.dart';
|
||||
import '../widgets/section_title.dart';
|
||||
import '../widgets/language_selector_bottom_sheet.dart';
|
||||
|
||||
/// The main Staff Profile page.
|
||||
///
|
||||
@@ -68,17 +67,15 @@ class StaffProfilePage extends StatelessWidget {
|
||||
},
|
||||
builder: (context, state) {
|
||||
// Show loading spinner if status is loading
|
||||
if (state.status == ProfileStatus.loading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
if (state.status == ProfileStatus.loading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
if (state.status == ProfileStatus.error) {
|
||||
if (state.status == ProfileStatus.error) {
|
||||
return Center(
|
||||
child: Text(
|
||||
state.errorMessage ?? 'An error occurred',
|
||||
style: UiTypography.body1r.copyWith(
|
||||
color: UiColors.destructive,
|
||||
),
|
||||
style: UiTypography.body1r.textError,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -121,7 +118,6 @@ class StaffProfilePage extends StatelessWidget {
|
||||
SectionTitle(i18n.sections.onboarding),
|
||||
ProfileMenuGrid(
|
||||
crossAxisCount: 3,
|
||||
|
||||
children: [
|
||||
ProfileMenuItem(
|
||||
icon: UiIcons.user,
|
||||
@@ -181,18 +177,23 @@ class StaffProfilePage extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
SectionTitle(
|
||||
i18n.header.title.contains("Perfil") ? "Ajustes" : "Settings",
|
||||
i18n.header.title.contains("Perfil")
|
||||
? "Ajustes"
|
||||
: "Settings",
|
||||
),
|
||||
ProfileMenuGrid(
|
||||
crossAxisCount: 3,
|
||||
children: [
|
||||
ProfileMenuItem(
|
||||
icon: UiIcons.globe,
|
||||
label: i18n.header.title.contains("Perfil") ? "Idioma" : "Language",
|
||||
label: i18n.header.title.contains("Perfil")
|
||||
? "Idioma"
|
||||
: "Language",
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) => const LanguageSelectorBottomSheet(),
|
||||
builder: (context) =>
|
||||
const LanguageSelectorBottomSheet(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
|
||||
/// A bottom sheet that allows the user to select their preferred language.
|
||||
@@ -15,10 +14,12 @@ class LanguageSelectorBottomSheet extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(UiConstants.space6),
|
||||
decoration: BoxDecoration(
|
||||
padding: const EdgeInsets.all(UiConstants.space6),
|
||||
decoration: const BoxDecoration(
|
||||
color: UiColors.background,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(UiConstants.radiusBase)),
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.circular(UiConstants.radiusBase),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -29,19 +30,19 @@ class LanguageSelectorBottomSheet extends StatelessWidget {
|
||||
style: UiTypography.headline4m,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: UiConstants.space6),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
_buildLanguageOption(
|
||||
context,
|
||||
label: 'English',
|
||||
locale: AppLocale.en,
|
||||
),
|
||||
SizedBox(height: UiConstants.space4),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
_buildLanguageOption(
|
||||
context,
|
||||
label: 'Español',
|
||||
locale: AppLocale.es,
|
||||
),
|
||||
SizedBox(height: UiConstants.space6),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -62,21 +63,23 @@ class LanguageSelectorBottomSheet extends StatelessWidget {
|
||||
onTap: () {
|
||||
// Dispatch the ChangeLocale event to the LocaleBloc
|
||||
Modular.get<LocaleBloc>().add(ChangeLocale(locale.flutterLocale));
|
||||
|
||||
|
||||
// Close the bottom sheet
|
||||
Navigator.pop(context);
|
||||
|
||||
|
||||
// Force a rebuild of the entire app to reflect locale change instantly if not handled by root widget
|
||||
// (Usually handled by BlocBuilder at the root, but this ensures settings are updated)
|
||||
},
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusMdValue),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space4,
|
||||
horizontal: UiConstants.space4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected ? UiColors.primary.withValues(alpha: 0.1) : UiColors.background,
|
||||
color: isSelected
|
||||
? UiColors.primary.withValues(alpha: 0.1)
|
||||
: UiColors.background,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusMdValue),
|
||||
border: Border.all(
|
||||
color: isSelected ? UiColors.primary : UiColors.border,
|
||||
@@ -88,12 +91,10 @@ class LanguageSelectorBottomSheet extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: isSelected
|
||||
? UiTypography.body1b.copyWith(color: UiColors.primary)
|
||||
: UiTypography.body1r,
|
||||
style: isSelected ? UiTypography.body1b.primary : UiTypography.body1r,
|
||||
),
|
||||
if (isSelected)
|
||||
Icon(
|
||||
const Icon(
|
||||
UiIcons.check,
|
||||
color: UiColors.primary,
|
||||
size: 24.0,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// The sign-out button widget.
|
||||
///
|
||||
@@ -14,31 +13,33 @@ class LogoutButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final i18n = t.staff.profile.header;
|
||||
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
child: Material(
|
||||
color: const Color(0x00000000),
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: UiConstants.space4),
|
||||
padding: const EdgeInsets.symmetric(vertical: UiConstants.space4),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(LucideIcons.logOut, color: UiColors.destructive, size: 20),
|
||||
SizedBox(width: UiConstants.space2),
|
||||
const Icon(
|
||||
UiIcons.logOut,
|
||||
color: UiColors.destructive,
|
||||
size: 20,
|
||||
),
|
||||
const SizedBox(width: UiConstants.space2),
|
||||
Text(
|
||||
i18n.sign_out,
|
||||
style: UiTypography.body1m.copyWith(
|
||||
color: UiColors.destructive,
|
||||
),
|
||||
style: UiTypography.body1m.textError,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -34,13 +34,13 @@ class ProfileHeader extends StatelessWidget {
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
UiConstants.space5,
|
||||
UiConstants.space5,
|
||||
UiConstants.space5,
|
||||
UiConstants.space16,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
decoration: const BoxDecoration(
|
||||
color: UiColors.primary,
|
||||
borderRadius: BorderRadius.vertical(
|
||||
bottom: Radius.circular(UiConstants.space6),
|
||||
@@ -56,22 +56,20 @@ class ProfileHeader extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
i18n.title,
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.primaryForeground,
|
||||
),
|
||||
style: UiTypography.headline4m.textSecondary,
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: onSignOutTap,
|
||||
child: Text(
|
||||
i18n.sign_out,
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.primaryForeground.withOpacity(0.8),
|
||||
color: UiColors.primaryForeground.withValues(alpha: 0.8),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: UiConstants.space8),
|
||||
const SizedBox(height: UiConstants.space8),
|
||||
// Avatar Section
|
||||
Stack(
|
||||
alignment: Alignment.bottomRight,
|
||||
@@ -79,7 +77,7 @@ class ProfileHeader extends StatelessWidget {
|
||||
Container(
|
||||
width: 112,
|
||||
height: 112,
|
||||
padding: EdgeInsets.all(UiConstants.space1),
|
||||
padding: const EdgeInsets.all(UiConstants.space1),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: LinearGradient(
|
||||
@@ -87,13 +85,13 @@ class ProfileHeader extends StatelessWidget {
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
UiColors.accent,
|
||||
UiColors.accent.withOpacity(0.5),
|
||||
UiColors.accent.withValues(alpha: 0.5),
|
||||
UiColors.primaryForeground,
|
||||
],
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: UiColors.foreground.withOpacity(0.2),
|
||||
color: UiColors.foreground.withValues(alpha: 0.2),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
@@ -103,7 +101,7 @@ class ProfileHeader extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: UiColors.primaryForeground.withOpacity(0.2),
|
||||
color: UiColors.primaryForeground.withValues(alpha: 0.2),
|
||||
width: 4,
|
||||
),
|
||||
),
|
||||
@@ -123,16 +121,16 @@ class ProfileHeader extends StatelessWidget {
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
UiColors.accent,
|
||||
UiColors.accent.withOpacity(0.7),
|
||||
UiColors.accent.withValues(alpha: 0.7),
|
||||
],
|
||||
),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
fullName.isNotEmpty ? fullName[0].toUpperCase() : 'K',
|
||||
style: UiTypography.displayM.copyWith(
|
||||
color: UiColors.primary,
|
||||
),
|
||||
fullName.isNotEmpty
|
||||
? fullName[0].toUpperCase()
|
||||
: 'K',
|
||||
style: UiTypography.displayM.primary,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
@@ -148,7 +146,7 @@ class ProfileHeader extends StatelessWidget {
|
||||
border: Border.all(color: UiColors.primary, width: 2),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: UiColors.foreground.withOpacity(0.1),
|
||||
color: UiColors.foreground.withValues(alpha: 0.1),
|
||||
blurRadius: 4,
|
||||
),
|
||||
],
|
||||
@@ -161,28 +159,24 @@ class ProfileHeader extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: UiConstants.space4),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
Text(
|
||||
fullName,
|
||||
style: UiTypography.headline3m.copyWith(
|
||||
color: UiColors.primaryForeground,
|
||||
),
|
||||
style: UiTypography.headline3m.textPlaceholder,
|
||||
),
|
||||
SizedBox(height: UiConstants.space1),
|
||||
const SizedBox(height: UiConstants.space1),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space3,
|
||||
vertical: UiConstants.space1,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.accent.withOpacity(0.2),
|
||||
color: UiColors.accent.withValues(alpha: 0.2),
|
||||
borderRadius: BorderRadius.circular(UiConstants.space5),
|
||||
),
|
||||
child: Text(
|
||||
level,
|
||||
style: UiTypography.footnote1b.copyWith(
|
||||
color: UiColors.accent,
|
||||
),
|
||||
style: UiTypography.footnote1b.accent,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -25,10 +25,10 @@ class ProfileMenuItem extends StatelessWidget {
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
padding: EdgeInsets.all(UiConstants.space2),
|
||||
padding: const EdgeInsets.all(UiConstants.space2),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1.0,
|
||||
child: Stack(
|
||||
@@ -42,24 +42,23 @@ class ProfileMenuItem extends StatelessWidget {
|
||||
width: 36,
|
||||
height: 36,
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.primary.withOpacity(0.08),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
color: UiColors.primary.withValues(alpha: 0.08),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Icon(icon, color: UiColors.primary, size: 20),
|
||||
),
|
||||
SizedBox(height: UiConstants.space1),
|
||||
const SizedBox(height: UiConstants.space1),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: UiConstants.space1),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space1,
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: UiTypography.footnote1m.copyWith(
|
||||
color: UiColors.foreground,
|
||||
height: 1.2,
|
||||
),
|
||||
style: UiTypography.footnote1m.textSecondary,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -76,16 +75,18 @@ class ProfileMenuItem extends StatelessWidget {
|
||||
shape: BoxShape.circle,
|
||||
color: completed!
|
||||
? UiColors.primary
|
||||
: UiColors.primary.withOpacity(0.1),
|
||||
: UiColors.primary.withValues(alpha: 0.1),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: completed!
|
||||
? const Icon(Icons.check, size: 10, color: UiColors.primaryForeground)
|
||||
? const Icon(
|
||||
UiIcons.check,
|
||||
size: 10,
|
||||
color: UiColors.primaryForeground,
|
||||
)
|
||||
: Text(
|
||||
"!",
|
||||
style: UiTypography.footnote2b.copyWith(
|
||||
color: UiColors.primary,
|
||||
),
|
||||
style: UiTypography.footnote2b.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -19,10 +19,10 @@ class ReliabilityScoreBar extends StatelessWidget {
|
||||
final score = (reliabilityScore ?? 0) / 100;
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.all(UiConstants.space4),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
color: UiColors.primary.withValues(alpha: 0.1),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -32,19 +32,15 @@ class ReliabilityScoreBar extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
i18n.title,
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.primary,
|
||||
),
|
||||
style: UiTypography.body2m.primary,
|
||||
),
|
||||
Text(
|
||||
"${reliabilityScore ?? 0}%",
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.primary,
|
||||
),
|
||||
style: UiTypography.headline4m.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: UiConstants.space2),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(UiConstants.space1),
|
||||
child: LinearProgressIndicator(
|
||||
@@ -55,12 +51,10 @@ class ReliabilityScoreBar extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: UiConstants.space2),
|
||||
padding: const EdgeInsets.only(top: UiConstants.space2),
|
||||
child: Text(
|
||||
i18n.description,
|
||||
style: UiTypography.footnote2r.copyWith(
|
||||
color: UiColors.mutedForeground,
|
||||
),
|
||||
style: UiTypography.footnote2r.textSecondary,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Displays the staff member's reliability statistics (Shifts, Rating, On Time, etc.).
|
||||
///
|
||||
@@ -24,14 +23,14 @@ class ReliabilityStatsCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(UiConstants.space4),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: UiColors.foreground.withOpacity(0.05),
|
||||
color: UiColors.foreground.withValues(alpha: 0.05),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 1),
|
||||
),
|
||||
@@ -42,31 +41,31 @@ class ReliabilityStatsCard extends StatelessWidget {
|
||||
children: [
|
||||
_buildStatItem(
|
||||
context,
|
||||
LucideIcons.briefcase,
|
||||
UiIcons.briefcase,
|
||||
"${totalShifts ?? 0}",
|
||||
"Shifts",
|
||||
),
|
||||
_buildStatItem(
|
||||
context,
|
||||
LucideIcons.star,
|
||||
UiIcons.star,
|
||||
(averageRating ?? 0.0).toStringAsFixed(1),
|
||||
"Rating",
|
||||
),
|
||||
_buildStatItem(
|
||||
context,
|
||||
LucideIcons.clock,
|
||||
UiIcons.clock,
|
||||
"${onTimeRate ?? 0}%",
|
||||
"On Time",
|
||||
),
|
||||
_buildStatItem(
|
||||
context,
|
||||
LucideIcons.xCircle,
|
||||
UiIcons.xCircle,
|
||||
"${noShowCount ?? 0}",
|
||||
"No Shows",
|
||||
),
|
||||
_buildStatItem(
|
||||
context,
|
||||
LucideIcons.ban,
|
||||
UiIcons.ban,
|
||||
"${cancellationCount ?? 0}",
|
||||
"Cancel.",
|
||||
),
|
||||
@@ -88,26 +87,22 @@ class ReliabilityStatsCard extends StatelessWidget {
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.primary.withOpacity(0.1),
|
||||
color: UiColors.primary.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusMdValue),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Icon(icon, size: 20, color: UiColors.primary),
|
||||
),
|
||||
SizedBox(height: UiConstants.space1),
|
||||
const SizedBox(height: UiConstants.space1),
|
||||
Text(
|
||||
value,
|
||||
style: UiTypography.body1b.copyWith(
|
||||
color: UiColors.foreground,
|
||||
),
|
||||
style: UiTypography.body1b.textSecondary,
|
||||
),
|
||||
FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Text(
|
||||
label,
|
||||
style: UiTypography.footnote2r.copyWith(
|
||||
color: UiColors.mutedForeground,
|
||||
),
|
||||
style: UiTypography.footnote2r.textSecondary,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -13,14 +13,11 @@ class SectionTitle extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.only(left: UiConstants.space1),
|
||||
margin: EdgeInsets.only(bottom: UiConstants.space3),
|
||||
padding: const EdgeInsets.only(left: UiConstants.space1),
|
||||
margin: const EdgeInsets.only(bottom: UiConstants.space3),
|
||||
child: Text(
|
||||
title.toUpperCase(),
|
||||
style: UiTypography.footnote1b.copyWith(
|
||||
color: UiColors.mutedForeground,
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
style: UiTypography.footnote1b.textSecondary,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user