From bdbeb428f80b16d14a009a3a6678af2feed05fe6 Mon Sep 17 00:00:00 2001 From: SurendarSuri30 Date: Fri, 4 Jul 2025 10:50:13 +0530 Subject: [PATCH] cd transaction added --- lib/cdTransactionDetails.dart | 715 ++++++++++++++++++++++++++++ lib/main.dart | 9 + lib/service/api_service.dart | 13 + lib/service/hrDashboardTabs/cd.dart | 37 +- 4 files changed, 763 insertions(+), 11 deletions(-) create mode 100644 lib/cdTransactionDetails.dart diff --git a/lib/cdTransactionDetails.dart b/lib/cdTransactionDetails.dart new file mode 100644 index 0000000..b6f343d --- /dev/null +++ b/lib/cdTransactionDetails.dart @@ -0,0 +1,715 @@ +import 'dart:convert'; + +import 'package:csv/csv.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:http/http.dart' as http; +import 'package:intl/intl.dart'; +import 'package:nhancepolicy/service/api_service.dart'; +import 'package:universal_html/html.dart' as html; + +import '../../models/environment.dart'; +import 'package:collection/collection.dart'; + +import 'customAppBar/customAppBar.dart'; + +class cdTransactionDetails extends StatefulWidget { + final String insurerName; + final String cdMasterAccountNo; + final String insurerId; + final String cd_ac_pk; + final String empClientId; + final String postToken; + const cdTransactionDetails( + {Key? key, + required this.insurerName, + required this.cdMasterAccountNo, + required this.insurerId, + required this.cd_ac_pk, + required this.empClientId, + required this.postToken + } + ); + + @override + State createState() => _cdTransactionDetailsState(); +} + +class _cdTransactionDetailsState extends State { + Uint8List? fileBytes; + List> getCDTransData = []; + bool isLoading = false; + bool _isLoading = false; + // dynamic clintID; + late TabController _tabController; + // List dataPolicy = []; + List reversedDataPolicy = []; + List> originalData = []; // Original data source + List> filteredData = []; // Filtered data source + List> getCDTransDataAmount = []; // Filtered data source + dynamic argumentsData; + dynamic policyType; + dynamic policyName; + dynamic clientPolicyId; + dynamic clientId; + dynamic empRefId; + dynamic total_deposit; + dynamic total_consumed; + dynamic total_refund; + dynamic currect_balance; + int inceptionType = 0; + TextEditingController searchController = TextEditingController(); + late ApiService apiService; + + @override + void initState() { + super.initState(); + apiService = ApiService(context); // Initialize ApiService here + getCdTransactionDetails(); + } + + @override + void dispose() { + super.dispose(); + } + + Future getCdTransactionDetails() async { + print('9'); + setState(() { + isLoading = true; + }); + try { + print('10'); + final response = await apiService.getCdTransactionData( + widget.empClientId, widget.insurerId,widget.cd_ac_pk, widget.postToken); + if (response['status'] == 'success') { + setState(() { + // isLoading = false; + }); + setState(() { + getCDTransData = List>.from(response['data']['deposit_data']); + originalData = getCDTransData; + filteredData = List.from(originalData); + total_deposit = response['data']['total_deposit']; + total_consumed = response['data']['total_consumed']; + total_refund = response['data']['total_refund']; + currect_balance = response['data']['currect_balance']; + print('filteredData'); + print(filteredData); + }); + } else { + setState(() { + // isLoading = false; + }); + + // ToastHelper.showWarningToast( + // context, 'Request failed with status: ${response.statusCode}'); + print('Request failed with status: ${response['code']}'); + } + } catch (e) { + setState(() { + // isLoading = false; + }); + print('Exception occurred: $e'); + } finally { + setState(() { + // _isLoading = false; + }); + } + } + + void search(String query) { + print(query); + // Check if the query is empty + if (query.isEmpty) { + // If search query is empty, show all data + setState(() { + filteredData = List.from(originalData); + }); + } else { + // Filter the original data based on the search query + setState(() { + filteredData = originalData.where((row) { + // Implement your filter logic here + // For example, check if any field in the row contains the query + // Adjust this logic based on your data structure + return row['created_at'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['record_date'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['unit'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['policy_type'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['policy_no'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['endorsement_no'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['sub_type'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['transaction_type'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['amount'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['balance'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['description'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()) || + row['username'] + .toString() + .toLowerCase() + .contains(query.toLowerCase()); + }).toList(); + }); + } + print(filteredData.length); + } + + void exportToCsv(List> data) { + List> rows = []; + + // Header + rows.add(['Date', 'Record Date', 'Unit','Policy','Endorsement No','Sub Type','Credit','Debit','Balance','Description','User']); + + // Data rows + for (var item in data) { + rows.add([ + item['created_at'] ?? '', + item['record_date'] ?? '', + item['unit'] ?? '', + item['policy_type'] != null && item['policy_type'].toString().trim().isNotEmpty && + item['policy_no'] != null && item['policy_no'].toString().trim().isNotEmpty + ? '${item['policy_type']} - ${item['policy_no']}' + : '-', + item['endorsement_no'] ?? '', + item['sub_type'] ?? '', + item['transaction_type'] == 'Credit' ? '₹${item['amount']}' : '-', + item['transaction_type'] == 'Debit' ? '₹${item['amount']}' : '-', + '₹${item['balance'] ?? '0'}', + item['description'] ?? '', + item['username'] ?? '', + ]); + } + + // Convert to CSV string + String csvData = const ListToCsvConverter().convert(rows); + + // For Web: Create download + final bytes = utf8.encode(csvData); + final blob = html.Blob([bytes]); + final url = html.Url.createObjectUrlFromBlob(blob); + final anchor = html.AnchorElement(href: url) + ..setAttribute("download", "CD_Policies.csv") + ..click(); + html.Url.revokeObjectUrl(url); + } + + String formatDate(String? dateString) { + if (dateString == null || dateString.isEmpty) return '-'; + + try { + DateTime parsedDate = DateTime.parse(dateString); + return DateFormat('dd-MM-yyyy hh:mm a').format(parsedDate); + } catch (e) { + return '-'; + } + } + + String formatDateNextLine(String? dateString) { + if (dateString == null || dateString.isEmpty) return '-'; + + try { + DateTime parsedDate = DateTime.parse(dateString); + String date = DateFormat('dd-MM-yyyy').format(parsedDate); + String time = DateFormat('hh:mm a').format(parsedDate); + return '$date\n$time'; + } catch (e) { + return '-'; + } + } + + + @override + Widget build(BuildContext context) { + // TODO: implement build + return Scaffold( + appBar: CustomAppBar(), + backgroundColor: Color(0xFFEFF3F6), + body: Stack( + children: [ + SingleChildScrollView( + child: Container( + padding: + EdgeInsets.only(top: 30, bottom: 200, left: 50, right: 50), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MouseRegion( + cursor: SystemMouseCursors.click, // 👈 shows pointer on hover + child: GestureDetector( + onTap: () { + Navigator.pop(context); // or your desired action + }, + child: Row( + children: [ + Icon(Icons.arrow_back_ios_new_outlined, color: Color(0xFF707070)), + SizedBox(width: 8), + Expanded( + child: Text( + 'Transaction Details - ${widget.insurerName} (${widget.cdMasterAccountNo})', + style: GoogleFonts.poppins( + fontSize: 18, + fontWeight: FontWeight.w600, + color: Color(0xFF101010), + ), + ), + ), + ], + ), + ), + ), + SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _buildInfoCard('Deposits', '₹$total_deposit', Color(0xFF39D45B), Icons.arrow_upward), + _buildInfoCard('Consumed', '₹$total_consumed', Color(0xFFED1D24), Icons.arrow_downward), + _buildInfoCard('Refund', '₹$total_refund', Color(0xFF39D45B), Icons.arrow_upward), + _buildInfoCard('Current Balance', '₹$currect_balance', Colors.black, null), + ], + ), + SizedBox(height: 16), + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.circular(10), // 👈 set your desired radius + ), + // height: 400, + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Row( + children: [ + Expanded( + flex: 4, + child: Align( + alignment: Alignment.centerLeft, + child: Container( + width: 400, + height: 37, + decoration: BoxDecoration( + color: Color(0xFFF0F0F0), + borderRadius: BorderRadius.circular(8), + ), + child: TextField( + decoration: InputDecoration( + hintText: 'Search', + prefixIcon: Icon(Icons.search, size: 18), + contentPadding: EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + border: InputBorder + .none, // No border since Container handles it + ), + controller: searchController, + onChanged: search, + style: GoogleFonts.poppins(fontSize: 14), + ), + ), + ), + ), + SizedBox(width: 12), + Expanded( + flex: 2, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 116, + height: 37, + child: ElevatedButton( + onPressed: () { + exportToCsv(filteredData); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFFE26728), + padding: EdgeInsets.all(10), // Internal padding + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(10), // Border radius + side: BorderSide( + color: Colors + .transparent, // Optional border color + width: 1, // Border width + ), + ), + elevation: 0, + ), + child: Text( + 'Export', + style: GoogleFonts.poppins( + fontSize: 16, + color: Color(0xFFFFFFFF), + fontWeight: FontWeight.w700, + letterSpacing: 1), + ), + ), + ), + ], + ), + ), + ], + ), + SizedBox(height: 20), + Row( + children: [ + Expanded( + child: SingleChildScrollView( + child: _buildCDDataTable(context), + ), + ) + ], + ), + ], + ), + ) + ], + ) + ) + ) + ] + ) + ); + } + + Widget _buildInfoCard(String label, String value, Color iconColor, IconData? icon) { + return Expanded( + child: Container( + margin: EdgeInsets.symmetric(horizontal: 4), + padding: EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + boxShadow: [ + BoxShadow( + color: Colors.black12, + blurRadius: 2, + offset: Offset(0, 1), + ), + ], + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, // label left, value right + children: [ + Text( + label, + style: GoogleFonts.poppins(color: Color(0xFF737373), fontSize: 14,fontWeight: FontWeight.w400), + textAlign: TextAlign.left, + ), + Row( + children: [ + if (icon != null) + Icon(icon, size: 20, color: iconColor), + if (icon != null) SizedBox(width: 4), + Text( + value, + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w400 , + color: Color(0xFF000000), + ), + ), + ], + ), + ], + ), + ], + ), + ), + ); + } + + + Widget _buildCDDataTable(BuildContext context) { + if (filteredData.isEmpty) { + return const SizedBox( + height: 50, + child: Center(child: Text('No available data')), + ); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header row + Container( + decoration: BoxDecoration( + color: Color(0xFFD7E9EB), + borderRadius: BorderRadius.circular(6), + ), + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), + child: Row( + children: [ + Expanded( + flex: 2, + child: Text( + 'Date', + textAlign: TextAlign.left, + style: GoogleFonts.poppins( + color: Color(0xFF000000), fontWeight: FontWeight.bold), + ), + ), + Expanded( + flex: 2, + child: Text( + 'Record Date', + textAlign: TextAlign.left, + style: GoogleFonts.poppins( + color: Color(0xFF000000), fontWeight: FontWeight.bold), + ), + ), + Expanded( + flex: 4, + child: Text( + 'Unit', + textAlign: TextAlign.left, + style: GoogleFonts.poppins( + color: Color(0xFF000000), fontWeight: FontWeight.bold), + ), + ), + Expanded( + flex: 3, + child: Text( + 'Policy', + textAlign: TextAlign.left, + style: GoogleFonts.poppins( + color: Color(0xFF000000), fontWeight: FontWeight.bold), + ), + ), + Expanded( + flex: 2, + child: Text( + 'Endorsement No', + textAlign: TextAlign.left, + style: GoogleFonts.poppins( + color: Color(0xFF000000), fontWeight: FontWeight.bold), + ), + ), + Expanded( + flex: 2, + child: Text( + 'Sub Type', + textAlign: TextAlign.left, + style: GoogleFonts.poppins( + color: Color(0xFF000000), fontWeight: FontWeight.bold), + ), + ), + Expanded( + flex: 2, + child: Text( + 'Credit', + textAlign: TextAlign.left, + style: GoogleFonts.poppins( + color: Color(0xFF000000), fontWeight: FontWeight.bold), + ), + ), + Expanded( + flex: 2, + child: Text( + 'Debit', + textAlign: TextAlign.left, + style: GoogleFonts.poppins( + color: Color(0xFF000000), fontWeight: FontWeight.bold), + ), + ), + Expanded( + flex: 2, + child: Text( + 'Balance', + textAlign: TextAlign.left, + style: GoogleFonts.poppins( + color: Color(0xFF000000), fontWeight: FontWeight.bold), + ), + ), + Expanded( + flex: 3, + child: Text( + 'Description', + textAlign: TextAlign.left, + style: GoogleFonts.poppins( + color: Color(0xFF000000), fontWeight: FontWeight.bold), + ), + ), + Expanded( + flex: 1, + child: Text( + 'User', + textAlign: TextAlign.left, + style: GoogleFonts.poppins( + color: Color(0xFF000000), fontWeight: FontWeight.bold), + ), + ), + ], + ), + ), + + const SizedBox(height: 6), + + // Table body rows + ...filteredData.mapIndexed((index, item) { + return Container( + margin: const EdgeInsets.only(bottom: 8), + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 16), + decoration: BoxDecoration( + // color: index % 2 == 0 ? Color(0xFFE6FAFB) : Colors.white, + color: Colors.white, + borderRadius: BorderRadius.circular(6), + border: Border( + bottom: BorderSide( + color: Color(0xFFD7E9EB), // 👈 Bottom border color + width: 1, // 👈 Optional: thickness + ), + ), + ), + child: Row( + children: [ + Expanded( + flex: 2, + child: Text( + formatDateNextLine(item['created_at']), + textAlign: TextAlign.left, + style: GoogleFonts.poppins(color: Color(0xFF000000)), + ), + ), + Expanded( + flex: 2, + child: Text( + item['record_date'] ?? '-', + textAlign: TextAlign.left, + style: GoogleFonts.poppins(color: Color(0xFF000000)), + ), + ), + Expanded( + flex: 4, + child: Text( + 'The Kancheepuram District Consumers Operative Wholesale Stores Limited-5526', + // item['unit'] ?? '-', + textAlign: TextAlign.left, + style: GoogleFonts.poppins(color: Color(0xFF000000)), + ), + ), + Expanded( + flex: 3, + child: Text( + 'Motor - 3001/379707905/00/000', + // item['policy_type'] != null && item['policy_type'].toString().trim().isNotEmpty && + // item['policy_no'] != null && item['policy_no'].toString().trim().isNotEmpty + // ? '${item['policy_type']} - ${item['policy_no']}' + // : '-', + textAlign: TextAlign.left, + style: GoogleFonts.poppins(color: Color(0xFF000000)), + ), + ), + Expanded( + flex: 2, + child: Text( + item['endorsement_no'] ?? '-', + textAlign: TextAlign.left, + style: GoogleFonts.poppins(color: Color(0xFF000000)), + ), + ), + Expanded( + flex: 2, + child: Text( + item['sub_type'] ?? '-', + textAlign: TextAlign.left, + style: GoogleFonts.poppins(color: Color(0xFF000000)), + ), + ), + Expanded( + flex: 2, + child: Text( + item['transaction_type'] == 'Credit' ? '₹${item['amount']}' : '-', + textAlign: TextAlign.left, + style: GoogleFonts.poppins(color: Color(0xFF000000)), + ), + ), + Expanded( + flex: 2, + child: Text( + item['transaction_type'] == 'Debit' ? '₹${item['amount']}' : '-', + textAlign: TextAlign.left, + style: GoogleFonts.poppins(color: Color(0xFF000000)), + ), + ), + Expanded( + flex: 2, + child: Text( + "₹${item['balance'] ?? '-'}", + textAlign: TextAlign.left, + style: GoogleFonts.poppins(color: Color(0xFF000000)), + ), + ), + Expanded( + flex: 3, + child: Text( + item['description'] ?? '-', + textAlign: TextAlign.left, + style: GoogleFonts.poppins(color: Color(0xFF000000)), + ), + ), + Expanded( + flex: 1, + child: Text( + item['username'] ?? '-', + textAlign: TextAlign.left, + style: GoogleFonts.poppins(color: Color(0xFF000000)), + ), + ), + ], + ), + ); + }).toList(), + ], + ); + } +} + + + +// Sample Data class representing each element in the array +class Data { + final dynamic value; + final int row; + final int column; + final String sheet; + + Data(this.value, this.row, this.column, this.sheet); +} diff --git a/lib/main.dart b/lib/main.dart index 4a25a4e..15eb7ba 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,6 +16,7 @@ import 'package:nhancepolicy/hrPolicyDetails.dart'; import 'package:nhancepolicy/oldPolicy.dart'; import 'package:firebase_core/firebase_core.dart'; +import 'cdTransactionDetails.dart'; import 'email_verify.dart'; Future main() async { @@ -57,6 +58,14 @@ Future main() async { 'addOnsDetails': (context) => addOnsDetails(), 'empReviewDetails': (context) => empReviewDetails(), 'hrDashboard': (context) => hrDashboard(), + 'cdTransactionDetails': (context) => cdTransactionDetails( + insurerName: '', + cdMasterAccountNo: '', + insurerId: '', + cd_ac_pk: '', + empClientId: '', + postToken: '', + ), 'hrPolicyDetails': (context) => hrPolicyDetails(), 'oldPolicy': (context) => oldPolicy(), }, diff --git a/lib/service/api_service.dart b/lib/service/api_service.dart index ec64aeb..5de769d 100755 --- a/lib/service/api_service.dart +++ b/lib/service/api_service.dart @@ -443,6 +443,19 @@ class ApiService { return response; } + Future> getCdTransactionData( + String clintID, String insurerId, String cd_ac_pk, String token) async { + print("getCashDepositDetailsToApi1"); + final url = Uri.parse( + '${Environment.apiUrlPost}cdTransactionData?client_id=$clintID&insurer_id=$insurerId&cd_ac_pk=$cd_ac_pk'); + + final headers = { + 'Authorization': 'Bearer $token' ?? '', + }; + final response = await _makeGetRequest(url, headers); + return response; + } + Future> getEmployeeAndDependenceToApi( String clintID, String getPolicyNo, String empRefId) async { print(_hrtoken); diff --git a/lib/service/hrDashboardTabs/cd.dart b/lib/service/hrDashboardTabs/cd.dart index 47b208a..ed5e758 100644 --- a/lib/service/hrDashboardTabs/cd.dart +++ b/lib/service/hrDashboardTabs/cd.dart @@ -5,9 +5,11 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; import 'package:universal_html/html.dart' as html; +import '../../cdTransactionDetails.dart'; import '../../models/environment.dart'; import '../api_service.dart'; import 'package:collection/collection.dart'; @@ -197,7 +199,7 @@ class _CdPolicieState extends State { ), controller: searchController, onChanged: search, - style: TextStyle(fontSize: 14), + style: GoogleFonts.poppins(fontSize: 14), ), ), ), @@ -229,7 +231,7 @@ class _CdPolicieState extends State { ), child: Text( 'Export', - style: TextStyle(fontSize: 16,color: Color(0xFFFFFFFF),fontWeight: FontWeight.w700,letterSpacing: 1), + style: GoogleFonts.poppins(fontSize: 16,color: Color(0xFFFFFFFF),fontWeight: FontWeight.w700,letterSpacing: 1), ), ), ), @@ -273,26 +275,26 @@ class _CdPolicieState extends State { ), padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), child: Row( - children: const [ + children: [ Expanded( flex: 4, child: Text( 'Insurer Name', - style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), + style: GoogleFonts.poppins(color: Colors.white, fontWeight: FontWeight.bold), ), ), Expanded( flex: 3, child: Text( 'CD Account number', - style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), + style: GoogleFonts.poppins(color: Colors.white, fontWeight: FontWeight.bold), ), ), Expanded( flex: 2, child: Text( 'Current Balance', - style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), + style: GoogleFonts.poppins(color: Colors.white, fontWeight: FontWeight.bold), ), ), Expanded( @@ -300,7 +302,7 @@ class _CdPolicieState extends State { child: Text( 'Action', textAlign: TextAlign.center, - style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), + style: GoogleFonts.poppins(color: Colors.white, fontWeight: FontWeight.bold), ), ), ], @@ -324,7 +326,7 @@ class _CdPolicieState extends State { flex: 4, child: Text( item['insurer_name'] ?? '-', - style: TextStyle( + style: GoogleFonts.poppins( color: Color(0xFF000000) ), ), @@ -333,7 +335,7 @@ class _CdPolicieState extends State { flex: 3, child: Text( item['cd_master_account_no'] ?? '-', - style: TextStyle( + style: GoogleFonts.poppins( color: Color(0xFF000000) ), ), @@ -342,7 +344,7 @@ class _CdPolicieState extends State { flex: 2, child: Text( "₹${item['balance'] ?? '0'}", - style: TextStyle( + style: GoogleFonts.poppins( color: Color(0xFF000000) ), ), @@ -353,7 +355,20 @@ class _CdPolicieState extends State { child: IconButton( icon: const Icon(Icons.remove_red_eye_outlined), onPressed: () { - // Add your logic here + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => cdTransactionDetails( + insurerName: item['insurer_name'], + cdMasterAccountNo: item['cd_master_account_no'], + insurerId: item['insurer_id'], + cd_ac_pk: item['cd_ac_pk'], + empClientId: widget.empClientId, + postToken:widget.postToken + ), + ), + ); + }, ), ),