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

View File

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

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: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 { class HomeHeader extends StatelessWidget {
/// Creates a [HomeHeader].
const HomeHeader({super.key}); const HomeHeader({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final headerI18n = t.staff.home.header; final headerI18n = t.staff.home.header;
return Padding( return Padding(
padding: const EdgeInsets.fromLTRB(20, 24, 20, 16), padding: EdgeInsets.fromLTRB(
child: Row( UiConstants.space4,
mainAxisAlignment: MainAxisAlignment.spaceBetween, UiConstants.space4,
children: [ UiConstants.space4,
Row( UiConstants.space3,
),
child:Row(
children: [ children: [
Container( Container(
width: 48, width: 48,
@@ -25,12 +26,12 @@ class HomeHeader extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
border: Border.all( border: Border.all(
color: UiColors.primary.withValues(alpha: 0.2), color: UiColors.primary.withOpacity(0.2),
width: 2, width: 2,
), ),
), ),
child: CircleAvatar( child: CircleAvatar(
backgroundColor: UiColors.primary.withValues(alpha: 0.1), backgroundColor: UiColors.primary.withOpacity(0.1),
child: const Text( child: const Text(
'K', 'K',
style: TextStyle( style: TextStyle(
@@ -40,83 +41,22 @@ class HomeHeader extends StatelessWidget {
), ),
), ),
), ),
const SizedBox(width: 12), const SizedBox(width: UiConstants.space3),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
headerI18n.welcome_back, headerI18n.welcome_back,
style: const TextStyle( style: UiTypography.body3r.copyWith(color: UiColors.mutedForeground),
color: UiColors.mutedForeground,
fontSize: 14,
),
), ),
Text( Text(
headerI18n.user_name_placeholder, headerI18n.user_name_placeholder,
style: const TextStyle( style: UiTypography.headline4m,
color: UiColors.foreground,
fontSize: 20,
fontWeight: FontWeight.bold,
),
), ),
], ],
), ),
], ],
), ),
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:core_localization/core_localization.dart';
import 'package:staff_home/src/presentation/navigation/home_navigator.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 { class PendingPaymentCard extends StatelessWidget {
/// Creates a [PendingPaymentCard].
const PendingPaymentCard({super.key}); const PendingPaymentCard({super.key});
@override @override
@@ -15,15 +18,15 @@ class PendingPaymentCard extends StatelessWidget {
return GestureDetector( return GestureDetector(
onTap: () => Modular.to.pushPayments(), onTap: () => Modular.to.pushPayments(),
child: Container( child: Container(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(UiConstants.space4),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( 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, begin: Alignment.centerLeft,
end: Alignment.centerRight, end: Alignment.centerRight,
), ),
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(UiConstants.radiusBase),
border: Border.all(color: Colors.blue[100]!.withValues(alpha: 0.5)), border: Border.all(color: UiColors.primary.withOpacity(0.12)),
), ),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -35,35 +38,28 @@ class PendingPaymentCard extends StatelessWidget {
width: 40, width: 40,
height: 40, height: 40,
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Color(0xFFE8F0FF), color: UiColors.bgHighlight,
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
child: const Icon( child: const Icon(
LucideIcons.dollarSign, LucideIcons.dollarSign,
color: Color(0xFF0047FF), color: UiColors.primary,
size: 20, size: 20,
), ),
), ),
const SizedBox(width: 12), const SizedBox(width: UiConstants.space3),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
pendingI18n.title, pendingI18n.title,
style: const TextStyle( style: UiTypography.body1b,
fontWeight: FontWeight.w500,
fontSize: 14,
color: UiColors.foreground,
),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
Text( Text(
pendingI18n.subtitle, pendingI18n.subtitle,
style: const TextStyle( style: UiTypography.body3r.copyWith(color: UiColors.mutedForeground),
fontSize: 12,
color: UiColors.mutedForeground,
),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
], ],
@@ -72,20 +68,16 @@ class PendingPaymentCard extends StatelessWidget {
], ],
), ),
), ),
const Row( Row(
children: [ children: [
Text( Text(
'\$285.00', '\$285.00',
style: TextStyle( style: UiTypography.headline4m,
fontWeight: FontWeight.bold,
fontSize: 18,
color: Color(0xFF0047FF),
),
), ),
SizedBox(width: 8), SizedBox(width: UiConstants.space2),
Icon( Icon(
LucideIcons.chevronRight, LucideIcons.chevronRight,
color: Color(0xFF94A3B8), color: UiColors.mutedForeground,
size: 20, size: 20,
), ),
], ],

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,7 +5,10 @@ import 'dart:math' as math;
import 'package:core_localization/core_localization.dart'; import 'package:core_localization/core_localization.dart';
/// Widget for displaying staff benefits, using design system tokens.
class BenefitsWidget extends StatelessWidget { class BenefitsWidget extends StatelessWidget {
/// Creates a [BenefitsWidget].
const BenefitsWidget({super.key}); const BenefitsWidget({super.key});
@override @override
@@ -14,12 +17,12 @@ class BenefitsWidget extends StatelessWidget {
return Container( return Container(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.grey.shade100), border: Border.all(color: Theme.of(context).dividerColor),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withValues(alpha: 0.05), color: Theme.of(context).colorScheme.onBackground.withOpacity(0.05),
blurRadius: 2, blurRadius: 2,
offset: const Offset(0, 1), offset: const Offset(0, 1),
), ),
@@ -32,10 +35,7 @@ class BenefitsWidget extends StatelessWidget {
children: [ children: [
Text( Text(
i18n.title, i18n.title,
style: const TextStyle( style: Theme.of(context).textTheme.titleMedium,
fontWeight: FontWeight.bold,
color: Color(0xFF0F172A),
),
), ),
GestureDetector( GestureDetector(
onTap: () => Modular.to.pushNamed('/benefits'), onTap: () => Modular.to.pushNamed('/benefits'),
@@ -43,16 +43,12 @@ class BenefitsWidget extends StatelessWidget {
children: [ children: [
Text( Text(
i18n.view_all, i18n.view_all,
style: const TextStyle( style: Theme.of(context).textTheme.labelLarge?.copyWith(color: Theme.of(context).colorScheme.primary),
fontSize: 14,
fontWeight: FontWeight.w500,
color: Color(0xFF0032A0),
),
), ),
const Icon( Icon(
LucideIcons.chevronRight, LucideIcons.chevronRight,
size: 16, size: 16,
color: Color(0xFF0032A0), color: Theme.of(context).colorScheme.primary,
), ),
], ],
), ),
@@ -67,19 +63,19 @@ class BenefitsWidget extends StatelessWidget {
label: i18n.items.sick_days, label: i18n.items.sick_days,
current: 10, current: 10,
total: 40, total: 40,
color: const Color(0xFF0A39DF), color: Theme.of(context).colorScheme.primary,
), ),
_BenefitItem( _BenefitItem(
label: i18n.items.vacation, label: i18n.items.vacation,
current: 40, current: 40,
total: 40, total: 40,
color: const Color(0xFF0A39DF), color: Theme.of(context).colorScheme.primary,
), ),
_BenefitItem( _BenefitItem(
label: i18n.items.holidays, label: i18n.items.holidays,
current: 24, current: 24,
total: 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:flutter_modular/flutter_modular.dart';
import 'package:core_localization/core_localization.dart'; import 'package:core_localization/core_localization.dart';
/// Widget for displaying self-improvement resources, using design system tokens.
class ImproveYourselfWidget extends StatelessWidget { class ImproveYourselfWidget extends StatelessWidget {
/// Creates an [ImproveYourselfWidget].
const ImproveYourselfWidget({super.key}); const ImproveYourselfWidget({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final i18n = t.staff.home.improve; final i18n = t.staff.home.improve;
@@ -12,16 +15,14 @@ class ImproveYourselfWidget extends StatelessWidget {
'id': 'training', 'id': 'training',
'title': i18n.items.training.title, 'title': i18n.items.training.title,
'description': i18n.items.training.description, 'description': i18n.items.training.description,
'image': 'image': 'https://images.unsplash.com/photo-1524995997946-a1c2e315a42f?w=400&h=300&fit=crop',
'https://images.unsplash.com/photo-1524995997946-a1c2e315a42f?w=400&h=300&fit=crop',
'page': i18n.items.training.page, 'page': i18n.items.training.page,
}, },
{ {
'id': 'podcast', 'id': 'podcast',
'title': i18n.items.podcast.title, 'title': i18n.items.podcast.title,
'description': i18n.items.podcast.description, 'description': i18n.items.podcast.description,
'image': 'image': 'https://images.unsplash.com/photo-1478737270239-2f02b77fc618?w=400&h=300&fit=crop',
'https://images.unsplash.com/photo-1478737270239-2f02b77fc618?w=400&h=300&fit=crop',
'page': i18n.items.podcast.page, 'page': i18n.items.podcast.page,
}, },
]; ];
@@ -31,11 +32,7 @@ class ImproveYourselfWidget extends StatelessWidget {
children: [ children: [
Text( Text(
i18n.title, i18n.title,
style: const TextStyle( style: Theme.of(context).textTheme.titleMedium,
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xFF0F172A),
),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
SingleChildScrollView( SingleChildScrollView(
@@ -56,12 +53,12 @@ class ImproveYourselfWidget extends StatelessWidget {
width: 160, width: 160,
margin: const EdgeInsets.only(right: 12), margin: const EdgeInsets.only(right: 12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.grey.shade100), border: Border.all(color: Theme.of(context).dividerColor),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withValues(alpha: 0.05), color: Theme.of(context).colorScheme.onBackground.withOpacity(0.05),
blurRadius: 2, blurRadius: 2,
offset: const Offset(0, 1), offset: const Offset(0, 1),
), ),
@@ -78,7 +75,7 @@ class ImproveYourselfWidget extends StatelessWidget {
item['image']!, item['image']!,
fit: BoxFit.cover, fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) => Container( errorBuilder: (context, error, stackTrace) => Container(
color: Colors.grey.shade200, color: Theme.of(context).colorScheme.surfaceVariant,
child: const Icon( child: const Icon(
Icons.image_not_supported, Icons.image_not_supported,
color: Colors.grey, color: Colors.grey,
@@ -93,11 +90,7 @@ class ImproveYourselfWidget extends StatelessWidget {
children: [ children: [
Text( Text(
item['title']!, item['title']!,
style: const TextStyle( style: Theme.of(context).textTheme.titleSmall,
fontSize: 14,
fontWeight: FontWeight.w600,
color: Color(0xFF0F172A),
),
), ),
const SizedBox(height: 2), const SizedBox(height: 2),
Text( Text(

View File

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