fix: add ignore_for_file to data connect Repos and modify CI to avoid analyzing deleted files

This commit is contained in:
2026-02-20 19:51:44 +05:30
parent 24835f127e
commit 474be43448
259 changed files with 1810 additions and 1714 deletions

View File

@@ -55,7 +55,7 @@ class ClientAuthBloc extends Bloc<ClientAuthEvent, ClientAuthState>
emit(state.copyWith(status: ClientAuthStatus.loading));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
final User user = await _signInWithEmail(
SignInWithEmailArguments(email: event.email, password: event.password),
@@ -77,7 +77,7 @@ class ClientAuthBloc extends Bloc<ClientAuthEvent, ClientAuthState>
emit(state.copyWith(status: ClientAuthStatus.loading));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
final User user = await _signUpWithEmail(
SignUpWithEmailArguments(
@@ -103,7 +103,7 @@ class ClientAuthBloc extends Bloc<ClientAuthEvent, ClientAuthState>
emit(state.copyWith(status: ClientAuthStatus.loading));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
final User user = await _signInWithSocial(
SignInWithSocialArguments(provider: event.provider),
@@ -125,7 +125,7 @@ class ClientAuthBloc extends Bloc<ClientAuthEvent, ClientAuthState>
emit(state.copyWith(status: ClientAuthStatus.loading));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
await _signOut();
emit(state.copyWith(status: ClientAuthStatus.signedOut, user: null));

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
import 'package:krow_domain/krow_domain.dart';
import '../../domain/repositories/billing_repository.dart';
@@ -7,8 +8,6 @@ import '../../domain/repositories/billing_repository.dart';
/// This implementation follows the "Buffer Layer" pattern by using a dedicated
/// connector repository from the data_connect package.
class BillingRepositoryImpl implements BillingRepository {
final dc.BillingConnectorRepository _connectorRepository;
final dc.DataConnectService _service;
BillingRepositoryImpl({
dc.BillingConnectorRepository? connectorRepository,
@@ -16,28 +15,30 @@ class BillingRepositoryImpl implements BillingRepository {
}) : _connectorRepository = connectorRepository ??
dc.DataConnectService.instance.getBillingRepository(),
_service = service ?? dc.DataConnectService.instance;
final dc.BillingConnectorRepository _connectorRepository;
final dc.DataConnectService _service;
@override
Future<List<BusinessBankAccount>> getBankAccounts() async {
final businessId = await _service.getBusinessId();
final String businessId = await _service.getBusinessId();
return _connectorRepository.getBankAccounts(businessId: businessId);
}
@override
Future<double> getCurrentBillAmount() async {
final businessId = await _service.getBusinessId();
final String businessId = await _service.getBusinessId();
return _connectorRepository.getCurrentBillAmount(businessId: businessId);
}
@override
Future<List<Invoice>> getInvoiceHistory() async {
final businessId = await _service.getBusinessId();
final String businessId = await _service.getBusinessId();
return _connectorRepository.getInvoiceHistory(businessId: businessId);
}
@override
Future<List<Invoice>> getPendingInvoices() async {
final businessId = await _service.getBusinessId();
final String businessId = await _service.getBusinessId();
return _connectorRepository.getPendingInvoices(businessId: businessId);
}
@@ -49,10 +50,11 @@ class BillingRepositoryImpl implements BillingRepository {
@override
Future<List<InvoiceItem>> getSpendingBreakdown(BillingPeriod period) async {
final businessId = await _service.getBusinessId();
final String businessId = await _service.getBusinessId();
return _connectorRepository.getSpendingBreakdown(
businessId: businessId,
period: period,
);
}
}

View File

@@ -47,7 +47,7 @@ class BillingBloc extends Bloc<BillingEvent, BillingState>
) async {
emit(state.copyWith(status: BillingStatus.loading));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
final List<dynamic> results =
await Future.wait<dynamic>(<Future<dynamic>>[
@@ -102,7 +102,7 @@ class BillingBloc extends Bloc<BillingEvent, BillingState>
Emitter<BillingState> emit,
) async {
await handleError(
emit: emit,
emit: emit.call,
action: () async {
final List<InvoiceItem> spendingItems =
await _getSpendingBreakdown.call(event.period);

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
import 'package:krow_domain/krow_domain.dart';
import '../../domain/repositories/coverage_repository.dart';
@@ -7,8 +8,6 @@ import '../../domain/repositories/coverage_repository.dart';
/// This implementation follows the "Buffer Layer" pattern by using a dedicated
/// connector repository from the data_connect package.
class CoverageRepositoryImpl implements CoverageRepository {
final dc.CoverageConnectorRepository _connectorRepository;
final dc.DataConnectService _service;
CoverageRepositoryImpl({
dc.CoverageConnectorRepository? connectorRepository,
@@ -16,10 +15,12 @@ class CoverageRepositoryImpl implements CoverageRepository {
}) : _connectorRepository = connectorRepository ??
dc.DataConnectService.instance.getCoverageRepository(),
_service = service ?? dc.DataConnectService.instance;
final dc.CoverageConnectorRepository _connectorRepository;
final dc.DataConnectService _service;
@override
Future<List<CoverageShift>> getShiftsForDate({required DateTime date}) async {
final businessId = await _service.getBusinessId();
final String businessId = await _service.getBusinessId();
return _connectorRepository.getShiftsForDate(
businessId: businessId,
date: date,
@@ -58,3 +59,4 @@ class CoverageRepositoryImpl implements CoverageRepository {
);
}
}

View File

@@ -43,7 +43,7 @@ class CoverageBloc extends Bloc<CoverageEvent, CoverageState>
);
await handleError(
emit: emit,
emit: emit.call,
action: () async {
// Fetch shifts and stats concurrently
final List<Object> results = await Future.wait<Object>(<Future<Object>>[

View File

@@ -36,7 +36,7 @@ class ClientMainBottomBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
final t = Translations.of(context);
final Translations t = Translations.of(context);
// Client App colors from design system
const Color activeColor = UiColors.textPrimary;
const Color inactiveColor = UiColors.textInactive;

View File

@@ -20,7 +20,7 @@ class ClientCreateOrderBloc
Emitter<ClientCreateOrderState> emit,
) async {
await handleError(
emit: emit,
emit: emit.call,
action: () async {
final List<OrderType> types = await _getOrderTypesUseCase();
emit(ClientCreateOrderLoadSuccess(types));

View File

@@ -220,7 +220,7 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
) async {
emit(state.copyWith(status: OneTimeOrderStatus.loading));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
final Map<String, double> roleRates = <String, double>{
for (final OneTimeOrderRoleOption role in state.roles)

View File

@@ -272,7 +272,7 @@ class PermanentOrderBloc extends Bloc<PermanentOrderEvent, PermanentOrderState>
) async {
emit(state.copyWith(status: PermanentOrderStatus.loading));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
final Map<String, double> roleRates = <String, double>{
for (final PermanentOrderRoleOption role in state.roles)
@@ -280,7 +280,7 @@ class PermanentOrderBloc extends Bloc<PermanentOrderEvent, PermanentOrderState>
};
final PermanentOrderHubOption? selectedHub = state.selectedHub;
if (selectedHub == null) {
throw domain.OrderMissingHubException();
throw const domain.OrderMissingHubException();
}
final domain.PermanentOrder order = domain.PermanentOrder(
startDate: state.startDate,

View File

@@ -69,7 +69,7 @@ class RapidOrderBloc extends Bloc<RapidOrderEvent, RapidOrderState>
emit(const RapidOrderSubmitting());
await handleError(
emit: emit,
emit: emit.call,
action: () async {
await _createRapidOrderUseCase(
RapidOrderArguments(description: message),

View File

@@ -289,7 +289,7 @@ class RecurringOrderBloc extends Bloc<RecurringOrderEvent, RecurringOrderState>
) async {
emit(state.copyWith(status: RecurringOrderStatus.loading));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
final Map<String, double> roleRates = <String, double>{
for (final RecurringOrderRoleOption role in state.roles)
@@ -297,7 +297,7 @@ class RecurringOrderBloc extends Bloc<RecurringOrderEvent, RecurringOrderState>
};
final RecurringOrderHubOption? selectedHub = state.selectedHub;
if (selectedHub == null) {
throw domain.OrderMissingHubException();
throw const domain.OrderMissingHubException();
}
final domain.RecurringOrder order = domain.RecurringOrder(
startDate: state.startDate,

View File

@@ -1,3 +1,5 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:firebase_data_connect/src/core/ref.dart';
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
import 'package:krow_domain/krow_domain.dart';
import '../../domain/repositories/home_repository_interface.dart';
@@ -7,8 +9,6 @@ import '../../domain/repositories/home_repository_interface.dart';
/// This implementation follows the "Buffer Layer" pattern by using a dedicated
/// connector repository from the data_connect package.
class HomeRepositoryImpl implements HomeRepositoryInterface {
final dc.HomeConnectorRepository _connectorRepository;
final dc.DataConnectService _service;
HomeRepositoryImpl({
dc.HomeConnectorRepository? connectorRepository,
@@ -16,10 +16,12 @@ class HomeRepositoryImpl implements HomeRepositoryInterface {
}) : _connectorRepository = connectorRepository ??
dc.DataConnectService.instance.getHomeRepository(),
_service = service ?? dc.DataConnectService.instance;
final dc.HomeConnectorRepository _connectorRepository;
final dc.DataConnectService _service;
@override
Future<HomeDashboardData> getDashboardData() async {
final businessId = await _service.getBusinessId();
final String businessId = await _service.getBusinessId();
return _connectorRepository.getDashboardData(businessId: businessId);
}
@@ -37,16 +39,16 @@ class HomeRepositoryImpl implements HomeRepositoryInterface {
return await _service.run(() async {
final String businessId = await _service.getBusinessId();
final businessResult = await _service.connector
final QueryResult<dc.GetBusinessByIdData, dc.GetBusinessByIdVariables> businessResult = await _service.connector
.getBusinessById(id: businessId)
.execute();
final b = businessResult.data.business;
final dc.GetBusinessByIdBusiness? b = businessResult.data.business;
if (b == null) {
throw Exception('Business data not found for ID: $businessId');
}
final updatedSession = dc.ClientSession(
final dc.ClientSession updatedSession = dc.ClientSession(
business: dc.ClientBusinessSession(
id: b.id,
businessName: b.businessName,
@@ -67,7 +69,8 @@ class HomeRepositoryImpl implements HomeRepositoryInterface {
@override
Future<List<ReorderItem>> getRecentReorders() async {
final businessId = await _service.getBusinessId();
final String businessId = await _service.getBusinessId();
return _connectorRepository.getRecentReorders(businessId: businessId);
}
}

View File

@@ -37,7 +37,7 @@ class ClientHomeBloc extends Bloc<ClientHomeEvent, ClientHomeState>
) async {
emit(state.copyWith(status: ClientHomeStatus.loading));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
// Get session data
final UserSessionData sessionData = await _getUserSessionDataUseCase();

View File

@@ -651,9 +651,9 @@ class _ShiftOrderFormSheetState extends State<ShiftOrderFormSheet> {
return Container(
height: MediaQuery.of(context).size.height * 0.95,
decoration: BoxDecoration(
decoration: const BoxDecoration(
color: UiColors.bgPrimary,
borderRadius: const BorderRadius.vertical(top: Radius.circular(UiConstants.space6)),
borderRadius: BorderRadius.vertical(top: Radius.circular(UiConstants.space6)),
),
child: Column(
children: <Widget>[

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
import 'package:krow_domain/krow_domain.dart';
import '../../domain/repositories/hub_repository_interface.dart';
@@ -7,8 +8,6 @@ import '../../domain/repositories/hub_repository_interface.dart';
/// This implementation follows the "Buffer Layer" pattern by using a dedicated
/// connector repository from the data_connect package.
class HubRepositoryImpl implements HubRepositoryInterface {
final dc.HubsConnectorRepository _connectorRepository;
final dc.DataConnectService _service;
HubRepositoryImpl({
dc.HubsConnectorRepository? connectorRepository,
@@ -16,10 +15,12 @@ class HubRepositoryImpl implements HubRepositoryInterface {
}) : _connectorRepository = connectorRepository ??
dc.DataConnectService.instance.getHubsRepository(),
_service = service ?? dc.DataConnectService.instance;
final dc.HubsConnectorRepository _connectorRepository;
final dc.DataConnectService _service;
@override
Future<List<Hub>> getHubs() async {
final businessId = await _service.getBusinessId();
final String businessId = await _service.getBusinessId();
return _connectorRepository.getHubs(businessId: businessId);
}
@@ -36,7 +37,7 @@ class HubRepositoryImpl implements HubRepositoryInterface {
String? country,
String? zipCode,
}) async {
final businessId = await _service.getBusinessId();
final String businessId = await _service.getBusinessId();
return _connectorRepository.createHub(
businessId: businessId,
name: name,
@@ -54,7 +55,7 @@ class HubRepositoryImpl implements HubRepositoryInterface {
@override
Future<void> deleteHub(String id) async {
final businessId = await _service.getBusinessId();
final String businessId = await _service.getBusinessId();
return _connectorRepository.deleteHub(businessId: businessId, id: id);
}
@@ -79,7 +80,7 @@ class HubRepositoryImpl implements HubRepositoryInterface {
String? country,
String? zipCode,
}) async {
final businessId = await _service.getBusinessId();
final String businessId = await _service.getBusinessId();
return _connectorRepository.updateHub(
businessId: businessId,
id: id,
@@ -96,3 +97,4 @@ class HubRepositoryImpl implements HubRepositoryInterface {
);
}
}

View File

@@ -73,7 +73,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
emit(state.copyWith(status: ClientHubsStatus.loading));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
final List<Hub> hubs = await _getHubsUseCase();
emit(state.copyWith(status: ClientHubsStatus.success, hubs: hubs));
@@ -92,7 +92,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
emit(state.copyWith(status: ClientHubsStatus.actionInProgress));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
await _createHubUseCase(
CreateHubArguments(
@@ -132,7 +132,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
emit(state.copyWith(status: ClientHubsStatus.actionInProgress));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
await _updateHubUseCase(
UpdateHubArguments(
@@ -172,7 +172,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
emit(state.copyWith(status: ClientHubsStatus.actionInProgress));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
await _deleteHubUseCase(DeleteHubArguments(hubId: event.hubId));
final List<Hub> hubs = await _getHubsUseCase();
@@ -198,7 +198,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
emit(state.copyWith(status: ClientHubsStatus.actionInProgress));
await handleError(
emit: emit,
emit: emit.call,
action: () async {
await _assignNfcTagUseCase(
AssignNfcTagArguments(hubId: event.hubId, nfcTagId: event.nfcTagId),

View File

@@ -7,10 +7,10 @@ import '../../domain/repositories/reports_repository.dart';
/// This implementation follows the "Buffer Layer" pattern by using a dedicated
/// connector repository from the data_connect package.
class ReportsRepositoryImpl implements ReportsRepository {
final ReportsConnectorRepository _connectorRepository;
ReportsRepositoryImpl({ReportsConnectorRepository? connectorRepository})
: _connectorRepository = connectorRepository ?? DataConnectService.instance.getReportsRepository();
final ReportsConnectorRepository _connectorRepository;
@override
Future<DailyOpsReport> getDailyOpsReport({

View File

@@ -1,16 +1,18 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_domain/src/entities/reports/coverage_report.dart';
import '../../../domain/repositories/reports_repository.dart';
import 'coverage_event.dart';
import 'coverage_state.dart';
class CoverageBloc extends Bloc<CoverageEvent, CoverageState> {
final ReportsRepository _reportsRepository;
CoverageBloc({required ReportsRepository reportsRepository})
: _reportsRepository = reportsRepository,
super(CoverageInitial()) {
on<LoadCoverageReport>(_onLoadCoverageReport);
}
final ReportsRepository _reportsRepository;
Future<void> _onLoadCoverageReport(
LoadCoverageReport event,
@@ -18,7 +20,7 @@ class CoverageBloc extends Bloc<CoverageEvent, CoverageState> {
) async {
emit(CoverageLoading());
try {
final report = await _reportsRepository.getCoverageReport(
final CoverageReport report = await _reportsRepository.getCoverageReport(
businessId: event.businessId,
startDate: event.startDate,
endDate: event.endDate,
@@ -29,3 +31,4 @@ class CoverageBloc extends Bloc<CoverageEvent, CoverageState> {
}
}
}

View File

@@ -1,23 +1,25 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:equatable/equatable.dart';
abstract class CoverageEvent extends Equatable {
const CoverageEvent();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class LoadCoverageReport extends CoverageEvent {
final String? businessId;
final DateTime startDate;
final DateTime endDate;
const LoadCoverageReport({
this.businessId,
required this.startDate,
required this.endDate,
});
final String? businessId;
final DateTime startDate;
final DateTime endDate;
@override
List<Object?> get props => [businessId, startDate, endDate];
List<Object?> get props => <Object?>[businessId, startDate, endDate];
}

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:equatable/equatable.dart';
import 'package:krow_domain/krow_domain.dart';
@@ -5,7 +6,7 @@ abstract class CoverageState extends Equatable {
const CoverageState();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class CoverageInitial extends CoverageState {}
@@ -13,19 +14,20 @@ class CoverageInitial extends CoverageState {}
class CoverageLoading extends CoverageState {}
class CoverageLoaded extends CoverageState {
final CoverageReport report;
const CoverageLoaded(this.report);
final CoverageReport report;
@override
List<Object?> get props => [report];
List<Object?> get props => <Object?>[report];
}
class CoverageError extends CoverageState {
final String message;
const CoverageError(this.message);
final String message;
@override
List<Object?> get props => [message];
List<Object?> get props => <Object?>[message];
}

View File

@@ -1,16 +1,17 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_domain/src/entities/reports/daily_ops_report.dart';
import '../../../domain/repositories/reports_repository.dart';
import 'daily_ops_event.dart';
import 'daily_ops_state.dart';
class DailyOpsBloc extends Bloc<DailyOpsEvent, DailyOpsState> {
final ReportsRepository _reportsRepository;
DailyOpsBloc({required ReportsRepository reportsRepository})
: _reportsRepository = reportsRepository,
super(DailyOpsInitial()) {
on<LoadDailyOpsReport>(_onLoadDailyOpsReport);
}
final ReportsRepository _reportsRepository;
Future<void> _onLoadDailyOpsReport(
LoadDailyOpsReport event,
@@ -18,7 +19,7 @@ class DailyOpsBloc extends Bloc<DailyOpsEvent, DailyOpsState> {
) async {
emit(DailyOpsLoading());
try {
final report = await _reportsRepository.getDailyOpsReport(
final DailyOpsReport report = await _reportsRepository.getDailyOpsReport(
businessId: event.businessId,
date: event.date,
);

View File

@@ -4,18 +4,18 @@ abstract class DailyOpsEvent extends Equatable {
const DailyOpsEvent();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class LoadDailyOpsReport extends DailyOpsEvent {
final String? businessId;
final DateTime date;
const LoadDailyOpsReport({
this.businessId,
required this.date,
});
final String? businessId;
final DateTime date;
@override
List<Object?> get props => [businessId, date];
List<Object?> get props => <Object?>[businessId, date];
}

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:equatable/equatable.dart';
import 'package:krow_domain/krow_domain.dart';
@@ -5,7 +6,7 @@ abstract class DailyOpsState extends Equatable {
const DailyOpsState();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class DailyOpsInitial extends DailyOpsState {}
@@ -13,19 +14,20 @@ class DailyOpsInitial extends DailyOpsState {}
class DailyOpsLoading extends DailyOpsState {}
class DailyOpsLoaded extends DailyOpsState {
final DailyOpsReport report;
const DailyOpsLoaded(this.report);
final DailyOpsReport report;
@override
List<Object?> get props => [report];
List<Object?> get props => <Object?>[report];
}
class DailyOpsError extends DailyOpsState {
final String message;
const DailyOpsError(this.message);
final String message;
@override
List<Object?> get props => [message];
List<Object?> get props => <Object?>[message];
}

View File

@@ -1,16 +1,17 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_domain/src/entities/reports/forecast_report.dart';
import '../../../domain/repositories/reports_repository.dart';
import 'forecast_event.dart';
import 'forecast_state.dart';
class ForecastBloc extends Bloc<ForecastEvent, ForecastState> {
final ReportsRepository _reportsRepository;
ForecastBloc({required ReportsRepository reportsRepository})
: _reportsRepository = reportsRepository,
super(ForecastInitial()) {
on<LoadForecastReport>(_onLoadForecastReport);
}
final ReportsRepository _reportsRepository;
Future<void> _onLoadForecastReport(
LoadForecastReport event,
@@ -18,7 +19,7 @@ class ForecastBloc extends Bloc<ForecastEvent, ForecastState> {
) async {
emit(ForecastLoading());
try {
final report = await _reportsRepository.getForecastReport(
final ForecastReport report = await _reportsRepository.getForecastReport(
businessId: event.businessId,
startDate: event.startDate,
endDate: event.endDate,

View File

@@ -4,20 +4,20 @@ abstract class ForecastEvent extends Equatable {
const ForecastEvent();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class LoadForecastReport extends ForecastEvent {
final String? businessId;
final DateTime startDate;
final DateTime endDate;
const LoadForecastReport({
this.businessId,
required this.startDate,
required this.endDate,
});
final String? businessId;
final DateTime startDate;
final DateTime endDate;
@override
List<Object?> get props => [businessId, startDate, endDate];
List<Object?> get props => <Object?>[businessId, startDate, endDate];
}

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:equatable/equatable.dart';
import 'package:krow_domain/krow_domain.dart';
@@ -5,7 +6,7 @@ abstract class ForecastState extends Equatable {
const ForecastState();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class ForecastInitial extends ForecastState {}
@@ -13,19 +14,20 @@ class ForecastInitial extends ForecastState {}
class ForecastLoading extends ForecastState {}
class ForecastLoaded extends ForecastState {
final ForecastReport report;
const ForecastLoaded(this.report);
final ForecastReport report;
@override
List<Object?> get props => [report];
List<Object?> get props => <Object?>[report];
}
class ForecastError extends ForecastState {
final String message;
const ForecastError(this.message);
final String message;
@override
List<Object?> get props => [message];
List<Object?> get props => <Object?>[message];
}

View File

@@ -1,16 +1,17 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_domain/src/entities/reports/no_show_report.dart';
import '../../../domain/repositories/reports_repository.dart';
import 'no_show_event.dart';
import 'no_show_state.dart';
class NoShowBloc extends Bloc<NoShowEvent, NoShowState> {
final ReportsRepository _reportsRepository;
NoShowBloc({required ReportsRepository reportsRepository})
: _reportsRepository = reportsRepository,
super(NoShowInitial()) {
on<LoadNoShowReport>(_onLoadNoShowReport);
}
final ReportsRepository _reportsRepository;
Future<void> _onLoadNoShowReport(
LoadNoShowReport event,
@@ -18,7 +19,7 @@ class NoShowBloc extends Bloc<NoShowEvent, NoShowState> {
) async {
emit(NoShowLoading());
try {
final report = await _reportsRepository.getNoShowReport(
final NoShowReport report = await _reportsRepository.getNoShowReport(
businessId: event.businessId,
startDate: event.startDate,
endDate: event.endDate,

View File

@@ -4,20 +4,20 @@ abstract class NoShowEvent extends Equatable {
const NoShowEvent();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class LoadNoShowReport extends NoShowEvent {
final String? businessId;
final DateTime startDate;
final DateTime endDate;
const LoadNoShowReport({
this.businessId,
required this.startDate,
required this.endDate,
});
final String? businessId;
final DateTime startDate;
final DateTime endDate;
@override
List<Object?> get props => [businessId, startDate, endDate];
List<Object?> get props => <Object?>[businessId, startDate, endDate];
}

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:equatable/equatable.dart';
import 'package:krow_domain/krow_domain.dart';
@@ -5,7 +6,7 @@ abstract class NoShowState extends Equatable {
const NoShowState();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class NoShowInitial extends NoShowState {}
@@ -13,19 +14,20 @@ class NoShowInitial extends NoShowState {}
class NoShowLoading extends NoShowState {}
class NoShowLoaded extends NoShowState {
final NoShowReport report;
const NoShowLoaded(this.report);
final NoShowReport report;
@override
List<Object?> get props => [report];
List<Object?> get props => <Object?>[report];
}
class NoShowError extends NoShowState {
final String message;
const NoShowError(this.message);
final String message;
@override
List<Object?> get props => [message];
List<Object?> get props => <Object?>[message];
}

View File

@@ -1,16 +1,17 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_domain/src/entities/reports/performance_report.dart';
import '../../../domain/repositories/reports_repository.dart';
import 'performance_event.dart';
import 'performance_state.dart';
class PerformanceBloc extends Bloc<PerformanceEvent, PerformanceState> {
final ReportsRepository _reportsRepository;
PerformanceBloc({required ReportsRepository reportsRepository})
: _reportsRepository = reportsRepository,
super(PerformanceInitial()) {
on<LoadPerformanceReport>(_onLoadPerformanceReport);
}
final ReportsRepository _reportsRepository;
Future<void> _onLoadPerformanceReport(
LoadPerformanceReport event,
@@ -18,7 +19,7 @@ class PerformanceBloc extends Bloc<PerformanceEvent, PerformanceState> {
) async {
emit(PerformanceLoading());
try {
final report = await _reportsRepository.getPerformanceReport(
final PerformanceReport report = await _reportsRepository.getPerformanceReport(
businessId: event.businessId,
startDate: event.startDate,
endDate: event.endDate,

View File

@@ -4,20 +4,20 @@ abstract class PerformanceEvent extends Equatable {
const PerformanceEvent();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class LoadPerformanceReport extends PerformanceEvent {
final String? businessId;
final DateTime startDate;
final DateTime endDate;
const LoadPerformanceReport({
this.businessId,
required this.startDate,
required this.endDate,
});
final String? businessId;
final DateTime startDate;
final DateTime endDate;
@override
List<Object?> get props => [businessId, startDate, endDate];
List<Object?> get props => <Object?>[businessId, startDate, endDate];
}

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:equatable/equatable.dart';
import 'package:krow_domain/krow_domain.dart';
@@ -5,7 +6,7 @@ abstract class PerformanceState extends Equatable {
const PerformanceState();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class PerformanceInitial extends PerformanceState {}
@@ -13,19 +14,20 @@ class PerformanceInitial extends PerformanceState {}
class PerformanceLoading extends PerformanceState {}
class PerformanceLoaded extends PerformanceState {
final PerformanceReport report;
const PerformanceLoaded(this.report);
final PerformanceReport report;
@override
List<Object?> get props => [report];
List<Object?> get props => <Object?>[report];
}
class PerformanceError extends PerformanceState {
final String message;
const PerformanceError(this.message);
final String message;
@override
List<Object?> get props => [message];
List<Object?> get props => <Object?>[message];
}

View File

@@ -1,16 +1,17 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_domain/src/entities/reports/spend_report.dart';
import '../../../domain/repositories/reports_repository.dart';
import 'spend_event.dart';
import 'spend_state.dart';
class SpendBloc extends Bloc<SpendEvent, SpendState> {
final ReportsRepository _reportsRepository;
SpendBloc({required ReportsRepository reportsRepository})
: _reportsRepository = reportsRepository,
super(SpendInitial()) {
on<LoadSpendReport>(_onLoadSpendReport);
}
final ReportsRepository _reportsRepository;
Future<void> _onLoadSpendReport(
LoadSpendReport event,
@@ -18,7 +19,7 @@ class SpendBloc extends Bloc<SpendEvent, SpendState> {
) async {
emit(SpendLoading());
try {
final report = await _reportsRepository.getSpendReport(
final SpendReport report = await _reportsRepository.getSpendReport(
businessId: event.businessId,
startDate: event.startDate,
endDate: event.endDate,

View File

@@ -4,20 +4,20 @@ abstract class SpendEvent extends Equatable {
const SpendEvent();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class LoadSpendReport extends SpendEvent {
final String? businessId;
final DateTime startDate;
final DateTime endDate;
const LoadSpendReport({
this.businessId,
required this.startDate,
required this.endDate,
});
final String? businessId;
final DateTime startDate;
final DateTime endDate;
@override
List<Object?> get props => [businessId, startDate, endDate];
List<Object?> get props => <Object?>[businessId, startDate, endDate];
}

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:equatable/equatable.dart';
import 'package:krow_domain/krow_domain.dart';
@@ -5,7 +6,7 @@ abstract class SpendState extends Equatable {
const SpendState();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class SpendInitial extends SpendState {}
@@ -13,19 +14,20 @@ class SpendInitial extends SpendState {}
class SpendLoading extends SpendState {}
class SpendLoaded extends SpendState {
final SpendReport report;
const SpendLoaded(this.report);
final SpendReport report;
@override
List<Object?> get props => [report];
List<Object?> get props => <Object?>[report];
}
class SpendError extends SpendState {
final String message;
const SpendError(this.message);
final String message;
@override
List<Object?> get props => [message];
List<Object?> get props => <Object?>[message];
}

View File

@@ -1,16 +1,17 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_domain/src/entities/reports/reports_summary.dart';
import '../../../domain/repositories/reports_repository.dart';
import 'reports_summary_event.dart';
import 'reports_summary_state.dart';
class ReportsSummaryBloc extends Bloc<ReportsSummaryEvent, ReportsSummaryState> {
final ReportsRepository _reportsRepository;
ReportsSummaryBloc({required ReportsRepository reportsRepository})
: _reportsRepository = reportsRepository,
super(ReportsSummaryInitial()) {
on<LoadReportsSummary>(_onLoadReportsSummary);
}
final ReportsRepository _reportsRepository;
Future<void> _onLoadReportsSummary(
LoadReportsSummary event,
@@ -18,7 +19,7 @@ class ReportsSummaryBloc extends Bloc<ReportsSummaryEvent, ReportsSummaryState>
) async {
emit(ReportsSummaryLoading());
try {
final summary = await _reportsRepository.getReportsSummary(
final ReportsSummary summary = await _reportsRepository.getReportsSummary(
businessId: event.businessId,
startDate: event.startDate,
endDate: event.endDate,

View File

@@ -4,20 +4,20 @@ abstract class ReportsSummaryEvent extends Equatable {
const ReportsSummaryEvent();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class LoadReportsSummary extends ReportsSummaryEvent {
final String? businessId;
final DateTime startDate;
final DateTime endDate;
const LoadReportsSummary({
this.businessId,
required this.startDate,
required this.endDate,
});
final String? businessId;
final DateTime startDate;
final DateTime endDate;
@override
List<Object?> get props => [businessId, startDate, endDate];
List<Object?> get props => <Object?>[businessId, startDate, endDate];
}

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:equatable/equatable.dart';
import 'package:krow_domain/krow_domain.dart';
@@ -5,7 +6,7 @@ abstract class ReportsSummaryState extends Equatable {
const ReportsSummaryState();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
class ReportsSummaryInitial extends ReportsSummaryState {}
@@ -13,19 +14,20 @@ class ReportsSummaryInitial extends ReportsSummaryState {}
class ReportsSummaryLoading extends ReportsSummaryState {}
class ReportsSummaryLoaded extends ReportsSummaryState {
final ReportsSummary summary;
const ReportsSummaryLoaded(this.summary);
final ReportsSummary summary;
@override
List<Object?> get props => [summary];
List<Object?> get props => <Object?>[summary];
}
class ReportsSummaryError extends ReportsSummaryState {
final String message;
const ReportsSummaryError(this.message);
final String message;
@override
List<Object?> get props => [message];
List<Object?> get props => <Object?>[message];
}

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:client_reports/src/presentation/blocs/coverage/coverage_bloc.dart';
import 'package:client_reports/src/presentation/blocs/coverage/coverage_event.dart';
import 'package:client_reports/src/presentation/blocs/coverage/coverage_state.dart';
@@ -23,12 +24,12 @@ class _CoverageReportPageState extends State<CoverageReportPage> {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => Modular.get<CoverageBloc>()
create: (BuildContext context) => Modular.get<CoverageBloc>()
..add(LoadCoverageReport(startDate: _startDate, endDate: _endDate)),
child: Scaffold(
backgroundColor: UiColors.bgMenu,
body: BlocBuilder<CoverageBloc, CoverageState>(
builder: (context, state) {
builder: (BuildContext context, CoverageState state) {
if (state is CoverageLoading) {
return const Center(child: CircularProgressIndicator());
}
@@ -38,10 +39,10 @@ class _CoverageReportPageState extends State<CoverageReportPage> {
}
if (state is CoverageLoaded) {
final report = state.report;
final CoverageReport report = state.report;
return SingleChildScrollView(
child: Column(
children: [
children: <Widget>[
// Header
Container(
padding: const EdgeInsets.only(
@@ -52,16 +53,16 @@ class _CoverageReportPageState extends State<CoverageReportPage> {
),
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [UiColors.primary, UiColors.tagInProgress],
colors: <Color>[UiColors.primary, UiColors.tagInProgress],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
@@ -81,7 +82,7 @@ class _CoverageReportPageState extends State<CoverageReportPage> {
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
context.t.client_reports.coverage_report.title,
style: const TextStyle(
@@ -113,10 +114,10 @@ class _CoverageReportPageState extends State<CoverageReportPage> {
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
// Summary Cards
Row(
children: [
children: <Widget>[
Expanded(
child: _CoverageSummaryCard(
label: context.t.client_reports.coverage_report.metrics.avg_coverage,
@@ -152,7 +153,7 @@ class _CoverageReportPageState extends State<CoverageReportPage> {
if (report.dailyCoverage.isEmpty)
Center(child: Text(context.t.client_reports.coverage_report.empty_state))
else
...report.dailyCoverage.map((day) => _CoverageListItem(
...report.dailyCoverage.map((CoverageDay day) => _CoverageListItem(
date: DateFormat('EEE, MMM dd').format(day.date),
needed: day.needed,
filled: day.filled,
@@ -176,10 +177,6 @@ class _CoverageReportPageState extends State<CoverageReportPage> {
}
class _CoverageSummaryCard extends StatelessWidget {
final String label;
final String value;
final IconData icon;
final Color color;
const _CoverageSummaryCard({
required this.label,
@@ -187,6 +184,10 @@ class _CoverageSummaryCard extends StatelessWidget {
required this.icon,
required this.color,
});
final String label;
final String value;
final IconData icon;
final Color color;
@override
Widget build(BuildContext context) {
@@ -195,7 +196,7 @@ class _CoverageSummaryCard extends StatelessWidget {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.04),
blurRadius: 10,
@@ -204,7 +205,7 @@ class _CoverageSummaryCard extends StatelessWidget {
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
@@ -224,10 +225,6 @@ class _CoverageSummaryCard extends StatelessWidget {
}
class _CoverageListItem extends StatelessWidget {
final String date;
final int needed;
final int filled;
final double percentage;
const _CoverageListItem({
required this.date,
@@ -235,6 +232,10 @@ class _CoverageListItem extends StatelessWidget {
required this.filled,
required this.percentage,
});
final String date;
final int needed;
final int filled;
final double percentage;
@override
Widget build(BuildContext context) {
@@ -255,11 +256,11 @@ class _CoverageListItem extends StatelessWidget {
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(date, style: const TextStyle(fontWeight: FontWeight.bold)),
const SizedBox(height: 4),
// Progress Bar
@@ -278,7 +279,7 @@ class _CoverageListItem extends StatelessWidget {
const SizedBox(width: 16),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
children: <Widget>[
Text(
'$filled/$needed',
style: const TextStyle(fontWeight: FontWeight.bold),
@@ -298,3 +299,4 @@ class _CoverageListItem extends StatelessWidget {
);
}
}

View File

@@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:intl/intl.dart';
import 'package:krow_domain/src/entities/reports/daily_ops_report.dart';
class DailyOpsReportPage extends StatefulWidget {
const DailyOpsReportPage({super.key});
@@ -49,12 +50,12 @@ class _DailyOpsReportPageState extends State<DailyOpsReportPage> {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => Modular.get<DailyOpsBloc>()
create: (BuildContext context) => Modular.get<DailyOpsBloc>()
..add(LoadDailyOpsReport(date: _selectedDate)),
child: Scaffold(
backgroundColor: UiColors.bgMenu,
body: BlocBuilder<DailyOpsBloc, DailyOpsState>(
builder: (context, state) {
builder: (BuildContext context, DailyOpsState state) {
if (state is DailyOpsLoading) {
return const Center(child: CircularProgressIndicator());
}
@@ -64,10 +65,10 @@ class _DailyOpsReportPageState extends State<DailyOpsReportPage> {
}
if (state is DailyOpsLoaded) {
final report = state.report;
final DailyOpsReport report = state.report;
return SingleChildScrollView(
child: Column(
children: [
children: <Widget>[
// Header
Container(
padding: const EdgeInsets.only(
@@ -78,7 +79,7 @@ class _DailyOpsReportPageState extends State<DailyOpsReportPage> {
),
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
colors: <Color>[
UiColors.primary,
UiColors.buttonPrimaryHover
],
@@ -88,9 +89,9 @@ class _DailyOpsReportPageState extends State<DailyOpsReportPage> {
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
@@ -110,7 +111,7 @@ class _DailyOpsReportPageState extends State<DailyOpsReportPage> {
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
context.t.client_reports.daily_ops_report
.title,
@@ -189,7 +190,7 @@ class _DailyOpsReportPageState extends State<DailyOpsReportPage> {
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
// Date Selector
GestureDetector(
onTap: () => _pickDate(context),
@@ -198,7 +199,7 @@ class _DailyOpsReportPageState extends State<DailyOpsReportPage> {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.06),
blurRadius: 4,
@@ -208,9 +209,9 @@ class _DailyOpsReportPageState extends State<DailyOpsReportPage> {
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
const Icon(
UiIcons.calendar,
size: 16,
@@ -246,7 +247,7 @@ class _DailyOpsReportPageState extends State<DailyOpsReportPage> {
mainAxisSpacing: 12,
crossAxisSpacing: 12,
childAspectRatio: 1.2,
children: [
children: <Widget>[
_OpsStatCard(
label: context.t.client_reports
.daily_ops_report.metrics.scheduled.label,
@@ -339,7 +340,7 @@ class _DailyOpsReportPageState extends State<DailyOpsReportPage> {
),
)
else
...report.shifts.map((shift) => _ShiftListItem(
...report.shifts.map((DailyOpsShift shift) => _ShiftListItem(
title: shift.title,
location: shift.location,
time:
@@ -376,11 +377,6 @@ class _DailyOpsReportPageState extends State<DailyOpsReportPage> {
}
class _OpsStatCard extends StatelessWidget {
final String label;
final String value;
final String subValue;
final Color color;
final IconData icon;
const _OpsStatCard({
required this.label,
@@ -389,6 +385,11 @@ class _OpsStatCard extends StatelessWidget {
required this.color,
required this.icon,
});
final String label;
final String value;
final String subValue;
final Color color;
final IconData icon;
@override
Widget build(BuildContext context) {
@@ -397,7 +398,7 @@ class _OpsStatCard extends StatelessWidget {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.06),
blurRadius: 4,
@@ -408,9 +409,9 @@ class _OpsStatCard extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
Icon(icon, size: 14, color: color),
const SizedBox(width: 8),
Expanded(
@@ -429,7 +430,7 @@ class _OpsStatCard extends StatelessWidget {
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
value,
style: const TextStyle(
@@ -467,13 +468,6 @@ class _OpsStatCard extends StatelessWidget {
}
class _ShiftListItem extends StatelessWidget {
final String title;
final String location;
final String time;
final String workers;
final String rate;
final String status;
final Color statusColor;
const _ShiftListItem({
required this.title,
@@ -484,6 +478,13 @@ class _ShiftListItem extends StatelessWidget {
required this.status,
required this.statusColor,
});
final String title;
final String location;
final String time;
final String workers;
final String rate;
final String status;
final Color statusColor;
@override
Widget build(BuildContext context) {
@@ -493,7 +494,7 @@ class _ShiftListItem extends StatelessWidget {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.02),
blurRadius: 2,
@@ -501,14 +502,14 @@ class _ShiftListItem extends StatelessWidget {
],
),
child: Column(
children: [
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
title,
style: const TextStyle(
@@ -519,7 +520,7 @@ class _ShiftListItem extends StatelessWidget {
),
const SizedBox(height: 4),
Row(
children: [
children: <Widget>[
const Icon(
UiIcons.mapPin,
size: 10,
@@ -565,7 +566,7 @@ class _ShiftListItem extends StatelessWidget {
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
_infoItem(
context,
UiIcons.clock,
@@ -591,12 +592,12 @@ class _ShiftListItem extends StatelessWidget {
Widget _infoItem(
BuildContext context, IconData icon, String label, String value) {
return Row(
children: [
children: <Widget>[
Icon(icon, size: 12, color: UiColors.textSecondary),
const SizedBox(width: 6),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
label,
style: const TextStyle(fontSize: 10, color: UiColors.pinInactive),

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:client_reports/src/presentation/blocs/forecast/forecast_bloc.dart';
import 'package:client_reports/src/presentation/blocs/forecast/forecast_event.dart';
import 'package:client_reports/src/presentation/blocs/forecast/forecast_state.dart';
@@ -24,12 +25,12 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => Modular.get<ForecastBloc>()
create: (BuildContext context) => Modular.get<ForecastBloc>()
..add(LoadForecastReport(startDate: _startDate, endDate: _endDate)),
child: Scaffold(
backgroundColor: UiColors.bgMenu,
body: BlocBuilder<ForecastBloc, ForecastState>(
builder: (context, state) {
builder: (BuildContext context, ForecastState state) {
if (state is ForecastLoading) {
return const Center(child: CircularProgressIndicator());
}
@@ -39,10 +40,10 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
}
if (state is ForecastLoaded) {
final report = state.report;
final ForecastReport report = state.report;
return SingleChildScrollView(
child: Column(
children: [
children: <Widget>[
// Header
_buildHeader(context),
@@ -53,7 +54,7 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
// Metrics Grid
_buildMetricsGrid(context, report),
const SizedBox(height: 16),
@@ -82,7 +83,7 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
)
else
...report.weeklyBreakdown.map(
(week) => _WeeklyBreakdownItem(week: week),
(ForecastWeek week) => _WeeklyBreakdownItem(week: week),
),
const SizedBox(height: 40),
@@ -112,16 +113,16 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
decoration: const BoxDecoration(
color: UiColors.primary,
gradient: LinearGradient(
colors: [UiColors.primary, Color(0xFF0020A0)], // Deep blue gradient
colors: <Color>[UiColors.primary, Color(0xFF0020A0)], // Deep blue gradient
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
@@ -141,7 +142,7 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
context.t.client_reports.forecast_report.title,
style: UiTypography.headline3m.copyWith(color: UiColors.white),
@@ -180,7 +181,7 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
}
Widget _buildMetricsGrid(BuildContext context, ForecastReport report) {
final t = context.t.client_reports.forecast_report;
final TranslationsClientReportsForecastReportEn t = context.t.client_reports.forecast_report;
return GridView.count(
crossAxisCount: 2,
shrinkWrap: true,
@@ -188,7 +189,7 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
mainAxisSpacing: 12,
crossAxisSpacing: 12,
childAspectRatio: 1.3,
children: [
children: <Widget>[
_MetricCard(
icon: UiIcons.dollar,
label: t.metrics.four_week_forecast,
@@ -232,7 +233,7 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.04),
blurRadius: 10,
@@ -241,7 +242,7 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
context.t.client_reports.forecast_report.chart_title,
style: UiTypography.headline4m,
@@ -257,9 +258,9 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
),
const SizedBox(height: 8),
// X Axis labels manually if chart doesn't handle them perfectly or for custom look
Row(
const Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
children: <Widget>[
Text('W1', style: TextStyle(color: UiColors.textSecondary, fontSize: 12)),
Text('W1', style: TextStyle(color: UiColors.transparent, fontSize: 12)), // Spacer
Text('W2', style: TextStyle(color: UiColors.textSecondary, fontSize: 12)),
@@ -276,12 +277,6 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
}
class _MetricCard extends StatelessWidget {
final IconData icon;
final String label;
final String value;
final String badgeText;
final Color iconColor;
final Color badgeColor;
const _MetricCard({
required this.icon,
@@ -291,6 +286,12 @@ class _MetricCard extends StatelessWidget {
required this.iconColor,
required this.badgeColor,
});
final IconData icon;
final String label;
final String value;
final String badgeText;
final Color iconColor;
final Color badgeColor;
@override
Widget build(BuildContext context) {
@@ -299,7 +300,7 @@ class _MetricCard extends StatelessWidget {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.04),
blurRadius: 8,
@@ -309,9 +310,9 @@ class _MetricCard extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
Icon(icon, size: 16, color: iconColor),
const SizedBox(width: 8),
Expanded(
@@ -349,13 +350,13 @@ class _MetricCard extends StatelessWidget {
}
class _WeeklyBreakdownItem extends StatelessWidget {
final ForecastWeek week;
const _WeeklyBreakdownItem({required this.week});
final ForecastWeek week;
@override
Widget build(BuildContext context) {
final t = context.t.client_reports.forecast_report.weekly_breakdown;
final TranslationsClientReportsForecastReportWeeklyBreakdownEn t = context.t.client_reports.forecast_report.weekly_breakdown;
return Container(
margin: const EdgeInsets.only(bottom: 12),
@@ -365,10 +366,10 @@ class _WeeklyBreakdownItem extends StatelessWidget {
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Text(
t.week(index: week.weekNumber),
style: UiTypography.headline4m,
@@ -391,7 +392,7 @@ class _WeeklyBreakdownItem extends StatelessWidget {
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
_buildStat(t.shifts, week.shiftsCount.toString()),
_buildStat(t.hours, week.hoursCount.toStringAsFixed(0)),
_buildStat(t.avg_shift, NumberFormat.currency(symbol: r'$', decimalDigits: 0).format(week.avgCostPerShift)),
@@ -405,7 +406,7 @@ class _WeeklyBreakdownItem extends StatelessWidget {
Widget _buildStat(String label, String value) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(label, style: UiTypography.footnote1r.textSecondary),
const SizedBox(height: 4),
Text(value, style: UiTypography.body1m),
@@ -415,9 +416,9 @@ class _WeeklyBreakdownItem extends StatelessWidget {
}
class _ForecastChart extends StatelessWidget {
final List<ForecastPoint> points;
const _ForecastChart({required this.points});
final List<ForecastPoint> points;
@override
Widget build(BuildContext context) {
@@ -430,11 +431,11 @@ class _ForecastChart extends StatelessWidget {
show: true,
drawVerticalLine: false,
horizontalInterval: 5000, // Dynamic?
getDrawingHorizontalLine: (value) {
return FlLine(
getDrawingHorizontalLine: (double value) {
return const FlLine(
color: UiColors.borderInactive,
strokeWidth: 1,
dashArray: [5, 5],
dashArray: <int>[5, 5],
);
},
),
@@ -443,9 +444,9 @@ class _ForecastChart extends StatelessWidget {
minX: 0,
maxX: points.length.toDouble() - 1,
// minY: 0, // Let it scale automatically
lineBarsData: [
lineBarsData: <LineChartBarData>[
LineChartBarData(
spots: points.asMap().entries.map((e) {
spots: points.asMap().entries.map((MapEntry<int, ForecastPoint> e) {
return FlSpot(e.key.toDouble(), e.value.projectedCost);
}).toList(),
isCurved: true,
@@ -454,7 +455,7 @@ class _ForecastChart extends StatelessWidget {
isStrokeCapRound: true,
dotData: FlDotData(
show: true,
getDotPainter: (spot, percent, barData, index) {
getDotPainter: (FlSpot spot, double percent, LineChartBarData barData, int index) {
return FlDotCirclePainter(
radius: 4,
color: UiColors.textWarning,
@@ -473,3 +474,4 @@ class _ForecastChart extends StatelessWidget {
);
}
}

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:krow_domain/krow_domain.dart';
import 'package:client_reports/src/presentation/blocs/no_show/no_show_bloc.dart';
import 'package:client_reports/src/presentation/blocs/no_show/no_show_event.dart';
@@ -17,18 +18,18 @@ class NoShowReportPage extends StatefulWidget {
}
class _NoShowReportPageState extends State<NoShowReportPage> {
DateTime _startDate = DateTime.now().subtract(const Duration(days: 30));
DateTime _endDate = DateTime.now();
final DateTime _startDate = DateTime.now().subtract(const Duration(days: 30));
final DateTime _endDate = DateTime.now();
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => Modular.get<NoShowBloc>()
create: (BuildContext context) => Modular.get<NoShowBloc>()
..add(LoadNoShowReport(startDate: _startDate, endDate: _endDate)),
child: Scaffold(
backgroundColor: UiColors.bgMenu,
body: BlocBuilder<NoShowBloc, NoShowState>(
builder: (context, state) {
builder: (BuildContext context, NoShowState state) {
if (state is NoShowLoading) {
return const Center(child: CircularProgressIndicator());
}
@@ -38,12 +39,12 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
}
if (state is NoShowLoaded) {
final report = state.report;
final uniqueWorkers = report.flaggedWorkers.length;
final NoShowReport report = state.report;
final int uniqueWorkers = report.flaggedWorkers.length;
return SingleChildScrollView(
child: Column(
children: [
// ── Header ──────────────────────────────────────────
children: <Widget>[
// ── Header ──────────────────────────────────────────
Container(
padding: const EdgeInsets.only(
top: 60,
@@ -53,7 +54,7 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
),
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
colors: <Color>[
UiColors.primary,
UiColors.buttonPrimaryHover,
],
@@ -63,9 +64,9 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
@@ -85,7 +86,7 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
context.t.client_reports.no_show_report.title,
style: const TextStyle(
@@ -150,17 +151,17 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
),
),
// ── Content ─────────────────────────────────────────
// ── Content ─────────────────────────────────────────
Transform.translate(
offset: const Offset(0, -16),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
// 3-chip summary row (matches prototype)
Row(
children: [
children: <Widget>[
Expanded(
child: _SummaryChip(
icon: UiIcons.warning,
@@ -220,7 +221,7 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
)
else
...report.flaggedWorkers.map(
(worker) => _WorkerCard(worker: worker),
(NoShowWorker worker) => _WorkerCard(worker: worker),
),
const SizedBox(height: 40),
@@ -240,12 +241,8 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
}
}
// ── Summary chip (top 3 stats) ───────────────────────────────────────────────
// ── Summary chip (top 3 stats) ───────────────────────────────────────────────
class _SummaryChip extends StatelessWidget {
final IconData icon;
final Color iconColor;
final String label;
final String value;
const _SummaryChip({
required this.icon,
@@ -253,6 +250,10 @@ class _SummaryChip extends StatelessWidget {
required this.label,
required this.value,
});
final IconData icon;
final Color iconColor;
final String label;
final String value;
@override
Widget build(BuildContext context) {
@@ -261,7 +262,7 @@ class _SummaryChip extends StatelessWidget {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.06),
blurRadius: 8,
@@ -271,9 +272,9 @@ class _SummaryChip extends StatelessWidget {
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
Icon(icon, size: 12, color: iconColor),
const SizedBox(width: 4),
Expanded(
@@ -304,11 +305,11 @@ class _SummaryChip extends StatelessWidget {
}
}
// ── Worker card with risk badge + latest incident ────────────────────────────
// ── Worker card with risk badge + latest incident ────────────────────────────
class _WorkerCard extends StatelessWidget {
final NoShowWorker worker;
const _WorkerCard({required this.worker});
final NoShowWorker worker;
String _riskLabel(BuildContext context, int count) {
if (count >= 3) return context.t.client_reports.no_show_report.risks.high;
@@ -330,9 +331,9 @@ class _WorkerCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final riskLabel = _riskLabel(context, worker.noShowCount);
final riskColor = _riskColor(worker.noShowCount);
final riskBg = _riskBg(worker.noShowCount);
final String riskLabel = _riskLabel(context, worker.noShowCount);
final Color riskColor = _riskColor(worker.noShowCount);
final Color riskBg = _riskBg(worker.noShowCount);
return Container(
margin: const EdgeInsets.only(bottom: 12),
@@ -340,7 +341,7 @@ class _WorkerCard extends StatelessWidget {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.04),
blurRadius: 6,
@@ -348,12 +349,12 @@ class _WorkerCard extends StatelessWidget {
],
),
child: Column(
children: [
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
Container(
width: 40,
height: 40,
@@ -370,7 +371,7 @@ class _WorkerCard extends StatelessWidget {
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
worker.fullName,
style: const TextStyle(
@@ -416,7 +417,7 @@ class _WorkerCard extends StatelessWidget {
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Text(
context.t.client_reports.no_show_report.latest_incident,
style: const TextStyle(
@@ -447,4 +448,5 @@ class _WorkerCard extends StatelessWidget {
}
}
// ── Insight line ─────────────────────────────────────────────────────────────
// ── Insight line ─────────────────────────────────────────────────────────────

View File

@@ -6,6 +6,7 @@ import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:krow_domain/src/entities/reports/performance_report.dart';
class PerformanceReportPage extends StatefulWidget {
const PerformanceReportPage({super.key});
@@ -15,18 +16,18 @@ class PerformanceReportPage extends StatefulWidget {
}
class _PerformanceReportPageState extends State<PerformanceReportPage> {
DateTime _startDate = DateTime.now().subtract(const Duration(days: 30));
DateTime _endDate = DateTime.now();
final DateTime _startDate = DateTime.now().subtract(const Duration(days: 30));
final DateTime _endDate = DateTime.now();
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => Modular.get<PerformanceBloc>()
create: (BuildContext context) => Modular.get<PerformanceBloc>()
..add(LoadPerformanceReport(startDate: _startDate, endDate: _endDate)),
child: Scaffold(
backgroundColor: UiColors.bgMenu,
body: BlocBuilder<PerformanceBloc, PerformanceState>(
builder: (context, state) {
builder: (BuildContext context, PerformanceState state) {
if (state is PerformanceLoading) {
return const Center(child: CircularProgressIndicator());
}
@@ -36,10 +37,10 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
}
if (state is PerformanceLoaded) {
final report = state.report;
final PerformanceReport report = state.report;
// Compute overall score (0100) from the 4 KPIs
final overallScore = ((report.fillRate * 0.3) +
final double overallScore = ((report.fillRate * 0.3) +
(report.completionRate * 0.3) +
(report.onTimeRate * 0.25) +
// avg fill time: 3h target → invert to score
@@ -49,24 +50,24 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
0.15))
.clamp(0.0, 100.0);
final scoreLabel = overallScore >= 90
final String scoreLabel = overallScore >= 90
? context.t.client_reports.performance_report.overall_score.excellent
: overallScore >= 75
? context.t.client_reports.performance_report.overall_score.good
: context.t.client_reports.performance_report.overall_score.needs_work;
final scoreLabelColor = overallScore >= 90
final Color scoreLabelColor = overallScore >= 90
? UiColors.success
: overallScore >= 75
? UiColors.textWarning
: UiColors.error;
final scoreLabelBg = overallScore >= 90
final Color scoreLabelBg = overallScore >= 90
? UiColors.tagSuccess
: overallScore >= 75
? UiColors.tagPending
: UiColors.tagError;
// KPI rows: label, value, target, color, met status
final kpis = [
final List<_KpiData> kpis = <_KpiData>[
_KpiData(
icon: UiIcons.users,
iconColor: UiColors.primary,
@@ -119,7 +120,7 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
return SingleChildScrollView(
child: Column(
children: [
children: <Widget>[
// ── Header ───────────────────────────────────────────
Container(
padding: const EdgeInsets.only(
@@ -130,16 +131,16 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
),
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [UiColors.primary, UiColors.buttonPrimaryHover],
colors: <Color>[UiColors.primary, UiColors.buttonPrimaryHover],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
@@ -159,7 +160,7 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
context.t.client_reports.performance_report
.title,
@@ -229,7 +230,7 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
children: [
children: <Widget>[
// ── Overall Score Hero Card ───────────────────
Container(
width: double.infinity,
@@ -240,7 +241,7 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
decoration: BoxDecoration(
color: const Color(0xFFF0F4FF),
borderRadius: BorderRadius.circular(16),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.04),
blurRadius: 10,
@@ -249,7 +250,7 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
],
),
child: Column(
children: [
children: <Widget>[
const Icon(
UiIcons.chart,
size: 32,
@@ -258,7 +259,7 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
const SizedBox(height: 12),
Text(
context.t.client_reports.performance_report.overall_score.title,
style: TextStyle(
style: const TextStyle(
fontSize: 13,
color: UiColors.textSecondary,
),
@@ -303,7 +304,7 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.04),
blurRadius: 10,
@@ -312,7 +313,7 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
context.t.client_reports.performance_report.kpis_title,
style: const TextStyle(
@@ -324,7 +325,7 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
),
const SizedBox(height: 20),
...kpis.map(
(kpi) => _KpiRow(kpi: kpi),
(_KpiData kpi) => _KpiRow(kpi: kpi),
),
],
),
@@ -349,15 +350,6 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
// ── KPI data model ────────────────────────────────────────────────────────────
class _KpiData {
final IconData icon;
final Color iconColor;
final String label;
final String target;
final double value; // 0100 for bar
final String displayValue;
final Color barColor;
final bool met;
final bool close;
const _KpiData({
required this.icon,
@@ -370,27 +362,36 @@ class _KpiData {
required this.met,
required this.close,
});
final IconData icon;
final Color iconColor;
final String label;
final String target;
final double value; // 0100 for bar
final String displayValue;
final Color barColor;
final bool met;
final bool close;
}
// ── KPI row widget ────────────────────────────────────────────────────────────
class _KpiRow extends StatelessWidget {
final _KpiData kpi;
const _KpiRow({required this.kpi});
final _KpiData kpi;
@override
Widget build(BuildContext context) {
final badgeText = kpi.met
final String badgeText = kpi.met
? context.t.client_reports.performance_report.kpis.met
: kpi.close
? context.t.client_reports.performance_report.kpis.close
: context.t.client_reports.performance_report.kpis.miss;
final badgeColor = kpi.met
final Color badgeColor = kpi.met
? UiColors.success
: kpi.close
? UiColors.textWarning
: UiColors.error;
final badgeBg = kpi.met
final Color badgeBg = kpi.met
? UiColors.tagSuccess
: kpi.close
? UiColors.tagPending
@@ -399,9 +400,9 @@ class _KpiRow extends StatelessWidget {
return Padding(
padding: const EdgeInsets.only(bottom: 20),
child: Column(
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
Container(
width: 36,
height: 36,
@@ -415,7 +416,7 @@ class _KpiRow extends StatelessWidget {
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
kpi.label,
style: const TextStyle(
@@ -437,7 +438,7 @@ class _KpiRow extends StatelessWidget {
// Value + badge inline (matches prototype)
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
children: <Widget>[
Text(
kpi.displayValue,
style: const TextStyle(

View File

@@ -24,7 +24,7 @@ class _ReportsPageState extends State<ReportsPage>
late ReportsSummaryBloc _summaryBloc;
// Date ranges per tab: Today, Week, Month, Quarter
final List<(DateTime, DateTime)> _dateRanges = [
final List<(DateTime, DateTime)> _dateRanges = <(DateTime, DateTime)>[
(
DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day),
DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day,
@@ -64,7 +64,7 @@ class _ReportsPageState extends State<ReportsPage>
}
void _loadSummary(int tabIndex) {
final range = _dateRanges[tabIndex];
final (DateTime, DateTime) range = _dateRanges[tabIndex];
_summaryBloc.add(LoadReportsSummary(
startDate: range.$1,
endDate: range.$2,
@@ -85,7 +85,7 @@ class _ReportsPageState extends State<ReportsPage>
backgroundColor: UiColors.bgMenu,
body: SingleChildScrollView(
child: Column(
children: [
children: <Widget>[
// Header with title and tabs
ReportsHeader(
tabController: _tabController,
@@ -93,20 +93,20 @@ class _ReportsPageState extends State<ReportsPage>
),
// Content
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
// Key Metrics Grid
const MetricsGrid(),
MetricsGrid(),
const SizedBox(height: 24),
SizedBox(height: 24),
// Quick Reports Section
const QuickReportsSection(),
QuickReportsSection(),
const SizedBox(height: 40),
SizedBox(height: 40),
],
),
),

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:client_reports/src/presentation/blocs/spend/spend_bloc.dart';
import 'package:client_reports/src/presentation/blocs/spend/spend_event.dart';
import 'package:client_reports/src/presentation/blocs/spend/spend_state.dart';
@@ -24,10 +25,10 @@ class _SpendReportPageState extends State<SpendReportPage> {
@override
void initState() {
super.initState();
final now = DateTime.now();
final DateTime now = DateTime.now();
// Monday alignment logic
final diff = now.weekday - DateTime.monday;
final monday = now.subtract(Duration(days: diff));
final int diff = now.weekday - DateTime.monday;
final DateTime monday = now.subtract(Duration(days: diff));
_startDate = DateTime(monday.year, monday.month, monday.day);
_endDate = _startDate.add(const Duration(days: 6, hours: 23, minutes: 59, seconds: 59));
}
@@ -35,12 +36,12 @@ class _SpendReportPageState extends State<SpendReportPage> {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => Modular.get<SpendBloc>()
create: (BuildContext context) => Modular.get<SpendBloc>()
..add(LoadSpendReport(startDate: _startDate, endDate: _endDate)),
child: Scaffold(
backgroundColor: UiColors.bgMenu,
body: BlocBuilder<SpendBloc, SpendState>(
builder: (context, state) {
builder: (BuildContext context, SpendState state) {
if (state is SpendLoading) {
return const Center(child: CircularProgressIndicator());
}
@@ -50,10 +51,10 @@ class _SpendReportPageState extends State<SpendReportPage> {
}
if (state is SpendLoaded) {
final report = state.report;
final SpendReport report = state.report;
return SingleChildScrollView(
child: Column(
children: [
children: <Widget>[
// Header
Container(
padding: const EdgeInsets.only(
@@ -67,9 +68,9 @@ class _SpendReportPageState extends State<SpendReportPage> {
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
@@ -89,7 +90,7 @@ class _SpendReportPageState extends State<SpendReportPage> {
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
context.t.client_reports.spend_report.title,
style: const TextStyle(
@@ -167,10 +168,10 @@ class _SpendReportPageState extends State<SpendReportPage> {
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
// Summary Cards (New Style)
Row(
children: [
children: <Widget>[
Expanded(
child: _SpendStatCard(
label: context.t.client_reports.spend_report
@@ -209,7 +210,7 @@ class _SpendReportPageState extends State<SpendReportPage> {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.04),
blurRadius: 10,
@@ -219,7 +220,7 @@ class _SpendReportPageState extends State<SpendReportPage> {
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
context.t.client_reports.spend_report.chart_title,
style: const TextStyle(
@@ -262,9 +263,9 @@ class _SpendReportPageState extends State<SpendReportPage> {
}
class _SpendBarChart extends StatelessWidget {
final List<dynamic> chartData;
const _SpendBarChart({required this.chartData});
final List<dynamic> chartData;
@override
Widget build(BuildContext context) {
@@ -272,14 +273,14 @@ class _SpendBarChart extends StatelessWidget {
BarChartData(
alignment: BarChartAlignment.spaceAround,
maxY: (chartData.fold<double>(0,
(prev, element) =>
(double prev, element) =>
element.amount > prev ? element.amount : prev) *
1.2)
.ceilToDouble(),
barTouchData: BarTouchData(
touchTooltipData: BarTouchTooltipData(
tooltipPadding: const EdgeInsets.all(8),
getTooltipItem: (group, groupIndex, rod, rodIndex) {
getTooltipItem: (BarChartGroupData group, int groupIndex, BarChartRodData rod, int rodIndex) {
return BarTooltipItem(
'\$${rod.toY.round()}',
const TextStyle(
@@ -296,7 +297,7 @@ class _SpendBarChart extends StatelessWidget {
sideTitles: SideTitles(
showTitles: true,
reservedSize: 30,
getTitlesWidget: (value, meta) {
getTitlesWidget: (double value, TitleMeta meta) {
if (value.toInt() >= chartData.length) return const SizedBox();
final date = chartData[value.toInt()].date;
return SideTitleWidget(
@@ -317,7 +318,7 @@ class _SpendBarChart extends StatelessWidget {
sideTitles: SideTitles(
showTitles: true,
reservedSize: 40,
getTitlesWidget: (value, meta) {
getTitlesWidget: (double value, TitleMeta meta) {
if (value == 0) return const SizedBox();
return SideTitleWidget(
axisSide: meta.axisSide,
@@ -343,7 +344,7 @@ class _SpendBarChart extends StatelessWidget {
show: true,
drawVerticalLine: false,
horizontalInterval: 1000,
getDrawingHorizontalLine: (value) => FlLine(
getDrawingHorizontalLine: (double value) => const FlLine(
color: UiColors.bgSecondary,
strokeWidth: 1,
),
@@ -351,9 +352,9 @@ class _SpendBarChart extends StatelessWidget {
borderData: FlBorderData(show: false),
barGroups: List.generate(
chartData.length,
(index) => BarChartGroupData(
(int index) => BarChartGroupData(
x: index,
barRods: [
barRods: <BarChartRodData>[
BarChartRodData(
toY: chartData[index].amount,
color: UiColors.success,
@@ -371,11 +372,6 @@ class _SpendBarChart extends StatelessWidget {
}
class _SpendStatCard extends StatelessWidget {
final String label;
final String value;
final String pillText;
final Color themeColor;
final IconData icon;
const _SpendStatCard({
required this.label,
@@ -384,6 +380,11 @@ class _SpendStatCard extends StatelessWidget {
required this.themeColor,
required this.icon,
});
final String label;
final String value;
final String pillText;
final Color themeColor;
final IconData icon;
@override
Widget build(BuildContext context) {
@@ -392,7 +393,7 @@ class _SpendStatCard extends StatelessWidget {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.06),
blurRadius: 8,
@@ -402,9 +403,9 @@ class _SpendStatCard extends StatelessWidget {
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Row(
children: [
children: <Widget>[
Icon(icon, size: 14, color: themeColor),
const SizedBox(width: 8),
Expanded(
@@ -453,9 +454,9 @@ class _SpendStatCard extends StatelessWidget {
}
class _SpendByIndustryCard extends StatelessWidget {
final List<SpendIndustryCategory> industries;
const _SpendByIndustryCard({required this.industries});
final List<SpendIndustryCategory> industries;
@override
Widget build(BuildContext context) {
@@ -464,7 +465,7 @@ class _SpendByIndustryCard extends StatelessWidget {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.04),
blurRadius: 10,
@@ -474,7 +475,7 @@ class _SpendByIndustryCard extends StatelessWidget {
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
context.t.client_reports.spend_report.spend_by_industry,
style: const TextStyle(
@@ -495,14 +496,14 @@ class _SpendByIndustryCard extends StatelessWidget {
),
)
else
...industries.map((ind) => Padding(
...industries.map((SpendIndustryCategory ind) => Padding(
padding: const EdgeInsets.only(bottom: 24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
Text(
ind.name,
style: const TextStyle(
@@ -547,3 +548,4 @@ class _SpendByIndustryCard extends StatelessWidget {
);
}
}

View File

@@ -6,6 +6,17 @@ import 'package:flutter/material.dart';
/// Shows a metric with an icon, label, value, and a badge with contextual
/// information. Used in the metrics grid of the reports page.
class MetricCard extends StatelessWidget {
const MetricCard({
super.key,
required this.icon,
required this.label,
required this.value,
required this.badgeText,
required this.badgeColor,
required this.badgeTextColor,
required this.iconColor,
});
/// The icon to display for this metric.
final IconData icon;
@@ -27,17 +38,6 @@ class MetricCard extends StatelessWidget {
/// Color for the icon.
final Color iconColor;
const MetricCard({
super.key,
required this.icon,
required this.label,
required this.value,
required this.badgeText,
required this.badgeColor,
required this.badgeTextColor,
required this.iconColor,
});
@override
Widget build(BuildContext context) {
return Container(
@@ -45,7 +45,7 @@ class MetricCard extends StatelessWidget {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.06),
blurRadius: 4,
@@ -56,10 +56,10 @@ class MetricCard extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
// Icon and Label
Row(
children: [
children: <Widget>[
Icon(icon, size: 16, color: iconColor),
const SizedBox(width: 8),
Expanded(
@@ -78,7 +78,7 @@ class MetricCard extends StatelessWidget {
// Value and Badge
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
value,
style: const TextStyle(

View File

@@ -5,6 +5,7 @@ import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';
import 'package:krow_domain/src/entities/reports/reports_summary.dart';
import 'metric_card.dart';
@@ -25,7 +26,7 @@ class MetricsGrid extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<ReportsSummaryBloc, ReportsSummaryState>(
builder: (context, state) {
builder: (BuildContext context, ReportsSummaryState state) {
// Loading or Initial State
if (state is ReportsSummaryLoading || state is ReportsSummaryInitial) {
return const Padding(
@@ -45,7 +46,7 @@ class MetricsGrid extends StatelessWidget {
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
children: <Widget>[
const Icon(UiIcons.warning,
color: UiColors.error, size: 16),
const SizedBox(width: 8),
@@ -63,8 +64,8 @@ class MetricsGrid extends StatelessWidget {
}
// Loaded State
final summary = (state as ReportsSummaryLoaded).summary;
final currencyFmt = NumberFormat.currency(
final ReportsSummary summary = (state as ReportsSummaryLoaded).summary;
final NumberFormat currencyFmt = NumberFormat.currency(
symbol: '\$', decimalDigits: 0);
return GridView.count(
@@ -74,7 +75,7 @@ class MetricsGrid extends StatelessWidget {
mainAxisSpacing: 12,
crossAxisSpacing: 12,
childAspectRatio: 1.2,
children: [
children: <Widget>[
// Total Hours
MetricCard(
icon: UiIcons.clock,

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:core_localization/core_localization.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
@@ -18,7 +19,7 @@ class QuickReportsSection extends StatelessWidget {
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
// Title
Text(
context.t.client_reports.quick_reports.title,
@@ -33,7 +34,7 @@ class QuickReportsSection extends StatelessWidget {
mainAxisSpacing: 12,
crossAxisSpacing: 12,
childAspectRatio: 1.3,
children: [
children: <Widget>[
// Daily Operations
ReportCard(
icon: UiIcons.calendar,
@@ -89,3 +90,4 @@ class QuickReportsSection extends StatelessWidget {
);
}
}

View File

@@ -8,6 +8,15 @@ import 'package:flutter_modular/flutter_modular.dart';
/// Displays an icon, name, and a quick navigation to a report page.
/// Used in the quick reports grid of the reports page.
class ReportCard extends StatelessWidget {
const ReportCard({
super.key,
required this.icon,
required this.name,
required this.iconBgColor,
required this.iconColor,
required this.route,
});
/// The icon to display for this report.
final IconData icon;
@@ -23,15 +32,6 @@ class ReportCard extends StatelessWidget {
/// Navigation route to the report page.
final String route;
const ReportCard({
super.key,
required this.icon,
required this.name,
required this.iconBgColor,
required this.iconColor,
required this.route,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
@@ -41,7 +41,7 @@ class ReportCard extends StatelessWidget {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.02),
blurRadius: 2,
@@ -51,7 +51,7 @@ class ReportCard extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
// Icon Container
Container(
width: 40,
@@ -65,7 +65,7 @@ class ReportCard extends StatelessWidget {
// Name and Export Info
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
name,
style: const TextStyle(
@@ -78,7 +78,7 @@ class ReportCard extends StatelessWidget {
),
const SizedBox(height: 4),
Row(
children: [
children: <Widget>[
const Icon(
UiIcons.download,
size: 12,

View File

@@ -32,7 +32,7 @@ class ReportsHeader extends StatelessWidget {
),
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
colors: <Color>[
UiColors.primary,
UiColors.buttonPrimaryHover,
],
@@ -41,10 +41,10 @@ class ReportsHeader extends StatelessWidget {
),
),
child: Column(
children: [
children: <Widget>[
// Title and Back Button
Row(
children: [
children: <Widget>[
GestureDetector(
onTap: () => Modular.to.toClientHome(),
child: Container(
@@ -104,7 +104,7 @@ class ReportsHeader extends StatelessWidget {
),
indicatorSize: TabBarIndicatorSize.tab,
dividerColor: Colors.transparent,
tabs: [
tabs: <Widget>[
Tab(text: context.t.client_reports.tabs.today),
Tab(text: context.t.client_reports.tabs.week),
Tab(text: context.t.client_reports.tabs.month),

View File

@@ -1,3 +1,4 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:client_reports/src/data/repositories_impl/reports_repository_impl.dart';
import 'package:client_reports/src/domain/repositories/reports_repository.dart';
import 'package:client_reports/src/presentation/blocs/daily_ops/daily_ops_bloc.dart';
@@ -19,7 +20,7 @@ import 'package:krow_data_connect/krow_data_connect.dart';
class ReportsModule extends Module {
@override
List<Module> get imports => [DataConnectModule()];
List<Module> get imports => <Module>[DataConnectModule()];
@override
void binds(Injector i) {
@@ -44,3 +45,4 @@ class ReportsModule extends Module {
r.child('/no-show', child: (_) => const NoShowReportPage());
}
}

View File

@@ -5,12 +5,12 @@ import '../repositories/settings_repository_interface.dart';
///
/// This use case delegates the sign out logic to the [SettingsRepositoryInterface].
class SignOutUseCase implements NoInputUseCase<void> {
final SettingsRepositoryInterface _repository;
/// Creates a [SignOutUseCase].
///
/// Requires a [SettingsRepositoryInterface] to perform the sign out operation.
SignOutUseCase(this._repository);
final SettingsRepositoryInterface _repository;
@override
Future<void> call() {

View File

@@ -9,13 +9,13 @@ part 'client_settings_state.dart';
/// BLoC to manage client settings and profile state.
class ClientSettingsBloc extends Bloc<ClientSettingsEvent, ClientSettingsState>
with BlocErrorHandler<ClientSettingsState> {
final SignOutUseCase _signOutUseCase;
ClientSettingsBloc({required SignOutUseCase signOutUseCase})
: _signOutUseCase = signOutUseCase,
super(const ClientSettingsInitial()) {
on<ClientSettingsSignOutRequested>(_onSignOutRequested);
}
final SignOutUseCase _signOutUseCase;
Future<void> _onSignOutRequested(
ClientSettingsSignOutRequested event,
@@ -23,7 +23,7 @@ class ClientSettingsBloc extends Bloc<ClientSettingsEvent, ClientSettingsState>
) async {
emit(const ClientSettingsLoading());
await handleError(
emit: emit,
emit: emit.call,
action: () async {
await _signOutUseCase();
emit(const ClientSettingsSignOutSuccess());

View File

@@ -20,9 +20,9 @@ class ClientSettingsSignOutSuccess extends ClientSettingsState {
}
class ClientSettingsError extends ClientSettingsState {
final String message;
const ClientSettingsError(this.message);
final String message;
@override
List<Object?> get props => <Object?>[message];

View File

@@ -110,9 +110,9 @@ class SettingsActions extends StatelessWidget {
/// Quick Links card — inline here since it's always part of SettingsActions ordering.
class _QuickLinksCard extends StatelessWidget {
final TranslationsClientSettingsProfileEn labels;
const _QuickLinksCard({required this.labels});
final TranslationsClientSettingsProfileEn labels;
@override
Widget build(BuildContext context) {
@@ -152,15 +152,15 @@ class _QuickLinksCard extends StatelessWidget {
/// A single quick link row item.
class _QuickLinkItem extends StatelessWidget {
final IconData icon;
final String title;
final VoidCallback onTap;
const _QuickLinkItem({
required this.icon,
required this.title,
required this.onTap,
});
final IconData icon;
final String title;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {

View File

@@ -75,7 +75,7 @@ class SettingsProfileHeader extends StatelessWidget {
color: UiColors.white.withValues(alpha: 0.6),
width: 3,
),
boxShadow: [
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withValues(alpha: 0.15),
blurRadius: 16,

View File

@@ -56,6 +56,13 @@ class SettingsQuickLinks extends StatelessWidget {
/// Internal widget for a single quick link item.
class _QuickLinkItem extends StatelessWidget {
/// Creates a [_QuickLinkItem].
const _QuickLinkItem({
required this.icon,
required this.title,
required this.onTap,
});
/// The icon to display.
final IconData icon;
@@ -65,13 +72,6 @@ class _QuickLinkItem extends StatelessWidget {
/// Callback when the link is tapped.
final VoidCallback onTap;
/// Creates a [_QuickLinkItem].
const _QuickLinkItem({
required this.icon,
required this.title,
required this.onTap,
});
@override
/// Builds the quick link item UI.
Widget build(BuildContext context) {

View File

@@ -6,11 +6,11 @@ import '../../domain/repositories/i_view_orders_repository.dart';
/// Implementation of [IViewOrdersRepository] using Data Connect.
class ViewOrdersRepositoryImpl implements IViewOrdersRepository {
final dc.DataConnectService _service;
ViewOrdersRepositoryImpl({
required dc.DataConnectService service,
}) : _service = service;
final dc.DataConnectService _service;
@override
Future<List<domain.OrderItem>> getOrdersForRange({

View File

@@ -9,10 +9,10 @@ import '../arguments/orders_range_arguments.dart';
/// and delegates the data retrieval to the [IViewOrdersRepository].
class GetOrdersUseCase
implements UseCase<OrdersRangeArguments, List<OrderItem>> {
final IViewOrdersRepository _repository;
/// Creates a [GetOrdersUseCase] with the required [IViewOrdersRepository].
GetOrdersUseCase(this._repository);
final IViewOrdersRepository _repository;
@override
Future<List<OrderItem>> call(OrdersRangeArguments input) {

View File

@@ -847,12 +847,12 @@ class _OrderEditSheetState extends State<_OrderEditSheet> {
.toList();
await _loadVendorsAndSelect(firstShift.order.vendorId);
final dc.ListShiftRolesByBusinessAndOrderShiftRolesShiftOrderTeamHub?
final dc.ListShiftRolesByBusinessAndOrderShiftRolesShiftOrderTeamHub
teamHub = firstShift.order.teamHub;
await _loadHubsAndSelect(
placeId: teamHub?.placeId,
hubName: teamHub?.hubName,
address: teamHub?.address,
placeId: teamHub.placeId,
hubName: teamHub.hubName,
address: teamHub.address,
);
if (mounted) {