FULL FLOW CODE
@ -1,4 +1,9 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<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
|
<application
|
||||||
android:label="nhancepolicy"
|
android:label="nhancepolicy"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 996 B |
|
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.3 KiB |
BIN
assets/Group.png
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 4.3 KiB |
BIN
assets/Solid_gray.png
Normal file
|
After Width: | Height: | Size: 99 B |
BIN
assets/Template_File.xlsx
Normal file
BIN
assets/img1.png
|
Before Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 212 KiB After Width: | Height: | Size: 146 KiB |
BIN
assets/nhance-loader.gif
Normal file
|
After Width: | Height: | Size: 493 KiB |
|
Before Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 494 B |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 772 B |
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 663 B |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 772 B |
|
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.4 KiB |
5693
lib/addons.dart
@ -17,7 +17,7 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
if (token != null && token.isNotEmpty) {
|
if (token != null && token.isNotEmpty) {
|
||||||
if (hrtoken != null && hrtoken.isNotEmpty) {
|
if (hrtoken != null && hrtoken.isNotEmpty) {
|
||||||
prefs.remove('token');
|
prefs.remove('token');
|
||||||
Navigator.pushNamed(context, 'hrHome');
|
Navigator.pushNamed(context, 'hrDashboard');
|
||||||
} else {
|
} else {
|
||||||
await prefs.clear();
|
await prefs.clear();
|
||||||
Navigator.pushNamed(context, 'phone');
|
Navigator.pushNamed(context, 'phone');
|
||||||
@ -99,13 +99,12 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
Navigator.pushNamed(context, "routeName");
|
Navigator.pushNamed(context, "routeName");
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (Responsive.isDesktop(context))
|
NavBarItem(
|
||||||
NavBarItem(
|
text: "Inactive Policy",
|
||||||
text: "",
|
onTap: () {
|
||||||
onTap: () {
|
Navigator.pushNamed(context, 'oldPolicy');
|
||||||
Navigator.pushNamed(context, "routeName");
|
},
|
||||||
},
|
),
|
||||||
),
|
|
||||||
NavBarItem(
|
NavBarItem(
|
||||||
text: "Logout",
|
text: "Logout",
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
|||||||
2136
lib/empDetails.dart
2501
lib/empReview.dart
@ -13,6 +13,9 @@ import 'package:flutter/foundation.dart' show kIsWeb;
|
|||||||
import 'package:excel/excel.dart';
|
import 'package:excel/excel.dart';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:csv/csv.dart';
|
||||||
|
|
||||||
|
import 'package:spreadsheet_decoder/spreadsheet_decoder.dart';
|
||||||
|
|
||||||
class excelVerify extends StatefulWidget {
|
class excelVerify extends StatefulWidget {
|
||||||
const excelVerify({Key? key}) : super(key: key);
|
const excelVerify({Key? key}) : super(key: key);
|
||||||
@ -37,13 +40,17 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
dynamic columnIndexMismatchCount = 0;
|
dynamic columnIndexMismatchCount = 0;
|
||||||
dynamic columnMissingCount = 0;
|
dynamic columnMissingCount = 0;
|
||||||
List<Map<String, dynamic>> extractedData = [];
|
List<Map<String, dynamic>> extractedData = [];
|
||||||
dynamic policyName;
|
dynamic argumentsData;
|
||||||
dynamic policyFirstPart;
|
|
||||||
List<Map<String, dynamic>> originalData = []; // Original data source
|
List<Map<String, dynamic>> originalData = []; // Original data source
|
||||||
List<Map<String, dynamic>> filteredData = []; // Filtered 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
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -53,6 +60,7 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
html.window.localStorage.remove('fileBytes');
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadToken() async {
|
Future<void> _loadToken() async {
|
||||||
@ -64,7 +72,7 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
});
|
});
|
||||||
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
|
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
|
||||||
clintID = decodedToken['client_id'].toString();
|
clintID = decodedToken['client_id'].toString();
|
||||||
await getPolicyName(clintID);
|
await getPolicyDetails();
|
||||||
} else {
|
} else {
|
||||||
// Token is empty or null, handle accordingly (e.g., navigate to login screen)
|
// Token is empty or null, handle accordingly (e.g., navigate to login screen)
|
||||||
// For now, let's navigate to the 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(() {
|
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 {
|
void _uploadFile(importPolicyName) async {
|
||||||
print('Test');
|
print('Test');
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
print('kIsWeb');
|
print('kIsWeb');
|
||||||
final input = html.FileUploadInputElement();
|
final input = html.FileUploadInputElement();
|
||||||
input.accept = '.xlsx';
|
input.accept = '.xlsx,.xls,.csv';
|
||||||
input.click();
|
input.click();
|
||||||
input.onChange.listen((event) async {
|
input.onChange.listen((event) async {
|
||||||
final file = input.files!.first;
|
final file = input.files!.first;
|
||||||
@ -159,7 +133,7 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
print('File Name: $fileName');
|
print('File Name: $fileName');
|
||||||
print('File Bytes: $fileBytes');
|
print('File Bytes: $fileBytes');
|
||||||
// Call the function to process Excel data here
|
// 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
|
// Decode the Excel file and extract relevant data
|
||||||
// Assuming dataArray is your array containing Excel 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());
|
// print(dataArray[0].toString());
|
||||||
// Extract Name, Age, and City from the array
|
// Extract Name, Age, and City from the array
|
||||||
print(dataArray[0].length);
|
print(dataArray[0].length);
|
||||||
|
|
||||||
if (dataArray[0].length == 10) {
|
if (dataArray[0].length == 11) {
|
||||||
for (int i = 0; i < dataArray.length; i++) {
|
for (int i = 0; i < dataArray.length; i++) {
|
||||||
Map<String, dynamic> dataMap = {
|
Map<String, dynamic> dataMap = {
|
||||||
"Sno": dataArray[i][0].value,
|
"Sno": dataArray[i][0].value,
|
||||||
"emp_code": dataArray[i][1].value,
|
"Emp_Code": dataArray[i][1].value,
|
||||||
"Name": dataArray[i][2].value,
|
"Name": dataArray[i][2].value,
|
||||||
"DOJ": dataArray[i][3].value,
|
"DOJ": dataArray[i][3].value,
|
||||||
"Gender": dataArray[i][4].value,
|
"Gender": dataArray[i][4].value,
|
||||||
@ -191,6 +178,7 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
"Mail": dataArray[i][7].value,
|
"Mail": dataArray[i][7].value,
|
||||||
"Mobile": dataArray[i][8].value,
|
"Mobile": dataArray[i][8].value,
|
||||||
"SI": dataArray[i][9].value,
|
"SI": dataArray[i][9].value,
|
||||||
|
"Grade": dataArray[i][10].value,
|
||||||
};
|
};
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
// print(dataMap);
|
// print(dataMap);
|
||||||
@ -203,47 +191,79 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
// Do something with extracted data (e.g., display in UI)
|
// Do something with extracted data (e.g., display in UI)
|
||||||
originalData = extractedData;
|
originalData = extractedData;
|
||||||
filteredData = List.from(originalData);
|
filteredData = List.from(originalData);
|
||||||
|
print('filteredData');
|
||||||
print(filteredData);
|
print(filteredData);
|
||||||
print(validationArray);
|
print(validationArray);
|
||||||
|
|
||||||
validationArray[0].forEach((key, value) {
|
validationArray[0].forEach((key, value) {
|
||||||
print(key);
|
print(key);
|
||||||
print(value);
|
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
|
// If key and value are not equal, increment mismatch count
|
||||||
columnIndexMismatchCount++;
|
columnIndexMismatchCount++;
|
||||||
|
print('columnIndexMismatchCount: $value');
|
||||||
}
|
}
|
||||||
if (value.toString() == 'null') {
|
if (value.toString() == 'null') {
|
||||||
// If value is null, increment missing count
|
// If value is null, increment missing count
|
||||||
columnMissingCount++;
|
columnMissingCount++;
|
||||||
|
print('Value: $value');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
print('columnIndexMismatchCount: $columnIndexMismatchCount');
|
print('columnIndexMismatchCount: $columnIndexMismatchCount');
|
||||||
print('columnMissingCount: $columnMissingCount');
|
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 {
|
} else {
|
||||||
print('Some Column is Missing');
|
print('Some Column is Missing');
|
||||||
var columnMissingCount = 10 - dataArray[0].length;
|
var columnMissingCount = 11 - dataArray[0].length;
|
||||||
missingColumnErrorMsg = columnMissingCount;
|
missingColumnErrorMsg = columnMissingCount;
|
||||||
print(missingColumnErrorMsg);
|
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
|
// Placeholder function for decoding Excel data
|
||||||
List<List<Data>> decodeExcelData(Uint8List fileBytes) {
|
List<List<Data>> decodeExcelData(Uint8List fileBytes) {
|
||||||
// Implement your logic to decode Excel data here
|
print('decodeExcelData');
|
||||||
// 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';
|
|
||||||
|
|
||||||
// Create an Excel instance from the fileBytes
|
// Create an Excel instance from the fileBytes
|
||||||
final excel = Excel.decodeBytes(fileBytes);
|
final excel = Excel.decodeBytes(fileBytes);
|
||||||
|
print('decodeExcelData');
|
||||||
|
print(excel);
|
||||||
|
|
||||||
// Assuming there's only one sheet in the Excel file
|
// Assuming there's only one sheet in the Excel file
|
||||||
final sheet = excel.tables.keys.first;
|
final sheet = excel.tables.keys.first;
|
||||||
@ -263,6 +283,72 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
return dataArray;
|
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 {
|
void _dragAndDropFile(html.File file) async {
|
||||||
print('file');
|
print('file');
|
||||||
print(file);
|
print(file);
|
||||||
@ -287,10 +373,13 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
final decodedBytes = json.decode(jsonString);
|
final decodedBytes = json.decode(jsonString);
|
||||||
if (decodedBytes is List<dynamic>) {
|
if (decodedBytes is List<dynamic>) {
|
||||||
setState(() {
|
setState(() {
|
||||||
fileName = 'Retrieved File'; // Provide a default name
|
fileName = fileName ??
|
||||||
|
'Retrieved File'; // Provide a default name if fileName is null
|
||||||
});
|
});
|
||||||
sendExcelFIleTOAPI(
|
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) {
|
if (fileBytes == null) {
|
||||||
print('return');
|
print('return');
|
||||||
return; // No file selected
|
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 {
|
} else {
|
||||||
// ToastHelper.showSuccessToast(
|
print('else');
|
||||||
// context, 'Failed to upload file: ${response.reasonPhrase}');
|
// // Prepare form data
|
||||||
ToastHelper.showSuccessToast(
|
// final formData = html.FormData();
|
||||||
context, 'Failed to send data: ${response.reasonPhrase}');
|
// formData.appendBlob('file', html.Blob([fileBytes]), fileName);
|
||||||
print('Failed to upload file: ${response.reasonPhrase}');
|
|
||||||
|
// 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
|
// Filter the data based on the search query
|
||||||
filteredData = originalData.where((item) {
|
filteredData = originalData.where((item) {
|
||||||
// Implement your filter logic here, for example:
|
// Implement your filter logic here, for example:
|
||||||
return item['emp_code'].toLowerCase().contains(query.toLowerCase());
|
return item['Emp_Code'].toLowerCase().contains(query.toLowerCase());
|
||||||
}).toList();
|
}).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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Retrieve the passed argument
|
dynamic arguments = ModalRoute.of(context)!.settings.arguments;
|
||||||
dynamic importPolicyName =
|
print('arguments');
|
||||||
ModalRoute.of(context)!.settings.arguments as String?;
|
print(arguments);
|
||||||
|
if (arguments != null && arguments is Map<String, dynamic>) {
|
||||||
// List<String> parts = importPolicyName.split(" - ");
|
argumentsData = arguments;
|
||||||
policyFirstPart = importPolicyName;
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(),
|
appBar: CustomAppBar(),
|
||||||
@ -395,16 +540,73 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
alignment: Alignment.bottomCenter,
|
alignment: Alignment.bottomCenter,
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: <Widget>[
|
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)
|
if (_currentStep != 0)
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
controls
|
controls.onStepCancel!();
|
||||||
.onStepCancel!(); // Call onStepCancel function
|
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'Cancel',
|
'Previous',
|
||||||
style: TextStyle(color: Color(0xFFE26728)),
|
style: TextStyle(color: Color(0xFFE26728)),
|
||||||
),
|
),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
@ -419,10 +621,19 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
if (_currentStep != 2)
|
if (_currentStep != 2)
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: _currentStep == 0
|
||||||
controls
|
? (fileName != null
|
||||||
.onStepContinue!(); // Call onStepContinue function
|
? controls.onStepContinue!
|
||||||
},
|
: null)
|
||||||
|
: (_currentStep == 1
|
||||||
|
? (missingColumnErrorMsg == 0 &&
|
||||||
|
columnIndexMismatchCount ==
|
||||||
|
0 &&
|
||||||
|
invalidRelationships == 0 &&
|
||||||
|
dobAgeCheckCount == 0
|
||||||
|
? controls.onStepContinue!
|
||||||
|
: null)
|
||||||
|
: null),
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'NEXT',
|
'NEXT',
|
||||||
style: TextStyle(color: Colors.white),
|
style: TextStyle(color: Colors.white),
|
||||||
@ -468,7 +679,9 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
} else if (_currentStep == 1) {
|
} else if (_currentStep == 1) {
|
||||||
// For the second step, allow continue if both errors are 0
|
// For the second step, allow continue if both errors are 0
|
||||||
if (missingColumnErrorMsg == 0 &&
|
if (missingColumnErrorMsg == 0 &&
|
||||||
columnIndexMismatchCount == 0) {
|
columnIndexMismatchCount == 0 &&
|
||||||
|
invalidRelationships == 0 &&
|
||||||
|
dobAgeCheckCount == 0) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_currentStep += 1;
|
_currentStep += 1;
|
||||||
});
|
});
|
||||||
@ -513,7 +726,7 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
policy_name ?? '',
|
'$policy_name - ($policyType)',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
@ -558,26 +771,92 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
MainAxisAlignment
|
MainAxisAlignment
|
||||||
.center,
|
.center,
|
||||||
children: [
|
children: [
|
||||||
if (fileName == null)
|
// if (fileName == null)
|
||||||
Text(
|
// ElevatedButton(
|
||||||
'Drop files here to start uploading',
|
// onPressed: () => {},
|
||||||
style: TextStyle(
|
// child: Icon(
|
||||||
fontSize: 16),
|
// Icons.download,
|
||||||
),
|
// color: Colors
|
||||||
SizedBox(height: 20),
|
// .grey), // You can replace the Icon with your custom button child
|
||||||
if (fileName == null)
|
// style:
|
||||||
Text(
|
// ElevatedButton
|
||||||
'OR',
|
// .styleFrom(
|
||||||
style: TextStyle(
|
// shape:
|
||||||
fontSize: 16),
|
// CircleBorder(), // Makes the button round
|
||||||
), // Add spacing between texts
|
// padding:
|
||||||
SizedBox(height: 20),
|
// 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
|
fileName != null
|
||||||
? Text(
|
? Column(
|
||||||
'File Uploaded: $fileName',
|
mainAxisAlignment:
|
||||||
style: TextStyle(
|
MainAxisAlignment
|
||||||
fontSize:
|
.center,
|
||||||
16),
|
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(
|
: ElevatedButton(
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
@ -596,6 +875,10 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
0xFFE26728),
|
0xFFE26728),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
if (fileName == null)
|
||||||
|
Text(
|
||||||
|
'Supported Files : XLSX')
|
||||||
// Add more Text widgets for additional lines of text
|
// 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
|
missingColumnErrorMsg == 0
|
||||||
? Icons.check_circle
|
? Icons.check_circle
|
||||||
: Icons.error,
|
: Icons.error,
|
||||||
'No of column missing - $missingColumnErrorMsg',
|
'No of column missing : $missingColumnErrorMsg Column',
|
||||||
iconColor: missingColumnErrorMsg == 0
|
iconColor: missingColumnErrorMsg == 0
|
||||||
? Colors.green
|
? Colors.green
|
||||||
: Colors
|
: Colors
|
||||||
@ -645,20 +965,29 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
columnIndexMismatchCount == 0
|
columnIndexMismatchCount == 0
|
||||||
? Icons.check_circle
|
? Icons.check_circle
|
||||||
: Icons.error,
|
: Icons.error,
|
||||||
'Column Index is Missmatching - $columnIndexMismatchCount',
|
'Mismatch in Column Order : $columnIndexMismatchCount - Column',
|
||||||
iconColor: columnIndexMismatchCount == 0
|
iconColor: columnIndexMismatchCount == 0
|
||||||
? Colors.green
|
? Colors.green
|
||||||
: Colors.red,
|
: Colors.red,
|
||||||
),
|
),
|
||||||
// _buildRowWithIcon(
|
_buildRowWithIcon(
|
||||||
// columnMissingCount == 0
|
invalidRelationships == 0
|
||||||
// ? Icons.check_circle
|
? Icons.check_circle
|
||||||
// : Icons.error,
|
: Icons.error,
|
||||||
// 'Column Missing - $columnMissingCount',
|
'Invalid Relationships : $invalidRelationships - Rows',
|
||||||
// iconColor: columnMissingCount == 0
|
iconColor: invalidRelationships == 0
|
||||||
// ? Colors.green
|
? Colors.green
|
||||||
// : Colors.red,
|
: 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(
|
return Card(
|
||||||
elevation: 0, // Set elevation to 0 for no shadow
|
elevation: 0, // Set elevation to 0 for no shadow
|
||||||
child: PaginatedDataTable(
|
child: PaginatedDataTable(
|
||||||
rowsPerPage: 10, // Adjust rows per page as needed
|
rowsPerPage: 25, // Adjust rows per page as needed
|
||||||
columns: [
|
columns: [
|
||||||
DataColumn(label: Text('S.No')),
|
DataColumn(label: Text('S.No')),
|
||||||
DataColumn(label: Text('Employee ID')),
|
DataColumn(label: Text('Employee ID')),
|
||||||
@ -785,6 +1114,7 @@ class _excelVerifyState extends State<excelVerify> {
|
|||||||
DataColumn(label: Text('Mail')),
|
DataColumn(label: Text('Mail')),
|
||||||
DataColumn(label: Text('Mobile No')),
|
DataColumn(label: Text('Mobile No')),
|
||||||
DataColumn(label: Text('SI')),
|
DataColumn(label: Text('SI')),
|
||||||
|
DataColumn(label: Text('Grade')),
|
||||||
],
|
],
|
||||||
source: _DependenceDataSource0(filteredData),
|
source: _DependenceDataSource0(filteredData),
|
||||||
),
|
),
|
||||||
@ -824,20 +1154,21 @@ class _DependenceDataSource0 extends DataTableSource {
|
|||||||
DataRow getRow(int index) {
|
DataRow getRow(int index) {
|
||||||
final row = _data[index];
|
final row = _data[index];
|
||||||
|
|
||||||
// Format date of birth to "July 10, 1996"
|
String dob = row['DOB'] != null ? formatDate(row['DOB']) : 'N/A';
|
||||||
String dob = row['dob'] != null ? formatDateString(row['dob']) : 'N/A';
|
String doj = row['DOJ'] != null ? formatDate(row['DOJ']) : 'N/A';
|
||||||
|
|
||||||
return DataRow(cells: [
|
return DataRow(cells: [
|
||||||
DataCell(Text(row['Sno'].toString())),
|
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['Name'].toString())),
|
||||||
DataCell(Text(row['DOJ']?.toString() ?? 'N/A')),
|
DataCell(Text(doj)),
|
||||||
DataCell(Text(row['Gender']?.toString() ?? 'N/A')),
|
DataCell(Text(row['Gender']?.toString() ?? 'N/A')),
|
||||||
DataCell(Text(row['Relation']?.toString() ?? 'N/A')),
|
DataCell(Text(row['Relation']?.toString() ?? 'N/A')),
|
||||||
DataCell(Text(dob)),
|
DataCell(Text(dob)),
|
||||||
DataCell(Text(row['Mail']?.toString() ?? 'N/A')),
|
DataCell(Text(row['Mail']?.toString() ?? 'N/A')),
|
||||||
DataCell(Text(row['Mobile']?.toString() ?? 'N/A')),
|
DataCell(Text(row['Mobile']?.toString() ?? 'N/A')),
|
||||||
DataCell(Text(row['SI']?.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
|
@override
|
||||||
int get selectedRowCount => 0;
|
int get selectedRowCount => 0;
|
||||||
|
|
||||||
String formatDateString(String dateString) {
|
String formatDate(dynamic dateValue) {
|
||||||
// Parse the date string to DateTime object
|
if (dateValue is String) {
|
||||||
DateTime dateTime = DateTime.parse(dateString);
|
// If the date is already in string format
|
||||||
// Format the DateTime object to "July 03, 2024"
|
DateTime dateTime = DateTime.parse(dateValue);
|
||||||
String formattedDate = DateFormat.yMMMMd().format(dateTime);
|
return DateFormat('dd-MM-yyyy').format(dateTime);
|
||||||
|
} else if (dateValue is DateCellValue) {
|
||||||
return formattedDate;
|
// 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
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
1100
lib/hrHome.dart
128
lib/hrLogin.dart
@ -7,6 +7,9 @@ import 'package:nhancepolicy/models/environment.dart';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:nhancepolicy/responsive.dart';
|
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 {
|
class MyHrLogin extends StatefulWidget {
|
||||||
const MyHrLogin({Key? key});
|
const MyHrLogin({Key? key});
|
||||||
@ -24,17 +27,30 @@ class _MyPhoneState extends State<MyHrLogin> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
countryController.text = "+91";
|
countryController.text = "+91";
|
||||||
super.initState();
|
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() {
|
void toggleLoginType() {
|
||||||
Navigator.pushNamed(context, 'phone'); // Navigate to another page
|
Navigator.pushNamed(context, 'phone'); // Navigate to another page
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> verifyMobileNumber(String mobileNumber) async {
|
Future<void> verifyMobileNumber() async {
|
||||||
try {
|
try {
|
||||||
|
var enteredMobileNumber = mobileController.text;
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse(Environment.apiUrl + 'verifyHrWithMobileNumber'),
|
Uri.parse(Environment.apiUrl + 'verifyHrWithMobileNumber'),
|
||||||
body: json.encode({'mobile_number': mobileNumber}),
|
body: json.encode({'mobile_number': enteredMobileNumber}),
|
||||||
headers: {
|
headers: {
|
||||||
HttpHeaders.contentTypeHeader: 'application/json',
|
HttpHeaders.contentTypeHeader: 'application/json',
|
||||||
},
|
},
|
||||||
@ -43,34 +59,41 @@ class _MyPhoneState extends State<MyHrLogin> {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
Map<String, dynamic> data = json.decode(response.body);
|
Map<String, dynamic> data = json.decode(response.body);
|
||||||
bool userVerification = data['data']['user_verification'];
|
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 {
|
} else {
|
||||||
ToastHelper.showErrorToast(context, 'Failed to verify mobile number');
|
ToastHelper.showErrorToast(context, 'Failed to verify mobile number');
|
||||||
throw Exception('Failed to verify mobile number');
|
throw Exception('Failed to verify mobile number');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error: $e');
|
print('Error: $e');
|
||||||
ToastHelper.showErrorToast(context, 'Error: $e');
|
ToastHelper.showErrorToast(context, 'Something went wrong');
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSubmit() async {
|
// void handleSubmit() async {
|
||||||
if (_formKey.currentState!.validate()) {
|
// if (_formKey.currentState!.validate()) {
|
||||||
// var enteredMobileNumber = countryController.text + mobileController.text;
|
// // var enteredMobileNumber = countryController.text + mobileController.text;
|
||||||
var enteredMobileNumber = mobileController.text;
|
// var enteredMobileNumber = mobileController.text;
|
||||||
|
//
|
||||||
bool isValid = await verifyMobileNumber(enteredMobileNumber);
|
// bool isValid = await verifyMobileNumber(enteredMobileNumber);
|
||||||
|
//
|
||||||
if (isValid) {
|
// if (isValid) {
|
||||||
ToastHelper.showSuccessToast(context, 'Mobile No Verified...');
|
// ToastHelper.showSuccessToast(context, 'Mobile No Verified...');
|
||||||
Navigator.pushNamed(context, 'hrVerify',
|
// Navigator.pushNamed(context, 'hrVerify',
|
||||||
arguments: enteredMobileNumber);
|
// arguments: enteredMobileNumber);
|
||||||
} else {
|
// } else {
|
||||||
ToastHelper.showErrorToast(context, 'Invalid mobile number');
|
// ToastHelper.showErrorToast(context, 'Invalid mobile number');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -142,7 +165,7 @@ class _MyPhoneState extends State<MyHrLogin> {
|
|||||||
),
|
),
|
||||||
SizedBox(width: 5),
|
SizedBox(width: 5),
|
||||||
Text(
|
Text(
|
||||||
'Customer Login',
|
'Member Login',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Color(0xFF000000), // Text color
|
color: Color(0xFF000000), // Text color
|
||||||
// Add other text styles as needed
|
// Add other text styles as needed
|
||||||
@ -269,36 +292,35 @@ class _MyPhoneState extends State<MyHrLogin> {
|
|||||||
flex: 4,
|
flex: 4,
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: MouseRegion(
|
child: AnimatedButton(
|
||||||
cursor:
|
animatedOn:
|
||||||
SystemMouseCursors.click,
|
AnimatedOn.onHover,
|
||||||
child: GestureDetector(
|
onPress: () {
|
||||||
onTap: () {
|
Navigator.pushNamed(
|
||||||
// Add your navigation logic here
|
context, 'phone');
|
||||||
// For example, you can use Navigator.push to navigate to another page
|
},
|
||||||
Navigator.pushNamed(
|
onChanges: (change) {},
|
||||||
context, 'phone');
|
height: 30,
|
||||||
},
|
width: 150,
|
||||||
child: Row(
|
text: 'Member Login',
|
||||||
children: [
|
isReverse: true,
|
||||||
Icon(
|
selectedTextColor:
|
||||||
Icons
|
Colors.black,
|
||||||
.west, // Icon for customer login
|
transitionType: TransitionType
|
||||||
color: Colors
|
.RIGHT_CENTER_ROUNDER,
|
||||||
.black, // Adjust color as needed
|
textStyle:
|
||||||
),
|
GoogleFonts.poppins(
|
||||||
SizedBox(width: 5),
|
fontSize: 16,
|
||||||
Text(
|
letterSpacing: 0,
|
||||||
'Customer Login',
|
color: Color(0xFF00989E),
|
||||||
style: TextStyle(
|
fontWeight: FontWeight.w300,
|
||||||
color: Color(
|
|
||||||
0xFF000000), // Text color
|
|
||||||
// Add other text styles as needed
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
selectedBackgroundColor:
|
||||||
|
Color(0xFF00989E),
|
||||||
|
borderColor:
|
||||||
|
Color(0xFF00989E),
|
||||||
|
borderWidth: 1,
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -360,7 +382,7 @@ class _MyPhoneState extends State<MyHrLogin> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
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(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Color(0xFF000000)),
|
color: Color(0xFF000000)),
|
||||||
@ -460,7 +482,7 @@ class _MyPhoneState extends State<MyHrLogin> {
|
|||||||
BorderRadius.circular(10),
|
BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: handleSubmit,
|
onPressed: verifyMobileNumber,
|
||||||
child: Text(
|
child: Text(
|
||||||
"Login With OTP",
|
"Login With OTP",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|||||||
746
lib/hrPolicyDetails.dart
Normal 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);
|
||||||
|
}
|
||||||
@ -24,10 +24,18 @@ class _MyVerifyState extends State<MyHrVerify> {
|
|||||||
late Timer _timer;
|
late Timer _timer;
|
||||||
int _secondsRemaining = 30;
|
int _secondsRemaining = 30;
|
||||||
bool _isTimerRunning = false;
|
bool _isTimerRunning = false;
|
||||||
|
dynamic _token;
|
||||||
|
dynamic empCodeString;
|
||||||
|
dynamic empPrimaryId;
|
||||||
|
dynamic gpaEmpName;
|
||||||
|
dynamic client_id;
|
||||||
|
dynamic clientName;
|
||||||
|
dynamic clientLogo;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
checkTokenAvailability();
|
||||||
// Start the timer when the widget is initialized
|
// Start the timer when the widget is initialized
|
||||||
startTimer();
|
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 {
|
Future<void> resendOTP(String mobileNumber) async {
|
||||||
print(mobileNumber);
|
print(mobileNumber);
|
||||||
// Update the UI as needed
|
// Update the UI as needed
|
||||||
@ -85,8 +103,7 @@ class _MyVerifyState extends State<MyHrVerify> {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Handle API call errors
|
// Handle API call errors
|
||||||
print('Error: $e');
|
print('Error: $e');
|
||||||
ToastHelper.showErrorToast(
|
ToastHelper.showErrorToast(context, 'Something went wrong');
|
||||||
context, 'Failed to resend OTP. Please try again.');
|
|
||||||
// ScaffoldMessenger.of(context).showSnackBar(
|
// ScaffoldMessenger.of(context).showSnackBar(
|
||||||
// SnackBar(
|
// SnackBar(
|
||||||
// content: Text('Failed to resend OTP. Please try again.'),
|
// content: Text('Failed to resend OTP. Please try again.'),
|
||||||
@ -110,16 +127,32 @@ class _MyVerifyState extends State<MyHrVerify> {
|
|||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
Map<String, dynamic> data = json.decode(response.body);
|
Map<String, dynamic> data = json.decode(response.body);
|
||||||
|
_token = data['data'];
|
||||||
print(data);
|
print(data);
|
||||||
String status = data['status'];
|
String status = data['status'];
|
||||||
print(status);
|
print(status);
|
||||||
if (status == 'success') {
|
if (status == 'success') {
|
||||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
prefs.setString('hrtoken', data['data']);
|
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');
|
final hrtoken = prefs.getString('hrtoken');
|
||||||
if (hrtoken != null && hrtoken.isNotEmpty) {
|
if (hrtoken != null && hrtoken.isNotEmpty) {
|
||||||
ToastHelper.showSuccessToast(context, 'Successfully Login');
|
ToastHelper.showSuccessToast(context, 'Successfully Login');
|
||||||
Navigator.pushNamed(context, 'hrHome');
|
Navigator.pushNamed(context, 'hrDashboard');
|
||||||
} else {
|
} else {
|
||||||
// Token is empty or null, handle accordingly (e.g., navigate to login screen)
|
// Token is empty or null, handle accordingly (e.g., navigate to login screen)
|
||||||
// For now, let's navigate to the 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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Retrieve the passed mobile number value
|
// Retrieve the passed mobile number value
|
||||||
|
|||||||
@ -9,8 +9,11 @@ import 'package:nhancepolicy/models/environment.dart';
|
|||||||
import 'package:nhancepolicy/phone.dart';
|
import 'package:nhancepolicy/phone.dart';
|
||||||
import 'package:nhancepolicy/verify.dart';
|
import 'package:nhancepolicy/verify.dart';
|
||||||
import 'package:nhancepolicy/home.dart';
|
import 'package:nhancepolicy/home.dart';
|
||||||
|
import 'package:nhancepolicy/hrDashboard.dart';
|
||||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
import 'package:nhancepolicy/hrLogin.dart';
|
import 'package:nhancepolicy/hrLogin.dart';
|
||||||
|
import 'package:nhancepolicy/hrPolicyDetails.dart';
|
||||||
|
import 'package:nhancepolicy/oldPolicy.dart';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
await dotenv.load(fileName: Environment.fileName);
|
await dotenv.load(fileName: Environment.fileName);
|
||||||
@ -29,6 +32,9 @@ Future<void> main() async {
|
|||||||
'empDetails': (context) => empDetails(),
|
'empDetails': (context) => empDetails(),
|
||||||
'addOnsDetails': (context) => addOnsDetails(),
|
'addOnsDetails': (context) => addOnsDetails(),
|
||||||
'empReviewDetails': (context) => empReviewDetails(),
|
'empReviewDetails': (context) => empReviewDetails(),
|
||||||
|
'hrDashboard': (context) => hrDashboard(),
|
||||||
|
'hrPolicyDetails': (context) => hrPolicyDetails(),
|
||||||
|
'oldPolicy': (context) => oldPolicy(),
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
385
lib/oldPolicy.dart
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
184
lib/phone.dart
@ -7,6 +7,9 @@ import 'dart:convert';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:nhancepolicy/responsive.dart';
|
import 'package:nhancepolicy/responsive.dart';
|
||||||
import 'package:nhancepolicy/customAppBar/toastHelper.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 {
|
class MyPhone extends StatefulWidget {
|
||||||
const MyPhone({Key? key});
|
const MyPhone({Key? key});
|
||||||
@ -24,53 +27,76 @@ class _MyPhoneState extends State<MyPhone> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
countryController.text = "+91";
|
countryController.text = "+91";
|
||||||
super.initState();
|
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() {
|
void toggleLoginType() {
|
||||||
Navigator.pushNamed(context, 'hrLogin'); // Navigate to another page
|
Navigator.pushNamed(context, 'hrLogin'); // Navigate to another page
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> verifyMobileNumber(String mobileNumber) async {
|
Future<void> verifyMobileNumber() async {
|
||||||
try {
|
try {
|
||||||
final response = await http.post(
|
if (_formKey.currentState!.validate()) {
|
||||||
Uri.parse(Environment.apiUrl + 'verifyEmployeeNumber'),
|
// var enteredMobileNumber = countryController.text + mobileController.text;
|
||||||
body: json.encode({'mobile_number': mobileNumber}),
|
var enteredMobileNumber = mobileController.text;
|
||||||
headers: {
|
final response = await http.post(
|
||||||
HttpHeaders.contentTypeHeader: 'application/json',
|
Uri.parse(Environment.apiUrl + 'verifyEmployeeNumber'),
|
||||||
},
|
body: json.encode({'mobile_number': enteredMobileNumber}),
|
||||||
);
|
headers: {
|
||||||
|
HttpHeaders.contentTypeHeader: 'application/json',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
Map<String, dynamic> data = json.decode(response.body);
|
Map<String, dynamic> data = json.decode(response.body);
|
||||||
bool userVerification = data['data']['user_verification'];
|
bool userVerification = data['data']['user_verification'];
|
||||||
return userVerification;
|
String message = data['data']['message'];
|
||||||
} else {
|
if (userVerification) {
|
||||||
ToastHelper.showErrorToast(context, 'Failed to verify mobile number');
|
ToastHelper.showSuccessToast(context, message);
|
||||||
throw Exception('Failed to verify mobile number');
|
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) {
|
} catch (e) {
|
||||||
ToastHelper.showErrorToast(context, '$e');
|
ToastHelper.showErrorToast(context, 'Something went wrong');
|
||||||
print('Error: $e');
|
print('Error: $e');
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSubmit() async {
|
// void handleSubmit() async {
|
||||||
if (_formKey.currentState!.validate()) {
|
// if (_formKey.currentState!.validate()) {
|
||||||
// var enteredMobileNumber = countryController.text + mobileController.text;
|
// // var enteredMobileNumber = countryController.text + mobileController.text;
|
||||||
var enteredMobileNumber = mobileController.text;
|
// var enteredMobileNumber = mobileController.text;
|
||||||
|
//
|
||||||
bool isValid = await verifyMobileNumber(enteredMobileNumber);
|
// bool isValid = await verifyMobileNumber(enteredMobileNumber);
|
||||||
|
//
|
||||||
if (isValid) {
|
// if (isValid) {
|
||||||
ToastHelper.showSuccessToast(context, 'Mobile No Verified..');
|
// ToastHelper.showSuccessToast(context, 'Mobile No Verified..');
|
||||||
Navigator.pushNamed(context, 'verify', arguments: enteredMobileNumber);
|
// Navigator.pushNamed(context, 'verify', arguments: enteredMobileNumber);
|
||||||
} else {
|
// } else {
|
||||||
ToastHelper.showErrorToast(context, 'Invalid mobile number..');
|
// ToastHelper.showErrorToast(context, 'Invalid mobile number..');
|
||||||
print('Invalid mobile number');
|
// print('Invalid mobile number');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -155,7 +181,7 @@ class _MyPhoneState extends State<MyPhone> {
|
|||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: _size.height /
|
height: _size.height /
|
||||||
6.4), // Adjust the spacing between the rows
|
8.0), // Adjust the spacing between the rows
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment
|
mainAxisAlignment: MainAxisAlignment
|
||||||
.center, // Align to the center
|
.center, // Align to the center
|
||||||
@ -167,9 +193,7 @@ class _MyPhoneState extends State<MyPhone> {
|
|||||||
? Alignment.centerLeft
|
? Alignment.centerLeft
|
||||||
: Alignment.bottomCenter,
|
: Alignment.bottomCenter,
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
_size.width <= 1100
|
'assets/mobileViewLogo.png',
|
||||||
? 'assets/mobileViewLogo.png'
|
|
||||||
: 'assets/Nhance-Logo-Final 1.png',
|
|
||||||
width: 150,
|
width: 150,
|
||||||
height: 150,
|
height: 150,
|
||||||
),
|
),
|
||||||
@ -273,43 +297,41 @@ class _MyPhoneState extends State<MyPhone> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment:
|
alignment: Alignment.centerLeft,
|
||||||
Alignment.centerRight,
|
child: AnimatedButton(
|
||||||
child: MouseRegion(
|
animatedOn:
|
||||||
cursor:
|
AnimatedOn.onHover,
|
||||||
SystemMouseCursors.click,
|
onPress: () {
|
||||||
child: GestureDetector(
|
Navigator.pushNamed(
|
||||||
onTap: () {
|
context, 'hrLogin');
|
||||||
// Add your navigation logic here
|
},
|
||||||
// For example, you can use Navigator.push to navigate to another page
|
onChanges: (change) {},
|
||||||
Navigator.pushNamed(
|
height: 30,
|
||||||
context, 'hrLogin');
|
width: 150,
|
||||||
},
|
text: 'HR Login',
|
||||||
child: Row(
|
isReverse: true,
|
||||||
children: [
|
selectedTextColor:
|
||||||
Text(
|
Colors.black,
|
||||||
'HR Login',
|
transitionType: TransitionType
|
||||||
style: TextStyle(
|
.LEFT_CENTER_ROUNDER,
|
||||||
color: Color(
|
textStyle:
|
||||||
0xFF000000), // Text color
|
GoogleFonts.poppins(
|
||||||
// Add other text styles as needed
|
fontSize: 16,
|
||||||
),
|
letterSpacing: 0,
|
||||||
),
|
color: Color(0xFF00989E),
|
||||||
SizedBox(width: 5),
|
fontWeight: FontWeight.w300,
|
||||||
Icon(
|
|
||||||
Icons
|
|
||||||
.east, // Icon for customer login
|
|
||||||
color: Colors
|
|
||||||
.black, // Adjust color as needed
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
selectedBackgroundColor:
|
||||||
|
Color(0xFF00989E),
|
||||||
|
borderColor:
|
||||||
|
Color(0xFF00989E),
|
||||||
|
borderWidth: 1,
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 15),
|
SizedBox(height: 10),
|
||||||
Container(
|
Container(
|
||||||
margin: Responsive.isDesktop(context)
|
margin: Responsive.isDesktop(context)
|
||||||
? EdgeInsets.symmetric(
|
? EdgeInsets.symmetric(
|
||||||
@ -321,7 +343,7 @@ class _MyPhoneState extends State<MyPhone> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Welcome to Nhance",
|
"Welcome to Nhance",
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@ -330,7 +352,7 @@ class _MyPhoneState extends State<MyPhone> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 15,
|
height: 10,
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
margin: Responsive.isDesktop(context)
|
margin: Responsive.isDesktop(context)
|
||||||
@ -343,8 +365,8 @@ class _MyPhoneState extends State<MyPhone> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
"Have a Health Insurance Policy number, but never signed in? Don't worry, We got you covered",
|
"Login with your mobile number and OTP to review and enroll for exciting health benefits for you and your family",
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Color(0xFF000000)),
|
color: Color(0xFF000000)),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
@ -443,10 +465,10 @@ class _MyPhoneState extends State<MyPhone> {
|
|||||||
BorderRadius.circular(10),
|
BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: handleSubmit,
|
onPressed: verifyMobileNumber,
|
||||||
child: Text(
|
child: Text(
|
||||||
"Login With OTP",
|
"Login With OTP",
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Color(0xFFFFFFFF)),
|
color: Color(0xFFFFFFFF)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -464,7 +486,7 @@ class _MyPhoneState extends State<MyPhone> {
|
|||||||
SizedBox(height: 30),
|
SizedBox(height: 30),
|
||||||
Text(
|
Text(
|
||||||
"Benefits of Login",
|
"Benefits of Login",
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@ -568,28 +590,28 @@ class _MyPhoneState extends State<MyPhone> {
|
|||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
text:
|
text:
|
||||||
'By continuing, you agree with our ',
|
'By continuing, you agree with our ',
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
fontSize: 9,
|
fontSize: 9,
|
||||||
),
|
),
|
||||||
children: <TextSpan>[
|
children: <TextSpan>[
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'privacy policy ',
|
text: 'privacy policy ',
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Color(0xFF00989E),
|
color: Color(0xFF00989E),
|
||||||
fontSize: 9,
|
fontSize: 9,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'and ',
|
text: 'and ',
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
fontSize: 9,
|
fontSize: 9,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'terms of use',
|
text: 'terms of use',
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Color(0xFF00989E),
|
color: Color(0xFF00989E),
|
||||||
fontSize: 9,
|
fontSize: 9,
|
||||||
),
|
),
|
||||||
@ -612,7 +634,7 @@ class _MyPhoneState extends State<MyPhone> {
|
|||||||
return Image.asset(
|
return Image.asset(
|
||||||
'assets/login_web.jpg',
|
'assets/login_web.jpg',
|
||||||
height: _size.height,
|
height: _size.height,
|
||||||
fit: BoxFit.fill,
|
fit: BoxFit.cover,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return SizedBox();
|
return SizedBox();
|
||||||
|
|||||||
108
lib/verify.dart
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:nhancepolicy/models/environment.dart';
|
import 'package:nhancepolicy/models/environment.dart';
|
||||||
import 'package:pinput/pinput.dart';
|
import 'package:pinput/pinput.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
@ -28,10 +29,14 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
dynamic empPrimaryId;
|
dynamic empPrimaryId;
|
||||||
dynamic gpaEmpName;
|
dynamic gpaEmpName;
|
||||||
dynamic client_id;
|
dynamic client_id;
|
||||||
|
dynamic _token;
|
||||||
|
dynamic clientName;
|
||||||
|
dynamic clientLogo;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
checkTokenAvailability();
|
||||||
// Start the timer when the widget is initialized
|
// Start the timer when the widget is initialized
|
||||||
startTimer();
|
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 {
|
Future<void> resendOTP(String mobileNumber) async {
|
||||||
print(mobileNumber);
|
print(mobileNumber);
|
||||||
// Update the UI as needed
|
// Update the UI as needed
|
||||||
@ -105,6 +121,7 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
Map<String, dynamic> data = json.decode(response.body);
|
Map<String, dynamic> data = json.decode(response.body);
|
||||||
print(data);
|
print(data);
|
||||||
|
_token = data['data'];
|
||||||
String status = data['status'];
|
String status = data['status'];
|
||||||
print(status);
|
print(status);
|
||||||
if (status == 'success') {
|
if (status == 'success') {
|
||||||
@ -122,6 +139,7 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
prefs.setString('gpaEmpName', gpaEmpName);
|
prefs.setString('gpaEmpName', gpaEmpName);
|
||||||
client_id = decodedToken['client_id'];
|
client_id = decodedToken['client_id'];
|
||||||
prefs.setString('client_id', client_id);
|
prefs.setString('client_id', client_id);
|
||||||
|
getClientLogoAndDetails();
|
||||||
|
|
||||||
print('Successfully Login');
|
print('Successfully Login');
|
||||||
|
|
||||||
@ -144,13 +162,12 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
print('Invalid OTP. Please try again');
|
print('Invalid OTP. Please try again');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ToastHelper.showErrorToast(context, 'Failed to verify OTP');
|
ToastHelper.showWarningToast(context, 'Something went wrong');
|
||||||
throw Exception('Failed to verify OTP');
|
throw Exception('Failed to verify OTP');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error: $e');
|
print('Error: $e');
|
||||||
ToastHelper.showErrorToast(
|
ToastHelper.showWarningToast(context, 'Something went wrong');
|
||||||
context, 'Failed to verify OTP. Please try again.');
|
|
||||||
// Show a Snackbar if there's an error while verifying OTP
|
// Show a Snackbar if there's an error while verifying OTP
|
||||||
// ToastHelper.showErrorToast(
|
// ToastHelper.showErrorToast(
|
||||||
// context, 'Failed to verify OTP. Please try again.');
|
// 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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Retrieve the passed mobile number value
|
// Retrieve the passed mobile number value
|
||||||
@ -237,7 +301,7 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: _size.height /
|
height: _size.height /
|
||||||
6.4), // Adjust the spacing between the rows
|
8.0), // Adjust the spacing between the rows
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment
|
mainAxisAlignment: MainAxisAlignment
|
||||||
.center, // Align to the center
|
.center, // Align to the center
|
||||||
@ -249,9 +313,7 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
? Alignment.centerLeft
|
? Alignment.centerLeft
|
||||||
: Alignment.bottomCenter,
|
: Alignment.bottomCenter,
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
_size.width <= 1100
|
'assets/mobileViewLogo.png',
|
||||||
? 'assets/mobileViewLogo.png'
|
|
||||||
: 'assets/Nhance-Logo-Final 1.png',
|
|
||||||
width: 150,
|
width: 150,
|
||||||
height: 150,
|
height: 150,
|
||||||
),
|
),
|
||||||
@ -276,7 +338,7 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'HR Login',
|
'HR Login',
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Color(
|
color: Color(
|
||||||
0xFF000000), // Text color
|
0xFF000000), // Text color
|
||||||
// Add other text styles as needed
|
// Add other text styles as needed
|
||||||
@ -366,7 +428,7 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Welcome to Nhance",
|
"Welcome to Nhance",
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@ -435,7 +497,7 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
_isTimerRunning
|
_isTimerRunning
|
||||||
? Text(
|
? Text(
|
||||||
"Resend OTP in $_secondsRemaining seconds",
|
"Resend OTP in $_secondsRemaining seconds",
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Colors.black),
|
color: Colors.black),
|
||||||
)
|
)
|
||||||
: InkWell(
|
: InkWell(
|
||||||
@ -444,7 +506,7 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Resend OTP",
|
"Resend OTP",
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Colors.blue),
|
color: Colors.blue),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -478,7 +540,7 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Submit",
|
"Submit",
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Color(0xFFFFFFFF)),
|
color: Color(0xFFFFFFFF)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -490,10 +552,10 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
horizontal: 150),
|
horizontal: 150),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 30),
|
SizedBox(height: 20),
|
||||||
Text(
|
Text(
|
||||||
"Benefits of Login",
|
"Benefits of Login",
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@ -548,7 +610,9 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: 10),
|
height: 10),
|
||||||
Text(
|
Text(
|
||||||
"View Policy"),
|
"View Policy",
|
||||||
|
style: GoogleFonts
|
||||||
|
.poppins()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -567,7 +631,9 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: 10),
|
height: 10),
|
||||||
Text(
|
Text(
|
||||||
"Manage Claims"),
|
"Manage Claims",
|
||||||
|
style: GoogleFonts
|
||||||
|
.poppins()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -597,28 +663,28 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
text:
|
text:
|
||||||
'By continuing, you agree with our ',
|
'By continuing, you agree with our ',
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
fontSize: 9,
|
fontSize: 9,
|
||||||
),
|
),
|
||||||
children: <TextSpan>[
|
children: <TextSpan>[
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'privacy policy ',
|
text: 'privacy policy ',
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Color(0xFF00989E),
|
color: Color(0xFF00989E),
|
||||||
fontSize: 9,
|
fontSize: 9,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'and ',
|
text: 'and ',
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
fontSize: 9,
|
fontSize: 9,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'terms of use',
|
text: 'terms of use',
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Color(0xFF00989E),
|
color: Color(0xFF00989E),
|
||||||
fontSize: 9,
|
fontSize: 9,
|
||||||
),
|
),
|
||||||
@ -641,7 +707,7 @@ class _MyVerifyState extends State<MyVerify> {
|
|||||||
return Image.asset(
|
return Image.asset(
|
||||||
'assets/login_web.jpg',
|
'assets/login_web.jpg',
|
||||||
height: _size.height,
|
height: _size.height,
|
||||||
fit: BoxFit.fill,
|
fit: BoxFit.cover,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return SizedBox();
|
return SizedBox();
|
||||||
|
|||||||
@ -7,9 +7,13 @@
|
|||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <smart_auth/smart_auth_plugin.h>
|
#include <smart_auth/smart_auth_plugin.h>
|
||||||
|
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
g_autoptr(FlPluginRegistrar) smart_auth_registrar =
|
g_autoptr(FlPluginRegistrar) smart_auth_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "SmartAuthPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "SmartAuthPlugin");
|
||||||
smart_auth_plugin_register_with_registrar(smart_auth_registrar);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
smart_auth
|
smart_auth
|
||||||
|
url_launcher_linux
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|||||||
@ -8,9 +8,11 @@ import Foundation
|
|||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import smart_auth
|
import smart_auth
|
||||||
|
import url_launcher_macos
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
SmartAuthPlugin.register(with: registry.registrar(forPlugin: "SmartAuthPlugin"))
|
SmartAuthPlugin.register(with: registry.registrar(forPlugin: "SmartAuthPlugin"))
|
||||||
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,13 +43,16 @@ dependencies:
|
|||||||
adaptive_navbar: ^0.0.3
|
adaptive_navbar: ^0.0.3
|
||||||
jwt_decode: ^0.3.1
|
jwt_decode: ^0.3.1
|
||||||
google_fonts: ^6.2.1
|
google_fonts: ^6.2.1
|
||||||
file_picker: ^6.2.0
|
file_picker: ^8.0.3
|
||||||
csv: ^6.0.0
|
csv: ^6.0.0
|
||||||
data_tables: ^1.4.0
|
data_tables: ^1.4.0
|
||||||
universal_html: ^2.2.4
|
universal_html: ^2.2.4
|
||||||
excel: ^4.0.3
|
excel: ^4.0.3
|
||||||
intl: ^0.19.0
|
intl: ^0.19.0
|
||||||
toastification: ^1.2.1
|
toastification: ^1.2.1
|
||||||
|
flutter_animated_button: ^2.0.3
|
||||||
|
spreadsheet_decoder: ^2.2.0
|
||||||
|
url_launcher: ^6.2.6
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|||||||
BIN
web/assets/Sample.xlsx
Normal file
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 8.8 KiB |
@ -95,7 +95,7 @@
|
|||||||
if(loadingIndicator){
|
if(loadingIndicator){
|
||||||
loadingIndicator.remove();
|
loadingIndicator.remove();
|
||||||
}
|
}
|
||||||
},10000);
|
},5000);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@ -7,8 +7,11 @@
|
|||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <smart_auth/smart_auth_plugin.h>
|
#include <smart_auth/smart_auth_plugin.h>
|
||||||
|
#include <url_launcher_windows/url_launcher_windows.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
SmartAuthPluginRegisterWithRegistrar(
|
SmartAuthPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("SmartAuthPlugin"));
|
registry->GetRegistrarForPlugin("SmartAuthPlugin"));
|
||||||
|
UrlLauncherWindowsRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
smart_auth
|
smart_auth
|
||||||
|
url_launcher_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|||||||