template details
This commit is contained in:
commit
4559eb7262
@ -567,8 +567,12 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
|
|
||||||
// List<Plan> plans = snapshot.data!;
|
// List<Plan> plans = snapshot.data!;
|
||||||
|
|
||||||
|
// List<Plan> plans =
|
||||||
|
// filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
||||||
|
|
||||||
List<Plan> plans =
|
List<Plan> plans =
|
||||||
filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
searchController.text.isEmpty ? allPlans : filteredPlans;
|
||||||
|
|
||||||
plans.sort((a, b) =>
|
plans.sort((a, b) =>
|
||||||
int.parse(b.planId).compareTo(int.parse(a.planId)));
|
int.parse(b.planId).compareTo(int.parse(a.planId)));
|
||||||
|
|
||||||
@ -654,7 +658,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
),
|
),
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis)),
|
overflow: TextOverflow.ellipsis)),
|
||||||
DataCell(Text(plan.employeeCode ?? "no data",
|
DataCell(Text(plan.employeeCode ?? " - ",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
@ -768,31 +772,32 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
plan.planId);
|
plan.planId);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.comment,
|
||||||
|
color: Color(0xFF475569),
|
||||||
|
size: 11,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) =>
|
||||||
|
CommentModalList(
|
||||||
|
// planId: plan.planId,
|
||||||
|
planId: plan
|
||||||
|
.planId
|
||||||
|
.toString(),
|
||||||
|
layoutColorForUser:
|
||||||
|
layoutColor!,
|
||||||
|
role: "Admin"),
|
||||||
|
);
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
IconButton(
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.comment,
|
|
||||||
color: Color(0xFF475569),
|
|
||||||
size: 11,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) =>
|
|
||||||
CommentModalList(
|
|
||||||
// planId: plan.planId,
|
|
||||||
planId:
|
|
||||||
plan.planId.toString(),
|
|
||||||
layoutColorForUser:
|
|
||||||
layoutColor!,
|
|
||||||
role: "Admin"),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -861,26 +866,8 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
plan: plan,
|
plan: plan,
|
||||||
deletePlan: deletePlan,
|
deletePlan: deletePlan,
|
||||||
apiService: apiService,
|
apiService: apiService,
|
||||||
|
layoutColor: layoutColor,
|
||||||
),
|
),
|
||||||
IconButton(
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.comment,
|
|
||||||
color: Color(0xFF475569),
|
|
||||||
size: 11,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) =>
|
|
||||||
CommentModalList(
|
|
||||||
// planId: plan.planId,
|
|
||||||
planId: plan.planId
|
|
||||||
.toString(),
|
|
||||||
layoutColorForUser:
|
|
||||||
layoutColor!,
|
|
||||||
role: "Admin"),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -985,11 +972,36 @@ class _ListAllPlansState extends State<ListAllPlans> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: isDesktop
|
child: isDesktop
|
||||||
? SingleChildScrollView(
|
? (searchController.text.isNotEmpty &&
|
||||||
scrollDirection: Axis.vertical,
|
filteredPlans.isEmpty
|
||||||
child: table, // <-- your existing table
|
? Center(
|
||||||
)
|
child: Text(
|
||||||
: buildMobileCardView(paginatedPlans),
|
"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(
|
PaginationControls(
|
||||||
currentPage: currentPage,
|
currentPage: currentPage,
|
||||||
|
|||||||
@ -498,8 +498,12 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
|||||||
|
|
||||||
// List<Plan> plans = snapshot.data!;
|
// List<Plan> plans = snapshot.data!;
|
||||||
|
|
||||||
|
// List<Plan> plans =
|
||||||
|
// filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
||||||
|
|
||||||
List<Plan> plans =
|
List<Plan> plans =
|
||||||
filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
searchController.text.isEmpty ? allPlans : filteredPlans;
|
||||||
|
|
||||||
plans.sort((a, b) =>
|
plans.sort((a, b) =>
|
||||||
int.parse(b.planId).compareTo(int.parse(a.planId)));
|
int.parse(b.planId).compareTo(int.parse(a.planId)));
|
||||||
|
|
||||||
@ -587,7 +591,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
|||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis)),
|
overflow: TextOverflow.ellipsis)),
|
||||||
|
|
||||||
DataCell(Text(plan.employeeCode ?? "no data",
|
DataCell(Text(plan.employeeCode ?? " - ",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
@ -702,29 +706,33 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
|||||||
plan.planId);
|
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"),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -819,24 +827,8 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
|||||||
plan: plan,
|
plan: plan,
|
||||||
deletePlan: deletePlan,
|
deletePlan: deletePlan,
|
||||||
apiService: apiService,
|
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"),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -941,11 +933,36 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: isDesktop
|
child: isDesktop
|
||||||
? SingleChildScrollView(
|
? (searchController.text.isNotEmpty &&
|
||||||
scrollDirection: Axis.vertical,
|
filteredPlans.isEmpty
|
||||||
child: table, // <-- your existing table
|
? Center(
|
||||||
)
|
child: Text(
|
||||||
: buildMobileCardView(paginatedPlans),
|
"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(
|
PaginationControls(
|
||||||
currentPage: currentPage,
|
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 =
|
List<Plan> plans =
|
||||||
filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
searchController.text.isEmpty ? allPlans : filteredPlans;
|
||||||
|
|
||||||
plans.sort((a, b) =>
|
plans.sort((a, b) =>
|
||||||
int.parse(b.planId).compareTo(int.parse(a.planId)));
|
int.parse(b.planId).compareTo(int.parse(a.planId)));
|
||||||
|
|
||||||
@ -619,7 +626,7 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
),
|
),
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis)),
|
overflow: TextOverflow.ellipsis)),
|
||||||
DataCell(Text(plan.employeeCode ?? "no data",
|
DataCell(Text(plan.employeeCode ?? " - ",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
@ -742,31 +749,33 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
plan.planId);
|
plan.planId);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.comment,
|
||||||
|
color: Color(0xFF475569),
|
||||||
|
size: 11,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) =>
|
||||||
|
CommentModalList(
|
||||||
|
// planId: plan.planId,
|
||||||
|
planId: plan
|
||||||
|
.planId
|
||||||
|
.toString(),
|
||||||
|
layoutColorForUser:
|
||||||
|
layoutColor!,
|
||||||
|
role:
|
||||||
|
"Approver"),
|
||||||
|
);
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
IconButton(
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.comment,
|
|
||||||
color: Color(0xFF475569),
|
|
||||||
size: 11,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) =>
|
|
||||||
CommentModalList(
|
|
||||||
// planId: plan.planId,
|
|
||||||
planId:
|
|
||||||
plan.planId.toString(),
|
|
||||||
layoutColorForUser:
|
|
||||||
layoutColor!,
|
|
||||||
role: "Approver"),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -934,31 +943,33 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
plan.planId);
|
plan.planId);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.comment,
|
||||||
|
color: Color(0xFF475569),
|
||||||
|
size: 11,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) =>
|
||||||
|
CommentModalList(
|
||||||
|
// planId: plan.planId,
|
||||||
|
planId: plan
|
||||||
|
.planId
|
||||||
|
.toString(),
|
||||||
|
layoutColorForUser:
|
||||||
|
layoutColor!,
|
||||||
|
role:
|
||||||
|
"Approver"),
|
||||||
|
);
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
IconButton(
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.comment,
|
|
||||||
color: Color(0xFF475569),
|
|
||||||
size: 11,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) =>
|
|
||||||
CommentModalList(
|
|
||||||
// planId: plan.planId,
|
|
||||||
planId:
|
|
||||||
plan.planId.toString(),
|
|
||||||
layoutColorForUser:
|
|
||||||
layoutColor!,
|
|
||||||
role: "Approver"),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -1062,11 +1073,36 @@ class _ApprovalListState extends State<ApprovalList> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: isDesktop
|
child: isDesktop
|
||||||
? SingleChildScrollView(
|
? (searchController.text.isNotEmpty &&
|
||||||
scrollDirection: Axis.vertical,
|
filteredPlans.isEmpty
|
||||||
child: table, // <-- your existing table
|
? Center(
|
||||||
)
|
child: Text(
|
||||||
: buildMobileCardView(paginatedPlans),
|
"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(
|
PaginationControls(
|
||||||
currentPage: currentPage,
|
currentPage: currentPage,
|
||||||
|
|||||||
@ -365,7 +365,7 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Text(
|
Text(
|
||||||
"Welcome To TravelSpends",
|
"Welcome To Trip Approval Tools",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:responsive_builder/responsive_builder.dart';
|
import 'package:responsive_builder/responsive_builder.dart';
|
||||||
@ -95,7 +96,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
|
|
||||||
print("Users fetched: ${_users.length}");
|
print("Users fetched: ${_users.length}");
|
||||||
for (var user in _users) {
|
for (var user in _users) {
|
||||||
print("${user.firstName} ${user.lastName}");
|
print("${user.firstName} ${user.lastName} ${user.empCode}");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
@ -145,7 +146,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
|
|
||||||
print("Users fetched: ${_users.length}");
|
print("Users fetched: ${_users.length}");
|
||||||
for (var travvelr in _traveller) {
|
for (var travvelr in _traveller) {
|
||||||
print("${travvelr.firstName} ${travvelr.lastName}");
|
print(
|
||||||
|
"${travvelr.firstName} ${travvelr.lastName} ${travvelr.mobileNo}");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
@ -199,6 +201,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
} else {
|
} else {
|
||||||
_filteredList = [
|
_filteredList = [
|
||||||
..._users.where((user) {
|
..._users.where((user) {
|
||||||
|
print("usersLLL : ${user}");
|
||||||
|
|
||||||
List<String> searchFields = [
|
List<String> searchFields = [
|
||||||
"${user.firstName} ${user.lastName}".toLowerCase(),
|
"${user.firstName} ${user.lastName}".toLowerCase(),
|
||||||
user.email.toLowerCase() ?? "",
|
user.email.toLowerCase() ?? "",
|
||||||
@ -221,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) {
|
void _filterUsersTravellers(String query) {
|
||||||
print("Filtering _filterUsersTravellers...");
|
print("Filtering _filterUsersTravellers...");
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -286,7 +323,11 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
mainAxisSize:
|
mainAxisSize:
|
||||||
MainAxisSize.min, // Ensures content doesn't expand unnecessarily
|
MainAxisSize.min, // Ensures content doesn't expand unnecessarily
|
||||||
children: [
|
children: [
|
||||||
Text("Please Select User", style: TextStyle(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),
|
SizedBox(height: 10),
|
||||||
|
|
||||||
// Search Field
|
// Search Field
|
||||||
@ -297,22 +338,24 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
_showTravellerForm = false;
|
_showTravellerForm = false;
|
||||||
});
|
});
|
||||||
widget.title == "Others"
|
widget.title == "Others"
|
||||||
? _filterUsersTravellers(query)
|
? _filterTravellers(query)
|
||||||
: _filterUsers(query);
|
: _filterUsers(query);
|
||||||
},
|
},
|
||||||
|
style: GoogleFonts.poppins(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search for a user",
|
hintText: "Search for a user",
|
||||||
hintStyle: TextStyle(fontSize: 14),
|
hintStyle:
|
||||||
|
GoogleFonts.poppins(fontSize: 14, color: Colors.grey),
|
||||||
prefixIcon: Icon(Icons.search),
|
prefixIcon: Icon(Icons.search),
|
||||||
border:
|
border:
|
||||||
OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
|
OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.grey, width: 1),
|
borderSide: BorderSide(color: Colors.grey.shade200, width: 1),
|
||||||
// borderSide: BorderSide(color: Color(0xFFF5F5F5), width: 2),
|
// borderSide: BorderSide(color: Color(0xFFF5F5F5), width: 2),
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
borderSide: BorderSide(color: Colors.blueAccent, width: 2),
|
borderSide: BorderSide(color: Colors.grey.shade200, width: 1),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -324,7 +367,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text("or create a new traveler",
|
Text("or create a new traveler",
|
||||||
style: TextStyle(fontSize: 14, color: Color(0xFF575A74))),
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 14, color: Color(0xFF575A74))),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -333,7 +377,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Text("Create",
|
child: Text("Create",
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14, color: widget.layoutColorForUser)),
|
fontSize: 14, color: widget.layoutColorForUser)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -351,8 +395,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No users found",
|
"No users found",
|
||||||
style:
|
style: GoogleFonts.poppins(
|
||||||
TextStyle(fontSize: 14, color: Colors.grey),
|
fontSize: 14, color: Colors.grey),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
@ -365,12 +409,30 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
final user = item["data"]; // Extract user object
|
final user = item["data"]; // Extract user object
|
||||||
final userType =
|
final userType =
|
||||||
item["type"]; // "user" or "traveller"
|
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(
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
"${user.firstName ?? "Unknown"} ${user.lastName ?? ""}"),
|
"${user.firstName ?? "Unknown"} ${user.lastName ?? ""}",
|
||||||
// subtitle: Text(
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
// "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: () {
|
onTap: () {
|
||||||
String selectedUser =
|
String selectedUser =
|
||||||
"${user.firstName ?? "Unknown"} ${user.lastName ?? ""}";
|
"${user.firstName ?? "Unknown"} ${user.lastName ?? ""}";
|
||||||
@ -395,7 +457,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
if (_showTravellerForm)
|
if (_showTravellerForm)
|
||||||
Container(
|
Container(
|
||||||
height: 300, // Set a defined height
|
height: 300, // Set a defined height
|
||||||
color: Color(0xFFF4F4FB),
|
// color: Color(0xFFF4F4FB),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: TravelerForm(
|
child: TravelerForm(
|
||||||
@ -435,6 +497,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Cancel",
|
"Cancel",
|
||||||
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
@ -456,7 +519,10 @@ class _UserSelectionDialogState extends State<UserSelectionDialog> {
|
|||||||
_searchController.text, userIdSelected, isTraveller);
|
_searchController.text, userIdSelected, isTraveller);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
child: Text("Submit"),
|
child: Text(
|
||||||
|
"Submit",
|
||||||
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -563,33 +629,37 @@ class _TravelerFormState extends State<TravelerForm> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
final Map<String, dynamic> responseData = jsonDecode(response.body);
|
||||||
final Map<String, dynamic> responseData =
|
if (responseData.containsKey("data")) {
|
||||||
jsonDecode(response.body); // Parse response
|
// Parse response
|
||||||
if (responseData["success"] == true &&
|
|
||||||
responseData.containsKey("data")) {
|
|
||||||
final travellerData = responseData["data"];
|
|
||||||
|
|
||||||
String travellerId = travellerData["traveller_id"];
|
print("responseData- $responseData ");
|
||||||
String firstName = travellerData["first_name"];
|
|
||||||
String lastName = travellerData["last_name"];
|
|
||||||
|
|
||||||
print(
|
final travellerData = responseData["data"];
|
||||||
"Traveller Added: ID: $travellerId, Name: $firstName $lastName");
|
|
||||||
|
|
||||||
// Pass data to callback
|
String travellerId = travellerData["traveller_id"];
|
||||||
widget.onSubmit("$firstName $lastName", travellerId, true);
|
String firstName = travellerData["first_name"];
|
||||||
|
String lastName = travellerData["last_name"];
|
||||||
|
|
||||||
// Close the dialog
|
print(
|
||||||
Navigator.pop(context);
|
"Traveller Added: ID: $travellerId, Name: $firstName $lastName");
|
||||||
}
|
|
||||||
|
// // Pass data to callback
|
||||||
|
// widget.onSubmit("$firstName $lastName", travellerId, true);
|
||||||
|
|
||||||
|
String fullName = "${firstName.trim()} ${lastName.trim()}";
|
||||||
|
widget.onSubmit(fullName, travellerId, true);
|
||||||
|
|
||||||
|
// Close the dialog
|
||||||
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(
|
content: Text(
|
||||||
"Traveller added successfully!",
|
"Traveller added successfully!",
|
||||||
style: TextStyle(color: Colors.white), // ✅ Set text color
|
style:
|
||||||
|
GoogleFonts.poppins(color: Colors.white), // ✅ Set text color
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
),
|
),
|
||||||
@ -627,7 +697,8 @@ class _TravelerFormState extends State<TravelerForm> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text("Create Traveler", style: TextStyle(color: Colors.black54)),
|
Text("Create Traveler",
|
||||||
|
style: GoogleFonts.poppins(color: Colors.black54)),
|
||||||
SizedBox(height: 7),
|
SizedBox(height: 7),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
@ -643,12 +714,13 @@ class _TravelerFormState extends State<TravelerForm> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
widget.formKey.currentState?.reset();
|
widget.formKey.currentState?.reset();
|
||||||
},
|
},
|
||||||
child: Text("Clear", style: TextStyle(color: Colors.grey)),
|
child: Text("Clear",
|
||||||
|
style: GoogleFonts.poppins(color: Colors.grey)),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => _onSubmit(context),
|
onPressed: () => _onSubmit(context),
|
||||||
child:
|
child: Text("Add",
|
||||||
Text("Add", style: TextStyle(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
@ -158,6 +158,13 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
_checkInController.text = DateFormat('yyyy-MM-dd').format(parsedDate);
|
_checkInController.text = DateFormat('yyyy-MM-dd').format(parsedDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final parsedEndDate =
|
||||||
|
DateTime.tryParse(flightLastTripDateNotifier.value ?? '');
|
||||||
|
if (parsedEndDate != null) {
|
||||||
|
_checkOutController.text =
|
||||||
|
DateFormat('yyyy-MM-dd').format(parsedEndDate);
|
||||||
|
}
|
||||||
|
|
||||||
// ✅ Check and set default times if empty
|
// ✅ Check and set default times if empty
|
||||||
if (_checkInTimeController.text.isEmpty) {
|
if (_checkInTimeController.text.isEmpty) {
|
||||||
_checkInTimeController.text = '14:00'; // 2 PM
|
_checkInTimeController.text = '14:00'; // 2 PM
|
||||||
|
|||||||
@ -513,6 +513,40 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
print("FlightData - $flightsData");
|
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() {
|
bool validateFields() {
|
||||||
errorMessages.clear(); // Reset errors
|
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(
|
TimeOfDay? pickedTime = await showTimePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialTime: _selectedCheckOutTime ?? TimeOfDay.now(),
|
initialTime: _selectedCheckOutTime ?? TimeOfDay.now(),
|
||||||
@ -1141,6 +1176,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
);
|
);
|
||||||
// _timeController.text = formattedTime;
|
// _timeController.text = formattedTime;
|
||||||
textControllers["_time${index}Controller"]?.text = formattedTime;
|
textControllers["_time${index}Controller"]?.text = formattedTime;
|
||||||
|
|
||||||
|
onPicked();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1485,12 +1522,23 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: GestureDetector(
|
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: AbsorbPointer(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: focusNodes["_time${index}FocusNode"],
|
focusNode: focusNodes["_time${index}FocusNode"],
|
||||||
// controller: _timeController,
|
// controller: _timeController,
|
||||||
controller: textControllers["_time${index}Controller"],
|
controller: textControllers["_time${index}Controller"],
|
||||||
|
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Time",
|
labelText: "Time",
|
||||||
@ -1509,7 +1557,7 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
if (errorMessages["time_$index"] != null) ...[
|
if (errorMessages["time_$index"] != null) ...[
|
||||||
SizedBox(height: 5), // Space before error message
|
SizedBox(height: 5), // Space before error message
|
||||||
Text(
|
Text(
|
||||||
"Required",
|
errorMessages["time_$index"]!,
|
||||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -492,7 +492,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
double.tryParse(textControllers["_telephone"]?.text ?? "0") ?? 0;
|
double.tryParse(textControllers["_telephone"]?.text ?? "0") ?? 0;
|
||||||
double calclateVal = (transport + accommodation + telephone);
|
double calclateVal = (transport + accommodation + telephone);
|
||||||
|
|
||||||
CalculatedOtherExpenses = (calclateVal).toStringAsFixed(2);
|
CalculatedOtherExpenses = (calclateVal).toStringAsFixed(0);
|
||||||
|
|
||||||
// Convert selectedPerdiemAmount to double before performing the addition
|
// Convert selectedPerdiemAmount to double before performing the addition
|
||||||
double perdiemAmount = double.tryParse(selectedPerdiemAmount ?? "0") ?? 0;
|
double perdiemAmount = double.tryParse(selectedPerdiemAmount ?? "0") ?? 0;
|
||||||
|
|||||||
0
lib/Screens/myTemplates/template.dart
Normal file
0
lib/Screens/myTemplates/template.dart
Normal file
@ -375,6 +375,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
late bool isApproverApproved = false;
|
late bool isApproverApproved = false;
|
||||||
late bool isApproverRejected = false;
|
late bool isApproverRejected = false;
|
||||||
|
|
||||||
|
String? temporaryMessage;
|
||||||
|
|
||||||
//Getter Method
|
//Getter Method
|
||||||
Map<String, dynamic> get planData => {
|
Map<String, dynamic> get planData => {
|
||||||
"org_id": orgId,
|
"org_id": orgId,
|
||||||
@ -474,6 +476,31 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleSelectedUser() {
|
||||||
|
if (widget.selectedPlanData != null) {
|
||||||
|
setState(() {
|
||||||
|
String userId = widget.selectedPlanData['user_id'] ?? '';
|
||||||
|
String userName = widget.selectedPlanData['user_name'] ?? '';
|
||||||
|
String travellerId = widget.selectedPlanData['traveller_id'] ?? '';
|
||||||
|
String travellerName = widget.selectedPlanData['traveller_name'] ?? '';
|
||||||
|
|
||||||
|
print("TestplanUsrId $userId --- $travellerId");
|
||||||
|
|
||||||
|
if (travellerId.isNotEmpty && travellerId != "0") {
|
||||||
|
print("TestplanUsrId1: $travellerId");
|
||||||
|
planTravlrId = travellerId;
|
||||||
|
_selectedOption = "Option 3";
|
||||||
|
otherUserName = travellerName;
|
||||||
|
} else if (userId.isNotEmpty && userId != "0") {
|
||||||
|
print("TestplanUsrId : $userId");
|
||||||
|
print("TestplanUsrIdSelf : $selfId");
|
||||||
|
_selectedOption = (selfId != userId) ? "Option 2" : "Option 1";
|
||||||
|
otherUserName = userName;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handleUpdateData() {
|
void handleUpdateData() {
|
||||||
if (widget.selectedPlanData != null) {
|
if (widget.selectedPlanData != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -641,10 +668,11 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void getSelectedPlanFor() {
|
void getSelectedPlanFor() {
|
||||||
if (!mounted) return;
|
// if (!mounted) return;
|
||||||
|
print("getSelectedPlanFor");
|
||||||
setState(() {
|
setState(() {
|
||||||
if (selectedplanUserId != null) {
|
if (selectedplanUserId != null) {
|
||||||
|
print("Is Not USER ID - $planUsrId ");
|
||||||
if (selectedIstravelUser!) {
|
if (selectedIstravelUser!) {
|
||||||
planUsrId = "";
|
planUsrId = "";
|
||||||
planTravlrId = selectedplanUserId;
|
planTravlrId = selectedplanUserId;
|
||||||
@ -653,8 +681,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
planTravlrId = "";
|
planTravlrId = "";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
print("Is USER ID - $planUsrId ");
|
||||||
planUsrId = selfId;
|
planUsrId = selfId;
|
||||||
planTravlrId = "";
|
planTravlrId = "";
|
||||||
|
_selectedOption = "Option 1";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -676,8 +706,12 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
}
|
}
|
||||||
orgId = await getOrgId();
|
orgId = await getOrgId();
|
||||||
print("userDetails - $selfId");
|
print("userDetails - $selfId");
|
||||||
|
// handleSelectedUser();
|
||||||
getSelectedPlanFor();
|
getSelectedPlanFor();
|
||||||
setTripPlanAction();
|
setTripPlanAction();
|
||||||
|
|
||||||
|
handleSelectedUser();
|
||||||
|
// handleUpdateData();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> getToken() async {
|
Future<String?> getToken() async {
|
||||||
@ -958,7 +992,20 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
bool anyServiceSelected =
|
bool anyServiceSelected =
|
||||||
serviceLists.any((list) => list != null && list.isNotEmpty);
|
serviceLists.any((list) => list != null && list.isNotEmpty);
|
||||||
if (!anyServiceSelected) {
|
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
|
return validationErrors.isEmpty; // Returns true if no errors
|
||||||
@ -1279,52 +1326,53 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74)),
|
||||||
),
|
),
|
||||||
SizedBox(height: 6),
|
SizedBox(height: 6),
|
||||||
isMobile
|
isDesktop
|
||||||
? SingleChildScrollView(
|
? SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: _buildPlanTrip(isMobile),
|
children: _buildPlanTrip(isDesktop),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Row(
|
: Row(
|
||||||
children: _buildPlanTrip(isMobile),
|
children: _buildPlanTrip(isDesktop),
|
||||||
),
|
),
|
||||||
SizedBox(height: 7),
|
SizedBox(height: 7),
|
||||||
Text(
|
// Text(
|
||||||
otherUserName ?? userName ?? " ", // Your label
|
// otherUserName ?? userName ?? " ", // Your label
|
||||||
|
//
|
||||||
style: GoogleFonts.poppins(
|
// style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
// fontSize: 11,
|
||||||
fontWeight: FontWeight.w400,
|
// fontWeight: FontWeight.w400,
|
||||||
color: widget.layoutColor,
|
// color: widget.layoutColor,
|
||||||
),
|
|
||||||
)
|
|
||||||
// Text.rich(
|
|
||||||
// TextSpan(
|
|
||||||
// text: "Trip Planned For : ", // Static text
|
|
||||||
// style: TextStyle(
|
|
||||||
// fontFamily: "Archivo",
|
|
||||||
// fontSize: 13,
|
|
||||||
// fontWeight: FontWeight.w600,
|
|
||||||
// color: Color(0xFF212121),
|
|
||||||
// // color: Color(0xFF575A74), // Default color
|
|
||||||
// ),
|
|
||||||
// children: [
|
|
||||||
// TextSpan(
|
|
||||||
// text: otherUserName ??
|
|
||||||
// userName ??
|
|
||||||
// " ", // Dynamic username
|
|
||||||
// style: TextStyle(
|
|
||||||
// fontSize: 12,
|
|
||||||
// fontWeight: FontWeight.w400,
|
|
||||||
// color: widget
|
|
||||||
// .layoutColor, // Change this to any color
|
|
||||||
// // color: Colors.blueAccent, // Change this to any color
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
|
|
||||||
|
Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
text: "Trip Planned User : ", // Static text
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Color(0xFF212121),
|
||||||
|
// color: Color(0xFF575A74), // Default color
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: otherUserName ??
|
||||||
|
userName ??
|
||||||
|
" ", // Dynamic username
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: widget
|
||||||
|
.layoutColor, // Change this to any color
|
||||||
|
// color: Colors.blueAccent, // Change this to any color
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 5),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1398,12 +1446,13 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
|
|
||||||
if (validationErrors["services"] != null)
|
if (temporaryMessage != null)
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
validationErrors["services"]!,
|
// validationErrors["services"]!,
|
||||||
|
temporaryMessage!,
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
@ -1412,6 +1461,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
if (temporaryMessage != null)
|
||||||
|
SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -1483,6 +1536,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74)),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
|
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: false,
|
isFocused: false,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
@ -1513,8 +1567,9 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none, // No underline
|
border: InputBorder.none, // No underline
|
||||||
|
|
||||||
contentPadding:
|
contentPadding:
|
||||||
EdgeInsets.symmetric(horizontal: 1, vertical: 5),
|
EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder: (context, selectedItem) {
|
dropdownBuilder: (context, selectedItem) {
|
||||||
@ -2205,6 +2260,77 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
{"title": "Others", "value": "Option 3"},
|
{"title": "Others", "value": "Option 3"},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
return [
|
||||||
|
CustomTextFieldWrapper(
|
||||||
|
isFocused: false,
|
||||||
|
isDesktop: isDesktop,
|
||||||
|
layoutColor: widget.layoutColor,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 35,
|
||||||
|
width: double.infinity,
|
||||||
|
child: DropdownSearch<String>(
|
||||||
|
selectedItem: options
|
||||||
|
.firstWhere((opt) => opt['value'] == _selectedOption)['title'],
|
||||||
|
enabled: !widget.isViewMode,
|
||||||
|
items: options.map((opt) => opt['title']!).toList(),
|
||||||
|
popupProps: PopupProps.menu(
|
||||||
|
showSearchBox: false,
|
||||||
|
menuProps: const MenuProps(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
),
|
||||||
|
constraints: BoxConstraints(maxHeight: 100),
|
||||||
|
itemBuilder: (context, item, isSelected) => Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 8.0, vertical: 6.0),
|
||||||
|
child: Text(
|
||||||
|
item,
|
||||||
|
style: GoogleFonts.poppins(fontSize: 13),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
|
dropdownSearchDecoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownBuilder: (context, selectedItem) {
|
||||||
|
return Text(
|
||||||
|
selectedItem ?? "Select Purpose",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: selectedItem == null ? Colors.grey : Colors.black,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onChanged: (String? newTitle) {
|
||||||
|
if (newTitle == null) return;
|
||||||
|
final selected =
|
||||||
|
options.firstWhere((opt) => opt["title"] == newTitle);
|
||||||
|
setState(() {
|
||||||
|
_selectedOption = selected["value"]!;
|
||||||
|
if (_selectedOption == "Option 2" ||
|
||||||
|
_selectedOption == "Option 3") {
|
||||||
|
_showInputDialog(selected["title"]!);
|
||||||
|
} else if (_selectedOption == "Option 1") {
|
||||||
|
otherUserName = userName;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> _buildPlanTrip1(bool isDesktop) {
|
||||||
|
List<Map<String, String>> options = [
|
||||||
|
{"title": "Self", "value": "Option 1"},
|
||||||
|
{"title": "Other Employee", "value": "Option 2"},
|
||||||
|
{"title": "Others", "value": "Option 3"},
|
||||||
|
];
|
||||||
|
|
||||||
print(" layoutColor: ${widget.layoutColor}");
|
print(" layoutColor: ${widget.layoutColor}");
|
||||||
return options.map((option) {
|
return options.map((option) {
|
||||||
return Padding(
|
return Padding(
|
||||||
@ -2502,7 +2628,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: _isdescriptionFocused,
|
isFocused: false,
|
||||||
|
// isFocused: _isdescriptionFocused,
|
||||||
// width: isDesktop
|
// width: isDesktop
|
||||||
// ? MediaQuery.of(context).size.width * 0.38
|
// ? MediaQuery.of(context).size.width * 0.38
|
||||||
// : MediaQuery.of(context).size.width * 0.85,
|
// : MediaQuery.of(context).size.width * 0.85,
|
||||||
@ -2604,7 +2731,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: "Trip Name *",
|
labelText: "Trip Name *",
|
||||||
|
|
||||||
labelStyle: GoogleFonts.poppins(fontSize: 14, color: Colors.grey),
|
labelStyle: GoogleFonts.poppins(fontSize: 14, color: Colors.black54),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||||
@ -3108,7 +3235,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
getSelectedPlanFor();
|
getSelectedPlanFor();
|
||||||
},
|
},
|
||||||
onClose: () {
|
onClose: () {
|
||||||
getSelectedPlanFor();
|
print("Choosede Clsoes");
|
||||||
|
fetchUserDetails();
|
||||||
},
|
},
|
||||||
layoutColorForUser: widget.layoutColor!,
|
layoutColorForUser: widget.layoutColor!,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -48,11 +48,24 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
// futurePlans = fetchPlans();
|
||||||
|
//
|
||||||
|
// futurePlans.then((plans) {
|
||||||
|
// setState(() {
|
||||||
|
// allPlans = plans;
|
||||||
|
// filteredPlans = plans;
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
getToken();
|
getToken();
|
||||||
|
initializeData();
|
||||||
|
loadInitialData();
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
initializeData();
|
// initializeData();
|
||||||
loadInitialData();
|
// loadInitialData();
|
||||||
|
|
||||||
// futurePlans.then((plans) {
|
// futurePlans.then((plans) {
|
||||||
// setState(() {
|
// setState(() {
|
||||||
@ -593,8 +606,11 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
|
|
||||||
// List<Plan> plans = snapshot.data!;
|
// List<Plan> plans = snapshot.data!;
|
||||||
|
|
||||||
|
// List<Plan> plans =
|
||||||
|
// filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
||||||
|
|
||||||
List<Plan> plans =
|
List<Plan> plans =
|
||||||
filteredPlans.isNotEmpty ? filteredPlans : allPlans;
|
searchController.text.isEmpty ? allPlans : filteredPlans;
|
||||||
plans.sort((a, b) =>
|
plans.sort((a, b) =>
|
||||||
int.parse(b.planId).compareTo(int.parse(a.planId)));
|
int.parse(b.planId).compareTo(int.parse(a.planId)));
|
||||||
|
|
||||||
@ -682,7 +698,7 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis)),
|
overflow: TextOverflow.ellipsis)),
|
||||||
|
|
||||||
DataCell(Text(plan.employeeCode ?? "no data",
|
DataCell(Text(plan.employeeCode ?? " - ",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontFamily: "Inter",
|
fontFamily: "Inter",
|
||||||
@ -813,31 +829,32 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
plan.planId);
|
plan.planId);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.comment,
|
||||||
|
color: Color(0xFF475569),
|
||||||
|
size: 11,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) =>
|
||||||
|
CommentModalList(
|
||||||
|
// planId: plan.planId,
|
||||||
|
planId: plan
|
||||||
|
.planId
|
||||||
|
.toString(),
|
||||||
|
layoutColorForUser:
|
||||||
|
layoutColor!,
|
||||||
|
role: "User"),
|
||||||
|
);
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
IconButton(
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.comment,
|
|
||||||
color: Color(0xFF475569),
|
|
||||||
size: 11,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) =>
|
|
||||||
CommentModalList(
|
|
||||||
// planId: plan.planId,
|
|
||||||
planId:
|
|
||||||
plan.planId.toString(),
|
|
||||||
layoutColorForUser:
|
|
||||||
layoutColor!,
|
|
||||||
role: "User"),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -940,26 +957,8 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
plan: plan,
|
plan: plan,
|
||||||
deletePlan: deletePlan,
|
deletePlan: deletePlan,
|
||||||
apiService: apiService,
|
apiService: apiService,
|
||||||
|
layoutColor: layoutColor,
|
||||||
),
|
),
|
||||||
IconButton(
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.comment,
|
|
||||||
color: Color(0xFF475569),
|
|
||||||
size: 11,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) =>
|
|
||||||
CommentModalList(
|
|
||||||
// planId: plan.planId,
|
|
||||||
planId:
|
|
||||||
plan.planId.toString(),
|
|
||||||
layoutColorForUser:
|
|
||||||
layoutColor!,
|
|
||||||
role: "User"),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -1063,11 +1062,35 @@ class _ListPlansState extends State<ListPlans> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: isDesktop
|
child: isDesktop
|
||||||
? SingleChildScrollView(
|
? (searchController.text.isNotEmpty &&
|
||||||
scrollDirection: Axis.vertical,
|
filteredPlans.isEmpty
|
||||||
child: table, // <-- your existing table
|
? Center(
|
||||||
)
|
child: Text(
|
||||||
: buildMobileCardView(paginatedPlans),
|
"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(
|
PaginationControls(
|
||||||
currentPage: currentPage,
|
currentPage: currentPage,
|
||||||
|
|||||||
@ -594,7 +594,8 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
"first_name",
|
"first_name",
|
||||||
"last_name",
|
"last_name",
|
||||||
"email",
|
"email",
|
||||||
"mobile_no"
|
"mobile_no",
|
||||||
|
"employeeCode"
|
||||||
];
|
];
|
||||||
|
|
||||||
if (apiselectedUser == null) {
|
if (apiselectedUser == null) {
|
||||||
@ -847,7 +848,6 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: (selectedTab == "travel" ||
|
children: (selectedTab == "travel" ||
|
||||||
selectedRole == "5" ||
|
selectedRole == "5" ||
|
||||||
isEditProfile ||
|
|
||||||
setSelectesUserType == true)
|
setSelectesUserType == true)
|
||||||
? _buildSubmit(isDesktop, layoutColor!)
|
? _buildSubmit(isDesktop, layoutColor!)
|
||||||
: _buildNext(isDesktop, layoutColor!),
|
: _buildNext(isDesktop, layoutColor!),
|
||||||
@ -885,18 +885,18 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (isEditProfile)
|
// if (isEditProfile)
|
||||||
IconButton(
|
// IconButton(
|
||||||
icon: Icon(
|
// icon: Icon(
|
||||||
Icons.edit,
|
// Icons.edit,
|
||||||
color: Color(0xFF114D8B),
|
// color: Color(0xFF114D8B),
|
||||||
size: 14,
|
// size: 14,
|
||||||
),
|
// ),
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
setState(() {
|
// setState(() {
|
||||||
isViewMode = !isViewMode;
|
// isViewMode = !isViewMode;
|
||||||
});
|
// });
|
||||||
})
|
// })
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@ -1115,8 +1115,9 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
|
|||||||
),
|
),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
onPressed:
|
onPressed: handleNext,
|
||||||
isViewMode ? null : handleNext, // Disable when in view mode
|
// onPressed:
|
||||||
|
// isViewMode ? null : handleNext, // Disable when in view mode
|
||||||
child: Text("Next"),
|
child: Text("Next"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -312,6 +312,9 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
controller: widget.controllers["employeeCode"],
|
controller: widget.controllers["employeeCode"],
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
|
onChanged: (value) {
|
||||||
|
_clearError("employeeCode");
|
||||||
|
},
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: "Employee Code",
|
labelText: "Employee Code",
|
||||||
labelStyle:
|
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),
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -343,7 +353,8 @@ class _OfficeDetailsState extends State<OfficeDetails> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 45, // Set appropriate height
|
height: 45, // Set appropriate height
|
||||||
child: DropdownButtonFormField<String>(
|
child: DropdownButtonFormField<String>(
|
||||||
value: widget.isViewMode ? null : selectedDepartment,
|
value: selectedDepartment,
|
||||||
|
// value: widget.isViewMode ? null : selectedDepartment,
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
|
|||||||
@ -280,7 +280,11 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
try {
|
try {
|
||||||
final result = await apiService.fetchAllServices();
|
final result = await apiService.fetchAllServices();
|
||||||
setState(() {
|
setState(() {
|
||||||
apiAllServices = result;
|
// apiAllServices = result;
|
||||||
|
setState(() {
|
||||||
|
apiAllServices = result
|
||||||
|
..sort((a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
print("Fetched services: $apiAllServices");
|
print("Fetched services: $apiAllServices");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -418,14 +422,17 @@ class PersonalDetailsState extends State<PersonalDetails> {
|
|||||||
height: 15,
|
height: 15,
|
||||||
width: 15,
|
width: 15,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.rectangle,
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: isSelected ? Colors.green : Colors.grey, width: 1),
|
color: isSelected ? Colors.green : Colors.grey.shade400,
|
||||||
|
width: isSelected ? 2 : 1,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.check_circle,
|
Icons.check,
|
||||||
size: 10,
|
size: 10,
|
||||||
color: isSelected ? Colors.green : Colors.grey,
|
|
||||||
|
color: isSelected ? Colors.green : Colors.white10,
|
||||||
// color: Colors.grey,
|
// color: Colors.grey,
|
||||||
)),
|
)),
|
||||||
]),
|
]),
|
||||||
|
|||||||
@ -265,7 +265,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Map<String, dynamic>> get hotelMembershipList {
|
List<Map<String, dynamic>> get hotelMembershipList {
|
||||||
return hotelLoyaltyEntries.map((entry) {
|
final mappedList = hotelLoyaltyEntries.map((entry) {
|
||||||
return {
|
return {
|
||||||
"id": entry["id"],
|
"id": entry["id"],
|
||||||
"hotel_name": entry["controller_hotel"].text ?? '',
|
"hotel_name": entry["controller_hotel"].text ?? '',
|
||||||
@ -275,6 +275,12 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
"is_active": entry["is_active"] ?? "1",
|
"is_active": entry["is_active"] ?? "1",
|
||||||
};
|
};
|
||||||
}).toList();
|
}).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 {
|
// List<Map<String, dynamic>> get frequentFlierList {
|
||||||
@ -293,14 +299,14 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
List<Map<String, dynamic>> get frequentFlierList {
|
List<Map<String, dynamic>> get frequentFlierList {
|
||||||
return frequentFlierEntries.map((entry) {
|
final mappedList = frequentFlierEntries.map((entry) {
|
||||||
final frequent_flier_number = entry["controller_flier_number"];
|
final frequent_flier_number = entry["controller_flier_number"];
|
||||||
|
|
||||||
print("frequent_flier_number- $frequent_flier_number");
|
print("frequent_flier_number- $frequent_flier_number");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"id": entry["id"],
|
"id": entry["id"],
|
||||||
"airline": entry["airline"], // ✅ string value
|
"airline": entry["airline"] ?? "",
|
||||||
"frequent_flier_number": frequent_flier_number is TextEditingController
|
"frequent_flier_number": frequent_flier_number is TextEditingController
|
||||||
? frequent_flier_number.text
|
? frequent_flier_number.text
|
||||||
: "",
|
: "",
|
||||||
@ -309,6 +315,12 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
"is_active": entry["is_active"] ?? "1",
|
"is_active": entry["is_active"] ?? "1",
|
||||||
};
|
};
|
||||||
}).toList();
|
}).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 {
|
// List<Map<String, dynamic>> get visaDetailsList {
|
||||||
@ -335,7 +347,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
List<Map<String, dynamic>> get visaDetailsList {
|
List<Map<String, dynamic>> get visaDetailsList {
|
||||||
return visaEntries.map((entry) {
|
final mappedList = visaEntries.map((entry) {
|
||||||
final fromController = entry["controller_valid_from"];
|
final fromController = entry["controller_valid_from"];
|
||||||
final uptoController = entry["controller_valid_upto"];
|
final uptoController = entry["controller_valid_upto"];
|
||||||
|
|
||||||
@ -352,6 +364,18 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
"is_active": entry["is_active"] ?? "1",
|
"is_active": entry["is_active"] ?? "1",
|
||||||
};
|
};
|
||||||
}).toList();
|
}).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() {
|
void updateTravel() {
|
||||||
@ -1983,11 +2007,16 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
|||||||
child: TextField(
|
child: TextField(
|
||||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
controller: controllers["emergency_contact"],
|
controller: controllers["emergency_contact"],
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.allow(RegExp(r'[0-9\s]')),
|
||||||
|
],
|
||||||
|
// maxLength: 10,
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_clearError("emergency_contact");
|
_clearError("emergency_contact");
|
||||||
},
|
},
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
// counterText: '',
|
||||||
labelText: "Contact Number",
|
labelText: "Contact Number",
|
||||||
labelStyle:
|
labelStyle:
|
||||||
GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
|
GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
|
||||||
|
|||||||
@ -4,7 +4,7 @@ class SearchTraveler {
|
|||||||
final String lastName;
|
final String lastName;
|
||||||
final String email;
|
final String email;
|
||||||
final String mobileNo;
|
final String mobileNo;
|
||||||
|
String? empCode;
|
||||||
|
|
||||||
SearchTraveler({
|
SearchTraveler({
|
||||||
required this.travellerId,
|
required this.travellerId,
|
||||||
@ -12,20 +12,17 @@ class SearchTraveler {
|
|||||||
required this.lastName,
|
required this.lastName,
|
||||||
required this.email,
|
required this.email,
|
||||||
required this.mobileNo,
|
required this.mobileNo,
|
||||||
|
this.empCode,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
factory SearchTraveler.fromJson(Map<String, dynamic> json) {
|
||||||
factory SearchTraveler.fromJson(Map<String, dynamic> json){
|
|
||||||
return SearchTraveler(
|
return SearchTraveler(
|
||||||
|
|
||||||
travellerId: json['traveller_id'].toString(),
|
travellerId: json['traveller_id'].toString(),
|
||||||
firstName: json['first_name'].toString()?? '',
|
firstName: json['first_name'].toString() ?? '',
|
||||||
lastName: json['last_name'].toString()?? '',
|
lastName: json['last_name'].toString() ?? '',
|
||||||
email: json['email'].toString()?? '',
|
email: json['email'].toString() ?? '',
|
||||||
mobileNo: json['mobile_no'].toString()?? '',
|
mobileNo: json['mobile'].toString() ?? '',
|
||||||
|
empCode: json['employee_code'].toString() ?? '',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,10 +1,11 @@
|
|||||||
class SearchUser{
|
class SearchUser {
|
||||||
final String userId;
|
final String userId;
|
||||||
final String firstName;
|
final String firstName;
|
||||||
final String lastName;
|
final String lastName;
|
||||||
final String email;
|
final String email;
|
||||||
final String mobileNo;
|
final String mobileNo;
|
||||||
final String alternateMobileNo;
|
final String alternateMobileNo;
|
||||||
|
String? empCode;
|
||||||
|
|
||||||
SearchUser({
|
SearchUser({
|
||||||
required this.userId,
|
required this.userId,
|
||||||
@ -13,18 +14,18 @@ class SearchUser{
|
|||||||
required this.email,
|
required this.email,
|
||||||
required this.mobileNo,
|
required this.mobileNo,
|
||||||
required this.alternateMobileNo,
|
required this.alternateMobileNo,
|
||||||
});
|
this.empCode,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory SearchUser.fromJson(Map<String, dynamic> json) {
|
||||||
factory SearchUser.fromJson(Map<String, dynamic> json){
|
|
||||||
return SearchUser(
|
return SearchUser(
|
||||||
userId: json['user_id'].toString(),
|
userId: json['user_id'].toString(),
|
||||||
firstName: json['first_name'].toString()?? '',
|
firstName: json['first_name'].toString() ?? '',
|
||||||
lastName: json['last_name'].toString()?? '',
|
lastName: json['last_name'].toString() ?? '',
|
||||||
email: json['email'].toString()?? '',
|
email: json['email'].toString() ?? '',
|
||||||
mobileNo: json['mobile_no'].toString()?? '',
|
mobileNo: json['mobile_no'].toString() ?? '',
|
||||||
alternateMobileNo: json['alternate_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'),
|
TabSelection.allTrips, '/listAllPlan'),
|
||||||
layoutColor!,
|
layoutColor!,
|
||||||
isSelected: selectedTab == TabSelection.allTrips,
|
isSelected: selectedTab == TabSelection.allTrips,
|
||||||
icon: Icons.insights_outlined,
|
icon: Icons.format_list_bulleted_rounded,
|
||||||
|
// icon: Icons.insights_outlined,
|
||||||
),
|
),
|
||||||
|
|
||||||
if (userDetails["role"] != "Travel Agent")
|
if (userDetails["role"] != "Travel Agent")
|
||||||
@ -282,7 +283,8 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
|||||||
layoutColor!,
|
layoutColor!,
|
||||||
// () => context.go('/listTravelAgentPlan'),
|
// () => context.go('/listTravelAgentPlan'),
|
||||||
isSelected: selectedTab == TabSelection.myTrips,
|
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
|
if (userData?["role"] != "Travel Agent") // for others
|
||||||
@ -368,8 +370,6 @@ class _CustomAppBarState extends State<CustomAppBar> {
|
|||||||
break;
|
break;
|
||||||
case '/PolicyList':
|
case '/PolicyList':
|
||||||
context.go('/PolicyList');
|
context.go('/PolicyList');
|
||||||
case '/templatesList':
|
|
||||||
context.go('/templatesList');
|
|
||||||
case '/CreateUserDetails':
|
case '/CreateUserDetails':
|
||||||
context.go(
|
context.go(
|
||||||
"/CreateUserDetails",
|
"/CreateUserDetails",
|
||||||
@ -511,11 +511,6 @@ final List<Map<String, dynamic>> menuItems = [
|
|||||||
'icon': Icons.account_circle,
|
'icon': Icons.account_circle,
|
||||||
'label': 'My Profile'
|
'label': 'My Profile'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
'value': '/templatesList',
|
|
||||||
'icon': Icons.temple_buddhist_outlined,
|
|
||||||
'label': 'My Templates'
|
|
||||||
},
|
|
||||||
{'value': '/logout', 'icon': Icons.login_outlined, 'label': 'Logout'},
|
{'value': '/logout', 'icon': Icons.login_outlined, 'label': 'Logout'},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:frontend/Screens/authentication/login/login_page.dart';
|
import 'package:frontend/Screens/authentication/login/login_page.dart';
|
||||||
import 'package:frontend/Screens/authentication/loginPage1.dart';
|
import 'package:frontend/Screens/authentication/loginPage1.dart';
|
||||||
import 'package:frontend/Screens/dashboard/home_page.dart';
|
import 'package:frontend/Screens/dashboard/home_page.dart';
|
||||||
import 'package:frontend/Screens/myTemplates/templatesList.dart';
|
import 'package:frontend/Screens/forex/forex_list.dart';
|
||||||
import 'package:frontend/Screens/organization/orgSetup.dart';
|
import 'package:frontend/Screens/organization/orgSetup.dart';
|
||||||
import 'package:frontend/Screens/organization/org_List.dart';
|
import 'package:frontend/Screens/organization/org_List.dart';
|
||||||
import 'package:frontend/Screens/plans/create_plans.dart';
|
import 'package:frontend/Screens/plans/create_plans.dart';
|
||||||
@ -44,10 +44,6 @@ final GoRouter router = GoRouter(
|
|||||||
path: '/listPlan',
|
path: '/listPlan',
|
||||||
builder: (context, state) => ListPlans(),
|
builder: (context, state) => ListPlans(),
|
||||||
),
|
),
|
||||||
GoRoute(
|
|
||||||
path: '/templatesList',
|
|
||||||
builder: (context, state) => templatesList(),
|
|
||||||
),
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/createPlan',
|
path: '/createPlan',
|
||||||
builder: (context, state) => CreatePlan(),
|
builder: (context, state) => CreatePlan(),
|
||||||
|
|||||||
@ -227,6 +227,7 @@ class CommentModalState extends State<CommentModal> {
|
|||||||
// You can also make a TextEditingController if you want to collect input
|
// You can also make a TextEditingController if you want to collect input
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 10),
|
contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 10),
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||||
content: Column(
|
content: Column(
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:responsive_builder/responsive_builder.dart';
|
import 'package:responsive_builder/responsive_builder.dart';
|
||||||
|
|
||||||
class CustomTextField extends StatelessWidget {
|
class CustomTextField extends StatelessWidget {
|
||||||
@ -22,7 +23,7 @@ class CustomTextField extends StatelessWidget {
|
|||||||
double widthFactor;
|
double widthFactor;
|
||||||
|
|
||||||
if (sizingInfo.deviceScreenType == DeviceScreenType.desktop) {
|
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) {
|
} else if (sizingInfo.deviceScreenType == DeviceScreenType.tablet) {
|
||||||
widthFactor = 0.8; // Slightly reduced width for tablets
|
widthFactor = 0.8; // Slightly reduced width for tablets
|
||||||
} else {
|
} else {
|
||||||
@ -31,49 +32,58 @@ class CustomTextField extends StatelessWidget {
|
|||||||
|
|
||||||
return Center(
|
return Center(
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 35,
|
height: 40,
|
||||||
width: MediaQuery.of(context).size.width * widthFactor,
|
width: MediaQuery.of(context).size.width * widthFactor,
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
keyboardType: keyboardType,
|
keyboardType: keyboardType,
|
||||||
cursorColor: Colors.blueAccent,
|
cursorColor: Colors.blueAccent,
|
||||||
style: TextStyle(fontSize: 12.0),
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintStyle: TextStyle(color: Colors.grey),
|
hintStyle: GoogleFonts.poppins(color: Colors.grey),
|
||||||
floatingLabelStyle: TextStyle(color: Colors.blueAccent,),
|
floatingLabelStyle: GoogleFonts.poppins(
|
||||||
|
// color: Colors.black,
|
||||||
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||||
labelText: labelText,
|
labelText: labelText,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 8, horizontal: 12), // Reduces inner padding
|
contentPadding: EdgeInsets.symmetric(
|
||||||
errorStyle: TextStyle(fontSize: 10, height: 0.8, color: Colors.red),
|
vertical: 8, horizontal: 12), // Reduces inner padding
|
||||||
|
errorStyle: GoogleFonts.poppins(
|
||||||
|
fontSize: 10, height: 0.8, color: Colors.red),
|
||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
borderSide: BorderSide(color: Colors.grey, width: 1), // Grey border
|
borderSide: BorderSide(
|
||||||
|
color: Colors.grey.shade200, width: 1), // Grey border
|
||||||
),
|
),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
borderSide: BorderSide(color: Colors.grey, width: 1), // Grey border when not focused
|
borderSide: BorderSide(
|
||||||
|
color: Colors.grey.shade200,
|
||||||
|
width: 1), // Grey border when not focused
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
borderSide: BorderSide(color: Colors.blueAccent, width: 2), // Blue border when focused
|
borderSide: BorderSide(
|
||||||
|
color: Colors.grey.shade200,
|
||||||
|
width: 1), // Blue border when focused
|
||||||
),
|
),
|
||||||
errorBorder: OutlineInputBorder(
|
errorBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
borderSide: BorderSide(color: Colors.grey, width: 1), // Same as normal
|
borderSide: BorderSide(
|
||||||
|
color: Colors.grey.shade200, width: 1), // Same as normal
|
||||||
),
|
),
|
||||||
focusedErrorBorder: OutlineInputBorder(
|
focusedErrorBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
borderSide: BorderSide(color: Colors.blueAccent, width: 2), // Same as focused
|
borderSide: BorderSide(
|
||||||
|
color: Colors.grey.shade200, width: 1), // Same as focused
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
validator: validator,
|
validator: validator,
|
||||||
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
);
|
);
|
||||||
|
},
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,24 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../Screens/allTrips/remarks_list.dart';
|
||||||
import '../data/models/plan.dart';
|
import '../data/models/plan.dart';
|
||||||
import '../services/apiService.dart';
|
import '../services/apiService.dart';
|
||||||
|
import '../utils/travelAgent_remarks.dart';
|
||||||
import 'custom_popup.dart';
|
import 'custom_popup.dart';
|
||||||
|
|
||||||
class PlanPopupMenu extends StatelessWidget {
|
class PlanPopupMenu extends StatelessWidget {
|
||||||
final Plan plan;
|
final Plan plan;
|
||||||
final Function(String planId) deletePlan;
|
final Function(String planId) deletePlan;
|
||||||
final ApiService apiService;
|
final ApiService apiService;
|
||||||
|
final Color? layoutColor;
|
||||||
|
|
||||||
const PlanPopupMenu({
|
const PlanPopupMenu({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.plan,
|
required this.plan,
|
||||||
required this.deletePlan,
|
required this.deletePlan,
|
||||||
required this.apiService,
|
required this.apiService,
|
||||||
|
required this.layoutColor,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -72,6 +76,38 @@ class PlanPopupMenu extends StatelessWidget {
|
|||||||
apiService.getPdfDownload(plan.planId);
|
apiService.getPdfDownload(plan.planId);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.comment,
|
||||||
|
color: Color(0xFF475569),
|
||||||
|
size: 11,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => CommentModalList(
|
||||||
|
// planId: plan.planId,
|
||||||
|
planId: plan.planId.toString(),
|
||||||
|
layoutColorForUser: layoutColor!,
|
||||||
|
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