diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 29b5ec2..7d480df 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":"/Users/venbateam/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_app_check","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_app_check-0.4.0+1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_auth","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_auth-6.0.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_core-4.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_secure_storage","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/fluttertoast-9.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_ios","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/google_sign_in_ios-6.1.0/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"/Users/venbateam/.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":"/Users/venbateam/.pub-cache/hosted/pub.dev/open_file_ios-1.0.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_ios","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.4/","native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"connectivity_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"firebase_app_check","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_app_check-0.4.0+1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_auth","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_auth-6.0.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_core-4.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_plugin_android_lifecycle","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.30/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/fluttertoast-9.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_android","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/google_sign_in_android-7.0.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_android","path":"/Users/venbateam/.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":"/Users/venbateam/.pub-cache/hosted/pub.dev/open_file_android-1.0.6/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/path_provider_android-2.2.18/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.12/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_android","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.20/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"connectivity_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_app_check","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_app_check-0.4.0+1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_auth","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_auth-6.0.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_core-4.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_secure_storage_macos","path":"/Users/venbateam/.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":"/Users/venbateam/.pub-cache/hosted/pub.dev/google_sign_in_ios-6.1.0/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"/Users/venbateam/.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":"/Users/venbateam/.pub-cache/hosted/pub.dev/open_file_mac-1.0.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_macos","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.3/","native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"connectivity_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage_linux","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_linux","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/open_file_linux-0.0.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false},{"name":"url_launcher_linux","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.1/","native_build":true,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"connectivity_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"firebase_auth","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_auth-6.0.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_core-4.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage_windows","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_windows","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/local_auth_windows-1.0.11/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_windows","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/open_file_windows-0.0.3/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false},{"name":"url_launcher_windows","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.4/","native_build":true,"dependencies":[],"dev_dependency":false}],"web":[{"name":"connectivity_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","dependencies":[],"dev_dependency":false},{"name":"firebase_app_check_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_app_check_web-0.2.0+16/","dependencies":["firebase_core_web"],"dev_dependency":false},{"name":"firebase_auth_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_auth_web-6.0.2/","dependencies":["firebase_core_web"],"dev_dependency":false},{"name":"firebase_core_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_core_web-3.1.0/","dependencies":[],"dev_dependency":false},{"name":"firebase_messaging_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_messaging_web-4.0.1/","dependencies":["firebase_core_web"],"dev_dependency":false},{"name":"flutter_secure_storage_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1/","dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/fluttertoast-9.0.0/","dependencies":[],"dev_dependency":false},{"name":"google_sign_in_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/google_sign_in_web-1.0.0/","dependencies":[],"dev_dependency":false},{"name":"open_file_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/open_file_web-0.0.4/","dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","dependencies":[],"dev_dependency":false},{"name":"shared_preferences_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3/","dependencies":[],"dev_dependency":false},{"name":"url_launcher_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/url_launcher_web-2.4.1/","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"connectivity_plus","dependencies":[]},{"name":"file_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"firebase_app_check","dependencies":["firebase_app_check_web","firebase_core"]},{"name":"firebase_app_check_web","dependencies":["firebase_core","firebase_core_web"]},{"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":"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":"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-11-20 11:03:06.002014","version":"3.35.7","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":"/Users/venbateam/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_app_check","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_app_check-0.4.0+1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_auth","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_auth-6.0.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_core-4.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_secure_storage","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/fluttertoast-9.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_ios","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/google_sign_in_ios-6.1.0/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"/Users/venbateam/.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":"/Users/venbateam/.pub-cache/hosted/pub.dev/open_file_ios-1.0.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_ios","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.4/","native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"connectivity_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"firebase_app_check","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_app_check-0.4.0+1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_auth","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_auth-6.0.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_core-4.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_plugin_android_lifecycle","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.30/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/fluttertoast-9.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_android","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/google_sign_in_android-7.0.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_android","path":"/Users/venbateam/.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":"/Users/venbateam/.pub-cache/hosted/pub.dev/open_file_android-1.0.6/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/path_provider_android-2.2.18/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.12/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_android","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.20/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"connectivity_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_app_check","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_app_check-0.4.0+1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_auth","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_auth-6.0.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_core-4.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_secure_storage_macos","path":"/Users/venbateam/.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":"/Users/venbateam/.pub-cache/hosted/pub.dev/google_sign_in_ios-6.1.0/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"/Users/venbateam/.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":"/Users/venbateam/.pub-cache/hosted/pub.dev/open_file_mac-1.0.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_macos","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.3/","native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"connectivity_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage_linux","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_linux","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/open_file_linux-0.0.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false},{"name":"url_launcher_linux","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.1/","native_build":true,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"connectivity_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"firebase_auth","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_auth-6.0.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_core-4.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage_windows","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_windows","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/local_auth_windows-1.0.11/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_windows","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/open_file_windows-0.0.3/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false},{"name":"url_launcher_windows","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.4/","native_build":true,"dependencies":[],"dev_dependency":false}],"web":[{"name":"connectivity_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","dependencies":[],"dev_dependency":false},{"name":"firebase_app_check_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_app_check_web-0.2.0+16/","dependencies":["firebase_core_web"],"dev_dependency":false},{"name":"firebase_auth_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_auth_web-6.0.2/","dependencies":["firebase_core_web"],"dev_dependency":false},{"name":"firebase_core_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_core_web-3.1.0/","dependencies":[],"dev_dependency":false},{"name":"firebase_messaging_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/firebase_messaging_web-4.0.1/","dependencies":["firebase_core_web"],"dev_dependency":false},{"name":"flutter_secure_storage_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1/","dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/fluttertoast-9.0.0/","dependencies":[],"dev_dependency":false},{"name":"google_sign_in_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/google_sign_in_web-1.0.0/","dependencies":[],"dev_dependency":false},{"name":"open_file_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/open_file_web-0.0.4/","dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","dependencies":[],"dev_dependency":false},{"name":"shared_preferences_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3/","dependencies":[],"dev_dependency":false},{"name":"url_launcher_web","path":"/Users/venbateam/.pub-cache/hosted/pub.dev/url_launcher_web-2.4.1/","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"connectivity_plus","dependencies":[]},{"name":"file_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"firebase_app_check","dependencies":["firebase_app_check_web","firebase_core"]},{"name":"firebase_app_check_web","dependencies":["firebase_core","firebase_core_web"]},{"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":"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":"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-11-20 11:03:06.002014","version":"3.35.7","swift_package_manager_enabled":{"ios":false,"macos":false}} diff --git a/lib/core/routing/app_router.dart b/lib/core/routing/app_router.dart index c5d5b8a..b132a91 100644 --- a/lib/core/routing/app_router.dart +++ b/lib/core/routing/app_router.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:nhance_partner/core/routing/routes.dart'; import 'package:nhance_partner/presentation/screens/Enquiry/enquiryList.dart'; +import 'package:nhance_partner/presentation/screens/Masters/PaymentMode/paymentList.dart'; import 'package:nhance_partner/presentation/screens/UserManagement/Profile/profile_web.dart'; import 'package:nhance_partner/presentation/screens/dashboard/dashboard.dart'; import 'package:nhance_partner/presentation/screens/payout/invoice_list.dart'; @@ -12,6 +13,7 @@ import '../../presentation/providers/manager_provider.dart'; import '../../presentation/screens/Enquiry/enquiry/tabs.dart'; import '../../presentation/screens/Enquiry/policy_claims_endros/claims.dart'; import '../../presentation/screens/Enquiry/policy_claims_endros/endrosment.dart'; +import '../../presentation/screens/Masters/Brokers/brokerList.dart'; import '../../presentation/screens/StaffAttendance/attendanceAllDetails.dart'; import '../../presentation/screens/StaffAttendance/individual_Attendance.dart'; import '../../presentation/screens/UserManagement/Agent/agent.dart'; @@ -192,6 +194,16 @@ final GoRouter appRouter = GoRouter( path: AppRoutes.individualAttendance, builder: (context, state) => const IndividualAttendanceDetails(), ), + + GoRoute( + path: AppRoutes.brokerLst, + builder: (context, state) => const BrokerList(), + ), + + GoRoute( + path: AppRoutes.paymentModeLst, + builder: (context, state) => const PaymentLsit(), + ), ], redirect: (context, state) async { final loggedIn = await AuthService.isLoggedIn(); diff --git a/lib/core/routing/routes.dart b/lib/core/routing/routes.dart index 3cf535e..704569d 100644 --- a/lib/core/routing/routes.dart +++ b/lib/core/routing/routes.dart @@ -24,4 +24,6 @@ class AppRoutes { static const String payout = '/payout'; static const String invoiceList = '/invoiceList'; + static const String brokerLst = '/brokerLst'; + static const String paymentModeLst = '/paymentMode'; } diff --git a/lib/core/services/api_service.dart b/lib/core/services/api_service.dart index 7507027..18d102b 100644 --- a/lib/core/services/api_service.dart +++ b/lib/core/services/api_service.dart @@ -342,14 +342,8 @@ class ApiService { final url; if (role == 'staff') { - // url = Uri.parse( - // 'https://venbait.in/nhance/partner/dev/api/staff/changeStaffStatus', - // ); url = Uri.parse('${Env.apiUrl}staff/changeStaffStatus'); } else { - // url = Uri.parse( - // 'https://venbait.in/nhance/partner/dev/api/agent/changeAgentStatus', - // ); url = Uri.parse('${Env.apiUrl}/api/agent/changeAgentStatus'); } @@ -372,6 +366,44 @@ class ApiService { return response; } + Future> updateStatusMasters( + id, + status, + masterName, + userId, + ) async { + print('updateStatusMaster $id $status $masterName $userId'); + final Map data = { + "is_active": int.parse(status), + "updated_by": userId, + }; + final url; + + if (masterName == 'Broker') { + url = Uri.parse('${Env.apiUrl}master/updateBrokerStatus/$id'); + } else { + url = Uri.parse('${Env.apiUrl}master/updatePaymentModeStatus/$id'); + } + + // final token = await getToken(); // Fetch token + + if (_token == null) { + throw Exception('Token not found. Please log in.'); + } + + print("data------- $data}"); + + final headers = { + 'Authorization': 'Bearer $_token', + 'Content-Type': 'application/json', + 'app-signature': Env.App_Signature, + // 'app-signature': 'nhance-partner-2025-signature-35468846JRhH551HK', + }; + + final response = await _makePostRequestJson(url, data, headers); + return response; + } + // ----------------------------------- Dashboard ------------------------------------------------- Future> fetchDashboard(int id, role, userId) async { // print(_token); @@ -1005,6 +1037,8 @@ class ApiService { url = Uri.parse('${Env.apiUrl}master/getEndorsementMaster'); } else if (val == 'Broker') { url = Uri.parse('${Env.apiUrl}master/getAllBrokers'); + } else if (val == 'PaymentMode') { + url = Uri.parse('${Env.apiUrl}master/getAllPaymentModelist'); } final headers = { diff --git a/lib/presentation/layouts/appheader.dart b/lib/presentation/layouts/appheader.dart index 6a84ac7..99a6943 100644 --- a/lib/presentation/layouts/appheader.dart +++ b/lib/presentation/layouts/appheader.dart @@ -146,6 +146,26 @@ class _AppHeaderState extends ConsumerState { }, ), ], + + if (key == 'Masters') ...[ + if (role == 'manager') ...[ + _buildPopupItem( + label: "Broker", + onTap: () { + _hidePopup(); + context.go(AppRoutes.brokerLst); + }, + ), + ], + SizedBox(height: 2), + _buildPopupItem( + label: "Payment Mode", + onTap: () { + _hidePopup(); + context.go(AppRoutes.paymentModeLst); + }, + ), + ], ], ), ), @@ -227,6 +247,16 @@ class _AppHeaderState extends ConsumerState { const SizedBox(width: 8), ], + // User (Manager Only) - with hover popup + if (roleId == 'manager') ...[ + _buildHoverMenuItem( + icon: Icons.settings_suggest_outlined, + label: "Masters", + popupKey: 'Masters', + ), + const SizedBox(width: 8), + ], + // Reports (Not Staff) - with hover popup if (roleId != 'staff') ...[ _buildHoverMenuItem( diff --git a/lib/presentation/screens/Masters/Brokers/broker.dart b/lib/presentation/screens/Masters/Brokers/broker.dart new file mode 100644 index 0000000..adfb291 --- /dev/null +++ b/lib/presentation/screens/Masters/Brokers/broker.dart @@ -0,0 +1,310 @@ +import 'dart:convert'; +// import 'dart:io' as html; +import 'dart:typed_data'; // Import for Uint8List +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:http/http.dart' as http; +import 'package:nhance_partner/core/routing/routes.dart'; +import 'package:nhance_partner/data/utils/toastNotification.dart'; +import 'package:nhance_partner/presentation/themes/indicators/text_field_theme.dart'; + +import '../../../../core/config/env.dart'; +import '../../../../core/services/api_service.dart'; +import '../../../../data/services/auth_service.dart'; +import '../../../../data/utils/validators.dart'; +import '../../../layouts/main_layout.dart'; +import '../../../layouts/responsive_layout.dart'; +import '../../../providers/manager_provider.dart'; + +import 'package:universal_html/html.dart' as html; + +import '../../../themes/indicators/input_field_decoration.dart'; + +class Broker extends ConsumerStatefulWidget { + final String? id; + final Map? data; + final VoidCallback onSubmit; + const Broker({super.key, this.id, this.data, required this.onSubmit}); + @override + ConsumerState createState() => BrokerState(); +} + +class BrokerState extends ConsumerState { + final _formKey = GlobalKey(); + late ApiService apiService; + + final GlobalKey>> dropDownKey = + GlobalKey>>(); + + final GlobalKey>> + dropDownKeyHandler = GlobalKey>>(); + + List tabHeader = ['name', 'email', 'mobile', 'code']; + late String isActive = "1"; + html.File? passportFile; + String? selectedFileNames; + String? passportFileUrlFromApi; + dynamic selectedId; + String? _token; + bool isLoading = false; + bool showHandler = false; + + String? selectedRole; + List> filteredRolesData = []; + List> getRolesData = []; + + List? selectedHandlerIds = []; + String? selectedHandler; + List> filteredHandlersData = []; + List> getHandlersData = []; + + Map controllers = {}; + + dynamic userId; + dynamic managerId; + + Map dataDetails() { + final data = {"name": controllers["name"]?.text, "is_active": isActive}; + return data; + } + + @override + void initState() { + super.initState(); + apiService = ApiService(); + for (String field in tabHeader) { + controllers[field] = TextEditingController(); + } + + _initializeToken(); + updateData(); + + Future.microtask(() { + managerId = ref.watch(managerIdProvider); + userId = ref.watch(userIdProvider); + if (managerId != null) { + print('hansles'); + // getHandlers(managerId); + } + }); + } + + Future _initializeToken() async { + _token = await AuthService.getToken(); + print("APISERTOKEN - $_token"); + } + + void updateData() async { + if (widget.data != null) { + dynamic id = widget.data?['id']; + final data = widget.data; + + if (data == null) return; + setState(() { + selectedId = id; + controllers['name']?.text = data['name'] ?? ''; + controllers["is_active"]?.text = data['is_active'].toString(); + }); + } + } + + Future handleSave() async { + if (!_formKey.currentState!.validate()) return; + setState(() { + if (_formKey.currentState!.validate()) { + dataDetails(); + final dataSet = dataDetails(); + print("dataSetAgent - $dataSet"); + + print("TYPE of is_active → ${dataSet['is_active'].runtimeType}"); + print("TYPE of name → ${dataSet['name'].runtimeType}"); + createUserData(dataSet); + } else { + // isDisable = false; + } + }); + } + + void refresh() { + print('REfresj'); + widget.onSubmit(); + setState(() { + // clear all text controllers + for (var controller in controllers.values) { + controller.clear(); + } // 👈 clear selected agent + controllers['name']?.clear(); + }); + } + + Future createUserData(data) async { + final bool isUpdating = selectedId != null; + final dynamic id = isUpdating ? int.tryParse(selectedId.toString()) : 0; + final String apiUrldata; + + print("TYPE of id → $id - ${id.runtimeType}"); + print("TYPE of id → $userId - ${userId.runtimeType}"); + + apiUrldata = isUpdating + ? '${Env.apiUrl}/master/updateBroker/$selectedId' + : '${Env.apiUrl}/master/createBroker'; + + // final token = await getToken(); // Fetch token + + if (_token == null) { + throw Exception('Token not found. Please log in.'); + } + + if (isUpdating) { + data['updated_by'] = userId.toString(); + } else { + data['created_by'] = userId.toString(); + } + + print("data------- $data}"); + + try { + final response = await http.post( + Uri.parse(apiUrldata), + headers: { + 'Authorization': 'Bearer $_token', + 'Content-Type': 'application/json', + 'app-signature': Env.App_Signature, + }, + body: jsonEncode(data), // Convert map to JSON + ); + + if (response.statusCode == 200) { + print("Broker submitted successfully!"); + print("Response: ${response.body}"); + + refresh(); + isUpdating + ? ToastHelper.showSuccessToast( + context, + 'Broker Updated Successfully', + ) + : ToastHelper.showSuccessToast( + context, + 'Broker Created Successfully', + ); + } else if (response.statusCode == 403) { + await apiService.clearLocalStorageAndRedirect(); + } else { + final responseBody = jsonDecode(response.body); + dynamic msg = responseBody['data']; + + print("Failed to submit plan. Status: ${response.statusCode}"); + print("Error: ${response.body}"); + + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text("Broker Creation Failed"), + content: Text(msg), + actions: [ + TextButton( + child: Text("OK"), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } catch (e) { + print(" Error submitting Staff: $e"); + } + } + + @override + void dispose() { + for (var controller in controllers.values) { + controller.dispose(); + } + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + buildFormFields(), + SizedBox(width: 5), + InkWell( + onTap: () { + handleSave(); + }, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 6), + + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8.0), + color: Color(0xFF2E7D6E), + ), + child: Text( + 'Save', + style: GoogleFonts.inter(color: Colors.white, fontSize: 10), + ), + ), + ), + SizedBox(width: 5), + InkWell( + onTap: () { + refresh(); + }, + child: Container( + padding: EdgeInsets.all(6.0), + decoration: BoxDecoration( + color: const Color(0xFF2E7D6E), + borderRadius: BorderRadius.circular(5.0), + ), + child: Icon(Icons.refresh, size: 13, color: Colors.white), + ), + ), + ], + ), + ); + } + + Widget buildFormFields() { + return Form( + key: _formKey, + child: Column(children: [buildName()]), + ); + } + + Widget buildName() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Broker *", style: _textStyle), + SizedBox(width: 10), + ThemedFormField( + controller: controllers['name']!, + validator: (value) => Validators.requiredField(value, "name"), + txtwidth: MediaQuery.of(context).size.width * 0.15, + borderColor: Color(0xFFE2E8F0), + highlightColor: Color(0xFF50A398), + txtheight: 30, + ), + ], + ); + } + + static final _textStyle = GoogleFonts.inter( + fontSize: 11, + fontWeight: FontWeight.w600, + ); +} diff --git a/lib/presentation/screens/Masters/Brokers/brokerList.dart b/lib/presentation/screens/Masters/Brokers/brokerList.dart new file mode 100644 index 0000000..a458dbe --- /dev/null +++ b/lib/presentation/screens/Masters/Brokers/brokerList.dart @@ -0,0 +1,475 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:nhance_partner/presentation/providers/userRoleProvider.dart'; +import 'package:nhance_partner/presentation/screens/Masters/Brokers/broker.dart'; + +import '../../../../core/routing/routes.dart'; +import '../../../../core/services/api_service.dart'; +import '../../../../data/utils/Pagination.dart'; +import '../../../layouts/main_layout.dart'; +import '../../../layouts/responsive_layout.dart'; +import '../../../providers/manager_provider.dart'; +import '../../../themes/indicators/export_btn.dart'; +import '../../../themes/indicators/filter_btn.dart'; +import '../../../themes/indicators/search_field_theme.dart'; +import '../../../themes/indicators/text_field_theme.dart'; +import '../../../widgets/custom_action_popup.dart'; + +class BrokerList extends ConsumerStatefulWidget { + const BrokerList({super.key}); + @override + ConsumerState createState() => BrokerListState(); +} + +class BrokerListState extends ConsumerState { + int currentPage = 1; + int itemsPerPage = 10; + late ApiService apiService; + dynamic managerId; + dynamic role; + dynamic prefid; + dynamic userId; + // List> dataVal = []; + List> getBrokerData = []; + List> originalData = []; + List> filteredData = []; + bool isLoading = false; + + Map? selectedBroker; + dynamic selectedId; + + @override + void initState() { + super.initState(); + + apiService = ApiService(); + + Future.microtask(() { + final data1 = ref.read(managerIdProvider); + userId = ref.watch(userIdProvider); + // final data2 = ref.read(handlerIdProvider); + print("Edata1 => mId: $data1 -2 :"); + prefid = data1; + role = ref.read(userRoleProvider); + print("E43 => mId: $prefid"); + if (prefid != null && role != null) { + getBroker(); + } + }); + // getBrokerList(); + } + + List get _paginatedData { + // Sort descending by id first + final sortedData = [...filteredData] + ..sort((a, b) => int.parse(b['id']) - int.parse(a['id'])); + + if (sortedData.isEmpty) return []; + + // Ensure currentPage is valid + final maxPage = (sortedData.length / itemsPerPage).ceil(); + final safePage = currentPage.clamp(1, maxPage); + + final startIndex = (safePage - 1) * itemsPerPage; + final endIndex = (startIndex + itemsPerPage).clamp(0, sortedData.length); + + return sortedData.sublist(startIndex, endIndex); + } + + void handleEdit(Map item) { + setState(() { + selectedId = item['id']; + selectedBroker = item; + }); + } + + void filterData(String query) { + setState(() { + final q = query.toLowerCase(); + + if (q.isEmpty) { + filteredData = getBrokerData; + return; + } + + filteredData = getBrokerData.where((item) { + final isActiveStatus = item['is_active'] == "1" ? "active" : "inactive"; + + return (item['name'] ?? '').toString().toLowerCase().contains(q) || + (item['email'] ?? '').toString().toLowerCase().contains(q) || + (item['mobile'] ?? '').toString().toLowerCase().contains(q) || + (item['address'] ?? '').toString().toLowerCase().contains(q) || + (item['emp_id'] ?? item['agent_code'] ?? '') + .toString() + .toLowerCase() + .contains(q) || + isActiveStatus.contains(q); + }).toList(); + }); + } + + final TextEditingController _searchStaffController = TextEditingController(); + + Future getBroker() async { + print('getBroker called'); + setState(() { + isLoading = true; + }); + + try { + final response = await apiService.fetchMasterDropDown('Broker'); + + if (response['status'] == 200) { + print('getBroker - ${response['data']}'); + setState(() { + getBrokerData = List>.from(response['data']); + print('API Data - $getBrokerData'); + + filteredData = List.from(getBrokerData); + print('originalData - $filteredData'); + }); + } else { + getBrokerData = []; + filteredData = []; + } + } catch (e) { + print('Exception occurred: $e'); + } finally { + setState(() { + isLoading = false; + }); + } + } + + List _buildPopupMenuActions(BuildContext context, dynamic data) { + return [ + GestureDetector( + onTap: () { + Navigator.pop(context); + print('EDITStaff - ${data['id']}'); + dynamic id = data['id']; + context.go('/staff/$id'); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.edit_sharp, color: Color(0xFF319718), size: 18), + SizedBox(width: 10), + Text('Edit'), + ], + ), + ), + ]; + } + + @override + Widget build(BuildContext context) { + managerId = ref.watch(managerIdProvider); + + return MainLayout( + title: "Broker", + body: Container( + // padding: EdgeInsets.all(8.0), + // margin: EdgeInsets.all(10.0), + + // color: Colors.yellow.shade50, + width: MediaQuery.of(context).size.width, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + // height: 30, + // color: Colors.red.shade50, + width: MediaQuery.of(context).size.width, + child: GestureDetector( + onTap: () { + context.go(AppRoutes.dashboard); + }, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [Text('Broker List', style: _headerStyle)], + ), + ), + ), + + SizedBox(height: 5), + Expanded( + child: Container( + // color: Colors.green, + // color: Colors.green.shade50, + width: MediaQuery.of(context).size.width, + // margin: EdgeInsets.all(10.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15.0), + ), + + padding: EdgeInsets.all(15.0), + child: Column( + children: [ + Container( + // height: 40, + // color: Colors.pink, + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Broker( + key: ValueKey(selectedId), + data: selectedBroker, + id: selectedId, + onSubmit: () { + getBroker(); + setState(() { + selectedBroker = null; + selectedId = null; + }); // reset after save + }, + ), + Spacer(), + ThemedSearchField( + hintText: 'Search', + // backgroundColor: Color(0xFFF6F8F8), + backgroundColor: Color(0xFFFFFFFF), + txtHeight: 30, + onChanged: filterData, + controller: _searchStaffController, + txtwidth: MediaQuery.of(context).size.width * 0.2, + ), + + SizedBox(width: 10), + ExportBtn( + sheetName: "Broker", + fileName: "broker_list", + txt: !ResponsiveLayout.isMobile(context) + ? true + : false, + data: filteredData, + displayHeaders: ['S.No.', 'Broker', 'Status'], + keys: ["sno", "name", "is_active"], + ), + ], + ), + ), + SizedBox(height: 10), + Container( + decoration: BoxDecoration( + color: Color(0xFFF1F5F9), + + // color: Color(0xFFEDF6F5), + borderRadius: BorderRadius.circular(6), + ), + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ), + child: Row( + children: [ + Expanded( + flex: 1, + child: Text('S.No.', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Broker', style: _headerStyle), + ), + + Expanded( + flex: 1, + child: Text('Status', style: _headerStyle), + ), + Expanded( + flex: 1, + child: Text('Action', style: _headerStyle), + ), + ], + ), + ), + Expanded(child: _buildDataTable(context)), + ], + ), + ), + ), + + Container( + // height: 20, + width: MediaQuery.of(context).size.width, + // color: Colors.green.shade50, + child: PaginationControls( + currentPage: currentPage, + itemsPerPage: itemsPerPage, + // totalItems: dataVal.length, + totalItems: filteredData.length, + // activeColor: layoutColor, // your theme color + onPageChanged: (page) { + setState(() { + currentPage = page; + }); + }, + onItemsPerPageChanged: (items) { + setState(() { + itemsPerPage = items; + currentPage = 1; + }); + }, + ), + ), + ], + ), + ), + ); + } + + Widget _buildDataTable(BuildContext context) { + if (filteredData.isEmpty) { + return const SizedBox( + height: 50, + child: Center(child: Text('No available data')), + ); + } + + final sortedData = [..._paginatedData]; + + return ListView.builder( + // itemCount: filteredData.length + 1, // +1 for header, +1 for pagination + itemCount: sortedData.length + 1, // +1 for header, +1 for pagination + itemBuilder: (context, index) { + if (index == 0) return _buildHeader(); + // if (index == dataVal.length + 1) + // return _buildPagination(context); + final startIndex = ((currentPage - 1) * itemsPerPage); + // final item = filteredData[index - 1]; + final item = sortedData[index - 1]; + final sno = startIndex + index; + return _buildDataRow(item, sno); + }, + ); + } + + Widget _buildHeader() { + return SizedBox.shrink(); + } + + Widget _buildDataRow(Map item, sno) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 16), + // margin: const EdgeInsets.only(top: 10), + decoration: BoxDecoration( + color: Colors.white, + // color: Color(0xFFE0F7F9), + border: const Border( + bottom: BorderSide(color: Colors.blueGrey, width: 0.15), + ), + // borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + Expanded(flex: 1, child: Text('$sno' ?? '-', style: _dataBold)), + Expanded(flex: 2, child: Text(item['name'] ?? '-', style: _dataBold)), + Expanded( + flex: 1, + child: Row( + children: [ + Container( + // color: Colors.yellow.shade50, + child: Transform.scale( + scale: 0.4, // reduce size (0.7–0.9 works well) + child: Switch( + value: item['is_active'] == "1", + onChanged: (val) { + setState(() { + item['is_active'] = val ? "1" : "0"; + }); + final response = apiService.updateStatusMasters( + item['id'], + val ? "0" : "1", + 'Broker', + userId, + ); + print("Response - $response"); + }, + activeColor: Color(0xFF2E7D6E), // thumb when active + // activeColor: Color(0xFF425B5B), // thumb when active + activeTrackColor: Color(0xFFDCFCE7), // track when active + // activeTrackColor: Color(0xFFB2D8D3), // track when active + inactiveThumbColor: + Colors.grey.shade400, // thumb when inactive + inactiveTrackColor: + Colors.grey.shade300, // track when inactive + ), + ), + ), + ], + ), + ), + + Expanded( + flex: 1, + child: item['is_active'] == "1" + ? Row( + children: [ + Tooltip( + message: 'Edit', + child: IconButton( + icon: Image.asset( + "assets/miscellaneous/Edit.png", + height: 12, + width: 15, + ), + onPressed: () { + print('EDITBrokwer - ${item['id']}'); + print('EDITBrokwer - ${item}'); + dynamic id = item['id']; + + handleEdit(item); + + print(item); + }, + splashRadius: 28, + hoverColor: Colors.black12, + padding: const EdgeInsets.all(8), + constraints: const BoxConstraints(), + ), + ), + ], + ) + : Row( + children: [ + Image.asset( + "assets/miscellaneous/Edit_muted.png", + height: 15, + width: 15, + ), + ], + ), + ), + ], + ), + ); + } + + static final _dataBold = GoogleFonts.inter( + fontSize: 11.5, + + fontWeight: FontWeight.w400, + color: Color(0xFF000000), + ); + + static final _dataSub = GoogleFonts.inter( + fontSize: 10, + fontWeight: FontWeight.w300, + color: Color(0xFF585757), + ); + + static final _headerStyle = GoogleFonts.inter( + color: Color(0XFF1e293b), + fontSize: 12, + + fontWeight: FontWeight.w600, + ); +} diff --git a/lib/presentation/screens/Masters/PaymentMode/payment.dart b/lib/presentation/screens/Masters/PaymentMode/payment.dart new file mode 100644 index 0000000..aa0ab7f --- /dev/null +++ b/lib/presentation/screens/Masters/PaymentMode/payment.dart @@ -0,0 +1,318 @@ +import 'dart:convert'; +// import 'dart:io' as html; +import 'dart:typed_data'; // Import for Uint8List +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:http/http.dart' as http; +import 'package:nhance_partner/core/routing/routes.dart'; +import 'package:nhance_partner/data/utils/toastNotification.dart'; +import 'package:nhance_partner/presentation/themes/indicators/text_field_theme.dart'; + +import '../../../../core/config/env.dart'; +import '../../../../core/services/api_service.dart'; +import '../../../../data/services/auth_service.dart'; +import '../../../../data/utils/validators.dart'; +import '../../../layouts/main_layout.dart'; +import '../../../layouts/responsive_layout.dart'; +import '../../../providers/manager_provider.dart'; + +import 'package:universal_html/html.dart' as html; + +import '../../../themes/indicators/input_field_decoration.dart'; + +class Payment extends ConsumerStatefulWidget { + final String? id; + final Map? data; + final VoidCallback onSubmit; + const Payment({super.key, this.id, this.data, required this.onSubmit}); + @override + ConsumerState createState() => PaymentState(); +} + +class PaymentState extends ConsumerState { + final _formKey = GlobalKey(); + late ApiService apiService; + + final GlobalKey>> dropDownKey = + GlobalKey>>(); + + final GlobalKey>> + dropDownKeyHandler = GlobalKey>>(); + + List tabHeader = ['value', 'email', 'mobile', 'code']; + late String isActive = "1"; + html.File? passportFile; + String? selectedFileNames; + String? passportFileUrlFromApi; + dynamic selectedId; + String? _token; + bool isLoading = false; + bool showHandler = false; + + String? selectedRole; + List> filteredRolesData = []; + List> getRolesData = []; + + List? selectedHandlerIds = []; + String? selectedHandler; + List> filteredHandlersData = []; + List> getHandlersData = []; + + Map controllers = {}; + + dynamic userId; + dynamic managerId; + + Map dataDetails() { + final data = {"value": controllers["value"]?.text, "is_active": isActive}; + return data; + } + + @override + void initState() { + super.initState(); + apiService = ApiService(); + for (String field in tabHeader) { + controllers[field] = TextEditingController(); + } + + _initializeToken(); + updateData(); + + Future.microtask(() { + managerId = ref.watch(managerIdProvider); + userId = ref.watch(userIdProvider); + if (managerId != null) { + print('hansles'); + // getHandlers(managerId); + } + }); + } + + Future _initializeToken() async { + _token = await AuthService.getToken(); + print("APISERTOKEN - $_token"); + } + + void updateData() async { + if (widget.data != null) { + dynamic id = widget.data?['id']; + final data = widget.data; + + if (data == null) return; + setState(() { + selectedId = id; + controllers['value']?.text = data['value'] ?? ''; + controllers["is_active"]?.text = data['is_active'].toString(); + }); + } + } + + Future handleSave() async { + if (!_formKey.currentState!.validate()) return; + setState(() { + if (_formKey.currentState!.validate()) { + dataDetails(); + final dataSet = dataDetails(); + print("dataSetAgent - $dataSet"); + + print("TYPE of is_active → ${dataSet['is_active'].runtimeType}"); + print("TYPE of value → ${dataSet['value'].runtimeType}"); + createUserData(dataSet); + } else { + // isDisable = false; + } + }); + } + + void refresh() { + print('REfresj'); + widget.onSubmit(); + setState(() { + // clear all text controllers + for (var controller in controllers.values) { + controller.clear(); + } // 👈 clear selected agent + controllers['value']?.clear(); + }); + } + + Future createUserData(data) async { + final bool isUpdating = selectedId != null; + final dynamic id = isUpdating ? int.tryParse(selectedId.toString()) : 0; + final String apiUrldata; + + print("TYPE of id → $id - ${id.runtimeType}"); + print("TYPE of id → $userId - ${userId.runtimeType}"); + + apiUrldata = isUpdating + ? '${Env.apiUrl}/master/updatePaymentMode/$selectedId' + : '${Env.apiUrl}/master/createPaymentMode'; + + print('apiUrldata - $apiUrldata'); + // final token = await getToken(); // Fetch token + + if (_token == null) { + throw Exception('Token not found. Please log in.'); + } + + if (isUpdating) { + data['updated_by'] = userId.toString(); + } else { + data['created_by'] = userId.toString(); + } + + // if (isUpdating) { + // data['updated_by'] = userId; + // // data.remove('id'); + // } else { + // data['created_by'] = userId; + // } + + print("data------- $data}"); + + try { + final response = await http.post( + Uri.parse(apiUrldata), + headers: { + 'Authorization': 'Bearer $_token', + 'Content-Type': 'application/json', + 'app-signature': Env.App_Signature, + }, + body: jsonEncode(data), // Convert map to JSON + ); + + if (response.statusCode == 200) { + print("Payment submitted successfully!"); + print("Response: ${response.body}"); + + refresh(); + isUpdating + ? ToastHelper.showSuccessToast( + context, + 'Payment Updated Successfully', + ) + : ToastHelper.showSuccessToast( + context, + 'Payment Created Successfully', + ); + } else if (response.statusCode == 403) { + await apiService.clearLocalStorageAndRedirect(); + } else { + final responseBody = jsonDecode(response.body); + dynamic msg = responseBody['data']; + + print("Failed to submit plan. Status: ${response.statusCode}"); + print("Error: ${response.body}"); + + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text("Payment Creation Failed"), + content: Text(msg), + actions: [ + TextButton( + child: Text("OK"), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } catch (e) { + print(" Error submitting Staff: $e"); + } + } + + @override + void dispose() { + for (var controller in controllers.values) { + controller.dispose(); + } + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + buildFormFields(), + SizedBox(width: 5), + InkWell( + onTap: () { + handleSave(); + }, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 6), + + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8.0), + color: Color(0xFF2E7D6E), + ), + child: Text( + 'Save', + style: GoogleFonts.inter(color: Colors.white, fontSize: 10), + ), + ), + ), + SizedBox(width: 5), + InkWell( + onTap: () { + refresh(); + }, + child: Container( + padding: EdgeInsets.all(6.0), + decoration: BoxDecoration( + color: const Color(0xFF2E7D6E), + borderRadius: BorderRadius.circular(5.0), + ), + child: Icon(Icons.refresh, size: 13, color: Colors.white), + ), + ), + ], + ), + ); + } + + Widget buildFormFields() { + return Form( + key: _formKey, + child: Column(children: [buildName()]), + ); + } + + Widget buildName() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Payment Mode *", style: _textStyle), + SizedBox(width: 10), + ThemedFormField( + controller: controllers['value']!, + validator: (value) => Validators.requiredField(value, "value"), + txtwidth: MediaQuery.of(context).size.width * 0.15, + borderColor: Color(0xFFE2E8F0), + highlightColor: Color(0xFF50A398), + txtheight: 30, + ), + ], + ); + } + + static final _textStyle = GoogleFonts.inter( + fontSize: 11, + fontWeight: FontWeight.w600, + ); +} diff --git a/lib/presentation/screens/Masters/PaymentMode/paymentList.dart b/lib/presentation/screens/Masters/PaymentMode/paymentList.dart new file mode 100644 index 0000000..768f2a3 --- /dev/null +++ b/lib/presentation/screens/Masters/PaymentMode/paymentList.dart @@ -0,0 +1,471 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:nhance_partner/presentation/providers/userRoleProvider.dart'; +import 'package:nhance_partner/presentation/screens/Masters/PaymentMode/payment.dart'; + +import '../../../../core/routing/routes.dart'; +import '../../../../core/services/api_service.dart'; +import '../../../../data/utils/Pagination.dart'; +import '../../../layouts/main_layout.dart'; +import '../../../layouts/responsive_layout.dart'; +import '../../../providers/manager_provider.dart'; +import '../../../themes/indicators/export_btn.dart'; +import '../../../themes/indicators/filter_btn.dart'; +import '../../../themes/indicators/search_field_theme.dart'; +import '../../../themes/indicators/text_field_theme.dart'; +import '../../../widgets/custom_action_popup.dart'; + +class PaymentLsit extends ConsumerStatefulWidget { + const PaymentLsit({super.key}); + @override + ConsumerState createState() => PaymentLsitState(); +} + +class PaymentLsitState extends ConsumerState { + int currentPage = 1; + int itemsPerPage = 10; + late ApiService apiService; + dynamic managerId; + dynamic role; + dynamic prefid; + dynamic userId; + // List> dataVal = []; + List> getPaymentData = []; + List> originalData = []; + List> filteredData = []; + bool isLoading = false; + + Map? selectedPayment; + dynamic selectedId; + + @override + void initState() { + super.initState(); + + apiService = ApiService(); + + Future.microtask(() { + final data1 = ref.read(managerIdProvider); + // final data2 = ref.read(handlerIdProvider); + print("Edata1 => mId: $data1 -2 :"); + prefid = data1; + role = ref.read(userRoleProvider); + userId = ref.watch(userIdProvider); + print("E43 => mId: $prefid"); + if (prefid != null && role != null) { + getPayment(); + } + }); + // getPaymentList(); + } + + List get _paginatedData { + // Sort descending by id first + final sortedData = [...filteredData] + ..sort((a, b) => int.parse(b['id']) - int.parse(a['id'])); + + if (sortedData.isEmpty) return []; + + // Ensure currentPage is valid + final maxPage = (sortedData.length / itemsPerPage).ceil(); + final safePage = currentPage.clamp(1, maxPage); + + final startIndex = (safePage - 1) * itemsPerPage; + final endIndex = (startIndex + itemsPerPage).clamp(0, sortedData.length); + + return sortedData.sublist(startIndex, endIndex); + } + + void handleEdit(Map item) { + setState(() { + selectedId = item['id']; + selectedPayment = item; + }); + } + + void filterData(String query) { + setState(() { + final q = query.toLowerCase(); + + if (q.isEmpty) { + filteredData = getPaymentData; + return; + } + + filteredData = getPaymentData.where((item) { + final isActiveStatus = item['is_active'] == "1" ? "active" : "inactive"; + + return (item['value'] ?? '').toString().toLowerCase().contains(q) || + isActiveStatus.contains(q); + }).toList(); + }); + } + + final TextEditingController _searchStaffController = TextEditingController(); + + Future getPayment() async { + print('getPayment called'); + setState(() { + isLoading = true; + }); + + try { + final response = await apiService.fetchMasterDropDown('PaymentMode'); + + if (response['status'] == 200) { + print('getPayment - ${response['data']}'); + setState(() { + getPaymentData = List>.from(response['data']); + print('API Data - $getPaymentData'); + + filteredData = List.from(getPaymentData); + print('originalData - $filteredData'); + }); + } else { + getPaymentData = []; + filteredData = []; + } + } catch (e) { + print('Exception occurred: $e'); + } finally { + setState(() { + isLoading = false; + }); + } + } + + List _buildPopupMenuActions(BuildContext context, dynamic data) { + return [ + GestureDetector( + onTap: () { + Navigator.pop(context); + print('EDITStaff - ${data['id']}'); + dynamic id = data['id']; + context.go('/staff/$id'); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.edit_sharp, color: Color(0xFF319718), size: 18), + SizedBox(width: 10), + Text('Edit'), + ], + ), + ), + ]; + } + + @override + Widget build(BuildContext context) { + managerId = ref.watch(managerIdProvider); + + return MainLayout( + title: "Staff", + body: Container( + // padding: EdgeInsets.all(8.0), + // margin: EdgeInsets.all(10.0), + + // color: Colors.yellow.shade50, + width: MediaQuery.of(context).size.width, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + // height: 30, + // color: Colors.red.shade50, + width: MediaQuery.of(context).size.width, + child: GestureDetector( + onTap: () { + context.go(AppRoutes.dashboard); + }, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [Text('Payment List', style: _headerStyle)], + ), + ), + ), + + SizedBox(height: 5), + Expanded( + child: Container( + // color: Colors.green, + // color: Colors.green.shade50, + width: MediaQuery.of(context).size.width, + // margin: EdgeInsets.all(10.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15.0), + ), + + padding: EdgeInsets.all(15.0), + child: Column( + children: [ + Container( + // height: 40, + // color: Colors.pink, + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Payment( + key: ValueKey(selectedId), + data: selectedPayment, + id: selectedId, + onSubmit: () { + getPayment(); + setState(() { + selectedPayment = null; + selectedId = null; + }); // reset after save + }, + ), + Spacer(), + ThemedSearchField( + hintText: 'Search', + // backgroundColor: Color(0xFFF6F8F8), + backgroundColor: Color(0xFFFFFFFF), + txtHeight: 30, + onChanged: filterData, + controller: _searchStaffController, + txtwidth: MediaQuery.of(context).size.width * 0.2, + ), + + SizedBox(width: 10), + ExportBtn( + sheetName: "Payment", + fileName: "Payment_list", + txt: !ResponsiveLayout.isMobile(context) + ? true + : false, + data: filteredData, + displayHeaders: ['S.No.', 'Payment', 'Status'], + keys: ["sno", "value", "is_active"], + ), + ], + ), + ), + SizedBox(height: 10), + Container( + decoration: BoxDecoration( + color: Color(0xFFF1F5F9), + + // color: Color(0xFFEDF6F5), + borderRadius: BorderRadius.circular(6), + ), + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ), + child: Row( + children: [ + Expanded( + flex: 1, + child: Text('S.No.', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Payment', style: _headerStyle), + ), + + Expanded( + flex: 1, + child: Text('Status', style: _headerStyle), + ), + Expanded( + flex: 1, + child: Text('Action', style: _headerStyle), + ), + ], + ), + ), + Expanded(child: _buildDataTable(context)), + ], + ), + ), + ), + + Container( + // height: 20, + width: MediaQuery.of(context).size.width, + // color: Colors.green.shade50, + child: PaginationControls( + currentPage: currentPage, + itemsPerPage: itemsPerPage, + // totalItems: dataVal.length, + totalItems: filteredData.length, + // activeColor: layoutColor, // your theme color + onPageChanged: (page) { + setState(() { + currentPage = page; + }); + }, + onItemsPerPageChanged: (items) { + setState(() { + itemsPerPage = items; + currentPage = 1; + }); + }, + ), + ), + ], + ), + ), + ); + } + + Widget _buildDataTable(BuildContext context) { + if (filteredData.isEmpty) { + return const SizedBox( + height: 50, + child: Center(child: Text('No available data')), + ); + } + + final sortedData = [..._paginatedData]; + + return ListView.builder( + // itemCount: filteredData.length + 1, // +1 for header, +1 for pagination + itemCount: sortedData.length + 1, // +1 for header, +1 for pagination + itemBuilder: (context, index) { + if (index == 0) return _buildHeader(); + // if (index == dataVal.length + 1) + // return _buildPagination(context); + final startIndex = ((currentPage - 1) * itemsPerPage); + // final item = filteredData[index - 1]; + final item = sortedData[index - 1]; + final sno = startIndex + index; + return _buildDataRow(item, sno); + }, + ); + } + + Widget _buildHeader() { + return SizedBox.shrink(); + } + + Widget _buildDataRow(Map item, sno) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 16), + // margin: const EdgeInsets.only(top: 10), + decoration: BoxDecoration( + color: Colors.white, + // color: Color(0xFFE0F7F9), + border: const Border( + bottom: BorderSide(color: Colors.blueGrey, width: 0.15), + ), + // borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + Expanded(flex: 1, child: Text('$sno' ?? '-', style: _dataBold)), + Expanded( + flex: 2, + child: Text(item['value'] ?? '-', style: _dataBold), + ), + Expanded( + flex: 1, + child: Row( + children: [ + Container( + // color: Colors.yellow.shade50, + child: Transform.scale( + scale: 0.4, // reduce size (0.7–0.9 works well) + child: Switch( + value: item['is_active'] == "1", + onChanged: (val) { + setState(() { + item['is_active'] = val ? "1" : "0"; + }); + final response = apiService.updateStatusMasters( + item['id'], + val ? "0" : "1", + 'PaymentMode', + userId, + ); + print("Response - $response"); + }, + activeColor: Color(0xFF2E7D6E), // thumb when active + // activeColor: Color(0xFF425B5B), // thumb when active + activeTrackColor: Color(0xFFDCFCE7), // track when active + // activeTrackColor: Color(0xFFB2D8D3), // track when active + inactiveThumbColor: + Colors.grey.shade400, // thumb when inactive + inactiveTrackColor: + Colors.grey.shade300, // track when inactive + ), + ), + ), + ], + ), + ), + + Expanded( + flex: 1, + child: item['is_active'] == "1" + ? Row( + children: [ + Tooltip( + message: 'Edit', + child: IconButton( + icon: Image.asset( + "assets/miscellaneous/Edit.png", + height: 12, + width: 15, + ), + onPressed: () { + print('EDITBrokwer - ${item['id']}'); + print('EDITBrokwer - ${item}'); + dynamic id = item['id']; + + handleEdit(item); + + print(item); + }, + splashRadius: 28, + hoverColor: Colors.black12, + padding: const EdgeInsets.all(8), + constraints: const BoxConstraints(), + ), + ), + ], + ) + : Row( + children: [ + Image.asset( + "assets/miscellaneous/Edit_muted.png", + height: 15, + width: 15, + ), + ], + ), + ), + ], + ), + ); + } + + static final _dataBold = GoogleFonts.inter( + fontSize: 11.5, + + fontWeight: FontWeight.w400, + color: Color(0xFF000000), + ); + + static final _dataSub = GoogleFonts.inter( + fontSize: 10, + fontWeight: FontWeight.w300, + color: Color(0xFF585757), + ); + + static final _headerStyle = GoogleFonts.inter( + color: Color(0XFF1e293b), + fontSize: 12, + + fontWeight: FontWeight.w600, + ); +} diff --git a/lib/presentation/screens/UserManagement/Staff/staff.dart b/lib/presentation/screens/UserManagement/Staff/staff.dart index f4df99c..674f91c 100644 --- a/lib/presentation/screens/UserManagement/Staff/staff.dart +++ b/lib/presentation/screens/UserManagement/Staff/staff.dart @@ -385,8 +385,8 @@ class StaffState extends ConsumerState { padding: EdgeInsets.symmetric(horizontal: 14.0, vertical: 20.0), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.0), - color: Colors.white, - // color: Color(0xFFEDF6F5), + // color: Colors.white, + color: Color(0xFFEDF6F5), ), child: Column( children: [ diff --git a/lib/presentation/screens/UserManagement/Staff/staffList.dart b/lib/presentation/screens/UserManagement/Staff/staffList.dart index 1ebf08e..e0feb96 100644 --- a/lib/presentation/screens/UserManagement/Staff/staffList.dart +++ b/lib/presentation/screens/UserManagement/Staff/staffList.dart @@ -203,55 +203,60 @@ class StaffListState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - // Container( - // // height: 30, - // // color: Colors.red.shade50, - // width: MediaQuery.of(context).size.width, - // child: GestureDetector( - // onTap: () { - // context.go(AppRoutes.dashboard); - // }, - // child: Row( - // crossAxisAlignment: CrossAxisAlignment.center, - // mainAxisAlignment: MainAxisAlignment.start, - // children: [ - // // Icon( - // // Icons.arrow_left_sharp, - // // size: 35, - // // color: Color(0xFF425B5B), - // // ), - // // Tooltip( - // // message: 'Back', - // // child: IconButton( - // // icon: const Icon( - // // Icons.arrow_left_sharp, - // // size: 25, - // // color: Color(0xFF425B5B), - // // ), - // // onPressed: () { - // // context.go(AppRoutes.dashboard); - // // }, - // // splashRadius: 18, - // // hoverColor: Colors.black12, - // // padding: const EdgeInsets.all(4), - // // constraints: const BoxConstraints(), - // // ), - // // ), - // // const SizedBox(width: 15), // spacing between icon and text - // - // ], - // ), - // ), - // ), - // - // SizedBox(height: 5), + Container( + // height: 30, + // color: Colors.red.shade50, + width: MediaQuery.of(context).size.width, + child: GestureDetector( + onTap: () { + context.go(AppRoutes.dashboard); + }, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text('Staff List', style: _headerStyle), + // Icon( + // Icons.arrow_left_sharp, + // size: 35, + // color: Color(0xFF425B5B), + // ), + // Tooltip( + // message: 'Back', + // child: IconButton( + // icon: const Icon( + // Icons.arrow_left_sharp, + // size: 25, + // color: Color(0xFF425B5B), + // ), + // onPressed: () { + // context.go(AppRoutes.dashboard); + // }, + // splashRadius: 18, + // hoverColor: Colors.black12, + // padding: const EdgeInsets.all(4), + // constraints: const BoxConstraints(), + // ), + // ), + // const SizedBox(width: 15), // spacing between icon and text + ], + ), + ), + ), + + SizedBox(height: 5), Expanded( child: Container( // color: Colors.green, // color: Colors.green.shade50, width: MediaQuery.of(context).size.width, + // margin: EdgeInsets.all(10.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15.0), + ), - // padding: EdgeInsets.all(8.0), + padding: EdgeInsets.all(15.0), child: Column( children: [ Container( @@ -261,14 +266,6 @@ class StaffListState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - Text( - "Staff", - style: GoogleFonts.inter( - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - Spacer(), ThemedSearchField( hintText: 'Search', // backgroundColor: Color(0xFFF6F8F8), @@ -279,8 +276,7 @@ class StaffListState extends ConsumerState { txtwidth: MediaQuery.of(context).size.width * 0.2, ), - SizedBox(width: 5), - + SizedBox(width: 10), ExportBtn( sheetName: "Staff", fileName: "staff_list", @@ -306,7 +302,7 @@ class StaffListState extends ConsumerState { ], ), - SizedBox(width: 10), + Spacer(), InkWell( onTap: () { context.go('/staff/create'); @@ -320,15 +316,6 @@ class StaffListState extends ConsumerState { child: Row( mainAxisSize: MainAxisSize.min, children: [ - // Text( - // 'Create New Staff', - // style: GoogleFonts.inter( - // color: Colors.white, - // fontWeight: FontWeight.w500, - // fontSize: 11, - // ), - // ), - // SizedBox(width: 10), Tooltip( message: 'Create Staff', child: Icon( @@ -457,15 +444,15 @@ class StaffListState extends ConsumerState { Widget _buildDataRow(Map item, sno) { return Container( - padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 16), + padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 16), // margin: const EdgeInsets.only(top: 10), decoration: BoxDecoration( color: Colors.white, // color: Color(0xFFE0F7F9), border: const Border( - bottom: BorderSide(color: Color(0xFFEAEAEA), width: 1), + bottom: BorderSide(color: Colors.blueGrey, width: 0.15), ), - borderRadius: BorderRadius.circular(8), + // borderRadius: BorderRadius.circular(8), ), child: Row( children: [ @@ -607,7 +594,7 @@ class StaffListState extends ConsumerState { } static final _dataBold = GoogleFonts.inter( - fontSize: 12, + fontSize: 11.5, fontWeight: FontWeight.w400, color: Color(0xFF000000), diff --git a/lib/presentation/screens/staff/Enquiry/enquiry_inline_list.dart b/lib/presentation/screens/staff/Enquiry/enquiry_inline_list.dart index ba98f8c..e07c0d7 100644 --- a/lib/presentation/screens/staff/Enquiry/enquiry_inline_list.dart +++ b/lib/presentation/screens/staff/Enquiry/enquiry_inline_list.dart @@ -713,8 +713,19 @@ class EnquiryStaffState extends ConsumerState { key: dropDownSelectStaffKey, // selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null, selectedItem: selectedVehicle, - items: (filter, infiniteScrollProps) { - return filteredStaffDataEnqAsgn; + + // items: (filter, infiniteScrollProps) { + // return filteredStaffDataEnqAsgn; + // }, + items: (filter, infiniteScrollProps) async { + if (filter.isEmpty) { + return filteredStaffDataEnqAsgn; + } + return filteredStaffDataEnqAsgn.where((item) { + return item['name'].toString().toLowerCase().contains( + filter.toLowerCase(), + ); + }).toList(); }, itemAsString: (val) => val['name'].toString(), @@ -791,7 +802,10 @@ class EnquiryStaffState extends ConsumerState { ), showSearchBox: true, searchFieldProps: TextFieldProps( + autofocus: true, + style: GoogleFonts.inter(fontSize: 11, color: Colors.black), decoration: InputDecoration( + contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Search Staff ...", @@ -951,8 +965,11 @@ class EnquiryStaffState extends ConsumerState { ), showSearchBox: true, searchFieldProps: TextFieldProps( + style: GoogleFonts.inter(fontSize: 11, color: Colors.black), + autofocus: true, decoration: InputDecoration( + contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Search Insurer...", @@ -1084,7 +1101,9 @@ class EnquiryStaffState extends ConsumerState { ), showSearchBox: true, searchFieldProps: TextFieldProps( + style: GoogleFonts.inter(fontSize: 11, color: Colors.black), decoration: InputDecoration( + contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Search Broker...", @@ -1331,14 +1350,18 @@ class EnquiryStaffState extends ConsumerState { showSearchBox: true, searchFieldProps: TextFieldProps( + autofocus: true, + style: GoogleFonts.inter(fontSize: 11, color: Colors.black), decoration: InputDecoration( + contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Partner Name", hintStyle: GoogleFonts.inter( fontSize: 10, - color: Colors.grey, + color: Colors.black, ), + enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.white, @@ -1538,8 +1561,10 @@ class EnquiryStaffState extends ConsumerState { ), showSearchBox: true, searchFieldProps: TextFieldProps( + style: GoogleFonts.inter(fontSize: 11, color: Colors.black), padding: const EdgeInsets.all(1.0), decoration: InputDecoration( + contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Search Vehicle Type...", @@ -1549,10 +1574,10 @@ class EnquiryStaffState extends ConsumerState { borderSide: BorderSide(color: Colors.white), // 👈 Normal border ), isDense: true, // reduces height - contentPadding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 8, // reduce this value for smaller height - ), + // contentPadding: const EdgeInsets.symmetric( + // horizontal: 8, + // vertical: 8, // reduce this value for smaller height + // ), focusedBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.white, @@ -3340,33 +3365,34 @@ class EnquiryStaffState extends ConsumerState { // Premium DataCell( - (item['status'] == 'Proposal Created' || - item['status'] == 'Proposal Rejected') - ? SizedBox( - width: 80, - child: InkWell( - onTap: () { - // handle approval logic - - handleProposalAccept(context, item['id']); - }, - child: Text( - 'Click To\nApprove', - style: GoogleFonts.inter( - color: Colors.green, - fontSize: 11, - fontWeight: FontWeight.w700, - ), - ), - ), - ) - : SizedBox( - width: 80, - child: Text( - item['premium_amount']?.toString() ?? '-', - style: _dataBold, - ), - ), + // (item['status'] == 'Proposal Created' || + // item['status'] == 'Proposal Rejected') + // ? SizedBox( + // width: 80, + // child: InkWell( + // onTap: () { + // // handle approval logic + // + // handleProposalAccept(context, item['id']); + // }, + // child: Text( + // 'Click To\nApprove', + // style: GoogleFonts.inter( + // color: Colors.green, + // fontSize: 11, + // fontWeight: FontWeight.w700, + // ), + // ), + // ), + // ) + // : + SizedBox( + width: 80, + child: Text( + item['premium_amount']?.toString() ?? '-', + style: _dataBold, + ), + ), ), // Payment Mode @@ -3430,7 +3456,8 @@ class EnquiryStaffState extends ConsumerState { item['status'] ?? '-', style: GoogleFonts.inter( fontSize: 11, - color: statusTextColors[status] ?? Colors.black, + color: Color(0XFF1e293b), + // color: statusTextColors[status] ?? Colors.black, fontWeight: FontWeight.w500, ), // overflow: TextOverflow.clip, // diff --git a/lib/presentation/screens/staff/Enquiry/raise_enq_form.dart b/lib/presentation/screens/staff/Enquiry/raise_enq_form.dart index 8ac5f57..0a09afe 100644 --- a/lib/presentation/screens/staff/Enquiry/raise_enq_form.dart +++ b/lib/presentation/screens/staff/Enquiry/raise_enq_form.dart @@ -355,8 +355,13 @@ class RaiseEnqFormState extends ConsumerState { buildInsuredName(context, fromHeader: true), buildVehicleNumber(context), - - buildSave(context), + Row( + children: [ + buildRefresh(context), + SizedBox(width: 5), + buildSave(context), + ], + ), ], ), ), @@ -474,6 +479,7 @@ class RaiseEnqFormState extends ConsumerState { searchFieldProps: TextFieldProps( autofocus: true, decoration: InputDecoration( + contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Partner Name", @@ -673,6 +679,7 @@ class RaiseEnqFormState extends ConsumerState { searchFieldProps: TextFieldProps( autofocus: true, decoration: InputDecoration( + contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Search Insurer...", @@ -864,6 +871,7 @@ class RaiseEnqFormState extends ConsumerState { searchFieldProps: TextFieldProps( autofocus: true, decoration: InputDecoration( + contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Search Staff ...", @@ -927,7 +935,7 @@ class RaiseEnqFormState extends ConsumerState { resetFields(); }, child: Container( - padding: EdgeInsets.all(8.0), + padding: EdgeInsets.all(5.0), decoration: BoxDecoration( color: const Color(0xFF2E7D6E), borderRadius: BorderRadius.circular(5.0), @@ -937,6 +945,22 @@ class RaiseEnqFormState extends ConsumerState { ); } + Widget buildRefresh(context) { + return InkWell( + onTap: () { + resetFields(); + }, + child: Container( + padding: EdgeInsets.all(6.0), + decoration: BoxDecoration( + color: const Color(0xFF2E7D6E), + borderRadius: BorderRadius.circular(5.0), + ), + child: Icon(Icons.refresh, size: 18, color: Colors.white), + ), + ); + } + void resetFields() { print('Field ReSET'); // 1. Reset all text controllers diff --git a/lib/presentation/screens/staff/Enquiry/tabs/createQuotation.dart b/lib/presentation/screens/staff/Enquiry/tabs/createQuotation.dart index 23f475c..3d40ac4 100644 --- a/lib/presentation/screens/staff/Enquiry/tabs/createQuotation.dart +++ b/lib/presentation/screens/staff/Enquiry/tabs/createQuotation.dart @@ -25,7 +25,7 @@ import '../../../../themes/indicators/customizd_file_upload.dart'; import '../../../../themes/indicators/input_field_decoration.dart'; import '../../../../themes/indicators/text_field_theme.dart'; -class CreateQuotationForm extends ConsumerStatefulWidget { +class CreateProposalForm extends ConsumerStatefulWidget { final dynamic userId; final dynamic managerId; final dynamic selectedEnquiryId; @@ -34,7 +34,7 @@ class CreateQuotationForm extends ConsumerStatefulWidget { final dynamic selectedQuotationFrmListId; final void Function(String value) onSubmit; - const CreateQuotationForm({ + const CreateProposalForm({ super.key, required this.userId, required this.managerId, @@ -46,12 +46,11 @@ class CreateQuotationForm extends ConsumerStatefulWidget { }); @override - ConsumerState createState() => - CreateQuotationFormState(); - // State createState() => _CreateQuotationFormState(); + ConsumerState createState() => CreateProposalFormState(); + // State createState() => _CreateProposalFormState(); } -class CreateQuotationFormState extends ConsumerState { +class CreateProposalFormState extends ConsumerState { late ApiService apiService; String? _token; @@ -75,16 +74,31 @@ class CreateQuotationFormState extends ConsumerState { final GlobalKey>> dropDownKey = GlobalKey>>(); + final GlobalKey>> dropDownKeyBroker = + GlobalKey>>(); + final GlobalKey>> dropDownKeyInsurer = GlobalKey>>(); + final GlobalKey>> + dropDownSelectPaymentModeKey = + GlobalKey>>(); + List tabHeader = ['idv', 'premium_Amount', 'insurer']; + List> getBrokerData = []; + List> filteredBrokerData = []; + String? selectedBroker; + + List> getPaymentModeData = []; + List> filteredPaymentModeData = []; + List> getInsuranceTypeData = []; List> filteredInsuranceData = []; String? selectedInsPlanType; String? selectedEndorsement; + String? selectedPaymentMode; Map dataDetails() { final data = { @@ -94,6 +108,8 @@ class CreateQuotationFormState extends ConsumerState { // "insurer_id": selectedInsurer, "premium_amount": controllers["premium_Amount"]?.text, "insurance_plan_type_id": selectedInsPlanType, + "payment_mode_id": selectedPaymentMode, + "broker_id": selectedBroker, // "additional_uploaded_file_name": "extra_doc.pdf", // "created_by": widget.userId, "manager_id": widget.managerId, @@ -112,8 +128,10 @@ class CreateQuotationFormState extends ConsumerState { // 🔹 Init logic here (API calls, token fetch, etc.) _initializeToken(); getInsuranceType(); + getPaymentMode(); // getInsurers(); updateData(); + getBroker(); } Future _initializeToken() async { @@ -157,6 +175,37 @@ class CreateQuotationFormState extends ConsumerState { setState(() {}); } + Future getBroker() async { + print('getBroker called'); + setState(() { + isLoading = true; + }); + + try { + final response = await apiService.fetchMasterDropDown('Broker'); + + if (response['status'] == 200) { + print('getBroker - ${response['data']}'); + setState(() { + getBrokerData = List>.from(response['data']); + print('API Data - $getBrokerData'); + + filteredBrokerData = List.from(getBrokerData); + print('originalData - $filteredBrokerData'); + }); + } else { + getBrokerData = []; + filteredBrokerData = []; + } + } catch (e) { + print('Exception occurred: $e'); + } finally { + setState(() { + isLoading = false; + }); + } + } + void updateData() { if (widget.selectedQuotationFrmListId != null && widget.selectedQuotationFrmListdata!.isNotEmpty) { @@ -174,8 +223,11 @@ class CreateQuotationFormState extends ConsumerState { selectedInsPlanType = widget .selectedQuotationFrmListdata!['insurance_plan_type_id'] ?.toString(); + selectedBroker = widget.selectedQuotationFrmListdata!['broker_id'] + ?.toString(); - selectedInsurer = '1'; + selectedPaymentMode = widget.selectedQuotationFrmListdata!['broker_id'] + ?.toString(); // controllers["insurer"]?.text = 'LIC'; @@ -183,7 +235,7 @@ class CreateQuotationFormState extends ConsumerState { // widget.selectedQuotationFrmListdata!['insurer_id']?.toString() ?? ''; String? apiDocPath = - widget.selectedQuotationFrmListdata!["additional_uploaded_file_name"]; + widget.selectedQuotationFrmListdata!["policy_pdf_file_name"]; if (apiDocPath != null && apiDocPath.isNotEmpty) { print('apiDocPath - $apiDocPath'); selectedFileNames = apiDocPath.split('/').last; @@ -263,6 +315,39 @@ class CreateQuotationFormState extends ConsumerState { } } + Future getPaymentMode() async { + print('getPaymentMode called'); + setState(() { + isLoading = true; + }); + + try { + final response = await apiService.fetchMasterDropDown('PaymentMode'); + + if (response['status'] == 200) { + print('getPaymentModeData - ${response['data']}'); + setState(() { + getPaymentModeData = List>.from( + response['data'], + ); + print('API Data - $getPaymentModeData'); + + filteredPaymentModeData = List.from(getPaymentModeData); + print('originalData - $filteredPaymentModeData'); + }); + } else { + getPaymentModeData = []; + filteredPaymentModeData = []; + } + } catch (e) { + print('Exception occurred: $e'); + } finally { + setState(() { + isLoading = false; + }); + } + } + void handleDone() { if (!_formKey.currentState!.validate()) return; @@ -292,11 +377,9 @@ class CreateQuotationFormState extends ConsumerState { print('id - $id'); final uri = Uri.parse( // isUpdating - // ? 'https://venbait.in/nhance/partner/dev/api/agent/updateAgent' - // : 'https://venbait.in/nhance/partner/dev/api/agent/createAgent', - isUpdating - ? '${Env.apiUrl}quotation/updateQuotation' - : '${Env.apiUrl}quotation/createQuotation', + // ? '${Env.apiUrl}quotation/updateQuotation' + // : '${Env.apiUrl}quotation/createQuotation', + '${Env.apiUrl}quotation/proceedQuotation', ); if (_token == null) { throw Exception('Token not found. Please log in.'); @@ -336,14 +419,14 @@ class CreateQuotationFormState extends ConsumerState { try { if (docUploadedFile!.bytes != null) { final multipartFile = http.MultipartFile.fromBytes( - 'additional_uploaded_file_name', + 'policy_pdf_file_name', docUploadedFile!.bytes!, filename: docUploadedFile!.name, ); request.files.add(multipartFile); } else if (docUploadedFile!.path != null) { final multipartFile = await http.MultipartFile.fromPath( - 'additional_uploaded_file_name', + 'policy_pdf_file_name', docUploadedFile!.path!, filename: docUploadedFile!.name, ); @@ -369,8 +452,9 @@ class CreateQuotationFormState extends ConsumerState { print("Response: ${response.body}"); widget.onSubmit('Success'); + // ToastHelper.showErrorToast(context, 'Proposal Created'); reset(); - // Navigator.of(context).pop(); + Navigator.of(context).pop(); } else if (response.statusCode == 403) { await apiService.clearLocalStorageAndRedirect(); } else { @@ -411,7 +495,43 @@ class CreateQuotationFormState extends ConsumerState { // const SizedBox(height: 8), // 🔹 Switch content dynamically - buildFormFields(context), + Container( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.525, + child: buildFormFields(context), + ), + + Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + GestureDetector( + onTap: () { + handleDone(); + // widget.onSubmit(controller.text.trim()); + // Navigator.of(context).pop(); + }, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 25.0, + vertical: 10, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8.0), + color: const Color(0xFF425B5B), + ), + child: Text( + 'Save', + style: GoogleFonts.poppins( + color: Colors.white, + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ], + ), ], ); } @@ -419,54 +539,43 @@ class CreateQuotationFormState extends ConsumerState { Widget buildFormFields(BuildContext context) { return Form( key: _formKey, - // autovalidateMode: AutovalidateMode.onUserInteraction, - // autovalidateMode: _autoValidate - // ? AutovalidateMode.onUserInteraction - // : AutovalidateMode.disabled, - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - + child: Column( children: [ - buildIdv(context), - Spacer(), - // buildInsurer(context), - buildInsurancePlanType(context), - Spacer(), - buildPremiumAmnt(context), - Spacer(), - // buildDocuments(context), - GestureDetector( - onTap: () { - handleDone(); - // widget.onSubmit(controller.text.trim()); - // Navigator.of(context).pop(); - }, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 25.0, - vertical: 15, - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8.0), - color: const Color(0xFF425B5B), - ), - child: const Text( - 'Save', - style: TextStyle( - color: Colors.white, - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, - // if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), - // _buildResponsiveRow( - // context, - // buildAdditonalDocuments(context), - // buildRemarks(context), - // ), + children: [ + buildIdv(context), + Spacer(), + // buildInsurer(context), + buildInsurancePlanType(context), + Spacer(), + buildPremiumAmnt(context), + Spacer(), + // buildDocuments(context), + + // if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), + // _buildResponsiveRow( + // context, + // buildAdditonalDocuments(context), + // buildRemarks(context), + // ), + ], + ), + SizedBox(height: 10), + + Row( + crossAxisAlignment: CrossAxisAlignment.end, + + children: [ + buildPaymentMode(context), + Spacer(), + // buildInsurer(context), + buildBroker(context), + Spacer(), + buildDocuments(context), Spacer(), + ], + ), ], ), ); @@ -486,103 +595,15 @@ class CreateQuotationFormState extends ConsumerState { FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')), ], validator: (value) => Validators.doubleNumber(value, "IDV"), + borderColor: Color(0xFFE2E8F0), + highlightColor: Color(0xFF50A398), // validator: (value) => Validators.number(value, "IDV"), - backgroundColor: Color(0xFFEDF6F5), + // backgroundColor: Color(0xFFEDF6F5), // readOnly: true, txtwidth: ResponsiveLayout.isMobile(context) ? null - : MediaQuery.of(context).size.width * 0.15, - ), - ], - ); - } - - Widget buildInsurer2(BuildContext context) { - Map? selectedInsurerd = filteredInsurersData.firstWhere( - (item) => item['id'].toString() == selectedInsurer, - orElse: () => {}, - ); - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Insurer *', style: _textStyle), - SizedBox(height: 10), - Container( - decoration: BoxDecoration( - color: Colors.white, - // borderRadius: BorderRadius.circular(10.0), - ), - width: ResponsiveLayout.isMobile(context) - ? null - : MediaQuery.of(context).size.width * 0.26, - // height: 40, - child: DropdownSearch>( - key: dropDownKeyInsurer, - selectedItem: selectedInsurerd.isNotEmpty ? selectedInsurerd : null, - items: (filter, infiniteScrollProps) { - return filteredInsurersData; - }, - - itemAsString: (val) => val['name'].toString(), // what to show - compareFn: (item, selectedItem) => - item['id'] == selectedItem['id'], // ✅ compare by id - validator: (val) { - if (val == null) { - return "Required"; // ✅ error message - } - return null; - }, - decoratorProps: DropDownDecoratorProps( - decoration: - AppInputDecorations.dropdownDecoration( - label: "Select Insurer", - ).copyWith( - filled: true, - fillColor: Color( - 0xFFEDF6F5, - ), // 👈 makes the dropdown input white - ), - ), - - popupProps: PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 250), - menuProps: MenuProps( - backgroundColor: - Colors.white, // 👈 sets dropdown background to white - ), - showSearchBox: true, - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - filled: true, - fillColor: Colors.white, - hintText: "Search Insurer...", - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.white, - ), // 👈 Normal border - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.white, - width: 1.5, - ), // 👈 Focused border - ), - ), - ), - // constraints: BoxConstraints(), - ), - - onChanged: (val) { - if (val != null) { - print("Selected Insurer : ${val['name']}"); - print("Id: ${val['id']}"); - selectedInsurer = val['id']; - // controllers['agentId']?.text = val['agent_code']; - // agentId = agent['id']; - } - }, - ), + : MediaQuery.of(context).size.width * 0.18, + txtheight: 35, ), ], ); @@ -596,7 +617,9 @@ class CreateQuotationFormState extends ConsumerState { SizedBox(height: 10), ThemedFormField( controller: controllers['premium_Amount']!, - backgroundColor: Color(0xFFEDF6F5), + borderColor: Color(0xFFE2E8F0), + highlightColor: Color(0xFF50A398), + // backgroundColor: Color(0xFFEDF6F5), inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')), ], @@ -604,7 +627,8 @@ class CreateQuotationFormState extends ConsumerState { // validator: (value) => Validators.number(value, "PremiumAmount "), txtwidth: ResponsiveLayout.isMobile(context) ? null - : MediaQuery.of(context).size.width * 0.15, + : MediaQuery.of(context).size.width * 0.18, + txtheight: 35, ), ], ); @@ -625,15 +649,24 @@ class CreateQuotationFormState extends ConsumerState { color: Colors.white, width: ResponsiveLayout.isMobile(context) ? null - : MediaQuery.of(context).size.width * 0.15, - // height: 40, + : MediaQuery.of(context).size.width * 0.18, + height: 35, child: DropdownSearch>( key: dropDownKey, selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null, - items: (filter, infiniteScrollProps) { - return filteredInsuranceData; + // items: (filter, infiniteScrollProps) { + // return filteredInsuranceData; + // }, + items: (filter, infiniteScrollProps) async { + if (filter.isEmpty) { + return filteredInsuranceData; + } + return filteredInsuranceData.where((item) { + return item['name'].toString().toLowerCase().contains( + filter.toLowerCase(), + ); + }).toList(); }, - itemAsString: (val) => val['insurance_plan_type'].toString(), compareFn: (item, selectedItem) => item['id'] == selectedItem['id'], // ✅ compare by id @@ -643,18 +676,36 @@ class CreateQuotationFormState extends ConsumerState { } return null; }, + decoratorProps: DropDownDecoratorProps( decoration: AppInputDecorations.dropdownDecoration( - label: "Select Plan Type", + label: "Select Staff Member", ).copyWith( filled: true, - fillColor: Color( - 0xFFEDF6F5, - ), // 👈 makes the dropdown input white + fillColor: + Colors.white, // 👈 makes the dropdown input white + isDense: true, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide( + color: Color(0xFFE2E8F0), + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide( + color: Color(0xFFE2E8F0), + width: 0.5, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 8, + vertical: 6, + ), ), ), - popupProps: PopupProps.menu( fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250), @@ -664,10 +715,16 @@ class CreateQuotationFormState extends ConsumerState { ), showSearchBox: true, searchFieldProps: TextFieldProps( + autofocus: true, decoration: InputDecoration( + contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, - hintText: "Search Plan Type...", + hintText: "Search Plan Type ...", + hintStyle: GoogleFonts.inter( + fontSize: 12, + color: Colors.black, + ), enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.white, @@ -681,6 +738,38 @@ class CreateQuotationFormState extends ConsumerState { ), ), ), + + itemBuilder: (context, item, isDisabled, isSelected) { + return Container( + // color: isSelected ? Colors.blue.withOpacity(0.1) : null, + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 3, + ), + child: Text( + item['insurance_plan_type'].toString(), + style: GoogleFonts.inter(fontSize: 12, color: Colors.black), + ), + ); + }, + // searchFieldProps: TextFieldProps( + // decoration: InputDecoration( + // filled: true, + // fillColor: Colors.white, + // hintText: "Search Plan Type...", + // enabledBorder: OutlineInputBorder( + // borderSide: BorderSide( + // color: Colors.white, + // ), // 👈 Normal border + // ), + // focusedBorder: OutlineInputBorder( + // borderSide: BorderSide( + // color: Colors.white, + // width: 1.5, + // ), // 👈 Focused border + // ), + // ), + // ), // constraints: BoxConstraints(), ), @@ -699,22 +788,291 @@ class CreateQuotationFormState extends ConsumerState { ); } + Widget buildPaymentMode(context) { + Map? selectedVehicle = filteredPaymentModeData.firstWhere( + (item) => item['id'].toString() == selectedPaymentMode, + orElse: () => {}, + ); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Payment Mode", style: _textStyle), + SizedBox(height: 10), + Container( + color: Colors.white, + width: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.18, + height: 35, + child: DropdownSearch>( + key: dropDownSelectPaymentModeKey, + selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null, + // items: (filter, infiniteScrollProps) { + // return filteredInsuranceData; + // }, + items: (filter, infiniteScrollProps) async { + if (filter.isEmpty) { + return filteredPaymentModeData; + } + return filteredPaymentModeData.where((item) { + return item['name'].toString().toLowerCase().contains( + filter.toLowerCase(), + ); + }).toList(); + }, + itemAsString: (val) => val['value'].toString(), + compareFn: (item, selectedItem) => + item['id'] == selectedItem['id'], // ✅ compare by id + validator: (val) { + if (val == null) { + return "Required"; // ✅ error message + } + return null; + }, + + decoratorProps: DropDownDecoratorProps( + decoration: + AppInputDecorations.dropdownDecoration( + label: "Select Payment Mode", + ).copyWith( + filled: true, + fillColor: + Colors.white, // 👈 makes the dropdown input white + isDense: true, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide( + color: Color(0xFFE2E8F0), + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide( + color: Color(0xFFE2E8F0), + width: 0.5, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 8, + vertical: 6, + ), + ), + ), + popupProps: PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250), + menuProps: MenuProps( + backgroundColor: + Colors.white, // 👈 sets dropdown background to white + ), + showSearchBox: true, + searchFieldProps: TextFieldProps( + autofocus: true, + decoration: InputDecoration( + contentPadding: EdgeInsets.all(1), + filled: true, + fillColor: Colors.white, + hintText: "Search Payment Mode ...", + hintStyle: GoogleFonts.inter( + fontSize: 12, + color: Colors.black, + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.white, + ), // 👈 Normal border + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.white, + width: 1.5, + ), // 👈 Focused border + ), + ), + ), + + itemBuilder: (context, item, isDisabled, isSelected) { + return Container( + // color: isSelected ? Colors.blue.withOpacity(0.1) : null, + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 3, + ), + child: Text( + item['value'].toString(), + style: GoogleFonts.inter(fontSize: 12, color: Colors.black), + ), + ); + }, + ), + + onChanged: (val) { + if (val != null) { + print("Selected value : ${val['value']}"); + print("Id: ${val['id']}"); + selectedPaymentMode = val['id']; + // controllers['agentId']?.text = val['agent_code']; + // agentId = agent['id']; + } + }, + ), + ), + ], + ); + } + + Widget buildBroker(context) { + Map? selectedBrokers = filteredBrokerData.firstWhere( + (item) => item['id'].toString() == selectedBroker, + orElse: () => {}, + ); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Broker", style: _textStyle), + SizedBox(height: 10), + Container( + color: Colors.white, + width: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.18, + height: 35, + child: DropdownSearch>( + key: dropDownKeyBroker, + selectedItem: selectedBrokers.isNotEmpty ? selectedBrokers : null, + // items: (filter, infiniteScrollProps) { + // return filteredInsuranceData; + // }, + items: (filter, infiniteScrollProps) async { + if (filter.isEmpty) { + return filteredBrokerData; + } + return filteredBrokerData.where((item) { + return item['name'].toString().toLowerCase().contains( + filter.toLowerCase(), + ); + }).toList(); + }, + itemAsString: (val) => val['name'].toString(), + compareFn: (item, selectedItem) => + item['id'] == selectedItem['id'], // ✅ compare by id + validator: (val) { + if (val == null) { + return "Required"; // ✅ error message + } + return null; + }, + + decoratorProps: DropDownDecoratorProps( + decoration: + AppInputDecorations.dropdownDecoration( + label: "Select Broker", + ).copyWith( + filled: true, + fillColor: + Colors.white, // 👈 makes the dropdown input white + isDense: true, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide( + color: Color(0xFFE2E8F0), + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: const BorderSide( + color: Color(0xFFE2E8F0), + width: 0.5, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 8, + vertical: 6, + ), + ), + ), + popupProps: PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250), + menuProps: MenuProps( + backgroundColor: + Colors.white, // 👈 sets dropdown background to white + ), + showSearchBox: true, + searchFieldProps: TextFieldProps( + autofocus: true, + decoration: InputDecoration( + contentPadding: EdgeInsets.all(1), + filled: true, + fillColor: Colors.white, + hintText: "Search Broker...", + hintStyle: GoogleFonts.inter( + fontSize: 12, + color: Colors.black, + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.white, + ), // 👈 Normal border + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.white, + width: 1.5, + ), // 👈 Focused border + ), + ), + ), + + itemBuilder: (context, item, isDisabled, isSelected) { + return Container( + // color: isSelected ? Colors.blue.withOpacity(0.1) : null, + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 3, + ), + child: Text( + item['name'].toString(), + style: GoogleFonts.inter(fontSize: 12, color: Colors.black), + ), + ); + }, + ), + + onChanged: (val) { + if (val != null) { + print("Selected ClaimsType : ${val['id']}"); + print("Id: ${val['id']}"); + selectedBroker = val['id']; + } + }, + ), + ), + ], + ); + } + Widget buildDocuments(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Proposal Documents ', style: _textStyle), + Text('Upload Policy PDF', style: _textStyle), const SizedBox(height: 10), - Column( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.end, + Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ ThemedUploadField( hintText: selectedFileNames ?? "Upload Document", + txtheight: 40, txtwidth: ResponsiveLayout.isMobile(context) ? null - : MediaQuery.of(context).size.width * 0.26, - backgroundColor: Color(0xFFEDF6F5), + : MediaQuery.of(context).size.width * 0.18, + borderColor: Color(0xFFE2E8F0), + // highlightColor: Color(0xFF50A398), + // backgroundColor: Color(0xFFEDF6F5), onFileSelected: (fileName, file) { print("Picked file: $fileName (${file.size} bytes)"); setState(() { @@ -722,47 +1080,40 @@ class CreateQuotationFormState extends ConsumerState { }); }, ), - const SizedBox(height: 5), - - if (docUploadedFileUrlFromApi != null) - Container( - // color: Colors.white, - child: Row( - children: [ - GestureDetector( - onTap: () => apiService.downloadFile( - apiUrl: - 'api/quotation/downloadAdditionalUploadedFile?id=$selectedId', - apiId: selectedId, - localFile: docUploadedFile, - fileName: selectedFileNames, - ), - child: Container( - padding: const EdgeInsets.all(5), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - color: Color(0xFF425B5B), - // color: Colors.green.shade300, - ), - child: Row( - children: const [ - Text( - "Download", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w200, - color: Colors.white, - ), - ), - SizedBox(width: 5), - Icon(Icons.download, size: 13, color: Colors.white), - ], - ), - ), - ), - ], - ), - ), + // const SizedBox(height: 5), + // + // if (docUploadedFileUrlFromApi != null) + // Container( + // // color: Colors.white, + // child: Row( + // children: [ + // GestureDetector( + // onTap: () => apiService.downloadFile( + // // apiUrl: + // // 'api/quotation/downloadAdditionalUploadedFile?id=$selectedId', + // apiUrl: + // 'api/policy/downloadPolicyFile?policy_id=$selectedId&file_type=policy_pdf', + // apiId: selectedId, + // localFile: docUploadedFile, + // fileName: selectedFileNames, + // ), + // child: Container( + // padding: const EdgeInsets.all(5), + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(5), + // color: Color(0xFF425B5B), + // // color: Colors.green.shade300, + // ), + // child: Row( + // children: const [ + // Icon(Icons.download, size: 13, color: Colors.white), + // ], + // ), + // ), + // ), + // ], + // ), + // ), ], ), ], @@ -772,7 +1123,8 @@ class CreateQuotationFormState extends ConsumerState { // ------------------- STyle --------------------------------- static final TextStyle _textStyle = TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, + fontSize: 11, + color: Color(0XFF334155), + fontWeight: FontWeight.w500, ); } diff --git a/lib/presentation/screens/staff/Enquiry/tabs/createQuotationOld.dart b/lib/presentation/screens/staff/Enquiry/tabs/createQuotationOld.dart new file mode 100644 index 0000000..23f475c --- /dev/null +++ b/lib/presentation/screens/staff/Enquiry/tabs/createQuotationOld.dart @@ -0,0 +1,778 @@ +import 'dart:convert'; + +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:http/http.dart' as http; +import 'package:nhance_partner/data/utils/toastNotification.dart'; + +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../../../../core/config/env.dart'; +import '../../../../../core/routing/routes.dart'; +import '../../../../../core/services/api_service.dart'; +import '../../../../../data/services/auth_service.dart'; +import '../../../../../data/utils/validators.dart'; +import '../../../../layouts/responsive_layout.dart'; +import '../../../../providers/manager_provider.dart'; +import '../../../../providers/quotation_staff_proivder.dart'; +import '../../../../themes/indicators/customizd_file_upload.dart'; +import '../../../../themes/indicators/input_field_decoration.dart'; +import '../../../../themes/indicators/text_field_theme.dart'; + +class CreateQuotationForm extends ConsumerStatefulWidget { + final dynamic userId; + final dynamic managerId; + final dynamic selectedEnquiryId; + final dynamic selectedInsurdId; + final dynamic selectedQuotationFrmListdata; + final dynamic selectedQuotationFrmListId; + final void Function(String value) onSubmit; + + const CreateQuotationForm({ + super.key, + required this.userId, + required this.managerId, + required this.selectedEnquiryId, + required this.selectedInsurdId, + this.selectedQuotationFrmListdata, + this.selectedQuotationFrmListId, + required this.onSubmit, + }); + + @override + ConsumerState createState() => + CreateQuotationFormState(); + // State createState() => _CreateQuotationFormState(); +} + +class CreateQuotationFormState extends ConsumerState { + late ApiService apiService; + String? _token; + + String? selectedFileNames; + + List> getInsurersData = []; + List> filteredInsurersData = []; + String? selectedInsurer; + + bool isLoading = false; + bool _autoValidate = false; + late TextEditingController controller; + Map controllers = {}; + + final _formKey = GlobalKey(); + + String? docUploadedFileUrlFromApi; + String? selectedId; + PlatformFile? docUploadedFile; + + final GlobalKey>> dropDownKey = + GlobalKey>>(); + + final GlobalKey>> + dropDownKeyInsurer = GlobalKey>>(); + + List tabHeader = ['idv', 'premium_Amount', 'insurer']; + + List> getInsuranceTypeData = []; + List> filteredInsuranceData = []; + + String? selectedInsPlanType; + String? selectedEndorsement; + + Map dataDetails() { + final data = { + "enquiry_id": widget.selectedEnquiryId, + "insured_declared_value": controllers["idv"]?.text, + "insurer_id": widget.selectedInsurdId, + // "insurer_id": selectedInsurer, + "premium_amount": controllers["premium_Amount"]?.text, + "insurance_plan_type_id": selectedInsPlanType, + // "additional_uploaded_file_name": "extra_doc.pdf", + // "created_by": widget.userId, + "manager_id": widget.managerId, + }; + return data; + } + + @override + void initState() { + super.initState(); + apiService = ApiService(); + for (String field in tabHeader) { + controllers[field] = TextEditingController(); + } + + // 🔹 Init logic here (API calls, token fetch, etc.) + _initializeToken(); + getInsuranceType(); + // getInsurers(); + updateData(); + } + + Future _initializeToken() async { + _token = await AuthService.getToken(); + print("APISERTOKEN - $_token"); + } + + @override + void dispose() { + // Dispose all TextEditingControllers + for (var controller in controllers.values) { + controller.dispose(); + } + super.dispose(); + } + + void reset() { + print('RESET'); + _formKey.currentState?.reset(); + // Clear all TextEditingControllers + for (var controller in controllers.values) { + controller.clear(); + } + dropDownKey.currentState?.changeSelectedItem(null); + dropDownKeyInsurer.currentState?.changeSelectedItem(null); + + // Reset dropdowns / selections + selectedInsurer = null; + selectedInsPlanType = null; + selectedEndorsement = null; + + // Reset file selection + selectedFileNames = null; + docUploadedFile = null; + docUploadedFileUrlFromApi = null; + + // Reset selected ID + selectedId = null; + + // Trigger UI update + setState(() {}); + } + + void updateData() { + if (widget.selectedQuotationFrmListId != null && + widget.selectedQuotationFrmListdata!.isNotEmpty) { + print('checkData -- ${widget.selectedQuotationFrmListdata}'); + selectedId = widget.selectedQuotationFrmListId!; + // Pre-fill controllers + controllers["idv"]?.text = + widget.selectedQuotationFrmListdata!['insured_declared_value'] + ?.toString() ?? + ''; + controllers["premium_Amount"]?.text = + widget.selectedQuotationFrmListdata!['premium_amount']?.toString() ?? + ''; + + selectedInsPlanType = widget + .selectedQuotationFrmListdata!['insurance_plan_type_id'] + ?.toString(); + + selectedInsurer = '1'; + + // controllers["insurer"]?.text = 'LIC'; + + // selectedInsurer = + // widget.selectedQuotationFrmListdata!['insurer_id']?.toString() ?? ''; + + String? apiDocPath = + widget.selectedQuotationFrmListdata!["additional_uploaded_file_name"]; + if (apiDocPath != null && apiDocPath.isNotEmpty) { + print('apiDocPath - $apiDocPath'); + selectedFileNames = apiDocPath.split('/').last; + print('selectedFileNames - $selectedFileNames'); + docUploadedFileUrlFromApi = apiDocPath; + print('passportFileUrlFromApi - $docUploadedFileUrlFromApi'); + docUploadedFile = null; + } else { + selectedFileNames = null; + docUploadedFile = null; + docUploadedFileUrlFromApi = null; + } + } + } + + Future getInsurers() async { + print('Insurers called'); + setState(() { + isLoading = true; + }); + + try { + final response = await apiService.fetchMasterDropDown('Insurers'); + + if (response['status'] == 200) { + print('getInsurers - ${response['data']}'); + setState(() { + getInsurersData = List>.from(response['data']); + print('API Data - $getInsurersData'); + + filteredInsurersData = List.from(getInsurersData); + print('originalData - $filteredInsurersData'); + }); + } else { + getInsurersData = []; + filteredInsurersData = []; + } + } catch (e) { + print('Exception occurred: $e'); + } finally { + setState(() { + isLoading = false; + }); + } + } + + Future getInsuranceType() async { + print('getClaimList called'); + setState(() { + isLoading = true; + }); + + try { + final response = await apiService.fetchMasterDropDown('InsuranceType'); + + if (response['status'] == 200) { + print('getInsuranceTypeData - ${response['data']}'); + setState(() { + getInsuranceTypeData = List>.from( + response['data'], + ); + print('API Data - $getInsuranceTypeData'); + + filteredInsuranceData = List.from(getInsuranceTypeData); + print('originalData - $filteredInsuranceData'); + }); + } else { + getInsuranceTypeData = []; + filteredInsuranceData = []; + } + } catch (e) { + print('Exception occurred: $e'); + } finally { + setState(() { + isLoading = false; + }); + } + } + + void handleDone() { + if (!_formKey.currentState!.validate()) return; + + // setState(() { + // _autoValidate = true; // enable autovalidation after first save attempt + // }); + setState(() { + if (_formKey.currentState!.validate()) { + dataDetails(); + final dataSet = dataDetails(); + print("dataSetAgent - $dataSet"); + // print("managerId - $managerId ,userId - $userId "); + createUserData(dataSet); + } else { + // isDi sable = false; + } + }); + } + + Future createUserData(Map userData) async { + // final bool isUpdating = widget.selectedQuotationFrmListId != null; + // final id = widget.selectedQuotationFrmListId!; + + final bool isUpdating = widget.selectedQuotationFrmListId != null; + final id = widget.selectedQuotationFrmListId; // keep nullable + + print('id - $id'); + final uri = Uri.parse( + // isUpdating + // ? 'https://venbait.in/nhance/partner/dev/api/agent/updateAgent' + // : 'https://venbait.in/nhance/partner/dev/api/agent/createAgent', + isUpdating + ? '${Env.apiUrl}quotation/updateQuotation' + : '${Env.apiUrl}quotation/createQuotation', + ); + if (_token == null) { + throw Exception('Token not found. Please log in.'); + } + + // Use MultipartRequest (POST only) + final request = http.MultipartRequest('POST', uri); + request.headers['Authorization'] = 'Bearer $_token'; + request.headers['app-signature'] = Env.App_Signature; + + // If updating, spoof the method Laravel-style + if (isUpdating) { + print('Updatrinf'); + // request.fields['_method'] = 'PUT'; + request.fields['id'] = id!; + request.fields['updated_by'] = widget.userId!.toString(); + } else { + print('Not Updatrinf'); + request.fields['created_by'] = widget.userId!.toString(); + } + + print("USerDAta - $userData"); + + // userData.forEach((key, value) { + // request.fields[key] = value.toString(); + // print("✅ Encoded travel_details2: ${request.fields[key]}"); + // }); + + userData.forEach((key, value) { + // if (key != 'certificate_file_name') { + request.fields[key] = value.toString(); + print("✅ Encoded $key: ${request.fields[key]}"); + // } + }); + + if (docUploadedFile != null) { + try { + if (docUploadedFile!.bytes != null) { + final multipartFile = http.MultipartFile.fromBytes( + 'additional_uploaded_file_name', + docUploadedFile!.bytes!, + filename: docUploadedFile!.name, + ); + request.files.add(multipartFile); + } else if (docUploadedFile!.path != null) { + final multipartFile = await http.MultipartFile.fromPath( + 'additional_uploaded_file_name', + docUploadedFile!.path!, + filename: docUploadedFile!.name, + ); + request.files.add(multipartFile); + } + print("📎 File attached: ${docUploadedFile!.name}"); + } catch (e) { + print("❌ Failed to attach file: $e"); + } + } + + print(" Sending request with fields: ${request.fields}"); + + try { + final streamedResponse = await request.send(); + final response = await http.Response.fromStream(streamedResponse); + print("Response status: ${response.statusCode}"); + print("Response body: ${response.body}"); + + if (response.statusCode == 200 || response.statusCode == 201) { + // dispose(); + print("✅ Agent submitted successfully!"); + + print("Response: ${response.body}"); + widget.onSubmit('Success'); + reset(); + // Navigator.of(context).pop(); + } else if (response.statusCode == 403) { + await apiService.clearLocalStorageAndRedirect(); + } else { + final responseBody = jsonDecode(response.body); + dynamic msg = responseBody['data']; + print("❌ Submission failed. Status: ${response.statusCode}"); + print("Body: ${response.body}"); + + ToastHelper.showErrorToast(context, 'Proposal Creation Failed'); + } + } catch (e) { + print("🔥 Error submitting user: $e"); + } + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Header row + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // widget.selectedQuotationFrmListId != null + // ? 'Update Proposal' + // : 'Create Proposal', + // style: GoogleFonts.inter( + // color: const Color(0xFF374141), + // fontSize: 14, + // fontWeight: FontWeight.w600, + // ), + // ), + // ], + // ), + // + // const SizedBox(height: 8), + + // 🔹 Switch content dynamically + buildFormFields(context), + ], + ); + } + + Widget buildFormFields(BuildContext context) { + return Form( + key: _formKey, + // autovalidateMode: AutovalidateMode.onUserInteraction, + // autovalidateMode: _autoValidate + // ? AutovalidateMode.onUserInteraction + // : AutovalidateMode.disabled, + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + + children: [ + buildIdv(context), + Spacer(), + // buildInsurer(context), + buildInsurancePlanType(context), + Spacer(), + buildPremiumAmnt(context), + Spacer(), + // buildDocuments(context), + GestureDetector( + onTap: () { + handleDone(); + // widget.onSubmit(controller.text.trim()); + // Navigator.of(context).pop(); + }, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 25.0, + vertical: 15, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8.0), + color: const Color(0xFF425B5B), + ), + child: const Text( + 'Save', + style: TextStyle( + color: Colors.white, + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + + // if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), + // _buildResponsiveRow( + // context, + // buildAdditonalDocuments(context), + // buildRemarks(context), + // ), + ], + ), + ); + } + + // ------------------------- Claims Part ----------------------------------- + + Widget buildIdv(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('IDV *', style: _textStyle), + SizedBox(height: 10), + ThemedFormField( + controller: controllers['idv']!, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')), + ], + validator: (value) => Validators.doubleNumber(value, "IDV"), + // validator: (value) => Validators.number(value, "IDV"), + backgroundColor: Color(0xFFEDF6F5), + // readOnly: true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.15, + ), + ], + ); + } + + Widget buildInsurer2(BuildContext context) { + Map? selectedInsurerd = filteredInsurersData.firstWhere( + (item) => item['id'].toString() == selectedInsurer, + orElse: () => {}, + ); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Insurer *', style: _textStyle), + SizedBox(height: 10), + Container( + decoration: BoxDecoration( + color: Colors.white, + // borderRadius: BorderRadius.circular(10.0), + ), + width: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + // height: 40, + child: DropdownSearch>( + key: dropDownKeyInsurer, + selectedItem: selectedInsurerd.isNotEmpty ? selectedInsurerd : null, + items: (filter, infiniteScrollProps) { + return filteredInsurersData; + }, + + itemAsString: (val) => val['name'].toString(), // what to show + compareFn: (item, selectedItem) => + item['id'] == selectedItem['id'], // ✅ compare by id + validator: (val) { + if (val == null) { + return "Required"; // ✅ error message + } + return null; + }, + decoratorProps: DropDownDecoratorProps( + decoration: + AppInputDecorations.dropdownDecoration( + label: "Select Insurer", + ).copyWith( + filled: true, + fillColor: Color( + 0xFFEDF6F5, + ), // 👈 makes the dropdown input white + ), + ), + + popupProps: PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250), + menuProps: MenuProps( + backgroundColor: + Colors.white, // 👈 sets dropdown background to white + ), + showSearchBox: true, + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + filled: true, + fillColor: Colors.white, + hintText: "Search Insurer...", + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.white, + ), // 👈 Normal border + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.white, + width: 1.5, + ), // 👈 Focused border + ), + ), + ), + // constraints: BoxConstraints(), + ), + + onChanged: (val) { + if (val != null) { + print("Selected Insurer : ${val['name']}"); + print("Id: ${val['id']}"); + selectedInsurer = val['id']; + // controllers['agentId']?.text = val['agent_code']; + // agentId = agent['id']; + } + }, + ), + ), + ], + ); + } + + Widget buildPremiumAmnt(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Premium Amount *', style: _textStyle), + SizedBox(height: 10), + ThemedFormField( + controller: controllers['premium_Amount']!, + backgroundColor: Color(0xFFEDF6F5), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')), + ], + validator: (value) => Validators.doubleNumber(value, "PremiumAmount"), + // validator: (value) => Validators.number(value, "PremiumAmount "), + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.15, + ), + ], + ); + } + + Widget buildInsurancePlanType(context) { + Map? selectedVehicle = filteredInsuranceData.firstWhere( + (item) => item['id'].toString() == selectedInsPlanType, + orElse: () => {}, + ); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Plan Type *", style: _textStyle), + SizedBox(height: 10), + Container( + color: Colors.white, + width: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.15, + // height: 40, + child: DropdownSearch>( + key: dropDownKey, + selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null, + items: (filter, infiniteScrollProps) { + return filteredInsuranceData; + }, + + itemAsString: (val) => val['insurance_plan_type'].toString(), + compareFn: (item, selectedItem) => + item['id'] == selectedItem['id'], // ✅ compare by id + validator: (val) { + if (val == null) { + return "Required"; // ✅ error message + } + return null; + }, + decoratorProps: DropDownDecoratorProps( + decoration: + AppInputDecorations.dropdownDecoration( + label: "Select Plan Type", + ).copyWith( + filled: true, + fillColor: Color( + 0xFFEDF6F5, + ), // 👈 makes the dropdown input white + ), + ), + + popupProps: PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250), + menuProps: MenuProps( + backgroundColor: + Colors.white, // 👈 sets dropdown background to white + ), + showSearchBox: true, + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + filled: true, + fillColor: Colors.white, + hintText: "Search Plan Type...", + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.white, + ), // 👈 Normal border + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.white, + width: 1.5, + ), // 👈 Focused border + ), + ), + ), + // constraints: BoxConstraints(), + ), + + onChanged: (val) { + if (val != null) { + print("Selected ClaimsType : ${val['insurance_plan_type']}"); + print("Id: ${val['id']}"); + selectedInsPlanType = val['id']; + // controllers['agentId']?.text = val['agent_code']; + // agentId = agent['id']; + } + }, + ), + ), + ], + ); + } + + Widget buildDocuments(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Proposal Documents ', style: _textStyle), + const SizedBox(height: 10), + Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + ThemedUploadField( + hintText: selectedFileNames ?? "Upload Document", + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + backgroundColor: Color(0xFFEDF6F5), + onFileSelected: (fileName, file) { + print("Picked file: $fileName (${file.size} bytes)"); + setState(() { + docUploadedFile = file; + }); + }, + ), + const SizedBox(height: 5), + + if (docUploadedFileUrlFromApi != null) + Container( + // color: Colors.white, + child: Row( + children: [ + GestureDetector( + onTap: () => apiService.downloadFile( + apiUrl: + 'api/quotation/downloadAdditionalUploadedFile?id=$selectedId', + apiId: selectedId, + localFile: docUploadedFile, + fileName: selectedFileNames, + ), + child: Container( + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: Color(0xFF425B5B), + // color: Colors.green.shade300, + ), + child: Row( + children: const [ + Text( + "Download", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w200, + color: Colors.white, + ), + ), + SizedBox(width: 5), + Icon(Icons.download, size: 13, color: Colors.white), + ], + ), + ), + ), + ], + ), + ), + ], + ), + ], + ); + } + + // ------------------- STyle --------------------------------- + + static final TextStyle _textStyle = TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + ); +} diff --git a/lib/presentation/screens/staff/Enquiry/tabs/policyTab.dart b/lib/presentation/screens/staff/Enquiry/tabs/policyTab.dart index 7f5dcfd..0b2483c 100644 --- a/lib/presentation/screens/staff/Enquiry/tabs/policyTab.dart +++ b/lib/presentation/screens/staff/Enquiry/tabs/policyTab.dart @@ -160,7 +160,6 @@ class PolicyStaffTabState extends ConsumerState { "sgst": controllers["sgst"]?.text, "igst": controllers["igst"]?.text, "premium_amount": controllers["premiumTOT"]?.text, - "manager_id": managerId, // "policy_pdf_file_name": "policy_doc.pdf", // "policy_payment_receipt_file_name": "receipt_doc.pdf", @@ -378,10 +377,11 @@ class PolicyStaffTabState extends ConsumerState { ); quotationAcceptedData = acceptedItem; - print('AcceptedData - $quotationAcceptedData'); + print('AcceptedData YYY - $quotationAcceptedData'); if (quotationAcceptedData != null) { if (!mounted) return; + print('AcceptedData YYY2'); setState(() { controllers["insurer"]?.text = quotationAcceptedData?['insurer_name']; acceptedQuotationId = quotationAcceptedData?['id']?.toString() ?? ''; @@ -392,6 +392,10 @@ class PolicyStaffTabState extends ConsumerState { quotationAcceptedData?['premium_amount']?.toString() ?? ''; controllers["planType"]?.text = quotationAcceptedData?['insurance_plan_type']?.toString() ?? ''; + controllers["policyPaymentMode"]?.text = + quotationAcceptedData?['payment_mode_value']?.toString() ?? ''; + selectedBroker = quotationAcceptedData?['broker_id'] ?? ''; + selectedBrokerName = quotationAcceptedData?['broker_name'] ?? ''; }); } } catch (e) { @@ -435,6 +439,7 @@ class PolicyStaffTabState extends ConsumerState { policyData['premium_amount']?.toString() ?? ''; selectedBroker = policyData['broker_id'] ?? ''; + selectedBrokerName = policyData['broker_name'] ?? ''; // RC FILE String? rcPath = policyData["policy_pdf_file_name"]; if (rcPath != null && rcPath.isNotEmpty) { @@ -485,6 +490,7 @@ class PolicyStaffTabState extends ConsumerState { policyData['policy_number']?.toString() ?? ''; controllers["policyPaymentMode"]?.text = policyData['payment_mode']?.toString() ?? ''; + controllers["issueDate"]?.text = _formatDate(policyData['issued_date']!.toString()) ?? ''; controllers["startDate"]?.text = @@ -531,15 +537,16 @@ class PolicyStaffTabState extends ConsumerState { final bool isUpdating = choosedPolcyId != null; - if (!isUpdating && selectedBrokerName == 'Nhance') { - // if (!isUpdating && enqBrokerName == 'Nhance') { - ToastHelper.showErrorToast(context, "Policy PDF is required"); - return; - } + // if (!isUpdating && selectedBrokerName == 'Nhance') { + // // if (!isUpdating && enqBrokerName == 'Nhance') { + // ToastHelper.showErrorToast(context, "Policy PDF is required"); + // return; + // } // (enqBrokerName != 'Nhance') // File validations - if ((selectedBrokerName != 'Nhance') && - (docPDFUploadedFile == null || docPDFUploadedFile?.bytes == null) && + if ( + // (selectedBrokerName != 'Nhance') && + (docPDFUploadedFile == null || docPDFUploadedFile?.bytes == null) && (docUploadedPDFFileUrlFromApi == null || docUploadedPDFFileUrlFromApi!.isEmpty)) { ToastHelper.showErrorToast(context, "Policy PDF is required"); @@ -849,8 +856,11 @@ class PolicyStaffTabState extends ConsumerState { // color: Colors.green, decoration: BoxDecoration( // color: Colors.orange.shade50, - color: Color(0xffEDF6F5), - borderRadius: BorderRadius.circular(10.0), + // color: Color(0xffEDF6F5), + border: Border( + top: BorderSide(color: Colors.blueGrey.shade200, width: 0.2), + ), + // borderRadius: BorderRadius.circular(10.0), ), width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height * 0.58, @@ -1064,13 +1074,14 @@ class PolicyStaffTabState extends ConsumerState { // mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ + Paymentmode(context), + SizedBox(width: 20), buildBroker(context), if (selectedBrokerName != null) ...[ SizedBox(width: 20), buildUploadPolicyPdf(context), - SizedBox(width: 20), - Paymentmode(context), + // SizedBox(width: 20), ], ], ), @@ -1386,6 +1397,8 @@ class PolicyStaffTabState extends ConsumerState { SizedBox(height: 10), ThemedFormField( controller: controllers['policyNumber']!, + borderColor: Color(0xFFE2E8F0), + highlightColor: Color(0xFF50A398), validator: (value) => Validators.requiredField(value, "policyNumber"), inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z 0-9]')), @@ -1406,7 +1419,14 @@ class PolicyStaffTabState extends ConsumerState { return Row( children: [ Text('Broker *', style: _textStyle), - SizedBox(width: 15), + SizedBox(width: 10), + // SizedBox( + // width: MediaQuery.of(context).size.width * 0.095, + // child: Text( + // '$selectedBrokerName', + // style: GoogleFonts.inter(fontSize: 12), + // ), + // ), SizedBox( height: 30, width: MediaQuery.of(context).size.width * 0.1, @@ -1456,20 +1476,21 @@ class PolicyStaffTabState extends ConsumerState { label: "Select Broker", ).copyWith( filled: true, - fillColor: - Colors.white, // 👈 makes the dropdown input white + fillColor: Color(0xffEDF6F5), + // fillColor: + // Colors.white, // 👈 makes the dropdown input white isDense: true, border: OutlineInputBorder( borderRadius: BorderRadius.circular(5), borderSide: const BorderSide( - color: Colors.black, + color: Color(0xffEDF6F5), width: 0.1, ), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(5), borderSide: const BorderSide( - color: Colors.black, + color: Color(0xffEDF6F5), width: 0.1, ), ), @@ -1548,23 +1569,34 @@ class PolicyStaffTabState extends ConsumerState { Widget Paymentmode(BuildContext context) { return Row( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Payment Mode *', style: _textStyle), - SizedBox(width: 25), - ThemedFormField( - controller: controllers['policyPaymentMode']!, - backgroundColor: Color(0xffEDF6F5), - errorBorderColor: Color(0xffEDF6F5), - hintText: 'Online / Cash', - // borderColor: Color(0xffEDF6F5), - validator: (value) => - Validators.requiredField(value, "policyPaymentMode"), - txtwidth: ResponsiveLayout.isMobile(context) - ? null - : MediaQuery.of(context).size.width * 0.07, + SizedBox(width: 15), + SizedBox( + width: MediaQuery.of(context).size.width * 0.075, + child: Text( + controllers['policyPaymentMode']?.text ?? 'Online', + style: GoogleFonts.inter(fontSize: 12), + ), ), + // ThemedFormField( + // controller: controllers['policyPaymentMode']!, + // // borderColor: Color(0xFFE2E8F0), + // borderColor: Colors.white, + // highlightColor: Colors.white, + // // highlightColor: Color(0xFF50A398), + // errorBorderColor: Color(0xffEDF6F5), + // hintText: 'Online / Cash', + // // borderColor: Color(0xffEDF6F5), + // readOnly: true, + // validator: (value) => + // Validators.requiredField(value, "policyPaymentMode"), + // txtwidth: ResponsiveLayout.isMobile(context) + // ? null + // : MediaQuery.of(context).size.width * 0.07, + // ), ], ); } @@ -1733,7 +1765,7 @@ class PolicyStaffTabState extends ConsumerState { // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox( - width: MediaQuery.of(context).size.width * 0.12, + width: MediaQuery.of(context).size.width * 0.15, child: Text('Upload Policy PDF * ', style: _textStyle), ), // const SizedBox(height: 10), @@ -1745,13 +1777,17 @@ class PolicyStaffTabState extends ConsumerState { ThemedUploadField( hintText: selectedPDFFileNames ?? "Upload Document", allowedExtensions: ['pdf'], + // backgroundColor: Colors.white, backgroundColor: Color(0xffEDF6F5), + txtheight: 35, txtwidth: ResponsiveLayout.isMobile(context) ? null : (docUploadedPDFFileUrlFromApi != null) - ? MediaQuery.of(context).size.width * 0.135 + ? MediaQuery.of(context).size.width * 0.117 + // ? MediaQuery.of(context).size.width * 0.135 // ? MediaQuery.of(context).size.width * 0.12 - : MediaQuery.of(context).size.width * 0.15, + : MediaQuery.of(context).size.width * 0.14, + // : MediaQuery.of(context).size.width * 0.15, // backgroundColor: Color(0xFFEDF6F5), onFileSelected: (fileName, file) async { print("Picked file: $fileName (${file.size} bytes)"); @@ -1775,9 +1811,9 @@ class PolicyStaffTabState extends ConsumerState { docPDFUploadedFile = file; }); - if (selectedBrokerName == 'Nhance') { - handleUploadPolicy(); - } + // if (selectedBrokerName == 'Nhance') { + // handleUploadPolicy(); + // } }, ), @@ -1962,7 +1998,7 @@ class PolicyStaffTabState extends ConsumerState { SizedBox(width: 20), ThemedFormField( controller: controllers['tp']!, - backgroundColor: Color(0xffEDF6F5), + // backgroundColor: Color(0xffEDF6F5), errorBorderColor: Color(0xffEDF6F5), hintText: '0', validator: (value) => Validators.requiredField(value, "Third Party"), @@ -1994,7 +2030,7 @@ class PolicyStaffTabState extends ConsumerState { SizedBox(width: 20), ThemedFormField( controller: controllers['od']!, - backgroundColor: Color(0xffEDF6F5), + // backgroundColor: Color(0xffEDF6F5), errorBorderColor: Color(0xffEDF6F5), hintText: '0', validator: (value) => Validators.requiredField(value, "OwnDamage"), @@ -2022,7 +2058,7 @@ class PolicyStaffTabState extends ConsumerState { SizedBox(width: 20), ThemedFormField( controller: controllers['pa']!, - backgroundColor: Color(0xffEDF6F5), + // backgroundColor: Color(0xffEDF6F5), errorBorderColor: Color(0xffEDF6F5), hintText: '0', onChanged: (value) => calculateAmount(), @@ -2051,7 +2087,7 @@ class PolicyStaffTabState extends ConsumerState { SizedBox(width: 20), ThemedFormField( controller: controllers['cgst']!, - backgroundColor: Color(0xffEDF6F5), + // backgroundColor: Color(0xffEDF6F5), errorBorderColor: Color(0xffEDF6F5), hintText: '0', validator: (value) => Validators.requiredField(value, "CGST"), @@ -2078,7 +2114,7 @@ class PolicyStaffTabState extends ConsumerState { SizedBox(width: 20), ThemedFormField( controller: controllers['sgst']!, - backgroundColor: Color(0xffEDF6F5), + // backgroundColor: Color(0xffEDF6F5), errorBorderColor: Color(0xffEDF6F5), hintText: '0', inputFormatters: [ @@ -2105,7 +2141,7 @@ class PolicyStaffTabState extends ConsumerState { SizedBox(width: 20), ThemedFormField( controller: controllers['igst']!, - backgroundColor: Color(0xffEDF6F5), + // backgroundColor: Color(0xffEDF6F5), errorBorderColor: Color(0xffEDF6F5), hintText: '0', validator: (value) => Validators.requiredField(value, "IGST"), @@ -2132,7 +2168,7 @@ class PolicyStaffTabState extends ConsumerState { SizedBox(width: 20), ThemedFormField( controller: controllers['premiumTOT']!, - backgroundColor: Color(0xffEDF6F5), + // backgroundColor: Color(0xffEDF6F5), errorBorderColor: Color(0xffEDF6F5), hintText: '0', validator: (value) => Validators.requiredField(value, "premium"), @@ -2381,9 +2417,10 @@ class PolicyStaffTabState extends ConsumerState { } } - static const _textStyle = TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, + static final _textStyle = GoogleFonts.inter( + fontSize: 11, + color: Color(0XFF334155), + fontWeight: FontWeight.w500, ); static const _textStrongStyle = TextStyle( fontSize: 12, diff --git a/lib/presentation/screens/staff/Enquiry/tabs/quotationTab.dart b/lib/presentation/screens/staff/Enquiry/tabs/quotationTab.dart index 3faaa32..79a4592 100644 --- a/lib/presentation/screens/staff/Enquiry/tabs/quotationTab.dart +++ b/lib/presentation/screens/staff/Enquiry/tabs/quotationTab.dart @@ -215,11 +215,32 @@ class QuotationStaffTabState extends ConsumerState { originalData = getQuotationData; filteredData = List.from(originalData); - blockKey = getQuotationData.any( - (item) => item['status'] == 'Accepted', - ); + // dynamic data = getQuotationData + // .where((item) => item['status'] == 'Accepted') + // .toList(); + // blockKey = getQuotationData.any( + // (item) => item['status'] == 'Accepted', + // ); + + final acceptedList = getQuotationData + .where((item) => item['status'] == 'Accepted') + .toList(); + print('blockKey- $blockKey'); - // print('originalData - $getClaimPolicies'); + print('originalDataData - $acceptedList'); + + final data = acceptedList.isNotEmpty ? acceptedList.first : null; + + final id = selectedQuotationFrmListData?['id']; + + handleEdit(id, data); + + // selectedQuotationFrmListData = data; + + print('originalDatasdata- $data'); + print( + 'originalDataselectedQuotationFrmListData - $selectedQuotationFrmListData', + ); }); } else { getQuotationData = []; @@ -265,51 +286,35 @@ class QuotationStaffTabState extends ConsumerState { return Container( height: MediaQuery.of(context).size.height, width: MediaQuery.of(context).size.width, + padding: EdgeInsets.symmetric(vertical: 10), + decoration: BoxDecoration( + border: Border( + top: BorderSide(color: Colors.blueGrey.shade200, width: 0.2), + ), + ), // child: SingleChildScrollView( // scrollDirection: Axis.vertical, child: Column( children: [ - if (!blockKey) ...[ - // if (!blockKey && roleId != 'manager') ...[ - CreateQuotationForm( - key: ValueKey(selectedQuotationFrmListId ?? "new"), - userId: userId, - selectedQuotationFrmListdata: selectedQuotationFrmListData, - selectedQuotationFrmListId: selectedQuotationFrmListId, - managerId: managerId, - selectedInsurdId: selectedInsurdId, - selectedEnquiryId: selectedEnquiryId, - onSubmit: (value) { - debugPrint("New Endorsement: $value"); - if (value == 'Success') { - refresh(); - } - }, - ), - SizedBox(height: 20), - ], - - Container( - // color: Colors.green, - decoration: BoxDecoration( - color: Color(0xFFEDF6F5), - borderRadius: BorderRadius.circular(10.0), - ), - width: MediaQuery.of(context).size.width, - height: !blockKey - ? MediaQuery.of(context).size.height * 0.4 - : MediaQuery.of(context).size.height * 0.55, - padding: EdgeInsets.all(12.0), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Column( - children: [ - // Text('datta') - _buildDataTable(context), - ], - ), - ), + // if (!blockKey) ...[ + // if (!blockKey && roleId != 'manager') ...[ + CreateProposalForm( + key: ValueKey(selectedQuotationFrmListId ?? "new"), + userId: userId, + selectedQuotationFrmListdata: selectedQuotationFrmListData, + selectedQuotationFrmListId: selectedQuotationFrmListId, + managerId: managerId, + selectedInsurdId: selectedInsurdId, + selectedEnquiryId: selectedEnquiryId, + onSubmit: (value) { + debugPrint("New Endorsement: $value"); + if (value == 'Success') { + refresh(); + } + }, ), + SizedBox(height: 20), + // ], ], ), // ), @@ -388,299 +393,6 @@ class QuotationStaffTabState extends ConsumerState { ); } - Widget _buildDataTable(BuildContext context) { - if (filteredData.isEmpty) { - return const SizedBox( - height: 50, - child: Center(child: Text('No available data')), - ); - } - - final sortedData = [...filteredData] - ..sort((a, b) => int.parse(b['id']) - int.parse(a['id'])); - - return SingleChildScrollView( - child: Column( - children: [ - ListView.builder( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - itemCount: ResponsiveLayout.isMobile(context) - ? sortedData - .length // only cards for mobile - : sortedData.length + 1, // +1 for header in desktop - itemBuilder: (context, index) { - if (!ResponsiveLayout.isMobile(context) && index == 0) { - return _buildHeader(); - } - final startIndex = (currentPage - 1) * itemsPerPage; - final item = - sortedData[index - - (ResponsiveLayout.isMobile(context) ? 0 : 1)]; - final sno = startIndex + index; - - // return ResponsiveLayout.isMobile(context) - // ? _buildDataCard(item, sno) - return _buildDataRow(item, sno); - }, - ), - ], - ), - ); - } - - Widget _buildHeader() { - return Container( - decoration: BoxDecoration( - color: Color(0xFFEDF6F5), - borderRadius: BorderRadius.circular(6), - ), - padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 3), - child: Row( - children: [ - // Expanded(flex: 3, child: Text(' ', style: _headerStyle)), - Expanded(flex: 2, child: Text('Vehicle Number', style: _headerStyle)), - Expanded(flex: 3, child: Text('Insurer', style: _headerStyle)), - Expanded(flex: 2, child: Text('IDV', style: _headerStyle)), - Expanded(flex: 2, child: Text('Plan Type', style: _headerStyle)), - Expanded(flex: 2, child: Text('Premium Amount', style: _headerStyle)), - Expanded(flex: 2, child: Text('Status', style: _headerStyle)), - Expanded(flex: 1, child: Text('', style: _headerStyle)), - ], - ), - ); - } - - Widget _buildDataRow(Map item, sno) { - return Container( - padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16), - margin: const EdgeInsets.only(top: 10), - decoration: BoxDecoration( - color: Colors.white, - // color: Color(0xFFE0F7F9), - border: const Border( - bottom: BorderSide(color: Color(0xFFEAEAEA), width: 1), - ), - borderRadius: BorderRadius.circular(8), - ), - child: Row( - children: [ - Expanded( - flex: 2, - child: Text(item['reg_no'] ?? '-', style: _dataBold), - ), - Expanded( - flex: 3, - child: Text(item['insurer_name'] ?? '-', style: _dataBold), - ), - Expanded( - flex: 2, - child: Text( - item['insured_declared_value'] ?? '-', - style: _dataBold, - ), - ), - Expanded( - flex: 2, - child: Text(item['insurance_plan_type'] ?? '-', style: _dataBold), - ), - Expanded( - flex: 2, - child: Text(item['premium_amount'] ?? '-', style: _dataBold), - ), - - Expanded( - flex: 2, - child: Text( - item['status'] ?? '-', - style: GoogleFonts.inter( - fontSize: 14, - fontWeight: FontWeight.w400, - color: _getStatusColor(item['status']), - ), - ), - ), - - Expanded( - flex: 1, - child: item['status'] == 'Pending' - ? Tooltip( - message: 'Edit', - child: IconButton( - icon: Image.asset( - "assets/miscellaneous/Edit.png", - height: 15, - width: 15, - ), - onPressed: () { - final id = item['id']; - print('RAV - $id'); - handleEdit(id, item); - }, - splashRadius: 20, - hoverColor: Colors.black12, - padding: const EdgeInsets.all(8), - constraints: const BoxConstraints(), - ), - ) - : Image.asset( - "assets/miscellaneous/Edit_muted.png", - height: 15, - width: 15, - ), - // child: GestureDetector( - // onTap: () { - // final id = item['id']; - // print('RAV - $id'); - // handleEdit(id, item); - // }, - // child: item['status'] == 'Pending' - // ? Image.asset( - // "assets/miscellaneous/Edit.png", - // height: 15, - // width: 15, - // ) - // : Image.asset( - // "assets/miscellaneous/Edit_muted.png", - // height: 15, - // width: 15, - // ), - // ), - ), - ], - ), - ); - } - - Widget _buildDataCard(Map item, int sno) { - return Container( - // margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 8), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFFFFFFF), - // color: const Color(0xFFF6FEFD), - borderRadius: BorderRadius.circular(8.0), - border: Border.all(color: const Color(0xffD9EBE8)), - ), - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - // "TN64V3456", - item['reg_no'] ?? '-', - style: _cardheaderStyle, - ), - item['status'] == 'Pending' - // ? GestureDetector( - // onTap: () { - // final id = item['id']; - // print('RAV - $id'); - // handleEdit(id, item); - // }, - // child: Image.asset( - // "assets/miscellaneous/Edit.png", - // height: 15, - // width: 15, - // ), - // ) - ? Tooltip( - message: 'Edit', - child: IconButton( - icon: Image.asset( - "assets/miscellaneous/Edit.png", - height: 15, - width: 15, - ), - onPressed: () { - final id = item['id']; - print('RAV - $id'); - // handleEdit(id, item); - }, - splashRadius: 28, - hoverColor: Colors.black12, - padding: const EdgeInsets.all(8), - constraints: const BoxConstraints(), - ), - ) - : Image.asset( - "assets/miscellaneous/Edit_muted.png", - height: 15, - width: 15, - ), - ], - ), - Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - // flex: 2, - child: Text( - item['insurer_name'] ?? '-', - style: _cardRow1BodyStyle, - ), - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - item['insurance_plan_type'] ?? '-', - style: _cardRow1BodyStyle, - ), - - Text( - 'IDV: ${item['insured_declared_value']}' ?? '-', - style: _cardRow2BodyStyle, - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - RichText( - text: TextSpan( - children: [ - TextSpan( - text: 'Status : ', // key - style: GoogleFonts.inter( - color: Colors.black, - fontWeight: FontWeight.w600, - fontSize: 11, - ), // key color - ), - TextSpan( - text: '${item['status'] ?? '-'}', // value - style: GoogleFonts.inter( - color: _getStatusColor(item['status']), - fontWeight: FontWeight.w600, - fontSize: 11, - ), // value color - ), - ], - ), - ), - - Text( - '${item['premium_amount']}' ?? '-', - style: _cardheaderStyle, - ), - ], - ), - ], - ), - ), - ], - ), - ); - } - static final _dataBold = GoogleFonts.inter( fontSize: 12, diff --git a/lib/presentation/screens/staff/Enquiry/tabs/quotationTab_old.dart b/lib/presentation/screens/staff/Enquiry/tabs/quotationTab_old.dart new file mode 100644 index 0000000..050d736 --- /dev/null +++ b/lib/presentation/screens/staff/Enquiry/tabs/quotationTab_old.dart @@ -0,0 +1,733 @@ +import 'dart:io' as html; + +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:nhance_partner/presentation/providers/userRoleProvider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../../../../core/routing/routes.dart'; +import '../../../../../core/services/api_service.dart'; +import '../../../../../data/services/auth_service.dart'; +import '../../../../../data/utils/validators.dart'; +import '../../../../layouts/main_layout.dart'; +import '../../../../layouts/responsive_layout.dart'; +import '../../../../providers/manager_provider.dart'; +import '../../../../providers/quotation_staff_proivder.dart'; +import '../../../../themes/indicators/text_field_theme.dart'; +import '../../quotations/createQuotationPopUp.dart'; +import 'createQuotation.dart'; +import 'createQuotationOld.dart'; + +class PropoalStaffTab extends ConsumerStatefulWidget { + String? id; + List>? data; + final Future Function()? onRefresh; + + PropoalStaffTab({super.key, this.data, this.id, this.onRefresh}); + @override + ConsumerState createState() => PropoalStaffTabState(); +} + +class PropoalStaffTabState extends ConsumerState { + int currentPage = 0; + int itemsPerPage = 10; + + bool blockKey = false; + + List> dataVal = []; + + final TextEditingController _searchController = TextEditingController(); + + late ApiService apiService; + final _formKey = GlobalKey(); + final GlobalKey>> dropDownKey = + GlobalKey>>(); + + List tabHeader = [ + 'regNum', + 'insurer', + 'mobile', + 'code', + 'address', + 'regNo', + ]; + late String isActive = "1"; + PlatformFile? docUploadedFile; + + // PlatformFile? passportFile; + String? selectedFileNames; + String? selectedInsurdId; + String? passportFileUrlFromApi; + String? selectedId; + bool isLoading = false; + bool isquotation = false; + + Map controllers = {}; + String? _token; + dynamic userId; + dynamic roleId; + dynamic selectedEnquiryId; + dynamic managerId; + dynamic enqQuotation; + dynamic selectedQuotationFrmListId; + + Map? selectedQuotationFrmListData; + + List> getVehicleTypeData = []; + List> filteredVechicleData = []; + + List> getInsurersData = []; + List> filteredInsurersData = []; + + Map dataDetails() { + final data = { + "regNum": controllers["regNum"]?.text, + // "insurer": controllers["insurer"]?.text, + "insurer": controllers["insurer"]?.text, + "mobile": controllers["mobile"]?.text, + "address": controllers["address"]?.text, + "agent_code": controllers["code"]?.text, + "is_active": isActive, + "manager_id": managerId, + }; + return data; + } + + List> getQuotationData = []; + late Map enquiryData; + List> originalData = []; + List> filteredData = []; + // bool isLoading = false; + + Future _restoreManagerId(WidgetRef ref) async { + final prefs = await SharedPreferences.getInstance(); + + final String? savedId = prefs.getString( + 'enqStaffDataId', + ); // already a string + if (savedId != null) { + ref.read(quotationStaffIdProvider.notifier).state = savedId; + print("savedenqStaffDataId ID restored: $savedId"); + + _loadData(savedId); + } + } + + @override + void initState() { + super.initState(); + apiService = ApiService(); + + if (kIsWeb) { + Future.microtask(() => _restoreManagerId(ref)); + } + + for (String field in tabHeader) { + controllers[field] = TextEditingController(); + } + + _initializeToken(); + + Future.microtask(() { + managerId = ref.read(managerIdProvider); // ✅ use read + userId = ref.read(userIdProvider); // ✅ use read + roleId = ref.read(userRoleProvider); // ✅ use read + + print('QmanagerId - $managerId'); + print('QuserId - $userId'); + print('QroleId - $roleId'); + enqQuotation = ref.read(quotationStaffIdProvider); // ✅ use read + print('QenqQuotation - $enqQuotation'); + if (enqQuotation != null) { + _loadData(enqQuotation); + } + }); + } + + @override + void dispose() { + // Dispose all TextEditingControllers + for (var controller in controllers.values) { + controller.dispose(); + } + super.dispose(); + } + + Future _initializeToken() async { + _token = await AuthService.getToken(); + print("APISERTOKEN - $_token"); + } + + void updateEnquiryData(enquiryData) { + print('updateEnquiryData - $enquiryData'); + if (!mounted) return; + setState(() { + selectedInsurdId = enquiryData['insurer_id']; + selectedEnquiryId = enquiryData['id']; + print('selectedEnquiryId- $selectedEnquiryId'); + controllers["regNum"]?.text = enquiryData['reg_no']; + // controllers["insurer"]?.text = enquiryData['insurer_name']; + }); + } + + Future _loadData(enqQuotation) async { + getQuotationList(enqQuotation); + } + + void refresh() { + print("refresh--"); + setState(() { + selectedQuotationFrmListId = null; + selectedQuotationFrmListData = null; + }); + + if (enqQuotation != null) { + _loadData(enqQuotation); + } + } + + Future getQuotationList(enqQuotation) async { + print('getClaimList called enqQuotation- $enqQuotation'); + if (!mounted) return; + setState(() { + isLoading = true; + }); + + try { + final response = await apiService.findEnqQuotePolicyView(enqQuotation); + if (!mounted) return; + if (response['status'] == 'success') { + print('quoationListData - ${response['data']}'); + setState(() { + enquiryData = Map.from(response['data']['enquiry']); + print('enquiryData - ${enquiryData}'); + + updateEnquiryData(enquiryData); + // getQuotationData = List>.from(response['data']); + getQuotationData = List>.from( + response['data']['quotations'], + ); + originalData = getQuotationData; + filteredData = List.from(originalData); + + blockKey = getQuotationData.any( + (item) => item['status'] == 'Accepted', + ); + print('blockKey- $blockKey'); + // print('originalData - $getClaimPolicies'); + }); + } else { + getQuotationData = []; + originalData = []; + } + } catch (e) { + print('Exception occurred: $e'); + } finally { + if (!mounted) return; + setState(() { + isLoading = false; + }); + } + } + + Color _getStatusColor(String? status) { + switch (status) { + case 'Pending': + return Colors.yellow; + case 'Accepted': + return Colors.green; + case 'Rejected': + return Colors.red; + default: + return Colors.grey; + } + } + + void handleEdit(id, data) { + print("sfd - $id"); + print("sfdewe - $data"); + setState(() { + selectedQuotationFrmListId = id; + selectedQuotationFrmListData = data; + // data = data; + }); + } + + @override + Widget build(BuildContext context) { + final isMobile = ResponsiveLayout.isMobile(context); + + return Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + // child: SingleChildScrollView( + // scrollDirection: Axis.vertical, + child: Column( + children: [ + if (!blockKey) ...[ + // if (!blockKey && roleId != 'manager') ...[ + CreateQuotationForm( + key: ValueKey(selectedQuotationFrmListId ?? "new"), + userId: userId, + selectedQuotationFrmListdata: selectedQuotationFrmListData, + selectedQuotationFrmListId: selectedQuotationFrmListId, + managerId: managerId, + selectedInsurdId: selectedInsurdId, + selectedEnquiryId: selectedEnquiryId, + onSubmit: (value) { + debugPrint("New Endorsement: $value"); + if (value == 'Success') { + refresh(); + } + }, + ), + SizedBox(height: 20), + ], + + Container( + // color: Colors.green, + decoration: BoxDecoration( + color: Color(0xFFEDF6F5), + borderRadius: BorderRadius.circular(10.0), + ), + width: MediaQuery.of(context).size.width, + height: !blockKey + ? MediaQuery.of(context).size.height * 0.4 + : MediaQuery.of(context).size.height * 0.55, + padding: EdgeInsets.all(12.0), + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + children: [ + // Text('datta') + _buildDataTable(context), + ], + ), + ), + ), + ], + ), + // ), + ); + } + + Widget registerNumber(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Vehicle Number', style: _textStyle), + SizedBox(height: 10), + ThemedFormField( + controller: controllers['regNum']!, + readOnly: true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.2, + ), + ], + ); + } + + Widget insurer(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Insurer', style: _textStyle), + SizedBox(height: 10), + ThemedFormField( + controller: controllers['insurer']!, + readOnly: true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.2, + ), + ], + ); + } + + Widget buildResponsiveField({required String label, required Widget field}) { + final isMobile = ResponsiveLayout.isMobile(context); + + if (isMobile) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, style: _textStyle), + const SizedBox(height: 8), + field, + const SizedBox(height: 16), + ], + ); + } else { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded(child: Text(label, style: _textStyle)), + const SizedBox(width: 10), + field, + ], + ); + } + } + + Widget buildId(BuildContext context) { + return buildResponsiveField( + label: "Vehicle Number *", + field: ThemedFormField( + controller: controllers['regNo']!, + validator: (value) => Validators.requiredField(value, "regNo"), + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ); + } + + Widget _buildDataTable(BuildContext context) { + if (filteredData.isEmpty) { + return const SizedBox( + height: 50, + child: Center(child: Text('No available data')), + ); + } + + final sortedData = [...filteredData] + ..sort((a, b) => int.parse(b['id']) - int.parse(a['id'])); + + return SingleChildScrollView( + child: Column( + children: [ + ListView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: ResponsiveLayout.isMobile(context) + ? sortedData + .length // only cards for mobile + : sortedData.length + 1, // +1 for header in desktop + itemBuilder: (context, index) { + if (!ResponsiveLayout.isMobile(context) && index == 0) { + return _buildHeader(); + } + final startIndex = (currentPage - 1) * itemsPerPage; + final item = + sortedData[index - + (ResponsiveLayout.isMobile(context) ? 0 : 1)]; + final sno = startIndex + index; + + // return ResponsiveLayout.isMobile(context) + // ? _buildDataCard(item, sno) + return _buildDataRow(item, sno); + }, + ), + ], + ), + ); + } + + Widget _buildHeader() { + return Container( + decoration: BoxDecoration( + color: Color(0xFFEDF6F5), + borderRadius: BorderRadius.circular(6), + ), + padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 3), + child: Row( + children: [ + // Expanded(flex: 3, child: Text(' ', style: _headerStyle)), + Expanded(flex: 2, child: Text('Vehicle Number', style: _headerStyle)), + Expanded(flex: 3, child: Text('Insurer', style: _headerStyle)), + Expanded(flex: 2, child: Text('IDV', style: _headerStyle)), + Expanded(flex: 2, child: Text('Plan Type', style: _headerStyle)), + Expanded(flex: 2, child: Text('Premium Amount', style: _headerStyle)), + Expanded(flex: 2, child: Text('Status', style: _headerStyle)), + Expanded(flex: 1, child: Text('', style: _headerStyle)), + ], + ), + ); + } + + Widget _buildDataRow(Map item, sno) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16), + margin: const EdgeInsets.only(top: 10), + decoration: BoxDecoration( + color: Colors.white, + // color: Color(0xFFE0F7F9), + border: const Border( + bottom: BorderSide(color: Color(0xFFEAEAEA), width: 1), + ), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + Expanded( + flex: 2, + child: Text(item['reg_no'] ?? '-', style: _dataBold), + ), + Expanded( + flex: 3, + child: Text(item['insurer_name'] ?? '-', style: _dataBold), + ), + Expanded( + flex: 2, + child: Text( + item['insured_declared_value'] ?? '-', + style: _dataBold, + ), + ), + Expanded( + flex: 2, + child: Text(item['insurance_plan_type'] ?? '-', style: _dataBold), + ), + Expanded( + flex: 2, + child: Text(item['premium_amount'] ?? '-', style: _dataBold), + ), + + Expanded( + flex: 2, + child: Text( + item['status'] ?? '-', + style: GoogleFonts.inter( + fontSize: 14, + fontWeight: FontWeight.w400, + color: _getStatusColor(item['status']), + ), + ), + ), + + Expanded( + flex: 1, + child: item['status'] == 'Pending' + ? Tooltip( + message: 'Edit', + child: IconButton( + icon: Image.asset( + "assets/miscellaneous/Edit.png", + height: 15, + width: 15, + ), + onPressed: () { + final id = item['id']; + print('RAV - $id'); + handleEdit(id, item); + }, + splashRadius: 20, + hoverColor: Colors.black12, + padding: const EdgeInsets.all(8), + constraints: const BoxConstraints(), + ), + ) + : Image.asset( + "assets/miscellaneous/Edit_muted.png", + height: 15, + width: 15, + ), + // child: GestureDetector( + // onTap: () { + // final id = item['id']; + // print('RAV - $id'); + // handleEdit(id, item); + // }, + // child: item['status'] == 'Pending' + // ? Image.asset( + // "assets/miscellaneous/Edit.png", + // height: 15, + // width: 15, + // ) + // : Image.asset( + // "assets/miscellaneous/Edit_muted.png", + // height: 15, + // width: 15, + // ), + // ), + ), + ], + ), + ); + } + + Widget _buildDataCard(Map item, int sno) { + return Container( + // margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 8), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: const Color(0xFFFFFFFF), + // color: const Color(0xFFF6FEFD), + borderRadius: BorderRadius.circular(8.0), + border: Border.all(color: const Color(0xffD9EBE8)), + ), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + // "TN64V3456", + item['reg_no'] ?? '-', + style: _cardheaderStyle, + ), + item['status'] == 'Pending' + // ? GestureDetector( + // onTap: () { + // final id = item['id']; + // print('RAV - $id'); + // handleEdit(id, item); + // }, + // child: Image.asset( + // "assets/miscellaneous/Edit.png", + // height: 15, + // width: 15, + // ), + // ) + ? Tooltip( + message: 'Edit', + child: IconButton( + icon: Image.asset( + "assets/miscellaneous/Edit.png", + height: 15, + width: 15, + ), + onPressed: () { + final id = item['id']; + print('RAV - $id'); + // handleEdit(id, item); + }, + splashRadius: 28, + hoverColor: Colors.black12, + padding: const EdgeInsets.all(8), + constraints: const BoxConstraints(), + ), + ) + : Image.asset( + "assets/miscellaneous/Edit_muted.png", + height: 15, + width: 15, + ), + ], + ), + Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + // flex: 2, + child: Text( + item['insurer_name'] ?? '-', + style: _cardRow1BodyStyle, + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + item['insurance_plan_type'] ?? '-', + style: _cardRow1BodyStyle, + ), + + Text( + 'IDV: ${item['insured_declared_value']}' ?? '-', + style: _cardRow2BodyStyle, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'Status : ', // key + style: GoogleFonts.inter( + color: Colors.black, + fontWeight: FontWeight.w600, + fontSize: 11, + ), // key color + ), + TextSpan( + text: '${item['status'] ?? '-'}', // value + style: GoogleFonts.inter( + color: _getStatusColor(item['status']), + fontWeight: FontWeight.w600, + fontSize: 11, + ), // value color + ), + ], + ), + ), + + Text( + '${item['premium_amount']}' ?? '-', + style: _cardheaderStyle, + ), + ], + ), + ], + ), + ), + ], + ), + ); + } + + static final _dataBold = GoogleFonts.inter( + fontSize: 12, + + fontWeight: FontWeight.w400, + color: Color(0xFF000000), + ); + + static final _dataSub = GoogleFonts.inter( + fontSize: 10, + fontWeight: FontWeight.w300, + color: Color(0xFF585757), + ); + + static final _headerStyle = GoogleFonts.inter( + color: Colors.black, + fontWeight: FontWeight.w600, + fontSize: 13, + ); + + static final _textStyle = GoogleFonts.inter( + fontSize: 14, + fontWeight: FontWeight.w600, + ); + + static final _cardheaderStyle = GoogleFonts.inter( + color: Colors.black, + fontWeight: FontWeight.w600, + fontSize: 12, + ); + + static final _cardBodyStyle = GoogleFonts.inter( + color: Color(0xFF545454), + fontWeight: FontWeight.w400, + fontSize: 12, + ); + + static final _cardRow1BodyStyle = GoogleFonts.inter( + // color: Color(0xFF545454), + color: Colors.black, + fontWeight: FontWeight.w500, + fontSize: 12, + ); + static final _cardRow2BodyStyle = GoogleFonts.inter( + color: const Color(0xFF545454), + // color: Colors.black, + fontWeight: FontWeight.w500, + fontSize: 12, + ); +} diff --git a/lib/presentation/screens/staff/Enquiry/tabs/tab.dart b/lib/presentation/screens/staff/Enquiry/tabs/tab.dart index 677cded..2fc696d 100644 --- a/lib/presentation/screens/staff/Enquiry/tabs/tab.dart +++ b/lib/presentation/screens/staff/Enquiry/tabs/tab.dart @@ -6,6 +6,7 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:nhance_partner/presentation/providers/userRoleProvider.dart'; import 'package:nhance_partner/presentation/screens/staff/Enquiry/tabs/policyTab.dart'; import 'package:nhance_partner/presentation/screens/staff/Enquiry/tabs/quotationTab.dart'; +import 'package:nhance_partner/presentation/screens/staff/Enquiry/tabs/quotationTab_old.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../../../core/routing/routes.dart'; @@ -62,8 +63,9 @@ class TabEnquiryStaffListState extends ConsumerState { } else { setState(() => isLoading = false); tabs = [ + // TabItem("Proposal", PropoalStaffTab()), TabItem("Proposal", QuotationStaffTab()), - // TabItem("Policy", PolicyStaffTab()), + TabItem("Policy", PolicyStaffTab()), ]; } }); @@ -103,19 +105,20 @@ class TabEnquiryStaffListState extends ConsumerState { selectedVehicleType = data['enquiry']?['vehicle_type']; selectedBrokerName = data['enquiry']?['broker_name']; selectedAgentName = data['enquiry']?['agent_name']; - selectedInsurer = data['enquiry']?['insurer_short_name']; + selectedInsurer = data['enquiry']?['short_name']; print( 'loadQuotationTab 4s -$selectedBrokerName $selectedInsuredName - $selectedVehicleNum - $selectedVehicleType', ); tabs = [ + // TabItem("Proposal", PropoalStaffTab()), TabItem("Proposal", QuotationStaffTab()), - // TabItem("Policy", PolicyStaffTab()), + TabItem("Policy", PolicyStaffTab()), ]; - if (widget.showKey == "Policy") { - tabs.add(TabItem("Policy", PolicyStaffTab())); - } + // if (widget.showKey == "Policy") { + // tabs.add(TabItem("Policy", PolicyStaffTab())); + // } // if (tabIndex != null) { // selectedIndex = tabIndex; @@ -246,12 +249,13 @@ class TabEnquiryStaffListState extends ConsumerState { ), ), - SizedBox(height: 10), + SizedBox(height: 20), Row( children: List.generate(tabs.length, (index) { final isSelected = selectedIndex == index; - return Padding( + return Container( + // decoration: BoxDecoration(border: Border(bottom: BorderSide())), padding: const EdgeInsets.symmetric(horizontal: 1.0), child: InkWell( onTap: () => setState(() => selectedIndex = index), @@ -259,18 +263,21 @@ class TabEnquiryStaffListState extends ConsumerState { mainAxisSize: MainAxisSize.min, children: [ // ---- TEXT ---- - Text( - tabs[index].title, - style: TextStyle( - fontSize: 12, - fontWeight: isSelected - ? FontWeight.w600 - : FontWeight.w400, - color: isSelected - ? const Color( - 0xFF2E7D6E, - ) // Purple-ish like screenshot - : Colors.black87, + SizedBox( + width: 80, + child: Text( + tabs[index].title, + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: isSelected + ? FontWeight.w600 + : FontWeight.w600, + color: isSelected + ? const Color( + 0xFF2E7D6E, + ) // Purple-ish like screenshot + : Colors.black87, + ), ), ), @@ -295,6 +302,7 @@ class TabEnquiryStaffListState extends ConsumerState { ); }), ), + Expanded(child: tabs[selectedIndex].widget), ], ); diff --git a/lib/presentation/themes/indicators/text_field_theme.dart b/lib/presentation/themes/indicators/text_field_theme.dart index 98bf402..c9dbc73 100644 --- a/lib/presentation/themes/indicators/text_field_theme.dart +++ b/lib/presentation/themes/indicators/text_field_theme.dart @@ -18,6 +18,7 @@ class ThemedFormField extends HookWidget { this.isObscurable = false, this.hintColor, this.backgroundColor, + this.highlightColor, this.borderColor, this.errorBorderColor, this.errorTextColor, @@ -39,6 +40,7 @@ class ThemedFormField extends HookWidget { final double? enableBorderWidth; final String? hintText; final Color? textColr; + final Color? highlightColor; final String? imgPath; final String? Function(String? text)? validator; @@ -133,7 +135,7 @@ class ThemedFormField extends HookWidget { : OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: BorderSide( - color: borderColor ?? Color(0xFF50A398), + color: highlightColor ?? borderColor ?? Color(0xFF50A398), width: 2, ), ), @@ -169,7 +171,6 @@ class ThemedFormField extends HookWidget { ); return Container( width: txtwidth ?? MediaQuery.of(context).size.width, - height: txtheight ?? null, child: DecoratedBox( decoration: boxDecoration,