Add explicit types and improve type safety across codebase

This commit adds explicit type annotations to variables, function parameters, and return types throughout the codebase, particularly in widget trees, Bloc logic, and repository implementations. The changes improve code readability, maintainability, and type safety, and align with Dart best practices. No business logic was changed.
This commit is contained in:
Achintha Isuru
2026-01-24 10:00:36 -05:00
parent ff93bfa4bd
commit f57f41c508
99 changed files with 495 additions and 485 deletions

View File

@@ -18,7 +18,7 @@ export 'src/presentation/navigation/client_home_navigator.dart';
/// including repositories, use cases, and BLoCs.
class ClientHomeModule extends Module {
@override
List<Module> get imports => [DataConnectModule()];
List<Module> get imports => <Module>[DataConnectModule()];
@override
void binds(Injector i) {
@@ -41,7 +41,7 @@ class ClientHomeModule extends Module {
}
@override
void routes(r) {
void routes(RouteManager r) {
r.child('/', child: (_) => const ClientHomePage());
}
}

View File

@@ -21,7 +21,7 @@ class HomeRepositoryImpl implements HomeRepositoryInterface {
@override
UserSessionData getUserSessionData() {
final (businessName, photoUrl) = _mock.getUserSession();
final (String businessName, String? photoUrl) = _mock.getUserSession();
return UserSessionData(
businessName: businessName,
photoUrl: photoUrl,

View File

@@ -1,4 +1,6 @@
import 'package:client_home/src/domain/repositories/home_repository_interface.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_domain/src/entities/home/home_dashboard_data.dart';
import '../../domain/usecases/get_dashboard_data_usecase.dart';
import '../../domain/usecases/get_user_session_data_usecase.dart';
import 'client_home_event.dart';
@@ -29,10 +31,10 @@ class ClientHomeBloc extends Bloc<ClientHomeEvent, ClientHomeState> {
emit(state.copyWith(status: ClientHomeStatus.loading));
try {
// Get session data
final sessionData = _getUserSessionDataUseCase();
final UserSessionData sessionData = _getUserSessionDataUseCase();
// Get dashboard data
final data = await _getDashboardDataUseCase();
final HomeDashboardData data = await _getDashboardDataUseCase();
emit(
state.copyWith(
@@ -63,7 +65,7 @@ class ClientHomeBloc extends Bloc<ClientHomeEvent, ClientHomeState> {
ClientHomeWidgetVisibilityToggled event,
Emitter<ClientHomeState> emit,
) {
final newVisibility = Map<String, bool>.from(state.widgetVisibility);
final Map<String, bool> newVisibility = Map<String, bool>.from(state.widgetVisibility);
newVisibility[event.widgetId] = !(newVisibility[event.widgetId] ?? true);
emit(state.copyWith(widgetVisibility: newVisibility));
}
@@ -72,14 +74,14 @@ class ClientHomeBloc extends Bloc<ClientHomeEvent, ClientHomeState> {
ClientHomeWidgetReordered event,
Emitter<ClientHomeState> emit,
) {
final newList = List<String>.from(state.widgetOrder);
final List<String> newList = List<String>.from(state.widgetOrder);
int oldIndex = event.oldIndex;
int newIndex = event.newIndex;
if (oldIndex < newIndex) {
newIndex -= 1;
}
final item = newList.removeAt(oldIndex);
final String item = newList.removeAt(oldIndex);
newList.insert(newIndex, item);
emit(state.copyWith(widgetOrder: newList));
@@ -91,14 +93,14 @@ class ClientHomeBloc extends Bloc<ClientHomeEvent, ClientHomeState> {
) {
emit(
state.copyWith(
widgetOrder: const [
widgetOrder: const <String>[
'actions',
'reorder',
'coverage',
'spending',
'liveActivity',
],
widgetVisibility: const {
widgetVisibility: const <String, bool>{
'actions': true,
'reorder': true,
'coverage': true,

View File

@@ -4,7 +4,7 @@ abstract class ClientHomeEvent extends Equatable {
const ClientHomeEvent();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class ClientHomeStarted extends ClientHomeEvent {}
@@ -16,7 +16,7 @@ class ClientHomeWidgetVisibilityToggled extends ClientHomeEvent {
const ClientHomeWidgetVisibilityToggled(this.widgetId);
@override
List<Object?> get props => [widgetId];
List<Object?> get props => <Object?>[widgetId];
}
class ClientHomeWidgetReordered extends ClientHomeEvent {
@@ -25,7 +25,7 @@ class ClientHomeWidgetReordered extends ClientHomeEvent {
const ClientHomeWidgetReordered(this.oldIndex, this.newIndex);
@override
List<Object?> get props => [oldIndex, newIndex];
List<Object?> get props => <Object?>[oldIndex, newIndex];
}
class ClientHomeLayoutReset extends ClientHomeEvent {}

View File

@@ -17,10 +17,10 @@ class ClientHomeState extends Equatable {
const ClientHomeState({
this.status = ClientHomeStatus.initial,
this.widgetOrder = const [
this.widgetOrder = const <String>[
'actions',
],
this.widgetVisibility = const {
this.widgetVisibility = const <String, bool>{
'actions': true,
},
this.isEditMode = false,
@@ -60,7 +60,7 @@ class ClientHomeState extends Equatable {
}
@override
List<Object?> get props => [
List<Object?> get props => <Object?>[
status,
widgetOrder,
widgetVisibility,

View File

@@ -31,10 +31,10 @@ class ClientHomeSheets {
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) {
builder: (BuildContext context) {
return ShiftOrderFormSheet(
initialData: initialData,
onSubmit: (data) {
onSubmit: (Map<String, dynamic> data) {
Navigator.pop(context);
onSubmit(data);
},

View File

@@ -21,20 +21,20 @@ class ClientHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final i18n = t.client_home;
final TranslationsClientHomeEn i18n = t.client_home;
return BlocProvider<ClientHomeBloc>(
create: (context) =>
create: (BuildContext context) =>
Modular.get<ClientHomeBloc>()..add(ClientHomeStarted()),
child: Scaffold(
body: SafeArea(
child: Column(
children: [
children: <Widget>[
ClientHomeHeader(i18n: i18n),
ClientHomeEditBanner(i18n: i18n),
Flexible(
child: BlocBuilder<ClientHomeBloc, ClientHomeState>(
builder: (context, state) {
builder: (BuildContext context, ClientHomeState state) {
if (state.isEditMode) {
return _buildEditModeList(context, state);
}
@@ -58,12 +58,12 @@ class ClientHomePage extends StatelessWidget {
UiConstants.space4,
100,
),
onReorder: (oldIndex, newIndex) {
onReorder: (int oldIndex, int newIndex) {
BlocProvider.of<ClientHomeBloc>(context).add(
ClientHomeWidgetReordered(oldIndex, newIndex),
);
},
children: state.widgetOrder.map((id) {
children: state.widgetOrder.map((String id) {
return Container(
key: ValueKey(id),
margin: const EdgeInsets.only(bottom: UiConstants.space4),
@@ -86,7 +86,7 @@ class ClientHomePage extends StatelessWidget {
UiConstants.space4,
100,
),
children: state.widgetOrder.map((id) {
children: state.widgetOrder.map((String id) {
return Padding(
padding: const EdgeInsets.only(bottom: UiConstants.space4),
child: DashboardWidgetBuilder(

View File

@@ -20,10 +20,10 @@ class ActionsWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Check if client_home exists in t
final i18n = t.client_home.actions;
final TranslationsClientHomeActionsEn i18n = t.client_home.actions;
return Row(
children: [
children: <Widget>[
Expanded(
child: _ActionCard(
title: i18n.rapid,
@@ -96,7 +96,7 @@ class _ActionCard extends StatelessWidget {
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
children: <Widget>[
Container(
width: 36,
height: 36,

View File

@@ -22,8 +22,8 @@ class ClientHomeEditBanner extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<ClientHomeBloc, ClientHomeState>(
buildWhen: (prev, curr) => prev.isEditMode != curr.isEditMode,
builder: (context, state) {
buildWhen: (ClientHomeState prev, ClientHomeState curr) => prev.isEditMode != curr.isEditMode,
builder: (BuildContext context, ClientHomeState state) {
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
height: state.isEditMode ? 76 : 0,
@@ -40,13 +40,13 @@ class ClientHomeEditBanner extends StatelessWidget {
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
const Icon(UiIcons.edit, size: 16, color: UiColors.primary),
const SizedBox(width: UiConstants.space2),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
children: <Widget>[
Text(
i18n.dashboard.edit_mode_active,
style: UiTypography.footnote1b.copyWith(

View File

@@ -25,10 +25,10 @@ class ClientHomeHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<ClientHomeBloc, ClientHomeState>(
builder: (context, state) {
final businessName = state.businessName;
final photoUrl = state.photoUrl;
final avatarLetter = businessName.trim().isNotEmpty
builder: (BuildContext context, ClientHomeState state) {
final String businessName = state.businessName;
final String? photoUrl = state.photoUrl;
final String avatarLetter = businessName.trim().isNotEmpty
? businessName.trim()[0].toUpperCase()
: 'C';
@@ -41,9 +41,9 @@ class ClientHomeHeader extends StatelessWidget {
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
Container(
width: 40,
height: 40,
@@ -73,7 +73,7 @@ class ClientHomeHeader extends StatelessWidget {
const SizedBox(width: UiConstants.space3),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
i18n.dashboard.welcome_back,
style: UiTypography.footnote2r.textSecondary,

View File

@@ -23,32 +23,32 @@ class CoverageDashboard extends StatelessWidget {
double todayCost = 0;
for (final s in shifts) {
final needed = s['workersNeeded'] as int? ?? 0;
final confirmed = s['filled'] as int? ?? 0;
final rate = s['hourlyRate'] as double? ?? 20.0;
final int needed = s['workersNeeded'] as int? ?? 0;
final int confirmed = s['filled'] as int? ?? 0;
final double rate = s['hourlyRate'] as double? ?? 20.0;
totalNeeded += needed;
totalConfirmed += confirmed;
todayCost += rate * 8 * confirmed;
}
final coveragePercent = totalNeeded > 0
final int coveragePercent = totalNeeded > 0
? ((totalConfirmed / totalNeeded) * 100).round()
: 100;
final unfilledPositions = totalNeeded - totalConfirmed;
final int unfilledPositions = totalNeeded - totalConfirmed;
final checkedInCount = applications
final int checkedInCount = applications
.where((a) => (a as Map)['checkInTime'] != null)
.length;
final lateWorkersCount = applications
final int lateWorkersCount = applications
.where((a) => (a as Map)['status'] == 'LATE')
.length;
final isCoverageGood = coveragePercent >= 90;
final coverageBadgeColor = isCoverageGood
final bool isCoverageGood = coveragePercent >= 90;
final Color coverageBadgeColor = isCoverageGood
? const Color(0xFFD1FAE5) // TODO: Use design system color if available
: const Color(0xFFFEF3C7);
final coverageTextColor = isCoverageGood
final Color coverageTextColor = isCoverageGood
? const Color(0xFF047857)
: const Color(0xFFB45309);
@@ -58,7 +58,7 @@ class CoverageDashboard extends StatelessWidget {
color: UiColors.white,
borderRadius: UiConstants.radiusLg,
border: Border.all(color: UiColors.border),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withValues(alpha: 0.02),
blurRadius: 4,
@@ -67,10 +67,10 @@ class CoverageDashboard extends StatelessWidget {
],
),
child: Column(
children: [
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Text("Today's Status", style: UiTypography.body1m.textSecondary),
Container(
padding: const EdgeInsets.symmetric(
@@ -94,17 +94,17 @@ class CoverageDashboard extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Expanded(
child: Column(
children: [
children: <Widget>[
_StatusCard(
label: 'Unfilled Today',
value: '$unfilledPositions',
icon: UiIcons.warning,
isWarning: unfilledPositions > 0,
),
if (lateWorkersCount > 0) ...[
if (lateWorkersCount > 0) ...<Widget>[
const SizedBox(height: UiConstants.space2),
_StatusCard(
label: 'Running Late',
@@ -119,7 +119,7 @@ class CoverageDashboard extends StatelessWidget {
const SizedBox(width: UiConstants.space2),
Expanded(
child: Column(
children: [
children: <Widget>[
_StatusCard(
label: 'Checked In',
value: '$checkedInCount/$totalConfirmed',
@@ -194,9 +194,9 @@ class _StatusCard extends StatelessWidget {
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
Icon(icon, size: 16, color: iconColor),
const SizedBox(width: UiConstants.space2),
Expanded(

View File

@@ -23,10 +23,10 @@ class CoverageWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Text(
"TODAY'S COVERAGE",
style: UiTypography.footnote1b.copyWith(
@@ -55,7 +55,7 @@ class CoverageWidget extends StatelessWidget {
),
const SizedBox(height: UiConstants.space2),
Row(
children: [
children: <Widget>[
Expanded(
child: _MetricCard(
icon: UiIcons.target,
@@ -114,7 +114,7 @@ class _MetricCard extends StatelessWidget {
color: UiColors.cardViewBackground,
borderRadius: UiConstants.radiusLg,
border: Border.all(color: UiColors.border),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withValues(alpha: 0.02),
blurRadius: 2,
@@ -123,9 +123,9 @@ class _MetricCard extends StatelessWidget {
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
Icon(icon, size: 14, color: iconColor),
const SizedBox(width: 6), // 6px
Text(

View File

@@ -34,8 +34,8 @@ class DashboardWidgetBuilder extends StatelessWidget {
@override
Widget build(BuildContext context) {
final i18n = t.client_home.widgets;
final widgetContent = _buildWidgetContent(context);
final TranslationsClientHomeWidgetsEn i18n = t.client_home.widgets;
final Widget widgetContent = _buildWidgetContent(context);
if (isEditMode) {
return DraggableWidgetWrapper(
@@ -64,11 +64,11 @@ class DashboardWidgetBuilder extends StatelessWidget {
);
case 'reorder':
return ReorderWidget(
onReorderPressed: (data) {
onReorderPressed: (Map<String, dynamic> data) {
ClientHomeSheets.showOrderFormSheet(
context,
data,
onSubmit: (submittedData) {
onSubmit: (Map<String, dynamic> submittedData) {
// Handle form submission if needed
},
);

View File

@@ -34,9 +34,9 @@ class DraggableWidgetWrapper extends StatelessWidget {
Widget build(BuildContext context) {
return Column(
spacing: UiConstants.space2,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
Container(
padding: const EdgeInsets.symmetric(
horizontal: UiConstants.space2,
@@ -48,7 +48,7 @@ class DraggableWidgetWrapper extends StatelessWidget {
border: Border.all(color: UiColors.border),
),
child: Row(
children: [
children: <Widget>[
const Icon(
UiIcons.gripVertical,
size: 14,

View File

@@ -33,14 +33,14 @@ class HeaderIconButton extends StatelessWidget {
onTap: onTap,
child: Stack(
clipBehavior: Clip.none,
children: [
children: <Widget>[
Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: isActive ? UiColors.primary : UiColors.white,
borderRadius: UiConstants.radiusMd,
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
blurRadius: 2,

View File

@@ -13,18 +13,18 @@ class LiveActivityWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final i18n = t.client_home;
final TranslationsClientHomeEn i18n = t.client_home;
// Mock data
final shifts = [
{
final List<Map<String, Object>> shifts = <Map<String, Object>>[
<String, Object>{
'workersNeeded': 5,
'filled': 4,
'hourlyRate': 20.0,
'status': 'OPEN',
'date': DateTime.now().toIso8601String().split('T')[0],
},
{
<String, Object>{
'workersNeeded': 5,
'filled': 5,
'hourlyRate': 22.0,
@@ -32,18 +32,18 @@ class LiveActivityWidget extends StatelessWidget {
'date': DateTime.now().toIso8601String().split('T')[0],
},
];
final applications = [
{'status': 'CONFIRMED', 'checkInTime': '09:00'},
{'status': 'CONFIRMED', 'checkInTime': '09:05'},
{'status': 'CONFIRMED'},
{'status': 'LATE'},
final List<Map<String, String>> applications = <Map<String, String>>[
<String, String>{'status': 'CONFIRMED', 'checkInTime': '09:00'},
<String, String>{'status': 'CONFIRMED', 'checkInTime': '09:05'},
<String, String>{'status': 'CONFIRMED'},
<String, String>{'status': 'LATE'},
];
return Column(
children: [
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Text(
i18n.widgets.live_activity.toUpperCase(),
style: UiTypography.footnote1b.textSecondary.copyWith(

View File

@@ -12,11 +12,11 @@ class ReorderWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final i18n = t.client_home.reorder;
final TranslationsClientHomeReorderEn i18n = t.client_home.reorder;
// Mock recent orders
final recentOrders = [
{
final List<Map<String, Object>> recentOrders = <Map<String, Object>>[
<String, Object>{
'title': 'Server',
'location': 'Downtown Restaurant',
'hourlyRate': 18.0,
@@ -24,7 +24,7 @@ class ReorderWidget extends StatelessWidget {
'workers': 3,
'type': 'One Day',
},
{
<String, Object>{
'title': 'Bartender',
'location': 'Rooftop Bar',
'hourlyRate': 22.0,
@@ -32,7 +32,7 @@ class ReorderWidget extends StatelessWidget {
'workers': 2,
'type': 'One Day',
},
{
<String, Object>{
'title': 'Event Staff',
'location': 'Convention Center',
'hourlyRate': 20.0,
@@ -44,7 +44,7 @@ class ReorderWidget extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
i18n.title,
style: UiTypography.footnote1b.textSecondary.copyWith(
@@ -57,11 +57,11 @@ class ReorderWidget extends StatelessWidget {
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: recentOrders.length,
separatorBuilder: (context, index) =>
separatorBuilder: (BuildContext context, int index) =>
const SizedBox(width: UiConstants.space3),
itemBuilder: (context, index) {
final order = recentOrders[index];
final totalCost =
itemBuilder: (BuildContext context, int index) {
final Map<String, Object> order = recentOrders[index];
final double totalCost =
(order['hourlyRate'] as double) *
(order['hours'] as int) *
(order['workers'] as int);
@@ -73,7 +73,7 @@ class ReorderWidget extends StatelessWidget {
color: UiColors.white,
borderRadius: UiConstants.radiusLg,
border: Border.all(color: UiColors.border),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withValues(alpha: 0.02),
blurRadius: 4,
@@ -82,13 +82,13 @@ class ReorderWidget extends StatelessWidget {
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Expanded(
child: Row(
children: [
children: <Widget>[
Container(
width: 36,
height: 36,
@@ -108,7 +108,7 @@ class ReorderWidget extends StatelessWidget {
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
order['title'] as String,
style: UiTypography.body2b,
@@ -128,7 +128,7 @@ class ReorderWidget extends StatelessWidget {
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
children: <Widget>[
Text(
'\$${totalCost.toStringAsFixed(0)}',
style: UiTypography.body1b,
@@ -146,7 +146,7 @@ class ReorderWidget extends StatelessWidget {
),
const SizedBox(height: UiConstants.space3),
Row(
children: [
children: <Widget>[
_Badge(
icon: UiIcons.success,
text: order['type'] as String,
@@ -222,7 +222,7 @@ class _Badge extends StatelessWidget {
decoration: BoxDecoration(color: bg, borderRadius: UiConstants.radiusSm),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
children: <Widget>[
Icon(icon, size: 10, color: bg == textColor ? UiColors.white : color),
const SizedBox(width: UiConstants.space1),
Text(text, style: UiTypography.footnote2b.copyWith(color: textColor)),

View File

@@ -34,7 +34,7 @@ class _ShiftOrderFormSheetState extends State<ShiftOrderFormSheet> {
late List<Map<String, dynamic>> _positions;
final List<String> _roles = [
final List<String> _roles = <String>[
'Server',
'Bartender',
'Cook',
@@ -48,11 +48,11 @@ class _ShiftOrderFormSheetState extends State<ShiftOrderFormSheet> {
];
// Vendor options
final List<Map<String, dynamic>> _vendors = [
{
final List<Map<String, dynamic>> _vendors = <Map<String, dynamic>>[
<String, dynamic>{
'id': 'v1',
'name': 'Elite Staffing',
'rates': {
'rates': <String, double>{
'Server': 25.0,
'Bartender': 30.0,
'Cook': 28.0,
@@ -63,10 +63,10 @@ class _ShiftOrderFormSheetState extends State<ShiftOrderFormSheet> {
'Event Staff': 19.0,
},
},
{
<String, dynamic>{
'id': 'v2',
'name': 'Premier Workforce',
'rates': {
'rates': <String, double>{
'Server': 22.0,
'Bartender': 28.0,
'Cook': 25.0,
@@ -81,7 +81,7 @@ class _ShiftOrderFormSheetState extends State<ShiftOrderFormSheet> {
String? _selectedVendorId;
final List<int> _lunchBreakOptions = [0, 30, 45, 60];
final List<int> _lunchBreakOptions = <int>[0, 30, 45, 60];
@override
void initState() {
@@ -427,7 +427,7 @@ class _ShiftOrderFormSheetState extends State<ShiftOrderFormSheet> {
style: UiTypography.body2r.textPrimary,
items: _vendors
.map(
(vendor) => DropdownMenuItem<String>(
(Map<String, dynamic> vendor) => DropdownMenuItem<String>(
value: vendor['id'],
child: Text(vendor['name']),
),
@@ -565,7 +565,7 @@ class _ShiftOrderFormSheetState extends State<ShiftOrderFormSheet> {
items: _roles,
itemBuilder: (dynamic role) {
final Map<String, dynamic>? vendor = _vendors.firstWhere(
(v) => v['id'] == _selectedVendorId,
(Map<String, dynamic> v) => v['id'] == _selectedVendorId,
orElse: () => _vendors.first,
);
final Map<String, dynamic>? rates = vendor?['rates'] as Map<String, dynamic>?;

View File

@@ -27,11 +27,11 @@ class SpendingWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final i18n = t.client_home;
final TranslationsClientHomeEn i18n = t.client_home;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
i18n.widgets.spending.toUpperCase(),
style: UiTypography.footnote1b.textSecondary.copyWith(
@@ -43,12 +43,12 @@ class SpendingWidget extends StatelessWidget {
padding: const EdgeInsets.all(UiConstants.space3),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [UiColors.primary, Color(0xFF0830B8)],
colors: <Color>[UiColors.primary, Color(0xFF0830B8)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: UiConstants.radiusLg,
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.primary.withValues(alpha: 0.3),
blurRadius: 4,
@@ -57,13 +57,13 @@ class SpendingWidget extends StatelessWidget {
],
),
child: Column(
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
const Text(
'This Week',
style: TextStyle(color: Colors.white70, fontSize: 9),
@@ -89,7 +89,7 @@ class SpendingWidget extends StatelessWidget {
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
children: <Widget>[
const Text(
'Next 7 Days',
style: TextStyle(color: Colors.white70, fontSize: 9),
@@ -122,7 +122,7 @@ class SpendingWidget extends StatelessWidget {
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Container(
width: 24,
height: 24,
@@ -142,7 +142,7 @@ class SpendingWidget extends StatelessWidget {
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
'💡 ' +
i18n.dashboard.insight_lightbulb(amount: '180'),