From 9cbb1d8cd58b0e2e4a57fc658c2cabdf8121b4a7 Mon Sep 17 00:00:00 2001 From: venbaittech Date: Tue, 23 Dec 2025 09:53:59 +0530 Subject: [PATCH] dashbaord login page changes --- .flutter-plugins-dependencies | 2 +- lib/core/services/api_service.dart | 24 +- lib/data/utils/commonLoaderButton.dart | 7 +- .../UserManagement/Profile/profile_web.dart | 24 +- .../screens/dashboard/tabs/bussiness.dart | 350 ++++-- .../screens/dashboard/tabs/partner.dart | 154 ++- .../screens/login/login_screen.dart | 1073 +++++++---------- lib/presentation/themes/charts/barChart.dart | 515 ++++---- .../themes/charts/barChart_horizontal.dart | 401 ++++++ 9 files changed, 1529 insertions(+), 1021 deletions(-) create mode 100644 lib/presentation/themes/charts/barChart_horizontal.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 3e03407..a59a342 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/device_info_plus-11.5.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.7/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_auth","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth-6.1.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core-4.2.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.4/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_secure_storage","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/home/venba/.pub-cache/hosted/pub.dev/fluttertoast-9.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_ios","path":"/home/venba/.pub-cache/hosted/pub.dev/google_sign_in_ios-6.2.1/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"/home/venba/.pub-cache/hosted/pub.dev/local_auth_darwin-1.6.0/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_ios","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_ios-1.0.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"pdf_render","path":"/home/venba/.pub-cache/hosted/pub.dev/pdf_render-1.4.12/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"syncfusion_flutter_pdfviewer","path":"/home/venba/.pub-cache/hosted/pub.dev/syncfusion_flutter_pdfviewer-31.1.19/","native_build":true,"dependencies":["device_info_plus"],"dev_dependency":false},{"name":"url_launcher_ios","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.4/","native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/device_info_plus-11.5.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.7/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"firebase_auth","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth-6.1.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core-4.2.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.4/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_plugin_android_lifecycle","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.31/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/home/venba/.pub-cache/hosted/pub.dev/fluttertoast-9.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_android","path":"/home/venba/.pub-cache/hosted/pub.dev/google_sign_in_android-7.2.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_android","path":"/home/venba/.pub-cache/hosted/pub.dev/local_auth_android-1.0.52/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"open_file_android","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_android-1.0.6/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_android-2.2.19/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"pdf_render","path":"/home/venba/.pub-cache/hosted/pub.dev/pdf_render-1.4.12/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.13/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"syncfusion_flutter_pdfviewer","path":"/home/venba/.pub-cache/hosted/pub.dev/syncfusion_flutter_pdfviewer-31.1.19/","native_build":true,"dependencies":["device_info_plus"],"dev_dependency":false},{"name":"url_launcher_android","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.20/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/device_info_plus-11.5.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.7/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_auth","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth-6.1.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core-4.2.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.4/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_secure_storage_macos","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage_macos-3.1.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_ios","path":"/home/venba/.pub-cache/hosted/pub.dev/google_sign_in_ios-6.2.1/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"/home/venba/.pub-cache/hosted/pub.dev/local_auth_darwin-1.6.0/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_mac","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_mac-1.0.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"pdf_render","path":"/home/venba/.pub-cache/hosted/pub.dev/pdf_render-1.4.12/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"syncfusion_pdfviewer_macos","path":"/home/venba/.pub-cache/hosted/pub.dev/syncfusion_pdfviewer_macos-31.1.19/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_macos","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.3/","native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/device_info_plus-11.5.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.7/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_linux-0.0.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false},{"name":"syncfusion_pdfviewer_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/syncfusion_pdfviewer_linux-31.1.19/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.2/","native_build":true,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/device_info_plus-11.5.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.7/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"firebase_auth","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth-6.1.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core-4.2.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/local_auth_windows-1.0.11/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_windows-0.0.3/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false},{"name":"syncfusion_pdfviewer_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/syncfusion_pdfviewer_windows-31.1.19/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.5/","native_build":true,"dependencies":[],"dev_dependency":false}],"web":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/device_info_plus-11.5.0/","dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.7/","dependencies":[],"dev_dependency":false},{"name":"firebase_auth_web","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth_web-6.1.0/","dependencies":["firebase_core_web"],"dev_dependency":false},{"name":"firebase_core_web","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core_web-3.3.0/","dependencies":[],"dev_dependency":false},{"name":"firebase_messaging_web","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_messaging_web-4.1.0/","dependencies":["firebase_core_web"],"dev_dependency":false},{"name":"flutter_secure_storage_web","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1/","dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/home/venba/.pub-cache/hosted/pub.dev/fluttertoast-9.0.0/","dependencies":[],"dev_dependency":false},{"name":"google_sign_in_web","path":"/home/venba/.pub-cache/hosted/pub.dev/google_sign_in_web-1.1.0/","dependencies":[],"dev_dependency":false},{"name":"open_file_web","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_web-0.0.4/","dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","dependencies":[],"dev_dependency":false},{"name":"pdf_render","path":"/home/venba/.pub-cache/hosted/pub.dev/pdf_render-1.4.12/","dependencies":[],"dev_dependency":false},{"name":"shared_preferences_web","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3/","dependencies":[],"dev_dependency":false},{"name":"syncfusion_pdfviewer_web","path":"/home/venba/.pub-cache/hosted/pub.dev/syncfusion_pdfviewer_web-31.1.19/","dependencies":[],"dev_dependency":false},{"name":"url_launcher_web","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_web-2.4.1/","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"connectivity_plus","dependencies":[]},{"name":"device_info_plus","dependencies":[]},{"name":"file_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"firebase_auth","dependencies":["firebase_auth_web","firebase_core"]},{"name":"firebase_auth_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"firebase_core","dependencies":["firebase_core_web"]},{"name":"firebase_core_web","dependencies":[]},{"name":"firebase_messaging","dependencies":["firebase_core","firebase_messaging_web"]},{"name":"firebase_messaging_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"flutter_secure_storage","dependencies":["flutter_secure_storage_linux","flutter_secure_storage_macos","flutter_secure_storage_web","flutter_secure_storage_windows"]},{"name":"flutter_secure_storage_linux","dependencies":[]},{"name":"flutter_secure_storage_macos","dependencies":[]},{"name":"flutter_secure_storage_web","dependencies":[]},{"name":"flutter_secure_storage_windows","dependencies":["path_provider"]},{"name":"fluttertoast","dependencies":[]},{"name":"google_sign_in","dependencies":["google_sign_in_android","google_sign_in_ios","google_sign_in_web"]},{"name":"google_sign_in_android","dependencies":[]},{"name":"google_sign_in_ios","dependencies":[]},{"name":"google_sign_in_web","dependencies":[]},{"name":"local_auth","dependencies":["local_auth_android","local_auth_darwin","local_auth_windows"]},{"name":"local_auth_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"local_auth_darwin","dependencies":[]},{"name":"local_auth_windows","dependencies":[]},{"name":"open_file","dependencies":["open_file_android","open_file_web","open_file_ios","open_file_mac","open_file_windows","open_file_linux"]},{"name":"open_file_android","dependencies":[]},{"name":"open_file_ios","dependencies":[]},{"name":"open_file_linux","dependencies":[]},{"name":"open_file_mac","dependencies":[]},{"name":"open_file_web","dependencies":[]},{"name":"open_file_windows","dependencies":[]},{"name":"package_info_plus","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"pdf_render","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]},{"name":"syncfusion_flutter_pdfviewer","dependencies":["url_launcher","device_info_plus","syncfusion_pdfviewer_web","syncfusion_pdfviewer_macos","syncfusion_pdfviewer_windows","syncfusion_pdfviewer_linux"]},{"name":"syncfusion_pdfviewer_linux","dependencies":[]},{"name":"syncfusion_pdfviewer_macos","dependencies":[]},{"name":"syncfusion_pdfviewer_web","dependencies":[]},{"name":"syncfusion_pdfviewer_windows","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_android","url_launcher_ios","url_launcher_linux","url_launcher_macos","url_launcher_web","url_launcher_windows"]},{"name":"url_launcher_android","dependencies":[]},{"name":"url_launcher_ios","dependencies":[]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2025-12-16 18:42:23.775793","version":"3.32.1","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/device_info_plus-11.5.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.7/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_auth","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth-6.1.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core-4.2.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.4/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_secure_storage","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/home/venba/.pub-cache/hosted/pub.dev/fluttertoast-9.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_ios","path":"/home/venba/.pub-cache/hosted/pub.dev/google_sign_in_ios-6.2.1/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"/home/venba/.pub-cache/hosted/pub.dev/local_auth_darwin-1.6.0/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_ios","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_ios-1.0.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"pdf_render","path":"/home/venba/.pub-cache/hosted/pub.dev/pdf_render-1.4.12/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"syncfusion_flutter_pdfviewer","path":"/home/venba/.pub-cache/hosted/pub.dev/syncfusion_flutter_pdfviewer-31.1.19/","native_build":true,"dependencies":["device_info_plus"],"dev_dependency":false},{"name":"url_launcher_ios","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.4/","native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/device_info_plus-11.5.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.7/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"firebase_auth","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth-6.1.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core-4.2.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.4/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_plugin_android_lifecycle","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.31/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/home/venba/.pub-cache/hosted/pub.dev/fluttertoast-9.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_android","path":"/home/venba/.pub-cache/hosted/pub.dev/google_sign_in_android-7.2.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_android","path":"/home/venba/.pub-cache/hosted/pub.dev/local_auth_android-1.0.52/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"open_file_android","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_android-1.0.6/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_android-2.2.19/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"pdf_render","path":"/home/venba/.pub-cache/hosted/pub.dev/pdf_render-1.4.12/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.13/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"syncfusion_flutter_pdfviewer","path":"/home/venba/.pub-cache/hosted/pub.dev/syncfusion_flutter_pdfviewer-31.1.19/","native_build":true,"dependencies":["device_info_plus"],"dev_dependency":false},{"name":"url_launcher_android","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.20/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/device_info_plus-11.5.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.7/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_auth","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth-6.1.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core-4.2.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.4/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_secure_storage_macos","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage_macos-3.1.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_ios","path":"/home/venba/.pub-cache/hosted/pub.dev/google_sign_in_ios-6.2.1/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"/home/venba/.pub-cache/hosted/pub.dev/local_auth_darwin-1.6.0/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_mac","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_mac-1.0.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"pdf_render","path":"/home/venba/.pub-cache/hosted/pub.dev/pdf_render-1.4.12/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"syncfusion_pdfviewer_macos","path":"/home/venba/.pub-cache/hosted/pub.dev/syncfusion_pdfviewer_macos-31.1.19/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_macos","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.3/","native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/device_info_plus-11.5.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.7/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_linux-0.0.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false},{"name":"syncfusion_pdfviewer_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/syncfusion_pdfviewer_linux-31.1.19/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.2/","native_build":true,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/device_info_plus-11.5.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.7/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"firebase_auth","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth-6.1.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core-4.2.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/local_auth_windows-1.0.11/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_windows-0.0.3/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false},{"name":"syncfusion_pdfviewer_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/syncfusion_pdfviewer_windows-31.1.19/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.5/","native_build":true,"dependencies":[],"dev_dependency":false}],"web":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/device_info_plus-11.5.0/","dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.7/","dependencies":[],"dev_dependency":false},{"name":"firebase_auth_web","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth_web-6.1.0/","dependencies":["firebase_core_web"],"dev_dependency":false},{"name":"firebase_core_web","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core_web-3.3.0/","dependencies":[],"dev_dependency":false},{"name":"firebase_messaging_web","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_messaging_web-4.1.0/","dependencies":["firebase_core_web"],"dev_dependency":false},{"name":"flutter_secure_storage_web","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1/","dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/home/venba/.pub-cache/hosted/pub.dev/fluttertoast-9.0.0/","dependencies":[],"dev_dependency":false},{"name":"google_sign_in_web","path":"/home/venba/.pub-cache/hosted/pub.dev/google_sign_in_web-1.1.0/","dependencies":[],"dev_dependency":false},{"name":"open_file_web","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_web-0.0.4/","dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","dependencies":[],"dev_dependency":false},{"name":"pdf_render","path":"/home/venba/.pub-cache/hosted/pub.dev/pdf_render-1.4.12/","dependencies":[],"dev_dependency":false},{"name":"shared_preferences_web","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3/","dependencies":[],"dev_dependency":false},{"name":"syncfusion_pdfviewer_web","path":"/home/venba/.pub-cache/hosted/pub.dev/syncfusion_pdfviewer_web-31.1.19/","dependencies":[],"dev_dependency":false},{"name":"url_launcher_web","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_web-2.4.1/","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"connectivity_plus","dependencies":[]},{"name":"device_info_plus","dependencies":[]},{"name":"file_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"firebase_auth","dependencies":["firebase_auth_web","firebase_core"]},{"name":"firebase_auth_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"firebase_core","dependencies":["firebase_core_web"]},{"name":"firebase_core_web","dependencies":[]},{"name":"firebase_messaging","dependencies":["firebase_core","firebase_messaging_web"]},{"name":"firebase_messaging_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"flutter_secure_storage","dependencies":["flutter_secure_storage_linux","flutter_secure_storage_macos","flutter_secure_storage_web","flutter_secure_storage_windows"]},{"name":"flutter_secure_storage_linux","dependencies":[]},{"name":"flutter_secure_storage_macos","dependencies":[]},{"name":"flutter_secure_storage_web","dependencies":[]},{"name":"flutter_secure_storage_windows","dependencies":["path_provider"]},{"name":"fluttertoast","dependencies":[]},{"name":"google_sign_in","dependencies":["google_sign_in_android","google_sign_in_ios","google_sign_in_web"]},{"name":"google_sign_in_android","dependencies":[]},{"name":"google_sign_in_ios","dependencies":[]},{"name":"google_sign_in_web","dependencies":[]},{"name":"local_auth","dependencies":["local_auth_android","local_auth_darwin","local_auth_windows"]},{"name":"local_auth_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"local_auth_darwin","dependencies":[]},{"name":"local_auth_windows","dependencies":[]},{"name":"open_file","dependencies":["open_file_android","open_file_web","open_file_ios","open_file_mac","open_file_windows","open_file_linux"]},{"name":"open_file_android","dependencies":[]},{"name":"open_file_ios","dependencies":[]},{"name":"open_file_linux","dependencies":[]},{"name":"open_file_mac","dependencies":[]},{"name":"open_file_web","dependencies":[]},{"name":"open_file_windows","dependencies":[]},{"name":"package_info_plus","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"pdf_render","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]},{"name":"syncfusion_flutter_pdfviewer","dependencies":["url_launcher","device_info_plus","syncfusion_pdfviewer_web","syncfusion_pdfviewer_macos","syncfusion_pdfviewer_windows","syncfusion_pdfviewer_linux"]},{"name":"syncfusion_pdfviewer_linux","dependencies":[]},{"name":"syncfusion_pdfviewer_macos","dependencies":[]},{"name":"syncfusion_pdfviewer_web","dependencies":[]},{"name":"syncfusion_pdfviewer_windows","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_android","url_launcher_ios","url_launcher_linux","url_launcher_macos","url_launcher_web","url_launcher_windows"]},{"name":"url_launcher_android","dependencies":[]},{"name":"url_launcher_ios","dependencies":[]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2025-12-19 18:43:25.853491","version":"3.32.1","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file diff --git a/lib/core/services/api_service.dart b/lib/core/services/api_service.dart index 3ee5dd1..021ffaf 100644 --- a/lib/core/services/api_service.dart +++ b/lib/core/services/api_service.dart @@ -133,7 +133,6 @@ class ApiService { return response; } - Future> logoutUsingAPI(agentId) async { // print(_token); if (_token == null) { @@ -177,8 +176,8 @@ class ApiService { } // 3. UNAUTHORIZED / FORBIDDEN (The 401/403 Fix) - if ((response.statusCode == 401 && body['status'] == 401) || (response.statusCode == 403 && body['status'] == 403)) { - + if ((response.statusCode == 401 && body['status'] == 401) || + (response.statusCode == 403 && body['status'] == 403)) { // Perform cleanup await AuthService.clearToken(); @@ -196,10 +195,8 @@ class ApiService { // 4. ALL OTHER ERRORS throw Exception('Server Error: ${response.statusCode}'); - } - Future> CheckDuplicate( BuildContext context, String value, @@ -454,6 +451,8 @@ class ApiService { } else if (path == 'PerformingTop50') { pathVal = 'dashboard/downloadAgentMonthlyPoliciesExcel?manager_id=$managerId&agent_id=$id'; + } else if (path == 'PerformingAgentAll50') { + pathVal = 'dashboard/downloadT50AgentPoliciesExcel?manager_id=$managerId'; } else if (path == 'NonPerformingBelow50K') { pathVal = 'dashboard/downloadLowPremiumAgentExcel?manager_id=$managerId'; } else { @@ -1972,10 +1971,10 @@ class ApiService { return response; } - - Future generatePolicyExcel(managerId,fromDate,toDate) async { - - final url = Uri.parse('${Env.apiUrl}reports/policy-excel?manager_id=$managerId&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}',); + Future generatePolicyExcel(managerId, fromDate, toDate) async { + final url = Uri.parse( + '${Env.apiUrl}reports/policy-excel?manager_id=$managerId&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}', + ); print('getPdfDownload policy-excel - $url'); await _initializeToken(); @@ -2042,14 +2041,15 @@ class ApiService { } Future> fetchAuditHistory(id) async { - - print( "fetchAuditHistory - $id " ); + print("fetchAuditHistory - $id "); if (_token == null) { await _initializeToken(); } // final url = Uri.parse('${Env.apiUrl}audit/history?table_name=partner_policy&pk=80',); - final url = Uri.parse('${Env.apiUrl}audit/history?table_name=partner_policy&pk=${id ?? ''}',); + final url = Uri.parse( + '${Env.apiUrl}audit/history?table_name=partner_policy&pk=${id ?? ''}', + ); final headers = { 'Authorization': 'Bearer $_token' ?? '', diff --git a/lib/data/utils/commonLoaderButton.dart b/lib/data/utils/commonLoaderButton.dart index 18a63f3..4d9d2cd 100644 --- a/lib/data/utils/commonLoaderButton.dart +++ b/lib/data/utils/commonLoaderButton.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:easy_loading_button/easy_loading_button.dart'; +import 'package:google_fonts/google_fonts.dart'; class CommonButton extends StatelessWidget { final String text; @@ -25,10 +26,10 @@ class CommonButton extends StatelessWidget { type: EasyButtonType.elevated, idleStateWidget: Text( text, - style: TextStyle( + style: GoogleFonts.poppins( color: textColor, - fontSize: 16, - fontWeight: FontWeight.w600, + fontSize: 14, + fontWeight: FontWeight.w500, ), ), loadingStateWidget: const CircularProgressIndicator( diff --git a/lib/presentation/screens/UserManagement/Profile/profile_web.dart b/lib/presentation/screens/UserManagement/Profile/profile_web.dart index 5d7ada5..2fef0b5 100644 --- a/lib/presentation/screens/UserManagement/Profile/profile_web.dart +++ b/lib/presentation/screens/UserManagement/Profile/profile_web.dart @@ -239,11 +239,7 @@ class ProfilePopUpState extends ConsumerState { ), ), const SizedBox(height: 26), - if (profileData?['mobile'] != null || - profileData!['mobile'] - .toString() - .trim() - .isNotEmpty) ...[ + if (hasValidValue(profileData?['mobile'])) ...[ Row( children: [ const Icon( @@ -260,11 +256,7 @@ class ProfilePopUpState extends ConsumerState { ), const SizedBox(height: 8), ], - if (profileData?['email'] != null || - profileData!['email'] - .toString() - .trim() - .isNotEmpty) ...[ + if (hasValidValue(profileData?['email'])) ...[ Row( children: [ const Icon( @@ -282,11 +274,7 @@ class ProfilePopUpState extends ConsumerState { const SizedBox(height: 16), ], - if (profileData?['address'] != null && - profileData!['address'] - .toString() - .trim() - .isNotEmpty) ...[ + if (hasValidValue(profileData?['address'])) ...[ if ((roleId != 1) && (roleId != 2) && (roleId != 3)) ...[ @@ -431,6 +419,12 @@ class ProfilePopUpState extends ConsumerState { ); } + bool hasValidValue(dynamic value) { + if (value == null) return false; + if (value is String) return value.trim().isNotEmpty; + return true; // for numbers, bool, etc. + } + static final _dataBold = TextStyle( fontSize: 11.8, fontWeight: FontWeight.w400, diff --git a/lib/presentation/screens/dashboard/tabs/bussiness.dart b/lib/presentation/screens/dashboard/tabs/bussiness.dart index fca0d93..bdd2e54 100644 --- a/lib/presentation/screens/dashboard/tabs/bussiness.dart +++ b/lib/presentation/screens/dashboard/tabs/bussiness.dart @@ -10,6 +10,7 @@ import '../../../../core/services/api_service.dart'; import '../../../../data/models/bar_data.dart'; import '../../../providers/userRoleProvider.dart'; import '../../../themes/charts/barChart.dart'; +import '../../../themes/charts/barChart_horizontal.dart'; import '../../../themes/indicators/input_field_decoration.dart'; class BussinessDashboard extends ConsumerStatefulWidget { @@ -163,7 +164,7 @@ class _BussinessDashboardState extends ConsumerState { } } - List buildInsurerBarData() { + List> getSortedInsurerWise() { double parseDouble(dynamic value) { if (value == null) return 0.0; if (value is num) return value.toDouble(); @@ -171,12 +172,45 @@ class _BussinessDashboardState extends ConsumerState { return 0.0; } - return filteredInsurerWise.map((item) { - print('policies_current - ${item['total_policies_current_month']}'); - print('policies_PREV - ${item['total_policies_pre_month']}'); + final List> sorted = List>.from( + filteredInsurerWise, + ); - print('premium_current - ${item['total_premium_current_month']}'); - print('premium_PREV - ${item['total_premium_pre_month']}'); + sorted.sort((a, b) { + final aCurrent = isInsureWisePolicy + ? parseDouble(a['total_policies_current_month']) + : parseDouble(a['total_premium_current_month']); + + final aPrev = isInsureWisePolicy + ? parseDouble(a['total_policies_pre_month']) + : parseDouble(a['total_premium_pre_month']); + + final bCurrent = isInsureWisePolicy + ? parseDouble(b['total_policies_current_month']) + : parseDouble(b['total_premium_current_month']); + + final bPrev = isInsureWisePolicy + ? parseDouble(b['total_policies_pre_month']) + : parseDouble(b['total_premium_pre_month']); + + final aMax = aCurrent > aPrev ? aCurrent : aPrev; + final bMax = bCurrent > bPrev ? bCurrent : bPrev; + + return bMax.compareTo(aMax); // DESC + }); + + return sorted; + } + + List buildInsurerBarData(List> sortedList) { + double parseDouble(dynamic value) { + if (value == null) return 0.0; + if (value is num) return value.toDouble(); + if (value is String) return double.tryParse(value) ?? 0.0; + return 0.0; + } + + return sortedList.map((item) { return BarData( Colors.blue, isInsureWisePolicy @@ -185,25 +219,23 @@ class _BussinessDashboardState extends ConsumerState { isInsureWisePolicy ? parseDouble(item['total_policies_pre_month']) : parseDouble(item['total_premium_pre_month']), - item['insurer_id'] != null ? item['insurer_id'] : '0', + item['insurer_id'] ?? '0', 'Insurer', 5, ); }).toList(); } - List buildInsurerLabels() { - return filteredInsurerWise.map((item) { + List buildInsurerLabels(List> sortedList) { + return sortedList.map((item) { final name = item['short_name']; - if (name != null && name.toString().trim().isNotEmpty) { - return name.toString(); - } else { - return item['short_name']?.toString() ?? ''; - } + return (name != null && name.toString().trim().isNotEmpty) + ? name.toString() + : ''; }).toList(); } - List buildBrokerBarData() { + List> getSortedBrokerWise() { double parseDouble(dynamic value) { if (value == null) return 0.0; if (value is num) return value.toDouble(); @@ -211,12 +243,45 @@ class _BussinessDashboardState extends ConsumerState { return 0.0; } - return filteredBrokerWise.map((item) { - print('policies_current - ${item['total_policies_current_month']}'); - print('policies_PREV - ${item['total_policies_pre_month']}'); + final List> sorted = List>.from( + filteredBrokerWise, + ); - print('premium_current - ${item['total_premium_current_month']}'); - print('premium_PREV - ${item['total_premium_pre_month']}'); + sorted.sort((a, b) { + final aCurrent = isBrokerWisePolicy + ? parseDouble(a['total_policies_current_month']) + : parseDouble(a['total_premium_current_month']); + + final aPrev = isBrokerWisePolicy + ? parseDouble(a['total_policies_pre_month']) + : parseDouble(a['total_premium_pre_month']); + + final bCurrent = isBrokerWisePolicy + ? parseDouble(b['total_policies_current_month']) + : parseDouble(b['total_premium_current_month']); + + final bPrev = isBrokerWisePolicy + ? parseDouble(b['total_policies_pre_month']) + : parseDouble(b['total_premium_pre_month']); + + final aMax = aCurrent > aPrev ? aCurrent : aPrev; + final bMax = bCurrent > bPrev ? bCurrent : bPrev; + + return bMax.compareTo(aMax); // 🔥 DESC + }); + + return sorted; + } + + List buildBrokerBarData(List> sortedList) { + double parseDouble(dynamic value) { + if (value == null) return 0.0; + if (value is num) return value.toDouble(); + if (value is String) return double.tryParse(value) ?? 0.0; + return 0.0; + } + + return sortedList.map((item) { return BarData( Colors.blue, isBrokerWisePolicy @@ -225,31 +290,97 @@ class _BussinessDashboardState extends ConsumerState { isBrokerWisePolicy ? parseDouble(item['total_policies_pre_month']) : parseDouble(item['total_premium_pre_month']), - item['broker_id'] != null ? item['broker_id'] : '0', + item['broker_id'] ?? '0', 'Broker', 5, ); }).toList(); } - List buildBrokerLabels() { - return filteredBrokerWise.map((item) { + List buildBrokerLabels(List> sortedList) { + return sortedList.map((item) { final name = item['broker_name']; - if (name != null && name.toString().trim().isNotEmpty) { - return name.toString(); - } else { - return item['broker_name']?.toString() ?? ''; - } + return (name != null && name.toString().trim().isNotEmpty) + ? name.toString() + : ''; }).toList(); } - List buildBrokerShortNames() { - return filteredBrokerWise.map((item) { + List buildBrokerShortNames(List> sortedList) { + return sortedList.map((item) { return item['broker_short_name']?.toString() ?? ''; }).toList(); } - List buildProductBarData() { + List> getSortedProductWise() { + double parseDouble(dynamic value) { + if (value == null) return 0.0; + if (value is num) return value.toDouble(); + if (value is String) return double.tryParse(value) ?? 0.0; + return 0.0; + } + + final List> sorted = List>.from( + filteredProductWise, + ); + + sorted.sort((a, b) { + final aCurrent = isProductWisePolicy + ? parseDouble(a['total_policies_current_month']) + : parseDouble(a['total_premium_current_month']); + + final aPrev = isProductWisePolicy + ? parseDouble(a['total_policies_pre_month']) + : parseDouble(a['total_premium_pre_month']); + + final bCurrent = isProductWisePolicy + ? parseDouble(b['total_policies_current_month']) + : parseDouble(b['total_premium_current_month']); + + final bPrev = isProductWisePolicy + ? parseDouble(b['total_policies_pre_month']) + : parseDouble(b['total_premium_pre_month']); + + final aMax = aCurrent > aPrev ? aCurrent : aPrev; + final bMax = bCurrent > bPrev ? bCurrent : bPrev; + + return bMax.compareTo(aMax); // DESC + }); + + return sorted; + } + + List buildProductBarData(List> sortedList) { + double parseDouble(dynamic value) { + if (value == null) return 0.0; + if (value is num) return value.toDouble(); + if (value is String) return double.tryParse(value) ?? 0.0; + return 0.0; + } + + return sortedList.map((item) { + return BarData( + Colors.blue, + isProductWisePolicy + ? parseDouble(item['total_policies_current_month']) + : parseDouble(item['total_premium_current_month']), + isProductWisePolicy + ? parseDouble(item['total_policies_pre_month']) + : parseDouble(item['total_premium_pre_month']), + item['vehicle_type']?.toString() ?? '', + 'Product', + 10, + ); + }).toList(); + } + + List buildProductLabels(List> sortedList) { + return sortedList.map((item) { + return item['vehicle_type']?.toString() ?? ''; + }).toList(); + } + + List buildProductBarData1() { double parseDouble(dynamic value) { if (value == null) return 0.0; if (value is num) return value.toDouble(); @@ -278,7 +409,7 @@ class _BussinessDashboardState extends ConsumerState { }).toList(); } - List buildProductLabels() { + List buildProductLabels1() { return filteredProductWise.map((item) { final name = item['vehicle_type']; if (name != null && name.toString().trim().isNotEmpty) { @@ -366,47 +497,96 @@ class _BussinessDashboardState extends ConsumerState { legendWidget(), ], ), - (showInsurer || showBroker) - ? Expanded( - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // if (showInsurer) Expanded(child: insurerContainer()), - // if (showBroker) Expanded(child: brokerContainer()), - showInsurer - ? Expanded(child: insurerContainer()) - : SizedBox(), - showBroker - ? Expanded(child: brokerContainer()) - : SizedBox(), - // showProduct ? Expanded(child: productContainer()) : SizedBox(), - ], - ), - ) - : SizedBox(), - if (showProduct) ...[ - SizedBox(height: 10), - Expanded( - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - showProduct - ? Expanded(child: productContainer()) - : SizedBox(), - ], - ), + + Expanded( + child: Row( + children: [ + (showInsurer || showBroker) + ? Expanded( + flex: 2, + child: Column( + children: [ + showInsurer + ? Expanded(child: insurerContainer()) + : SizedBox(), + showInsurer ? SizedBox(height: 10) : SizedBox(), + + showBroker + ? Expanded(child: brokerContainer()) + : SizedBox(), + ], + ), + ) + : SizedBox(), + + showProduct + ? Expanded(flex: 1, child: productContainer()) + : SizedBox(), + ], ), - ] else ...[ - SizedBox.shrink(), - ], + ), + + // (showInsurer || showBroker) + // ? Expanded( + // child: Row( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // if (showInsurer) Expanded(child: insurerContainer()), + // // if (showBroker) Expanded(child: brokerContainer()), + // showInsurer + // ? Expanded(child: insurerContainer()) + // : SizedBox(), + // showBroker + // ? Expanded(child: brokerContainer()) + // : SizedBox(), + // // showProduct ? Expanded(child: productContainer()) : SizedBox(), + // ], + // ), + // ) + // : SizedBox(), + + // if (showBroker) ...[ + // SizedBox(height: 10), + // Expanded( + // child: Row( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // showBroker ? Expanded(child: brokerContainer()) : SizedBox(), + // ], + // ), + // ), + // ] else ...[ + // SizedBox.shrink(), + // ], + // if (showProduct) ...[ + // SizedBox(height: 10), + // Expanded( + // child: Row( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // showProduct + // ? Expanded(child: productContainer()) + // : SizedBox(), + // ], + // ), + // ), + // ] else ...[ + // SizedBox.shrink(), + // ], ], ), ); } Widget insurerContainer() { - final chartInsurerData = buildInsurerBarData(); - final chartInsurerLabels = buildInsurerLabels(); + // final chartInsurerData = buildInsurerBarData(); + // final chartInsurerLabels = buildInsurerLabels(); + + final sortedInsurer = getSortedInsurerWise(); + + final chartInsurerData = buildInsurerBarData(sortedInsurer); + final chartInsurerLabels = buildInsurerLabels(sortedInsurer); + print('chartInsurerData - $chartInsurerData'); print('chartInsurerLabels - $chartInsurerLabels'); return Card( @@ -460,9 +640,15 @@ class _BussinessDashboardState extends ConsumerState { } Widget brokerContainer() { - final chartBrokerData = buildBrokerBarData(); - final chartBrokerLabels = buildBrokerLabels(); - final chartBrokerShortName = buildBrokerShortNames(); + // final chartBrokerData = buildBrokerBarData(); + // final chartBrokerLabels = buildBrokerLabels(); + // final chartBrokerShortName = buildBrokerShortNames(); + + final sortedBroker = getSortedBrokerWise(); + + final chartBrokerData = buildBrokerBarData(sortedBroker); + final chartBrokerLabels = buildBrokerLabels(sortedBroker); + final chartBrokerShortNames = buildBrokerShortNames(sortedBroker); print('chartBrokerData - $chartBrokerData'); print('chartBrokerLabels - $chartBrokerLabels'); return Card( @@ -498,7 +684,7 @@ class _BussinessDashboardState extends ConsumerState { Expanded( child: CustomBarChart( dataList: chartBrokerData, - labels: chartBrokerShortName, + labels: chartBrokerShortNames, shortName: chartBrokerLabels, // labels: chartBrokerLabels, @@ -513,8 +699,12 @@ class _BussinessDashboardState extends ConsumerState { } Widget productContainer() { - final chartProductData = buildProductBarData(); - final chartProductLabels = buildProductLabels(); + final sortedList = getSortedProductWise(); + + final chartProductData = buildProductBarData(sortedList); + final chartProductLabels = buildProductLabels(sortedList); + // final chartProductData = buildProductBarData(); + // final chartProductLabels = buildProductLabels(); print('chartProductData - $chartProductData'); print('chartProductLabels - $chartProductLabels'); return Card( @@ -547,7 +737,7 @@ class _BussinessDashboardState extends ConsumerState { ), SizedBox(height: 10), Expanded( - child: CustomBarChart( + child: CustomBarChartHorizontal( dataList: chartProductData, labels: chartProductLabels, ), @@ -563,11 +753,21 @@ class _BussinessDashboardState extends ConsumerState { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(Icons.circle, size: 10, color: Colors.cyan.shade300), + Icon( + Icons.circle, + size: 10, + color: Color(0xFF34a9a8), + // color: Colors.cyan.shade300 + ), SizedBox(width: 2), Text('Current Month', style: _styleSmall1), SizedBox(width: 5), - Icon(Icons.circle, size: 10, color: Colors.orange.shade300), + Icon( + Icons.circle, + size: 10, + // color: Colors.orange.shade300 + color: const Color(0xFFA5E4E1), + ), SizedBox(width: 2), Text('Previous Month', style: _styleSmall1), ], diff --git a/lib/presentation/screens/dashboard/tabs/partner.dart b/lib/presentation/screens/dashboard/tabs/partner.dart index e17fce2..dbdc258 100644 --- a/lib/presentation/screens/dashboard/tabs/partner.dart +++ b/lib/presentation/screens/dashboard/tabs/partner.dart @@ -332,9 +332,57 @@ class _DashboardState extends ConsumerState { child: Row( children: [ Expanded( - child: Text( - 'Performing Partner ( Top 50 )', - style: _chartHeader, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Performing Partner ( Top 50 )', + style: _chartHeader, + ), + + SizedBox(width: 10), + InkWell( + onTap: () async { + final path = + "PerformingAgentAll50"; + final id = ''; + final month = 'current'; + + await apiService + .generateChartExcel( + path, + id, + month, + managerId, + ); + }, + child: Tooltip( + message: 'Export Excel', + child: Container( + padding: const EdgeInsets.all( + 5.0, + ), + decoration: BoxDecoration( + color: const Color( + 0xFF2E7D6E, + ), + // color: const Color(0xFF425B5B), + borderRadius: + BorderRadius.circular( + 2.0, + ), + ), + child: Image.asset( + "assets/miscellaneous/export.png", + height: 11, + width: 11, + // color: Colors.green, + ), + ), + ), + ), + ], ), ), @@ -406,6 +454,8 @@ class _DashboardState extends ConsumerState { ), ), + SizedBox(width: 10), + Text( isNonPerfomingAgntPolicy ? "No Business" @@ -429,6 +479,42 @@ class _DashboardState extends ConsumerState { }, ), ), + SizedBox(width: 5), + InkWell( + onTap: () async { + final path = isNonPerfomingAgntPolicy + ? "NoBusiness" + : "NonPerformingBelow50K"; + final id = ''; + final month = 'current'; + + await apiService.generateChartExcel( + path, + id, + month, + managerId, + ); + }, + child: Tooltip( + message: 'Export Excel', + child: Container( + padding: const EdgeInsets.all(5.0), + decoration: BoxDecoration( + color: const Color(0xFF2E7D6E), + // color: const Color(0xFF425B5B), + borderRadius: BorderRadius.circular( + 2.0, + ), + ), + child: Image.asset( + "assets/miscellaneous/export.png", + height: 11, + width: 11, + // color: Colors.green, + ), + ), + ), + ), ], ), Expanded( @@ -624,39 +710,43 @@ class _PerformanceState extends State { ), ], SizedBox(width: 10), - InkWell( - onTap: () async { - final path1 = 'PerformingTop50'; - final path2 = widget.isPerfomingAgntPolicy - ? "NoBusiness" - : "NonPerformingBelow50K"; - final path = (widget.title == 'Performing Partner') - ? path1 - : path2; - final id = - ((widget.title == 'Performing Partner') && - (row['agent_id'] != null)) - ? row['agent_id'] - : ''; - final month = 'current'; + if (widget.title == 'Performing Partner') ...[ + InkWell( + onTap: () async { + final path1 = 'PerformingTop50'; + final path2 = widget.isPerfomingAgntPolicy + ? "NoBusiness" + : "NonPerformingBelow50K"; + final path = + (widget.title == 'Performing Partner') + ? path1 + : path2; - await widget.apiService.generateChartExcel( - path, - id, - month, - widget.managerId, - ); - }, - child: Tooltip( - message: 'Click To Download Excel', - child: Icon( - Icons.download, - size: 14, - color: Colors.green.shade300, + final id = + ((widget.title == 'Performing Partner') && + (row['agent_id'] != null)) + ? row['agent_id'] + : ''; + final month = 'current'; + + await widget.apiService.generateChartExcel( + path, + id, + month, + widget.managerId, + ); + }, + child: Tooltip( + message: 'Click To Download Excel', + child: Icon( + Icons.download, + size: 14, + color: Colors.green.shade300, + ), ), ), - ), + ], ], ), ); diff --git a/lib/presentation/screens/login/login_screen.dart b/lib/presentation/screens/login/login_screen.dart index 4e6a264..6f2981c 100644 --- a/lib/presentation/screens/login/login_screen.dart +++ b/lib/presentation/screens/login/login_screen.dart @@ -38,6 +38,9 @@ class _LoginScreenState extends ConsumerState { final TextEditingController _PhoneNumberController = TextEditingController(); final TextEditingController _otpController = TextEditingController(); final TextEditingController _countryController = TextEditingController(); + + final TextEditingController _loginController = TextEditingController(); + final FirebaseAuth _auth = FirebaseAuth.instance; late String _verificationId; int? _resendToken; @@ -50,47 +53,10 @@ class _LoginScreenState extends ConsumerState { dynamic token; dynamic fCMToken; - // Future _handleLogin() async { - // if (!_formKey.currentState!.validate()) return; - // - // setState(() => _isLoading = true); - // - // // Simulate API call - // await Future.delayed(const Duration(seconds: 2)); - // - // // TODO: Replace with your AuthService - // final success = - // _emailController.text == "test@example.com" && - // // _passwordController.text == "password"; - // - // // setState(() => _isLoading = false); - // - // print("Succes - $success"); - // if (success) { - // print("Ckeck 1"); - // if (mounted) { - // print("Ckeck 2"); - // await AuthService.saveToken('1234'); - // final dynamic token = AuthService.saveToken('1234'); - // print('token - $token'); - // - // print('AppRoutes.home'); - // context.go(AppRoutes.home); - // print("Ckeck 3"); - // } - // } else { - // if (mounted) { - // ScaffoldMessenger.of( - // context, - // ).showSnackBar(const SnackBar(content: Text("Invalid credentials"))); - // } - // } - // } - final defaultPinTheme = PinTheme( width: 56, height: 56, - textStyle: TextStyle( + textStyle: GoogleFonts.poppins( fontSize: 20, color: Color.fromRGBO(30, 60, 87, 1), fontWeight: FontWeight.w600, @@ -210,141 +176,321 @@ class _LoginScreenState extends ConsumerState { // final userId = ref.watch(userIdProvider); } - // Future _saveManagerId(String token) async { - // Map? decodedToken = await Jwt.parseJwt(token); - // print('decodedToken : $decodedToken'); - // final dynamic managerIdRaw = decodedToken['data']?['manager_id']; - // final int? managerId = managerIdRaw is int - // ? managerIdRaw - // : int.tryParse(managerIdRaw.toString()); - // - // if (managerId != null) { - // ref.read(managerIdProvider.notifier).state = managerId; - // print("Manager ID saved globally: $managerId"); - // } else { - // print("Manager ID is null or invalid"); - // } - // print(managerId); - // // final managerId = ref.watch(managerIdProvider); - // } - - Future sendMobileOrEmailVerify(String loginUser) async { - // await Future.delayed(const Duration(seconds: 5)); + Future verifyOTP(String otp) async { try { - if (_formKey.currentState!.validate()) { - String apiEndpoint; - if (loginUser == 'agent') { - apiEndpoint = switcherStatus == 1 - ? Env.apiUrl + 'auth/verifyAgentWithMobileNumber' - : Env.apiUrl + 'auth/verifyAgentWithEmailId'; - } else { - apiEndpoint = switcherStatus == 1 - ? Env.apiUrl + 'auth/verifyStaffWithMobileNumber' - : Env.apiUrl + 'auth/verifyStaffWithEmailId'; - } + final input = _loginController.text.trim(); - Map payload = switcherStatus == 1 - ? {'mobile': _PhoneNumberController.text} - : {'email': _emailController.text}; - - final response = await http.post( - Uri.parse(apiEndpoint), - body: json.encode(payload), - headers: { - HttpHeaders.contentTypeHeader: 'application/json', - 'app-signature': Env.App_Signature, - }, - ); - - if (response.statusCode == 200) { - final data = json.decode(response.body); - - final verification = loginUser == 'agent' - ? data['data']['agent_verification'] - : data['data']['Staff_verification']; - - final message = data['data']['message']; - - // setState(() { - // enteredEmailOrMobile = true; - // }); - - if (verification == true) { - // if (switcherStatus == 1) { - // _verifyPhoneNumber(); - // } else { - setState(() { - enteredEmailOrMobile = true; - }); - ToastHelper.showSuccessToast(context, 'OTP sent successfully'); - // } - return true; // ✅ success - } else { - ToastHelper.showErrorToast(context, message); - return false; // ❌ fail - } - } else { - ToastHelper.showErrorToast(context, 'Something went wrong'); - return false; // ❌ fail - } + if (!isEmail(input) && !isMobile(input)) { + ToastHelper.showErrorToast(context, 'Enter valid email or mobile'); + return; } - return false; - } catch (e) { - ToastHelper.showErrorToast(context, 'Something went wrong'); - print('Error: $e'); - return false; - } - } - Future verifyMobileOrMailOTP(otpVerifyStatus) async { - try { - // Select API endpoint final String apiEndpoint = (clickedButtonName == 'agent') ? '${Env.apiUrl}auth/getVerifiedAgentData' : '${Env.apiUrl}auth/getVerifiedStaffData'; - // Build payload depending on switcher status - final Map payload = (switcherStatus == 1) - ? { - 'otp': otpVerifyStatus, - 'mobile': _PhoneNumberController.text.trim(), - } - : {'otp': otpVerifyStatus, 'email': _emailController.text.trim()}; + final Map payload = { + 'otp': otp, + if (isEmail(input)) 'email': input, + if (isMobile(input)) 'mobile': input, + }; - // Send request final response = await http.post( Uri.parse(apiEndpoint), - body: json.encode(payload), headers: { HttpHeaders.contentTypeHeader: 'application/json', 'app-signature': Env.App_Signature, }, + body: json.encode(payload), ); - // Check response if (response.statusCode == 200) { - final Map data = json.decode(response.body); + final data = json.decode(response.body); - final String status = data['status']?.toString() ?? 'error'; - token = data['data']; // can be string or object + if (data['status'] == 'success') { + ToastHelper.showSuccessToast(context, 'OTP verified'); + token = data['data']; - print('Response status: ${response.statusCode}'); - print('Response body: $data'); - - if (status == 'success') { - ToastHelper.showSuccessToast(context, 'OTP verified successfully'); await AuthService.saveToken(token); await _saveUserRole(token); await _saveIdsFromToken(token); - final managerId = ref.watch(managerIdProvider); - print('managerId -- $managerId'); + + final role = ref.watch(userRoleProvider); + + if (role == 'staff') { + context.go(AppRoutes.enquiryForStaff); + } else if (role == 'Accounts') { + context.go(AppRoutes.invoiceList); + } else { + context.go(AppRoutes.dashboard); + } + } else { + ToastHelper.showErrorToast(context, data['message'] ?? 'Invalid OTP'); + } + } else { + ToastHelper.showErrorToast(context, 'Server error'); + } + } catch (e) { + ToastHelper.showErrorToast(context, 'Something went wrong'); + } + } + + // Future sendMobileOrEmailVerify(String loginUser) async { + // // await Future.delayed(const Duration(seconds: 5)); + // try { + // if (_formKey.currentState!.validate()) { + // String apiEndpoint; + // if (loginUser == 'agent') { + // apiEndpoint = switcherStatus == 1 + // ? Env.apiUrl + 'auth/verifyAgentWithMobileNumber' + // : Env.apiUrl + 'auth/verifyAgentWithEmailId'; + // } else { + // apiEndpoint = switcherStatus == 1 + // ? Env.apiUrl + 'auth/verifyStaffWithMobileNumber' + // : Env.apiUrl + 'auth/verifyStaffWithEmailId'; + // } + // + // Map payload = switcherStatus == 1 + // ? {'mobile': _PhoneNumberController.text} + // : {'email': _emailController.text}; + // + // final response = await http.post( + // Uri.parse(apiEndpoint), + // body: json.encode(payload), + // headers: { + // HttpHeaders.contentTypeHeader: 'application/json', + // 'app-signature': Env.App_Signature, + // }, + // ); + // + // if (response.statusCode == 200) { + // final data = json.decode(response.body); + // + // final verification = loginUser == 'agent' + // ? data['data']['agent_verification'] + // : data['data']['Staff_verification']; + // + // final message = data['data']['message']; + // + // // setState(() { + // // enteredEmailOrMobile = true; + // // }); + // + // if (verification == true) { + // // if (switcherStatus == 1) { + // // _verifyPhoneNumber(); + // // } else { + // setState(() { + // enteredEmailOrMobile = true; + // }); + // ToastHelper.showSuccessToast(context, 'OTP sent successfully'); + // // } + // return true; // ✅ success + // } else { + // ToastHelper.showErrorToast(context, message); + // return false; // ❌ fail + // } + // } else { + // ToastHelper.showErrorToast(context, 'Something went wrong'); + // return false; // ❌ fail + // } + // } + // return false; + // } catch (e) { + // ToastHelper.showErrorToast(context, 'Something went wrong'); + // print('Error: $e'); + // return false; + // } + // } + + Future sendMobileOrEmailVerify( + String loginUser, + Map payload, + ) async { + try { + if (!_formKey.currentState!.validate()) return false; + + String apiEndpoint; + + if (loginUser == 'agent') { + apiEndpoint = payload.containsKey('mobile') + ? '${Env.apiUrl}auth/verifyAgentWithMobileNumber' + : '${Env.apiUrl}auth/verifyAgentWithEmailId'; + } else { + apiEndpoint = payload.containsKey('mobile') + ? '${Env.apiUrl}auth/verifyStaffWithMobileNumber' + : '${Env.apiUrl}auth/verifyStaffWithEmailId'; + } + + final response = await http.post( + Uri.parse(apiEndpoint), + headers: { + HttpHeaders.contentTypeHeader: 'application/json', + 'app-signature': Env.App_Signature, + }, + body: json.encode(payload), + ); + + if (response.statusCode == 200) { + final data = json.decode(response.body); + + final verification = loginUser == 'agent' + ? data['data']['agent_verification'] + : data['data']['Staff_verification']; + + if (verification == true) { + setState(() => enteredEmailOrMobile = true); + ToastHelper.showSuccessToast(context, 'OTP sent successfully'); + return true; + } else { + ToastHelper.showErrorToast(context, data['data']['message']); + return false; + } + } + + ToastHelper.showErrorToast(context, 'Something went wrong'); + return false; + } catch (e) { + ToastHelper.showErrorToast(context, 'Something went wrong'); + return false; + } + } + + Future sendOTP(String role) async { + final input = _loginController.text.trim(); + + if (!isEmail(input) && !isMobile(input)) { + ToastHelper.showErrorToast(context, 'Enter valid email or mobile'); + return false; + } + + clickedButtonName = role; + + final payload = { + if (isEmail(input)) 'email': input, + if (isMobile(input)) 'mobile': input, + }; + + return await sendMobileOrEmailVerify(role, payload); + } + + // Future verifyMobileOrMailOTP(otpVerifyStatus) async { + // try { + // // Select API endpoint + // final String apiEndpoint = (clickedButtonName == 'agent') + // ? '${Env.apiUrl}auth/getVerifiedAgentData' + // : '${Env.apiUrl}auth/getVerifiedStaffData'; + // + // // Build payload depending on switcher status + // final Map payload = (switcherStatus == 1) + // ? { + // 'otp': otpVerifyStatus, + // 'mobile': _PhoneNumberController.text.trim(), + // } + // : {'otp': otpVerifyStatus, 'email': _emailController.text.trim()}; + // + // // Send request + // final response = await http.post( + // Uri.parse(apiEndpoint), + // body: json.encode(payload), + // headers: { + // HttpHeaders.contentTypeHeader: 'application/json', + // 'app-signature': Env.App_Signature, + // }, + // ); + // + // // Check response + // if (response.statusCode == 200) { + // final Map data = json.decode(response.body); + // + // final String status = data['status']?.toString() ?? 'error'; + // token = data['data']; // can be string or object + // + // print('Response status: ${response.statusCode}'); + // print('Response body: $data'); + // + // if (status == 'success') { + // ToastHelper.showSuccessToast(context, 'OTP verified successfully'); + // await AuthService.saveToken(token); + // await _saveUserRole(token); + // await _saveIdsFromToken(token); + // final managerId = ref.watch(managerIdProvider); + // print('managerId -- $managerId'); + // final userRole = ref.watch(userRoleProvider); + // print('userRole -- $userRole'); + // + // if (userRole == 'staff') { + // context.go(AppRoutes.enquiryForStaff); + // } else if (userRole == 'Accounts') { + // // context.go(AppRoutes.payout); + // context.go(AppRoutes.invoiceList); + // } else { + // context.go(AppRoutes.dashboard); + // } + // } else { + // ToastHelper.showErrorToast(context, data['message'] ?? 'Invalid OTP'); + // } + // } else { + // ToastHelper.showErrorToast( + // context, + // 'Server error: ${response.statusCode}', + // ); + // } + // } catch (e, stacktrace) { + // print('Error verifying OTP: $e'); + // print(stacktrace); + // ToastHelper.showErrorToast( + // context, + // 'Something went wrong. Please try again.', + // ); + // } + // } + + Future verifyMobileOrMailOTP(String otp) async { + try { + final input = _loginController.text.trim(); + + if (!isEmail(input) && !isMobile(input)) { + ToastHelper.showErrorToast(context, 'Invalid email or mobile'); + return; + } + + final String apiEndpoint = (clickedButtonName == 'agent') + ? '${Env.apiUrl}auth/getVerifiedAgentData' + : '${Env.apiUrl}auth/getVerifiedStaffData'; + + final Map payload = { + 'otp': otp, + if (isEmail(input)) 'email': input, + if (isMobile(input)) 'mobile': input, + }; + + final response = await http.post( + Uri.parse(apiEndpoint), + headers: { + HttpHeaders.contentTypeHeader: 'application/json', + 'app-signature': Env.App_Signature, + }, + body: json.encode(payload), + ); + + if (response.statusCode == 200) { + final Map data = json.decode(response.body); + + if (data['status'] == 'success') { + token = data['data']; + + ToastHelper.showSuccessToast(context, 'OTP verified successfully'); + + await AuthService.saveToken(token); + await _saveUserRole(token); + await _saveIdsFromToken(token); + final userRole = ref.watch(userRoleProvider); - print('userRole -- $userRole'); if (userRole == 'staff') { context.go(AppRoutes.enquiryForStaff); } else if (userRole == 'Accounts') { - // context.go(AppRoutes.payout); context.go(AppRoutes.invoiceList); } else { context.go(AppRoutes.dashboard); @@ -359,8 +505,8 @@ class _LoginScreenState extends ConsumerState { ); } } catch (e, stacktrace) { - print('Error verifying OTP: $e'); - print(stacktrace); + debugPrint('Error verifying OTP: $e'); + debugPrint('$stacktrace'); ToastHelper.showErrorToast( context, 'Something went wrong. Please try again.', @@ -393,7 +539,7 @@ class _LoginScreenState extends ConsumerState { if (userCredential.user != null) { print('otp firebase check done'); bool otpVerifyStatus = true; - await verifyMobileOrMailOTP(otpVerifyStatus); + await verifyMobileOrMailOTP(_otpController.text); } else { ToastHelper.showErrorToast(context, 'Invalid OTP. Please try again.'); } @@ -535,40 +681,6 @@ class _LoginScreenState extends ConsumerState { ); } - // void _resendCode(String mobileNumber, int? resendToken) async { - // await _auth.verifyPhoneNumber( - // phoneNumber: '${_countryController.text + mobileNumber}', - // timeout: const Duration(seconds: 60), - // forceResendingToken: resendToken, - // verificationCompleted: (PhoneAuthCredential credential) async { - // await _auth.signInWithCredential(credential); - // }, - // verificationFailed: (FirebaseAuthException e) { - // if (e.code == 'invalid-phone-number') { - // print('The provided phone number is not valid.'); - // } - // }, - // codeSent: (String verificationId, int? resendToken) async { - // final prefs = await SharedPreferences.getInstance(); - // await prefs.setString('verificationId', verificationId); - // setState(() { - // _verificationId = verificationId; - // _resendToken = resendToken; - // }); - // ToastHelper.showSuccessToast( - // context, - // 'Verification code resent to ${mobileNumber}', - // ); - // }, - // codeAutoRetrievalTimeout: (String verificationId) async { - // final prefs = await SharedPreferences.getInstance(); - // await prefs.setString('verificationId', verificationId); - // setState(() { - // _verificationId = verificationId; - // }); - // }, - // ); - // } void _resendCode(String mobileNumber, int? resendToken) async { await _auth.verifyPhoneNumber( phoneNumber: '${_countryController.text + mobileNumber}', @@ -604,137 +716,21 @@ class _LoginScreenState extends ConsumerState { ); } - // Future _verifyPhoneNumber() async { - // var enteredMobileNumber = mobileController.text; - // var countryCode = countryController.text; - // print('${countryCode + enteredMobileNumber}'); - // await _auth.verifyPhoneNumber( - // phoneNumber: '${countryCode + enteredMobileNumber}', - // timeout: const Duration(seconds: 60), - // verificationCompleted: (PhoneAuthCredential credential) async { - // await _auth.signInWithCredential(credential); - // // ToastHelper.showSuccessToast(context, 'Verified Successfully!'); - // // setState(() { - // // _isLoading = false; - // // }); - // }, - // verificationFailed: (FirebaseAuthException e) { - // print('Verification Failed: ${e.code} - ${e.message}'); - // String errorMessage; - // if (e.code == 'invalid-app-credential') { - // errorMessage = 'Invalid Credential. Please try again.'; - // } else if (e.code == 'invalid-phone-number') { - // errorMessage = 'The provided phone number is not valid.'; - // } else if (e.code == 'too-many-requests') { - // errorMessage = 'Too many requests. Try again later.'; - // } else { - // errorMessage = 'Verification Failed: ${e.message}'; - // } - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // content: Text(errorMessage), - // duration: Duration(seconds: 2), - // ), - // ); - // - // ToastHelper.showSuccessToast(context, errorMessage); - // setState(() { - // _isLoading = false; - // }); - // }, - // codeSent: (String verificationId, int? resendToken) async { - // setState(() { - // _verificationId = verificationId; - // _resendToken = resendToken; - // }); - // - // // When getting the verificationId - // SharedPreferences prefs = await SharedPreferences.getInstance(); - // prefs.setString('verificationId', _verificationId); - // - // - // ToastHelper.showSuccessToast( - // context, 'Verification code sent to ${enteredMobileNumber}'); - // - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => MyVerify( - // verificationId: _verificationId, - // mobileNumber: enteredMobileNumber, - // resendToken: _resendToken, - // onResendCode: _resendCode, // Pass the phone number - // ), - // ), - // ); - // setState(() { - // _isLoading = false; - // }); - // }, - // codeAutoRetrievalTimeout: (String verificationId) async{ - // setState(() { - // _verificationId = verificationId; - // }); - // final prefs = await SharedPreferences.getInstance(); - // await prefs.setString('verificationId', verificationId); - // ToastHelper.showSuccessToast(context, 'Code auto-retrieval timed out.'); - // setState(() { - // _isLoading = false; - // }); - // }, - // ); - // } - // - // void _resendCode(String mobileNumber, int? resendToken) async { - // await _auth.verifyPhoneNumber( - // phoneNumber: '${countryController.text + mobileNumber}', - // timeout: const Duration(seconds: 60), - // forceResendingToken: resendToken, - // verificationCompleted: (PhoneAuthCredential credential) async { - // await _auth.signInWithCredential(credential); - // }, - // verificationFailed: (FirebaseAuthException e) { - // if (e.code == 'invalid-phone-number') { - // print('The provided phone number is not valid.'); - // } - // }, - // codeSent: (String verificationId, int? resendToken) async{ - // final prefs = await SharedPreferences.getInstance(); - // await prefs.setString('verificationId', verificationId); - // setState(() { - // _verificationId = verificationId; - // _resendToken = resendToken; - // }); - // ToastHelper.showSuccessToast( - // context, 'Verification code resent to ${mobileNumber}'); - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => MyVerify( - // verificationId: _verificationId, - // mobileNumber: mobileNumber, - // resendToken: _resendToken, - // onResendCode: _resendCode, - // ), - // ), - // ); - // }, - // codeAutoRetrievalTimeout: (String verificationId) async{ - // final prefs = await SharedPreferences.getInstance(); - // await prefs.setString('verificationId', verificationId); - // setState(() { - // _verificationId = verificationId; - // }); - // }, - // ); - // } + Future resendOTP() async { + final input = _loginController.text.trim(); - // Future sendMobileOrEmailVerify() async { - // if (!_formKey.currentState!.validate()) return; - // setState(() { - // enteredEmailOrMobile = true; - // }); - // } + if (!isEmail(input) && !isMobile(input)) { + ToastHelper.showErrorToast(context, 'Invalid email or mobile'); + return; + } + + final payload = { + if (isEmail(input)) 'email': input, + if (isMobile(input)) 'mobile': input, + }; + + await sendMobileOrEmailVerify(clickedButtonName, payload); + } Widget build(BuildContext context) { return Scaffold( @@ -763,7 +759,7 @@ class _LoginScreenState extends ConsumerState { children: [ Text( "Welcome Back", - style: TextStyle( + style: GoogleFonts.poppins( fontSize: 50, fontWeight: FontWeight.w600, color: Color(0xFF425C5C), @@ -778,11 +774,11 @@ class _LoginScreenState extends ConsumerState { fit: BoxFit.contain, ), const SizedBox(height: 10), - const Text( + Text( '${'"'}Manage your policies, track quotations, and grow your business all in one place.${'"'}', textAlign: TextAlign.center, - style: TextStyle( - fontSize: 18, + style: GoogleFonts.poppins( + fontSize: 14, color: Color(0xFF000000), fontWeight: FontWeight.w500, ), @@ -850,7 +846,7 @@ class _LoginScreenState extends ConsumerState { child: Text( '${'"'}Manage your policies, track quotations, and grow your business all in one place.${'"'}', textAlign: TextAlign.center, - style: TextStyle( + style: GoogleFonts.poppins( fontSize: 14, color: Color(0xFF000000), fontWeight: FontWeight.w500, @@ -896,9 +892,9 @@ class _LoginScreenState extends ConsumerState { children: [ Text( "Login to your account", - style: TextStyle( + style: GoogleFonts.poppins( fontSize: ResponsiveLayout.isMobile(context) ? 20 : 35, - fontWeight: FontWeight.w600, + fontWeight: FontWeight.w500, color: Colors.white, ), ), @@ -906,34 +902,34 @@ class _LoginScreenState extends ConsumerState { Text( "Enter your email or mobile number to receive a one time password.", textAlign: TextAlign.center, - style: TextStyle( - fontSize: ResponsiveLayout.isMobile(context) ? 12 : 18, + style: GoogleFonts.poppins( + fontSize: ResponsiveLayout.isMobile(context) ? 12 : 14, color: Colors.white, - fontWeight: FontWeight.w600, + fontWeight: FontWeight.w400, ), ), const SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - padding: const EdgeInsets.all(3), - decoration: BoxDecoration( - color: Colors.grey.shade50, - borderRadius: BorderRadius.circular(50), - ), - - child: Row( - children: [ - buildTab("Mobile", 0), - const SizedBox(width: 10), - buildTab("Email", 1), - ], - ), - ), - ], - ), - const SizedBox(height: 30), + // Row( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Container( + // padding: const EdgeInsets.all(3), + // decoration: BoxDecoration( + // color: Colors.grey.shade50, + // borderRadius: BorderRadius.circular(50), + // ), + // + // child: Row( + // children: [ + // // buildTab("Mobile", 0), + // // const SizedBox(width: 10), + // // buildTab("Email", 1), + // ], + // ), + // ), + // ], + // ), + // const SizedBox(height: 30), Container( child: Form( key: _formKey, @@ -945,52 +941,23 @@ class _LoginScreenState extends ConsumerState { height: 70, child: Column( children: [ - if (switcherStatus == 0) - ThemedFormField( - hintText: 'Email', - backgroundColor: Colors.white, - validator: (value) => - Validators.email(value, "Email"), - // imgPath: "MiscIconAssetPath.person", - controller: _emailController, - inputFormatters: [ - FilteringTextInputFormatter.allow( - RegExp(r'[a-zA-Z0-9_@.]'), - ), - ], - ), - if (switcherStatus == 1) - ThemedFormField( - hintText: 'Mobile Number', - backgroundColor: Colors.white, - validator: (value) => - Validators.phone(value, "Phone"), - // imgPath: "MiscIconAssetPath.person", - controller: _PhoneNumberController, - - // txtwidth: MediaQuery.of(context).size.width * 0.5, - keyboardType: TextInputType.number, - maxLength: 10, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly, - ], - // readOnly: true, - ), - // const SizedBox(height: 16), - // ThemedFormField( - // hintText: 'Password', - // backgroundColor: Colors.white, - // validator: (value) => - // Validators.passwordlogIn(value, "Password"), - // // imgPath: "MiscIconAssetPath.person", - // controller: _passwordController, - // isObscurable: true, - // // txtwidth: MediaQuery.of(context).size.width * 0.5, - // // keyboardType: TextInputType.number, - // // maxLength: 10, - // // inputFormatters: [FilteringTextInputFormatter.digitsOnly], - // // readOnly: true, - // ), + ThemedFormField( + hintText: 'Email or Mobile Number', + controller: _loginController, + backgroundColor: Colors.white, + validator: (value) { + if (!isEmail(value!) && !isMobile(value)) { + return 'Enter valid email or mobile'; + } + return null; + }, + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9@._\-+]'), + ), + ], + keyboardType: TextInputType.emailAddress, + ), ], ), ), @@ -1003,15 +970,18 @@ class _LoginScreenState extends ConsumerState { height: 50, child: CommonButton( text: "Login as Partner", + backgroundColor: Color(0xFF436462), onPressed: () async { setState(() { clickedButtonName = 'agent'; }); // ⏳ Wait for API to finish - final success = await sendMobileOrEmailVerify( - 'agent', - ); + // final success = await sendMobileOrEmailVerify( + // 'agent', + // ); + + final success = await sendOTP('agent'); if (success) { // API success → loader stops immediately @@ -1022,31 +992,6 @@ class _LoginScreenState extends ConsumerState { } }, ), - // ElevatedButton( - // style: ElevatedButton.styleFrom( - // backgroundColor: Color(0xFF436462), - // padding: const EdgeInsets.symmetric(vertical: 16), - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(8), - // ), - // ), - // onPressed: () { - // sendMobileOrEmailVerify('agent'); - // setState(() { - // clickedButtonName = 'agent'; - // }); - // }, - // child: Text( - // 'Login as Agent', - // style: TextStyle( - // fontSize: ResponsiveLayout.isMobile(context) - // ? 18 - // : 20, - // fontWeight: FontWeight.w600, - // color: Colors.white, - // ), - // ), - // ), ), ), @@ -1056,7 +1001,7 @@ class _LoginScreenState extends ConsumerState { Container( child: Text( 'OR', - style: TextStyle( + style: GoogleFonts.poppins( fontSize: ResponsiveLayout.isMobile(context) ? 14 : 18, fontWeight: FontWeight.w600, color: Colors.white, @@ -1077,9 +1022,11 @@ class _LoginScreenState extends ConsumerState { clickedButtonName = 'staff'; }); // ⏳ Wait for API to finish - final success = await sendMobileOrEmailVerify( - 'staff', - ); + // final success = await sendMobileOrEmailVerify( + // 'staff', + // ); + + final success = await sendOTP('staff'); if (success) { // API success → loader stops immediately @@ -1090,120 +1037,10 @@ class _LoginScreenState extends ConsumerState { } }, ), - // ElevatedButton( - // style: ElevatedButton.styleFrom( - // backgroundColor: Color(0xFF436462), - // padding: const EdgeInsets.symmetric(vertical: 16), - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(8), - // ), - // ), - // onPressed: () { - // sendMobileOrEmailVerify('staff'); - // setState(() { - // clickedButtonName = 'staff'; - // }); - // }, - // child: Text( - // 'Login as Staff', - // style: TextStyle( - // fontSize: ResponsiveLayout.isMobile(context) - // ? 18 - // : 20, - // fontWeight: FontWeight.w600, - // color: Colors.white, - // ), - // ), - // ), ), ), ], - // if (enteredEmailOrMobile) ...[ - // Container( - // child: Text( - // 'OTP', - // style: TextStyle( - // fontSize: ResponsiveLayout.isMobile(context) ? 14 : 18, - // fontWeight: FontWeight.w600, - // color: Colors.white, - // ), - // ), - // ), - // Container( - // child: Pinput( - // length: 6, - // defaultPinTheme: defaultPinTheme, - // separatorBuilder: (index) => const SizedBox(width: 8), - // showCursor: true, - // controller: _otpController, - // // validator: _validatePin, - // errorPinTheme: defaultPinTheme.copyBorderWith( - // border: Border.all(color: Colors.redAccent), - // ), - // hapticFeedbackType: HapticFeedbackType.lightImpact, - // onCompleted: (pin) { - // debugPrint('onCompleted: $pin'); - // }, - // onChanged: (value) { - // debugPrint('onChanged: $value'); - // }, - // cursor: Column( - // mainAxisAlignment: MainAxisAlignment.end, - // children: [ - // Container( - // margin: const EdgeInsets.only(bottom: 9), - // width: 22, - // height: 1, - // color: focusedBorderColor, - // ), - // ], - // ), - // focusedPinTheme: defaultPinTheme.copyWith( - // decoration: defaultPinTheme.decoration!.copyWith( - // borderRadius: BorderRadius.circular(8), - // border: Border.all(color: focusedBorderColor), - // ), - // ), - // submittedPinTheme: defaultPinTheme.copyWith( - // decoration: defaultPinTheme.decoration!.copyWith( - // color: fillColor, - // borderRadius: BorderRadius.circular(19), - // border: Border.all(color: focusedBorderColor), - // ), - // ), - // ), - // ), - // const SizedBox(height: 20), - // SizedBox( - // width: 400, - // child: SizedBox( - // width: double.infinity, - // height: 50, - // child: ElevatedButton( - // style: ElevatedButton.styleFrom( - // backgroundColor: Color(0xFF436462), - // padding: const EdgeInsets.symmetric(vertical: 16), - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(8), - // ), - // ), - // onPressed: () { - // // sendMobileOrEmailVerify('staff'); - // }, - // child: Text( - // 'Continue', - // style: TextStyle( - // fontSize: ResponsiveLayout.isMobile(context) - // ? 18 - // : 20, - // fontWeight: FontWeight.w600, - // color: Colors.white, - // ), - // ), - // ), - // ), - // ), - // ], + AnimatedSwitcher( duration: const Duration( milliseconds: 500, @@ -1219,7 +1056,7 @@ class _LoginScreenState extends ConsumerState { child: Center( child: Text( 'OTP', - style: TextStyle( + style: GoogleFonts.poppins( fontSize: ResponsiveLayout.isMobile(context) ? 14 : 18, @@ -1287,7 +1124,7 @@ class _LoginScreenState extends ConsumerState { textAlign: TextAlign.center, text: TextSpan( text: 'Didn’t Receive Code? ', // normal text - style: TextStyle( + style: GoogleFonts.poppins( fontSize: ResponsiveLayout.isMobile(context) ? 12 : 14, @@ -1297,36 +1134,39 @@ class _LoginScreenState extends ConsumerState { children: [ TextSpan( text: 'Resend', // bold clickable part - style: TextStyle( + style: GoogleFonts.poppins( fontWeight: FontWeight.bold, color: Colors.white, decoration: TextDecoration .underline, // optional ), + recognizer: TapGestureRecognizer() - ..onTap = () { - print('Resend clicked'); - print(enteredEmailOrMobile); - print(clickedButtonName); - if (_PhoneNumberController - .text - .isNotEmpty) { - print('1224'); - _resendCode( - _PhoneNumberController.text, - _resendToken, - ); - } else if (_PhoneNumberController - .text - .isEmpty) { - print('1227'); - sendMobileOrEmailVerify( - clickedButtonName, - ); - } else { - print('data not found'); - } - }, + ..onTap = () async => await resendOTP(), + // recognizer: TapGestureRecognizer() + // ..onTap = () { + // print('Resend clicked'); + // print(enteredEmailOrMobile); + // print(clickedButtonName); + // if (_PhoneNumberController + // .text + // .isNotEmpty) { + // print('1224'); + // _resendCode( + // _PhoneNumberController.text, + // _resendToken, + // ); + // } else if (_PhoneNumberController + // .text + // .isEmpty) { + // print('1227'); + // sendMobileOrEmailVerify( + // clickedButtonName, + // ); + // } else { + // print('data not found'); + // } + // }, ), ], ), @@ -1369,7 +1209,7 @@ class _LoginScreenState extends ConsumerState { // }, // child: Text( // 'Continue', - // style: TextStyle( + // style: GoogleFonts.poppins( // fontSize: ResponsiveLayout.isMobile(context) // ? 18 // : 20, @@ -1448,111 +1288,12 @@ class _LoginScreenState extends ConsumerState { ), ); } -} -// -// @override -// Widget build(BuildContext context) { -// final isWeb = MediaQuery.of(context).size.width > 600; -// -// return Scaffold( -// body: Center( -// child: Container( -// constraints: const BoxConstraints(maxWidth: 400), -// padding: const EdgeInsets.all(16.0), -// decoration: isWeb -// ? BoxDecoration( -// color: Colors.white, -// borderRadius: BorderRadius.circular(8), -// boxShadow: [ -// BoxShadow( -// blurRadius: 12, -// color: Colors.black.withOpacity(0.1), -// ), -// ], -// ) -// : null, -// child: Form( -// key: _formKey, -// child: Column( -// mainAxisSize: MainAxisSize.min, -// children: [ -// // App Logo -// Image.asset('assets/logo.png', width: 80, height: 80), -// const SizedBox(height: 20), -// -// // Environment label -// Text( -// "Environment: ${Env.envName.toUpperCase()}", -// style: const TextStyle(fontSize: 14, color: Colors.grey), -// ), -// const SizedBox(height: 20), -// -// ThemedFormField( -// hintText: 'Email', -// backgroundColor: Colors.white, -// validator: (value) => Validators.email(value, "Email"), -// // imgPath: "MiscIconAssetPath.person", -// controller: _emailController, -// // txtwidth: MediaQuery.of(context).size.width * 0.5, -// // keyboardType: TextInputType.number, -// // maxLength: 10, -// // inputFormatters: [FilteringTextInputFormatter.digitsOnly], -// // readOnly: true, -// ), -// -// const SizedBox(height: 16), -// ThemedFormField( -// hintText: 'Password', -// backgroundColor: Colors.white, -// validator: (value) => -// Validators.passwordlogIn(value, "Password"), -// // imgPath: "MiscIconAssetPath.person", -// controller: _passwordController, -// isObscurable: true, -// // txtwidth: MediaQuery.of(context).size.width * 0.5, -// // keyboardType: TextInputType.number, -// // maxLength: 10, -// // inputFormatters: [FilteringTextInputFormatter.digitsOnly], -// // readOnly: true, -// ), -// -// // Password -// const SizedBox(height: 24), -// -// // Login Button -// SizedBox( -// width: double.infinity, -// child: ElevatedButton( -// onPressed: _isLoading ? null : _handleLogin, -// child: _isLoading -// ? const SizedBox( -// height: 20, -// width: 20, -// child: CircularProgressIndicator( -// strokeWidth: 2, -// valueColor: AlwaysStoppedAnimation( -// Colors.white, -// ), -// ), -// ) -// : const Text("Login"), -// ), -// ), -// -// const SizedBox(height: 12), -// -// // Forgot password link -// TextButton( -// onPressed: () { -// // TODO: Navigate to forgot password screen -// }, -// child: const Text("Forgot password?"), -// ), -// ], -// ), -// ), -// ), -// ), -// ); -// } + bool isEmail(String value) { + return RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value); + } + + bool isMobile(String value) { + return RegExp(r'^[0-9]{10}$').hasMatch(value); + } +} diff --git a/lib/presentation/themes/charts/barChart.dart b/lib/presentation/themes/charts/barChart.dart index 8ca5b80..9b74b9d 100644 --- a/lib/presentation/themes/charts/barChart.dart +++ b/lib/presentation/themes/charts/barChart.dart @@ -64,266 +64,347 @@ class _CustomBarChartState extends ConsumerState { x: x, groupVertically: false, - // showingTooltipIndicators: [0], + // showingTooltipIndicators: [x], + showingTooltipIndicators: const [1, 2], + // barsSpace: 30, barRods: [ BarChartRodData(toY: 0, color: Colors.transparent, width: 10), BarChartRodData( toY: value1, - color: Colors.cyan.shade300, + color: const Color(0xFF34a9a8), + // color: Color(0xFF0FB9B1), width: 20, + borderRadius: BorderRadius.circular(0), ), // BarChartRodData(toY: 2, color: Colors.orange.shade300, width: 6), BarChartRodData( toY: value2, - color: Colors.orange.shade300, + color: const Color(0xFFA5E4E1), + // color: const Color(0xFF64748B), + // color: Colors.orange.shade300, + // color: Color(0xFF2F3640), width: 20, borderRadius: BorderRadius.circular(0), ), ], - showingTooltipIndicators: touchedGroupIndex == x ? [0] : [], + // showingTooltipIndicators: touchedGroupIndex == x ? [0] : [], ); } - @override + String compactNumber(num value) { + if (value >= 10000000) { + return '${(value / 10000000).toStringAsFixed(1).replaceAll('.0', '')}Cr'; + } else if (value >= 1000000) { + return '${(value / 1000000).toStringAsFixed(1).replaceAll('.0', '')}M'; + } else if (value >= 1000) { + return '${(value / 1000).toStringAsFixed(1).replaceAll('.0', '')}K'; + } else { + return value.toInt().toString(); + } + } + // Widget build(BuildContext context) { // return AspectRatio( // aspectRatio: 1.4, // // ); // } + + double getChartWidth() { + const double barWidth = 40; // bar + spacing + double minWidth = + MediaQuery.of(context).size.width * 0.9; // minimum chart width + + final calculatedWidth = widget.dataList.length * barWidth; + return calculatedWidth < minWidth ? minWidth : calculatedWidth; + } + @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { - return SizedBox( - width: constraints.maxWidth, - height: constraints.maxHeight, - child: BarChart( - BarChartData( - // alignment: BarChartAlignment.spaceBetween, - alignment: BarChartAlignment.start, - // verticalAxis: Axis.horizontal, - // rotationQuarterTurns: rotationTurns, - barTouchData: BarTouchData( - enabled: true, - handleBuiltInTouches: true, - touchTooltipData: BarTouchTooltipData( - tooltipMargin: 6, - tooltipRoundedRadius: 6, - tooltipPadding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - // ask fl_chart to fit tooltip inside available space - fitInsideVertically: - true, // if your fl_chart version supports it - fitInsideHorizontally: - true, // if your fl_chart version supports it - getTooltipItem: - ( - BarChartGroupData group, - int groupIndex, - BarChartRodData rod, - int rodIndex, - ) { - final textColor = rodIndex == 1 - ? Colors.cyan.shade300 - : Colors.orange.shade300; - final textStyle = TextStyle( - color: textColor, - fontSize: 12, - fontWeight: FontWeight.w600, - ); - - final formattedValue = indianFormatter.format( - rod.toY.round(), - ); - - return BarTooltipItem(formattedValue, textStyle); - // return BarTooltipItem('${rod.toY.round()}', textStyle); - }, - ), - - touchCallback: (FlTouchEvent e, BarTouchResponse? r) async { - // optional: change state to highlight tapped group - if (r == null || r.spot == null) { - setState(() => touchedGroupIndex = -1); - return; - } - setState( - () => touchedGroupIndex = r.spot!.touchedBarGroupIndex, - ); - - final spot = r.spot!; - final groupIndex = spot.touchedBarGroupIndex; - final rodIndex = spot.touchedRodDataIndex; - - final barData = widget.dataList[groupIndex]; - - final name = barData.chartName; - final val = barData.id; - final month = rodIndex == 1 ? 'current' : 'previous'; - print('name - $name'); - print('val - $val'); - print('month - $month'); - print('managerId - $managerId'); - if (e is FlTapUpEvent) { - debugPrint( - 'Tapped value → ${rodIndex == 1 ? barData.value1 : barData.value2} -> ${barData.id}-' - ' ${rodIndex == 1 ? 'current' : 'previous'} -> ${barData.chartName}', - ); - if (managerId != null) { - print('managerId - $managerId'); - await apiService.generateChartExcel( - name, - val, - month, - managerId, - ); - } - } - }, - ), - - borderData: FlBorderData( - show: true, - border: Border( - bottom: BorderSide( - color: AppColors.contentColorBlack, - width: 0.1, - ), - left: BorderSide( - color: AppColors.contentColorBlack, - width: 0.1, - ), - ), - ), - gridData: FlGridData( - show: true, - // drawVerticalLine: true, - drawVerticalLine: false, - getDrawingHorizontalLine: (value) => FlLine( - // color: AppColors.gridLinesColor.withValues(alpha: 0.2), - color: Colors.blueGrey.shade100, - // color: Colors.black, - // color: AppColors.borderColor, - strokeWidth: 0.3, - ), - ), - titlesData: FlTitlesData( - bottomTitles: AxisTitles( - axisNameWidget: widget.btnName != null - ? Text(widget.btnName!) - : Text(''), - axisNameSize: 10, - sideTitles: SideTitles( - reservedSize: 30, - showTitles: true, - getTitlesWidget: (value, meta) { - final i = value.toInt(); - if (i >= widget.labels.length) return const SizedBox(); - final hasShortName = - widget.shortName != null && - widget.shortName!.length > i && - widget.shortName![i].trim().isNotEmpty; - - return SideTitleWidget( - meta: meta, - child: hasShortName - ? Tooltip( - message: widget.shortName![i], - child: Text( - widget.labels[i], - style: GoogleFonts.poppins( - fontSize: 9.5, - fontWeight: FontWeight.w500, - ), - textAlign: TextAlign.end, - ), - ) - : Text( - widget.labels[i], - style: GoogleFonts.poppins( - fontSize: 9.5, - fontWeight: FontWeight.w500, - ), - textAlign: TextAlign.end, - ), - ); + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: SizedBox( + // width: constraints.maxWidth, + // height: constraints.maxHeight, + width: getChartWidth(), // 👈 IMPORTANT + height: constraints.maxHeight, + child: BarChart( + BarChartData( + // alignment: BarChartAlignment.spaceBetween, + alignment: BarChartAlignment.start, + // verticalAxis: Axis.horizontal, + // rotationQuarterTurns: rotationTurns, + barTouchData: BarTouchData( + enabled: true, + handleBuiltInTouches: true, + touchTooltipData: BarTouchTooltipData( + tooltipMargin: 20, + tooltipRoundedRadius: 6, + getTooltipColor: (group) { + return Colors.transparent; // 👈 tooltip background color }, + tooltipPadding: const EdgeInsets.symmetric( + horizontal: 7, + vertical: 2, + ), + // rotateAngle: -85, + // ask fl_chart to fit tooltip inside available space + fitInsideVertically: + true, // if your fl_chart version supports it + fitInsideHorizontally: + true, // if your fl_chart version supports it + + getTooltipItem: + ( + BarChartGroupData group, + int groupIndex, + BarChartRodData rod, + int rodIndex, + ) { + if (rod.toY == 0) { + return null; + } + final textColor = rodIndex == 1 + ? Color(0xFF34a9a8) + : Color(0xFF020050); + + // final textColor = Colors.black87; + // final textColor = Color(0xFF020050); + // final textColor =; + final textStyle = GoogleFonts.poppins( + color: textColor, + fontSize: 8, + fontWeight: rodIndex == 1 + ? FontWeight.w600 + : FontWeight.w400, + ); + + // final formattedValue = indianFormatter.format( + // rod.toY.round(), + // ); + + final formattedValue = compactNumber(rod.toY); + return BarTooltipItem(formattedValue, textStyle); + // return BarTooltipItem('${rod.toY.round()}', textStyle); + }, ), + + touchCallback: (FlTouchEvent e, BarTouchResponse? r) async { + // optional: change state to highlight tapped group + if (r == null || r.spot == null) { + setState(() => touchedGroupIndex = -1); + return; + } + setState( + () => touchedGroupIndex = r.spot!.touchedBarGroupIndex, + ); + + final spot = r.spot!; + final groupIndex = spot.touchedBarGroupIndex; + final rodIndex = spot.touchedRodDataIndex; + + final barData = widget.dataList[groupIndex]; + + final name = barData.chartName; + final val = barData.id; + final month = rodIndex == 1 ? 'current' : 'previous'; + print('name - $name'); + print('val - $val'); + print('month - $month'); + print('managerId - $managerId'); + if (e is FlTapUpEvent) { + debugPrint( + 'Tapped value → ${rodIndex == 1 ? barData.value1 : barData.value2} -> ${barData.id}-' + ' ${rodIndex == 1 ? 'current' : 'previous'} -> ${barData.chartName}', + ); + if (managerId != null) { + print('managerId - $managerId'); + await apiService.generateChartExcel( + name, + val, + month, + managerId, + ); + } + } + }, ), - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - // interval: 10, - getTitlesWidget: (value, meta) { - // print("valuevalue - $value"); + borderData: FlBorderData( + show: true, + border: Border( + bottom: BorderSide( + color: AppColors.contentColorBlack, + width: 0.1, + ), + left: BorderSide( + color: AppColors.contentColorBlack, + width: 0.1, + ), + ), + ), + gridData: FlGridData( + show: true, + // drawVerticalLine: true, + drawVerticalLine: false, + getDrawingHorizontalLine: (value) => FlLine( + // color: AppColors.gridLinesColor.withValues(alpha: 0.2), + color: Colors.blueGrey.shade100, + // color: Colors.black, + // color: AppColors.borderColor, + strokeWidth: 0.3, + ), + ), + titlesData: FlTitlesData( + bottomTitles: AxisTitles( + axisNameWidget: widget.btnName != null + ? Text(widget.btnName!) + : Text(''), + axisNameSize: 10, + sideTitles: SideTitles( + reservedSize: 30, + showTitles: true, + getTitlesWidget: (value, meta) { + if (value == 0) { + return const SizedBox.shrink(); // 👈 hide 0 + } + final i = value.toInt(); + if (i >= widget.labels.length) return const SizedBox(); + final hasShortName = + widget.shortName != null && + widget.shortName!.length > i && + widget.shortName![i].trim().isNotEmpty; - final text = value.toInt().toString(); + return SideTitleWidget( + meta: meta, + child: hasShortName + ? Tooltip( + message: widget.shortName![i], + child: Transform.rotate( + angle: -1, + child: Padding( + padding: const EdgeInsets.only( + right: 3.0, + ), + child: Text( + truncate(widget.labels[i], max: 5), + // widget.labels[i], + style: GoogleFonts.poppins( + fontSize: 9, + fontWeight: FontWeight.w500, + color: Color(0xFF1E293B), + ), + textAlign: TextAlign.end, + ), + ), + ), + ) + : Tooltip( + message: widget.labels[i], + child: Transform.rotate( + angle: -1, + child: Padding( + padding: const EdgeInsets.only( + right: 3.0, + ), + child: Text( + truncate(widget.labels[i], max: 5), + // widget.[i], + style: GoogleFonts.poppins( + fontSize: 9, + fontWeight: FontWeight.w400, + color: Color(0xFF1E293B), + ), + textAlign: TextAlign.end, + ), + ), + ), + ), + ); + }, + ), + ), - final bool isLast = value == meta.max; - // if (isLast) { - // return const SizedBox.shrink(); // 👈 hide last label - // } - // print('value: $value'); - // print('text: $text'); - // print('length: ${text.length}'); - // print('isLast: $isLast'); - return Transform.rotate( - // angle: -3, - angle: 0, - child: Padding( - padding: const EdgeInsets.only(right: 3.0), - child: Text( - isLast ? '0' : value.toInt().toString(), - textAlign: TextAlign.end, - style: GoogleFonts.inter( - fontSize: 9, - color: isLast ? Colors.white : Colors.black, - fontWeight: isLast - ? FontWeight.w100 - : FontWeight.w400, + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + // interval: 10, + getTitlesWidget: (value, meta) { + // print("valuevalue - $value"); + + final text = value.toInt().toString(); + + final bool isLast = value == meta.max; + // if (isLast) { + // return const SizedBox.shrink(); // 👈 hide last label + // } + // print('value: $value'); + // print('text: $text'); + // print('length: ${text.length}'); + // print('isLast: $isLast'); + return Transform.rotate( + // angle: -3, + angle: 0, + child: Padding( + padding: const EdgeInsets.only(right: 3.0), + child: Text( + // isLast ? '0' : value.toInt().toString(), + isLast ? '0' : compactNumber(value), + textAlign: TextAlign.end, + style: GoogleFonts.inter( + fontSize: 9, + color: isLast ? Colors.white : Colors.black, + fontWeight: isLast + ? FontWeight.w100 + : FontWeight.w300, + ), ), ), - ), - ); - }, - reservedSize: 45, + ); + }, + reservedSize: 45, + ), ), + rightTitles: const AxisTitles(), + topTitles: const AxisTitles(), ), - rightTitles: const AxisTitles(), - topTitles: const AxisTitles(), + barGroups: widget.dataList.asMap().entries.map((e) { + final index = e.key; + final data = e.value; + print('generateBarGroupBAR - $data'); + return generateBarGroup( + index, + data.color, + data.value1, + data.value2, + data.shadowValue, + ); + }).toList(), + groupsSpace: 12, + // maxY: widget.maxY, + maxY: (widget.dataList != null && widget.dataList!.isNotEmpty) + ? widget.dataList! + .map( + (e) => + e.value1 > e.value2 ? e.value1 : e.value2, + ) + .reduce((a, b) => a > b ? a : b) * + 1.15 + : 20, ), - barGroups: widget.dataList.asMap().entries.map((e) { - final index = e.key; - final data = e.value; - print('generateBarGroupBAR - $data'); - return generateBarGroup( - index, - data.color, - data.value1, - data.value2, - data.shadowValue, - ); - }).toList(), - - // maxY: widget.maxY, - maxY: (widget.dataList != null && widget.dataList!.isNotEmpty) - ? widget.dataList! - .map( - (e) => e.value1 > e.value2 ? e.value1 : e.value2, - ) - .reduce((a, b) => a > b ? a : b) + - 15 - : 20, ), ), ); }, ); } + + String truncate(String text, {int max = 6}) { + if (text.length <= max) return text; + return text.substring(0, max); + } } diff --git a/lib/presentation/themes/charts/barChart_horizontal.dart b/lib/presentation/themes/charts/barChart_horizontal.dart new file mode 100644 index 0000000..55babf7 --- /dev/null +++ b/lib/presentation/themes/charts/barChart_horizontal.dart @@ -0,0 +1,401 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; +import '../../../core/services/api_service.dart'; +import '../../../data/models/bar_data.dart'; +import '../../providers/manager_provider.dart'; +import 'appChartColors.dart'; + +class CustomBarChartHorizontal extends ConsumerStatefulWidget { + final List dataList; + final List labels; + final List? shortName; + final String title; + final String? btnName; + final double maxY; + final int initialRotation; + + const CustomBarChartHorizontal({ + super.key, + required this.dataList, + required this.labels, + this.shortName, + this.btnName, + this.title = "Horizontal Bar Chart", + this.maxY = 20, + this.initialRotation = 1, + }); + + final shadowColor = const Color(0xFFCCCCCC); + + @override + // State createState() => _CustomBarChartState(); + ConsumerState createState() => + _CustomBarChartState(); +} + +class _CustomBarChartState extends ConsumerState { + int touchedGroupIndex = -1; + late int rotationTurns; + dynamic managerId; + late ApiService apiService; + + @override + void initState() { + super.initState(); + apiService = ApiService(); + rotationTurns = widget.initialRotation; + Future.microtask(() { + managerId = ref.read(managerIdProvider); + }); + } + + final indianFormatter = NumberFormat('#,##,##0', 'en_IN'); + BarChartGroupData generateBarGroup( + int x, + Color color, + double value1, + double value2, + double shadowValue, + ) { + return BarChartGroupData( + x: x, + groupVertically: false, + + // showingTooltipIndicators: [x], + showingTooltipIndicators: const [1, 2], + + // barsSpace: 30, + barRods: [ + BarChartRodData(toY: 0, color: Colors.transparent, width: 10), + BarChartRodData( + toY: value1, + color: const Color(0xFF34a9a8), + // color: Colors.cyan.shade300, + width: 10, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(5), + topRight: Radius.circular(5), + ), + // borderRadius: BorderRadius.circular(5), + ), + // BarChartRodData(toY: 2, color: Colors.orange.shade300, width: 6), + BarChartRodData( + toY: value2, + color: const Color(0xFFA5E4E1), + // color: Colors.orange.shade300, + width: 10, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(5), + topRight: Radius.circular(5), + ), + // borderRadius: BorderRadius.circular(5), + ), + ], + // showingTooltipIndicators: touchedGroupIndex == x ? [0] : [], + ); + } + + String compactNumber(num value) { + if (value >= 10000000) { + return '${(value / 10000000).toStringAsFixed(1).replaceAll('.0', '')}Cr'; + } else if (value >= 1000000) { + return '${(value / 1000000).toStringAsFixed(1).replaceAll('.0', '')}M'; + } else if (value >= 1000) { + return '${(value / 1000).toStringAsFixed(1).replaceAll('.0', '')}K'; + } else { + return value.toInt().toString(); + } + } + + // Widget build(BuildContext context) { + // return AspectRatio( + // aspectRatio: 1.4, + // + // ); + // } + + double getChartWidth() { + const double barWidth = 40; // bar + spacing + double minWidth = + MediaQuery.of(context).size.width * 0.9; // minimum chart width + + final calculatedWidth = widget.dataList.length * barWidth; + return calculatedWidth < minWidth ? minWidth : calculatedWidth; + } + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return SizedBox( + // width: constraints.maxWidth, + // height: constraints.maxHeight, + width: getChartWidth(), // 👈 IMPORTANT + height: constraints.maxHeight, + child: BarChart( + BarChartData( + // alignment: BarChartAlignment.spaceBetween, + alignment: BarChartAlignment.start, + // verticalAxis: Axis.horizontal, + rotationQuarterTurns: rotationTurns, + barTouchData: BarTouchData( + enabled: true, + handleBuiltInTouches: true, + touchTooltipData: BarTouchTooltipData( + tooltipMargin: 6, + tooltipRoundedRadius: 6, + getTooltipColor: (group) { + return Colors.transparent; // 👈 tooltip background color + }, + tooltipPadding: const EdgeInsets.symmetric( + horizontal: 7, + vertical: 2, + ), + // rotateAngle: -85, + // ask fl_chart to fit tooltip inside available space + fitInsideVertically: + true, // if your fl_chart version supports it + fitInsideHorizontally: + true, // if your fl_chart version supports it + + getTooltipItem: + ( + BarChartGroupData group, + int groupIndex, + BarChartRodData rod, + int rodIndex, + ) { + if (rod.toY == 0) { + return null; + } + // final textColor = rodIndex == 1 + // ? Colors.cyan.shade500 + // : Colors.orange.shade500; + + // final textColor = Colors.black; + + final textColor = rodIndex == 1 + ? Color(0xFF34a9a8) + : Color(0xFF020050); + final textStyle = GoogleFonts.poppins( + color: textColor, + fontSize: 8, + fontWeight: rodIndex == 1 + ? FontWeight.w600 + : FontWeight.w400, + ); + + // final formattedValue = indianFormatter.format( + // rod.toY.round(), + // ); + + final formattedValue = compactNumber(rod.toY); + return BarTooltipItem(formattedValue, textStyle); + // return BarTooltipItem('${rod.toY.round()}', textStyle); + }, + ), + + touchCallback: (FlTouchEvent e, BarTouchResponse? r) async { + // optional: change state to highlight tapped group + if (r == null || r.spot == null) { + setState(() => touchedGroupIndex = -1); + return; + } + setState( + () => touchedGroupIndex = r.spot!.touchedBarGroupIndex, + ); + + final spot = r.spot!; + final groupIndex = spot.touchedBarGroupIndex; + final rodIndex = spot.touchedRodDataIndex; + + final barData = widget.dataList[groupIndex]; + + final name = barData.chartName; + final val = barData.id; + final month = rodIndex == 1 ? 'current' : 'previous'; + print('name - $name'); + print('val - $val'); + print('month - $month'); + print('managerId - $managerId'); + if (e is FlTapUpEvent) { + debugPrint( + 'Tapped value → ${rodIndex == 1 ? barData.value1 : barData.value2} -> ${barData.id}-' + ' ${rodIndex == 1 ? 'current' : 'previous'} -> ${barData.chartName}', + ); + if (managerId != null) { + print('managerId - $managerId'); + await apiService.generateChartExcel( + name, + val, + month, + managerId, + ); + } + } + }, + ), + + borderData: FlBorderData( + show: true, + border: Border( + bottom: BorderSide( + color: AppColors.gridLinesColor, + // color: AppColors.contentColorBlack, + width: 0.1, + ), + right: BorderSide( + color: AppColors.gridLinesColor, + // color: AppColors.contentColorBlack, + width: 0.1, + ), + ), + ), + gridData: FlGridData( + show: true, + // drawVerticalLine: true, + drawVerticalLine: false, + getDrawingHorizontalLine: (value) => FlLine( + // color: AppColors.gridLinesColor.withValues(alpha: 0.2), + color: Colors.blueGrey.shade100, + // color: Colors.black, + // color: AppColors.borderColor, + strokeWidth: 0.3, + ), + ), + titlesData: FlTitlesData( + bottomTitles: AxisTitles( + axisNameWidget: widget.btnName != null + ? Text(widget.btnName!) + : Text(''), + axisNameSize: 10, + sideTitles: SideTitles( + // reservedSize: 90, + reservedSize: MediaQuery.of(context).size.width * 0.1, + showTitles: true, + getTitlesWidget: (value, meta) { + final i = value.toInt(); + if (i >= widget.labels.length) return const SizedBox(); + final hasShortName = + widget.shortName != null && + widget.shortName!.length > i && + widget.shortName![i].trim().isNotEmpty; + + return SideTitleWidget( + meta: meta, + child: hasShortName + ? Tooltip( + message: widget.shortName![i], + child: Transform.rotate( + angle: 0, + child: Text( + // widget.labels[i], + truncate(widget.labels[i], max: 5), + style: GoogleFonts.poppins( + fontSize: 9, + fontWeight: FontWeight.w600, + color: Color(0xFF1E293B), + ), + textAlign: TextAlign.end, + ), + ), + ) + : Transform.rotate( + angle: 0, + child: Text( + widget.labels[i], + style: GoogleFonts.poppins( + fontSize: 9, + fontWeight: FontWeight.w600, + color: Color(0xFF1E293B), + ), + textAlign: TextAlign.end, + ), + ), + ); + }, + ), + ), + + rightTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + // interval: 10, + getTitlesWidget: (value, meta) { + // print("valuevalue - $value"); + + final text = value.toInt().toString(); + + final bool isLast = value == meta.max; + // if (isLast) { + // return const SizedBox.shrink(); // 👈 hide last label + // } + // print('value: $value'); + // print('text: $text'); + // print('length: ${text.length}'); + // print('isLast: $isLast'); + return Transform.rotate( + angle: -3, + // angle: 0, + child: Padding( + padding: const EdgeInsets.only(right: 3.0), + child: Text( + // isLast ? '0' : value.toInt().toString(), + isLast ? '0' : compactNumber(value), + textAlign: TextAlign.end, + style: GoogleFonts.inter( + fontSize: 9, + // color: isLast ? Colors.white : Colors.black, + color: Colors.white, + fontWeight: isLast + ? FontWeight.w100 + : FontWeight.w400, + ), + ), + ), + ); + }, + reservedSize: 5, + ), + ), + leftTitles: const AxisTitles(), + topTitles: const AxisTitles(), + ), + barGroups: widget.dataList.asMap().entries.map((e) { + final index = e.key; + final data = e.value; + print('generateBarGroupBAR - $data'); + return generateBarGroup( + index, + data.color, + data.value1, + data.value2, + data.shadowValue, + ); + }).toList(), + groupsSpace: 12, + // maxY: widget.maxY, + maxY: (widget.dataList != null && widget.dataList!.isNotEmpty) + ? widget.dataList! + .map( + (e) => e.value1 > e.value2 ? e.value1 : e.value2, + ) + .reduce((a, b) => a > b ? a : b) * + 1.15 + : 20, + ), + ), + ); + }, + ); + } + + String truncate(String text, {int max = 6}) { + if (text.length <= max) return text; + return text.substring(0, max); + } +}