feat: update profile setup and bank account management; enhance API integration and data handling

This commit is contained in:
Achintha Isuru
2026-03-17 14:32:26 -04:00
parent b6a655a261
commit de388c9a77
21 changed files with 142 additions and 85 deletions

View File

@@ -18,7 +18,8 @@ class EmergencyContactRepositoryImpl
Future<List<EmergencyContact>> getContacts() async {
final ApiResponse response =
await _api.get(StaffEndpoints.emergencyContacts);
final List<dynamic> items = response.data['contacts'] as List<dynamic>? ?? <dynamic>[];
final List<dynamic> items =
response.data['items'] as List<dynamic>? ?? <dynamic>[];
return items
.map((dynamic json) =>
EmergencyContact.fromJson(json as Map<String, dynamic>))
@@ -27,12 +28,27 @@ class EmergencyContactRepositoryImpl
@override
Future<void> saveContacts(List<EmergencyContact> contacts) async {
await _api.post(
StaffEndpoints.emergencyContacts,
data: <String, dynamic>{
'contacts':
contacts.map((EmergencyContact c) => c.toJson()).toList(),
},
);
for (final EmergencyContact contact in contacts) {
final Map<String, dynamic> body = <String, dynamic>{
'fullName': contact.fullName,
'phone': contact.phone,
'relationshipType': contact.relationshipType,
'isPrimary': contact.isPrimary,
};
if (contact.contactId.isNotEmpty) {
// Existing contact — update via PUT.
await _api.put(
StaffEndpoints.emergencyContactUpdate(contact.contactId),
data: body,
);
} else {
// New contact — create via POST.
await _api.post(
StaffEndpoints.emergencyContacts,
data: body,
);
}
}
}
}

View File

@@ -1,3 +1,4 @@
import 'package:dio/dio.dart';
import 'package:krow_core/core.dart';
import 'package:krow_domain/krow_domain.dart';
@@ -10,20 +11,12 @@ import 'package:staff_profile_info/src/domain/repositories/personal_info_reposit
class PersonalInfoRepositoryImpl implements PersonalInfoRepositoryInterface {
/// Creates a [PersonalInfoRepositoryImpl].
///
/// Requires the V2 [BaseApiService] for HTTP communication,
/// [FileUploadService] for uploading files to cloud storage, and
/// [SignedUrlService] for generating signed download URLs.
/// Requires the V2 [BaseApiService] for HTTP communication.
PersonalInfoRepositoryImpl({
required BaseApiService apiService,
required FileUploadService uploadService,
required SignedUrlService signedUrlService,
}) : _api = apiService,
_uploadService = uploadService,
_signedUrlService = signedUrlService;
}) : _api = apiService;
final BaseApiService _api;
final FileUploadService _uploadService;
final SignedUrlService _signedUrlService;
@override
Future<StaffPersonalInfo> getStaffProfile() async {
@@ -39,39 +32,34 @@ class PersonalInfoRepositoryImpl implements PersonalInfoRepositoryInterface {
required String staffId,
required Map<String, dynamic> data,
}) async {
final ApiResponse response = await _api.put(
// The PUT response returns { staffId, fullName, email, phone, metadata }
// which does not match the StaffPersonalInfo shape. Perform the update
// and then re-fetch the full profile to return the correct entity.
await _api.put(
StaffEndpoints.personalInfo,
data: data,
);
final Map<String, dynamic> json =
response.data as Map<String, dynamic>;
return StaffPersonalInfo.fromJson(json);
return getStaffProfile();
}
@override
Future<String> uploadProfilePhoto(String filePath) async {
// 1. Upload the file to cloud storage.
final FileUploadResponse uploadRes = await _uploadService.uploadFile(
filePath: filePath,
fileName:
'staff_profile_photo_${DateTime.now().millisecondsSinceEpoch}.jpg',
visibility: FileVisibility.public,
);
// The backend expects a multipart file upload at /staff/profile/photo.
// It uploads to GCS, updates staff metadata, and returns a signed URL.
final String fileName =
'staff_profile_photo_${DateTime.now().millisecondsSinceEpoch}.jpg';
final FormData formData = FormData.fromMap(<String, dynamic>{
'file': await MultipartFile.fromFile(filePath, filename: fileName),
});
// 2. Generate a signed URL for the uploaded file.
final SignedUrlResponse signedUrlRes =
await _signedUrlService.createSignedUrl(fileUri: uploadRes.fileUri);
final String photoUrl = signedUrlRes.signedUrl;
// 3. Submit the photo URL to the V2 API.
await _api.post(
final ApiResponse response = await _api.post(
StaffEndpoints.profilePhoto,
data: <String, dynamic>{
'fileUri': uploadRes.fileUri,
'photoUrl': photoUrl,
},
data: formData,
);
final Map<String, dynamic> json =
response.data as Map<String, dynamic>;
return photoUrl;
// Backend returns { staffId, fileUri, signedUrl, expiresAt }.
return json['signedUrl'] as String? ?? '';
}
}

View File

@@ -27,8 +27,6 @@ class StaffProfileInfoModule extends Module {
i.addLazySingleton<PersonalInfoRepositoryInterface>(
() => PersonalInfoRepositoryImpl(
apiService: i.get<BaseApiService>(),
uploadService: i.get<FileUploadService>(),
signedUrlService: i.get<SignedUrlService>(),
),
);

View File

@@ -14,6 +14,7 @@ dependencies:
flutter_bloc: ^8.1.0
bloc: ^8.1.0
flutter_modular: ^6.3.0
dio: ^5.9.1
equatable: ^2.0.5
# Architecture Packages