APP-SIGNATURE
This commit is contained in:
parent
d29caf66c5
commit
f7342a14b4
@ -221,6 +221,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token', // Add token here
|
'Authorization': 'Bearer $token', // Add token here
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -253,6 +254,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(planData), // Convert map to JSON
|
body: jsonEncode(planData), // Convert map to JSON
|
||||||
);
|
);
|
||||||
@ -308,6 +310,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,8 @@ class _CommentModalListState extends State<CommentModalList> {
|
|||||||
Future<List<Map<String, dynamic>>> fetchComments1() async {
|
Future<List<Map<String, dynamic>>> fetchComments1() async {
|
||||||
final response = await http.get(
|
final response = await http.get(
|
||||||
Uri.parse(
|
Uri.parse(
|
||||||
'$apiUrl/api/plans/getRemarksByPlanId?plan_id=${widget.planId}'),
|
'$apiUrl/api/plans/getRemarksByPlanId?plan_id=${widget.planId}',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
@ -58,6 +59,7 @@ class _CommentModalListState extends State<CommentModalList> {
|
|||||||
Uri.parse(apiUrldata),
|
Uri.parse(apiUrldata),
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -81,10 +83,7 @@ class _CommentModalListState extends State<CommentModalList> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
title: Text(
|
title: Text('Comments', style: GoogleFonts.poppins(color: Colors.black)),
|
||||||
'Comments',
|
|
||||||
style: GoogleFonts.poppins(color: Colors.black),
|
|
||||||
),
|
|
||||||
content: ConstrainedBox(
|
content: ConstrainedBox(
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(
|
||||||
maxWidth: 500, // ✅ You can adjust this width
|
maxWidth: 500, // ✅ You can adjust this width
|
||||||
@ -119,64 +118,86 @@ class _CommentModalListState extends State<CommentModalList> {
|
|||||||
child: DataTable(
|
child: DataTable(
|
||||||
columns: [
|
columns: [
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Name',
|
'Name',
|
||||||
style:
|
style: GoogleFonts.poppins(
|
||||||
GoogleFonts.poppins(fontSize: 11, color: Colors.black),
|
fontSize: 11,
|
||||||
)),
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Comment',
|
'Comment',
|
||||||
style:
|
style: GoogleFonts.poppins(
|
||||||
GoogleFonts.poppins(fontSize: 11, color: Colors.black),
|
fontSize: 11,
|
||||||
)),
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text(
|
label: Text(
|
||||||
'Updated On',
|
'Updated On',
|
||||||
style:
|
style: GoogleFonts.poppins(
|
||||||
GoogleFonts.poppins(fontSize: 11, color: Colors.black),
|
fontSize: 11,
|
||||||
)),
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
rows: comments.map((comment) {
|
rows:
|
||||||
final name = comment['created_by_name'] ?? 'Unknown';
|
comments.map((comment) {
|
||||||
final remark = comment['remarks'] ?? '';
|
final name = comment['created_by_name'] ?? 'Unknown';
|
||||||
final rawDateStr = comment['updated_on'];
|
final remark = comment['remarks'] ?? '';
|
||||||
String updatedOn = '';
|
final rawDateStr = comment['updated_on'];
|
||||||
|
String updatedOn = '';
|
||||||
|
|
||||||
if (rawDateStr != null && rawDateStr.isNotEmpty) {
|
if (rawDateStr != null && rawDateStr.isNotEmpty) {
|
||||||
try {
|
try {
|
||||||
final parsedDate = DateTime.parse(rawDateStr);
|
final parsedDate = DateTime.parse(rawDateStr);
|
||||||
updatedOn = DateFormat('d MMM yyyy')
|
updatedOn = DateFormat(
|
||||||
.format(parsedDate); // e.g., 15 May 2025
|
'd MMM yyyy',
|
||||||
} catch (e) {
|
).format(parsedDate); // e.g., 15 May 2025
|
||||||
updatedOn = rawDateStr.split(' ').first; // fallback
|
} catch (e) {
|
||||||
}
|
updatedOn = rawDateStr.split(' ').first; // fallback
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return DataRow(cells: [
|
return DataRow(
|
||||||
DataCell(Text(
|
cells: [
|
||||||
name,
|
DataCell(
|
||||||
style: GoogleFonts.poppins(
|
Text(
|
||||||
fontSize: 12,
|
name,
|
||||||
color: Colors.black,
|
style: GoogleFonts.poppins(
|
||||||
fontWeight: FontWeight.w500),
|
fontSize: 12,
|
||||||
)),
|
color: Colors.black,
|
||||||
DataCell(Text(
|
fontWeight: FontWeight.w500,
|
||||||
remark,
|
),
|
||||||
style: GoogleFonts.poppins(
|
),
|
||||||
fontSize: 12,
|
),
|
||||||
color: Colors.black,
|
DataCell(
|
||||||
fontWeight: FontWeight.w500),
|
Text(
|
||||||
)),
|
remark,
|
||||||
DataCell(Text(
|
style: GoogleFonts.poppins(
|
||||||
updatedOn,
|
fontSize: 12,
|
||||||
style: GoogleFonts.poppins(
|
color: Colors.black,
|
||||||
fontSize: 12,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.black,
|
),
|
||||||
fontWeight: FontWeight.w500),
|
),
|
||||||
)),
|
),
|
||||||
]);
|
DataCell(
|
||||||
}).toList(),
|
Text(
|
||||||
|
updatedOn,
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -185,11 +206,14 @@ class _CommentModalListState extends State<CommentModalList> {
|
|||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
child: Text('Close',
|
child: Text(
|
||||||
style: GoogleFonts.poppins(
|
'Close',
|
||||||
fontSize: 12,
|
style: GoogleFonts.poppins(
|
||||||
fontWeight: FontWeight.w500,
|
fontSize: 12,
|
||||||
color: widget.layoutColorForUser)),
|
fontWeight: FontWeight.w500,
|
||||||
|
color: widget.layoutColorForUser,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -211,6 +211,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token', // Add token here
|
'Authorization': 'Bearer $token', // Add token here
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -243,6 +244,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(planData), // Convert map to JSON
|
body: jsonEncode(planData), // Convert map to JSON
|
||||||
);
|
);
|
||||||
|
|||||||
@ -200,6 +200,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token', // Add token here
|
'Authorization': 'Bearer $token', // Add token here
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -233,6 +234,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(planData), // Convert map to JSON
|
body: jsonEncode(planData), // Convert map to JSON
|
||||||
);
|
);
|
||||||
@ -293,6 +295,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token', // Add token here
|
'Authorization': 'Bearer $token', // Add token here
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -525,6 +528,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -117,6 +117,7 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
'email': _emailController.text.trim(),
|
'email': _emailController.text.trim(),
|
||||||
@ -214,11 +215,14 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
if (_isForgotPassword && !_showOtpResetFields) {
|
if (_isForgotPassword && !_showOtpResetFields) {
|
||||||
print('11');
|
print('11');
|
||||||
// Step 1: Send OTP
|
// Step 1: Send OTP
|
||||||
final url = '$apiUrl/forgotPassword/verifyUser';
|
final url = '$apiUrl/api/forgotPassword/verifyUser';
|
||||||
try {
|
try {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse(url),
|
Uri.parse(url),
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
|
},
|
||||||
body: jsonEncode({'email': _emailController.text.trim()}),
|
body: jsonEncode({'email': _emailController.text.trim()}),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -273,12 +277,15 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
} else if (!_isForgotPassword && _showOtpResetFields) {
|
} else if (!_isForgotPassword && _showOtpResetFields) {
|
||||||
print('22');
|
print('22');
|
||||||
// Step 2: Verify OTP & Reset Password
|
// Step 2: Verify OTP & Reset Password
|
||||||
final url = '$apiUrl/forgotPassword/changePassword';
|
final url = '$apiUrl/api/forgotPassword/changePassword';
|
||||||
try {
|
try {
|
||||||
print('21');
|
print('21');
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse(url),
|
Uri.parse(url),
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
|
},
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
'email': _emailController.text.trim(),
|
'email': _emailController.text.trim(),
|
||||||
'otp': _otpController.text.trim(),
|
'otp': _otpController.text.trim(),
|
||||||
@ -1111,12 +1118,15 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> handleMS() async {
|
Future<void> handleMS() async {
|
||||||
final url = '$apiUrl/auth/mslogin';
|
final url = '$apiUrl/api/auth/mslogin';
|
||||||
print(url);
|
print(url);
|
||||||
try {
|
try {
|
||||||
final response = await http.get(
|
final response = await http.get(
|
||||||
Uri.parse(url),
|
Uri.parse(url),
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
|
},
|
||||||
);
|
);
|
||||||
print("inside try method");
|
print("inside try method");
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
|
|||||||
@ -105,6 +105,7 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
}
|
}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
node.addListener(() {
|
node.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -168,7 +169,7 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postCostCenterData();
|
postCostCenterData();
|
||||||
}else{
|
} else {
|
||||||
isDisable = false;
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -212,6 +213,7 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
final headers = {
|
final headers = {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
};
|
};
|
||||||
final body = jsonEncode(costcenterData);
|
final body = jsonEncode(costcenterData);
|
||||||
|
|
||||||
@ -426,22 +428,23 @@ class CostCenterDataState extends State<CostCenterData> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: isDisable
|
onPressed:
|
||||||
? null
|
isDisable
|
||||||
: () async {
|
? null
|
||||||
setState(() {
|
: () async {
|
||||||
isDisable = true;
|
setState(() {
|
||||||
});
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
await handleSubmit();
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
// Optional: re-enable only on error
|
// Optional: re-enable only on error
|
||||||
// setState(() {
|
// setState(() {
|
||||||
// isDisable = false;
|
// isDisable = false;
|
||||||
// });
|
// });
|
||||||
},
|
},
|
||||||
// onPressed: () {
|
// onPressed: () {
|
||||||
// handleSubmit();
|
// handleSubmit();
|
||||||
// // You can get text from commentController.text
|
// // You can get text from commentController.text
|
||||||
|
|||||||
@ -149,6 +149,7 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
print("called api : $apiUrlData");
|
print("called api : $apiUrlData");
|
||||||
@ -286,15 +287,13 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Org Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
}
|
},
|
||||||
),
|
|
||||||
BreadcrumbItem(
|
|
||||||
title: 'Cost Center Details',
|
|
||||||
),
|
),
|
||||||
|
BreadcrumbItem(title: 'Cost Center Details'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -310,8 +309,8 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
SizedBox(width: MediaQuery.of(context).size.width * 0.08),
|
SizedBox(width: MediaQuery.of(context).size.width * 0.08),
|
||||||
// SizedBox(width: MediaQuery.of(context).size.width * 0.16),
|
|
||||||
|
|
||||||
|
// SizedBox(width: MediaQuery.of(context).size.width * 0.16),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
Container(
|
Container(
|
||||||
width: MediaQuery.of(context).size.width * 0.2,
|
width: MediaQuery.of(context).size.width * 0.2,
|
||||||
@ -458,7 +457,7 @@ class CostCenterListState extends State<CostCenterList> {
|
|||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final adjHgt = MediaQuery.of(context).size.height;
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (futureCostCenter == null) {
|
if (futureCostCenter == null) {
|
||||||
return CircularProgressIndicator();
|
return const Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
|||||||
@ -205,6 +205,7 @@ class StatusDashboardState extends State<StatusDashboard> {
|
|||||||
Uri.parse(apiUrlData),
|
Uri.parse(apiUrlData),
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@ -105,6 +105,7 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
}
|
}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
node.addListener(() {
|
node.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -168,7 +169,7 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postDepartmentData();
|
postDepartmentData();
|
||||||
}else{
|
} else {
|
||||||
isDisable = false;
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -212,6 +213,7 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
final headers = {
|
final headers = {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
};
|
};
|
||||||
final body = jsonEncode(departmentData);
|
final body = jsonEncode(departmentData);
|
||||||
|
|
||||||
@ -428,22 +430,23 @@ class DepartmentDataState extends State<DepartmentData> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: isDisable
|
onPressed:
|
||||||
? null
|
isDisable
|
||||||
: () async {
|
? null
|
||||||
setState(() {
|
: () async {
|
||||||
isDisable = true;
|
setState(() {
|
||||||
});
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
await handleSubmit();
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
// Optional: re-enable only on error
|
// Optional: re-enable only on error
|
||||||
// setState(() {
|
// setState(() {
|
||||||
// isDisable = false;
|
// isDisable = false;
|
||||||
// });
|
// });
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
|
|||||||
@ -149,6 +149,7 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
print("called api : $apiUrlData");
|
print("called api : $apiUrlData");
|
||||||
@ -181,11 +182,10 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
allDepartment.where((object) {
|
allDepartment.where((object) {
|
||||||
final isActiveStatus =
|
final isActiveStatus =
|
||||||
object['is_active'] == "1" ? "active" : "inactive";
|
object['is_active'] == "1" ? "active" : "inactive";
|
||||||
return (object['id']?.toLowerCase().contains(
|
return (object['id']?.toLowerCase().contains(lowerQuery) ??
|
||||||
lowerQuery,
|
false) ||
|
||||||
) ??
|
(object['dropdown_value']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
(object['dropdown_value']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
|
||||||
// (object['description']?.toLowerCase().contains(lowerQuery) ??
|
// (object['description']?.toLowerCase().contains(lowerQuery) ??
|
||||||
// false) ||
|
// false) ||
|
||||||
(isActiveStatus.contains(lowerQuery));
|
(isActiveStatus.contains(lowerQuery));
|
||||||
@ -285,15 +285,13 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Org Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
}
|
},
|
||||||
),
|
|
||||||
BreadcrumbItem(
|
|
||||||
title: 'Department Details',
|
|
||||||
),
|
),
|
||||||
|
BreadcrumbItem(title: 'Department Details'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -309,8 +307,8 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
SizedBox(width: MediaQuery.of(context).size.width * 0.08),
|
SizedBox(width: MediaQuery.of(context).size.width * 0.08),
|
||||||
// SizedBox(width: MediaQuery.of(context).size.width * 0.16),
|
|
||||||
|
|
||||||
|
// SizedBox(width: MediaQuery.of(context).size.width * 0.16),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
Container(
|
Container(
|
||||||
width: MediaQuery.of(context).size.width * 0.2,
|
width: MediaQuery.of(context).size.width * 0.2,
|
||||||
@ -584,8 +582,7 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
rows:
|
rows:
|
||||||
paginatedDepartment.map((tableObject) {
|
paginatedDepartment.map((tableObject) {
|
||||||
String departmentId =
|
String departmentId =
|
||||||
tableObject['id']
|
tableObject['id'].toString(); // Get user ID
|
||||||
.toString(); // Get user ID
|
|
||||||
bool isSelected =
|
bool isSelected =
|
||||||
selectedDepartmentId == departmentId;
|
selectedDepartmentId == departmentId;
|
||||||
|
|
||||||
@ -648,8 +645,7 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
// final usersData = await getUserDetails(userId);
|
// final usersData = await getUserDetails(userId);
|
||||||
//
|
//
|
||||||
final departmentId = int.tryParse(
|
final departmentId = int.tryParse(
|
||||||
tableObject['id']
|
tableObject['id'].toString(),
|
||||||
.toString(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (departmentId != null) {
|
if (departmentId != null) {
|
||||||
@ -741,8 +737,7 @@ class DepartmentListState extends State<DepartmentList> {
|
|||||||
// final usersData = await getUserDetails(userId);
|
// final usersData = await getUserDetails(userId);
|
||||||
//
|
//
|
||||||
final departmentId = int.tryParse(
|
final departmentId = int.tryParse(
|
||||||
cardObject['id']
|
cardObject['id'].toString(),
|
||||||
.toString(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (departmentId != null) {
|
if (departmentId != null) {
|
||||||
|
|||||||
@ -71,6 +71,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -95,7 +96,6 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
_users = userList.map((user) => SearchUser.fromJson(user)).toList();
|
_users = userList.map((user) => SearchUser.fromJson(user)).toList();
|
||||||
_filteredUsers = List.from(_users);
|
_filteredUsers = List.from(_users);
|
||||||
_filterUsers("");
|
_filterUsers("");
|
||||||
|
|
||||||
});
|
});
|
||||||
print("filtered user === ${_filteredUsers.length}");
|
print("filtered user === ${_filteredUsers.length}");
|
||||||
print("Users fetched: ${_users.length}");
|
print("Users fetched: ${_users.length}");
|
||||||
@ -132,6 +132,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -211,10 +212,15 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
|
|
||||||
if (query.isEmpty) {
|
if (query.isEmpty) {
|
||||||
// ✅ Return all users excluding self and roleId == 5
|
// ✅ Return all users excluding self and roleId == 5
|
||||||
_filteredList = _users.where((user) =>
|
_filteredList =
|
||||||
user.userId.toString() != excludedUserId && user.roleId.toString() != "5")
|
_users
|
||||||
.map((user) => {"type": "user", "data": user})
|
.where(
|
||||||
.toList();
|
(user) =>
|
||||||
|
user.userId.toString() != excludedUserId &&
|
||||||
|
user.roleId.toString() != "5",
|
||||||
|
)
|
||||||
|
.map((user) => {"type": "user", "data": user})
|
||||||
|
.toList();
|
||||||
|
|
||||||
// _filteredList = [
|
// _filteredList = [
|
||||||
// // ..._users.map((user) => {"type": "user", "data": user}),
|
// // ..._users.map((user) => {"type": "user", "data": user}),
|
||||||
@ -277,9 +283,10 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_filteredList.clear(); // Reset the list before filtering
|
_filteredList.clear(); // Reset the list before filtering
|
||||||
if (query.isEmpty) {
|
if (query.isEmpty) {
|
||||||
_filteredList = _traveller
|
_filteredList =
|
||||||
.map((traveller) => {"type": "traveller", "data": traveller})
|
_traveller
|
||||||
.toList();
|
.map((traveller) => {"type": "traveller", "data": traveller})
|
||||||
|
.toList();
|
||||||
// _filteredList = [
|
// _filteredList = [
|
||||||
// ..._users.map((user) => {"type": "user", "data": user}),
|
// ..._users.map((user) => {"type": "user", "data": user}),
|
||||||
// ];
|
// ];
|
||||||
@ -377,19 +384,21 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
if (widget.title == "Others (Non Employee)"){ fetchTraveller(); }
|
if (widget.title == "Others (Non Employee)") {
|
||||||
else{ fetchUsers(); }
|
fetchTraveller();
|
||||||
|
} else {
|
||||||
|
fetchUsers();
|
||||||
|
}
|
||||||
print("SelffsdfcurrentUser - ${widget.currentUser}");
|
print("SelffsdfcurrentUser - ${widget.currentUser}");
|
||||||
_filterByTitle("");
|
_filterByTitle("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final isValid =
|
||||||
final isValid = _searchController.text.trim().isNotEmpty &&
|
_searchController.text.trim().isNotEmpty &&
|
||||||
userIdSelected.trim().isNotEmpty;
|
userIdSelected.trim().isNotEmpty;
|
||||||
|
|
||||||
|
|
||||||
return Dialog(
|
return Dialog(
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
child: Container(
|
child: Container(
|
||||||
@ -482,81 +491,100 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
// _searchController.text.isNotEmpty
|
// _searchController.text.isNotEmpty
|
||||||
// ?
|
// ?
|
||||||
if (!_showTravellerForm)
|
if (!_showTravellerForm)
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 300, // Limit height to avoid overflow
|
height: 300, // Limit height to avoid overflow
|
||||||
// child: _filteredUsers.isEmpty
|
// child: _filteredUsers.isEmpty
|
||||||
child:
|
child:
|
||||||
_filteredList.isEmpty
|
_filteredList.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No users found",
|
"No users found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
|
||||||
: ListView.builder(
|
|
||||||
// itemCount: _filteredUsers.length,
|
|
||||||
itemCount: _filteredList.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
// final user = _filteredUsers[index];
|
|
||||||
|
|
||||||
final item = _filteredList[index];
|
|
||||||
final user = item["data"]; // Extract user object
|
|
||||||
final userType =
|
|
||||||
item["type"]; // "user" or "traveller"
|
|
||||||
if (user is Map<String, dynamic>) {
|
|
||||||
print("userLsirer - ${jsonEncode(user)}"); // pretty JSON-like string
|
|
||||||
} else {
|
|
||||||
print("userLsirer - $user"); // fallback
|
|
||||||
}
|
|
||||||
final isSelected = userIdSelected == (userType == "user" ? user.userId : user.travellerId);
|
|
||||||
return ListTile(
|
|
||||||
// hoverColor: ,
|
|
||||||
title: Text(
|
|
||||||
"${user.firstName ?? "Unknown"}" "${(user.lastName?.isNotEmpty ?? false) ? " ${user.lastName}" : ""}",
|
|
||||||
style: GoogleFonts.poppins(fontSize: 11 , color: isSelected ? widget.layoutColorForUser : Colors.black),
|
|
||||||
),
|
|
||||||
subtitle:
|
|
||||||
userType == "user"
|
|
||||||
? Text(
|
|
||||||
"Employee ID: ${user.empCode ?? "-"} ",
|
|
||||||
// "Employee ID: ${userType == "user" ? user.userId : user.travellerId}",
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 10,
|
|
||||||
color: isSelected ? widget.layoutColorForUser : Colors.black,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Text(
|
|
||||||
"Mobile : ${user.mobileNo ?? "-"} ",
|
|
||||||
// "Employee ID: ${userType == "user" ? user.userId : user.travellerId}",
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 10,
|
|
||||||
color: isSelected ? widget.layoutColorForUser : Colors.black,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
String selectedUser =
|
|
||||||
"${user.firstName ?? "Unknown"} ${user.lastName ?? ""}";
|
|
||||||
setState(() {
|
|
||||||
_searchController.text = selectedUser;
|
|
||||||
userIdSelected =
|
|
||||||
userType == "user"
|
|
||||||
? user.userId
|
|
||||||
: user.travellerId;
|
|
||||||
isTraveller = userType == "traveller";
|
|
||||||
});
|
|
||||||
print(
|
|
||||||
"Selected: $selectedUser, ID: ${userType == "user" ? user.userId : user.travellerId},"
|
|
||||||
" isTraveller: $userIdSelected",
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
// : SizedBox.shrink(),
|
: ListView.builder(
|
||||||
|
// itemCount: _filteredUsers.length,
|
||||||
|
itemCount: _filteredList.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
// final user = _filteredUsers[index];
|
||||||
|
|
||||||
|
final item = _filteredList[index];
|
||||||
|
final user = item["data"]; // Extract user object
|
||||||
|
final userType =
|
||||||
|
item["type"]; // "user" or "traveller"
|
||||||
|
if (user is Map<String, dynamic>) {
|
||||||
|
print(
|
||||||
|
"userLsirer - ${jsonEncode(user)}",
|
||||||
|
); // pretty JSON-like string
|
||||||
|
} else {
|
||||||
|
print("userLsirer - $user"); // fallback
|
||||||
|
}
|
||||||
|
final isSelected =
|
||||||
|
userIdSelected ==
|
||||||
|
(userType == "user"
|
||||||
|
? user.userId
|
||||||
|
: user.travellerId);
|
||||||
|
return ListTile(
|
||||||
|
// hoverColor: ,
|
||||||
|
title: Text(
|
||||||
|
"${user.firstName ?? "Unknown"}"
|
||||||
|
"${(user.lastName?.isNotEmpty ?? false) ? " ${user.lastName}" : ""}",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 11,
|
||||||
|
color:
|
||||||
|
isSelected
|
||||||
|
? widget.layoutColorForUser
|
||||||
|
: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle:
|
||||||
|
userType == "user"
|
||||||
|
? Text(
|
||||||
|
"Employee ID: ${user.empCode ?? "-"} ",
|
||||||
|
// "Employee ID: ${userType == "user" ? user.userId : user.travellerId}",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 10,
|
||||||
|
color:
|
||||||
|
isSelected
|
||||||
|
? widget.layoutColorForUser
|
||||||
|
: Colors.black,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
"Mobile : ${user.mobileNo ?? "-"} ",
|
||||||
|
// "Employee ID: ${userType == "user" ? user.userId : user.travellerId}",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 10,
|
||||||
|
color:
|
||||||
|
isSelected
|
||||||
|
? widget.layoutColorForUser
|
||||||
|
: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
String selectedUser =
|
||||||
|
"${user.firstName ?? "Unknown"} ${user.lastName ?? ""}";
|
||||||
|
setState(() {
|
||||||
|
_searchController.text = selectedUser;
|
||||||
|
userIdSelected =
|
||||||
|
userType == "user"
|
||||||
|
? user.userId
|
||||||
|
: user.travellerId;
|
||||||
|
isTraveller = userType == "traveller";
|
||||||
|
});
|
||||||
|
print(
|
||||||
|
"Selected: $selectedUser, ID: ${userType == "user" ? user.userId : user.travellerId},"
|
||||||
|
" isTraveller: $userIdSelected",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// : SizedBox.shrink(),
|
||||||
|
|
||||||
// Traveler Form
|
// Traveler Form
|
||||||
if (_showTravellerForm)
|
if (_showTravellerForm)
|
||||||
@ -616,32 +644,35 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: isValid ? widget.layoutColorForUser : Colors.grey,
|
backgroundColor:
|
||||||
|
isValid ? widget.layoutColorForUser : Colors.grey,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
side: BorderSide(
|
side: BorderSide(
|
||||||
// color: widget.layoutColorForUser,
|
// color: widget.layoutColorForUser,
|
||||||
color: isValid ? widget.layoutColorForUser : Colors.grey,
|
color:
|
||||||
|
isValid ? widget.layoutColorForUser : Colors.grey,
|
||||||
width: isValid ? 2 : 0,
|
width: isValid ? 2 : 0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
onPressed: isValid ? () {
|
onPressed:
|
||||||
print("Submitting: ${_searchController.text}, ID: $userIdSelected");
|
isValid
|
||||||
widget.onSubmit(
|
? () {
|
||||||
_searchController.text,
|
print(
|
||||||
userIdSelected,
|
"Submitting: ${_searchController.text}, ID: $userIdSelected",
|
||||||
isTraveller,
|
);
|
||||||
);
|
widget.onSubmit(
|
||||||
Navigator.pop(context);
|
_searchController.text,
|
||||||
}
|
userIdSelected,
|
||||||
: null,
|
isTraveller,
|
||||||
child: Text(
|
);
|
||||||
"Save",
|
Navigator.pop(context);
|
||||||
style: GoogleFonts.poppins(fontSize: 11),
|
}
|
||||||
),
|
: null,
|
||||||
|
child: Text("Save", style: GoogleFonts.poppins(fontSize: 11)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -745,6 +776,7 @@ class _TravelerFormState extends State<TravelerForm> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(requestBody),
|
body: jsonEncode(requestBody),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -247,6 +247,7 @@ class _groupState extends State<Group> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(groupData),
|
body: jsonEncode(groupData),
|
||||||
)
|
)
|
||||||
@ -255,6 +256,7 @@ class _groupState extends State<Group> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(groupData),
|
body: jsonEncode(groupData),
|
||||||
));
|
));
|
||||||
|
|||||||
@ -232,7 +232,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postGroupData();
|
postGroupData();
|
||||||
}else{
|
} else {
|
||||||
isDisable = false;
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -270,6 +270,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
final headers = {
|
final headers = {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
};
|
};
|
||||||
final body = jsonEncode(groupData);
|
final body = jsonEncode(groupData);
|
||||||
|
|
||||||
@ -308,12 +309,12 @@ class GroupDataState extends State<GroupData> {
|
|||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
print("Failed to submit plan. Status: ${response.statusCode}");
|
print("Failed to submit plan. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
final message = jsonDecode(response.body);
|
final message = jsonDecode(response.body);
|
||||||
final errorMessage = message['messages']?['error'] ?? 'Unknown error occurred';
|
final errorMessage =
|
||||||
|
message['messages']?['error'] ?? 'Unknown error occurred';
|
||||||
|
|
||||||
if (errorMessage.contains("Duplicate entry")) {
|
if (errorMessage.contains("Duplicate entry")) {
|
||||||
_clearError();
|
_clearError();
|
||||||
@ -464,7 +465,11 @@ class GroupDataState extends State<GroupData> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.remove_circle_sharp, size: 12, color: Colors.redAccent),
|
icon: Icon(
|
||||||
|
Icons.remove_circle_sharp,
|
||||||
|
size: 12,
|
||||||
|
color: Colors.redAccent,
|
||||||
|
),
|
||||||
tooltip: "Reset",
|
tooltip: "Reset",
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -506,15 +511,15 @@ class GroupDataState extends State<GroupData> {
|
|||||||
constraints: BoxConstraints(maxHeight: 250),
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
itemBuilder:
|
itemBuilder:
|
||||||
(context, object, isSelected) => Padding(
|
(context, object, isSelected) => Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 8.0,
|
horizontal: 8.0,
|
||||||
vertical: 6.0,
|
vertical: 6.0,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
object,
|
object,
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search ...",
|
hintText: "Search ...",
|
||||||
@ -533,40 +538,47 @@ class GroupDataState extends State<GroupData> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color:
|
color:
|
||||||
(focusStates["domestic_policy_nameFocused"] ?? false)
|
(focusStates["domestic_policy_nameFocused"] ??
|
||||||
? widget.layoutColor!
|
false)
|
||||||
: Colors.white,
|
? widget.layoutColor!
|
||||||
|
: Colors.white,
|
||||||
// width: 0.5,
|
// width: 0.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color:
|
color:
|
||||||
(focusStates["domestic_policy_nameFocused"] ?? false)
|
(focusStates["domestic_policy_nameFocused"] ??
|
||||||
? widget.layoutColor!
|
false)
|
||||||
: Colors.white,
|
? widget.layoutColor!
|
||||||
|
: Colors.white,
|
||||||
// : const Color(0xFFD6D5E6),
|
// : const Color(0xFFD6D5E6),
|
||||||
// width: 0.5,
|
// width: 0.5,
|
||||||
// const Color(0xFFD6D5E6),
|
// const Color(0xFFD6D5E6),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: widget.layoutColor!, width: 1),
|
borderSide: BorderSide(
|
||||||
|
color: widget.layoutColor!,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10.0,
|
||||||
|
vertical: 8.0,
|
||||||
),
|
),
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 10.0,
|
|
||||||
vertical: 8.0,),
|
|
||||||
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
(context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
// Center-align selected item
|
// Center-align selected item
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select ",
|
selectedItem ?? "Select ",
|
||||||
style: GoogleFonts.poppins(fontSize: 11),
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
// Find the country_code based on selected country_name
|
// Find the country_code based on selected country_name
|
||||||
@ -574,7 +586,7 @@ class GroupDataState extends State<GroupData> {
|
|||||||
DomesticMap.entries
|
DomesticMap.entries
|
||||||
.firstWhere(
|
.firstWhere(
|
||||||
(entry) => entry.value == newValue,
|
(entry) => entry.value == newValue,
|
||||||
)
|
)
|
||||||
.key;
|
.key;
|
||||||
selectedDomesticPolicyName = newValue;
|
selectedDomesticPolicyName = newValue;
|
||||||
});
|
});
|
||||||
@ -602,7 +614,11 @@ class GroupDataState extends State<GroupData> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.remove_circle_sharp, size: 12, color: Colors.redAccent),
|
icon: Icon(
|
||||||
|
Icons.remove_circle_sharp,
|
||||||
|
size: 12,
|
||||||
|
color: Colors.redAccent,
|
||||||
|
),
|
||||||
tooltip: "Reset",
|
tooltip: "Reset",
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -673,28 +689,35 @@ class GroupDataState extends State<GroupData> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color:
|
color:
|
||||||
(focusStates["international_policy_nameFocused"] ?? false)
|
(focusStates["international_policy_nameFocused"] ??
|
||||||
? widget.layoutColor!
|
false)
|
||||||
: Colors.white,
|
? widget.layoutColor!
|
||||||
|
: Colors.white,
|
||||||
width: 0.5,
|
width: 0.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color:
|
color:
|
||||||
(focusStates["international_policy_nameFocused"] ?? false)
|
(focusStates["international_policy_nameFocused"] ??
|
||||||
? widget.layoutColor!
|
false)
|
||||||
: Colors.white,
|
? widget.layoutColor!
|
||||||
|
: Colors.white,
|
||||||
// : const Color(0xFFD6D5E6),
|
// : const Color(0xFFD6D5E6),
|
||||||
width: 0.5,
|
width: 0.5,
|
||||||
// const Color(0xFFD6D5E6),
|
// const Color(0xFFD6D5E6),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: widget.layoutColor!, width: 1),
|
borderSide: BorderSide(
|
||||||
|
color: widget.layoutColor!,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10.0,
|
||||||
|
vertical: 8.0,
|
||||||
),
|
),
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 10.0,
|
|
||||||
vertical: 8.0,),
|
|
||||||
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -833,21 +856,22 @@ class GroupDataState extends State<GroupData> {
|
|||||||
// // You can get text from commentController.text
|
// // You can get text from commentController.text
|
||||||
// // Navigator.of(context).pop(); // Close the modal
|
// // Navigator.of(context).pop(); // Close the modal
|
||||||
// },
|
// },
|
||||||
onPressed: isDisable
|
onPressed:
|
||||||
? null
|
isDisable
|
||||||
: () async {
|
? null
|
||||||
setState(() {
|
: () async {
|
||||||
isDisable = true;
|
setState(() {
|
||||||
});
|
isDisable = true;
|
||||||
await handleSubmit();
|
});
|
||||||
// You can get text from commentController.text
|
await handleSubmit();
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// You can get text from commentController.text
|
||||||
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
// Optional: re-enable only on error
|
// Optional: re-enable only on error
|
||||||
// setState(() {
|
// setState(() {
|
||||||
// isDisable = false;
|
// isDisable = false;
|
||||||
// });
|
// });
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
|
|||||||
@ -190,6 +190,7 @@ class _GroupListState extends State<GroupList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"is_active": newStatus, // Set new status dynamically
|
"is_active": newStatus, // Set new status dynamically
|
||||||
@ -304,18 +305,17 @@ class _GroupListState extends State<GroupList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Org Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
}
|
},
|
||||||
),
|
|
||||||
BreadcrumbItem(
|
|
||||||
title: 'Group ',
|
|
||||||
),
|
),
|
||||||
|
BreadcrumbItem(title: 'Group '),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Text(
|
// Text(
|
||||||
// 'Group',
|
// 'Group',
|
||||||
// style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
@ -324,13 +324,12 @@ class _GroupListState extends State<GroupList> {
|
|||||||
// color: Colors.black,
|
// color: Colors.black,
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
SizedBox(width: MediaQuery.of(context).size.width * 0.145),
|
SizedBox(width: MediaQuery.of(context).size.width * 0.145),
|
||||||
// SizedBox(width: MediaQuery.of(context).size.width * 0.28),
|
|
||||||
|
|
||||||
|
// SizedBox(width: MediaQuery.of(context).size.width * 0.28),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
Container(
|
Container(
|
||||||
width: MediaQuery.of(context).size.width * 0.2,
|
width: MediaQuery.of(context).size.width * 0.2,
|
||||||
@ -625,7 +624,9 @@ class _GroupListState extends State<GroupList> {
|
|||||||
// ),
|
// ),
|
||||||
DataCell(
|
DataCell(
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(maxWidth: 200), // limit description width
|
constraints: BoxConstraints(
|
||||||
|
maxWidth: 200,
|
||||||
|
), // limit description width
|
||||||
child: Text(
|
child: Text(
|
||||||
"${group['name'] ?? ''}",
|
"${group['name'] ?? ''}",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -633,7 +634,8 @@ class _GroupListState extends State<GroupList> {
|
|||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
),
|
),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 1, // optional: show only 1 line
|
maxLines:
|
||||||
|
1, // optional: show only 1 line
|
||||||
softWrap: false,
|
softWrap: false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -667,7 +669,9 @@ class _GroupListState extends State<GroupList> {
|
|||||||
// ),
|
// ),
|
||||||
DataCell(
|
DataCell(
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(maxWidth: 200), // limit description width
|
constraints: BoxConstraints(
|
||||||
|
maxWidth: 200,
|
||||||
|
), // limit description width
|
||||||
child: Text(
|
child: Text(
|
||||||
"${group['description'] ?? 'N/A'}",
|
"${group['description'] ?? 'N/A'}",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|||||||
@ -120,6 +120,7 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
}
|
}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
node.addListener(() {
|
node.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -201,7 +202,7 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postHotelsData();
|
postHotelsData();
|
||||||
}else{
|
} else {
|
||||||
isDisable = false;
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -247,6 +248,7 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
final headers = {
|
final headers = {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
};
|
};
|
||||||
final body = jsonEncode(hotelsData);
|
final body = jsonEncode(hotelsData);
|
||||||
|
|
||||||
@ -282,7 +284,6 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
isDisable = false;
|
isDisable = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
print("Failed to submit plan. Status: ${response.statusCode}");
|
print("Failed to submit plan. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
@ -291,14 +292,12 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
isDisable = false;
|
isDisable = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
|
||||||
print("Error submitting plan: $e");
|
print("Error submitting plan: $e");
|
||||||
setState(() {
|
setState(() {
|
||||||
isDisable = false;
|
isDisable = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -318,7 +317,7 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
countryMap = {
|
countryMap = {
|
||||||
for (var country in countryList)
|
for (var country in countryList)
|
||||||
(country['country_code'] ?? ''):
|
(country['country_code'] ?? ''):
|
||||||
'${country['country_name'] ?? ''} (${country['country_code'] ?? ''})',
|
'${country['country_name'] ?? ''} (${country['country_code'] ?? ''})',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract only country codes for processing
|
// Extract only country codes for processing
|
||||||
@ -455,7 +454,9 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
focusNode: focusNodes["categoryFocusNode"],
|
focusNode: focusNodes["categoryFocusNode"],
|
||||||
controller: controllers["category"],
|
controller: controllers["category"],
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 ]')),
|
FilteringTextInputFormatter.allow(
|
||||||
|
RegExp(r'[a-zA-Z0-9 ]'),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
@ -489,119 +490,144 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: Focus(
|
child: Focus(
|
||||||
focusNode: focusNodes["country_codeFocusNode"],
|
focusNode: focusNodes["country_codeFocusNode"],
|
||||||
onFocusChange: (hasFocus) {
|
onFocusChange: (hasFocus) {
|
||||||
setState(() {
|
setState(() {
|
||||||
focusStates["country_codeFocused"] = hasFocus;
|
focusStates["country_codeFocused"] = hasFocus;
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Request focus when user taps
|
||||||
|
focusNodes["country_codeFocusNode"]?.requestFocus();
|
||||||
},
|
},
|
||||||
child: GestureDetector(
|
child: DropdownSearch<String>(
|
||||||
onTap: () {
|
selectedItem: countryMap[selectedCountry],
|
||||||
// Request focus when user taps
|
popupProps: PopupProps.menu(
|
||||||
focusNodes["country_codeFocusNode"]?.requestFocus();
|
showSearchBox: true, // Enables search functionality
|
||||||
},
|
menuProps: const MenuProps(
|
||||||
child: DropdownSearch<String>(
|
backgroundColor: Colors.white,
|
||||||
selectedItem: countryMap[selectedCountry],
|
|
||||||
popupProps: PopupProps.menu(
|
|
||||||
showSearchBox: true, // Enables search functionality
|
|
||||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
|
||||||
constraints: BoxConstraints(maxHeight: 200),
|
|
||||||
itemBuilder:
|
|
||||||
(context, item, isSelected) {
|
|
||||||
print("contryItem - $item");
|
|
||||||
final match = RegExp(r'^(.*)\s\((.*)\)$',).firstMatch(item);
|
|
||||||
final countryName = match?.group(1) ?? '';
|
|
||||||
final countryCode = match?.group(2) ?? '';
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 8.0,
|
|
||||||
vertical: 0.02,
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
countryName,
|
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
countryCode,
|
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5,color:Colors.grey),
|
|
||||||
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);},
|
|
||||||
searchFieldProps: TextFieldProps(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
hintText: "Search ...",
|
|
||||||
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 1,vertical: 1),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
items: countryMap.values.toList(),
|
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
|
||||||
dropdownSearchDecoration: InputDecoration(
|
|
||||||
// border: InputBorder.none,
|
|
||||||
border: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color:
|
|
||||||
(focusStates["country_codeFocused"] ?? false)
|
|
||||||
? widget.layoutColor!
|
|
||||||
: Colors.white,
|
|
||||||
// width: 0.5,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color:
|
|
||||||
(focusStates["country_codeFocused"] ?? false)
|
|
||||||
? widget.layoutColor!
|
|
||||||
: Colors.white,
|
|
||||||
// : const Color(0xFFD6D5E6),
|
|
||||||
// width: 0.5,
|
|
||||||
// const Color(0xFFD6D5E6),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(color: widget.layoutColor!, width: 1),
|
|
||||||
),
|
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 10.0,
|
|
||||||
vertical: 8.0,),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
dropdownBuilder:
|
|
||||||
(context, selectedItem) => Align(
|
|
||||||
// Center-align selected item
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Text(
|
|
||||||
selectedItem ?? "Select ",
|
|
||||||
style: GoogleFonts.poppins(fontSize: 11),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onChanged: (String? newValue) {
|
|
||||||
setState(() {
|
|
||||||
// Find the country_code based on selected country_name
|
|
||||||
selectedCountry =
|
|
||||||
countryMap.entries
|
|
||||||
.firstWhere((entry) => entry.value == newValue)
|
|
||||||
.key;
|
|
||||||
final match = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(newValue!);
|
|
||||||
final countryName = match?.group(1) ?? newValue; // --> "Ascension Islands"
|
|
||||||
// final countryCode = match?.group(2) ?? "";
|
|
||||||
selectedCountryName = countryName;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
)
|
constraints: BoxConstraints(maxHeight: 200),
|
||||||
)
|
itemBuilder: (context, item, isSelected) {
|
||||||
|
print("contryItem - $item");
|
||||||
|
final match = RegExp(
|
||||||
|
r'^(.*)\s\((.*)\)$',
|
||||||
|
).firstMatch(item);
|
||||||
|
final countryName = match?.group(1) ?? '';
|
||||||
|
final countryCode = match?.group(2) ?? '';
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8.0,
|
||||||
|
vertical: 0.02,
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
countryName,
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 11.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
countryCode,
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 11.5,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
searchFieldProps: TextFieldProps(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "Search ...",
|
||||||
|
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 1,
|
||||||
|
vertical: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
items: countryMap.values.toList(),
|
||||||
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
|
dropdownSearchDecoration: InputDecoration(
|
||||||
|
// border: InputBorder.none,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["country_codeFocused"] ??
|
||||||
|
false)
|
||||||
|
? widget.layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
// width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["country_codeFocused"] ??
|
||||||
|
false)
|
||||||
|
? widget.layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
// width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: widget.layoutColor!,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10.0,
|
||||||
|
vertical: 8.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownBuilder:
|
||||||
|
(context, selectedItem) => Align(
|
||||||
|
// Center-align selected item
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
selectedItem ?? "Select ",
|
||||||
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onChanged: (String? newValue) {
|
||||||
|
setState(() {
|
||||||
|
// Find the country_code based on selected country_name
|
||||||
|
selectedCountry =
|
||||||
|
countryMap.entries
|
||||||
|
.firstWhere(
|
||||||
|
(entry) => entry.value == newValue,
|
||||||
|
)
|
||||||
|
.key;
|
||||||
|
final match = RegExp(
|
||||||
|
r'^(.*)\s\((.*)\)$',
|
||||||
|
).firstMatch(newValue!);
|
||||||
|
final countryName =
|
||||||
|
match?.group(1) ??
|
||||||
|
newValue; // --> "Ascension Islands"
|
||||||
|
// final countryCode = match?.group(2) ?? "";
|
||||||
|
selectedCountryName = countryName;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["country_code"] != null) ...[
|
if (errorMessages["country_code"] != null) ...[
|
||||||
@ -712,22 +738,23 @@ class HotelsDataState extends State<HotelsData> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: isDisable
|
onPressed:
|
||||||
? null
|
isDisable
|
||||||
: () async {
|
? null
|
||||||
setState(() {
|
: () async {
|
||||||
isDisable = true;
|
setState(() {
|
||||||
});
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
await handleSubmit();
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
// Optional: re-enable only on error
|
// Optional: re-enable only on error
|
||||||
// setState(() {
|
// setState(() {
|
||||||
// isDisable = false;
|
// isDisable = false;
|
||||||
// });
|
// });
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
|
|||||||
@ -152,6 +152,7 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -177,6 +178,7 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -338,15 +340,13 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Org Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
}
|
},
|
||||||
),
|
|
||||||
BreadcrumbItem(
|
|
||||||
title: 'Hotel Details',
|
|
||||||
),
|
),
|
||||||
|
BreadcrumbItem(title: 'Hotel Details'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -508,7 +508,7 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final adjHgt = MediaQuery.of(context).size.height;
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (futureHotels == null) {
|
if (futureHotels == null) {
|
||||||
return CircularProgressIndicator();
|
return const Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
@ -892,7 +892,7 @@ class HotelsDataListState extends State<HotelsDataList> {
|
|||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment:
|
||||||
CrossAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"${hotels['category'] ?? ''} ",
|
"${hotels['category'] ?? ''} ",
|
||||||
|
|||||||
@ -207,6 +207,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(forexData), // Convert map to JSON
|
body: jsonEncode(forexData), // Convert map to JSON
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:html' as html;
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:io' as io show Directory, File;
|
import 'dart:io' as io show Directory, File;
|
||||||
import 'package:delta_to_html/delta_to_html.dart';
|
import 'package:delta_to_html/delta_to_html.dart';
|
||||||
import 'package:flutter/cupertino.dart' as dom;
|
import 'package:flutter/cupertino.dart' as dom;
|
||||||
@ -15,6 +17,9 @@ import 'package:frontend/Screens/myTemplates/templateForex.dart'
|
|||||||
as _editorScrollController;
|
as _editorScrollController;
|
||||||
import 'package:frontend/Screens/myTemplates/templateForex.dart' as _controller;
|
import 'package:frontend/Screens/myTemplates/templateForex.dart' as _controller;
|
||||||
import 'package:html2md/html2md.dart' as html2md;
|
import 'package:html2md/html2md.dart' as html2md;
|
||||||
|
import 'package:http_parser/http_parser.dart';
|
||||||
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:mime/mime.dart';
|
||||||
import 'package:vsc_quill_delta_to_html/vsc_quill_delta_to_html.dart';
|
import 'package:vsc_quill_delta_to_html/vsc_quill_delta_to_html.dart';
|
||||||
|
|
||||||
import 'package:flutter_quill/flutter_quill.dart' as quill;
|
import 'package:flutter_quill/flutter_quill.dart' as quill;
|
||||||
@ -59,6 +64,8 @@ class TemplateForex extends StatefulWidget {
|
|||||||
class TemplateForexState extends State<TemplateForex> {
|
class TemplateForexState extends State<TemplateForex> {
|
||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
|
|
||||||
|
Uint8List? _imageBytes;
|
||||||
|
String? selectedOrglogo;
|
||||||
// final QuillController _controller = QuillController.basic();
|
// final QuillController _controller = QuillController.basic();
|
||||||
String? orgId;
|
String? orgId;
|
||||||
String? userId;
|
String? userId;
|
||||||
@ -91,11 +98,6 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
"body_html": DeltaToHTML.encodeJson(
|
"body_html": DeltaToHTML.encodeJson(
|
||||||
_controller.document.toDelta().toJson(),
|
_controller.document.toDelta().toJson(),
|
||||||
),
|
),
|
||||||
// "body_html": jsonEncode(_controller.document.toDelta().toJson()),
|
|
||||||
|
|
||||||
// "body_html": _controller,
|
|
||||||
// "body_html": convertQuillDocToHtml(_controller.document),
|
|
||||||
// ✅ convert delta to HTML
|
|
||||||
"placeholder": jsonEncode(placeholderList),
|
"placeholder": jsonEncode(placeholderList),
|
||||||
// "created_by": userId
|
// "created_by": userId
|
||||||
};
|
};
|
||||||
@ -363,7 +365,7 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
print(
|
print(
|
||||||
"API Selected User Has - ${widget.templateData?["templateData"]?["subject"]}",
|
"API Selected User Has - ${widget.templateData?["templateData"]?["subject"]}",
|
||||||
);
|
);
|
||||||
setState(() {
|
setState(() async {
|
||||||
// ✅ Wrap in setState to update the UI
|
// ✅ Wrap in setState to update the UI
|
||||||
controllers["templateName"]?.text =
|
controllers["templateName"]?.text =
|
||||||
widget.templateData?["templateData"]?["template_name"] ?? "";
|
widget.templateData?["templateData"]?["template_name"] ?? "";
|
||||||
@ -432,7 +434,7 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
) ??
|
) ??
|
||||||
0;
|
0;
|
||||||
print("Fetched template_id: $templateId");
|
print("Fetched template_id: $templateId");
|
||||||
|
fetchSignature();
|
||||||
// if (widget.group?["international_policy_id"] != null) {
|
// if (widget.group?["international_policy_id"] != null) {
|
||||||
// selectedInternational =
|
// selectedInternational =
|
||||||
// widget.group!["international_policy_id"].toString();
|
// widget.group!["international_policy_id"].toString();
|
||||||
@ -443,6 +445,34 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> fetchSignature() async {
|
||||||
|
final uri = Uri.parse('$apiUrl/api/getForexSignaturePath');
|
||||||
|
final token = await getToken();
|
||||||
|
|
||||||
|
final response = await http.get(
|
||||||
|
uri,
|
||||||
|
headers: {'Authorization': 'Bearer $token'},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
print("ERS - $response");
|
||||||
|
final json = jsonDecode(response.body);
|
||||||
|
|
||||||
|
print("ERSjson - $json");
|
||||||
|
|
||||||
|
String? rawLogoPath = json['url']?.toString();
|
||||||
|
|
||||||
|
if (rawLogoPath != null && rawLogoPath.isNotEmpty) {
|
||||||
|
print("ERSrawLogoPath - $rawLogoPath");
|
||||||
|
setState(() {
|
||||||
|
selectedOrglogo = rawLogoPath;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("❌ Failed to fetch signature: ${response.statusCode}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> handleSubmit() async {
|
Future<void> handleSubmit() async {
|
||||||
Map<String, dynamic> data = TemplateData;
|
Map<String, dynamic> data = TemplateData;
|
||||||
|
|
||||||
@ -492,6 +522,7 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(policyData), // Convert map to JSON
|
body: jsonEncode(policyData), // Convert map to JSON
|
||||||
);
|
);
|
||||||
@ -519,6 +550,70 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _pickImage() async {
|
||||||
|
final picker = ImagePicker();
|
||||||
|
final XFile? pickedFile = await picker.pickImage(
|
||||||
|
source: ImageSource.gallery,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (pickedFile != null && kIsWeb) {
|
||||||
|
try {
|
||||||
|
final bytes = await pickedFile.readAsBytes();
|
||||||
|
print('✅ Image loaded, size: ${bytes.length} bytes');
|
||||||
|
setState(() {
|
||||||
|
_imageBytes = bytes;
|
||||||
|
});
|
||||||
|
await uploadSignature();
|
||||||
|
} catch (e) {
|
||||||
|
print('❌ Error reading image bytes: $e');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print('⚠️ Image picking canceled or not on web.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> uploadSignature() async {
|
||||||
|
if (_imageBytes == null) {
|
||||||
|
print('⚠️ No image selected');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final token = await getToken(); // Fetch token
|
||||||
|
|
||||||
|
if (token == null) {
|
||||||
|
throw Exception('Token not found. Please log in.');
|
||||||
|
}
|
||||||
|
|
||||||
|
final uri = Uri.parse('$apiUrl/api/forex_signature_upload');
|
||||||
|
final request = http.MultipartRequest('POST', uri);
|
||||||
|
|
||||||
|
// Add auth header
|
||||||
|
request.headers['Authorization'] = 'Bearer $token';
|
||||||
|
|
||||||
|
// Add the image as multipart with the key "signature"
|
||||||
|
request.files.add(
|
||||||
|
http.MultipartFile.fromBytes(
|
||||||
|
'signature', // <-- key name
|
||||||
|
_imageBytes!, // <-- image bytes
|
||||||
|
filename: 'signature.png', // <-- filename (can be png/jpg)
|
||||||
|
contentType: MediaType('image', 'png'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await request.send();
|
||||||
|
final respStr = await response.stream.bytesToString();
|
||||||
|
|
||||||
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||||
|
print('✅ Upload successful: $respStr');
|
||||||
|
} else {
|
||||||
|
print('❌ Upload failed (${response.statusCode}): $respStr');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('❌ Error uploading signature: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(
|
return ResponsiveBuilder(
|
||||||
@ -683,56 +778,65 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.8 : null,
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.8 : null,
|
||||||
child: IconTheme(
|
child: IconTheme(
|
||||||
data: IconThemeData(size: 18), // Set icon size here
|
data: IconThemeData(size: 18), // Set icon size here
|
||||||
child: QuillSimpleToolbar(
|
|
||||||
controller: _controller,
|
|
||||||
config: QuillSimpleToolbarConfig(
|
|
||||||
embedButtons: FlutterQuillEmbeds.toolbarButtons(),
|
|
||||||
showClipboardPaste: true,
|
|
||||||
customButtons: [
|
|
||||||
QuillToolbarCustomButtonOptions(
|
|
||||||
icon: const Icon(Icons.add_alarm_rounded),
|
|
||||||
onPressed: () {
|
|
||||||
_controller.document.insert(
|
|
||||||
_controller.selection.extentOffset,
|
|
||||||
TimeStampEmbed(DateTime.now().toString()),
|
|
||||||
);
|
|
||||||
|
|
||||||
_controller.updateSelection(
|
child: Container(
|
||||||
TextSelection.collapsed(
|
color: Color(0xFFFFFEF0),
|
||||||
offset: _controller.selection.extentOffset + 1,
|
width: isDesktop ? MediaQuery.of(context).size.width * 0.8 : null,
|
||||||
),
|
child: IconTheme(
|
||||||
ChangeSource.local,
|
data: IconThemeData(size: 18), // Set icon size here
|
||||||
);
|
child: QuillSimpleToolbar(controller: _controller),
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
buttonOptions: QuillSimpleToolbarButtonOptions(
|
|
||||||
base: QuillToolbarBaseButtonOptions(
|
|
||||||
afterButtonPressed: () {
|
|
||||||
final isDesktop = {
|
|
||||||
TargetPlatform.linux,
|
|
||||||
TargetPlatform.windows,
|
|
||||||
TargetPlatform.macOS,
|
|
||||||
}.contains(defaultTargetPlatform);
|
|
||||||
// if (isDesktop) {
|
|
||||||
// _editorFocusNode.requestFocus();
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
),
|
|
||||||
linkStyle: QuillToolbarLinkStyleButtonOptions(
|
|
||||||
validateLink: (link) {
|
|
||||||
// Treats all links as valid. When launching the URL,
|
|
||||||
// `https://` is prefixed if the link is incomplete (e.g., `google.com` → `https://google.com`)
|
|
||||||
// however this happens only within the editor.
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// child: QuillSimpleToolbar(
|
||||||
|
// controller: _controller,
|
||||||
|
// config: QuillSimpleToolbarConfig(
|
||||||
|
// embedButtons: FlutterQuillEmbeds.toolbarButtons(),
|
||||||
|
// showClipboardPaste: true,
|
||||||
|
// customButtons: [
|
||||||
|
// QuillToolbarCustomButtonOptions(
|
||||||
|
// icon: const Icon(Icons.add_alarm_rounded),
|
||||||
|
// onPressed: () {
|
||||||
|
// _controller.document.insert(
|
||||||
|
// _controller.selection.extentOffset,
|
||||||
|
// TimeStampEmbed(DateTime.now().toString()),
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// _controller.updateSelection(
|
||||||
|
// TextSelection.collapsed(
|
||||||
|
// offset: _controller.selection.extentOffset + 1,
|
||||||
|
// ),
|
||||||
|
// ChangeSource.local,
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// buttonOptions: QuillSimpleToolbarButtonOptions(
|
||||||
|
// base: QuillToolbarBaseButtonOptions(
|
||||||
|
// afterButtonPressed: () {
|
||||||
|
// final isDesktop = {
|
||||||
|
// TargetPlatform.linux,
|
||||||
|
// TargetPlatform.windows,
|
||||||
|
// TargetPlatform.macOS,
|
||||||
|
// }.contains(defaultTargetPlatform);
|
||||||
|
// // if (isDesktop) {
|
||||||
|
// // _editorFocusNode.requestFocus();
|
||||||
|
// // }
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// linkStyle: QuillToolbarLinkStyleButtonOptions(
|
||||||
|
// validateLink: (link) {
|
||||||
|
// // Treats all links as valid. When launching the URL,
|
||||||
|
// // `https://` is prefixed if the link is incomplete (e.g., `google.com` → `https://google.com`)
|
||||||
|
// // however this happens only within the editor.
|
||||||
|
// return true;
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
SizedBox(height: 2),
|
||||||
Container(
|
Container(
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
@ -782,9 +886,10 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
height: MediaQuery.of(context).size.height * 0.45,
|
height: MediaQuery.of(context).size.height * 0.38,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
border: Border.all(color: Color(0xFFD6D5E6), width: 0.5),
|
border: Border.all(color: Color(0xFFD6D5E6), width: 0.5),
|
||||||
@ -799,15 +904,16 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
embedBuilders: [
|
embedBuilders: [
|
||||||
...FlutterQuillEmbeds.editorBuilders(
|
...FlutterQuillEmbeds.editorBuilders(
|
||||||
imageEmbedConfig: QuillEditorImageEmbedConfig(
|
// imageEmbedConfig: QuillEditorImageEmbedConfig(
|
||||||
imageProviderBuilder: (context, imageUrl) {
|
// imageProviderBuilder: (context, imageUrl) {
|
||||||
// https://pub.dev/packages/flutter_quill_extensions#-image-assets
|
// if (imageUrl.startsWith('data:image')) {
|
||||||
if (imageUrl.startsWith('assets/')) {
|
// return MemoryImage(
|
||||||
return AssetImage(imageUrl);
|
// base64Decode(imageUrl.split(',').last),
|
||||||
}
|
// );
|
||||||
return null;
|
// }
|
||||||
},
|
// return null;
|
||||||
),
|
// },
|
||||||
|
// ),
|
||||||
videoEmbedConfig: QuillEditorVideoEmbedConfig(
|
videoEmbedConfig: QuillEditorVideoEmbedConfig(
|
||||||
customVideoBuilder: (videoUrl, readOnly) {
|
customVideoBuilder: (videoUrl, readOnly) {
|
||||||
// To load YouTube videos https://github.com/singerdmx/flutter-quill/releases/tag/v10.8.0
|
// To load YouTube videos https://github.com/singerdmx/flutter-quill/releases/tag/v10.8.0
|
||||||
@ -820,6 +926,58 @@ class TemplateForexState extends State<TemplateForex> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
SizedBox(height: 4),
|
||||||
|
Container(
|
||||||
|
child: Row(
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Upload Signature",
|
||||||
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
|
),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: _pickImage,
|
||||||
|
|
||||||
|
child:
|
||||||
|
_imageBytes != null
|
||||||
|
? ClipOval(
|
||||||
|
child: Image.memory(
|
||||||
|
_imageBytes!,
|
||||||
|
// width: 50,
|
||||||
|
// height: 50,
|
||||||
|
width: 50, // Use responsive width
|
||||||
|
height: 50,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: selectedOrglogo != null
|
||||||
|
? ClipRect(
|
||||||
|
child: Image.network(
|
||||||
|
selectedOrglogo!,
|
||||||
|
width: 50, // Use responsive width
|
||||||
|
height: 50,
|
||||||
|
// width: 250,
|
||||||
|
// height: 55,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
errorBuilder: (context, error, stackTrace) {
|
||||||
|
return const CircleAvatar(
|
||||||
|
radius: 20,
|
||||||
|
backgroundColor: Colors.redAccent,
|
||||||
|
child: Icon(Icons.error, size: 10),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const CircleAvatar(
|
||||||
|
radius: 20,
|
||||||
|
backgroundColor: Colors.amber,
|
||||||
|
child: Icon(Icons.add_a_photo, size: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -178,6 +178,7 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -210,6 +211,7 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
// Use MultipartRequest (POST only)
|
// Use MultipartRequest (POST only)
|
||||||
final request = http.MultipartRequest('POST', uri);
|
final request = http.MultipartRequest('POST', uri);
|
||||||
request.headers['Authorization'] = 'Bearer $token';
|
request.headers['Authorization'] = 'Bearer $token';
|
||||||
|
request.headers['app-signature'] = 'ts-traveltool-2025-signature-123456';
|
||||||
|
|
||||||
// If updating, spoof the method Laravel-style
|
// If updating, spoof the method Laravel-style
|
||||||
|
|
||||||
@ -447,24 +449,22 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Org Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
}
|
},
|
||||||
),
|
|
||||||
BreadcrumbItem(
|
|
||||||
title: 'Templates',
|
|
||||||
),
|
),
|
||||||
|
BreadcrumbItem(title: 'Templates'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
SizedBox(width: MediaQuery.of(context).size.width * 0.13),
|
SizedBox(width: MediaQuery.of(context).size.width * 0.13),
|
||||||
// SizedBox(width: MediaQuery.of(context).size.width * 0.23),
|
|
||||||
|
|
||||||
|
// SizedBox(width: MediaQuery.of(context).size.width * 0.23),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
Container(
|
Container(
|
||||||
width: MediaQuery.of(context).size.width * 0.2,
|
width: MediaQuery.of(context).size.width * 0.2,
|
||||||
@ -597,7 +597,7 @@ class TemplatesListState extends State<TemplatesList> {
|
|||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final adjHgt = MediaQuery.of(context).size.height;
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (futureTemplates == null) {
|
if (futureTemplates == null) {
|
||||||
return CircularProgressIndicator();
|
return const Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
|||||||
@ -50,6 +50,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> getMailData() => mailData;
|
Map<String, dynamic> getMailData() => mailData;
|
||||||
|
|
||||||
Map<String, dynamic> get mailData {
|
Map<String, dynamic> get mailData {
|
||||||
@ -169,6 +170,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(mailData), // Convert map to JSON
|
body: jsonEncode(mailData), // Convert map to JSON
|
||||||
);
|
);
|
||||||
@ -353,7 +355,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if(isDesktop) SizedBox(width:20),
|
if (isDesktop) SizedBox(width: 20),
|
||||||
Column(
|
Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, // ✅ This works
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, // ✅ This works
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -447,9 +449,9 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
isFocused: focusStates["senderEmailFocused"] ?? false,
|
isFocused: focusStates["senderEmailFocused"] ?? false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
width:
|
width:
|
||||||
widget.isDesktop
|
widget.isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.23
|
? MediaQuery.of(context).size.width * 0.23
|
||||||
: MediaQuery.of(context).size.width * 0.85,
|
: MediaQuery.of(context).size.width * 0.85,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -465,8 +467,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
} else if (!RegExp(
|
} else if (!RegExp(
|
||||||
r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
|
r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
|
||||||
).hasMatch(value)) {
|
).hasMatch(value)) {
|
||||||
errorMessages["sender_email"] =
|
errorMessages["sender_email"] = "Invalid email format";
|
||||||
"Invalid email format";
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
style: GoogleFonts.poppins(fontSize: 12),
|
style: GoogleFonts.poppins(fontSize: 12),
|
||||||
@ -492,7 +493,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if(isDesktop) SizedBox(width:20),
|
if (isDesktop) SizedBox(width: 20),
|
||||||
Column(
|
Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, // ✅ This works
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, // ✅ This works
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -545,7 +546,7 @@ class _MailSettingState extends State<MailSetting> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if(isDesktop) SizedBox(width:20),
|
if (isDesktop) SizedBox(width: 20),
|
||||||
Column(
|
Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, // ✅ This works
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, // ✅ This works
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
|||||||
@ -333,6 +333,7 @@ class _OrgSetUpState extends State<OrgSetUp> {
|
|||||||
// Use MultipartRequest (POST only)
|
// Use MultipartRequest (POST only)
|
||||||
final request = http.MultipartRequest('POST', uri);
|
final request = http.MultipartRequest('POST', uri);
|
||||||
request.headers['Authorization'] = 'Bearer $token';
|
request.headers['Authorization'] = 'Bearer $token';
|
||||||
|
request.headers['app-signature'] = 'ts-traveltool-2025-signature-123456';
|
||||||
|
|
||||||
// If updating, spoof the method Laravel-style
|
// If updating, spoof the method Laravel-style
|
||||||
if (isUpdating) {
|
if (isUpdating) {
|
||||||
|
|||||||
@ -130,6 +130,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
}
|
}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
node.addListener(() {
|
node.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -247,7 +248,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postForexData();
|
postForexData();
|
||||||
}else{
|
} else {
|
||||||
isDisable = false;
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -256,7 +257,6 @@ class ForexDataState extends State<ForexData> {
|
|||||||
print("ForexDAta - $forexData1");
|
print("ForexDAta - $forexData1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> postForexData({int isActive = 1}) async {
|
Future<void> postForexData({int isActive = 1}) async {
|
||||||
// final remarksData = getData();
|
// final remarksData = getData();
|
||||||
|
|
||||||
@ -296,6 +296,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
final headers = {
|
final headers = {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
};
|
};
|
||||||
final body = jsonEncode(forexData);
|
final body = jsonEncode(forexData);
|
||||||
|
|
||||||
@ -375,7 +376,7 @@ class ForexDataState extends State<ForexData> {
|
|||||||
countryMap = {
|
countryMap = {
|
||||||
for (var country in countryList)
|
for (var country in countryList)
|
||||||
(country['country_code'] ?? ''):
|
(country['country_code'] ?? ''):
|
||||||
'${country['country_name'] ?? ''} (${country['country_code'] ?? ''})',
|
'${country['country_name'] ?? ''} (${country['country_code'] ?? ''})',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract only country codes for processing
|
// Extract only country codes for processing
|
||||||
@ -435,105 +436,130 @@ class ForexDataState extends State<ForexData> {
|
|||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: Focus(
|
child: Focus(
|
||||||
focusNode: focusNodes["country_codeFocusNode"],
|
focusNode: focusNodes["country_codeFocusNode"],
|
||||||
onFocusChange: (hasFocus) {
|
onFocusChange: (hasFocus) {
|
||||||
setState(() {
|
setState(() {
|
||||||
focusStates["country_codeFocused"] = hasFocus;
|
focusStates["country_codeFocused"] = hasFocus;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// Request focus when user taps
|
// Request focus when user taps
|
||||||
focusNodes["country_codeFocusNode"]?.requestFocus();
|
focusNodes["country_codeFocusNode"]?.requestFocus();
|
||||||
},
|
},
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
selectedItem: countryMap[selectedCountry],
|
selectedItem: countryMap[selectedCountry],
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
showSearchBox: true, // Enables search functionality
|
showSearchBox: true, // Enables search functionality
|
||||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
menuProps: const MenuProps(
|
||||||
constraints: BoxConstraints(maxHeight: 200),
|
backgroundColor: Colors.white,
|
||||||
itemBuilder:
|
),
|
||||||
(context, item, isSelected) {
|
constraints: BoxConstraints(maxHeight: 200),
|
||||||
print("contryItem - $item");
|
itemBuilder: (context, item, isSelected) {
|
||||||
final match = RegExp(r'^(.*)\s\((.*)\)$',).firstMatch(item);
|
print("contryItem - $item");
|
||||||
final countryName = match?.group(1) ?? '';
|
final match = RegExp(
|
||||||
final countryCode = match?.group(2) ?? '';
|
r'^(.*)\s\((.*)\)$',
|
||||||
return Padding(
|
).firstMatch(item);
|
||||||
padding: const EdgeInsets.symmetric(
|
final countryName = match?.group(1) ?? '';
|
||||||
horizontal: 8.0,
|
final countryCode = match?.group(2) ?? '';
|
||||||
vertical: 0.02,
|
return Padding(
|
||||||
),
|
padding: const EdgeInsets.symmetric(
|
||||||
child: Padding(
|
horizontal: 8.0,
|
||||||
padding: const EdgeInsets.all(8.0),
|
vertical: 0.02,
|
||||||
child: Row(
|
),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
child: Padding(
|
||||||
children: [
|
padding: const EdgeInsets.all(8.0),
|
||||||
Text(
|
child: Row(
|
||||||
countryName,
|
mainAxisAlignment:
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
MainAxisAlignment.spaceBetween,
|
||||||
),
|
children: [
|
||||||
Text(
|
Text(
|
||||||
countryCode,
|
countryName,
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5,color:Colors.grey),
|
style: GoogleFonts.poppins(
|
||||||
),
|
fontSize: 11.5,
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
Text(
|
||||||
);},
|
countryCode,
|
||||||
searchFieldProps: TextFieldProps(
|
style: GoogleFonts.poppins(
|
||||||
decoration: InputDecoration(
|
fontSize: 11.5,
|
||||||
hintText: "Search ...",
|
color: Colors.grey,
|
||||||
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
),
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 3,vertical: 3),
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
items: countryMap.values.toList(),
|
},
|
||||||
filterFn: (item, filter) {
|
searchFieldProps: TextFieldProps(
|
||||||
final lowerFilter = filter.toLowerCase();
|
decoration: InputDecoration(
|
||||||
|
hintText: "Search ...",
|
||||||
final match = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(item);
|
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
||||||
final countryName = match?.group(1)?.toLowerCase() ?? '';
|
contentPadding: EdgeInsets.symmetric(
|
||||||
final countryCode = match?.group(2)?.toLowerCase() ?? '';
|
horizontal: 3,
|
||||||
|
vertical: 3,
|
||||||
// Prioritize country code match, fallback to country name
|
|
||||||
return countryCode.contains(lowerFilter) || countryName.contains(lowerFilter);
|
|
||||||
},
|
|
||||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
|
||||||
dropdownSearchDecoration: InputDecoration(
|
|
||||||
// border: InputBorder.none,
|
|
||||||
border: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color:
|
|
||||||
(focusStates["country_codeFocused"] ?? false)
|
|
||||||
? widget.layoutColor!
|
|
||||||
: Colors.white,
|
|
||||||
// width: 0.5,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color:
|
|
||||||
(focusStates["country_codeFocused"] ?? false)
|
|
||||||
? widget.layoutColor!
|
|
||||||
: Colors.white,
|
|
||||||
// : const Color(0xFFD6D5E6),
|
|
||||||
// width: 0.5,
|
|
||||||
// const Color(0xFFD6D5E6),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(color: widget.layoutColor!, width: 1),
|
|
||||||
),
|
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 10.0,
|
|
||||||
vertical: 8.0,),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder:
|
),
|
||||||
(context, selectedItem) => Align(
|
),
|
||||||
|
items: countryMap.values.toList(),
|
||||||
|
filterFn: (item, filter) {
|
||||||
|
final lowerFilter = filter.toLowerCase();
|
||||||
|
|
||||||
|
final match = RegExp(
|
||||||
|
r'^(.*)\s\((.*)\)$',
|
||||||
|
).firstMatch(item);
|
||||||
|
final countryName =
|
||||||
|
match?.group(1)?.toLowerCase() ?? '';
|
||||||
|
final countryCode =
|
||||||
|
match?.group(2)?.toLowerCase() ?? '';
|
||||||
|
|
||||||
|
// Prioritize country code match, fallback to country name
|
||||||
|
return countryCode.contains(lowerFilter) ||
|
||||||
|
countryName.contains(lowerFilter);
|
||||||
|
},
|
||||||
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
|
dropdownSearchDecoration: InputDecoration(
|
||||||
|
// border: InputBorder.none,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["country_codeFocused"] ??
|
||||||
|
false)
|
||||||
|
? widget.layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
// width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color:
|
||||||
|
(focusStates["country_codeFocused"] ??
|
||||||
|
false)
|
||||||
|
? widget.layoutColor!
|
||||||
|
: Colors.white,
|
||||||
|
// : const Color(0xFFD6D5E6),
|
||||||
|
// width: 0.5,
|
||||||
|
// const Color(0xFFD6D5E6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: widget.layoutColor!,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10.0,
|
||||||
|
vertical: 8.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownBuilder:
|
||||||
|
(context, selectedItem) => Align(
|
||||||
// Center-align selected item
|
// Center-align selected item
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -541,100 +567,105 @@ class ForexDataState extends State<ForexData> {
|
|||||||
style: GoogleFonts.poppins(fontSize: 11),
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
// Find the country_code based on selected country_name
|
// Find the country_code based on selected country_name
|
||||||
selectedCountry =
|
selectedCountry =
|
||||||
countryMap.entries
|
countryMap.entries
|
||||||
.firstWhere((entry) => entry.value == newValue)
|
.firstWhere(
|
||||||
.key;
|
(entry) => entry.value == newValue,
|
||||||
final setMatch = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(newValue!);
|
)
|
||||||
final setCountryName = setMatch?.group(1)?.toLowerCase() ?? '';
|
.key;
|
||||||
selectedCountryName = setCountryName;
|
final setMatch = RegExp(
|
||||||
setCurrencyFromSelectedCountry(selectedCountry!);
|
r'^(.*)\s\((.*)\)$',
|
||||||
});
|
).firstMatch(newValue!);
|
||||||
},
|
final setCountryName =
|
||||||
),
|
setMatch?.group(1)?.toLowerCase() ?? '';
|
||||||
// child: DropdownSearch<String>(
|
selectedCountryName = setCountryName;
|
||||||
// selectedItem: countryMap[selectedCountry],
|
setCurrencyFromSelectedCountry(selectedCountry!);
|
||||||
// popupProps: PopupProps.menu(
|
});
|
||||||
// showSearchBox: true, // Enables search functionality
|
},
|
||||||
// menuProps: const MenuProps(backgroundColor: Colors.white),
|
),
|
||||||
// constraints: BoxConstraints(maxHeight: 250),
|
// child: DropdownSearch<String>(
|
||||||
// itemBuilder:
|
// selectedItem: countryMap[selectedCountry],
|
||||||
// (context, item, isSelected) => Padding(
|
// popupProps: PopupProps.menu(
|
||||||
// padding: const EdgeInsets.symmetric(
|
// showSearchBox: true, // Enables search functionality
|
||||||
// horizontal: 10.0,
|
// menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
// vertical: 8.0,
|
// constraints: BoxConstraints(maxHeight: 250),
|
||||||
// ),
|
// itemBuilder:
|
||||||
// child: Text(
|
// (context, item, isSelected) => Padding(
|
||||||
// item,
|
// padding: const EdgeInsets.symmetric(
|
||||||
// style: GoogleFonts.poppins(fontSize: 11.5),
|
// horizontal: 10.0,
|
||||||
// ),
|
// vertical: 8.0,
|
||||||
// ),
|
// ),
|
||||||
// searchFieldProps: TextFieldProps(
|
// child: Text(
|
||||||
// decoration: InputDecoration(
|
// item,
|
||||||
// hintText: "Search ...",
|
// style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
// hintStyle: GoogleFonts.poppins(fontSize: 11),
|
// ),
|
||||||
// contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
// ),
|
||||||
// ),
|
// searchFieldProps: TextFieldProps(
|
||||||
// ),
|
// decoration: InputDecoration(
|
||||||
// ),
|
// hintText: "Search ...",
|
||||||
// items: countryMap.values.toList(),
|
// hintStyle: GoogleFonts.poppins(fontSize: 11),
|
||||||
// dropdownDecoratorProps: DropDownDecoratorProps(
|
// contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||||
// dropdownSearchDecoration: InputDecoration(
|
// ),
|
||||||
// // border: InputBorder.none,
|
// ),
|
||||||
// border: OutlineInputBorder(
|
// ),
|
||||||
// borderRadius: BorderRadius.circular(8),
|
// items: countryMap.values.toList(),
|
||||||
// borderSide: BorderSide(
|
// dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
// color:
|
// dropdownSearchDecoration: InputDecoration(
|
||||||
// (focusStates["country_codeFocused"] ?? false)
|
// // border: InputBorder.none,
|
||||||
// ? widget.layoutColor!
|
// border: OutlineInputBorder(
|
||||||
// : Colors.white,
|
// borderRadius: BorderRadius.circular(8),
|
||||||
// // width: 0.5,
|
// borderSide: BorderSide(
|
||||||
// ),
|
// color:
|
||||||
// ),
|
// (focusStates["country_codeFocused"] ?? false)
|
||||||
// enabledBorder: OutlineInputBorder(
|
// ? widget.layoutColor!
|
||||||
// borderSide: BorderSide(
|
// : Colors.white,
|
||||||
// color:
|
// // width: 0.5,
|
||||||
// (focusStates["country_codeFocused"] ?? false)
|
// ),
|
||||||
// ? widget.layoutColor!
|
// ),
|
||||||
// : Colors.white,
|
// enabledBorder: OutlineInputBorder(
|
||||||
// // : const Color(0xFFD6D5E6),
|
// borderSide: BorderSide(
|
||||||
// // width: 0.5,
|
// color:
|
||||||
// // const Color(0xFFD6D5E6),
|
// (focusStates["country_codeFocused"] ?? false)
|
||||||
// ),
|
// ? widget.layoutColor!
|
||||||
// ),
|
// : Colors.white,
|
||||||
// focusedBorder: OutlineInputBorder(
|
// // : const Color(0xFFD6D5E6),
|
||||||
// borderSide: BorderSide(color: widget.layoutColor!, width: 1),
|
// // width: 0.5,
|
||||||
// ),
|
// // const Color(0xFFD6D5E6),
|
||||||
// contentPadding: EdgeInsets.symmetric(horizontal: 10.0,
|
// ),
|
||||||
// vertical: 8.0,),
|
// ),
|
||||||
// ),
|
// focusedBorder: OutlineInputBorder(
|
||||||
// ),
|
// borderSide: BorderSide(color: widget.layoutColor!, width: 1),
|
||||||
// dropdownBuilder:
|
// ),
|
||||||
// (context, selectedItem) => Align(
|
// contentPadding: EdgeInsets.symmetric(horizontal: 10.0,
|
||||||
// // Center-align selected item
|
// vertical: 8.0,),
|
||||||
// alignment: Alignment.centerLeft,
|
// ),
|
||||||
// child: Text(
|
// ),
|
||||||
// selectedItem ?? "Select ",
|
// dropdownBuilder:
|
||||||
// style: GoogleFonts.poppins(fontSize: 11),
|
// (context, selectedItem) => Align(
|
||||||
// ),
|
// // Center-align selected item
|
||||||
// ),
|
// alignment: Alignment.centerLeft,
|
||||||
// onChanged: (String? newValue) {
|
// child: Text(
|
||||||
// setState(() {
|
// selectedItem ?? "Select ",
|
||||||
// // Find the country_code based on selected country_name
|
// style: GoogleFonts.poppins(fontSize: 11),
|
||||||
// selectedCountry =
|
// ),
|
||||||
// countryMap.entries
|
// ),
|
||||||
// .firstWhere((entry) => entry.value == newValue)
|
// onChanged: (String? newValue) {
|
||||||
// .key;
|
// setState(() {
|
||||||
// selectedCountryName = newValue;
|
// // Find the country_code based on selected country_name
|
||||||
// setCurrencyFromSelectedCountry(selectedCountry!);
|
// selectedCountry =
|
||||||
// });
|
// countryMap.entries
|
||||||
// },
|
// .firstWhere((entry) => entry.value == newValue)
|
||||||
// ),
|
// .key;
|
||||||
)
|
// selectedCountryName = newValue;
|
||||||
)
|
// setCurrencyFromSelectedCountry(selectedCountry!);
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["country_code"] != null) ...[
|
if (errorMessages["country_code"] != null) ...[
|
||||||
@ -913,22 +944,23 @@ class ForexDataState extends State<ForexData> {
|
|||||||
// // You can get text from commentController.text
|
// // You can get text from commentController.text
|
||||||
// // Navigator.of(context).pop(); // Close the modal
|
// // Navigator.of(context).pop(); // Close the modal
|
||||||
// },
|
// },
|
||||||
onPressed: isDisable
|
onPressed:
|
||||||
? null
|
isDisable
|
||||||
: () async {
|
? null
|
||||||
setState(() {
|
: () async {
|
||||||
isDisable = true;
|
setState(() {
|
||||||
});
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
await handleSubmit();
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
// Optional: re-enable only on error
|
// Optional: re-enable only on error
|
||||||
// setState(() {
|
// setState(() {
|
||||||
// isDisable = false;
|
// isDisable = false;
|
||||||
// });
|
// });
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
|
|||||||
@ -168,6 +168,7 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -193,6 +194,7 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -368,9 +370,10 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
return input
|
return input
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.map((word) => word.isNotEmpty
|
.map(
|
||||||
? word[0].toUpperCase() + word.substring(1)
|
(word) =>
|
||||||
: '')
|
word.isNotEmpty ? word[0].toUpperCase() + word.substring(1) : '',
|
||||||
|
)
|
||||||
.join(' ');
|
.join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,15 +467,13 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Org Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
}
|
},
|
||||||
),
|
|
||||||
BreadcrumbItem(
|
|
||||||
title: 'Perdiem Amount Details',
|
|
||||||
),
|
),
|
||||||
|
BreadcrumbItem(title: 'Perdiem Amount Details'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -488,8 +489,8 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
SizedBox(width: MediaQuery.of(context).size.width * 0.1),
|
SizedBox(width: MediaQuery.of(context).size.width * 0.1),
|
||||||
// SizedBox(width: MediaQuery.of(context).size.width * 0.16),
|
|
||||||
|
|
||||||
|
// SizedBox(width: MediaQuery.of(context).size.width * 0.16),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
Container(
|
Container(
|
||||||
width: MediaQuery.of(context).size.width * 0.2,
|
width: MediaQuery.of(context).size.width * 0.2,
|
||||||
@ -634,7 +635,7 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
future: futureForex,
|
future: futureForex,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (futureForex == null) {
|
if (futureForex == null) {
|
||||||
return const CircularProgressIndicator();
|
return const Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
@ -790,7 +791,8 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
),
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
Text(
|
||||||
toTitleCase(forex['country_name']) ?? '',
|
toTitleCase(forex['country_name']) ??
|
||||||
|
'',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
@ -921,7 +923,8 @@ class ForexDataListState extends State<ForexDataList> {
|
|||||||
MainAxisAlignment.spaceBetween,
|
MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
toTitleCase(forex['country_name']) ?? 'N/A',
|
toTitleCase(forex['country_name']) ??
|
||||||
|
'N/A',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: Colors.black87,
|
color: Colors.black87,
|
||||||
|
|||||||
@ -824,6 +824,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -964,6 +965,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1010,6 +1012,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1081,6 +1084,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1139,6 +1143,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1289,6 +1294,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(data),
|
body: jsonEncode(data),
|
||||||
);
|
);
|
||||||
@ -1500,6 +1506,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(planData), // Convert map to JSON
|
body: jsonEncode(planData), // Convert map to JSON
|
||||||
);
|
);
|
||||||
|
|||||||
@ -300,6 +300,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token', // Add token here
|
'Authorization': 'Bearer $token', // Add token here
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -332,6 +333,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(planData), // Convert map to JSON
|
body: jsonEncode(planData), // Convert map to JSON
|
||||||
);
|
);
|
||||||
@ -446,6 +448,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -595,6 +595,7 @@ class _PolicyState extends State<Policy> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(policyData), // Convert map to JSON
|
body: jsonEncode(policyData), // Convert map to JSON
|
||||||
);
|
);
|
||||||
|
|||||||
@ -139,10 +139,12 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
filteredPolicy =
|
filteredPolicy =
|
||||||
allPolicy.where((object) {
|
allPolicy.where((object) {
|
||||||
final isActiveStatus =
|
final isActiveStatus =
|
||||||
object['is_active'] == "1" ? "active" : "inactive";
|
object['is_active'] == "1" ? "active" : "inactive";
|
||||||
return (object['policy_id']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
return (object['policy_id']?.toLowerCase().contains(lowerQuery) ??
|
||||||
|
false) ||
|
||||||
(object['name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
(object['name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
(object['policy_type']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
(object['policy_type']?.toLowerCase().contains(lowerQuery) ??
|
||||||
|
false) ||
|
||||||
(isActiveStatus.contains(lowerQuery));
|
(isActiveStatus.contains(lowerQuery));
|
||||||
}).toList();
|
}).toList();
|
||||||
currentPage = 0;
|
currentPage = 0;
|
||||||
@ -185,6 +187,7 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(policyData), // Convert map to JSON
|
body: jsonEncode(policyData), // Convert map to JSON
|
||||||
);
|
);
|
||||||
@ -339,15 +342,13 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Org Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
}
|
},
|
||||||
),
|
|
||||||
BreadcrumbItem(
|
|
||||||
title: 'Policy',
|
|
||||||
),
|
),
|
||||||
|
BreadcrumbItem(title: 'Policy'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -363,8 +364,8 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
SizedBox(width: MediaQuery.of(context).size.width * 0.145),
|
SizedBox(width: MediaQuery.of(context).size.width * 0.145),
|
||||||
// SizedBox(width: MediaQuery.of(context).size.width * 0.28),
|
|
||||||
|
|
||||||
|
// SizedBox(width: MediaQuery.of(context).size.width * 0.28),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
Container(
|
Container(
|
||||||
width: MediaQuery.of(context).size.width * 0.2,
|
width: MediaQuery.of(context).size.width * 0.2,
|
||||||
@ -1029,32 +1030,34 @@ class _PolicyListState extends State<PolicyList> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child:
|
child:
|
||||||
isDesktop
|
isDesktop
|
||||||
? (searchController.text.isNotEmpty && filteredPolicy.isEmpty
|
? (searchController.text.isNotEmpty &&
|
||||||
? Center(
|
filteredPolicy.isEmpty
|
||||||
child: Text( "No Matches Found",
|
? Center(
|
||||||
style: GoogleFonts.poppins(
|
child: Text(
|
||||||
fontSize: 14,
|
|
||||||
color: Colors.grey,
|
|
||||||
),),
|
|
||||||
)
|
|
||||||
: SingleChildScrollView(
|
|
||||||
scrollDirection: Axis.vertical,
|
|
||||||
child: table,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
: (searchController.text.isNotEmpty && filteredPolicy.isEmpty
|
|
||||||
? Center(
|
|
||||||
child: Text(
|
|
||||||
"No Matches Found",
|
"No Matches Found",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: buildMobileCardView(paginatedUser)
|
: SingleChildScrollView(
|
||||||
),
|
scrollDirection: Axis.vertical,
|
||||||
|
child: table,
|
||||||
|
))
|
||||||
|
: (searchController.text.isNotEmpty &&
|
||||||
|
filteredPolicy.isEmpty
|
||||||
|
? Center(
|
||||||
|
child: Text(
|
||||||
|
"No Matches Found",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: buildMobileCardView(paginatedUser)),
|
||||||
),
|
),
|
||||||
PaginationControls(
|
PaginationControls(
|
||||||
currentPage: currentPage,
|
currentPage: currentPage,
|
||||||
|
|||||||
@ -105,6 +105,7 @@ class PurposeOfTravelDataState extends State<PurposeOfTravelData> {
|
|||||||
}
|
}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
node.addListener(() {
|
node.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -168,7 +169,7 @@ class PurposeOfTravelDataState extends State<PurposeOfTravelData> {
|
|||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postPurposeOfTravelData();
|
postPurposeOfTravelData();
|
||||||
}else{
|
} else {
|
||||||
isDisable = false;
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -212,6 +213,7 @@ class PurposeOfTravelDataState extends State<PurposeOfTravelData> {
|
|||||||
final headers = {
|
final headers = {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
};
|
};
|
||||||
final body = jsonEncode(purposeOfTravelData);
|
final body = jsonEncode(purposeOfTravelData);
|
||||||
|
|
||||||
@ -429,22 +431,23 @@ class PurposeOfTravelDataState extends State<PurposeOfTravelData> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: isDisable
|
onPressed:
|
||||||
? null
|
isDisable
|
||||||
: () async {
|
? null
|
||||||
setState(() {
|
: () async {
|
||||||
isDisable = true;
|
setState(() {
|
||||||
});
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
await handleSubmit();
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
// Optional: re-enable only on error
|
// Optional: re-enable only on error
|
||||||
// setState(() {
|
// setState(() {
|
||||||
// isDisable = false;
|
// isDisable = false;
|
||||||
// });
|
// });
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
|
|||||||
@ -132,7 +132,8 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> fetchGetPurposeOfTravel() async {
|
Future<List<dynamic>> fetchGetPurposeOfTravel() async {
|
||||||
final String apiUrlData = '$apiUrl/api/getPurposeOfTravelList?for=table_view';
|
final String apiUrlData =
|
||||||
|
'$apiUrl/api/getPurposeOfTravelList?for=table_view';
|
||||||
|
|
||||||
final String? token = await getToken();
|
final String? token = await getToken();
|
||||||
|
|
||||||
@ -148,6 +149,7 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
print("called api : $apiUrlData");
|
print("called api : $apiUrlData");
|
||||||
@ -180,11 +182,10 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
allPurposeOfTravel.where((object) {
|
allPurposeOfTravel.where((object) {
|
||||||
final isActiveStatus =
|
final isActiveStatus =
|
||||||
object['is_active'] == "1" ? "active" : "inactive";
|
object['is_active'] == "1" ? "active" : "inactive";
|
||||||
return (object['id']?.toLowerCase().contains(
|
return (object['id']?.toLowerCase().contains(lowerQuery) ??
|
||||||
lowerQuery,
|
false) ||
|
||||||
) ??
|
(object['dropdown_value']?.toLowerCase().contains(lowerQuery) ??
|
||||||
false) ||
|
false) ||
|
||||||
(object['dropdown_value']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
|
||||||
// (object['description']?.toLowerCase().contains(lowerQuery) ??
|
// (object['description']?.toLowerCase().contains(lowerQuery) ??
|
||||||
// false) ||
|
// false) ||
|
||||||
(isActiveStatus.contains(lowerQuery));
|
(isActiveStatus.contains(lowerQuery));
|
||||||
@ -284,15 +285,13 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Org Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
}
|
},
|
||||||
),
|
|
||||||
BreadcrumbItem(
|
|
||||||
title: 'Purpose Of Travel Details',
|
|
||||||
),
|
),
|
||||||
|
BreadcrumbItem(title: 'Purpose Of Travel Details'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -308,8 +307,8 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
SizedBox(width: MediaQuery.of(context).size.width * 0.08),
|
SizedBox(width: MediaQuery.of(context).size.width * 0.08),
|
||||||
// SizedBox(width: MediaQuery.of(context).size.width * 0.16),
|
|
||||||
|
|
||||||
|
// SizedBox(width: MediaQuery.of(context).size.width * 0.16),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
Container(
|
Container(
|
||||||
width: MediaQuery.of(context).size.width * 0.2,
|
width: MediaQuery.of(context).size.width * 0.2,
|
||||||
@ -583,10 +582,10 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
rows:
|
rows:
|
||||||
paginatedPurposeOfTravel.map((tableObject) {
|
paginatedPurposeOfTravel.map((tableObject) {
|
||||||
String purposeOfTravelId =
|
String purposeOfTravelId =
|
||||||
tableObject['id']
|
tableObject['id'].toString(); // Get user ID
|
||||||
.toString(); // Get user ID
|
|
||||||
bool isSelected =
|
bool isSelected =
|
||||||
selectedPurposeOfTravelId == purposeOfTravelId;
|
selectedPurposeOfTravelId ==
|
||||||
|
purposeOfTravelId;
|
||||||
|
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
@ -635,7 +634,8 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
// ),
|
// ),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
message: 'Edit Purpose Of Travel Details',
|
message:
|
||||||
|
'Edit Purpose Of Travel Details',
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
'assets/images/IconsImg/edit.png',
|
'assets/images/IconsImg/edit.png',
|
||||||
width: 20,
|
width: 20,
|
||||||
@ -646,10 +646,10 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
// final userId = getUserId(user['user_id']);
|
// final userId = getUserId(user['user_id']);
|
||||||
// final usersData = await getUserDetails(userId);
|
// final usersData = await getUserDetails(userId);
|
||||||
//
|
//
|
||||||
final purposeOfTravelId = int.tryParse(
|
final purposeOfTravelId =
|
||||||
tableObject['id']
|
int.tryParse(
|
||||||
.toString(),
|
tableObject['id'].toString(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (purposeOfTravelId != null) {
|
if (purposeOfTravelId != null) {
|
||||||
print(
|
print(
|
||||||
@ -664,7 +664,9 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder:
|
builder:
|
||||||
(context) => PurposeOfTravelData(
|
(
|
||||||
|
context,
|
||||||
|
) => PurposeOfTravelData(
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
purposeOfTravelId:
|
purposeOfTravelId:
|
||||||
purposeOfTravelId, // Pass the ID
|
purposeOfTravelId, // Pass the ID
|
||||||
@ -728,7 +730,8 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
|
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
message: 'Edit Purpose Of Travel Details',
|
message:
|
||||||
|
'Edit Purpose Of Travel Details',
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
'assets/images/IconsImg/edit.png',
|
'assets/images/IconsImg/edit.png',
|
||||||
width: 20,
|
width: 20,
|
||||||
@ -740,8 +743,7 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
// final usersData = await getUserDetails(userId);
|
// final usersData = await getUserDetails(userId);
|
||||||
//
|
//
|
||||||
final purposeOfTravelId = int.tryParse(
|
final purposeOfTravelId = int.tryParse(
|
||||||
cardObject['id']
|
cardObject['id'].toString(),
|
||||||
.toString(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (purposeOfTravelId != null) {
|
if (purposeOfTravelId != null) {
|
||||||
@ -757,7 +759,9 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
|
|||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder:
|
builder:
|
||||||
(context) => PurposeOfTravelData(
|
(
|
||||||
|
context,
|
||||||
|
) => PurposeOfTravelData(
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
purposeOfTravelId:
|
purposeOfTravelId:
|
||||||
purposeOfTravelId, // Pass the ID
|
purposeOfTravelId, // Pass the ID
|
||||||
|
|||||||
@ -106,6 +106,7 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
}
|
}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
node.addListener(() {
|
node.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -188,7 +189,7 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
// This triggers UI rebuild with error messages
|
// This triggers UI rebuild with error messages
|
||||||
if (validateData()) {
|
if (validateData()) {
|
||||||
postTravellerData();
|
postTravellerData();
|
||||||
}else{
|
} else {
|
||||||
isDisable = false;
|
isDisable = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -235,6 +236,7 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
final headers = {
|
final headers = {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
};
|
};
|
||||||
final body = jsonEncode(travellerData);
|
final body = jsonEncode(travellerData);
|
||||||
|
|
||||||
@ -550,22 +552,23 @@ class TravellerDataState extends State<TravellerData> {
|
|||||||
// ),
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: isDisable
|
onPressed:
|
||||||
? null
|
isDisable
|
||||||
: () async {
|
? null
|
||||||
setState(() {
|
: () async {
|
||||||
isDisable = true;
|
setState(() {
|
||||||
});
|
isDisable = true;
|
||||||
|
});
|
||||||
|
|
||||||
await handleSubmit();
|
await handleSubmit();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
// Navigator.of(context).pop(); // Close the modal
|
// Navigator.of(context).pop(); // Close the modal
|
||||||
|
|
||||||
// Optional: re-enable only on error
|
// Optional: re-enable only on error
|
||||||
// setState(() {
|
// setState(() {
|
||||||
// isDisable = false;
|
// isDisable = false;
|
||||||
// });
|
// });
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColor,
|
backgroundColor: widget.layoutColor,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
|
|||||||
@ -151,6 +151,7 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
print("called api : $apiUrlData");
|
print("called api : $apiUrlData");
|
||||||
@ -294,15 +295,13 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
breadcrumbItems: [
|
breadcrumbItems: [
|
||||||
BreadcrumbItem(
|
BreadcrumbItem(
|
||||||
title: 'Org Settings',
|
title: 'Org Settings',
|
||||||
tooltip: 'Go To Organization Settings',
|
tooltip: 'Go To Organization Settings',
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
context.go("/OrganizationSettings");
|
context.go("/OrganizationSettings");
|
||||||
}
|
},
|
||||||
),
|
|
||||||
BreadcrumbItem(
|
|
||||||
title: 'Traveller Details',
|
|
||||||
),
|
),
|
||||||
|
BreadcrumbItem(title: 'Traveller Details'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -318,8 +317,8 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
SizedBox(width: MediaQuery.of(context).size.width * 0.10),
|
SizedBox(width: MediaQuery.of(context).size.width * 0.10),
|
||||||
// SizedBox(width: MediaQuery.of(context).size.width * 0.16),
|
|
||||||
|
|
||||||
|
// SizedBox(width: MediaQuery.of(context).size.width * 0.16),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
Container(
|
Container(
|
||||||
width: MediaQuery.of(context).size.width * 0.2,
|
width: MediaQuery.of(context).size.width * 0.2,
|
||||||
@ -466,7 +465,7 @@ class TravellerListState extends State<TravellerList> {
|
|||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final adjHgt = MediaQuery.of(context).size.height;
|
final adjHgt = MediaQuery.of(context).size.height;
|
||||||
if (futureTraveller == null) {
|
if (futureTraveller == null) {
|
||||||
return CircularProgressIndicator();
|
return const Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
|||||||
@ -990,6 +990,7 @@ class _CreateTravelAgentFormDetialsState
|
|||||||
// Use MultipartRequest (POST only)
|
// Use MultipartRequest (POST only)
|
||||||
final request = http.MultipartRequest('POST', uri);
|
final request = http.MultipartRequest('POST', uri);
|
||||||
request.headers['Authorization'] = 'Bearer $token';
|
request.headers['Authorization'] = 'Bearer $token';
|
||||||
|
request.headers['app-signature'] = 'ts-traveltool-2025-signature-123456';
|
||||||
|
|
||||||
// If updating, spoof the method Laravel-style
|
// If updating, spoof the method Laravel-style
|
||||||
if (isUpdating) {
|
if (isUpdating) {
|
||||||
|
|||||||
@ -12,43 +12,35 @@ import '../../../services/apiService.dart';
|
|||||||
import '../../../utils/auth_utils.dart';
|
import '../../../utils/auth_utils.dart';
|
||||||
import '../../../widgets/custom_user_form.dart';
|
import '../../../widgets/custom_user_form.dart';
|
||||||
|
|
||||||
|
|
||||||
class ChangePasswordDialogData extends StatefulWidget {
|
class ChangePasswordDialogData extends StatefulWidget {
|
||||||
|
|
||||||
final dynamic isDesktop;
|
final dynamic isDesktop;
|
||||||
final dynamic layoutColor;
|
final dynamic layoutColor;
|
||||||
final dynamic updaterUserId;
|
final dynamic updaterUserId;
|
||||||
final dynamic updaterEmail;
|
final dynamic updaterEmail;
|
||||||
|
|
||||||
const ChangePasswordDialogData({
|
const ChangePasswordDialogData({
|
||||||
super.key,
|
super.key,
|
||||||
this.isDesktop,
|
this.isDesktop,
|
||||||
this.layoutColor,
|
this.layoutColor,
|
||||||
this.updaterUserId,
|
this.updaterUserId,
|
||||||
this.updaterEmail
|
this.updaterEmail,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
@override
|
ChangePasswordDialogDataState createState() =>
|
||||||
ChangePasswordDialogDataState createState() => ChangePasswordDialogDataState();
|
ChangePasswordDialogDataState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
||||||
|
|
||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
|
|
||||||
final Map<String, TextEditingController> controllers = {};
|
final Map<String, TextEditingController> controllers = {};
|
||||||
Map<String, String> errorMessages = {};
|
Map<String, String> errorMessages = {};
|
||||||
|
|
||||||
|
|
||||||
String? loggeduserId;
|
String? loggeduserId;
|
||||||
String? updaterUserIdForAPI;
|
String? updaterUserIdForAPI;
|
||||||
|
|
||||||
List<String> dataHeader = [
|
List<String> dataHeader = ["email", "changePassword", "confirmPassword"];
|
||||||
"email",
|
|
||||||
"changePassword",
|
|
||||||
"confirmPassword"
|
|
||||||
];
|
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
// void initState() {
|
// void initState() {
|
||||||
@ -75,15 +67,13 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
controllers['email']?.text = widget.updaterEmail ;
|
controllers['email']?.text = widget.updaterEmail;
|
||||||
controllers['changePassword']?.text = '';
|
controllers['changePassword']?.text = '';
|
||||||
controllers['confirmPassword']?.text = '';
|
controllers['confirmPassword']?.text = '';
|
||||||
updaterUserIdForAPI = widget.updaterUserId;
|
updaterUserIdForAPI = widget.updaterUserId;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void _clearError() {
|
void _clearError() {
|
||||||
setState(() {
|
setState(() {
|
||||||
errorMessages.clear();
|
errorMessages.clear();
|
||||||
@ -98,40 +88,37 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool validateData() {
|
bool validateData() {
|
||||||
errorMessages.clear();
|
errorMessages.clear();
|
||||||
|
|
||||||
final String? email = controllers["email"]?.text;
|
final String? email = controllers["email"]?.text;
|
||||||
final String? changePassword = controllers["changePassword"]?.text;
|
final String? changePassword = controllers["changePassword"]?.text;
|
||||||
final String? confirmPassword = controllers["confirmPassword"]?.text;
|
final String? confirmPassword = controllers["confirmPassword"]?.text;
|
||||||
|
|
||||||
// Required fields check
|
// Required fields check
|
||||||
if (email == null || email.trim().isEmpty) {
|
if (email == null || email.trim().isEmpty) {
|
||||||
errorMessages["email"] = "Required";
|
errorMessages["email"] = "Required";
|
||||||
}
|
|
||||||
|
|
||||||
if (changePassword == null || changePassword.trim().isEmpty) {
|
|
||||||
errorMessages["changePassword"] = "Required";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (confirmPassword == null || confirmPassword.trim().isEmpty) {
|
|
||||||
errorMessages["confirmPassword"] = "Required";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Password match check
|
|
||||||
if ((changePassword?.isNotEmpty ?? false) &&
|
|
||||||
(confirmPassword?.isNotEmpty ?? false) &&
|
|
||||||
changePassword != confirmPassword) {
|
|
||||||
errorMessages["changePassword"] = "Passwords do not match";
|
|
||||||
errorMessages["confirmPassword"] = "Passwords do not match";
|
|
||||||
}
|
|
||||||
|
|
||||||
// setState(() {}); // Update UI with any error messages
|
|
||||||
return errorMessages.isEmpty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changePassword == null || changePassword.trim().isEmpty) {
|
||||||
|
errorMessages["changePassword"] = "Required";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (confirmPassword == null || confirmPassword.trim().isEmpty) {
|
||||||
|
errorMessages["confirmPassword"] = "Required";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Password match check
|
||||||
|
if ((changePassword?.isNotEmpty ?? false) &&
|
||||||
|
(confirmPassword?.isNotEmpty ?? false) &&
|
||||||
|
changePassword != confirmPassword) {
|
||||||
|
errorMessages["changePassword"] = "Passwords do not match";
|
||||||
|
errorMessages["confirmPassword"] = "Passwords do not match";
|
||||||
|
}
|
||||||
|
|
||||||
|
// setState(() {}); // Update UI with any error messages
|
||||||
|
return errorMessages.isEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> handleSubmit() async {
|
Future<void> handleSubmit() async {
|
||||||
loggeduserId = await getUserId();
|
loggeduserId = await getUserId();
|
||||||
@ -142,7 +129,6 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
postData();
|
postData();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> postData() async {
|
Future<void> postData() async {
|
||||||
@ -152,12 +138,14 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
|
|
||||||
final password = controllers["changePassword"]?.text ?? '';
|
final password = controllers["changePassword"]?.text ?? '';
|
||||||
final confirmPassword = controllers["confirmPassword"]?.text ?? '';
|
final confirmPassword = controllers["confirmPassword"]?.text ?? '';
|
||||||
final String apiUrldata = '$apiUrl/api/user/user-password/$updaterUserIdForAPI';
|
final String apiUrldata =
|
||||||
|
'$apiUrl/api/user/user-password/$updaterUserIdForAPI';
|
||||||
|
|
||||||
final token = await getToken();
|
final token = await getToken();
|
||||||
final headers = {
|
final headers = {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -165,6 +153,7 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
final headers = {
|
final headers = {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
};
|
};
|
||||||
final body = jsonEncode({
|
final body = jsonEncode({
|
||||||
"password": password,
|
"password": password,
|
||||||
@ -200,7 +189,6 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30),
|
contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30),
|
||||||
@ -220,10 +208,7 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Divider(
|
Divider(thickness: 0.2, color: Colors.blueGrey.shade100),
|
||||||
thickness: 0.2,
|
|
||||||
color: Colors.blueGrey.shade100,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
@ -232,9 +217,10 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
Text(
|
Text(
|
||||||
"Email",
|
"Email",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
@ -245,18 +231,19 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
// ? MediaQuery.of(context).size.width * 0.330
|
// ? MediaQuery.of(context).size.width * 0.330
|
||||||
// : MediaQuery.of(context).size.width * 0.66,
|
// : MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: controllers["email"],
|
controller: controllers["email"],
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Email",
|
labelText: "Email",
|
||||||
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["email"] != null) ...[
|
if (errorMessages["email"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -267,18 +254,17 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 10),
|
||||||
height: 10,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Change Password",
|
"Change Password",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
@ -286,18 +272,19 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: controllers["changePassword"],
|
controller: controllers["changePassword"],
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Change Password",
|
labelText: "Change Password",
|
||||||
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["changePassword"] != null) ...[
|
if (errorMessages["changePassword"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -308,18 +295,17 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 15),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Confirm Password",
|
"Confirm Password",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldUserWrapper(
|
CustomTextFieldUserWrapper(
|
||||||
@ -327,18 +313,19 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: controllers["confirmPassword"],
|
controller: controllers["confirmPassword"],
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Confirm Password",
|
labelText: "Confirm Password",
|
||||||
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (errorMessages["confirmPassword"] != null) ...[
|
if (errorMessages["confirmPassword"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
@ -349,10 +336,8 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 15),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
@ -367,17 +352,20 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text('Save',
|
child: Text(
|
||||||
style: GoogleFonts.poppins(
|
'Save',
|
||||||
fontSize: 11, color: Colors.white)),
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 11,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
// : SizedBox.shrink(),
|
// : SizedBox.shrink(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1259,6 +1259,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
// Use MultipartRequest (POST only)
|
// Use MultipartRequest (POST only)
|
||||||
final request = http.MultipartRequest('POST', uri);
|
final request = http.MultipartRequest('POST', uri);
|
||||||
request.headers['Authorization'] = 'Bearer $token';
|
request.headers['Authorization'] = 'Bearer $token';
|
||||||
|
request.headers['app-signature'] = 'ts-traveltool-2025-signature-123456';
|
||||||
|
|
||||||
// If updating, spoof the method Laravel-style
|
// If updating, spoof the method Laravel-style
|
||||||
if (isUpdating) {
|
if (isUpdating) {
|
||||||
|
|||||||
@ -161,6 +161,7 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -186,6 +187,7 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -587,6 +589,9 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
// Attach the file to the request
|
// Attach the file to the request
|
||||||
// Set authorization token in headers
|
// Set authorization token in headers
|
||||||
request.headers['Authorization'] = 'Bearer $token';
|
request.headers['Authorization'] = 'Bearer $token';
|
||||||
|
request.headers['app-signature'] =
|
||||||
|
'ts-traveltool-2025-signature-123456';
|
||||||
|
|
||||||
// request.files.add(http.MultipartFile.fromBytes('file', fileBytes, filename: fileName));
|
// request.files.add(http.MultipartFile.fromBytes('file', fileBytes, filename: fileName));
|
||||||
|
|
||||||
request.files.add(
|
request.files.add(
|
||||||
@ -718,6 +723,7 @@ class _UserListScreenState extends State<UserListScreen> {
|
|||||||
// Use MultipartRequest (POST only)
|
// Use MultipartRequest (POST only)
|
||||||
final request = http.MultipartRequest('POST', uri);
|
final request = http.MultipartRequest('POST', uri);
|
||||||
request.headers['Authorization'] = 'Bearer $token';
|
request.headers['Authorization'] = 'Bearer $token';
|
||||||
|
request.headers['app-signature'] = 'ts-traveltool-2025-signature-123456';
|
||||||
|
|
||||||
// If updating, spoof the method Laravel-style
|
// If updating, spoof the method Laravel-style
|
||||||
|
|
||||||
|
|||||||
@ -34,8 +34,8 @@ class _MyAppState extends State<MyApp> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
SemanticsBinding.instance
|
// SemanticsBinding.instance
|
||||||
.ensureSemantics(); // -only for testing uncomment, Otherwise Email Template wont allow to type
|
// .ensureSemantics(); // -only for testing uncomment, Otherwise Email Template wont allow to type
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
final uri = Uri.parse(html.window.location.href);
|
final uri = Uri.parse(html.window.location.href);
|
||||||
print("URI - $uri");
|
print("URI - $uri");
|
||||||
@ -87,7 +87,7 @@ class _MyAppState extends State<MyApp> {
|
|||||||
print("handleTokenUsingMS- $authCode");
|
print("handleTokenUsingMS- $authCode");
|
||||||
try {
|
try {
|
||||||
// final url = 'http://localhost:43627/tstat/auth/verifyMSAuthUser?code=$authCode';
|
// final url = 'http://localhost:43627/tstat/auth/verifyMSAuthUser?code=$authCode';
|
||||||
final url = '$apiUrl/auth/verifyMSAuthUser?code=$authCode';
|
final url = '$apiUrl/api/auth/verifyMSAuthUser?code=$authCode';
|
||||||
print("Microsoft BE URL - $url");
|
print("Microsoft BE URL - $url");
|
||||||
final response = await http.get(
|
final response = await http.get(
|
||||||
Uri.parse(url),
|
Uri.parse(url),
|
||||||
|
|||||||
@ -44,6 +44,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -80,6 +81,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -116,6 +118,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -156,6 +159,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -185,6 +189,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -240,6 +245,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -291,6 +297,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -330,6 +337,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -367,6 +375,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -404,6 +413,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -441,6 +451,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -476,6 +487,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -518,6 +530,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -559,6 +572,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token', // Add token here
|
'Authorization': 'Bearer $token', // Add token here
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -583,6 +597,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token', // Add token here
|
'Authorization': 'Bearer $token', // Add token here
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -664,6 +679,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -710,6 +726,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
// 'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -747,6 +764,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
// 'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -786,6 +804,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
// 'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -850,6 +869,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
// 'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -915,6 +935,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
// 'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -965,6 +986,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1010,6 +1032,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1054,6 +1077,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1100,6 +1124,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1146,6 +1171,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1200,6 +1226,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1346,6 +1373,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1392,6 +1420,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1438,6 +1467,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1480,6 +1510,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1534,6 +1565,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
@ -1573,6 +1605,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: body,
|
body: body,
|
||||||
);
|
);
|
||||||
@ -1616,6 +1649,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: body,
|
body: body,
|
||||||
);
|
);
|
||||||
@ -1673,6 +1707,7 @@ class ApiService {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -122,6 +122,7 @@ class CommentModalState extends State<CommentModal> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -143,7 +144,8 @@ class CommentModalState extends State<CommentModal> {
|
|||||||
print("Res1 - $data");
|
print("Res1 - $data");
|
||||||
if (!data.containsKey('data') || data['data'] is! Map) {
|
if (!data.containsKey('data') || data['data'] is! Map) {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
"Invalid response format: 'data' field is missing or not a Map");
|
"Invalid response format: 'data' field is missing or not a Map",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return data['data'];
|
return data['data'];
|
||||||
} else {
|
} else {
|
||||||
@ -186,6 +188,7 @@ class CommentModalState extends State<CommentModal> {
|
|||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer $token',
|
'Authorization': 'Bearer $token',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
||||||
},
|
},
|
||||||
body: jsonEncode(remarksData), // Convert map to JSON
|
body: jsonEncode(remarksData), // Convert map to JSON
|
||||||
);
|
);
|
||||||
@ -255,7 +258,8 @@ class CommentModalState extends State<CommentModal> {
|
|||||||
icon: const Icon(Icons.delete, size: 20),
|
icon: const Icon(Icons.delete, size: 20),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await postRemarksData(
|
await postRemarksData(
|
||||||
isActive: 0); // Marks the remark as deleted
|
isActive: 0,
|
||||||
|
); // Marks the remark as deleted
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -280,27 +284,30 @@ class CommentModalState extends State<CommentModal> {
|
|||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
// Row 3: OK button
|
// Row 3: OK button
|
||||||
|
|
||||||
editRemarks
|
editRemarks
|
||||||
? SizedBox(
|
? SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
postRemarksData();
|
postRemarksData();
|
||||||
// You can get text from commentController.text
|
// You can get text from commentController.text
|
||||||
Navigator.of(context).pop(); // Close the modal
|
Navigator.of(context).pop(); // Close the modal
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: widget.layoutColorForUser,
|
backgroundColor: widget.layoutColorForUser,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: Text('OK',
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 13, color: Colors.white)),
|
|
||||||
),
|
),
|
||||||
)
|
child: Text(
|
||||||
|
'OK',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 13,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
: SizedBox.shrink(),
|
: SizedBox.shrink(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -609,10 +609,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: mime
|
name: mime
|
||||||
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "1.0.6"
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user