diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index dda7089..e80da35 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":"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":"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.53/","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.21/","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":"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":"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-09-15 17:48:52.204941","version":"3.35.2","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_app_check","path":"/home/venba/.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":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth-6.0.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core-4.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_messaging-16.0.1/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"flutter_secure_storage","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_ios","path":"/home/venba/.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":"/home/venba/.pub-cache/hosted/pub.dev/local_auth_darwin-1.6.0/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_ios","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_ios-1.0.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_ios","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.4/","native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.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":"/home/venba/.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":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth-6.0.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core-4.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/home/venba/.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":"/home/venba/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.30/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_android","path":"/home/venba/.pub-cache/hosted/pub.dev/google_sign_in_android-7.0.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_android","path":"/home/venba/.pub-cache/hosted/pub.dev/local_auth_android-1.0.52/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"open_file_android","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_android-1.0.6/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_android-2.2.18/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.12/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_android","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.20/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_app_check","path":"/home/venba/.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":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth-6.0.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core-4.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"firebase_messaging","path":"/home/venba/.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":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage_macos-3.1.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"google_sign_in_ios","path":"/home/venba/.pub-cache/hosted/pub.dev/google_sign_in_ios-6.1.0/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"/home/venba/.pub-cache/hosted/pub.dev/local_auth_darwin-1.6.0/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_mac","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_mac-1.0.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.2/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_macos","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.3/","native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_linux-0.0.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false},{"name":"url_launcher_linux","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.1/","native_build":true,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"firebase_auth","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth-6.0.2/","native_build":true,"dependencies":["firebase_core"],"dev_dependency":false},{"name":"firebase_core","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core-4.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_secure_storage_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/local_auth_windows-1.0.11/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"open_file_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_windows-0.0.3/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false},{"name":"url_launcher_windows","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.4/","native_build":true,"dependencies":[],"dev_dependency":false}],"web":[{"name":"connectivity_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.5/","dependencies":[],"dev_dependency":false},{"name":"file_picker","path":"/home/venba/.pub-cache/hosted/pub.dev/file_picker-10.3.3/","dependencies":[],"dev_dependency":false},{"name":"firebase_app_check_web","path":"/home/venba/.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":"/home/venba/.pub-cache/hosted/pub.dev/firebase_auth_web-6.0.2/","dependencies":["firebase_core_web"],"dev_dependency":false},{"name":"firebase_core_web","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_core_web-3.1.0/","dependencies":[],"dev_dependency":false},{"name":"firebase_messaging_web","path":"/home/venba/.pub-cache/hosted/pub.dev/firebase_messaging_web-4.0.1/","dependencies":["firebase_core_web"],"dev_dependency":false},{"name":"flutter_secure_storage_web","path":"/home/venba/.pub-cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1/","dependencies":[],"dev_dependency":false},{"name":"google_sign_in_web","path":"/home/venba/.pub-cache/hosted/pub.dev/google_sign_in_web-1.0.0/","dependencies":[],"dev_dependency":false},{"name":"open_file_web","path":"/home/venba/.pub-cache/hosted/pub.dev/open_file_web-0.0.4/","dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"/home/venba/.pub-cache/hosted/pub.dev/package_info_plus-8.3.1/","dependencies":[],"dev_dependency":false},{"name":"shared_preferences_web","path":"/home/venba/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3/","dependencies":[],"dev_dependency":false},{"name":"url_launcher_web","path":"/home/venba/.pub-cache/hosted/pub.dev/url_launcher_web-2.4.1/","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"connectivity_plus","dependencies":[]},{"name":"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":"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-09-18 18:22:04.874824","version":"3.32.1","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file diff --git a/lib/core/routing/app_router.dart b/lib/core/routing/app_router.dart index 1f58845..7431719 100644 --- a/lib/core/routing/app_router.dart +++ b/lib/core/routing/app_router.dart @@ -1,12 +1,15 @@ import 'package:flutter/material.dart'; +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/UserManagement/Profile/profile_web.dart'; -import 'package:nhance_partner/presentation/screens/claims/claimsList.dart'; import 'package:nhance_partner/presentation/screens/dashboard/dashboard.dart'; import '../../data/services/auth_service.dart'; +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/UserManagement/Agent/agent.dart'; import '../../presentation/screens/UserManagement/Agent/agentList.dart'; import '../../presentation/screens/UserManagement/Profile/profile_mobile.dart'; @@ -15,6 +18,9 @@ import '../../presentation/screens/UserManagement/Staff/staffList.dart'; import '../../presentation/screens/home/home_screen.dart'; import '../../presentation/screens/login/login_screen.dart'; import '../../presentation/screens/splash/splash_screen.dart'; +import '../../presentation/screens/staff/policy/policy.dart'; +import '../../presentation/screens/staff/policy/policy_list.dart'; +import '../../presentation/screens/staff/quotations/quotation.dart'; final GoRouter appRouter = GoRouter( initialLocation: AppRoutes.home, @@ -85,9 +91,59 @@ final GoRouter appRouter = GoRouter( builder: (context, state) => const EnquiryList(), ), + // GoRoute( + // path: '/tabEnquiry/:id', + // builder: (context, state) { + // final id = state.pathParameters['id']!; + // // if "create", open empty form + // if (id == 'tab') { + // return TabEnquiryList(); // create mode + // } else { + // return TabEnquiryList(id: id); // update mode + // } + // }, + // ), GoRoute( path: AppRoutes.tabEnquiry, - builder: (context, state) => const TabEnquiryList(), + builder: (context, state) { + return TabEnquiryList(); // no id in path + }, + ), + + // GoRoute( + // path: AppRoutes.tabEnquiry, + // builder: (context, state) { + // return Consumer( + // builder: (context, ref, _) { + // final id = state.pathParameters['id']!; + // ref.read(enquiryIdProvider.notifier).state = (id == 'tab') + // ? null + // : id; + // return TabEnquiryList(); + // }, + // ); + // }, + // ), + GoRoute( + path: AppRoutes.claimlist, + builder: (context, state) => const claimList(), + ), + GoRoute( + path: AppRoutes.endosement, + builder: (context, state) => const endosement(), + ), + GoRoute( + path: AppRoutes.policylist, + builder: (context, state) => const policylist(), + ), + + GoRoute( + path: AppRoutes.quotation, + builder: (context, state) => const QuotationScreen(), + ), + GoRoute( + path: AppRoutes.policy, + builder: (context, state) => const PolicyScreen(), ), ], redirect: (context, state) async { diff --git a/lib/core/routing/routes.dart b/lib/core/routing/routes.dart index 21a0f0f..2656487 100644 --- a/lib/core/routing/routes.dart +++ b/lib/core/routing/routes.dart @@ -10,4 +10,10 @@ class AppRoutes { static const staff = '/staff/:id'; static const String enquiryLst = '/enquiryLst'; static const String tabEnquiry = '/tabEnquiry'; + + static const String claimlist = '/claimList'; + static const String endosement = '/endosement'; + static const String policylist = '/policylist'; + static const String quotation = '/QuotationScreen'; + static const String policy = '/PolicyScreen'; } diff --git a/lib/core/services/api_service.dart b/lib/core/services/api_service.dart index e508983..34f8b4c 100644 --- a/lib/core/services/api_service.dart +++ b/lib/core/services/api_service.dart @@ -402,6 +402,22 @@ class ApiService { return response; } + Future> findEnqQuotePolicyView(id) async { + // print(_token); + if (_token == null) { + await _initializeToken(); + } + final url = Uri.parse( + '${Env.apiUrl}enquiry/enquiryQuotePolicyView?enquiry_id=$id', + ); + final headers = { + 'Authorization': 'Bearer $_token' ?? '', + 'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK', + }; + final response = await _makeGetRequest(url, headers); + return response; + } + //------------------------------------ Quotation ------------------------------------------------ Future> fetchQuotationList(int managerId) async { @@ -425,6 +441,114 @@ class ApiService { return response; } + Future> findSingleQuotationData(id) async { + // print(_token); + if (_token == null) { + await _initializeToken(); + } + final url = Uri.parse('${Env.apiUrl}/quotation/findQuotation?id=1=$id'); + final headers = { + 'Authorization': 'Bearer $_token' ?? '', + 'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK', + }; + final response = await _makeGetRequest(url, headers); + return response; + } + + // ----------------------------------- POLICY ------------------------------------------------- + + Future> fetchPolicyList(int id, role) async { + // print(_token); + if (_token == null) { + await _initializeToken(); + } + + final userId = '1'; + final url; + + if (role == 'manager') { + url = Uri.parse('${Env.apiUrl}enquiry/enquiryList?manager_id=$id'); + } else { + url = Uri.parse('${Env.apiUrl}enquiry/enquiryList?staff_id=$id'); + } + // else { + // url = Uri.parse('${Env.apiUrl}endorsement/endorsementList?agent_id=$id'); + // } + // final url = Uri.parse( + // 'https://venbait.in/nhance/partner/dev/api/agent/agentList?manager_id=${managerId}', + // ); + final headers = { + 'Authorization': 'Bearer $_token' ?? '', + 'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK', + }; + final response = await _makeGetRequest(url, headers); + return response; + } + + // ----------------------------------- CLAIMS ------------------------------------------------- + + Future> fetchClaimList(int id, role) async { + // print(_token); + if (_token == null) { + await _initializeToken(); + } + + final userId = '1'; + final url; + + if (role == 'manager') { + url = Uri.parse('${Env.apiUrl}claim/ClaimList?manager_id=$id'); + } + // else if (role == 'staff') { + // url = Uri.parse('${Env.apiUrl}enquiry/enquiryList?staff_id=$id'); + // } + else { + url = Uri.parse('${Env.apiUrl}claim/ClaimList?agent_id=$id'); + } + // final url = Uri.parse( + // 'https://venbait.in/nhance/partner/dev/api/agent/agentList?manager_id=${managerId}', + // ); + final headers = { + 'Authorization': 'Bearer $_token' ?? '', + 'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK', + }; + final response = await _makeGetRequest(url, headers); + return response; + } + + // ----------------------------------- ENDORSEMENT ------------------------------------------------- + + Future> fetchEndorsementList(int id, role) async { + // print(_token); + if (_token == null) { + await _initializeToken(); + } + + final userId = '1'; + final url; + + if (role == 'manager') { + url = Uri.parse( + '${Env.apiUrl}endorsement/endorsementList?manager_id=$id', + ); + } + // else if (role == 'staff') { + // url = Uri.parse('${Env.apiUrl}enquiry/enquiryList?staff_id=$id'); + // } + else { + url = Uri.parse('${Env.apiUrl}endorsement/endorsementList?agent_id=$id'); + } + // final url = Uri.parse( + // 'https://venbait.in/nhance/partner/dev/api/agent/agentList?manager_id=${managerId}', + // ); + final headers = { + 'Authorization': 'Bearer $_token' ?? '', + 'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK', + }; + final response = await _makeGetRequest(url, headers); + return response; + } + // --------------------------------- MASTER DATA ---------------------------------------------- Future> fetchMasterDropDown(String val) async { diff --git a/lib/presentation/providers/manager_provider.dart b/lib/presentation/providers/manager_provider.dart index a03cf55..f3ef0db 100644 --- a/lib/presentation/providers/manager_provider.dart +++ b/lib/presentation/providers/manager_provider.dart @@ -2,3 +2,4 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; final managerIdProvider = StateProvider((ref) => null); final userIdProvider = StateProvider((ref) => null); +final enquiryIdProvider = StateProvider((ref) => null); diff --git a/lib/presentation/screens/Enquiry/enquiry/enquiry_tab.dart b/lib/presentation/screens/Enquiry/enquiry/enquiry_tab.dart index e9feac8..78396f0 100644 --- a/lib/presentation/screens/Enquiry/enquiry/enquiry_tab.dart +++ b/lib/presentation/screens/Enquiry/enquiry/enquiry_tab.dart @@ -6,6 +6,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:http/http.dart' as http; import 'package:nhance_partner/presentation/layouts/responsive_layout.dart'; +import 'package:toastification/toastification.dart'; import 'package:universal_html/html.dart' as html; import '../../../../core/config/env.dart'; @@ -13,6 +14,7 @@ import '../../../../core/routing/routes.dart'; import '../../../../core/services/api_service.dart'; import '../../../../data/services/auth_service.dart'; import '../../../../data/utils/Pagination.dart'; +import '../../../../data/utils/toastNotification.dart'; import '../../../../data/utils/validators.dart'; import '../../../layouts/main_layout.dart'; import '../../../providers/manager_provider.dart'; @@ -25,7 +27,9 @@ import '../../../themes/indicators/upload_doc_theme.dart' hide ThemedUploadField; class EnquiryTab extends ConsumerStatefulWidget { - const EnquiryTab({super.key}); + String? id; + final Map? data; + EnquiryTab({super.key, this.data, this.id}); @override ConsumerState createState() => EnquiryTabState(); } @@ -84,15 +88,6 @@ class EnquiryTabState extends ConsumerState { List> filteredInsurersData = []; Map dataDetails() { - // final data = { - // "name": controllers["name"]?.text, - // "email": controllers["email"]?.text, - // "mobile": controllers["mobile"]?.text, - // "address": controllers["address"]?.text, - // "agent_code": controllers["code"]?.text, - // "is_active": isActive, - // "manager_id": managerId, - // }; final data = { "agent_id": 1, "name": controllers["name"]?.text, @@ -121,6 +116,11 @@ class EnquiryTabState extends ConsumerState { controllers[field] = TextEditingController(); } + if (widget.data != null) { + print("EnQ has Data"); + } else { + print("EnQ has Data 1"); + } _initializeToken(); Future.microtask(() { managerId = ref.watch(managerIdProvider); @@ -203,68 +203,64 @@ class EnquiryTabState extends ConsumerState { } void updateData() async { - // if (widget.id != null && widget.id != 'create') { + if (widget.data != null && widget.data != 'tab' && widget.id != null) { + // dynamic response = await apiService.findEnqQuotePolicyView(widget.id!); + // final enq = response['data']; + final data = widget.data; + print("updateDataEnq - $data"); - dynamic response = await apiService.findSingleEnquiryData(1); - // dynamic response = await apiService.findSingleAgentData(widget.id!); - final data = response['data']; - print("updateData - ${response['data']}"); + if (data == null) return; - if (data == null) return; - setState(() { - // selectedId = widget.id; - controllers['name']?.text = data['name'] ?? ''; - controllers['email']?.text = data['email'] ?? ''; - controllers['mobile']?.text = data['mobile'] ?? ''; - controllers['regNo']?.text = data['reg_no'] ?? ''; - controllers['remarks']?.text = data['remarks'] ?? ''; - isActive = data["is_active"]; - // selectedVehicleType = data['vehicle_type_id'] ?? '2'; - selectedVehicleTypeId = 2; - selectedInsurer = data['insurer_id'] ?? '3'; + setState(() { + selectedId = widget.id; + controllers['name']?.text = data['name'] ?? ''; + controllers['email']?.text = data['email'] ?? ''; + controllers['mobile']?.text = data['mobile'] ?? ''; + controllers['regNo']?.text = data['reg_no'] ?? ''; + controllers['remarks']?.text = data['remarks'] ?? ''; + isActive = data["is_active"]; + selectedVehicleType = data['vehicle_type_id'] ?? ''; + selectedInsurer = data['insurer_id'] ?? ''; - String? apiDocPath = data["rc_file_name"]; - if (apiDocPath != null && apiDocPath.isNotEmpty) { - print('apiDocPath - $apiDocPath'); - selectedRCFile = apiDocPath.split('/').last; - print('selectedRCFile - $selectedRCFile'); - rcFileUrlFromApi = apiDocPath; - print('rcFileUrlFromApi - $rcFileUrlFromApi'); - docUploadedRCFile = null; - } else { - selectedRCFile = null; - docUploadedRCFile = null; - rcFileUrlFromApi = null; - } + // RC FILE + String? rcPath = data["rc_file_name"]; + if (rcPath != null && rcPath.isNotEmpty) { + selectedRCFile = rcPath.split('/').last; // UI filename + rcFileUrlFromApi = rcPath; // API download URL + docUploadedRCFile = + rcFileUrlFromApi as PlatformFile?; // user has not re-uploaded yet + } else { + selectedRCFile = null; // no UI file shown + rcFileUrlFromApi = null; + docUploadedRCFile = null; + } - String? apiDocPathRC = data["id_proof_file_name"]; - if (apiDocPathRC != null && apiDocPathRC.isNotEmpty) { - print('apiDocPathRC - $apiDocPathRC'); - selectedIdProof = apiDocPathRC.split('/').last; - print('selectedIdProof - $selectedIdProof'); - prevPolicyFileUrlFromApi = apiDocPathRC; - print('prevPolicyFileUrlFromApi - $prevPolicyFileUrlFromApi'); - docUploadedIDProof = null; - } else { - selectedIdProof = null; - docUploadedIDProof = null; - prevPolicyFileUrlFromApi = null; - } + // ID PROOF FILE + String? idProofPath = data["id_proof_file_name"]; + if (idProofPath != null && idProofPath.isNotEmpty) { + selectedIdProof = idProofPath.split('/').last; + idProofFileUrlFromApi = idProofPath; // ✅ FIXED → correct variable + docUploadedIDProof = idProofFileUrlFromApi as PlatformFile?; + } else { + selectedIdProof = null; + idProofFileUrlFromApi = null; + docUploadedIDProof = null; + } - String? apiDocPathPrevPolicy = data["previous_policy_file_name"]; - if (apiDocPathPrevPolicy != null && apiDocPathPrevPolicy.isNotEmpty) { - print('apiDocPathPrevPolicy - $apiDocPathPrevPolicy'); - selectedPrevPolicy = apiDocPathPrevPolicy.split('/').last; - print('selectedPrevPolicy - $selectedPrevPolicy'); - idProofFileUrlFromApi = apiDocPathPrevPolicy; - print('idProofFileUrlFromApi - $idProofFileUrlFromApi'); - docUploadedPrevPolicy = null; - } else { - selectedPrevPolicy = null; - docUploadedPrevPolicy = null; - idProofFileUrlFromApi = null; - } - }); + // PREVIOUS POLICY FILE + String? prevPolicyPath = data["previous_policy_file_name"]; + if (prevPolicyPath != null && prevPolicyPath.isNotEmpty) { + selectedPrevPolicy = prevPolicyPath.split('/').last; + prevPolicyFileUrlFromApi = + prevPolicyPath; // ✅ FIXED → correct variable + docUploadedPrevPolicy = prevPolicyFileUrlFromApi as PlatformFile?; + } else { + selectedPrevPolicy = null; + prevPolicyFileUrlFromApi = null; + docUploadedPrevPolicy = null; + } + }); + } } Future handleSave() async { @@ -283,6 +279,59 @@ class EnquiryTabState extends ConsumerState { } Future attachFiles(http.MultipartRequest request) async { + Future addFileOrKeepName( + PlatformFile? file, + String? apiFileName, + String fieldName, + ) async { + if (file != null) { + // User uploaded a new file → send as multipart + if (file.bytes != null) { + request.files.add( + http.MultipartFile.fromBytes( + fieldName, + file.bytes!, + filename: file.name, + ), + ); + } else if (file.path != null) { + request.files.add( + await http.MultipartFile.fromPath( + fieldName, + file.path!, + filename: file.name, + ), + ); + } + print("📎 Attached new file → $fieldName"); + } else if (apiFileName != null && apiFileName.isNotEmpty) { + // No new upload → tell backend to keep old file + request.fields[fieldName] = apiFileName; + print("🔗 Kept old file → $fieldName = $apiFileName"); + } else { + // Nothing at all + request.fields[fieldName] = ""; + } + } + + await addFileOrKeepName( + docUploadedRCFile, + rcFileUrlFromApi, + 'rc_file_name', + ); + await addFileOrKeepName( + docUploadedIDProof, + idProofFileUrlFromApi, + 'id_proof_file_name', + ); + await addFileOrKeepName( + docUploadedPrevPolicy, + prevPolicyFileUrlFromApi, + 'previous_policy_file_name', + ); + } + + Future attachFiles1(http.MultipartRequest request) async { Future addFile(PlatformFile? file, String fieldName) async { if (file == null) return; try { @@ -313,14 +362,16 @@ class EnquiryTabState extends ConsumerState { } Future createUserData(Map userData) async { - // final bool isUpdating = widget.id != null && widget.id != 'create'; - // final id = widget.id; - final bool isUpdating = false; + final bool isUpdating = + widget.data != null && widget.id != 'tab' && widget.id != 'null'; + final id = widget.id; + print('UPDId- $id'); + + // final bool isUpdating = false; final uri = Uri.parse( - // isUpdating - // ? '${Env.apiUrl}agent/updateAgent' - // : '${Env.apiUrl}agent/createAgent', - '${Env.apiUrl}enquiry/createEnquiry', + isUpdating + ? '${Env.apiUrl}enquiry/updateEnquiry' + : '${Env.apiUrl}enquiry/createEnquiry', ); if (_token == null) { throw Exception('Token not found. Please log in.'); @@ -334,7 +385,7 @@ class EnquiryTabState extends ConsumerState { // If updating, spoof the method Laravel-style if (isUpdating) { - // request.fields['id'] = id!; + request.fields['id'] = id!; request.fields['updated_by'] = userId!.toString(); } else { request.fields['created_by'] = userId!.toString(); @@ -370,7 +421,7 @@ class EnquiryTabState extends ConsumerState { if (response.statusCode == 200 || response.statusCode == 201) { // dispose(); print("✅ Agent submitted successfully!"); - + ToastHelper.showSuccessToast(context, 'Saved Enquiry'); print("Response: ${response.body}"); context.go(AppRoutes.tabEnquiry); } else { @@ -532,40 +583,41 @@ class EnquiryTabState extends ConsumerState { } } - Widget buildResponsiveUploadField({ - required String label, - required String? hintText, - required void Function(String fileName, dynamic file) onFileSelected, - }) { - final isMobile = ResponsiveLayout.isMobile(context); - - final uploadWidget = ThemedUploadField( - hintText: hintText ?? "Upload Document", - txtwidth: MediaQuery.of(context).size.width * 0.26, - onFileSelected: onFileSelected, - ); - - if (isMobile) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(label, style: _textStyle), - const SizedBox(height: 8), - uploadWidget, - const SizedBox(height: 16), - ], - ); - } else { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded(child: Text(label, style: _textStyle)), - const SizedBox(width: 10), - uploadWidget, - ], - ); - } - } + // Widget buildResponsiveUploadField({ + // required String label, + // required String? hintText, + // required void Function(String fileName, dynamic file) onFileSelected, + // }) + // { + // final isMobile = ResponsiveLayout.isMobile(context); + // + // final uploadWidget = ThemedUploadField( + // hintText: hintText ?? "Upload Document", + // txtwidth: MediaQuery.of(context).size.width * 0.26, + // onFileSelected: onFileSelected, + // ); + // + // if (isMobile) { + // return Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text(label, style: _textStyle), + // const SizedBox(height: 8), + // uploadWidget, + // const SizedBox(height: 16), + // ], + // ); + // } else { + // return Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Expanded(child: Text(label, style: _textStyle)), + // const SizedBox(width: 10), + // uploadWidget, + // ], + // ); + // } + // } Widget buildName(BuildContext context) { return buildResponsiveField( @@ -621,8 +673,9 @@ class EnquiryTabState extends ConsumerState { Widget buildVehicleType(BuildContext context) { // Find the matching map from your list + Map? selectedVehicle = filteredVechicleData.firstWhere( - (item) => item['id'] == selectedVehicleTypeId, + (item) => item['id'].toString() == selectedVehicleType, orElse: () => {}, ); @@ -698,6 +751,10 @@ class EnquiryTabState extends ConsumerState { } Widget buildInsurer(BuildContext context) { + Map? selectedInsurerd = filteredInsurersData.firstWhere( + (item) => item['id'].toString() == selectedInsurer, + orElse: () => {}, + ); return buildResponsiveField( label: "Insurer", field: Container( @@ -708,7 +765,7 @@ class EnquiryTabState extends ConsumerState { // height: 40, child: DropdownSearch>( key: dropDownKeyInsurer, - selectedItem: null, + selectedItem: selectedInsurerd.isNotEmpty ? selectedInsurerd : null, items: (filter, infiniteScrollProps) { return filteredInsurersData; }, @@ -769,42 +826,223 @@ class EnquiryTabState extends ConsumerState { ); } + // Widget buildUploadRCDocument(BuildContext context) { + // return buildResponsiveUploadField( + // label: "Upload RC Document", + // hintText: selectedRCFile, + // onFileSelected: (fileName, file) { + // print("File picked: $fileName"); + // setState(() { + // docUploadedRCFile = file; + // }); + // }, + // ); + // } + + Widget buildResponsiveUploadField({ + required String label, + required String? hintText, + required void Function(String fileName, dynamic file) onFileSelected, + bool showDownload = false, + VoidCallback? onRemove, + VoidCallback? onDownload, + }) { + final isMobile = ResponsiveLayout.isMobile(context); + + final uploadWidget = ThemedUploadField( + hintText: hintText ?? "Upload Document", + txtwidth: isMobile ? null : MediaQuery.of(context).size.width * 0.26, + onFileSelected: onFileSelected, + ); + + final downloadRow = showDownload + ? Padding( + padding: const EdgeInsets.only(top: 5), + child: Row( + children: [ + IconButton( + onPressed: onRemove, + icon: const Icon( + Icons.remove_circle_outline_rounded, + color: Colors.redAccent, + ), + tooltip: 'Remove Upload', + ), + GestureDetector( + onTap: onDownload, + child: Container( + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: const Color(0xFF425B5B), + ), + 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.shrink(); + + if (isMobile) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, style: _textStyle), + const SizedBox(height: 8), + uploadWidget, + downloadRow, + const SizedBox(height: 16), + ], + ); + } else { + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded(child: Text(label, style: _textStyle)), + const SizedBox(width: 10), + uploadWidget, + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [SizedBox.shrink(), downloadRow], + ), + ], + ); + } + } + Widget buildUploadRCDocument(BuildContext context) { return buildResponsiveUploadField( label: "Upload RC Document", hintText: selectedRCFile, onFileSelected: (fileName, file) { - print("File picked: $fileName"); setState(() { docUploadedRCFile = file; + // selectedFileNames = fileName; }); }, + showDownload: docUploadedRCFile != null || rcFileUrlFromApi != null, + onRemove: () { + setState(() { + docUploadedRCFile = null; + rcFileUrlFromApi = null; + // selectedFileNames = null; + }); + }, + onDownload: () => apiService.downloadFile( + // apiUrl: 'api/agent/downloadAgentCertificateFile?agent_id=$selectedId', + apiUrl: + 'api/enquiry/downloadEnquiryFile?enquiry_id=$selectedId&file_type=rc', + + apiId: null, + localFile: docUploadedRCFile, + fileName: 'RC', + ), ); } + // Widget buildUploadIDDocument(BuildContext context) { + // return buildResponsiveUploadField( + // label: "Upload ID Proof", + // hintText: selectedIdProof, + // onFileSelected: (fileName, file) { + // print("File picked: $fileName"); + // setState(() { + // docUploadedIDProof = file; + // }); + // }, + // ); + // } + Widget buildUploadIDDocument(BuildContext context) { return buildResponsiveUploadField( label: "Upload ID Proof", hintText: selectedIdProof, onFileSelected: (fileName, file) { - print("File picked: $fileName"); setState(() { docUploadedIDProof = file; + // selectedFileNames = fileName; }); }, + showDownload: docUploadedIDProof != null || idProofFileUrlFromApi != null, + onRemove: () { + setState(() { + docUploadedIDProof = null; + idProofFileUrlFromApi = null; + // selectedFileNames = null; + }); + }, + onDownload: () => apiService.downloadFile( + // apiUrl: 'api/agent/downloadAgentCertificateFile?agent_id=$selectedId', + apiUrl: + 'api/enquiry/downloadEnquiryFile?enquiry_id=$selectedId&file_type=id_proof', + + apiId: null, + localFile: docUploadedRCFile, + fileName: 'Id_Proof', + ), ); } + // Widget buildUploadPolicyDocument(BuildContext context) { + // return buildResponsiveUploadField( + // label: "Upload Previous Policy", + // hintText: selectedPrevPolicy, + // onFileSelected: (fileName, file) { + // print("File picked: $fileName"); + // setState(() { + // docUploadedPrevPolicy = file; + // }); + // }, + // ); + // } + Widget buildUploadPolicyDocument(BuildContext context) { return buildResponsiveUploadField( label: "Upload Previous Policy", hintText: selectedPrevPolicy, onFileSelected: (fileName, file) { - print("File picked: $fileName"); setState(() { docUploadedPrevPolicy = file; + // selectedFileNames = fileName; }); }, + showDownload: + docUploadedPrevPolicy != null || prevPolicyFileUrlFromApi != null, + onRemove: () { + setState(() { + docUploadedPrevPolicy = null; + prevPolicyFileUrlFromApi = null; + // selectedFileNames = null; + }); + }, + onDownload: () => apiService.downloadFile( + // apiUrl: 'api/agent/downloadAgentCertificateFile?agent_id=$selectedId', + apiUrl: + 'api/enquiry/downloadEnquiryFile?enquiry_id=$selectedId&file_type=previous_policy', + + apiId: null, + localFile: docUploadedPrevPolicy, + fileName: 'Previous_Policy', + ), ); } diff --git a/lib/presentation/screens/Enquiry/enquiry/policy_popup.dart b/lib/presentation/screens/Enquiry/enquiry/policy_popup.dart new file mode 100644 index 0000000..f667aae --- /dev/null +++ b/lib/presentation/screens/Enquiry/enquiry/policy_popup.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter/material.dart'; + +Future showAddDialog({ + required BuildContext context, + required String title, + required void Function(String value) onSubmit, +}) async { + final TextEditingController controller = TextEditingController(); + + await showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text(title), + content: title == 'Claim' + ? claims() + : endorsement(), // 👈 conditional content + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text("Cancel"), + ), + ElevatedButton( + onPressed: () { + onSubmit(controller.text.trim()); + Navigator.of(context).pop(); + }, + child: const Text("Save"), + ), + ], + ); + }, + ); +} + +Widget claims() { + return Container( + padding: const EdgeInsets.all(16), + color: Colors.redAccent, + child: const Text('Claims', style: TextStyle(color: Colors.white)), + ); +} + +Widget endorsement() { + return Container( + padding: const EdgeInsets.all(16), + color: Colors.yellow, + child: const Text('Endorsement', style: TextStyle(color: Colors.black)), + ); +} diff --git a/lib/presentation/screens/Enquiry/enquiry/policy_tab.dart b/lib/presentation/screens/Enquiry/enquiry/policy_tab.dart index 9830b7e..d1c3268 100644 --- a/lib/presentation/screens/Enquiry/enquiry/policy_tab.dart +++ b/lib/presentation/screens/Enquiry/enquiry/policy_tab.dart @@ -2,6 +2,8 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:nhance_partner/presentation/screens/Enquiry/enquiry/policy_popup.dart'; import '../../../../core/services/api_service.dart'; import '../../../../data/services/auth_service.dart'; @@ -15,7 +17,9 @@ import '../../../themes/indicators/search_field_theme.dart'; import '../../../themes/indicators/text_field_theme.dart'; class PolicyTab extends ConsumerStatefulWidget { - const PolicyTab({super.key}); + final List>? data; + // const PolicyTab({super.key}); + const PolicyTab({super.key, this.data}); @override ConsumerState createState() => PolicyTabState(); } @@ -40,6 +44,15 @@ class PolicyTabState extends ConsumerState { 'code', 'address', 'regNo', + + 'regNum', + 'insurer', + 'idv', + 'insurerName', + 'policyNo', + 'paymentMode', + 'premAmount', + 'planType', ]; Map controllers = {}; @@ -77,12 +90,15 @@ class PolicyTabState extends ConsumerState { }); try { - final response = await apiService.fetchQuotationList(managerId); + // final response = await apiService.fetchQuotationList(managerId); - if (response['status'] == 'success') { - print('quoationListData - ${response['data']}'); + if (widget.data != null) { + final data = List>.from(widget.data as Iterable); + + print('policyListData - ${widget.data}'); setState(() { - getQuotationData = List>.from(response['data']); + getQuotationData = data; + // getQuotationData = List>.from(response['data']); originalData = getQuotationData; filteredData = List.from(originalData); // print('originalData - $getClaimPolicies'); @@ -120,6 +136,80 @@ class PolicyTabState extends ConsumerState { padding: EdgeInsets.all(26.0), child: Column( children: [ + Container( + child: Row( + children: [ + Text( + 'Policy Details', + style: GoogleFonts.inter( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + + Spacer(), + GestureDetector( + onTap: () {}, + child: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: const Color(0xFF425B5B), + ), + child: Row( + children: const [ + Text( + "Download Policy", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w200, + color: Colors.white, + ), + ), + SizedBox(width: 15), + Icon( + Icons.file_download_outlined, + size: 16, + color: Colors.white, + ), + ], + ), + ), + ), + + SizedBox(width: 15), + GestureDetector( + onTap: () {}, + child: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: const Color(0xFF425B5B), + ), + child: Row( + children: const [ + Text( + "Download Receipt", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w200, + color: Colors.white, + ), + ), + SizedBox(width: 15), + Icon( + Icons.file_download_outlined, + size: 16, + color: Colors.white, + ), + ], + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), SingleChildScrollView(child: buildFormFields(context)), const SizedBox(height: 20), @@ -159,9 +249,18 @@ class PolicyTabState extends ConsumerState { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text('', style: _headerStyle), + Container(child: buildClaimTable()), IconButton( - onPressed: () {}, + onPressed: () { + showAddDialog( + context: context, + title: "Claim", + onSubmit: (value) { + print("New Claim: $value"); + // update claim list here + }, + ); + }, icon: Icon(Icons.add), ), ], @@ -189,9 +288,18 @@ class PolicyTabState extends ConsumerState { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text('', style: _headerStyle), + Container(child: buildEndrosmentTable()), IconButton( - onPressed: () {}, + onPressed: () { + showAddDialog( + context: context, + title: "Endorsement", + onSubmit: (value) { + print("New Claim: $value"); + // update claim list here + }, + ); + }, icon: Icon(Icons.add), ), ], @@ -302,7 +410,7 @@ class PolicyTabState extends ConsumerState { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded(child: Text(label, style: _textStyle)), + Text(label, style: _textStyle), const SizedBox(height: 8), field, const SizedBox(height: 16), @@ -424,6 +532,14 @@ class PolicyTabState extends ConsumerState { ); } + Widget buildClaimTable() { + return Text('data'); + } + + Widget buildEndrosmentTable() { + return Text('data'); + } + static const _headerStyle = TextStyle( color: Colors.black, fontWeight: FontWeight.bold, diff --git a/lib/presentation/screens/Enquiry/enquiry/quotation_tab.dart b/lib/presentation/screens/Enquiry/enquiry/quotation_tab.dart index 9da42f0..bdb4c4d 100644 --- a/lib/presentation/screens/Enquiry/enquiry/quotation_tab.dart +++ b/lib/presentation/screens/Enquiry/enquiry/quotation_tab.dart @@ -1,10 +1,15 @@ +import 'dart:convert'; 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/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:http/http.dart' as http; +import '../../../../core/config/env.dart'; import '../../../../core/services/api_service.dart'; import '../../../../data/services/auth_service.dart'; +import '../../../../data/utils/toastNotification.dart'; import '../../../../data/utils/validators.dart'; import '../../../layouts/responsive_layout.dart'; import '../../../providers/manager_provider.dart'; @@ -15,7 +20,10 @@ import '../../../themes/indicators/upload_doc_theme.dart' hide ThemedUploadField; class QuotationTab extends ConsumerStatefulWidget { - const QuotationTab({super.key}); + // final Map? data; + final List>? data; + String? id; + QuotationTab({super.key, this.data, this.id}); @override ConsumerState createState() => QuotationTabState(); } @@ -34,19 +42,25 @@ class QuotationTabState extends ConsumerState { GlobalKey>>(); List tabHeader = [ - 'name', - 'email', - 'mobile', - 'code', - 'address', - 'regNo', + 'regNum', + 'insurer', + 'idv', + 'premAmount', + 'planType', + 'addit_doc', + 'remarks', + + // 'mobile', + // 'code', + // 'address', + // 'regNo', ]; late String isActive = "1"; - html.File? docUploadedFile; + // html.File? docUploadedFile; - // PlatformFile? passportFile; + PlatformFile? docUploadedFile; String? selectedFileNames; - String? passportFileUrlFromApi; + String? docUploadedFileFromApi; String? selectedId; bool isLoading = false; bool isquotation = false; @@ -64,8 +78,8 @@ class QuotationTabState extends ConsumerState { Map dataDetails() { final data = { - "name": controllers["name"]?.text, - "email": controllers["email"]?.text, + "regNum": controllers["regNum"]?.text, + "insurer": controllers["insurer"]?.text, "mobile": controllers["mobile"]?.text, "address": controllers["address"]?.text, "agent_code": controllers["code"]?.text, @@ -78,6 +92,7 @@ class QuotationTabState extends ConsumerState { List> getQuotationData = []; List> originalData = []; List> filteredData = []; + // bool isLoading = false; @override @@ -103,19 +118,46 @@ class QuotationTabState extends ConsumerState { print("APISERTOKEN - $_token"); } - Future getQuotationList(int managerId) async { + void refresh() { + getQuotationList(managerId); + } + + Future getQuotationList(managerId) async { print('getClaimList called MagId - $managerId'); setState(() { isLoading = true; }); try { - final response = await apiService.fetchQuotationList(managerId); + // if (widget.data != null) { + // final data = List>.from(widget.data as Iterable); + // + // print('quoationListData - ${widget.data}'); + // setState(() { + // getQuotationData = data; + // // getQuotationData = List>.from(response['data']); + // originalData = getQuotationData; + // filteredData = List.from(originalData); + // // print('originalData - $getClaimPolicies'); + // }); + // } + + final response = await apiService.findSingleQuotationData(managerId); if (response['status'] == 'success') { - print('quoationListData - ${response['data']}'); + final rawData = response['data']; + print('quoationListData1 - ${response['data']}'); setState(() { - getQuotationData = List>.from(response['data']); + if (rawData is List) { + // already a list + getQuotationData = List>.from(rawData); + } else if (rawData is Map) { + // single object, wrap into a list + getQuotationData = [Map.from(rawData)]; + } else { + getQuotationData = []; + } + // getQuotationData = List>.from(response['data']); originalData = getQuotationData; filteredData = List.from(originalData); // print('originalData - $getClaimPolicies'); @@ -133,6 +175,97 @@ class QuotationTabState extends ConsumerState { } } + void findAndUpdateById(updateId) { + try { + final match = getQuotationData.firstWhere( + (q) => q['id'] == updateId, + orElse: () => {}, + ); + + if (match.isNotEmpty) { + print("Found quotation: $match"); + updateData(match); + } else { + print("No quotation found with id $updateId"); + } + } catch (e) { + print("Error finding quotation: $e"); + } + } + + void updateData(Map data) { + print('UPDID - $data}'); + + setState(() { + controllers['regNum']?.text = data['reg_no']?.toString() ?? ''; + controllers['insurer']?.text = data['insurer_name']?.toString() ?? ''; + controllers['idv']?.text = + data['insured_declared_value']?.toString() ?? ''; + controllers['premAmount']?.text = + data['premium_amount']?.toString() ?? ''; + controllers['planType']?.text = + data['insurance_plan_type_id']?.toString() ?? ''; + controllers['addit_doc']?.text = + data['additional_uploaded_file_name']?.toString() ?? ''; + controllers['remarks']?.text = data['reject_reason']?.toString() ?? ''; + }); + } + + void handleActions(data) { + print('Action - $data'); + createData(data); + } + + Future createData(val) async { + final String apiUrldata; + apiUrldata = '${Env.apiUrl}quotation/acceptOrRejectQuotation'; + + // final token = await getToken(); // Fetch token + + if (_token == null) { + throw Exception('Token not found. Please log in.'); + } + + final Map data = {"id": selectedId, "status": val}; + + // data['id'] = selectedId; // Add plan_id for update + // data['status'] = val; + + print("data------- $data}"); + + try { + final response = await http.post( + Uri.parse(apiUrldata), + headers: { + 'Authorization': 'Bearer $_token', + 'Content-Type': 'application/json', + 'app-signature': 'nhance-partner-2025-signature-35468846JRhH551HK', + }, + body: jsonEncode(data), // Convert map to JSON + ); + + if (response.statusCode == 200) { + print("Response: ${response.body}"); + + ToastHelper.showSuccessToast(context, 'Status Updated'); + + selectedId = null; // just update field + isquotation = false; + refresh(); + + // context.go(AppRoutes.staffLst); + } else { + final responseBody = jsonDecode(response.body); + dynamic msg = responseBody['data']; + ToastHelper.showErrorToast(context, 'Status Updation Failed'); + print("Failed to submit plan. Status: ${response.statusCode}"); + print("Error: ${response.body}"); + } + } catch (e) { + print(" Error submitting Staff: $e"); + } + } + @override Widget build(BuildContext context) { return Container( @@ -181,7 +314,7 @@ class QuotationTabState extends ConsumerState { children: [ GestureDetector( onTap: () { - // handleSave(); + handleActions('Rejected'); }, child: Container( padding: EdgeInsets.symmetric( @@ -202,7 +335,7 @@ class QuotationTabState extends ConsumerState { const SizedBox(width: 10), GestureDetector( onTap: () { - // handleSave(); + handleActions('Accepted'); }, child: Container( padding: EdgeInsets.symmetric( @@ -231,240 +364,6 @@ class QuotationTabState extends ConsumerState { ); } - Widget buildFormFields(BuildContext context) { - return Form( - key: _formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildResponsiveRow( - context, - buildName(context), - buildInsusrer(context), - ), - if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), - - _buildResponsiveRow( - context, - buildIdv(context), - buildPremiumAmnt(context), - ), - if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), - - _buildResponsiveRow( - context, - buildPlanType(context), - buildDocuments(context), - ), - - if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), - _buildResponsiveRow( - context, - buildAdditonalDocuments(context), - buildRemarks(context), - ), - ], - ), - ); - } - - Widget _buildResponsiveRow( - BuildContext context, - Widget first, - Widget second, - ) { - if (ResponsiveLayout.isMobile(context)) { - // Stack vertically - return Column(children: [first, const SizedBox(height: 2), second]); - } else { - // Place side by side - return Row( - children: [ - Expanded(child: first), - const SizedBox(width: 25), - Expanded(child: second), - ], - ); - } - } - - Widget buildName(BuildContext context) { - return buildResponsiveField( - label: "Registration Number", - field: ThemedFormField( - controller: controllers['name']!, - validator: (value) => Validators.requiredField(value, "name"), - txtwidth: ResponsiveLayout.isMobile(context) - ? null - : MediaQuery.of(context).size.width * 0.26, - ), - ); - } - - Widget buildInsusrer(BuildContext context) { - return buildResponsiveField( - label: "Insusrer", - field: ThemedFormField( - controller: controllers['email']!, - validator: (value) => Validators.email(value, "email"), - txtwidth: ResponsiveLayout.isMobile(context) - ? null - : MediaQuery.of(context).size.width * 0.26, - ), - ); - } - - Widget buildIdv(BuildContext context) { - return buildResponsiveField( - label: "IDV", - field: ThemedFormField( - controller: controllers['mobile']!, - validator: (value) => Validators.phone(value, "phNumber"), - txtwidth: ResponsiveLayout.isMobile(context) - ? null - : MediaQuery.of(context).size.width * 0.26, - ), - ); - } - - Widget buildPremiumAmnt(BuildContext context) { - return buildResponsiveField( - label: "Premium Amount", - field: ThemedFormField( - controller: controllers['mobile']!, - validator: (value) => Validators.phone(value, "phNumber"), - txtwidth: ResponsiveLayout.isMobile(context) - ? null - : MediaQuery.of(context).size.width * 0.26, - ), - ); - } - - Widget buildPlanType(BuildContext context) { - return buildResponsiveField( - label: "Plan Type", - field: ThemedFormField( - controller: controllers['mobile']!, - validator: (value) => Validators.phone(value, "phNumber"), - txtwidth: ResponsiveLayout.isMobile(context) - ? null - : MediaQuery.of(context).size.width * 0.26, - ), - ); - } - - Widget buildDocuments(BuildContext context) { - return buildResponsiveUploadField( - label: "Upload RC Certificate", - hintText: selectedFileNames, - onFileSelected: (fileName, file) { - print("File picked: $fileName"); - setState(() { - docUploadedFile = file; - }); - }, - ); - } - - Widget buildAdditonalDocuments(BuildContext context) { - return buildResponsiveField( - label: "Additional Documents", - field: ThemedFormField( - controller: controllers['mobile']!, - validator: (value) => Validators.phone(value, "phNumber"), - txtwidth: ResponsiveLayout.isMobile(context) - ? null - : MediaQuery.of(context).size.width * 0.26, - ), - ); - } - - Widget buildRemarks(BuildContext context) { - return buildResponsiveField( - label: "Remarks", - field: ThemedFormField( - controller: controllers['mobile']!, - validator: (value) => Validators.phone(value, "phNumber"), - txtwidth: ResponsiveLayout.isMobile(context) - ? null - : MediaQuery.of(context).size.width * 0.26, - ), - ); - } - - 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 buildResponsiveUploadField({ - required String label, - required String? hintText, - required void Function(String fileName, dynamic file) onFileSelected, - }) { - final isMobile = ResponsiveLayout.isMobile(context); - - final uploadWidget = ThemedUploadField( - hintText: hintText ?? "Upload Document", - txtwidth: isMobile ? null : MediaQuery.of(context).size.width * 0.26, - onFileSelected: onFileSelected, - ); - - if (isMobile) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(label, style: _textStyle), - const SizedBox(height: 8), - uploadWidget, - const SizedBox(height: 16), - ], - ); - } else { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded(child: Text(label, style: _textStyle)), - const SizedBox(width: 10), - uploadWidget, - ], - ); - } - } - - Widget buildId(BuildContext context) { - return buildResponsiveField( - label: "Registration 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( @@ -507,6 +406,346 @@ class QuotationTabState extends ConsumerState { ); } + Widget buildFormFields(BuildContext context) { + return Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildResponsiveRow( + context, + buildName(context), + buildInsusrer(context), + ), + if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), + + _buildResponsiveRow( + context, + buildIdv(context), + buildPremiumAmnt(context), + ), + if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), + + _buildResponsiveRow( + context, + buildPlanType(context), + buildDocuments(context), + ), + + // if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), + // _buildResponsiveRow( + // context, + // buildAdditonalDocuments(context), + // buildRemarks(context), + // ), + ], + ), + ); + } + + Widget _buildResponsiveRow( + BuildContext context, + Widget first, + Widget second, + ) { + if (ResponsiveLayout.isMobile(context)) { + // Stack vertically + return Column(children: [first, const SizedBox(height: 2), second]); + } else { + // Place side by side + return Row( + children: [ + Expanded(child: first), + const SizedBox(width: 25), + Expanded(child: second), + ], + ); + } + } + + Widget buildName(BuildContext context) { + return buildResponsiveField( + label: "Registration Number", + field: ThemedFormField( + controller: controllers['regNum']!, + readOnly: true, + // validator: (value) => Validators.requiredField(value, "regNum"), + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ); + } + + Widget buildInsusrer(BuildContext context) { + return buildResponsiveField( + label: "Insusrer", + field: ThemedFormField( + controller: controllers['insurer']!, + readOnly: true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ); + } + + Widget buildIdv(BuildContext context) { + return buildResponsiveField( + label: "IDV", + field: ThemedFormField( + controller: controllers['idv']!, + readOnly: true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ); + } + + Widget buildPremiumAmnt(BuildContext context) { + return buildResponsiveField( + label: "Premium Amount", + field: ThemedFormField( + controller: controllers['premAmount']!, + readOnly: true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ); + } + + Widget buildPlanType(BuildContext context) { + return buildResponsiveField( + label: "Plan Type", + field: ThemedFormField( + controller: controllers['planType']!, + readOnly: true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ); + } + + Widget buildDocuments(BuildContext context) { + return buildResponsiveUploadField( + label: "Passport File", + hintText: selectedFileNames, + onFileSelected: (fileName, file) { + setState(() { + docUploadedFile = file; + selectedFileNames = fileName; + }); + }, + showDownload: docUploadedFile != null || docUploadedFileFromApi != null, + onRemove: () { + setState(() { + docUploadedFile = null; + docUploadedFileFromApi = null; + selectedFileNames = null; + }); + }, + onDownload: () => apiService.downloadFile( + apiUrl: 'api/agent/downloadAgentCertificateFile?agent_id=$selectedId', + apiId: null, + localFile: docUploadedFile, + fileName: selectedFileNames, + ), + ); + } + + // Widget buildAdditonalDocuments(BuildContext context) { + // return buildResponsiveField( + // label: "Additional Documents", + // field: ThemedFormField( + // controller: controllers['addit_doc']!, + // // validator: (value) => Validators.phone(value, "phNumber"), + // txtwidth: ResponsiveLayout.isMobile(context) + // ? null + // : MediaQuery.of(context).size.width * 0.26, + // ), + // ); + // } + // + // Widget buildRemarks(BuildContext context) { + // return buildResponsiveField( + // label: "Remarks", + // field: ThemedFormField( + // controller: controllers['remarks']!, + // // validator: (value) => Validators.phone(value, "phNumber"), + // txtwidth: ResponsiveLayout.isMobile(context) + // ? null + // : MediaQuery.of(context).size.width * 0.26, + // ), + // ); + // } + + 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 buildResponsiveUploadField({ + // required String label, + // required String? hintText, + // required void Function(String fileName, dynamic file) onFileSelected, + // }) + // { + // final isMobile = ResponsiveLayout.isMobile(context); + // + // final uploadWidget = ThemedUploadField( + // hintText: hintText ?? "Upload Document", + // txtwidth: isMobile ? null : MediaQuery.of(context).size.width * 0.26, + // onFileSelected: onFileSelected, + // ); + // + // if (isMobile) { + // return Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text(label, style: _textStyle), + // const SizedBox(height: 8), + // uploadWidget, + // const SizedBox(height: 16), + // ], + // ); + // } else { + // return Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Expanded(child: Text(label, style: _textStyle)), + // const SizedBox(width: 10), + // uploadWidget, + // ], + // ); + // } + // } + + Widget buildResponsiveUploadField({ + required String label, + required String? hintText, + required void Function(String fileName, dynamic file) onFileSelected, + bool showDownload = false, + VoidCallback? onRemove, + VoidCallback? onDownload, + }) { + final isMobile = ResponsiveLayout.isMobile(context); + + final uploadWidget = ThemedUploadField( + hintText: hintText ?? "Upload Document", + txtwidth: isMobile ? null : MediaQuery.of(context).size.width * 0.26, + onFileSelected: onFileSelected, + ); + + final downloadRow = showDownload + ? Padding( + padding: const EdgeInsets.only(top: 5), + child: Row( + children: [ + IconButton( + onPressed: onRemove, + icon: const Icon( + Icons.remove_circle_outline_rounded, + color: Colors.redAccent, + ), + tooltip: 'Remove Upload', + ), + GestureDetector( + onTap: onDownload, + child: Container( + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: const Color(0xFF425B5B), + ), + 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.shrink(); + + if (isMobile) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, style: _textStyle), + const SizedBox(height: 8), + uploadWidget, + downloadRow, + const SizedBox(height: 16), + ], + ); + } else { + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded(child: Text(label, style: _textStyle)), + const SizedBox(width: 10), + uploadWidget, + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [SizedBox.shrink(), downloadRow], + ), + ], + ); + } + } + + Widget buildId(BuildContext context) { + return buildResponsiveField( + label: "Registration 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 _buildHeader() { return Container( decoration: BoxDecoration( @@ -560,23 +799,20 @@ class QuotationTabState extends ConsumerState { isquotation = false; // unselect } }); + + findAndUpdateById(selectedId); print("Selected row id: $selectedId"); }, ), ), - Expanded(flex: 1, child: Text(item['id'] ?? '-', style: _dataBold)), Expanded( flex: 1, - child: Text(item['email'] ?? '-', style: _dataBold), + child: Text(item['reg_no'] ?? '-', style: _dataBold), ), Expanded( flex: 1, - child: Text(item['mobile'] ?? '-', style: _dataBold), - ), - Expanded( - flex: 1, - child: Text(item['insurance_plan_type'] ?? '-', style: _dataBold), + child: Text(item['insurer_name'] ?? '-', style: _dataBold), ), Expanded( flex: 1, @@ -585,6 +821,17 @@ class QuotationTabState extends ConsumerState { style: _dataBold, ), ), + Expanded( + flex: 1, + child: Text( + item['insurance_plan_type_id'] ?? '-', + style: _dataBold, + ), + ), + Expanded( + flex: 1, + child: Text(item['premium_amount'] ?? '-', style: _dataBold), + ), Expanded( flex: 1, child: Text( @@ -628,6 +875,8 @@ class QuotationTabState extends ConsumerState { isquotation = false; // unselect } }); + + findAndUpdateById(selectedId); print("Selected row id: $selectedId"); }, ), @@ -648,9 +897,22 @@ class QuotationTabState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.start, children: [ - const Text("New India", style: _cardBodyStyle), - const Text("TN64V3456", style: _cardheaderStyle), - const Text("Status: Rejected", style: _cardBodyStyle), + Text( + item['insurer_name'] ?? '-', + + style: _cardBodyStyle, + ), + Text( + // "TN64V3456", + item['reg_no'] ?? '-', + + style: _cardheaderStyle, + ), + Text( + 'Status : ${item['status']}' ?? '-', + + style: _cardBodyStyle, + ), ], ), ), @@ -660,9 +922,18 @@ class QuotationTabState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - const Text("Comprehensive", style: _cardBodyStyle), - const Text("IDV:₹145000", style: _cardBodyStyle), - const Text("₹1000", style: _cardheaderStyle), + Text( + item['insurance_plan_type_id'] ?? '-', + style: _cardBodyStyle, + ), + Text( + item['insured_declared_value'] ?? '-', + style: _cardBodyStyle, + ), + Text( + 'Premium Amount - ${item['premium_amount']}' ?? '-', + style: _cardheaderStyle, + ), ], ), ), diff --git a/lib/presentation/screens/Enquiry/enquiry/tabs.dart b/lib/presentation/screens/Enquiry/enquiry/tabs.dart index 57258fe..0def356 100644 --- a/lib/presentation/screens/Enquiry/enquiry/tabs.dart +++ b/lib/presentation/screens/Enquiry/enquiry/tabs.dart @@ -4,124 +4,633 @@ import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import '../../../../core/routing/routes.dart'; +import '../../../../core/services/api_service.dart'; +import '../../../providers/manager_provider.dart'; import 'enquiry_tab.dart'; import 'quotation_tab.dart'; import 'policy_tab.dart'; import '../../../layouts/main_layout.dart'; class TabEnquiryList extends ConsumerStatefulWidget { - const TabEnquiryList({super.key}); + String? id; + TabEnquiryList({super.key, this.id}); @override ConsumerState createState() => TabEnquiryListState(); } class TabEnquiryListState extends ConsumerState { - int selectedIndex = 0; // 0 = Enquiry, 1 = Quotation, 2 = Policy + int selectedIndex = 0; + List tabs = []; + Map? enquiryData; + bool isLoading = true; + late ApiService apiService; - final List tabs = ["Enquiry", "Quotation", "Policy"]; - final List tabWidgets = [EnquiryTab(), QuotationTab(), PolicyTab()]; + @override + void initState() { + super.initState(); + apiService = ApiService(); + + Future.microtask(() { + final id = ref.read(enquiryIdProvider); + + print("IntialID - $id"); + if (id != null) { + _loadData(id); + } else { + setState(() => isLoading = false); + tabs = [ + TabItem("Enquiry", EnquiryTab()), + TabItem("Quotation", QuotationTab()), + TabItem("Policy", PolicyTab()), + ]; + } + }); + // fetch immediately + } + + Future _loadData(id) async { + print('Load Data'); + setState(() => isLoading = true); + final response = await apiService.findEnqQuotePolicyView(id); + setState(() { + enquiryData = response["data"]; + print('Load Data - $enquiryData'); + isLoading = false; + tabs = [ + TabItem( + "Enquiry", + EnquiryTab(data: enquiryData?["enquiry"], id: id ?? ""), + ), + TabItem( + "Quotation", + QuotationTab( + data: (enquiryData?["quotations"] as List?)! + .map((e) => Map.from(e as Map)) + .toList(), + id: id ?? "", + ), + ), + TabItem( + "Policy", + PolicyTab( + data: (enquiryData?["policies"] as List?)! + .map((e) => Map.from(e as Map)) + .toList(), + ), + ), + + // TabItem("Quotation", QuotationTab(data: enquiryData?["quotations"])), + // TabItem("Policy", PolicyTab()), + ]; + }); + } @override Widget build(BuildContext context) { + final bool isMobile = MediaQuery.of(context).size.width < 600; + final id = ref.watch(enquiryIdProvider); + + print("TABUPDID- $id"); + + // When provider changes, re-fetch + ref.listen(enquiryIdProvider, (prev, next) { + if (prev != next) { + _loadData(id); + } + }); + + print('ENQID: $id'); + return MainLayout( title: "Enquiry", body: SafeArea( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - // Header - Padding( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - child: GestureDetector( - onTap: () { - context.go(AppRoutes.dashboard); - }, - child: Row( - children: [ - const Icon( - Icons.arrow_left_sharp, - size: 35, - color: Color(0xFF425B5B), - ), - const SizedBox(width: 8), - Text( - "Enquiry", - style: GoogleFonts.inter( - fontSize: 18, - fontWeight: FontWeight.w700, - color: Colors.black87, - ), - ), - ], - ), - ), - ), - - const SizedBox(height: 10), - - // Tab Buttons - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - children: List.generate(tabs.length, (index) { - final bool isSelected = selectedIndex == index; - return Padding( - padding: const EdgeInsets.only(right: 12), - child: ElevatedButton( - style: ElevatedButton.styleFrom( - elevation: 2, - backgroundColor: isSelected - ? const Color(0xFF425B5B) // selected dark green - : const Color(0xFFEDFFFC), // light teal - foregroundColor: isSelected - ? Colors.white - : Colors.black87, - side: BorderSide( - color: isSelected - ? const Color(0xFF425B5B) - : const Color(0xFFEDFFFC), - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), - ), - padding: const EdgeInsets.symmetric( - horizontal: 24, - vertical: 12, - ), - ), - onPressed: () { - setState(() { - selectedIndex = index; - }); - }, - child: Text( - tabs[index], - style: GoogleFonts.inter( - fontWeight: isSelected - ? FontWeight.w600 - : FontWeight.w500, - fontSize: 15, - ), - ), - ), - ); - }), - ), - ), - - const SizedBox(height: 16), - - // Tab content - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: tabWidgets[selectedIndex], - ), - ), - ], - ), + child: isLoading + ? const Center(child: CircularProgressIndicator()) + : isMobile + ? _buildMobileTabs() + : _buildDesktopTabs(), ), ); } + + Widget _buildMobileTabs() { + return ListView.builder( + itemCount: tabs.length, + padding: const EdgeInsets.all(16), + itemBuilder: (context, index) { + return Card( + margin: const EdgeInsets.only(bottom: 12), + color: const Color(0xFF425B5B), + child: ExpansionTile( + collapsedIconColor: Colors.white, + iconColor: Colors.white, + title: Text( + tabs[index].title, + style: GoogleFonts.inter( + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ), + children: [ + Container( + padding: const EdgeInsets.all(12), + child: tabs[index].widget, + ), + ], + ), + ); + }, + ); + } + + Widget _buildDesktopTabs() { + return Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + child: GestureDetector( + onTap: () { + context.go(AppRoutes.dashboard); + }, + child: Row( + children: [ + const Icon( + Icons.arrow_left_sharp, + size: 35, + color: Color(0xFF425B5B), + ), + const SizedBox(width: 8), + Text( + "Enquiry", + style: GoogleFonts.inter( + fontSize: 18, + fontWeight: FontWeight.w700, + color: Colors.black87, + ), + ), + ], + ), + ), + ), + Row( + children: List.generate(tabs.length, (index) { + final isSelected = selectedIndex == index; + return Padding( + padding: const EdgeInsets.only(left: 10.0), + child: ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 2, + backgroundColor: isSelected + ? const Color(0xFF425B5B) + : const Color(0xFFEDFFFC), + foregroundColor: isSelected ? Colors.white : Colors.black87, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + ), + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 12, + ), + ), + onPressed: () { + setState(() => selectedIndex = index); + }, + child: Text(tabs[index].title), + ), + ); + }), + ), + + SizedBox(height: 10), + Expanded(child: tabs[selectedIndex].widget), + ], + ); + } } + +class TabItem { + final String title; + final Widget widget; + TabItem(this.title, this.widget); +} + +// class TabEnquiryListState extends ConsumerState { +// int selectedIndex = 0; // 0 = Enquiry, 1 = Quotation, 2 = Policy +// +// // final List tabs = ["Enquiry", "Quotation", "Policy"]; +// // final List tabWidgets = [EnquiryTab(), QuotationTab(), PolicyTab()]; +// // late List tabWidgets; +// +// late List> tabs; +// +// Map? enquiryData; +// bool isLoading = true; +// late ApiService apiService; +// +// @override +// void initState() { +// super.initState(); +// apiService = ApiService(); +// _loadData(); +// } +// +// Future _loadData() async { +// final id = ref.read(enquiryIdProvider); +// if (id != null && id.isNotEmpty) { +// setState(() => isLoading = true); +// final response = await apiService.findEnqQuotePolicyView(id); +// setState(() { +// enquiryData = response["data"]; +// isLoading = false; +// tabs = [ +// TabItem("Enquiry", EnquiryTab(data: enquiryData?["enquiry"])), +// TabItem("Quotation", QuotationTab(id: id)), +// TabItem("Policy", PolicyTab()), +// ]; +// }); +// } else { +// setState(() { +// isLoading = false; +// tabs = [ +// TabItem("Enquiry", EnquiryTab()), +// TabItem("Quotation", QuotationTab(id: "")), +// TabItem("Policy", PolicyTab()), +// ]; +// }); +// } +// } +// +// // Future _fetchData() async { +// // final id = ref.read(enquiryIdProvider); +// // if (id != null && id.isNotEmpty) { +// // setState(() { +// // isLoading = true; +// // }); +// // +// // final response = await apiService.findEnqQuotePolicyView(id); +// // +// // setState(() { +// // enquiryData = response["data"]; +// // tabs = [ +// // TabItem("Enquiry", EnquiryTab(data: enquiryData?["enquiry"])), +// // TabItem("Quotation", QuotationTab(id: id)), +// // TabItem("Policy", PolicyTab()), +// // ]; +// // isLoading = false; +// // }); +// // } else { +// // setState(() { +// // tabs = [ +// // TabItem("Enquiry", EnquiryTab()), +// // TabItem("Quotation", QuotationTab(id: "")), +// // TabItem("Policy", PolicyTab()), +// // ]; +// // isLoading = false; +// // }); +// // } +// // } +// +// // Future _fetchData() async { +// // final id = ref.read(enquiryIdProvider); +// // if (id != null && id.isNotEmpty) { +// // final response = await apiService.findEnqQuotePolicyView(id); +// // setState(() { +// // enquiryData = response["data"]; +// // isLoading = false; +// // }); +// // } +// // } +// +// // @override +// // Widget build(BuildContext context) { +// // final bool isMobile = MediaQuery.of(context).size.width < 600; +// // final id = ref.watch(enquiryIdProvider); // listen to provider +// // +// // print('ENQID: $id'); +// // // final tabs = [ +// // // TabItem("Enquiry", EnquiryTab(id: id ?? "")), +// // // TabItem("Quotation", QuotationTab(id: id ?? "")), +// // // TabItem("Policy", PolicyTab()), +// // // ]; +// // final tabs; +// // if (id != null) { +// // print('HASENQID: $id'); +// // setState(() { +// // isLoading = true; +// // }); +// // +// // _fetchData(); +// // +// // setState(() { +// // isLoading = false; +// // }); +// // +// // tabs = [ +// // TabItem("Enquiry", EnquiryTab(data: enquiryData?["enquiry"])), +// // +// // // TabItem("Quotation", QuotationTab(data: enquiryData?["quotations"])), +// // // TabItem("Policy", PolicyTab(data: enquiryData?["policies"])), +// // TabItem("Quotation", QuotationTab(id: id ?? "")), +// // TabItem("Policy", PolicyTab()), +// // ]; +// // } else { +// // setState(() { +// // isLoading = false; +// // }); +// // +// // print('HASENQIDNot'); +// // tabs = [ +// // TabItem("Enquiry", EnquiryTab()), +// // +// // // TabItem("Quotation", QuotationTab(data: enquiryData?["quotations"])), +// // // TabItem("Policy", PolicyTab(data: enquiryData?["policies"])), +// // TabItem("Quotation", QuotationTab(id: id ?? "")), +// // TabItem("Policy", PolicyTab()), +// // ]; +// // } +// // +// // return MainLayout( +// // title: "Enquiry", +// // body: SafeArea( +// // child: isLoading +// // ? const Center( +// // child: CircularProgressIndicator(), // 👈 loader inside SafeArea +// // ) +// // : isMobile +// // ? ListView.builder( +// // itemCount: tabs.length, +// // padding: const EdgeInsets.all(16), +// // itemBuilder: (context, index) { +// // return Card( +// // shape: RoundedRectangleBorder( +// // borderRadius: BorderRadius.circular(8), +// // ), +// // margin: const EdgeInsets.only(bottom: 12), +// // color: const Color(0xFF425B5B), // Header background +// // child: Theme( +// // data: Theme.of(context).copyWith( +// // dividerColor: +// // Colors.transparent, // remove default divider +// // ), +// // child: ExpansionTile( +// // collapsedIconColor: Colors.white, +// // iconColor: Colors.white, +// // title: Text( +// // // tabs[index]["title"], +// // tabs[index].title, +// // style: GoogleFonts.inter( +// // color: Colors.white, +// // fontWeight: FontWeight.w600, +// // ), +// // ), +// // children: [ +// // Container( +// // width: double.infinity, +// // decoration: BoxDecoration( +// // color: const Color(0xFFEAF6F4), +// // borderRadius: BorderRadius.circular(8), +// // border: Border.all( +// // color: const Color(0xFFB0CFCB), +// // width: 1, +// // ), +// // ), +// // padding: const EdgeInsets.all(12), +// // child: SizedBox( +// // height: MediaQuery.of(context).size.height, +// // child: tabs[selectedIndex].widget, +// // // child: tabs[index]["widget"] as Widget, +// // ), // ✅ directly, no SizedBox height +// // ), +// // // Container( +// // // width: double.infinity, +// // // +// // // decoration: BoxDecoration( +// // // color: const Color(0xFFEAF6F4), // light teal bg like screenshot +// // // borderRadius: BorderRadius.circular(8), +// // // border: Border.all( +// // // color: const Color(0xFFB0CFCB), // soft border color +// // // width: 1, +// // // ), +// // // ), +// // // padding: const EdgeInsets.all(12), +// // // child: SizedBox( +// // // height: MediaQuery.of(context).size.height, +// // // // mainAxisSize: MainAxisSize.min, // 👈 prevents collapse +// // // // children: [ +// // // child: tabs[index]["widget"] as Widget, // ✅ actual tab widget +// // // // ], +// // // ), +// // // ), +// // ], +// // ), +// // ), +// // ); +// // }, +// // ) +// // : Column( +// // crossAxisAlignment: CrossAxisAlignment.start, +// // children: [ +// // // Back Button + Title +// // Padding( +// // padding: const EdgeInsets.symmetric( +// // horizontal: 6, +// // vertical: 2, +// // ), +// // child: GestureDetector( +// // onTap: () { +// // context.go(AppRoutes.dashboard); +// // }, +// // child: Row( +// // children: [ +// // const Icon( +// // Icons.arrow_left_sharp, +// // size: 35, +// // color: Color(0xFF425B5B), +// // ), +// // const SizedBox(width: 8), +// // Text( +// // "Enquiry", +// // style: GoogleFonts.inter( +// // fontSize: 18, +// // fontWeight: FontWeight.w700, +// // color: Colors.black87, +// // ), +// // ), +// // ], +// // ), +// // ), +// // ), +// // +// // const SizedBox(height: 10), +// // +// // // Tabs +// // Padding( +// // padding: const EdgeInsets.symmetric(horizontal: 16), +// // child: Row( +// // children: List.generate(tabs.length, (index) { +// // final bool isSelected = selectedIndex == index; +// // return Padding( +// // padding: const EdgeInsets.only(right: 12), +// // child: ElevatedButton( +// // style: ElevatedButton.styleFrom( +// // elevation: 2, +// // backgroundColor: isSelected +// // ? const Color(0xFF425B5B) +// // : const Color(0xFFEDFFFC), +// // foregroundColor: isSelected +// // ? Colors.white +// // : Colors.black87, +// // shape: RoundedRectangleBorder( +// // borderRadius: BorderRadius.circular(6), +// // ), +// // padding: const EdgeInsets.symmetric( +// // horizontal: 24, +// // vertical: 12, +// // ), +// // ), +// // onPressed: () { +// // setState(() { +// // selectedIndex = index; +// // }); +// // }, +// // child: Text( +// // // tabs[index]["title"], +// // tabs[index].title, +// // style: GoogleFonts.inter( +// // fontWeight: isSelected +// // ? FontWeight.w600 +// // : FontWeight.w500, +// // fontSize: 15, +// // ), +// // ), +// // ), +// // ); +// // }), +// // ), +// // ), +// // +// // const SizedBox(height: 16), +// // +// // // Tab Content +// // Expanded( +// // child: Padding( +// // padding: const EdgeInsets.symmetric(horizontal: 16), +// // child: tabs[selectedIndex].widget, +// // // child: tabs[selectedIndex]["widget"], +// // ), +// // ), +// // ], +// // ), +// // ), +// // ); +// // } +// +// // Widget build(BuildContext context) { +// // return MainLayout( +// // title: "Enquiry", +// // body: SafeArea( +// // child: Column( +// // crossAxisAlignment: CrossAxisAlignment.start, +// // mainAxisAlignment: MainAxisAlignment.start, +// // children: [ +// // // Header +// // Padding( +// // padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), +// // child: GestureDetector( +// // onTap: () { +// // context.go(AppRoutes.dashboard); +// // }, +// // child: Row( +// // children: [ +// // const Icon( +// // Icons.arrow_left_sharp, +// // size: 35, +// // color: Color(0xFF425B5B), +// // ), +// // const SizedBox(width: 8), +// // Text( +// // "Enquiry", +// // style: GoogleFonts.inter( +// // fontSize: 18, +// // fontWeight: FontWeight.w700, +// // color: Colors.black87, +// // ), +// // ), +// // ], +// // ), +// // ), +// // ), +// // +// // const SizedBox(height: 10), +// // +// // // Tab Buttons +// // Padding( +// // padding: const EdgeInsets.symmetric(horizontal: 16), +// // child: Row( +// // children: List.generate(tabs.length, (index) { +// // final bool isSelected = selectedIndex == index; +// // return Padding( +// // padding: const EdgeInsets.only(right: 12), +// // child: ElevatedButton( +// // style: ElevatedButton.styleFrom( +// // elevation: 2, +// // backgroundColor: isSelected +// // ? const Color(0xFF425B5B) // selected dark green +// // : const Color(0xFFEDFFFC), // light teal +// // foregroundColor: isSelected +// // ? Colors.white +// // : Colors.black87, +// // side: BorderSide( +// // color: isSelected +// // ? const Color(0xFF425B5B) +// // : const Color(0xFFEDFFFC), +// // ), +// // shape: RoundedRectangleBorder( +// // borderRadius: BorderRadius.circular(6), +// // ), +// // padding: const EdgeInsets.symmetric( +// // horizontal: 24, +// // vertical: 12, +// // ), +// // ), +// // onPressed: () { +// // setState(() { +// // selectedIndex = index; +// // }); +// // }, +// // child: Text( +// // tabs[index], +// // style: GoogleFonts.inter( +// // fontWeight: isSelected +// // ? FontWeight.w600 +// // : FontWeight.w500, +// // fontSize: 15, +// // ), +// // ), +// // ), +// // ); +// // }), +// // ), +// // ), +// // +// // const SizedBox(height: 16), +// // +// // // Tab content +// // Expanded( +// // child: Padding( +// // padding: const EdgeInsets.symmetric(horizontal: 16), +// // child: tabWidgets[selectedIndex], +// // ), +// // ), +// // ], +// // ), +// // ), +// // ); +// // } +// } + +// class TabItem { +// final String title; +// final Widget widget; +// TabItem(this.title, this.widget); +// } diff --git a/lib/presentation/screens/Enquiry/enquiryList.dart b/lib/presentation/screens/Enquiry/enquiryList.dart index 9ea4d6f..89194c5 100644 --- a/lib/presentation/screens/Enquiry/enquiryList.dart +++ b/lib/presentation/screens/Enquiry/enquiryList.dart @@ -2,6 +2,7 @@ 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:http/http.dart'; import 'package:intl/intl.dart'; import 'package:nhance_partner/presentation/providers/userRoleProvider.dart'; import '../../../../core/routing/routes.dart'; @@ -139,8 +140,13 @@ class EnquiryListState extends ConsumerState { onTap: () { Navigator.pop(context); print('EDITStaff - ${data['id']}'); - dynamic id = data['id']; - // context.go('/staff/$id'); + // dynamic id = data['id']; + // context.go('/tabEnquiry/$id'); + + // update provider + final id = data['id'].toString(); + ref.read(enquiryIdProvider.notifier).state = id; + context.go(AppRoutes.tabEnquiry); }, child: Row( mainAxisSize: MainAxisSize.min, @@ -262,10 +268,10 @@ class EnquiryListState extends ConsumerState { GestureDetector( onTap: () { // context.go(AppRoutes.agent / create); - context.go('/staff/create'); + context.go('/tabEnquiry/tab'); }, child: Text( - 'Create New Staff', + 'Create New Enquiry', style: TextStyle( color: Colors.white, fontWeight: FontWeight.w600, diff --git a/lib/presentation/screens/Enquiry/policy_claims_endros/claims.dart b/lib/presentation/screens/Enquiry/policy_claims_endros/claims.dart new file mode 100644 index 0000000..8836eb0 --- /dev/null +++ b/lib/presentation/screens/Enquiry/policy_claims_endros/claims.dart @@ -0,0 +1,699 @@ +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:intl/intl.dart'; +import 'package:nhance_partner/presentation/providers/userRoleProvider.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/search_field_theme.dart'; +import '../../../widgets/custom_action_popup.dart'; + +class claimList extends ConsumerStatefulWidget { + const claimList({super.key}); + @override + ConsumerState createState() => claimListState(); +} + +class claimListState extends ConsumerState { + int currentPage = 1; + int itemsPerPage = 10; + late ApiService apiService; + + // List> dataVal = []; + List> getStaffData = []; + List> originalData = []; + List> filteredData = []; + bool isLoading = false; + + @override + void initState() { + super.initState(); + + apiService = ApiService(); + + Future.microtask(() { + final id = ref.read(managerIdProvider); + final roleId = ref.read(userRoleProvider); + + print("ENQroleId - $roleId"); + if (id != null) { + getStaffList(id, roleId); + } + }); + } + + Future getStaffList(int managerId, role) async { + print('getClaimList called MagId - $managerId - $role'); + setState(() { + isLoading = true; + }); + + try { + final response = await apiService.fetchClaimList(managerId, role); + + if (response['status'] == 'success') { + final data = response['data']; + print('clImlist - ${response['data']}'); + setState(() { + if (data is List) { + // Already a list of maps + getStaffData = List>.from(data); + } else if (data is Map) { + // Single object, wrap in a list + getStaffData = [Map.from(data)]; + } else { + getStaffData = []; + } + // getStaffData = List>.from(response['data']); + originalData = getStaffData; + filteredData = List.from(originalData); + // print('originalData - $getClaimPolicies'); + }); + } else { + getStaffData = []; + originalData = []; + } + } catch (e) { + print('Exception occurred: $e'); + } finally { + setState(() { + isLoading = false; + }); + } + } + + List get _paginatedData { + // Sort descending by id first + final sortedData = [...filteredData] + ..sort((a, b) => int.parse(b['id']) - int.parse(a['id'])); + + final startIndex = (currentPage - 1) * itemsPerPage; + final endIndex = (currentPage * itemsPerPage).clamp(0, sortedData.length); + + return sortedData.sublist(startIndex, endIndex); + } + + void filterData(String query) { + print("FilterDAta - $query"); + setState(() { + filteredData = getStaffData.where((item) { + // final isActiveStatus = item['is_active'] == "1" ? "active" : "inactive"; + + return (item['reg_no'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['insurer_name'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['policy_no'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['policy_end_date'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['claim_type'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['claim_number'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ); + }).toList(); + }); + } + + final TextEditingController _searchStaffController = TextEditingController(); + + String _formatDate(String rawDate) { + try { + final dateTime = DateTime.parse(rawDate); + return DateFormat('dd/MM/yyyy HH:mm').format(dateTime); // 24-hour format + } catch (e) { + return rawDate; // fallback if parsing fails + } + } + + 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) { + return MainLayout( + title: "claims", + body: Container( + // color: Colors.yellow.shade50, + width: MediaQuery.of(context).size.width, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + height: 30, + 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), + ), + Text( + "Claims", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ), + + SizedBox(height: 10), + + Expanded( + child: Container( + // color: Colors.green, + // color: Colors.green.shade50, + width: MediaQuery.of(context).size.width, + + padding: EdgeInsets.all(8.0), + child: Column( + children: [ + Container( + // height: 40, + // color: Colors.pink, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ThemedSearchField( + hintText: 'Search', + backgroundColor: Color(0xFFF6F8F8), + onChanged: filterData, + controller: _searchStaffController, + txtwidth: ResponsiveLayout.isMobile(context) + ? MediaQuery.of(context).size.width * 0.6 + : MediaQuery.of(context).size.width * 0.2, + ), + + Spacer(), + + ExportBtn( + sheetName: "Claims", + fileName: "claim_list", + data: filteredData, + txt: !ResponsiveLayout.isMobile(context) + ? true + : false, + headers: [ + "reg_no", + "insurer_name", + "policy_no", + "policy_end_date", + "claim_number", + "claim_type", + ], + ), + + // SizedBox(width: 10), + // GestureDetector( + // onTap: () { + // // print('Export'); + // }, + // child: Container( + // padding: EdgeInsets.all(8.0), + // decoration: BoxDecoration( + // color: Color(0xFF425B5B), + // borderRadius: BorderRadius.circular(8.0), + // ), + // child: Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // Icon(Icons.add, color: Colors.white), + // + // if (!ResponsiveLayout.isMobile(context)) ...[ + // SizedBox(width: 10), + // + // GestureDetector( + // onTap: () { + // // context.go(AppRoutes.agent / create); + // context.go('/staff/create'); + // }, + // child: Text( + // 'Create New Staff', + // style: TextStyle( + // color: Colors.white, + // fontWeight: FontWeight.w600, + // fontSize: 14, + // ), + // ), + // ), + // ], + // ], + // ), + // ), + // ), + ], + ), + ), + SizedBox(height: 10), + if (!ResponsiveLayout.isMobile(context)) + Container( + decoration: BoxDecoration( + color: const Color(0xFFEDF6F5), + borderRadius: BorderRadius.circular(6), + ), + padding: const EdgeInsets.symmetric( + vertical: 12, + horizontal: 16, + ), + child: const Row( + children: [ + Expanded( + flex: 2, + child: Text('S.No.', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Reg.No.', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Company', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Policy No.', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text( + 'Policy Expiry Date', + style: _headerStyle, + ), + ), + Expanded( + flex: 2, + child: Text('Claim Type', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Claim No.', 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: 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) + ? _buildDataRow(item, sno) + : _buildDataCard(item, sno); + }, + ); + } + + Widget _buildHeader() { + return SizedBox.shrink(); + } + + 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('$sno' ?? '-', style: _dataBold)), + Expanded( + flex: 2, + child: Text( + item['reg_no'] != null + ? _formatDate(item['reg_no']) + : '-', // fallback + style: _dataBold, + ), + ), + Expanded( + flex: 2, + child: Text( + item['insurer_name'] != null + ? _formatDate(item['insurer_name']) + : '-', // fallback + style: _dataBold, + ), + ), + Expanded( + flex: 2, + child: Text( + _formatDate(item['policy_no']) ?? '-', + style: _dataBold, + ), + ), + Expanded( + flex: 2, + child: Text( + _formatDate(item['policy_end_date']) ?? '-', + style: _dataBold, + ), + ), + Expanded( + flex: 2, + child: Text( + item['claim_type'] != null + ? _formatDate(item['claim_number']) + : '-', // fallback + style: _dataBold, + ), + ), + Expanded( + flex: 2, + child: Text( + item['claim_number'] != null + ? _formatDate(item['claim_number']) + : '-', // fallback + style: _dataBold, + ), + ), + Expanded( + flex: 1, + child: Row( + children: [ + PopupMenuButton( + color: Colors.white, + padding: EdgeInsets.zero, + offset: Offset(0, 30), + icon: Icon( + Icons.more_vert, + color: Color(0xFF475569), + size: 14, + ), + itemBuilder: (context) => [ + CustomPopupMenuEntry( + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 8, + vertical: 8, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: _buildPopupMenuActions(context, item), + ), + ), + ), + ], + ), + ], + ), + ), + // Expanded(s + // flex: 1, + // child: Row( + // children: [ + // PopupMenuButton( + // color: Colors.white, + // padding: EdgeInsets.zero, + // offset: Offset(0, 30), + // icon: Icon( + // Icons.more_vert, + // color: Color(0xFF475569), + // size: 14, + // ), + // itemBuilder: (context) => [ + // CustomPopupMenuEntry( + // child: Container( + // padding: EdgeInsets.symmetric( + // horizontal: 8, + // vertical: 8, + // ), + // child: Column( + // mainAxisSize: MainAxisSize.min, + // mainAxisAlignment: MainAxisAlignment.center, + // children: _buildPopupMenuActions(context, item), + // ), + // ), + // ), + // ], + // ), + // ], + // ), + // ), + ], + ), + ); + } + + 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(0xFFF6FEFD), + borderRadius: BorderRadius.circular(8.0), + border: Border.all(color: const Color(0xffD9EBE8)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + //reg no + Text( + item['reg_no'] != null ? _formatDate(item['reg_no']) : '-', + style: _headerStyle, + ), + PopupMenuButton( + color: Colors.white, + padding: EdgeInsets.zero, + offset: Offset(0, 30), + icon: Icon(Icons.more_vert, color: Color(0xFF475569), size: 14), + itemBuilder: (context) => [ + CustomPopupMenuEntry( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: _buildPopupMenuActions(context, item), + ), + ), + ), + ], + ), + ], + ), + const Divider(color: Color(0xffD9EBE8), thickness: 0.8), + + // Company + Vehicle Reg No + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + + mainAxisAlignment: MainAxisAlignment.start, + children: [ + //company + const Text("Company", style: _cardheaderStyle), + Text( + item['reg_no'] != null + ? _formatDate(item['reg_no']) + : '-', + style: _cardBodyStyle, + maxLines: 3, + softWrap: true, + ), + ], + ), + ), + SizedBox(width: 5), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + //status + const Text("Claim Type", style: _cardheaderStyle), + Text( + item['claim_type'] ?? '-', + style: _cardBodyStyle, + maxLines: 2, + softWrap: true, + ), + ], + ), + ), + ], + ), + const SizedBox(height: 15), + + // Created On + Remarks + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + //date and time + const Text("policy Number", style: _cardheaderStyle), + Text( + _formatDate(item['policy_no']) ?? '-', + style: _cardBodyStyle, + ), + ], + ), + ), + SizedBox(width: 5), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + //remarks + const Text("Claim Number", style: _cardheaderStyle), + Text( + item['claim_number'] ?? '-', + style: _cardBodyStyle, + maxLines: 3, + softWrap: true, + ), + ], + ), + ), + ], + ), + ], + ), + ); + } + + static final _dataBold = TextStyle( + fontSize: 14, + + fontWeight: FontWeight.w400, + color: Color(0xFF000000), + ); + + static final _dataSub = TextStyle( + fontSize: 10, + fontWeight: FontWeight.w300, + color: Color(0xFF585757), + ); + + static const _headerStyle = TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + ); + static const _cardheaderStyle = TextStyle( + color: Colors.black, + fontWeight: FontWeight.w600, + fontSize: 12, + ); + + static const _cardBodyStyle = TextStyle( + color: Color(0xFF545454), + fontWeight: FontWeight.w400, + fontSize: 12, + ); +} diff --git a/lib/presentation/screens/Enquiry/policy_claims_endros/endrosment.dart b/lib/presentation/screens/Enquiry/policy_claims_endros/endrosment.dart new file mode 100644 index 0000000..20a5156 --- /dev/null +++ b/lib/presentation/screens/Enquiry/policy_claims_endros/endrosment.dart @@ -0,0 +1,651 @@ +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:intl/intl.dart'; +import 'package:nhance_partner/presentation/providers/userRoleProvider.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/search_field_theme.dart'; +import '../../../widgets/custom_action_popup.dart'; + +class endosement extends ConsumerStatefulWidget { + const endosement({super.key}); + @override + ConsumerState createState() => endosementState(); +} + +class endosementState extends ConsumerState { + int currentPage = 1; + int itemsPerPage = 10; + late ApiService apiService; + + // List> dataVal = []; + List> getStaffData = []; + List> originalData = []; + List> filteredData = []; + bool isLoading = false; + + @override + void initState() { + super.initState(); + + apiService = ApiService(); + + Future.microtask(() { + final id = ref.read(managerIdProvider); + final roleId = ref.read(userRoleProvider); + + print("ENQroleId - $roleId"); + if (id != null) { + getStaffList(id, roleId); + } + }); + } + + Future getStaffList(int managerId, role) async { + print('getClaimList called MagId - $managerId - $role'); + setState(() { + isLoading = true; + }); + + try { + final response = await apiService.fetchEndorsementList(managerId, role); + + if (response['status'] == 'success') { + final data = response['data']; + print('getStaffListData - ${response['data']}'); + setState(() { + if (data is List) { + // Already a list of maps + getStaffData = List>.from(data); + } else if (data is Map) { + // Single object, wrap in a list + getStaffData = [Map.from(data)]; + } else { + getStaffData = []; + } + // getStaffData = List>.from(response['data']); + originalData = getStaffData; + filteredData = List.from(originalData); + // print('originalData - $getClaimPolicies'); + }); + } else { + getStaffData = []; + originalData = []; + } + } catch (e) { + print('Exception occurred: $e'); + } finally { + setState(() { + isLoading = false; + }); + } + } + + List get _paginatedData { + // Sort descending by id first + final sortedData = [...filteredData] + ..sort((a, b) => int.parse(b['id']) - int.parse(a['id'])); + + final startIndex = (currentPage - 1) * itemsPerPage; + final endIndex = (currentPage * itemsPerPage).clamp(0, sortedData.length); + + return sortedData.sublist(startIndex, endIndex); + } + + void filterData(String query) { + print("FilterDAta - $query"); + setState(() { + filteredData = getStaffData.where((item) { + // final isActiveStatus = item['is_active'] == "1" ? "active" : "inactive"; + + return (item['reg_no'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['insurer_name'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['policy_number'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['endorsement_type'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['endorsement_no'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ); + }).toList(); + }); + } + + final TextEditingController _searchStaffController = TextEditingController(); + + String _formatDate(String rawDate) { + try { + final dateTime = DateTime.parse(rawDate); + return DateFormat('dd/MM/yyyy HH:mm').format(dateTime); // 24-hour format + } catch (e) { + return rawDate; // fallback if parsing fails + } + } + + 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) { + return MainLayout( + title: "Endosement", + body: Container( + // color: Colors.yellow.shade50, + width: MediaQuery.of(context).size.width, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + height: 30, + 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), + ), + Text( + "Endosement", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ), + + SizedBox(height: 10), + + Expanded( + child: Container( + // color: Colors.green, + // color: Colors.green.shade50, + width: MediaQuery.of(context).size.width, + + padding: EdgeInsets.all(8.0), + child: Column( + children: [ + Container( + // height: 40, + // color: Colors.pink, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ThemedSearchField( + hintText: 'Search', + backgroundColor: Color(0xFFF6F8F8), + onChanged: filterData, + controller: _searchStaffController, + txtwidth: ResponsiveLayout.isMobile(context) + ? MediaQuery.of(context).size.width * 0.6 + : MediaQuery.of(context).size.width * 0.2, + ), + + Spacer(), + + ExportBtn( + sheetName: "Endorsement", + fileName: "endorsement_list", + data: filteredData, + txt: !ResponsiveLayout.isMobile(context) + ? true + : false, + headers: [ + "reg_no", + "insurer_name", + "policy_number", + "endorsement_type", + "endorsement_no", + ], + ), + + // SizedBox(width: 10), + // GestureDetector( + // onTap: () { + // // print('Export'); + // }, + // child: Container( + // padding: EdgeInsets.all(8.0), + // decoration: BoxDecoration( + // color: Color(0xFF425B5B), + // borderRadius: BorderRadius.circular(8.0), + // ), + // child: Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // Icon(Icons.add, color: Colors.white), + // + // if (!ResponsiveLayout.isMobile(context)) ...[ + // SizedBox(width: 10), + // + // GestureDetector( + // onTap: () { + // // context.go(AppRoutes.agent / create); + // context.go('/staff/create'); + // }, + // child: Text( + // 'Create New Staff', + // style: TextStyle( + // color: Colors.white, + // fontWeight: FontWeight.w600, + // fontSize: 14, + // ), + // ), + // ), + // ], + // ], + // ), + // ), + // ), + ], + ), + ), + SizedBox(height: 10), + if (!ResponsiveLayout.isMobile(context)) + Container( + decoration: BoxDecoration( + color: Color(0xFFEDF6F5), + borderRadius: BorderRadius.circular(6), + ), + padding: const EdgeInsets.symmetric( + vertical: 12, + horizontal: 16, + ), + child: const Row( + children: [ + Expanded( + flex: 2, + child: Text('S.No.', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Reg.No.', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Company', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Policy No.', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text( + 'Endorsement Type', + style: _headerStyle, + ), + ), + Expanded( + flex: 2, + child: Text( + 'Endorsement No', + 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: 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) + ? _buildDataRow(item, sno) + : _buildDataCard(item, sno); + }, + ); + } + + Widget _buildHeader() { + return SizedBox.shrink(); + } + + 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('$sno' ?? '-', style: _dataBold)), + Expanded( + flex: 2, + child: Text( + item['reg_no'] != null + ? _formatDate(item['reg_no']) + : '-', // fallback + style: _dataBold, + ), + ), + Expanded( + flex: 2, + child: Text( + item['insurer_name'] != null + ? _formatDate(item['insurer_name']) + : '-', // fallback + style: _dataBold, + ), + ), + Expanded( + flex: 2, + child: Text( + _formatDate(item['policy_number']) ?? '-', + style: _dataBold, + ), + ), + Expanded( + flex: 2, + child: Text( + _formatDate(item['endorsement_no']) ?? '-', + style: _dataBold, + ), + ), + Expanded( + flex: 2, + child: Text( + _formatDate(item['endorsement_type']) ?? '-', + style: _dataBold, + ), + ), + Expanded( + flex: 1, + child: Row( + children: [ + PopupMenuButton( + color: Colors.white, + padding: EdgeInsets.zero, + offset: Offset(0, 30), + icon: Icon( + Icons.more_vert, + color: Color(0xFF475569), + size: 14, + ), + itemBuilder: (context) => [ + CustomPopupMenuEntry( + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 8, + vertical: 8, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: _buildPopupMenuActions(context, item), + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ); + } + + 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(0xFFF6FEFD), + borderRadius: BorderRadius.circular(8.0), + border: Border.all(color: const Color(0xffD9EBE8)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + //reg no + Text( + item['reg_no'] != null ? _formatDate(item['reg_no']) : '-', + style: _headerStyle, + ), + PopupMenuButton( + color: Colors.white, + padding: EdgeInsets.zero, + offset: Offset(0, 30), + icon: Icon(Icons.more_vert, color: Color(0xFF475569), size: 14), + itemBuilder: (context) => [ + CustomPopupMenuEntry( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: _buildPopupMenuActions(context, item), + ), + ), + ), + ], + ), + ], + ), + const Divider(color: Color(0xffD9EBE8), thickness: 0.8), + + // Company + Vehicle Reg No + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + + mainAxisAlignment: MainAxisAlignment.start, + children: [ + //company + const Text("Company", style: _cardheaderStyle), + Text( + item['insurer_name'] != null + ? _formatDate(item['insurer_name']) + : '-', + style: _cardBodyStyle, + maxLines: 3, + softWrap: true, + ), + ], + ), + ), + SizedBox(width: 5), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + //status + const Text("Endorsement Type", style: _cardheaderStyle), + Text( + item['endorsement_type'] ?? '-', + style: _cardBodyStyle, + maxLines: 2, + softWrap: true, + ), + ], + ), + ), + ], + ), + const SizedBox(height: 15), + + // Created On + Remarks + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + //date and time + const Text("policy Number", style: _cardheaderStyle), + Text( + _formatDate(item['policy_number']) ?? '-', + style: _cardBodyStyle, + ), + ], + ), + ), + SizedBox(width: 5), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + //remarks + const Text("Endorsement Number", style: _cardheaderStyle), + Text( + item['endorsement_no'] ?? '-', + style: _cardBodyStyle, + maxLines: 3, + softWrap: true, + ), + ], + ), + ), + ], + ), + ], + ), + ); + } + + static final _dataBold = TextStyle( + fontSize: 14, + + fontWeight: FontWeight.w400, + color: Color(0xFF000000), + ); + + static final _dataSub = TextStyle( + fontSize: 10, + fontWeight: FontWeight.w300, + color: Color(0xFF585757), + ); + + static const _headerStyle = TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + ); + static const _cardheaderStyle = TextStyle( + color: Colors.black, + fontWeight: FontWeight.w600, + fontSize: 12, + ); + + static const _cardBodyStyle = TextStyle( + color: Color(0xFF545454), + fontWeight: FontWeight.w400, + fontSize: 12, + ); +} diff --git a/lib/presentation/screens/claims/claimsList.dart b/lib/presentation/screens/claims/claimsList.dart deleted file mode 100644 index 7f1fec0..0000000 --- a/lib/presentation/screens/claims/claimsList.dart +++ /dev/null @@ -1,235 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import '../../../data/utils/Pagination.dart'; -import '../../layouts/main_layout.dart'; -import '../../widgets/custom_action_popup.dart'; -// import '../../widgets/custom_dataTable.dart'; - -class ClaimsList extends StatefulWidget { - const ClaimsList({super.key}); - - @override - State createState() => _ClaimsListState(); -} - -class _ClaimsListState extends State { - int currentPage = 0; - int itemsPerPage = 10; - - List> dataVal = [ - { - "planId": "PLAN-1001", - "tripTitle": "Trip to Bangalore", - "tripType": "Business", - "employeeCode": "EMP200", - "userName": "Alice", - "travellerName": "Traveller 1", - "createdOn": "2025-08-01T10:00:00Z", - "statusValue": "Pending Approval", - "forexId": "FX-501", - }, - { - "planId": "PLAN-1002", - "tripTitle": "Trip to Goa", - "tripType": "Leisure", - "employeeCode": "EMP201", - "userName": "", - "travellerName": "Traveller 2", - "createdOn": "2025-08-05T14:30:00Z", - "statusValue": "Approved", - "forexId": null, - }, - // ...more dummy data - ]; - - List> get paginatedData => - dataVal.skip(currentPage * itemsPerPage).take(itemsPerPage).toList(); - - List _buildPopupMenuActions(BuildContext context, dynamic data) { - return [ - IconButton( - icon: const Icon( - Icons.remove_red_eye, - color: Color(0xFF475569), - size: 18, - ), - tooltip: 'View The Trip Details', - onPressed: () { - Navigator.pop(context); - // ApiService.viewPlan(context, plan.planId, isViewMode: true); - }, - ), - - IconButton( - icon: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: 15, - ), - tooltip: 'Edit The Trip Details', - onPressed: () { - Navigator.pop(context); - // ApiService.viewPlan(context, data.planId, isViewMode: false); - }, - ), - - IconButton( - icon: const Icon(Icons.cancel_rounded, size: 18), - tooltip: 'Cancellation The Trip Details', - onPressed: () { - Navigator.pop(context); - // deletePlan(data.planId); - }, - ), - - IconButton( - icon: const Icon(Icons.download, color: Color(0xFF475569), size: 18), - tooltip: 'Download The PDF', - onPressed: () { - Navigator.pop(context); - // apiService.getPdfDownload(data.planId); - }, - ), - - IconButton( - icon: const Icon( - Icons.monetization_on_outlined, - color: Color(0xFF475569), - size: 18, - ), - tooltip: 'Download Forex PDF', - onPressed: () { - Navigator.pop(context); - // apiService.getForexPdfDownload(data.forexId); - }, - ), - ]; - } - - @override - Widget build(BuildContext context) { - return MainLayout( - title: "Claims", - body: Container( - // color: Colors.yellow.shade50, - margin: const EdgeInsets.all(8.0), - child: Column( - children: [ - Container( - width: MediaQuery.of(context).size.width, - - padding: const EdgeInsets.all(8.0), - // color: Colors.grey.shade200, - // color: Colors.red.shade50, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: DataTable( - columns: const [ - DataColumn(label: Text("S.NO")), - DataColumn(label: Text("Trip ID")), - DataColumn(label: Text("Trip Name")), - DataColumn(label: Text("Trip Type")), - DataColumn(label: Text("Emp Code")), - DataColumn(label: Text("Traveller")), - DataColumn(label: Text("Created On")), - DataColumn(label: Text("Actions")), - ], - rows: paginatedData.asMap().entries.map((entry) { - int index = entry.key; - var data = entry.value; - - String createdOn = ""; - final rawDateStr = data["createdOn"]; - if (rawDateStr != null && - rawDateStr.toString().isNotEmpty) { - try { - final parsed = DateTime.parse(rawDateStr); - createdOn = DateFormat("d MMM yyyy").format(parsed); - } catch (_) { - createdOn = rawDateStr.toString().split(" ").first; - } - } - - return DataRow( - cells: [ - DataCell( - Text("${(currentPage * itemsPerPage) + index + 1}"), - ), - DataCell(Text(data["planId"] ?? "-")), - DataCell(Text(data["tripTitle"] ?? "-")), - DataCell(Text(data["tripType"] ?? "-")), - DataCell(Text(data["employeeCode"] ?? "-")), - DataCell( - Text( - (data["userName"] != null && - data["userName"].toString().isNotEmpty) - ? data["userName"] - : data["travellerName"] ?? "-", - ), - ), - DataCell(Text(createdOn)), - DataCell( - Row( - children: [ - PopupMenuButton( - color: Colors.white, - padding: EdgeInsets.zero, - offset: Offset(0, 30), - icon: Icon( - Icons.more_vert, - color: Color(0xFF475569), - size: 14, - ), - itemBuilder: (context) => [ - CustomPopupMenuEntry( - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 8, - vertical: 8, - ), - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: - MainAxisAlignment.center, - children: _buildPopupMenuActions( - context, - data, - ), - ), - ), - ), - ], - ), - ], - ), - ), - ], - ); - }).toList(), - ), - ), - ), - - PaginationControls( - currentPage: currentPage, - itemsPerPage: itemsPerPage, - totalItems: dataVal.length, - // activeColor: layoutColor, // your theme color - onPageChanged: (page) { - setState(() { - currentPage = page; - }); - }, - onItemsPerPageChanged: (items) { - setState(() { - itemsPerPage = items; - currentPage = 0; - }); - }, - ), - ], - ), - ), - ); - } -} diff --git a/lib/presentation/screens/staff/policy/policy.dart b/lib/presentation/screens/staff/policy/policy.dart new file mode 100644 index 0000000..5bf92ec --- /dev/null +++ b/lib/presentation/screens/staff/policy/policy.dart @@ -0,0 +1,761 @@ +import 'dart:io' as html; + +import 'package:dropdown_search/dropdown_search.dart'; +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 '../../../../core/routing/routes.dart'; +import '../../../../core/services/api_service.dart'; +import '../../../../data/services/auth_service.dart'; +import '../../../../data/utils/Pagination.dart'; +import '../../../../data/utils/validators.dart'; + +import '../../../layouts/main_layout.dart'; +import '../../../layouts/responsive_layout.dart'; +import '../../../providers/manager_provider.dart'; +import '../../../themes/indicators/customizd_file_upload.dart'; +import '../../../themes/indicators/text_field_theme.dart'; + + + +class PolicyScreen extends ConsumerStatefulWidget { + const PolicyScreen({super.key}); + @override + ConsumerState createState() => PolicyScreenState(); +} + +class PolicyScreenState extends ConsumerState { + int currentPage = 0; + int itemsPerPage = 10; + + List> dataVal = []; + + final TextEditingController _searchController = TextEditingController(); + + late ApiService apiService; + final _formKey = GlobalKey(); + final GlobalKey>> dropDownKey = + GlobalKey>>(); + + List tabHeader = [ + 'name', + 'email', + 'mobile', + 'code', + 'address', + 'regNo', + ]; + late String isActive = "1"; + html.File? docUploadedFile; + + // PlatformFile? passportFile; + String? selectedFileNames; + String? passportFileUrlFromApi; + String? selectedId; + bool isLoading = false; + bool isquotation = false; + + Map controllers = {}; + String? _token; + dynamic userId; + dynamic managerId; + + List> getVehicleTypeData = []; + List> filteredVechicleData = []; + + List> getInsurersData = []; + List> filteredInsurersData = []; + + Map dataDetails() { + final data = { + "name": controllers["name"]?.text, + "email": controllers["email"]?.text, + "mobile": controllers["mobile"]?.text, + "address": controllers["address"]?.text, + "agent_code": controllers["code"]?.text, + "is_active": isActive, + "manager_id": managerId, + }; + return data; + } + + List> getQuotationData = []; + List> originalData = []; + List> filteredData = []; + // bool isLoading = false; + + @override + void initState() { + super.initState(); + apiService = ApiService(); + + for (String field in tabHeader) { + controllers[field] = TextEditingController(); + } + // updateData(); + _initializeToken(); + Future.microtask(() { + managerId = ref.watch(managerIdProvider); + userId = ref.watch(userIdProvider); + + getQuotationList(managerId); + }); + } + + Future _initializeToken() async { + _token = await AuthService.getToken(); + print("APISERTOKEN - $_token"); + } + + Future getQuotationList(int managerId) async { + print('getClaimList called MagId - $managerId'); + setState(() { + isLoading = true; + }); + + try { + final response = await apiService.fetchQuotationList(managerId); + + if (response['status'] == 'success') { + print('quoationListData - ${response['data']}'); + setState(() { + getQuotationData = List>.from(response['data']); + originalData = getQuotationData; + filteredData = List.from(originalData); + // print('originalData - $getClaimPolicies'); + }); + } else { + getQuotationData = []; + originalData = []; + } + } catch (e) { + print('Exception occurred: $e'); + } finally { + setState(() { + isLoading = false; + }); + } + } + + @override + Widget build(BuildContext context) { + return + MainLayout( + title: 'policy', + body: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + children: [ + + Container( + height: 30, + 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), + ), + Text( + "Policy", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ), + + SizedBox(height: 10), + + + //1ST SECTION + Container( + decoration: BoxDecoration( + color: const Color(0xFFEDF6F5), + borderRadius: BorderRadius.circular(10), + ), + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Enquiry Details", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + ), + ), + SizedBox(height: 10), + LayoutBuilder( + builder: (context, constraints) { + final isMobile = constraints.maxWidth < 600; // breakpoint + + if (isMobile) { + // 📱 MOBILE → Column layout + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + registernumber(context), + const SizedBox(height: 16), + insurer(context), + const SizedBox(height: 16), + buildIdv(context), + const SizedBox(height: 16), + buildPremiumAmnt(context), + const SizedBox(height: 16), + buildPlanType(context), + const SizedBox(height: 16), + Wrap( + spacing: 12, + runSpacing: 8, + children: [ + _downloadButton("Download RC"), + _downloadButton("Download ID Proof"), + _downloadButton("Download Previous Policy"), + _downloadButton("Quotation Document"), + ], + ), + ], + ); + } else { + // 💻 WEB → Row layout + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded(flex: 2, child: registernumber(context)), + const SizedBox(width: 20), + Expanded(flex: 2, child: insurer(context)), + const SizedBox(width: 20), + Expanded(flex: 2, child: buildIdv(context)), + const SizedBox(width: 20), + Expanded(flex: 2, child: buildPremiumAmnt(context)), + const SizedBox(width: 20), + Expanded(flex: 2, child: buildPlanType(context)), + const SizedBox(width: 20), + ], + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + _downloadButton("Download RC"), + const SizedBox(width: 20), + _downloadButton("Download ID Proof"), + const SizedBox(width: 20), + _downloadButton("Download Previous Policy"), + const SizedBox(width: 20), + _downloadButton("Quotation Document"), + + ], + ), + ], + ); + } + }, + ), + ], + ), + ), + + + const SizedBox(height: 20), + + //2ND SECTION + Container( + // color: Colors.green, + decoration: BoxDecoration( + color: Color(0xffEDF6F5), + borderRadius: BorderRadius.circular(10.0), + ), + width: MediaQuery.of(context).size.width, + // height: MediaQuery.of(context).size.height * 0.8, + padding: EdgeInsets.all(26.0), + child: Column( + children: [ + + + SingleChildScrollView(child: buildFormFields(context)), + + const SizedBox(height: 20), + + //confirm button + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + GestureDetector( + onTap: () { + // handleSave(); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 45.0, + vertical: 8, + ), + + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8.0), + color: Color(0xFF425B5B), + ), + child: Text( + 'Sumbit', + style: TextStyle(color: Colors.white), + ), + ), + ), + ], + ), + ], + ), + ), + + const SizedBox(height: 20), + + + + ], + ), + ), + ), + ); + } + + Widget _readonlyField(String label, String value) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, style: GoogleFonts.inter(fontSize: 13, fontWeight: FontWeight.w600)), + const SizedBox(height: 6), + Container( + padding: const EdgeInsets.symmetric(horizontal: 60, vertical: 14), + decoration: BoxDecoration( + color: Colors.red, + borderRadius: BorderRadius.circular(6), + border: Border.all(color: Colors.grey.shade300), + ), + child: Text(value, style: GoogleFonts.inter(fontSize: 14)), + ), + ], + ); + } + + Widget _downloadButton(String label) { + return ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF425B5B), + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)), + ), + onPressed: () { + // TODO: file download logic + }, + icon: const Icon(Icons.download, size: 18), + label: Text(label, style: GoogleFonts.inter(fontSize: 13)), + ); + } + + Widget buildFormFields(BuildContext context) { + return Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildResponsiveRow( + context, + Insuredname(context), + premiumamount(context), + policynumber(context), + ), + if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), + + _buildResponsiveRow( + context, + Paymentmode(context), + policyissuedate(context), + policystartdate(context), + ), + if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), + + _buildResponsiveRow( + context, + policyenddate(context), + buildDocuments(context), + buildDocuments(context), + ), + + // if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), + // _buildResponsiveRow( + // context, + // buildAdditonalDocuments(context), + // buildRemarks(context), + // ), + ], + ), + ); + } + + Widget _buildResponsiveRow( + BuildContext context, + Widget first, + Widget second, + Widget third, + ) + { + if (ResponsiveLayout.isMobile(context)) { + // Stack vertically + return Column(children: [first, const SizedBox(height: 2), second]); + } else { + // Place side by side + return Row( + children: [ + Expanded(child: first), + const SizedBox(width: 25), + Expanded(child: second), + const SizedBox(width: 25), + Expanded(child: third), + ], + ); + } + } + + // Widget buildName(BuildContext context) { + // return buildResponsiveField( + // label: "Registration Number", + // field: ThemedFormField( + // controller: controllers['name']!, + // validator: (value) => Validators.requiredField(value, "name"), + // txtwidth: ResponsiveLayout.isMobile(context) + // ? null + // : MediaQuery.of(context).size.width * 0.26, + // ), + // ); + // } + // + // Widget buildInsusrer(BuildContext context) { + // return buildResponsiveField( + // label: "Insusrer", + // field: ThemedFormField( + // controller: controllers['email']!, + // validator: (value) => Validators.email(value, "email"), + // txtwidth: ResponsiveLayout.isMobile(context) + // ? null + // : MediaQuery.of(context).size.width * 0.26, + // ), + // ); + // } + + Widget registernumber(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Register Number',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + readOnly:true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget insurer(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Insurer',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + readOnly:true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget buildIdv(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('IDV',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + readOnly:true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget buildPremiumAmnt(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Premium Amount',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + readOnly:true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget buildPlanType(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Plan Type',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + readOnly:true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + + + + + Widget Insuredname(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Insured Name',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget premiumamount(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Premium Amount',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget policynumber(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Policy Number',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget Paymentmode(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Payment Mode',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget policyissuedate(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Policy Issue Date',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget policystartdate(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Policy Start Date',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget policyenddate(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Policy End Date',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget buildDocuments(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Quotation Documents ', + style: _textStyle, + ), + const SizedBox(height: 10), + buildResponsiveUploadField( + hintText: selectedFileNames, + onFileSelected: (fileName, file) { + print("File picked: $fileName"); + setState(() { + docUploadedFile = file; + }); + }, + ), + ], + ); + } + + + Widget buildResponsiveUploadField({ + String? label, // 🔹 make optional + required String? hintText, + required void Function(String fileName, dynamic file) onFileSelected, + }) { + final isMobile = ResponsiveLayout.isMobile(context); + + final uploadWidget = ThemedUploadField( + hintText: hintText ?? "Upload Documents", + txtwidth: isMobile ? null : MediaQuery.of(context).size.width * 0.26, + onFileSelected: onFileSelected, + ); + + if (isMobile) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (label != null && label.isNotEmpty) ...[ // ✅ only render if label is given + Text(label, style: _textStyle), + const SizedBox(height: 8), + ], + uploadWidget, + const SizedBox(height: 16), + ], + ); + } else { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (label != null && label.isNotEmpty) ...[ + Expanded(child: Text(label, style: _textStyle)), + const SizedBox(width: 10), + ], + uploadWidget, + ], + ); + } + } + + 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, + ], + ); + } + } + + + + static const _textStyle = TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + ); + + +} diff --git a/lib/presentation/screens/staff/policy/policy_list.dart b/lib/presentation/screens/staff/policy/policy_list.dart new file mode 100644 index 0000000..1775f04 --- /dev/null +++ b/lib/presentation/screens/staff/policy/policy_list.dart @@ -0,0 +1,700 @@ +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:intl/intl.dart'; +import 'package:nhance_partner/presentation/providers/userRoleProvider.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/search_field_theme.dart'; +import '../../../widgets/custom_action_popup.dart'; + + +class policylist extends ConsumerStatefulWidget { + const policylist({super.key}); + @override + ConsumerState createState() => policylistState(); +} + +class policylistState extends ConsumerState { + int currentPage = 1; + int itemsPerPage = 10; + late ApiService apiService; + + // List> dataVal = []; + List> getStaffData = []; + List> originalData = []; + List> filteredData = []; + bool isLoading = false; + + @override + void initState() { + super.initState(); + + apiService = ApiService(); + + Future.microtask(() { + final id = ref.read(managerIdProvider); + final roleId = ref.read(userRoleProvider); + + print("ENQroleId - $roleId"); + if (id != null) { + getStaffList(id, roleId); + } + }); + } + + Future getStaffList(int managerId, role) async { + print('getClaimList called MagId - $managerId - $role'); + setState(() { + isLoading = true; + }); + + try { + final response = await apiService.fetchPolicyList(managerId, role); + + if (response['status'] == 'success') { + final data = response['data']; + print('getStaffListData - ${response['data']}'); + setState(() { + if (data is List) { + // Already a list of maps + getStaffData = List>.from(data); + } else if (data is Map) { + // Single object, wrap in a list + getStaffData = [Map.from(data)]; + } else { + getStaffData = []; + } + // getStaffData = List>.from(response['data']); + originalData = getStaffData; + filteredData = List.from(originalData); + // print('originalData - $getClaimPolicies'); + }); + } else { + getStaffData = []; + originalData = []; + } + } catch (e) { + print('Exception occurred: $e'); + } finally { + setState(() { + isLoading = false; + }); + } + } + + List get _paginatedData { + // Sort descending by id first + final sortedData = [...filteredData] + ..sort((a, b) => int.parse(b['id']) - int.parse(a['id'])); + + final startIndex = (currentPage - 1) * itemsPerPage; + final endIndex = (currentPage * itemsPerPage).clamp(0, sortedData.length); + + return sortedData.sublist(startIndex, endIndex); + } + + void filterData(String query) { + print("FilterDAta - $query"); + setState(() { + filteredData = getStaffData.where((item) { + // final isActiveStatus = item['is_active'] == "1" ? "active" : "inactive"; + + return (item['agent_name'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['reg_no'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['insurer_name'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['assigned_to_name'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['insured_name'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['premium_amount'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['payment_mode'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['updated_on'] ?? '').toLowerCase().contains( + query.toLowerCase(), + ) || + (item['policy_number'] ?? '').toLowerCase().contains(query.toLowerCase()); + }).toList(); + }); + } + + final TextEditingController _searchStaffController = TextEditingController(); + + String _formatDate(String rawDate) { + try { + final dateTime = DateTime.parse(rawDate); + return DateFormat('dd/MM/yyyy HH:mm').format(dateTime); // 24-hour format + } catch (e) { + return rawDate; // fallback if parsing fails + } + } + + 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) { + return MainLayout( + title: "Policy", + body: Container( + // color: Colors.yellow.shade50, + width: MediaQuery.of(context).size.width, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + height: 30, + 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), + ), + Text( + "Policy", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ), + + SizedBox(height: 10), + + Expanded( + child: Container( + // color: Colors.green, + // color: Colors.green.shade50, + width: MediaQuery.of(context).size.width, + + padding: EdgeInsets.all(8.0), + child: Column( + children: [ + Container( + // height: 40, + // color: Colors.pink, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ThemedSearchField( + hintText: 'Search', + backgroundColor: Color(0xFFF6F8F8), + onChanged: filterData, + controller: _searchStaffController, + txtwidth: ResponsiveLayout.isMobile(context) + ? MediaQuery.of(context).size.width * 0.6 + : MediaQuery.of(context).size.width * 0.2, + ), + + Spacer(), + + ExportBtn( + sheetName: "Policy", + fileName: "Policy_list", + data: filteredData, + txt: !ResponsiveLayout.isMobile(context) + ? true + : false, + headers: [ + "reg_no", + "agent_name", + "assigned_to_name", + "insurer_name", + "insured_name", + "premium_amount", + "payment_mode", + "updated_on", + "status", + ], + ), + + // SizedBox(width: 10), + // GestureDetector( + // onTap: () { + // // print('Export'); + // }, + // child: Container( + // padding: EdgeInsets.all(8.0), + // decoration: BoxDecoration( + // color: Color(0xFF425B5B), + // borderRadius: BorderRadius.circular(8.0), + // ), + // child: Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // Icon(Icons.add, color: Colors.white), + // + // if (!ResponsiveLayout.isMobile(context)) ...[ + // SizedBox(width: 10), + // + // GestureDetector( + // onTap: () { + // // context.go(AppRoutes.agent / create); + // context.go('/staff/create'); + // }, + // child: Text( + // 'Create New Staff', + // style: TextStyle( + // color: Colors.white, + // fontWeight: FontWeight.w600, + // fontSize: 14, + // ), + // ), + // ), + // ], + // ], + // ), + // ), + // ), + ], + ), + ), + SizedBox(height: 10), + if (!ResponsiveLayout.isMobile(context)) + Container( + decoration: BoxDecoration( + color: Color(0xFFEDF6F5), + borderRadius: BorderRadius.circular(6), + ), + padding: const EdgeInsets.symmetric( + vertical: 12, + horizontal: 16, + ), + child: const Row( + children: [ + Expanded( + flex: 2, + child: Text('Reg.No', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text( + 'Agents', + style: _headerStyle, + ), + ), + Expanded( + flex: 2, + child: Text('Assigned To', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Insurer', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Insured Name', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Premium', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Payment Mode', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Policy Number', style: _headerStyle), + ), + Expanded( + flex: 2, + child: Text('Date', style: _headerStyle), + ), + Expanded( + flex: 2, + 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: 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) + ? _buildDataRow(item, sno) + : _buildDataCard(item, sno); + }, + ); + } + + Widget _buildHeader() { + return SizedBox.shrink(); + } + + Widget _buildDataRow(Map item, sno) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 10, 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('reg_no' ?? '-', style: _dataBold)), + Expanded( + flex: 2, + child: Text( + _formatDate(item['agent_name']) ?? '-', + style: _dataBold, + ), + ), + Expanded( + flex: 2, + child: Text(item['assigned_to_name'] ?? '-', style: _dataBold), + ), + Expanded( + flex: 2, + child: Text( + item['insurer_name'] ?? '-', + style: _dataBold, + softWrap: true, + maxLines: 3, + ), + ), + Expanded( + flex: 2, + child: Text( + item['insured_name'] ?? '-', + style: _dataBold, + softWrap: true, + maxLines: 3, + ), + ), + Expanded( + flex: 2, + child: Text( + item['premium_amount'] ?? '-', + style: _dataBold, + softWrap: true, + maxLines: 3, + ), + ), + Expanded( + flex: 2, + child: Text( + item['payment_mode'] ?? '-', + style: _dataBold, + softWrap: true, + maxLines: 3, + ), + ), + Expanded( + flex: 2, + child: Text( + item['policy_number'] ?? '-', + style: _dataBold, + softWrap: true, + maxLines: 3, + ), + ), + Expanded( + flex: 2, + child: Text( + item['updated_on'] ?? '-', + style: _dataBold, + softWrap: true, + maxLines: 3, + ), + ), + Expanded( + flex: 2, + child: Text(item['status'] ?? '-', style: _dataBold), + ), + + Expanded( + flex: 1, + child: Row( + children: [ + PopupMenuButton( + color: Colors.white, + padding: EdgeInsets.zero, + offset: Offset(0, 30), + icon: Icon( + Icons.more_vert, + color: Color(0xFF475569), + size: 14, + ), + itemBuilder: (context) => [ + CustomPopupMenuEntry( + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 8, + vertical: 8, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: _buildPopupMenuActions(context, item), + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ); + } + + 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(0xFFF6FEFD), + borderRadius: BorderRadius.circular(8.0), + border: Border.all(color: const Color(0xffD9EBE8)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(item['reg_no'] ?? '-', style: _headerStyle), + PopupMenuButton( + color: Colors.white, + padding: EdgeInsets.zero, + offset: Offset(0, 30), + icon: Icon(Icons.more_vert, color: Color(0xFF475569), size: 14), + itemBuilder: (context) => [ + CustomPopupMenuEntry( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: _buildPopupMenuActions(context, item), + ), + ), + ), + ], + ), + ], + ), + const Divider(color: Color(0xffD9EBE8), thickness: 0.8), + + // Company + Vehicle Reg No + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text("Company", style: _cardheaderStyle), + Text( + item['insurer_name'] ?? '-', + style: _cardBodyStyle, + maxLines: 3, + softWrap: true, + ), + ], + ), + ), + SizedBox(width: 5), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text("Status", style: _cardheaderStyle), + Text( + item['status'] ?? '-', + style: _cardBodyStyle, + maxLines: 2, + softWrap: true, + ), + ], + ), + ), + ], + ), + const SizedBox(height: 15), + + // Created On + Remarks + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text("Received Date & Time", style: _cardheaderStyle), + Text( + _formatDate(item['created_on']) ?? '-', + style: _cardBodyStyle, + ), + ], + ), + ), + SizedBox(width: 5), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text("Remarks", style: _cardheaderStyle), + Text( + item['remarks'] ?? '-', + style: _cardBodyStyle, + maxLines: 3, + softWrap: true, + ), + ], + ), + ), + ], + ), + ], + ), + ); + } + + static final _dataBold = TextStyle( + fontSize: 14, + + fontWeight: FontWeight.w400, + color: Color(0xFF000000), + ); + + static final _dataSub = TextStyle( + fontSize: 10, + fontWeight: FontWeight.w300, + color: Color(0xFF585757), + ); + + static const _headerStyle = TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + ); + static const _cardheaderStyle = TextStyle( + color: Colors.black, + fontWeight: FontWeight.w600, + fontSize: 12, + ); + + static const _cardBodyStyle = TextStyle( + color: Color(0xFF545454), + fontWeight: FontWeight.w400, + fontSize: 12, + ); +} diff --git a/lib/presentation/screens/staff/quotations/quotation.dart b/lib/presentation/screens/staff/quotations/quotation.dart new file mode 100644 index 0000000..d80161f --- /dev/null +++ b/lib/presentation/screens/staff/quotations/quotation.dart @@ -0,0 +1,855 @@ +import 'dart:io' as html; + +import 'package:dropdown_search/dropdown_search.dart'; +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 '../../../../core/routing/routes.dart'; +import '../../../../core/services/api_service.dart'; +import '../../../../data/services/auth_service.dart'; +import '../../../../data/utils/Pagination.dart'; +import '../../../../data/utils/validators.dart'; + +import '../../../layouts/main_layout.dart'; +import '../../../layouts/responsive_layout.dart'; +import '../../../providers/manager_provider.dart'; +import '../../../themes/indicators/customizd_file_upload.dart'; +import '../../../themes/indicators/text_field_theme.dart'; + + + +class QuotationScreen extends ConsumerStatefulWidget { + const QuotationScreen({super.key}); + @override + ConsumerState createState() => QuotationScreenState(); +} + +class QuotationScreenState extends ConsumerState { + int currentPage = 0; + int itemsPerPage = 10; + + List> dataVal = []; + + final TextEditingController _searchController = TextEditingController(); + + late ApiService apiService; + final _formKey = GlobalKey(); + final GlobalKey>> dropDownKey = + GlobalKey>>(); + + List tabHeader = [ + 'name', + 'email', + 'mobile', + 'code', + 'address', + 'regNo', + ]; + late String isActive = "1"; + html.File? docUploadedFile; + + // PlatformFile? passportFile; + String? selectedFileNames; + String? passportFileUrlFromApi; + String? selectedId; + bool isLoading = false; + bool isquotation = false; + + Map controllers = {}; + String? _token; + dynamic userId; + dynamic managerId; + + List> getVehicleTypeData = []; + List> filteredVechicleData = []; + + List> getInsurersData = []; + List> filteredInsurersData = []; + + Map dataDetails() { + final data = { + "name": controllers["name"]?.text, + "email": controllers["email"]?.text, + "mobile": controllers["mobile"]?.text, + "address": controllers["address"]?.text, + "agent_code": controllers["code"]?.text, + "is_active": isActive, + "manager_id": managerId, + }; + return data; + } + + List> getQuotationData = []; + List> originalData = []; + List> filteredData = []; + // bool isLoading = false; + + @override + void initState() { + super.initState(); + apiService = ApiService(); + + for (String field in tabHeader) { + controllers[field] = TextEditingController(); + } + // updateData(); + _initializeToken(); + Future.microtask(() { + managerId = ref.watch(managerIdProvider); + userId = ref.watch(userIdProvider); + + getQuotationList(managerId); + }); + } + + Future _initializeToken() async { + _token = await AuthService.getToken(); + print("APISERTOKEN - $_token"); + } + + Future getQuotationList(int managerId) async { + print('getClaimList called MagId - $managerId'); + setState(() { + isLoading = true; + }); + + try { + final response = await apiService.fetchQuotationList(managerId); + + if (response['status'] == 'success') { + print('quoationListData - ${response['data']}'); + setState(() { + getQuotationData = List>.from(response['data']); + originalData = getQuotationData; + filteredData = List.from(originalData); + // print('originalData - $getClaimPolicies'); + }); + } else { + getQuotationData = []; + originalData = []; + } + } catch (e) { + print('Exception occurred: $e'); + } finally { + setState(() { + isLoading = false; + }); + } + } + + @override + Widget build(BuildContext context) { + return + MainLayout( + title: 'quotation', + body: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + children: [ + + Container( + height: 30, + 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), + ), + Text( + "Quotation", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ), + + SizedBox(height: 10), + + //1ST SECTION + Container( + decoration: BoxDecoration( + color: const Color(0xFFEDF6F5), + borderRadius: BorderRadius.circular(10), + ), + padding: const EdgeInsets.all(20), + child: LayoutBuilder( + builder: (context, constraints) { + final isMobile = constraints.maxWidth < 600; // breakpoint + + if (isMobile) { + // 📱 MOBILE → Column layout + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + registernumber(context), + const SizedBox(height: 16), + insurer(context), + const SizedBox(height: 16), + Wrap( + spacing: 12, + runSpacing: 8, + children: [ + _downloadButton("Download RC"), + _downloadButton("Download ID Proof"), + _downloadButton("Download Previous Policy"), + ], + ), + ], + ); + } else { + // 💻 WEB → Row layout + return Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded(flex: 2, child: registernumber(context)), + const SizedBox(width: 20), + Expanded(flex: 2, child: insurer(context)), + const SizedBox(width: 20), + _downloadButton("Download RC"), + const SizedBox(width: 20), + _downloadButton("Download ID Proof"), + const SizedBox(width: 20), + _downloadButton("Download Previous Policy"), + ], + ); + } + }, + ), + ), + + + const SizedBox(height: 20), + + //2ND SECTION + Container( + // color: Colors.green, + decoration: BoxDecoration( + color: Color(0xffEDF6F5), + borderRadius: BorderRadius.circular(10.0), + ), + width: MediaQuery.of(context).size.width, + // height: MediaQuery.of(context).size.height * 0.8, + padding: EdgeInsets.all(26.0), + child: Column( + children: [ + + + SingleChildScrollView(child: buildFormFields(context)), + + const SizedBox(height: 20), + + //confirm button + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + // GestureDetector( + // onTap: () { + // // handleSave(); + // }, + // child: Container( + // padding: EdgeInsets.symmetric( + // horizontal: 45.0, + // vertical: 8, + // ), + // + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(8.0), + // color: Color(0xFF425B5B), + // ), + // child: Text( + // 'Reject', + // style: TextStyle(color: Colors.white), + // ), + // ), + // ), + + //confirm button + GestureDetector( + onTap: () { + // handleSave(); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 45.0, + vertical: 8, + ), + + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8.0), + color: Color(0xFF425B5B), + ), + child: Text( + 'Confirm', + style: TextStyle(color: Colors.white), + ), + ), + ), + ], + ), + ], + ), + ), + + const SizedBox(height: 20), + + //3RD SECTION (TABLE) + Container( + // color: Colors.green, + decoration: BoxDecoration( + color: Color(0xFFEDF6F5), + borderRadius: BorderRadius.circular(10.0), + ), + width: MediaQuery.of(context).size.width, + // height: MediaQuery.of(context).size.height * 0.8, + padding: EdgeInsets.all(16.0), + child: Column( + children: [ + // Text('datta') + _buildDataTable(context), + ], + ), + ), + + + ], + ), + ), + ), + ); + } + + Widget _readonlyField(String label, String value) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, style: GoogleFonts.inter(fontSize: 13, fontWeight: FontWeight.w600)), + const SizedBox(height: 6), + Container( + padding: const EdgeInsets.symmetric(horizontal: 60, vertical: 14), + decoration: BoxDecoration( + color: Colors.red, + borderRadius: BorderRadius.circular(6), + border: Border.all(color: Colors.grey.shade300), + ), + child: Text(value, style: GoogleFonts.inter(fontSize: 14)), + ), + ], + ); + } + + Widget _downloadButton(String label) { + return ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF425B5B), + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)), + ), + onPressed: () { + // TODO: file download logic + }, + icon: const Icon(Icons.download, size: 18), + label: Text(label, style: GoogleFonts.inter(fontSize: 13)), + ); + } + + Widget buildFormFields(BuildContext context) { + return Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // _buildResponsiveRow( + // context, + // buildName(context), + // buildInsusrer(context), + // ), + if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), + + _buildResponsiveRow( + context, + buildIdv(context), + buildPremiumAmnt(context), + ), + if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), + + _buildResponsiveRow( + context, + buildPlanType(context), + buildDocuments(context), + ), + + // if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10), + // _buildResponsiveRow( + // context, + // buildAdditonalDocuments(context), + // buildRemarks(context), + // ), + ], + ), + ); + } + + Widget _buildResponsiveRow( + BuildContext context, + Widget first, + Widget second, + ) + { + if (ResponsiveLayout.isMobile(context)) { + // Stack vertically + return Column(children: [first, const SizedBox(height: 2), second]); + } else { + // Place side by side + return Row( + children: [ + Expanded(child: first), + const SizedBox(width: 25), + Expanded(child: second), + ], + ); + } + } + + + + Widget registernumber(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Register Number',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + readOnly:true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget insurer(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Insurer',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + readOnly:true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget buildIdv(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('IDV',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + readOnly:true, + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget buildPremiumAmnt(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Premium Amount',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget buildPlanType(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Plan Type',style:_textStyle ,), + SizedBox(height: 10,), + ThemedFormField( + controller: controllers['mobile']!, + validator: (value) => Validators.phone(value, "phNumber"), + txtwidth: ResponsiveLayout.isMobile(context) + ? null + : MediaQuery.of(context).size.width * 0.26, + ), + ] + ); + } + Widget buildDocuments(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Quotation Documents ', + style: _textStyle, + ), + const SizedBox(height: 10), + buildResponsiveUploadField( + hintText: selectedFileNames, + onFileSelected: (fileName, file) { + print("File picked: $fileName"); + setState(() { + docUploadedFile = file; + }); + }, + ), + ], + ); + } + + + + + + + Widget buildResponsiveUploadField({ + String? label, // 🔹 make optional + required String? hintText, + required void Function(String fileName, dynamic file) onFileSelected, + }) { + final isMobile = ResponsiveLayout.isMobile(context); + + final uploadWidget = ThemedUploadField( + hintText: hintText ?? "Upload Documents", + txtwidth: isMobile ? null : MediaQuery.of(context).size.width * 0.26, + onFileSelected: onFileSelected, + ); + + if (isMobile) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (label != null && label.isNotEmpty) ...[ // ✅ only render if label is given + Text(label, style: _textStyle), + const SizedBox(height: 8), + ], + uploadWidget, + const SizedBox(height: 16), + ], + ); + } else { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (label != null && label.isNotEmpty) ...[ + Expanded(child: Text(label, style: _textStyle)), + const SizedBox(width: 10), + ], + uploadWidget, + ], + ); + } + } + + + + + + 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: "Registration 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) + ? _buildDataRow(item, sno) + : _buildDataCard(item, sno); + }, + ), + ], + ), + ); + } + + Widget _buildHeader() { + return Container( + decoration: BoxDecoration( + color: Color(0xFFEDF6F5), + borderRadius: BorderRadius.circular(6), + ), + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), + child: const Row( + children: [ + // Expanded(flex: 3, child: Text(' ', style: _headerStyle)), + Expanded( + flex: 3, + child: Text('Registration Number', style: _headerStyle), + ), + Expanded(flex: 3, child: Text('Insurer', style: _headerStyle)), + Expanded(flex: 3, child: Text('IDV', style: _headerStyle)), + Expanded(flex: 3, child: Text('Plan Type', style: _headerStyle)), + Expanded(flex: 3, child: Text('Premium Amount', style: _headerStyle)), + // Expanded(flex: 1, child: Text('Status', 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: [ + // ✅ Single-select checkbox + // Expanded( + // flex: 1, + // child: Checkbox( + // value: selectedId == item['id'], // only selected row is checked + // onChanged: (val) { + // setState(() { + // if (val == true) { + // selectedId = item['id']; // select this row + // isquotation = true; + // } else { + // selectedId = null; + // isquotation = false; // unselect + // } + // }); + // print("Selected row id: $selectedId"); + // }, + // ), + // ), + + Expanded(flex: 2, child: Text(item['id'] ?? '-', style: _dataBold)), + Expanded( + flex: 2, + child: Text(item['email'] ?? '-', style: _dataBold), + ), + Expanded( + flex: 2, + child: Text(item['mobile'] ?? '-', style: _dataBold), + ), + Expanded( + flex: 2, + child: Text(item['premium_amount'] ?? '-', style: _dataBold), + ), + Expanded( + flex: 2, + child: Text( + item['premium_amount'] ?? '-', + style: _dataBold, + ), + ), + // Expanded( + // flex: 1, + // child: Text( + // item['status'] ?? '-', + // style: TextStyle( + // fontSize: 14, + // + // fontWeight: FontWeight.w400, + // color: item['status'] == 'Accepted' ? Colors.green : Colors.red, + // ), + // ), + // ), + ], + ), + ); + } + + 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(0xFFF6FEFD), + borderRadius: BorderRadius.circular(8.0), + border: Border.all(color: const Color(0xffD9EBE8)), + ), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Company + Vehicle Reg No + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text("New India", style: _cardBodyStyle), + const Text("TN64V3456", style: _cardheaderStyle), + const Text("Status: Rejected", style: _cardBodyStyle), + ], + ), + ), + SizedBox(width: 5), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text("Comprehensive", style: _cardBodyStyle), + const Text("IDV:₹145000", style: _cardBodyStyle), + const Text("₹1000", style: _cardheaderStyle), + ], + ), + ), + ], + ), + ], + ), + ), + ], + ), + ); + } + + static final _dataBold = TextStyle( + fontSize: 14, + + fontWeight: FontWeight.w400, + color: Color(0xFF000000), + ); + + static final _dataSub = TextStyle( + fontSize: 10, + fontWeight: FontWeight.w300, + color: Color(0xFF585757), + ); + + static const _headerStyle = TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + ); + + static const _textStyle = TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + ); + + static const _cardheaderStyle = TextStyle( + color: Colors.black, + fontWeight: FontWeight.w600, + fontSize: 12, + ); + + static const _cardBodyStyle = TextStyle( + color: Color(0xFF545454), + fontWeight: FontWeight.w400, + fontSize: 12, + ); +} diff --git a/lib/presentation/widgets/drawer_menu.dart b/lib/presentation/widgets/drawer_menu.dart index 219e6b5..277f98b 100644 --- a/lib/presentation/widgets/drawer_menu.dart +++ b/lib/presentation/widgets/drawer_menu.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/routing/routes.dart'; import 'package:go_router/go_router.dart'; +import '../providers/manager_provider.dart'; import '../providers/userRoleProvider.dart'; import 'drawerContentWrapper.dart'; @@ -70,6 +71,19 @@ class DrawerMenuState extends ConsumerState { ], if (key == 'Reports') ...[ + GestureDetector( + onTap: () { + context.go(AppRoutes.claimlist); + }, + child: const Text( + "Claims", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + ), + ), + ), + const SizedBox(height: 5), GestureDetector( onTap: () { context.go(AppRoutes.enquiryLst); @@ -85,10 +99,10 @@ class DrawerMenuState extends ConsumerState { const SizedBox(height: 5), GestureDetector( onTap: () { - print("Bf clicked"); + context.go(AppRoutes.endosement); }, child: const Text( - "Claims", + "Endorsement", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, @@ -98,10 +112,39 @@ class DrawerMenuState extends ConsumerState { const SizedBox(height: 5), GestureDetector( onTap: () { - print("Bf clicked"); + context.go(AppRoutes.policylist); }, child: const Text( - "Endorsement", + "Policy", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + ), + ), + ), + + const SizedBox(height: 5), + + GestureDetector( + onTap: () { + context.go(AppRoutes.quotation); + }, + child: const Text( + "Quotation", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + ), + ), + ), + + const SizedBox(height: 5), + GestureDetector( + onTap: () { + context.go(AppRoutes.policy); + }, + child: const Text( + "Policy Form", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w400, @@ -172,13 +215,31 @@ class DrawerMenuState extends ConsumerState { }, ), DrawerLabel("Reports"), - + // DrawerContentWrapper( + // child: IconButton( + // onPressed: () { + // // context.go('/tabEnquiry/tab'); + // ref.read(enquiryIdProvider.notifier).state = 'tab'; + // context.go(AppRoutes.tabEnquiry); + // }, + // icon: Icon(Icons.list_alt_rounded, size: 30, color: Colors.black), + // ), + // ), DrawerContentWrapper( - child: IconButton( - onPressed: () { - context.go(AppRoutes.tabEnquiry); + child: Consumer( + builder: (context, ref, _) { + return IconButton( + onPressed: () { + ref.read(enquiryIdProvider.notifier).state = null; + context.go(AppRoutes.tabEnquiry); + }, + icon: const Icon( + Icons.list_alt_rounded, + size: 30, + color: Colors.black, + ), + ); }, - icon: Icon(Icons.list_alt_rounded, size: 30, color: Colors.black), ), ), diff --git a/pubspec.lock b/pubspec.lock index f398908..7ae7a0d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -692,26 +692,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" url: "https://pub.dev" source: hosted - version: "11.0.2" + version: "10.0.9" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 url: "https://pub.dev" source: hosted - version: "3.0.10" + version: "3.0.9" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.1" lints: dependency: transitive description: @@ -732,10 +732,10 @@ packages: dependency: transitive description: name: local_auth_android - sha256: "1ee0e63fb8b5c6fa286796b5fb1570d256857c2f4a262127e728b36b80a570cf" + sha256: "48924f4a8b3cc45994ad5993e2e232d3b00788a305c1bf1c7db32cef281ce9a3" url: "https://pub.dev" source: hosted - version: "1.0.53" + version: "1.0.52" local_auth_darwin: dependency: transitive description: @@ -1217,10 +1217,10 @@ packages: dependency: transitive description: name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.6" + version: "0.7.4" toastification: dependency: "direct main" description: @@ -1273,10 +1273,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "07cffecb7d68cbc6437cd803d5f11a86fe06736735c3dfe46ff73bcb0f958eed" + sha256: "81777b08c498a292d93ff2feead633174c386291e35612f8da438d6e92c4447e" url: "https://pub.dev" source: hosted - version: "6.3.21" + version: "6.3.20" url_launcher_ios: dependency: transitive description: @@ -1337,18 +1337,18 @@ packages: dependency: transitive description: name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.1.4" vm_service: dependency: transitive description: name: vm_service - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 url: "https://pub.dev" source: hosted - version: "15.0.2" + version: "15.0.0" watcher: dependency: transitive description: @@ -1414,5 +1414,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.9.0 <4.0.0" - flutter: ">=3.35.0" + dart: ">=3.8.1 <4.0.0" + flutter: ">=3.32.0"