diff --git a/apps/mobile/apps/staff/lib/main.dart b/apps/mobile/apps/staff/lib/main.dart index 52919e9a..4852b03d 100644 --- a/apps/mobile/apps/staff/lib/main.dart +++ b/apps/mobile/apps/staff/lib/main.dart @@ -1,5 +1,6 @@ import 'package:core_localization/core_localization.dart' as core_localization; import 'package:design_system/design_system.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; @@ -7,7 +8,6 @@ import 'package:flutter_modular/flutter_modular.dart'; import 'package:staff_authentication/staff_authentication.dart' as staff_authentication; import 'package:staff_main/staff_main.dart' as staff_main; -import 'package:firebase_core/firebase_core.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); diff --git a/apps/mobile/packages/domain/lib/src/adapters/profile/tax_form_adapter.dart b/apps/mobile/packages/domain/lib/src/adapters/profile/tax_form_adapter.dart index 41f85479..8c070da4 100644 --- a/apps/mobile/packages/domain/lib/src/adapters/profile/tax_form_adapter.dart +++ b/apps/mobile/packages/domain/lib/src/adapters/profile/tax_form_adapter.dart @@ -15,18 +15,36 @@ class TaxFormAdapter { DateTime? createdAt, DateTime? updatedAt, }) { - return TaxForm( - id: id, - type: _stringToType(type), - title: title, - subtitle: subtitle, - description: description, - status: _stringToStatus(status), - staffId: staffId, - formData: formData is Map ? Map.from(formData) : null, - createdAt: createdAt, - updatedAt: updatedAt, - ); + final TaxFormType formType = _stringToType(type); + final TaxFormStatus formStatus = _stringToStatus(status); + final Map formDetails = + formData is Map ? Map.from(formData as Map) : {}; + + if (formType == TaxFormType.i9) { + return I9TaxForm( + id: id, + title: title, + subtitle: subtitle, + description: description, + status: formStatus, + staffId: staffId, + formData: formDetails, + createdAt: createdAt, + updatedAt: updatedAt, + ); + } else { + return W4TaxForm( + id: id, + title: title, + subtitle: subtitle, + description: description, + status: formStatus, + staffId: staffId, + formData: formDetails, + createdAt: createdAt, + updatedAt: updatedAt, + ); + } } static TaxFormType _stringToType(String? value) { diff --git a/apps/mobile/packages/domain/lib/src/entities/profile/tax_form.dart b/apps/mobile/packages/domain/lib/src/entities/profile/tax_form.dart index 096380c5..bdb07d7b 100644 --- a/apps/mobile/packages/domain/lib/src/entities/profile/tax_form.dart +++ b/apps/mobile/packages/domain/lib/src/entities/profile/tax_form.dart @@ -4,27 +4,26 @@ enum TaxFormType { i9, w4 } enum TaxFormStatus { notStarted, inProgress, submitted, approved, rejected } -class TaxForm extends Equatable { +abstract class TaxForm extends Equatable { final String id; - final TaxFormType type; + TaxFormType get type; final String title; final String? subtitle; final String? description; final TaxFormStatus status; final String? staffId; - final Map? formData; + final Map formData; final DateTime? createdAt; final DateTime? updatedAt; const TaxForm({ required this.id, - required this.type, required this.title, this.subtitle, this.description, this.status = TaxFormStatus.notStarted, this.staffId, - this.formData, + this.formData = const {}, this.createdAt, this.updatedAt, }); @@ -43,3 +42,37 @@ class TaxForm extends Equatable { updatedAt, ]; } + +class I9TaxForm extends TaxForm { + const I9TaxForm({ + required super.id, + required super.title, + super.subtitle, + super.description, + super.status, + super.staffId, + super.formData, + super.createdAt, + super.updatedAt, + }); + + @override + TaxFormType get type => TaxFormType.i9; +} + +class W4TaxForm extends TaxForm { + const W4TaxForm({ + required super.id, + required super.title, + super.subtitle, + super.description, + super.status, + super.staffId, + super.formData, + super.createdAt, + super.updatedAt, + }); + + @override + TaxFormType get type => TaxFormType.w4; +} diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/data/mappers/tax_form_mapper.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/data/mappers/tax_form_mapper.dart new file mode 100644 index 00000000..5949d032 --- /dev/null +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/data/mappers/tax_form_mapper.dart @@ -0,0 +1,67 @@ +import 'package:krow_data_connect/krow_data_connect.dart' as dc; +import 'package:krow_domain/krow_domain.dart'; + +class TaxFormMapper { + static TaxForm fromDataConnect(dc.GetTaxFormsByStaffIdTaxForms form) { + // Construct the legacy map for the entity + final Map formData = { + 'firstName': form.firstName, + 'lastName': form.lastName, + 'middleInitial': form.mInitial, + 'otherLastNames': form.oLastName, + 'dob': form.dob?.toDateTime().toIso8601String(), + '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, + + // I-9 Fields + 'citizenshipStatus': form.citizen?.stringValue, + 'uscisNumber': form.uscis, + 'passportNumber': form.passportNumber, + 'countryIssuance': form.countryIssue, + 'preparerUsed': form.prepartorOrTranslator, + + // W-4 Fields + 'filingStatus': form.marital?.stringValue, + 'multipleJobs': form.multipleJob, + 'qualifyingChildren': form.childrens, + 'otherDependents': form.otherDeps, + 'otherIncome': form.otherInconme?.toString(), + 'deductions': form.deductions?.toString(), + 'extraWithholding': form.extraWithholding?.toString(), + + 'signature': form.signature, + }; + + String title = ''; + String subtitle = ''; + String description = ''; + + if (form.formType == dc.TaxFormType.I9) { + title = 'Form I-9'; + subtitle = 'Employment Eligibility Verification'; + description = 'Required for all new hires to verify identity.'; + } else { + title = 'Form W-4'; + subtitle = 'Employee\'s Withholding Certificate'; + description = 'Determines federal income tax withholding.'; + } + + return TaxFormAdapter.fromPrimitives( + id: form.id, + type: form.formType.stringValue, + title: title, + subtitle: subtitle, + description: description, + status: form.status.stringValue, + staffId: form.staffId, + formData: formData, + updatedAt: form.updatedAt?.toDateTime(), + ); + } +} diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/data/repositories/tax_forms_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/data/repositories/tax_forms_repository_impl.dart index abc1cbc3..e35d6244 100644 --- a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/data/repositories/tax_forms_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/data/repositories/tax_forms_repository_impl.dart @@ -6,6 +6,7 @@ import 'package:krow_data_connect/krow_data_connect.dart' as dc; import 'package:krow_domain/krow_domain.dart'; import '../../domain/repositories/tax_forms_repository.dart'; +import '../mappers/tax_form_mapper.dart'; class TaxFormsRepositoryImpl implements TaxFormsRepository { TaxFormsRepositoryImpl({ @@ -37,7 +38,7 @@ class TaxFormsRepositoryImpl implements TaxFormsRepository { result = await dataConnect.getTaxFormsByStaffId(staffId: staffId).execute(); - final List forms = result.data.taxForms.map((dc.GetTaxFormsByStaffIdTaxForms e) => _mapToEntity(e)).toList(); + final List forms = result.data.taxForms.map(TaxFormMapper.fromDataConnect).toList(); // Check if required forms exist, create if not. final Set typesPresent = forms.map((TaxForm f) => f.type).toSet(); @@ -56,7 +57,7 @@ class TaxFormsRepositoryImpl implements TaxFormsRepository { final QueryResult result2 = await dataConnect.getTaxFormsByStaffId(staffId: staffId).execute(); - return result2.data.taxForms.map((dc.GetTaxFormsByStaffIdTaxForms e) => _mapToEntity(e)).toList(); + return result2.data.taxForms.map(TaxFormMapper.fromDataConnect).toList(); } return forms; @@ -78,155 +79,111 @@ class TaxFormsRepositoryImpl implements TaxFormsRepository { } @override - Future submitForm(TaxFormType type, Map data) async { - final String staffId = _getStaffId(); - final QueryResult - 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'), - ); - + Future updateI9Form(I9TaxForm form) async { + final Map data = form.formData; final builder = dataConnect.updateTaxForm(id: form.id); + _mapCommonFields(builder, data); + _mapI9Fields(builder, data); + await builder.execute(); + } - // 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 - } - + @override + Future submitI9Form(I9TaxForm form) async { + final Map data = form.formData; + final builder = dataConnect.updateTaxForm(id: form.id); + _mapCommonFields(builder, data); + _mapI9Fields(builder, data); await builder.status(dc.TaxFormStatus.SUBMITTED).execute(); } @override - Future updateFormStatus(TaxFormType type, TaxFormStatus status) async { - final String staffId = _getStaffId(); - final QueryResult - 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(); + Future updateW4Form(W4TaxForm form) async { + final Map data = form.formData; + final builder = dataConnect.updateTaxForm(id: form.id); + _mapCommonFields(builder, data); + _mapW4Fields(builder, data); + await builder.execute(); } - TaxForm _mapToEntity(dc.GetTaxFormsByStaffIdTaxForms form) { - // Construct the legacy map for the entity - final Map formData = { - 'firstName': form.firstName, - 'lastName': form.lastName, - 'middleInitial': form.mInitial, - 'otherLastNames': form.oLastName, - 'dob': form.dob.toString(), - '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, - - // I-9 Fields - 'citizenshipStatus': form.citizen, - 'uscisNumber': form.uscis, - 'passportNumber': form.passportNumber, - 'countryIssuance': form.countryIssue, - 'preparerUsed': form.prepartorOrTranslator, - - // W-4 Fields - 'filingStatus': form.marital, - 'multipleJobs': form.multipleJob, - 'qualifyingChildren': form.childrens, - 'otherDependents': form.otherDeps, - 'otherIncome': form.otherInconme.toString(), // Note backend typo - 'deductions': form.deductions.toString(), - 'extraWithholding': form.extraWithholding.toString(), - - 'signature': form.signature, - }; + @override + Future submitW4Form(W4TaxForm form) async { + final Map data = form.formData; + final builder = dataConnect.updateTaxForm(id: form.id); + _mapCommonFields(builder, data); + _mapW4Fields(builder, data); + await builder.status(dc.TaxFormStatus.SUBMITTED).execute(); + } - String title = ''; - String subtitle = ''; - String description = ''; - - if (form.formType == dc.TaxFormType.I9) { - title = 'Form I-9'; - subtitle = 'Employment Eligibility Verification'; - description = 'Required for all new hires to verify identity.'; - } else { - title = 'Form W-4'; - subtitle = 'Employee\'s Withholding Certificate'; - description = 'Determines federal income tax withholding.'; + void _mapCommonFields(dc.UpdateTaxFormVariablesBuilder builder, Map data) { + 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']?.toString().isNotEmpty == true) { + builder.socialSN(int.tryParse(data['ssn'].toString().replaceAll(RegExp(r'\D'), '')) ?? 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?); + } - return TaxFormAdapter.fromPrimitives( - id: form.id, - type: form.formType.stringValue, - title: title, - subtitle: subtitle, - description: description, - status: form.status.stringValue, - staffId: form.staffId, - formData: formData, - updatedAt: form.updatedAt?.toDateTime(), - ); + void _mapI9Fields(dc.UpdateTaxFormVariablesBuilder builder, Map data) { + if (data.containsKey('citizenshipStatus')) { + final String status = data['citizenshipStatus'] as String; + // Map string to enum if possible, or handle otherwise. + // Generated enum: CITIZEN, NONCITIZEN_NATIONAL, PERMANENT_RESIDENT, ALIEN_AUTHORIZED + try { + builder.citizen(dc.CitizenshipStatus.values.byName(status.toUpperCase())); + } catch (_) {} + } + if (data.containsKey('uscisNumber')) builder.uscis(data['uscisNumber'] as String?); + if (data.containsKey('passportNumber')) builder.passportNumber(data['passportNumber'] as String?); + if (data.containsKey('countryIssuance')) builder.countryIssue(data['countryIssuance'] as String?); + if (data.containsKey('preparerUsed')) builder.prepartorOrTranslator(data['preparerUsed'] as bool?); + if (data.containsKey('signature')) builder.signature(data['signature'] as String?); + // Note: admissionNumber not in builder based on file read + } + + void _mapW4Fields(dc.UpdateTaxFormVariablesBuilder builder, Map data) { + if (data.containsKey('cityStateZip')) { + final String csz = data['cityStateZip'] as String; + // Extremely basic split: City, State Zip + final List parts = csz.split(','); + if (parts.length >= 2) { + builder.city(parts[0].trim()); + final String stateZip = parts[1].trim(); + final List szParts = stateZip.split(' '); + if (szParts.isNotEmpty) builder.state(szParts[0]); + if (szParts.length > 1) builder.zipCode(szParts.last); + } + } + if (data.containsKey('filingStatus')) { + // MARITIAL_STATUS_SINGLE, MARITIAL_STATUS_MARRIED, MARITIAL_STATUS_HEAD + try { + final String status = data['filingStatus'] as String; + // Simple mapping assumptions: + if (status.contains('single')) builder.marital(dc.MaritalStatus.SINGLE); + else if (status.contains('married')) builder.marital(dc.MaritalStatus.MARRIED); + else if (status.contains('head')) builder.marital(dc.MaritalStatus.HEAD); + } catch (_) {} + } + if (data.containsKey('multipleJobs')) builder.multipleJob(data['multipleJobs'] as bool?); + if (data.containsKey('qualifyingChildren')) builder.childrens(data['qualifyingChildren'] as int?); + if (data.containsKey('otherDependents')) builder.otherDeps(data['otherDependents'] as int?); + if (data.containsKey('otherIncome')) { + builder.otherInconme(double.tryParse(data['otherIncome'].toString())); + } + if (data.containsKey('deductions')) { + builder.deductions(double.tryParse(data['deductions'].toString())); + } + if (data.containsKey('extraWithholding')) { + builder.extraWithholding(double.tryParse(data['extraWithholding'].toString())); + } + if (data.containsKey('signature')) builder.signature(data['signature'] as String?); } } diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/repositories/tax_forms_repository.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/repositories/tax_forms_repository.dart index de7095f5..26f5b061 100644 --- a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/repositories/tax_forms_repository.dart +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/repositories/tax_forms_repository.dart @@ -2,6 +2,8 @@ import 'package:krow_domain/krow_domain.dart'; abstract class TaxFormsRepository { Future> getTaxForms(); - Future submitForm(TaxFormType type, Map data); - Future updateFormStatus(TaxFormType type, TaxFormStatus status); + Future updateI9Form(I9TaxForm form); + Future submitI9Form(I9TaxForm form); + Future updateW4Form(W4TaxForm form); + Future submitW4Form(W4TaxForm form); } diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/save_i9_form_usecase.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/save_i9_form_usecase.dart new file mode 100644 index 00000000..09c52e27 --- /dev/null +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/save_i9_form_usecase.dart @@ -0,0 +1,12 @@ +import 'package:krow_domain/krow_domain.dart'; +import '../repositories/tax_forms_repository.dart'; + +class SaveI9FormUseCase { + final TaxFormsRepository _repository; + + SaveI9FormUseCase(this._repository); + + Future call(I9TaxForm form) async { + return _repository.updateI9Form(form); + } +} diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/save_w4_form_usecase.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/save_w4_form_usecase.dart new file mode 100644 index 00000000..995e090a --- /dev/null +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/save_w4_form_usecase.dart @@ -0,0 +1,12 @@ +import 'package:krow_domain/krow_domain.dart'; +import '../repositories/tax_forms_repository.dart'; + +class SaveW4FormUseCase { + final TaxFormsRepository _repository; + + SaveW4FormUseCase(this._repository); + + Future call(W4TaxForm form) async { + return _repository.updateW4Form(form); + } +} diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/submit_i9_form_usecase.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/submit_i9_form_usecase.dart new file mode 100644 index 00000000..b57370c7 --- /dev/null +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/submit_i9_form_usecase.dart @@ -0,0 +1,12 @@ +import 'package:krow_domain/krow_domain.dart'; +import '../repositories/tax_forms_repository.dart'; + +class SubmitI9FormUseCase { + final TaxFormsRepository _repository; + + SubmitI9FormUseCase(this._repository); + + Future call(I9TaxForm form) async { + return _repository.submitI9Form(form); + } +} diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/submit_tax_form_usecase.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/submit_tax_form_usecase.dart deleted file mode 100644 index c6a7f143..00000000 --- a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/submit_tax_form_usecase.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:krow_domain/krow_domain.dart'; -import '../repositories/tax_forms_repository.dart'; - -class SubmitTaxFormUseCase { - final TaxFormsRepository _repository; - - SubmitTaxFormUseCase(this._repository); - - Future call(TaxFormType type, Map data) async { - return _repository.submitForm(type, data); - } -} diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/submit_w4_form_usecase.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/submit_w4_form_usecase.dart new file mode 100644 index 00000000..d4170855 --- /dev/null +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/domain/usecases/submit_w4_form_usecase.dart @@ -0,0 +1,12 @@ +import 'package:krow_domain/krow_domain.dart'; +import '../repositories/tax_forms_repository.dart'; + +class SubmitW4FormUseCase { + final TaxFormsRepository _repository; + + SubmitW4FormUseCase(this._repository); + + Future call(W4TaxForm form) async { + return _repository.submitW4Form(form); + } +} diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/presentation/blocs/i9/form_i9_cubit.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/presentation/blocs/i9/form_i9_cubit.dart index 8eb19060..4c7a6430 100644 --- a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/presentation/blocs/i9/form_i9_cubit.dart +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/presentation/blocs/i9/form_i9_cubit.dart @@ -1,13 +1,15 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:krow_domain/krow_domain.dart'; +import 'package:uuid/uuid.dart'; -import '../../../domain/usecases/submit_tax_form_usecase.dart'; +import '../../../domain/usecases/submit_i9_form_usecase.dart'; import 'form_i9_state.dart'; class FormI9Cubit extends Cubit { - final SubmitTaxFormUseCase _submitTaxFormUseCase; + final SubmitI9FormUseCase _submitI9FormUseCase; + String _formId = ''; - FormI9Cubit(this._submitTaxFormUseCase) : super(const FormI9State()); + FormI9Cubit(this._submitI9FormUseCase) : super(const FormI9State()); void initialize(TaxForm? form) { if (form == null || form.formData.isEmpty) { @@ -16,6 +18,7 @@ class FormI9Cubit extends Cubit { } final Map data = form.formData; + _formId = form.id; emit(FormI9State( firstName: data['firstName'] as String? ?? '', lastName: data['lastName'] as String? ?? '', @@ -83,18 +86,36 @@ class FormI9Cubit extends Cubit { Future submit() async { emit(state.copyWith(status: FormI9Status.submitting)); try { - await _submitTaxFormUseCase( - TaxFormType.i9, - { - 'firstName': state.firstName, - 'lastName': state.lastName, - 'middleInitial': state.middleInitial, - 'citizenshipStatus': state.citizenshipStatus, - 'ssn': state.ssn, - 'signature': state.signature, - // ... add other fields as needed for backend - }, + final Map formData = { + 'firstName': state.firstName, + 'lastName': state.lastName, + 'middleInitial': state.middleInitial, + 'otherLastNames': state.otherLastNames, + 'dob': state.dob, + 'ssn': state.ssn, + 'email': state.email, + 'phone': state.phone, + 'address': state.address, + 'aptNumber': state.aptNumber, + 'city': state.city, + 'state': state.state, + 'zipCode': state.zipCode, + 'citizenshipStatus': state.citizenshipStatus, + 'uscisNumber': state.uscisNumber, + 'admissionNumber': state.admissionNumber, + 'passportNumber': state.passportNumber, + 'countryIssuance': state.countryIssuance, + 'preparerUsed': state.preparerUsed, + 'signature': state.signature, + }; + + final I9TaxForm form = I9TaxForm( + id: _formId.isNotEmpty ? _formId : const Uuid().v4(), + title: 'Form I-9', + formData: formData, ); + + await _submitI9FormUseCase(form); emit(state.copyWith(status: FormI9Status.success)); } catch (e) { emit(state.copyWith( diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/presentation/blocs/w4/form_w4_cubit.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/presentation/blocs/w4/form_w4_cubit.dart index 3db1cf51..440ef51c 100644 --- a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/presentation/blocs/w4/form_w4_cubit.dart +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/presentation/blocs/w4/form_w4_cubit.dart @@ -1,13 +1,15 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:krow_domain/krow_domain.dart'; +import 'package:uuid/uuid.dart'; -import '../../../domain/usecases/submit_tax_form_usecase.dart'; +import '../../../domain/usecases/submit_w4_form_usecase.dart'; import 'form_w4_state.dart'; class FormW4Cubit extends Cubit { - final SubmitTaxFormUseCase _submitTaxFormUseCase; + final SubmitW4FormUseCase _submitW4FormUseCase; + String _formId = ''; - FormW4Cubit(this._submitTaxFormUseCase) : super(const FormW4State()); + FormW4Cubit(this._submitW4FormUseCase) : super(const FormW4State()); void initialize(TaxForm? form) { if (form == null || form.formData.isEmpty) { @@ -16,6 +18,7 @@ class FormW4Cubit extends Cubit { } final Map data = form.formData; + _formId = form.id; // Combine address parts if needed, or take existing final String city = data['city'] as String? ?? ''; @@ -76,18 +79,29 @@ class FormW4Cubit extends Cubit { Future submit() async { emit(state.copyWith(status: FormW4Status.submitting)); try { - await _submitTaxFormUseCase( - TaxFormType.w4, - { - 'firstName': state.firstName, - 'lastName': state.lastName, - 'ssn': state.ssn, - 'filingStatus': state.filingStatus, - 'multipleJobs': state.multipleJobs, - 'signature': state.signature, - // ... add other fields as needed - }, + final Map formData = { + 'firstName': state.firstName, + 'lastName': state.lastName, + 'ssn': state.ssn, + 'address': state.address, + 'cityStateZip': state.cityStateZip, // Note: Repository should split this if needed. + 'filingStatus': state.filingStatus, + 'multipleJobs': state.multipleJobs, + 'qualifyingChildren': state.qualifyingChildren, + 'otherDependents': state.otherDependents, + 'otherIncome': state.otherIncome, + 'deductions': state.deductions, + 'extraWithholding': state.extraWithholding, + 'signature': state.signature, + }; + + final W4TaxForm form = W4TaxForm( + id: _formId.isNotEmpty ? _formId : const Uuid().v4(), + title: 'Form W-4', + formData: formData, ); + + await _submitW4FormUseCase(form); emit(state.copyWith(status: FormW4Status.success)); } catch (e) { emit(state.copyWith( diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/presentation/pages/tax_forms_page.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/presentation/pages/tax_forms_page.dart index 7bc41bc1..bc241a7b 100644 --- a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/presentation/pages/tax_forms_page.dart +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/presentation/pages/tax_forms_page.dart @@ -140,13 +140,13 @@ class TaxFormsPage extends StatelessWidget { Widget _buildFormCard(TaxForm form) { // Helper to get icon based on type (could be in entity or a mapper) - final String icon = form.type == TaxFormType.i9 ? '🛂' : '📋'; + final String icon = form is I9TaxForm ? '🛂' : '📋'; return GestureDetector( onTap: () { - if (form.type == TaxFormType.i9) { + if (form is I9TaxForm) { Modular.to.pushNamed('i9', arguments: form); - } else if (form.type == TaxFormType.w4) { + } else if (form is W4TaxForm) { Modular.to.pushNamed('w4', arguments: form); } }, diff --git a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/staff_tax_forms_module.dart b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/staff_tax_forms_module.dart index b7f3bbe2..7b390a17 100644 --- a/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/staff_tax_forms_module.dart +++ b/apps/mobile/packages/features/staff/profile_sections/compliance/tax_forms/lib/src/staff_tax_forms_module.dart @@ -5,7 +5,8 @@ import 'package:krow_domain/krow_domain.dart'; import 'data/repositories/tax_forms_repository_impl.dart'; import 'domain/repositories/tax_forms_repository.dart'; import 'domain/usecases/get_tax_forms_usecase.dart'; -import 'domain/usecases/submit_tax_form_usecase.dart'; +import 'domain/usecases/submit_i9_form_usecase.dart'; +import 'domain/usecases/submit_w4_form_usecase.dart'; import 'presentation/blocs/i9/form_i9_cubit.dart'; import 'presentation/blocs/tax_forms/tax_forms_cubit.dart'; import 'presentation/blocs/w4/form_w4_cubit.dart'; @@ -25,7 +26,8 @@ class StaffTaxFormsModule extends Module { // Use Cases i.addLazySingleton(GetTaxFormsUseCase.new); - i.addLazySingleton(SubmitTaxFormUseCase.new); + i.addLazySingleton(SubmitI9FormUseCase.new); + i.addLazySingleton(SubmitW4FormUseCase.new); // Blocs i.addLazySingleton(TaxFormsCubit.new);