diff --git a/assets/claim.png b/assets/claim.png index 4caf897..9390709 100644 Binary files a/assets/claim.png and b/assets/claim.png differ diff --git a/assets/credit_card.png b/assets/credit_card.png index 4e720c1..119ab6d 100644 Binary files a/assets/credit_card.png and b/assets/credit_card.png differ diff --git a/lib/customAppBar/customAppBar.dart b/lib/customAppBar/customAppBar.dart index 79e59cd..94b795e 100755 --- a/lib/customAppBar/customAppBar.dart +++ b/lib/customAppBar/customAppBar.dart @@ -30,6 +30,7 @@ class _CustomAppBarState extends State { // final String? hrtoken = prefs.getString('_postToken'); // final String? token = prefs.getString('enrollToken'); prefs.clear(); + print('LocalStorage Cleared'); Navigator.pushNamed(context, 'hrLogin'); } diff --git a/lib/excel_verification.dart b/lib/excel_verification.dart index c04799d..f0e1883 100755 --- a/lib/excel_verification.dart +++ b/lib/excel_verification.dart @@ -1018,9 +1018,7 @@ class _excelVerifyState extends State { ], ) : ElevatedButton( - onPressed: () => - _uploadFile( - 'Policy Name'), + onPressed: () => _uploadFile('Policy Name'), child: Text( 'Select File', style: TextStyle( diff --git a/lib/hrDashboard.dart b/lib/hrDashboard.dart index 9d9b073..54c9f6f 100755 --- a/lib/hrDashboard.dart +++ b/lib/hrDashboard.dart @@ -80,7 +80,7 @@ class _hrDashboardState extends State void initState() { super.initState(); apiService = ApiService(context); // Initialize ApiService here - _loadToken(); + checkToken(); empCodeFromHrPolcy = widget.empCodeFromHrPolicy; // _tabController = TabController(length: 4, vsync: this); @@ -102,6 +102,22 @@ class _hrDashboardState extends State _tabController.dispose(); } + checkToken() async { + final SharedPreferences prefs = await SharedPreferences.getInstance(); + enrollToken = prefs.getString('enrollToken'); + _postToken = prefs.getString('_postToken'); + + print('token check in'); + if((enrollToken != null && enrollToken!.isNotEmpty) || (_postToken != null && _postToken!.isNotEmpty)){ + print('token check done'); + _loadToken(); + } else { + print('token check reject'); + ToastHelper.showErrorToast(context, 'Session Out'); + Navigator.pushReplacementNamed(context, 'hrLogin'); + } + } + Future _loadToken() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); _postToken = prefs.getString('_postToken'); diff --git a/lib/hrLogin.dart b/lib/hrLogin.dart index 3e54ae6..a6539f0 100755 --- a/lib/hrLogin.dart +++ b/lib/hrLogin.dart @@ -1,5 +1,6 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:http/http.dart' as http; @@ -40,10 +41,23 @@ class _MyPhoneState extends State { @override void initState() { + print('vndbbcbdskbvkjs1'); countryController.text = "+91"; super.initState(); + clearLocalStorageWhenStarts('initState'); } + clearLocalStorageWhenStarts(fromData) async { + print(fromData); + if(kIsWeb) { + print('vndbbcbdskbvkj3'); + final SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.clear(); + print('Local Storage Clear'); + } + } + + void toggleField() { setState(() { isEmailFieldVisible = !isEmailFieldVisible; @@ -51,6 +65,9 @@ class _MyPhoneState extends State { } Future verifyMobileAndEmailNumber() async { + final SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.clear(); + print('verifyMobileAndEmailNumber :- Local Storage Clear'); try { if (_formKey.currentState!.validate()) { setState(() { diff --git a/lib/hrPolicyDetails.dart b/lib/hrPolicyDetails.dart index b1e4bc0..25349bd 100755 --- a/lib/hrPolicyDetails.dart +++ b/lib/hrPolicyDetails.dart @@ -4,6 +4,7 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:nhancepolicy/customAppBar/customAppBar.dart'; import 'package:nhancepolicy/excel_verification.dart'; import 'package:nhancepolicy/models/environment.dart'; +import 'package:nhancepolicy/postFileUpload.dart'; import 'package:nhancepolicy/service/api_service.dart'; import 'package:nhancepolicy/service/hrDashboardTabs/claims.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -463,13 +464,13 @@ class _HrPolicyDetailsState extends State child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - if (widget.TokenType != "post") + // if (widget.TokenType != "post") ElevatedButton( onPressed: () { Navigator.push( context, MaterialPageRoute( - builder: (context) => excelVerify( + builder: (context) => widget.TokenType != "post" ? excelVerify( ClientId: widget.ClientId, // <-- from map policyTypeId: widget.policyTypeId, @@ -494,7 +495,32 @@ class _HrPolicyDetailsState extends State // PolicyNo: widget.cardPolicyNo, // ClientBranchId: widget.HrId, // PolicyType: widget.cardType, - ), + ) : postFileUpload( + ClientId: + widget.ClientId, // <-- from map + policyTypeId: widget.policyTypeId, + ClientPoliyId: widget.ClientPoliyId, + clientBranchId: + widget.clientBranchId, + Token: widget.Token, + TokenType: widget.TokenType, + cardType: widget.cardType, + cardPolicyNo: widget.cardPolicyNo, + cardInsurer_name: + widget.cardInsurer_name, + cardPolicy_name: + widget.cardPolicy_name, + cardPolicy_ExpDate: + widget.cardPolicy_ExpDate, + + // Token: widget.Token, + // ClientId: widget.ClientId, + // ClientPolicyId : widget.ClientPoliyId, + // PolicyName: widget.cardPolicy_name, + // PolicyNo: widget.cardPolicyNo, + // ClientBranchId: widget.HrId, + // PolicyType: widget.cardType, + ) ), ); // exportToCsv(filteredData); @@ -910,14 +936,14 @@ class _HrPolicyDetailsState extends State _launchURL(item['ecard_download_link']); }, child: Container( - height: 35, - width: 35, + height: 40, + width: 40, decoration: BoxDecoration( color: Color(0xFFE6F5F6), borderRadius: BorderRadius.circular(8), ), child: Padding( - padding: EdgeInsets.all(6), + padding: EdgeInsets.all(4), child: Image.asset( 'assets/credit_card.png', fit: BoxFit.contain, @@ -946,14 +972,14 @@ class _HrPolicyDetailsState extends State ); }, child: Container( - height: 35, - width: 35, + height: 40, + width: 40, decoration: BoxDecoration( color: Color(0xFFE6F5F6), borderRadius: BorderRadius.circular(8), ), child: Padding( - padding: EdgeInsets.all(6), + padding: EdgeInsets.all(4), child: Image.asset( 'assets/claim.png', fit: BoxFit.contain, diff --git a/lib/hrPolicyDetials b/lib/hrPolicyDetials deleted file mode 100644 index c22637f..0000000 --- a/lib/hrPolicyDetials +++ /dev/null @@ -1,887 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:nhancepolicy/customAppBar/enrollmentAppBar.dart'; -import 'package:nhancepolicy/excel_verification.dart'; -import 'package:nhancepolicy/models/environment.dart'; -import 'package:nhancepolicy/service/api_service.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:jwt_decode/jwt_decode.dart'; -import 'dart:convert'; -import 'dart:async'; -import 'package:http/http.dart' as http; -import 'package:nhancepolicy/customAppBar/toastHelper.dart'; -import 'package:universal_html/html.dart' as html; -import 'dart:typed_data'; -import 'dart:io'; -import 'package:flutter/foundation.dart' show kIsWeb; -import 'package:intl/intl.dart'; -import 'package:excel/excel.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:path/path.dart' as path; - -import 'customAppBar/customFooter.dart'; - -class hrPolicyDetails extends StatefulWidget { - const hrPolicyDetails({Key? key}) : super(key: key); - - @override - State createState() => _HrPolicyDetailsState(); -} - -class _HrPolicyDetailsState extends State - with TickerProviderStateMixin { - Uint8List? fileBytes; - late String _token; - List> getEmpDependenceByClintId = []; - bool isLoading = false; - bool _isLoading = false; - // dynamic clintID; - late TabController _tabController; - // List dataPolicy = []; - List reversedDataPolicy = []; - List> originalData = []; // Original data source - List> filteredData = []; // Filtered data source - dynamic argumentsData; - dynamic policyType; - dynamic policyName; - dynamic clientPolicyId; - dynamic clientId; - dynamic empRefId; - int inceptionType = 0; - TextEditingController searchController = TextEditingController(); - late ApiService apiService; - - @override - void initState() { - super.initState(); - apiService = ApiService(context); // Initialize ApiService here - _tabController = TabController(length: 4, vsync: this); - _loadToken(); - } - - @override - void dispose() { - _tabController.dispose(); - super.dispose(); - } - - Future _loadToken() async { - print('1'); - final SharedPreferences prefs = await SharedPreferences.getInstance(); - final token = prefs.getString('hrtoken'); - if (token != null && token.isNotEmpty) { - print('2'); - setState(() { - _token = token; - }); - Map? decodedToken = Jwt.parseJwt(token); - empRefId = prefs.getString('empRefId'); - // clintID = decodedToken['client_id']; - getPolicyDetails(); - } else { - // Token is empty or null, handle accordingly (e.g., navigate to login screen) - // For now, let's navigate to the login screen - ToastHelper.showErrorToast(context, 'Session Out'); - Navigator.pushReplacementNamed(context, 'hrLogin'); - } - } - - Future _saveArgumentsDataToLocalStorage(argumentsData) async { - print('6'); - print('argumentsData'); - final prefs = await SharedPreferences.getInstance(); - await prefs.setString('hrSelectArgumentsData', jsonEncode(argumentsData)); - } - - Future getPolicyDetails() async { - print('3'); - try { - print('4'); - setState(() { - if (argumentsData != null && argumentsData is Map) { - print('5'); - _saveArgumentsDataToLocalStorage(argumentsData); - print('7'); - if (argumentsData['type'] == 'GPA') { - print('8'); - _isLoading = true; - clientPolicyId = argumentsData['client_policy_id']; - clientId = argumentsData['client_id']; - policyType = argumentsData['type']; - policyName = argumentsData['policy_name']; - String int_inception_type = argumentsData['inception_type']; - inceptionType = int.parse(int_inception_type); - getEmployeeAndDependence(clientId, clientPolicyId); - } else if (argumentsData['type'] == 'GMC') { - _isLoading = true; - clientPolicyId = argumentsData['client_policy_id']; - clientId = argumentsData['client_id']; - policyType = argumentsData['type']; - policyName = argumentsData['policy_name']; - String int_inception_type = argumentsData['inception_type']; - inceptionType = int.parse(int_inception_type); - getEmployeeAndDependence(clientId, clientPolicyId); - } else if (argumentsData['type'] == 'GMC - Parents') { - _isLoading = true; - clientPolicyId = argumentsData['client_policy_id']; - clientId = argumentsData['client_id']; - policyType = argumentsData['type']; - policyName = argumentsData['policy_name']; - String int_inception_type = argumentsData['inception_type']; - inceptionType = int.parse(int_inception_type); - getEmployeeAndDependence(clientId, clientPolicyId); - } else if (argumentsData['type'] == 'GMC - Topup') { - _isLoading = true; - clientPolicyId = argumentsData['client_policy_id']; - clientId = argumentsData['client_id']; - policyType = argumentsData['type']; - policyName = argumentsData['policy_name']; - String int_inception_type = argumentsData['inception_type']; - inceptionType = int.parse(int_inception_type); - getEmployeeAndDependence(clientId, clientPolicyId); - } else if (argumentsData['type'] == 'GMC - Topup(Parents)') { - _isLoading = true; - clientPolicyId = argumentsData['client_policy_id']; - clientId = argumentsData['client_id']; - policyType = argumentsData['type']; - policyName = argumentsData['policy_name']; - String int_inception_type = argumentsData['inception_type']; - inceptionType = int.parse(int_inception_type); - getEmployeeAndDependence(clientId, clientPolicyId); - } else if (argumentsData['type'] == 'EDLI') { - _isLoading = true; - clientPolicyId = argumentsData['client_policy_id']; - clientId = argumentsData['client_id']; - policyType = argumentsData['type']; - policyName = argumentsData['policy_name']; - String int_inception_type = argumentsData['inception_type']; - inceptionType = int.parse(int_inception_type); - getEmployeeAndDependence(clientId, clientPolicyId); - } else if (argumentsData['type'] == 'GTLI') { - _isLoading = true; - clientPolicyId = argumentsData['client_policy_id']; - clientId = argumentsData['client_id']; - policyType = argumentsData['type']; - policyName = argumentsData['policy_name']; - String int_inception_type = argumentsData['inception_type']; - inceptionType = int.parse(int_inception_type); - getEmployeeAndDependence(clientId, clientPolicyId); - } - } - }); - } catch (e) { - _isLoading = false; - print('Exception occurred: $e'); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - Future getEmployeeAndDependence(clintID, getPolicyNo) async { - print('9'); - setState(() { - isLoading = true; - }); - try { - print('10'); - final response = await apiService.getEmployeeAndDependenceToApi( - clintID!, getPolicyNo!, empRefId!); - if (response['status'] == 'success') { - setState(() { - isLoading = false; - }); - setState(() { - getEmpDependenceByClintId = - List>.from(response['data']); - originalData = getEmpDependenceByClintId; - filteredData = List.from(originalData); - print('filteredData'); - print(filteredData); - }); - } else { - setState(() { - isLoading = false; - }); - - // ToastHelper.showWarningToast( - // context, 'Request failed with status: ${response.statusCode}'); - print('Request failed with status: ${response['code']}'); - } - } catch (e) { - setState(() { - isLoading = false; - }); - print('Exception occurred: $e'); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - void _uploadFile(type) async { - var argumentType; - if (type == 'GPA') { - // argumentDetails = importPolicyName + ' - ' + getPolicyNameDetails2; - argumentType = 'GPA'; - } else if (type == 'GMC') { - // argumentDetails = importPolicyName + ' - ' + getPolicyNameDetails1; - argumentType = 'GMC'; - } - // else if (importPolicyName == 'SI-TopUp') { - // // argumentDetails = importPolicyName + ' - ' + getPolicyNameDetails0; - // argumentDetails = 'SI-TopUp'; - // } else if (importPolicyName == 'Dependent-AddOn') { - // // argumentDetails = importPolicyName + ' - ' + getPolicyNameDetails0; - // argumentDetails = 'Dependent-AddOn'; - // } - - Navigator.pushNamed(context, 'excelVerify', arguments: argumentsData); - // return; - // if (kIsWeb) { - // final input = html.FileUploadInputElement(); - // input.accept = '.xlsx'; - // input.click(); - // input.onChange.listen((event) async { - // final file = input.files!.first; - // final reader = html.FileReader(); - // reader.readAsArrayBuffer(file); - // reader.onLoadEnd.listen((event) async { - // final Uint8List? fileBytes = reader.result as Uint8List?; - // if (fileBytes != null) { - // // Call function to process Excel data - // } - // }); - // }); - // } - } - - // Implement a method to handle the search functionality - void search(String query) { - print(query); - // Check if the query is empty - if (query.isEmpty) { - // If search query is empty, show all data - setState(() { - filteredData = List.from(originalData); - }); - } else { - // Filter the original data based on the search query - setState(() { - filteredData = originalData.where((row) { - // Implement your filter logic here - // For example, check if any field in the row contains the query - // Adjust this logic based on your data structure - return row['emp_code'] - .toString() - .toLowerCase() - .contains(query.toLowerCase()) || - row['name'] - .toString() - .toLowerCase() - .contains(query.toLowerCase()) || - row['relationship'] - .toString() - .toLowerCase() - .contains(query.toLowerCase()) || - row['dob'] - .toString() - .toLowerCase() - .contains(query.toLowerCase()) || - row['gender'] - .toString() - .toLowerCase() - .contains(query.toLowerCase()) || - row['mobile'] - .toString() - .toLowerCase() - .contains(query.toLowerCase()); - }).toList(); - }); - } - print(filteredData.length); - } - - Future downloadExcel() async { - // API endpoint to download the Excel file - - // Send GET request to the API - var url = Uri.parse(Environment.apiUrl + - 'exportDataByClientPolicyId?client_id=$clientId&client_policy_id=$clientPolicyId&client_branch_id=$empRefId'); - - var response = await http.get( - url, - headers: { - 'Authorization': 'Bearer $_token', - }, - ); - - // Check if the request was successful (status code 200) - // Check if the request was successful (status code 200) - // Check if the request was successful (status code 200) - if (response.statusCode == 200) { - // 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', '$policyName - ($policyType).xlsx') - ..click(); - - // Revoke the download URL to free up resources - html.Url.revokeObjectUrl(url); - } else { - // Handle error - print('Failed to download Excel file: ${response.statusCode}'); - } - } - - @override - Widget build(BuildContext context) { - dynamic arguments = ModalRoute.of(context)!.settings.arguments; - print('arguments'); - print(arguments); - if (arguments != null && arguments is Map) { - argumentsData = arguments; - print('argumentsData $argumentsData'); - } - if (filteredData == []) { - return Scaffold( - appBar: CustomAppBar(), - body: Stack(children: [ - SingleChildScrollView( - child: Container( - color: Color(0xFFEFF3F6), - child: Column( - children: [ - Center( - child: Text('No Data Available'), - ) - ], - ), - ), - ), - if (isLoading) - Container( - color: Color(0x98FFFCE5), // Semi-transparent background - child: Center( - child: // Your GIF loader widget - Image.asset( - height: 60, - width: 60, - 'assets/nhance-loader.gif'), // Adjust path to your GIF loader - ), - ), - Align( - alignment: Alignment.bottomCenter, - child: Container( - width: double.infinity, // Make the footer full width - child: CustomFooter(), - ), - ), - ])); - } else { - return Scaffold( - appBar: CustomAppBar(), - body: Stack(children: [ - Container( - padding: const EdgeInsets.only( - top: 30, bottom: 70, left: 30, right: 30), - color: Color(0xFFEFF3F6), - height: MediaQuery.of(context).size.height, - child: Card( - elevation: 0, - color: Colors.white, - child: SingleChildScrollView( - child: Column( - children: [ - Center( - child: Padding( - padding: const EdgeInsets.all(20), - child: _isLoading - ? Center(child: CircularProgressIndicator()) - : originalData.isNotEmpty - ? SingleChildScrollView( - child: Column( - children: [ - Container( - padding: EdgeInsets.all( - 10), // Set your desired padding - color: Color( - 0xFFE26728), // Set your desired background color - child: Row( - children: [ - Expanded( - flex: 6, - child: Container( - alignment: Alignment - .centerLeft, // Align text to the center - child: Text( - '$policyName - ($policyType)', - textAlign: TextAlign - .center, // Align text to the center - style: - GoogleFonts.poppins( - fontSize: 16, - fontWeight: - FontWeight.w500, - color: Colors.white, - ), - ), - ), - ), - Expanded( - flex: 6, - child: Container( - alignment: Alignment - .centerRight, // Align text to the center - child: MouseRegion( - cursor: SystemMouseCursors - .click, - child: GestureDetector( - onTap: () async { - final prefs = - await SharedPreferences - .getInstance(); - await prefs.remove( - 'hrSelectArgumentsData'); - Navigator.pushNamed( - context, - 'hrDashboard'); - }, - child: Icon( - Icons - .close, // Replace with your desired icon - color: Colors - .white, // Replace with your desired icon color - ), - ), - ), - ), - ), - ], - ), - ), - SizedBox(height: 20), - Row( - children: [ - Expanded( - flex: (policyType == 'GPA' || - policyType == 'GMC') - ? 8 - : 10, - child: Container( - alignment: - Alignment.centerLeft, - child: Container( - width: - 350, // Set your desired width here - height: - 40, // Set your desired height here - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - color: Color.fromRGBO( - 255, - 255, - 255, - 0.5), // Shadow color with opacity - offset: Offset(5, - 5), // Shadow position (horizontal, vertical) - blurRadius: - 10, // Blur radius - spreadRadius: - 0, // Spread radius - ), - ], - borderRadius: - BorderRadius - .circular(5), - ), - child: TextField( - textAlignVertical: - TextAlignVertical - .center, // Center the text vertically - decoration: - InputDecoration( - hintText: 'Search', - suffixIcon: Icon( - Icons.search), - contentPadding: - EdgeInsets.all( - 10), // Adjust the horizontal padding - border: - OutlineInputBorder( - borderSide: BorderSide( - color: Color( - 0xFFf5f5f7)), // Set border color to gray - ), - ), - controller: - searchController, - onChanged: - search, // Call the search method on text change - ), - )), - ), - Expanded( - flex: 2, - child: Container( - alignment: - Alignment.centerRight, - child: Row( - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - Expanded( - child: ElevatedButton( - onPressed: () => - {downloadExcel()}, - child: Text( - 'Export', - style: TextStyle( - color: Colors - .white), - ), - style: ElevatedButton - .styleFrom( - backgroundColor: - Color( - 0xFFE26728), - shape: - RoundedRectangleBorder( - borderRadius: - BorderRadius - .circular( - 5), - ), - ), - ), - ), - ], - ), - ), - ), - SizedBox( - width: (policyType == 'GPA' || - policyType == 'GMC') - ? 5 - : 0), - if ((policyType == 'GPA' || - policyType == 'GMC' || - policyType == 'EDLI' || - policyType == 'GTLI') && - inceptionType == 2) - Expanded( - flex: 2, - child: Container( - alignment: - Alignment.centerRight, - child: Row( - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - Expanded( - child: ElevatedButton( - onPressed: () => - _uploadFile( - policyType), - child: Text( - 'Import Data', - style: TextStyle( - color: Colors - .white), - ), - style: - ElevatedButton - .styleFrom( - backgroundColor: - Color( - 0xFFE26728), - shape: - RoundedRectangleBorder( - borderRadius: - BorderRadius - .circular( - 5), - ), - ), - ), - ), - ], - ), - ), - ), - ], - ), - SizedBox(height: 20), - Row( - children: [ - Expanded( - child: SingleChildScrollView( - child: _buildDataTableGPA( - context), - ), - ) - ], - ), - ], - )) - : Container( - height: - MediaQuery.of(context).size.height, - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Container( - padding: EdgeInsets.all( - 10), // Set your desired padding - color: Color( - 0xFFE26728), // Set your desired background color - child: Row( - children: [ - Expanded( - flex: 6, - child: Container( - alignment: Alignment - .centerLeft, // Align text to the center - child: Text( - (policyName != null && - policyType != - null) - ? '$policyName - ($policyType)' - : '', - textAlign: TextAlign - .center, // Align text to the center - style: - GoogleFonts.poppins( - fontSize: 16, - fontWeight: - FontWeight.w500, - color: Colors.white, - ), - ), - ), - ), - Expanded( - flex: 6, - child: Container( - alignment: Alignment - .centerRight, // Align text to the center - child: MouseRegion( - cursor: - SystemMouseCursors - .click, - child: GestureDetector( - onTap: () { - Navigator.pushNamed( - context, - 'hrDashboard'); - }, - child: Icon( - Icons - .close, // Replace with your desired icon - color: Colors - .white, // Replace with your desired icon color - ), - ), - ), - ), - ), - ], - ), - ), - SizedBox(height: 200), - if (inceptionType == 2) - Center( - child: ElevatedButton( - onPressed: () => - _uploadFile(policyType), - child: Text( - 'Import Data', - style: TextStyle( - color: Colors.white), - ), - style: - ElevatedButton.styleFrom( - backgroundColor: - Color(0xFFE26728), - shape: - RoundedRectangleBorder( - borderRadius: - BorderRadius.circular( - 5), - ), - ), - ), - ) - else - Center( - child: Text( - 'No Data Available', - style: GoogleFonts.poppins( - fontSize: 16, - letterSpacing: 0, - color: Colors.black, - fontWeight: FontWeight.w300, - ), - ), - ) - ], - ), - ), - ), - ), - ], - ), - )), - ), - if (isLoading) - Container( - color: Color(0x98FFFCE5), // Semi-transparent background - child: Center( - child: // Your GIF loader widget - Image.asset( - height: 60, - width: 60, - 'assets/nhance-loader.gif'), // Adjust path to your GIF loader - ), - ), - Align( - alignment: Alignment.bottomCenter, - child: Container( - width: double.infinity, // Make the footer full width - child: CustomFooter(), - ), - ), - ])); - } - } - - Widget _buildDataTableGPA(context) { - if (filteredData.isEmpty) { - SizedBox(height: 25); - return Text('No available data'); - } else { - return Card( - elevation: 0, - color: Colors.white, // Set elevation to 0 for no shadow - child: PaginatedDataTable( - rowsPerPage: filteredData.length, // Adjust rows per page as needed - columns: [ - DataColumn(label: Text('Employee ID')), - DataColumn(label: Text('TPA ID')), - DataColumn(label: Text('Name')), - DataColumn(label: Text('Relationship')), - DataColumn(label: Text('Date of Birth')), - DataColumn(label: Text('Gender')), - DataColumn(label: Text('Mobile No')), - // DataColumn(label: Text('Date of Joining')), - DataColumn(label: Text('Date Coverage')), - DataColumn(label: Text('Email')), - DataColumn(label: Text('SI')), - DataColumn(label: Text('Grade')), - DataColumn(label: Text('Basic Pay')), - ], - source: _DependenceDataSource0(filteredData, context), - ), - ); - } - } -} - -class _DependenceDataSource0 extends DataTableSource { - final List> _data; - final BuildContext context; - _DependenceDataSource0(this._data, this.context); - - @override - DataRow getRow(int index) { - final row = _data[index]; - Color rowColor = Colors.transparent; - TextStyle textStyle = TextStyle(color: Colors.black); - bool isClickable = false; - - if (row['relationship'] == 'Self') { - rowColor = Color(0xFFFFF1DD); // Setting background color for 'Self' rows - textStyle = TextStyle(color: Colors.black); - isClickable = true; // Making 'Self' rows clickable - } - // Format date of birth to "July 10, 1996" - String dob = row['dob'] != null ? formatDateString(row['dob']) : 'N/A'; - // String doj = row['doj'] != null ? formatDateString(row['doj']) : 'N/A'; - String dateCoverage = row['date_coverage'] != null - ? formatDateString(row['date_coverage']) - : 'N/A'; - - return DataRow( - color: MaterialStateColor.resolveWith( - (states) => rowColor), // Setting row background color - cells: [ - DataCell( - Text(row['emp_code'].toString(), style: textStyle), - onTap: isClickable - ? () => _navigateToAnotherPage(row) - : null, // Navigation only for 'Self' rows - ), - DataCell(Text(row['tpa_id'].toString(), style: textStyle)), - DataCell(Text(row['name'].toString(), style: textStyle)), - DataCell(Text(row['relationship'].toString(), style: textStyle)), - DataCell(Text(dob, style: textStyle)), - DataCell(Text(row['gender'] ?? 'N/A', style: textStyle)), - DataCell(Text(row['mobile'] ?? 'N/A', style: textStyle)), - // DataCell(Text(doj, style: textStyle)), - DataCell(Text(dateCoverage, style: textStyle)), - DataCell(Text(row['email_corporate'] ?? 'N/A', style: textStyle)), - DataCell(Text(row['basic_cover_si'] ?? 'N/A', style: textStyle)), - DataCell(Text(row['grade'] ?? 'N/A', style: textStyle)), - DataCell(Text(row['basic_pay'] ?? 'N/A', style: textStyle)), - ], - ); - } - - @override - bool get isRowCountApproximate => false; - - @override - int get rowCount => _data.length; - - @override - int get selectedRowCount => 0; - - void _navigateToAnotherPage(row) async { - print(row['mobile']); - final SharedPreferences prefs = await SharedPreferences.getInstance(); - prefs.setBool('showBackToHR', true); - prefs.setString('employee_id', row['employee_id']); - // Navigation logic here - Navigator.pushNamed(context, 'empDetails', - arguments: {'mobile': row['mobile']}); - } - - String formatDateString(String dateString) { - // Parse the date string to DateTime object - DateTime dateTime = DateTime.parse(dateString); - // Format the DateTime object to "dd-mm-yyyy" - String formattedDate = DateFormat('dd-MM-yyyy').format(dateTime); - return formattedDate; - } -} - -// Sample Data class representing each element in the array -class Data { - final dynamic value; - final int row; - final int column; - final String sheet; - - Data(this.value, this.row, this.column, this.sheet); -} diff --git a/lib/main.dart b/lib/main.dart index 34fee4b..feecec8 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ + import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:nhancepolicy/addons.dart'; @@ -8,6 +9,7 @@ import 'package:nhancepolicy/hrHome.dart'; import 'package:nhancepolicy/hrVerify.dart'; import 'package:nhancepolicy/models/environment.dart'; import 'package:nhancepolicy/phone.dart'; +import 'package:nhancepolicy/postFileUpload.dart'; import 'package:nhancepolicy/verify.dart'; import 'package:nhancepolicy/home.dart'; import 'package:nhancepolicy/hrDashboard.dart'; @@ -19,8 +21,13 @@ import 'package:firebase_core/firebase_core.dart'; import 'cdTransactionDetails.dart'; import 'email_verify.dart'; +import 'dart:html' as html; Future main() async { + // html.window.onBeforeUnload.listen((event) { + // print('Local Storage cleared by window'); + // html.window.localStorage.clear(); + // }); // await dotenv.load(fileName: Environment.fileName); WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( @@ -80,6 +87,19 @@ Future main() async { cardPolicy_name: '', cardPolicy_ExpDate: '', ), + 'postFileUpload': (context) => const postFileUpload( + ClientId: '', + policyTypeId: '', + ClientPoliyId: '', + clientBranchId: '', + Token: '', + TokenType: '', + cardType: '', + cardPolicyNo: '', + cardInsurer_name: '', + cardPolicy_name: '', + cardPolicy_ExpDate: '', + ), 'empDetails': (context) => empDetails(), 'addOnsDetails': (context) => addOnsDetails(), 'empReviewDetails': (context) => empReviewDetails(), diff --git a/lib/postFileUpload.dart b/lib/postFileUpload.dart new file mode 100644 index 0000000..850ac4c --- /dev/null +++ b/lib/postFileUpload.dart @@ -0,0 +1,1217 @@ +import 'dart:typed_data'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:jwt_decode/jwt_decode.dart'; +import 'package:nhancepolicy/customAppBar/customAppBar.dart'; +import 'dart:convert'; +import 'dart:async'; +import 'package:http/http.dart' as http; +import 'package:nhancepolicy/customAppBar/toastHelper.dart'; +import 'package:nhancepolicy/hrPolicyDetails.dart'; +import 'package:nhancepolicy/models/environment.dart'; +import 'package:nhancepolicy/service/api_service.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:universal_html/html.dart' as html; +import 'package:flutter/foundation.dart' show kIsWeb; +import 'dart:io'; +import 'package:intl/intl.dart'; +import 'package:csv/csv.dart'; + +import 'package:spreadsheet_decoder/spreadsheet_decoder.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import 'customAppBar/customFooter.dart'; + +class postFileUpload extends StatefulWidget { + final String ClientId; + final String policyTypeId; + final String ClientPoliyId; + final String clientBranchId; + final String Token; + final String TokenType; + final String cardType; + final String cardPolicyNo; + final String cardInsurer_name; + final String cardPolicy_name; + final String cardPolicy_ExpDate; + const postFileUpload( + {Key? key, + required this.ClientId, + required this.policyTypeId, + required this.ClientPoliyId, + required this.clientBranchId, + required this.Token, + required this.TokenType, + required this.cardType, + required this.cardPolicyNo, + required this.cardInsurer_name, + required this.cardPolicy_name, + required this.cardPolicy_ExpDate}) + : super(key: key); + + @override + State createState() => _postFileUploadState(); +} + +class _postFileUploadState extends State { + Uint8List? fileBytes; + Uint8List? fileBytes2; + late String _token; + dynamic getPolicyNo; + bool _isLoading = false; + dynamic getPolicyNameDetails; + dynamic clintID; + String? fileName; + int _currentStep = 0; // Step index tracker + List dataPolicy = []; + dynamic validationArray = []; + dynamic missingColumnErrorMsg = 0; + dynamic columnIndexMismatchCount = 0; + dynamic columnMissingCount = 0; + List> extractedData = []; + dynamic argumentsData; + List> originalData = []; // Original data source + List> filteredData = []; // Filtered data source + List> tableData = []; // Filtered data source + + List> nonExcelFilteredData = []; + dynamic invalidRelationships = 0; + dynamic dobAgeCheckCount = 0; + dynamic empRefId; + dynamic empPrimaryId; + List> getFileUploadMasterList = []; + dynamic getThrFileList = []; + late int excelValidationStaus = 1; + bool isSuccess = false; + String successContent = ''; + bool isLoading = false; + late ApiService apiService; + TextEditingController searchController = TextEditingController(); + String? _selectedOption; + + int _currentPage = 1; + int _rowsPerPage = 5; + + List get _paginatedData { + final startIndex = (_currentPage - 1) * _rowsPerPage; + final endIndex = + (_currentPage * _rowsPerPage).clamp(0, filteredData.length); + return filteredData.sublist(startIndex, endIndex); + } + + final List> serviceList = [ + {"id": 1, "name": "Sales"}, + {"id": 2, "name": "Service"}, + ]; + + String? selectedKey; + String? selectedValue; + String? _selectedAction; + + + @override + void initState() { + super.initState(); + apiService = ApiService(context); + _loadToken(); + getFileUploadMasterDetails(); + getFileListDetails(); + } + + @override + void dispose() { + super.dispose(); + html.window.localStorage.remove('fileBytes'); + } + + Future _loadToken() async { + final SharedPreferences prefs = await SharedPreferences.getInstance(); + // final token = prefs.getString('hrtoken'); + final token = widget.Token; + if (token != null && token.isNotEmpty) { + setState(() { + _token = token; + }); + Map? decodedToken = Jwt.parseJwt(token); + print('decodedToken $decodedToken'); + } else { + // Token is empty or null, handle accordingly (e.g., navigate to login screen) + // For now, let's navigate to the login screen + ToastHelper.showErrorToast(context, 'Session Out'); + Navigator.pushReplacementNamed(context, 'hrLogin'); + } + } + + // Future getPolicyDetails() async { + // setState(() { + // clientPolicyId = argumentsData['client_policy_id']; + // clientId = argumentsData['client_id']; + // policyType = argumentsData['type']; + // policy_name = argumentsData['policy_name']; + // }); + // } + + // Future _uploadFile1(importPolicyName) async { + // FilePickerResult? result = await FilePicker.platform.pickFiles( + // type: FileType.custom, + // allowedExtensions: ['xlsx', 'xls', 'csv'], + // ); + // + // if (result != null) { + // PlatformFile file = result.files.first; + // Uint8List fileBytes = file.bytes!; + // // Use the fileBytes as needed + // print('File name: ${file.name}'); + // print('File size: ${file.size}'); + // print('File bytes: $fileBytes'); + // _processExcelData(fileBytes); + // } else { + // // User canceled the picker + // } + // } + + Future getFileUploadMasterDetails() async { + print('9'); + try { + + final response = await apiService.getFileUploadMastersToApi(widget.Token); + + if (response['status'] == true) { + print('getFileUploadMasterList1'); + setState(() { + final actions = Map.from(response['data']['actions']); + setState(() { + getFileUploadMasterList = actions.entries + .map((e) => {"key": e.key, "value": e.value}) + .toList(); + print('getFileUploadMasterList: $getFileUploadMasterList'); + }); + print('getFileUploadMasterList'); + print(getFileUploadMasterList); + }); + } else { + print('Request failed with status: ${response['code']}'); + } + } catch (e) { + setState(() { + isLoading = false; + }); + print('Exception occurred: $e'); + } finally { + setState(() { + // _isLoading = false; + }); + } + } + + Future getFileListDetails() async { + final SharedPreferences prefs = await SharedPreferences.getInstance(); + empPrimaryId = prefs.getString('empPrimaryId'); + print('9'); + try { + + final response = await apiService.getFileListToApi(empPrimaryId,widget.cardPolicyNo,widget.Token); + + if (response['status'] == 'success') { + print('getThrFileList'); + setState(() { + getThrFileList = List>.from(response['data']); + originalData = getThrFileList; + filteredData = List.from(originalData); + print('filteredData'); + print(filteredData); + }); + } else { + print('Request failed with status: ${response['code']}'); + } + } catch (e) { + setState(() { + isLoading = false; + }); + print('Exception occurred: $e'); + } finally { + setState(() { + // _isLoading = false; + }); + } + } + + Future getHrFileDownload(id,file_name) async { + // final http.Response response = await apiService.getHrFileDownloadToApi(id, widget.Token); + final apiurl = Environment.apiUrlPost; + final String url = '$apiurl/hrFileDownload?id=$id'; + final token = widget.Token; + + final response = await http.get( + Uri.parse(url), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + // 'app-signature': 'ts-traveltool-2025-signature-123456', + }, + ); + + + if (response.statusCode == 200) { + try { + print("PDF Downloaded"); + + // ✅ Create a blob from the response body bytes + final blob = html.Blob([response.bodyBytes]); + + // ✅ Generate a download URL + final url = html.Url.createObjectUrlFromBlob(blob); + + // ✅ Trigger file download automatically + final anchor = html.AnchorElement(href: url) + ..setAttribute('download', '$file_name') + ..click(); + + // ✅ Revoke the URL to free memory + html.Url.revokeObjectUrl(url); + } catch (e) { + throw Exception('Error parsing response: $e'); + } + } else { + print("Download failed with status: ${response.statusCode}"); + } + } + + void _uploadFile() async { + print('Test'); + if (kIsWeb) { + print('kIsWeb'); + final input = html.FileUploadInputElement(); + input.accept = '.xlsx,.xls,.csv'; + input.click(); + input.onChange.listen((event) async { + final file = input.files!.first; + final reader = html.FileReader(); + reader.readAsArrayBuffer(file); + await reader.onLoadEnd.first; // Wait for the file to be loaded + if (reader.readyState == html.FileReader.DONE) { + Uint8List? fileBytes = reader.result as Uint8List?; + if (fileBytes != null) { + setState(() { + fileName = file.name; + }); + // Save fileBytes to local storage + final jsonString = json.encode(fileBytes); + html.window.localStorage['fileBytes'] = jsonString; + print('File Name: $fileName'); + print('File Bytes: $fileBytes'); + sendExcelFIleTOAPI(fileBytes, fileName); + // Call the function to process Excel data here + // _processExcelData(fileBytes, fileName); + } + } + }); + } else { + // Handle non-web platforms here (e.g., show an error message) + print('File upload is only supported on web platforms.'); + } + } + + int countInvalidDobs(List> data) { + int invalidCount = 0; + + for (var entry in data) { + DateTime dob; + + // if (entry['DOB'] is String) { + dob = DateTime.parse(entry['DOB'].toString()); + // } else if (entry['DOB'] is DateTime) { + // dob = entry['DOB']; + // } else { + // // Invalid DOB format, skip this entry + // continue; + // } + print(entry['Relation']); + if ((entry['Relation'].toString() == 'Son' || + entry['Relation'].toString() == 'Daughter')) { + if (DateTime.now().difference(dob).inDays > 25 * 365) { + print('child $dob'); + invalidCount++; + } + } else if ((entry['Relation'] != 'Son' && + entry['Relation'] != 'Daughter')) { + if (DateTime.now().difference(dob).inDays < 18 * 365) { + print('others $dob'); + invalidCount++; + } + } + } + + return invalidCount; + } + + void _dragAndDropFile(html.File file) async { + print('file'); + print(file); + // Prepare form data + final formData = html.FormData(); + formData.appendBlob('file', file); + + // Send formData to API endpoint + final response = await html.HttpRequest.request( + 'your_api_endpoint_here', + method: 'POST', + sendData: formData, + ); + + // Handle response as needed + print(response.responseText); + } + + Future sendExcelFIleTOAPI(Uint8List fileBytes, fileName) async { + final SharedPreferences prefs = await SharedPreferences.getInstance(); + empPrimaryId = prefs.getString('empPrimaryId'); + // Future.delayed(Duration(seconds: 3), () { + setState(() { + isLoading = true; + }); + // }); + print('submit'); + print(fileBytes); + if (fileBytes == null) { + ToastHelper.showErrorToast(context, 'Please upload file'); + print('return'); + return; // No file selected + } else { + print('else'); + // // Prepare form data + // final formData = html.FormData(); + // formData.appendBlob('file', html.Blob([fileBytes]), fileName); + + // URL of the API where you want to send the file + final apiUrl = Environment.apiUrlPost + 'hrFileUpload'; + print('else'); + // Create a multipart request + final request = http.MultipartRequest('POST', Uri.parse(apiUrl)); + print('else'); + // Attach the file to the request + // Set authorization token in headers + request.headers['Authorization'] = 'Bearer $_token'; + // request.files.add(http.MultipartFile.fromBytes('file', fileBytes, + // filename: fileName)); + print('Filename: $fileName'); + // request.files.add(http.MultipartFile.fromBytes( + // 'file', + // fileBytes, + // filename: fileName ?? 'default_filename.xlsx', + // )); + request.files.add(http.MultipartFile.fromBytes( + 'file_name', + fileBytes, + filename: fileName ?? 'default_filename.xlsx', + )); + print('clintID: $clintID'); + + request.fields['client_id'] = widget.ClientId; + request.fields['policy_no'] = widget.cardPolicyNo; + request.fields['client_branch_id'] = widget.clientBranchId; + request.fields['file_action'] = selectedKey!; + // request.fields['status'] = selectedKey!; + request.fields['created_by'] = empPrimaryId; + request.fields['policy_id'] = widget.ClientPoliyId; + // "client_id": 1, + // "client_branch_id": 2, + // "policy_no": "POL123456", + // "file_action": , + // "status": "inception", + // "created_by": 10 + + print('request : $request'); + // Send the request + final response = await request.send(); + print('else'); + // Read response stream as a string + final responseString = await response.stream.bytesToString(); + print(responseString); + Map data = json.decode(responseString); + if (data['status'] == true) { + print('upload success'); + setState(() { + isLoading = false; + }); + ToastHelper.showSuccessToast(context, data['message']); + getFileListDetails(); + setState(() { + selectedValue = null; + selectedKey = null; + resetErrorCount(); + }); + } else { + setState(() { + isLoading = false; + }); + ToastHelper.showErrorToast(context, data['message']); + } + } + } + + resetErrorCount() { + setState(() { + fileBytes = null; + fileName = null; + }); + } + + void search(String query) { + print(query); + // Check if the query is empty + if (query.isEmpty) { + // If search query is empty, show all data + setState(() { + filteredData = List.from(originalData); + }); + } else { + // Filter the original data based on the search query + setState(() { + filteredData = originalData.where((row) { + // Implement your filter logic here + // For example, check if any field in the row contains the query + // Adjust this logic based on your data structure + return row['file_name'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['file_action'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['created_at'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()); + }).toList(); + }); + } + print(filteredData.length); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar(), + backgroundColor: Color(0xFFEFF3F6), + body: Stack(children: [ + // color: Color(0xFFEFF3F6), + + // padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 40), + SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Container( + padding: EdgeInsets.only(top: 30, bottom: 200, left: 50, right: 50), + child: Column( + children: [ + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, // 👈 fix alignment + children: [ + Expanded( + flex: 8, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // back button + texts + Row( + children: [ + IconButton( + padding: EdgeInsets.zero, + constraints: BoxConstraints(), + onPressed: () { + Navigator.pop(context); + }, + icon: Icon( + Icons.arrow_back_ios, + color: Colors.grey, + size: 17, + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "${widget.cardType} - ${widget.cardPolicyNo}", + style: GoogleFonts.poppins( + color: Colors.black, + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + Text( + widget.TokenType == 'pre' + ? "${widget.cardPolicy_name} (${widget.cardPolicy_ExpDate})" + : "${widget.cardInsurer_name} - ${widget.cardPolicy_name} (${widget.cardPolicy_ExpDate})", + style: GoogleFonts.poppins( + color: Colors.grey, + fontSize: 12, + fontWeight: FontWeight.w400, + ), + ), + ], + ) + ], + ), + ], + ), + ), + Expanded( + flex: 4, + child: Container( + padding: const EdgeInsets.only(top: 4), + child: getFileUploadMasterList.isEmpty + ? const SizedBox() // 👈 avoid crash on first build + : buildDropdownField( + 'File Action', + (value) { + setState(() { + selectedKey = value; + selectedValue = getFileUploadMasterList + .firstWhere((item) => item['key'] == value)['value']; + }); + debugPrint("Selected Key: $selectedKey"); + debugPrint("Selected Value: $selectedValue"); + }, + false, + getFileUploadMasterList, + 'value', + selectedKey, + valueKey: 'key', + ), + ), + ), + + ], + ), + ), + SizedBox( + height: 20, + ), + + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.circular(10), // 👈 set your desired radius + ), + // height: 400, + // margin: const EdgeInsets.only(left: 40.0, right: 40.0), + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 12, + child: Column( + children: [ + // Row( + // mainAxisAlignment: + // MainAxisAlignment.center, + // children: [ + // Expanded( + // child: Text( + // '${widget.cardPolicy_name} - (${widget.cardType})', + // textAlign: TextAlign.center, + // style: const TextStyle( + // fontSize: 20, + // fontWeight: FontWeight + // .w600, // Adjust the font size as needed + // color: Color( + // 0xFF181818), // Adjust the text color as needed + // ), + // ), + // ) + // ], + // ), + SizedBox(height: 20), + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Expanded( + child: Container( + margin: EdgeInsets.symmetric( + horizontal: 150), + alignment: Alignment.center, + color: Colors.grey[200], + height: 180, + child: DragTarget( + onAccept: (html.File + droppedFile) { + setState(() { + fileName = + droppedFile.name; + }); + _dragAndDropFile( + droppedFile); + }, + builder: + (BuildContext context, + List + candidateData, + List + rejectedData) { + return Container( + alignment: + Alignment.center, + child: Column( + mainAxisAlignment: + MainAxisAlignment + .center, + children: [ + + fileName != null + ? Column( + mainAxisAlignment: + MainAxisAlignment + .center, + children: [ + Icon( + Icons + .upload_file, // Choose the appropriate icon + size: + 35, + color: Color( + 0xFFE26728), // Adjust the size as needed + ), + SizedBox( + height: + 15), // Add some space between the icon and text + Text( + '$fileName', + style: TextStyle( + fontSize: + 16), + ), + SizedBox( + height: + 25), // Add some space between the icon and text + MouseRegion( + cursor: + SystemMouseCursors.click, // Set cursor to pointer on hover + child: + GestureDetector( + onTap: + () { + resetErrorCount(); + }, + child: + const Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.delete_forever, // Choose the remove icon + size: 20, // Adjust the size as needed + color: Colors.red, // Set the color of the remove icon + ), + SizedBox(width: 1), // Add some space between the icon and text + Text( + 'Remove', + style: TextStyle(fontSize: 13, color: Color(0xFF727272)), + ), + ], + ), + ), + ) + ], + ) + : ElevatedButton( + onPressed: () => { + print('selectedValue $selectedValue'), + if(selectedValue != null){ + _uploadFile(), + } else { + ToastHelper.showErrorToast(context, 'Please select file action') + } + + }, + child: Text( + 'Select File', + style: TextStyle( + color: + Colors.white), + ), + style: ElevatedButton + .styleFrom( + backgroundColor: + Color( + 0xFFE26728), + ), + ), + SizedBox( + height: 20), + if (fileName == + null) + Text( + 'Supported Files : XLSX') + // Add more Text widgets for additional lines of text + ], + ), + ); + }, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + SizedBox(height: 10), + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.circular(10), // 👈 set your desired radius + ), + // width: double.infinity, // take full width + // height: MediaQuery.of(context).size.height * 0.8, // 80% of screen height + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Row( + children: [ + Expanded( + flex: 4, + child: Align( + alignment: Alignment.centerLeft, + child: Container( + width: 400, + height: 37, + decoration: BoxDecoration( + color: Color(0xFFF0F0F0), + borderRadius: BorderRadius.circular(8), + ), + child: TextField( + decoration: InputDecoration( + hintText: 'Search', + prefixIcon: Icon(Icons.search, size: 18), + contentPadding: EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + border: InputBorder + .none, // No border since Container handles it + ), + controller: searchController, + onChanged: search, + style: TextStyle(fontSize: 14), + ), + ), + ), + ), + ], + ), + SizedBox(height: 20), + Row( + children: [ + Expanded( + child: _buildFileUploadedListTable(context), + ) + ], + ), + ], + ), + ), + ], + ), + ), + ), + + if (isLoading) + Container( + color: Color(0x98FFFCE5), // Semi-transparent background + child: Center( + child: // Your GIF loader widget + Image.asset( + height: 60, + width: 60, + 'assets/nhance-loader.gif'), // Adjust path to your GIF loader + ), + ), + Align( + alignment: Alignment.bottomCenter, + child: Container( + width: double.infinity, // Make the footer full width + child: CustomFooter(), + ), + ), + ]), + ); + } + + Widget buildDropdownField( + String label, + void Function(T?) onChanged, + bool readOnly, + List> itemsList, + String displayField, + T? selectedValue, { + String valueKey = 'id', + }) { + return DropdownButtonFormField( + value: selectedValue, + decoration: InputDecoration(labelText: label), + items: itemsList.map>((item) { + return DropdownMenuItem( + value: item[valueKey] as T, // ✅ cast to generic type + child: + Text(item[displayField].toString()), // always display as String + ); + }).toList(), + onChanged: readOnly ? null : onChanged, + validator: (value) { + if (value == null) { + return 'Please select a $label'; + } + return null; + }, + ); + } + + Widget _buildFileUploadedListTable(BuildContext context) { + // Loader overlay + + if (filteredData.isEmpty) { + return const SizedBox( + height: 50, + child: Center(child: Text('No available data')), + ); + } + + print('filteredData12345 $filteredData'); + + return ListView.builder( + shrinkWrap: true, // important for nested lists + physics: const AlwaysScrollableScrollPhysics(), + itemCount: _paginatedData.length + 2, + itemBuilder: (context, index) { + if (index == 0) return _buildHeader(); + if (index == _paginatedData.length + 1) return _buildPagination(context); + + final item = _paginatedData[index - 1]; + return _buildDataRow(item); + }, + ); + + + // return Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // Header row + // Container( + // decoration: BoxDecoration( + // color: Color(0xFF00A6A6), + // borderRadius: BorderRadius.circular(6), + // ), + // padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), + // child: Row( + // children: [ + // Expanded( + // flex: 4, + // child: Text( + // 'Insurer Name', + // style: GoogleFonts.poppins( + // color: Colors.white, fontWeight: FontWeight.bold), + // ), + // ), + // Expanded( + // flex: 3, + // child: Text( + // 'CD Account number', + // style: GoogleFonts.poppins( + // color: Colors.white, fontWeight: FontWeight.bold), + // ), + // ), + // Expanded( + // flex: 2, + // child: Text( + // 'Current Balance', + // style: GoogleFonts.poppins( + // color: Colors.white, fontWeight: FontWeight.bold), + // ), + // ), + // Expanded( + // flex: 1, + // child: Text( + // 'Action', + // textAlign: TextAlign.center, + // style: GoogleFonts.poppins( + // color: Colors.white, fontWeight: FontWeight.bold), + // ), + // ), + // ], + // ), + // ), + // + // const SizedBox(height: 6), + // + // // Table body rows + // ..._paginatedData.mapIndexed((index, item) { + // return Container( + // margin: const EdgeInsets.only(bottom: 8), + // padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 16), + // decoration: BoxDecoration( + // color: index % 2 == 0 ? Color(0xFFE6FAFB) : Colors.white, + // borderRadius: BorderRadius.circular(6), + // ), + // child: Row( + // children: [ + // Expanded( + // flex: 4, + // child: Text( + // item['insurer_name'] ?? '-', + // style: GoogleFonts.poppins(color: Color(0xFF000000)), + // ), + // ), + // Expanded( + // flex: 3, + // child: Text( + // item['cd_master_account_no'] ?? '-', + // style: GoogleFonts.poppins(color: Color(0xFF000000)), + // ), + // ), + // Expanded( + // flex: 2, + // child: Text( + // "₹${item['balance'] ?? '0'}", + // style: GoogleFonts.poppins(color: Color(0xFF000000)), + // ), + // ), + // Expanded( + // flex: 1, + // child: Center( + // child: IconButton( + // icon: const Icon(Icons.remove_red_eye_outlined), + // onPressed: () { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => cdTransactionDetails( + // insurerName: item['insurer_name'], + // cdMasterAccountNo: item['cd_master_account_no'], + // insurerId: item['insurer_id'], + // cd_ac_pk: item['cd_ac_pk'], + // empClientId: widget.empClientId, + // postToken: widget.postToken), + // ), + // ); + // }, + // ), + // ), + // ), + // ], + // ), + // ); + // }).toList(), + // + // + // ], + // ); + } + + Widget _buildDataRow(Map item) { + print('item $item'); + return Container( + padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16), + margin: const EdgeInsets.only(top: 10), + decoration: BoxDecoration( + color: Color(0xFFE0F7F9), + border: const Border( + bottom: BorderSide(color: Color(0xFFD7E9EB), width: 1), + ), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + Expanded( + flex: 4, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MouseRegion( + cursor: SystemMouseCursors.click, // 👆 Pointer cursor + child: Tooltip( + message: "Click to Download", // 📝 Tooltip text + child: GestureDetector( + onTap: () { + getHrFileDownload(item['id'],item['file_name']); // ✅ Call your API/download logic + }, + child: Text( + item['file_name'] ?? '-', + style: _dataBold.copyWith( + color: Colors.blue, // 🔗 Make it look like a link + decoration: TextDecoration.underline, + ), + ), + ), + ), + ), + ], + ), + ), + Expanded( + flex: 3, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(item['file_action'] ?? '-', style: _dataBold), + ], + ), + ), + Expanded( + flex: 2, + child: Text(formatDate(item['created_at']), style: _dataBold), + ), + Expanded( + flex: 2, + child: Text(item['status'], style: _dataBold), + ), + ], + ), + ); + } + + Widget _buildHeader() { + return Container( + decoration: BoxDecoration( + color: Color(0xFF00A6A6), + borderRadius: BorderRadius.circular(6), + ), + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), + child: const Row( + children: [ + Expanded(flex: 4, child: Text('File Name', style: _headerStyle)), + Expanded( + flex: 3, child: Text('File Action', style: _headerStyle)), + Expanded( + flex: 2, child: Text('Created At', style: _headerStyle)), + Expanded( + flex: 2, child: Text('Status', style: _headerStyle)) + + ], + ), + ); + } + + static final _dataBold = GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w400, + color: Color(0xFF000000), + ); + + static final _dataSub = GoogleFonts.poppins( + fontSize: 10, + fontWeight: FontWeight.w300, + color: Color(0xFF585757), + ); + + static const _headerStyle = TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ); + + Widget _buildPagination(BuildContext context) { + return Row(mainAxisAlignment: MainAxisAlignment.end, children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + DropdownButton( + value: _rowsPerPage, + items: [5, 10, 15, 20, 50].map((int value) { + return DropdownMenuItem( + value: value, + child: Text( + ' $value ', + style: GoogleFonts.poppins(fontSize: 15), + ), + ); + }).toList(), + onChanged: (newValue) { + setState(() { + _rowsPerPage = newValue!; + _currentPage = + 1; // Reset to first page when rows per page changes + }); + }, + ), + IconButton( + onPressed: _currentPage > 1 + ? () { + setState(() { + _currentPage--; + }); + } + : null, + icon: Icon(Icons.chevron_left), + ), + for (int i = 1; + i <= (filteredData.length / _rowsPerPage).ceil(); + i++) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: _currentPage == i + ? Color(0xFF00A6A6) + : Colors.grey[300], + foregroundColor: + _currentPage == i ? Colors.white : Colors.black, + minimumSize: Size(36, 36), + padding: EdgeInsets.zero, + ), + onPressed: () { + setState(() { + _currentPage = i; + }); + }, + child: Text(i.toString()), + ), + ), + IconButton( + onPressed: + _currentPage < (filteredData.length / _rowsPerPage).ceil() + ? () { + setState(() { + _currentPage++; + }); + } + : null, + icon: Icon(Icons.chevron_right), + ), + ], + ), + ), + ]); + } + + String formatDate(String? dateString) { + if (dateString == null || dateString.isEmpty) return '-'; + + try { + DateTime parsedDate = DateTime.parse(dateString); + return DateFormat('dd-MM-yyyy hh:mm a').format(parsedDate); + } catch (e) { + return '-'; + } + } + +} + + + + diff --git a/lib/service/api_service.dart b/lib/service/api_service.dart index 504b30f..3b3a6f5 100755 --- a/lib/service/api_service.dart +++ b/lib/service/api_service.dart @@ -650,6 +650,48 @@ class ApiService { return response; } + Future> getFileUploadMastersToApi(String token) async { + print(_hrtoken); + if (token == null) { + await _initializeToken(); + } + final url = Uri.parse( + '${Environment.apiUrlPost}hrFileUploadMasters'); + final headers = { + 'Authorization': 'Bearer $token' ?? '', + }; + final response = await _makeGetRequest(url, headers); + return response; + } + + Future> getFileListToApi(empPrimaryId,cardPolicyNo,String token) async { + print(_hrtoken); + if (token == null) { + await _initializeToken(); + } + final url = Uri.parse( + '${Environment.apiUrlPost}hrFileList?created_by=$empPrimaryId&policy_no=$cardPolicyNo'); + final headers = { + 'Authorization': 'Bearer $token' ?? '', + }; + final response = await _makeGetRequest(url, headers); + return response; + } + + // Future> getHrFileDownloadToApi(id,String token) async { + // print(_hrtoken); + // if (token == null) { + // await _initializeToken(); + // } + // final url = Uri.parse( + // '${Environment.apiUrl}hrFileDownload?id=$id'); + // final headers = { + // 'Authorization': 'Bearer $token' ?? '', + // }; + // final response = await _makeGetRequest(url, headers); + // return response; + // } + Future> getEmployeeAndDependenceToApiPre( String clintID, String getPolicyNo, String empRefId, String token) async { print(_hrtoken);