issues fixes
This commit is contained in:
parent
1005ff962d
commit
5d7faf309a
@ -1012,6 +1012,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
return OfficeDetails(
|
return OfficeDetails(
|
||||||
isDesktop: isDesktop, // pass isDesktop as a named argument
|
isDesktop: isDesktop, // pass isDesktop as a named argument
|
||||||
isViewMode: isViewMode,
|
isViewMode: isViewMode,
|
||||||
|
userIdApi:userIdApi,
|
||||||
controllers: controllers,
|
controllers: controllers,
|
||||||
errorMessages: errorMessages,
|
errorMessages: errorMessages,
|
||||||
selectedLevel: selectedLevel,
|
selectedLevel: selectedLevel,
|
||||||
@ -1062,12 +1063,14 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
errorMessages: errorMessages,
|
errorMessages: errorMessages,
|
||||||
travelDetails: travelDetailsDataFromAPI, // 👈 Pass this down
|
travelDetails: travelDetailsDataFromAPI, // 👈 Pass this down
|
||||||
passportFileUrlFromApi: passportFileUrlFromApi,
|
passportFileUrlFromApi: passportFileUrlFromApi,
|
||||||
|
userIdApi:userIdApi,
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return PersonalDetails(
|
return PersonalDetails(
|
||||||
personalDetailsKey: personalDetailsKey,
|
personalDetailsKey: personalDetailsKey,
|
||||||
isDesktop: isDesktop, // pass isDesktop as a named argument
|
isDesktop: isDesktop, // pass isDesktop as a named argument
|
||||||
isViewMode: isViewMode,
|
isViewMode: isViewMode,
|
||||||
|
userIdApi:userIdApi,
|
||||||
controllers: controllers,
|
controllers: controllers,
|
||||||
errorMessages: errorMessages,
|
errorMessages: errorMessages,
|
||||||
selectedGender: selectedGender,
|
selectedGender: selectedGender,
|
||||||
|
|||||||
@ -15,6 +15,8 @@ class OfficeDetails extends StatefulWidget {
|
|||||||
final Map<String, String> errorMessages;
|
final Map<String, String> errorMessages;
|
||||||
final bool isDesktop;
|
final bool isDesktop;
|
||||||
final bool isViewMode;
|
final bool isViewMode;
|
||||||
|
final String? userIdApi;
|
||||||
|
|
||||||
|
|
||||||
final ValueChanged<String?>? onLevelChanged;
|
final ValueChanged<String?>? onLevelChanged;
|
||||||
final ValueChanged<String?>? onDepartmentChanged;
|
final ValueChanged<String?>? onDepartmentChanged;
|
||||||
@ -48,6 +50,7 @@ class OfficeDetails extends StatefulWidget {
|
|||||||
this.onThirdApproverChanged,
|
this.onThirdApproverChanged,
|
||||||
this.selectedSubstituteApprover,
|
this.selectedSubstituteApprover,
|
||||||
this.onFirstSubsApproverChanged,
|
this.onFirstSubsApproverChanged,
|
||||||
|
this.userIdApi,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -154,6 +157,28 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
fetchFindGroup();
|
fetchFindGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> apiCheckDuplicate(String label, String field, String value, String? userId) async {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (field == "employeeCode") {
|
||||||
|
field = "employee_code";
|
||||||
|
}
|
||||||
|
|
||||||
|
final response = await apiService.CheckDuplicate(label, field, value, userId);
|
||||||
|
if (response.isNotEmpty) {
|
||||||
|
_clearError(field);
|
||||||
|
widget.errorMessages[field] = response['message'] ?? "$label already exists";
|
||||||
|
print("Duplicate found: ${response['message']}");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
_clearError(field);
|
||||||
|
print("No duplicates found.");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print("Error in checkDuplicate: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _clearError(String field) {
|
void _clearError(String field) {
|
||||||
setState(() {
|
setState(() {
|
||||||
widget.errorMessages.remove(field);
|
widget.errorMessages.remove(field);
|
||||||
@ -412,6 +437,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("employeeCode");
|
_clearError("employeeCode");
|
||||||
|
apiCheckDuplicate("Employee Code", "employeeCode",value,widget.userIdApi);
|
||||||
},
|
},
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: "Employee Code",
|
labelText: "Employee Code",
|
||||||
|
|||||||
@ -157,6 +157,34 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> apiCheckDuplicate(String label, String field, String value, String? userId) async {
|
||||||
|
try {
|
||||||
|
// Basic validation: Check mobile number length
|
||||||
|
if (field == "mobile_no" && value.length != 10) {
|
||||||
|
_clearError(field);
|
||||||
|
widget.errorMessages[field] = "$label is invalid";
|
||||||
|
print("Validation failed: $label is too short.");
|
||||||
|
return; // Skip the API call if input is invalid
|
||||||
|
}
|
||||||
|
|
||||||
|
final response = await apiService.CheckDuplicate(label, field, value, userId);
|
||||||
|
if (response.isNotEmpty) {
|
||||||
|
_clearError(field);
|
||||||
|
widget.errorMessages[field] = response['message'] ?? "$label already exists";
|
||||||
|
print("Duplicate found: ${response['message']}");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
_clearError(field);
|
||||||
|
print("No duplicates found.");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print("Error in checkDuplicate: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void _clearError(String field) {
|
void _clearError(String field) {
|
||||||
setState(() {
|
setState(() {
|
||||||
widget.errorMessages.remove(field);
|
widget.errorMessages.remove(field);
|
||||||
@ -1004,6 +1032,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
controller: widget.controllers["email"],
|
controller: widget.controllers["email"],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("email");
|
_clearError("email");
|
||||||
|
apiCheckDuplicate("Email", "email",value,widget.userIdApi);
|
||||||
},
|
},
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
@ -1054,6 +1083,7 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("mobile_no");
|
_clearError("mobile_no");
|
||||||
|
apiCheckDuplicate("Mobile Number", "mobile_no",value,widget.userIdApi);
|
||||||
},
|
},
|
||||||
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
|
|||||||
@ -31,6 +31,8 @@ class TravellerDetails extends StatefulWidget {
|
|||||||
final bool isViewMode;
|
final bool isViewMode;
|
||||||
final Map<String, dynamic>? travelDetails;
|
final Map<String, dynamic>? travelDetails;
|
||||||
final String? passportFileUrlFromApi;
|
final String? passportFileUrlFromApi;
|
||||||
|
final String? userIdApi;
|
||||||
|
|
||||||
|
|
||||||
const TravellerDetails({
|
const TravellerDetails({
|
||||||
Key? key,
|
Key? key,
|
||||||
@ -40,6 +42,7 @@ class TravellerDetails extends StatefulWidget {
|
|||||||
required this.isViewMode,
|
required this.isViewMode,
|
||||||
this.travelDetails,
|
this.travelDetails,
|
||||||
this.passportFileUrlFromApi,
|
this.passportFileUrlFromApi,
|
||||||
|
this.userIdApi,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@override
|
@override
|
||||||
TravellerDetailsState createState() => TravellerDetailsState();
|
TravellerDetailsState createState() => TravellerDetailsState();
|
||||||
@ -146,6 +149,26 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> apiCheckDuplicate(String label, String field, String value, String? userId) async {
|
||||||
|
try {
|
||||||
|
if(field == "forex_card_num"){
|
||||||
|
field = "forex_pre_paid_card_number";
|
||||||
|
}
|
||||||
|
final response = await apiService.CheckDuplicate(label, field, value, userId);
|
||||||
|
if (response.isNotEmpty) {
|
||||||
|
_clearError(field);
|
||||||
|
widget.errorMessages[field] = response['message'] ?? "$label already exists";
|
||||||
|
print("Duplicate found: ${response['message']}");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
_clearError(field);
|
||||||
|
print("No duplicates found.");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print("Error in checkDuplicate: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _clearError(String field) {
|
void _clearError(String field) {
|
||||||
setState(() {
|
setState(() {
|
||||||
widget.errorMessages.remove(field);
|
widget.errorMessages.remove(field);
|
||||||
@ -2308,6 +2331,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("forex_card_num");
|
_clearError("forex_card_num");
|
||||||
|
apiCheckDuplicate("Forex Pre-Paid Card Number", "forex_card_num",value,widget.userIdApi);
|
||||||
},
|
},
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: "Card Number",
|
labelText: "Card Number",
|
||||||
@ -2439,14 +2463,24 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
SizedBox(width: 25),
|
SizedBox(width: 25),
|
||||||
buildFrequentFlierInformation(entry),
|
buildFrequentFlierInformation(entry),
|
||||||
SizedBox(width: 15),
|
SizedBox(width: 15),
|
||||||
IconButton(
|
SizedBox(
|
||||||
icon: Icon(Icons.cancel, color: Colors.red, size: 15),
|
height: 60,
|
||||||
|
child: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(top: 20, left: 8), // 👈 Add top padding here
|
||||||
|
child: IconButton(
|
||||||
|
icon: Icon(Icons.horizontal_rule, color: Colors.red, size: 15),
|
||||||
|
tooltip: 'Cancel the Details',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
removeFrequentFlierEntry(entry);
|
removeFrequentFlierEntry(entry);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: Column(
|
: Column(
|
||||||
@ -2457,7 +2491,8 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
buildFrequentFlierInformation(entry),
|
buildFrequentFlierInformation(entry),
|
||||||
SizedBox(width: 15),
|
SizedBox(width: 15),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.cancel, color: Colors.red, size: 15),
|
icon: Icon(Icons.horizontal_rule, color: Colors.red, size: 15),
|
||||||
|
tooltip: 'Cancel the Details',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
removeFrequentFlierEntry(entry);
|
removeFrequentFlierEntry(entry);
|
||||||
@ -2743,15 +2778,23 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
buildHotel(entry),
|
buildHotel(entry),
|
||||||
SizedBox(width: 25),
|
SizedBox(width: 25),
|
||||||
buildHotelMembershipNum(entry),
|
buildHotelMembershipNum(entry),
|
||||||
IconButton(
|
SizedBox(
|
||||||
icon: Icon(Icons.cancel, color: Colors.red, size: 15),
|
height: 60,
|
||||||
|
child: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(top: 20, left: 8), // 👈 Add top padding here
|
||||||
|
child: IconButton(
|
||||||
|
icon: Icon(Icons.horizontal_rule, color: Colors.red, size: 15),
|
||||||
|
tooltip: 'Cancel the Details',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
// removeHotelLoyaltyEntry(localId);
|
|
||||||
removeHotelLoyaltyEntry(entry);
|
removeHotelLoyaltyEntry(entry);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: Column(
|
: Column(
|
||||||
@ -2761,7 +2804,8 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
buildHotelMembershipNum(entry),
|
buildHotelMembershipNum(entry),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.cancel, color: Colors.red, size: 15),
|
icon: Icon(Icons.horizontal_rule, color: Colors.red, size: 15),
|
||||||
|
tooltip: 'Cancel the Details',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
// removeHotelLoyaltyEntry(localId);
|
// removeHotelLoyaltyEntry(localId);
|
||||||
@ -2987,14 +3031,23 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
buildVisaValidFrom(entry),
|
buildVisaValidFrom(entry),
|
||||||
SizedBox(width: 15),
|
SizedBox(width: 15),
|
||||||
buildVisaValidUpTo(entry),
|
buildVisaValidUpTo(entry),
|
||||||
IconButton(
|
SizedBox(
|
||||||
icon: Icon(Icons.cancel, color: Colors.red, size: 15),
|
height: 60,
|
||||||
|
child: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(top: 20, left: 8), // 👈 Add top padding here
|
||||||
|
child: IconButton(
|
||||||
|
icon: Icon(Icons.horizontal_rule, color: Colors.red, size: 15),
|
||||||
|
tooltip: 'Cancel the Details',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
removeVisaEntry(entry);
|
removeVisaEntry(entry);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: Column(
|
: Column(
|
||||||
@ -3008,7 +3061,8 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
buildVisaValidUpTo(entry),
|
buildVisaValidUpTo(entry),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.cancel, color: Colors.red, size: 15),
|
icon: Icon(Icons.horizontal_rule, color: Colors.red, size: 15),
|
||||||
|
tooltip: 'Cancel the Details',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
// visaRowIds.remove(id);
|
// visaRowIds.remove(id);
|
||||||
|
|||||||
@ -1234,4 +1234,52 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------- User Management - CheckDuplicate ---------------
|
||||||
|
Future<Map<String, dynamic>> CheckDuplicate(String label, String field, String value, String? userId) async {
|
||||||
|
String apiUrldata;
|
||||||
|
if (userId == null || userId.isEmpty) {
|
||||||
|
apiUrldata = '$apiUrl/api/checkDuplicate?$field=$value';
|
||||||
|
} else {
|
||||||
|
apiUrldata = '$apiUrl/api/checkDuplicate?$field=$value&user_id=$userId';
|
||||||
|
}
|
||||||
|
|
||||||
|
final token = await getToken();
|
||||||
|
|
||||||
|
if (token == null) {
|
||||||
|
throw Exception('Token not found. Please log in.');
|
||||||
|
}
|
||||||
|
|
||||||
|
final response = await http.get(
|
||||||
|
Uri.parse(apiUrldata),
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer $token',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
try {
|
||||||
|
final data = json.decode(response.body);
|
||||||
|
|
||||||
|
// Updated to match actual response structure
|
||||||
|
if (data['status'] == "exists") {
|
||||||
|
print("${data['field']} - $value already exists");
|
||||||
|
return {
|
||||||
|
"message": "$label already exists",
|
||||||
|
"field": data['field']
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
print("$label - $value is a new value");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw Exception('Error parsing response: $e');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw Exception('Failed to load checkDuplicate data. Status code: ${response.statusCode}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------- User Management - CheckDuplicate end here ----------------------------------
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user