report completed 2

This commit is contained in:
venba-Inspriron-3558 2025-06-18 16:26:09 +05:30
parent 25239c6e62
commit ce9bcb113b
12 changed files with 5167 additions and 2108 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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