Forex List
This commit is contained in:
parent
cafa8cbc95
commit
d85209139f
@ -567,8 +567,12 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
||||
|
||||
// List<Plan> plans = snapshot.data!;
|
||||
|
||||
// List<Plan> plans =
|
||||
// filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
||||
|
||||
List<Plan> plans =
|
||||
filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
||||
searchController.text.isEmpty ? allPlans : filteredPlans;
|
||||
|
||||
plans.sort((a, b) =>
|
||||
int.parse(b.planId).compareTo(int.parse(a.planId)));
|
||||
|
||||
@ -654,7 +658,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
||||
),
|
||||
softWrap: true,
|
||||
overflow: TextOverflow.ellipsis)),
|
||||
DataCell(Text(plan.employeeCode ?? "no data",
|
||||
DataCell(Text(plan.employeeCode ?? " - ",
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontFamily: "Inter",
|
||||
@ -968,11 +972,36 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: isDesktop
|
||||
? SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: table, // <-- your existing table
|
||||
)
|
||||
: buildMobileCardView(paginatedPlans),
|
||||
? (searchController.text.isNotEmpty &&
|
||||
filteredPlans.isEmpty
|
||||
? Center(
|
||||
child: Text(
|
||||
"No matches found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
)
|
||||
: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: table,
|
||||
))
|
||||
: (searchController.text.isNotEmpty &&
|
||||
filteredPlans.isEmpty
|
||||
? Center(
|
||||
child: Text(
|
||||
"No matches found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
)
|
||||
: buildMobileCardView(paginatedPlans)),
|
||||
|
||||
// child: isDesktop
|
||||
// ? SingleChildScrollView(
|
||||
// scrollDirection: Axis.vertical,
|
||||
// child: table, // <-- your existing table
|
||||
// )
|
||||
// : buildMobileCardView(paginatedPlans),
|
||||
),
|
||||
PaginationControls(
|
||||
currentPage: currentPage,
|
||||
|
||||
@ -498,8 +498,12 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
||||
|
||||
// List<Plan> plans = snapshot.data!;
|
||||
|
||||
// List<Plan> plans =
|
||||
// filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
||||
|
||||
List<Plan> plans =
|
||||
filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
||||
searchController.text.isEmpty ? allPlans : filteredPlans;
|
||||
|
||||
plans.sort((a, b) =>
|
||||
int.parse(b.planId).compareTo(int.parse(a.planId)));
|
||||
|
||||
@ -587,7 +591,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
||||
softWrap: true,
|
||||
overflow: TextOverflow.ellipsis)),
|
||||
|
||||
DataCell(Text(plan.employeeCode ?? "no data",
|
||||
DataCell(Text(plan.employeeCode ?? " - ",
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontFamily: "Inter",
|
||||
@ -702,29 +706,33 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
||||
plan.planId);
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.comment,
|
||||
color: Color(0xFF475569),
|
||||
size: 11,
|
||||
),
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) =>
|
||||
CommentModal(
|
||||
// planId: plan.planId,
|
||||
planId: plan
|
||||
.planId
|
||||
.toString(),
|
||||
layoutColorForUser:
|
||||
layoutColor!,
|
||||
role:
|
||||
"Travel Agent"),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.comment,
|
||||
color: Color(0xFF475569),
|
||||
size: 11,
|
||||
),
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => CommentModal(
|
||||
// planId: plan.planId,
|
||||
planId: plan.planId.toString(),
|
||||
layoutColorForUser:
|
||||
layoutColor!,
|
||||
role: "Travel Agent"),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -821,23 +829,6 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
||||
apiService: apiService,
|
||||
layoutColor: layoutColor,
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.comment,
|
||||
color: Color(0xFF475569),
|
||||
size: 11,
|
||||
),
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => CommentModal(
|
||||
// planId: plan.planId,
|
||||
planId: plan.planId.toString(),
|
||||
layoutColorForUser:
|
||||
layoutColor!,
|
||||
role: "Travel Agent"),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
|
||||
@ -942,11 +933,36 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: isDesktop
|
||||
? SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: table, // <-- your existing table
|
||||
)
|
||||
: buildMobileCardView(paginatedPlans),
|
||||
? (searchController.text.isNotEmpty &&
|
||||
filteredPlans.isEmpty
|
||||
? Center(
|
||||
child: Text(
|
||||
"No matches found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
)
|
||||
: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: table,
|
||||
))
|
||||
: (searchController.text.isNotEmpty &&
|
||||
filteredPlans.isEmpty
|
||||
? Center(
|
||||
child: Text(
|
||||
"No matches found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
)
|
||||
: buildMobileCardView(paginatedPlans)),
|
||||
|
||||
// child: isDesktop
|
||||
// ? SingleChildScrollView(
|
||||
// scrollDirection: Axis.vertical,
|
||||
// child: table, // <-- your existing table
|
||||
// )
|
||||
// : buildMobileCardView(paginatedPlans),
|
||||
),
|
||||
PaginationControls(
|
||||
currentPage: currentPage,
|
||||
|
||||
@ -529,8 +529,15 @@ class _ApprovalListState extends State<ApprovalList> {
|
||||
);
|
||||
}
|
||||
|
||||
// List<Plan> plans =
|
||||
// filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
||||
|
||||
// List<Plan> plans =
|
||||
// searchController.text.isEmpty ? allPlans : filteredPlans;
|
||||
|
||||
List<Plan> plans =
|
||||
filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
||||
searchController.text.isEmpty ? allPlans : filteredPlans;
|
||||
|
||||
plans.sort((a, b) =>
|
||||
int.parse(b.planId).compareTo(int.parse(a.planId)));
|
||||
|
||||
@ -619,7 +626,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
||||
),
|
||||
softWrap: true,
|
||||
overflow: TextOverflow.ellipsis)),
|
||||
DataCell(Text(plan.employeeCode ?? "no data",
|
||||
DataCell(Text(plan.employeeCode ?? " - ",
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontFamily: "Inter",
|
||||
@ -1066,11 +1073,36 @@ class _ApprovalListState extends State<ApprovalList> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: isDesktop
|
||||
? SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: table, // <-- your existing table
|
||||
)
|
||||
: buildMobileCardView(paginatedPlans),
|
||||
? (searchController.text.isNotEmpty &&
|
||||
filteredPlans.isEmpty
|
||||
? Center(
|
||||
child: Text(
|
||||
"No matches found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
)
|
||||
: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: table,
|
||||
))
|
||||
: (searchController.text.isNotEmpty &&
|
||||
filteredPlans.isEmpty
|
||||
? Center(
|
||||
child: Text(
|
||||
"No matches found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
)
|
||||
: buildMobileCardView(paginatedPlans)),
|
||||
|
||||
// child: isDesktop
|
||||
// ? SingleChildScrollView(
|
||||
// scrollDirection: Axis.vertical,
|
||||
// child: table, // <-- your existing table
|
||||
// )
|
||||
// : buildMobileCardView(paginatedPlans),
|
||||
),
|
||||
PaginationControls(
|
||||
currentPage: currentPage,
|
||||
|
||||
@ -365,7 +365,7 @@ class _LoginWidgetState extends State<LoginWidget> {
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
"Welcome To TravelSpends",
|
||||
"Welcome To Trip Approval Tools",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w400,
|
||||
|
||||
@ -96,7 +96,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
||||
|
||||
print("Users fetched: ${_users.length}");
|
||||
for (var user in _users) {
|
||||
print("${user.firstName} ${user.lastName}");
|
||||
print("${user.firstName} ${user.lastName} ${user.empCode}");
|
||||
}
|
||||
} else {
|
||||
throw Exception(
|
||||
@ -146,7 +146,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
||||
|
||||
print("Users fetched: ${_users.length}");
|
||||
for (var travvelr in _traveller) {
|
||||
print("${travvelr.firstName} ${travvelr.lastName}");
|
||||
print(
|
||||
"${travvelr.firstName} ${travvelr.lastName} ${travvelr.mobileNo}");
|
||||
}
|
||||
} else {
|
||||
throw Exception(
|
||||
@ -200,6 +201,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
||||
} else {
|
||||
_filteredList = [
|
||||
..._users.where((user) {
|
||||
print("usersLLL : ${user}");
|
||||
|
||||
List<String> searchFields = [
|
||||
"${user.firstName} ${user.lastName}".toLowerCase(),
|
||||
user.email.toLowerCase() ?? "",
|
||||
@ -222,6 +225,39 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
||||
}
|
||||
}
|
||||
|
||||
void _filterTravellers(String query) {
|
||||
print("Filtering _filterUsersTravellers...");
|
||||
setState(() {
|
||||
_filteredList.clear(); // Reset the list before filtering
|
||||
|
||||
if (query.isEmpty) {
|
||||
_filteredList = [
|
||||
..._users.map((user) => {"type": "user", "data": user}),
|
||||
];
|
||||
} else {
|
||||
_filteredList = [
|
||||
..._traveller.where((traveller) {
|
||||
List<String> searchFields = [
|
||||
"${traveller.firstName} ${traveller.lastName}".toLowerCase(),
|
||||
traveller.email.toLowerCase() ?? "",
|
||||
traveller.travellerId.toLowerCase() ?? "",
|
||||
traveller.mobileNo ?? "",
|
||||
];
|
||||
return searchFields
|
||||
.any((field) => field.contains(query.toLowerCase()));
|
||||
}).map((traveller) => {"type": "traveller", "data": traveller}),
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
print("Filtered List:");
|
||||
for (var item in _filteredList) {
|
||||
var user = item["data"];
|
||||
print(
|
||||
"${item["type"].toUpperCase()} - ${user.firstName} ${user.lastName}");
|
||||
}
|
||||
}
|
||||
|
||||
void _filterUsersTravellers(String query) {
|
||||
print("Filtering _filterUsersTravellers...");
|
||||
setState(() {
|
||||
@ -287,8 +323,11 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
||||
mainAxisSize:
|
||||
MainAxisSize.min, // Ensures content doesn't expand unnecessarily
|
||||
children: [
|
||||
Text("Please Select User",
|
||||
style: GoogleFonts.poppins(fontSize: 14)),
|
||||
widget.title == "Others"
|
||||
? Text("Please Select Other User",
|
||||
style: GoogleFonts.poppins(fontSize: 14))
|
||||
: Text("Please Select Other Employee",
|
||||
style: GoogleFonts.poppins(fontSize: 14)),
|
||||
SizedBox(height: 10),
|
||||
|
||||
// Search Field
|
||||
@ -299,7 +338,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
||||
_showTravellerForm = false;
|
||||
});
|
||||
widget.title == "Others"
|
||||
? _filterUsersTravellers(query)
|
||||
? _filterTravellers(query)
|
||||
: _filterUsers(query);
|
||||
},
|
||||
style: GoogleFonts.poppins(fontSize: 12),
|
||||
@ -370,14 +409,30 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
||||
final user = item["data"]; // Extract user object
|
||||
final userType =
|
||||
item["type"]; // "user" or "traveller"
|
||||
|
||||
if (user is Map<String, dynamic>) {
|
||||
print(
|
||||
"userLsirer - ${jsonEncode(user)}"); // pretty JSON-like string
|
||||
} else {
|
||||
print("userLsirer - $user"); // fallback
|
||||
}
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"${user.firstName ?? "Unknown"} ${user.lastName ?? ""}",
|
||||
style: GoogleFonts.poppins(fontSize: 11),
|
||||
),
|
||||
// subtitle: Text(
|
||||
// "ID: ${userType == "user" ? user.userId : user.travellerId}"),
|
||||
subtitle: userType == "user"
|
||||
? Text(
|
||||
"Employee ID: ${user.empCode ?? ""} ",
|
||||
// "Employee ID: ${userType == "user" ? user.userId : user.travellerId}",
|
||||
style:
|
||||
GoogleFonts.poppins(fontSize: 10),
|
||||
)
|
||||
: Text(
|
||||
"Mobile : ${user.mobileNo ?? ""} ",
|
||||
// "Employee ID: ${userType == "user" ? user.userId : user.travellerId}",
|
||||
style:
|
||||
GoogleFonts.poppins(fontSize: 10),
|
||||
),
|
||||
onTap: () {
|
||||
String selectedUser =
|
||||
"${user.firstName ?? "Unknown"} ${user.lastName ?? ""}";
|
||||
@ -642,7 +697,8 @@ class _TravelerFormState extends State<TravelerForm> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text("Create Traveler", style: TextStyle(color: Colors.black54)),
|
||||
Text("Create Traveler",
|
||||
style: GoogleFonts.poppins(color: Colors.black54)),
|
||||
SizedBox(height: 7),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
@ -664,7 +720,7 @@ class _TravelerFormState extends State<TravelerForm> {
|
||||
TextButton(
|
||||
onPressed: () => _onSubmit(context),
|
||||
child: Text("Add",
|
||||
style: GoogleFonts.poppins(color: Colors.blueAccent)),
|
||||
style: GoogleFonts.poppins(color: Color(0xFF114D8B))),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
262
lib/Screens/forex/forexDetails.dart
Normal file
262
lib/Screens/forex/forexDetails.dart
Normal file
@ -0,0 +1,262 @@
|
||||
import 'package:dropdown_search/dropdown_search.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../../widgets/custom_text_forex.dart';
|
||||
|
||||
class ForexData extends StatefulWidget {
|
||||
final bool isDesktop;
|
||||
final Color? layoutColor;
|
||||
const ForexData({super.key, required this.isDesktop, this.layoutColor});
|
||||
|
||||
@override
|
||||
ForexDataState createState() => ForexDataState();
|
||||
}
|
||||
|
||||
class ForexDataState extends State<ForexData> {
|
||||
List<dynamic> countryList = [];
|
||||
String? selectedCountry;
|
||||
String? selectedCurrency;
|
||||
String? selectedDuration;
|
||||
String? selectedPerdiemAmount;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
late Map<String, String> countryMap; // Mapping country_code -> country_name
|
||||
late List<String> countryCodes; // List of country codes
|
||||
|
||||
countryList = [];
|
||||
// countryList = widget.apiCountryData ?? [];
|
||||
|
||||
// Map country codes to country names
|
||||
countryMap = {
|
||||
for (var item in countryList)
|
||||
item['country_code'] as String: item['country_name'] as String
|
||||
};
|
||||
|
||||
// Extract only country codes for processing
|
||||
countryCodes = countryMap.keys.toList();
|
||||
|
||||
selectedCountry ??= null;
|
||||
|
||||
return AlertDialog(
|
||||
backgroundColor: Colors.white,
|
||||
contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30),
|
||||
// contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 10),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// Row 1: Title + Edit + Delete buttons
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'Create Forex Details',
|
||||
style: GoogleFonts.poppins(fontSize: 18, color: Colors.black),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Country",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF575A74)),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isDesktop: widget.isDesktop,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: DropdownSearch<String>(
|
||||
selectedItem: countryMap[selectedCountry],
|
||||
popupProps: PopupProps.menu(
|
||||
showSearchBox: true, // Enables search functionality
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search Country...",
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||
),
|
||||
),
|
||||
),
|
||||
items: countryMap.values.toList(),
|
||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||
dropdownSearchDecoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
dropdownBuilder: (context, selectedItem) => Align(
|
||||
// Center-align selected item
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
selectedItem ?? "Select Country",
|
||||
style: TextStyle(fontSize: 12),
|
||||
),
|
||||
),
|
||||
onChanged: (String? newValue) {
|
||||
setState(() {
|
||||
// Find the country_code based on selected country_name
|
||||
selectedCountry = countryMap.entries
|
||||
.firstWhere((entry) => entry.value == newValue)
|
||||
.key;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
// if (errorMessages["country_code"] != null) ...[
|
||||
// SizedBox(height: 5), // Space before error message
|
||||
// Text(
|
||||
// "Select Country",
|
||||
// style: TextStyle(color: Colors.red, fontSize: 12),
|
||||
// ),
|
||||
// ],
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Currency *",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF575A74)),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
// width: isDesktop
|
||||
// ? MediaQuery.of(context).size.width * 0.330
|
||||
// : MediaQuery.of(context).size.width * 0.66,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Center(
|
||||
child: Text(
|
||||
// "cur",
|
||||
// "${selectedCurrency}",
|
||||
selectedCurrency ?? "Currency",
|
||||
// selectedCurrency?.isNotEmpty == true ? selectedCurrency! : "Currency",
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF575A74)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// if (isDesktop)SizedBox(width: 8,) else SizedBox(height: 8,),
|
||||
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Perdiem Amount",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF575A74)),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 35,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
// "amo",
|
||||
selectedPerdiemAmount ?? "Amount",
|
||||
// selectedPerdiemAmount?.isNotEmpty == true ? selectedPerdiemAmount! : "Amount",
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF575A74)),
|
||||
// decoration: const InputDecoration(
|
||||
// labelText: "To",
|
||||
// labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||
// floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
// border: InputBorder.none,
|
||||
// contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||
// ),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
// SizedBox(
|
||||
// child: ElevatedButton(
|
||||
// onPressed: () {
|
||||
// // You can get text from commentController.text
|
||||
// Navigator.of(context).pop(); // Close the modal
|
||||
// },
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: widget.layoutColor,
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// ),
|
||||
// ),
|
||||
// child: Text('Cancel',
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: 13, color: Colors.white)),
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: 10,
|
||||
// ),
|
||||
SizedBox(
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
// You can get text from commentController.text
|
||||
Navigator.of(context).pop(); // Close the modal
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: widget.layoutColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Text('Submit',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 11, color: Colors.white)),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
// : SizedBox.shrink(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
1062
lib/Screens/forex/forex_list.dart
Normal file
1062
lib/Screens/forex/forex_list.dart
Normal file
File diff suppressed because it is too large
Load Diff
@ -513,6 +513,40 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
print("FlightData - $flightsData");
|
||||
}
|
||||
|
||||
void validateTimeDifference(int index) {
|
||||
if (index <= 1) return; // Skip validation for the first row
|
||||
|
||||
String? prevDateStr = textControllers["_date${index - 1}Controller"]?.text;
|
||||
String? prevTimeStr = textControllers["_time${index - 1}Controller"]?.text;
|
||||
String? currDateStr = textControllers["_date${index}Controller"]?.text;
|
||||
String? currTimeStr = textControllers["_time${index}Controller"]?.text;
|
||||
|
||||
if (prevDateStr != null &&
|
||||
prevDateStr.isNotEmpty &&
|
||||
prevTimeStr != null &&
|
||||
prevTimeStr.isNotEmpty &&
|
||||
currDateStr != null &&
|
||||
currDateStr.isNotEmpty &&
|
||||
currTimeStr != null &&
|
||||
currTimeStr.isNotEmpty) {
|
||||
try {
|
||||
final prevDateTime = DateTime.parse("$prevDateStr $prevTimeStr");
|
||||
final currDateTime = DateTime.parse("$currDateStr $currTimeStr");
|
||||
|
||||
if (!currDateTime.isAfter(prevDateTime)) {
|
||||
errorMessages["time_$index"] = "Must be after previous time";
|
||||
} else if (currDateTime.difference(prevDateTime).inMinutes < 30) {
|
||||
errorMessages["time_$index"] =
|
||||
"Must be least 30 mins after previous time";
|
||||
} else {
|
||||
errorMessages.remove("time_$index");
|
||||
}
|
||||
} catch (e) {
|
||||
errorMessages["time_$index"] = "Invalid time format";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool validateFields() {
|
||||
errorMessages.clear(); // Reset errors
|
||||
|
||||
@ -1124,7 +1158,8 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _selectCheckOutTime(BuildContext context) async {
|
||||
Future<void> _selectCheckOutTime(
|
||||
BuildContext context, int index, VoidCallback onPicked) async {
|
||||
TimeOfDay? pickedTime = await showTimePicker(
|
||||
context: context,
|
||||
initialTime: _selectedCheckOutTime ?? TimeOfDay.now(),
|
||||
@ -1141,6 +1176,8 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
);
|
||||
// _timeController.text = formattedTime;
|
||||
textControllers["_time${index}Controller"]?.text = formattedTime;
|
||||
|
||||
onPicked();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1485,12 +1522,23 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: GestureDetector(
|
||||
onTap: () => _selectCheckOutTime(context),
|
||||
onTap: () {
|
||||
_clearError("time_$index");
|
||||
// validateTimeDifference(index);
|
||||
// _selectCheckOutTime(context);
|
||||
|
||||
_selectCheckOutTime(context, index, () {
|
||||
validateTimeDifference(index);
|
||||
setState(
|
||||
() {}); // ✅ Force rebuild to show the error immediately
|
||||
});
|
||||
},
|
||||
child: AbsorbPointer(
|
||||
child: TextField(
|
||||
focusNode: focusNodes["_time${index}FocusNode"],
|
||||
// controller: _timeController,
|
||||
controller: textControllers["_time${index}Controller"],
|
||||
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Time",
|
||||
@ -1509,7 +1557,7 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
if (errorMessages["time_$index"] != null) ...[
|
||||
SizedBox(height: 5), // Space before error message
|
||||
Text(
|
||||
"Required",
|
||||
errorMessages["time_$index"]!,
|
||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||
),
|
||||
],
|
||||
|
||||
@ -375,6 +375,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
late bool isApproverApproved = false;
|
||||
late bool isApproverRejected = false;
|
||||
|
||||
String? temporaryMessage;
|
||||
|
||||
//Getter Method
|
||||
Map<String, dynamic> get planData => {
|
||||
"org_id": orgId,
|
||||
@ -990,7 +992,20 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
bool anyServiceSelected =
|
||||
serviceLists.any((list) => list != null && list.isNotEmpty);
|
||||
if (!anyServiceSelected) {
|
||||
validationErrors["services"] = "Please select at least one service";
|
||||
// validationErrors["services"] = "Please select at least one service";
|
||||
|
||||
setState(() {
|
||||
temporaryMessage = "Please select at least one service";
|
||||
});
|
||||
|
||||
// Clear message after 3 seconds
|
||||
Future.delayed(Duration(seconds: 3), () {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
temporaryMessage = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return validationErrors.isEmpty; // Returns true if no errors
|
||||
@ -1431,12 +1446,13 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
height: 20,
|
||||
),
|
||||
|
||||
if (validationErrors["services"] != null)
|
||||
if (temporaryMessage != null)
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
validationErrors["services"]!,
|
||||
// validationErrors["services"]!,
|
||||
temporaryMessage!,
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.red,
|
||||
fontSize: 10,
|
||||
@ -1445,6 +1461,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
],
|
||||
),
|
||||
|
||||
if (temporaryMessage != null)
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
@ -2293,6 +2313,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
if (_selectedOption == "Option 2" ||
|
||||
_selectedOption == "Option 3") {
|
||||
_showInputDialog(selected["title"]!);
|
||||
} else if (_selectedOption == "Option 1") {
|
||||
otherUserName = userName;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@ -606,8 +606,11 @@ class _ListPlansState extends State<ListPlans> {
|
||||
|
||||
// List<Plan> plans = snapshot.data!;
|
||||
|
||||
// List<Plan> plans =
|
||||
// filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
||||
|
||||
List<Plan> plans =
|
||||
filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
||||
searchController.text.isEmpty ? allPlans : filteredPlans;
|
||||
plans.sort((a, b) =>
|
||||
int.parse(b.planId).compareTo(int.parse(a.planId)));
|
||||
|
||||
@ -695,7 +698,7 @@ class _ListPlansState extends State<ListPlans> {
|
||||
softWrap: true,
|
||||
overflow: TextOverflow.ellipsis)),
|
||||
|
||||
DataCell(Text(plan.employeeCode ?? "no data",
|
||||
DataCell(Text(plan.employeeCode ?? " - ",
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontFamily: "Inter",
|
||||
@ -1059,11 +1062,35 @@ class _ListPlansState extends State<ListPlans> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: isDesktop
|
||||
? SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: table, // <-- your existing table
|
||||
)
|
||||
: buildMobileCardView(paginatedPlans),
|
||||
? (searchController.text.isNotEmpty &&
|
||||
filteredPlans.isEmpty
|
||||
? Center(
|
||||
child: Text(
|
||||
"No matches found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
)
|
||||
: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: table,
|
||||
))
|
||||
: (searchController.text.isNotEmpty &&
|
||||
filteredPlans.isEmpty
|
||||
? Center(
|
||||
child: Text(
|
||||
"No matches found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
)
|
||||
: buildMobileCardView(paginatedPlans)),
|
||||
// child: isDesktop
|
||||
// ? SingleChildScrollView(
|
||||
// scrollDirection: Axis.vertical,
|
||||
// child: table, // <-- your existing table
|
||||
// )
|
||||
// : buildMobileCardView(paginatedPlans),
|
||||
),
|
||||
PaginationControls(
|
||||
currentPage: currentPage,
|
||||
|
||||
@ -594,7 +594,8 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
||||
"first_name",
|
||||
"last_name",
|
||||
"email",
|
||||
"mobile_no"
|
||||
"mobile_no",
|
||||
"employeeCode"
|
||||
];
|
||||
|
||||
if (apiselectedUser == null) {
|
||||
|
||||
@ -312,6 +312,9 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||
controller: widget.controllers["employeeCode"],
|
||||
enabled: !widget.isViewMode,
|
||||
onChanged: (value) {
|
||||
_clearError("employeeCode");
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
labelText: "Employee Code",
|
||||
labelStyle:
|
||||
@ -323,6 +326,13 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.errorMessages["employeeCode"] != null) ...[
|
||||
SizedBox(height: 5), // Space before error message
|
||||
Text(
|
||||
widget.errorMessages["employeeCode"]!,
|
||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@ -265,7 +265,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> get hotelMembershipList {
|
||||
return hotelLoyaltyEntries.map((entry) {
|
||||
final mappedList = hotelLoyaltyEntries.map((entry) {
|
||||
return {
|
||||
"id": entry["id"],
|
||||
"hotel_name": entry["controller_hotel"].text ?? '',
|
||||
@ -275,6 +275,12 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
||||
"is_active": entry["is_active"] ?? "1",
|
||||
};
|
||||
}).toList();
|
||||
|
||||
final allEntriesEmpty = mappedList.every((entry) =>
|
||||
(entry["hotel_name"] as String).trim().isEmpty &&
|
||||
(entry["membership_number"] as String).trim().isEmpty);
|
||||
|
||||
return allEntriesEmpty ? [] : mappedList;
|
||||
}
|
||||
|
||||
// List<Map<String, dynamic>> get frequentFlierList {
|
||||
@ -293,14 +299,14 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
||||
// }
|
||||
|
||||
List<Map<String, dynamic>> get frequentFlierList {
|
||||
return frequentFlierEntries.map((entry) {
|
||||
final mappedList = frequentFlierEntries.map((entry) {
|
||||
final frequent_flier_number = entry["controller_flier_number"];
|
||||
|
||||
print("frequent_flier_number- $frequent_flier_number");
|
||||
|
||||
return {
|
||||
"id": entry["id"],
|
||||
"airline": entry["airline"], // ✅ string value
|
||||
"airline": entry["airline"] ?? "",
|
||||
"frequent_flier_number": frequent_flier_number is TextEditingController
|
||||
? frequent_flier_number.text
|
||||
: "",
|
||||
@ -309,6 +315,12 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
||||
"is_active": entry["is_active"] ?? "1",
|
||||
};
|
||||
}).toList();
|
||||
|
||||
final allEntriesEmpty = mappedList.every((entry) =>
|
||||
(entry["airline"] as String).trim().isEmpty &&
|
||||
(entry["frequent_flier_number"] as String).trim().isEmpty);
|
||||
|
||||
return allEntriesEmpty ? [] : mappedList;
|
||||
}
|
||||
|
||||
// List<Map<String, dynamic>> get visaDetailsList {
|
||||
@ -335,7 +347,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
||||
// }
|
||||
|
||||
List<Map<String, dynamic>> get visaDetailsList {
|
||||
return visaEntries.map((entry) {
|
||||
final mappedList = visaEntries.map((entry) {
|
||||
final fromController = entry["controller_valid_from"];
|
||||
final uptoController = entry["controller_valid_upto"];
|
||||
|
||||
@ -352,6 +364,18 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
||||
"is_active": entry["is_active"] ?? "1",
|
||||
};
|
||||
}).toList();
|
||||
|
||||
final allEntriesEmpty = mappedList.every((entry) =>
|
||||
(entry["country_code"] == null ||
|
||||
entry["country_code"].toString().trim().isEmpty) &&
|
||||
(entry["visa_type_id"] == null ||
|
||||
entry["visa_type_id"].toString().trim().isEmpty) &&
|
||||
(entry["valid_from"] == null ||
|
||||
entry["valid_from"].toString().trim().isEmpty) &&
|
||||
(entry["valid_upto"] == null ||
|
||||
entry["valid_upto"].toString().trim().isEmpty));
|
||||
|
||||
return allEntriesEmpty ? [] : mappedList;
|
||||
}
|
||||
|
||||
void updateTravel() {
|
||||
@ -1983,11 +2007,16 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
||||
child: TextField(
|
||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||
controller: controllers["emergency_contact"],
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9\s]')),
|
||||
],
|
||||
// maxLength: 10,
|
||||
enabled: !widget.isViewMode,
|
||||
onChanged: (value) {
|
||||
_clearError("emergency_contact");
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
// counterText: '',
|
||||
labelText: "Contact Number",
|
||||
labelStyle:
|
||||
GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
|
||||
|
||||
@ -4,7 +4,7 @@ class SearchTraveler {
|
||||
final String lastName;
|
||||
final String email;
|
||||
final String mobileNo;
|
||||
|
||||
String? empCode;
|
||||
|
||||
SearchTraveler({
|
||||
required this.travellerId,
|
||||
@ -12,20 +12,17 @@ class SearchTraveler {
|
||||
required this.lastName,
|
||||
required this.email,
|
||||
required this.mobileNo,
|
||||
|
||||
this.empCode,
|
||||
});
|
||||
|
||||
|
||||
factory SearchTraveler.fromJson(Map<String, dynamic> json){
|
||||
factory SearchTraveler.fromJson(Map<String, dynamic> json) {
|
||||
return SearchTraveler(
|
||||
|
||||
travellerId: json['traveller_id'].toString(),
|
||||
firstName: json['first_name'].toString()?? '',
|
||||
lastName: json['last_name'].toString()?? '',
|
||||
email: json['email'].toString()?? '',
|
||||
mobileNo: json['mobile_no'].toString()?? '',
|
||||
|
||||
firstName: json['first_name'].toString() ?? '',
|
||||
lastName: json['last_name'].toString() ?? '',
|
||||
email: json['email'].toString() ?? '',
|
||||
mobileNo: json['mobile'].toString() ?? '',
|
||||
empCode: json['employee_code'].toString() ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
class SearchUser{
|
||||
class SearchUser {
|
||||
final String userId;
|
||||
final String firstName;
|
||||
final String lastName;
|
||||
final String email;
|
||||
final String mobileNo;
|
||||
final String alternateMobileNo;
|
||||
String? empCode;
|
||||
|
||||
SearchUser({
|
||||
required this.userId,
|
||||
@ -13,18 +14,18 @@ class SearchUser{
|
||||
required this.email,
|
||||
required this.mobileNo,
|
||||
required this.alternateMobileNo,
|
||||
});
|
||||
this.empCode,
|
||||
});
|
||||
|
||||
|
||||
factory SearchUser.fromJson(Map<String, dynamic> json){
|
||||
factory SearchUser.fromJson(Map<String, dynamic> json) {
|
||||
return SearchUser(
|
||||
userId: json['user_id'].toString(),
|
||||
firstName: json['first_name'].toString()?? '',
|
||||
lastName: json['last_name'].toString()?? '',
|
||||
email: json['email'].toString()?? '',
|
||||
mobileNo: json['mobile_no'].toString()?? '',
|
||||
alternateMobileNo: json['alternate_mobile_no'].toString()?? '',
|
||||
userId: json['user_id'].toString(),
|
||||
firstName: json['first_name'].toString() ?? '',
|
||||
lastName: json['last_name'].toString() ?? '',
|
||||
email: json['email'].toString() ?? '',
|
||||
mobileNo: json['mobile_no'].toString() ?? '',
|
||||
alternateMobileNo: json['alternate_mobile_no'].toString() ?? '',
|
||||
empCode: json['employee_code'].toString() ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,7 +268,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
||||
TabSelection.allTrips, '/listAllPlan'),
|
||||
layoutColor!,
|
||||
isSelected: selectedTab == TabSelection.allTrips,
|
||||
icon: Icons.insights_outlined,
|
||||
icon: Icons.format_list_bulleted_rounded,
|
||||
// icon: Icons.insights_outlined,
|
||||
),
|
||||
|
||||
if (userDetails["role"] != "Travel Agent")
|
||||
@ -282,7 +283,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
||||
layoutColor!,
|
||||
// () => context.go('/listTravelAgentPlan'),
|
||||
isSelected: selectedTab == TabSelection.myTrips,
|
||||
icon: Icons.request_page_outlined,
|
||||
icon: Icons.shopping_bag_outlined,
|
||||
// icon: Icons.request_page_outlined,
|
||||
),
|
||||
|
||||
if (userData?["role"] != "Travel Agent") // for others
|
||||
@ -293,7 +295,7 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
||||
layoutColor!,
|
||||
// () => context.go('/listPlan'),
|
||||
isSelected: selectedTab == TabSelection.myTrips,
|
||||
icon: Icons.request_page_outlined,
|
||||
icon: Icons.shopping_bag_outlined,
|
||||
),
|
||||
// if (userDetails["role"] == "Travel Agent")
|
||||
// buildNavItem("My Trips", _myTravelRequestColor,
|
||||
@ -317,7 +319,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
||||
layoutColor!,
|
||||
// () => context.go('/ApprovalList'),
|
||||
isSelected: selectedTab == TabSelection.myApprovals,
|
||||
icon: Icons.assessment_outlined,
|
||||
icon: Icons.verified_outlined,
|
||||
// icon: Icons.assessment_outlined,
|
||||
),
|
||||
|
||||
// buildNavItem("My Approvals", _myApprovalsColor, () {
|
||||
@ -368,6 +371,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
||||
break;
|
||||
case '/PolicyList':
|
||||
context.go('/PolicyList');
|
||||
case '/getForexDetails':
|
||||
context.go('/getForexDetails');
|
||||
case '/CreateUserDetails':
|
||||
context.go(
|
||||
"/CreateUserDetails",
|
||||
@ -504,6 +509,7 @@ final List<Map<String, dynamic>> menuItems = [
|
||||
},
|
||||
{'value': '/group', 'icon': Icons.group, 'label': 'Group'},
|
||||
{'value': '/PolicyList', 'icon': Icons.policy, 'label': 'Policy'},
|
||||
{'value': '/getForexDetails', 'icon': Icons.policy, 'label': 'Forex'},
|
||||
{
|
||||
'value': '/CreateUserDetails',
|
||||
'icon': Icons.account_circle,
|
||||
|
||||
@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:frontend/Screens/authentication/login/login_page.dart';
|
||||
import 'package:frontend/Screens/authentication/loginPage1.dart';
|
||||
import 'package:frontend/Screens/dashboard/home_page.dart';
|
||||
import 'package:frontend/Screens/forex/forex_list.dart';
|
||||
import 'package:frontend/Screens/organization/orgSetup.dart';
|
||||
import 'package:frontend/Screens/organization/org_List.dart';
|
||||
import 'package:frontend/Screens/plans/create_plans.dart';
|
||||
@ -95,6 +96,10 @@ final GoRouter router = GoRouter(
|
||||
path: '/group',
|
||||
builder: (context, state) => GroupList(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/getForexDetails',
|
||||
builder: (context, state) => ForexDataList(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/approvallist',
|
||||
builder: (context, state) => ApprovalList(),
|
||||
|
||||
@ -227,6 +227,7 @@ class CommentModalState extends State<CommentModal> {
|
||||
// You can also make a TextEditingController if you want to collect input
|
||||
|
||||
return AlertDialog(
|
||||
backgroundColor: Colors.white,
|
||||
contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 10),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
content: Column(
|
||||
|
||||
@ -23,7 +23,7 @@ class CustomTextField extends StatelessWidget {
|
||||
double widthFactor;
|
||||
|
||||
if (sizingInfo.deviceScreenType == DeviceScreenType.desktop) {
|
||||
widthFactor = 0.15; // Reduce width for desktop
|
||||
widthFactor = 0.9; // Reduce width for desktop
|
||||
} else if (sizingInfo.deviceScreenType == DeviceScreenType.tablet) {
|
||||
widthFactor = 0.8; // Slightly reduced width for tablets
|
||||
} else {
|
||||
@ -32,17 +32,18 @@ class CustomTextField extends StatelessWidget {
|
||||
|
||||
return Center(
|
||||
child: Container(
|
||||
height: 35,
|
||||
height: 40,
|
||||
width: MediaQuery.of(context).size.width * widthFactor,
|
||||
child: TextFormField(
|
||||
controller: controller,
|
||||
keyboardType: keyboardType,
|
||||
cursorColor: Colors.blueAccent,
|
||||
style: GoogleFonts.poppins(fontSize: 12.0),
|
||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||
decoration: InputDecoration(
|
||||
hintStyle: GoogleFonts.poppins(color: Colors.grey),
|
||||
floatingLabelStyle: GoogleFonts.poppins(
|
||||
color: Colors.black,
|
||||
// color: Colors.black,
|
||||
color: Color(0xFF575A74),
|
||||
),
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||
labelText: labelText,
|
||||
@ -52,30 +53,30 @@ class CustomTextField extends StatelessWidget {
|
||||
fontSize: 10, height: 0.8, color: Colors.red),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: Colors.grey, width: 0.5), // Grey border
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade200, width: 1), // Grey border
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.black54,
|
||||
width: 0.2), // Grey border when not focused
|
||||
color: Colors.grey.shade200,
|
||||
width: 1), // Grey border when not focused
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey,
|
||||
width: 0.5), // Blue border when focused
|
||||
color: Colors.grey.shade200,
|
||||
width: 1), // Blue border when focused
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey, width: 0.5), // Same as normal
|
||||
color: Colors.grey.shade200, width: 1), // Same as normal
|
||||
),
|
||||
focusedErrorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey, width: 0.5), // Same as focused
|
||||
color: Colors.grey.shade200, width: 1), // Same as focused
|
||||
),
|
||||
),
|
||||
validator: validator,
|
||||
|
||||
@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import '../Screens/allTrips/remarks_list.dart';
|
||||
import '../data/models/plan.dart';
|
||||
import '../services/apiService.dart';
|
||||
import '../utils/travelAgent_remarks.dart';
|
||||
import 'custom_popup.dart';
|
||||
|
||||
class PlanPopupMenu extends StatelessWidget {
|
||||
@ -91,6 +92,22 @@ class PlanPopupMenu extends StatelessWidget {
|
||||
role: "User"),
|
||||
);
|
||||
}),
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.comment,
|
||||
color: Color(0xFF475569),
|
||||
size: 11,
|
||||
),
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => CommentModal(
|
||||
// planId: plan.planId,
|
||||
planId: plan.planId.toString(),
|
||||
layoutColorForUser: layoutColor!,
|
||||
role: "Travel Agent"),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user