Commit 94df616d authored by Sai Srinivas's avatar Sai Srinivas
Browse files

16-05-2025 By Sai Srinivas

Finance Module requisition Lists and Details
parent 6a825b3f
import 'package:flutter/foundation.dart';
import 'package:generp/Models/financeModels/paymentRequisitionDetailsResponse.dart';
import 'package:generp/Notifiers/HomeScreenNotifier.dart';
import 'package:generp/services/api_calling.dart';
import 'package:provider/provider.dart';
import 'approveRejectPaymentRequestResponse.dart';
class Requesitionlidtdetailsprovider extends ChangeNotifier{
PaymentDetails _paymentDetails = PaymentDetails();
RequestDetails _requestDetails = RequestDetails();
PaymentDetails get paymentsDetails => _paymentDetails;
RequestDetails get requestsDetails => _requestDetails;
List<PaymentAccounts> _paymentAccounts = [];
PaymentRequestDetails _paymentRequestDetails = PaymentRequestDetails();
List<PaymentModes> _paymentModes = [];
PaymentAccounts? _selectedPaymentAccounts;
List<PaymentAccounts> get paymentsAccounts => _paymentAccounts;
List<PaymentModes> get paymentsModes => _paymentModes;
PaymentRequestDetails get paymentsReqDetails => _paymentRequestDetails;
PaymentAccounts? get selectedPaymentAccounts => _selectedPaymentAccounts;
var _selectedValue;
var _selectedID;
get selectedValue => _selectedValue;
get selectedID => _selectedID;
List<String> _headings = [
];
List<String> _subHeadings =[];
List<String> get subHeadings => _subHeadings;
List<String> get Headings => _headings;
set selectedPaymentAccounts(PaymentAccounts? value){
_selectedPaymentAccounts = value;
_selectedValue = value!.name!;
_selectedID = value!.id;
notifyListeners();
}
set selectedValue(value){
_selectedValue = value;
notifyListeners();
}
set selectedID(value){
_selectedID = value;
notifyListeners();
}
Future<void> paymentRequesitionDetails(context,payment_request_id) async {
try{
var provider = Provider.of<HomescreenNotifier>(context,listen: false);
final data = await ApiCalling.paymentRequestionDetailsAPI(provider.empId, provider.session, payment_request_id);
if(data!=null){
if(data.error=="0"){
_headings = [
"Requested Account",
"Proposed Account Name",
"Branch",
"Requesting Propose",
"Payment Mode",
"Created Employee",
"Attachment",
"Requested Date",
"Note",
"Level 1 Remarks",
"Level 1 Approved By",
"Level 2 Remarks",
"Level 2 Approved By",
"Created Date/Time",
"Updated Date/Time",
];
_paymentDetails = data.paymentDetails??PaymentDetails(
accountId: "",
accountName: "",
amount: "",
attachmentDirFilePath: "",
attachmentViewFileName: "",
bankAccountHolderName: "",
bankAccountNumber: "",
bankBranchName: "",
bankIfscCode: "",
bankName: "",
bankUpiId: "",
createdDatetime: "",
createdEmployeeId: "",
description: "",
id: "",
isExists: "",
mode: "",
paymentAccountId: "",
paymentAccountName: "",
paymentDate: "",
paymentEmployeeName: "",
paymentModeId: "",
paymentReferenceNumber: "",
paymentRemarks: "",
refId: "",
refType: "",
updatedDatetime: ""
);
_requestDetails = data.requestDetails??RequestDetails(
updatedDatetime: "",
id: "",
description: "",
createdDatetime: "",
attachmentViewFileName: "",
attachmentDirFilePath: "",
amount: "",
accountName: "",
accountId: "",
branch: "",
createdEmployee: "",
date: "",
isProcessedPaymentRequest: "",
level1ApprovalRemarks: "",
level1Employee: "",
level2ApprovalRemarks: "",
level2Employee: "",
proposedAccount: "",
proposedAccountId: "",
requestedAmount: "",
requestingPurpose: "",
requestMode: "",
status: "",
transDis: ""
);
_subHeadings = [
_requestDetails.accountName??"-",
_requestDetails.proposedAccount??"-",
_requestDetails.branch??"-",
_requestDetails.requestingPurpose??"-",
_requestDetails.requestMode??"-",
_requestDetails.createdEmployee??"-",
_requestDetails.attachmentViewFileName??"-",
_requestDetails.date??"-",
_requestDetails.description??"-",
_requestDetails.level1ApprovalRemarks??"-",
_requestDetails.level1Employee??"-",
_requestDetails.level2ApprovalRemarks??"-",
_requestDetails.level2Employee??"-",
_requestDetails.createdDatetime??"-",
_requestDetails.updatedDatetime??"-"
];
notifyListeners();
}
}
}catch (e,s){}
}
Future<void> approveRejectPaymentRequestAPIFunction(context,payment_request_id) async {
try{
var provider = Provider.of<HomescreenNotifier>(context,listen: false);
final data = await ApiCalling.approveRejectPaymentRequestAPI(provider.empId, provider.session, payment_request_id);
if(data!=null){
if(data.error=="0"){
_paymentModes = data.paymentModes!;
_paymentAccounts = data.paymentAccounts!;
_paymentRequestDetails= data.paymentRequestDetails!;
notifyListeners();
}
}
}catch (e,s){}
}
Future<void> paymentrequisitionRejectSubmitAPIFunction(context, mode, payment_request_id, approve_remarks) async {
try{
var provider = Provider.of<HomescreenNotifier>(context,listen: false);
final data = await ApiCalling.RejectPaymentRequestSubmitAPI(provider.empId, provider.session, mode, payment_request_id, approve_remarks);
}catch (e,s){
}
}
Future<void> paymentrequisitionApproveSubmitAPIFunction(context, mode, payment_request_id,approved_amount, approve_remarks,proposed_payment_account_id) async {
try{
var provider = Provider.of<HomescreenNotifier>(context,listen: false);
final data = await ApiCalling.ApprovePaymentRequestSubmitAPI(provider.empId, provider.session, mode, payment_request_id, approved_amount, approve_remarks, proposed_payment_account_id);
}catch (e,s){
}
}
Future<void> paymentrequisitionProcessSubmitAPIFunction(context, mode, payment_request_id,approved_amount, approve_remarks,proposed_payment_account_id,payment_account_id,processing_remarks,attachment) async {
try{
var provider = Provider.of<HomescreenNotifier>(context,listen: false);
final data = await ApiCalling.processApproveRejectPaymentRequestSubmitAPI(provider.empId, provider.session, mode, payment_request_id, approved_amount, approve_remarks, proposed_payment_account_id, payment_account_id, processing_remarks, attachment);
}catch (e,s){
}
}
}
\ No newline at end of file
......@@ -3,37 +3,28 @@ import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:generp/Notifiers/HomeScreenNotifier.dart';
import 'package:generp/Utils/commonServices.dart';
import 'package:generp/services/api_calling.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:share_plus/share_plus.dart';
import '../../Models/financeModels/addPaymentRequestionResponse.dart';
import '../../Models/financeModels/paymentRequesitionListsResponse.dart';
import 'package:csv/csv.dart';
import 'package:excel/excel.dart';
import 'package:path_provider/path_provider.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:printing/printing.dart';
class Requestionlistprovider extends ChangeNotifier {
var res = {
"requesting_purposes": [
"Salary Advance",
"Incentive Advance",
"Tour Advance",
],
"accounts": [
{"id": "22", "name": "Super Admin"},
],
"payment_modes": [
{"id": "1", "name": "Cash"},
{"id": "2", "name": "Cheque"},
{"id": "3", "name": "RTGS"},
{"id": "4", "name": "NEFT"},
{"id": "5", "name": "IMPS"},
{"id": "6", "name": "UPI"},
{"id": "7", "name": "Online Portal"},
],
"error": "0",
"message": "Fetched Successfully",
};
TextEditingController reqPurposeController = TextEditingController();
TextEditingController descController = TextEditingController();
......@@ -48,6 +39,7 @@ class Requestionlistprovider extends ChangeNotifier {
List<Accounts> _accounts = [];
List<PaymentModes> _paymentModes = [];
List<String> _requestingPurposes = [];
List<RequistionList> _requisitionList = [];
Accounts? _selectedAccounts;
PaymentModes? _selectedPayment;
String? _selectReqPurpose;
......@@ -74,10 +66,9 @@ class Requestionlistprovider extends ChangeNotifier {
// bool _submitClicked = false;
var _image_picked = 0;
final ImagePicker _picker = ImagePicker();
File? _image;
String get paymentModeId => _paymentModeId;
......@@ -103,6 +94,8 @@ class Requestionlistprovider extends ChangeNotifier {
List<PaymentModes> get paymentModes => _paymentModes;
List<String> get requestingPurposes => _requestingPurposes;
List<RequistionList> get requisitionList => _requisitionList;
// bool get submitClicked => _submitClicked;
// set submitClicked(bool value){
......@@ -268,6 +261,270 @@ class Requestionlistprovider extends ChangeNotifier {
} catch (e, s) {}
}
Future<void> paymentRequestionListsAPIFunction(context, mode) async {
try {
var homeProvider = Provider.of<HomescreenNotifier>(
context,
listen: false,
);
final data = await ApiCalling.paymentRequestionListsAPI(
homeProvider.empId,
homeProvider.session,
mode,
);
if (data != null) {
if (data.error == "0") {
_requisitionList = data.requistionList!;
notifyListeners();
} else {}
}
} catch (e, s) {}
}
List<List<String>> prepareExportData() {
final headers = [
'ID',
'Account Name',
'Branch',
'Purpose',
'Description',
'Amount',
'Mode',
'Status',
'Date',
];
final rows = requisitionList.map((item) => [
item.id ?? '',
item.accountName ?? '',
item.branch ?? '',
item.requestingPurpose ?? '',
item.description ?? '',
item.amount ?? '',
item.requestMode ?? '',
item.status ?? '',
item.date ?? '',
]).toList();
return [headers, ...rows];
}
void copyToClipboard(BuildContext context) async {
try {
if (requisitionList.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("No data to copy")),
);
return;
}
final data = prepareExportData();
String raw = data.map((row) => row.join('\t')).join('\n');
print('Clipboard data: $raw');
await Clipboard.setData(ClipboardData(text: raw));
toast(context, "Copied to Clipboard");
} catch (e) {
print('Error copying to clipboard: $e');
}
}
Future<String> getSaveDirectory() async {
// Try Downloads directory first
try {
if (Platform.isAndroid) {
// Request storage permission for Android
if (await Permission.storage.request().isGranted ||
await Permission.manageExternalStorage.request().isGranted) {
final dir = await getApplicationDocumentsDirectory();
if (dir != null) {
print('Using Downloads directory: ${dir.path}');
return dir.path;
}
}
}
} catch (e) {
print('Error accessing Downloads directory: $e');
}
// Fallback to shared Documents directory
try {
final dir = await getDownloadsDirectory();
if (dir != null) {
final customDir = Directory('${dir.path}/RequisitionData');
if (!await customDir.exists()) {
await customDir.create(recursive: true);
}
print('Using custom Documents directory: ${customDir.path}');
return customDir.path;
}
} catch (e) {
print('Error accessing Documents directory: $e');
}
// Final fallback to app's Documents directory
final dir = await getApplicationDocumentsDirectory();
print('Using app Documents directory: ${dir.path}');
return dir.path;
}
Future<void> downloadCSV(BuildContext context) async {
try {
if (requisitionList.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("No data to export")),
);
return;
}
final data = prepareExportData();
final csvData = const ListToCsvConverter().convert(data);
final dirPath = await getSaveDirectory();
final file = File('$dirPath/requisition_data.csv');
await file.writeAsString(csvData);
print('CSV saved at: ${file.path}');
bool exists = await file.exists();
print('File exists: $exists');
// await OpenFile.open(file.path); // Open the file
// await Share.share(file.path); // Share the file
toast(context, "CSV Downloaded");
} catch (e) {
print('Error downloading CSV: $e');
}
}
Future<void> downloadXLS(BuildContext context) async {
try {
if (requisitionList.isEmpty) {
toast(context, "No Data to export");
return;
}
final data = prepareExportData();
var excel = Excel.createExcel();
Sheet sheet = excel['Sheet1'];
for (var row in data) {
sheet.appendRow(row.map((cell) => TextCellValue(cell)).toList());
}
final dirPath = await getSaveDirectory();
final file = File('$dirPath/requisition_data.xlsx');
final bytes = excel.encode();
if (bytes == null) throw Exception("Excel encoding failed");
await file.writeAsBytes(bytes);
print('XLSX saved at: ${file.path}');
bool exists = await file.exists();
print('File exists: $exists');
// await OpenFile.open(file.path); // Open the file
// await Share.share([file.path], text: 'Requisition Data XLSX'); // Share the file
toast(context, ("XLSX Downloaded and opened"));
} catch (e) {
print('Error downloading XLSX: $e');
}
}
Future<void> downloadPDF(BuildContext context) async {
try {
if (requisitionList.isEmpty) {
toast(context, "No Data to export");
return;
}
final data = prepareExportData();
final pdf = pw.Document();
pdf.addPage(
pw.Page(
build: (context) => pw.Table.fromTextArray(data: data),
),
);
final dirPath = await getSaveDirectory();
final file = File('$dirPath/requisition_data.pdf');
await file.writeAsBytes(await pdf.save());
print('PDF saved at: ${file.path}');
bool exists = await file.exists();
print('File exists: $exists');
// await OpenFile.open(file.path); // Open the file
// await Share.shareXFiles([file.path], text: 'Requisition Data PDF'); // Share the file
toast(context, "PDF Downloaded ");
} catch (e) {
print('Error downloading PDF: $e');
}
}
Future<void> printData(BuildContext context) async {
try {
if (requisitionList.isEmpty) {
toast(context, "No Data to Print");
return;
}
final data = prepareExportData();
final pdf = pw.Document();
pdf.addPage(
pw.Page(
build: (context) => pw.Table.fromTextArray(data: data),
),
);
await Printing.layoutPdf(
onLayout: (PdfPageFormat format) async => pdf.save(),
);
} catch (e) {
print('Error printing data: $e');
}
}
// void copyToClipboard(context) {
// final data = prepareExportData();
// String raw = data.map((row) => row.join('\t')).join('\n');
// Clipboard.setData(ClipboardData(text: raw));
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Copied to clipboard")));
// }
//
// Future<void> downloadCSV(context) async {
// final data = prepareExportData();
// final csvData = const ListToCsvConverter().convert(data);
// final dir = await getApplicationDocumentsDirectory();
// final file = File('${dir.path}/requisition_data.csv');
// await file.writeAsString(csvData);
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("CSV Downloaded")));
// }
//
// Future<void> downloadXLS(context) async {
// final data = prepareExportData();
// var excel = Excel.createExcel();
// Sheet sheet = excel['Sheet1'];
//
// for (var row in data) {
// sheet.appendRow(row.map((cell) => TextCellValue(cell)).toList());
// }
// final dir = await getApplicationDocumentsDirectory();
// final file = File('${dir.path}/requisition_data.xlsx');
// await file.writeAsBytes(excel.encode()!);
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("XLSX Downloaded")));
// }
//
// Future<void> downloadPDF(context) async {
// final data = prepareExportData();
// final pdf = pw.Document();
// pdf.addPage(
// pw.Page(
// build: (context) => pw.Table.fromTextArray(data: data),
// ),
// );
// final dir = await getApplicationDocumentsDirectory();
// final file = File('${dir.path}/requisition_data.pdf');
// await file.writeAsBytes(await pdf.save());
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("PDF Downloaded")));
// }
//
// Future<void> printData(context) async {
// final data = prepareExportData();
// final pdf = pw.Document();
// pdf.addPage(
// pw.Page(
// build: (context) => pw.Table.fromTextArray(data: data),
// ),
// );
// await Printing.layoutPdf(
// onLayout: (PdfPageFormat format) async => pdf.save(),
// );
// }
void resetForm() {
reqPurposeController.clear();
descController.clear();
......
class approveRejectPaymentRequestResponse {
List<PaymentAccounts>? paymentAccounts;
PaymentRequestDetails? paymentRequestDetails;
List<PaymentModes>? paymentModes;
String? error;
String? message;
approveRejectPaymentRequestResponse(
{this.paymentAccounts,
this.paymentRequestDetails,
this.paymentModes,
this.error,
this.message});
approveRejectPaymentRequestResponse.fromJson(Map<String, dynamic> json) {
if (json['payment_accounts'] != null) {
paymentAccounts = <PaymentAccounts>[];
json['payment_accounts'].forEach((v) {
paymentAccounts!.add(new PaymentAccounts.fromJson(v));
});
}
paymentRequestDetails = json['payment_request_details'] != null
? new PaymentRequestDetails.fromJson(json['payment_request_details'])
: null;
if (json['payment_modes'] != null) {
paymentModes = <PaymentModes>[];
json['payment_modes'].forEach((v) {
paymentModes!.add(new PaymentModes.fromJson(v));
});
}
error = json['error'];
message = json['message'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.paymentAccounts != null) {
data['payment_accounts'] =
this.paymentAccounts!.map((v) => v.toJson()).toList();
}
if (this.paymentRequestDetails != null) {
data['payment_request_details'] = this.paymentRequestDetails!.toJson();
}
if (this.paymentModes != null) {
data['payment_modes'] =
this.paymentModes!.map((v) => v.toJson()).toList();
}
data['error'] = this.error;
data['message'] = this.message;
return data;
}
}
class PaymentAccounts {
String? id;
String? name;
String? accountBalance;
PaymentAccounts({this.id, this.name, this.accountBalance});
PaymentAccounts.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
accountBalance = json['account_balance'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['account_balance'] = this.accountBalance;
return data;
}
}
class PaymentRequestDetails {
String? id;
String? accountId;
String? requestingPurpose;
String? description;
String? amount;
String? requestedAmount;
String? paymentRequestModeId;
String? bankName;
String? bankBranchName;
String? bankIfscCode;
String? bankAccountHolderName;
String? bankAccountNumber;
String? bankUpiId;
PaymentRequestDetails(
{this.id,
this.accountId,
this.requestingPurpose,
this.description,
this.amount,
this.requestedAmount,
this.paymentRequestModeId,
this.bankName,
this.bankBranchName,
this.bankIfscCode,
this.bankAccountHolderName,
this.bankAccountNumber,
this.bankUpiId});
PaymentRequestDetails.fromJson(Map<String, dynamic> json) {
id = json['id'];
accountId = json['account_id'];
requestingPurpose = json['requesting_purpose'];
description = json['description'];
amount = json['amount'];
requestedAmount = json['requested_amount'];
paymentRequestModeId = json['payment_request_mode_id'];
bankName = json['bank_name'];
bankBranchName = json['bank_branch_name'];
bankIfscCode = json['bank_ifsc_code'];
bankAccountHolderName = json['bank_account_holder_name'];
bankAccountNumber = json['bank_account_number'];
bankUpiId = json['bank_upi_id'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['account_id'] = this.accountId;
data['requesting_purpose'] = this.requestingPurpose;
data['description'] = this.description;
data['amount'] = this.amount;
data['requested_amount'] = this.requestedAmount;
data['payment_request_mode_id'] = this.paymentRequestModeId;
data['bank_name'] = this.bankName;
data['bank_branch_name'] = this.bankBranchName;
data['bank_ifsc_code'] = this.bankIfscCode;
data['bank_account_holder_name'] = this.bankAccountHolderName;
data['bank_account_number'] = this.bankAccountNumber;
data['bank_upi_id'] = this.bankUpiId;
return data;
}
}
class PaymentModes {
String? id;
String? name;
PaymentModes({this.id, this.name});
PaymentModes.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
return data;
}
}
......@@ -100,6 +100,7 @@ int get loginStatus => _loginStatus;
print(_deviceDetails);
print(_deviceId);
print(_androidId);
notifyListeners();
}
Future<String?> getDevId() async {
......@@ -107,6 +108,7 @@ int get loginStatus => _loginStatus;
var iosDeviceInfo = await deviceInfo.iosInfo;
_deviceId = iosDeviceInfo.identifierForVendor!;
_deviceDetails = iosDeviceInfo.toString();
notifyListeners();
}
......
......@@ -33,6 +33,8 @@ import 'package:generp/screens/HomeScreen.dart';
import 'package:generp/screens/splash.dart';
import 'package:provider/provider.dart';
import 'Notifiers/financeProvider/RequesitionLidtDetailsProvider.dart';
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'generp_channel', // id
'generp_channel_name',
......@@ -209,6 +211,7 @@ class MyApp extends StatelessWidget {
///finance
ChangeNotifierProvider(create: (_) => Dashboardprovider(),),
ChangeNotifierProvider(create: (_) => Requestionlistprovider(),),
ChangeNotifierProvider(create: (_) => Requesitionlidtdetailsprovider(),),
],
child: Builder(
builder: (BuildContext context) {
......
......@@ -16,6 +16,7 @@ import 'package:generp/screens/finance/financeDashboard.dart';
import 'package:generp/screens/genTracker/GenTrackerDashboard.dart';
import 'package:generp/screens/serviceEngineer/NearbyGenerators.dart';
import 'package:generp/screens/serviceEngineer/serviceEngineerDashboard.dart';
import 'package:generp/screens/webtest.dart';
import 'package:geolocator/geolocator.dart';
import 'package:provider/provider.dart';
import 'package:cached_network_image/cached_network_image.dart';
......@@ -126,8 +127,8 @@ class _MyHomePageState extends State<MyHomePage> {
"Nearby",
"Inventory",
"Whizzdom",
// "CRM",
// "Finance",
"CRM",
"Finance",
];
final icons = [
"assets/svg/home_icons_1.svg",
......@@ -137,8 +138,8 @@ class _MyHomePageState extends State<MyHomePage> {
"assets/svg/home_icons_5.svg",
"assets/svg/home_icons_6.svg",
"assets/svg/home_icons_81.svg",
// "assets/svg/home_icons_8.svg",
// "assets/svg/home_icons_8.svg",
"assets/svg/home_icons_8.svg",
"assets/svg/home_icons_8.svg",
];
final requiredRoles = [
"430",
......@@ -148,8 +149,8 @@ class _MyHomePageState extends State<MyHomePage> {
"433",
"432",
"431",
// "431",
// "431",
"431",
"431",
];
final filteredItems = <Map<String, String>>[];
......@@ -444,13 +445,13 @@ class _MyHomePageState extends State<MyHomePage> {
//res = await Navigator.push(context, MaterialPageRoute(builder: (context)=>CRMScreen()));
break;
case "Finance":
// res = await Navigator.push(
// context,
// MaterialPageRoute(
// builder:
// (context) => Financedashboard(),
// ),
// );
res = await Navigator.push(
context,
MaterialPageRoute(
builder:
(context) => Financedashboard(),
),
);
break;
default:
print("111");
......
......@@ -4,6 +4,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:generp/Notifiers/loginNotifier.dart';
import 'package:provider/provider.dart';
import 'package:share_plus/share_plus.dart';
......@@ -151,455 +152,453 @@ class _LoginScreenState extends State<LoginScreen>
}
@override
Widget build(BuildContext context) {
var loginProv = Provider.of<Loginnotifier>(context,listen: true);
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
return WillPopScope(
onWillPop: onBackPressed,
child: Scaffold(
resizeToAvoidBottomInset: true,
backgroundColor: AppColors.scaffold_bg_color,
body: KeyboardVisibilityProvider(
controller: _keyboardVisibilityController,
child: Stack(
alignment: Alignment.center,
children: [
// Background scrolling logos
ListView.builder(
controller: _scrollController,
itemBuilder: (context, index) {
int logoIndex = index % logos.length;
return Padding(
padding: const EdgeInsets.all(3.0),
child: CustomGridRow(logos: logos, logoIndex: logoIndex),
);
},
),
AnimatedPositioned(
bottom: 0,
left: 0,
right: 0,
duration: Duration(milliseconds: 300),
child: Container(
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment(-0.00, -1.00),
end: Alignment(0, 1),
colors: [
Colors.white.withOpacity(0.0),
// Fully transparent at the very top
Colors.white.withOpacity(0.3),
// Light fade-in
Colors.white.withOpacity(0.6),
// Mid fade
Colors.white,
// Solid white for the rest
],
stops: [0.0, 0.05, 0.1, 0.15],
),
return Consumer<Loginnotifier>(
builder: (context,loginProv,child) {
return WillPopScope(
onWillPop: onBackPressed,
child: Scaffold(
resizeToAvoidBottomInset: true,
backgroundColor: AppColors.scaffold_bg_color,
body: KeyboardVisibilityProvider(
controller: _keyboardVisibilityController,
child: Stack(
alignment: Alignment.center,
children: [
// Background scrolling logos
ListView.builder(
controller: _scrollController,
itemBuilder: (context, index) {
int logoIndex = index % logos.length;
return Padding(
padding: const EdgeInsets.all(3.0),
child: CustomGridRow(logos: logos, logoIndex: logoIndex),
);
},
),
child: SingleChildScrollView(
child: Stack(
alignment: Alignment.center,
children: [
Container(
AnimatedPositioned(
bottom: 0,
left: 0,
right: 0,
duration: Duration(milliseconds: 300),
child: Container(
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment(-0.00, -1.00),
end: Alignment(0, 1),
colors: [
Colors.white.withOpacity(0.0),
// Fully transparent at the very top
Colors.white.withOpacity(0.3),
// Light fade-in
Colors.white.withOpacity(0.6),
// Mid fade
Colors.white,
// Solid white for the rest
],
stops: [0.0, 0.05, 0.1, 0.15],
),
),
child: SingleChildScrollView(
child: Stack(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(
horizontal: 15,
vertical: 10,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedContainer(
duration: const Duration(milliseconds: 1200),
curve: Curves.easeInOut,
child:
_isTextFieldFocused
? Row(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: SizedBox(width: 10),
),
Expanded(
flex: 2,
child: Image.asset(
"assets/images/gen_logo.png",
),
),
const SizedBox(width: 10),
Expanded(
flex: 3,
child: Image.asset("assets/images/gen_logo_grad.png"),
),
Expanded(
flex: 1,
child: SizedBox(width: 10),
),
],
)
: Column(
children: [
Container(
width: 180,
height: 120,
child: Image.asset(
"assets/images/gen_logo.png",
),
),
Image.asset("assets/images/gen_logo_grad.png",width: 150,),
],
),
),
SizedBox(height: 10,),
Text(
"Login to enter",
style: TextStyle(
fontSize: 14,
fontFamily: "JakartaMedium",
color: AppColors.app_blue,
),
),
Container(
padding: EdgeInsets.only(left: 10,bottom: 5),
alignment: Alignment.topLeft,
child: Text(
"Email ID",
style: TextStyle(
color: AppColors.semi_black,
fontFamily: "JakartaMedium",
fontSize: 14,
),
),
children: [
Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(
horizontal: 15,
vertical: 10,
),
Container(
height: 48,
alignment: Alignment.center,
decoration: BoxDecoration(
color: AppColors.text_field_color,
borderRadius: BorderRadius.circular(14),
border: _emailFocusNode.hasFocus?Border.all(color: AppColors.app_blue,width: 0.5):null
),
// alignment: Alignment.center,
margin: EdgeInsets.only(left: 5.0, right: 5.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(
10.0,
0.0,
15,
0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedContainer(
duration: const Duration(milliseconds: 1200),
curve: Curves.easeInOut,
child:
_isTextFieldFocused
? Row(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: SizedBox(width: 10),
),
Expanded(
flex: 2,
child: Image.asset(
"assets/images/gen_logo.png",
),
),
const SizedBox(width: 10),
Expanded(
flex: 3,
child: Image.asset("assets/images/gen_logo_grad.png"),
),
Expanded(
flex: 1,
child: SizedBox(width: 10),
),
],
)
: Column(
children: [
Container(
width: 180,
height: 120,
child: Image.asset(
"assets/images/gen_logo.png",
),
),
Image.asset("assets/images/gen_logo_grad.png",width: 150,),
],
),
),
child: TextField(
controller: email,
keyboardType: TextInputType.emailAddress,
focusNode: _emailFocusNode,
SizedBox(height: 10,),
Text(
"Login to enter",
style: TextStyle(
fontSize: 14
fontSize: 14,
fontFamily: "JakartaMedium",
color: AppColors.app_blue,
),
onChanged: (value) {
loginProv.updateEmail(email.text);
},
onTapOutside: (event) {
// Handle onTapOutside
FocusScope.of(context).unfocus();
},
decoration: InputDecoration(
isDense: true,
hintStyle: TextStyle(
fontWeight: FontWeight.w400,
),
Container(
padding: EdgeInsets.only(left: 10,bottom: 5),
alignment: Alignment.topLeft,
child: Text(
"Email ID",
style: TextStyle(
color: AppColors.semi_black,
fontFamily: "JakartaMedium",
fontSize: 14,
color: Color(0xFF818181)
),
//contentPadding: EdgeInsets.fromLTRB(5.0, 10.0, 5.0, 10.0),
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintText: 'Enter Your Email',
),
),
),
),
if (loginProv.emailError != null) ...[
Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(
top: 2.5,
bottom: 2.5,
left: 25,
),
child: Text(
loginProv.emailError,
textAlign: TextAlign.start,
style: TextStyle(color: Colors.red),
),
),
] else ...[
SizedBox(height: 10.0),
],
Container(
padding: EdgeInsets.only(left: 10,bottom: 5),
alignment: Alignment.topLeft,
child: Text(
"Password",
style: TextStyle(
color: AppColors.semi_black,
fontFamily: "JakartaMedium",
fontSize: 14,
),
),
),
Container(
height: 48,
alignment: Alignment.center,
decoration: BoxDecoration(
color: AppColors.text_field_color,
borderRadius: BorderRadius.circular(14),
border: _passwordFocusNode.hasFocus?Border.all(color: AppColors.app_blue,width: 0.5):null
),
// alignment: Alignment.center,
margin: EdgeInsets.only(left: 5.0, right: 5.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(
10.0,
0.0,
0,
0,
),
child: TextField(
controller: password,
focusNode: _passwordFocusNode,
obscureText: !loginProv.pwdVisible,
keyboardType: TextInputType.visiblePassword,
style: TextStyle(
fontSize: 14,
Container(
height: 48,
alignment: Alignment.center,
decoration: BoxDecoration(
color: AppColors.text_field_color,
borderRadius: BorderRadius.circular(14),
border: _emailFocusNode.hasFocus?Border.all(color: AppColors.app_blue,width: 0.5):null
),
onChanged: (value) {
loginProv.updatePassword(password.text);
},
onEditingComplete: () {
},
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(
0,
10,
0,
// alignment: Alignment.center,
margin: EdgeInsets.only(left: 5.0, right: 5.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(
10.0,
0.0,
15,
0,
),
hintText: "Enter Password",
suffixIcon: IconButton(
icon: Icon(
loginProv.pwdVisible
? CupertinoIcons.eye_solid
: CupertinoIcons.eye_slash_fill,
size: 30,
child: TextField(
controller: email,
keyboardType: TextInputType.emailAddress,
focusNode: _emailFocusNode,
style: TextStyle(
fontSize: 14
),
onPressed: () {
loginProv.visibility_ov();
onChanged: (value) {
loginProv.updateEmail(email.text);
},
onTapOutside: (event) {
// Handle onTapOutside
FocusScope.of(context).unfocus();
},
decoration: InputDecoration(
isDense: true,
hintStyle: TextStyle(
fontWeight: FontWeight.w400,
fontSize: 14,
color: Color(0xFF818181)
),
//contentPadding: EdgeInsets.fromLTRB(5.0, 10.0, 5.0, 10.0),
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintText: 'Enter Your Email',
),
),
),
),
if (loginProv.emailError != null) ...[
Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(
top: 2.5,
bottom: 2.5,
left: 25,
),
hintStyle: TextStyle(
child: Text(
loginProv.emailError,
textAlign: TextAlign.start,
style: TextStyle(color: Colors.red),
),
),
] else ...[
SizedBox(height: 10.0),
],
Container(
padding: EdgeInsets.only(left: 10,bottom: 5),
alignment: Alignment.topLeft,
child: Text(
"Password",
style: TextStyle(
color: AppColors.semi_black,
fontFamily: "JakartaMedium",
fontSize: 14,
color: Color(0xFF818181),
fontWeight: FontWeight.w400,
),
isDense: true,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
),
),
),
),
if (loginProv.passwordError != null) ...[
Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(
top: 2.5,
bottom: 2.5,
left: 25,
),
child: Text(
loginProv.passwordError,
textAlign: TextAlign.start,
style: TextStyle(color: Colors.red),
),
),
] else ...[
SizedBox(height: 25.0),
],
Container(
child: InkWell(
onTap: () {
// LoginApiFunction();
loginProv.LoginApiFunction(context, email.text, password.text);
var f = FocusScope.of(context);
if (!f.hasPrimaryFocus) {
f.unfocus();
}
// Navigator.push(context,MaterialPageRoute(builder: (context)=>Profile()));
},
child: Container(
Container(
height: 48,
alignment: Alignment.center,
height: 45,
width: screenWidth,
margin: EdgeInsets.only(
left: 5.0,
right: 5.0,
),
decoration: BoxDecoration(
color: loginProv.isButtonEnabled?AppColors.app_blue:AppColors.button_disabled, //1487C9
borderRadius: BorderRadius.circular(15.0),
color: AppColors.text_field_color,
borderRadius: BorderRadius.circular(14),
border: _passwordFocusNode.hasFocus?Border.all(color: AppColors.app_blue,width: 0.5):null
),
child: Center(
// alignment: Alignment.center,
margin: EdgeInsets.only(left: 5.0, right: 5.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(
10.0,
0.0,
0,
0,
),
child: TextField(
controller: password,
focusNode: _passwordFocusNode,
obscureText: !loginProv.pwdVisible,
keyboardType: TextInputType.visiblePassword,
style: TextStyle(
fontSize: 14,
),
onChanged: (value) {
loginProv.updatePassword(password.text);
},
onEditingComplete: () {
},
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(
0,
10,
0,
0,
),
hintText: "Enter Password",
suffixIcon: IconButton(
icon: Icon(
loginProv.pwdVisible
? CupertinoIcons.eye_solid
: CupertinoIcons.eye_slash_fill,
size: 30,
),
onPressed: () {
loginProv.visibility_ov();
},
),
hintStyle: TextStyle(
fontSize: 14,
color: Color(0xFF818181),
fontWeight: FontWeight.w400,
),
isDense: true,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
),
),
),
),
if (loginProv.passwordError != null) ...[
Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(
top: 2.5,
bottom: 2.5,
left: 25,
),
child: Text(
"Login",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white,
fontFamily: "JakartaRegular",),
loginProv.passwordError,
textAlign: TextAlign.start,
style: TextStyle(color: Colors.red),
),
),
] else ...[
SizedBox(height: 25.0),
],
Container(
child: InkWell(
onTap: () {
// LoginApiFunction();
loginProv.LoginApiFunction(context, email.text, password.text);
var f = FocusScope.of(context);
if (!f.hasPrimaryFocus) {
f.unfocus();
}
// Navigator.push(context,MaterialPageRoute(builder: (context)=>Profile()));
},
child: Container(
alignment: Alignment.center,
height: 45,
width: screenWidth,
margin: EdgeInsets.only(
left: 5.0,
right: 5.0,
),
decoration: BoxDecoration(
color: loginProv.isButtonEnabled?AppColors.app_blue:AppColors.button_disabled, //1487C9
borderRadius: BorderRadius.circular(15.0),
),
child: Center(
child: Text(
"Login",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white,
fontFamily: "JakartaRegular",),
),
),
),
),
),
),
],
),
],
),
),
],
),
],
),
),
),
),
),
Positioned(
top: 50,
right: 20,
child: InkResponse(
Positioned(
top: 50,
right: 20,
child: InkResponse(
child: GestureDetector(
onTap: () async {
await tooltipcontroller.showTooltip();
child: GestureDetector(
onTap: () async {
await tooltipcontroller.showTooltip();
},
child: SuperTooltip(
controller: tooltipcontroller,
popupDirection: TooltipDirection.down,
backgroundColor: Colors.white,
borderColor: Colors.white,
showCloseButton: true,
left: 50,
right: 30,
barrierColor: Colors.transparent,
arrowTipDistance: 20.0,
minimumOutsideMargin: 120,
arrowBaseWidth: 20.0,
arrowLength: 20.0,
borderWidth: 2.0,
constraints: const BoxConstraints(
minHeight: 0.0,
maxHeight: 100,
minWidth: 0.0,
maxWidth: 100,
),
touchThroughAreaShape: ClipAreaShape.rectangle,
touchThroughAreaCornerRadius: 30,
content: Container(
height: 100,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text("Device ID",
style: TextStyle(
fontSize: 16,
fontFamily: "JakartaMedium",
color: AppColors.app_blue
),),
SizedBox(height: 15,),
Row(
mainAxisAlignment: MainAxisAlignment.start,
},
child: SuperTooltip(
controller: tooltipcontroller,
popupDirection: TooltipDirection.down,
backgroundColor: Colors.white,
borderColor: Colors.white,
showCloseButton: true,
left: 50,
right: 30,
barrierColor: Colors.transparent,
arrowTipDistance: 20.0,
minimumOutsideMargin: 120,
arrowBaseWidth: 20.0,
arrowLength: 20.0,
borderWidth: 2.0,
constraints: const BoxConstraints(
minHeight: 0.0,
maxHeight: 100,
minWidth: 0.0,
maxWidth: 100,
),
touchThroughAreaShape: ClipAreaShape.rectangle,
touchThroughAreaCornerRadius: 30,
content: Container(
height: 100,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 50,
padding: EdgeInsets.symmetric(horizontal: 10,vertical: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18),
color: AppColors.text_field_color
),
child: Row(
children: [
Container(
width: 180,
height: 45,
alignment: Alignment.center,
margin: EdgeInsets.only(right: 5.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0)),
child: Text(
'${loginProv.deviceId}',
style: TextStyle(
fontSize: 16,
color: AppColors.semi_black
Text("Device ID",
style: TextStyle(
fontSize: 16,
fontFamily: "JakartaMedium",
color: AppColors.app_blue
),),
SizedBox(height: 15,),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 50,
padding: EdgeInsets.symmetric(horizontal: 10,vertical: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18),
color: AppColors.text_field_color
),
child: Row(
children: [
Container(
width: 180,
height: 45,
alignment: Alignment.center,
margin: EdgeInsets.only(right: 5.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0)),
child: Text(
'${loginProv.deviceId}',
style: TextStyle(
fontSize: 16,
color: AppColors.semi_black
),
)),
Container(
child: InkWell(
onTap: () async {
Clipboard.setData(ClipboardData(text: loginProv.deviceId.trim()));
toast(context, "Device ID has been copied!");
},
child: SvgPicture.asset("assets/svg/copy_ic.svg"),
),
)),
Container(
child: InkWell(
onTap: () async {
Clipboard.setData(ClipboardData(text: loginProv.deviceId.trim()));
toast(context, "Device ID has been copied!");
},
child: Icon(
Icons.copy
),
),
],
),
],
),
),
Spacer(),
Container(
width: 60,
height: 50,
decoration: BoxDecoration(
color: AppColors.app_blue,
borderRadius: BorderRadius.circular(18)
),
child: InkWell(
onTap: () {
Share.share("${loginProv.deviceId}");
},
child: Icon(
Icons.share_outlined,
color: Colors.white,
),
Spacer(),
Container(
width: 60,
height: 50,
decoration: BoxDecoration(
color: AppColors.app_blue,
borderRadius: BorderRadius.circular(18)
),
)),
child: InkWell(
onTap: () {
Share.share("${loginProv.deviceId}");
},
child: SvgPicture.asset("assets/svg/share_ic.svg",height: 25,width: 25,fit: BoxFit.scaleDown,),
)),
],
),
],
),
],
),
),
child: Align(
alignment: Alignment.topRight,
child: Container(
width: 100,
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: AppColors.overlay_box_color,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColors.app_blue, width: 0.5),
),
child: Center(
child: Text(
"Device ID",
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.app_blue,
fontSize: 14,
child: Align(
alignment: Alignment.topRight,
child: Container(
width: 100,
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: AppColors.overlay_box_color,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColors.app_blue, width: 0.5),
),
child: Center(
child: Text(
"Device ID",
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.app_blue,
fontSize: 14,
),
),
),
),
),
......@@ -607,14 +606,14 @@ class _LoginScreenState extends State<LoginScreen>
),
),
),
),
),
],
],
),
),
// bottomNavigationBar: ,
),
),
// bottomNavigationBar: ,
),
);
}
);
}
......
import 'dart:async';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:generp/Utils/commonServices.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_download_manager/flutter_download_manager.dart';
......@@ -9,10 +13,12 @@ import 'package:flutter_svg/svg.dart';
import 'package:generp/Utils/app_colors.dart';
import 'package:generp/Utils/commonWidgets.dart';
import 'package:generp/services/api_calling.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'dart:math';
import 'package:flutter/widgets.dart';
import 'package:url_launcher/url_launcher.dart';
const MAX_PROGRESS = 100;
Future main() async {
......@@ -35,34 +41,57 @@ class _WebErpScreenState extends State<WebErpScreen> {
var empId = "";
var sessionId = "";
bool isLoading = true;
InAppWebViewController? webViewController;
InAppWebViewController? _webViewController;
PullToRefreshController? pullToRefreshController;
PullToRefreshSettings pullToRefreshSettings = PullToRefreshSettings(
color: AppColors.app_blue,
);
bool pullToRefreshEnabled = true;
final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin();
static const platform = MethodChannel('in.webgrid.generp/download');
final GlobalKey webViewKey = GlobalKey();
var dl = DownloadManager();
@override
void initState() {
// loadData();
super.initState();
pullToRefreshController = kIsWeb
? null
: PullToRefreshController(
settings: pullToRefreshSettings,
onRefresh: () async {
if (defaultTargetPlatform == TargetPlatform.android) {
webViewController?.reload();
_webViewController?.reload();
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
webViewController?.loadUrl(
_webViewController?.loadUrl(
urlRequest:
URLRequest(url: await webViewController?.getUrl()));
URLRequest(url: await _webViewController?.getUrl()));
}
},
);
// print("URL:${widget.url}");
super.initState();
_initializeNotifications();
}
Future<void> _initializeNotifications() async {
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/ic_launcher');
final InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
);
await _notificationsPlugin.initialize(initializationSettings);
// Create a notification channel for Android
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'download_channel',
'Downloads',
description: 'Notifications for file downloads',
importance: Importance.high,
);
await _notificationsPlugin
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
}
@override
......@@ -73,8 +102,8 @@ class _WebErpScreenState extends State<WebErpScreen> {
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
if (await webViewController!.canGoBack()) {
webViewController!.goBack();
if (await _webViewController!.canGoBack()) {
_webViewController!.goBack();
return false; // Prevent default back button behavior
}
return true; // Allow default back button behavior
......@@ -90,6 +119,10 @@ class _WebErpScreenState extends State<WebErpScreen> {
InAppWebView(
initialUrlRequest: URLRequest(
url: WebUri(widget.erp_url),
allowsCellularAccess: true,
allowsConstrainedNetworkAccess: true,
allowsExpensiveNetworkAccess: true,
),
androidOnGeolocationPermissionsShowPrompt:
(InAppWebViewController controller, String origin) async {
......@@ -97,7 +130,9 @@ class _WebErpScreenState extends State<WebErpScreen> {
origin: origin, allow: true, retain: true);
},
initialOptions: InAppWebViewGroupOptions(
android: AndroidInAppWebViewOptions(
useWideViewPort: true,
loadWithOverviewMode: true,
allowContentAccess: true,
......@@ -111,10 +146,25 @@ class _WebErpScreenState extends State<WebErpScreen> {
false, // Disables displaying zoom controls
safeBrowsingEnabled: true, // Enables Safe Browsing
clearSessionCache: true,
loadsImagesAutomatically: true,
thirdPartyCookiesEnabled: true,
blockNetworkImage: false,
supportMultipleWindows: true,
// Enable camera access
),
ios: IOSInAppWebViewOptions(
allowsInlineMediaPlayback: true,
),
crossPlatform: InAppWebViewOptions(
javaScriptEnabled: true,
useOnDownloadStart: true,
allowFileAccessFromFileURLs: true,
allowUniversalAccessFromFileURLs: true,
mediaPlaybackRequiresUserGesture: true,
),
),
......@@ -125,8 +175,22 @@ class _WebErpScreenState extends State<WebErpScreen> {
action: PermissionRequestResponseAction.GRANT);
},
onWebViewCreated: (controller) {
webViewController = controller;
_webViewController = controller;
_controller.complete(controller);
_webViewController!.addJavaScriptHandler(
handlerName: 'MobileAppJavascriptInterface',
callback: (args) {
print("JavaScript called MobileAppJavascriptInterface with args: $args");
return {'status': 'success'};
},
);
_webViewController!.addJavaScriptHandler(
handlerName: 'downloadFile',
callback: (args) async {
final url = args[0] as String;
await _handleDownload(url, '', 'application/octet-stream','');
},
);
},
pullToRefreshController: pullToRefreshController,
onLoadStart: (controller, url) {
......@@ -134,6 +198,74 @@ class _WebErpScreenState extends State<WebErpScreen> {
isLoading = true;
});
},
initialSettings: InAppWebViewSettings(
allowUniversalAccessFromFileURLs: true,
allowFileAccessFromFileURLs: true,
allowFileAccess: true,
allowsInlineMediaPlayback: true,
allowsPictureInPictureMediaPlayback: true,
allowsBackForwardNavigationGestures: true,
iframeAllow: "camera;microphone;files;media;",
domStorageEnabled: true,
allowContentAccess: true,
javaScriptEnabled: true,
supportZoom: true,
builtInZoomControls: true,
displayZoomControls: false,
textZoom: 125,
blockNetworkImage: false,
loadsImagesAutomatically: true,
safeBrowsingEnabled: true,
useWideViewPort: true,
loadWithOverviewMode: true,
javaScriptCanOpenWindowsAutomatically: true,
mediaPlaybackRequiresUserGesture: false,
geolocationEnabled: true,
useOnDownloadStart: true,
allowsLinkPreview: true,
databaseEnabled: true, // Enables the WebView database
clearSessionCache: true,
mediaType:"image/*",
),
shouldOverrideUrlLoading:
(controller, navigationAction) async {
var uri = navigationAction.request.url!;
print("urib scgefes");
print(uri);
print(uri.scheme);
if (uri.scheme == "tel") {
// Launch the phone dialer app with the specified phone number
if (await canLaunch(uri.toString())) {
await launch(uri.toString());
return NavigationActionPolicy.CANCEL;
}
} else if (uri.scheme == "mailto") {
if (await canLaunch(uri.toString())) {
await launch(uri.toString());
return NavigationActionPolicy.CANCEL;
}
} else if (uri.scheme == "whatsapp") {
// Launch WhatsApp with the specified chat or phone number
if (await canLaunch(uri.toString())) {
await launch(uri.toString());
return NavigationActionPolicy.CANCEL;
}
}
// // Check if the URL is trying to access the camera for image upload
// if (uri.scheme == 'camera' && uri.path.contains('/camera/')) {
// // Handle camera image upload here
// // You might want to display a custom UI for image selection or directly trigger the camera
// // You can use platform-specific plugins like image_picker for this purpose
// // Once the image is selected, you can pass it to the web view using JavaScript injection
// if (await canLaunch(uri.toString())) {
// await launch(uri.toString());
// return NavigationActionPolicy.CANCEL;
// }
// }
return NavigationActionPolicy.ALLOW;
},
onLoadStop: (controller, url) {
pullToRefreshController?.endRefreshing();
return setState(() {
......@@ -155,12 +287,28 @@ class _WebErpScreenState extends State<WebErpScreen> {
debugPrint(
"JavaScript console message: ${consoleMessage.message}");
},
onDownloadStartRequest: (controller, url) async {
await ApiCalling.download_files(
empId, sessionId, "${url.url}", context)
.then((data) => {debugPrint(data)});
// onDownloadStartRequest: (controller, url) async {
// await ApiCalling.download_files(
// empId, sessionId, "${url.url}", context)
// .then((data) => {debugPrint(data)});
//
// },
onDownloadStartRequest: (controller, downloadStartRequest) async {
await _handleDownload(
downloadStartRequest.url.toString(),
downloadStartRequest.suggestedFilename!,
downloadStartRequest.mimeType ?? 'application/octet-stream',
downloadStartRequest.suggestedFilename ?? '',
);
},
shouldInterceptAjaxRequest: (controller, ajaxRequest) async {
if (ajaxRequest.url.toString().contains('download')) {
await _handleDownload(ajaxRequest.url.toString(), '', 'application/octet-stream','');
return ajaxRequest;
}
return ajaxRequest;
},
),
if (isLoading) ...[Container(
color: Colors.white.withOpacity(0.7),
......@@ -200,6 +348,32 @@ class _WebErpScreenState extends State<WebErpScreen> {
),
);
}
Future<void> _handleDownload(String url, String contentDisposition, String mimeType,String suggestedFilename) async {
// Request notification permission for Android 13+
if (await Permission.notification.request().isGranted) {
try {
// Show custom notification (optional, since DownloadManager shows its own)
// Call native Android Download Manager
final userAgent = 'Flutter InAppWebView';
await platform.invokeMethod('startDownload', {
'url': url,
'userAgent': userAgent,
'contentDisposition': contentDisposition,
'mimeType': mimeType,
'suggestedFilename': suggestedFilename,
});
} catch (e) {
print("Download Error $e");
}
} else {
toast(context, "Notification Permission Denied");
}
}
}
......
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:generp/Notifiers/financeProvider/RequestionListProvider.dart';
import 'package:generp/Utils/app_colors.dart';
import 'package:generp/Utils/commonWidgets.dart';
import 'package:generp/screens/finance/FileViewer.dart';
import 'package:provider/provider.dart';
import 'PaymentRequestionListDetails.dart';
class Allpaymentrequesitionlistsbymodes extends StatefulWidget {
final String mode;
final String pageTitleName;
const Allpaymentrequesitionlistsbymodes({
super.key,
required this.mode,
required this.pageTitleName,
});
@override
State<Allpaymentrequesitionlistsbymodes> createState() =>
_AllpaymentrequesitionlistsbymodesState();
}
class _AllpaymentrequesitionlistsbymodesState
extends State<Allpaymentrequesitionlistsbymodes> {
@override
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
var provider = Provider.of<Requestionlistprovider>(
context,
listen: false,
);
provider.paymentRequestionListsAPIFunction(context, widget.mode);
});
}
@override
Widget build(BuildContext context) {
return Consumer<Requestionlistprovider>(
builder: (context, provider, child) {
final requestLists = provider.requisitionList;
return WillPopScope(
onWillPop: () {
return onBackPressed(context);
},
child: Scaffold(
appBar: appbar2(
context,
widget.pageTitleName,
Row(
children: [
InkResponse(
onTap: () {
_showOptionsSheet(context);
},
child: Icon(CupertinoIcons.down_arrow),
),
],
),
),
backgroundColor: AppColors.scaffold_bg_color,
body: Container(
child: SingleChildScrollView(
child: Column(
children: [
ListView.builder(
itemCount: requestLists.length,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
margin: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
children: [
Row(
children: [
Expanded(
flex: 1,
child: Container(
height: 50,
width: 35,
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Color(0xFFFFF3CE),
borderRadius: BorderRadius.circular(8),
),
child: SvgPicture.asset(
"assets/svg/fin_ic.svg",
),
),
),
SizedBox(width: 10),
Expanded(
flex: 4,
child: SizedBox(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
requestLists[index].accountName!,
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.semi_black,
),
),
Text(
"₹"
"${requestLists[index].amount}",
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.app_blue,
),
),
],
),
),
),
Expanded(
flex: 2,
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 5,
vertical: 10,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Color(0xFFE3FFE0),
),
child: Center(
child: Text(
requestLists[index].status!,
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: Color(0xFF0D9C00),
),
),
),
),
),
],
),
Divider(thickness: 0.5, color: Color(0xFFD7D7D7)),
...List.generate(4, (j) {
final headings = [
"Requesting Propose",
"Attachment",
"Requested Date",
"Note",
];
final subHeadings = [
requestLists[index].requestingPurpose,
"View",
// requestLists[index].attachmentDirFilePath
requestLists[index].date,
requestLists[index].description,
];
return Container(
padding: EdgeInsets.symmetric(vertical: 5),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
headings[j],
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.semi_black,
),
),
),
Expanded(
child: InkResponse(
onTap:
j != 1
? null
: () {
Navigator.push(
context,
MaterialPageRoute(
builder:
(
context,
) => Fileviewer(
fileName:
requestLists[index]
.attachmentViewFileName!,
fileUrl:
requestLists[index]
.attachmentDirFilePath!,
),
),
);
},
child: Text(
subHeadings[j]!,
style: TextStyle(
fontSize: 14,
color:
j == 1
? AppColors.app_blue
: Color(0xFF818181),
decoration:
j == 1
? TextDecoration.underline
: TextDecoration.none,
decorationColor:
j == 1
? AppColors.app_blue
: AppColors.white,
),
),
),
),
],
),
);
}),
InkResponse(
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(
builder:
(context) =>
Paymentrequestionlistdetails(
pageName: widget.pageTitleName,
mode:widget.mode,
paymentRequestId:
requestLists[index].id,
),
),
);
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 5),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"View Details",
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.app_blue,
),
),
SizedBox(width: 5),
SvgPicture.asset(
"assets/svg/next_button.svg",
),
],
),
),
),
],
),
);
},
),
],
),
),
),
),
);
},
);
}
Future<void> _showOptionsSheet(BuildContext context) {
return showModalBottomSheet(
useSafeArea: true,
isDismissible: true,
isScrollControlled: true,
showDragHandle: true,
backgroundColor: Colors.white,
enableDrag: true,
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return SafeArea(
child: Consumer<Requestionlistprovider>(
builder: (context, provider, child) {
return Container(
margin: EdgeInsets.only(
bottom: 15,
left: 15,
right: 15,
top: 10,
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 15),
...List.generate(5, (index) {
final assetnames = [
"se_locate_customer",
"se_locate_customer",
"se_update_complaint",
"se_payment_details",
"se_payment_details",
];
final Headingnames = [
"Copy to Clipboard",
"Download CSV",
"Download XLSX",
"Download PDF",
"Print Data",
];
return ListTile(
onTap: () {
switch (index) {
case 0:
provider.copyToClipboard(context);
break;
case 1:
provider.downloadCSV(context);
break;
case 2:
provider.downloadXLS(context);
break;
case 3:
provider.downloadPDF(context);
break;
case 4:
provider.printData(context);
break;
}
},
leading: SvgPicture.asset(
"assets/svg/${assetnames[index]}.svg",
),
title: Text(
Headingnames[index],
style: TextStyle(fontFamily: "JakartaMedium"),
),
trailing: SvgPicture.asset(
"assets/svg/arrow_right_new.svg",
),
);
}),
],
),
),
);
},
),
);
},
);
},
);
}
}
import 'dart:async';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:generp/Utils/commonWidgets.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart';
import 'package:http/http.dart' as http;
import 'dart:typed_data';
import '../../Utils/app_colors.dart';
class Fileviewer extends StatefulWidget {
final String fileName;
final String fileUrl;
const Fileviewer({super.key,required this.fileName,required this.fileUrl});
@override
State<Fileviewer> createState() => _FileviewerState();
}
class _FileviewerState extends State<Fileviewer> {
final Completer<InAppWebViewController> _controller =
Completer<InAppWebViewController>();
var empId = "";
var sessionId = "";
bool isLoading = true;
InAppWebViewController? webViewController;
PullToRefreshController? pullToRefreshController;
PullToRefreshSettings pullToRefreshSettings = PullToRefreshSettings(
color: AppColors.app_blue,
);
bool pullToRefreshEnabled = true;
final GlobalKey webViewKey = GlobalKey();
String getFileExtension(String fileName) {
print(widget.fileUrl);
return fileName.split('.').last.toLowerCase();
}
Future<void> _launchUrl(String url) async {
final Uri uri = Uri.parse(url);
if (await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication);
} else {
throw 'Could not launch $url';
}
}
var Finalurl;
@override
void initState() {
// loadData();
pullToRefreshController = kIsWeb
? null
: PullToRefreshController(
settings: pullToRefreshSettings,
onRefresh: () async {
if (defaultTargetPlatform == TargetPlatform.android) {
webViewController?.reload();
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
webViewController?.loadUrl(
urlRequest:
URLRequest(url: await webViewController?.getUrl()));
}
},
);
// print("URL:${widget.url}");
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: appbar(context, "File Viewer"),
body: fileWidget(context),
);
}
Widget fileWidget(BuildContext context){
final extension = getFileExtension(widget.fileName);
switch (extension) {
case 'jpg':
case 'jpeg':
case 'png':
case 'gif':
return CachedNetworkImage(
imageUrl: widget.fileUrl,
placeholder: (context, url) => const Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) => const Icon(Icons.error),
fit: BoxFit.contain,
);
case 'pdf':
return SfPdfViewer.network(
widget.fileUrl,
key: GlobalKey(),
);
case 'doc':
case 'docx':
case 'xls':
case 'xlsx':
return InAppWebView(
initialUrlRequest: URLRequest(
url: WebUri(widget.fileUrl),
),
androidOnGeolocationPermissionsShowPrompt:
(InAppWebViewController controller, String origin) async {
return GeolocationPermissionShowPromptResponse(
origin: origin, allow: true, retain: true);
},
initialOptions: InAppWebViewGroupOptions(
android: AndroidInAppWebViewOptions(
useWideViewPort: true,
loadWithOverviewMode: true,
allowContentAccess: true,
geolocationEnabled: true,
allowFileAccess: true,
databaseEnabled: true, // Enables the WebView database
domStorageEnabled: true, // Enables DOM storage
builtInZoomControls:
true, // Enables the built-in zoom controls
displayZoomControls:
false, // Disables displaying zoom controls
safeBrowsingEnabled: true, // Enables Safe Browsing
clearSessionCache: true,
),
ios: IOSInAppWebViewOptions(
allowsInlineMediaPlayback: true,
),
),
androidOnPermissionRequest: (InAppWebViewController controller,
String origin, List<String> resources) async {
return PermissionRequestResponse(
resources: resources,
action: PermissionRequestResponseAction.GRANT);
},
onWebViewCreated: (controller) {
webViewController = controller;
_controller.complete(controller);
},
pullToRefreshController: pullToRefreshController,
onLoadStart: (controller, url) {
return setState(() {
isLoading = true;
});
},
onLoadStop: (controller, url) {
pullToRefreshController?.endRefreshing();
return setState(() {
isLoading = false;
});
},
onReceivedError: (controller, request, error) {
pullToRefreshController?.endRefreshing();
},
onProgressChanged: (controller, progress) {
if (progress == 100) {
pullToRefreshController?.endRefreshing();
}
},
onConsoleMessage: (controller, consoleMessage) {
if (kDebugMode) {
debugPrint("consoleMessage${consoleMessage}");
}
debugPrint(
"JavaScript console message: ${consoleMessage.message}");
},
);
default:
return Container();
}
}
Future<Uint8List?> _loadPdf(String url) async {
try {
final response = await http.get(Uri.parse(url));
if(response!=null){
if (response.statusCode == 200) {
print(response.bodyBytes);
return response.bodyBytes;
}
}
} catch (e) {
print('Error loading PDF: $e');
}
return null;
}
}
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:generp/Notifiers/financeProvider/RequesitionLidtDetailsProvider.dart';
import 'package:generp/Notifiers/financeProvider/approveRejectPaymentRequestResponse.dart';
import 'package:generp/Utils/app_colors.dart';
import 'package:generp/Utils/commonWidgets.dart';
import 'package:provider/provider.dart';
import 'FileViewer.dart';
class Paymentrequestionlistdetails extends StatefulWidget {
final paymentRequestId;
final pageName;
final mode;
const Paymentrequestionlistdetails({
super.key,
required this.mode,
required this.paymentRequestId,
required this.pageName,
});
@override
State<Paymentrequestionlistdetails> createState() =>
_PaymentrequestionlistdetailsState();
}
class _PaymentrequestionlistdetailsState
extends State<Paymentrequestionlistdetails> {
TextEditingController requestedAmount = TextEditingController();
TextEditingController approvedAmount = TextEditingController();
TextEditingController remarks = TextEditingController();
FocusNode request = FocusNode();
FocusNode approve = FocusNode();
FocusNode remarkNode = FocusNode();
@override
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
var provider = Provider.of<Requesitionlidtdetailsprovider>(
context,
listen: false,
);
provider.paymentRequesitionDetails(context, widget.paymentRequestId);
});
}
@override
Widget build(BuildContext context) {
return Consumer<Requesitionlidtdetailsprovider>(
builder: (context, provider, child) {
var payment_det = provider.paymentsDetails;
var req_det = provider.requestsDetails;
return WillPopScope(
child: Scaffold(
appBar: appbar(context, widget.pageName),
backgroundColor: AppColors.scaffold_bg_color,
body: Container(
child: SingleChildScrollView(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
margin: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
child: Column(
children: [
Row(
children: [
Expanded(
flex: 1,
child: Container(
height: 50,
width: 35,
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Color(0xFFFFF3CE),
borderRadius: BorderRadius.circular(8),
),
child: SvgPicture.asset("assets/svg/fin_ic.svg"),
),
),
SizedBox(width: 10),
Expanded(
flex: 4,
child: SizedBox(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
req_det.accountName!,
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.semi_black,
),
),
Text(
"₹"
"${req_det.amount}",
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.app_blue,
),
),
],
),
),
),
Expanded(
flex: 2,
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 5,
vertical: 10,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Color(0xFFE3FFE0),
),
child: Center(
child: Text(
req_det.status!,
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: Color(0xFF0D9C00),
),
),
),
),
),
],
),
Divider(thickness: 0.5, color: Color(0xFFD7D7D7)),
...List.generate(provider.subHeadings.length, (j) {
return Container(
padding: EdgeInsets.symmetric(vertical: 7),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
provider.Headings[j],
style: TextStyle(
fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.semi_black,
),
),
),
Expanded(
child: InkResponse(
onTap: () {
if (provider.Headings[j] == "Attachment") {
Navigator.push(
context,
MaterialPageRoute(
builder:
(context) =>
Fileviewer(
fileName:
req_det
.attachmentViewFileName!,
fileUrl:
req_det
.attachmentDirFilePath!,
),
),
);
}
},
child: Text(
provider.Headings[j] == "Attachment"
? "View"
: "${provider.subHeadings[j]}",
style: TextStyle(
fontSize: 14,
color:
provider.Headings[j] == "Attachment"
? AppColors.app_blue
: Color(0xFF818181),
decoration:
provider.Headings[j] == "Attachment"
? TextDecoration.underline
: TextDecoration.none,
decorationColor:
provider.Headings[j] == "Attachment"
? AppColors.app_blue
: AppColors.white,
),
),
),
),
],
),
);
}),
],
),
),
),
),
bottomNavigationBar:
(["admin", "self"].contains(widget.mode))
? Container(height: 0)
: Container(
margin: EdgeInsets.symmetric(horizontal: 10),
alignment: Alignment.bottomCenter,
height: 60,
child: Container(
margin: EdgeInsets.only(bottom: 10),
alignment: Alignment.center,
height: 45,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: InkResponse(
onTap: () {
_showLevelRejectionSheet(context);
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Color(0xFFFFEFEF),
border: Border.all(
color: Color(0xFFED3424),
width: 0.5,
),
),
child: Center(
child: Text(
"Reject",
style: TextStyle(color: Color(0xFFED3424)),
),
),
),
),
),
SizedBox(width: 10),
if ([
"apr_lvl1",
"apr_lvl2",
].contains(widget.mode)) ...[
Expanded(
child: InkResponse(
onTap: () {
provider.approveRejectPaymentRequestAPIFunction(
context, provider.requestsDetails.id);
_showLevelApprovalSheet(context);
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Color(0xFFE7FFE5),
border: Border.all(
color: Color(0xFF0D9C00),
width: 0.5,
),
),
child: Center(
child: Text(
"Approve",
style: TextStyle(
color: Color(0xFF0D9C00),
),
),
),
),
),
),
] else
if (widget.mode == "process") ...[
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Color(0xFFE7FFE5),
border: Border.all(
color: Color(0xFF0D9C00),
width: 0.5,
),
),
child: Center(
child: Text(
"Add Payment",
style: TextStyle(
color: Color(0xFF0D9C00),
),
),
),
),
),
],
],
),
),
),
),
onWillPop: () {
return onBackPressed(context);
},
);
},
);
}
Future<void> _showLevelApprovalSheet(BuildContext context) {
return showModalBottomSheet(
useSafeArea: true,
isDismissible: true,
isScrollControlled: true,
showDragHandle: true,
backgroundColor: Colors.white,
enableDrag: true,
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return SafeArea(
child: Consumer<Requesitionlidtdetailsprovider>(
builder: (context, provider, child) {
return Container(
margin: EdgeInsets.only(
bottom: 15,
left: 15,
right: 15,
top: 10,
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Align(
alignment: Alignment.topLeft,
child: Text(
"Level 1 Approval",
style: TextStyle(
color: AppColors.app_blue,
fontSize: 16
),
),
),
textControllerWidget(
context,
requestedAmount,
"Enter Requested Amount",
(p0) {},
),
textControllerWidget(
context,
approvedAmount,
"Enter Approved Amount",
(p0) {},
),
textControllerWidget(
context,
remarks,
"Enter Remarks",
(p0) {},
),
TextWidget(context, "Proposed Payment Account"),
DropdownButtonHideUnderline(
child: Row(
children: [
Expanded(
child: DropdownButton2<PaymentAccounts>(
isExpanded: true,
hint: Text(
'Select Payment mode',
style: TextStyle(fontSize: 14),
overflow: TextOverflow.ellipsis,
),
items:
provider.paymentsAccounts
.map(
(paymenents) =>
DropdownMenuItem<PaymentAccounts>(
value: paymenents,
child: Text(
paymenents.name ?? '',
style: const TextStyle(
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
),
),
)
.toList(),
value: provider.selectedPaymentAccounts,
onChanged: (PaymentAccounts? value) {
if (value != null) {
if (provider.paymentsAccounts
.isNotEmpty) {
provider.selectedPaymentAccounts =
value;
print(
"Selected Complaint Type: ${value
.name}, ID: ${value.id}",
);
provider.selectedID = value.id!;
provider.selectedValue = value.name!;
print(
"hfjkshfg" +
provider.selectedID.toString(),
);
}
}
},
buttonStyleData: ButtonStyleData(
height: 50,
width: 160,
padding: const EdgeInsets.only(
left: 14,
right: 14,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: AppColors.text_field_color,
),
),
iconStyleData: const IconStyleData(
icon: Icon(Icons.keyboard_arrow_down),
iconSize: 12,
iconEnabledColor: Color(0xFF2D2D2D),
iconDisabledColor: Colors.grey,
),
dropdownStyleData: DropdownStyleData(
maxHeight: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: AppColors.text_field_color,
),
scrollbarTheme: ScrollbarThemeData(
radius: const Radius.circular(15),
thickness: MaterialStateProperty.all<
double>(
6,
),
thumbVisibility:
MaterialStateProperty.all<bool>(true),
),
),
menuItemStyleData: const MenuItemStyleData(
height: 40,
padding: EdgeInsets.only(
left: 14, right: 14),
),
),
),
],
),
),
InkWell(
onTap: () {
provider
.paymentrequisitionApproveSubmitAPIFunction(
context, widget.mode,
provider.paymentsReqDetails.id,
approvedAmount.text, remarks.text,
provider.selectedID);
},
child: Container(
alignment: Alignment.center,
height: 45,
margin: EdgeInsets.only(
left: 5.0,
right: 5.0,
top: 5.0,
bottom: 5.0,
),
decoration: BoxDecoration(
color: AppColors.app_blue, //1487C9
borderRadius: BorderRadius.circular(30.0),
),
child: Center(
child: Text(
"Submit",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
),
),
],
),
),
);
},
),
);
},
);
},
);
}
Future<void> _showLevelRejectionSheet(BuildContext context) {
return showModalBottomSheet(
useSafeArea: true,
isDismissible: true,
isScrollControlled: true,
showDragHandle: true,
backgroundColor: Colors.white,
enableDrag: true,
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return SafeArea(
child: Consumer<Requesitionlidtdetailsprovider>(
builder: (context, provider, child) {
return Container(
margin: EdgeInsets.only(
bottom: 15,
left: 15,
right: 15,
top: 10,
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Align(
alignment: Alignment.topLeft,
child: Text(
"Level 1 Rejection",
style: TextStyle(
color: AppColors.app_blue,
fontSize: 16
),
),
),
textControllerWidget(
context,
requestedAmount,
"Enter Requested Amount",
(p0) {},
),
textControllerWidget(
context,
remarks,
"Enter Remarks",
(p0) {},
),
InkWell(
onTap: () {
provider
.paymentrequisitionRejectSubmitAPIFunction(
context, widget.mode,
provider.paymentsReqDetails.id, remarks.text);
},
child: Container(
alignment: Alignment.center,
height: 45,
margin: EdgeInsets.only(
left: 5.0,
right: 5.0,
top: 5.0,
bottom: 5.0,
),
decoration: BoxDecoration(
color: AppColors.app_blue, //1487C9
borderRadius: BorderRadius.circular(30.0),
),
child: Center(
child: Text(
"Submit",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
),
),
],
),
),
);
},
),
);
},
);
},
);
}
Widget TextWidget(context, text) {
return Padding(
padding: const EdgeInsets.only(bottom: 5.0, top: 8.0),
child: Text(text),
);
}
Widget ErrorWidget(context, text) {
if (text != null)
return Text(text!, style: TextStyle(color: Colors.red, fontSize: 12));
else
return SizedBox(height: 10);
}
Widget textControllerWidget(context,
controller,
hintText,
Function(String)? onChanged,) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 5.0, top: 8.0),
child: Text(hintText),
),
Container(
height: hintText == "Enter Description" ? 150 : 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: AppColors.text_field_color,
borderRadius: BorderRadius.circular(14),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10, 0),
child: TextFormField(
controller: controller,
keyboardType: TextInputType.text,
maxLines: hintText == "Enter Description" ? 60 : 1,
onChanged: onChanged,
decoration: InputDecoration(
hintText: hintText,
hintStyle: TextStyle(
fontWeight: FontWeight.w400,
color: Color(0xFFB4BEC0),
fontSize: 14,
),
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
),
),
),
),
],
);
}
}
import 'package:flutter/material.dart';
class Directpaymentrequesitionlist extends StatefulWidget {
const Directpaymentrequesitionlist({super.key});
@override
State<Directpaymentrequesitionlist> createState() => _DirectpaymentrequesitionlistState();
}
class _DirectpaymentrequesitionlistState extends State<Directpaymentrequesitionlist> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
......@@ -3,7 +3,9 @@ import 'package:flutter_svg/svg.dart';
import 'package:generp/Notifiers/financeProvider/DashboardProvider.dart';
import 'package:generp/Utils/app_colors.dart';
import 'package:generp/Utils/commonWidgets.dart';
import 'package:generp/screens/finance/paymentRequestionListsByMode.dart';
import 'package:generp/screens/finance/AllPaymentRequesitionListsByModes.dart';
import 'package:generp/screens/finance/directPaymentRequesitionList.dart';
import 'package:generp/screens/finance/submitPaymentRequestionListsByMode.dart';
import 'package:provider/provider.dart';
class Financedashboard extends StatefulWidget {
......@@ -61,35 +63,44 @@ class _FinancedashboardState extends State<Financedashboard> {
SvgIcon = SvgPicture.asset("assets/svg/fin_ic.svg");
break;
}
return Container(
margin: EdgeInsets.symmetric(
horizontal: 5,
vertical: 5,
),
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 15,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(14),
),
child: Row(
children: [
Expanded(flex: 1, child: SvgIcon),
Expanded(
flex: 5,
child: Text(
"${provider.accessiblePagesList[index].pageName}",
return InkResponse(
onTap: () async {
await Navigator.push(context, MaterialPageRoute(
builder: (context) =>
Allpaymentrequesitionlistsbymodes(mode: provider.accessiblePagesList[index].mode!,
pageTitleName: provider.accessiblePagesList[index].pageName!),));
},
child: Container(
margin: EdgeInsets.symmetric(
horizontal: 5,
vertical: 5,
),
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 15,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(14),
),
child: Row(
children: [
Expanded(flex: 1, child: SvgIcon),
Expanded(
flex: 5,
child: Text(
"${provider.accessiblePagesList[index]
.pageName}",
),
),
),
Expanded(
flex: 1,
child: SvgPicture.asset(
"assets/svg/arrow_right_new.svg",
Expanded(
flex: 1,
child: SvgPicture.asset(
"assets/svg/arrow_right_new.svg",
),
),
),
],
],
),
),
);
},
......@@ -99,7 +110,7 @@ class _FinancedashboardState extends State<Financedashboard> {
),
),
floatingActionButtonLocation:
FloatingActionButtonLocation.centerFloat,
FloatingActionButtonLocation.centerFloat,
floatingActionButton: InkResponse(
onTap: () {
_showPaymentOptionsSheet(context);
......@@ -158,7 +169,8 @@ class _FinancedashboardState extends State<Financedashboard> {
children: [
SizedBox(height: 15),
...List.generate(provider.accessiblePagesList2.length, (index) {
...List.generate(
provider.accessiblePagesList2.length, (index) {
print(provider.accessiblePagesList2[index].mode);
List<String> mode_lst = [
"self",
......@@ -175,25 +187,38 @@ class _FinancedashboardState extends State<Financedashboard> {
"Add Direct Payment",
];
return ListTile(
onTap: () {
onTap: () async {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder:
(context) =>
Paymentrequestionlistsbymode(
mode: "${provider.accessiblePagesList2[index].mode}",
pageTitleName: "${provider.accessiblePagesList2[index].pageName}",
),
),
);
var res;
if (provider.accessiblePagesList2[index]
.pageName == "Add Direct Payment") {
res = await Navigator.push(context,
MaterialPageRoute(builder: (context) =>
Directpaymentrequesitionlist(),));
} else {
res = await Navigator.push(
context,
MaterialPageRoute(
builder:
(context) =>
Submitpaymentrequestionlistsbymode(
mode: "${provider
.accessiblePagesList2[index]
.mode}",
pageTitleName: "${provider
.accessiblePagesList2[index]
.pageName}",
),
),
);
}
},
leading: SvgPicture.asset(
"assets/svg/fin_ic.svg",
),
title: Text(
"${provider.accessiblePagesList2[index].pageName}",
"${provider.accessiblePagesList2[index]
.pageName}",
style: TextStyle(
fontSize: 14,
fontFamily: "JakartaMedium",
......
......@@ -7,19 +7,19 @@ import 'package:provider/provider.dart';
import '../../Models/financeModels/addPaymentRequestionResponse.dart';
class Paymentrequestionlistsbymode extends StatefulWidget {
class Submitpaymentrequestionlistsbymode extends StatefulWidget {
final String mode;
final String pageTitleName;
const Paymentrequestionlistsbymode({super.key, required this.mode,required this.pageTitleName});
const Submitpaymentrequestionlistsbymode({super.key, required this.mode,required this.pageTitleName});
@override
State<Paymentrequestionlistsbymode> createState() =>
_PaymentrequestionlistsbymodeState();
State<Submitpaymentrequestionlistsbymode> createState() =>
_SubmitpaymentrequestionlistsbymodeState();
}
class _PaymentrequestionlistsbymodeState
extends State<Paymentrequestionlistsbymode> {
class _SubmitpaymentrequestionlistsbymodeState
extends State<Submitpaymentrequestionlistsbymode> {
@override
void initState() {
// TODO: implement initState
......
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter/services.dart';
class WebViewPage extends StatefulWidget {
final erp_url;
const WebViewPage({super.key, this.erp_url});
@override
_WebViewPageState createState() => _WebViewPageState();
}
class _WebViewPageState extends State<WebViewPage> {
InAppWebViewController? _webViewController;
final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin();
static const platform = MethodChannel('in.webgrid.generp/download');
@override
void initState() {
super.initState();
_initializeNotifications();
}
// Initialize notifications
Future<void> _initializeNotifications() async {
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/ic_launcher');
final InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
);
await _notificationsPlugin.initialize(initializationSettings);
// Create a notification channel for Android
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'download_channel',
'Downloads',
description: 'Notifications for file downloads',
importance: Importance.high,
);
await _notificationsPlugin
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("CRM WebView")),
body: InAppWebView(
initialUrlRequest: URLRequest(url: WebUri(widget.erp_url)),
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
domStorageEnabled: true,
allowFileAccess: true,
allowContentAccess: true,
useShouldInterceptAjaxRequest: true,
),
onWebViewCreated: (controller) {
_webViewController = controller;
_webViewController!.addJavaScriptHandler(
handlerName: 'MobileAppJavascriptInterface',
callback: (args) {
print("JavaScript called MobileAppJavascriptInterface with args: $args");
return {'status': 'success'};
},
);
_webViewController!.addJavaScriptHandler(
handlerName: 'downloadFile',
callback: (args) async {
final url = args[0] as String;
await _handleDownload(url, '', 'application/octet-stream');
},
);
},
onDownloadStartRequest: (controller, downloadStartRequest) async {
await _handleDownload(
downloadStartRequest.url.toString(),
downloadStartRequest.suggestedFilename!,
downloadStartRequest.mimeType ?? 'application/octet-stream',
);
},
shouldInterceptAjaxRequest: (controller, ajaxRequest) async {
if (ajaxRequest.url.toString().contains('download')) {
await _handleDownload(ajaxRequest.url.toString(), '', 'application/octet-stream');
return ajaxRequest;
}
return ajaxRequest;
},
onConsoleMessage: (controller, consoleMessage) {
print("JavaScript console message: ${consoleMessage.message}");
},
),
);
}
Future<void> _handleDownload(String url, String contentDisposition, String mimeType) async {
// Request notification permission for Android 13+
if (await Permission.notification.request().isGranted) {
try {
// Show custom notification (optional, since DownloadManager shows its own)
await _showNotification(
id: 1,
title: 'Download Started',
body: 'Downloading ${url.split('/').last}',
);
// Call native Android Download Manager
final userAgent = 'Flutter InAppWebView';
await platform.invokeMethod('startDownload', {
'url': url,
'userAgent': userAgent,
'contentDisposition': contentDisposition,
'mimeType': mimeType,
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Download started for ${url.split('/').last}")),
);
} catch (e) {
await _showNotification(
id: 1,
title: 'Download Error',
body: 'Error: $e',
);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Download error: $e")),
);
}
} else {
await _showNotification(
id: 1,
title: 'Permission Denied',
body: 'Notification permission denied',
);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Notification permission denied")),
);
}
}
Future<void> _showNotification({
required int id,
required String title,
required String body,
}) async {
final AndroidNotificationDetails androidPlatformChannelSpecifics = AndroidNotificationDetails(
'download_channel',
'Downloads',
channelDescription: 'Notifications for file downloads',
importance: Importance.high,
priority: Priority.high,
onlyAlertOnce: true,
);
final NotificationDetails platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
);
await _notificationsPlugin.show(
id,
title,
body,
platformChannelSpecifics,
);
}
}
\ No newline at end of file
......@@ -38,9 +38,12 @@ import '../Models/UpdatePasswordResponse.dart';
import '../Models/VersionsResponse.dart';
import '../Models/ViewVisitDetailsResponse.dart';
import '../Models/financeModels/addPaymentRequestionResponse.dart';
import '../Models/financeModels/paymentRequesitionListsResponse.dart';
import '../Models/financeModels/paymentRequisitionDetailsResponse.dart';
import '../Models/generatorComplaintResponse.dart';
import '../Models/loadGeneratorDetailsResponse.dart';
import '../Models/financeModels/financeDashboardPagesResponse.dart';
import '../Notifiers/financeProvider/approveRejectPaymentRequestResponse.dart';
import '../Utils/commonServices.dart';
class ApiCalling {
......@@ -1131,10 +1134,8 @@ class ApiCalling {
}
}
static Future<financeDashboardPagesResponse?> addFormfinanceFormAccessPagesAPI(
empId,
session,
) async {
static Future<financeDashboardPagesResponse?>
addFormfinanceFormAccessPagesAPI(empId, session) async {
try {
Map<String, String> data = {
'emp_id': (empId).toString(),
......@@ -1194,7 +1195,7 @@ class ApiCalling {
bank_ifsc_code,
acc_holder_name,
bank_upi_id,
attachment
attachment,
) async {
try {
Map<String, String> data = {
......@@ -1216,14 +1217,19 @@ class ApiCalling {
var res;
if (attachment != null) {
res = await postImageNew(data, {}, addPaymentRequestionSubmitUrl, attachment,"attachment");
res = await postImageNew(
data,
{},
addPaymentRequestionSubmitUrl,
attachment,
"attachment",
);
res = jsonDecode(res);
} else {
res = await post(data, addPaymentRequestionSubmitUrl, {});
res = jsonDecode(res);
}
if (res != null) {
return res;
} else {
debugPrint("Null Response");
......@@ -1234,4 +1240,193 @@ class ApiCalling {
return null;
}
}
static Future<paymentRequesitionListsResponse?> paymentRequestionListsAPI(
empId,
session,
mode,
) async {
try {
Map<String, String> data = {
'emp_id': (empId).toString(),
'session_id': (session).toString(),
'mode': (mode).toString(),
};
final res = await post(data, paymentRequestionListUrl, {});
if (res != null) {
debugPrint(res.body);
return paymentRequesitionListsResponse.fromJson(jsonDecode(res.body));
} else {
debugPrint("Null Response");
return null;
}
} catch (e) {
debugPrint('hello bev=bug $e ');
return null;
}
}
static Future<paymentRequisitionDetailsResponse?> paymentRequestionDetailsAPI(
empId,
session,
payment_request_id,
) async {
try {
Map<String, String> data = {
'emp_id': (empId).toString(),
'session_id': (session).toString(),
'payment_request_id': (payment_request_id).toString(),
};
final res = await post(data, paymentRequestionDetailsUrl, {});
if (res != null) {
debugPrint(res.body);
return paymentRequisitionDetailsResponse.fromJson(jsonDecode(res.body));
} else {
debugPrint("Null Response");
return null;
}
} catch (e) {
debugPrint('hello bev=bug $e ');
return null;
}
}
static Future<approveRejectPaymentRequestResponse?> approveRejectPaymentRequestAPI(
empId,
session,
payment_request_id,
) async {
try {
Map<String, String> data = {
'emp_id': (empId).toString(),
'session_id': (session).toString(),
'payment_request_id': (payment_request_id).toString(),
};
final res = await post(data, approveRejectPaymentRequestUrl, {});
if (res != null) {
debugPrint(res.body);
return approveRejectPaymentRequestResponse.fromJson(jsonDecode(res.body));
} else {
debugPrint("Null Response");
return null;
}
} catch (e) {
debugPrint('hello bev=bug $e ');
return null;
}
}
static Future<approveRejectPaymentRequestResponse?> RejectPaymentRequestSubmitAPI(
empId,
session,
mode,
payment_request_id,
approve_remarks,
) async {
try {
Map<String, String> data = {
'emp_id': (empId).toString(),
'session_id': (session).toString(),
'type':'reject',
'mode':mode.toString(),
'payment_request_id': (payment_request_id).toString(),
'approve_remarks':approve_remarks,
};
final res = await post(data, approveRejectPaymentRequestSubmitUrl, {});
if (res != null) {
debugPrint(res.body);
return approveRejectPaymentRequestResponse.fromJson(jsonDecode(res.body));
} else {
debugPrint("Null Response");
return null;
}
} catch (e) {
debugPrint('hello bev=bug $e ');
return null;
}
}
static Future<approveRejectPaymentRequestResponse?> ApprovePaymentRequestSubmitAPI(
empId,
session,
mode,
payment_request_id,
approved_amount,
approve_remarks,
proposed_payment_account_id,
) async {
try {
Map<String, String> data = {
'emp_id': (empId).toString(),
'session_id': (session).toString(),
'type':'approve',
'mode':mode.toString(),
'payment_request_id': (payment_request_id).toString(),
'approve_remarks':approve_remarks,
'proposed_payment_account_id':proposed_payment_account_id,
};
final res = await post(data, approveRejectPaymentRequestSubmitUrl, {});
if (res != null) {
debugPrint(res.body);
return approveRejectPaymentRequestResponse.fromJson(jsonDecode(res.body));
} else {
debugPrint("Null Response");
return null;
}
} catch (e) {
debugPrint('hello bev=bug $e ');
return null;
}
}
static Future<approveRejectPaymentRequestResponse?> processApproveRejectPaymentRequestSubmitAPI(
empId,
session,
mode,
payment_request_id,
approved_amount,
approve_remarks,
proposed_payment_account_id,
payment_account_id,
processing_remarks,
attachment
) async {
try {
Map<String, String> data = {
'emp_id': (empId).toString(),
'session_id': (session).toString(),
'type':'approve',
'mode':mode.toString(),
'payment_request_id': (payment_request_id).toString(),
'approved_amount':approved_amount,
'approve_remarks':approve_remarks,
'proposed_payment_account_id':proposed_payment_account_id,
'payment_account_id':payment_account_id,
'processing_remarks':processing_remarks,
};
var res;
if (attachment != null) {
res = await postImageNew(
data,
{},
approveRejectPaymentRequestSubmitUrl,
attachment,
"attachment",
);
res = jsonDecode(res);
} else {
res = await post(data, approveRejectPaymentRequestSubmitUrl, {});
res = jsonDecode(res);
}
} catch (e) {
debugPrint('hello bev=bug $e ');
return null;
}
}
}
const baseUrl = "https://erp.gengroup.in/ci/app/";
const baseUrl_test = "https://erp.gengroup.in/ci/app/Dheeraj/";
const baseUrl_test = "https://erp.gengroup.in/ci/app/Api_home/";
// var WEB_SOCKET_URL = "wss://ws.erp.gengroup.in/?type=user&route=employe_live_location_update&session_id=${Sessionid}";
const getAppVersionUrl = "https://erp.gengroup.in/ci/assets/appversion.json";
......@@ -58,3 +58,6 @@ const financeAddFormPagesAccessUrl = "${baseUrl_test}finance_add_form_page_acces
const addPaymentRequestionViewUrl = "${baseUrl_test}add_payment_requisiton_view";
const addPaymentRequestionSubmitUrl = "${baseUrl_test}add_payment_requsition_submit";
const paymentRequestionListUrl = "${baseUrl_test}payment_requsition_list";
const paymentRequestionDetailsUrl = "${baseUrl_test}payment_requisition_details";
const approveRejectPaymentRequestUrl = "${baseUrl_test}approve_reject_payment_request_view";
const approveRejectPaymentRequestSubmitUrl = "${baseUrl_test}approve_reject_payment_request_submit";
......@@ -7,12 +7,16 @@
#include "generated_plugin_registrant.h"
#include <file_selector_linux/file_selector_plugin.h>
#include <printing/printing_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) printing_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "PrintingPlugin");
printing_plugin_register_with_registrar(printing_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
file_selector_linux
printing
url_launcher_linux
)
......
......@@ -17,9 +17,11 @@ import geolocator_apple
import location
import package_info_plus
import path_provider_foundation
import printing
import share_plus
import shared_preferences_foundation
import sqflite_darwin
import syncfusion_pdfviewer_macos
import url_launcher_macos
import webview_flutter_wkwebview
......@@ -36,9 +38,11 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
PrintingPlugin.register(with: registry.registrar(forPlugin: "PrintingPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
SyncfusionFlutterPdfViewerPlugin.register(with: registry.registrar(forPlugin: "SyncfusionFlutterPdfViewerPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin"))
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment