FULL FLOW CODE

This commit is contained in:
Venba 2024-05-28 08:48:53 +05:30
parent 20ae302ab8
commit 88cbcb4e96
56 changed files with 10325 additions and 4328 deletions

View File

@ -1,4 +1,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:label="nhancepolicy"
android:name="${applicationName}"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 996 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

BIN
assets/Solid_gray.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

BIN
assets/Template_File.xlsx Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

After

Width:  |  Height:  |  Size: 146 KiB

BIN
assets/nhance-loader.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
if (token != null && token.isNotEmpty) {
if (hrtoken != null && hrtoken.isNotEmpty) {
prefs.remove('token');
Navigator.pushNamed(context, 'hrHome');
Navigator.pushNamed(context, 'hrDashboard');
} else {
await prefs.clear();
Navigator.pushNamed(context, 'phone');
@ -99,13 +99,12 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
Navigator.pushNamed(context, "routeName");
},
),
if (Responsive.isDesktop(context))
NavBarItem(
text: "",
onTap: () {
Navigator.pushNamed(context, "routeName");
},
),
NavBarItem(
text: "Inactive Policy",
onTap: () {
Navigator.pushNamed(context, 'oldPolicy');
},
),
NavBarItem(
text: "Logout",
onTap: () async {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,9 @@ import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:excel/excel.dart';
import 'dart:io';
import 'package:intl/intl.dart';
import 'package:csv/csv.dart';
import 'package:spreadsheet_decoder/spreadsheet_decoder.dart';
class excelVerify extends StatefulWidget {
const excelVerify({Key? key}) : super(key: key);
@ -37,13 +40,17 @@ class _excelVerifyState extends State<excelVerify> {
dynamic columnIndexMismatchCount = 0;
dynamic columnMissingCount = 0;
List<Map<String, dynamic>> extractedData = [];
dynamic policyName;
dynamic policyFirstPart;
dynamic argumentsData;
List<Map<String, dynamic>> originalData = []; // Original data source
List<Map<String, dynamic>> filteredData = []; // Filtered data source
dynamic client_policy_id;
dynamic policy_name;
dynamic policy_name;
dynamic clientPolicyId;
dynamic clientId;
dynamic policyType;
List<Map<String, dynamic>> nonExcelFilteredData = [];
dynamic invalidRelationships = 0;
dynamic dobAgeCheckCount = 0;
@override
void initState() {
super.initState();
@ -53,6 +60,7 @@ class _excelVerifyState extends State<excelVerify> {
@override
void dispose() {
super.dispose();
html.window.localStorage.remove('fileBytes');
}
Future<void> _loadToken() async {
@ -64,7 +72,7 @@ class _excelVerifyState extends State<excelVerify> {
});
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
clintID = decodedToken['client_id'].toString();
await getPolicyName(clintID);
await getPolicyDetails();
} else {
// Token is empty or null, handle accordingly (e.g., navigate to login screen)
// For now, let's navigate to the login screen
@ -73,74 +81,40 @@ class _excelVerifyState extends State<excelVerify> {
}
}
Future<void> getPolicyName(String clintID) async {
Future<void> getPolicyDetails() async {
setState(() {
_isLoading = true;
clientPolicyId = argumentsData['client_policy_id'];
clientId = argumentsData['client_id'];
policyType = argumentsData['type'];
policy_name = argumentsData['policy_name'];
});
var url =
Uri.parse(Environment.apiUrl + 'getClientPolicy?client_id=' + clintID);
try {
var response = await http.get(
url,
headers: {
'Authorization': 'Bearer $_token',
},
);
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
if (data['status'] == 'success') {
print(data);
setState(() {
dataPolicy = List<Map<String, dynamic>>.from(data['data']);
print(dataPolicy);
// Find the object where the 'type' matches the 'policyFirstPart'
Map<String, dynamic> matchingPolicy = dataPolicy.firstWhere(
(policy) => policy['type'] == policyFirstPart,
orElse: () => <String,
dynamic>{} // Return an empty map if no matching policy is found
);
print(matchingPolicy);
if (matchingPolicy != null) {
// Matching policy found
print('Matching Policy: $matchingPolicy');
client_policy_id = matchingPolicy['client_policy_id'];
policy_name = matchingPolicy['policy_name'];
} else {
// No matching policy found
print('No matching policy found for $policyFirstPart');
}
// getPolicyNameDetails = dataPolicy[0]['policy_name'];
// print(getPolicyNameDetails);
// getPolicyNo = dataPolicy[0]['client_policy_id'];
});
print('Successfully Sent');
} else {
ToastHelper.showErrorToast(
context, 'API request failed with status: ${data['status']}');
print('API request failed with status: ${data['status']}');
}
} else {
ToastHelper.showErrorToast(
context, 'Request failed with status: ${response.statusCode}');
print('Request failed with status: ${response.statusCode}');
}
} catch (e) {
print('Exception occurred: $e');
} finally {
setState(() {
_isLoading = false;
});
}
}
// Future<void> _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
// }
// }
void _uploadFile(importPolicyName) async {
print('Test');
if (kIsWeb) {
print('kIsWeb');
final input = html.FileUploadInputElement();
input.accept = '.xlsx';
input.accept = '.xlsx,.xls,.csv';
input.click();
input.onChange.listen((event) async {
final file = input.files!.first;
@ -159,7 +133,7 @@ class _excelVerifyState extends State<excelVerify> {
print('File Name: $fileName');
print('File Bytes: $fileBytes');
// Call the function to process Excel data here
_processExcelData(fileBytes);
_processExcelData(fileBytes, fileName);
}
}
});
@ -169,20 +143,33 @@ class _excelVerifyState extends State<excelVerify> {
}
}
void _processExcelData(Uint8List fileBytes) {
void _processExcelData(Uint8List fileBytes, fileName) {
List<List<Data>> dataArray;
if (fileName.endsWith('.xlsx')) {
dataArray = decodeExcelData(fileBytes);
} else if (fileName.endsWith('.xls')) {
dataArray = decodeXLSData(fileBytes);
} else if (fileName.endsWith('.csv')) {
print('csv');
dataArray = decodeCSVData(fileBytes);
} else {
throw UnsupportedError('Unsupported file format: $fileName');
}
print('_processExcelData');
// Decode the Excel file and extract relevant data
// Assuming dataArray is your array containing Excel data
List<List<Data>> dataArray = decodeExcelData(fileBytes);
// List<List<Data>> dataArray = decodeExcelData(fileBytes);
print(dataArray);
// print(dataArray[0].toString());
// Extract Name, Age, and City from the array
print(dataArray[0].length);
if (dataArray[0].length == 10) {
if (dataArray[0].length == 11) {
for (int i = 0; i < dataArray.length; i++) {
Map<String, dynamic> dataMap = {
"Sno": dataArray[i][0].value,
"emp_code": dataArray[i][1].value,
"Emp_Code": dataArray[i][1].value,
"Name": dataArray[i][2].value,
"DOJ": dataArray[i][3].value,
"Gender": dataArray[i][4].value,
@ -191,6 +178,7 @@ class _excelVerifyState extends State<excelVerify> {
"Mail": dataArray[i][7].value,
"Mobile": dataArray[i][8].value,
"SI": dataArray[i][9].value,
"Grade": dataArray[i][10].value,
};
if (i == 0) {
// print(dataMap);
@ -203,47 +191,79 @@ class _excelVerifyState extends State<excelVerify> {
// Do something with extracted data (e.g., display in UI)
originalData = extractedData;
filteredData = List.from(originalData);
print('filteredData');
print(filteredData);
print(validationArray);
validationArray[0].forEach((key, value) {
print(key);
print(value);
if (key.toString() != value.toString()) {
if (key.toString().trim().toLowerCase() !=
value.toString().trim().toLowerCase()) {
// If key and value are not equal, increment mismatch count
columnIndexMismatchCount++;
print('columnIndexMismatchCount: $value');
}
if (value.toString() == 'null') {
// If value is null, increment missing count
columnMissingCount++;
print('Value: $value');
}
});
print('columnIndexMismatchCount: $columnIndexMismatchCount');
print('columnMissingCount: $columnMissingCount');
nonExcelFilteredData = filteredData.where((item) {
final relation = item['Relation'];
return relation != null &&
relation.toString().trim().toLowerCase() != 'self';
}).toList();
print('nonExcelFilteredData');
print(nonExcelFilteredData);
print(nonExcelFilteredData.length);
if (argumentsData['type'] == 'GPA') {
if (nonExcelFilteredData.length > 0) {
print('nonSelf');
invalidRelationships = nonExcelFilteredData.length;
} else {
print('Self');
invalidRelationships = nonExcelFilteredData.length;
}
print('invalidRelationships: $invalidRelationships');
} else {
invalidRelationships = 0;
}
int invalidDobCount = countInvalidDobs(filteredData);
print('Number of invalid DOBs: $invalidDobCount');
dobAgeCheckCount = invalidDobCount;
} else {
print('Some Column is Missing');
var columnMissingCount = 10 - dataArray[0].length;
var columnMissingCount = 11 - dataArray[0].length;
missingColumnErrorMsg = columnMissingCount;
print(missingColumnErrorMsg);
}
}
// bool checkAllSelf(List<Map<String, dynamic>> dataList) {
// // Check if any value of 'Relation' key is not 'Self'
// bool allSelf = dataList.every((data) => data['Relation'] == 'Self');
// // If all values are 'Self', return true; otherwise, return false
// return allSelf;
// }
// Placeholder function for decoding Excel data
List<List<Data>> decodeExcelData(Uint8List fileBytes) {
// Implement your logic to decode Excel data here
// This function should return your array containing Excel data
// For example, you can use the excel package to decode the Excel file
// Import the excel package in your pubspec.yaml file:
// dependencies:
// excel: ^1.1.0
// Then use the following code to decode the Excel file:
// Import the necessary packages
// import 'package:excel/excel.dart';
print('decodeExcelData');
// Create an Excel instance from the fileBytes
final excel = Excel.decodeBytes(fileBytes);
print('decodeExcelData');
print(excel);
// Assuming there's only one sheet in the Excel file
final sheet = excel.tables.keys.first;
@ -263,6 +283,72 @@ class _excelVerifyState extends State<excelVerify> {
return dataArray;
}
List<List<Data>> decodeXLSData(Uint8List fileBytes) {
final Excel excelData = Excel.decodeBytes(fileBytes);
final sheet = excelData.tables.keys.first;
final table = excelData.tables[sheet]!;
List<List<Data>> dataArray = [];
for (int rowIdx = 0; rowIdx < table.rows.length; rowIdx++) {
List<Data> rowData = [];
for (int colIdx = 0; colIdx < table.rows[rowIdx].length; colIdx++) {
var value = table.rows[rowIdx][colIdx]?.value;
rowData.add(Data(value, rowIdx, colIdx, sheet));
}
dataArray.add(rowData);
}
return dataArray;
}
List<List<Data>> decodeCSVData(Uint8List fileBytes) {
String csvString = utf8.decode(fileBytes);
List<List<dynamic>> csvData = const CsvToListConverter().convert(csvString);
List<List<Data>> dataArray = [];
// Skip the header row (if it exists) and start from index 1
for (int i = 1; i < csvData.length; i++) {
List<Data> rowData = [];
for (int j = 0; j < csvData[i].length; j++) {
// Assuming the CSV data is of type String
rowData.add(Data(csvData[i][j].toString(), i, j, 'Sheet1'));
}
dataArray.add(rowData);
}
return dataArray;
}
int countInvalidDobs(List<Map<String, dynamic>> 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);
@ -287,10 +373,13 @@ class _excelVerifyState extends State<excelVerify> {
final decodedBytes = json.decode(jsonString);
if (decodedBytes is List<dynamic>) {
setState(() {
fileName = 'Retrieved File'; // Provide a default name
fileName = fileName ??
'Retrieved File'; // Provide a default name if fileName is null
});
sendExcelFIleTOAPI(
Uint8List.fromList(decodedBytes.cast<int>()), fileName!);
Uint8List.fromList(decodedBytes.cast<int>()),
fileName!,
);
}
}
}
@ -301,44 +390,66 @@ class _excelVerifyState extends State<excelVerify> {
if (fileBytes == null) {
print('return');
return; // No file selected
}
// // 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.apiUrl + 'employeeUpload';
// Create a multipart request
final request = http.MultipartRequest('POST', Uri.parse(apiUrl));
// 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)); // Specify filename here
request.fields['client_id'] = clintID;
// if (policyFirstPart == 'GPA') {
request.fields['policy_id'] = client_policy_id;
// } else {
// request.fields['policy_id'] = '3';
// }
// Send the request
final response = await request.send();
// Check the status code of the response
if (response.statusCode == 200) {
// ToastHelper.showSuccessToast(context, 'File uploaded successfully');
ToastHelper.showSuccessToast(context, 'Data Successfully Send...');
print('File uploaded successfully');
Navigator.pushNamed(context, 'hrHome');
} else {
// ToastHelper.showSuccessToast(
// context, 'Failed to upload file: ${response.reasonPhrase}');
ToastHelper.showSuccessToast(
context, 'Failed to send data: ${response.reasonPhrase}');
print('Failed to upload file: ${response.reasonPhrase}');
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.apiUrl + 'employeeUpload';
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',
));
print('clintID: $clintID');
request.fields['client_id'] = clintID;
print('clientPolicyId: $clientPolicyId');
// if (policyFirstPart == 'GPA') {
request.fields['policy_id'] = clientPolicyId;
// } else {
// request.fields['policy_id'] = '3';
// }
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('else');
// Check the status code of the response
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(responseString);
if (data['status'] == 'success') {
html.window.localStorage.remove('fileBytes');
// ToastHelper.showSuccessToast(context, 'File uploaded successfully');
ToastHelper.showSuccessToast(
context, 'Data Successfully Imported...');
print('Data Successfully Imported');
Navigator.pushNamed(context, 'hrPolicyDetails',
arguments: argumentsData);
} else {
// ToastHelper.showSuccessToast(context, 'File uploaded successfully');
ToastHelper.showErrorToast(context, 'Failed to Imported...');
// Navigator.pushNamed(context, 'hrHome');
}
} else {
// ToastHelper.showSuccessToast(
// context, 'Failed to upload file: ${response.reasonPhrase}');
ToastHelper.showSuccessToast(context, 'Something went wrong');
print('Failed to upload file: ${response.reasonPhrase}');
}
}
}
@ -351,20 +462,54 @@ class _excelVerifyState extends State<excelVerify> {
// Filter the data based on the search query
filteredData = originalData.where((item) {
// Implement your filter logic here, for example:
return item['emp_code'].toLowerCase().contains(query.toLowerCase());
return item['Emp_Code'].toLowerCase().contains(query.toLowerCase());
}).toList();
}
});
}
downloadSampleFile() {
final anchor = html.AnchorElement(href: 'assets/assets/Template_File.xlsx');
anchor.download = 'Template_File.xlsx'; // Set the filename
anchor.click(); // Trigger a click on the anchor element
}
resetErrorCount() {
setState(() {
fileBytes = null;
fileName = null;
_currentStep = 0;
extractedData = [];
originalData = [];
filteredData = [];
validationArray = [];
nonExcelFilteredData = [];
print('filteredData');
print(filteredData);
print(validationArray);
missingColumnErrorMsg = 0;
print(missingColumnErrorMsg);
columnMissingCount = 0;
print(columnMissingCount);
columnIndexMismatchCount = 0;
print(columnIndexMismatchCount);
invalidRelationships = 0;
dobAgeCheckCount = 0;
html.window.localStorage.remove('fileBytes');
});
}
@override
Widget build(BuildContext context) {
// Retrieve the passed argument
dynamic importPolicyName =
ModalRoute.of(context)!.settings.arguments as String?;
// List<String> parts = importPolicyName.split(" - ");
policyFirstPart = importPolicyName;
dynamic arguments = ModalRoute.of(context)!.settings.arguments;
print('arguments');
print(arguments);
if (arguments != null && arguments is Map<String, dynamic>) {
argumentsData = arguments;
}
return Scaffold(
appBar: CustomAppBar(),
@ -395,16 +540,73 @@ class _excelVerifyState extends State<excelVerify> {
alignment: Alignment.bottomCenter,
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
ElevatedButton(
onPressed: () {
html.window.localStorage.remove('fileBytes');
fileBytes = null;
fileName = null;
_currentStep = 0;
missingColumnErrorMsg = 0;
columnIndexMismatchCount = 0;
columnMissingCount = 0;
invalidRelationships = 0;
dobAgeCheckCount = 0;
nonExcelFilteredData = [];
Navigator.pushNamed(
context, 'hrPolicyDetails',
arguments: argumentsData);
},
child: Text(
'Close',
style: TextStyle(color: Color(0xFFE26728)),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
side: BorderSide(color: Color(0xFFE26728)),
),
),
),
// SizedBox(width: 10),
// if (fileName != null)
// ElevatedButton(
// onPressed: () {
// // Reset localStorage and fileBytes
// setState(() {
// html.window.localStorage
// .remove('fileBytes');
// fileBytes = null;
// fileName = null;
// _currentStep = 0;
// });
// },
// child: Text(
// 'Reselect File',
// style: TextStyle(color: Color(0xFFE26728)),
// ),
// style: ElevatedButton.styleFrom(
// backgroundColor: Colors.white,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(5),
// side:
// BorderSide(color: Color(0xFFE26728)),
// ),
// ),
// ),
Spacer(),
SizedBox(
width:
10), // This pushes the buttons to the right
if (_currentStep != 0)
ElevatedButton(
onPressed: () {
controls
.onStepCancel!(); // Call onStepCancel function
controls.onStepCancel!();
},
child: Text(
'Cancel',
'Previous',
style: TextStyle(color: Color(0xFFE26728)),
),
style: ElevatedButton.styleFrom(
@ -419,10 +621,19 @@ class _excelVerifyState extends State<excelVerify> {
SizedBox(width: 10),
if (_currentStep != 2)
ElevatedButton(
onPressed: () {
controls
.onStepContinue!(); // Call onStepContinue function
},
onPressed: _currentStep == 0
? (fileName != null
? controls.onStepContinue!
: null)
: (_currentStep == 1
? (missingColumnErrorMsg == 0 &&
columnIndexMismatchCount ==
0 &&
invalidRelationships == 0 &&
dobAgeCheckCount == 0
? controls.onStepContinue!
: null)
: null),
child: const Text(
'NEXT',
style: TextStyle(color: Colors.white),
@ -468,7 +679,9 @@ class _excelVerifyState extends State<excelVerify> {
} else if (_currentStep == 1) {
// For the second step, allow continue if both errors are 0
if (missingColumnErrorMsg == 0 &&
columnIndexMismatchCount == 0) {
columnIndexMismatchCount == 0 &&
invalidRelationships == 0 &&
dobAgeCheckCount == 0) {
setState(() {
_currentStep += 1;
});
@ -513,7 +726,7 @@ class _excelVerifyState extends State<excelVerify> {
children: [
Expanded(
child: Text(
policy_name ?? '',
'$policy_name - ($policyType)',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
@ -558,26 +771,92 @@ class _excelVerifyState extends State<excelVerify> {
MainAxisAlignment
.center,
children: [
if (fileName == null)
Text(
'Drop files here to start uploading',
style: TextStyle(
fontSize: 16),
),
SizedBox(height: 20),
if (fileName == null)
Text(
'OR',
style: TextStyle(
fontSize: 16),
), // Add spacing between texts
SizedBox(height: 20),
// if (fileName == null)
// ElevatedButton(
// onPressed: () => {},
// child: Icon(
// Icons.download,
// color: Colors
// .grey), // You can replace the Icon with your custom button child
// style:
// ElevatedButton
// .styleFrom(
// shape:
// CircleBorder(), // Makes the button round
// padding:
// EdgeInsets.all(
// 18), // Change the button color as needed
// ),
// ),
// SizedBox(height: 20),
// if (fileName == null)
// Text(
// 'Drag and drop file to import',
// style: TextStyle(
// fontSize: 16,
// fontWeight:
// FontWeight
// .w600),
// ), // Add spacing between texts
// SizedBox(height: 20),
fileName != null
? Text(
'File Uploaded: $fileName',
style: TextStyle(
fontSize:
16),
? 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:
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: () =>
@ -596,6 +875,10 @@ class _excelVerifyState extends State<excelVerify> {
0xFFE26728),
),
),
SizedBox(height: 20),
if (fileName == null)
Text(
'Supported Files : XLSX')
// Add more Text widgets for additional lines of text
],
),
@ -606,6 +889,43 @@ class _excelVerifyState extends State<excelVerify> {
),
],
),
Row(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Text(
'Ensure that the import file is in the correct format by comparing it with our template file.',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
fontWeight:
FontWeight.w400,
)),
MouseRegion(
cursor:
SystemMouseCursors.click,
child: GestureDetector(
onTap: () {
downloadSampleFile();
},
child: Text(
'Template File',
style: TextStyle(
fontSize: 15,
color: Color(
0xFFE26728), // Add underline decoration
),
),
),
)
]))
],
)
],
),
),
@ -634,7 +954,7 @@ class _excelVerifyState extends State<excelVerify> {
missingColumnErrorMsg == 0
? Icons.check_circle
: Icons.error,
'No of column missing - $missingColumnErrorMsg',
'No of column missing : $missingColumnErrorMsg Column',
iconColor: missingColumnErrorMsg == 0
? Colors.green
: Colors
@ -645,20 +965,29 @@ class _excelVerifyState extends State<excelVerify> {
columnIndexMismatchCount == 0
? Icons.check_circle
: Icons.error,
'Column Index is Missmatching - $columnIndexMismatchCount',
'Mismatch in Column Order : $columnIndexMismatchCount - Column',
iconColor: columnIndexMismatchCount == 0
? Colors.green
: Colors.red,
),
// _buildRowWithIcon(
// columnMissingCount == 0
// ? Icons.check_circle
// : Icons.error,
// 'Column Missing - $columnMissingCount',
// iconColor: columnMissingCount == 0
// ? Colors.green
// : Colors.red,
// ),
_buildRowWithIcon(
invalidRelationships == 0
? Icons.check_circle
: Icons.error,
'Invalid Relationships : $invalidRelationships - Rows',
iconColor: invalidRelationships == 0
? Colors.green
: Colors.red,
),
_buildRowWithIcon(
dobAgeCheckCount == 0
? Icons.check_circle
: Icons.error,
'Age Config - $dobAgeCheckCount - Rows',
iconColor: dobAgeCheckCount == 0
? Colors.green
: Colors.red,
),
],
),
),
@ -773,7 +1102,7 @@ class _excelVerifyState extends State<excelVerify> {
return Card(
elevation: 0, // Set elevation to 0 for no shadow
child: PaginatedDataTable(
rowsPerPage: 10, // Adjust rows per page as needed
rowsPerPage: 25, // Adjust rows per page as needed
columns: [
DataColumn(label: Text('S.No')),
DataColumn(label: Text('Employee ID')),
@ -785,6 +1114,7 @@ class _excelVerifyState extends State<excelVerify> {
DataColumn(label: Text('Mail')),
DataColumn(label: Text('Mobile No')),
DataColumn(label: Text('SI')),
DataColumn(label: Text('Grade')),
],
source: _DependenceDataSource0(filteredData),
),
@ -824,20 +1154,21 @@ class _DependenceDataSource0 extends DataTableSource {
DataRow getRow(int index) {
final row = _data[index];
// Format date of birth to "July 10, 1996"
String dob = row['dob'] != null ? formatDateString(row['dob']) : 'N/A';
String dob = row['DOB'] != null ? formatDate(row['DOB']) : 'N/A';
String doj = row['DOJ'] != null ? formatDate(row['DOJ']) : 'N/A';
return DataRow(cells: [
DataCell(Text(row['Sno'].toString())),
DataCell(Text(row['emp_code'].toString())),
DataCell(Text(row['Emp_Code'].toString())),
DataCell(Text(row['Name'].toString())),
DataCell(Text(row['DOJ']?.toString() ?? 'N/A')),
DataCell(Text(doj)),
DataCell(Text(row['Gender']?.toString() ?? 'N/A')),
DataCell(Text(row['Relation']?.toString() ?? 'N/A')),
DataCell(Text(dob)),
DataCell(Text(row['Mail']?.toString() ?? 'N/A')),
DataCell(Text(row['Mobile']?.toString() ?? 'N/A')),
DataCell(Text(row['SI']?.toString() ?? 'N/A')),
DataCell(Text(row['Grade']?.toString() ?? 'N/A')),
]);
}
@ -850,12 +1181,18 @@ class _DependenceDataSource0 extends DataTableSource {
@override
int get selectedRowCount => 0;
String formatDateString(String dateString) {
// Parse the date string to DateTime object
DateTime dateTime = DateTime.parse(dateString);
// Format the DateTime object to "July 03, 2024"
String formattedDate = DateFormat.yMMMMd().format(dateTime);
return formattedDate;
String formatDate(dynamic dateValue) {
if (dateValue is String) {
// If the date is already in string format
DateTime dateTime = DateTime.parse(dateValue);
return DateFormat('dd-MM-yyyy').format(dateTime);
} else if (dateValue is DateCellValue) {
// If dateValue is an instance of DateCellValue
return DateFormat('dd-MM-yyyy')
.format(DateTime.parse(dateValue.toString()));
} else {
// Handle other cases or null values
return 'N/A';
}
}
}

845
lib/hrDashboard.dart Normal file
View File

@ -0,0 +1,845 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:jwt_decode/jwt_decode.dart';
import 'package:nhancepolicy/models/environment.dart';
import 'package:nhancepolicy/responsive.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import 'customAppBar/customAppBar.dart';
import 'customAppBar/toastHelper.dart';
import 'package:universal_html/html.dart' as html;
import 'package:intl/intl.dart';
class hrDashboard extends StatefulWidget {
const hrDashboard({Key? key}) : super(key: key);
@override
State<hrDashboard> createState() => _hrDashboardState();
}
class _hrDashboardState extends State<hrDashboard> {
bool isLoading = true;
late String _token;
dynamic getPolicyNo;
bool _isLoading = false;
dynamic getPolicyNameDetails;
dynamic clintID;
dynamic policy_name;
dynamic getCardArrays = [];
dynamic clientName;
dynamic clientLogo;
final List<Color> cardColors = [
Color(0xFFFFE3D9),
Color(0xFFFFD9EE),
Color(0xFFDBFFDE),
Color(0xFFE4DFFF),
];
@override
void initState() {
super.initState();
_loadToken();
Future.delayed(Duration(seconds: 3), () {
setState(() {
isLoading = false;
});
});
}
@override
void dispose() {
super.dispose();
}
Future<void> _loadToken() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final token = prefs.getString('hrtoken');
if (token != null && token.isNotEmpty) {
setState(() {
_token = token;
});
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
clintID = decodedToken['client_id'].toString();
print(clintID);
if (prefs.containsKey('clientLogo') && prefs.containsKey('clientName')) {
clientLogo = prefs.getString('clientLogo');
clientName = prefs.getString('clientName');
} else {
getClientLogoAndDetails();
}
await getCashDepositDetails(clintID);
} 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<void> getClientLogoAndDetails() async {
var url =
Uri.parse(Environment.apiUrl + 'getClientDetails?client_id=$clintID');
try {
var response = await http.get(
url,
headers: {
'Authorization':
'Bearer $_token', // Add token to the Authorization header
},
);
if (response.statusCode == 200) {
print('response.statusCode == 200');
Map<String, dynamic> data = json.decode(response.body);
print(data);
if (data.containsKey('data')) {
dynamic clientDetails = data['data'];
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('clientLogo', clientDetails['client']['client_logo']);
prefs.setString('clientName', clientDetails['client']['client_name']);
setState(() {
// dynamic clientDetails = data['data'];
// print(clientDetails);
clientName = clientDetails['client']['client_name'];
print(clientName);
clientLogo = clientDetails['client']['client_logo'];
print(clientLogo);
});
} else {
// Handle other status messages if needed
// ToastHelper.showErrorToast(
// context, 'API request failed with status: ${data['status']}');
print('API request failed with status: ${data['status']}');
}
} else {
// Handle other status codes
// ToastHelper.showErrorToast(
// context, 'Request failed with status: ${response.statusCode}');
print('Request failed with status: ${response.statusCode}');
}
} catch (e) {
// Handle exceptions
print('Exception occurred: $e');
}
}
Future<void> getCashDepositDetails(String clintID) async {
setState(() {
_isLoading = true;
});
var url = Uri.parse(
Environment.apiUrl + 'getCashDepositData?client_id=' + clintID);
try {
var response = await http.get(
url,
headers: {
'Authorization': 'Bearer $_token',
},
);
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
if (data['status'] == 'success') {
setState(() {
getCardArrays = List<Map<String, dynamic>>.from(data['data']);
print(getCardArrays);
});
} else {
// No matching policy found
print('No matching policy found for');
}
} else {
print('API request failed with status');
}
} catch (e) {
print('Exception occurred: $e');
}
}
Future<void> downloadExcel(clintId, clintIdclintId, insurerName) async {
// API endpoint to download the Excel file
// Send GET request to the API
var url = Uri.parse(Environment.apiUrl +
'exportCashDepositData?client_id=$clintId&insurer_id=$clintIdclintId');
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', '$insurerName.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) {
if (getCardArrays == []) {
return Scaffold(
appBar: CustomAppBar(),
body: SingleChildScrollView(
child: Container(
color: Color(0xFFEFF3F6),
child: Column(
children: [
Center(
child: Text('No Data Available'),
)
],
),
),
));
} else {
int numCards = getCardArrays.length;
int numExpanded = numCards < 4 ? numCards : 4;
double cardHeight = MediaQuery.of(context).size.height / 4.5;
double policyHeight = MediaQuery.of(context).size.height / 4.5;
double cardWidth = MediaQuery.of(context).size.width / 6;
return Scaffold(
appBar: CustomAppBar(),
body: Stack(children: [
SingleChildScrollView(
child: Container(
padding:
EdgeInsets.only(top: 30, bottom: 30, left: 50, right: 50),
color: Color(0xFFEFF3F6),
child: Column(
children: [
Card(
elevation: 0,
child: Container(
width: double.infinity,
height: 75,
padding: Responsive.isDesktop(context)
? EdgeInsets.only(
top: 10, bottom: 10, left: 20, right: 20)
: EdgeInsets.only(
top: 12,
bottom: 12,
left: 10,
right: 10), // Add padding to the container
child: Row(
children: [
Expanded(
flex: 6,
child: Container(
width: 150,
height: 150,
alignment: Alignment.centerLeft,
child: Image.network(
clientLogo ?? '',
width: 80, // Set the width here
height: 80, // Set the height here
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress
.expectedTotalBytes !=
null
? loadingProgress
.cumulativeBytesLoaded /
loadingProgress
.expectedTotalBytes!
: null,
),
);
},
errorBuilder: (BuildContext context,
Object error, StackTrace? stackTrace) {
return Image.asset(
'assets/Solid_gray.png', // Replace 'default_image.png' with your default image asset path
width: 80,
height: 80,
fit: BoxFit.cover,
);
},
),
),
),
Expanded(
flex: 9,
child: Text(
clientName ?? '',
textAlign: TextAlign.right,
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context) ? 20 : 18,
fontWeight: FontWeight.w600,
),
),
)
],
),
),
),
SizedBox(height: 16),
Card(
elevation: 0,
child: Container(
width: double.infinity,
padding: Responsive.isDesktop(context)
? EdgeInsets.all(20)
: EdgeInsets.all(
10), // Add padding to the container
child: Column(children: [
Row(children: [
Text(
'Cash Transaction',
style: GoogleFonts.poppins(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.black,
),
)
]),
SizedBox(height: 8),
Row(
children: [
// Create an Expanded widget with flex of 4 for each card
for (var cardData in getCardArrays)
Container(
width:
300, // Set a fixed width for the card
height: cardHeight,
child: Card(
elevation: 3,
color: cardColors[
getCardArrays.indexOf(cardData) %
cardColors.length],
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
ListTile(
title: SizedBox(
height: 50,
child: Text(
cardData['insurerName'],
style: GoogleFonts.poppins(
fontSize: 18,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
height: 1.5,
),
),
),
subtitle: Text(
'Balance: ₹ ${cardData['balance']}',
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Color(0xFF000000),
height: 1.5,
),
),
),
SizedBox(height: 10),
Padding(
padding: EdgeInsets.symmetric(
horizontal: 15),
child: GestureDetector(
onTap: () {
openForm(
cardData['depositData'],
cardData['insurerName'],
cardData['clientId'],
cardData['insurerId'],
cardColors[getCardArrays
.indexOf(cardData) %
cardColors.length],
);
},
child: MouseRegion(
cursor:
SystemMouseCursors.click,
child: Align(
alignment:
Alignment.centerRight,
child: Text(
'View Details',
style: GoogleFonts.poppins(
color: Color(0xFF000000),
fontSize: 14,
fontWeight:
FontWeight.w300,
height: 1.5,
),
),
),
),
),
),
],
),
),
),
],
),
])),
),
SizedBox(height: 16),
Card(
elevation: 0,
child: Padding(
padding: Responsive.isDesktop(context)
? EdgeInsets.all(20)
: EdgeInsets.all(10),
child: Column(
children: [
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: List.generate(
numExpanded,
(index) {
var insurerName = getCardArrays[index]
['insurerName'];
var policyDetails =
getCardArrays[index]
['policyDetails'];
// Determine the color for the policyDetails based on the index of the card in getCardArrays
var cardColorIndex =
getCardArrays.indexOf(
getCardArrays[index]) %
cardColors.length;
var cardColor =
cardColors[cardColorIndex];
return Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
insurerName,
style: GoogleFonts.poppins(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
SizedBox(height: 8),
Row(
children: List.generate(
policyDetails.length,
(index) => Container(
width: 300,
height: policyHeight,
child: GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
'hrPolicyDetails',
arguments:
policyDetails[
index]);
},
child: MouseRegion(
cursor:
SystemMouseCursors
.click,
child: Card(
elevation: 3,
color:
cardColor, // Use the determined color
child: Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
ListTile(
title: SizedBox(
height: 50,
child: Text(
'${policyDetails[index]['policy_name']} - (${policyDetails[index]['type']})',
style: GoogleFonts
.poppins(
fontSize:
16,
fontWeight:
FontWeight
.w500,
color: Color(
0xFF000000),
height:
1.5,
),
softWrap:
true, // Allow text to wrap to the next line if needed
),
),
),
SizedBox(
height: 8),
Padding(
padding: EdgeInsets
.only(
left:
15,
right:
15),
child: Row(
children: [
Expanded(
flex: 4,
child:
Column(
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
Text(
'Draft',
style:
GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
height: 1.5,
),
),
Text(
policyDetails[index]['membersCountOfDraft'].toString(),
style:
GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Color(0xFF000000),
height: 1.5,
),
),
],
),
),
Expanded(
flex: 4,
child:
Column(
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
Text(
'Enrolled',
style:
GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
height: 1.5,
),
),
Text(
policyDetails[index]['membersCountOfEnrolled'].toString(),
style:
GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Color(0xFF000000),
height: 1.5,
),
),
],
),
),
Expanded(
flex: 4,
child:
Column(
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
Text(
'Total',
style:
GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF000000),
height: 1.5,
),
),
Text(
policyDetails[index]['totalMembersCount'].toString(),
style:
GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Color(0xFF000000),
height: 1.5,
),
),
],
),
),
],
), // Adjust the horizontal padding as needed
)
],
),
),
),
),
),
),
),
SizedBox(height: 20),
],
);
},
),
),
),
],
)
],
),
))
],
),
),
),
if (isLoading)
Container(
color: Color(0xFFFFFCE5), // 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
),
),
]));
}
}
void openForm(dynamic floaterData, dynamic insurerName, dynamic clintId,
dynamic insurerId, dynamic cardColors) {
print(clintId);
print(insurerId);
print(floaterData);
print(floaterData);
print('test');
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
elevation: 0,
backgroundColor: Colors.transparent,
content: SizedBox(
width: 1000,
child: SingleChildScrollView(
child: Card(
elevation: 0,
child: Column(
children: [
Container(
child: Column(
children: [
Container(
padding:
EdgeInsets.all(10), // Set your desired padding
color:
cardColors, // Set your desired background color
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 10,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
Text(insurerName ?? '',
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.black,
)),
],
),
),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment
.centerRight, // Align text to the center
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () {
downloadExcel(
clintId, insurerId, insurerName);
},
child: Icon(
Icons
.download, // Replace with your desired icon
color: Colors
.black, // Replace with your desired icon color
),
),
),
),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment
.centerRight, // Align text to the center
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () {
Navigator.of(context).pop();
},
child: Icon(
Icons
.close, // Replace with your desired icon
color: Colors
.black, // Replace with your desired icon color
),
),
),
),
),
],
),
),
SizedBox(height: 15),
Row(
children: [
Expanded(
child: SingleChildScrollView(
child: _buildDataTable(context, floaterData),
),
)
],
),
],
),
),
],
),
),
),
),
);
},
);
}
Widget _buildDataTable(BuildContext context, dynamic tableData) {
print('tableData');
print(tableData);
// Check if tableData is a list
if (tableData is List) {
// If tableData is a list and not empty
if (tableData.isNotEmpty && tableData[0] is Map<String, dynamic>) {
return Card(
elevation: 0, // Set elevation to 0 for no shadow
child: PaginatedDataTable(
rowsPerPage: 10, // Adjust rows per page as needed
columns: [
DataColumn(label: Text('Date')),
DataColumn(label: Text('Description')),
DataColumn(label: Text('Transaction Type')),
DataColumn(label: Text('Amount')),
DataColumn(label: Text('Balance')),
],
source: _DependenceDataSource(context, tableData),
),
);
} else {
// If tableData is empty or not in the expected format
return Text('No Data Available', textAlign: TextAlign.center);
}
} else {
// If tableData is not a list, return a message indicating invalid data
return Text('Invalid Data Format', textAlign: TextAlign.center);
}
}
}
class _DependenceDataSource extends DataTableSource {
final List<Map<String, dynamic>> _data;
final BuildContext context;
_DependenceDataSource(this.context, List<dynamic> tableData)
: _data = tableData.map((e) => e as Map<String, dynamic>).toList();
@override
DataRow getRow(int index) {
final row = _data[index];
// Format date of birth to "July 10, 1996"
String created_Date =
row['created_at'] != null ? formatDateString(row['created_at']) : 'N/A';
return DataRow(
// Setting row background color
cells: [
DataCell(Text(created_Date)),
DataCell(Text(row['description'] ?? 'N/A')),
DataCell(Text(row['transaction_type'].toString() ?? '')),
DataCell(Text(row['amount'] ?? 'N/A')),
DataCell(Text(row['balance'] ?? 'N/A')),
],
);
}
@override
bool get isRowCountApproximate => false;
@override
int get rowCount => _data.length;
@override
int get selectedRowCount => 0;
String formatDateString(String dateString) {
// Parse the input date string
DateTime inputDate = DateTime.parse(dateString);
// Format the date as DD-MM-YYYY HH:mm A
String formattedDate = DateFormat('dd-MM-yyyy hh:mm a').format(inputDate);
return formattedDate;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,9 @@ import 'package:nhancepolicy/models/environment.dart';
import 'dart:convert';
import 'dart:io';
import 'package:nhancepolicy/responsive.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:flutter_animated_button/flutter_animated_button.dart';
class MyHrLogin extends StatefulWidget {
const MyHrLogin({Key? key});
@ -24,17 +27,30 @@ class _MyPhoneState extends State<MyHrLogin> {
void initState() {
countryController.text = "+91";
super.initState();
checkTokenAvailability();
}
Future<void> checkTokenAvailability() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String? hrtoken = prefs.getString('hrtoken');
if (hrtoken != null && hrtoken.isNotEmpty) {
// Token available, navigate to home page
Navigator.pushReplacementNamed(context, 'hrDashboard',
arguments: {'mobile': ''});
}
}
void toggleLoginType() {
Navigator.pushNamed(context, 'phone'); // Navigate to another page
}
Future<bool> verifyMobileNumber(String mobileNumber) async {
Future<void> verifyMobileNumber() async {
try {
var enteredMobileNumber = mobileController.text;
final response = await http.post(
Uri.parse(Environment.apiUrl + 'verifyHrWithMobileNumber'),
body: json.encode({'mobile_number': mobileNumber}),
body: json.encode({'mobile_number': enteredMobileNumber}),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
},
@ -43,34 +59,41 @@ class _MyPhoneState extends State<MyHrLogin> {
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
bool userVerification = data['data']['user_verification'];
return userVerification;
String message = data['data']['message'];
if (userVerification) {
ToastHelper.showSuccessToast(context, message);
Navigator.pushNamed(context, 'hrVerify',
arguments: enteredMobileNumber);
} else {
ToastHelper.showErrorToast(context, message);
print('Invalid mobile number');
}
} else {
ToastHelper.showErrorToast(context, 'Failed to verify mobile number');
throw Exception('Failed to verify mobile number');
}
} catch (e) {
print('Error: $e');
ToastHelper.showErrorToast(context, 'Error: $e');
return false;
ToastHelper.showErrorToast(context, 'Something went wrong');
}
}
void handleSubmit() async {
if (_formKey.currentState!.validate()) {
// var enteredMobileNumber = countryController.text + mobileController.text;
var enteredMobileNumber = mobileController.text;
bool isValid = await verifyMobileNumber(enteredMobileNumber);
if (isValid) {
ToastHelper.showSuccessToast(context, 'Mobile No Verified...');
Navigator.pushNamed(context, 'hrVerify',
arguments: enteredMobileNumber);
} else {
ToastHelper.showErrorToast(context, 'Invalid mobile number');
}
}
}
// void handleSubmit() async {
// if (_formKey.currentState!.validate()) {
// // var enteredMobileNumber = countryController.text + mobileController.text;
// var enteredMobileNumber = mobileController.text;
//
// bool isValid = await verifyMobileNumber(enteredMobileNumber);
//
// if (isValid) {
// ToastHelper.showSuccessToast(context, 'Mobile No Verified...');
// Navigator.pushNamed(context, 'hrVerify',
// arguments: enteredMobileNumber);
// } else {
// ToastHelper.showErrorToast(context, 'Invalid mobile number');
// }
// }
// }
@override
Widget build(BuildContext context) {
@ -142,7 +165,7 @@ class _MyPhoneState extends State<MyHrLogin> {
),
SizedBox(width: 5),
Text(
'Customer Login',
'Member Login',
style: TextStyle(
color: Color(0xFF000000), // Text color
// Add other text styles as needed
@ -269,36 +292,35 @@ class _MyPhoneState extends State<MyHrLogin> {
flex: 4,
child: Align(
alignment: Alignment.centerLeft,
child: MouseRegion(
cursor:
SystemMouseCursors.click,
child: GestureDetector(
onTap: () {
// Add your navigation logic here
// For example, you can use Navigator.push to navigate to another page
Navigator.pushNamed(
context, 'phone');
},
child: Row(
children: [
Icon(
Icons
.west, // Icon for customer login
color: Colors
.black, // Adjust color as needed
),
SizedBox(width: 5),
Text(
'Customer Login',
style: TextStyle(
color: Color(
0xFF000000), // Text color
// Add other text styles as needed
),
),
],
),
child: AnimatedButton(
animatedOn:
AnimatedOn.onHover,
onPress: () {
Navigator.pushNamed(
context, 'phone');
},
onChanges: (change) {},
height: 30,
width: 150,
text: 'Member Login',
isReverse: true,
selectedTextColor:
Colors.black,
transitionType: TransitionType
.RIGHT_CENTER_ROUNDER,
textStyle:
GoogleFonts.poppins(
fontSize: 16,
letterSpacing: 0,
color: Color(0xFF00989E),
fontWeight: FontWeight.w300,
),
backgroundColor: Colors.white,
selectedBackgroundColor:
Color(0xFF00989E),
borderColor:
Color(0xFF00989E),
borderWidth: 1,
),
)),
Expanded(
@ -360,7 +382,7 @@ class _MyPhoneState extends State<MyHrLogin> {
children: [
Expanded(
child: Text(
"Have a Health Insurance Policy number, but never signed in? Don't worry, We got you covered",
"Login to manage the employee enrollment and overall health insurance programme of your organisation",
style: TextStyle(
fontSize: 12,
color: Color(0xFF000000)),
@ -460,7 +482,7 @@ class _MyPhoneState extends State<MyHrLogin> {
BorderRadius.circular(10),
),
),
onPressed: handleSubmit,
onPressed: verifyMobileNumber,
child: Text(
"Login With OTP",
style: TextStyle(

746
lib/hrPolicyDetails.dart Normal file
View File

@ -0,0 +1,746 @@
import 'package:flutter/material.dart';
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: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;
class hrPolicyDetails extends StatefulWidget {
const hrPolicyDetails({Key? key}) : super(key: key);
@override
State<hrPolicyDetails> createState() => _HrPolicyDetailsState();
}
class _HrPolicyDetailsState extends State<hrPolicyDetails>
with TickerProviderStateMixin {
Uint8List? fileBytes;
late String _token;
List<Map<String, dynamic>> getEmpDependenceByClintId = [];
bool _isLoading = false;
// dynamic clintID;
late TabController _tabController;
// List<dynamic> dataPolicy = [];
List<dynamic> reversedDataPolicy = [];
List<Map<String, dynamic>> originalData = []; // Original data source
List<Map<String, dynamic>> filteredData = []; // Filtered data source
dynamic argumentsData;
dynamic policyType;
dynamic policyName;
dynamic clientPolicyId;
dynamic clientId;
int inceptionType = 0;
TextEditingController searchController = TextEditingController();
@override
void initState() {
super.initState();
_tabController = TabController(length: 4, vsync: this);
_loadToken();
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
Future<void> _loadToken() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final token = prefs.getString('hrtoken');
if (token != null && token.isNotEmpty) {
setState(() {
_token = token;
});
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
// 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<void> getPolicyDetails() async {
setState(() {
_isLoading = true;
});
try {
setState(() {
if (argumentsData != null && argumentsData is Map<String, dynamic>) {
if (argumentsData['type'] == 'GPA') {
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') {
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'] == 'SI TopUp') {
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'] == 'Dependent AddOn') {
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) {
print('Exception occurred: $e');
} finally {
setState(() {
_isLoading = false;
});
}
}
Future<void> getEmployeeAndDependence(clintID, getPolicyNo) async {
setState(() {
_isLoading = true;
});
var url = Uri.parse(Environment.apiUrl +
'getEmployeeAndDependenceByClientId?client_id=$clintID&client_policy_id=$getPolicyNo');
try {
var response = await http.get(
url,
headers: {
'Authorization': 'Bearer $_token',
},
);
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
if (data['status'] == 'success') {
setState(() {
getEmpDependenceByClintId =
List<Map<String, dynamic>>.from(data['data']);
originalData = getEmpDependenceByClintId;
filteredData = List.from(originalData);
print('filteredData');
print(filteredData);
});
} else {
// ToastHelper.showWarningToast(
// context, 'API request failed with status: ${data['status']}');
print('API request failed with status: ${data['status']}');
}
} else {
// ToastHelper.showWarningToast(
// context, 'Request failed with status: ${response.statusCode}');
print('Request failed with status: ${response.statusCode}');
}
} catch (e) {
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<void> 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');
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<String, dynamic>) {
argumentsData = arguments;
}
if (filteredData == []) {
return Scaffold(
appBar: CustomAppBar(),
body: SingleChildScrollView(
child: Container(
color: Color(0xFFEFF3F6),
child: Column(
children: [
Center(
child: Text('No Data Available'),
)
],
),
),
));
} else {
return Scaffold(
appBar: CustomAppBar(),
body: Container(
padding: const EdgeInsets.all(20),
color: Color(0xFFEFF3F6),
child: Card(
elevation: 0,
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: () {
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') &&
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,
),
),
)
],
),
),
),
),
],
),
)),
),
);
}
}
Widget _buildDataTableGPA(context) {
if (filteredData.isEmpty) {
SizedBox(height: 25);
return Text('No available data');
} else {
return Card(
elevation: 0, // Set elevation to 0 for no shadow
child: PaginatedDataTable(
rowsPerPage: 25, // Adjust rows per page as needed
columns: [
DataColumn(label: Text('Employee ID')),
DataColumn(label: Text('Name')),
DataColumn(label: Text('Relationship')),
DataColumn(label: Text('Date of Birth')),
DataColumn(label: Text('Gender')),
DataColumn(label: Text('Mobile No')),
],
source: _DependenceDataSource0(filteredData, context),
),
);
}
}
}
class _DependenceDataSource0 extends DataTableSource {
final List<Map<String, dynamic>> _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';
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['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)),
],
);
}
@override
bool get isRowCountApproximate => false;
@override
int get rowCount => _data.length;
@override
int get selectedRowCount => 0;
void _navigateToAnotherPage(row) {
print(row['mobile']);
// 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);
}

View File

@ -24,10 +24,18 @@ class _MyVerifyState extends State<MyHrVerify> {
late Timer _timer;
int _secondsRemaining = 30;
bool _isTimerRunning = false;
dynamic _token;
dynamic empCodeString;
dynamic empPrimaryId;
dynamic gpaEmpName;
dynamic client_id;
dynamic clientName;
dynamic clientLogo;
@override
void initState() {
super.initState();
checkTokenAvailability();
// Start the timer when the widget is initialized
startTimer();
}
@ -52,6 +60,16 @@ class _MyVerifyState extends State<MyHrVerify> {
});
}
Future<void> checkTokenAvailability() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String? hrtoken = prefs.getString('hrtoken');
if (hrtoken != null && hrtoken.isNotEmpty) {
// Token available, navigate to home page
Navigator.pushReplacementNamed(context, 'hrDashboard');
}
}
Future<void> resendOTP(String mobileNumber) async {
print(mobileNumber);
// Update the UI as needed
@ -85,8 +103,7 @@ class _MyVerifyState extends State<MyHrVerify> {
} catch (e) {
// Handle API call errors
print('Error: $e');
ToastHelper.showErrorToast(
context, 'Failed to resend OTP. Please try again.');
ToastHelper.showErrorToast(context, 'Something went wrong');
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
// content: Text('Failed to resend OTP. Please try again.'),
@ -110,16 +127,32 @@ class _MyVerifyState extends State<MyHrVerify> {
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
_token = data['data'];
print(data);
String status = data['status'];
print(status);
if (status == 'success') {
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('hrtoken', data['data']);
// Decode the JWT token received from the API response
Map<String, dynamic>? decodedToken = Jwt.parseJwt(data['data']);
print(decodedToken);
empCodeString = decodedToken['emp_code'].toString();
prefs.setString('empCode', empCodeString);
empPrimaryId = decodedToken['id'];
prefs.setString('empPrimaryId', empPrimaryId);
gpaEmpName = decodedToken['name'].toString();
prefs.setString('gpaEmpName', gpaEmpName);
client_id = decodedToken['client_id'];
prefs.setString('client_id', client_id);
getClientLogoAndDetails();
print('Successfully Login');
final hrtoken = prefs.getString('hrtoken');
if (hrtoken != null && hrtoken.isNotEmpty) {
ToastHelper.showSuccessToast(context, 'Successfully Login');
Navigator.pushNamed(context, 'hrHome');
Navigator.pushNamed(context, 'hrDashboard');
} else {
// Token is empty or null, handle accordingly (e.g., navigate to login screen)
// For now, let's navigate to the login screen
@ -153,6 +186,53 @@ class _MyVerifyState extends State<MyHrVerify> {
}
}
Future<void> getClientLogoAndDetails() async {
var url = Uri.parse(Environment.apiUrl +
'getClientDetails?client_id=$client_id&emp_code=$empCodeString');
try {
var response = await http.get(
url,
headers: {
'Authorization':
'Bearer $_token', // Add token to the Authorization header
},
);
if (response.statusCode == 200) {
// print('response.statusCode == 200');
Map<String, dynamic> data = json.decode(response.body);
// print(data);
if (data.containsKey('data')) {
dynamic clientDetails = data['data'];
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('clientLogo', clientDetails['client']['client_logo']);
prefs.setString('clientName', clientDetails['client']['client_name']);
setState(() {
// dynamic clientDetails = data['data'];
// print(clientDetails);
clientName = clientDetails['client']['client_name'];
print(clientName);
clientLogo = clientDetails['client']['client_logo'];
print(clientLogo);
});
} else {
// Handle other status messages if needed
// ToastHelper.showErrorToast(
// context, 'API request failed with status: ${data['status']}');
print('API request failed with status: ${data['status']}');
}
} else {
// Handle other status codes
// ToastHelper.showErrorToast(
// context, 'Request failed with status: ${response.statusCode}');
print('Request failed with status: ${response.statusCode}');
}
} catch (e) {
// Handle exceptions
print('Exception occurred: $e');
}
}
@override
Widget build(BuildContext context) {
// Retrieve the passed mobile number value

View File

@ -9,8 +9,11 @@ import 'package:nhancepolicy/models/environment.dart';
import 'package:nhancepolicy/phone.dart';
import 'package:nhancepolicy/verify.dart';
import 'package:nhancepolicy/home.dart';
import 'package:nhancepolicy/hrDashboard.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:nhancepolicy/hrLogin.dart';
import 'package:nhancepolicy/hrPolicyDetails.dart';
import 'package:nhancepolicy/oldPolicy.dart';
Future<void> main() async {
await dotenv.load(fileName: Environment.fileName);
@ -29,6 +32,9 @@ Future<void> main() async {
'empDetails': (context) => empDetails(),
'addOnsDetails': (context) => addOnsDetails(),
'empReviewDetails': (context) => empReviewDetails(),
'hrDashboard': (context) => hrDashboard(),
'hrPolicyDetails': (context) => hrPolicyDetails(),
'oldPolicy': (context) => oldPolicy(),
},
));
}

385
lib/oldPolicy.dart Normal file
View File

@ -0,0 +1,385 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:jwt_decode/jwt_decode.dart';
import 'package:nhancepolicy/models/environment.dart';
import 'package:nhancepolicy/responsive.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import 'customAppBar/customAppBar.dart';
import 'customAppBar/toastHelper.dart';
class oldPolicy extends StatefulWidget {
const oldPolicy({Key? key}) : super(key: key);
@override
State<oldPolicy> createState() => _oldPolicyState();
}
class _oldPolicyState extends State<oldPolicy> {
dynamic _token;
dynamic empCodeString;
dynamic empPrimaryId;
dynamic client_id;
dynamic gpaEmpName;
dynamic oldPolicyList;
dynamic oldPolicyName;
dynamic oldPolicyClientId;
dynamic oldPolicyClientPolicyId;
dynamic oldPolicySiGstValue;
dynamic oldPolicySiPremiumValue;
dynamic oldPolicySiValue;
dynamic oldPolicyType;
dynamic oldPolicyEmployeePolicy;
dynamic oldPolicyDataIsEmpty = 1;
dynamic oldPolicyTypeHeading;
dynamic oldPolicyFloaterTextHeading;
dynamic oldPolicyStartDate;
dynamic oldPolicyEndDate;
@override
void initState() {
super.initState();
_loadToken();
}
@override
void dispose() {
super.dispose();
}
Future<void> _loadToken() async {
print('_loadToken');
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String? token = prefs.getString('token');
if (token != null && token.isNotEmpty) {
setState(() {
_token = token;
});
// Decode the JWT token received from the API response
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
print(decodedToken);
empCodeString = prefs.getString('empCode');
print(empCodeString); // Check if emp_code is correct
empPrimaryId = prefs.getString('empPrimaryId');
gpaEmpName = prefs.getString('gpaEmpName');
client_id = prefs.getString('client_id');
print(client_id);
getOldPolicyDetails();
} 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, 'phone');
}
}
Future<void> getOldPolicyDetails() async {
var url = Uri.parse(Environment.apiUrl +
'getEmployeeActiveOrInactivePolicy?client_id=$client_id&emp_code=$empCodeString&type=Inactive');
try {
var response = await http.get(
url,
headers: {
'Authorization':
'Bearer $_token', // Add token to the Authorization header
},
);
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
if (data['status'] == 'success') {
setState(() {
oldPolicyList = data['data'];
print('gmcPolicies');
});
// Assuming data is a List
print(oldPolicyList);
} else {
setState(() {
oldPolicyDataIsEmpty = 0;
});
// Handle other status messages if needed
// ToastHelper.showErrorToast(
// context, 'API request failed with status: ${data['status']}');
print('API request failed with status: ${data['status']}');
}
} else {
setState(() {
oldPolicyDataIsEmpty = 0;
});
// Handle other status codes
// ToastHelper.showErrorToast(
// context, 'Request failed with status: ${response.statusCode}');
print('Request failed with status: ${response.statusCode}');
}
} catch (e) {
// Handle exceptions
print('Exception occurred: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(),
body: _buildBody(),
);
}
Widget _buildBody() {
if (oldPolicyList == null) {
return Center(child: _buildNoDataWidget());
} else if (oldPolicyList!.isEmpty) {
return Center(child: _buildNoDataWidget());
} else {
return _buildPolicyListWidget();
}
}
Widget _buildNoDataWidget() {
return SingleChildScrollView(
child: Container(
color: Color(0xFFEFF3F6),
child: Column(
children: [
Center(
child: Text('No Data Available'),
)
],
),
),
);
}
Widget _buildPolicyListWidget() {
return Stack(
children: [
SingleChildScrollView(
child: Container(
padding: Responsive.isDesktop(context)
? EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width *
0.2, // 30% of screen width as horizontal padding
vertical: MediaQuery.of(context).size.height *
0.03, // 5% of screen height as vertical padding
)
: EdgeInsets.all(10),
color: Color(0xFFEFF3F6),
child: Column(
children: [
if (oldPolicyDataIsEmpty == 1)
...generateGmcCards(oldPolicyList),
],
),
),
)
],
);
}
List<Widget> generateGmcCards(List<dynamic> data) {
List<Widget> cards = [];
print('data');
print(data);
for (var item in data) {
setState(() {
oldPolicyName = item['policy_name'];
oldPolicyTypeHeading = item['heading'];
oldPolicyFloaterTextHeading = item['floter_text_heading'];
oldPolicyClientId = item['client_id'];
oldPolicyClientPolicyId = item['client_policy_id'];
oldPolicySiGstValue = item['si_gst_value'];
oldPolicySiPremiumValue = item['si_premium_value'];
oldPolicySiValue = item['si_value'];
oldPolicyType = item['policy_type'];
oldPolicyStartDate = item['policy_start_date'];
oldPolicyEndDate = item['policy_end_date'];
oldPolicyEmployeePolicy = item['EmployeePolicy'];
});
Widget card = Card(
elevation: 0,
child: Padding(
padding: Responsive.isDesktop(context)
? EdgeInsets.all(20)
: EdgeInsets.all(10),
child: Column(
children: [
Container(
decoration: BoxDecoration(
color: Color(
0xFFFFF1DD), // Set background color for the container
borderRadius: BorderRadius.circular(
5), // Set border radius for the container
),
padding: Responsive.isDesktop(context)
? EdgeInsets.only(
top: 15, bottom: 15, left: 25, right: 25)
: EdgeInsets.only(
top: 10, bottom: 10, left: 10, right: 10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 8,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
oldPolicyName ?? '',
textAlign: TextAlign.left,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 18
: 14,
),
),
Text(
oldPolicyTypeHeading ?? '',
textAlign: TextAlign.left,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 20
: 16,
fontWeight: FontWeight.w600,
),
),
],
))),
Expanded(
flex: 4,
child: Container(
alignment: Alignment.centerRight,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
oldPolicyFloaterTextHeading ?? '',
textAlign: TextAlign.right,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 18
: 14,
),
),
Text(
'${oldPolicySiValue != null ? oldPolicySiValue : 'NA'}',
textAlign: TextAlign.right,
style: GoogleFonts.poppins(
fontSize: Responsive.isDesktop(context)
? 20
: 16,
fontWeight: FontWeight.w600,
),
),
],
))),
],
),
),
SizedBox(height: 15),
Container(
padding: Responsive.isDesktop(context)
? EdgeInsets.only(top: 0, bottom: 0, left: 15, right: 15)
: EdgeInsets.only(top: 0, bottom: 0, left: 5, right: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: oldPolicyEmployeePolicy.map<Widget>((data) {
String formattedDate = formatDate(data['dob']);
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(Icons.arrow_right,
color: Color(0xFFE26728)), // Arrow icon
SizedBox(
width: Responsive.isDesktop(context)
? 10
: 5), // Space between icon and text
Expanded(
child: Text(
'${data['name']} ~ ${data['relationship']} ~ DOB : $formattedDate',
style: GoogleFonts.poppins(
fontSize:
Responsive.isDesktop(context) ? 18 : 16,
color: Color(0xFF232526),
),
),
),
],
);
}).toList(),
),
),
SizedBox(height: 15),
Container(
padding: Responsive.isDesktop(context)
? EdgeInsets.only(top: 0, bottom: 0, left: 25, right: 25)
: EdgeInsets.only(top: 0, bottom: 0, left: 10, right: 10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 12,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
text: 'Policy Period : ',
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF232526),
),
children: <TextSpan>[
TextSpan(
text:
'$oldPolicyStartDate To $oldPolicyEndDate',
style: GoogleFonts.poppins(
fontSize: 14,
color: Color(0xFF232526),
),
),
],
),
),
],
),
),
),
],
),
),
],
),
));
cards.add(card);
cards.add(SizedBox(height: 10));
}
return cards;
}
String formatDate(String inputDate) {
// Parse the input date string
DateTime dateTime = DateTime.parse(inputDate);
// Format the date to 'dd MMMM yyyy'
String formattedDate = DateFormat('dd MMMM yyyy').format(dateTime);
return formattedDate;
}
}

View File

@ -7,6 +7,9 @@ import 'dart:convert';
import 'dart:io';
import 'package:nhancepolicy/responsive.dart';
import 'package:nhancepolicy/customAppBar/toastHelper.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_animated_button/flutter_animated_button.dart';
import 'package:google_fonts/google_fonts.dart';
class MyPhone extends StatefulWidget {
const MyPhone({Key? key});
@ -24,53 +27,76 @@ class _MyPhoneState extends State<MyPhone> {
void initState() {
countryController.text = "+91";
super.initState();
checkTokenAvailability();
}
Future<void> checkTokenAvailability() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String? token = prefs.getString('token');
if (token != null && token.isNotEmpty) {
// Token available, navigate to home page
Navigator.pushReplacementNamed(context, 'empDetails',
arguments: {'mobile': ''});
}
}
void toggleLoginType() {
Navigator.pushNamed(context, 'hrLogin'); // Navigate to another page
}
Future<bool> verifyMobileNumber(String mobileNumber) async {
Future<void> verifyMobileNumber() async {
try {
final response = await http.post(
Uri.parse(Environment.apiUrl + 'verifyEmployeeNumber'),
body: json.encode({'mobile_number': mobileNumber}),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
},
);
if (_formKey.currentState!.validate()) {
// var enteredMobileNumber = countryController.text + mobileController.text;
var enteredMobileNumber = mobileController.text;
final response = await http.post(
Uri.parse(Environment.apiUrl + 'verifyEmployeeNumber'),
body: json.encode({'mobile_number': enteredMobileNumber}),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
},
);
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
bool userVerification = data['data']['user_verification'];
return userVerification;
} else {
ToastHelper.showErrorToast(context, 'Failed to verify mobile number');
throw Exception('Failed to verify mobile number');
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
bool userVerification = data['data']['user_verification'];
String message = data['data']['message'];
if (userVerification) {
ToastHelper.showSuccessToast(context, message);
Navigator.pushNamed(context, 'verify',
arguments: enteredMobileNumber);
} else {
ToastHelper.showErrorToast(context, message);
print('Invalid mobile number');
}
} else {
ToastHelper.showErrorToast(context, 'Something went wrong');
throw Exception('Failed to verify mobile number');
}
}
} catch (e) {
ToastHelper.showErrorToast(context, '$e');
ToastHelper.showErrorToast(context, 'Something went wrong');
print('Error: $e');
return false;
}
}
void handleSubmit() async {
if (_formKey.currentState!.validate()) {
// var enteredMobileNumber = countryController.text + mobileController.text;
var enteredMobileNumber = mobileController.text;
bool isValid = await verifyMobileNumber(enteredMobileNumber);
if (isValid) {
ToastHelper.showSuccessToast(context, 'Mobile No Verified..');
Navigator.pushNamed(context, 'verify', arguments: enteredMobileNumber);
} else {
ToastHelper.showErrorToast(context, 'Invalid mobile number..');
print('Invalid mobile number');
}
}
}
// void handleSubmit() async {
// if (_formKey.currentState!.validate()) {
// // var enteredMobileNumber = countryController.text + mobileController.text;
// var enteredMobileNumber = mobileController.text;
//
// bool isValid = await verifyMobileNumber(enteredMobileNumber);
//
// if (isValid) {
// ToastHelper.showSuccessToast(context, 'Mobile No Verified..');
// Navigator.pushNamed(context, 'verify', arguments: enteredMobileNumber);
// } else {
// ToastHelper.showErrorToast(context, 'Invalid mobile number..');
// print('Invalid mobile number');
// }
// }
// }
@override
Widget build(BuildContext context) {
@ -155,7 +181,7 @@ class _MyPhoneState extends State<MyPhone> {
children: [
SizedBox(
height: _size.height /
6.4), // Adjust the spacing between the rows
8.0), // Adjust the spacing between the rows
Row(
mainAxisAlignment: MainAxisAlignment
.center, // Align to the center
@ -167,9 +193,7 @@ class _MyPhoneState extends State<MyPhone> {
? Alignment.centerLeft
: Alignment.bottomCenter,
child: Image.asset(
_size.width <= 1100
? 'assets/mobileViewLogo.png'
: 'assets/Nhance-Logo-Final 1.png',
'assets/mobileViewLogo.png',
width: 150,
height: 150,
),
@ -273,43 +297,41 @@ class _MyPhoneState extends State<MyPhone> {
Expanded(
flex: 2,
child: Align(
alignment:
Alignment.centerRight,
child: MouseRegion(
cursor:
SystemMouseCursors.click,
child: GestureDetector(
onTap: () {
// Add your navigation logic here
// For example, you can use Navigator.push to navigate to another page
Navigator.pushNamed(
context, 'hrLogin');
},
child: Row(
children: [
Text(
'HR Login',
style: TextStyle(
color: Color(
0xFF000000), // Text color
// Add other text styles as needed
),
),
SizedBox(width: 5),
Icon(
Icons
.east, // Icon for customer login
color: Colors
.black, // Adjust color as needed
),
],
),
alignment: Alignment.centerLeft,
child: AnimatedButton(
animatedOn:
AnimatedOn.onHover,
onPress: () {
Navigator.pushNamed(
context, 'hrLogin');
},
onChanges: (change) {},
height: 30,
width: 150,
text: 'HR Login',
isReverse: true,
selectedTextColor:
Colors.black,
transitionType: TransitionType
.LEFT_CENTER_ROUNDER,
textStyle:
GoogleFonts.poppins(
fontSize: 16,
letterSpacing: 0,
color: Color(0xFF00989E),
fontWeight: FontWeight.w300,
),
backgroundColor: Colors.white,
selectedBackgroundColor:
Color(0xFF00989E),
borderColor:
Color(0xFF00989E),
borderWidth: 1,
),
)),
],
),
SizedBox(height: 15),
SizedBox(height: 10),
Container(
margin: Responsive.isDesktop(context)
? EdgeInsets.symmetric(
@ -321,7 +343,7 @@ class _MyPhoneState extends State<MyPhone> {
children: [
Text(
"Welcome to Nhance",
style: TextStyle(
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.bold,
),
@ -330,7 +352,7 @@ class _MyPhoneState extends State<MyPhone> {
),
),
SizedBox(
height: 15,
height: 10,
),
Container(
margin: Responsive.isDesktop(context)
@ -343,8 +365,8 @@ class _MyPhoneState extends State<MyPhone> {
children: [
Expanded(
child: Text(
"Have a Health Insurance Policy number, but never signed in? Don't worry, We got you covered",
style: TextStyle(
"Login with your mobile number and OTP to review and enroll for exciting health benefits for you and your family",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF000000)),
textAlign: TextAlign.center,
@ -443,10 +465,10 @@ class _MyPhoneState extends State<MyPhone> {
BorderRadius.circular(10),
),
),
onPressed: handleSubmit,
onPressed: verifyMobileNumber,
child: Text(
"Login With OTP",
style: TextStyle(
style: GoogleFonts.poppins(
color: Color(0xFFFFFFFF)),
),
),
@ -464,7 +486,7 @@ class _MyPhoneState extends State<MyPhone> {
SizedBox(height: 30),
Text(
"Benefits of Login",
style: TextStyle(
style: GoogleFonts.poppins(
fontSize: 20,
fontWeight: FontWeight.bold,
),
@ -568,28 +590,28 @@ class _MyPhoneState extends State<MyPhone> {
text: TextSpan(
text:
'By continuing, you agree with our ',
style: TextStyle(
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 9,
),
children: <TextSpan>[
TextSpan(
text: 'privacy policy ',
style: TextStyle(
style: GoogleFonts.poppins(
color: Color(0xFF00989E),
fontSize: 9,
),
),
TextSpan(
text: 'and ',
style: TextStyle(
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 9,
),
),
TextSpan(
text: 'terms of use',
style: TextStyle(
style: GoogleFonts.poppins(
color: Color(0xFF00989E),
fontSize: 9,
),
@ -612,7 +634,7 @@ class _MyPhoneState extends State<MyPhone> {
return Image.asset(
'assets/login_web.jpg',
height: _size.height,
fit: BoxFit.fill,
fit: BoxFit.cover,
);
} else {
return SizedBox();

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:nhancepolicy/models/environment.dart';
import 'package:pinput/pinput.dart';
import 'dart:async';
@ -28,10 +29,14 @@ class _MyVerifyState extends State<MyVerify> {
dynamic empPrimaryId;
dynamic gpaEmpName;
dynamic client_id;
dynamic _token;
dynamic clientName;
dynamic clientLogo;
@override
void initState() {
super.initState();
checkTokenAvailability();
// Start the timer when the widget is initialized
startTimer();
}
@ -56,6 +61,17 @@ class _MyVerifyState extends State<MyVerify> {
});
}
Future<void> checkTokenAvailability() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String? token = prefs.getString('token');
if (token != null && token.isNotEmpty) {
// Token available, navigate to home page
Navigator.pushReplacementNamed(context, 'empDetails',
arguments: {'mobile': ''});
}
}
Future<void> resendOTP(String mobileNumber) async {
print(mobileNumber);
// Update the UI as needed
@ -105,6 +121,7 @@ class _MyVerifyState extends State<MyVerify> {
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
print(data);
_token = data['data'];
String status = data['status'];
print(status);
if (status == 'success') {
@ -122,6 +139,7 @@ class _MyVerifyState extends State<MyVerify> {
prefs.setString('gpaEmpName', gpaEmpName);
client_id = decodedToken['client_id'];
prefs.setString('client_id', client_id);
getClientLogoAndDetails();
print('Successfully Login');
@ -144,13 +162,12 @@ class _MyVerifyState extends State<MyVerify> {
print('Invalid OTP. Please try again');
}
} else {
ToastHelper.showErrorToast(context, 'Failed to verify OTP');
ToastHelper.showWarningToast(context, 'Something went wrong');
throw Exception('Failed to verify OTP');
}
} catch (e) {
print('Error: $e');
ToastHelper.showErrorToast(
context, 'Failed to verify OTP. Please try again.');
ToastHelper.showWarningToast(context, 'Something went wrong');
// Show a Snackbar if there's an error while verifying OTP
// ToastHelper.showErrorToast(
// context, 'Failed to verify OTP. Please try again.');
@ -158,6 +175,53 @@ class _MyVerifyState extends State<MyVerify> {
}
}
Future<void> getClientLogoAndDetails() async {
var url = Uri.parse(Environment.apiUrl +
'getClientDetails?client_id=$client_id&emp_code=$empCodeString');
try {
var response = await http.get(
url,
headers: {
'Authorization':
'Bearer $_token', // Add token to the Authorization header
},
);
if (response.statusCode == 200) {
// print('response.statusCode == 200');
Map<String, dynamic> data = json.decode(response.body);
// print(data);
if (data.containsKey('data')) {
dynamic clientDetails = data['data'];
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('clientLogo', clientDetails['client']['client_logo']);
prefs.setString('clientName', clientDetails['client']['client_name']);
setState(() {
// dynamic clientDetails = data['data'];
// print(clientDetails);
clientName = clientDetails['client']['client_name'];
print(clientName);
clientLogo = clientDetails['client']['client_logo'];
print(clientLogo);
});
} else {
// Handle other status messages if needed
// ToastHelper.showErrorToast(
// context, 'API request failed with status: ${data['status']}');
print('API request failed with status: ${data['status']}');
}
} else {
// Handle other status codes
// ToastHelper.showErrorToast(
// context, 'Request failed with status: ${response.statusCode}');
print('Request failed with status: ${response.statusCode}');
}
} catch (e) {
// Handle exceptions
print('Exception occurred: $e');
}
}
@override
Widget build(BuildContext context) {
// Retrieve the passed mobile number value
@ -237,7 +301,7 @@ class _MyVerifyState extends State<MyVerify> {
children: [
SizedBox(
height: _size.height /
6.4), // Adjust the spacing between the rows
8.0), // Adjust the spacing between the rows
Row(
mainAxisAlignment: MainAxisAlignment
.center, // Align to the center
@ -249,9 +313,7 @@ class _MyVerifyState extends State<MyVerify> {
? Alignment.centerLeft
: Alignment.bottomCenter,
child: Image.asset(
_size.width <= 1100
? 'assets/mobileViewLogo.png'
: 'assets/Nhance-Logo-Final 1.png',
'assets/mobileViewLogo.png',
width: 150,
height: 150,
),
@ -276,7 +338,7 @@ class _MyVerifyState extends State<MyVerify> {
children: [
Text(
'HR Login',
style: TextStyle(
style: GoogleFonts.poppins(
color: Color(
0xFF000000), // Text color
// Add other text styles as needed
@ -366,7 +428,7 @@ class _MyVerifyState extends State<MyVerify> {
children: [
Text(
"Welcome to Nhance",
style: TextStyle(
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.bold,
),
@ -435,7 +497,7 @@ class _MyVerifyState extends State<MyVerify> {
_isTimerRunning
? Text(
"Resend OTP in $_secondsRemaining seconds",
style: TextStyle(
style: GoogleFonts.poppins(
color: Colors.black),
)
: InkWell(
@ -444,7 +506,7 @@ class _MyVerifyState extends State<MyVerify> {
},
child: Text(
"Resend OTP",
style: TextStyle(
style: GoogleFonts.poppins(
color: Colors.blue),
),
),
@ -478,7 +540,7 @@ class _MyVerifyState extends State<MyVerify> {
},
child: Text(
"Submit",
style: TextStyle(
style: GoogleFonts.poppins(
color: Color(0xFFFFFFFF)),
),
),
@ -490,10 +552,10 @@ class _MyVerifyState extends State<MyVerify> {
horizontal: 150),
child: Column(
children: [
SizedBox(height: 30),
SizedBox(height: 20),
Text(
"Benefits of Login",
style: TextStyle(
style: GoogleFonts.poppins(
fontSize: 20,
fontWeight: FontWeight.bold,
),
@ -548,7 +610,9 @@ class _MyVerifyState extends State<MyVerify> {
SizedBox(
height: 10),
Text(
"View Policy"),
"View Policy",
style: GoogleFonts
.poppins()),
],
),
),
@ -567,7 +631,9 @@ class _MyVerifyState extends State<MyVerify> {
SizedBox(
height: 10),
Text(
"Manage Claims"),
"Manage Claims",
style: GoogleFonts
.poppins()),
],
),
),
@ -597,28 +663,28 @@ class _MyVerifyState extends State<MyVerify> {
text: TextSpan(
text:
'By continuing, you agree with our ',
style: TextStyle(
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 9,
),
children: <TextSpan>[
TextSpan(
text: 'privacy policy ',
style: TextStyle(
style: GoogleFonts.poppins(
color: Color(0xFF00989E),
fontSize: 9,
),
),
TextSpan(
text: 'and ',
style: TextStyle(
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 9,
),
),
TextSpan(
text: 'terms of use',
style: TextStyle(
style: GoogleFonts.poppins(
color: Color(0xFF00989E),
fontSize: 9,
),
@ -641,7 +707,7 @@ class _MyVerifyState extends State<MyVerify> {
return Image.asset(
'assets/login_web.jpg',
height: _size.height,
fit: BoxFit.fill,
fit: BoxFit.cover,
);
} else {
return SizedBox();

View File

@ -7,9 +7,13 @@
#include "generated_plugin_registrant.h"
#include <smart_auth/smart_auth_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) smart_auth_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "SmartAuthPlugin");
smart_auth_plugin_register_with_registrar(smart_auth_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
}

View File

@ -4,6 +4,7 @@
list(APPEND FLUTTER_PLUGIN_LIST
smart_auth
url_launcher_linux
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

View File

@ -8,9 +8,11 @@ import Foundation
import path_provider_foundation
import shared_preferences_foundation
import smart_auth
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SmartAuthPlugin.register(with: registry.registrar(forPlugin: "SmartAuthPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
}

View File

@ -43,13 +43,16 @@ dependencies:
adaptive_navbar: ^0.0.3
jwt_decode: ^0.3.1
google_fonts: ^6.2.1
file_picker: ^6.2.0
file_picker: ^8.0.3
csv: ^6.0.0
data_tables: ^1.4.0
universal_html: ^2.2.4
excel: ^4.0.3
intl: ^0.19.0
toastification: ^1.2.1
flutter_animated_button: ^2.0.3
spreadsheet_decoder: ^2.2.0
url_launcher: ^6.2.6
dev_dependencies:

BIN
web/assets/Sample.xlsx Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -95,7 +95,7 @@
if(loadingIndicator){
loadingIndicator.remove();
}
},10000);
},5000);
};
</script>
</body>

View File

@ -7,8 +7,11 @@
#include "generated_plugin_registrant.h"
#include <smart_auth/smart_auth_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
SmartAuthPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SmartAuthPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
}

View File

@ -4,6 +4,7 @@
list(APPEND FLUTTER_PLUGIN_LIST
smart_auth
url_launcher_windows
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST