feat: Update employee creation process and API endpoints for improved functionality
This commit is contained in:
parent
943c7c7b50
commit
69e64ec789
@ -110,7 +110,8 @@ class AddEmployeeController extends MyController {
|
||||
logSafe("Failed to fetch roles: null result", level: LogLevel.error);
|
||||
}
|
||||
} catch (e, st) {
|
||||
logSafe("Error fetching roles", level: LogLevel.error, error: e, stackTrace: st);
|
||||
logSafe("Error fetching roles",
|
||||
level: LogLevel.error, error: e, stackTrace: st);
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,7 +121,7 @@ class AddEmployeeController extends MyController {
|
||||
update();
|
||||
}
|
||||
|
||||
Future<bool> createEmployees() async {
|
||||
Future<Map<String, dynamic>?> createEmployees() async {
|
||||
logSafe("Starting employee creation...");
|
||||
if (selectedGender == null || selectedRoleId == null) {
|
||||
logSafe("Missing gender or role.", level: LogLevel.warning);
|
||||
@ -129,14 +130,13 @@ class AddEmployeeController extends MyController {
|
||||
message: "Please select both Gender and Role.",
|
||||
type: SnackbarType.warning,
|
||||
);
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
final firstName = basicValidator.getController("first_name")?.text.trim();
|
||||
final lastName = basicValidator.getController("last_name")?.text.trim();
|
||||
final phoneNumber = basicValidator.getController("phone_number")?.text.trim();
|
||||
|
||||
logSafe("Creating employee", level: LogLevel.info);
|
||||
final phoneNumber =
|
||||
basicValidator.getController("phone_number")?.text.trim();
|
||||
|
||||
try {
|
||||
final response = await ApiService.createEmployee(
|
||||
@ -146,20 +146,24 @@ class AddEmployeeController extends MyController {
|
||||
gender: selectedGender!.name,
|
||||
jobRoleId: selectedRoleId!,
|
||||
);
|
||||
logSafe("Response: $response");
|
||||
if (response == true) {
|
||||
|
||||
logSafe("Response: $response");
|
||||
|
||||
if (response != null && response['success'] == true) {
|
||||
logSafe("Employee created successfully.");
|
||||
showAppSnackbar(
|
||||
title: "Success",
|
||||
message: "Employee created successfully!",
|
||||
type: SnackbarType.success,
|
||||
);
|
||||
return true;
|
||||
return response;
|
||||
} else {
|
||||
logSafe("Failed to create employee (response false)", level: LogLevel.error);
|
||||
logSafe("Failed to create employee (response false)",
|
||||
level: LogLevel.error);
|
||||
}
|
||||
} catch (e, st) {
|
||||
logSafe("Error creating employee", level: LogLevel.error, error: e, stackTrace: st);
|
||||
logSafe("Error creating employee",
|
||||
level: LogLevel.error, error: e, stackTrace: st);
|
||||
}
|
||||
|
||||
showAppSnackbar(
|
||||
@ -167,7 +171,7 @@ logSafe("Response: $response");
|
||||
message: "Failed to create employee.",
|
||||
type: SnackbarType.error,
|
||||
);
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<bool> _checkAndRequestContactsPermission() async {
|
||||
@ -181,7 +185,8 @@ logSafe("Response: $response");
|
||||
|
||||
showAppSnackbar(
|
||||
title: "Permission Required",
|
||||
message: "Please allow Contacts permission from settings to pick a contact.",
|
||||
message:
|
||||
"Please allow Contacts permission from settings to pick a contact.",
|
||||
type: SnackbarType.warning,
|
||||
);
|
||||
return false;
|
||||
@ -195,7 +200,8 @@ logSafe("Response: $response");
|
||||
final picked = await FlutterContacts.openExternalPick();
|
||||
if (picked == null) return;
|
||||
|
||||
final contact = await FlutterContacts.getContact(picked.id, withProperties: true);
|
||||
final contact =
|
||||
await FlutterContacts.getContact(picked.id, withProperties: true);
|
||||
if (contact == null) {
|
||||
showAppSnackbar(
|
||||
title: "Error",
|
||||
@ -216,7 +222,8 @@ logSafe("Response: $response");
|
||||
|
||||
final indiaPhones = contact.phones.where((p) {
|
||||
final normalized = p.number.replaceAll(RegExp(r'[^0-9+]'), '');
|
||||
return normalized.startsWith('+91') || RegExp(r'^\d{10}$').hasMatch(normalized);
|
||||
return normalized.startsWith('+91') ||
|
||||
RegExp(r'^\d{10}$').hasMatch(normalized);
|
||||
}).toList();
|
||||
|
||||
if (indiaPhones.isEmpty) {
|
||||
@ -256,10 +263,12 @@ logSafe("Response: $response");
|
||||
? normalizedPhone.substring(normalizedPhone.length - 10)
|
||||
: normalizedPhone;
|
||||
|
||||
basicValidator.getController('phone_number')?.text = phoneWithoutCountryCode;
|
||||
basicValidator.getController('phone_number')?.text =
|
||||
phoneWithoutCountryCode;
|
||||
update();
|
||||
} catch (e, st) {
|
||||
logSafe("Error fetching contacts", level: LogLevel.error, error: e, stackTrace: st);
|
||||
logSafe("Error fetching contacts",
|
||||
level: LogLevel.error, error: e, stackTrace: st);
|
||||
showAppSnackbar(
|
||||
title: "Error",
|
||||
message: "Failed to fetch contacts.",
|
||||
|
@ -18,7 +18,7 @@ class ApiEndpoints {
|
||||
static const String getAllEmployeesByProject = "/employee/list";
|
||||
static const String getAllEmployees = "/employee/list";
|
||||
static const String getRoles = "/roles/jobrole";
|
||||
static const String createEmployee = "/employee/manage";
|
||||
static const String createEmployee = "/employee/manage-mobile";
|
||||
static const String getEmployeeInfo = "/employee/profile/get";
|
||||
static const String assignEmployee = "/employee/profile/get";
|
||||
static const String getAssignedProjects = "/project/assigned-projects";
|
||||
|
@ -479,37 +479,37 @@ class ApiService {
|
||||
|
||||
/// Get list of assigned projects for a specific employee
|
||||
/// Get list of assigned projects for a specific employee
|
||||
static Future<List<dynamic>?> getAssignedProjects(String employeeId) async {
|
||||
if (employeeId.isEmpty) {
|
||||
throw ArgumentError("employeeId must not be empty");
|
||||
}
|
||||
|
||||
final endpoint = "${ApiEndpoints.getAssignedProjects}/$employeeId";
|
||||
|
||||
try {
|
||||
final response = await _getRequest(endpoint);
|
||||
|
||||
if (response == null) {
|
||||
logSafe("Failed to fetch assigned projects: null response",
|
||||
level: LogLevel.error);
|
||||
return null;
|
||||
static Future<List<dynamic>?> getAssignedProjects(String employeeId) async {
|
||||
if (employeeId.isEmpty) {
|
||||
throw ArgumentError("employeeId must not be empty");
|
||||
}
|
||||
|
||||
final parsed = _parseResponse(response, label: "Assigned Projects");
|
||||
if (parsed is List) {
|
||||
return parsed;
|
||||
} else {
|
||||
logSafe("Unexpected response format for assigned projects.",
|
||||
final endpoint = "${ApiEndpoints.getAssignedProjects}/$employeeId";
|
||||
|
||||
try {
|
||||
final response = await _getRequest(endpoint);
|
||||
|
||||
if (response == null) {
|
||||
logSafe("Failed to fetch assigned projects: null response",
|
||||
level: LogLevel.error);
|
||||
return null;
|
||||
}
|
||||
|
||||
final parsed = _parseResponse(response, label: "Assigned Projects");
|
||||
if (parsed is List) {
|
||||
return parsed;
|
||||
} else {
|
||||
logSafe("Unexpected response format for assigned projects.",
|
||||
level: LogLevel.error);
|
||||
return null;
|
||||
}
|
||||
} catch (e, stack) {
|
||||
logSafe("Exception during getAssignedProjects API: $e",
|
||||
level: LogLevel.error);
|
||||
logSafe("StackTrace: $stack", level: LogLevel.debug);
|
||||
return null;
|
||||
}
|
||||
} catch (e, stack) {
|
||||
logSafe("Exception during getAssignedProjects API: $e",
|
||||
level: LogLevel.error);
|
||||
logSafe("StackTrace: $stack", level: LogLevel.debug);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Assign projects to a specific employee
|
||||
static Future<bool> assignProjects({
|
||||
@ -839,8 +839,7 @@ static Future<List<dynamic>?> getAssignedProjects(String employeeId) async {
|
||||
static Future<List<dynamic>?> getRoles() async =>
|
||||
_getRequest(ApiEndpoints.getRoles).then(
|
||||
(res) => res != null ? _parseResponse(res, label: 'Roles') : null);
|
||||
|
||||
static Future<bool> createEmployee({
|
||||
static Future<Map<String, dynamic>?> createEmployee({
|
||||
required String firstName,
|
||||
required String lastName,
|
||||
required String phoneNumber,
|
||||
@ -854,15 +853,20 @@ static Future<List<dynamic>?> getAssignedProjects(String employeeId) async {
|
||||
"gender": gender,
|
||||
"jobRoleId": jobRoleId,
|
||||
};
|
||||
|
||||
final response = await _postRequest(
|
||||
ApiEndpoints.createEmployee,
|
||||
body,
|
||||
customTimeout: extendedTimeout,
|
||||
);
|
||||
|
||||
if (response == null) return false;
|
||||
if (response == null) return null;
|
||||
|
||||
final json = jsonDecode(response.body);
|
||||
return response.statusCode == 200 && json['success'] == true;
|
||||
return {
|
||||
"success": response.statusCode == 200 && json['success'] == true,
|
||||
"data": json
|
||||
};
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>?> getEmployeeDetails(
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:marco/controller/dashboard/add_employee_controller.dart';
|
||||
import 'package:marco/controller/dashboard/employees_screen_controller.dart';
|
||||
@ -274,6 +275,12 @@ class _AddEmployeeBottomSheetState extends State<AddEmployeeBottomSheet>
|
||||
return null;
|
||||
},
|
||||
keyboardType: TextInputType.phone,
|
||||
inputFormatters: [
|
||||
// Allow only digits
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
// Limit to 10 digits
|
||||
LengthLimitingTextInputFormatter(10),
|
||||
],
|
||||
decoration: _inputDecoration("e.g., 9876543210")
|
||||
.copyWith(
|
||||
suffixIcon: IconButton(
|
||||
@ -355,9 +362,12 @@ class _AddEmployeeBottomSheetState extends State<AddEmployeeBottomSheet>
|
||||
onPressed: () async {
|
||||
if (_controller.basicValidator
|
||||
.validateForm()) {
|
||||
final success =
|
||||
final result =
|
||||
await _controller.createEmployees();
|
||||
if (success) {
|
||||
|
||||
if (result != null &&
|
||||
result['success'] == true) {
|
||||
final employeeData = result['data'];
|
||||
final employeeController =
|
||||
Get.find<EmployeesScreenController>();
|
||||
final projectId =
|
||||
@ -387,7 +397,7 @@ class _AddEmployeeBottomSheetState extends State<AddEmployeeBottomSheet>
|
||||
_controller.selectedRoleId = null;
|
||||
_controller.update();
|
||||
|
||||
Navigator.pop(context);
|
||||
Navigator.pop(context, employeeData);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -13,6 +13,7 @@ import 'package:marco/helpers/widgets/my_custom_skeleton.dart';
|
||||
import 'package:marco/view/employees/employee_detail_screen.dart';
|
||||
import 'package:marco/model/employee_model.dart';
|
||||
import 'package:marco/helpers/utils/launcher_utils.dart';
|
||||
import 'package:marco/view/employees/assign_employee_bottom_sheet.dart';
|
||||
|
||||
class EmployeesScreen extends StatefulWidget {
|
||||
const EmployeesScreen({super.key});
|
||||
@ -162,7 +163,8 @@ class _EmployeesScreenState extends State<EmployeesScreen> with UIMixin {
|
||||
),
|
||||
floatingActionButton: InkWell(
|
||||
onTap: () async {
|
||||
final result = await showModalBottomSheet<bool>(
|
||||
// Step 1: Open AddEmployeeBottomSheet
|
||||
final result = await showModalBottomSheet<Map<String, dynamic>>(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
shape: const RoundedRectangleBorder(
|
||||
@ -172,7 +174,29 @@ class _EmployeesScreenState extends State<EmployeesScreen> with UIMixin {
|
||||
builder: (context) => AddEmployeeBottomSheet(),
|
||||
);
|
||||
|
||||
if (result == true) {
|
||||
// Step 2: Check if employee creation was successful
|
||||
if (result != null && result['success'] == true) {
|
||||
print("Employee data from bottom sheet: $result");
|
||||
|
||||
final employeeData = result['data'];
|
||||
final employeeId = employeeData['id'] as String;
|
||||
final jobRoleId = employeeData['jobRoleId'] as String?;
|
||||
|
||||
// Step 3: Open AssignProjectBottomSheet for the new employee
|
||||
await showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
||||
),
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (context) => AssignProjectBottomSheet(
|
||||
employeeId: employeeId,
|
||||
jobRoleId: jobRoleId ?? '',
|
||||
),
|
||||
);
|
||||
|
||||
// Step 4: Refresh employee list after project assignment
|
||||
await _refreshEmployees();
|
||||
}
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user