refactor: replace model with entity for shift and update imports

This commit is contained in:
Achintha Isuru
2026-01-24 12:58:21 -05:00
parent 67749ba1a8
commit bcd3a9d670
20 changed files with 208 additions and 179 deletions

View File

@@ -1,4 +1,4 @@
import 'package:staff_home/src/domain/models/shift.dart'; import 'package:staff_home/src/domain/entities/shift.dart';
import 'package:staff_home/src/domain/repositories/home_repository.dart'; import 'package:staff_home/src/domain/repositories/home_repository.dart';
import 'package:staff_home/src/data/services/mock_service.dart'; import 'package:staff_home/src/data/services/mock_service.dart';

View File

@@ -1,4 +1,4 @@
import 'package:staff_home/src/domain/models/shift.dart'; import 'package:staff_home/src/domain/entities/shift.dart';
class MockService { class MockService {
static final Shift _sampleShift1 = Shift( static final Shift _sampleShift1 = Shift(
@@ -74,5 +74,3 @@ class MockService {
await Future.delayed(const Duration(seconds: 1)); await Future.delayed(const Duration(seconds: 1));
} }
} }
final mockService = MockService();

View File

@@ -1,29 +1,10 @@
class Shift { import 'package:equatable/equatable.dart';
final String id;
final String title;
final String clientName;
final String? logoUrl;
final double hourlyRate;
final String location;
final String? locationAddress;
final String date;
final String startTime;
final String endTime;
final String createdDate;
final bool? tipsAvailable;
final bool? travelTime;
final bool? mealProvided;
final bool? parkingAvailable;
final bool? gasCompensation;
final String? description;
final String? instructions;
final List<ShiftManager>? managers;
final double? latitude;
final double? longitude;
final String? status;
final int? durationDays;
Shift({ /// Entity representing a shift for the staff home screen.
///
/// This entity aggregates essential shift details needed for display cards.
class Shift extends Equatable {
const Shift({
required this.id, required this.id,
required this.title, required this.title,
required this.clientName, required this.clientName,
@@ -48,12 +29,66 @@ class Shift {
this.status, this.status,
this.durationDays, this.durationDays,
}); });
final String id;
final String title;
final String clientName;
final String? logoUrl;
final double hourlyRate;
final String location;
final String? locationAddress;
final String date;
final String startTime;
final String endTime;
final String createdDate;
final bool? tipsAvailable;
final bool? travelTime;
final bool? mealProvided;
final bool? parkingAvailable;
final bool? gasCompensation;
final String? description;
final String? instructions;
final List<ShiftManager>? managers;
final double? latitude;
final double? longitude;
final String? status;
final int? durationDays;
@override
List<Object?> get props => [
id,
title,
clientName,
logoUrl,
hourlyRate,
location,
locationAddress,
date,
startTime,
endTime,
createdDate,
tipsAvailable,
travelTime,
mealProvided,
parkingAvailable,
gasCompensation,
description,
instructions,
managers,
latitude,
longitude,
status,
durationDays,
];
} }
class ShiftManager { class ShiftManager extends Equatable {
const ShiftManager({required this.name, required this.phone, this.avatar});
final String name; final String name;
final String phone; final String phone;
final String? avatar; final String? avatar;
ShiftManager({required this.name, required this.phone, this.avatar}); @override
List<Object?> get props => [name, phone, avatar];
} }

View File

@@ -1,7 +1,17 @@
import 'package:staff_home/src/domain/models/shift.dart'; import 'package:staff_home/src/domain/entities/shift.dart';
/// Repository interface for home screen data operations.
///
/// This interface defines the contract for fetching shift data
/// displayed on the worker home screen. Implementations should
/// handle data retrieval from appropriate data sources.
abstract class HomeRepository { abstract class HomeRepository {
/// Retrieves the list of shifts scheduled for today.
Future<List<Shift>> getTodayShifts(); Future<List<Shift>> getTodayShifts();
/// Retrieves the list of shifts scheduled for tomorrow.
Future<List<Shift>> getTomorrowShifts(); Future<List<Shift>> getTomorrowShifts();
/// Retrieves shifts recommended for the worker based on their profile.
Future<List<Shift>> getRecommendedShifts(); Future<List<Shift>> getRecommendedShifts();
} }

View File

@@ -1,11 +1,19 @@
import 'package:staff_home/src/domain/models/shift.dart'; import 'package:staff_home/src/domain/entities/shift.dart';
import 'package:staff_home/src/domain/repositories/home_repository.dart'; import 'package:staff_home/src/domain/repositories/home_repository.dart';
/// Use case for fetching all shifts displayed on the home screen.
///
/// This use case aggregates shift data from multiple time periods
/// (today, tomorrow, and recommended) into a single response.
class GetHomeShifts { class GetHomeShifts {
final HomeRepository repository; final HomeRepository repository;
GetHomeShifts(this.repository); GetHomeShifts(this.repository);
/// Executes the use case to fetch all home screen shift data.
///
/// Returns a [HomeShifts] object containing today's shifts,
/// tomorrow's shifts, and recommended shifts.
Future<HomeShifts> call() async { Future<HomeShifts> call() async {
final today = await repository.getTodayShifts(); final today = await repository.getTodayShifts();
final tomorrow = await repository.getTomorrowShifts(); final tomorrow = await repository.getTomorrowShifts();
@@ -18,6 +26,9 @@ class GetHomeShifts {
} }
} }
/// Data transfer object containing all shifts for the home screen.
///
/// Groups shifts by time period for easy presentation layer consumption.
class HomeShifts { class HomeShifts {
final List<Shift> today; final List<Shift> today;
final List<Shift> tomorrow; final List<Shift> tomorrow;

View File

@@ -1,7 +1,7 @@
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:staff_home/src/domain/models/shift.dart'; import 'package:staff_home/src/domain/entities/shift.dart';
import 'package:staff_home/src/domain/usecases/get_home_shifts.dart'; import 'package:staff_home/src/domain/usecases/get_home_shifts.dart';
import 'package:staff_home/src/domain/repositories/home_repository.dart'; import 'package:staff_home/src/domain/repositories/home_repository.dart';

View File

@@ -45,12 +45,12 @@ class HomeState extends Equatable {
@override @override
List<Object?> get props => [ List<Object?> get props => [
status, status,
todayShifts, todayShifts,
tomorrowShifts, tomorrowShifts,
recommendedShifts, recommendedShifts,
autoMatchEnabled, autoMatchEnabled,
isProfileComplete, isProfileComplete,
errorMessage, errorMessage,
]; ];
} }

View File

@@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_modular/flutter_modular.dart'; import 'package:flutter_modular/flutter_modular.dart';
import 'package:lucide_icons/lucide_icons.dart'; import 'package:lucide_icons/lucide_icons.dart';
import 'package:core_localization/core_localization.dart'; import 'package:core_localization/core_localization.dart';
import 'package:design_system/design_system.dart';
import 'package:staff_home/src/presentation/blocs/home_cubit.dart'; import 'package:staff_home/src/presentation/blocs/home_cubit.dart';
import 'package:staff_home/src/presentation/navigation/home_navigator.dart'; import 'package:staff_home/src/presentation/navigation/home_navigator.dart';
@@ -18,8 +19,13 @@ import 'package:staff_home/src/presentation/widgets/worker/auto_match_toggle.dar
import 'package:staff_home/src/presentation/widgets/worker/benefits_widget.dart'; 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';
import 'package:staff_home/src/theme.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].
class WorkerHomePage extends StatelessWidget { class WorkerHomePage extends StatelessWidget {
const WorkerHomePage({super.key}); const WorkerHomePage({super.key});
@@ -34,7 +40,7 @@ class WorkerHomePage extends StatelessWidget {
return BlocProvider( return BlocProvider(
create: (_) => Modular.get<HomeCubit>()..loadShifts(), create: (_) => Modular.get<HomeCubit>()..loadShifts(),
child: Scaffold( child: Scaffold(
backgroundColor: AppColors.krowBackground, backgroundColor: UiColors.background,
body: SafeArea( body: SafeArea(
child: SingleChildScrollView( child: SingleChildScrollView(
padding: const EdgeInsets.only(bottom: 100), padding: const EdgeInsets.only(bottom: 100),
@@ -76,13 +82,15 @@ class WorkerHomePage extends StatelessWidget {
// Auto Match Toggle // Auto Match Toggle
BlocBuilder<HomeCubit, HomeState>( BlocBuilder<HomeCubit, HomeState>(
buildWhen: (previous, current) => buildWhen: (previous, current) =>
previous.autoMatchEnabled != current.autoMatchEnabled, previous.autoMatchEnabled !=
current.autoMatchEnabled,
builder: (context, state) { builder: (context, state) {
return AutoMatchToggle( return AutoMatchToggle(
enabled: state.autoMatchEnabled, enabled: state.autoMatchEnabled,
onToggle: (val) => context onToggle: (val) => BlocProvider.of<HomeCubit>(
.read<HomeCubit>() context,
.toggleAutoMatch(val), listen: false,
).toggleAutoMatch(val),
); );
}, },
), ),
@@ -176,9 +184,7 @@ class WorkerHomePage extends StatelessWidget {
final shifts = state.tomorrowShifts; final shifts = state.tomorrowShifts;
return Column( return Column(
children: [ children: [
SectionHeader( SectionHeader(title: sectionsI18n.tomorrow),
title: sectionsI18n.tomorrow,
),
if (shifts.isEmpty) if (shifts.isEmpty)
EmptyStateWidget( EmptyStateWidget(
message: emptyI18n.no_shifts_tomorrow, message: emptyI18n.no_shifts_tomorrow,
@@ -252,4 +258,4 @@ class WorkerHomePage extends StatelessWidget {
), ),
); );
} }
} }

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:staff_home/src/theme.dart';
import 'package:design_system/design_system.dart';
class EmptyStateWidget extends StatelessWidget { class EmptyStateWidget extends StatelessWidget {
final String message; final String message;
@@ -27,7 +28,10 @@ class EmptyStateWidget extends StatelessWidget {
children: [ children: [
Text( Text(
message, message,
style: const TextStyle(color: AppColors.krowMuted, fontSize: 14), style: const TextStyle(
color: UiColors.mutedForeground,
fontSize: 14,
),
), ),
if (actionLink != null) if (actionLink != null)
GestureDetector( GestureDetector(
@@ -37,7 +41,7 @@ class EmptyStateWidget extends StatelessWidget {
child: Text( child: Text(
actionLink!, actionLink!,
style: const TextStyle( style: const TextStyle(
color: AppColors.krowBlue, color: UiColors.primary,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),

View File

@@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart'; import 'package:flutter_modular/flutter_modular.dart';
import 'package:lucide_icons/lucide_icons.dart'; import 'package:lucide_icons/lucide_icons.dart';
import 'package:staff_home/src/theme.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:staff_home/src/presentation/navigation/home_navigator.dart';
@@ -24,16 +25,16 @@ class HomeHeader extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
border: Border.all( border: Border.all(
color: AppColors.krowBlue.withValues(alpha: 0.2), color: UiColors.primary.withValues(alpha: 0.2),
width: 2, width: 2,
), ),
), ),
child: CircleAvatar( child: CircleAvatar(
backgroundColor: AppColors.krowBlue.withValues(alpha: 0.1), backgroundColor: UiColors.primary.withValues(alpha: 0.1),
child: const Text( child: const Text(
'K', 'K',
style: TextStyle( style: TextStyle(
color: AppColors.krowBlue, color: UiColors.primary,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
@@ -46,14 +47,14 @@ class HomeHeader extends StatelessWidget {
Text( Text(
headerI18n.welcome_back, headerI18n.welcome_back,
style: const TextStyle( style: const TextStyle(
color: AppColors.krowMuted, color: UiColors.mutedForeground,
fontSize: 14, fontSize: 14,
), ),
), ),
Text( Text(
headerI18n.user_name_placeholder, headerI18n.user_name_placeholder,
style: const TextStyle( style: const TextStyle(
color: AppColors.krowCharcoal, color: UiColors.foreground,
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -115,7 +116,7 @@ class HomeHeader extends StatelessWidget {
), ),
], ],
), ),
child: Icon(icon, color: AppColors.krowMuted, size: 20), child: Icon(icon, color: UiColors.mutedForeground, size: 20),
); );
} }
} }

View File

@@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart'; import 'package:flutter_modular/flutter_modular.dart';
import 'package:lucide_icons/lucide_icons.dart'; import 'package:lucide_icons/lucide_icons.dart';
import 'package:staff_home/src/theme.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:staff_home/src/presentation/navigation/home_navigator.dart';
@@ -53,7 +54,7 @@ class PendingPaymentCard extends StatelessWidget {
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
fontSize: 14, fontSize: 14,
color: AppColors.krowCharcoal, color: UiColors.foreground,
), ),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@@ -61,7 +62,7 @@ class PendingPaymentCard extends StatelessWidget {
pendingI18n.subtitle, pendingI18n.subtitle,
style: const TextStyle( style: const TextStyle(
fontSize: 12, fontSize: 12,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lucide_icons/lucide_icons.dart'; import 'package:lucide_icons/lucide_icons.dart';
import 'package:staff_home/src/theme.dart';
import 'package:design_system/design_system.dart';
class PlaceholderBanner extends StatelessWidget { class PlaceholderBanner extends StatelessWidget {
final String title; final String title;
@@ -48,14 +49,14 @@ class PlaceholderBanner extends StatelessWidget {
title, title,
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.krowCharcoal, color: UiColors.foreground,
), ),
), ),
Text( Text(
subtitle, subtitle,
style: const TextStyle( style: const TextStyle(
fontSize: 12, fontSize: 12,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
), ),
], ],

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lucide_icons/lucide_icons.dart';
import 'package:staff_home/src/theme.dart'; import 'package:design_system/design_system.dart';
class QuickActionItem extends StatelessWidget { class QuickActionItem extends StatelessWidget {
final IconData icon; final IconData icon;
@@ -36,7 +36,7 @@ class QuickActionItem extends StatelessWidget {
), ),
], ],
), ),
child: Icon(icon, color: AppColors.krowBlue, size: 24), child: Icon(icon, color: UiColors.primary, size: 24),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
@@ -44,7 +44,7 @@ class QuickActionItem extends StatelessWidget {
style: const TextStyle( style: const TextStyle(
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: AppColors.krowCharcoal, color: UiColors.foreground,
), ),
), ),
], ],

View File

@@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lucide_icons/lucide_icons.dart'; import 'package:lucide_icons/lucide_icons.dart';
import 'package:staff_home/src/domain/models/shift.dart';
import 'package:staff_home/src/theme.dart'; import 'package:design_system/design_system.dart';
import 'package:staff_home/src/domain/entities/shift.dart';
import 'package:core_localization/core_localization.dart'; import 'package:core_localization/core_localization.dart';
class RecommendedShiftCard extends StatelessWidget { class RecommendedShiftCard extends StatelessWidget {
@@ -19,9 +20,7 @@ class RecommendedShiftCard extends StatelessWidget {
onTap: () { onTap: () {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text( content: Text(recI18n.applied_for(title: shift.title)),
recI18n.applied_for(title: shift.title),
),
backgroundColor: Colors.green, backgroundColor: Colors.green,
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
), ),
@@ -33,7 +32,7 @@ class RecommendedShiftCard extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.krowBorder), border: Border.all(color: UiColors.border),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withValues(alpha: 0.02), color: Colors.black.withValues(alpha: 0.02),
@@ -108,7 +107,7 @@ class RecommendedShiftCard extends StatelessWidget {
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 16, fontSize: 16,
color: AppColors.krowCharcoal, color: UiColors.foreground,
), ),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@@ -119,7 +118,7 @@ class RecommendedShiftCard extends StatelessWidget {
style: const TextStyle( style: const TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.krowCharcoal, color: UiColors.foreground,
), ),
), ),
], ],
@@ -132,14 +131,14 @@ class RecommendedShiftCard extends StatelessWidget {
shift.clientName, shift.clientName,
style: const TextStyle( style: const TextStyle(
fontSize: 12, fontSize: 12,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
), ),
Text( Text(
'\$${shift.hourlyRate.toStringAsFixed(0)}/hr • ${duration}h', '\$${shift.hourlyRate.toStringAsFixed(0)}/hr • ${duration}h',
style: const TextStyle( style: const TextStyle(
fontSize: 10, fontSize: 10,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
), ),
], ],
@@ -155,21 +154,21 @@ class RecommendedShiftCard extends StatelessWidget {
const Icon( const Icon(
LucideIcons.calendar, LucideIcons.calendar,
size: 14, size: 14,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
recI18n.today, recI18n.today,
style: const TextStyle( style: const TextStyle(
fontSize: 12, fontSize: 12,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
const Icon( const Icon(
LucideIcons.clock, LucideIcons.clock,
size: 14, size: 14,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
@@ -179,7 +178,7 @@ class RecommendedShiftCard extends StatelessWidget {
), ),
style: const TextStyle( style: const TextStyle(
fontSize: 12, fontSize: 12,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
), ),
], ],
@@ -190,7 +189,7 @@ class RecommendedShiftCard extends StatelessWidget {
const Icon( const Icon(
LucideIcons.mapPin, LucideIcons.mapPin,
size: 14, size: 14,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
Expanded( Expanded(
@@ -198,7 +197,7 @@ class RecommendedShiftCard extends StatelessWidget {
shift.locationAddress ?? shift.location, shift.locationAddress ?? shift.location,
style: const TextStyle( style: const TextStyle(
fontSize: 12, fontSize: 12,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lucide_icons/lucide_icons.dart'; import 'package:lucide_icons/lucide_icons.dart';
import 'package:staff_home/src/theme.dart';
import 'package:design_system/design_system.dart';
class SectionHeader extends StatelessWidget { class SectionHeader extends StatelessWidget {
final String title; final String title;
@@ -26,7 +27,7 @@ class SectionHeader extends StatelessWidget {
style: const TextStyle( style: const TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.krowCharcoal, color: UiColors.foreground,
), ),
), ),
if (action != null) if (action != null)
@@ -38,7 +39,7 @@ class SectionHeader extends StatelessWidget {
Text( Text(
action!, action!,
style: const TextStyle( style: const TextStyle(
color: AppColors.krowBlue, color: UiColors.primary,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
@@ -46,7 +47,7 @@ class SectionHeader extends StatelessWidget {
const Icon( const Icon(
LucideIcons.chevronRight, LucideIcons.chevronRight,
size: 16, size: 16,
color: AppColors.krowBlue, color: UiColors.primary,
), ),
], ],
), ),
@@ -55,10 +56,10 @@ 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: AppColors.krowBlue.withValues(alpha: 0.08), color: UiColors.primary.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all( border: Border.all(
color: AppColors.krowBlue.withValues(alpha: 0.2), color: UiColors.primary.withValues(alpha: 0.2),
), ),
), ),
child: Text( child: Text(
@@ -66,7 +67,7 @@ class SectionHeader extends StatelessWidget {
style: const TextStyle( style: const TextStyle(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: AppColors.krowBlue, color: UiColors.primary,
), ),
), ),
), ),

View File

@@ -3,8 +3,8 @@ import 'package:flutter_modular/flutter_modular.dart';
import 'package:lucide_icons/lucide_icons.dart'; import 'package:lucide_icons/lucide_icons.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:staff_home/src/domain/models/shift.dart'; import 'package:design_system/design_system.dart';
import 'package:staff_home/src/theme.dart'; import 'package:staff_home/src/domain/entities/shift.dart';
class ShiftCard extends StatefulWidget { class ShiftCard extends StatefulWidget {
final Shift shift; final Shift shift;
@@ -65,7 +65,6 @@ class _ShiftCardState extends State<ShiftCard> {
} }
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (widget.compact) { if (widget.compact) {
@@ -85,7 +84,7 @@ class _ShiftCardState extends State<ShiftCard> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.krowBorder), border: Border.all(color: UiColors.border),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withValues(alpha: 0.05), color: Colors.black.withValues(alpha: 0.05),
@@ -102,7 +101,7 @@ class _ShiftCardState extends State<ShiftCard> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all(color: AppColors.krowBorder), border: Border.all(color: UiColors.border),
), ),
child: widget.shift.logoUrl != null child: widget.shift.logoUrl != null
? ClipRRect( ? ClipRRect(
@@ -114,7 +113,7 @@ class _ShiftCardState extends State<ShiftCard> {
) )
: const Icon( : const Icon(
LucideIcons.building2, LucideIcons.building2,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
@@ -130,7 +129,7 @@ class _ShiftCardState extends State<ShiftCard> {
widget.shift.title, widget.shift.title,
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.krowCharcoal, color: UiColors.foreground,
), ),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@@ -141,7 +140,7 @@ class _ShiftCardState extends State<ShiftCard> {
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 16, fontSize: 16,
color: AppColors.krowCharcoal, color: UiColors.foreground,
), ),
children: const [ children: const [
TextSpan( TextSpan(
@@ -159,7 +158,7 @@ class _ShiftCardState extends State<ShiftCard> {
Text( Text(
widget.shift.clientName, widget.shift.clientName,
style: const TextStyle( style: const TextStyle(
color: AppColors.krowMuted, color: UiColors.mutedForeground,
fontSize: 13, fontSize: 13,
), ),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@@ -168,7 +167,7 @@ class _ShiftCardState extends State<ShiftCard> {
Text( Text(
'${_formatTime(widget.shift.startTime)}${widget.shift.location}', '${_formatTime(widget.shift.startTime)}${widget.shift.location}',
style: const TextStyle( style: const TextStyle(
color: AppColors.krowMuted, color: UiColors.mutedForeground,
fontSize: 12, fontSize: 12,
), ),
), ),
@@ -186,7 +185,7 @@ class _ShiftCardState extends State<ShiftCard> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.krowBorder), border: Border.all(color: UiColors.border),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withValues(alpha: 0.05), color: Colors.black.withValues(alpha: 0.05),
@@ -211,7 +210,7 @@ class _ShiftCardState extends State<ShiftCard> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all(color: AppColors.krowBorder), border: Border.all(color: UiColors.border),
), ),
child: widget.shift.logoUrl != null child: widget.shift.logoUrl != null
? ClipRRect( ? ClipRRect(
@@ -224,7 +223,7 @@ class _ShiftCardState extends State<ShiftCard> {
: const Icon( : const Icon(
LucideIcons.building2, LucideIcons.building2,
size: 28, size: 28,
color: AppColors.krowBlue, color: UiColors.primary,
), ),
), ),
Container( Container(
@@ -233,7 +232,7 @@ class _ShiftCardState extends State<ShiftCard> {
vertical: 6, vertical: 6,
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.krowBlue, color: UiColors.primary,
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
), ),
child: Text( child: Text(
@@ -263,13 +262,13 @@ class _ShiftCardState extends State<ShiftCard> {
style: const TextStyle( style: const TextStyle(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.krowCharcoal, color: UiColors.foreground,
), ),
), ),
Text( Text(
widget.shift.clientName, widget.shift.clientName,
style: const TextStyle( style: const TextStyle(
color: AppColors.krowMuted, color: UiColors.mutedForeground,
fontSize: 14, fontSize: 14,
), ),
), ),
@@ -282,7 +281,7 @@ class _ShiftCardState extends State<ShiftCard> {
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 20, fontSize: 20,
color: AppColors.krowCharcoal, color: UiColors.foreground,
), ),
children: const [ children: const [
TextSpan( TextSpan(
@@ -305,14 +304,14 @@ class _ShiftCardState extends State<ShiftCard> {
const Icon( const Icon(
LucideIcons.mapPin, LucideIcons.mapPin,
size: 16, size: 16,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
Expanded( Expanded(
child: Text( child: Text(
widget.shift.location, widget.shift.location,
style: const TextStyle( style: const TextStyle(
color: AppColors.krowMuted, color: UiColors.mutedForeground,
fontSize: 14, fontSize: 14,
), ),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@@ -322,13 +321,13 @@ class _ShiftCardState extends State<ShiftCard> {
const Icon( const Icon(
LucideIcons.calendar, LucideIcons.calendar,
size: 16, size: 16,
color: AppColors.krowMuted, color: UiColors.mutedForeground,
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
Text( Text(
'${_formatDate(widget.shift.date)}, ${_formatTime(widget.shift.startTime)}', '${_formatDate(widget.shift.date)}, ${_formatTime(widget.shift.startTime)}',
style: const TextStyle( style: const TextStyle(
color: AppColors.krowMuted, color: UiColors.mutedForeground,
fontSize: 14, fontSize: 14,
), ),
), ),
@@ -344,8 +343,8 @@ class _ShiftCardState extends State<ShiftCard> {
_buildTag( _buildTag(
LucideIcons.zap, LucideIcons.zap,
'Immediate start', 'Immediate start',
AppColors.krowYellow.withValues(alpha: 0.3), UiColors.accent.withValues(alpha: 0.3),
AppColors.krowCharcoal, UiColors.foreground,
), ),
_buildTag( _buildTag(
LucideIcons.timer, LucideIcons.timer,
@@ -373,7 +372,7 @@ class _ShiftCardState extends State<ShiftCard> {
child: ElevatedButton( child: ElevatedButton(
onPressed: widget.onApply, onPressed: widget.onApply,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: AppColors.krowCharcoal, backgroundColor: UiColors.foreground,
foregroundColor: Colors.white, foregroundColor: Colors.white,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
@@ -439,6 +438,4 @@ class _ShiftCardState extends State<ShiftCard> {
), ),
); );
} }
} }

View File

@@ -39,7 +39,7 @@ class _AutoMatchToggleState extends State<AutoMatchToggle>
boxShadow: widget.enabled boxShadow: widget.enabled
? [ ? [
BoxShadow( BoxShadow(
color: const Color(0xFF0032A0).withOpacity(0.3), color: const Color(0xFF0032A0).withValues(alpha: 0.3),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@@ -58,8 +58,8 @@ class _AutoMatchToggleState extends State<AutoMatchToggle>
height: 40, height: 40,
decoration: BoxDecoration( decoration: BoxDecoration(
color: widget.enabled color: widget.enabled
? Colors.white.withOpacity(0.2) ? Colors.white.withValues(alpha: 0.2)
: const Color(0xFF0032A0).withOpacity(0.1), : const Color(0xFF0032A0).withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
child: Icon( child: Icon(
@@ -100,7 +100,7 @@ class _AutoMatchToggleState extends State<AutoMatchToggle>
value: widget.enabled, value: widget.enabled,
onChanged: widget.onToggle, onChanged: widget.onToggle,
activeThumbColor: Colors.white, activeThumbColor: Colors.white,
activeTrackColor: Colors.white.withOpacity(0.3), activeTrackColor: Colors.white.withValues(alpha: 0.3),
inactiveThumbColor: Colors.white, inactiveThumbColor: Colors.white,
inactiveTrackColor: Colors.grey.shade300, inactiveTrackColor: Colors.grey.shade300,
), ),
@@ -115,7 +115,7 @@ class _AutoMatchToggleState extends State<AutoMatchToggle>
const SizedBox(height: 16), const SizedBox(height: 16),
Container( Container(
height: 1, height: 1,
color: Colors.white.withOpacity(0.2), color: Colors.white.withValues(alpha: 0.2),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
@@ -150,7 +150,7 @@ class _AutoMatchToggleState extends State<AutoMatchToggle>
return Container( return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2), color: Colors.white.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: Row( child: Row(

View File

@@ -6,12 +6,23 @@ import 'package:staff_home/src/domain/repositories/home_repository.dart';
import 'package:staff_home/src/presentation/blocs/home_cubit.dart'; import 'package:staff_home/src/presentation/blocs/home_cubit.dart';
import 'package:staff_home/src/presentation/pages/worker_home_page.dart'; import 'package:staff_home/src/presentation/pages/worker_home_page.dart';
/// The module for the staff home feature.
///
/// This module provides dependency injection bindings for the home feature
/// following Clean Architecture principles. It injects the repository
/// implementation and state management components.
class StaffHomeModule extends Module { class StaffHomeModule extends Module {
@override @override
void binds(Injector i) { void binds(Injector i) {
// Data layer - Mock service (will be replaced with real implementation)
i.addLazySingleton<MockService>(MockService.new);
// Repository
i.addLazySingleton<HomeRepository>( i.addLazySingleton<HomeRepository>(
() => HomeRepositoryImpl(mockService), () => HomeRepositoryImpl(i.get<MockService>()),
); );
// Presentation layer - Cubit
i.addSingleton(HomeCubit.new); i.addSingleton(HomeCubit.new);
} }

View File

@@ -1,51 +0,0 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class AppColors {
static const Color krowBlue = Color(0xFF0A39DF);
static const Color krowYellow = Color(0xFFFFED4A);
static const Color krowCharcoal = Color(0xFF121826);
static const Color krowMuted = Color(0xFF6A7382);
static const Color krowBorder = Color(0xFFE3E6E9);
static const Color krowBackground = Color(0xFFFAFBFC);
static const Color white = Colors.white;
static const Color black = Colors.black;
// helpers used by prototype (withValues extension in prototype); keep simple aliases
static Color withAlpha(Color c, double alpha) => c.withOpacity(alpha);
}
class AppTheme {
static ThemeData get lightTheme {
return ThemeData(
useMaterial3: true,
scaffoldBackgroundColor: AppColors.krowBackground,
colorScheme: ColorScheme.fromSeed(
seedColor: AppColors.krowBlue,
primary: AppColors.krowBlue,
secondary: AppColors.krowYellow,
surface: AppColors.white,
background: AppColors.krowBackground,
),
textTheme: GoogleFonts.instrumentSansTextTheme().apply(
bodyColor: AppColors.krowCharcoal,
displayColor: AppColors.krowCharcoal,
),
appBarTheme: const AppBarTheme(
backgroundColor: AppColors.krowBackground,
elevation: 0,
iconTheme: IconThemeData(color: AppColors.krowCharcoal),
titleTextStyle: TextStyle(
color: AppColors.krowCharcoal,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
);
}
}
extension ColorWithValues on Color {
Color withValues({double alpha = 1.0}) => withOpacity(alpha);
}

View File

@@ -1,3 +1,8 @@
/// Staff Home Feature Library
///
/// This library exports the public API for the staff home feature,
/// following Clean Architecture principles. Only the module is exported
/// as it contains all necessary bindings and routes for integration.
library; library;
export 'src/staff_home_module.dart'; export 'src/staff_home_module.dart';