Add explicit types and improve type safety across codebase

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

View File

@@ -1,4 +1,5 @@
import 'package:firebase_auth/firebase_auth.dart' as firebase;
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' as domain;
import '../../domain/repositories/hub_repository_interface.dart';
@@ -16,8 +17,8 @@ class HubRepositoryImpl implements HubRepositoryInterface {
@override
Future<List<domain.Hub>> getHubs() async {
final business = await _getBusinessForCurrentUser();
final teamId = await _getOrCreateTeamId(business);
final dc.GetBusinessesByUserIdBusinesses business = await _getBusinessForCurrentUser();
final String teamId = await _getOrCreateTeamId(business);
return _fetchHubsForTeam(teamId: teamId, businessId: business.id);
}
@@ -26,11 +27,11 @@ class HubRepositoryImpl implements HubRepositoryInterface {
required String name,
required String address,
}) async {
final business = await _getBusinessForCurrentUser();
final teamId = await _getOrCreateTeamId(business);
final city = business.city;
final dc.GetBusinessesByUserIdBusinesses business = await _getBusinessForCurrentUser();
final String teamId = await _getOrCreateTeamId(business);
final String? city = business.city;
final result = await _dataConnect
final OperationResult<dc.CreateTeamHubData, dc.CreateTeamHubVariables> result = await _dataConnect
.createTeamHub(
teamId: teamId,
hubName: name,
@@ -38,17 +39,17 @@ class HubRepositoryImpl implements HubRepositoryInterface {
)
.city(city?.isNotEmpty == true ? city : '')
.execute();
final createdId = result.data?.teamHub_insert.id;
final String? createdId = result.data?.teamHub_insert.id;
if (createdId == null) {
throw Exception('Hub creation failed.');
}
final hubs = await _fetchHubsForTeam(
final List<domain.Hub> hubs = await _fetchHubsForTeam(
teamId: teamId,
businessId: business.id,
);
domain.Hub? createdHub;
for (final hub in hubs) {
for (final domain.Hub hub in hubs) {
if (hub.id == createdId) {
createdHub = hub;
break;
@@ -79,8 +80,8 @@ class HubRepositoryImpl implements HubRepositoryInterface {
}
Future<dc.GetBusinessesByUserIdBusinesses> _getBusinessForCurrentUser() async {
final session = dc.ClientSessionStore.instance.session;
final cachedBusiness = session?.business;
final dc.ClientSession? session = dc.ClientSessionStore.instance.session;
final dc.ClientBusinessSession? cachedBusiness = session?.business;
if (cachedBusiness != null) {
return dc.GetBusinessesByUserIdBusinesses(
id: cachedBusiness.id,
@@ -103,12 +104,12 @@ class HubRepositoryImpl implements HubRepositoryInterface {
);
}
final user = _firebaseAuth.currentUser;
final firebase.User? user = _firebaseAuth.currentUser;
if (user == null) {
throw Exception('User is not authenticated.');
}
final result = await _dataConnect.getBusinessesByUserId(
final QueryResult<dc.GetBusinessesByUserIdData, dc.GetBusinessesByUserIdVariables> result = await _dataConnect.getBusinessesByUserId(
userId: user.uid,
).execute();
if (result.data.businesses.isEmpty) {
@@ -116,7 +117,7 @@ class HubRepositoryImpl implements HubRepositoryInterface {
throw Exception('No business found for this user. Please sign in again.');
}
final business = result.data.businesses.first;
final dc.GetBusinessesByUserIdBusinesses business = result.data.businesses.first;
if (session != null) {
dc.ClientSessionStore.instance.setSession(
dc.ClientSession(
@@ -140,14 +141,14 @@ class HubRepositoryImpl implements HubRepositoryInterface {
Future<String> _getOrCreateTeamId(
dc.GetBusinessesByUserIdBusinesses business,
) async {
final teamsResult = await _dataConnect.getTeamsByOwnerId(
final QueryResult<dc.GetTeamsByOwnerIdData, dc.GetTeamsByOwnerIdVariables> teamsResult = await _dataConnect.getTeamsByOwnerId(
ownerId: business.id,
).execute();
if (teamsResult.data.teams.isNotEmpty) {
return teamsResult.data.teams.first.id;
}
final createTeamBuilder = _dataConnect.createTeam(
final dc.CreateTeamVariablesBuilder createTeamBuilder = _dataConnect.createTeam(
teamName: '${business.businessName} Team',
ownerId: business.id,
ownerName: business.contactName ?? '',
@@ -157,8 +158,8 @@ class HubRepositoryImpl implements HubRepositoryInterface {
createTeamBuilder.email(business.email);
}
final createTeamResult = await createTeamBuilder.execute();
final teamId = createTeamResult.data?.team_insert.id;
final OperationResult<dc.CreateTeamData, dc.CreateTeamVariables> createTeamResult = await createTeamBuilder.execute();
final String? teamId = createTeamResult.data?.team_insert.id;
if (teamId == null) {
throw Exception('Team creation failed.');
}
@@ -170,13 +171,13 @@ class HubRepositoryImpl implements HubRepositoryInterface {
required String teamId,
required String businessId,
}) async {
final hubsResult = await _dataConnect.getTeamHubsByTeamId(
final QueryResult<dc.GetTeamHubsByTeamIdData, dc.GetTeamHubsByTeamIdVariables> hubsResult = await _dataConnect.getTeamHubsByTeamId(
teamId: teamId,
).execute();
return hubsResult.data.teamHubs
.map(
(hub) => domain.Hub(
(dc.GetTeamHubsByTeamIdTeamHubs hub) => domain.Hub(
id: hub.id,
businessId: businessId,
name: hub.hubName,

View File

@@ -16,5 +16,5 @@ class AssignNfcTagArguments extends UseCaseArgument {
const AssignNfcTagArguments({required this.hubId, required this.nfcTagId});
@override
List<Object?> get props => [hubId, nfcTagId];
List<Object?> get props => <Object?>[hubId, nfcTagId];
}

View File

@@ -16,5 +16,5 @@ class CreateHubArguments extends UseCaseArgument {
const CreateHubArguments({required this.name, required this.address});
@override
List<Object?> get props => [name, address];
List<Object?> get props => <Object?>[name, address];
}

View File

@@ -13,5 +13,5 @@ class DeleteHubArguments extends UseCaseArgument {
const DeleteHubArguments({required this.hubId});
@override
List<Object?> get props => [hubId];
List<Object?> get props => <Object?>[hubId];
}

View File

@@ -1,5 +1,6 @@
import 'package:bloc/bloc.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:krow_domain/src/entities/business/hub.dart';
import '../../domain/arguments/assign_nfc_tag_arguments.dart';
import '../../domain/arguments/create_hub_arguments.dart';
import '../../domain/arguments/delete_hub_arguments.dart';
@@ -64,7 +65,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
) async {
emit(state.copyWith(status: ClientHubsStatus.loading));
try {
final hubs = await _getHubsUseCase();
final List<Hub> hubs = await _getHubsUseCase();
emit(state.copyWith(status: ClientHubsStatus.success, hubs: hubs));
} catch (e) {
emit(
@@ -85,7 +86,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
await _createHubUseCase(
CreateHubArguments(name: event.name, address: event.address),
);
final hubs = await _getHubsUseCase();
final List<Hub> hubs = await _getHubsUseCase();
emit(
state.copyWith(
status: ClientHubsStatus.actionSuccess,
@@ -111,7 +112,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
emit(state.copyWith(status: ClientHubsStatus.actionInProgress));
try {
await _deleteHubUseCase(DeleteHubArguments(hubId: event.hubId));
final hubs = await _getHubsUseCase();
final List<Hub> hubs = await _getHubsUseCase();
emit(
state.copyWith(
status: ClientHubsStatus.actionSuccess,
@@ -138,7 +139,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
await _assignNfcTagUseCase(
AssignNfcTagArguments(hubId: event.hubId, nfcTagId: event.nfcTagId),
);
final hubs = await _getHubsUseCase();
final List<Hub> hubs = await _getHubsUseCase();
emit(
state.copyWith(
status: ClientHubsStatus.actionSuccess,

View File

@@ -6,7 +6,7 @@ abstract class ClientHubsEvent extends Equatable {
const ClientHubsEvent();
@override
List<Object?> get props => [];
List<Object?> get props => <Object?>[];
}
/// Event triggered to fetch the list of hubs.
@@ -22,7 +22,7 @@ class ClientHubsAddRequested extends ClientHubsEvent {
const ClientHubsAddRequested({required this.name, required this.address});
@override
List<Object?> get props => [name, address];
List<Object?> get props => <Object?>[name, address];
}
/// Event triggered to delete a hub.
@@ -32,7 +32,7 @@ class ClientHubsDeleteRequested extends ClientHubsEvent {
const ClientHubsDeleteRequested(this.hubId);
@override
List<Object?> get props => [hubId];
List<Object?> get props => <Object?>[hubId];
}
/// Event triggered to assign an NFC tag to a hub.
@@ -46,7 +46,7 @@ class ClientHubsNfcTagAssignRequested extends ClientHubsEvent {
});
@override
List<Object?> get props => [hubId, nfcTagId];
List<Object?> get props => <Object?>[hubId, nfcTagId];
}
/// Event triggered to clear any error or success messages.
@@ -61,7 +61,7 @@ class ClientHubsAddDialogToggled extends ClientHubsEvent {
const ClientHubsAddDialogToggled({required this.visible});
@override
List<Object?> get props => [visible];
List<Object?> get props => <Object?>[visible];
}
/// Event triggered to toggle the visibility of the "Identify NFC" dialog.
@@ -71,5 +71,5 @@ class ClientHubsIdentifyDialogToggled extends ClientHubsEvent {
const ClientHubsIdentifyDialogToggled({this.hub});
@override
List<Object?> get props => [hub];
List<Object?> get props => <Object?>[hub];
}

View File

@@ -28,7 +28,7 @@ class ClientHubsState extends Equatable {
const ClientHubsState({
this.status = ClientHubsStatus.initial,
this.hubs = const [],
this.hubs = const <Hub>[],
this.errorMessage,
this.successMessage,
this.showAddHubDialog = false,
@@ -57,7 +57,7 @@ class ClientHubsState extends Equatable {
}
@override
List<Object?> get props => [
List<Object?> get props => <Object?>[
status,
hubs,
errorMessage,

View File

@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:core_localization/core_localization.dart';
import 'package:krow_domain/src/entities/business/hub.dart';
import '../blocs/client_hubs_bloc.dart';
import '../blocs/client_hubs_event.dart';
import '../blocs/client_hubs_state.dart';
@@ -23,10 +24,10 @@ class ClientHubsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider<ClientHubsBloc>(
create: (context) =>
create: (BuildContext context) =>
Modular.get<ClientHubsBloc>()..add(const ClientHubsFetched()),
child: BlocConsumer<ClientHubsBloc, ClientHubsState>(
listener: (context, state) {
listener: (BuildContext context, ClientHubsState state) {
if (state.errorMessage != null) {
ScaffoldMessenger.of(
context,
@@ -44,7 +45,7 @@ class ClientHubsPage extends StatelessWidget {
).add(const ClientHubsMessageCleared());
}
},
builder: (context, state) {
builder: (BuildContext context, ClientHubsState state) {
return Scaffold(
backgroundColor: UiColors.bgMenu,
floatingActionButton: FloatingActionButton(
@@ -67,7 +68,7 @@ class ClientHubsPage extends StatelessWidget {
vertical: UiConstants.space5,
).copyWith(bottom: 100),
sliver: SliverList(
delegate: SliverChildListDelegate([
delegate: SliverChildListDelegate(<Widget>[
if (state.status == ClientHubsStatus.loading)
const Center(child: CircularProgressIndicator())
else if (state.hubs.isEmpty)
@@ -79,9 +80,9 @@ class ClientHubsPage extends StatelessWidget {
),
),
)
else ...[
else ...<Widget>[
...state.hubs.map(
(hub) => HubCard(
(Hub hub) => HubCard(
hub: hub,
onNfcPressed: () =>
BlocProvider.of<ClientHubsBloc>(
@@ -105,7 +106,7 @@ class ClientHubsPage extends StatelessWidget {
),
if (state.showAddHubDialog)
AddHubDialog(
onCreate: (name, address) {
onCreate: (String name, String address) {
BlocProvider.of<ClientHubsBloc>(context).add(
ClientHubsAddRequested(name: name, address: address),
);
@@ -117,7 +118,7 @@ class ClientHubsPage extends StatelessWidget {
if (state.hubToIdentify != null)
IdentifyNfcDialog(
hub: state.hubToIdentify!,
onAssign: (tagId) {
onAssign: (String tagId) {
BlocProvider.of<ClientHubsBloc>(context).add(
ClientHubsNfcTagAssignRequested(
hubId: state.hubToIdentify!.id,
@@ -159,7 +160,7 @@ class ClientHubsPage extends StatelessWidget {
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
GestureDetector(
onTap: () => Modular.to.pop(),
child: Container(

View File

@@ -51,14 +51,14 @@ class _AddHubDialogState extends State<AddHubDialog> {
decoration: BoxDecoration(
color: UiColors.bgPopup,
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
boxShadow: const [
boxShadow: const <BoxShadow>[
BoxShadow(color: UiColors.popupShadow, blurRadius: 20),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
children: <Widget>[
Text(
t.client_hubs.add_hub_dialog.title,
style: UiTypography.headline3m.textPrimary,
@@ -83,7 +83,7 @@ class _AddHubDialogState extends State<AddHubDialog> {
),
const SizedBox(height: UiConstants.space8),
Row(
children: [
children: <Widget>[
Expanded(
child: UiButton.secondary(
onPressed: widget.onCancel,

View File

@@ -31,7 +31,7 @@ class HubCard extends StatelessWidget {
decoration: BoxDecoration(
color: UiColors.white,
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
boxShadow: const [
boxShadow: const <BoxShadow>[
BoxShadow(
color: UiColors.popupShadow,
blurRadius: 10,
@@ -42,7 +42,7 @@ class HubCard extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.all(UiConstants.space4),
child: Row(
children: [
children: <Widget>[
Container(
width: 52,
height: 52,
@@ -60,13 +60,13 @@ class HubCard extends StatelessWidget {
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(hub.name, style: UiTypography.body1b.textPrimary),
if (hub.address.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: UiConstants.space1),
child: Row(
children: [
children: <Widget>[
const Icon(
UiIcons.mapPin,
size: 12,
@@ -99,7 +99,7 @@ class HubCard extends StatelessWidget {
),
),
Row(
children: [
children: <Widget>[
IconButton(
onPressed: onDeletePressed,
icon: const Icon(

View File

@@ -17,7 +17,7 @@ class HubEmptyState extends StatelessWidget {
decoration: BoxDecoration(
color: UiColors.bgBanner,
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
boxShadow: const [
boxShadow: const <BoxShadow>[
BoxShadow(
color: UiColors.popupShadow,
blurRadius: 10,
@@ -26,7 +26,7 @@ class HubEmptyState extends StatelessWidget {
],
),
child: Column(
children: [
children: <Widget>[
Container(
width: 64,
height: 64,

View File

@@ -17,13 +17,13 @@ class HubInfoCard extends StatelessWidget {
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
const Icon(UiIcons.nfc, size: 20, color: UiColors.primary),
const SizedBox(width: UiConstants.space3),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
children: <Widget>[
Text(
t.client_hubs.about_hubs.title,
style: UiTypography.body2b.textPrimary,

View File

@@ -48,13 +48,13 @@ class _IdentifyNfcDialogState extends State<IdentifyNfcDialog> {
decoration: BoxDecoration(
color: UiColors.bgPopup,
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
boxShadow: const [
boxShadow: const <BoxShadow>[
BoxShadow(color: UiColors.popupShadow, blurRadius: 20),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
children: <Widget>[
Text(
t.client_hubs.nfc_dialog.title,
style: UiTypography.headline3m.textPrimary,
@@ -87,7 +87,7 @@ class _IdentifyNfcDialogState extends State<IdentifyNfcDialog> {
text: t.client_hubs.nfc_dialog.scan_button,
leadingIcon: UiIcons.nfc,
),
if (_nfcTagId != null) ...[
if (_nfcTagId != null) ...<Widget>[
const SizedBox(height: UiConstants.space6),
Container(
padding: const EdgeInsets.all(UiConstants.space4),
@@ -98,10 +98,10 @@ class _IdentifyNfcDialogState extends State<IdentifyNfcDialog> {
),
),
child: Column(
children: [
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.min,
children: [
children: <Widget>[
const Icon(
UiIcons.success,
size: 20,
@@ -141,7 +141,7 @@ class _IdentifyNfcDialogState extends State<IdentifyNfcDialog> {
],
const SizedBox(height: UiConstants.space8),
Row(
children: [
children: <Widget>[
Expanded(
child: UiButton.secondary(
onPressed: widget.onCancel,