APP-SIGNATURE

This commit is contained in:
venbaittech 2025-08-20 17:45:27 +05:30
parent d29caf66c5
commit f7342a14b4
39 changed files with 1371 additions and 981 deletions

View File

@ -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',
}, },
); );

View File

@ -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
@ -121,23 +120,33 @@ class _CommentModalListState extends State<CommentModalList> {
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:
comments.map((comment) {
final name = comment['created_by_name'] ?? 'Unknown'; final name = comment['created_by_name'] ?? 'Unknown';
final remark = comment['remarks'] ?? ''; final remark = comment['remarks'] ?? '';
final rawDateStr = comment['updated_on']; final rawDateStr = comment['updated_on'];
@ -146,36 +155,48 @@ class _CommentModalListState extends State<CommentModalList> {
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',
).format(parsedDate); // e.g., 15 May 2025
} catch (e) { } catch (e) {
updatedOn = rawDateStr.split(' ').first; // fallback updatedOn = rawDateStr.split(' ').first; // fallback
} }
} }
return DataRow(cells: [ return DataRow(
DataCell(Text( cells: [
DataCell(
Text(
name, name,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
color: Colors.black, color: Colors.black,
fontWeight: FontWeight.w500), fontWeight: FontWeight.w500,
)), ),
DataCell(Text( ),
),
DataCell(
Text(
remark, remark,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
color: Colors.black, color: Colors.black,
fontWeight: FontWeight.w500), fontWeight: FontWeight.w500,
)), ),
DataCell(Text( ),
),
DataCell(
Text(
updatedOn, updatedOn,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
color: Colors.black, color: Colors.black,
fontWeight: FontWeight.w500), fontWeight: FontWeight.w500,
)), ),
]); ),
),
],
);
}).toList(), }).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(
'Close',
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: widget.layoutColorForUser)), color: widget.layoutColorForUser,
),
),
), ),
], ],
); );

View File

@ -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
); );

View File

@ -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',
}, },
); );

View File

@ -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) {

View File

@ -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,7 +428,8 @@ class CostCenterDataState extends State<CostCenterData> {
// ), // ),
SizedBox( SizedBox(
child: ElevatedButton( child: ElevatedButton(
onPressed: isDisable onPressed:
isDisable
? null ? null
: () async { : () async {
setState(() { setState(() {

View File

@ -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");
@ -290,11 +291,9 @@ class CostCenterListState extends State<CostCenterList> {
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) {

View File

@ -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',
}, },
); );

View File

@ -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,7 +430,8 @@ class DepartmentDataState extends State<DepartmentData> {
// ), // ),
SizedBox( SizedBox(
child: ElevatedButton( child: ElevatedButton(
onPressed: isDisable onPressed:
isDisable
? null ? null
: () async { : () async {
setState(() { setState(() {

View File

@ -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));
@ -289,11 +289,9 @@ class DepartmentListState extends State<DepartmentList> {
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) {

View File

@ -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,8 +212,13 @@ 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
.where(
(user) =>
user.userId.toString() != excludedUserId &&
user.roleId.toString() != "5",
)
.map((user) => {"type": "user", "data": user}) .map((user) => {"type": "user", "data": user})
.toList(); .toList();
@ -277,7 +283,8 @@ 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 =
_traveller
.map((traveller) => {"type": "traveller", "data": traveller}) .map((traveller) => {"type": "traveller", "data": traveller})
.toList(); .toList();
// _filteredList = [ // _filteredList = [
@ -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(
@ -507,16 +516,29 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
final userType = final userType =
item["type"]; // "user" or "traveller" item["type"]; // "user" or "traveller"
if (user is Map<String, dynamic>) { if (user is Map<String, dynamic>) {
print("userLsirer - ${jsonEncode(user)}"); // pretty JSON-like string print(
"userLsirer - ${jsonEncode(user)}",
); // pretty JSON-like string
} else { } else {
print("userLsirer - $user"); // fallback print("userLsirer - $user"); // fallback
} }
final isSelected = userIdSelected == (userType == "user" ? user.userId : user.travellerId); final isSelected =
userIdSelected ==
(userType == "user"
? user.userId
: user.travellerId);
return ListTile( return ListTile(
// hoverColor: , // hoverColor: ,
title: Text( title: Text(
"${user.firstName ?? "Unknown"}" "${(user.lastName?.isNotEmpty ?? false) ? " ${user.lastName}" : ""}", "${user.firstName ?? "Unknown"}"
style: GoogleFonts.poppins(fontSize: 11 , color: isSelected ? widget.layoutColorForUser : Colors.black), "${(user.lastName?.isNotEmpty ?? false) ? " ${user.lastName}" : ""}",
style: GoogleFonts.poppins(
fontSize: 11,
color:
isSelected
? widget.layoutColorForUser
: Colors.black,
),
), ),
subtitle: subtitle:
userType == "user" userType == "user"
@ -525,7 +547,10 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
// "Employee ID: ${userType == "user" ? user.userId : user.travellerId}", // "Employee ID: ${userType == "user" ? user.userId : user.travellerId}",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 10, fontSize: 10,
color: isSelected ? widget.layoutColorForUser : Colors.black, color:
isSelected
? widget.layoutColorForUser
: Colors.black,
), ),
) )
: Text( : Text(
@ -533,7 +558,10 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
// "Employee ID: ${userType == "user" ? user.userId : user.travellerId}", // "Employee ID: ${userType == "user" ? user.userId : user.travellerId}",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 10, fontSize: 10,
color: isSelected ? widget.layoutColorForUser : Colors.black, color:
isSelected
? widget.layoutColorForUser
: Colors.black,
), ),
), ),
onTap: () { onTap: () {
@ -616,20 +644,26 @@ 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
? () {
print(
"Submitting: ${_searchController.text}, ID: $userIdSelected",
);
widget.onSubmit( widget.onSubmit(
_searchController.text, _searchController.text,
userIdSelected, userIdSelected,
@ -638,10 +672,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
Navigator.pop(context); Navigator.pop(context);
} }
: null, : null,
child: Text( child: Text("Save", style: GoogleFonts.poppins(fontSize: 11)),
"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),
); );

View File

@ -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),
)); ));

View File

@ -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(() {
@ -533,7 +538,8 @@ 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"] ??
false)
? widget.layoutColor! ? widget.layoutColor!
: Colors.white, : Colors.white,
// width: 0.5, // width: 0.5,
@ -542,7 +548,8 @@ class GroupDataState extends State<GroupData> {
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(focusStates["domestic_policy_nameFocused"] ?? false) (focusStates["domestic_policy_nameFocused"] ??
false)
? widget.layoutColor! ? widget.layoutColor!
: Colors.white, : Colors.white,
// : const Color(0xFFD6D5E6), // : const Color(0xFFD6D5E6),
@ -551,10 +558,15 @@ class GroupDataState extends State<GroupData> {
), ),
), ),
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),
), ),
), ),
@ -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,7 +689,8 @@ 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"] ??
false)
? widget.layoutColor! ? widget.layoutColor!
: Colors.white, : Colors.white,
width: 0.5, width: 0.5,
@ -682,7 +699,8 @@ class GroupDataState extends State<GroupData> {
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(focusStates["international_policy_nameFocused"] ?? false) (focusStates["international_policy_nameFocused"] ??
false)
? widget.layoutColor! ? widget.layoutColor!
: Colors.white, : Colors.white,
// : const Color(0xFFD6D5E6), // : const Color(0xFFD6D5E6),
@ -691,10 +709,15 @@ class GroupDataState extends State<GroupData> {
), ),
), ),
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,7 +856,8 @@ 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:
isDisable
? null ? null
: () async { : () async {
setState(() { setState(() {

View File

@ -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
@ -308,14 +309,13 @@ class _GroupListState extends State<GroupList> {
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(

View File

@ -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
@ -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(
@ -506,12 +507,15 @@ class HotelsDataState extends State<HotelsData> {
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(
backgroundColor: Colors.white,
),
constraints: BoxConstraints(maxHeight: 200), constraints: BoxConstraints(maxHeight: 200),
itemBuilder: itemBuilder: (context, item, isSelected) {
(context, item, isSelected) {
print("contryItem - $item"); print("contryItem - $item");
final match = RegExp(r'^(.*)\s\((.*)\)$',).firstMatch(item); final match = RegExp(
r'^(.*)\s\((.*)\)$',
).firstMatch(item);
final countryName = match?.group(1) ?? ''; final countryName = match?.group(1) ?? '';
final countryCode = match?.group(2) ?? ''; final countryCode = match?.group(2) ?? '';
return Padding( return Padding(
@ -522,26 +526,35 @@ class HotelsDataState extends State<HotelsData> {
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
countryName, countryName,
style: GoogleFonts.poppins(fontSize: 11.5), style: GoogleFonts.poppins(
fontSize: 11.5,
),
), ),
Text( Text(
countryCode, countryCode,
style: GoogleFonts.poppins(fontSize: 11.5,color:Colors.grey), style: GoogleFonts.poppins(
fontSize: 11.5,
color: Colors.grey,
),
), ),
], ],
), ),
), ),
);}, );
},
searchFieldProps: TextFieldProps( searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search ...", hintText: "Search ...",
hintStyle: GoogleFonts.poppins(fontSize: 11), hintStyle: GoogleFonts.poppins(fontSize: 11),
contentPadding: EdgeInsets.symmetric(horizontal: 1,vertical: 1), contentPadding: EdgeInsets.symmetric(
horizontal: 1,
vertical: 1,
),
), ),
), ),
), ),
@ -553,7 +566,8 @@ class HotelsDataState extends State<HotelsData> {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(focusStates["country_codeFocused"] ?? false) (focusStates["country_codeFocused"] ??
false)
? widget.layoutColor! ? widget.layoutColor!
: Colors.white, : Colors.white,
// width: 0.5, // width: 0.5,
@ -562,7 +576,8 @@ class HotelsDataState extends State<HotelsData> {
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(focusStates["country_codeFocused"] ?? false) (focusStates["country_codeFocused"] ??
false)
? widget.layoutColor! ? widget.layoutColor!
: Colors.white, : Colors.white,
// : const Color(0xFFD6D5E6), // : const Color(0xFFD6D5E6),
@ -571,10 +586,15 @@ class HotelsDataState extends State<HotelsData> {
), ),
), ),
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,),
), ),
), ),
dropdownBuilder: dropdownBuilder:
@ -591,17 +611,23 @@ class HotelsDataState extends State<HotelsData> {
// 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(
(entry) => entry.value == newValue,
)
.key; .key;
final match = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(newValue!); final match = RegExp(
final countryName = match?.group(1) ?? newValue; // --> "Ascension Islands" r'^(.*)\s\((.*)\)$',
).firstMatch(newValue!);
final countryName =
match?.group(1) ??
newValue; // --> "Ascension Islands"
// final countryCode = match?.group(2) ?? ""; // final countryCode = match?.group(2) ?? "";
selectedCountryName = countryName; selectedCountryName = countryName;
}); });
}, },
), ),
) ),
) ),
), ),
), ),
if (errorMessages["country_code"] != null) ...[ if (errorMessages["country_code"] != null) ...[
@ -712,7 +738,8 @@ class HotelsDataState extends State<HotelsData> {
// ), // ),
SizedBox( SizedBox(
child: ElevatedButton( child: ElevatedButton(
onPressed: isDisable onPressed:
isDisable
? null ? null
: () async { : () async {
setState(() { setState(() {

View File

@ -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',
}, },
); );
@ -342,11 +344,9 @@ class HotelsDataListState extends State<HotelsDataList> {
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) {

View File

@ -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
); );

View File

@ -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),
),
),
],
),
),
], ],
); );
} }

View File

@ -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
@ -451,11 +453,9 @@ class TemplatesListState extends State<TemplatesList> {
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'),
], ],
), ),
), ),
@ -463,8 +463,8 @@ class TemplatesListState extends State<TemplatesList> {
), ),
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());

View File

@ -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,
@ -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,

View File

@ -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) {

View File

@ -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);
@ -452,12 +453,15 @@ class ForexDataState extends State<ForexData> {
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(
backgroundColor: Colors.white,
),
constraints: BoxConstraints(maxHeight: 200), constraints: BoxConstraints(maxHeight: 200),
itemBuilder: itemBuilder: (context, item, isSelected) {
(context, item, isSelected) {
print("contryItem - $item"); print("contryItem - $item");
final match = RegExp(r'^(.*)\s\((.*)\)$',).firstMatch(item); final match = RegExp(
r'^(.*)\s\((.*)\)$',
).firstMatch(item);
final countryName = match?.group(1) ?? ''; final countryName = match?.group(1) ?? '';
final countryCode = match?.group(2) ?? ''; final countryCode = match?.group(2) ?? '';
return Padding( return Padding(
@ -468,25 +472,35 @@ class ForexDataState extends State<ForexData> {
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
countryName, countryName,
style: GoogleFonts.poppins(fontSize: 11.5), style: GoogleFonts.poppins(
fontSize: 11.5,
),
), ),
Text( Text(
countryCode, countryCode,
style: GoogleFonts.poppins(fontSize: 11.5,color:Colors.grey), style: GoogleFonts.poppins(
fontSize: 11.5,
color: Colors.grey,
),
), ),
], ],
), ),
), ),
);}, );
},
searchFieldProps: TextFieldProps( searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search ...", hintText: "Search ...",
hintStyle: GoogleFonts.poppins(fontSize: 11), hintStyle: GoogleFonts.poppins(fontSize: 11),
contentPadding: EdgeInsets.symmetric(horizontal: 3,vertical: 3), contentPadding: EdgeInsets.symmetric(
horizontal: 3,
vertical: 3,
),
), ),
), ),
), ),
@ -494,12 +508,17 @@ class ForexDataState extends State<ForexData> {
filterFn: (item, filter) { filterFn: (item, filter) {
final lowerFilter = filter.toLowerCase(); final lowerFilter = filter.toLowerCase();
final match = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(item); final match = RegExp(
final countryName = match?.group(1)?.toLowerCase() ?? ''; r'^(.*)\s\((.*)\)$',
final countryCode = match?.group(2)?.toLowerCase() ?? ''; ).firstMatch(item);
final countryName =
match?.group(1)?.toLowerCase() ?? '';
final countryCode =
match?.group(2)?.toLowerCase() ?? '';
// Prioritize country code match, fallback to country name // Prioritize country code match, fallback to country name
return countryCode.contains(lowerFilter) || countryName.contains(lowerFilter); return countryCode.contains(lowerFilter) ||
countryName.contains(lowerFilter);
}, },
dropdownDecoratorProps: DropDownDecoratorProps( dropdownDecoratorProps: DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration( dropdownSearchDecoration: InputDecoration(
@ -508,7 +527,8 @@ class ForexDataState extends State<ForexData> {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(focusStates["country_codeFocused"] ?? false) (focusStates["country_codeFocused"] ??
false)
? widget.layoutColor! ? widget.layoutColor!
: Colors.white, : Colors.white,
// width: 0.5, // width: 0.5,
@ -517,7 +537,8 @@ class ForexDataState extends State<ForexData> {
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(focusStates["country_codeFocused"] ?? false) (focusStates["country_codeFocused"] ??
false)
? widget.layoutColor! ? widget.layoutColor!
: Colors.white, : Colors.white,
// : const Color(0xFFD6D5E6), // : const Color(0xFFD6D5E6),
@ -526,10 +547,15 @@ class ForexDataState extends State<ForexData> {
), ),
), ),
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,),
), ),
), ),
dropdownBuilder: dropdownBuilder:
@ -546,10 +572,15 @@ class ForexDataState extends State<ForexData> {
// 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(
(entry) => entry.value == newValue,
)
.key; .key;
final setMatch = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(newValue!); final setMatch = RegExp(
final setCountryName = setMatch?.group(1)?.toLowerCase() ?? ''; r'^(.*)\s\((.*)\)$',
).firstMatch(newValue!);
final setCountryName =
setMatch?.group(1)?.toLowerCase() ?? '';
selectedCountryName = setCountryName; selectedCountryName = setCountryName;
setCurrencyFromSelectedCountry(selectedCountry!); setCurrencyFromSelectedCountry(selectedCountry!);
}); });
@ -633,8 +664,8 @@ class ForexDataState extends State<ForexData> {
// }); // });
// }, // },
// ), // ),
) ),
) ),
), ),
), ),
if (errorMessages["country_code"] != null) ...[ if (errorMessages["country_code"] != null) ...[
@ -913,7 +944,8 @@ 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:
isDisable
? null ? null
: () async { : () async {
setState(() { setState(() {

View File

@ -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(' ');
} }
@ -468,11 +471,9 @@ class ForexDataListState extends State<ForexDataList> {
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,

View File

@ -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
); );

View File

@ -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',
}, },
); );

View File

@ -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
); );

View File

@ -140,9 +140,11 @@ class _PolicyListState extends State<PolicyList> {
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
); );
@ -343,11 +346,9 @@ class _PolicyListState extends State<PolicyList> {
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,
@ -1030,20 +1031,8 @@ class _PolicyListState extends State<PolicyList> {
Expanded( Expanded(
child: child:
isDesktop isDesktop
? (searchController.text.isNotEmpty && filteredPolicy.isEmpty ? (searchController.text.isNotEmpty &&
? Center( filteredPolicy.isEmpty
child: Text( "No Matches Found",
style: GoogleFonts.poppins(
fontSize: 14,
color: Colors.grey,
),),
)
: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: table,
)
)
: (searchController.text.isNotEmpty && filteredPolicy.isEmpty
? Center( ? Center(
child: Text( child: Text(
"No Matches Found", "No Matches Found",
@ -1053,9 +1042,23 @@ class _PolicyListState extends State<PolicyList> {
), ),
), ),
) )
: 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,
itemsPerPage: itemsPerPage, itemsPerPage: itemsPerPage,

View File

@ -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,7 +431,8 @@ class PurposeOfTravelDataState extends State<PurposeOfTravelData> {
// ), // ),
SizedBox( SizedBox(
child: ElevatedButton( child: ElevatedButton(
onPressed: isDisable onPressed:
isDisable
? null ? null
: () async { : () async {
setState(() { setState(() {

View File

@ -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));
@ -288,11 +289,9 @@ class PurposeOfTravelListState extends State<PurposeOfTravelList> {
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,9 +646,9 @@ 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) {
@ -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

View File

@ -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,7 +552,8 @@ class TravellerDataState extends State<TravellerData> {
// ), // ),
SizedBox( SizedBox(
child: ElevatedButton( child: ElevatedButton(
onPressed: isDisable onPressed:
isDisable
? null ? null
: () async { : () async {
setState(() { setState(() {

View File

@ -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");
@ -298,11 +299,9 @@ class TravellerListState extends State<TravellerList> {
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) {

View File

@ -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) {

View File

@ -12,9 +12,7 @@ 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;
@ -25,30 +23,24 @@ class ChangePasswordDialogData extends StatefulWidget {
this.isDesktop, this.isDesktop,
this.layoutColor, this.layoutColor,
this.updaterUserId, this.updaterUserId,
this.updaterEmail this.updaterEmail,
}); });
@override @override
ChangePasswordDialogDataState createState() => ChangePasswordDialogDataState(); ChangePasswordDialogDataState createState() =>
} 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,8 +88,6 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
super.dispose(); super.dispose();
} }
bool validateData() { bool validateData() {
errorMessages.clear(); errorMessages.clear();
@ -132,7 +120,6 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
return errorMessages.isEmpty; 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(
@ -234,7 +219,8 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
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(
@ -256,7 +242,8 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
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,9 +254,7 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
], ],
], ],
), ),
SizedBox( SizedBox(height: 10),
height: 10,
),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -278,7 +263,8 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
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(
@ -297,7 +283,8 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
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,9 +295,7 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
], ],
], ],
), ),
SizedBox( SizedBox(height: 15),
height: 15,
),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -319,7 +304,8 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
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(
@ -338,7 +324,8 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
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,9 +336,7 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
], ],
], ],
), ),
SizedBox( SizedBox(height: 15),
height: 15,
),
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
@ -367,17 +352,20 @@ class ChangePasswordDialogDataState extends State<ChangePasswordDialogData> {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
), ),
child: Text('Save', child: Text(
'Save',
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 11, color: Colors.white)), fontSize: 11,
color: Colors.white,
),
),
), ),
), ),
], ],
) ),
// : SizedBox.shrink(), // : SizedBox.shrink(),
], ],
), ),
); );
} }
} }

View File

@ -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) {

View File

@ -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

View File

@ -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),

View File

@ -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',
}, },
); );

View File

@ -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,7 +284,6 @@ 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,
@ -296,9 +299,13 @@ class CommentModalState extends State<CommentModal> {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
), ),
child: Text('OK', child: Text(
'OK',
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 13, color: Colors.white)), fontSize: 13,
color: Colors.white,
),
),
), ),
) )
: SizedBox.shrink(), : SizedBox.shrink(),

View File

@ -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: