report completed 2
This commit is contained in:
parent
25239c6e62
commit
ce9bcb113b
@ -94,6 +94,8 @@ class _PolicyListState extends State<PolicyList> {
|
||||
futurePolicy.then((object) {
|
||||
setState(() {
|
||||
allPolicy = object;
|
||||
filteredPolicy = object;
|
||||
searchController.text = "";
|
||||
});
|
||||
});
|
||||
// Wait for futurePlans to be fetched and update allPlans
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:core';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
@ -8,23 +10,23 @@ import 'package:frontend/config/apiUrl.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:responsive_builder/responsive_builder.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:universal_html/html.dart' as html;
|
||||
|
||||
import '../../routes/custom_appBar.dart';
|
||||
import '../../routes/custom_drawer.dart';
|
||||
import '../../routes/mainLayout.dart';
|
||||
import '../../services/apiService.dart';
|
||||
import '../../utils/auth_utils.dart';
|
||||
import '../../utils/pagination.dart';
|
||||
import '../../widgets/custom_text_field.dart';
|
||||
|
||||
class AdvancePurchase extends StatefulWidget {
|
||||
const AdvancePurchase({super.key});
|
||||
class MIShotel extends StatefulWidget {
|
||||
const MIShotel({super.key});
|
||||
|
||||
@override
|
||||
_AdvancePurchaseState createState() => _AdvancePurchaseState();
|
||||
_MIShotelState createState() => _MIShotelState();
|
||||
}
|
||||
|
||||
class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
class _MIShotelState extends State<MIShotel>
|
||||
with SingleTickerProviderStateMixin {
|
||||
final ApiService apiService = ApiService();
|
||||
|
||||
@ -42,12 +44,12 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
int currentPage2 = 0;
|
||||
int itemsPerPage2 = 10;
|
||||
late TabController _tabController;
|
||||
final List<String> tabNames = ['Domestic', 'International'];
|
||||
String selectedTabName = 'domestic';
|
||||
Map<String, FocusNode> focusNodes = {};
|
||||
Map<String, bool> focusStates = {};
|
||||
Map<String, TextEditingController> textControllers = {};
|
||||
Map<String, String> errorMessages = {};
|
||||
// Map<String, dynamic> advancePurchaseReport = {};
|
||||
// Map<String, dynamic> MIShotelReport = {};
|
||||
List<Map<String, dynamic>> domesticData = [];
|
||||
List<Map<String, dynamic>> internationalData = [];
|
||||
// Map<String, dynamic> domesticData = {};
|
||||
@ -59,6 +61,7 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
void initState() {
|
||||
super.initState();
|
||||
loadInitialData();
|
||||
_checkAuthAndLoadData();
|
||||
if (!textControllers.containsKey("from_date")) {
|
||||
textControllers["from_date"] = TextEditingController();
|
||||
}
|
||||
@ -83,6 +86,9 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
_tabController.addListener(() {
|
||||
if (_tabController.indexIsChanging == false) {
|
||||
// Only fire when tab change is complete
|
||||
setState(() {
|
||||
selectedTabName = getTabName(_tabController.index);
|
||||
});
|
||||
print(" :) :X Selected Tab: ${getTabName(_tabController.index)}");
|
||||
}
|
||||
});
|
||||
@ -97,17 +103,18 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
});
|
||||
|
||||
getToken();
|
||||
// fetchAdvancePurchaseReport();
|
||||
// fetchMIShotelReport();
|
||||
}
|
||||
|
||||
String getTabName(int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return "Domestic";
|
||||
return "domestic";
|
||||
case 1:
|
||||
return "International";
|
||||
return "international";
|
||||
default:
|
||||
return "Unknown";
|
||||
// return "Unknown";
|
||||
return "domestic";
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,7 +125,26 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
});
|
||||
});
|
||||
}
|
||||
void _checkAuthAndLoadData() async {
|
||||
final String? token = await getToken(); // Your async function to get token
|
||||
|
||||
if (token == null || token.isEmpty) {
|
||||
// Token doesn't exist → redirect to login
|
||||
context.go(
|
||||
"/",
|
||||
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||
return;
|
||||
}
|
||||
if (!mounted) return;
|
||||
try {
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
loadInitialData();
|
||||
});
|
||||
} catch (e) {
|
||||
print("service report : $e");
|
||||
}
|
||||
}
|
||||
void loadInitialData() async {
|
||||
String? layoutString = await getLayoutColor();
|
||||
String? bodyStringColor = await getBodyColor();
|
||||
@ -190,14 +216,18 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
setState(() {
|
||||
domesticData = [];
|
||||
internationalData = [];
|
||||
currentPage1 = 0;
|
||||
itemsPerPage1 = 10;
|
||||
currentPage2 = 0;
|
||||
itemsPerPage2 = 10;
|
||||
});
|
||||
final fromDateText = textControllers["from_date"]?.text;
|
||||
final toDateText = textControllers["to_date"]?.text;
|
||||
|
||||
if (fromDateText == null || fromDateText.isEmpty ||
|
||||
toDateText == null || toDateText.isEmpty) {
|
||||
errorMessages["from_date"] = "Required";
|
||||
errorMessages["to_date"] = "Required";
|
||||
fromDateText == null || fromDateText.isEmpty ? errorMessages["from_date"] = "Required" : errorMessages.remove("from_date");
|
||||
toDateText == null || toDateText.isEmpty ? errorMessages["to_date"] = "Required" : errorMessages.remove("to_date");
|
||||
setState(() {});
|
||||
return;
|
||||
}
|
||||
@ -224,13 +254,18 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
loaderFlag = true;
|
||||
try {
|
||||
final result = await apiService.CallReports(
|
||||
'advancePurchaseReport',
|
||||
formattedfromDate,
|
||||
formattedtoDate,
|
||||
'misHotelReport',
|
||||
jsonEncode({"fromDate":'$formattedfromDate',"toDate":'$formattedtoDate'}),
|
||||
);
|
||||
setState(() {
|
||||
domesticData = List<Map<String, dynamic>>.from(result['data']['domestic'] ?? []);
|
||||
internationalData = List<Map<String, dynamic>>.from(result['data']['international'] ?? []);
|
||||
// domesticData = List<Map<String, dynamic>>.from(result['data']['domestic'] ?? []);
|
||||
domesticData = List<Map<String, dynamic>>.from(
|
||||
result['status'] == 'success' ? result['data']['domestic'] ?? [] : []
|
||||
);
|
||||
|
||||
internationalData = List<Map<String, dynamic>>.from(
|
||||
result['status'] == 'success' ? result['data']['international'] ?? [] : []
|
||||
);
|
||||
loaderFlag = false;
|
||||
});
|
||||
} catch (e) {
|
||||
@ -243,6 +278,51 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Future<void> handleDownload() async {
|
||||
final dateFormat = DateFormat('dd-MM-yyyy');
|
||||
|
||||
if (textControllers["from_date"]!.text.isEmpty || textControllers["to_date"]!.text.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
backgroundColor: Colors.redAccent,
|
||||
content: Text("Please choose a valid date range."),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final DateTime fromDate = dateFormat.parse(textControllers["from_date"]!.text);
|
||||
final DateTime toDate = dateFormat.parse(textControllers["to_date"]!.text);
|
||||
|
||||
final formattedFromDate = DateFormat('yyyy-MM-dd').format(fromDate);
|
||||
final formattedToDate = DateFormat('yyyy-MM-dd').format(toDate);
|
||||
|
||||
final name =
|
||||
'MIS Hotel - $selectedTabName Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})';
|
||||
final safeName = name.replaceAll(RegExp(r'[^\w\s-]'), '');
|
||||
final excelName = '$safeName';
|
||||
|
||||
final result = await apiService.reportExcelDownload(
|
||||
'misHotelReport',
|
||||
jsonEncode({
|
||||
"fromDate": formattedFromDate,
|
||||
"toDate": formattedToDate,
|
||||
"export": selectedTabName,
|
||||
}),
|
||||
excelName,
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
backgroundColor: Colors.green,
|
||||
content: Text(result as String),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
}
|
||||
@override
|
||||
// Widget build(BuildContext context) {
|
||||
// // TODO: implement build
|
||||
@ -274,7 +354,7 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
children: [
|
||||
// if (isDesktop) CustomDrawer(isDesktop: true),
|
||||
// const Expanded(child: Center(child: Text("User Page Content"))),
|
||||
Expanded(child: buildAdvancePurchaseLayout(isDesktop))
|
||||
Expanded(child: buildMIShotelLayout(isDesktop))
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -283,11 +363,11 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildAdvancePurchaseLayout(bool isDesktop) {
|
||||
return Container( child: buildAdvancePurchaseFormLayout(isDesktop) );
|
||||
Widget buildMIShotelLayout(bool isDesktop) {
|
||||
return Container( child: buildMIShotelFormLayout(isDesktop) );
|
||||
}
|
||||
|
||||
Widget buildAdvancePurchaseFormLayout(bool isDesktop) {
|
||||
Widget buildMIShotelFormLayout(bool isDesktop) {
|
||||
return Container(
|
||||
margin: isDesktop ? EdgeInsets.all(10.0) : null,
|
||||
padding: const EdgeInsets.only(top: 5, bottom: 5, left: 20, right: 20),
|
||||
@ -309,7 +389,7 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Advance Purchase',
|
||||
'Mis Hotel Report',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: isDesktop ? 16 : 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -327,9 +407,7 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
),
|
||||
onPressed: () {
|
||||
// Your Excel export logic here
|
||||
},
|
||||
onPressed: handleDownload,
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
@ -344,33 +422,33 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Color(0xFF114D8B),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
),
|
||||
onPressed: () {
|
||||
// Your PDF export logic here
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"PDF",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: isDesktop ? 13 : 11,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white),
|
||||
],
|
||||
),
|
||||
),
|
||||
// SizedBox(width: 10),
|
||||
// ElevatedButton(
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: Color(0xFF114D8B),
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
// ),
|
||||
// padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
// ),
|
||||
// onPressed: () {
|
||||
// // Your PDF export logic here
|
||||
// },
|
||||
// child: Row(
|
||||
// children: [
|
||||
// Text(
|
||||
// "PDF",
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: isDesktop ? 13 : 11,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(width: 8),
|
||||
// Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
],
|
||||
@ -519,43 +597,47 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
],
|
||||
),
|
||||
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||
SizedBox(
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Color(0xFF114D8B),
|
||||
foregroundColor: Colors.white,
|
||||
disabledBackgroundColor: Color(0xFF114D8B),
|
||||
disabledForegroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 10, left: 4),
|
||||
child : SizedBox(
|
||||
child: ElevatedButton(
|
||||
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Color(0xFF114D8B),
|
||||
foregroundColor: Colors.white,
|
||||
disabledBackgroundColor: Color(0xFF114D8B),
|
||||
disabledForegroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 12,
|
||||
),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 12,
|
||||
),
|
||||
),
|
||||
onPressed: () {handleSubmit();},
|
||||
child: Row(
|
||||
mainAxisSize:
|
||||
MainAxisSize.min, // Ensures content fits nicely
|
||||
children: [
|
||||
Text(
|
||||
"Search",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: isDesktop ? 13 : 11,
|
||||
onPressed: () {handleSubmit();},
|
||||
child: Row(
|
||||
mainAxisSize:
|
||||
MainAxisSize.min, // Ensures content fits nicely
|
||||
children: [
|
||||
Text(
|
||||
"Search",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: isDesktop ? 13 : 11,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8), // spacing between icon and text
|
||||
Icon(
|
||||
Icons.search,
|
||||
size: 15,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
SizedBox(width: 8), // spacing between icon and text
|
||||
Icon(
|
||||
Icons.search,
|
||||
size: 15,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
@ -616,65 +698,61 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
overflow: TextOverflow.ellipsis, // Ensures title doesn't overflow
|
||||
),
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
/// Buttons on the right
|
||||
Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Color(0xFF114D8B),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
),
|
||||
onPressed: () {
|
||||
// Excel export logic
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"Excel",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: isDesktop ? 13 : 11,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Icon(Icons.file_present_outlined, size: 15, color: Colors.white),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Color(0xFF114D8B),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
),
|
||||
onPressed: () {
|
||||
// PDF export logic
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"PDF",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: isDesktop ? 13 : 11,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// SizedBox(width: 16),
|
||||
// /// Buttons on the right
|
||||
// Row(
|
||||
// children: [
|
||||
// ElevatedButton(
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: Color(0xFF114D8B),
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
// ),
|
||||
// padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
// ),
|
||||
// onPressed: handleDownload,
|
||||
// child: Row(
|
||||
// children: [
|
||||
// Text(
|
||||
// "Excel",
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: isDesktop ? 13 : 11,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(width: 8),
|
||||
// Icon(Icons.file_present_outlined, size: 15, color: Colors.white),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(width: 10),
|
||||
// ElevatedButton(
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: Color(0xFF114D8B),
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
// ),
|
||||
// padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
// ),
|
||||
// onPressed: handleDownload,
|
||||
// child: Row(
|
||||
// children: [
|
||||
// Text(
|
||||
// "PDF",
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: isDesktop ? 13 : 11,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(width: 8),
|
||||
// Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -748,26 +826,40 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
color: Colors.grey.shade200,
|
||||
),
|
||||
),
|
||||
// rows: paginatedDomestic
|
||||
columns: [
|
||||
DataColumn(label: Text('Plan Id', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Employee Code', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Employee Name', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('SO Number', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Department', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Flight Trip Type', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Plan Trip Type', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Sector', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Hotel Name', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Hotel City', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Check In Date', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Check Out Date', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
],
|
||||
rows: paginatedDomestic.map((entry) {
|
||||
final checkInDate = DateFormat('dd-MM-yyyy').format(DateTime.parse(entry['check_in_date']));
|
||||
final checkOutDate = DateFormat('dd-MM-yyyy').format(DateTime.parse(entry['check_out_date']));
|
||||
|
||||
return DataRow(cells: [
|
||||
DataCell(Text('${entry['plan_id']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['employee_code']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['employee_name']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['so_number']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['functional_department']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['flight_trip_type']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['plan_trip_type']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['sector']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['hotel_name']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['hotel_city']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text(checkInDate, style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text(checkOutDate, style: GoogleFonts.poppins(fontSize: 12))),
|
||||
|
||||
]);
|
||||
}).toList(),
|
||||
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -971,24 +1063,35 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
|
||||
color: Colors.grey.shade200,
|
||||
),
|
||||
),
|
||||
// rows: paginatedInternational
|
||||
columns: [
|
||||
DataColumn(label: Text('Plan Id', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Employee Code', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Employee Name', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('SO Number', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Department', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Flight Trip Type', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Plan Trip Type', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Sector', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Hotel Name', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Hotel City', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Check In Date', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
DataColumn(label: Text('Check Out Date', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
],
|
||||
rows: paginatedInternational.map((entry) {
|
||||
final checkInDate = DateFormat('dd-MM-yyyy').format(DateTime.parse(entry['check_in_date']));
|
||||
final checkOutDate = DateFormat('dd-MM-yyyy').format(DateTime.parse(entry['check_out_date']));
|
||||
return DataRow(cells: [
|
||||
DataCell(Text('${entry['plan_id']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['employee_code']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['employee_name']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['so_number']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['functional_department']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['flight_trip_type']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['plan_trip_type']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['sector']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['hotel_name']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text('${entry['hotel_city']}', style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text(checkInDate, style: GoogleFonts.poppins(fontSize: 12))),
|
||||
DataCell(Text(checkOutDate, style: GoogleFonts.poppins(fontSize: 12))),
|
||||
]);
|
||||
}).toList(),
|
||||
),
|
||||
|
||||
@ -30,6 +30,7 @@ class _ReportListState extends State<ReportList> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
loadInitialData();
|
||||
_checkAuthAndLoadData();
|
||||
}
|
||||
|
||||
void loadInitialData() async {
|
||||
@ -38,13 +39,32 @@ class _ReportListState extends State<ReportList> {
|
||||
|
||||
setState(() {
|
||||
layoutColor =
|
||||
layoutString != null
|
||||
? Color(int.parse(layoutString))
|
||||
: Colors.redAccent;
|
||||
|
||||
layoutString != null
|
||||
? Color(int.parse(layoutString))
|
||||
: Colors.redAccent;
|
||||
});
|
||||
}
|
||||
|
||||
void _checkAuthAndLoadData() async {
|
||||
final String? token = await getToken(); // Your async function to get token
|
||||
|
||||
if (token == null || token.isEmpty) {
|
||||
// Token doesn't exist → redirect to login
|
||||
context.go(
|
||||
"/",
|
||||
); // or use: router.go("/") if you're using `GoRouter` directly
|
||||
return;
|
||||
}
|
||||
if (!mounted) return;
|
||||
try {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
loadInitialData();
|
||||
});
|
||||
} catch (e) {
|
||||
print("service report : $e");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ResponsiveBuilder(
|
||||
@ -62,16 +82,16 @@ class _ReportListState extends State<ReportList> {
|
||||
drawer: CustomDrawer(isDesktop: false),
|
||||
body: Padding(
|
||||
padding:
|
||||
isDesktop
|
||||
? EdgeInsets.symmetric(
|
||||
horizontal:
|
||||
MediaQuery.of(context).size.width *
|
||||
0.1, // 30% of screen width as horizontal padding
|
||||
vertical:
|
||||
MediaQuery.of(context).size.height *
|
||||
0, // 5% of screen height as vertical padding
|
||||
)
|
||||
: EdgeInsets.all(0),
|
||||
isDesktop
|
||||
? EdgeInsets.symmetric(
|
||||
horizontal:
|
||||
MediaQuery.of(context).size.width *
|
||||
0.1, // 30% of screen width as horizontal padding
|
||||
vertical:
|
||||
MediaQuery.of(context).size.height *
|
||||
0, // 5% of screen height as vertical padding
|
||||
)
|
||||
: EdgeInsets.all(0),
|
||||
child: Row(
|
||||
children: [
|
||||
// if (isDesktop) CustomDrawer(isDesktop: true),
|
||||
@ -97,38 +117,37 @@ class _ReportListState extends State<ReportList> {
|
||||
{
|
||||
'value': '/misServicesAnalysis',
|
||||
'icon': Icons.miscellaneous_services,
|
||||
'label': 'Miscellaneous Services Analysis',
|
||||
'description': 'View Miscellaneous Services Analysis',
|
||||
'label': 'MIS Services Analysis',
|
||||
'description': 'View MIS Services Analysis',
|
||||
},
|
||||
{
|
||||
'value': '/misAirReport',
|
||||
'icon': Icons.flight,
|
||||
'label': 'Miscellaneous Air Report',
|
||||
'description': 'View Miscellaneous Air Report',
|
||||
'label': 'MIS Air Report',
|
||||
'description': 'View MIS Air Report',
|
||||
},
|
||||
{
|
||||
'value': '/misHotelReport',
|
||||
'icon': Icons.add_business,
|
||||
'label': 'Miscellaneous Hotel Report',
|
||||
'description': 'View Miscellaneous Hotel Report',
|
||||
'label': 'MIS Hotel Report',
|
||||
'description': 'View MIS Hotel Report',
|
||||
},
|
||||
|
||||
{
|
||||
'value': '/misForexReport',
|
||||
'icon': Icons.credit_card,
|
||||
'label': 'Miscellaneous Forex Report',
|
||||
'description': 'View Miscellaneous Forex Report',
|
||||
'label': 'MIS Forex Report',
|
||||
'description': 'View MIS Forex Report',
|
||||
},
|
||||
|
||||
{
|
||||
'value': '/guestHouseReport',
|
||||
'icon': Icons.add_home_work_sharp,
|
||||
'icon': Icons.home_work,
|
||||
'label': 'Guest House Report',
|
||||
'description': 'View Guest House Report',
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 16, horizontal: 12),
|
||||
child: Column(
|
||||
@ -152,73 +171,73 @@ class _ReportListState extends State<ReportList> {
|
||||
spacing: 16,
|
||||
runSpacing: 16,
|
||||
children:
|
||||
menuItems.map((item) {
|
||||
return SizedBox(
|
||||
width: isDesktop ? 325 : double.infinity,
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
if (item['value'] as String ==
|
||||
"/forexTexmplate") {
|
||||
final data =
|
||||
await apiService.getForexTemplate();
|
||||
print("ForexId -- $data");
|
||||
menuItems.map((item) {
|
||||
return SizedBox(
|
||||
width: isDesktop ? 325 : double.infinity,
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
if (item['value'] as String ==
|
||||
"/forexTexmplate") {
|
||||
final data =
|
||||
await apiService.getForexTemplate();
|
||||
print("ForexId -- $data");
|
||||
|
||||
context.go(
|
||||
'/templateForex',
|
||||
extra: {'templateData': data},
|
||||
);
|
||||
} else {
|
||||
final route = item['value'] as String;
|
||||
context.go(route);
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(12),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
item['icon'],
|
||||
size: 40,
|
||||
color: layoutColor,
|
||||
// color: Color(0xFF114D8B),
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
item['label'],
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
context.go(
|
||||
'/templateForex',
|
||||
extra: {'templateData': data},
|
||||
);
|
||||
} else {
|
||||
final route = item['value'] as String;
|
||||
context.go(route);
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(12),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
item['icon'],
|
||||
size: 40,
|
||||
color: layoutColor,
|
||||
// color: Color(0xFF114D8B),
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
item['label'],
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
item['description'],
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: false,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey[700],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
item['description'],
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: false,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey[700],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,3 @@
|
||||
//api url
|
||||
// const String apiUrl = 'http://apitest.tripapprovaltool.com/tstat_be';
|
||||
const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be';
|
||||
const String apiUrl = 'http://apitest.tripapprovaltool.com/tstat_be';
|
||||
// const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be';
|
||||
|
||||
@ -632,11 +632,11 @@ final List<Map<String, dynamic>> menuItems = [
|
||||
// 'label': 'Template List'
|
||||
// },
|
||||
// {'value': '/template', 'icon': Icons.ac_unit_sharp, 'label': 'Template'},
|
||||
// {
|
||||
// 'value': '/report',
|
||||
// 'icon': Icons.auto_graph,
|
||||
// 'label': 'Reports',
|
||||
// },
|
||||
{
|
||||
'value': '/report',
|
||||
'icon': Icons.auto_graph,
|
||||
'label': 'Reports',
|
||||
},
|
||||
{
|
||||
'value': '/CreateUserDetails',
|
||||
'icon': Icons.account_circle,
|
||||
|
||||
@ -35,9 +35,9 @@ import '../Screens/traveller/travellerList.dart';
|
||||
import '../Screens/reports/reportList.dart';
|
||||
import '../Screens/reports/advancePurchase.dart';
|
||||
import '../Screens/reports/servicesAnalysis.dart';
|
||||
import '../Screens/reports/miscellaneousAir.dart';
|
||||
import '../Screens/reports/miscellaneousHotel.dart';
|
||||
import '../Screens/reports/miscellaneousForex.dart';
|
||||
import '../Screens/reports/misAir.dart';
|
||||
import '../Screens/reports/misHotel.dart';
|
||||
import '../Screens/reports/misForex.dart';
|
||||
import '../Screens/reports/guestHouse.dart';
|
||||
|
||||
import 'mainLayout.dart';
|
||||
@ -164,15 +164,15 @@ final GoRouter router = GoRouter(
|
||||
),
|
||||
GoRoute(
|
||||
path: '/misAirReport',
|
||||
builder: (context, state) => MiscellaneousAir(),
|
||||
builder: (context, state) => MISair(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/misHotelReport',
|
||||
builder: (context, state) => MiscellaneousHotel(),
|
||||
builder: (context, state) => MIShotel(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/misForexReport',
|
||||
builder: (context, state) => MiscellaneousForex(),
|
||||
builder: (context, state) => MISforex(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/guestHouseReport',
|
||||
|
||||
@ -1511,11 +1511,9 @@ class ApiService {
|
||||
|
||||
// ----------------------- User Management - CheckDuplicate end here ----------------------------------
|
||||
// ----------------------- Report -------------------------
|
||||
Future<Map<String, dynamic>> CallReports(String apiRoute,String FromDate,String ToDate) async {
|
||||
Future<Map<String, dynamic>> CallReports(String apiRoute,String body) async {
|
||||
String apiUrldata = '$apiUrl/api/$apiRoute';
|
||||
final token = await getToken();
|
||||
final body = jsonEncode({"fromDate":'$FromDate',"toDate":'$ToDate'});
|
||||
|
||||
|
||||
if (token == null) {
|
||||
throw Exception('Token not found. Please log in.');
|
||||
@ -1536,9 +1534,58 @@ class ApiService {
|
||||
}
|
||||
} else {
|
||||
throw Exception(
|
||||
'Failed to load checkDuplicate data. Status code: ${response.statusCode}',
|
||||
'Failed to load data. Status code: ${response.statusCode}',
|
||||
);
|
||||
}
|
||||
}
|
||||
// ----------------------- Report -------------------------
|
||||
|
||||
Future<void> reportExcelDownload(String apiRoute,String body,String name) async {
|
||||
final String apiUrldata = '$apiUrl/api/$apiRoute';
|
||||
|
||||
// Sanitize name for filename (optional)
|
||||
final safeName = name.replaceAll(RegExp(r'[^\w\s-]'), ''); // remove any special chars if needed
|
||||
final excelName = '$safeName.xlsx';
|
||||
|
||||
|
||||
final token = await getToken();
|
||||
|
||||
if (token == null) {
|
||||
throw Exception('Token not found. Please log in.');
|
||||
}
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse(apiUrldata),
|
||||
headers: {'Authorization': 'Bearer $token','Content-Type': 'application/json'},
|
||||
body: body
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
print("report XL Dowloaded");
|
||||
print(excelName);
|
||||
// Create a blob from the response body
|
||||
final blob = html.Blob([response.bodyBytes]);
|
||||
|
||||
// Generate a download URL for the blob
|
||||
final url = html.Url.createObjectUrlFromBlob(blob);
|
||||
|
||||
// Create a link element to trigger the download
|
||||
final anchor =
|
||||
html.AnchorElement(href: url)
|
||||
..setAttribute('download', excelName)
|
||||
..click();
|
||||
|
||||
// Revoke the download URL to free up resources
|
||||
html.Url.revokeObjectUrl(url);
|
||||
throw Exception('Sucessfully Downloaded');
|
||||
} catch (e) {
|
||||
throw Exception('Error parsing response: $e');
|
||||
}
|
||||
} else if (response.statusCode == 404) {
|
||||
throw Exception('File not found.');
|
||||
} else {
|
||||
throw Exception('Failed to Download');
|
||||
}
|
||||
}
|
||||
// ----------------------- Report -------------------------
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user