diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 81eb5ec..55610e2 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":"file_selector_ios","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_selector_ios-0.5.3+2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_pdfview","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_pdfview-1.4.3\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"image_picker_ios","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_picker_ios-0.8.13\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\package_info_plus-9.0.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.4.2\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"permission_handler_apple","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_apple-9.4.7\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"pusher_channels_flutter","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\pusher_channels_flutter-2.5.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-10.1.4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\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":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_ios-6.3.4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"video_player_avfoundation","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\video_player_avfoundation-2.8.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"wakelock_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\wakelock_plus-1.4.0\\\\","native_build":true,"dependencies":["package_info_plus"],"dev_dependency":false}],"android":[{"name":"file_selector_android","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_selector_android-0.5.1+17\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_pdfview","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_pdfview-1.4.3\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_plugin_android_lifecycle","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_plugin_android_lifecycle-2.0.31\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"image_picker_android","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_picker_android-0.8.13+1\\\\","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"package_info_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\package_info_plus-9.0.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.2.19\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"permission_handler_android","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_android-12.1.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"pusher_channels_flutter","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\pusher_channels_flutter-2.5.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-10.1.4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_android-2.4.13\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_android","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_android-6.3.20\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"video_player_android","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\video_player_android-2.8.15\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"wakelock_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\wakelock_plus-1.4.0\\\\","native_build":true,"dependencies":["package_info_plus"],"dev_dependency":false}],"macos":[{"name":"file_selector_macos","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_selector_macos-0.9.4+4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"image_picker_macos","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_picker_macos-0.2.2\\\\","native_build":false,"dependencies":["file_selector_macos"],"dev_dependency":false},{"name":"package_info_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\package_info_plus-9.0.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.4.2\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-10.1.4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\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":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_macos-3.2.3\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"video_player_avfoundation","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\video_player_avfoundation-2.8.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"wakelock_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\wakelock_plus-1.4.0\\\\","native_build":true,"dependencies":["package_info_plus"],"dev_dependency":false}],"linux":[{"name":"file_selector_linux","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_selector_linux-0.9.4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"image_picker_linux","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_picker_linux-0.2.2\\\\","native_build":false,"dependencies":["file_selector_linux"],"dev_dependency":false},{"name":"package_info_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\package_info_plus-9.0.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.2.1\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-10.1.4\\\\","native_build":false,"dependencies":["url_launcher_linux"],"dev_dependency":false},{"name":"shared_preferences_linux","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\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":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_linux-3.2.2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"wakelock_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\wakelock_plus-1.4.0\\\\","native_build":false,"dependencies":["package_info_plus"],"dev_dependency":false}],"windows":[{"name":"file_selector_windows","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_selector_windows-0.9.3+5\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"image_picker_windows","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_picker_windows-0.2.2\\\\","native_build":false,"dependencies":["file_selector_windows"],"dev_dependency":false},{"name":"package_info_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\package_info_plus-9.0.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.3.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"permission_handler_windows","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_windows-0.2.1\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-10.1.4\\\\","native_build":true,"dependencies":["url_launcher_windows"],"dev_dependency":false},{"name":"shared_preferences_windows","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\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":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_windows-3.1.5\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"wakelock_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\wakelock_plus-1.4.0\\\\","native_build":false,"dependencies":["package_info_plus"],"dev_dependency":false}],"web":[{"name":"file_selector_web","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_selector_web-0.9.4+2\\\\","dependencies":[],"dev_dependency":false},{"name":"image_picker_for_web","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_picker_for_web-3.1.1\\\\","dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\package_info_plus-9.0.0\\\\","dependencies":[],"dev_dependency":false},{"name":"permission_handler_html","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_html-0.1.3+5\\\\","dependencies":[],"dev_dependency":false},{"name":"pusher_channels_flutter","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\pusher_channels_flutter-2.5.0\\\\","dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-10.1.4\\\\","dependencies":["url_launcher_web"],"dev_dependency":false},{"name":"shared_preferences_web","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_web-2.4.3\\\\","dependencies":[],"dev_dependency":false},{"name":"url_launcher_web","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_web-2.4.1\\\\","dependencies":[],"dev_dependency":false},{"name":"video_player_web","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\video_player_web-2.4.0\\\\","dependencies":[],"dev_dependency":false},{"name":"wakelock_plus","path":"C:\\\\Users\\\\malia\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\wakelock_plus-1.4.0\\\\","dependencies":["package_info_plus"],"dev_dependency":false}]},"dependencyGraph":[{"name":"file_selector","dependencies":["file_selector_android","file_selector_ios","file_selector_linux","file_selector_macos","file_selector_web","file_selector_windows"]},{"name":"file_selector_android","dependencies":[]},{"name":"file_selector_ios","dependencies":[]},{"name":"file_selector_linux","dependencies":[]},{"name":"file_selector_macos","dependencies":[]},{"name":"file_selector_web","dependencies":[]},{"name":"file_selector_windows","dependencies":[]},{"name":"flutter_pdfview","dependencies":[]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"image_picker","dependencies":["image_picker_android","image_picker_for_web","image_picker_ios","image_picker_linux","image_picker_macos","image_picker_windows"]},{"name":"image_picker_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"image_picker_for_web","dependencies":[]},{"name":"image_picker_ios","dependencies":[]},{"name":"image_picker_linux","dependencies":["file_selector_linux"]},{"name":"image_picker_macos","dependencies":["file_selector_macos"]},{"name":"image_picker_windows","dependencies":["file_selector_windows"]},{"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":"permission_handler","dependencies":["permission_handler_android","permission_handler_apple","permission_handler_html","permission_handler_windows"]},{"name":"permission_handler_android","dependencies":[]},{"name":"permission_handler_apple","dependencies":[]},{"name":"permission_handler_html","dependencies":[]},{"name":"permission_handler_windows","dependencies":[]},{"name":"pusher_channels_flutter","dependencies":[]},{"name":"share_plus","dependencies":["url_launcher_web","url_launcher_windows","url_launcher_linux"]},{"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":[]},{"name":"video_player","dependencies":["video_player_android","video_player_avfoundation","video_player_web"]},{"name":"video_player_android","dependencies":[]},{"name":"video_player_avfoundation","dependencies":[]},{"name":"video_player_web","dependencies":[]},{"name":"wakelock_plus","dependencies":["package_info_plus"]}],"date_created":"2025-12-19 09:47:09.643670","version":"3.32.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":"file_selector_ios","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_selector_ios-0.5.3+2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_pdfview","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_pdfview-1.4.3\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"image_picker_ios","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_picker_ios-0.8.13\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\package_info_plus-9.0.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.4.2\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"permission_handler_apple","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_apple-9.4.7\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"pusher_channels_flutter","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\pusher_channels_flutter-2.5.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-10.1.4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\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":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_ios-6.3.4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"video_player_avfoundation","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\video_player_avfoundation-2.8.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"wakelock_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\wakelock_plus-1.4.0\\\\","native_build":true,"dependencies":["package_info_plus"],"dev_dependency":false}],"android":[{"name":"file_selector_android","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_selector_android-0.5.1+17\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_pdfview","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_pdfview-1.4.3\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_plugin_android_lifecycle","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_plugin_android_lifecycle-2.0.31\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"image_picker_android","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_picker_android-0.8.13+1\\\\","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"package_info_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\package_info_plus-9.0.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.2.19\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"permission_handler_android","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_android-12.1.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"pusher_channels_flutter","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\pusher_channels_flutter-2.5.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-10.1.4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_android-2.4.13\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_android","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_android-6.3.20\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"video_player_android","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\video_player_android-2.8.15\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"wakelock_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\wakelock_plus-1.4.0\\\\","native_build":true,"dependencies":["package_info_plus"],"dev_dependency":false}],"macos":[{"name":"file_selector_macos","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_selector_macos-0.9.4+4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"image_picker_macos","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_picker_macos-0.2.2\\\\","native_build":false,"dependencies":["file_selector_macos"],"dev_dependency":false},{"name":"package_info_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\package_info_plus-9.0.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.4.2\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-10.1.4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\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":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_macos-3.2.3\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"video_player_avfoundation","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\video_player_avfoundation-2.8.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"wakelock_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\wakelock_plus-1.4.0\\\\","native_build":true,"dependencies":["package_info_plus"],"dev_dependency":false}],"linux":[{"name":"file_selector_linux","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_selector_linux-0.9.4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"image_picker_linux","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_picker_linux-0.2.2\\\\","native_build":false,"dependencies":["file_selector_linux"],"dev_dependency":false},{"name":"package_info_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\package_info_plus-9.0.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.2.1\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-10.1.4\\\\","native_build":false,"dependencies":["url_launcher_linux"],"dev_dependency":false},{"name":"shared_preferences_linux","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\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":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_linux-3.2.2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"wakelock_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\wakelock_plus-1.4.0\\\\","native_build":false,"dependencies":["package_info_plus"],"dev_dependency":false}],"windows":[{"name":"file_selector_windows","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_selector_windows-0.9.3+5\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"image_picker_windows","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_picker_windows-0.2.2\\\\","native_build":false,"dependencies":["file_selector_windows"],"dev_dependency":false},{"name":"package_info_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\package_info_plus-9.0.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.3.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"permission_handler_windows","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_windows-0.2.1\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-10.1.4\\\\","native_build":true,"dependencies":["url_launcher_windows"],"dev_dependency":false},{"name":"shared_preferences_windows","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\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":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_windows-3.1.5\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"wakelock_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\wakelock_plus-1.4.0\\\\","native_build":false,"dependencies":["package_info_plus"],"dev_dependency":false}],"web":[{"name":"file_selector_web","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_selector_web-0.9.4+2\\\\","dependencies":[],"dev_dependency":false},{"name":"image_picker_for_web","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_picker_for_web-3.1.1\\\\","dependencies":[],"dev_dependency":false},{"name":"package_info_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\package_info_plus-9.0.0\\\\","dependencies":[],"dev_dependency":false},{"name":"permission_handler_html","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_html-0.1.3+5\\\\","dependencies":[],"dev_dependency":false},{"name":"pusher_channels_flutter","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\pusher_channels_flutter-2.5.0\\\\","dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-10.1.4\\\\","dependencies":["url_launcher_web"],"dev_dependency":false},{"name":"shared_preferences_web","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_web-2.4.3\\\\","dependencies":[],"dev_dependency":false},{"name":"url_launcher_web","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_web-2.4.1\\\\","dependencies":[],"dev_dependency":false},{"name":"video_player_web","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\video_player_web-2.4.0\\\\","dependencies":[],"dev_dependency":false},{"name":"wakelock_plus","path":"C:\\\\Users\\\\Divya\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\wakelock_plus-1.4.0\\\\","dependencies":["package_info_plus"],"dev_dependency":false}]},"dependencyGraph":[{"name":"file_selector","dependencies":["file_selector_android","file_selector_ios","file_selector_linux","file_selector_macos","file_selector_web","file_selector_windows"]},{"name":"file_selector_android","dependencies":[]},{"name":"file_selector_ios","dependencies":[]},{"name":"file_selector_linux","dependencies":[]},{"name":"file_selector_macos","dependencies":[]},{"name":"file_selector_web","dependencies":[]},{"name":"file_selector_windows","dependencies":[]},{"name":"flutter_pdfview","dependencies":[]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"image_picker","dependencies":["image_picker_android","image_picker_for_web","image_picker_ios","image_picker_linux","image_picker_macos","image_picker_windows"]},{"name":"image_picker_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"image_picker_for_web","dependencies":[]},{"name":"image_picker_ios","dependencies":[]},{"name":"image_picker_linux","dependencies":["file_selector_linux"]},{"name":"image_picker_macos","dependencies":["file_selector_macos"]},{"name":"image_picker_windows","dependencies":["file_selector_windows"]},{"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":"permission_handler","dependencies":["permission_handler_android","permission_handler_apple","permission_handler_html","permission_handler_windows"]},{"name":"permission_handler_android","dependencies":[]},{"name":"permission_handler_apple","dependencies":[]},{"name":"permission_handler_html","dependencies":[]},{"name":"permission_handler_windows","dependencies":[]},{"name":"pusher_channels_flutter","dependencies":[]},{"name":"share_plus","dependencies":["url_launcher_web","url_launcher_windows","url_launcher_linux"]},{"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":[]},{"name":"video_player","dependencies":["video_player_android","video_player_avfoundation","video_player_web"]},{"name":"video_player_android","dependencies":[]},{"name":"video_player_avfoundation","dependencies":[]},{"name":"video_player_web","dependencies":[]},{"name":"wakelock_plus","dependencies":["package_info_plus"]}],"date_created":"2025-12-20 16:53:58.746464","version":"3.38.3","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file diff --git a/lib/config/api_config.dart b/lib/config/api_config.dart index b6a86a1..224bfbf 100644 --- a/lib/config/api_config.dart +++ b/lib/config/api_config.dart @@ -1,4 +1,4 @@ class ApiConfig { - static const String baseUrl = "http://10.119.0.74:8000/api"; - static const String fileBaseUrl = "http://10.119.0.74:8000/"; + static const String baseUrl = "http://192.168.0.105:8000/api"; + static const String fileBaseUrl = "http://192.168.0.105:8000/"; } diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart index 0b526d4..8f1f72a 100644 --- a/lib/config/app_config.dart +++ b/lib/config/app_config.dart @@ -6,7 +6,7 @@ class AppConfig { static const String logoUrlEmulator = "http://10.0.2.2:8000/images/kent_logo2.png"; // For Physical Device (Replace with your actual PC local IP) - static const String logoUrlDevice = "http://10.119.0.74:8000/images/kent_logo2.png"; + static const String logoUrlDevice = "http://192.168.0.105:8000/images/kent_logo2.png"; // Which one to use? static const String logoUrl = logoUrlDevice; // CHANGE THIS WHEN TESTING ON REAL DEVICE diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart index 88c52d2..f28710f 100644 --- a/lib/screens/chat_screen.dart +++ b/lib/screens/chat_screen.dart @@ -1,18 +1,14 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'dart:io'; +import 'package:file_selector/file_selector.dart'; import '../services/chat_service.dart'; import '../services/reverb_socket_service.dart'; import '../services/dio_client.dart'; import '../providers/chat_unread_provider.dart'; -import 'package:url_launcher/url_launcher.dart'; -import 'dart:io'; -import 'package:file_selector/file_selector.dart'; -import 'chat_file_viewer.dart'; import '../widgets/chat_file_preview.dart'; - - - +import 'chat_file_viewer.dart'; class ChatScreen extends StatefulWidget { const ChatScreen({super.key}); @@ -24,6 +20,7 @@ class ChatScreen extends StatefulWidget { class _ChatScreenState extends State { final TextEditingController _messageCtrl = TextEditingController(); final ScrollController _scrollCtrl = ScrollController(); + Map? uploadingMessage; late ChatService _chatService; @@ -33,22 +30,18 @@ class _ChatScreenState extends State { List> messages = []; bool isLoading = true; - // ============================ - // INIT STATE - // ============================ @override void initState() { super.initState(); - _chatService = ChatService(DioClient.getInstance(context)); - // 🔔 Mark chat as OPEN (important) WidgetsBinding.instance.addPostFrameCallback((_) { context.read().setChatOpen(true); }); _initChat(); } + String _guessMimeType(String path) { final lower = path.toLowerCase(); if (lower.endsWith('.jpg') || lower.endsWith('.png')) return 'image/*'; @@ -63,7 +56,6 @@ class _ChatScreenState extends State { final file = File(picked.path); - // 1️⃣ Show uploading UI setState(() { uploadingMessage = { 'local_file': file, @@ -72,44 +64,26 @@ class _ChatScreenState extends State { }; }); - // 2️⃣ Upload (NO adding message) await _chatService.sendFile( ticketId!, file, onProgress: (progress) { if (!mounted) return; - setState(() { - uploadingMessage!['progress'] = progress; - }); + setState(() => uploadingMessage!['progress'] = progress); }, ); - // 3️⃣ Remove sending bubble ONLY if (!mounted) return; - setState(() { - uploadingMessage = null; - }); - - // 🚫 DO NOT add message here - // WebSocket will handle it + setState(() => uploadingMessage = null); } - - - - // ============================ - // INIT CHAT - // ============================ Future _initChat() async { - // 1️⃣ Start chat final ticketRes = await _chatService.startChat(); ticketId = ticketRes['ticket']['id']; - // 2️⃣ Load messages final msgs = await _chatService.getMessages(ticketId!); messages = List>.from(msgs); - // 3️⃣ Realtime socket await _socket.connect( context: context, ticketId: ticketId!, @@ -117,20 +91,12 @@ class _ChatScreenState extends State { final incomingClientId = msg['client_id']; setState(() { - // 🧹 Remove local temp message with same client_id - messages.removeWhere( - (m) => m['client_id'] != null && - m['client_id'] == incomingClientId, - ); - - // ✅ Add confirmed socket message + messages.removeWhere((m) => m['client_id'] == incomingClientId); messages.add(msg); }); _scrollToBottom(); }, - - onAdminMessage: () { if (!mounted) { context.read().increment(); @@ -138,37 +104,30 @@ class _ChatScreenState extends State { }, ); - - - if (!mounted) return; setState(() => isLoading = false); _scrollToBottom(); } - // ============================ - // SCROLL - // ============================ void _scrollToBottom() { WidgetsBinding.instance.addPostFrameCallback((_) { if (_scrollCtrl.hasClients) { - _scrollCtrl.jumpTo(_scrollCtrl.position.maxScrollExtent); + _scrollCtrl.animateTo( + _scrollCtrl.position.maxScrollExtent, + duration: const Duration(milliseconds: 250), + curve: Curves.easeOut, + ); } }); } - // ============================ - // SEND MESSAGE - // ============================ Future _sendMessage() async { final text = _messageCtrl.text.trim(); if (text.isEmpty || ticketId == null) return; _messageCtrl.clear(); - final clientId = DateTime.now().millisecondsSinceEpoch.toString(); - // 1️⃣ ADD LOCAL MESSAGE IMMEDIATELY setState(() { messages.add({ 'client_id': clientId, @@ -182,7 +141,6 @@ class _ChatScreenState extends State { _scrollToBottom(); - // 2️⃣ SEND TO SERVER await _chatService.sendMessage( ticketId!, message: text, @@ -190,28 +148,68 @@ class _ChatScreenState extends State { ); } - - // ============================ - // DISPOSE - // ============================ @override void dispose() { - // 🔕 Mark chat CLOSED context.read().setChatOpen(false); - _socket.disconnect(); _messageCtrl.dispose(); _scrollCtrl.dispose(); super.dispose(); } - // ============================ - // UI - // ============================ @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text("Support Chat")), + appBar: PreferredSize( + preferredSize: const Size.fromHeight(56), + child: AnimatedContainer( + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + decoration: const BoxDecoration( + gradient: LinearGradient( + colors: [ + Color(0xFF2196F3), + Color(0xFF1565C0), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + boxShadow: [ + BoxShadow( + color: Colors.black26, + blurRadius: 10, + offset: Offset(0, 3), + ), + ], + ), + child: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leading: Padding( + padding: const EdgeInsets.only(left: 12), + child: CircleAvatar( + radius: 18, + backgroundColor: Colors.white, + child: Icon( + Icons.support_agent, + color: Colors.blue, + size: 20, + ), + ), + ), + title: const Text( + "Support Chat", + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.w600, + fontSize: 18, + ), + ), + centerTitle: false, + iconTheme: const IconThemeData(color: Colors.white), + ), + ), + ), body: isLoading ? const Center(child: CircularProgressIndicator()) : Column( @@ -223,100 +221,54 @@ class _ChatScreenState extends State { ); } - - // Future _openUrl(String url) async { - // final uri = Uri.parse(url); - // - // if (await canLaunchUrl(uri)) { - // await launchUrl( - // uri, - // mode: LaunchMode.externalApplication, - // ); - // } else { - // debugPrint("❌ Cannot launch URL: $url"); - // } - // } - - - - Widget _buildMessageContent({ - String? message, - String? filePath, - String? fileType, - required bool isUser, - }) { - final textColor = isUser ? Colors.white : Colors.black; - - if (filePath == null) { - return Text(message ?? '', style: TextStyle(color: textColor)); - } - - final url = "${DioClient.baseUrl}/storage/$filePath"; - - return GestureDetector( - onTap: () { - ChatFileViewer.open( - context, - url: url, - fileType: fileType ?? '', - ); - }, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(_iconForFile(fileType), color: textColor), - const SizedBox(width: 8), - Text( - _labelForFile(fileType), - style: TextStyle(color: textColor), - ), - ], - ), - ); - } - - IconData _iconForFile(String? type) { - if (type == null) return Icons.insert_drive_file; - if (type.startsWith('image/')) return Icons.image; - if (type.startsWith('video/')) return Icons.play_circle_fill; - if (type == 'application/pdf') return Icons.picture_as_pdf; - return Icons.insert_drive_file; - } - - String _labelForFile(String? type) { - if (type == null) return "File"; - if (type.startsWith('image/')) return "Image"; - if (type.startsWith('video/')) return "Video"; - if (type == 'application/pdf') return "PDF"; - return "Download file"; - } - - - - Widget _buildMessages() { return ListView( controller: _scrollCtrl, - padding: const EdgeInsets.all(12), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), children: [ - // EXISTING MESSAGES ...messages.map((msg) { final isUser = msg['sender_type'] == 'App\\Models\\User'; return Align( - alignment: isUser ? Alignment.centerRight : Alignment.centerLeft, + alignment: + isUser ? Alignment.centerRight : Alignment.centerLeft, child: Container( + constraints: const BoxConstraints(maxWidth: 280), margin: const EdgeInsets.symmetric(vertical: 6), - padding: const EdgeInsets.all(10), + padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: isUser ? Colors.blue : Colors.grey.shade300, - borderRadius: BorderRadius.circular(12), + color: isUser ? null : Colors.white, + gradient: isUser + ? LinearGradient( + colors: [ + Colors.lightBlueAccent, + Colors.blue.shade700, + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : null, + borderRadius: BorderRadius.only( + topLeft: const Radius.circular(16), + topRight: const Radius.circular(16), + bottomLeft: + isUser ? const Radius.circular(16) : Radius.zero, + bottomRight: + isUser ? Radius.zero : const Radius.circular(16), + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 6, + ), + ], ), child: msg['file_path'] == null ? Text( msg['message'] ?? '', style: TextStyle( - color: isUser ? Colors.white : Colors.black, + color: isUser ? Colors.white : Colors.blue, + fontSize: 15, ), ) : ChatFilePreview( @@ -327,75 +279,49 @@ class _ChatScreenState extends State { ), ); }), - - // ⏳ UPLOADING MESSAGE - if (uploadingMessage != null) - Align( - alignment: Alignment.centerRight, - child: Container( - margin: const EdgeInsets.symmetric(vertical: 6), - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - color: Colors.blue, - borderRadius: BorderRadius.circular(12), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ChatFilePreview( - filePath: uploadingMessage!['local_file'].path, - fileType: uploadingMessage!['file_type'], - isUser: true, - isLocal: true, - ), - const SizedBox(height: 8), - LinearProgressIndicator( - value: uploadingMessage!['progress'], - backgroundColor: Colors.white24, - valueColor: - const AlwaysStoppedAnimation(Colors.white), - ), - const SizedBox(height: 4), - const Text( - "Sending…", - style: TextStyle( - color: Colors.white, - fontSize: 12, - ), - ), - ], - ), - ), - ), ], ); } - Widget _buildInput() { return SafeArea( - child: Row( - children: [ - IconButton( - icon: const Icon(Icons.attach_file), - onPressed: _pickAndSendFile, - ), - Expanded( - child: TextField( - controller: _messageCtrl, - decoration: const InputDecoration( - hintText: "Type message", - border: InputBorder.none, + child: Padding( + padding: const EdgeInsets.all(8), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(24), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 6, ), - ), + ], ), - IconButton( - icon: const Icon(Icons.send), - onPressed: _sendMessage, + child: Row( + children: [ + IconButton( + icon: const Icon(Icons.attach_file), + onPressed: _pickAndSendFile, + ), + Expanded( + child: TextField( + controller: _messageCtrl, + decoration: const InputDecoration( + hintText: "Type a message…", + border: InputBorder.none, + ), + ), + ), + IconButton( + icon: const Icon(Icons.send, color: Colors.blue), + onPressed: _sendMessage, + ), + ], ), - ], + ), ), ); } - } diff --git a/lib/screens/dashboard_screen.dart b/lib/screens/dashboard_screen.dart index dbb7d47..cc07642 100644 --- a/lib/screens/dashboard_screen.dart +++ b/lib/screens/dashboard_screen.dart @@ -541,7 +541,22 @@ class _DashboardScreenState extends State vertical: 6 * scale, ), decoration: BoxDecoration( - color: Colors.white.withOpacity(.2), + gradient: (m['status'] ?? '') + .toString() + .toLowerCase() == + 'active' + ? const LinearGradient( + colors: [ + Color(0xFF2ECC71), // Green + Color(0xFF16A085), // Teal Green + ], + ) + : const LinearGradient( + colors: [ + Color(0xFFE74C3C), // Red + Color(0xFFC0392B), // Dark Red + ], + ), borderRadius: BorderRadius.circular(8 * scale), ), child: Text( @@ -552,7 +567,7 @@ class _DashboardScreenState extends State fontWeight: FontWeight.bold, ), ), - ), + ) ], ), ); diff --git a/lib/screens/invoice_detail_screen.dart b/lib/screens/invoice_detail_screen.dart index b7d6a53..2122028 100644 --- a/lib/screens/invoice_detail_screen.dart +++ b/lib/screens/invoice_detail_screen.dart @@ -175,4 +175,4 @@ class _InvoiceDetailScreenState extends State { ), ); } -} +} \ No newline at end of file diff --git a/lib/screens/mark_list_screen.dart b/lib/screens/mark_list_screen.dart index 0e92ddd..31a0bb4 100644 --- a/lib/screens/mark_list_screen.dart +++ b/lib/screens/mark_list_screen.dart @@ -24,19 +24,16 @@ class _MarkListScreenState extends State { Widget build(BuildContext context) { final marks = Provider.of(context); - // Responsive scale factor final screenWidth = MediaQuery.of(context).size.width; final scale = (screenWidth / 390).clamp(0.82, 1.35); return Scaffold( backgroundColor: Colors.white, - appBar: AppBar( backgroundColor: Colors.white, elevation: 0, centerTitle: true, iconTheme: const IconThemeData(color: Colors.black), - title: Text( "All Mark Numbers", style: TextStyle( @@ -50,14 +47,31 @@ class _MarkListScreenState extends State { body: marks.loading ? const Center(child: CircularProgressIndicator()) : ListView.builder( - padding: EdgeInsets.all(10 * scale), // smaller padding + padding: EdgeInsets.all(10 * scale), itemCount: marks.marks.length, itemBuilder: (_, i) { final m = marks.marks[i]; + final status = + (m['status'] ?? '').toString().toLowerCase(); + + final LinearGradient statusGradient = + status == 'active' + ? const LinearGradient( + colors: [ + Color(0xFF2ECC71), // Green + Color(0xFF1E8449), // Deep Emerald + ], + ) + : const LinearGradient( + colors: [ + Color(0xFFE74C3C), // Red + Color(0xFFC0392B), // Dark Red + ], + ); return Container( - margin: EdgeInsets.only(bottom: 10 * scale), // reduced margin - padding: EdgeInsets.all(12 * scale), // smaller padding + margin: EdgeInsets.only(bottom: 10 * scale), + padding: EdgeInsets.all(12 * scale), decoration: BoxDecoration( gradient: const LinearGradient( colors: [ @@ -67,16 +81,15 @@ class _MarkListScreenState extends State { begin: Alignment.topLeft, end: Alignment.bottomRight, ), - borderRadius: BorderRadius.circular(14 * scale), // smaller radius + borderRadius: BorderRadius.circular(14 * scale), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.06), - blurRadius: 5 * scale, // smaller shadow + blurRadius: 5 * scale, offset: Offset(0, 2 * scale), ), ], ), - child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -85,24 +98,20 @@ class _MarkListScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // MARK NUMBER Text( m['mark_no'], style: TextStyle( color: Colors.white, - fontSize: 16 * scale, // reduced font + fontSize: 16 * scale, fontWeight: FontWeight.bold, ), ), - SizedBox(height: 3 * scale), - - // ROUTE Text( "${m['origin']} → ${m['destination']}", style: TextStyle( color: Colors.white, - fontSize: 13 * scale, // reduced font + fontSize: 13 * scale, fontWeight: FontWeight.w500, ), ), @@ -110,21 +119,21 @@ class _MarkListScreenState extends State { ), ), - // STATUS BADGE + // STATUS BADGE (GREEN / RED) Container( padding: EdgeInsets.symmetric( horizontal: 10 * scale, - vertical: 5 * scale, // smaller badge + vertical: 5 * scale, ), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.92), - borderRadius: BorderRadius.circular(24 * scale), + gradient: statusGradient, + borderRadius: BorderRadius.circular(20 * scale), ), child: Text( m['status'], style: TextStyle( fontSize: 11.5 * scale, - color: Colors.black87, + color: Colors.white, fontWeight: FontWeight.bold, ), ), diff --git a/lib/screens/order_invoice_screen.dart b/lib/screens/order_invoice_screen.dart index b1be55e..8a2311e 100644 --- a/lib/screens/order_invoice_screen.dart +++ b/lib/screens/order_invoice_screen.dart @@ -84,7 +84,6 @@ class _OrderInvoiceScreenState extends State children: [ _headerCard(scale), - // SUMMARY SECTION _sectionHeader("Invoice Summary", Icons.receipt, s1, () { setState(() => s1 = !s1); }, scale), @@ -92,12 +91,8 @@ class _OrderInvoiceScreenState extends State _detailRow(Icons.numbers, "Invoice No", invoice['invoice_number'], scale), _detailRow(Icons.calendar_month, "Invoice Date", invoice['invoice_date'], scale), _detailRow(Icons.date_range, "Due Date", invoice['due_date'], scale), - // _detailRow(Icons.payment, "Payment Method", invoice['payment_method'], scale), - // _detailRow(Icons.confirmation_number, "Reference No", - // invoice['reference_no'], scale), ], scale), - // AMOUNT SECTION _sectionHeader("Amount Details", Icons.currency_rupee, s2, () { setState(() => s2 = !s2); }, scale), @@ -109,7 +104,6 @@ class _OrderInvoiceScreenState extends State invoice['final_amount_with_gst'], scale), ], scale), - // CUSTOMER SECTION _sectionHeader("Customer Details", Icons.person, s3, () { setState(() => s3 = !s3); }, scale), @@ -121,7 +115,6 @@ class _OrderInvoiceScreenState extends State _detailRow(Icons.location_on, "Address", invoice['customer_address'], scale), ], scale), - // ITEMS SECTION _sectionHeader("Invoice Items", Icons.shopping_cart, s4, () { setState(() => s4 = !s4); }, scale), @@ -139,44 +132,63 @@ class _OrderInvoiceScreenState extends State // ---------------- HEADER CARD ---------------- Widget _headerCard(double scale) { + final statusColor = getInvoiceStatusColor(invoice["status"]); + return Container( padding: EdgeInsets.all(18 * scale), margin: EdgeInsets.only(bottom: 18 * scale), decoration: BoxDecoration( - gradient: - LinearGradient(colors: [Colors.indigo.shade400, Colors.blue.shade600]), + gradient: LinearGradient( + colors: [Colors.indigo.shade400, Colors.blue.shade600], + ), borderRadius: BorderRadius.circular(16 * scale), boxShadow: [ BoxShadow( - blurRadius: 10 * scale, - color: Colors.black.withOpacity(.15), - offset: Offset(0, 3 * scale)) + blurRadius: 10 * scale, + color: Colors.black.withOpacity(.15), + offset: Offset(0, 3 * scale), + ) ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Invoice #${invoice['invoice_number'] ?? '-'}", - style: TextStyle( - fontSize: 22 * scale, - fontWeight: FontWeight.bold, - color: Colors.white)), + Text( + "Invoice #${invoice['invoice_number'] ?? '-'}", + style: TextStyle( + fontSize: 22 * scale, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), SizedBox(height: 6 * scale), - Text("Date: ${invoice['invoice_date'] ?? '-'}", - style: TextStyle(color: Colors.white70, fontSize: 14 * scale)), + Text( + "Date: ${invoice['invoice_date'] ?? '-'}", + style: TextStyle(color: Colors.white70, fontSize: 14 * scale), + ), SizedBox(height: 10 * scale), Container( padding: EdgeInsets.symmetric( vertical: 6 * scale, horizontal: 14 * scale), decoration: BoxDecoration( - color: Colors.white.withOpacity(.2), + color: Colors.white, // ✅ Always white borderRadius: BorderRadius.circular(50 * scale), + border: Border.all( + color: statusColor, // ✅ Different for each status + width: 1.4 * scale, + ), ), child: Text( - invoice["status"]?.toString() ?? "Unknown", - style: TextStyle(color: Colors.white, fontSize: 14 * scale), + (invoice["status"] ?? "Unknown").toString().toUpperCase(), + style: TextStyle( + color: statusColor, // ✅ Text color changes + fontSize: 14 * scale, + fontWeight: FontWeight.bold, + letterSpacing: 0.5, + ), ), ) + ], ), ); @@ -199,11 +211,14 @@ class _OrderInvoiceScreenState extends State children: [ Icon(icon, color: Colors.white, size: 20 * scale), SizedBox(width: 10 * scale), - Text(title, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 15 * scale, - color: Colors.white)), + Text( + title, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 15 * scale, + color: Colors.white, + ), + ), const Spacer(), AnimatedRotation( turns: expanded ? .5 : 0, @@ -234,9 +249,10 @@ class _OrderInvoiceScreenState extends State color: Colors.white, boxShadow: [ BoxShadow( - blurRadius: 8 * scale, - offset: Offset(0, 3 * scale), - color: Colors.black.withOpacity(.08)), + blurRadius: 8 * scale, + offset: Offset(0, 3 * scale), + color: Colors.black.withOpacity(.08), + ), ], ), child: Column(children: children), @@ -256,16 +272,19 @@ class _OrderInvoiceScreenState extends State Icon(icon, color: Colors.blueGrey, size: 20 * scale), SizedBox(width: 10 * scale), Expanded( - child: Text(label, - style: TextStyle( - color: Colors.grey.shade700, fontSize: 14 * scale)), + child: Text( + label, + style: TextStyle(color: Colors.grey.shade700, fontSize: 14 * scale), + ), ), Expanded( child: Text( value?.toString() ?? "N/A", textAlign: TextAlign.end, style: TextStyle( - fontWeight: FontWeight.bold, fontSize: 15 * scale), + fontWeight: FontWeight.bold, + fontSize: 15 * scale, + ), ), ) ], @@ -287,16 +306,16 @@ class _OrderInvoiceScreenState extends State color: Colors.white, boxShadow: [ BoxShadow( - blurRadius: 8 * scale, - offset: Offset(0, 3 * scale), - color: Colors.black.withOpacity(.08)), + blurRadius: 8 * scale, + offset: Offset(0, 3 * scale), + color: Colors.black.withOpacity(.08), + ), ], border: Border.all(color: Colors.grey.shade300, width: 1), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // TITLE Row( children: [ Container( @@ -313,15 +332,14 @@ class _OrderInvoiceScreenState extends State child: Text( item['description'] ?? "Item", style: TextStyle( - fontSize: 16 * scale, fontWeight: FontWeight.w600), + fontSize: 16 * scale, + fontWeight: FontWeight.w600, + ), ), ), ], ), - SizedBox(height: 14 * scale), - - // QTY & PRICE Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -329,10 +347,7 @@ class _OrderInvoiceScreenState extends State _itemBadge(Icons.currency_rupee, "Price", "₹$price", false, scale), ], ), - SizedBox(height: 12 * scale), - - // TOTAL Container( padding: EdgeInsets.symmetric( vertical: 10 * scale, horizontal: 14 * scale), @@ -384,8 +399,9 @@ class _OrderInvoiceScreenState extends State borderRadius: BorderRadius.circular(12 * scale), color: highlight ? Colors.indigo.shade50 : Colors.grey.shade100, border: Border.all( - color: highlight ? Colors.indigo : Colors.grey.shade300, - width: highlight ? 1.5 * scale : 1), + color: highlight ? Colors.indigo : Colors.grey.shade300, + width: highlight ? 1.5 * scale : 1, + ), ), child: Row( children: [ @@ -414,3 +430,22 @@ class _OrderInvoiceScreenState extends State ); } } + +// ---------------- STATUS COLOR HELPER ---------------- + +Color getInvoiceStatusColor(String? status) { + final s = (status ?? '') + .toLowerCase() + .replaceAll('_', ' ') + .replaceAll('-', ' ') + .trim(); + + if (s == 'paid') return Colors.green.shade600; + if (s == 'pending') return Colors.orange.shade600; + if (s == 'overdue') return Colors.red.shade600; + if (s == 'cancelled' || s == 'canceled') return Colors.grey.shade600; + if (s == 'in progress') return Colors.blue.shade600; + if (s == 'draft') return Colors.purple.shade600; + + return Colors.blueGrey; +} diff --git a/lib/screens/order_screen.dart b/lib/screens/order_screen.dart index 5f48b89..5c50220 100644 --- a/lib/screens/order_screen.dart +++ b/lib/screens/order_screen.dart @@ -34,7 +34,6 @@ class _OrdersScreenState extends State { final screenWidth = MediaQuery.of(context).size.width; final scale = (screenWidth / 420).clamp(0.85, 1.15); - // FILTER ORDERS final filteredOrders = provider.orders.where((o) { final q = searchQuery.toLowerCase(); return o["order_id"].toString().toLowerCase().contains(q) || @@ -45,7 +44,7 @@ class _OrdersScreenState extends State { return Column( children: [ - // ⭐⭐ WHITE ELEVATED SEARCH BAR ⭐⭐ + // SEARCH BAR Container( margin: EdgeInsets.fromLTRB(16 * scale, 16 * scale, 16 * scale, 10 * scale), padding: EdgeInsets.symmetric(horizontal: 14 * scale), @@ -63,11 +62,8 @@ class _OrdersScreenState extends State { ), child: Row( children: [ - Icon(Icons.search, - size: 22 * scale, color: Colors.grey.shade700), - + Icon(Icons.search, size: 22 * scale, color: Colors.grey.shade700), SizedBox(width: 10 * scale), - Expanded( child: TextField( onChanged: (value) => setState(() => searchQuery = value), @@ -86,7 +82,7 @@ class _OrdersScreenState extends State { ), ), - // LIST OF ORDERS + // ORDER LIST Expanded( child: ListView.builder( padding: EdgeInsets.all(16 * scale), @@ -101,7 +97,6 @@ class _OrdersScreenState extends State { ); } - // ORDER CARD UI Widget _orderCard(Map o, double scale) { final progress = getProgress(o['status']); final badgeColor = getStatusColor(o['status']); @@ -118,7 +113,6 @@ class _OrdersScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // TOP ROW Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -151,12 +145,7 @@ class _OrdersScreenState extends State { ), SizedBox(height: 10 * scale), - - Text( - o['description'], - style: TextStyle(fontSize: 14 * scale), - ), - + Text(o['description'], style: TextStyle(fontSize: 14 * scale)), SizedBox(height: 5 * scale), Text( @@ -168,12 +157,9 @@ class _OrdersScreenState extends State { ), SizedBox(height: 18 * scale), - _AnimatedProgressBar(progress: progress, scale: scale), - SizedBox(height: 18 * scale), - // BUTTONS Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -193,21 +179,14 @@ class _OrdersScreenState extends State { ); } - // BUTTON UI Widget _btn(IconData icon, String text, Color fg, Color bg, VoidCallback onTap, double scale) { return InkWell( borderRadius: BorderRadius.circular(12 * scale), onTap: onTap, child: Container( - padding: EdgeInsets.symmetric( - horizontal: 20 * scale, - vertical: 12 * scale, - ), - decoration: BoxDecoration( - color: bg, - borderRadius: BorderRadius.circular(12 * scale), - ), + padding: EdgeInsets.symmetric(horizontal: 20 * scale, vertical: 12 * scale), + decoration: BoxDecoration(color: bg, borderRadius: BorderRadius.circular(12 * scale)), child: Row( children: [ Icon(icon, size: 18 * scale, color: fg), @@ -226,30 +205,24 @@ class _OrdersScreenState extends State { ); } - // NAVIGATION void _openOrderDetails(String id) { - Navigator.push( - context, - MaterialPageRoute(builder: (_) => OrderDetailScreen(orderId: id)), - ); + Navigator.push(context, + MaterialPageRoute(builder: (_) => OrderDetailScreen(orderId: id))); } void _openInvoice(String id) { - Navigator.push( - context, - MaterialPageRoute(builder: (_) => OrderInvoiceScreen(orderId: id)), - ); + Navigator.push(context, + MaterialPageRoute(builder: (_) => OrderInvoiceScreen(orderId: id))); } void _openTrack(String id) { - Navigator.push( - context, - MaterialPageRoute(builder: (_) => OrderTrackScreen(orderId: id)), - ); + Navigator.push(context, + MaterialPageRoute(builder: (_) => OrderTrackScreen(orderId: id))); } } -// PROGRESS BAR +// ================= PROGRESS BAR ================= + class _AnimatedProgressBar extends StatelessWidget { final double progress; final double scale; @@ -258,61 +231,65 @@ class _AnimatedProgressBar extends StatelessWidget { @override Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - final maxW = constraints.maxWidth; - - return Stack( - children: [ - Container( - height: 10 * scale, - decoration: BoxDecoration( - color: Colors.grey.shade300, - borderRadius: BorderRadius.circular(20 * scale), + return LayoutBuilder(builder: (context, constraints) { + return Stack( + children: [ + Container( + height: 10 * scale, + decoration: BoxDecoration( + color: Colors.grey.shade300, + borderRadius: BorderRadius.circular(20 * scale), + ), + ), + AnimatedContainer( + duration: const Duration(milliseconds: 650), + curve: Curves.easeInOut, + height: 10 * scale, + width: constraints.maxWidth * progress, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20 * scale), + gradient: const LinearGradient( + colors: [ + Color(0xFF4F8CFF), + Color(0xFF8A4DFF), + ], ), ), - AnimatedContainer( - duration: const Duration(milliseconds: 650), - curve: Curves.easeInOut, - height: 10 * scale, - width: maxW * progress, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20 * scale), - gradient: const LinearGradient( - colors: [ - Color(0xFF4F8CFF), - Color(0xFF8A4DFF), - ], - ), - ), - ), - ], - ); - }, - ); + ), + ], + ); + }); } } -// PROGRESS VALUES +// ================= FIXED STATUS LOGIC ================= + double getProgress(String? status) { - final s = (status ?? '').toLowerCase(); + final s = (status ?? '') + .toLowerCase() + .replaceAll('_', ' ') + .replaceAll('-', ' ') + .trim(); if (s == "pending") return 0.25; if (s == "loading") return 0.40; - if (s == "in transit" || s == "intransit") return 0.65; + if (s.contains("transit")) return 0.65; if (s == "dispatched") return 0.85; if (s == "delivered") return 1.0; return 0.05; } -// STATUS COLORS Color getStatusColor(String? status) { - final s = (status ?? '').toLowerCase(); + final s = (status ?? '') + .toLowerCase() + .replaceAll('_', ' ') + .replaceAll('-', ' ') + .trim(); if (s == "pending") return Colors.orange; if (s == "loading") return Colors.amber.shade800; - if (s == "in transit" || s == "intransit") return Colors.red; + if (s.contains("transit")) return Colors.red; if (s == "dispatched") return Colors.blue.shade700; if (s == "delivered") return Colors.green.shade700; diff --git a/lib/widgets/invoice_detail_view.dart b/lib/widgets/invoice_detail_view.dart index c561740..4e49c53 100644 --- a/lib/widgets/invoice_detail_view.dart +++ b/lib/widgets/invoice_detail_view.dart @@ -16,7 +16,6 @@ class _InvoiceDetailViewState extends State bool s1 = true; bool s2 = false; bool s3 = false; - bool s4 = false; @override void initState() { @@ -27,8 +26,12 @@ class _InvoiceDetailViewState extends State duration: const Duration(milliseconds: 350), ); - _slideAnimation = Tween(begin: const Offset(0, -0.1), end: Offset.zero) - .animate(CurvedAnimation(parent: _controller, curve: Curves.easeOut)); + _slideAnimation = Tween( + begin: const Offset(0, -0.1), + end: Offset.zero, + ).animate( + CurvedAnimation(parent: _controller, curve: Curves.easeOut), + ); _controller.forward(); } @@ -40,13 +43,93 @@ class _InvoiceDetailViewState extends State } // ------------------------------------------------------------------ - // HEADER SUMMARY CARD + // STATUS BADGE (WHITE + GRADIENT BORDER) + // ------------------------------------------------------------------ + Widget statusBadge(String status, double scale) { + final s = status.toLowerCase(); + + LinearGradient gradient; + Color textColor; + + switch (s) { + case 'paid': + gradient = const LinearGradient( + colors: [Color(0xFF2ECC71), Color(0xFF27AE60)], + ); + textColor = const Color(0xFF27AE60); + break; + + case 'pending': + gradient = const LinearGradient( + colors: [ + Color(0xFF5B8DEF), // Soft Blue + Color(0xFF7B5CFA), // Purple Blue + ], + ); + textColor = const Color(0xFF5B8DEF); + break; + + case 'overdue': + gradient = const LinearGradient( + colors: [ + Color(0xFFFFB300), // Amber + Color(0xFFFF6F00), // Deep Orange + ], + ); + textColor = const Color(0xFFFF6F00); + break; + + case 'cancelled': + case 'failed': + gradient = const LinearGradient( + colors: [Color(0xFFE74C3C), Color(0xFFC0392B)], + ); + textColor = const Color(0xFFE74C3C); + break; + + default: + gradient = const LinearGradient( + colors: [Color(0xFF95A5A6), Color(0xFF7F8C8D)], + ); + textColor = Colors.grey.shade700; + } + + return Container( + padding: const EdgeInsets.all(1.5), + decoration: BoxDecoration( + gradient: gradient, + borderRadius: BorderRadius.circular(20 * scale), + ), + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 14 * scale, + vertical: 6 * scale, + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(18 * scale), + ), + child: Text( + status.toUpperCase(), + style: TextStyle( + fontSize: 12 * scale, + fontWeight: FontWeight.w700, + color: textColor, + letterSpacing: .6, + ), + ), + ), + ); + } + + // ------------------------------------------------------------------ + // HEADER CARD // ------------------------------------------------------------------ Widget headerCard(Map invoice, double scale) { return Container( width: double.infinity, - padding: EdgeInsets.all(16 * scale), // tighter - margin: EdgeInsets.only(bottom: 14 * scale), // closer + padding: EdgeInsets.all(16 * scale), + margin: EdgeInsets.only(bottom: 14 * scale), decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.blue.shade400, Colors.indigo.shade600], @@ -76,40 +159,34 @@ class _InvoiceDetailViewState extends State "Date: ${invoice['invoice_date']}", style: TextStyle(color: Colors.white70, fontSize: 13 * scale), ), - SizedBox(height: 8 * scale), - Container( - padding: EdgeInsets.symmetric( - vertical: 5 * scale, horizontal: 12 * scale), - decoration: BoxDecoration( - color: Colors.white.withOpacity(.2), - borderRadius: BorderRadius.circular(40 * scale), - ), - child: Text( - invoice['status'] ?? "Unknown", - style: TextStyle( - color: Colors.white, - fontSize: 13 * scale, - ), - ), - ) + SizedBox(height: 10 * scale), + + /// STATUS BADGE + statusBadge(invoice['status'] ?? 'Unknown', scale), ], ), ); } // ------------------------------------------------------------------ - // SECTION HEADER (Closer Spacing) + // SECTION HEADER // ------------------------------------------------------------------ Widget sectionHeader( - String title, IconData icon, bool expanded, Function() tap, double scale) { + String title, + IconData icon, + bool expanded, + VoidCallback tap, + double scale, + ) { return GestureDetector( onTap: tap, child: Container( - padding: EdgeInsets.all(12 * scale), // tighter - margin: EdgeInsets.only(bottom: 8 * scale), // closer + padding: EdgeInsets.all(12 * scale), + margin: EdgeInsets.only(bottom: 8 * scale), decoration: BoxDecoration( gradient: LinearGradient( - colors: [Colors.indigo.shade500, Colors.blue.shade400]), + colors: [Colors.indigo.shade500, Colors.blue.shade400], + ), borderRadius: BorderRadius.circular(12 * scale), boxShadow: [ BoxShadow( @@ -126,16 +203,20 @@ class _InvoiceDetailViewState extends State Text( title, style: TextStyle( - fontSize: 15 * scale, - color: Colors.white, - fontWeight: FontWeight.bold), + fontSize: 15 * scale, + color: Colors.white, + fontWeight: FontWeight.bold, + ), ), const Spacer(), AnimatedRotation( turns: expanded ? .5 : 0, duration: const Duration(milliseconds: 250), - child: Icon(Icons.keyboard_arrow_down, - color: Colors.white, size: 20 * scale), + child: Icon( + Icons.keyboard_arrow_down, + color: Colors.white, + size: 20 * scale, + ), ) ], ), @@ -144,7 +225,7 @@ class _InvoiceDetailViewState extends State } // ------------------------------------------------------------------ - // SECTION BODY (Closer Spacing) + // SECTION BODY // ------------------------------------------------------------------ Widget sectionBody(bool visible, List children, double scale) { return AnimatedCrossFade( @@ -155,17 +236,17 @@ class _InvoiceDetailViewState extends State secondChild: SlideTransition( position: _slideAnimation, child: Container( - width: double.infinity, - padding: EdgeInsets.all(14 * scale), // tighter - margin: EdgeInsets.only(bottom: 10 * scale), // closer + padding: EdgeInsets.all(14 * scale), + margin: EdgeInsets.only(bottom: 10 * scale), decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(12 * scale), boxShadow: [ BoxShadow( - blurRadius: 7 * scale, - offset: Offset(0, 2 * scale), - color: Colors.black.withOpacity(.07)) + blurRadius: 7 * scale, + offset: Offset(0, 2 * scale), + color: Colors.black.withOpacity(.07), + ) ], ), child: Column(children: children), @@ -175,11 +256,11 @@ class _InvoiceDetailViewState extends State } // ------------------------------------------------------------------ - // DETAIL ROW (Closer Spacing) + // DETAIL ROW // ------------------------------------------------------------------ Widget detailRow(IconData icon, String label, dynamic value, double scale) { return Padding( - padding: EdgeInsets.symmetric(vertical: 5 * scale), // closer + padding: EdgeInsets.symmetric(vertical: 5 * scale), child: Row( children: [ Icon(icon, size: 18 * scale, color: Colors.blueGrey), @@ -196,11 +277,18 @@ class _InvoiceDetailViewState extends State ), Expanded( flex: 4, - child: Text( + child: label == "Status" + ? Align( + alignment: Alignment.centerRight, + child: statusBadge(value ?? 'Unknown', scale), + ) + : Text( value?.toString() ?? "N/A", textAlign: TextAlign.right, - style: - TextStyle(fontSize: 14 * scale, fontWeight: FontWeight.bold), + style: TextStyle( + fontSize: 14 * scale, + fontWeight: FontWeight.bold, + ), ), ) ], @@ -208,60 +296,6 @@ class _InvoiceDetailViewState extends State ); } - // ------------------------------------------------------------------ - // TIMELINE (Closer Spacing) - // ------------------------------------------------------------------ - Widget invoiceTimeline(double scale) { - final steps = ["Invoice Created", "Payment Received", "Out for Delivery", "Completed"]; - final icons = [Icons.receipt_long, Icons.payments, Icons.local_shipping, Icons.verified]; - - return Container( - padding: EdgeInsets.all(16 * scale), - margin: EdgeInsets.only(bottom: 16 * scale), // closer - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - borderRadius: BorderRadius.circular(14 * scale), - boxShadow: [ - BoxShadow( - blurRadius: 7 * scale, - color: Colors.black.withOpacity(.1), - offset: Offset(0, 3 * scale), - ) - ], - ), - child: Column( - children: List.generate(steps.length, (i) { - return Padding( - padding: EdgeInsets.symmetric(vertical: 4 * scale), // closer - child: Row( - children: [ - Column( - children: [ - Icon(icons[i], size: 22 * scale, color: Colors.indigo), - if (i < steps.length - 1) - Container( - height: 28 * scale, - width: 2 * scale, - color: Colors.indigo.shade300, - ) - ], - ), - SizedBox(width: 10 * scale), - Expanded( - child: Text( - steps[i], - style: - TextStyle(fontSize: 14 * scale, fontWeight: FontWeight.w600), - ), - ) - ], - ), - ); - }), - ), - ); - } - // ------------------------------------------------------------------ // MAIN BUILD // ------------------------------------------------------------------ @@ -272,21 +306,30 @@ class _InvoiceDetailViewState extends State final scale = (width / 390).clamp(0.85, 1.25); return ListView( - padding: EdgeInsets.all(14 * scale), // slightly tighter + padding: EdgeInsets.all(14 * scale), children: [ headerCard(invoice, scale), - invoiceTimeline(scale), - sectionHeader("Invoice Summary", Icons.receipt_long, s1, - () => setState(() => s1 = !s1), scale), + sectionHeader( + "Invoice Summary", + Icons.receipt_long, + s1, + () => setState(() => s1 = !s1), + scale, + ), sectionBody(s1, [ detailRow(Icons.numbers, "Invoice No", invoice['invoice_number'], scale), detailRow(Icons.calendar_today, "Date", invoice['invoice_date'], scale), detailRow(Icons.label, "Status", invoice['status'], scale), ], scale), - sectionHeader("Customer Details", Icons.person, s2, - () => setState(() => s2 = !s2), scale), + sectionHeader( + "Customer Details", + Icons.person, + s2, + () => setState(() => s2 = !s2), + scale, + ), sectionBody(s2, [ detailRow(Icons.person_outline, "Name", invoice['customer_name'], scale), detailRow(Icons.mail, "Email", invoice['customer_email'], scale), @@ -294,22 +337,19 @@ class _InvoiceDetailViewState extends State detailRow(Icons.location_on, "Address", invoice['customer_address'], scale), ], scale), - sectionHeader("Amount Details", Icons.currency_rupee, s3, - () => setState(() => s3 = !s3), scale), + sectionHeader( + "Amount Details", + Icons.currency_rupee, + s3, + () => setState(() => s3 = !s3), + scale, + ), sectionBody(s3, [ detailRow(Icons.money, "Amount", invoice['final_amount'], scale), - detailRow(Icons.percent, "GST percent %", invoice['gst_percent'], scale), - detailRow(Icons.percent, "GST amount %", invoice['gst_amount'], scale), + detailRow(Icons.percent, "GST %", invoice['gst_percent'], scale), + detailRow(Icons.percent, "GST Amount", invoice['gst_amount'], scale), detailRow(Icons.summarize, "Total", invoice['final_amount_with_gst'], scale), ], scale), - - // sectionHeader("Payment Details", Icons.payment, s4, - // () => setState(() => s4 = !s4), scale), - // sectionBody(s4, [ - // detailRow(Icons.credit_card, "Method", invoice['payment_method'], scale), - // detailRow(Icons.confirmation_number, "Reference", - // invoice['reference_no'], scale), - // ], scale), ], ); } diff --git a/pubspec.lock b/pubspec.lock index 7290043..3f5917b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -388,26 +388,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -436,10 +436,10 @@ packages: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: transitive description: @@ -777,10 +777,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.7" typed_data: dependency: transitive description: @@ -865,10 +865,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" video_player: dependency: "direct main" description: