diff --git a/lib/controller/kyc_controller.dart b/lib/controller/kyc_controller.dart new file mode 100644 index 0000000..a66758d --- /dev/null +++ b/lib/controller/kyc_controller.dart @@ -0,0 +1,81 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../models/kyc_model.dart'; +import 'kyc_service.dart'; + +class KycController extends GetxController { + var kycList = [].obs; // Using an observable list to store KYC data + var isLoading = false.obs; + + Future fetchKycData() async { + try { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? token = prefs.getString('token'); + isLoading(true); + + // Call the API to get KYC data + var data = await KycService().getKycData(token!); + + if (data != null && data.isNotEmpty) { + // Parse the list of KYC objects + kycList.value = KycModel.fromJsonList(data); // Convert to List + } else { + print("No KYC data found or API response is empty."); + } + + print("KYC details: ${kycList}"); + } finally { + isLoading(false); + } + } + + // Update KYC status locally and persist the changes + Future updateKycStatus(KycModel kycModel, String status, String comment) async { + final index = kycList.indexOf(kycModel); + if (index != -1) { + kycList[index].status = status; // Update status locally + saveKycToLocalStorage(); // Persist the changes locally + update(); // Notify listeners about the change + + // Show a success message after updating + Get.snackbar( + "Success", + "KYC status updated to $status.", + snackPosition: SnackPosition.BOTTOM, + backgroundColor: Colors.green, + colorText: Colors.white, + ); + } + } + + // Save the current KYC list to SharedPreferences + Future saveKycToLocalStorage() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + List kycListJson = kycList.map((kyc) => jsonEncode(kyc.toJson())).toList(); + prefs.setStringList('kycList', kycListJson); // Save the updated list locally + } + + // Load the KYC list from SharedPreferences + Future loadKycFromLocalStorage() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + List? storedKycList = prefs.getStringList('kycList'); + + if (storedKycList != null) { + // If local data is found, update the KYC list with the locally saved data + List localKycList = storedKycList.map((kycJson) => KycModel.fromJson(jsonDecode(kycJson))).toList(); + + // Merge local data with the API data (if any exists in kycList) + for (var localKyc in localKycList) { + int index = kycList.indexWhere((kyc) => kyc.id == localKyc.id); + if (index != -1) { + // Update the status with the locally saved status + kycList[index].status = localKyc.status; + } + } + } + } +} \ No newline at end of file diff --git a/lib/controller/kyc_service.dart b/lib/controller/kyc_service.dart new file mode 100644 index 0000000..b352d87 --- /dev/null +++ b/lib/controller/kyc_service.dart @@ -0,0 +1,66 @@ + + +import 'package:dio/dio.dart'; + +class KycService { + Future> getKycData(String token) async { + try { + var response = await Dio().get( + 'https://api.cnapp.co.in/api/kyc/getAll', + options: Options( + headers: { + 'Authorization': 'Bearer $token', + }, + ), + ); + + if (response.statusCode == 200) { + print("response of /api/kyc/getAll : ${response.data}"); + return response.data; // Return the data as a List + } else { + throw Exception("Failed to load KYC data"); + } + } catch (e) { + print("Error fetching KYC data: $e"); + return []; + } + } +} + + + +// import 'dart:convert'; +// import 'package:cheminova/utils/api_urls.dart'; +// import '../models/kyc_model.dart'; +// import '../utils/common_api_service.dart'; +// +// class KycService { +// Future?> getKycData(String token) async { +// String url = ApiUrls.getKyc; // API endpoint for KYC data +// +// // Use the commonApiService for making the API request +// final response = await commonApiService>( +// method: "GET", +// url: url, +// additionalHeaders: { +// 'Authorization': 'Bearer $token', // Add the token in headers +// }, +// fromJson: (json) +// { +// if (json != null && json['data'] != null) { +// List dataList = json['data']; // Access 'data' array +// return dataList.map((item) => KycModel.fromJson(item)).toList(); +// } else { +// print('Invalid KYC response or data is null'); +// return []; +// } +// +// +// +// }, +// ); +// +// // Return the parsed KYC data list, or an empty list in case of failure +// return response; +// } +// } diff --git a/lib/models/kyc_model.dart b/lib/models/kyc_model.dart new file mode 100644 index 0000000..33d661b --- /dev/null +++ b/lib/models/kyc_model.dart @@ -0,0 +1,257 @@ +class KycModel { + String? id; + String? name; + String? email; + String? tradeName; + String? address; + String? state; + String? city; + String? district; + String? pincode; + String? mobileNumber; + PrincipalDistributer? principalDistributer; + String? panNumber; + ImageModel? panImg; + String? aadharNumber; + ImageModel? aadharImg; + String? gstNumber; + ImageModel? gstImg; + ImageModel? pesticideLicenseImg; + ImageModel? selfieEntranceImg; + String? status; + AddedBy? addedBy; + String? userType; + List? notes; + String? createdAt; + String? updatedAt; + int? v; + + KycModel({ + this.id, + this.name, + this.email, + this.tradeName, + this.address, + this.state, + this.city, + this.district, + this.pincode, + this.mobileNumber, + this.principalDistributer, + this.panNumber, + this.panImg, + this.aadharNumber, + this.aadharImg, + this.gstNumber, + this.gstImg, + this.pesticideLicenseImg, + this.selfieEntranceImg, + this.status, + this.addedBy, + this.userType, + this.notes, + this.createdAt, + this.updatedAt, + this.v, + }); + + factory KycModel.fromJson(Map json) { + return KycModel( + id: json["_id"], + name: json["name"], + email: json["email"], + tradeName: json["trade_name"], + address: json["address"], + state: json["state"], + city: json["city"], + district: json["district"], + pincode: json["pincode"], + mobileNumber: json["mobile_number"], + principalDistributer: json["principal_distributer"] != null + ? PrincipalDistributer.fromJson(json["principal_distributer"]) + : null, + panNumber: json["pan_number"], + panImg: json["pan_img"] != null ? ImageModel.fromJson(json["pan_img"]) : null, + aadharNumber: json["aadhar_number"], + aadharImg: json["aadhar_img"] != null + ? ImageModel.fromJson(json["aadhar_img"]) + : null, + gstNumber: json["gst_number"], + gstImg: json["gst_img"] != null ? ImageModel.fromJson(json["gst_img"]) : null, + pesticideLicenseImg: json["pesticide_license_img"] != null + ? ImageModel.fromJson(json["pesticide_license_img"]) + : null, + selfieEntranceImg: json["selfie_entrance_img"] != null + ? ImageModel.fromJson(json["selfie_entrance_img"]) + : null, + status: json["status"], + addedBy: json["addedBy"] != null ? AddedBy.fromJson(json["addedBy"]) : null, + userType: json["userType"], + notes: json["notes"], + createdAt: json["createdAt"], + updatedAt: json["updatedAt"], + v: json["__v"], + ); + } + + // Method for parsing list of JSON objects + static List fromJsonList(List jsonList) { + return jsonList.map((json) => KycModel.fromJson(json)).toList(); + } + + Map toJson() { + return { + "_id": id, + "name": name, + "email": email, + "trade_name": tradeName, + "address": address, + "state": state, + "city": city, + "district": district, + "pincode": pincode, + "mobile_number": mobileNumber, + "principal_distributer": principalDistributer?.toJson(), + "pan_number": panNumber, + "pan_img": panImg?.toJson(), + "aadhar_number": aadharNumber, + "aadhar_img": aadharImg?.toJson(), + "gst_number": gstNumber, + "gst_img": gstImg?.toJson(), + "pesticide_license_img": pesticideLicenseImg?.toJson(), + "selfie_entrance_img": selfieEntranceImg?.toJson(), + "status": status, + "addedBy": addedBy?.toJson(), + "userType": userType, + "notes": notes, + "createdAt": createdAt, + "updatedAt": updatedAt, + "__v": v, + }; + } + + @override + String toString() { + return 'KycModel{id: $id, name: $name, email: $email, tradeName: $tradeName, address: $address, state: $state, city: $city, district: $district, pincode: $pincode, mobileNumber: $mobileNumber, principalDistributer: $principalDistributer, panNumber: $panNumber, panImg: $panImg, aadharNumber: $aadharNumber, aadharImg: $aadharImg, gstNumber: $gstNumber, gstImg: $gstImg, pesticideLicenseImg: $pesticideLicenseImg, selfieEntranceImg: $selfieEntranceImg, status: $status, addedBy: $addedBy, userType: $userType, notes: $notes, createdAt: $createdAt, updatedAt: $updatedAt, v: $v}'; + } +} + +class PrincipalDistributer { + String? id; + String? name; + + PrincipalDistributer({this.id, this.name}); + + factory PrincipalDistributer.fromJson(Map json) { + return PrincipalDistributer( + id: json["_id"], + name: json["name"], + ); + } + + Map toJson() { + return { + "_id": id, + "name": name, + }; + } + + @override + String toString() { + return 'PrincipalDistributer{id: $id, name: $name}'; + } +} + +class ImageModel { + String? publicId; + String? url; + + ImageModel({this.publicId, this.url}); + + factory ImageModel.fromJson(Map json) { + return ImageModel( + publicId: json["public_id"], + url: json["url"], + ); + } + + Map toJson() { + return { + "public_id": publicId, + "url": url, + }; + } + + @override + String toString() { + return 'ImageModel{publicId: $publicId, url: $url}'; + } +} + +class AddedBy { + String? id; + String? designation; + String? name; + String? mobileNumber; + bool? isVerified; + String? email; + String? fcmToken; + String? uniqueId; + String? createdAt; + String? updatedAt; + int? v; + + AddedBy({ + this.id, + this.designation, + this.name, + this.mobileNumber, + this.isVerified, + this.email, + this.fcmToken, + this.uniqueId, + this.createdAt, + this.updatedAt, + this.v, + }); + + factory AddedBy.fromJson(Map json) { + return AddedBy( + id: json["_id"], + designation: json["designation"], + name: json["name"], + mobileNumber: json["mobileNumber"], + isVerified: json["isVerified"], + email: json["email"], + fcmToken: json["fcm_token"], + uniqueId: json["uniqueId"], + createdAt: json["createdAt"], + updatedAt: json["updatedAt"], + v: json["__v"], + ); + } + + Map toJson() { + return { + "_id": id, + "designation": designation, + "name": name, + "mobileNumber": mobileNumber, + "isVerified": isVerified, + "email": email, + "fcm_token": fcmToken, + "uniqueId": uniqueId, + "createdAt": createdAt, + "updatedAt": updatedAt, + "__v": v, + }; + } + + @override + String toString() { + return 'AddedBy{id: $id, designation: $designation, name: $name, mobileNumber: $mobileNumber, isVerified: $isVerified, email: $email, fcmToken: $fcmToken, uniqueId: $uniqueId, createdAt: $createdAt, updatedAt: $updatedAt, v: $v}'; + } +} + + + diff --git a/lib/screens/kyc/kyc_retailer_details_screen.dart b/lib/screens/kyc/kyc_retailer_details_screen.dart new file mode 100644 index 0000000..998aa9d --- /dev/null +++ b/lib/screens/kyc/kyc_retailer_details_screen.dart @@ -0,0 +1,396 @@ +import 'package:cheminova/screens/retail/kyc_verification_screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; + +import '../../controller/kyc_controller.dart'; +import '../../models/kyc_model.dart'; +import 'kyc_verify_screen.dart'; + +class KycRetailerDetailScreen extends StatefulWidget { + KycModel? kycModel; + KycRetailerDetailScreen({super.key,this.kycModel}); + + @override + State createState() => + _KycRetailerDetailScreenState(); +} + +class _KycRetailerDetailScreenState + extends State { + + final KycController _kycController = Get.put(KycController()); + final commentController = TextEditingController(); + String currentStatus = "new"; + + void _approveKyc() { + if (widget.kycModel!.status == "approved") { + Get.snackbar("Error", "The KYC has already been approved.", snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white); + } else { + _kycController.updateKycStatus(widget.kycModel!, "approved",""); + Get.snackbar("Success", "KYC approved successfully.", snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.green, colorText: Colors.white); + Get.back(); // Go back after approval + } + } + + void _rejectKyc() { + if (widget.kycModel!.status == "reject") { + Get.snackbar("Error", "The KYC has already been rejected.", snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white); + } else { + // Show dialog to enter a comment + Get.dialog( + AlertDialog( + title: Text("Reject KYC"), + content: TextField( + controller: commentController, // TextEditingController for comment + decoration: InputDecoration(hintText: "Enter rejection comment"), + ), + actions: [ + TextButton( + onPressed: () { + Get.back(); // Close dialog without action + }, + child: Text("Cancel"), + ), + TextButton( + onPressed: () { + String comment = commentController.text; + if (comment.isNotEmpty) { + // Call reject method with comment + _kycController.updateKycStatus(widget.kycModel!, "reject", comment); + Get.snackbar("Success", "KYC rejected with comment: $comment", snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.green, colorText: Colors.white); + Get.back(); // Close the dialog + Get.back(); // Go back to the previous screen + } else { + Get.snackbar("Error", "Comment is required", snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white); + } + }, + child: Text("Reject"), + ), + ], + ), + ); + } + } + + + + + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + centerTitle: true, + backgroundColor: Colors.transparent, + elevation: 0, + leading: GestureDetector( + onTap: () {}, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset( + 'assets/svg/menu.svg', + ), + ), + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset( + 'assets/svg/back_arrow.svg', + ), + ), + ), + ], + title: const Text( + "Retail Distributer Detail", + ), + ), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset( + 'assets/images/image_1.png', + fit: BoxFit.cover, + ), + SafeArea( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: Get.height * 0.02, + ), + SizedBox( + height: Get.height * 0.85, + child: Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _buildCard( + title: "Retailer Information", + rows: [ + _buildInfoRow("Trade Name:", widget.kycModel!.tradeName), + _buildInfoRow("Name:", widget.kycModel!.name), + _buildInfoRow("Address:", widget.kycModel!.address), + _buildInfoRow("Town/City:", widget.kycModel!.city), + ], + width: Get.width, + height: Get.height, + ), + SizedBox(height: Get.height * 0.01), + _buildCard( + title: "Details", + rows: [ + _buildInfoRow("District:", widget.kycModel!.district), + _buildInfoRow("State:", widget.kycModel!.state), + _buildInfoRow("Pincode:", widget.kycModel!.pincode), + _buildInfoRow("Mobile Number:", widget.kycModel!.mobileNumber), + _buildInfoRow("Mapped Principal Distributor:", widget.kycModel!.principalDistributer?.name), + ], + width: Get.width, + height: Get.height*0.5, + ), + + SizedBox(height: Get.height * 0.01), + Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildTitle(), + _buildDocumentRow("Aadhaar number:", widget.kycModel!.aadharNumber, widget.kycModel!.aadharImg!.url), + SizedBox(height: 10), + _buildDocumentRow("Pan number:", widget.kycModel!.panNumber, widget.kycModel!.panImg!.url), + SizedBox(height: 10), + _buildDocumentRow("GST Number:", widget.kycModel!.gstNumber, widget.kycModel!.gstImg!.url), + SizedBox(height: 10), + _buildDocumentRow("Pesticide License:", "", widget.kycModel!.pesticideLicenseImg!.url), + SizedBox(height: 10), + _buildDocumentRow("Fertilizer License (optional):", "",widget.kycModel!.selfieEntranceImg!.url), + SizedBox(height: 10), + _buildDocumentRow("Selfie of Entrance Board::", "", widget.kycModel!.selfieEntranceImg!.url), + ], + ), + ), + SizedBox(height: Get.height * 0.01), + SizedBox( + width: Get.width*0.9, + child: Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB( + 16, 8, 8, 0), + child: Text( + "Verification Options", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.w700, + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: _approveKyc, + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: + const Color(0xFF004791), + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(10), + ), + ), + child: Text( + "Approve", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.w400, + ), + ), + ), + ), + ), + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: _rejectKyc, + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: + const Color(0xFF910000), + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(10), + ), + ), + child: Text( + "Reject", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.w400, + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ), + SizedBox(height: Get.height * 0.01), + Card( + child: SizedBox( + width: Get.width*0.9, + height: Get.height * 0.2, + child: Padding( + padding: const EdgeInsets.all(12), + child: Text( + "Comment:", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.w700, + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + + ], + ), + ), + ), + ], + ), + ); + } + + + Widget _buildCard({required String title, required List rows, required double width, required double height}) { + return Card( + child: Column( + children: [ + _buildTitle1(title, width), + ...rows, + ], + ), + ); + } + + Widget _buildTitle1(String title, double width) { + return SizedBox( + width: width, + child: Padding( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), + child: Center( + child: Text( + title, + style: GoogleFonts.roboto( + fontSize: width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ); + } + + Widget _buildInfoRow(String label, String? value) { + return SizedBox( + width: double.infinity, + child: Padding( + padding: const EdgeInsets.fromLTRB(5, 8, 8, 1), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: GoogleFonts.roboto( + fontSize: 16, // Adjust as needed + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 8), // Space between label and value + Expanded( + child: Text(value ?? 'N/A'), // Handle null case + ), + ], + ), + ), + ); + } +} + + Widget _buildTitle() { + return Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Center( + child: Text( + "KYC Documents", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04,// You can adjust this based on screen size + fontWeight: FontWeight.bold, + ), + ), + ), + ); + } + + Widget _buildDocumentRow(String title, String? number, String? imageUrl) { + return Column( + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + children: [ + Text(title, style: TextStyle(fontWeight: FontWeight.bold)), + SizedBox(width: 8), // Space between title and number + Text(number ?? 'N/A'), // Handle null case + ], + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Image.network( + imageUrl ?? 'No Image Available', + fit: BoxFit.contain, + ), + ), + ), + ], + ); + } + + diff --git a/lib/screens/kyc/kyc_retailer_info_screen.dart b/lib/screens/kyc/kyc_retailer_info_screen.dart new file mode 100644 index 0000000..9d76262 --- /dev/null +++ b/lib/screens/kyc/kyc_retailer_info_screen.dart @@ -0,0 +1,627 @@ +import 'package:cheminova/controller/kyc_controller.dart'; +import 'package:cheminova/models/kyc_model.dart'; +import 'package:cheminova/widgets/input_field.dart'; +import 'package:cheminova/widgets/my_drawer.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; +import '../../controller/cart_controller.dart'; +import 'kyc_retailer_details_screen.dart'; + +class KycRetailerInfoScreen extends StatefulWidget { + KycModel? kycModel; + KycRetailerInfoScreen({super.key, this.kycModel}); + + @override + State createState() => _KycRetailerInfoScreenState(); +} + +class _KycRetailerInfoScreenState extends State { + final _searchController = TextEditingController(); + final List _filterList = ["Order Status", "Date Range"]; + + final KycController _kycController = Get.put(KycController()); + final CartController _cartController = Get.put(CartController()); + final GlobalKey _refreshIndicatorKey = + GlobalKey(); + + String selectedStatus = "All"; // Default selected status + + @override + void initState() { + super.initState(); + getKycData(); + } + + Future _onRefresh() async { + await getKycData(); + await Future.delayed(Duration(seconds: 1)); + } + + Future getKycData() async { + await _kycController.fetchKycData(); + print("kyc successfully"); + } + + String capitalizeFirstLetter(String text) { + if (text.isEmpty) return text; + return text[0].toUpperCase() + text.substring(1).toLowerCase(); + } + + String formatDate(String apiDate) { + DateTime parsedDate = DateTime.parse(apiDate); + String formattedDate = DateFormat('dd-MMM-yyyy').format(parsedDate); + return formattedDate; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + centerTitle: true, + backgroundColor: Colors.transparent, + elevation: 0, + leading: Builder( + builder: (context) { + return GestureDetector( + onTap: () => Scaffold.of(context).openDrawer(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset('assets/svg/menu.svg'), + ), + ); + }, + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset('assets/svg/back_arrow.svg'), + ), + ), + ], + title: const Text("Kyc Management"), + ), + drawer: MyDrawer(), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset('assets/images/image_1.png', fit: BoxFit.cover), + SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only( + bottom: MediaQuery.of(context).viewInsets.bottom), + child: RefreshIndicator( + key: _refreshIndicatorKey, + onRefresh: _onRefresh, + color: Colors.black, + backgroundColor: Colors.white, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + InputField( + hintText: "Search Order", + labelText: "Search Order", + controller: _searchController, + ), + SizedBox(height: Get.height * 0.035), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: Get.height * 0.05, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Text( + "Kyc Status: ", + style: TextStyle(fontWeight: FontWeight.bold), + ), + SizedBox(width: 10), // Space between label and dropdown + Expanded( + child: DropdownButtonFormField( + value: selectedStatus, + decoration: InputDecoration( + filled: true, + fillColor: Colors.white, // White background + contentPadding: EdgeInsets.symmetric( + vertical: 10, horizontal: 12), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Colors.grey, + width: 1, + ), + ), + ), + items: [ + "All", + "new", + "approved", + "reject" + ].map((String status) { + return DropdownMenuItem( + value: status, + child: Text(capitalizeFirstLetter(status)), + ); + }).toList(), + onChanged: (newValue) { + setState(() { + selectedStatus = newValue!; + }); + }, + ), + ), + ], + ), + ), + SizedBox( + height: Get.height * 0.6, + child: Obx(() { + // Filter the list based on the selected status + List filteredOrders = + selectedStatus == "All" + ? _kycController.kycList + : _kycController.kycList + .where((order) => + order.status == + selectedStatus) + .toList(); + + return ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: filteredOrders.length, + itemBuilder: (context, index) { + final order = filteredOrders[index]; + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 8), + child: Card( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Padding( + padding: + const EdgeInsets.fromLTRB( + 16, 8, 8, 0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Text( + "Order ID: ", + style: GoogleFonts + .roboto( + fontSize: 14, + fontWeight: + FontWeight + .bold)), + Text("${order.id}") + ], + ), + ), + Padding( + padding: + const EdgeInsets.fromLTRB( + 16, 8, 8, 0), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Product Names: ", + style: + GoogleFonts.roboto( + fontSize: 14, + fontWeight: + FontWeight.bold, + ), + ), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + '${capitalizeFirstLetter(order!.tradeName.toString())}', + textAlign: + TextAlign.left, + style: GoogleFonts + .roboto( + fontSize: 14, + ), + ), + ], + ), + ), + ], + ), + ), + Padding( + padding: + const EdgeInsets.fromLTRB( + 16, 8, 8, 0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Text( + "Order Date: ", + style: GoogleFonts + .roboto( + fontSize: 14, + fontWeight: + FontWeight + .bold)), + Text(formatDate( + "${order.createdAt}")) + ], + ), + ), + Padding( + padding: + const EdgeInsets.fromLTRB( + 16, 8, 8, 8), + child: Row( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Text("Status: ", + style: GoogleFonts + .roboto( + fontSize: 14, + fontWeight: + FontWeight + .bold)), + Text(capitalizeFirstLetter( + "${order.status}")) + ], + ), + ), + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: + const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () => Get.to(() => + KycRetailerDetailScreen( + kycModel: + _kycController + .kycList[ + index])), + style: + ElevatedButton.styleFrom( + foregroundColor: + Colors.white, + backgroundColor: + const Color( + 0xFF004791), + shape: + RoundedRectangleBorder( + borderRadius: + BorderRadius + .circular( + 10)), + ), + child: Text("View Details"), + ), + ), + ), + ], + ), + ), + ); + }, + ); + }), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ); + } +} + + + + + + +// import 'package:cheminova/controller/kyc_controller.dart'; +// import 'package:cheminova/models/kyc_model.dart'; +// import 'package:cheminova/widgets/input_field.dart'; +// import 'package:cheminova/widgets/my_drawer.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter_svg/svg.dart'; +// import 'package:get/get.dart'; +// import 'package:google_fonts/google_fonts.dart'; +// import 'package:intl/intl.dart'; +// import '../../controller/cart_controller.dart'; +// import 'kyc_retailer_details_screen.dart'; +// +// +// class KycRetailerInfoScreen extends StatefulWidget { +// +// KycModel? kycModel; +// KycRetailerInfoScreen({super.key, this.kycModel}); +// +// @override +// State createState() => _KycRetailerInfoScreenState(); +// } +// +// class _KycRetailerInfoScreenState extends State { +// final _searchController = TextEditingController(); +// final List _filterList = ["Order Status", "Date Range"]; +// +// final KycController _kycController = Get.put(KycController()); +// final CartController _cartController = Get.put(CartController()); +// final GlobalKey _refreshIndicatorKey = +// GlobalKey(); +// +// @override +// void initState() { +// super.initState(); +// getKycData(); +// } +// +// Future _onRefresh() async { +// await getKycData(); +// await Future.delayed(Duration(seconds: 1)); +// } +// +// Future getKycData() async { +// await _kycController.fetchKycData(); +// print("kyc successfully"); +// } +// +// String capitalizeFirstLetter(String text) { +// if (text.isEmpty) return text; +// return text[0].toUpperCase() + text.substring(1).toLowerCase(); +// } +// +// String formatDate(String apiDate) { +// DateTime parsedDate = DateTime.parse(apiDate); +// String formattedDate = DateFormat('dd-MMM-yyyy').format(parsedDate); +// return formattedDate; +// } +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// extendBodyBehindAppBar: true, +// appBar: AppBar( +// centerTitle: true, +// backgroundColor: Colors.transparent, +// elevation: 0, +// leading: Builder( +// builder: (context) { +// return GestureDetector( +// onTap: () => Scaffold.of(context).openDrawer(), +// child: Padding( +// padding: const EdgeInsets.all(16.0), +// child: SvgPicture.asset('assets/svg/menu.svg'), +// ), +// ); +// }, +// ), +// actions: [ +// GestureDetector( +// onTap: () => Get.back(), +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: SvgPicture.asset('assets/svg/back_arrow.svg'), +// ), +// ), +// ], +// title: const Text("Kyc Management"), +// ), +// drawer: MyDrawer(), +// body: Stack( +// fit: StackFit.expand, +// children: [ +// Image.asset('assets/images/image_1.png', fit: BoxFit.cover), +// SafeArea( +// child: SingleChildScrollView( +// child: Padding( +// padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), +// child: RefreshIndicator( +// key: _refreshIndicatorKey, +// onRefresh: _onRefresh, +// color: Colors.black, +// backgroundColor: Colors.white, +// child: Column( +// mainAxisSize: MainAxisSize.min, +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// InputField( +// hintText: "Search Order", +// labelText: "Search Order", +// controller: _searchController, +// ), +// SizedBox(height: Get.height * 0.035), +// Card( +// margin: const EdgeInsets.symmetric(horizontal: 18), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(19), +// side: const BorderSide(color: Color(0xFFFDFDFD)), +// ), +// color: const Color(0xFFB4D1E5).withOpacity(0.9), +// child: Padding( +// padding: const EdgeInsets.all(12.0), +// child: Column( +// mainAxisSize: MainAxisSize.min, +// children: [ +// SizedBox( +// height: Get.height * 0.05, +// child: ListView.builder( +// shrinkWrap: true, +// scrollDirection: Axis.horizontal, +// itemCount: _filterList.length, +// itemBuilder: (context, index) => Padding( +// padding: const EdgeInsets.symmetric(horizontal: 4), +// child: Chip( +// label: Text( +// _filterList[index], +// style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w500), +// ), +// ), +// ), +// ), +// ), +// SizedBox( +// height: Get.height * 0.6, +// child: Obx(() { +// // // Use a set to keep track of unique order IDs +// // final Set uniqueOrderIds = {}; +// // final List uniqueOrders = []; +// // +// // for (var order in _kycController.kycList) { +// // if (uniqueOrderIds.add(order.id)) { +// // uniqueOrders.add(order); +// // } +// // } +// +// return ListView.builder( +// padding: EdgeInsets.zero, +// shrinkWrap: true, +// itemCount: _kycController.kycList.length, +// itemBuilder: (context, index) { +// final order = _kycController.kycList[index]; +// return Padding( +// padding: const EdgeInsets.symmetric(vertical: 8), +// child: Card( +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Padding( +// padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), +// child: Row( +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// Text("Order ID: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), +// Text("${order.id}") +// ], +// ), +// ), +// Padding( +// padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), +// child: Row( +// crossAxisAlignment: CrossAxisAlignment.start, // Aligns the Column to the top of the Text +// children: [ +// Text( +// "Product Names: ", +// style: GoogleFonts.roboto( +// fontSize: 14, +// fontWeight: FontWeight.bold, +// ), +// ), +// Expanded( +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, // Aligns text to the right within the Column +// children: [ +// +// Text( +// '${capitalizeFirstLetter(order!.tradeName.toString())}', // Adds index and trims whitespace +// textAlign: TextAlign.left, // Aligns text to the right +// style: GoogleFonts.roboto( +// fontSize: 14, +// ), +// ), +// ], +// ), +// ), +// ], +// ), +// ), +// +// +// Padding( +// padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), +// child: Row( +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// Text("Order Date: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), +// Text(formatDate("${order.createdAt}")) +// ], +// ), +// ), +// Padding( +// padding: const EdgeInsets.fromLTRB(16, 8, 8, 8), +// child: Row( +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// Text("Status: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), +// Text(capitalizeFirstLetter("${order.status}")) +// ], +// ), +// ), +// SizedBox( +// width: Get.width * 0.4, +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: ElevatedButton( +// onPressed: ()=> +// Get.to(() => KycRetailerDetailScreen( +// kycModel: _kycController.kycList[index])), +// style: ElevatedButton.styleFrom( +// foregroundColor: Colors.white, +// backgroundColor: const Color(0xFF004791), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(10)), +// ), +// child: Text("View Details", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), +// ), +// ), +// ) +// ], +// ), +// ), +// ); +// }, +// ); +// }), +// ) +// ], +// ), +// ), +// ), +// ], +// ), +// ), +// ), +// ), +// ), +// ], +// ), +// ); +// } +// } +// diff --git a/lib/screens/kyc/kyc_verify_screen.dart b/lib/screens/kyc/kyc_verify_screen.dart new file mode 100644 index 0000000..d89e123 --- /dev/null +++ b/lib/screens/kyc/kyc_verify_screen.dart @@ -0,0 +1,232 @@ +import 'package:cheminova/models/kyc_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; + +import '../../controller/kyc_controller.dart'; + +class KycVerificationScreen1 extends StatefulWidget { + KycModel? kycModel; + KycVerificationScreen1({super.key,this.kycModel}); + + @override + State createState() => _KycVerificationScreen1State(); +} + +class _KycVerificationScreen1State extends State { + + final KycController _kycController = Get.put(KycController()); + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + centerTitle: true, + backgroundColor: Colors.transparent, + elevation: 0, + leading: GestureDetector( + onTap: () {}, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset( + 'assets/svg/menu.svg', + ), + ), + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset( + 'assets/svg/back_arrow.svg', + ), + ), + ), + ], + title: const Text( + "KYC Verification", + ), + ), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset( + 'assets/images/image_1.png', + fit: BoxFit.cover, + ), + SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(18.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox(height: Get.height * 0.02), + Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox(height: Get.height * 0.02), + SizedBox( + width: Get.width, + child: Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB( + 16, 8, 8, 0), + child: Text( + "Document Viewer", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.w700, + ), + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Image.network( + + _kycController.kycList[0].aadharImg!.url as String, + //"assets/images/aadhaar_card_sample_300_x_212.png", + fit: BoxFit.contain, + ), + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Image.network( + + _kycController.kycList[0].panImg!.url as String, + + //"assets/images/asample_of_permanent_account_number_pan_card.png", + fit: BoxFit.contain, + ), + ), + ), + ], + ), + ), + ), + SizedBox(height: Get.height * 0.01), + SizedBox( + width: Get.width, + child: Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB( + 16, 8, 8, 0), + child: Text( + "Verification Options", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.w700, + ), + ), + ), + Row( + children: [ + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () {}, + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: + const Color(0xFF004791), + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(10), + ), + ), + child: Text( + "Approve", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.w400, + ), + ), + ), + ), + ), + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () {}, + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: + const Color(0xFF910000), + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(10), + ), + ), + child: Text( + "Reject", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.w400, + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + ), + SizedBox(height: Get.height * 0.01), + Card( + child: SizedBox( + width: Get.width, + height: Get.height * 0.2, + child: Padding( + padding: const EdgeInsets.all(12), + child: Text( + "Comment:", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.w700, + ), + ), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ], + ), + ); + } +}