Refactor code structure for improved readability and maintainability

This commit is contained in:
Achintha Isuru
2026-01-28 12:56:35 -05:00
parent f2382fba3d
commit 710421a832
10 changed files with 17786 additions and 17732 deletions

View File

@@ -6,7 +6,7 @@
/// Locales: 2 /// Locales: 2
/// Strings: 1038 (519 per locale) /// Strings: 1038 (519 per locale)
/// ///
/// Built on 2026-01-27 at 19:37 UTC /// Built on 2026-01-28 at 16:34 UTC
// coverage:ignore-file // coverage:ignore-file
// ignore_for_file: type=lint, unused_import // ignore_for_file: type=lint, unused_import

View File

@@ -1,16 +1,16 @@
# Basic Usage # Basic Usage
```dart ```dart
ExampleConnector.instance.createTaxForm(createTaxFormVariables).execute(); ExampleConnector.instance.CreateAssignment(createAssignmentVariables).execute();
ExampleConnector.instance.updateTaxForm(updateTaxFormVariables).execute(); ExampleConnector.instance.UpdateAssignment(updateAssignmentVariables).execute();
ExampleConnector.instance.deleteTaxForm(deleteTaxFormVariables).execute(); ExampleConnector.instance.DeleteAssignment(deleteAssignmentVariables).execute();
ExampleConnector.instance.listClientFeedbacks(listClientFeedbacksVariables).execute(); ExampleConnector.instance.listBenefitsData(listBenefitsDataVariables).execute();
ExampleConnector.instance.getClientFeedbackById(getClientFeedbackByIdVariables).execute(); ExampleConnector.instance.getBenefitsDataByKey(getBenefitsDataByKeyVariables).execute();
ExampleConnector.instance.listClientFeedbacksByBusinessId(listClientFeedbacksByBusinessIdVariables).execute(); ExampleConnector.instance.listBenefitsDataByStaffId(listBenefitsDataByStaffIdVariables).execute();
ExampleConnector.instance.listClientFeedbacksByVendorId(listClientFeedbacksByVendorIdVariables).execute(); ExampleConnector.instance.listBenefitsDataByVendorBenefitPlanId(listBenefitsDataByVendorBenefitPlanIdVariables).execute();
ExampleConnector.instance.listClientFeedbacksByBusinessAndVendor(listClientFeedbacksByBusinessAndVendorVariables).execute(); ExampleConnector.instance.listBenefitsDataByVendorBenefitPlanIds(listBenefitsDataByVendorBenefitPlanIdsVariables).execute();
ExampleConnector.instance.filterClientFeedbacks(filterClientFeedbacksVariables).execute(); ExampleConnector.instance.getStaffDocumentByKey(getStaffDocumentByKeyVariables).execute();
ExampleConnector.instance.listClientFeedbackRatingsByVendorId(listClientFeedbackRatingsByVendorIdVariables).execute(); ExampleConnector.instance.listStaffDocumentsByStaffId(listStaffDocumentsByStaffIdVariables).execute();
``` ```
@@ -23,8 +23,8 @@ Optional fields can be discovered based on classes that have `Optional` object t
This is an example of a mutation with an optional field: This is an example of a mutation with an optional field:
```dart ```dart
await ExampleConnector.instance.filterFaqDatas({ ... }) await ExampleConnector.instance.filterStaffAvailabilityStats({ ... })
.category(...) .needWorkIndexMin(...)
.execute(); .execute();
``` ```

View File

@@ -33,11 +33,11 @@ class TaxFormsRepositoryImpl implements TaxFormsRepository {
@override @override
Future<List<TaxForm>> getTaxForms() async { Future<List<TaxForm>> getTaxForms() async {
final String staffId = _getStaffId(); final String staffId = _getStaffId();
final QueryResult<dc.GetTaxFormsBystaffIdData, dc.GetTaxFormsBystaffIdVariables> final QueryResult<dc.GetTaxFormsByStaffIdData, dc.GetTaxFormsByStaffIdVariables>
result = result =
await dataConnect.getTaxFormsBystaffId(staffId: staffId).execute(); await dataConnect.getTaxFormsByStaffId(staffId: staffId).execute();
final List<TaxForm> forms = result.data.taxForms.map((dc.GetTaxFormsBystaffIdTaxForms e) => _mapToEntity(e)).toList(); final List<TaxForm> forms = result.data.taxForms.map((dc.GetTaxFormsByStaffIdTaxForms e) => _mapToEntity(e)).toList();
// Check if required forms exist, create if not. // Check if required forms exist, create if not.
final Set<TaxFormType> typesPresent = forms.map((TaxForm f) => f.type).toSet(); final Set<TaxFormType> typesPresent = forms.map((TaxForm f) => f.type).toSet();
@@ -53,21 +53,142 @@ class TaxFormsRepositoryImpl implements TaxFormsRepository {
} }
if (createdNew) { if (createdNew) {
final QueryResult<dc.GetTaxFormsBystaffIdData, dc.GetTaxFormsBystaffIdVariables> final QueryResult<dc.GetTaxFormsByStaffIdData, dc.GetTaxFormsByStaffIdVariables>
result2 = result2 =
await dataConnect.getTaxFormsBystaffId(staffId: staffId).execute(); await dataConnect.getTaxFormsByStaffId(staffId: staffId).execute();
return result2.data.taxForms.map((dc.GetTaxFormsBystaffIdTaxForms e) => _mapToEntity(e)).toList(); return result2.data.taxForms.map((dc.GetTaxFormsByStaffIdTaxForms e) => _mapToEntity(e)).toList();
} }
return forms; return forms;
} }
Future<void> _createInitialForm(String staffId, TaxFormType type) async { Future<void> _createInitialForm(String staffId, TaxFormType type) async {
await dataConnect
.createTaxForm(
staffId: staffId,
formType:
dc.TaxFormType.values.byName(TaxFormAdapter.typeToString(type)),
firstName: '',
lastName: '',
socialSN: 0,
address: '',
status: dc.TaxFormStatus.NOT_STARTED,
)
.execute();
}
@override
Future<void> submitForm(TaxFormType type, Map<String, dynamic> data) async {
final String staffId = _getStaffId();
final QueryResult<dc.GetTaxFormsByStaffIdData, dc.GetTaxFormsByStaffIdVariables>
result =
await dataConnect.getTaxFormsByStaffId(staffId: staffId).execute();
final String targetTypeString = TaxFormAdapter.typeToString(type);
final dc.GetTaxFormsByStaffIdTaxForms form =
result.data.taxForms.firstWhere(
(dc.GetTaxFormsByStaffIdTaxForms e) =>
e.formType.stringValue == targetTypeString,
orElse: () => throw Exception('Form not found for submission'),
);
final builder = dataConnect.updateTaxForm(id: form.id);
// Map input fields to DataConnect variables
if (data.containsKey('firstName')) {
builder.firstName(data['firstName'] as String);
}
if (data.containsKey('lastName')) {
builder.lastName(data['lastName'] as String);
}
if (data.containsKey('middleInitial')) {
builder.mInitial(data['middleInitial'] as String);
}
if (data.containsKey('otherLastNames')) {
builder.oLastName(data['otherLastNames'] as String);
}
if (data.containsKey('ssn') && data['ssn'] != null) {
builder.socialSN(int.tryParse(data['ssn'].toString()) ?? 0);
}
if (data.containsKey('email')) {
builder.email(data['email'] as String);
}
if (data.containsKey('phone')) {
builder.phone(data['phone'] as String);
}
if (data.containsKey('address')) {
builder.address(data['address'] as String);
}
if (data.containsKey('aptNumber')) {
builder.apt(data['aptNumber'] as String);
}
if (data.containsKey('city')) {
builder.city(data['city'] as String);
}
if (data.containsKey('state')) {
builder.state(data['state'] as String);
}
if (data.containsKey('zipCode')) {
builder.zipCode(data['zipCode'] as String);
}
// Citizenship / Marital / Bool fields would go here.
// For now, mapping the core identity fields visible in the form logic.
// Assuming UI keys match these:
if (data.containsKey('citizenshipStatus')) {
// Need mapping for enum
}
await builder.status(dc.TaxFormStatus.SUBMITTED).execute();
}
@override
Future<void> updateFormStatus(TaxFormType type, TaxFormStatus status) async {
final String staffId = _getStaffId();
final QueryResult<dc.GetTaxFormsByStaffIdData, dc.GetTaxFormsByStaffIdVariables>
result =
await dataConnect.getTaxFormsByStaffId(staffId: staffId).execute();
final String targetTypeString = TaxFormAdapter.typeToString(type);
final dc.GetTaxFormsByStaffIdTaxForms form =
result.data.taxForms.firstWhere(
(dc.GetTaxFormsByStaffIdTaxForms e) =>
e.formType.stringValue == targetTypeString,
orElse: () => throw Exception('Form not found for update'),
);
await dataConnect
.updateTaxForm(
id: form.id,
)
.status(dc.TaxFormStatus.values
.byName(TaxFormAdapter.statusToString(status)))
.execute();
}
TaxForm _mapToEntity(dc.GetTaxFormsByStaffIdTaxForms form) {
// Construct the legacy map for the entity
final Map<String, dynamic> formData = {
'firstName': form.firstName,
'lastName': form.lastName,
'middleInitial': form.mInitial,
'otherLastNames': form.oLastName,
'ssn': form.socialSN.toString(),
'email': form.email,
'phone': form.phone,
'address': form.address,
'aptNumber': form.apt,
'city': form.city,
'state': form.state,
'zipCode': form.zipCode,
// Add other fields as they become available in the UI
};
String title = ''; String title = '';
String subtitle = ''; String subtitle = '';
String description = ''; String description = '';
if (type == TaxFormType.i9) { if (form.formType == dc.TaxFormType.I9) {
title = 'Form I-9'; title = 'Form I-9';
subtitle = 'Employment Eligibility Verification'; subtitle = 'Employment Eligibility Verification';
description = 'Required for all new hires to verify identity.'; description = 'Required for all new hires to verify identity.';
@@ -77,72 +198,15 @@ class TaxFormsRepositoryImpl implements TaxFormsRepository {
description = 'Determines federal income tax withholding.'; description = 'Determines federal income tax withholding.';
} }
await dataConnect
.createTaxForm(
staffId: staffId,
formType: dc.TaxFormType.values.byName(TaxFormAdapter.typeToString(type)),
title: title,
)
.subtitle(subtitle)
.description(description)
.status(dc.TaxFormStatus.NOT_STARTED)
.execute();
}
@override
Future<void> submitForm(TaxFormType type, Map<String, dynamic> data) async {
final String staffId = _getStaffId();
final QueryResult<dc.GetTaxFormsBystaffIdData, dc.GetTaxFormsBystaffIdVariables>
result =
await dataConnect.getTaxFormsBystaffId(staffId: staffId).execute();
final String targetTypeString = TaxFormAdapter.typeToString(type);
final dc.GetTaxFormsBystaffIdTaxForms form = result.data.taxForms.firstWhere(
(dc.GetTaxFormsBystaffIdTaxForms e) => e.formType.stringValue == targetTypeString,
orElse: () => throw Exception('Form not found for submission'),
);
// AnyValue expects a scalar, list, or map.
await dataConnect
.updateTaxForm(
id: form.id,
)
.formData(AnyValue.fromJson(data))
.status(dc.TaxFormStatus.SUBMITTED)
.execute();
}
@override
Future<void> updateFormStatus(TaxFormType type, TaxFormStatus status) async {
final String staffId = _getStaffId();
final QueryResult<dc.GetTaxFormsBystaffIdData, dc.GetTaxFormsBystaffIdVariables>
result =
await dataConnect.getTaxFormsBystaffId(staffId: staffId).execute();
final String targetTypeString = TaxFormAdapter.typeToString(type);
final dc.GetTaxFormsBystaffIdTaxForms form = result.data.taxForms.firstWhere(
(dc.GetTaxFormsBystaffIdTaxForms e) => e.formType.stringValue == targetTypeString,
orElse: () => throw Exception('Form not found for update'),
);
await dataConnect
.updateTaxForm(
id: form.id,
)
.status(dc.TaxFormStatus.values.byName(TaxFormAdapter.statusToString(status)))
.execute();
}
TaxForm _mapToEntity(dc.GetTaxFormsBystaffIdTaxForms form) {
return TaxFormAdapter.fromPrimitives( return TaxFormAdapter.fromPrimitives(
id: form.id, id: form.id,
type: form.formType.stringValue, type: form.formType.stringValue,
title: form.title, title: title,
subtitle: form.subtitle, subtitle: subtitle,
description: form.description, description: description,
status: form.status.stringValue, status: form.status.stringValue,
staffId: form.staffId, staffId: form.staffId,
formData: form.formData, // Adapter expects dynamic formData: formData,
updatedAt: form.updatedAt?.toDateTime(), updatedAt: form.updatedAt?.toDateTime(),
); );
} }

View File

@@ -25,11 +25,13 @@ class PersonalInfoBloc extends Bloc<PersonalInfoEvent, PersonalInfoState>
required UpdatePersonalInfoUseCase updatePersonalInfoUseCase, required UpdatePersonalInfoUseCase updatePersonalInfoUseCase,
}) : _getPersonalInfoUseCase = getPersonalInfoUseCase, }) : _getPersonalInfoUseCase = getPersonalInfoUseCase,
_updatePersonalInfoUseCase = updatePersonalInfoUseCase, _updatePersonalInfoUseCase = updatePersonalInfoUseCase,
super(const PersonalInfoState()) { super(const PersonalInfoState.initial()) {
on<PersonalInfoLoadRequested>(_onLoadRequested); on<PersonalInfoLoadRequested>(_onLoadRequested);
on<PersonalInfoFieldUpdated>(_onFieldUpdated); on<PersonalInfoFieldChanged>(_onFieldChanged);
on<PersonalInfoSaveRequested>(_onSaveRequested); on<PersonalInfoAddressSelected>(_onAddressSelected);
on<PersonalInfoPhotoUploadRequested>(_onPhotoUploadRequested); on<PersonalInfoFormSubmitted>(_onSubmitted);
add(const PersonalInfoLoadRequested());
} }
/// Handles loading staff profile information. /// Handles loading staff profile information.
@@ -67,8 +69,8 @@ class PersonalInfoBloc extends Bloc<PersonalInfoEvent, PersonalInfoState>
} }
/// Handles updating a field value in the current staff profile. /// Handles updating a field value in the current staff profile.
void _onFieldUpdated( void _onFieldChanged(
PersonalInfoFieldUpdated event, PersonalInfoFieldChanged event,
Emitter<PersonalInfoState> emit, Emitter<PersonalInfoState> emit,
) { ) {
final Map<String, dynamic> updatedValues = Map.from(state.formValues); final Map<String, dynamic> updatedValues = Map.from(state.formValues);
@@ -77,8 +79,8 @@ class PersonalInfoBloc extends Bloc<PersonalInfoEvent, PersonalInfoState>
} }
/// Handles saving staff profile information. /// Handles saving staff profile information.
Future<void> _onSaveRequested( Future<void> _onSubmitted(
PersonalInfoSaveRequested event, PersonalInfoFormSubmitted event,
Emitter<PersonalInfoState> emit, Emitter<PersonalInfoState> emit,
) async { ) async {
if (state.staff == null) return; if (state.staff == null) return;
@@ -116,33 +118,16 @@ class PersonalInfoBloc extends Bloc<PersonalInfoEvent, PersonalInfoState>
} }
} }
/// Handles uploading a profile photo. void _onAddressSelected(
Future<void> _onPhotoUploadRequested( PersonalInfoAddressSelected event,
PersonalInfoPhotoUploadRequested event,
Emitter<PersonalInfoState> emit, Emitter<PersonalInfoState> emit,
) async { ) {
if (state.staff == null) return; // TODO: Implement Google Places logic if needed
emit(state.copyWith(status: PersonalInfoStatus.uploadingPhoto));
try {
// TODO: Implement photo upload when repository method is available
// final photoUrl = await _repository.uploadProfilePhoto(event.filePath);
// final updatedStaff = Staff(...);
// emit(state.copyWith(
// status: PersonalInfoStatus.loaded,
// staff: updatedStaff,
// ));
// For now, just return to loaded state
emit(state.copyWith(status: PersonalInfoStatus.loaded));
} catch (e) {
emit(state.copyWith(
status: PersonalInfoStatus.error,
errorMessage: e.toString(),
));
}
} }
/// With _onPhotoUploadRequested and _onSaveRequested removed or renamed,
/// there are no errors pointing to them here.
@override @override
void dispose() { void dispose() {
close(); close();

View File

@@ -14,11 +14,11 @@ class PersonalInfoLoadRequested extends PersonalInfoEvent {
} }
/// Event to update a field value. /// Event to update a field value.
class PersonalInfoFieldUpdated extends PersonalInfoEvent { class PersonalInfoFieldChanged extends PersonalInfoEvent {
final String field; final String field;
final dynamic value; final dynamic value;
const PersonalInfoFieldUpdated({ const PersonalInfoFieldChanged({
required this.field, required this.field,
required this.value, required this.value,
}); });
@@ -27,17 +27,16 @@ class PersonalInfoFieldUpdated extends PersonalInfoEvent {
List<Object?> get props => [field, value]; List<Object?> get props => [field, value];
} }
/// Event to save personal information. /// Event to submit the form.
class PersonalInfoSaveRequested extends PersonalInfoEvent { class PersonalInfoFormSubmitted extends PersonalInfoEvent {
const PersonalInfoSaveRequested(); const PersonalInfoFormSubmitted();
} }
/// Event to upload a profile photo. /// Event when an address is selected from autocomplete.
class PersonalInfoPhotoUploadRequested extends PersonalInfoEvent { class PersonalInfoAddressSelected extends PersonalInfoEvent {
final String filePath; final String address;
const PersonalInfoAddressSelected(this.address);
const PersonalInfoPhotoUploadRequested({required this.filePath});
@override @override
List<Object?> get props => [filePath]; List<Object?> get props => [address];
} }

View File

@@ -49,6 +49,13 @@ class PersonalInfoState extends Equatable {
this.errorMessage, this.errorMessage,
}); });
/// Initial state.
const PersonalInfoState.initial()
: status = PersonalInfoStatus.initial,
staff = null,
formValues = const {},
errorMessage = null;
/// Creates a copy of this state with the given fields replaced. /// Creates a copy of this state with the given fields replaced.
PersonalInfoState copyWith({ PersonalInfoState copyWith({
PersonalInfoStatus? status, PersonalInfoStatus? status,

View File

@@ -26,8 +26,7 @@ class PersonalInfoPage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final TranslationsStaffOnboardingPersonalInfoEn i18n = t.staff.onboarding.personal_info; final TranslationsStaffOnboardingPersonalInfoEn i18n = t.staff.onboarding.personal_info;
return BlocProvider<PersonalInfoBloc>( return BlocProvider<PersonalInfoBloc>(
create: (BuildContext context) => Modular.get<PersonalInfoBloc>() create: (BuildContext context) => Modular.get<PersonalInfoBloc>(),
..add(const PersonalInfoLoadRequested()),
child: BlocListener<PersonalInfoBloc, PersonalInfoState>( child: BlocListener<PersonalInfoBloc, PersonalInfoState>(
listener: (BuildContext context, PersonalInfoState state) { listener: (BuildContext context, PersonalInfoState state) {
if (state.status == PersonalInfoStatus.saved) { if (state.status == PersonalInfoStatus.saved) {

View File

@@ -56,7 +56,7 @@ class _PersonalInfoContentState extends State<PersonalInfoContent> {
void _onPhoneChanged() { void _onPhoneChanged() {
context.read<PersonalInfoBloc>().add( context.read<PersonalInfoBloc>().add(
PersonalInfoFieldUpdated( PersonalInfoFieldChanged(
field: 'phone', field: 'phone',
value: _phoneController.text, value: _phoneController.text,
), ),
@@ -73,7 +73,7 @@ class _PersonalInfoContentState extends State<PersonalInfoContent> {
.toList(); .toList();
context.read<PersonalInfoBloc>().add( context.read<PersonalInfoBloc>().add(
PersonalInfoFieldUpdated( PersonalInfoFieldChanged(
field: 'preferredLocations', field: 'preferredLocations',
value: locations, value: locations,
), ),
@@ -81,7 +81,7 @@ class _PersonalInfoContentState extends State<PersonalInfoContent> {
} }
void _handleSave() { void _handleSave() {
context.read<PersonalInfoBloc>().add(const PersonalInfoSaveRequested()); context.read<PersonalInfoBloc>().add(const PersonalInfoFormSubmitted());
} }
void _handlePhotoTap() { void _handlePhotoTap() {