feat: enhance staff home page with new widgets and improved UI consistency

This commit is contained in:
Achintha Isuru
2026-01-24 13:26:44 -05:00
parent bcd3a9d670
commit 633af6fab0
12 changed files with 169 additions and 272 deletions

View File

@@ -35,4 +35,9 @@ extension HomeNavigator on IModularNavigator {
pushNamed('/shifts?tab=$tab');
}
}
/// Navigates to the settings page.
void pushSettings() {
pushNamed('/settings');
}
}

View File

@@ -20,6 +20,12 @@ import 'package:staff_home/src/presentation/widgets/worker/benefits_widget.dart'
import 'package:staff_home/src/presentation/widgets/worker/improve_yourself_widget.dart';
import 'package:staff_home/src/presentation/widgets/worker/more_ways_widget.dart';
/// The home page for the staff worker application.
///
/// This page displays the worker's dashboard including today's shifts,
/// tomorrow's shifts, recommended shifts, benefits, and other relevant
/// information. It follows Clean Architecture principles with state
/// managed by [HomeCubit].
/// The home page for the staff worker application.
///
/// This page displays the worker's dashboard including today's shifts,
@@ -27,6 +33,7 @@ import 'package:staff_home/src/presentation/widgets/worker/more_ways_widget.dart
/// information. It follows Clean Architecture principles with state
/// managed by [HomeCubit].
class WorkerHomePage extends StatelessWidget {
/// Creates a [WorkerHomePage].
const WorkerHomePage({super.key});
@override
@@ -37,19 +44,18 @@ class WorkerHomePage extends StatelessWidget {
final sectionsI18n = i18n.sections;
final emptyI18n = i18n.empty_states;
return BlocProvider(
create: (_) => Modular.get<HomeCubit>()..loadShifts(),
return BlocProvider<HomeCubit>(
create: (context) => Modular.get<HomeCubit>()..loadShifts(),
child: Scaffold(
backgroundColor: UiColors.background,
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.only(bottom: 100),
padding: const EdgeInsets.only(bottom: UiConstants.space6),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const HomeHeader(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
padding: const EdgeInsets.symmetric(horizontal: UiConstants.space4),
child: Column(
children: [
BlocBuilder<HomeCubit, HomeState>(
@@ -61,23 +67,23 @@ class WorkerHomePage extends StatelessWidget {
return PlaceholderBanner(
title: bannersI18n.complete_profile_title,
subtitle: bannersI18n.complete_profile_subtitle,
bg: Colors.blue[50]!,
accent: Colors.blue,
bg: UiColors.bgHighlight,
accent: UiColors.primary,
onTap: () {
Modular.to.pushWorkerProfile();
},
);
},
),
const SizedBox(height: 20),
const SizedBox(height: UiConstants.space6),
PlaceholderBanner(
title: bannersI18n.availability_title,
subtitle: bannersI18n.availability_subtitle,
bg: Colors.orange[50]!,
accent: Colors.orange,
bg: UiColors.accent.withOpacity(0.1),
accent: UiColors.accent,
onTap: () => Modular.to.pushAvailability(),
),
const SizedBox(height: 20),
const SizedBox(height: UiConstants.space6),
// Auto Match Toggle
BlocBuilder<HomeCubit, HomeState>(
@@ -94,7 +100,7 @@ class WorkerHomePage extends StatelessWidget {
);
},
),
const SizedBox(height: 20),
const SizedBox(height: UiConstants.space6),
// Quick Actions
Row(

View File

@@ -2,49 +2,43 @@ import 'package:flutter/material.dart';
import 'package:design_system/design_system.dart';
/// Widget for displaying an empty state message, using design system tokens.
class EmptyStateWidget extends StatelessWidget {
/// The message to display.
final String message;
/// Optional action link label.
final String? actionLink;
/// Optional action callback.
final VoidCallback? onAction;
const EmptyStateWidget({
super.key,
required this.message,
this.actionLink,
this.onAction,
});
/// Creates an [EmptyStateWidget].
const EmptyStateWidget({super.key, required this.message, this.actionLink, this.onAction});
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
padding: const EdgeInsets.all(UiConstants.space4),
decoration: BoxDecoration(
color: const Color(0xFFF1F3F5),
borderRadius: BorderRadius.circular(8),
color: UiColors.bgSecondary,
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
),
alignment: Alignment.center,
child: Column(
children: [
Text(
message,
style: const TextStyle(
color: UiColors.mutedForeground,
fontSize: 14,
),
style: UiTypography.body2r.copyWith(color: UiColors.mutedForeground),
),
if (actionLink != null)
GestureDetector(
onTap: onAction,
child: Padding(
padding: const EdgeInsets.only(top: 4),
padding: const EdgeInsets.only(top: UiConstants.space2),
child: Text(
actionLink!,
style: const TextStyle(
color: UiColors.primary,
fontSize: 14,
fontWeight: FontWeight.w500,
),
style: UiTypography.body2m.copyWith(color: UiColors.primary),
),
),
),

View File

@@ -1,23 +1,24 @@
import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:lucide_icons/lucide_icons.dart';
import 'package:design_system/design_system.dart';
import 'package:core_localization/core_localization.dart';
import 'package:staff_home/src/presentation/navigation/home_navigator.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
/// Header widget for the staff home page, using design system tokens.
class HomeHeader extends StatelessWidget {
/// Creates a [HomeHeader].
const HomeHeader({super.key});
@override
Widget build(BuildContext context) {
final headerI18n = t.staff.home.header;
return Padding(
padding: const EdgeInsets.fromLTRB(20, 24, 20, 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
padding: EdgeInsets.fromLTRB(
UiConstants.space4,
UiConstants.space4,
UiConstants.space4,
UiConstants.space3,
),
child:Row(
children: [
Container(
width: 48,
@@ -25,12 +26,12 @@ class HomeHeader extends StatelessWidget {
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: UiColors.primary.withValues(alpha: 0.2),
color: UiColors.primary.withOpacity(0.2),
width: 2,
),
),
child: CircleAvatar(
backgroundColor: UiColors.primary.withValues(alpha: 0.1),
backgroundColor: UiColors.primary.withOpacity(0.1),
child: const Text(
'K',
style: TextStyle(
@@ -40,83 +41,22 @@ class HomeHeader extends StatelessWidget {
),
),
),
const SizedBox(width: 12),
const SizedBox(width: UiConstants.space3),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
headerI18n.welcome_back,
style: const TextStyle(
color: UiColors.mutedForeground,
fontSize: 14,
),
style: UiTypography.body3r.copyWith(color: UiColors.mutedForeground),
),
Text(
headerI18n.user_name_placeholder,
style: const TextStyle(
color: UiColors.foreground,
fontSize: 20,
fontWeight: FontWeight.bold,
),
style: UiTypography.headline4m,
),
],
),
],
),
Row(
children: [
GestureDetector(
onTap: () => Modular.to.pushMessages(),
child: Stack(
children: [
_buildHeaderIcon(LucideIcons.bell),
const Positioned(
top: -2,
right: -2,
child: CircleAvatar(
radius: 8,
backgroundColor: Color(0xFFF04444),
child: Text(
'2',
style: TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
const SizedBox(width: 8),
GestureDetector(
onTap: () => Modular.to.pushWorkerProfile(),
child: _buildHeaderIcon(LucideIcons.settings),
),
],
),
],
),
);
}
Widget _buildHeaderIcon(IconData icon) {
return Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
blurRadius: 2,
offset: const Offset(0, 1),
),
],
),
child: Icon(icon, color: UiColors.mutedForeground, size: 20),
);
}
}

View File

@@ -6,7 +6,10 @@ import 'package:design_system/design_system.dart';
import 'package:core_localization/core_localization.dart';
import 'package:staff_home/src/presentation/navigation/home_navigator.dart';
/// Card widget for displaying pending payment information, using design system tokens.
class PendingPaymentCard extends StatelessWidget {
/// Creates a [PendingPaymentCard].
const PendingPaymentCard({super.key});
@override
@@ -15,15 +18,15 @@ class PendingPaymentCard extends StatelessWidget {
return GestureDetector(
onTap: () => Modular.to.pushPayments(),
child: Container(
padding: const EdgeInsets.all(16),
padding: const EdgeInsets.all(UiConstants.space4),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue[50]!.withValues(alpha: 0.5), Colors.blue[50]!],
colors: [UiColors.primary.withOpacity(0.08), UiColors.primary.withOpacity(0.04)],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.blue[100]!.withValues(alpha: 0.5)),
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
border: Border.all(color: UiColors.primary.withOpacity(0.12)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -35,35 +38,28 @@ class PendingPaymentCard extends StatelessWidget {
width: 40,
height: 40,
decoration: const BoxDecoration(
color: Color(0xFFE8F0FF),
color: UiColors.bgHighlight,
shape: BoxShape.circle,
),
child: const Icon(
LucideIcons.dollarSign,
color: Color(0xFF0047FF),
color: UiColors.primary,
size: 20,
),
),
const SizedBox(width: 12),
const SizedBox(width: UiConstants.space3),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
pendingI18n.title,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 14,
color: UiColors.foreground,
),
style: UiTypography.body1b,
overflow: TextOverflow.ellipsis,
),
Text(
pendingI18n.subtitle,
style: const TextStyle(
fontSize: 12,
color: UiColors.mutedForeground,
),
style: UiTypography.body3r.copyWith(color: UiColors.mutedForeground),
overflow: TextOverflow.ellipsis,
),
],
@@ -72,20 +68,16 @@ class PendingPaymentCard extends StatelessWidget {
],
),
),
const Row(
Row(
children: [
Text(
'\$285.00',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
color: Color(0xFF0047FF),
),
style: UiTypography.headline4m,
),
SizedBox(width: 8),
SizedBox(width: UiConstants.space2),
Icon(
LucideIcons.chevronRight,
color: Color(0xFF94A3B8),
color: UiColors.mutedForeground,
size: 20,
),
],

View File

@@ -3,61 +3,58 @@ import 'package:lucide_icons/lucide_icons.dart';
import 'package:design_system/design_system.dart';
/// Banner widget for placeholder actions, using design system tokens.
class PlaceholderBanner extends StatelessWidget {
/// Banner title
final String title;
/// Banner subtitle
final String subtitle;
/// Banner background color
final Color bg;
/// Banner accent color
final Color accent;
/// Optional tap callback
final VoidCallback? onTap;
const PlaceholderBanner({
super.key,
required this.title,
required this.subtitle,
required this.bg,
required this.accent,
this.onTap,
});
/// Creates a [PlaceholderBanner].
const PlaceholderBanner({super.key, required this.title, required this.subtitle, required this.bg, required this.accent, this.onTap});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: const EdgeInsets.all(16),
padding: const EdgeInsets.all(UiConstants.space4),
decoration: BoxDecoration(
color: bg,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: accent.withValues(alpha: 0.3)),
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
border: Border.all(color: accent.withOpacity(0.3)),
),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(8),
width: 40,
height: 40,
padding: const EdgeInsets.all(UiConstants.space2),
decoration: const BoxDecoration(
color: Colors.white,
color: UiColors.bgBanner,
shape: BoxShape.circle,
),
child: Icon(LucideIcons.star, color: accent, size: 20),
child: Icon(LucideIcons.sparkles, color: accent, size: 20),
),
const SizedBox(width: 12),
const SizedBox(width: UiConstants.space3),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: UiColors.foreground,
),
style: UiTypography.body1b,
),
Text(
subtitle,
style: const TextStyle(
fontSize: 12,
color: UiColors.mutedForeground,
),
style: UiTypography.body3r.copyWith(color: UiColors.mutedForeground),
),
],
),

View File

@@ -2,17 +2,18 @@ import 'package:flutter/material.dart';
import 'package:design_system/design_system.dart';
/// Widget for a quick action button on the home page, using design system tokens.
class QuickActionItem extends StatelessWidget {
/// The icon to display.
final IconData icon;
/// The label for the action.
final String label;
/// The callback when tapped.
final VoidCallback onTap;
const QuickActionItem({
super.key,
required this.icon,
required this.label,
required this.onTap,
});
/// Creates a [QuickActionItem].
const QuickActionItem({super.key, required this.icon, required this.label, required this.onTap});
@override
Widget build(BuildContext context) {
@@ -21,16 +22,16 @@ class QuickActionItem extends StatelessWidget {
child: Column(
children: [
Container(
width: 50,
height: 50,
padding: const EdgeInsets.all(12),
width: 64,
height: 64,
padding: const EdgeInsets.all(UiConstants.space4),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: const Color(0xFFF1F5F9)),
color: UiColors.bgBanner,
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
border: Border.all(color: UiColors.bgSecondary),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
color: UiColors.foreground.withOpacity(0.05),
blurRadius: 4,
offset: const Offset(0, 2),
),
@@ -38,14 +39,10 @@ class QuickActionItem extends StatelessWidget {
),
child: Icon(icon, color: UiColors.primary, size: 24),
),
const SizedBox(height: 8),
const SizedBox(height: UiConstants.space2),
Text(
label,
style: const TextStyle(
fontSize: 10,
fontWeight: FontWeight.w500,
color: UiColors.foreground,
),
style: UiTypography.body3r.copyWith(color: UiColors.foreground),
),
],
),

View File

@@ -3,32 +3,29 @@ import 'package:lucide_icons/lucide_icons.dart';
import 'package:design_system/design_system.dart';
/// Section header widget for home page sections, using design system tokens.
class SectionHeader extends StatelessWidget {
/// Section title
final String title;
/// Optional action label
final String? action;
/// Optional action callback
final VoidCallback? onAction;
const SectionHeader({
super.key,
required this.title,
this.action,
this.onAction,
});
/// Creates a [SectionHeader].
const SectionHeader({super.key, required this.title, this.action, this.onAction});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.only(bottom: UiConstants.space3),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: UiColors.foreground,
),
style: UiTypography.headline4m,
),
if (action != null)
if (onAction != null)
@@ -38,11 +35,7 @@ class SectionHeader extends StatelessWidget {
children: [
Text(
action!,
style: const TextStyle(
color: UiColors.primary,
fontSize: 14,
fontWeight: FontWeight.w500,
),
style: UiTypography.body2m.copyWith(color: UiColors.primary),
),
const Icon(
LucideIcons.chevronRight,
@@ -56,19 +49,15 @@ class SectionHeader extends StatelessWidget {
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
decoration: BoxDecoration(
color: UiColors.primary.withValues(alpha: 0.08),
color: UiColors.primary.withOpacity(0.08),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: UiColors.primary.withValues(alpha: 0.2),
color: UiColors.primary.withOpacity(0.2),
),
),
child: Text(
action!,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: UiColors.primary,
),
style: UiTypography.body3r.copyWith(color: UiColors.primary),
),
),
],

View File

@@ -3,33 +3,33 @@ import 'package:lucide_icons/lucide_icons.dart';
import 'package:core_localization/core_localization.dart';
/// Toggle widget for auto-match feature, using design system tokens.
class AutoMatchToggle extends StatefulWidget {
/// Whether auto-match is enabled.
final bool enabled;
/// Callback when toggled.
final ValueChanged<bool> onToggle;
const AutoMatchToggle({
super.key,
required this.enabled,
required this.onToggle,
});
/// Creates an [AutoMatchToggle].
const AutoMatchToggle({super.key, required this.enabled, required this.onToggle});
@override
State<AutoMatchToggle> createState() => _AutoMatchToggleState();
}
class _AutoMatchToggleState extends State<AutoMatchToggle>
with SingleTickerProviderStateMixin {
class _AutoMatchToggleState extends State<AutoMatchToggle> with SingleTickerProviderStateMixin {
@override
Widget build(BuildContext context) {
final i18n = t.staff.home.auto_match;
final Color primary = Theme.of(context).colorScheme.primary;
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
gradient: widget.enabled
? const LinearGradient(
colors: [Color(0xFF0032A0), Color(0xFF0047CC)],
? LinearGradient(
colors: [primary, primary.withOpacity(0.8)],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
)
@@ -39,7 +39,7 @@ class _AutoMatchToggleState extends State<AutoMatchToggle>
boxShadow: widget.enabled
? [
BoxShadow(
color: const Color(0xFF0032A0).withValues(alpha: 0.3),
color: primary.withOpacity(0.3),
blurRadius: 10,
offset: const Offset(0, 4),
),
@@ -58,15 +58,13 @@ class _AutoMatchToggleState extends State<AutoMatchToggle>
height: 40,
decoration: BoxDecoration(
color: widget.enabled
? Colors.white.withValues(alpha: 0.2)
: const Color(0xFF0032A0).withValues(alpha: 0.1),
? Colors.white.withOpacity(0.2)
: primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
LucideIcons.zap,
color: widget.enabled
? Colors.white
: const Color(0xFF0032A0),
color: widget.enabled ? Colors.white : primary,
size: 20,
),
),
@@ -78,18 +76,14 @@ class _AutoMatchToggleState extends State<AutoMatchToggle>
i18n.title,
style: TextStyle(
fontWeight: FontWeight.bold,
color: widget.enabled
? Colors.white
: const Color(0xFF0F172A),
color: widget.enabled ? Colors.white : const Color(0xFF0F172A),
),
),
Text(
widget.enabled ? i18n.finding_shifts : i18n.get_matched,
style: TextStyle(
fontSize: 12,
color: widget.enabled
? const Color(0xFFF8E08E)
: Colors.grey.shade500,
color: widget.enabled ? const Color(0xFFF8E08E) : Colors.grey.shade500,
),
),
],

View File

@@ -5,7 +5,10 @@ import 'dart:math' as math;
import 'package:core_localization/core_localization.dart';
/// Widget for displaying staff benefits, using design system tokens.
class BenefitsWidget extends StatelessWidget {
/// Creates a [BenefitsWidget].
const BenefitsWidget({super.key});
@override
@@ -14,12 +17,12 @@ class BenefitsWidget extends StatelessWidget {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
color: Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.grey.shade100),
border: Border.all(color: Theme.of(context).dividerColor),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
color: Theme.of(context).colorScheme.onBackground.withOpacity(0.05),
blurRadius: 2,
offset: const Offset(0, 1),
),
@@ -32,10 +35,7 @@ class BenefitsWidget extends StatelessWidget {
children: [
Text(
i18n.title,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Color(0xFF0F172A),
),
style: Theme.of(context).textTheme.titleMedium,
),
GestureDetector(
onTap: () => Modular.to.pushNamed('/benefits'),
@@ -43,16 +43,12 @@ class BenefitsWidget extends StatelessWidget {
children: [
Text(
i18n.view_all,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Color(0xFF0032A0),
),
style: Theme.of(context).textTheme.labelLarge?.copyWith(color: Theme.of(context).colorScheme.primary),
),
const Icon(
Icon(
LucideIcons.chevronRight,
size: 16,
color: Color(0xFF0032A0),
color: Theme.of(context).colorScheme.primary,
),
],
),
@@ -67,19 +63,19 @@ class BenefitsWidget extends StatelessWidget {
label: i18n.items.sick_days,
current: 10,
total: 40,
color: const Color(0xFF0A39DF),
color: Theme.of(context).colorScheme.primary,
),
_BenefitItem(
label: i18n.items.vacation,
current: 40,
total: 40,
color: const Color(0xFF0A39DF),
color: Theme.of(context).colorScheme.primary,
),
_BenefitItem(
label: i18n.items.holidays,
current: 24,
total: 24,
color: const Color(0xFF0A39DF),
color: Theme.of(context).colorScheme.primary,
),
],
),

View File

@@ -2,8 +2,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:core_localization/core_localization.dart';
/// Widget for displaying self-improvement resources, using design system tokens.
class ImproveYourselfWidget extends StatelessWidget {
/// Creates an [ImproveYourselfWidget].
const ImproveYourselfWidget({super.key});
@override
Widget build(BuildContext context) {
final i18n = t.staff.home.improve;
@@ -12,16 +15,14 @@ class ImproveYourselfWidget extends StatelessWidget {
'id': 'training',
'title': i18n.items.training.title,
'description': i18n.items.training.description,
'image':
'https://images.unsplash.com/photo-1524995997946-a1c2e315a42f?w=400&h=300&fit=crop',
'image': 'https://images.unsplash.com/photo-1524995997946-a1c2e315a42f?w=400&h=300&fit=crop',
'page': i18n.items.training.page,
},
{
'id': 'podcast',
'title': i18n.items.podcast.title,
'description': i18n.items.podcast.description,
'image':
'https://images.unsplash.com/photo-1478737270239-2f02b77fc618?w=400&h=300&fit=crop',
'image': 'https://images.unsplash.com/photo-1478737270239-2f02b77fc618?w=400&h=300&fit=crop',
'page': i18n.items.podcast.page,
},
];
@@ -31,11 +32,7 @@ class ImproveYourselfWidget extends StatelessWidget {
children: [
Text(
i18n.title,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xFF0F172A),
),
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 12),
SingleChildScrollView(
@@ -56,12 +53,12 @@ class ImproveYourselfWidget extends StatelessWidget {
width: 160,
margin: const EdgeInsets.only(right: 12),
decoration: BoxDecoration(
color: Colors.white,
color: Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.grey.shade100),
border: Border.all(color: Theme.of(context).dividerColor),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
color: Theme.of(context).colorScheme.onBackground.withOpacity(0.05),
blurRadius: 2,
offset: const Offset(0, 1),
),
@@ -78,7 +75,7 @@ class ImproveYourselfWidget extends StatelessWidget {
item['image']!,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) => Container(
color: Colors.grey.shade200,
color: Theme.of(context).colorScheme.surfaceVariant,
child: const Icon(
Icons.image_not_supported,
color: Colors.grey,
@@ -93,11 +90,7 @@ class ImproveYourselfWidget extends StatelessWidget {
children: [
Text(
item['title']!,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Color(0xFF0F172A),
),
style: Theme.of(context).textTheme.titleSmall,
),
const SizedBox(height: 2),
Text(

View File

@@ -2,8 +2,12 @@ import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:core_localization/core_localization.dart';
/// Widget for displaying more ways to use Krow, using design system tokens.
class MoreWaysToUseKrowWidget extends StatelessWidget {
/// Creates a [MoreWaysToUseKrowWidget].
const MoreWaysToUseKrowWidget({super.key});
@override
Widget build(BuildContext context) {
final i18n = t.staff.home.more_ways;
@@ -11,15 +15,13 @@ class MoreWaysToUseKrowWidget extends StatelessWidget {
{
'id': 'benefits',
'title': i18n.items.benefits.title,
'image':
'https://images.unsplash.com/photo-1481627834876-b7833e8f5570?w=400&h=300&fit=crop',
'image': 'https://images.unsplash.com/photo-1481627834876-b7833e8f5570?w=400&h=300&fit=crop',
'page': i18n.items.benefits.page,
},
{
'id': 'refer',
'title': i18n.items.refer.title,
'image':
'https://images.unsplash.com/photo-1529156069898-49953e39b3ac?w=400&h=300&fit=crop',
'image': 'https://images.unsplash.com/photo-1529156069898-49953e39b3ac?w=400&h=300&fit=crop',
'page': i18n.items.refer.page,
},
];
@@ -29,11 +31,7 @@ class MoreWaysToUseKrowWidget extends StatelessWidget {
children: [
Text(
i18n.title,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xFF0F172A),
),
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 12),
SingleChildScrollView(
@@ -54,12 +52,12 @@ class MoreWaysToUseKrowWidget extends StatelessWidget {
width: 160,
margin: const EdgeInsets.only(right: 12),
decoration: BoxDecoration(
color: Colors.white,
color: Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.grey.shade100),
border: Border.all(color: Theme.of(context).dividerColor),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
color: Theme.of(context).colorScheme.onBackground.withOpacity(0.05),
blurRadius: 2,
offset: const Offset(0, 1),
),
@@ -76,7 +74,7 @@ class MoreWaysToUseKrowWidget extends StatelessWidget {
item['image']!,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) => Container(
color: Colors.grey.shade200,
color: Theme.of(context).colorScheme.surfaceVariant,
child: const Icon(
Icons.image_not_supported,
color: Colors.grey,
@@ -88,11 +86,7 @@ class MoreWaysToUseKrowWidget extends StatelessWidget {
padding: const EdgeInsets.all(12),
child: Text(
item['title']!,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Color(0xFF0F172A),
),
style: Theme.of(context).textTheme.titleSmall,
),
),
],