diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json new file mode 100644 index 0000000..f15bca7 --- /dev/null +++ b/.dart_tool/package_config.json @@ -0,0 +1,1156 @@ +{ + "configVersion": 2, + "packages": [ + { + "name": "_fe_analyzer_shared", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/_fe_analyzer_shared-67.0.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "analyzer", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/analyzer-6.4.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "animated_toggle_switch", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/animated_toggle_switch-0.8.7", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "ansicolor", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/ansicolor-2.0.3", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "archive", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/archive-3.6.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "args", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/args-2.7.0", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "asn1lib", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/asn1lib-1.6.5", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "async", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/async-2.13.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "auto_size_text", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/auto_size_text-3.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "back_button_interceptor", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/back_button_interceptor-7.0.3", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "boolean_selector", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/boolean_selector-2.1.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "build", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/build-2.4.1", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "build_config", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/build_config-1.2.0", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "buttons_tabbar", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/buttons_tabbar-1.3.8", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "calendar_date_picker2", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/calendar_date_picker2-1.0.2", + "packageUri": "lib/", + "languageVersion": "2.16" + }, + { + "name": "camera", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/camera-0.10.6", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "camera_android", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/camera_android-0.10.10+14", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "camera_avfoundation", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/camera_avfoundation-0.9.23+2", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "camera_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/camera_platform_interface-2.12.0", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "camera_web", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/camera_web-0.3.5+3", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "characters", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/characters-1.4.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "checked_yaml", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/checked_yaml-2.0.4", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "chunked_stream", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/chunked_stream-1.4.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "circular_buffer", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/circular_buffer-0.12.0", + "packageUri": "lib/", + "languageVersion": "2.13" + }, + { + "name": "clock", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/clock-1.1.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "code_assets", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/code_assets-1.0.0", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "collection", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "connectivity_plus", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/connectivity_plus-6.1.5", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "connectivity_plus_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/connectivity_plus_platform_interface-2.0.1", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "convert", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/convert-3.1.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "country_code_picker", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/country_code_picker-3.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "cross_file", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/cross_file-0.3.5+2", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "crypto", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/crypto-3.0.7", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "csv", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/csv-6.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "cupertino_icons", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/cupertino_icons-1.0.8", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "dart_console", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dart_console-4.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "dart_style", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dart_style-2.3.6", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "dbus", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dbus-0.7.12", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "dcli", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dcli-6.1.2", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "dcli_common", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dcli_common-6.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "dcli_core", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dcli_core-6.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "dcli_terminal", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dcli_terminal-6.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "device_info_plus", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/device_info_plus-10.1.2", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "device_info_plus_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/device_info_plus_platform_interface-7.0.3", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "dio", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dio-4.0.6", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "dropdown_button2", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/dropdown_button2-2.3.9", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "encrypt", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/encrypt-5.0.3", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "equatable", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/equatable-2.0.8", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "fake_async", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/fake_async-1.3.3", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "ffi", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/ffi-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "file", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/file-7.0.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "fixnum", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/fixnum-1.1.1", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "flutter", + "rootUri": "file:///C:/flutter/packages/flutter", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "flutter_camera_overlay_new", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_camera_overlay_new-0.0.1", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "flutter_contacts", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_contacts-1.1.9+2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_custom_clippers", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_custom_clippers-2.1.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_dotenv", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_dotenv-5.2.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_form_builder", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_form_builder-9.2.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "flutter_keyboard_visibility", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_keyboard_visibility-6.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_linux", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_keyboard_visibility_linux-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_macos", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_keyboard_visibility_macos-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_keyboard_visibility_platform_interface-2.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_web", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_keyboard_visibility_web-2.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_windows", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_keyboard_visibility_windows-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_lints", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_lints-6.0.0", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "flutter_plugin_android_lifecycle", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.33", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "flutter_rounded_date_picker", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_rounded_date_picker-3.0.4", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "flutter_svg", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_svg-2.2.3", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "flutter_test", + "rootUri": "file:///C:/flutter/packages/flutter_test", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "flutter_timer_countdown", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_timer_countdown-1.0.7", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_web_plugins", + "rootUri": "file:///C:/flutter/packages/flutter_web_plugins", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "flutter_zoom_drawer", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_zoom_drawer-3.1.2", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "fluttertoast", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/fluttertoast-8.2.14", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "functional_data", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/functional_data-1.2.0", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "get", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/get-4.6.6", + "packageUri": "lib/", + "languageVersion": "2.15" + }, + { + "name": "get_cli", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/get_cli-1.9.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "getwidget", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/getwidget-4.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "glob", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/glob-2.1.3", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "globbing", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/globbing-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "google_fonts", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/google_fonts-7.0.0", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "hive", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/hive-2.2.3", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "hive_flutter", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/hive_flutter-1.1.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "hooks", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/hooks-1.0.1", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "http", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/http-1.6.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "http_parser", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/http_parser-4.1.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "image", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/image-4.3.0", + "packageUri": "lib/", + "languageVersion": "2.15" + }, + { + "name": "ini", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/ini-2.1.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "intl", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/intl-0.19.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "introduction_slider", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/introduction_slider-2.0.1", + "packageUri": "lib/", + "languageVersion": "2.16" + }, + { + "name": "js", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/js-0.7.2", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "json2yaml", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/json2yaml-3.0.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "json_annotation", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/json_annotation-4.8.1", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "json_serializable", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/json_serializable-6.7.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "leak_tracker", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker-11.0.2", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "leak_tracker_flutter_testing", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.10", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "leak_tracker_testing", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_testing-3.0.2", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "lints", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/lints-6.1.0", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "lists", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/lists-1.0.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "loader_overlay", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/loader_overlay-4.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "local_auth", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/local_auth-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "local_auth_android", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/local_auth_android-1.0.56", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "local_auth_darwin", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/local_auth_darwin-1.6.1", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "local_auth_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/local_auth_platform_interface-1.1.0", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "local_auth_windows", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/local_auth_windows-1.0.11", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "logging", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/logging-1.3.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "matcher", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/matcher-0.12.17", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "material_color_utilities", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/material_color_utilities-0.11.1", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "meta", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.17.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "mime", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/mime-2.0.0", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "mobile_scanner", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/mobile_scanner-6.0.11", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "native_synchronization_temp", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/native_synchronization_temp-0.7.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "native_toolchain_c", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/native_toolchain_c-0.17.4", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "nm", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/nm-0.5.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "objective_c", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/objective_c-9.3.0", + "packageUri": "lib/", + "languageVersion": "3.10" + }, + { + "name": "package_config", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/package_config-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "path", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path-1.9.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "path_parsing", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_parsing-1.1.0", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "path_provider", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider-2.1.3", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "path_provider_android", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_android-2.2.22", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "path_provider_foundation", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_foundation-2.6.0", + "packageUri": "lib/", + "languageVersion": "3.10" + }, + { + "name": "path_provider_linux", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.2.1", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "path_provider_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_platform_interface-2.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "path_provider_windows", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_windows-2.3.0", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "permission_handler", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/permission_handler-11.3.0", + "packageUri": "lib/", + "languageVersion": "2.15" + }, + { + "name": "permission_handler_android", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/permission_handler_android-12.1.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "permission_handler_apple", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/permission_handler_apple-9.4.7", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "permission_handler_html", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/permission_handler_html-0.1.3+5", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "permission_handler_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/permission_handler_platform_interface-4.3.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "permission_handler_windows", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/permission_handler_windows-0.2.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "petitparser", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/petitparser-7.0.2", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "pin_code_fields", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/pin_code_fields-8.0.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "platform", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/platform-3.1.6", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "plugin_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/plugin_platform_interface-2.1.8", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "pointycastle", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/pointycastle-3.9.1", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "posix", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/posix-6.0.3", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "process_run", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/process_run-1.3.0", + "packageUri": "lib/", + "languageVersion": "3.10" + }, + { + "name": "pub_semver", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/pub_semver-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "pubspec_lock", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/pubspec_lock-3.0.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "pubspec_manager", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/pubspec_manager-1.0.3", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "pubspec_parse", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/pubspec_parse-1.4.0", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "qr", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/qr-3.0.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "qr_flutter", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/qr_flutter-4.1.0", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "quickalert", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/quickalert-1.0.2", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "recase", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/recase-4.1.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "responsive_framework", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/responsive_framework-1.4.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "root_checker_plus", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/root_checker_plus-0.0.7", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "scope", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/scope-5.1.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "screenshot", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/screenshot-3.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "settings_yaml", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/settings_yaml-8.3.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "share_plus", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/share_plus-12.0.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "share_plus_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/share_plus_platform_interface-6.1.0", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "simple_speed_dial", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/simple_speed_dial-0.1.7", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "sky_engine", + "rootUri": "file:///C:/flutter/bin/cache/pkg/sky_engine", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "source_gen", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/source_gen-1.5.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "source_helper", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/source_helper-1.3.5", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "source_span", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/source_span-1.10.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "stack_trace", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/stack_trace-1.12.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "stream_channel", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/stream_channel-2.1.4", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "stream_transform", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/stream_transform-2.1.1", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "string_scanner", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/string_scanner-1.4.1", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "string_validator", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/string_validator-1.0.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "strings", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/strings-3.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "stylish_bottom_bar", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/stylish_bottom_bar-1.0.3", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "sum_types", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/sum_types-0.3.5", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "synchronized", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/synchronized-3.4.0", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "system_info2", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/system_info2-4.1.0", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "term_glyph", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/term_glyph-1.2.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "test_api", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/test_api-0.7.7", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "timer_count_down", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/timer_count_down-2.2.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "typed_data", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/typed_data-1.4.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "unicode", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/unicode-0.3.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "url_launcher_linux", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/url_launcher_linux-3.2.2", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "url_launcher_platform_interface", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/url_launcher_platform_interface-2.3.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "url_launcher_web", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/url_launcher_web-2.4.2", + "packageUri": "lib/", + "languageVersion": "3.10" + }, + { + "name": "url_launcher_windows", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/url_launcher_windows-3.1.5", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "uuid", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/uuid-4.5.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "validators2", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/validators2-5.1.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "vector_graphics", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/vector_graphics-1.1.19", + "packageUri": "lib/", + "languageVersion": "3.6" + }, + { + "name": "vector_graphics_codec", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/vector_graphics_codec-1.1.13", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "vector_graphics_compiler", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/vector_graphics_compiler-1.1.20", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "vector_math", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/vector_math-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "version", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/version-3.0.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "vm_service", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/vm_service-15.0.2", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "watcher", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/watcher-1.2.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "web", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/web-1.1.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "win32", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/win32-5.15.0", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "win32_registry", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/win32_registry-1.1.5", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "xdg_directories", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/xdg_directories-1.1.0", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "xml", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/xml-6.6.1", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "yaml", + "rootUri": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache/hosted/pub.dev/yaml-3.1.3", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "uco_mobile_poc", + "rootUri": "../", + "packageUri": "lib/", + "languageVersion": "3.10" + } + ], + "generator": "pub", + "generatorVersion": "3.10.7", + "flutterRoot": "file:///C:/flutter", + "flutterVersion": "3.38.7", + "pubCache": "file:///C:/Users/samanwaqar/AppData/Local/Pub/Cache" +} diff --git a/.dart_tool/package_graph.json b/.dart_tool/package_graph.json new file mode 100644 index 0000000..81c4321 --- /dev/null +++ b/.dart_tool/package_graph.json @@ -0,0 +1,1724 @@ +{ + "roots": [ + "uco_mobile_poc" + ], + "packages": [ + { + "name": "uco_mobile_poc", + "version": "1.0.0+1", + "dependencies": [ + "animated_toggle_switch", + "auto_size_text", + "buttons_tabbar", + "calendar_date_picker2", + "camera", + "connectivity_plus", + "country_code_picker", + "cupertino_icons", + "device_info_plus", + "dio", + "dropdown_button2", + "encrypt", + "flutter", + "flutter_camera_overlay_new", + "flutter_contacts", + "flutter_custom_clippers", + "flutter_dotenv", + "flutter_form_builder", + "flutter_keyboard_visibility", + "flutter_rounded_date_picker", + "flutter_svg", + "flutter_timer_countdown", + "flutter_zoom_drawer", + "fluttertoast", + "get", + "get_cli", + "getwidget", + "google_fonts", + "hive_flutter", + "image", + "introduction_slider", + "json_serializable", + "loader_overlay", + "local_auth", + "mobile_scanner", + "path_provider", + "permission_handler", + "pin_code_fields", + "pointycastle", + "qr_flutter", + "quickalert", + "responsive_framework", + "root_checker_plus", + "screenshot", + "share_plus", + "simple_speed_dial", + "string_validator", + "stylish_bottom_bar", + "timer_count_down" + ], + "devDependencies": [ + "flutter_lints", + "flutter_test" + ] + }, + { + "name": "flutter_lints", + "version": "6.0.0", + "dependencies": [ + "lints" + ] + }, + { + "name": "flutter_test", + "version": "0.0.0", + "dependencies": [ + "clock", + "collection", + "fake_async", + "flutter", + "leak_tracker_flutter_testing", + "matcher", + "meta", + "path", + "stack_trace", + "stream_channel", + "test_api", + "vector_math" + ] + }, + { + "name": "flutter_dotenv", + "version": "5.2.1", + "dependencies": [ + "flutter" + ] + }, + { + "name": "pointycastle", + "version": "3.9.1", + "dependencies": [ + "collection", + "convert", + "js" + ] + }, + { + "name": "encrypt", + "version": "5.0.3", + "dependencies": [ + "args", + "asn1lib", + "clock", + "collection", + "crypto", + "pointycastle" + ] + }, + { + "name": "root_checker_plus", + "version": "0.0.7", + "dependencies": [ + "flutter", + "plugin_platform_interface" + ] + }, + { + "name": "device_info_plus", + "version": "10.1.2", + "dependencies": [ + "device_info_plus_platform_interface", + "ffi", + "file", + "flutter", + "flutter_web_plugins", + "meta", + "web", + "win32", + "win32_registry" + ] + }, + { + "name": "get_cli", + "version": "1.9.1", + "dependencies": [ + "ansicolor", + "collection", + "dart_style", + "dcli", + "http", + "intl", + "meta", + "path", + "process_run", + "pub_semver", + "pubspec_parse", + "recase", + "version", + "yaml" + ] + }, + { + "name": "connectivity_plus", + "version": "6.1.5", + "dependencies": [ + "collection", + "connectivity_plus_platform_interface", + "flutter", + "flutter_web_plugins", + "meta", + "nm", + "web" + ] + }, + { + "name": "image", + "version": "4.3.0", + "dependencies": [ + "archive", + "meta", + "xml" + ] + }, + { + "name": "auto_size_text", + "version": "3.0.0", + "dependencies": [ + "flutter" + ] + }, + { + "name": "animated_toggle_switch", + "version": "0.8.7", + "dependencies": [ + "flutter" + ] + }, + { + "name": "flutter_keyboard_visibility", + "version": "6.0.0", + "dependencies": [ + "flutter", + "flutter_keyboard_visibility_linux", + "flutter_keyboard_visibility_macos", + "flutter_keyboard_visibility_platform_interface", + "flutter_keyboard_visibility_web", + "flutter_keyboard_visibility_windows", + "meta" + ] + }, + { + "name": "screenshot", + "version": "3.0.0", + "dependencies": [ + "flutter" + ] + }, + { + "name": "mobile_scanner", + "version": "6.0.11", + "dependencies": [ + "flutter", + "flutter_web_plugins", + "plugin_platform_interface", + "web" + ] + }, + { + "name": "qr_flutter", + "version": "4.1.0", + "dependencies": [ + "flutter", + "qr" + ] + }, + { + "name": "path_provider", + "version": "2.1.3", + "dependencies": [ + "flutter", + "path_provider_android", + "path_provider_foundation", + "path_provider_linux", + "path_provider_platform_interface", + "path_provider_windows" + ] + }, + { + "name": "buttons_tabbar", + "version": "1.3.8", + "dependencies": [ + "flutter" + ] + }, + { + "name": "json_serializable", + "version": "6.7.1", + "dependencies": [ + "analyzer", + "async", + "build", + "build_config", + "collection", + "json_annotation", + "meta", + "path", + "pub_semver", + "pubspec_parse", + "source_gen", + "source_helper" + ] + }, + { + "name": "calendar_date_picker2", + "version": "1.0.2", + "dependencies": [ + "flutter", + "intl" + ] + }, + { + "name": "flutter_rounded_date_picker", + "version": "3.0.4", + "dependencies": [ + "flutter" + ] + }, + { + "name": "getwidget", + "version": "4.0.0", + "dependencies": [ + "flutter" + ] + }, + { + "name": "loader_overlay", + "version": "4.0.0", + "dependencies": [ + "back_button_interceptor", + "flutter" + ] + }, + { + "name": "country_code_picker", + "version": "3.0.0", + "dependencies": [ + "collection", + "flutter" + ] + }, + { + "name": "string_validator", + "version": "1.0.2", + "dependencies": [] + }, + { + "name": "share_plus", + "version": "12.0.1", + "dependencies": [ + "cross_file", + "ffi", + "file", + "flutter", + "flutter_web_plugins", + "meta", + "mime", + "share_plus_platform_interface", + "url_launcher_linux", + "url_launcher_platform_interface", + "url_launcher_web", + "url_launcher_windows", + "web", + "win32" + ] + }, + { + "name": "dio", + "version": "4.0.6", + "dependencies": [ + "http_parser", + "path" + ] + }, + { + "name": "local_auth", + "version": "2.2.0", + "dependencies": [ + "flutter", + "local_auth_android", + "local_auth_darwin", + "local_auth_platform_interface", + "local_auth_windows" + ] + }, + { + "name": "responsive_framework", + "version": "1.4.0", + "dependencies": [ + "collection", + "flutter" + ] + }, + { + "name": "flutter_svg", + "version": "2.2.3", + "dependencies": [ + "flutter", + "http", + "vector_graphics", + "vector_graphics_codec", + "vector_graphics_compiler" + ] + }, + { + "name": "flutter_camera_overlay_new", + "version": "0.0.1", + "dependencies": [ + "camera", + "flutter", + "plugin_platform_interface" + ] + }, + { + "name": "camera", + "version": "0.10.6", + "dependencies": [ + "camera_android", + "camera_avfoundation", + "camera_platform_interface", + "camera_web", + "flutter", + "flutter_plugin_android_lifecycle" + ] + }, + { + "name": "flutter_form_builder", + "version": "9.2.1", + "dependencies": [ + "flutter", + "intl" + ] + }, + { + "name": "permission_handler", + "version": "11.3.0", + "dependencies": [ + "flutter", + "meta", + "permission_handler_android", + "permission_handler_apple", + "permission_handler_html", + "permission_handler_platform_interface", + "permission_handler_windows" + ] + }, + { + "name": "flutter_contacts", + "version": "1.1.9+2", + "dependencies": [ + "flutter" + ] + }, + { + "name": "dropdown_button2", + "version": "2.3.9", + "dependencies": [ + "flutter", + "meta" + ] + }, + { + "name": "stylish_bottom_bar", + "version": "1.0.3", + "dependencies": [ + "flutter" + ] + }, + { + "name": "simple_speed_dial", + "version": "0.1.7", + "dependencies": [ + "flutter" + ] + }, + { + "name": "quickalert", + "version": "1.0.2", + "dependencies": [ + "flutter", + "vector_math" + ] + }, + { + "name": "flutter_zoom_drawer", + "version": "3.1.2", + "dependencies": [ + "flutter" + ] + }, + { + "name": "flutter_timer_countdown", + "version": "1.0.7", + "dependencies": [ + "flutter" + ] + }, + { + "name": "timer_count_down", + "version": "2.2.2", + "dependencies": [ + "flutter" + ] + }, + { + "name": "pin_code_fields", + "version": "8.0.1", + "dependencies": [ + "flutter" + ] + }, + { + "name": "fluttertoast", + "version": "8.2.14", + "dependencies": [ + "flutter", + "flutter_web_plugins", + "web" + ] + }, + { + "name": "flutter_custom_clippers", + "version": "2.1.0", + "dependencies": [ + "flutter" + ] + }, + { + "name": "introduction_slider", + "version": "2.0.1", + "dependencies": [ + "flutter" + ] + }, + { + "name": "hive_flutter", + "version": "1.1.0", + "dependencies": [ + "flutter", + "hive", + "path", + "path_provider" + ] + }, + { + "name": "google_fonts", + "version": "7.0.0", + "dependencies": [ + "crypto", + "flutter", + "http", + "path_provider" + ] + }, + { + "name": "get", + "version": "4.6.6", + "dependencies": [ + "flutter" + ] + }, + { + "name": "cupertino_icons", + "version": "1.0.8", + "dependencies": [] + }, + { + "name": "flutter", + "version": "0.0.0", + "dependencies": [ + "characters", + "collection", + "material_color_utilities", + "meta", + "sky_engine", + "vector_math" + ] + }, + { + "name": "lints", + "version": "6.1.0", + "dependencies": [] + }, + { + "name": "stream_channel", + "version": "2.1.4", + "dependencies": [ + "async" + ] + }, + { + "name": "meta", + "version": "1.17.0", + "dependencies": [] + }, + { + "name": "collection", + "version": "1.19.1", + "dependencies": [] + }, + { + "name": "leak_tracker_flutter_testing", + "version": "3.0.10", + "dependencies": [ + "flutter", + "leak_tracker", + "leak_tracker_testing", + "matcher", + "meta" + ] + }, + { + "name": "vector_math", + "version": "2.2.0", + "dependencies": [] + }, + { + "name": "stack_trace", + "version": "1.12.1", + "dependencies": [ + "path" + ] + }, + { + "name": "clock", + "version": "1.1.2", + "dependencies": [] + }, + { + "name": "fake_async", + "version": "1.3.3", + "dependencies": [ + "clock", + "collection" + ] + }, + { + "name": "path", + "version": "1.9.1", + "dependencies": [] + }, + { + "name": "matcher", + "version": "0.12.17", + "dependencies": [ + "async", + "meta", + "stack_trace", + "term_glyph", + "test_api" + ] + }, + { + "name": "test_api", + "version": "0.7.7", + "dependencies": [ + "async", + "boolean_selector", + "collection", + "meta", + "source_span", + "stack_trace", + "stream_channel", + "string_scanner", + "term_glyph" + ] + }, + { + "name": "js", + "version": "0.7.2", + "dependencies": [] + }, + { + "name": "convert", + "version": "3.1.2", + "dependencies": [ + "typed_data" + ] + }, + { + "name": "crypto", + "version": "3.0.7", + "dependencies": [ + "typed_data" + ] + }, + { + "name": "asn1lib", + "version": "1.6.5", + "dependencies": [] + }, + { + "name": "args", + "version": "2.7.0", + "dependencies": [] + }, + { + "name": "plugin_platform_interface", + "version": "2.1.8", + "dependencies": [ + "meta" + ] + }, + { + "name": "win32_registry", + "version": "1.1.5", + "dependencies": [ + "ffi", + "win32" + ] + }, + { + "name": "win32", + "version": "5.15.0", + "dependencies": [ + "ffi" + ] + }, + { + "name": "web", + "version": "1.1.1", + "dependencies": [] + }, + { + "name": "flutter_web_plugins", + "version": "0.0.0", + "dependencies": [ + "flutter" + ] + }, + { + "name": "file", + "version": "7.0.1", + "dependencies": [ + "meta", + "path" + ] + }, + { + "name": "ffi", + "version": "2.2.0", + "dependencies": [] + }, + { + "name": "device_info_plus_platform_interface", + "version": "7.0.3", + "dependencies": [ + "flutter", + "meta", + "plugin_platform_interface" + ] + }, + { + "name": "yaml", + "version": "3.1.3", + "dependencies": [ + "collection", + "source_span", + "string_scanner" + ] + }, + { + "name": "version", + "version": "3.0.2", + "dependencies": [] + }, + { + "name": "recase", + "version": "4.1.0", + "dependencies": [] + }, + { + "name": "pub_semver", + "version": "2.2.0", + "dependencies": [ + "collection" + ] + }, + { + "name": "pubspec_parse", + "version": "1.4.0", + "dependencies": [ + "checked_yaml", + "collection", + "json_annotation", + "pub_semver", + "yaml" + ] + }, + { + "name": "process_run", + "version": "1.3.0", + "dependencies": [ + "args", + "collection", + "meta", + "path", + "pub_semver", + "string_scanner", + "synchronized", + "yaml" + ] + }, + { + "name": "intl", + "version": "0.19.0", + "dependencies": [ + "clock", + "meta", + "path" + ] + }, + { + "name": "http", + "version": "1.6.0", + "dependencies": [ + "async", + "http_parser", + "meta", + "web" + ] + }, + { + "name": "dcli", + "version": "6.1.2", + "dependencies": [ + "archive", + "args", + "async", + "chunked_stream", + "collection", + "convert", + "crypto", + "csv", + "dart_console", + "dcli_common", + "dcli_core", + "dcli_terminal", + "equatable", + "ffi", + "file", + "glob", + "ini", + "logging", + "meta", + "mime", + "native_synchronization_temp", + "path", + "posix", + "pub_semver", + "pubspec_lock", + "pubspec_manager", + "scope", + "settings_yaml", + "stack_trace", + "system_info2", + "uuid", + "validators2", + "win32", + "yaml" + ] + }, + { + "name": "dart_style", + "version": "2.3.6", + "dependencies": [ + "analyzer", + "args", + "collection", + "path", + "pub_semver", + "source_span" + ] + }, + { + "name": "ansicolor", + "version": "2.0.3", + "dependencies": [] + }, + { + "name": "nm", + "version": "0.5.0", + "dependencies": [ + "dbus" + ] + }, + { + "name": "connectivity_plus_platform_interface", + "version": "2.0.1", + "dependencies": [ + "flutter", + "meta", + "plugin_platform_interface" + ] + }, + { + "name": "xml", + "version": "6.6.1", + "dependencies": [ + "collection", + "meta", + "petitparser" + ] + }, + { + "name": "archive", + "version": "3.6.1", + "dependencies": [ + "crypto", + "path" + ] + }, + { + "name": "flutter_keyboard_visibility_windows", + "version": "1.0.0", + "dependencies": [ + "flutter", + "flutter_keyboard_visibility_platform_interface" + ] + }, + { + "name": "flutter_keyboard_visibility_web", + "version": "2.0.0", + "dependencies": [ + "flutter", + "flutter_keyboard_visibility_platform_interface", + "flutter_web_plugins" + ] + }, + { + "name": "flutter_keyboard_visibility_macos", + "version": "1.0.0", + "dependencies": [ + "flutter", + "flutter_keyboard_visibility_platform_interface" + ] + }, + { + "name": "flutter_keyboard_visibility_linux", + "version": "1.0.0", + "dependencies": [ + "flutter", + "flutter_keyboard_visibility_platform_interface" + ] + }, + { + "name": "flutter_keyboard_visibility_platform_interface", + "version": "2.0.0", + "dependencies": [ + "flutter", + "meta", + "plugin_platform_interface" + ] + }, + { + "name": "qr", + "version": "3.0.2", + "dependencies": [ + "meta" + ] + }, + { + "name": "path_provider_windows", + "version": "2.3.0", + "dependencies": [ + "ffi", + "flutter", + "path", + "path_provider_platform_interface" + ] + }, + { + "name": "path_provider_platform_interface", + "version": "2.1.2", + "dependencies": [ + "flutter", + "platform", + "plugin_platform_interface" + ] + }, + { + "name": "path_provider_linux", + "version": "2.2.1", + "dependencies": [ + "ffi", + "flutter", + "path", + "path_provider_platform_interface", + "xdg_directories" + ] + }, + { + "name": "path_provider_foundation", + "version": "2.6.0", + "dependencies": [ + "ffi", + "flutter", + "objective_c", + "path_provider_platform_interface" + ] + }, + { + "name": "path_provider_android", + "version": "2.2.22", + "dependencies": [ + "flutter", + "path_provider_platform_interface" + ] + }, + { + "name": "source_helper", + "version": "1.3.5", + "dependencies": [ + "analyzer", + "collection", + "source_gen" + ] + }, + { + "name": "source_gen", + "version": "1.5.0", + "dependencies": [ + "analyzer", + "async", + "build", + "dart_style", + "glob", + "path", + "source_span", + "yaml" + ] + }, + { + "name": "json_annotation", + "version": "4.8.1", + "dependencies": [ + "meta" + ] + }, + { + "name": "build_config", + "version": "1.2.0", + "dependencies": [ + "checked_yaml", + "json_annotation", + "path", + "pubspec_parse" + ] + }, + { + "name": "build", + "version": "2.4.1", + "dependencies": [ + "analyzer", + "async", + "convert", + "crypto", + "glob", + "logging", + "meta", + "package_config", + "path" + ] + }, + { + "name": "async", + "version": "2.13.0", + "dependencies": [ + "collection", + "meta" + ] + }, + { + "name": "analyzer", + "version": "6.4.1", + "dependencies": [ + "_fe_analyzer_shared", + "collection", + "convert", + "crypto", + "glob", + "meta", + "package_config", + "path", + "pub_semver", + "source_span", + "watcher", + "yaml" + ] + }, + { + "name": "back_button_interceptor", + "version": "7.0.3", + "dependencies": [ + "collection", + "flutter" + ] + }, + { + "name": "url_launcher_platform_interface", + "version": "2.3.2", + "dependencies": [ + "flutter", + "plugin_platform_interface" + ] + }, + { + "name": "url_launcher_linux", + "version": "3.2.2", + "dependencies": [ + "flutter", + "url_launcher_platform_interface" + ] + }, + { + "name": "url_launcher_windows", + "version": "3.1.5", + "dependencies": [ + "flutter", + "url_launcher_platform_interface" + ] + }, + { + "name": "url_launcher_web", + "version": "2.4.2", + "dependencies": [ + "flutter", + "flutter_web_plugins", + "url_launcher_platform_interface", + "web" + ] + }, + { + "name": "share_plus_platform_interface", + "version": "6.1.0", + "dependencies": [ + "cross_file", + "flutter", + "meta", + "mime", + "path_provider", + "plugin_platform_interface", + "uuid" + ] + }, + { + "name": "mime", + "version": "2.0.0", + "dependencies": [] + }, + { + "name": "cross_file", + "version": "0.3.5+2", + "dependencies": [ + "meta", + "web" + ] + }, + { + "name": "http_parser", + "version": "4.1.2", + "dependencies": [ + "collection", + "source_span", + "string_scanner", + "typed_data" + ] + }, + { + "name": "local_auth_windows", + "version": "1.0.11", + "dependencies": [ + "flutter", + "local_auth_platform_interface" + ] + }, + { + "name": "local_auth_platform_interface", + "version": "1.1.0", + "dependencies": [ + "flutter", + "plugin_platform_interface" + ] + }, + { + "name": "local_auth_darwin", + "version": "1.6.1", + "dependencies": [ + "flutter", + "intl", + "local_auth_platform_interface" + ] + }, + { + "name": "local_auth_android", + "version": "1.0.56", + "dependencies": [ + "flutter", + "flutter_plugin_android_lifecycle", + "intl", + "local_auth_platform_interface" + ] + }, + { + "name": "vector_graphics_compiler", + "version": "1.1.20", + "dependencies": [ + "args", + "meta", + "path", + "path_parsing", + "vector_graphics_codec", + "xml" + ] + }, + { + "name": "vector_graphics_codec", + "version": "1.1.13", + "dependencies": [] + }, + { + "name": "vector_graphics", + "version": "1.1.19", + "dependencies": [ + "flutter", + "http", + "vector_graphics_codec" + ] + }, + { + "name": "flutter_plugin_android_lifecycle", + "version": "2.0.33", + "dependencies": [ + "flutter" + ] + }, + { + "name": "camera_web", + "version": "0.3.5+3", + "dependencies": [ + "camera_platform_interface", + "flutter", + "flutter_web_plugins", + "stream_transform", + "web" + ] + }, + { + "name": "camera_platform_interface", + "version": "2.12.0", + "dependencies": [ + "cross_file", + "flutter", + "plugin_platform_interface", + "stream_transform" + ] + }, + { + "name": "camera_avfoundation", + "version": "0.9.23+2", + "dependencies": [ + "camera_platform_interface", + "flutter", + "stream_transform" + ] + }, + { + "name": "camera_android", + "version": "0.10.10+14", + "dependencies": [ + "camera_platform_interface", + "flutter", + "flutter_plugin_android_lifecycle", + "stream_transform" + ] + }, + { + "name": "permission_handler_platform_interface", + "version": "4.3.0", + "dependencies": [ + "flutter", + "meta", + "plugin_platform_interface" + ] + }, + { + "name": "permission_handler_windows", + "version": "0.2.1", + "dependencies": [ + "flutter", + "permission_handler_platform_interface" + ] + }, + { + "name": "permission_handler_html", + "version": "0.1.3+5", + "dependencies": [ + "flutter", + "flutter_web_plugins", + "permission_handler_platform_interface", + "web" + ] + }, + { + "name": "permission_handler_apple", + "version": "9.4.7", + "dependencies": [ + "flutter", + "permission_handler_platform_interface" + ] + }, + { + "name": "permission_handler_android", + "version": "12.1.0", + "dependencies": [ + "flutter", + "permission_handler_platform_interface" + ] + }, + { + "name": "hive", + "version": "2.2.3", + "dependencies": [ + "crypto", + "meta" + ] + }, + { + "name": "sky_engine", + "version": "0.0.0", + "dependencies": [] + }, + { + "name": "material_color_utilities", + "version": "0.11.1", + "dependencies": [ + "collection" + ] + }, + { + "name": "characters", + "version": "1.4.0", + "dependencies": [] + }, + { + "name": "leak_tracker_testing", + "version": "3.0.2", + "dependencies": [ + "leak_tracker", + "matcher", + "meta" + ] + }, + { + "name": "leak_tracker", + "version": "11.0.2", + "dependencies": [ + "clock", + "collection", + "meta", + "path", + "vm_service" + ] + }, + { + "name": "term_glyph", + "version": "1.2.2", + "dependencies": [] + }, + { + "name": "string_scanner", + "version": "1.4.1", + "dependencies": [ + "source_span" + ] + }, + { + "name": "source_span", + "version": "1.10.2", + "dependencies": [ + "collection", + "path", + "term_glyph" + ] + }, + { + "name": "boolean_selector", + "version": "2.1.2", + "dependencies": [ + "source_span", + "string_scanner" + ] + }, + { + "name": "typed_data", + "version": "1.4.0", + "dependencies": [ + "collection" + ] + }, + { + "name": "checked_yaml", + "version": "2.0.4", + "dependencies": [ + "json_annotation", + "source_span", + "yaml" + ] + }, + { + "name": "synchronized", + "version": "3.4.0", + "dependencies": [] + }, + { + "name": "validators2", + "version": "5.1.0", + "dependencies": [] + }, + { + "name": "uuid", + "version": "4.5.2", + "dependencies": [ + "crypto", + "fixnum", + "meta" + ] + }, + { + "name": "system_info2", + "version": "4.1.0", + "dependencies": [ + "globbing", + "path" + ] + }, + { + "name": "settings_yaml", + "version": "8.3.1", + "dependencies": [ + "collection", + "meta", + "path", + "uuid", + "yaml" + ] + }, + { + "name": "scope", + "version": "5.1.0", + "dependencies": [ + "meta" + ] + }, + { + "name": "pubspec_manager", + "version": "1.0.3", + "dependencies": [ + "meta", + "path", + "pub_semver", + "strings" + ] + }, + { + "name": "pubspec_lock", + "version": "3.0.2", + "dependencies": [ + "functional_data", + "json2yaml", + "meta", + "sum_types", + "yaml" + ] + }, + { + "name": "posix", + "version": "6.0.3", + "dependencies": [ + "ffi", + "meta", + "path" + ] + }, + { + "name": "native_synchronization_temp", + "version": "0.7.1", + "dependencies": [ + "ffi" + ] + }, + { + "name": "logging", + "version": "1.3.0", + "dependencies": [] + }, + { + "name": "ini", + "version": "2.1.0", + "dependencies": [] + }, + { + "name": "glob", + "version": "2.1.3", + "dependencies": [ + "async", + "collection", + "file", + "path", + "string_scanner" + ] + }, + { + "name": "equatable", + "version": "2.0.8", + "dependencies": [ + "collection", + "meta" + ] + }, + { + "name": "dcli_terminal", + "version": "6.1.2", + "dependencies": [ + "dart_console" + ] + }, + { + "name": "dcli_core", + "version": "6.1.2", + "dependencies": [ + "async", + "circular_buffer", + "collection", + "crypto", + "dcli_common", + "ffi", + "logging", + "meta", + "path", + "scope", + "stack_trace", + "uuid" + ] + }, + { + "name": "dcli_common", + "version": "6.1.2", + "dependencies": [ + "meta", + "path", + "scope" + ] + }, + { + "name": "dart_console", + "version": "4.1.2", + "dependencies": [ + "characters", + "ffi", + "intl", + "win32" + ] + }, + { + "name": "csv", + "version": "6.0.0", + "dependencies": [] + }, + { + "name": "chunked_stream", + "version": "1.4.2", + "dependencies": [ + "meta" + ] + }, + { + "name": "dbus", + "version": "0.7.12", + "dependencies": [ + "args", + "ffi", + "meta", + "xml" + ] + }, + { + "name": "petitparser", + "version": "7.0.2", + "dependencies": [ + "collection", + "meta" + ] + }, + { + "name": "platform", + "version": "3.1.6", + "dependencies": [] + }, + { + "name": "xdg_directories", + "version": "1.1.0", + "dependencies": [ + "meta", + "path" + ] + }, + { + "name": "objective_c", + "version": "9.3.0", + "dependencies": [ + "code_assets", + "collection", + "ffi", + "hooks", + "logging", + "native_toolchain_c", + "pub_semver" + ] + }, + { + "name": "package_config", + "version": "2.2.0", + "dependencies": [ + "path" + ] + }, + { + "name": "watcher", + "version": "1.2.1", + "dependencies": [ + "async", + "path" + ] + }, + { + "name": "_fe_analyzer_shared", + "version": "67.0.0", + "dependencies": [ + "meta" + ] + }, + { + "name": "path_parsing", + "version": "1.1.0", + "dependencies": [ + "meta", + "vector_math" + ] + }, + { + "name": "stream_transform", + "version": "2.1.1", + "dependencies": [] + }, + { + "name": "vm_service", + "version": "15.0.2", + "dependencies": [] + }, + { + "name": "fixnum", + "version": "1.1.1", + "dependencies": [] + }, + { + "name": "globbing", + "version": "1.0.0", + "dependencies": [ + "path" + ] + }, + { + "name": "strings", + "version": "3.1.2", + "dependencies": [ + "characters", + "unicode" + ] + }, + { + "name": "sum_types", + "version": "0.3.5", + "dependencies": [ + "meta" + ] + }, + { + "name": "json2yaml", + "version": "3.0.1", + "dependencies": [ + "meta" + ] + }, + { + "name": "functional_data", + "version": "1.2.0", + "dependencies": [ + "collection", + "meta" + ] + }, + { + "name": "circular_buffer", + "version": "0.12.0", + "dependencies": [] + }, + { + "name": "native_toolchain_c", + "version": "0.17.4", + "dependencies": [ + "code_assets", + "glob", + "hooks", + "logging", + "meta", + "pub_semver" + ] + }, + { + "name": "hooks", + "version": "1.0.1", + "dependencies": [ + "collection", + "crypto", + "logging", + "meta", + "pub_semver", + "yaml" + ] + }, + { + "name": "code_assets", + "version": "1.0.0", + "dependencies": [ + "collection", + "hooks" + ] + }, + { + "name": "unicode", + "version": "0.3.1", + "dependencies": [ + "lists" + ] + }, + { + "name": "lists", + "version": "1.0.1", + "dependencies": [ + "meta" + ] + } + ], + "configVersion": 1 +} \ No newline at end of file diff --git a/.dart_tool/version b/.dart_tool/version new file mode 100644 index 0000000..6a20a82 --- /dev/null +++ b/.dart_tool/version @@ -0,0 +1 @@ +3.38.7 \ No newline at end of file diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies new file mode 100644 index 0000000..483ad75 --- /dev/null +++ b/.flutter-plugins-dependencies @@ -0,0 +1 @@ +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"camera_avfoundation","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\camera_avfoundation-0.9.23+2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"connectivity_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\connectivity_plus-6.1.5\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\device_info_plus-10.1.2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_contacts","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_contacts-1.1.9+2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_keyboard_visibility","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_keyboard_visibility-6.0.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\fluttertoast-8.2.14\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\local_auth_darwin-1.6.1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"mobile_scanner","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\mobile_scanner-6.0.11\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.6.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"permission_handler_apple","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_apple-9.4.7\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"root_checker_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\root_checker_plus-0.0.7\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-12.0.1\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"camera_android","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\camera_android-0.10.10+14\\\\","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"connectivity_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\connectivity_plus-6.1.5\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\device_info_plus-10.1.2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_contacts","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_contacts-1.1.9+2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_keyboard_visibility","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_keyboard_visibility-6.0.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_plugin_android_lifecycle","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_plugin_android_lifecycle-2.0.33\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\fluttertoast-8.2.14\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"local_auth_android","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\local_auth_android-1.0.56\\\\","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"mobile_scanner","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\mobile_scanner-6.0.11\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.2.22\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"permission_handler_android","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_android-12.1.0\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"root_checker_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\root_checker_plus-0.0.7\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-12.0.1\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"connectivity_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\connectivity_plus-6.1.5\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\device_info_plus-10.1.2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"flutter_keyboard_visibility_macos","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_keyboard_visibility_macos-1.0.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"local_auth_darwin","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\local_auth_darwin-1.6.1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"mobile_scanner","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\mobile_scanner-6.0.11\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.6.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-12.0.1\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"connectivity_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\connectivity_plus-6.1.5\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\device_info_plus-10.1.2\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"flutter_keyboard_visibility_linux","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_keyboard_visibility_linux-1.0.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"C:\\\\Users\\\\samanwaqar\\\\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\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-12.0.1\\\\","native_build":false,"dependencies":["url_launcher_linux"],"dev_dependency":false},{"name":"url_launcher_linux","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_linux-3.2.2\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"connectivity_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\connectivity_plus-6.1.5\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\device_info_plus-10.1.2\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"flutter_keyboard_visibility_windows","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_keyboard_visibility_windows-1.0.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"local_auth_windows","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\local_auth_windows-1.0.11\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"C:\\\\Users\\\\samanwaqar\\\\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\\\\samanwaqar\\\\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\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-12.0.1\\\\","native_build":true,"dependencies":["url_launcher_windows"],"dev_dependency":false},{"name":"url_launcher_windows","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_windows-3.1.5\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"web":[{"name":"camera_web","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\camera_web-0.3.5+3\\\\","dependencies":[],"dev_dependency":false},{"name":"connectivity_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\connectivity_plus-6.1.5\\\\","dependencies":[],"dev_dependency":false},{"name":"device_info_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\device_info_plus-10.1.2\\\\","dependencies":[],"dev_dependency":false},{"name":"flutter_keyboard_visibility_web","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_keyboard_visibility_web-2.0.0\\\\","dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\fluttertoast-8.2.14\\\\","dependencies":[],"dev_dependency":false},{"name":"mobile_scanner","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\mobile_scanner-6.0.11\\\\","dependencies":[],"dev_dependency":false},{"name":"permission_handler_html","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\permission_handler_html-0.1.3+5\\\\","dependencies":[],"dev_dependency":false},{"name":"share_plus","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\share_plus-12.0.1\\\\","dependencies":["url_launcher_web"],"dev_dependency":false},{"name":"url_launcher_web","path":"C:\\\\Users\\\\samanwaqar\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_web-2.4.2\\\\","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"camera","dependencies":["camera_android","camera_avfoundation","camera_web","flutter_plugin_android_lifecycle"]},{"name":"camera_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"camera_avfoundation","dependencies":[]},{"name":"camera_web","dependencies":[]},{"name":"connectivity_plus","dependencies":[]},{"name":"device_info_plus","dependencies":[]},{"name":"flutter_camera_overlay_new","dependencies":["camera"]},{"name":"flutter_contacts","dependencies":[]},{"name":"flutter_keyboard_visibility","dependencies":["flutter_keyboard_visibility_linux","flutter_keyboard_visibility_macos","flutter_keyboard_visibility_web","flutter_keyboard_visibility_windows"]},{"name":"flutter_keyboard_visibility_linux","dependencies":[]},{"name":"flutter_keyboard_visibility_macos","dependencies":[]},{"name":"flutter_keyboard_visibility_web","dependencies":[]},{"name":"flutter_keyboard_visibility_windows","dependencies":[]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"fluttertoast","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":"mobile_scanner","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":"root_checker_plus","dependencies":[]},{"name":"share_plus","dependencies":["url_launcher_web","url_launcher_windows","url_launcher_linux"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2026-02-19 10:21:40.359562","version":"3.38.7","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..04b285e --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,19 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Flutter +.dart_tool/ +build/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ + +# Android +android/.gradle/ +android/local.properties + +# iOS +ios/Pods/ +ios/.symlinks/ diff --git a/.idea/caches/deviceStreaming.xml b/.idea/caches/deviceStreaming.xml new file mode 100644 index 0000000..5c94783 --- /dev/null +++ b/.idea/caches/deviceStreaming.xml @@ -0,0 +1,1414 @@ + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml new file mode 100644 index 0000000..0442d0e --- /dev/null +++ b/.idea/libraries/Dart_Packages.xml @@ -0,0 +1,1532 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Dart_SDK.xml b/.idea/libraries/Dart_SDK.xml new file mode 100644 index 0000000..0218bad --- /dev/null +++ b/.idea/libraries/Dart_SDK.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Flutter_Plugins.xml b/.idea/libraries/Flutter_Plugins.xml new file mode 100644 index 0000000..b4235ba --- /dev/null +++ b/.idea/libraries/Flutter_Plugins.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 4c38193..f4fe1c8 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,5 @@ - - + \ No newline at end of file diff --git a/.idea/uco-mobile-poc.iml b/.idea/uco-mobile-poc.iml index d6ebd48..d327551 100644 --- a/.idea/uco-mobile-poc.iml +++ b/.idea/uco-mobile-poc.iml @@ -2,8 +2,15 @@ - + + + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index bdbb48d..46c390f 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -16,9 +16,9 @@ - + { + "associatedIndex": 8 +} ", + "io.flutter.project.isFirstOpen": "true", + "io.flutter.reload.alreadyRun": "true", + "kotlin-language-version-configured": "true", + "last_opened_file_path": "C:/Users/samanwaqar/Documents/GitHub/uco-mobile-poc", + "project.structure.last.edited": "Project", + "project.structure.proportion": "0.0", + "project.structure.side.proportion": "0.2", + "settings.editor.selected.configurable": "configurable.group.build", "show.migrate.to.gradle.popup": "false" } }]]> + + + + + + + + + + diff --git a/assets/.en b/assets/.en new file mode 100644 index 0000000..e69de29 diff --git a/assets/uco/icons/arrow.svg b/assets/uco/icons/arrow.svg new file mode 100644 index 0000000..711df5c --- /dev/null +++ b/assets/uco/icons/arrow.svg @@ -0,0 +1,94 @@ + + + + + + + diff --git a/assets/uco/icons/aud_flag.png b/assets/uco/icons/aud_flag.png new file mode 100644 index 0000000..fdf4da0 Binary files /dev/null and b/assets/uco/icons/aud_flag.png differ diff --git a/assets/uco/icons/bankDetails.svg b/assets/uco/icons/bankDetails.svg new file mode 100644 index 0000000..924a01c --- /dev/null +++ b/assets/uco/icons/bankDetails.svg @@ -0,0 +1,293 @@ + + + + + + + diff --git a/assets/uco/icons/changePassoword.svg b/assets/uco/icons/changePassoword.svg new file mode 100644 index 0000000..3945d28 --- /dev/null +++ b/assets/uco/icons/changePassoword.svg @@ -0,0 +1,238 @@ + + + + + + + diff --git a/assets/uco/icons/drop_down_ic.png b/assets/uco/icons/drop_down_ic.png new file mode 100644 index 0000000..0cda291 Binary files /dev/null and b/assets/uco/icons/drop_down_ic.png differ diff --git a/assets/uco/icons/euro_flag.png b/assets/uco/icons/euro_flag.png new file mode 100644 index 0000000..9d0fb03 Binary files /dev/null and b/assets/uco/icons/euro_flag.png differ diff --git a/assets/uco/icons/gbp_flag.png b/assets/uco/icons/gbp_flag.png new file mode 100644 index 0000000..640d145 Binary files /dev/null and b/assets/uco/icons/gbp_flag.png differ diff --git a/assets/uco/icons/ic_QR.png b/assets/uco/icons/ic_QR.png new file mode 100644 index 0000000..90e01e7 Binary files /dev/null and b/assets/uco/icons/ic_QR.png differ diff --git a/assets/uco/icons/ic_QR.svg b/assets/uco/icons/ic_QR.svg new file mode 100644 index 0000000..353dfc0 --- /dev/null +++ b/assets/uco/icons/ic_QR.svg @@ -0,0 +1,340 @@ + + + + + + + diff --git a/assets/uco/icons/ic_activation.svg b/assets/uco/icons/ic_activation.svg new file mode 100644 index 0000000..06cd521 --- /dev/null +++ b/assets/uco/icons/ic_activation.svg @@ -0,0 +1,317 @@ + + + + + + + diff --git a/assets/uco/icons/ic_activity.svg b/assets/uco/icons/ic_activity.svg new file mode 100644 index 0000000..b006868 --- /dev/null +++ b/assets/uco/icons/ic_activity.svg @@ -0,0 +1,164 @@ + + + + + + + diff --git a/assets/uco/icons/ic_add.svg b/assets/uco/icons/ic_add.svg new file mode 100644 index 0000000..012f6a3 --- /dev/null +++ b/assets/uco/icons/ic_add.svg @@ -0,0 +1,92 @@ + + + + + + + diff --git a/assets/uco/icons/ic_add_new_Account.png b/assets/uco/icons/ic_add_new_Account.png new file mode 100644 index 0000000..7f4899c Binary files /dev/null and b/assets/uco/icons/ic_add_new_Account.png differ diff --git a/assets/uco/icons/ic_arrow_down.svg b/assets/uco/icons/ic_arrow_down.svg new file mode 100644 index 0000000..2d06387 --- /dev/null +++ b/assets/uco/icons/ic_arrow_down.svg @@ -0,0 +1,102 @@ + + + + + + + diff --git a/assets/uco/icons/ic_arrow_down_icon.png b/assets/uco/icons/ic_arrow_down_icon.png new file mode 100644 index 0000000..27e3719 Binary files /dev/null and b/assets/uco/icons/ic_arrow_down_icon.png differ diff --git a/assets/uco/icons/ic_back_arrow_appbar.svg b/assets/uco/icons/ic_back_arrow_appbar.svg new file mode 100644 index 0000000..b90d2db --- /dev/null +++ b/assets/uco/icons/ic_back_arrow_appbar.svg @@ -0,0 +1,253 @@ + + + + + + + diff --git a/assets/uco/icons/ic_back_white.svg b/assets/uco/icons/ic_back_white.svg new file mode 100644 index 0000000..01780e5 --- /dev/null +++ b/assets/uco/icons/ic_back_white.svg @@ -0,0 +1,78 @@ + + + + + + + diff --git a/assets/uco/icons/ic_bank_transfer.svg b/assets/uco/icons/ic_bank_transfer.svg new file mode 100644 index 0000000..cbf40e0 --- /dev/null +++ b/assets/uco/icons/ic_bank_transfer.svg @@ -0,0 +1,218 @@ + + + + + + + diff --git a/assets/uco/icons/ic_bill.svg b/assets/uco/icons/ic_bill.svg new file mode 100644 index 0000000..da95543 --- /dev/null +++ b/assets/uco/icons/ic_bill.svg @@ -0,0 +1,160 @@ + + + + + + + diff --git a/assets/uco/icons/ic_call.svg b/assets/uco/icons/ic_call.svg new file mode 100644 index 0000000..64ca357 --- /dev/null +++ b/assets/uco/icons/ic_call.svg @@ -0,0 +1,234 @@ + + + + + + + diff --git a/assets/uco/icons/ic_camera.svg b/assets/uco/icons/ic_camera.svg new file mode 100644 index 0000000..824e6ec --- /dev/null +++ b/assets/uco/icons/ic_camera.svg @@ -0,0 +1,451 @@ + + + + + + + diff --git a/assets/uco/icons/ic_camera_profile.svg b/assets/uco/icons/ic_camera_profile.svg new file mode 100644 index 0000000..fa91a70 --- /dev/null +++ b/assets/uco/icons/ic_camera_profile.svg @@ -0,0 +1,242 @@ + + + + + + + diff --git a/assets/uco/icons/ic_chat.svg b/assets/uco/icons/ic_chat.svg new file mode 100644 index 0000000..91a660b --- /dev/null +++ b/assets/uco/icons/ic_chat.svg @@ -0,0 +1,225 @@ + + + + + + + diff --git a/assets/uco/icons/ic_check_status.svg b/assets/uco/icons/ic_check_status.svg new file mode 100644 index 0000000..cd3c3ea --- /dev/null +++ b/assets/uco/icons/ic_check_status.svg @@ -0,0 +1,181 @@ + + + + + + + diff --git a/assets/uco/icons/ic_cheque_deposit.svg b/assets/uco/icons/ic_cheque_deposit.svg new file mode 100644 index 0000000..94b8b01 --- /dev/null +++ b/assets/uco/icons/ic_cheque_deposit.svg @@ -0,0 +1,185 @@ + + + + + + + diff --git a/assets/uco/icons/ic_cheque_management.svg b/assets/uco/icons/ic_cheque_management.svg new file mode 100644 index 0000000..56dc9c8 --- /dev/null +++ b/assets/uco/icons/ic_cheque_management.svg @@ -0,0 +1,117 @@ + + + + + + + diff --git a/assets/uco/icons/ic_chnage_pin.svg b/assets/uco/icons/ic_chnage_pin.svg new file mode 100644 index 0000000..55585ab --- /dev/null +++ b/assets/uco/icons/ic_chnage_pin.svg @@ -0,0 +1,269 @@ + + + + + + + diff --git a/assets/uco/icons/ic_client.png b/assets/uco/icons/ic_client.png new file mode 100644 index 0000000..6ae5613 Binary files /dev/null and b/assets/uco/icons/ic_client.png differ diff --git a/assets/uco/icons/ic_client.svg b/assets/uco/icons/ic_client.svg new file mode 100644 index 0000000..f639234 --- /dev/null +++ b/assets/uco/icons/ic_client.svg @@ -0,0 +1,303 @@ + + + + + + + diff --git a/assets/uco/icons/ic_clock_circle.svg b/assets/uco/icons/ic_clock_circle.svg new file mode 100644 index 0000000..c2d051b --- /dev/null +++ b/assets/uco/icons/ic_clock_circle.svg @@ -0,0 +1,151 @@ + + + + + + + diff --git a/assets/uco/icons/ic_congratulation.svg b/assets/uco/icons/ic_congratulation.svg new file mode 100644 index 0000000..5d08598 --- /dev/null +++ b/assets/uco/icons/ic_congratulation.svg @@ -0,0 +1,456 @@ + + + + + + + diff --git a/assets/uco/icons/ic_congratulations!.svg b/assets/uco/icons/ic_congratulations!.svg new file mode 100644 index 0000000..b306cea --- /dev/null +++ b/assets/uco/icons/ic_congratulations!.svg @@ -0,0 +1,343 @@ + + + + + + + diff --git a/assets/uco/icons/ic_contact_us.png b/assets/uco/icons/ic_contact_us.png new file mode 100644 index 0000000..cdacc44 Binary files /dev/null and b/assets/uco/icons/ic_contact_us.png differ diff --git a/assets/uco/icons/ic_contact_us.svg b/assets/uco/icons/ic_contact_us.svg new file mode 100644 index 0000000..f896a59 --- /dev/null +++ b/assets/uco/icons/ic_contact_us.svg @@ -0,0 +1,429 @@ + + + + + + + diff --git a/assets/uco/icons/ic_credit.svg b/assets/uco/icons/ic_credit.svg new file mode 100644 index 0000000..fe98f01 --- /dev/null +++ b/assets/uco/icons/ic_credit.svg @@ -0,0 +1,117 @@ + + + + + + + diff --git a/assets/uco/icons/ic_credit_card_bills.svg b/assets/uco/icons/ic_credit_card_bills.svg new file mode 100644 index 0000000..eea7150 --- /dev/null +++ b/assets/uco/icons/ic_credit_card_bills.svg @@ -0,0 +1,144 @@ + + + + + + + diff --git a/assets/uco/icons/ic_cross.svg b/assets/uco/icons/ic_cross.svg new file mode 100644 index 0000000..67cdbe8 --- /dev/null +++ b/assets/uco/icons/ic_cross.svg @@ -0,0 +1,165 @@ + + + + + + + diff --git a/assets/uco/icons/ic_cross_option.svg b/assets/uco/icons/ic_cross_option.svg new file mode 100644 index 0000000..bc8ef87 --- /dev/null +++ b/assets/uco/icons/ic_cross_option.svg @@ -0,0 +1,140 @@ + + + + + + + diff --git a/assets/uco/icons/ic_cross_white.svg b/assets/uco/icons/ic_cross_white.svg new file mode 100644 index 0000000..af9e31d --- /dev/null +++ b/assets/uco/icons/ic_cross_white.svg @@ -0,0 +1,113 @@ + + + + + + + diff --git a/assets/uco/icons/ic_current_account_arrow.svg b/assets/uco/icons/ic_current_account_arrow.svg new file mode 100644 index 0000000..b690338 --- /dev/null +++ b/assets/uco/icons/ic_current_account_arrow.svg @@ -0,0 +1,160 @@ + + + + + + + diff --git a/assets/uco/icons/ic_customer_service.svg b/assets/uco/icons/ic_customer_service.svg new file mode 100644 index 0000000..84bb24b --- /dev/null +++ b/assets/uco/icons/ic_customer_service.svg @@ -0,0 +1,159 @@ + + + + + + + diff --git a/assets/uco/icons/ic_cyber_security.svg b/assets/uco/icons/ic_cyber_security.svg new file mode 100644 index 0000000..6177c76 --- /dev/null +++ b/assets/uco/icons/ic_cyber_security.svg @@ -0,0 +1,437 @@ + + + + + + + diff --git a/assets/uco/icons/ic_daily_transaction.svg b/assets/uco/icons/ic_daily_transaction.svg new file mode 100644 index 0000000..3682ec3 --- /dev/null +++ b/assets/uco/icons/ic_daily_transaction.svg @@ -0,0 +1,324 @@ + + + + + + + diff --git a/assets/uco/icons/ic_debit.svg b/assets/uco/icons/ic_debit.svg new file mode 100644 index 0000000..39d481b --- /dev/null +++ b/assets/uco/icons/ic_debit.svg @@ -0,0 +1,110 @@ + + + + + + + diff --git a/assets/uco/icons/ic_debit_card.svg b/assets/uco/icons/ic_debit_card.svg new file mode 100644 index 0000000..4ba4a47 --- /dev/null +++ b/assets/uco/icons/ic_debit_card.svg @@ -0,0 +1,176 @@ + + + + + + + diff --git a/assets/uco/icons/ic_desposit_account_arrow.svg b/assets/uco/icons/ic_desposit_account_arrow.svg new file mode 100644 index 0000000..e3f7937 --- /dev/null +++ b/assets/uco/icons/ic_desposit_account_arrow.svg @@ -0,0 +1,144 @@ + + + + + + + diff --git a/assets/uco/icons/ic_device_management.svg b/assets/uco/icons/ic_device_management.svg new file mode 100644 index 0000000..3ed645e --- /dev/null +++ b/assets/uco/icons/ic_device_management.svg @@ -0,0 +1,319 @@ + + + + + + + diff --git a/assets/uco/icons/ic_dollar_symbol.svg b/assets/uco/icons/ic_dollar_symbol.svg new file mode 100644 index 0000000..6e89e61 --- /dev/null +++ b/assets/uco/icons/ic_dollar_symbol.svg @@ -0,0 +1,120 @@ + + + + + + + diff --git a/assets/uco/icons/ic_download.svg b/assets/uco/icons/ic_download.svg new file mode 100644 index 0000000..42a019d --- /dev/null +++ b/assets/uco/icons/ic_download.svg @@ -0,0 +1,136 @@ + + + + + + + diff --git a/assets/uco/icons/ic_electricity.png b/assets/uco/icons/ic_electricity.png new file mode 100644 index 0000000..7e13f54 Binary files /dev/null and b/assets/uco/icons/ic_electricity.png differ diff --git a/assets/uco/icons/ic_email.svg b/assets/uco/icons/ic_email.svg new file mode 100644 index 0000000..82e310e --- /dev/null +++ b/assets/uco/icons/ic_email.svg @@ -0,0 +1,246 @@ + + + + + + + diff --git a/assets/uco/icons/ic_filter_statement.svg b/assets/uco/icons/ic_filter_statement.svg new file mode 100644 index 0000000..1f82d5a --- /dev/null +++ b/assets/uco/icons/ic_filter_statement.svg @@ -0,0 +1,76 @@ + + + + + + + diff --git a/assets/uco/icons/ic_finger_print.svg b/assets/uco/icons/ic_finger_print.svg new file mode 100644 index 0000000..c248d87 --- /dev/null +++ b/assets/uco/icons/ic_finger_print.svg @@ -0,0 +1,361 @@ + + + + + + + diff --git a/assets/uco/icons/ic_fingerprint.svg b/assets/uco/icons/ic_fingerprint.svg new file mode 100644 index 0000000..ec175fc --- /dev/null +++ b/assets/uco/icons/ic_fingerprint.svg @@ -0,0 +1,645 @@ + + + + + + + diff --git a/assets/uco/icons/ic_gas.png b/assets/uco/icons/ic_gas.png new file mode 100644 index 0000000..baa1cbd Binary files /dev/null and b/assets/uco/icons/ic_gas.png differ diff --git a/assets/uco/icons/ic_general_ledger.svg b/assets/uco/icons/ic_general_ledger.svg new file mode 100644 index 0000000..3a68a42 --- /dev/null +++ b/assets/uco/icons/ic_general_ledger.svg @@ -0,0 +1,246 @@ + + + + + + + diff --git a/assets/uco/icons/ic_government.png b/assets/uco/icons/ic_government.png new file mode 100644 index 0000000..716a165 Binary files /dev/null and b/assets/uco/icons/ic_government.png differ diff --git a/assets/uco/icons/ic_holding_money.svg b/assets/uco/icons/ic_holding_money.svg new file mode 100644 index 0000000..e49bd5f --- /dev/null +++ b/assets/uco/icons/ic_holding_money.svg @@ -0,0 +1,360 @@ + + + + + + + diff --git a/assets/uco/icons/ic_home_icon.svg b/assets/uco/icons/ic_home_icon.svg new file mode 100644 index 0000000..c9805ee --- /dev/null +++ b/assets/uco/icons/ic_home_icon.svg @@ -0,0 +1,143 @@ + + + + + + + diff --git a/assets/uco/icons/ic_internet.png b/assets/uco/icons/ic_internet.png new file mode 100644 index 0000000..a703cad Binary files /dev/null and b/assets/uco/icons/ic_internet.png differ diff --git a/assets/uco/icons/ic_internet.svg b/assets/uco/icons/ic_internet.svg new file mode 100644 index 0000000..9752e43 --- /dev/null +++ b/assets/uco/icons/ic_internet.svg @@ -0,0 +1,471 @@ + + + + + + + diff --git a/assets/uco/icons/ic_isb.png b/assets/uco/icons/ic_isb.png new file mode 100644 index 0000000..d3dbd6f Binary files /dev/null and b/assets/uco/icons/ic_isb.png differ diff --git a/assets/uco/icons/ic_karachi.png b/assets/uco/icons/ic_karachi.png new file mode 100644 index 0000000..ab5f353 Binary files /dev/null and b/assets/uco/icons/ic_karachi.png differ diff --git a/assets/uco/icons/ic_kc.png b/assets/uco/icons/ic_kc.png new file mode 100644 index 0000000..fc3b0a6 Binary files /dev/null and b/assets/uco/icons/ic_kc.png differ diff --git a/assets/uco/icons/ic_ke.png b/assets/uco/icons/ic_ke.png new file mode 100644 index 0000000..a07e744 Binary files /dev/null and b/assets/uco/icons/ic_ke.png differ diff --git a/assets/uco/icons/ic_khan.png b/assets/uco/icons/ic_khan.png new file mode 100644 index 0000000..b681155 Binary files /dev/null and b/assets/uco/icons/ic_khan.png differ diff --git a/assets/uco/icons/ic_kprogresshud_spinner.png b/assets/uco/icons/ic_kprogresshud_spinner.png new file mode 100644 index 0000000..1291fac Binary files /dev/null and b/assets/uco/icons/ic_kprogresshud_spinner.png differ diff --git a/assets/uco/icons/ic_kyc_unverified.svg b/assets/uco/icons/ic_kyc_unverified.svg new file mode 100644 index 0000000..13a8680 --- /dev/null +++ b/assets/uco/icons/ic_kyc_unverified.svg @@ -0,0 +1,116 @@ + + + + + + + diff --git a/assets/uco/icons/ic_language.svg b/assets/uco/icons/ic_language.svg new file mode 100644 index 0000000..8103335 --- /dev/null +++ b/assets/uco/icons/ic_language.svg @@ -0,0 +1,289 @@ + + + + + + + diff --git a/assets/uco/icons/ic_link.png b/assets/uco/icons/ic_link.png new file mode 100644 index 0000000..6e00808 Binary files /dev/null and b/assets/uco/icons/ic_link.png differ diff --git a/assets/uco/icons/ic_location.svg b/assets/uco/icons/ic_location.svg new file mode 100644 index 0000000..1846090 --- /dev/null +++ b/assets/uco/icons/ic_location.svg @@ -0,0 +1,217 @@ + + + + + + + diff --git a/assets/uco/icons/ic_log_out.svg b/assets/uco/icons/ic_log_out.svg new file mode 100644 index 0000000..92aa3f3 --- /dev/null +++ b/assets/uco/icons/ic_log_out.svg @@ -0,0 +1,275 @@ + + + + + + + diff --git a/assets/uco/icons/ic_logout.svg b/assets/uco/icons/ic_logout.svg new file mode 100644 index 0000000..31256e4 --- /dev/null +++ b/assets/uco/icons/ic_logout.svg @@ -0,0 +1,130 @@ + + + + + + + diff --git a/assets/uco/icons/ic_manage_account.svg b/assets/uco/icons/ic_manage_account.svg new file mode 100644 index 0000000..1346f93 --- /dev/null +++ b/assets/uco/icons/ic_manage_account.svg @@ -0,0 +1,346 @@ + + + + + + + diff --git a/assets/uco/icons/ic_menu_bar.svg b/assets/uco/icons/ic_menu_bar.svg new file mode 100644 index 0000000..91d0af6 --- /dev/null +++ b/assets/uco/icons/ic_menu_bar.svg @@ -0,0 +1,73 @@ + + + + + + + diff --git a/assets/uco/icons/ic_money_management.svg b/assets/uco/icons/ic_money_management.svg new file mode 100644 index 0000000..c66f9d8 --- /dev/null +++ b/assets/uco/icons/ic_money_management.svg @@ -0,0 +1,262 @@ + + + + + + + diff --git a/assets/uco/icons/ic_multan.png b/assets/uco/icons/ic_multan.png new file mode 100644 index 0000000..31fd012 Binary files /dev/null and b/assets/uco/icons/ic_multan.png differ diff --git a/assets/uco/icons/ic_next.svg b/assets/uco/icons/ic_next.svg new file mode 100644 index 0000000..3b7020b --- /dev/null +++ b/assets/uco/icons/ic_next.svg @@ -0,0 +1,84 @@ + + + + + + + diff --git a/assets/uco/icons/ic_notifactions.svg b/assets/uco/icons/ic_notifactions.svg new file mode 100644 index 0000000..ea573bb --- /dev/null +++ b/assets/uco/icons/ic_notifactions.svg @@ -0,0 +1,142 @@ + + + + + + + diff --git a/assets/uco/icons/ic_notification_filter.svg b/assets/uco/icons/ic_notification_filter.svg new file mode 100644 index 0000000..8535a07 --- /dev/null +++ b/assets/uco/icons/ic_notification_filter.svg @@ -0,0 +1,83 @@ + + + + + + + diff --git a/assets/uco/icons/ic_pakistan.png b/assets/uco/icons/ic_pakistan.png new file mode 100644 index 0000000..5778eba Binary files /dev/null and b/assets/uco/icons/ic_pakistan.png differ diff --git a/assets/uco/icons/ic_person_setting.svg b/assets/uco/icons/ic_person_setting.svg new file mode 100644 index 0000000..e5cc6a2 --- /dev/null +++ b/assets/uco/icons/ic_person_setting.svg @@ -0,0 +1,194 @@ + + + + + + + diff --git a/assets/uco/icons/ic_phone.svg b/assets/uco/icons/ic_phone.svg new file mode 100644 index 0000000..b3a8b29 --- /dev/null +++ b/assets/uco/icons/ic_phone.svg @@ -0,0 +1,491 @@ + + + + + + + diff --git a/assets/uco/icons/ic_phone_bottom_sheet.svg b/assets/uco/icons/ic_phone_bottom_sheet.svg new file mode 100644 index 0000000..19a7520 --- /dev/null +++ b/assets/uco/icons/ic_phone_bottom_sheet.svg @@ -0,0 +1,474 @@ + + + + + + + diff --git a/assets/uco/icons/ic_qr_setting.svg b/assets/uco/icons/ic_qr_setting.svg new file mode 100644 index 0000000..8204123 --- /dev/null +++ b/assets/uco/icons/ic_qr_setting.svg @@ -0,0 +1,277 @@ + + + + + + + diff --git a/assets/uco/icons/ic_receiving_money.svg b/assets/uco/icons/ic_receiving_money.svg new file mode 100644 index 0000000..f77d07a --- /dev/null +++ b/assets/uco/icons/ic_receiving_money.svg @@ -0,0 +1,481 @@ + + + + + + + diff --git a/assets/uco/icons/ic_request.svg b/assets/uco/icons/ic_request.svg new file mode 100644 index 0000000..bac79e8 --- /dev/null +++ b/assets/uco/icons/ic_request.svg @@ -0,0 +1,315 @@ + + + + + + + diff --git a/assets/uco/icons/ic_search.svg b/assets/uco/icons/ic_search.svg new file mode 100644 index 0000000..5e0aaf0 --- /dev/null +++ b/assets/uco/icons/ic_search.svg @@ -0,0 +1,104 @@ + + + + + + + diff --git a/assets/uco/icons/ic_security.png b/assets/uco/icons/ic_security.png new file mode 100644 index 0000000..9a3c90d Binary files /dev/null and b/assets/uco/icons/ic_security.png differ diff --git a/assets/uco/icons/ic_select_contact.svg b/assets/uco/icons/ic_select_contact.svg new file mode 100644 index 0000000..b658f1c --- /dev/null +++ b/assets/uco/icons/ic_select_contact.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/uco/icons/ic_setting.svg b/assets/uco/icons/ic_setting.svg new file mode 100644 index 0000000..28d93c1 --- /dev/null +++ b/assets/uco/icons/ic_setting.svg @@ -0,0 +1,291 @@ + + + + + + + diff --git a/assets/uco/icons/ic_share.svg b/assets/uco/icons/ic_share.svg new file mode 100644 index 0000000..77b20d2 --- /dev/null +++ b/assets/uco/icons/ic_share.svg @@ -0,0 +1,261 @@ + + + + + + + diff --git a/assets/uco/icons/ic_share_qr.svg b/assets/uco/icons/ic_share_qr.svg new file mode 100644 index 0000000..4873e3b --- /dev/null +++ b/assets/uco/icons/ic_share_qr.svg @@ -0,0 +1,129 @@ + + + + + + + diff --git a/assets/uco/icons/ic_snding_money.svg b/assets/uco/icons/ic_snding_money.svg new file mode 100644 index 0000000..a776adc --- /dev/null +++ b/assets/uco/icons/ic_snding_money.svg @@ -0,0 +1,363 @@ + + + + + + + diff --git a/assets/uco/icons/ic_sort.png b/assets/uco/icons/ic_sort.png new file mode 100644 index 0000000..507212e Binary files /dev/null and b/assets/uco/icons/ic_sort.png differ diff --git a/assets/uco/icons/ic_stop.svg b/assets/uco/icons/ic_stop.svg new file mode 100644 index 0000000..d59daac --- /dev/null +++ b/assets/uco/icons/ic_stop.svg @@ -0,0 +1,118 @@ + + + + + + + diff --git a/assets/uco/icons/ic_sub_accounts.svg b/assets/uco/icons/ic_sub_accounts.svg new file mode 100644 index 0000000..2e69d4f --- /dev/null +++ b/assets/uco/icons/ic_sub_accounts.svg @@ -0,0 +1,239 @@ + + + + + + + diff --git a/assets/uco/icons/ic_tick.svg b/assets/uco/icons/ic_tick.svg new file mode 100644 index 0000000..e792fa6 --- /dev/null +++ b/assets/uco/icons/ic_tick.svg @@ -0,0 +1,96 @@ + + + + + + + diff --git a/assets/uco/icons/ic_tick_option.svg b/assets/uco/icons/ic_tick_option.svg new file mode 100644 index 0000000..3fc28dd --- /dev/null +++ b/assets/uco/icons/ic_tick_option.svg @@ -0,0 +1,150 @@ + + + + + + + diff --git a/assets/uco/icons/ic_u_cash.svg b/assets/uco/icons/ic_u_cash.svg new file mode 100644 index 0000000..71e5d11 --- /dev/null +++ b/assets/uco/icons/ic_u_cash.svg @@ -0,0 +1,186 @@ + + + + + + + diff --git a/assets/uco/icons/ic_u_receive_menu.svg b/assets/uco/icons/ic_u_receive_menu.svg new file mode 100644 index 0000000..397ccc1 --- /dev/null +++ b/assets/uco/icons/ic_u_receive_menu.svg @@ -0,0 +1,221 @@ + + + + + + + diff --git a/assets/uco/icons/ic_u_recive.svg b/assets/uco/icons/ic_u_recive.svg new file mode 100644 index 0000000..2608645 --- /dev/null +++ b/assets/uco/icons/ic_u_recive.svg @@ -0,0 +1,181 @@ + + + + + + + diff --git a/assets/uco/icons/ic_u_shop.svg b/assets/uco/icons/ic_u_shop.svg new file mode 100644 index 0000000..0e11c73 --- /dev/null +++ b/assets/uco/icons/ic_u_shop.svg @@ -0,0 +1,174 @@ + + + + + + + diff --git a/assets/uco/icons/ic_user.svg b/assets/uco/icons/ic_user.svg new file mode 100644 index 0000000..0852680 --- /dev/null +++ b/assets/uco/icons/ic_user.svg @@ -0,0 +1,216 @@ + + + + + + + diff --git a/assets/uco/icons/ic_utility_bills.svg b/assets/uco/icons/ic_utility_bills.svg new file mode 100644 index 0000000..8f0813b --- /dev/null +++ b/assets/uco/icons/ic_utility_bills.svg @@ -0,0 +1,269 @@ + + + + + + + diff --git a/assets/uco/icons/ic_voice.svg b/assets/uco/icons/ic_voice.svg new file mode 100644 index 0000000..1df121b --- /dev/null +++ b/assets/uco/icons/ic_voice.svg @@ -0,0 +1,116 @@ + + + + + + + diff --git a/assets/uco/icons/ic_wallet.svg b/assets/uco/icons/ic_wallet.svg new file mode 100644 index 0000000..ce25941 --- /dev/null +++ b/assets/uco/icons/ic_wallet.svg @@ -0,0 +1,217 @@ + + + + + + + diff --git a/assets/uco/icons/ic_warning.png b/assets/uco/icons/ic_warning.png new file mode 100644 index 0000000..d2c8afa Binary files /dev/null and b/assets/uco/icons/ic_warning.png differ diff --git a/assets/uco/icons/ic_water.png b/assets/uco/icons/ic_water.png new file mode 100644 index 0000000..94c64c8 Binary files /dev/null and b/assets/uco/icons/ic_water.png differ diff --git a/assets/uco/icons/ic_wise_card.svg b/assets/uco/icons/ic_wise_card.svg new file mode 100644 index 0000000..195538b --- /dev/null +++ b/assets/uco/icons/ic_wise_card.svg @@ -0,0 +1,254 @@ + + + + + + + diff --git a/assets/uco/icons/ind_flag.png b/assets/uco/icons/ind_flag.png new file mode 100644 index 0000000..7d4fd0d Binary files /dev/null and b/assets/uco/icons/ind_flag.png differ diff --git a/assets/uco/icons/inviteFriendsUco.svg b/assets/uco/icons/inviteFriendsUco.svg new file mode 100644 index 0000000..d8e68ab --- /dev/null +++ b/assets/uco/icons/inviteFriendsUco.svg @@ -0,0 +1,321 @@ + + + + + + + diff --git a/assets/uco/icons/sending_icon.svg b/assets/uco/icons/sending_icon.svg new file mode 100644 index 0000000..a94f461 --- /dev/null +++ b/assets/uco/icons/sending_icon.svg @@ -0,0 +1,435 @@ + + + + + + + diff --git a/assets/uco/icons/usa.png b/assets/uco/icons/usa.png new file mode 100644 index 0000000..9de5283 Binary files /dev/null and b/assets/uco/icons/usa.png differ diff --git a/assets/uco/icons/use_flag.png b/assets/uco/icons/use_flag.png new file mode 100644 index 0000000..ca0eadd Binary files /dev/null and b/assets/uco/icons/use_flag.png differ diff --git a/assets/uco/images/im_qr.png b/assets/uco/images/im_qr.png new file mode 100644 index 0000000..505235a Binary files /dev/null and b/assets/uco/images/im_qr.png differ diff --git a/assets/uco/images/img_country_flag.png b/assets/uco/images/img_country_flag.png new file mode 100644 index 0000000..3649412 Binary files /dev/null and b/assets/uco/images/img_country_flag.png differ diff --git a/assets/uco/images/img_country_flag.svg b/assets/uco/images/img_country_flag.svg new file mode 100644 index 0000000..47f462b --- /dev/null +++ b/assets/uco/images/img_country_flag.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/uco/images/img_debet.png b/assets/uco/images/img_debet.png new file mode 100644 index 0000000..b9ff4bf Binary files /dev/null and b/assets/uco/images/img_debet.png differ diff --git a/assets/uco/images/img_global.svg b/assets/uco/images/img_global.svg new file mode 100644 index 0000000..60095d5 --- /dev/null +++ b/assets/uco/images/img_global.svg @@ -0,0 +1,6789 @@ + + + + + + + diff --git a/assets/uco/images/img_intro_slider_1.png b/assets/uco/images/img_intro_slider_1.png new file mode 100644 index 0000000..40bd2c2 Binary files /dev/null and b/assets/uco/images/img_intro_slider_1.png differ diff --git a/assets/uco/images/img_intro_slider_2.png b/assets/uco/images/img_intro_slider_2.png new file mode 100644 index 0000000..3389cc1 Binary files /dev/null and b/assets/uco/images/img_intro_slider_2.png differ diff --git a/assets/uco/images/img_round_dashboard_card.png b/assets/uco/images/img_round_dashboard_card.png new file mode 100644 index 0000000..073a222 Binary files /dev/null and b/assets/uco/images/img_round_dashboard_card.png differ diff --git a/assets/uco/images/img_slider.svg b/assets/uco/images/img_slider.svg new file mode 100644 index 0000000..e7ff970 --- /dev/null +++ b/assets/uco/images/img_slider.svg @@ -0,0 +1,4901 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/uco/logo/ic_dashboard_logo.svg b/assets/uco/logo/ic_dashboard_logo.svg new file mode 100644 index 0000000..0fa0a6c --- /dev/null +++ b/assets/uco/logo/ic_dashboard_logo.svg @@ -0,0 +1,942 @@ + + + + + + + diff --git a/assets/uco/logo/ic_launcher.png b/assets/uco/logo/ic_launcher.png new file mode 100644 index 0000000..99993ae Binary files /dev/null and b/assets/uco/logo/ic_launcher.png differ diff --git a/assets/uco/logo/lg_back_arrow.svg b/assets/uco/logo/lg_back_arrow.svg new file mode 100644 index 0000000..5b6451f --- /dev/null +++ b/assets/uco/logo/lg_back_arrow.svg @@ -0,0 +1,151 @@ + + + + + + + diff --git a/assets/uco/logo/lg_dialog_logo.svg b/assets/uco/logo/lg_dialog_logo.svg new file mode 100644 index 0000000..53c412f --- /dev/null +++ b/assets/uco/logo/lg_dialog_logo.svg @@ -0,0 +1,1184 @@ + + + + + + + diff --git a/assets/uco/logo/lg_lunch_icon.svg b/assets/uco/logo/lg_lunch_icon.svg new file mode 100644 index 0000000..8fbe6c6 --- /dev/null +++ b/assets/uco/logo/lg_lunch_icon.svg @@ -0,0 +1,2720 @@ + + + + + + + diff --git a/assets/uco/logo/lg_mfsys.png b/assets/uco/logo/lg_mfsys.png new file mode 100644 index 0000000..02b25b4 Binary files /dev/null and b/assets/uco/logo/lg_mfsys.png differ diff --git a/assets/uco/logo/lg_uco_logo_white.svg b/assets/uco/logo/lg_uco_logo_white.svg new file mode 100644 index 0000000..f4fec68 --- /dev/null +++ b/assets/uco/logo/lg_uco_logo_white.svg @@ -0,0 +1,480 @@ + + + + + + + diff --git a/assets/uco/logo/shopping-cart.png b/assets/uco/logo/shopping-cart.png new file mode 100644 index 0000000..fad6fd4 Binary files /dev/null and b/assets/uco/logo/shopping-cart.png differ diff --git a/assets/uco/logo/uc-logo.png b/assets/uco/logo/uc-logo.png new file mode 100644 index 0000000..99993ae Binary files /dev/null and b/assets/uco/logo/uc-logo.png differ diff --git a/assets/uco/logo/uc_logo.png b/assets/uco/logo/uc_logo.png new file mode 100644 index 0000000..dfcc1d1 Binary files /dev/null and b/assets/uco/logo/uc_logo.png differ diff --git a/fonts/Inter-Black.ttf b/fonts/Inter-Black.ttf new file mode 100644 index 0000000..e69de29 diff --git a/fonts/Inter-Bold.ttf b/fonts/Inter-Bold.ttf new file mode 100644 index 0000000..e69de29 diff --git a/fonts/Inter-ExtraBold.ttf b/fonts/Inter-ExtraBold.ttf new file mode 100644 index 0000000..e69de29 diff --git a/fonts/Inter-ExtraLight.ttf b/fonts/Inter-ExtraLight.ttf new file mode 100644 index 0000000..e69de29 diff --git a/fonts/Inter-Light.ttf b/fonts/Inter-Light.ttf new file mode 100644 index 0000000..e69de29 diff --git a/fonts/Inter-Medium.ttf b/fonts/Inter-Medium.ttf new file mode 100644 index 0000000..e69de29 diff --git a/fonts/Inter-Regular.ttf b/fonts/Inter-Regular.ttf new file mode 100644 index 0000000..e69de29 diff --git a/fonts/Inter-SemiBold.ttf b/fonts/Inter-SemiBold.ttf new file mode 100644 index 0000000..e69de29 diff --git a/fonts/Inter-Thin.ttf b/fonts/Inter-Thin.ttf new file mode 100644 index 0000000..e69de29 diff --git a/fonts/Poppins-Medium.ttf b/fonts/Poppins-Medium.ttf new file mode 100644 index 0000000..e69de29 diff --git a/fonts/Poppins-Regular.ttf b/fonts/Poppins-Regular.ttf new file mode 100644 index 0000000..e69de29 diff --git a/lib/app/bindings/dependency_injections.dart b/lib/app/bindings/dependency_injections.dart new file mode 100644 index 0000000..b62149f --- /dev/null +++ b/lib/app/bindings/dependency_injections.dart @@ -0,0 +1,26 @@ +import 'package:get/get.dart'; + +import '../core/data/data_source_auth/remote_data_source/app_remote_data_source.dart'; +import '../core/data/repositories/app_repositories.dart'; + + +class DependencysInjections implements Bindings { + @override + void dependencies() { + Get.put(AppRemoteDataSource()); + Get.put(AppRepositoriesImpl(remoteDataSource: Get.find())); + // Get.lazyPut(() => SendPaymentController()); + // Get.lazyPut(() => FeedBackController()); + // Get.lazyPut(() => TransactionHistoryController()); + // Get.lazyPut(() => ForgetPasswordController()); + // Get.lazyPut(() => BeneficiaryDetailsController()); + // Get.lazyPut(() => FingerPrintController()); + // Get.lazyPut(() => ChangePasswordController()); + // Get.lazyPut(() => LoginController()); + // Get.lazyPut(() => TermAndConditionsController()); + // Get.lazyPut(() => ProfileSettingsController()); + // Get.lazyPut(() => SendPaymentController()); + // Get.lazyPut(() => LoanTransactionHistoryController()); + // Get.lazyPut(() => LocaleController()); + } +} diff --git a/lib/app/core/config/api_utils.dart b/lib/app/core/config/api_utils.dart new file mode 100644 index 0000000..6c542f5 --- /dev/null +++ b/lib/app/core/config/api_utils.dart @@ -0,0 +1,60 @@ +import 'package:dio/dio.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; + +import '../constants/translation_keys.dart'; + + + +class ApiUtils { + static bool isHeaderRequired = false; + + static ServerResponse parseServerResponse(Response response) { + return ServerResponse(response.data.toString().isEmpty ? {} : response.data, false, "", "", response.statusCode!); + } + // static void parseError(ServerResponse responseModel, Response response) { + // Map errorResponse = response.data; + // String errCode = errorResponse.containsKey("errorCode") ? errorResponse["errorCode"] : ""; + // dynamic arguments = errorResponse.containsKey("arguments") ? errorResponse["arguments"] : []; + // responseModel.setErrorMsg(replaceArguments(arguments, TranslationKeys.makeTranslation(errCode))); + // responseModel.setErrorCode(errCode); + // responseModel.setResponse(response.data); + // } + static void parseError(ServerResponse responseModel, Response response) { + dynamic data = response.data; + Map errorResponse = {}; + if (data is Map) { + errorResponse = data; + } + else if (data is String) { + responseModel.setErrorMsg(data); + responseModel.setErrorCode(""); + responseModel.setResponse(data); + return; + } + else { + responseModel.setErrorMsg("Something went wrong"); + responseModel.setErrorCode(""); + responseModel.setResponse(data); + return; + } + String errCode = errorResponse.containsKey("errorCode") ? errorResponse["errorCode"] ?? "" : ""; + dynamic arguments = errorResponse.containsKey("arguments") ? errorResponse["arguments"] ?? [] : []; + responseModel.setErrorMsg(replaceArguments(arguments, TranslationKeys.makeTranslation(errCode),),); + responseModel.setErrorCode(errCode); + responseModel.setResponse(data); + } + + + static String replaceArguments(List? argumentsArray, String errorString) { + if (argumentsArray == null){ + return errorString; + } + for (int i = 0; i < argumentsArray.length; i++) { + int indexToReplace = i + 1; + String valueToReplace = "\\{\\{*value$indexToReplace\\}\\}"; + String replacement = (argumentsArray[i] ?? "").toString(); + errorString = errorString.replaceAll(RegExp(valueToReplace), replacement); + } + return errorString; + } +} diff --git a/lib/app/core/config/connectivity_service.dart b/lib/app/core/config/connectivity_service.dart new file mode 100644 index 0000000..e46f385 --- /dev/null +++ b/lib/app/core/config/connectivity_service.dart @@ -0,0 +1,46 @@ +import 'dart:async'; + +import 'package:connectivity_plus/connectivity_plus.dart'; + +import '../utils/logs_utils.dart'; + +class ConnectivityHelper { + final Connectivity _connectivity = Connectivity(); + + late StreamSubscription> _subscription; + + static bool isNetworkConnected = false; + + checkNetworkConnectivity() async { + initConnectivity(); + _subscription = _connectivity.onConnectivityChanged.listen(_updateConnectionStatus); + } + + disposeConnectivity() { + _subscription.cancel(); + } + + Future initConnectivity() async { + List result; + try { + result = await _connectivity.checkConnectivity(); + } catch (e) { + result = [ConnectivityResult.none]; + } + _updateConnectionStatus(result); + } + + void _updateConnectionStatus(List result) { + dp("Connectivity result is", result); + result.forEach( + (e) { + if (e == ConnectivityResult.none || e == ConnectivityResult.bluetooth || e == ConnectivityResult.other) { + isNetworkConnected = false; + } else { + isNetworkConnected = true; + } + }, + ); + } + +} diff --git a/lib/app/core/config/dio_exceptions.dart b/lib/app/core/config/dio_exceptions.dart new file mode 100644 index 0000000..181b91b --- /dev/null +++ b/lib/app/core/config/dio_exceptions.dart @@ -0,0 +1,93 @@ +import 'package:dio/dio.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; + +import '../utils/logs_utils.dart'; +import 'api_utils.dart'; + + +class DioExceptions { + static String errorMsg = ""; + static int statusCode = -1; + + static ServerResponse responseModel = + ServerResponse({}, true, "", errorMsg, statusCode); + + static ServerResponse parseError(DioError dioError) { + // + + dp("============================================", dioError); + + pe("Error response", dioError.response); + statusCode = dioError.response?.statusCode ?? -1; + responseModel.setStatusCode(statusCode); + switch (dioError.type) { + case DioErrorType.cancel: + errorMsg = "Request to API server was cancelled"; + break; + case DioErrorType.connectTimeout: + errorMsg = "Connection timeout with API server"; + break; + case DioErrorType.receiveTimeout: + errorMsg = "Receive timeout in connection with API server"; + break; + case DioErrorType.response: + _handleError(dioError.response); + break; + case DioErrorType.sendTimeout: + errorMsg = "Send timeout in connection with API server"; + break; + case DioErrorType.other: + if (dioError.message.contains("SocketException")) { + errorMsg = 'No Internet'; + break; + } + errorMsg = "Unexpected error occurred"; + break; + default: + errorMsg = "Something went wrong"; + break; + } + + return responseModel; + } + + static void _handleError(dynamic error) { + switch (statusCode) { + case 400: + { + ApiUtils.parseError(responseModel, error); + } + break; + case 401: + { + responseModel.setErrorMsg("Unauthorized"); + } + break; + case 403: + { + responseModel.setErrorMsg("Forbidden"); + } + break; + case 404: + { + responseModel.setResponse(error['message']); + } + break; + case 500: + { + responseModel.setErrorMsg("Something went wrong, please try again"); + } + break; + case 502: + { + responseModel.setErrorMsg("Bad gateway"); + } + break; + default: + { + responseModel + .setErrorMsg("Oops something went wrong, please try again"); + } + } + } +} diff --git a/lib/app/core/config/error_message_model.dart b/lib/app/core/config/error_message_model.dart new file mode 100644 index 0000000..833a5e6 --- /dev/null +++ b/lib/app/core/config/error_message_model.dart @@ -0,0 +1,41 @@ +// To parse this JSON data, do +// +// final errorMessageModel = errorMessageModelFromJson(jsonString); + +import 'dart:convert'; + +ErrorMessageModel errorMessageModelFromJson(String str) => ErrorMessageModel.fromJson(json.decode(str)); + +String errorMessageModelToJson(ErrorMessageModel data) => json.encode(data.toJson()); + +class ErrorMessageModel { + final DateTime? timestamp; + final String? debugMessage; + final dynamic trackingId; + final String? errorCode; + final List? arguments; + + ErrorMessageModel({ + this.timestamp, + this.debugMessage, + this.trackingId, + this.errorCode, + this.arguments, + }); + + factory ErrorMessageModel.fromJson(Map json) => ErrorMessageModel( + timestamp: json["timestamp"] == null ? null : DateTime.parse(json["timestamp"]), + debugMessage: json["debugMessage"], + trackingId: json["trackingId"], + errorCode: json["errorCode"], + arguments: json["arguments"] == null ? [] : List.from(json["arguments"]!.map((x) => x)), + ); + + Map toJson() => { + "timestamp": timestamp?.toIso8601String(), + "debugMessage": debugMessage, + "trackingId": trackingId, + "errorCode": errorCode, + "arguments": arguments == null ? [] : List.from(arguments!.map((x) => x)), + }; +} diff --git a/lib/app/core/config/logging.dart b/lib/app/core/config/logging.dart new file mode 100644 index 0000000..e4b7fb3 --- /dev/null +++ b/lib/app/core/config/logging.dart @@ -0,0 +1,52 @@ +import 'package:dio/dio.dart'; +import 'package:uco_mobile_poc/app/core/config/requset_attr.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import '../dialogs/custom_loading.dart'; +import '../utils/logs_utils.dart'; +import 'api_utils.dart'; + +class Logging extends Interceptor { + late RequestAttr requestAttr; + + Logging(this.requestAttr); + + @override + void onRequest(RequestOptions options, RequestInterceptorHandler handler) { + showLoader(); + + // refresh token if expired + if (ApiUtils.isHeaderRequired) { + // options.headers['Authorization'] = 'Bearer $API_KEY'; + } + + print( + "request_data =>> TYPE: ${options.method}\n" + requestAttr.toString()); + + return super.onRequest(options, handler); + } + + @override + void onResponse(Response response, ResponseInterceptorHandler handler) { + hideLoader(); + print("Response_SUCCESS =>> ${response.data.toString()}"); + return super.onResponse(response, handler); + } + + @override + void onError(DioError err, ErrorInterceptorHandler handler) { + hideLoader(); + dp("============Error Response", err.response); + ServerResponse response = ServerResponse.init(); + + ApiUtils.parseError(response, err.response!); + + pe("Response_ERROR =>> ", response.toString()); + + if (err.response != null) { + ServerResponse response = ServerResponse.init(); + ApiUtils.parseError(response, err.response!); + pe("Response_ERROR =>> ", response.toString()); + } + return super.onError(err, handler); + } +} diff --git a/lib/app/core/config/requset_attr.dart b/lib/app/core/config/requset_attr.dart new file mode 100644 index 0000000..9b88b4b --- /dev/null +++ b/lib/app/core/config/requset_attr.dart @@ -0,0 +1,40 @@ +import '../enums/http_methods.dart'; + +class RequestAttr { + String _url; + bool _isDialogRequired = true; + Map _headers = {}; + Map _queryParams = {}; + Map _pathParams = {}; + Map _body = {}; + HttpMethod _requestType; + + RequestAttr.withParamsAndBody(this._url, this._requestType, this._body, + [this._headers = const {}, + this._queryParams = const {}, + this._pathParams = const {}]); + + RequestAttr.withHeaderAndParams(this._url, this._requestType, + [this._headers = const {}, + this._queryParams = const {}, + this._pathParams = const {}]); + + @override + String toString() { + return 'RequestAttr{_url: $_url, _isDialogRequired: $_isDialogRequired, _headers: $_headers, _queryParams: $_queryParams, _pathParams: $_pathParams, _body: $_body, _requestType: $_requestType}'; + } + + HttpMethod get requestType => _requestType; + + Map get body => _body; + + Map get pathParams => _pathParams; + + Map get queryParams => _queryParams; + + Map get headers => _headers; + + bool get isDialogRequired => _isDialogRequired; + + String get url => _url; +} diff --git a/lib/app/core/config/server_request.dart b/lib/app/core/config/server_request.dart new file mode 100644 index 0000000..94064db --- /dev/null +++ b/lib/app/core/config/server_request.dart @@ -0,0 +1,121 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:dio/adapter.dart'; +import 'package:dio/dio.dart'; +import 'package:uco_mobile_poc/app/core/config/requset_attr.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; + +import '../constants/translation_keys.dart'; +import '../utils/logs_utils.dart'; +import 'api_utils.dart'; +import 'connectivity_service.dart'; +import 'dio_exceptions.dart'; +import 'logging.dart'; + +class ServerRequest { + static Future request(RequestAttr requestAttr) async { + /// Internet Connectivity Check + if (!ConnectivityHelper.isNetworkConnected) { + ServerResponse serverResponse = ServerResponse.init(); + serverResponse.isError = true; + serverResponse.errorCode = "ERR_CONNECTION"; + serverResponse.errorMsg = TranslationKeys.makeTranslation(TranslationKeys.ERR_CONNECTION); + return serverResponse; + } + + _initRequest(requestAttr); + + try { + dp("============request Before>>>> ", requestAttr.toString()); + + final response = await _requestDio.request( + requestAttr.url, + options: Options( + method: requestAttr.requestType.name, + headers: requestAttr.headers, + ), + queryParameters: requestAttr.queryParams, + data: requestAttr.body, + ); + + dp("============after Before>>>> ", response.toString()); + + return ApiUtils.parseServerResponse(response); + } on DioError catch (e) { + ServerResponse response = DioExceptions.parseError(e); + // if (response.statusCode == 401) { + // return refreshToken(requestAttr); + // } + pe("============catch Before>>>> ", e.toString()); + pe("Error responce", e.response); + return DioExceptions.parseError(e); + } + } + + static late Dio _requestDio; + static late BaseOptions _baseOptions; + + static void _initRequest(RequestAttr attr) { + _baseOptions = BaseOptions(baseUrl: attr.url, connectTimeout: 15000, receiveTimeout: 9000); + _baseOptions.contentType = Headers.jsonContentType; + + if (attr.headers.isNotEmpty) { + _baseOptions.headers.addAll(attr.headers); + } + + if (attr.queryParams.isNotEmpty) { + _baseOptions.queryParameters.addAll(attr.queryParams); + } + + _requestDio = Dio(_baseOptions); + _requestDio.interceptors.add(Logging(attr)); + _requestDio.interceptors.add(InterceptorsWrapper( + onResponse: (Response response, ResponseInterceptorHandler handler) { + // Create a new response object without headers + final newResponse = Response( + requestOptions: response.requestOptions, + data: response.data, + statusCode: response.statusCode, + statusMessage: response.statusMessage, + ); + return handler.resolve(newResponse); + }, + )); + _requestDio.transformer = DefaultTransformer(); + + (_requestDio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) { + client.badCertificateCallback = (X509Certificate cert, String host, int port) => true; + return client; + }; + } + +// static Future refreshToken(RequestAttr requestAttr) async { +// RefreshTokenRequestModel userInfo = RefreshTokenRequestModel( +// porOrgacode: SessionCache.instance.userInfo.porOrgacode, +// pctCstycode: SessionCache.instance.userInfo.pctCstycode, +// cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, +// cmpUserId: SessionCache.instance.userInfo.cmpUserId, +// token: SessionCache.instance.userInfo.jwtToken, +// ); +// +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// // headers["Devicename"] = "Mobile"; +// +// ServerResponse refreshTokenResponse = await ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.REFRESH_TOKEN, HttpMethod.POST, userInfo.toMap(), headers, {})); +// String token = refreshTokenResponse.response["token"] ?? ""; +// if (token.isEmpty) { +// Toasty.error("Session timeout, Signing out..."); +// Get.offAllNamed(Routes.LOGIN); +// return ServerResponse.init(); +// } +// +// SessionCache.instance.userInfo.jwtToken = token; +// if (requestAttr.headers.containsKey("Authorization")) { +// requestAttr.headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// } +// return await ServerRequest.request(requestAttr); +// } +} diff --git a/lib/app/core/config/server_response.dart b/lib/app/core/config/server_response.dart new file mode 100644 index 0000000..eb37a76 --- /dev/null +++ b/lib/app/core/config/server_response.dart @@ -0,0 +1,72 @@ +class ServerResponse { + dynamic response = {}; + bool isError = false; + String errorCode = ""; + String errorMsg = ""; + int statusCode = -1; + + ServerResponse(this.response, this.isError, this.errorCode, this.errorMsg, this.statusCode); + + ServerResponse.init() { + response = {}; + isError = false; + errorCode = ""; + errorMsg = ""; + statusCode; + } + + Map toMap() { + return { + 'response': response, + 'isError': isError, + 'errorCode': errorCode, + 'errorMsg': errorMsg, + 'statusCode': statusCode, + }; + } + + factory ServerResponse.fromMap(Map map) { + return ServerResponse( + map['response'] as Map, + map['isError'] as bool, + map['errorCode'] ?? "", + map['errorMsg'] ?? "", + map['statusCode'] as int, + ); + } + + ServerResponse setStatusCode(int value) { + statusCode = value; + return this; + } + + ServerResponse setErrorMsg(String value) { + errorMsg = value; + return this; + } + + ServerResponse setErrorCode(String value) { + errorCode = value; + return this; + } + + ServerResponse setIsError(bool value) { + isError = value; + return this; + } + + // ServerResponse setResponse(Map value) { + // response = value; + // return this; + // } + ServerResponse setResponse(dynamic value) { + response = value; + return this; + } + + + @override + String toString() { + return 'ServerResponse{response: $response, isError: $isError, errorCode: $errorCode, errorMsg: $errorMsg, statusCode: $statusCode}'; + } +} diff --git a/lib/app/core/constants/PinType.dart b/lib/app/core/constants/PinType.dart new file mode 100644 index 0000000..da2902c --- /dev/null +++ b/lib/app/core/constants/PinType.dart @@ -0,0 +1,4 @@ +class PinType { + static String PIN_TYPE_SIGNUP = "01"; + static String PIN_TYPE_LOGIN = "02"; +} diff --git a/lib/app/core/constants/api_keys.dart b/lib/app/core/constants/api_keys.dart new file mode 100644 index 0000000..d1f0048 --- /dev/null +++ b/lib/app/core/constants/api_keys.dart @@ -0,0 +1,141 @@ +class ApiKeys { + + static const String cmpUserId = 'cmpUserId'; + static const String cmpCustpassword = 'cmpCustpassword'; + static const String channelCode = 'channelCode'; + static const String porOrgacode = 'porOrgacode'; + // static const String pctCstycode = 'pctCstycode'; + // static const String cmpIdennumber = 'cmpIdennumber'; + // static const String cmpUserIdType = 'cmpUserIdType'; + // static const String arguments = 'arguments'; + // static const String cmpAccountno = 'cmpAccountno'; + // static const String cmpCustcode = 'cmpCustcode'; + // static const String phoneNo = 'phoneNo'; + // static const String obpPincode = 'obpPincode'; + // static const String newCustpassword = 'newCustpassword'; + // static const String createdDate = 'sgtGntrCreatedAt'; + // static const String narration = 'sgtGntrNarration'; + // static const String deposit = 'deposit'; + // static const String withdrawl = 'withdrawl'; + // static const String balance = 'sgtGntramt'; + // static const String transcationDesc = 'ptrTrandesc'; + // static const String generateDate = 'sgtGntrdate'; + // static const String valueDate = 'sgtGntrvaluedate'; + // static const String amount = 'sgtGntramt'; + // static const String chargesDes = 'pchChrgdesc'; + // static const String porOrgaCodeDbName = 'POR_ORGACODE'; + // static const String porOrgaCodeVarName = 'porOrgacode'; + // static const String plcLocacodeDbName = 'PLC_LOCACODE'; + // static const String plcLocacodeVarNam = 'plcLocacode'; + // static const String requestIdDbName = 'REQUEST_ID'; + // static const String requestIdVarName = 'requestId'; + // static const String userIdDbName = 'USER_ID'; + // static const String userIdVarName = 'USER_ID'; + // static const String channelCodeDbName = 'CHANNEL_CODE'; + // static const String channelCodeVarNam = 'CHANNEL_CODE'; + // static const String accountInfoDbName = 'ACCOUNT_INFO'; + // static const String accountInfoVarName = 'accountInfo'; + // static const String dmpProdcodeDbName = 'DMP_PRODCODE'; + // static const String dmpProdcodeVarName = 'dmpProdcode'; + // static const String dcsSchemcodeDbName = 'DCS_SCHEMCODE'; + // static const String dcsSchemcodeVarName = 'dcsSchemcode'; + // static const String mbmBkmsnumberDbName = 'MBM_BKMSNUMBER'; + // static const String mbmBkmsnumberVarName = 'mbmBkmsnumber'; + // static const String ppcPrcgcodeDbName = 'PPC_PRCGCODE'; + // static const String ppcPrcgcodeVarName = 'ppcPrcgcode'; + // static const String mbmBkmstitleacntDbName = 'MBM_BKMSTITLEACNT'; + // static const String mbmBkmstitleacntVarName = 'mbmBkmstitleacnt'; + // static const String pcrCurrcodeDbName = 'PCR_CURRCODE'; + // static const String pcrCurrcodearName = 'pcrCurrcodear'; + // static const String mbmBkmsbalamountfcDbName = 'MBM_BKMSBALAMOUNTFC'; + // static const String mbmBkmsbalamountfcVarName = 'mbmBkmsbalamountfc'; + // static const String pasAcstcodeDbName = 'PAS_ACSTCODE'; + // static const String pasAcstcodeVarName = 'pasAcstcode'; + // static const String mbmBkmslienamountfcDbName = 'MBM_BKMSLIENAMOUNTFC'; + // static const String mbmBkmslienamountfcVarName = 'mbmBkmslienamountfc'; + // static const String blockedDbName = 'BLOCKED'; + // static const String blockedVarName = 'blocked'; + // static const String noOfTransactionDbName = 'NO_OF_TRANSACTION'; + // static const String noOfTransactiondVarName = 'noOfTransaction'; + // static const String noOfDaysDbName = 'NO_OF_DAYS'; + // static const String noOfDaysVarName = 'noOfDays'; + // static const String noOfMonthsDbName = 'NO_OF_MONTHS'; + // static const String noOfMonthsVarName = 'noOfMonths'; + // static const String fromDateDbName = 'FROM_DATE'; + // static const String fromDateVarName = 'fromDate'; + // static const String toDateDbName = 'TO_DATE'; + // static const String toDateVarName = 'toDate'; + // static const String sgtGntrdateDbName = 'SGT_GNTRDATE'; + // static const String sgtGntrdateVarName = 'sgtGntrdate'; + // static const String sgtGntrvaluedatDbName = 'SGT_GNTRVALUEDAT'; + // static const String sgtGntrvaluedatVarName = 'sgtGntrvaluedat'; + // static const String sgtGntrnumberDbName = 'SGT_GNTRNUMBER'; + // static const String sgtGntrnumberVarName = 'sgtGntrnumber'; + // static const String sgtGntrtimestampDbName = 'SGT_GNTRTIMESTAMP'; + // static const String sgtGntrtimestampVarName = 'sgtGntrtimestamp'; + // static const String transactionDetailInfoDbName = 'TRANSACTION_DETAIL_INFO'; + // static const String transactionDetailInfoVarName = 'transactionDetailInfo'; + // static const String ptrTrancodeDbName = 'PTR_TRANCODE'; + // static const String ptrTrancodeVarName = 'ptrTrancode'; + // static const String sgtGntrdrcrDbName = 'SGT_GNTRDRCR'; + // static const String sgtGntrdrcrVarName = 'sgtGntrdrcr'; + // static const String sgtGntramtfcDbName = 'SGT_GNTRAMTFC'; + // static const String sgtGntramtfcVarName =me = 'SGT_GNTRAMTFC1'; + // static const String sgtGntramtfc1VarName = 'sgtGntramtfc1'; + // static const String sgtGntram 'sgtGntramtfc'; + // static const String sgtGntramtfc1DbNatfc2DbName = 'SGT_GNTRAMTFC2'; + // static const String colorCodeDbName = 'COLOR_CODE'; + // static const String colorCodeVarName = 'colorCode'; + // static const String debitInfoDbName = 'DEBIT_INFO'; + // static const String debitInfoVarName = 'debitInfo'; + // static const String creditInfoDbName = 'CREDIT_INFO'; + // static const String creditInfoVarName = 'creditInfo'; + // static const String pinInfoDbName = 'PIN_INFO'; + // static const String pinInfoVarName = 'pinInfo'; + // static const String operationInfoDbName = 'OPERATION_INFO'; + // static const String operationInfoVarName = 'operationInfo'; + // static const String beneficiaryInfoDbName = 'BENEFICIARY_INFO'; + // static const String beneficiaryInfoVarName = 'beneficiaryInfo'; + // static const String pbtBntpcodeDbName = 'PBT_BNTPCODE'; + // static const String pbtBntpcodeVarName = 'pbtBntpcode'; + // static const String pbtBntpdescDbName = 'PBT_BNTPDESC'; + // static const String pbtBntpdescVarName = 'pbtBntpdesc'; + // static const String ibanDbName = 'IBAN'; + // static const String ibanVarName = 'IBAN'; + // static const String mobileDbName = 'MOBILE'; + // static const String mobileVarName = 'mobile'; + // static const String emailDbName = 'EMAIL'; + // static const String emailVarName = 'email'; + // static const String operationIdDbName = 'OPERATION_ID'; + // static const String operationIdVarName = 'operationId'; + // static const String creditedAtDbName = 'CREDITED_AT'; + // static const String creditedAtVarName = 'creditedAt'; + // static const String statusDbName = 'STATUS'; + // static const String statusVarName = 'status'; + // static const String reconciliationStatusDbName = 'RECONCILIATION_STATUS'; + // static const String reconciliationStatusVarName = 'reconciliationStatus'; + // static const String amountDbName = 'AMOUNT'; + // static const String amountVarName = 'amount'; + // static const String timeZoneDbName = 'TIME_ZONE'; + // static const String timeZoneVarName = 'timeZone'; + // static const String senderInfoDbName = 'SENDER_INFO'; + // static const String senderInfoVarName = 'senderInfo'; + // static const String receiverInfoDbName = 'RECEIVER_INFO'; + // static const String receiverInfoVarName = 'receiverInfo'; + // static const String nameDbName = 'NAME'; + // static const String nameVarName = 'name'; + // static const String idTypeDbName = 'ID_TYPE'; + // static const String idTypeVarName = 'idType'; + // static const String idValueDbName = 'ID_VALUE'; + // static const String idValueVarName = 'idValue'; + // static const String mobileNoDbName = 'MOBILE_NO'; + // static const String mobileNoVarName = 'mobileNo'; + // static const String passKeyDbName = 'PASS_KEY'; + // static const String passKeyVarName = 'passKey'; + // static const String passCodeDbName = 'PASS_CODE'; + // static const String passCodeVarName = 'passCode'; + // static const String pinCodeDbName = 'PIN_CODE'; + // static const String pinCodeVarName = 'pinCode'; + // static const String pinValueDbName = 'PIN_VALUE'; + // static const String pinValueVarName = 'pinValue'; +} diff --git a/lib/app/core/constants/app_assets.dart b/lib/app/core/constants/app_assets.dart new file mode 100644 index 0000000..7454051 --- /dev/null +++ b/lib/app/core/constants/app_assets.dart @@ -0,0 +1,141 @@ +class AppAssets { + static const String ORGANIZATION = "uco"; + + /// Logos + static const lg_uco_logo_white = "assets/$ORGANIZATION/logo/lg_uco_logo_white.svg"; + static const lg_logo_black = "assets/$ORGANIZATION/logo/lg_logo_black.svg"; + static const lg_mfsys = "assets/$ORGANIZATION/logo/lg_mfsys.png"; + static const lg_bank = "assets/$ORGANIZATION/logo/lg_bank.png"; + static const uc_logo = "assets/$ORGANIZATION/logo/uc_logo.png"; + static const ic_dashboard_logo = "assets/$ORGANIZATION/logo/ic_dashboard_logo.svg"; + static const lg_back_arrow = "assets/$ORGANIZATION/logo/lg_back_arrow.svg"; + static const u_receive = "assets/$ORGANIZATION/logo/u_receive.svg"; + static const u_send = "assets/$ORGANIZATION/logo/u_send.svg"; + static const u_shop = "assets/$ORGANIZATION/logo/u_shop.svg"; + static const ic_launcher = "assets/$ORGANIZATION/logo/ic_launcher.png"; + + /// Images + static const img_slider = "assets/$ORGANIZATION/images/img_slider.svg"; + static const img_global = "assets/${ORGANIZATION}/images/img_global.svg"; + static const img_qr = "assets/${ORGANIZATION}/images/im_qr.svg"; + + ///Icons ic_desposit_account_arrow + static const ic_pakistan = "assets/${ORGANIZATION}/icons/ic_pakistan.png"; + static const ic_arrow_down = "assets/${ORGANIZATION}/icons/ic_arrow_down.svg"; + static const ic_client = "assets/$ORGANIZATION/icons/ic_client.png"; + static const ic_contact_us = "assets/$ORGANIZATION/icons/ic_contact_us.png"; + static const ic_cyber_security = "assets/$ORGANIZATION/icons/ic_cyber_security.svg"; + static const ic_security = "assets/$ORGANIZATION/icons/ic_security.png"; + static const ic_QR = "assets/$ORGANIZATION/icons/ic_QR.png"; + static const ic_cross = "assets/$ORGANIZATION/icons/ic_cross.svg"; + static const ic_email = "assets/$ORGANIZATION/icons/ic_email.svg"; + static const ic_phone = "assets/$ORGANIZATION/icons/ic_phone.svg"; + static const ic_clock_circle = "assets/$ORGANIZATION/icons/ic_clock_circle.svg"; + static const ic_success_tick = "assets/$ORGANIZATION/icons/ic_success_tick.svg"; + + static const ic_cheque_management = "assets/$ORGANIZATION/icons/ic_cheque_management.svg"; + static const ic_activity = "assets/$ORGANIZATION/icons/ic_activity.svg"; + static const ic_close = "assets/$ORGANIZATION/icons/ic_close.svg"; + + // static const ic_customer_service = "assets/$ORGANIZATION/icons/ic_customer_service.svg"; + static const ic_location = "assets/$ORGANIZATION/icons/ic_location.svg"; + static const ic_logout = "assets/$ORGANIZATION/icons/ic_logout.svg"; + static const ic_management = "assets/$ORGANIZATION/icons/ic_management.svg"; + static const ic_money_management = "assets/$ORGANIZATION/icons/ic_money_management.svg"; + static const ic_night_mode = "assets/$ORGANIZATION/icons/ic_night_mode.svg"; + static const ic_setting = "assets/$ORGANIZATION/icons/ic_setting.svg"; + static const ic_social_network = "assets/$ORGANIZATION/icons/ic_social_network.svg"; + static const ic_u_send = "assets/$ORGANIZATION/icons/ic_u_send.svg"; + static const ic_user = "assets/$ORGANIZATION/icons/ic_user.svg"; + static const ic_white_color_user = "assets/$ORGANIZATION/icons/ic_white_color_user.svg"; + static const ic_person = "assets/$ORGANIZATION/icons/ic_user.svg"; + static const ic_accounts = "assets/$ORGANIZATION/icons/ic_accounts.svg"; + static const ic_cash_bottombar = "assets/$ORGANIZATION/icons/ic_cash_bottombar.svg"; + static const ic_shoping = "assets/$ORGANIZATION/icons/ic_shoping.svg"; + static const ic_money_send = "assets/$ORGANIZATION/icons/ic_money_send.svg"; + static const lg_dialog_logo = "assets/$ORGANIZATION/logo/lg_dialog_logo.svg"; + static const sending_icon = "assets/$ORGANIZATION/icons/sending_icon.svg"; + static const ic_snding_money = "assets/$ORGANIZATION/icons/ic_snding_money.svg"; + static const ic_u_cash = "assets/$ORGANIZATION/icons/ic_u_cash.svg"; + static const ic_u_recive = "assets/$ORGANIZATION/icons/ic_u_recive.svg"; + static const ic_u_shop = "assets/$ORGANIZATION/icons/ic_u_shop.svg"; + static const img_round_dashboard_card = "assets/$ORGANIZATION/images/img_round_dashboard_card.svg"; + static const img_debet = "assets/$ORGANIZATION/images/img_debet.svg"; + static const ic_camera = "assets/$ORGANIZATION/icons/ic_camera.svg"; + static const ic_next = "assets/$ORGANIZATION/icons/ic_next.svg"; + + static const ic_feature_icon = "assets/$ORGANIZATION/icons/ic_feature_icon.svg"; + static const ic_country_flag = "assets/$ORGANIZATION/icons/ic_country_flag.svg"; + static const ic_desposit_account_arrow = "assets/$ORGANIZATION/icons/ic_desposit_account_arrow.svg"; + static const ic_saving_account = "assets/$ORGANIZATION/icons/ic_saving_account.svg"; + static const ic_back_arrow_appbar = "assets/$ORGANIZATION/icons/ic_back_arrow_appbar.svg"; + + static const kprogresshud_spinner = "assets/uco/icons/ic_kprogresshud_spinner.png"; + + static const ic_electricity = "assets/${ORGANIZATION}/icons/ic_electricity.png"; + static const ic_gas = "assets/${ORGANIZATION}/icons/ic_gas.png"; + static const ic_internet = "assets/${ORGANIZATION}/icons/ic_internet.png"; + static const ic_ptcl = "assets/${ORGANIZATION}/icons/ic_ptcl.svg"; + static const ic_water = "assets/${ORGANIZATION}/icons/ic_water.png"; + static const ic_card = "assets/${ORGANIZATION}/icons/ic_card.svg"; + static const ic_government = "assets/${ORGANIZATION}/icons/ic_government.png"; + static const ic_multan = "assets/${ORGANIZATION}/icons/ic_multan.png"; + static const ic_khan = "assets/${ORGANIZATION}/icons/ic_khan.png"; + static const ic_ke = "assets/${ORGANIZATION}/icons/ic_ke.png"; + static const ic_kc = "assets/${ORGANIZATION}/icons/ic_kc.png"; + static const ic_removeImage = "assets/${ORGANIZATION}/icons/ic_removeImage.svg"; + static const ic_check_status = "assets/${ORGANIZATION}/icons/ic_check_status.svg"; + static const ic_cheque_deposit = "assets/${ORGANIZATION}/icons/ic_cheque_deposit.svg"; + static const ic_activation = "assets/${ORGANIZATION}/icons/ic_activation.svg"; + static const ic_request = "assets/${ORGANIZATION}/icons/ic_request.svg"; + static const ic_cheque = "assets/${ORGANIZATION}/icons/ic_cheque.svg"; + static const ic_download = "assets/${ORGANIZATION}/icons/ic_download.svg"; + static const ic_share = "assets/${ORGANIZATION}/icons/ic_share.svg"; + + static const arrow = "assets/$ORGANIZATION/icons/arrow.svg"; + static const ic_manage_account = "assets/$ORGANIZATION/icons/ic_manage_account.svg"; + static const bankDetails = "assets/$ORGANIZATION/icons/bankDetails.svg"; + static const changePassoword = "assets/$ORGANIZATION/icons/changePassoword.svg"; + static const inviteFriendsUco = "assets/$ORGANIZATION/icons/inviteFriendsUco.svg"; + static const personalDetails = "assets/$ORGANIZATION/icons/personal_details.svg"; + static const ic_sort = "assets/$ORGANIZATION/icons/ic_sort.png"; + static const ic_featured = "assets/$ORGANIZATION/icons/ic_featured.svg"; + static const ic_congratulations = "assets/$ORGANIZATION/icons/ic_congratulations.svg"; + static const ic_correct_icon = "assets/$ORGANIZATION/icons/ic_correct_icon.svg"; + + static const ic_arrow = "assets/$ORGANIZATION/icons/ic_arrow.svg"; + + static const icCloseDash = "assets/$ORGANIZATION/icons/_ic_close_dashboard.svg"; + + static String use_flag = "assets/$ORGANIZATION/icons/use_flag.png"; + + static String euro_flag = "assets/$ORGANIZATION/icons/euro_flag.png"; + static String gbp_flag = "assets/$ORGANIZATION/icons/gbp_flag.png"; + static String aud_flag = "assets/$ORGANIZATION/icons/aud_flag.png"; + static String ind_flag = "assets/$ORGANIZATION/icons/ind_flag.png"; + + static String drop_down_ic = "assets/uco/icons/drop_down_ic.png"; + static const ic_debit_card = "assets/$ORGANIZATION/icons/ic_debit_card.svg"; + static const ic_bank = "assets/$ORGANIZATION/icons/ic_bank.svg"; + static const ic_general_ledger = "assets/$ORGANIZATION/icons/ic_general_ledger.svg"; + static const ic_home_icon = "assets/$ORGANIZATION/icons/ic_home_icon.svg"; + static const ic_tick_option = "assets/$ORGANIZATION/icons/ic_tick_option.svg"; + static const ic_cross_option = "assets/$ORGANIZATION/icons/ic_cross_option.svg"; + + static var ic_sui_gas = "assets/$ORGANIZATION/icons/suigas.svg"; + static var ic_filter_statement = "assets/$ORGANIZATION/icons/ic_filter_statement.svg"; + static var ic_u_receive_menu = "assets/$ORGANIZATION/icons/ic_u_receive_menu.svg"; + static var ic_cross_white = "assets/$ORGANIZATION/icons/ic_cross_white.svg"; + static var ic_sub_accounts = "assets/$ORGANIZATION/icons/ic_sub_accounts.svg"; + static var sending_icon_icon = "assets/$ORGANIZATION/icons/sending_icon_icon.svg"; + static var bankAccountDetails = "assets/$ORGANIZATION/icons/bankAccountDetails.svg"; + static var ic_language = "assets/$ORGANIZATION/icons/ic_language.svg"; + static var ic_daily_transaction = "assets/$ORGANIZATION/icons/ic_daily_transaction.svg"; + static var ic_customer_service = "assets/$ORGANIZATION/icons/ic_customer_service.svg"; + static var ic_bill = "assets/$ORGANIZATION/icons/ic_bill.svg"; + static var ic_arrow_down_icon = "assets/$ORGANIZATION/icons/ic_arrow_down_icon.png"; + static var ic_select_contact = "assets/$ORGANIZATION/icons/ic_select_contact.svg"; + static var ic_bank_transfer = "assets/$ORGANIZATION/icons/ic_bank_transfer.svg"; + static var ic_add_new_Account = "assets/$ORGANIZATION/icons/ic_add_new_Account.png"; + static var ic_warning = "assets/$ORGANIZATION/icons/ic_warning.png"; +} diff --git a/lib/app/core/constants/app_contants.dart b/lib/app/core/constants/app_contants.dart new file mode 100644 index 0000000..0d48b08 --- /dev/null +++ b/lib/app/core/constants/app_contants.dart @@ -0,0 +1,88 @@ +class AppConstants { + + // Pin Type + static const String PIN_TYPE_SIGNUP = "01"; + static const String PIN_TYPE_LOGIN = "02"; + static const String PIN_TYPE_Transaction = "03"; + + + // User Role + static const String ROLE_USER = "USER"; + static const String ROLE_ADMIN = "ADMIN"; + + + // Identification type + static const String IDEN_TYPE_CNIC = "01"; + static const String IDEN_TYPE_PASSPORT = "02"; + static const String IDEN_TYPE_DRIVING_LICIENCE = "03"; + + + /// ------------------------- DashBoard Drawer + static const ID_CHANGE_THEME = "ID_CHANGE_THEME"; + static const ID_MY_ACCOUNT = "ID_MY_ACCOUNT"; + static const ID_BILL_MANAGEMENT = "ID_BILL_MANAGEMENT"; + static const ID_CHEQUE_MANAGEMENT = "ID_CHEQUE_MANAGEMENT"; + static const ID_U_SEND = "ID_U_SEND"; + static const ID_INTERNAL_TRANSACTION = "ID_INTERNAL_TRANSACTION"; + static const ID_BENEFICIARY_MANAGEMENT = "ID_BENEFICIARY_MANAGEMENT"; + static const ID_PROFILE = "ID_PROFILE"; + static const ID_AGENT_LOCATION = "ID_AGENT_LOCATION"; + static const ID_ACCOUNT_STATEMENT = "ID_ACCOUNT_STATEMENT"; + static const ID_SUPPORT = "ID_SUPPORT"; + static const ID_USER_ACTIVITY = "ID_USER_ACTIVITY"; + static const ID_LOGOUT = "ID_LOGOUT"; + static const ID_USER_PROFILE = "ID_USER_PROFILE"; + static const ID_APP_SETTING = "ID_APP_SETTING"; + static const ID_PRIVACY_POLICY = "ID_PRIVACY_POLICY"; + static const ID_VERSION = "ID_VERSION"; + static const SELECTED_LOCALE = "selectedLocale"; + static const SELECTED_CONTACT = "selectedContact"; + static const IS_RTL = "isRTL"; + static const ID_ABOUT_US = "ID_ABOUT_US"; + static const ID_CAREER = "ID_CAREER"; + + static var SIGN_UP_FIRST_STEP_DATA = "SIGN_UP_FIRST_STEP_DATA"; + static var SIGN_UP_SECOND_STEP_DATA = "SIGN_UP_SECOND_STEP_DATA"; + static const IS_DARK_MODE = "isDarkMode"; + static const IS_FINGER_PRINT_ENABLED = "isFingrPrinterEnabled"; + + + static const SEND_TRANS_STEP1_DATA = "SEND_TRANS_STEP1_DATA"; + static const SEND_TRANS_PIN_REQUEST = "SEND_TRANS_PIN_REQUEST"; + static const INTERNAL_TRANSACTION_PIN_REQUEST = "INTERNAL_TRANSACTION_PIN_REQUEST"; + static const EXCHANGE_RATE = "EXCHANGE_RATE"; + + /// Request constants + static const FETCH_ACCOUNT_DETAILS = "FETCH_ACCOUNT_DETAILS"; + static const SEND_TRANSACTION_STEP_1 = "SEND_TRANSACTION_STEP_1"; + static const SEND_TRANSACTION_STEP_2 = "SEND_TRANSACTION_STEP_2"; + static const ADD_NEW_BENEFICIARY = "ADD_NEW_BENEFICIARY"; + static const UPLOAD_USER_PROFILE_PICTURE = "UPLOAD_USER_PROFILE_PICTURE"; + static const GET_LOGIN_OTP = "GET_LOGIN_OTP"; + static const VALIDATE_LOGIN_PIN = "VALIDATE_LOGIN_PIN"; + static const FETCH_DEPOSITE_ACCOUNT_TRANSACTIONS = "FETCH_DEPOSITE_ACCOUNT_TRANSACTIONS"; + static const FETCH_EXCHANGE_RATE = "FETCH_EXCHANGE_RATE"; + static const FETCH_ACCOUNT_IQUIRY = "FETCH_ACCOUNT_IQUIRY"; + static const FETCH_ALL_BENEFICIARY = "FETCH_ALL_BENEFICIARY"; + static const DELETE_BENEFICIARY = "DELETE_BENEFICIARY"; + static const CREATE_TRANSACTION_PIN = "CREATE_TRANSACTION_PIN"; + static const CHANGE_TRANSACTION_PIN = "CHANGE_TRANSACTION_PIN"; + static const GENERATE_REPORTS = "GENERATE_REPORTS"; + static const SIGNUP_STEP_1 = "SIGNUP_STEP_1"; + static const SIGUP_STEP_2 = "SIGUP_STEP_2"; + static const SIGUP_STEP_3 = "SIGUP_STEP_3"; + static const CHANGE_PASSWORD_SEND_OTP = "CHANGE_PASSWORD_SEND_OTP"; + static const CHANGE_PASSWORD = "CHANGE_PASSWORD"; + static const GET_PENDING_TRANSITION = "GET_PENDING_TRANSITION"; + static const ACCEPT_RECEIVE_TRANSACTION = "ACCEPT_RECEIVE_TRANSACTION"; + static const REVERSE_TRANSACTION = "REVERSE_TRANSACTION"; + static const FETCH_ACCOUNT_STATEMENT = "FETCH_ACCOUNT_STATEMENT"; + static const DEVICE_NAME = "Mobile"; + static const FETCH_USER_ACTIVITY = "FETCH_USER_ACTIVITY"; + static const FETCH_DEPOSIT_PRODUCTS = "FETCH_DEPOSIT_PRODUCTS"; + static const FETCH_GLS_ACCOUNTS = "FETCH_GLS_ACCOUNTS"; + static const ADD_NEW_ACCOUNT = "ADD_NEW_ACCOUNT"; + static const CREATE_TRANSACTION_PIN_OTP = "CREATE_TRANSACTION_PIN_OTP"; + static const CHANGE_TRANSACTION_PIN_OTP = "CHANGE_TRANSACTION_PIN_OTP"; + +} diff --git a/lib/app/core/constants/form_field_constants.dart b/lib/app/core/constants/form_field_constants.dart new file mode 100644 index 0000000..22f677c --- /dev/null +++ b/lib/app/core/constants/form_field_constants.dart @@ -0,0 +1,30 @@ +import 'package:flutter/cupertino.dart'; + +class FormFieldConstants { + static FormFieldConstants instance() { + return _instance; + } + + static final FormFieldConstants _instance = FormFieldConstants._internal(); + + FormFieldConstants._internal(); + + factory FormFieldConstants() { + return _instance; + } + + final Map> _keys = {}; + final Map _controllers = {}; + + TextEditingController getController(String keyName) { + return _controllers[keyName] ??= TextEditingController(); // Assign if not exist + } + + GlobalKey getFormKey(String keyName) { + return _keys[keyName] ??= GlobalKey(); // Assign if not exist + } + void clearKeysForScreen(String screenPrefix) { + _keys.removeWhere((key, value) => key.startsWith(screenPrefix)); + _controllers.removeWhere((key, value) => key.startsWith(screenPrefix)); + } +} diff --git a/lib/app/core/constants/translation_keys.dart b/lib/app/core/constants/translation_keys.dart new file mode 100644 index 0000000..5affafd --- /dev/null +++ b/lib/app/core/constants/translation_keys.dart @@ -0,0 +1,344 @@ +import 'package:get/get.dart'; + +class TranslationKeys { + static String textUserActivityTitle = "textUserActivityTitle"; + static String textAddBeneficiary = "textAddBeneficiary"; + static String textWarningContent = "textWarningContent"; + + static String textUserActivityChannel = "textUserActivityChannel"; + static String textReferenceCode = "textReferenceCode"; + + static var textUserActivityDevice = "textUserActivityDevice"; + static var textInternetConnectivity = "textInternetConnectivity"; + static var textInternalAccountTransaction = "textInternalAccountTransaction"; + + static var textPay = "textPay"; + static var textTransferAmount = "textTransferAmount"; + static var textAddToBeneficiary = "textAddToBeneficiary"; + static var textDelete = "textDelete"; + + static String changepassword = "changepassword"; + static String textAddAccount = "textAddAccount"; + static String textCreateAccount = "textCreateAccount"; + static String textReverse = "textReverse"; + + static String textChangePassword = "textChangePassword"; + static String textEnterEmail = "textEnterEmail"; + static String textCongratulationsContent = "textCongratulationsContent"; + + static String textSelectFromDateAndProceed = "textSelectFromDateAndProceed"; + static String transPakGasAgency = "transPakGasAgency"; + static String transSuiGas = "transSuiGas"; + static String transMinerva = "transMinerva"; + static String transNestle = "transNestle"; + static String transAquaFujitenma = "transAquaFujitenma"; + static String transPepsiCo = "transPepsiCo"; + static String transFiber = "transFiber"; + static String transZong = "transZong"; + static String textPasswordPattern = "textPasswordPattern"; + static String textOurFee = "textOurFee"; + static String textTotalAmountWellConvert = "textTotalAmountWellConvert"; + static String textGuaranteedExchnageRate = "textGuaranteedExchnageRate"; + static String textSelectYourGLSAccount = "textSelectYourGLSAccount"; + static String textGlsAccounts = "textGlsAccounts"; + static String textEnterMessage = "textEnterMessage"; + + static String continueText = "Continue"; + static String ERR_CONNECTION = "ERR_CONNECTION"; + + static String makeTranslation(String key) { + return key.tr; + } + + static String textWelcomeToJoin = "textWelcomeToJoin"; + static String textShare = "textShare"; + static String textIntroDescription = "textIntroDescription"; + static String textLogin = "textLogin"; + static String textRegister = "textRegister"; + static String textFindUAgent = "textFindUAgent"; + static String textQRPay = "textQRPay"; + static String textHelp = "textHelp"; + static String textContactUs = "textContactUs"; + static String textGetInTouch = "textGetInTouch"; + static String textEmail = "textEmail"; + static String textPhone = "textPhone"; + static String textOTPDescription = "textOTPDescription"; + static String textOTP = "textOTP"; + static String textOTPValid = "textOTPValid"; + static String textResend = "textResend"; + static String textVerify = "textVerify"; + static String textCongratulations = "textCongratulations"; + static String textOTPMessage = "textOTPMessage"; + static String resetPasswordMessage = "resetPasswordMessage"; + static String textContinue = "textContinue"; + static String textAccountTitle = "textAccountTitle"; + static String textAccountSession = "textAccountSession"; + static String textSuccess = "textSuccess"; + static String textOK = "textOK"; + static String textWarning = "textWarning"; + static String textCancel = "textCancel"; + static String textConformation = "textConformation"; + static String textLogOutContent = "textLogOutContent"; + static String textManage = "textManage"; + static String textLogout = "textLogout"; + static String textVersion = "textVersion"; + static String textMyAccount = "textMyAccount"; + static String textBillManagement = "textBillManagement"; + static String textChequeManagement = "textChequeManagement"; + static String textUSend = "textUSend"; + static String textUReceived = "textUReceived"; + static String textBeneficiaryManagement = "textBeneficiaryManagement"; + static String textAgentLocation = "textAgentLocation"; + static String textAccountStatement = "textAccountStatement"; + static String textSupport = "textSupport"; + static String textUserProfile = "textUserProfile"; + static String textUserActivity = "textUserActivity"; + static String textLogOut = "textLogOut"; + static String textUCash = "textUCash"; + static String textUShop = "textUShop"; + static String textOverView = "textOverView"; + static String textDashboardWelcomeUser = "textDashboardWelcomeUser"; + static String textTotalAvailableFunds = "textTotalAvailableFunds"; + static String textTotalAvailableBalance = "textTotalAvailableBalance"; + static String textTotalAvailableBalanceInWords = "textTotalAvailableBalanceInWords"; + static String textAccountNumber = "textAccountNumber"; + static String textPleaseSelectAccount = "textPleaseSelectAccount"; + static String textStatementDetails = "textStatementDetails"; + static String textBalance = "textBalance"; + static String textUPrimary = "textUPrimary"; + static String textUSave = "textUSave"; + static String textUChaChing = "textUChaChing"; + static String textAboutUs = "textAboutUs"; + static String textCareer = "textCareer"; + static String textWHY = "textWHY"; + static String textWHYDescription = "textWHYDescription"; + static String textWHAT = "textWHAT"; + static String textWHATDescription = "textWHATDescription"; + static String textWHO = "textWHO"; + static String textWHODescription = "textWHODescription"; + static String textJobTitle = "textJobTitle"; + static String textApply = "textApply"; + static String textOfficeAddress = "textOfficeAddress"; + static String textJobSkills = "textJobSkills"; + static String textSelectPersonalAccount = "textSelectPersonalAccount"; + static String textRecipientDetail = "textRecipientDetail"; + static String textPhoneNumber = "textPhoneNumber"; + static String textRecipientCardName = "textRecipientCardName"; + static String textSelectCurrency = "textSelectCurrency"; + static String textSendingAmount = "textSendingAmount"; + static String textExchangeRate = "textExchangeRate"; + static String textMessageMemo = "textMessageMemo"; + static String textSend = "textSend"; + static String textClear = "textClear"; + static String textPermissionDenied = "textPermissionDenied"; + static String textMyProfile = "textMyProfile"; + static String textNotFound = "textNotFound"; + static String textRecipient = "textRecipient"; + static String textHome = "textHome"; + static String textCurrency = "textCurrency"; + static String textMessage = "textMessage"; + static String textConfirm = "textConfirm"; + static String textEndingBalance = "textEndingBalance"; + static String textPendingRemittance = "textPendingRemittance"; + static String textReceived = "textReceived"; + static String textPinCode = "textPinCode"; + static String textBack = "textBack"; + static String textCancelDescription = "textCancelDescription"; + static String textYes = "textYes"; + static String textErrorRequired = "textErrorRequired"; + static String textUserName = "textUserName"; + static String textPassword = "textPassword"; + static String textConfirmPassword = "textConfirmPassword"; + static String textEmailID = "textEmailID"; + static String textCellNumber = "textCellNumber"; + static String textNext = "textNext"; + static String textName = "textName"; + static String textAddress = "textAddress"; + static String textIdentityNumber = "textIdentityNumber"; + static String textSSNTaxPayerID = "textSSNTaxPayerID"; + static String textPassportAlienID = "textPassportAlienID"; + static String textChooseDocumentType = "textChooseDocumentType"; + static String textCNIC = "textCNIC"; + static String textDivingLicense = "textDivingLicense"; + static String textPassport = "textPassport"; + static String textDocumentsDescription = "textDocumentsDescription"; + static String textFront = "textFront"; + static String textSkipKYC = "textSkipKYC"; + static String textSignUpDescriptionDailog = "textSignUpDescriptionDailog"; + static String textNotRegisterUser = "textNotRegisterUser"; + static String textRegisterNow = "textRegisterNow"; + static String textSingUp = "textSingUp"; + static String textUploadKYC = "textUploadKYC"; + static String textTransactionHistory = "textTransactionHistory"; + static String textSelectOption = "textSelectOption"; + static String textSearch = "textSearch"; + + /// import from Include app + static String textMapLocationTitle = "textMapLocationTitle"; + static String textNormalMap = "textNormalMap"; + static String textSatelliteMap = "textSatelliteMap"; + static String textHybridMap = "textHybridMap"; + static String textMapContactNumber = "textMapContactNumber"; + static String transUtilityBillCategory = "transUtilityBillCategory".tr; + static String transUtilityBill = "transUtilityBill"; + static String textSelectBillType = "textSelectBillType"; + static String transUtilityElectricity = "transUtilityElectricity"; + static String transUtilityGas = "transUtilityGas"; + static String transUtilityInternet = "transUtilityInternet"; + static String transUtilityPTCL = "transUtilityPTCL"; + static String transUtilityWater = "transUtilityWater"; + static String transUtilityCreditCard = "transUtilityCreditCard"; + static String textSelectCompany = "textSelectCompany"; + static String transUtilityAJKBARKIYAT = "transUtilityAJKBARKIYAT".tr; + static String transUtilityFESCO = "transUtilityFESCO".tr; + static String transUtilityGBBARKIYAT = "transUtilityGBBARKIYAT".tr; + static String transUtilityGEPCO = "transUtilityGEPCO".tr; + static String transUtilityHESCO = "transUtilityHESCO".tr; + static String transUtilityIESCO = "transUtilityIESCO".tr; + static String textChequeBookActivation = "textChequeBookActivation"; + static String textChequeBookActivationDialogMsg = "textChequeBookActivationDialogMsg"; + static String textActivationContent = "textActivationContent"; + static String textActivationContentPart = "textActivationContentPart"; + static String textAccount = "textAccount"; + + //static String textAccountNumber = "textAccountNumber"; + static String textBillDetailCustomerName = "textBillDetailCustomerName"; + static String textFirstLeaf = "textFirstLeaf"; + static String textEnterChequeNumber = "textEnterChequeNumber"; + static String textLastLeaf = "textLastLeaf"; + static String textChequeRequestDetail = "textChequeRequestDetail"; + static String textChequeBookRequestContent = "textChequeBookRequestContent"; + static String textLeave20 = "textLeave20"; + static String textLeaves = "textLeaves"; + static String textGet = "textGet"; + static String textLeave50 = "textLeave50"; + static String textLeave100 = "textLeave100"; + static String textChange = "textChange"; + static String textDeliveryAddress = "textDeliveryAddress"; + static String textChequeBookRequestAddress = "textChequeBookRequestAddress"; + static String textCharges = "textCharges"; + static String textScheduleCharges = "textScheduleCharges"; + static String textDate = "textDate"; + static String textDateContent = "textDateContent"; + static String textRequestSummary = "textRequestSummary"; + static String textNumberofLeaves = "textNumberofLeaves"; + static String textQueryContent = "textQueryContent"; + static String textDeposit = "textDeposit"; + static String textChequeDeposit = "textChequeDeposit"; + static String textChequeStatusContent = "textChequeStatusContent"; + static String textDepositToChequing = "textDepositToChequing"; + static String text1000 = "text1000"; + static String textMax300000 = "textMax300000"; + static String textSelectAccount = "textSelectAccount"; + static String textFrontOfCheque = "textFrontOfCheque"; + static String textBackofCheque = "textBackofCheque"; + static String textTryAgain = "textTryAgain"; + static String textChequeStatus = "textChequeStatus"; + static String textChequeActivation = "textChequeActivation"; + static String textChequeRequest = "textChequeRequest"; + static String textChequeRequestContent = "textChequeRequestContent"; + static String textChequeNumber = "textChequeNumber"; + static String textChequeStatusHistory = "textChequeStatusHistory"; + static String textChequeStatusHistoryContent = "textChequeStatusHistoryContent"; + static String textChequeStatusCheckNumber = "textChequeStatusCheckNumber"; + static String textChequeStatusHistoryRefNo = "textChequeStatusHistoryRefNo"; + static String textChequeStatusHistorySuccess = "textChequeStatusHistorySuccess"; + static String textChequeStatusHistoryCancel = "textChequeStatusHistoryCancel"; + static String textPTCLLandLine = "textPTCLLandLine"; + static String textSelectAccountDetails = "textSelectAccountDetails"; + static String textCreditCard = "textCreditCard"; + static String textCreditCardNumber = "textCreditCardNumber"; + static String textAmountDebit = "textAmountDebit"; + static String textEnterConsumerName = "textEnterConsumerName"; + static String textTotalAmount = "textTotalAmount"; + static String textEnterAmount = "textEnterAmount"; + static String textBillDetails = "textBillDetails"; + static String textBillConsumerName = "textBillConsumerName"; + static String textBillAmount = "textBillAmount"; + static String textDueDate = "textDueDate"; + static String textAmountDueAfterDueDate = "textAmountDueAfterDueDate"; + static String textBillStatus = "textBillStatus"; + static String textBillDetailZero = "textBillDetailZero"; + static String textBillDetailDate = "textBillDetailDate"; + static String textBillDetailUnPaid = "textBillDetailUnPaid"; + static String textPayNow = "textPayNow"; + static String textBillDetailContent = "textBillDetailContent"; + static String textBillDetailBalance = "textBillDetailBalance"; + static String textBillDetailBillAmount = "textBillDetailBillAmount"; + static String textBillDetailBillDueDate = "textBillDetailBillDueDate"; + static String textBillDetailBillAmountDue = "textBillDetailBillAmountDue"; + static String textBillDetailBillAfterDueDate = "textBillDetailBillAfterDueDate"; + static String textBillDetailBillStatus = "textBillDetailBillStatus"; + static String textProfileHey = "textProfileHey"; + static String textProfileUsername = "textProfileUsername"; + static String textAppSettingTitle = "textAppSettingTitle"; + static String textLanguagesTitle = "textLanguagesTitle"; + static String textDarkModeContent = "textDarkModeContent"; + static String textFingerPrintTitle = "textFingerPrintTitle"; + static String textFingerPrintContent = "textFingerPrintContent"; + static String textPasswordChangeTitle = "textPasswordChangeTitle"; + static String textPasswordChangeContent = "textPasswordChangeContent"; + static String textTermOfService = "textTermOfService"; + static String textPrivacy = "textPrivacy"; + static String textInviteFriends = "textInviteFriends"; + static String textDialogConformation = "textDialogConformation"; + static String textDialogContent = "textDialogContent"; + static String textSignOut = "textSignOut"; + static String textSelectYourOption = "textSelectYourOption"; + static String textLanguageEnglish = "textLanguageEnglish"; + static String textLanguageArabic = "textLanguageArabic"; + static String textLanguageUrdu = "textLanguageUrdu"; + static String textNoSelect = "textNoSelect"; + static String textMyAccountTitle = "textMyAccountTitle"; + static String textMyAccountAccountTitle = "textMyAccountAccountTitle"; + static String textMyAccountAccountNumber = "textMyAccountAccountNumber"; + static String textMyAccountBranchCode = "textMyAccountBranchCode"; + static String textMyAccountAccountOpeningDate = "textMyAccountAccountOpeningDate"; + static String textAppSetting = "textAppSetting"; + static String textLoginTitle = "textLoginTitle"; + static String textInvalidFingerprint = "textInvalidFingerprint"; + static String textDailyTransactionLimit = "textDailyTransactionLimit"; + static String textChangeTransactionPin = "textChangeTransactionPin"; + static String textQRSetting = "textQRSetting"; + static String textTransactionLimit = "textTransactionLimit"; + static String textTransactionPin = "textTransactionPin"; + static String textOldLimit = "textOldLimit"; + static String textMaximumLengthContent = "textMaximumLengthContent"; + static String textLimitNoteContent = "textLimitNoteContent"; + static String textCurrentDailyLimit = "textCurrentDailyLimit"; + static String textDone = "textDone"; + static String textPinOTPMessage = "textPinOTPMessage"; + static String textYourUCOQR = "textYourUCOQR"; + static String textUCOQRContent = "textUCOQRContent"; + static String textQrAccountName = "textQrAccountName"; + static String textQrAccountNumber = "textQrAccountNumber"; + static String textShareQRCode = "textShareQRCode"; + static String textSavetoGallery = "textSavetoGallery"; + static String textNotifications = "textNotifications"; + static String textFilter = "textFilter"; + static String textCreateTransactionPin = "textCreateTransactionPin"; + static String textPleaseCreatenewtransactionpin = "textPleaseCreatenewtransactionpin"; + static String textConfirmTransactionPin = "textConfirmTransactionPin"; + static String textOldTransactionPin = "textOldTransactionPin"; + static String textNotificationDetails = "textNotificationDetails"; + static String textNotificationDetailsContent = "textNotificationDetailsContent"; + static String textError = "textError"; + static String textDescription = "textDescription"; + static String textInform = "textInform"; + static String textConfirmTransaction = "textConfirmTransaction"; + static String textHowdoyouwanttopay = "textHowdoyouwanttopay"; + static String textDebitCard = "textDebitCard"; + static String textDebitCardContent = "textDebitCardContent"; + static String textBankTransfer = "textBankTransfer"; + static String textGeneralLedger = "textGeneralLedger"; + static String transAddMoney = "transAddMoney"; + static String textGLCode = "textGLCode"; + static String textFaqs = "textFaqs"; + static String textHowCanIHelpYou = "textHowCanIHelpYou"; + static String textExploreAllArticles = "textExploreAllArticles"; + static String textFirstName = "textFirstName"; + static String textLastName = "textLastName"; + + + +} \ No newline at end of file diff --git a/lib/app/core/constants/url_constants.dart b/lib/app/core/constants/url_constants.dart new file mode 100644 index 0000000..29aa807 --- /dev/null +++ b/lib/app/core/constants/url_constants.dart @@ -0,0 +1,100 @@ +import 'package:uco_mobile_poc/app/core/utils/url_encryption.dart'; + +class UrlContants { + static const baseUrl = "http://192.168.0.250:8888"; + // FMFI + // static const baseUrl = "https://uco.mfsys.ca"; // FMFI + // public interface SecurityURI { + // String REGISTER_USER = "/security/auth/user/register"; + // String LOGIN = "/security/auth/user/authenticate"; + // String REFRESH_TOKEN = "/security/auth/refresh-token"; + // String SIGNUP_OTP = "/security/auth/signup-otp"; + // String VERIFY_SINGUP_OTP = "/security/auth/verifysignup-otp"; + // String CHANGE_PASSWORD = "/security/user/changePassword"; + // String RESET_PASSWORD = "/security/user/resetPassword"; + // String GENERATE_INTERNAL_TOKEN = "/security/auth/generateInternalToken"; + // } + /// Encrypted Url constant.... + // static final UrlEncryption encryption = UrlEncryption(); + // static final String encryptedUrl = encryption.encryptData('https://uco.mfsys.ca'); + // static final String baseUrl =''; + + static final REFRESH_TOKEN = "$baseUrl/refreshtoken"; + static final LOGIN = "$baseUrl/security/auth/user/authenticate"; + static final LOGIN_OTP = "$baseUrl/security/auth/verifylogin-otp"; + static final RESEND_OTP = "$baseUrl/customer/login/otp-send"; + static final REGISTER = "$baseUrl/customer/register"; + static final VERIFY_ID = "$REGISTER/checkid"; + static final VERIFY_ACCOUNT_NO = "$REGISTER/checkaccountno"; + static final PIN_VERIFY = "$REGISTER/pin-verify"; + static final SET_PASSWORD = "$baseUrl/customer/set-password"; + static final ACCOUNT_DETAILS = "$baseUrl/uco/depositAccounts"; + static final ACCOUNT_INQUIRY = "$baseUrl/uco/accountInquiry"; + + static final EXCHANGE_RATE = "$baseUrl/uco/fetchExchangeRate"; + + static final FETCH_PAYMENT_PURPOSE = "$baseUrl/getPurposes"; + static final LOAN_ACCOUNT_DETAILS = "$baseUrl/account/indvdetails"; + static final ACCOUNT_TRANSACTIONS = "$baseUrl/uco/accountStatement"; + static final LOAN_ACCOUNT_TRANSACTIONS = "$baseUrl/account/loan/history"; + + static final BENEFICIARY_ACCOUNTS = "$baseUrl/beneficiary"; + static final ACTIVITY_DETAILS = "$baseUrl/account/activity"; + static final SEND_TRANSACTION_STEP1 = "$baseUrl/uco/sendDrTranOtpAndVerifyTranPin"; + static final SEND_TRANSACTION_STEP2 = "$baseUrl/uco/submitDrTransaction"; + static final UPLOAD_USER_PROFILE_PICTURE = "$baseUrl/uco/updateCustomerProfile"; + + static final CREATE_TRANSACTION_PIN_OTP = "$baseUrl/uco/createTransactionPin"; + static final CREATE_TRANSACTION_PIN = "$baseUrl/uco/verifyTransactionPin"; + static final CHANGE_TRANSACTION_PIN = "$baseUrl/uco/changeTransactionPin"; + static final BENEFICIARY_PIN = "$baseUrl/beneficiary"; + static final GENERATE_REPORTS = "$baseUrl/uco/generateReport"; + static final DELETE_BENEFICIARYT = "$baseUrl/beneficiary"; + + static final CHANGE_PASSWORD_SEND_OTP = "$baseUrl/security/user/changePassword"; + static final CHANGE_PASSWORD = "$baseUrl/customer/change-password"; + + static final FORGET_PASSWORD_STEP_1 = "$baseUrl/customer/forgetPassword/userid"; + static final FORGET_PASSWORD_STEP_2 = "$baseUrl/customer/forgetpassword"; + static final FORGET_PASSWORD_STEP_3 = "$baseUrl/customer/register/otp-resend"; + static final FORGET_PASSWORD_STEP_4 = "$baseUrl/customer/updatepassword"; + + static final SIGNUP_STEP_1 = "$baseUrl/security/auth/user/register"; + static final SIGNUP_STEP_2 = "$baseUrl/security/auth/verifysignup-otp"; + static final SIGNUP_STEP_3 = "$baseUrl/uco/auth/user/authenticate/onboardCustomer"; + static final SIGNUP_STEP_4 = "$baseUrl/customer/register/pin-verify"; + static final SIGNUP_STEP_4_RESEND_OTP = "$baseUrl/customer/register/pin-resend"; + static final SIGNUP_STEP_5 = "$baseUrl/customer/set-password"; + static final SEND_FEED_BACK = "$baseUrl/send-email"; + static final fetchPendingCredittransaction = "$baseUrl/uco/fetchPendingCredittransaction"; + static final ACCEPT_RECEIVE_TRANSACTION = "$baseUrl/uco/submitCrTransaction"; + static final REVERSE_TRANSACTION = "$baseUrl/uco/reverseTransaction"; + + static final FETCH_ACCOUNT_STATEMENT = "$baseUrl/uco/fetchDepositAccountStatement"; + static final FETCH_USER_ACTIVITY = "$baseUrl/uco/account/activity/"; + + static final fetchUcoDepositProducts = "$baseUrl/uco/auth/user/authenticate/onboardCustomer/fetchUcoDepositProducts"; + + static final FETCH_DEPOSIT_PRODUCTS = "$baseUrl/uco/deposit/fetchUcoDepositProducts"; + static final FETCH_GLS_ACCOUNTS = "$baseUrl/uco/deposit/fetchUcoGls"; + + static final SEND_ADD_MONEY_OTP = SEND_TRANSACTION_STEP1; + static final SEND_ADD_MONEY_TRANSACTION = "$baseUrl/uco/submitGLAccontAddMoneyTranasction"; + + static final evaluateCurrency = "$baseUrl/uco/getEvaluatedCurrency"; + static final ADD_NEW_ACCOUNT = "$baseUrl/uco/createUcoAccount"; + + + + static String resendOtp = "$baseUrl/security/auth/resend-otp"; + + + static String resendOtpUSend = "$baseUrl/uco/resendDrTranOtp"; + + static String resendTransOtp = "$baseUrl/uco/changeTransactionPin"; + static String createPinOtp = "$baseUrl/uco/createTransactionPin"; + static final ADD_NEW_BENEIFCIARY = "$baseUrl/uco/addBeneficary"; + static final DELETE_BENEFICIARY = "$baseUrl/uco/deleteBeneficary"; + static final FETCH_ALL_BENEFICIARY = "$baseUrl/uco/getBeneficary"; + +} \ No newline at end of file diff --git a/lib/app/core/constants/widget_types.dart b/lib/app/core/constants/widget_types.dart new file mode 100644 index 0000000..f1ea2c9 --- /dev/null +++ b/lib/app/core/constants/widget_types.dart @@ -0,0 +1,4 @@ +class WidgetTypes { + static const CUSTOM_EDIT_TEXT = "customEditText"; + static const CUSTOM_OTP_FIELD = "customOtpField"; +} diff --git a/lib/app/core/data/data_source_auth/remote_data_source/app_remote_data_source.dart b/lib/app/core/data/data_source_auth/remote_data_source/app_remote_data_source.dart new file mode 100644 index 0000000..18015cc --- /dev/null +++ b/lib/app/core/data/data_source_auth/remote_data_source/app_remote_data_source.dart @@ -0,0 +1,706 @@ + + +import '../../../../models/AddNewAccountRequestModel.dart'; +import '../../../../models/AuthenticationRequest.dart'; +import '../../../../models/BeneficiaryAccountModel.dart'; +import '../../../../models/ChangePasswordRequest.dart'; +import '../../../../models/ChangeTransactionPinRequest.dart'; +import '../../../../models/CreateTransactionPinOTPRequest.dart'; +import '../../../../models/CreateTransactionPinRequest.dart'; +import '../../../../models/GLACCAddMoneyRequestModel.dart'; +import '../../../../models/GenerateReportRequestModel.dart'; +import '../../../../models/RegisterRequest.dart'; +import '../../../../models/SignupOtpRequest.dart'; +import '../../../../models/SignupStep3RequestModel.dart'; +import '../../../../models/TransactionPinRequestModel.dart'; +import '../../../../models/TransactionSubmitRequestModel.dart'; +import '../../../../models/VerifyLoginOtpRequest.dart'; +import '../../../../models/accept_receive_transaction.dart'; +import '../../../../models/chanange_password_params.dart'; +import '../../../../models/resen_ot_chanange_trans_pin.dart'; +import '../../../../models/resend_ot_login_model.dart'; +import '../../../../models/resend_otp_usend.dart'; +import '../../../../models/upload_user_profile_model.dart'; +import '../../../config/requset_attr.dart'; +import '../../../config/server_request.dart'; +import '../../../config/server_response.dart'; +import '../../../constants/app_contants.dart'; +import '../../../constants/url_constants.dart'; +import '../../../enums/http_methods.dart'; +import '../../../utils/SessionCache.dart'; + +class AppRemoteDataSource { + Future fetchAccountDetails() { + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["pctCstycode"] = SessionCache.instance.userInfo.pctCstycode; + queryParams["cmpCustcode"] = SessionCache.instance.userInfo.cmpCustcode; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_ACCOUNT_DETAILS; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.ACCOUNT_DETAILS, HttpMethod.GET, {}, headers, queryParams)); + } + + Future sendAddMoneyOtp(TransactionPinRequestModel transactionPinRequestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SEND_TRANSACTION_STEP_1; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SEND_ADD_MONEY_OTP, HttpMethod.POST, transactionPinRequestModel.toMap(), headers)); + } + + Future sendTransactionStep1(TransactionPinRequestModel transactionPinRequestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SEND_TRANSACTION_STEP_1; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SEND_TRANSACTION_STEP1, HttpMethod.POST, transactionPinRequestModel.toMap(), headers)); + } + + Future sendTransactionStep2(TransactionSubmitRequestModel transactionSubmitRequestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SEND_TRANSACTION_STEP_2; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SEND_TRANSACTION_STEP2, HttpMethod.POST, transactionSubmitRequestModel.toMap(), headers)); + } + + Future sendAddMoneyTransaction(GLACCAddMoneyRequestModel transactionSubmitRequestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SEND_TRANSACTION_STEP_2; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SEND_ADD_MONEY_TRANSACTION, HttpMethod.POST, transactionSubmitRequestModel.toMap(), headers)); + } + + Future getLoginOTP(AuthenticationRequest requestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.GET_LOGIN_OTP; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.LOGIN, HttpMethod.POST, requestModel.toMap())); + } + +// Future reSendOTP(ReSendOTPModel requestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.LOGIN_OTP, HttpMethod.POST, requestModel.toJson())); +// } + + Future validateLoginPin(VerifyLoginOtpRequest requestBody) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.VALIDATE_LOGIN_PIN; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.LOGIN_OTP, HttpMethod.POST, requestBody.toMap())); + } + + ///Fetch Account Transactions + Future fetchDepositAccountTransactions(String accountNumber, String fromDate, String toDate) async { + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["mbmBkmsnumber"] = accountNumber; + queryParams["sgtGntrvaluedatefrom"] = fromDate; + queryParams["sgtGntrvaluedateto"] = toDate; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_DEPOSITE_ACCOUNT_TRANSACTIONS; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.ACCOUNT_TRANSACTIONS, HttpMethod.GET, {}, headers, queryParams, {})); + } + + + Future addNewBeneficiary(BeneficiaryAccountModel beneficiaryModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.ADD_NEW_BENEFICIARY; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.ADD_NEW_BENEIFCIARY, HttpMethod.POST, beneficiaryModel.toMap(), headers)); + } + + +// Future fetchLoanAccountDetails(String accountNumber) async { +// Map queryParams = {}; +// queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; +// queryParams["mbmBkmsnumber"] = accountNumber; +// +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.LOAN_ACCOUNT_DETAILS, HttpMethod.GET, {}, headers, queryParams, {})); +// } + +// // http: //192.168.1.20:8080/MCONNECT/account/indvdetails?porOrgacode=0004&mbmBkmsnumber=0001325 + +// Future fetchLoanAccountTransactions(String accountNumber) async { +// Map queryParams = {}; +// queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; +// queryParams["mbmBkmsnumber"] = accountNumber; +// +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.LOAN_ACCOUNT_TRANSACTIONS, HttpMethod.GET, {}, headers, queryParams, {})); +// } + + /// Fetch User Activity Data + Future fetchUserActivity(String fromDate, String toDate) async { + Map paramParameters = {}; + paramParameters["organization"] = SessionCache.instance.userInfo.porOrgacode; + paramParameters["customer"] = SessionCache.instance.userInfo.cmpCustcode; + // paramParameters["customertype"] = "I"; + paramParameters["fromdate"] = fromDate; + paramParameters["todate"] = toDate; + + // "uco/account/activity/organization/{porOrgacode}/customer/{cmpCustcode}/fromdate/{fdate}/todate/{tdate}"; + // /organization/0006/customer/I003120/fromdate/2024-01-01/todate/2024-04-29 + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = "Mobile"; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_USER_ACTIVITY; + + return ServerRequest.request(RequestAttr.withParamsAndBody(buildPathParameters(UrlContants.FETCH_USER_ACTIVITY, paramParameters), HttpMethod.GET, {}, headers, {}, {})); + } + + + /// Method for handling Parameter + String buildPathParameters(String basePath, Map parameters) { + parameters.forEach((key, value) { + basePath += "/$key/$value"; + }); + return basePath; + } + + +// Future generatePinForBeneficiaryAccount(BeneficiaryPinRequestModel beneficiaryPinRequestModel) { +// Map paramParameters = {}; +// paramParameters["channel"] = SessionCache.instance.userInfo.channelCode; + +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// headers["Devicename"] = "Mobile"; +// return ServerRequest.request(RequestAttr.withParamsAndBody(buildPathParameters(UrlContants.BENEFICIARY_PIN, paramParameters), HttpMethod.POST, beneficiaryPinRequestModel.toMap(), headers)); +// } + + Future fetchExchangeRate() { + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_EXCHANGE_RATE; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.EXCHANGE_RATE, HttpMethod.GET, {}, headers, queryParams)); + } + + Future fetchAccountInquiry(String type, String value) { + Map queryParams = {}; + queryParams["acntTypeCode"] = type; + queryParams["acntTypeValue"] = value; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["channelCode"] = SessionCache.instance.userInfo.channelCode; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_ACCOUNT_IQUIRY; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.ACCOUNT_INQUIRY, HttpMethod.GET, {}, headers, queryParams)); + } + + + + Future createTransactionPinOTP(CreateTransactionPinOTPRequest requestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.CREATE_TRANSACTION_PIN; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.CREATE_TRANSACTION_PIN_OTP, HttpMethod.POST, requestModel.toMap(), headers)); + } + + + Future createTransactionPin(CreateTransactionPinRequest requestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.CREATE_TRANSACTION_PIN; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.CREATE_TRANSACTION_PIN, HttpMethod.POST, requestModel.toMap(), headers)); + } + + Future changeTransactionPin(ChangeTransactionPinRequest requestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.CHANGE_TRANSACTION_PIN; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.CHANGE_TRANSACTION_PIN, HttpMethod.PUT, requestModel.toMap(), headers)); + } + + + Future generateReports(GenerateReportRequestModel requestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.GENERATE_REPORTS; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.GENERATE_REPORTS, HttpMethod.POST, requestModel.toMap(), headers)); + } + + Future fetchGlsAllAccounts() { + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["glsTransaction"] = AppConstants.FETCH_GLS_ACCOUNTS; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FETCH_GLS_ACCOUNTS, HttpMethod.GET, {}, headers, queryParams)); + } + + Future uploadUserProfilePicture(UploadUserProfileModel uploadUserProfileModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.UPLOAD_USER_PROFILE_PICTURE; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.UPLOAD_USER_PROFILE_PICTURE, HttpMethod.POST, uploadUserProfileModel.toMap(), headers)); + } + +// Future deleteBeneficiary(String accountNumber) { +// Map paramParameters = {}; +// paramParameters["organization"] = SessionCache.instance.userInfo.porOrgacode; +// paramParameters["customer"] = SessionCache.instance.userInfo.cmpCustcode; +// paramParameters["customertype"] = "I"; +// paramParameters["account"] = accountNumber; +// +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// headers["Devicename"] = "Mobile"; +// return ServerRequest.request(RequestAttr.withParamsAndBody(buildPathParameters(UrlContants.DELETE_BENEFICIARYT, paramParameters), HttpMethod.DELETE, {}, headers, {}, {})); +// } + +// ------------------ Forget password ---------------- + +// Future forgetPasswordStep1(ForgetPasswordStep1RequestModel forgetPasswordStep1RequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FORGET_PASSWORD_STEP_1, HttpMethod.POST, forgetPasswordStep1RequestModel.toMap(), {})); +// } + +// Future forgetPasswordStep2(ForgetPasswordStep2RequestModel forgetPasswordStep2RequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FORGET_PASSWORD_STEP_2, HttpMethod.POST, forgetPasswordStep2RequestModel.toMap(), {})); +// } + +// Future forgetPasswordStep3(ForgetPasswordStep3RequestModel forgetPasswordStep3RequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FORGET_PASSWORD_STEP_3, HttpMethod.POST, forgetPasswordStep3RequestModel.toMap(), {})); +// } + +// Future forgetPasswordStep4(ForgetPasswordStep4RequestModel forgetPasswordStep4RequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FORGET_PASSWORD_STEP_4, HttpMethod.POST, forgetPasswordStep4RequestModel.toMap(), {})); +// } + +// sign up process + Future signupStep1(RegisterRequest registerRequest) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SIGNUP_STEP_1; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SIGNUP_STEP_1, HttpMethod.POST, registerRequest.toMap(), {})); + } + + Future signupStep2(SignupOtpRequest signupOtpRequest) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SIGUP_STEP_2; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SIGNUP_STEP_2, HttpMethod.POST, signupOtpRequest.toMap(), {})); + } + + + Future signupStep3(SignupStep3RequestModel signupStep3RequestModel) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.SIGUP_STEP_3; + + var header = {'Content-Type': 'application/json'}; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SIGNUP_STEP_3, HttpMethod.POST, signupStep3RequestModel.toMap(), headers)); + } + + +// Future signupStep4(SignUpStep4RequestModel signUpStep4RequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SIGNUP_STEP_4, HttpMethod.POST, signUpStep4RequestModel.toMap(), {})); +// } + +// Future signupStep4ResendOtp(SignUpStep4ResendOtpRequestModel signUpStep4ResendOtpRequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SIGNUP_STEP_4_RESEND_OTP, HttpMethod.POST, signUpStep4ResendOtpRequestModel.toMap(), {})); +// } + +// Future signupStep5(SignUpStep5RequestModel signUpStep5RequestModel) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SIGNUP_STEP_5, HttpMethod.POST, signUpStep5RequestModel.toMap(), {})); +// } + + Future changePasswordSendOTP(ChangePasswordRequest changePasswordRequest) { + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.CHANGE_PASSWORD_SEND_OTP; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.CHANGE_PASSWORD_SEND_OTP, HttpMethod.POST, changePasswordRequest.toMap(), headers)); + } + + Future changePassword(ChangePasswordParams changePasswordParams) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.CHANGE_PASSWORD; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.CHANGE_PASSWORD_SEND_OTP, HttpMethod.PATCH, changePasswordParams.toJson(), headers)); + } + + Future getPendingTransition(String accountNumber) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.GET_PENDING_TRANSITION; + + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["mbmBkmsnumber"] = accountNumber; + + return ServerRequest.request(RequestAttr.withHeaderAndParams(UrlContants.fetchPendingCredittransaction, HttpMethod.GET, headers, queryParams)); + } + + + Future acceptReceiveTransition(AcceptReceiveTransactionModel requestModel) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.ACCEPT_RECEIVE_TRANSACTION; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.ACCEPT_RECEIVE_TRANSACTION, HttpMethod.POST, requestModel.toMap(), headers)); + } + + Future reverseTransition(String nodeId, String sgtGntrnumber) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.REVERSE_TRANSACTION; + + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["nodeId"] = nodeId; + queryParams["sgtGntrnumber"] = sgtGntrnumber; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.REVERSE_TRANSACTION, HttpMethod.POST, {},headers, queryParams)); + } + + Future fetchAccountStatement(String accountNumber) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_ACCOUNT_STATEMENT; + + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["mbmBkmsnumber"] = accountNumber; + + return ServerRequest.request(RequestAttr.withHeaderAndParams(UrlContants.FETCH_ACCOUNT_STATEMENT, HttpMethod.GET, headers, queryParams)); + } + + Future getCurrencyList() { + Map queryParams = {}; + + queryParams["porOrgacode"] = "0005"; + + return ServerRequest.request( + RequestAttr.withHeaderAndParams(UrlContants.fetchUcoDepositProducts, HttpMethod.GET, {}, queryParams), + ); + } + + Future getConvertedCurrency(String baseCurrency, String targetCurrency, String sgtGntramtfc) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_ACCOUNT_STATEMENT; + + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["baseCurrency"] = baseCurrency; + queryParams["targetCurrency"] = targetCurrency; + queryParams["sgtGntramtfc"] = sgtGntramtfc; + + return ServerRequest.request(RequestAttr.withHeaderAndParams(UrlContants.evaluateCurrency, HttpMethod.GET, headers, queryParams)); + } + + Future addNewAccount(AddNewAccountRequestModel addNewAccountModel) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["addNewAccount"] = AppConstants.ADD_NEW_ACCOUNT; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.ADD_NEW_ACCOUNT, HttpMethod.POST, addNewAccountModel.toMap(), headers)); + } + + Future resentOtpLoginSignUp(ResendOtpLoginModel model) { + Map headers = {}; + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.resendOtp, HttpMethod.POST, model.toMap(), headers)); + } + + Future resendOtpUsend(ResendOtpUsendModel model) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.resendOtpUSend, HttpMethod.POST, model.toMap(), headers)); + } + + Future resendOtpTransPin( + ResendOtpChangeTransPin resendOtpChangeTransPin, + ) { + + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.resendTransOtp, HttpMethod.PUT, resendOtpChangeTransPin.toMap(), headers)); + } + + Future createPinResndOtp(CreateTransactionPinOTPRequest createTransactionPinRequest) { + Map headers = {}; + + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + + return ServerRequest.request(RequestAttr.withParamsAndBody( + UrlContants.createPinOtp, + HttpMethod.PUT, + createTransactionPinRequest.toMap(), + headers, + )); + } + + Future fetchAllBeneficiary(String porOrgacode, String email) { + Map queryParams = {}; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + queryParams["email"] = SessionCache.instance.userInfo.cmpUserId; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.FETCH_ALL_BENEFICIARY; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FETCH_ALL_BENEFICIARY, HttpMethod.GET, {}, headers, queryParams)); + } + + Future deleteBeneficiary(String mbmBkmsnumberRef, String email, String porOrgacode) { + Map queryParams = {}; + queryParams["mbmBkmsnumberRef"] = mbmBkmsnumberRef; + queryParams["email"] = SessionCache.instance.userInfo.cmpUserId; + queryParams["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + + Map headers = {}; + headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; + headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; + headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; + headers["Devicename"] = AppConstants.DEVICE_NAME; + headers["porOrgacode"] = SessionCache.instance.userInfo.porOrgacode; + headers["email"] = SessionCache.instance.userInfo.cmpUserId; + headers["channalCode"] = SessionCache.instance.userInfo.channelCode; + headers["userActivity"] = AppConstants.DELETE_BENEFICIARY; + + return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.DELETE_BENEFICIARY, HttpMethod.DELETE, {}, headers, queryParams)); + } + +// Future loginResendOtp(LoginResendOtpRequestModel request) { +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.RESEND_OTP, HttpMethod.POST, request.toMap(), {})); +// } + +// Future fetchPaymentPurposes() { +// Map queryParams = {}; +// +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// headers["Devicename"] = "Mobile"; +// +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.FETCH_PAYMENT_PURPOSE, HttpMethod.GET, {}, headers, queryParams)); +// } + +// Future sendFeedBack(SendFeedBackRequestModel sendFeedBackRequestModel) { +// Map headers = {}; +// headers["Authorization"] = "Bearer ${SessionCache.instance.userInfo.jwtToken}"; +// headers["Channelcode"] = SessionCache.instance.userInfo.channelCode; +// headers["Cmpuserid"] = SessionCache.instance.userInfo.cmpUserId; +// headers["Devicename"] = "Mobile"; +// return ServerRequest.request(RequestAttr.withParamsAndBody(UrlContants.SEND_FEED_BACK, HttpMethod.POST, sendFeedBackRequestModel.toMap(), headers)); +// } + +} diff --git a/lib/app/core/data/repositories/app_repositories.dart b/lib/app/core/data/repositories/app_repositories.dart new file mode 100644 index 0000000..70015f4 --- /dev/null +++ b/lib/app/core/data/repositories/app_repositories.dart @@ -0,0 +1,271 @@ + + +import '../../../models/AddNewAccountRequestModel.dart'; +import '../../../models/AuthenticationRequest.dart'; +import '../../../models/BeneficiaryAccountModel.dart'; +import '../../../models/ChangeTransactionPinRequest.dart'; +import '../../../models/CreateTransactionPinOTPRequest.dart'; +import '../../../models/CreateTransactionPinRequest.dart'; +import '../../../models/GLACCAddMoneyRequestModel.dart'; +import '../../../models/RegisterRequest.dart'; +import '../../../models/SignupOtpRequest.dart'; +import '../../../models/SignupStep3RequestModel.dart'; +import '../../../models/TransactionPinRequestModel.dart'; +import '../../../models/TransactionSubmitRequestModel.dart'; +import '../../../models/VerifyLoginOtpRequest.dart'; +import '../../../models/accept_receive_transaction.dart'; +import '../../../models/chanange_password_params.dart'; +import '../../../models/resen_ot_chanange_trans_pin.dart'; +import '../../../models/resend_ot_login_model.dart'; +import '../../../models/resend_otp_usend.dart'; +import '../../../models/upload_user_profile_model.dart'; +import '../../config/server_response.dart'; +import '../data_source_auth/remote_data_source/app_remote_data_source.dart'; + +abstract class AppRepositories { + Future login(AuthenticationRequest request); + + Future validateLoginPin(VerifyLoginOtpRequest request); + + Future fetchAccountDetails(); + + Future fetchGlsAccounts(); + + Future fetchAccountInquiry(String type, String value); + + Future fetchDepositAccountTransactions(String accountNumber, String fromDate, String toDate); + + Future fetchExchangeRate(); + + Future createTransactionPinOTP(CreateTransactionPinOTPRequest requestModel); + + Future createTransactionPin(CreateTransactionPinRequest requestModel); + + Future uploadUserProfilePicture(UploadUserProfileModel requestModel); + + Future changeTransactionPin(ChangeTransactionPinRequest requestModel); + + Future sendTransactionStep1(TransactionPinRequestModel transactionPinRequestModel); + + Future sendAddMoneyOtp(TransactionPinRequestModel transactionPinRequestModel); + + Future sendTransactionStep2(TransactionSubmitRequestModel transactionSubmitRequestModel); + + Future sendAddMoneyTransaction(GLACCAddMoneyRequestModel transactionSubmitRequestModel); + + Future acceptReceiveTransaction(AcceptReceiveTransactionModel requestModel); + + Future reverseTransaction(String nodeId, String sgtGntrnumber); + + Future addNewBeneficiary(BeneficiaryAccountModel requestModel); + + Future fetchAllBeneficiary(String porOrgacode, String email); + + Future deleteBeneficiary(String mbmBkmsnumberRef, String email, String porOrgacode); + + Future signupStep1(RegisterRequest registerRequest); + + Future signupStep2(SignupOtpRequest signupOtpRequest); + + Future signupStep3(SignupStep3RequestModel signupStep3RequestModel); + + Future changePassword(ChangePasswordParams changePasswordParams); + + Future getPendingTransition(String accountNumber); + + Future fetchAccountStatement(String accountNumber); + + Future fetchUserActivity(String fromDate, String toDate); + + Future resentOtpLoginSignUp(ResendOtpLoginModel model); + + Future getCurrencyList(); + + Future addNewAccount(AddNewAccountRequestModel addNewAccountRequest); + + Future resendOtpUsend(ResendOtpUsendModel resendOtpUsendModel); + + Future resendOtpTransPin(ResendOtpChangeTransPin resendOtpChangeTransPin); + + Future createPinResndOtp(CreateTransactionPinOTPRequest createTransactionPinRequest); + + Future getConvertedCurrency(String baseCurrency, String targetCurrency, String sgtGntramtfc); +} + +class AppRepositoriesImpl implements AppRepositories { + AppRemoteDataSource remoteDataSource; + + AppRepositoriesImpl({required this.remoteDataSource}); + + @override + Future login(AuthenticationRequest requestModel) { + return remoteDataSource.getLoginOTP(requestModel); + } + + @override + Future fetchAccountDetails() { + return remoteDataSource.fetchAccountDetails(); + } + + @override + Future fetchAccountInquiry(String type, String value) { + return remoteDataSource.fetchAccountInquiry(type, value); + } + + /// + @override + Future validateLoginPin(VerifyLoginOtpRequest requestModel) { + return remoteDataSource.validateLoginPin(requestModel); + } + + @override + Future fetchDepositAccountTransactions(String accountNumber, String fromDate, String toDate) { + return remoteDataSource.fetchDepositAccountTransactions(accountNumber, fromDate, toDate); + } + + @override + Future fetchExchangeRate() { + return remoteDataSource.fetchExchangeRate(); + } + + @override + Future sendTransactionStep1(TransactionPinRequestModel transactionPinRequestModel) { + return remoteDataSource.sendTransactionStep1(transactionPinRequestModel); + } + + // + @override + Future sendTransactionStep2(TransactionSubmitRequestModel transactionSubmitRequestModel) { + return remoteDataSource.sendTransactionStep2(transactionSubmitRequestModel); + } + + @override + Future sendAddMoneyOtp(TransactionPinRequestModel transactionPinRequestModel) { + return remoteDataSource.sendAddMoneyOtp(transactionPinRequestModel); + } + + @override + Future sendAddMoneyTransaction(GLACCAddMoneyRequestModel transactionSubmitRequestModel) { + return remoteDataSource.sendAddMoneyTransaction(transactionSubmitRequestModel); + } + + @override + Future signupStep1(RegisterRequest registerRequest) { + return remoteDataSource.signupStep1(registerRequest); + } + + @override + Future signupStep2(SignupOtpRequest signupOtpRequest) { + return remoteDataSource.signupStep2(signupOtpRequest); + } + + @override + Future signupStep3(SignupStep3RequestModel signupStep3RequestModel) { + return remoteDataSource.signupStep3(signupStep3RequestModel); + } + + @override + Future changePassword(ChangePasswordParams changePasswordParams) { + return remoteDataSource.changePassword(changePasswordParams); + } + + @override + Future getPendingTransition(String accountNumber) { + return remoteDataSource.getPendingTransition(accountNumber); + } + + @override + Future createTransactionPinOTP(CreateTransactionPinOTPRequest requestModel) { + return remoteDataSource.createTransactionPinOTP(requestModel); + } + + @override + Future createTransactionPin(CreateTransactionPinRequest requestModel) { + return remoteDataSource.createTransactionPin(requestModel); + } + + @override + Future changeTransactionPin(ChangeTransactionPinRequest requestModel) { + return remoteDataSource.changeTransactionPin(requestModel); + } + + @override + Future acceptReceiveTransaction(AcceptReceiveTransactionModel requestModel) { + return remoteDataSource.acceptReceiveTransition(requestModel); + } + + @override + Future fetchAccountStatement(String accountNumber) { + return remoteDataSource.fetchAccountStatement(accountNumber); + } + + @override + Future fetchUserActivity(String fromDate, String toDate) { + return remoteDataSource.fetchUserActivity(fromDate, toDate); + } + + @override + Future getCurrencyList() { + return remoteDataSource.getCurrencyList(); + } + + @override + Future fetchGlsAccounts() { + return remoteDataSource.fetchGlsAllAccounts(); + } + + @override + Future getConvertedCurrency(String baseCurrency, String targetCurrency, String sgtGntramtfc) { + return remoteDataSource.getConvertedCurrency(baseCurrency, targetCurrency, sgtGntramtfc); + } + + @override + Future addNewAccount(AddNewAccountRequestModel addNewAccountRequest) { + return remoteDataSource.addNewAccount(addNewAccountRequest); + } + + @override + Future resentOtpLoginSignUp(ResendOtpLoginModel model) { + return remoteDataSource.resentOtpLoginSignUp(model); + } + + @override + Future resendOtpUsend(ResendOtpUsendModel resendOtpUsendModel) { + return remoteDataSource.resendOtpUsend(resendOtpUsendModel); + } + + @override + Future resendOtpTransPin(ResendOtpChangeTransPin resendOtpChangeTransPin) { + return remoteDataSource.resendOtpTransPin(resendOtpChangeTransPin); + } + + @override + Future createPinResndOtp(CreateTransactionPinOTPRequest createTransactionPinRequest) { + return remoteDataSource.createPinResndOtp(createTransactionPinRequest); + } + + @override + Future uploadUserProfilePicture(UploadUserProfileModel requestModel) { + return remoteDataSource.uploadUserProfilePicture(requestModel); + } + + @override + Future reverseTransaction(String nodeId, String sgtGntrnumber) { + return remoteDataSource.reverseTransition(nodeId, sgtGntrnumber); + } + + @override + Future addNewBeneficiary(BeneficiaryAccountModel requestModel) { + return remoteDataSource.addNewBeneficiary(requestModel); + } + + @override + Future fetchAllBeneficiary(String porOrgacode, String email) { + return remoteDataSource.fetchAllBeneficiary(porOrgacode, email); + } + + @override + Future deleteBeneficiary(String mbmBkmsnumberRef, String email, String porOrgacode) { + return remoteDataSource.deleteBeneficiary(mbmBkmsnumberRef, email, porOrgacode); + } +} diff --git a/lib/app/core/dialogs/custom_loading.dart b/lib/app/core/dialogs/custom_loading.dart new file mode 100644 index 0000000..448a580 --- /dev/null +++ b/lib/app/core/dialogs/custom_loading.dart @@ -0,0 +1,162 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:loader_overlay/loader_overlay.dart'; + +import '../../res/app_colors.dart'; +import '../constants/app_assets.dart'; + + +class CustomLoading extends StatefulWidget { + const CustomLoading({Key? key, this.type = 0}) : super(key: key); + + final int type; + + @override + _CustomLoadingState createState() => _CustomLoadingState(); +} + +class _CustomLoadingState extends State with TickerProviderStateMixin { + late AnimationController _controller; + + @override + void initState() { + _controller = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + _controller.forward(); + _controller.addStatusListener((status) { + if (status == AnimationStatus.completed) { + _controller.reset(); + _controller.forward(); + } + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Visibility(visible: widget.type == 2, child: _buildLoadingTwo()); + } + + // Widget _buildLoadingOne() { + // return Stack(alignment: Alignment.center, children: [ + // RotationTransition( + // alignment: Alignment.center, + // turns: _controller, + // child: Image.network( + // 'https://cdn.jsdelivr.net/gh/xdd666t/MyData@master/pic/flutter/blog/20211101174606.png', + // height: 110, + // width: 110, + // ), + // ), + // Image.network( + // 'https://cdn.jsdelivr.net/gh/xdd666t/MyData@master/pic/flutter/blog/20211101181404.png', + // height: 60, + // width: 60, + // ), + // ]); + // } + + Widget _buildLoadingTwo() { + return Container( + padding: const EdgeInsets.all(30.0), + decoration: BoxDecoration( + color: AppColors.white, + border: Border.all(color: Colors.white), + borderRadius: BorderRadius.circular(20.0), + ), + child: RotationTransition( + alignment: Alignment.center, + turns: _controller, + child: Image( + image: const AssetImage(AppAssets.kprogresshud_spinner), + color: Colors.black.withOpacity(0.5), + height: 50, + width: 50, + ), + ), + ); + } + + // Widget _buildLoadingThree() { + // return Center( + // child: Container( + // height: 120, + // width: 180, + // decoration: BoxDecoration( + // color: Colors.white, + // borderRadius: BorderRadius.circular(15), + // ), + // alignment: Alignment.center, + // child: Column(mainAxisSize: MainAxisSize.min, children: [ + // RotationTransition( + // alignment: Alignment.center, + // turns: _controller, + // child: Image.network( + // 'https://cdn.jsdelivr.net/gh/xdd666t/MyData@master/pic/flutter/blog/20211101163010.png', + // height: 50, + // width: 50, + // ), + // ), + // Container( + // margin: EdgeInsets.only(top: 20), + // child: Text(TranslationKeys.makeTranslation(TranslationKeys.textLoading)), + // ), + // ]), + // ), + // ); + // } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } +} + +showLoader() { + // Get.context!.loaderOverlay.show( + // widgetBuilder: (progress) => const Center( + // child: CustomLoading( + // type: 2, + // ), + // ), + // ); + + Get.context!.loaderOverlay.show( + widgetBuilder: (progress) => const Center( + child: Card( + color: Colors.white, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12))), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 10), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // SizedBox( + // height: 15, + // ), + // const CupertinoActivityIndicator( + // radius: 25, + // ), + CustomLoading(type: 2), + //SizedBox(height: 15), + // Text( + // "Loading", + // style: Theme.of(Get.context!).textTheme.bodyMedium, + // ), + // const SizedBox( + // height: 15, + // ), + ], + ), + ), + ), + ), + ); +} + +hideLoader() { + Get.context!.loaderOverlay.hide(); +} diff --git a/lib/app/core/enums/api_keys.dart b/lib/app/core/enums/api_keys.dart new file mode 100644 index 0000000..e6e3e91 --- /dev/null +++ b/lib/app/core/enums/api_keys.dart @@ -0,0 +1,66 @@ +/* +enum ApiKeys { + cmpUserId, + cmpCustpassword, + channelCode, + porOrgacode, + pctCstycode, + cmpIdennumber, + cmpUserIdType, + arguments, + cmpAccountno, + cmpCustcode, + phoneNo, + obpPincode, + newCustpassword +} + +extension ApiKeysExtension on ApiKeys { + String get value { + switch (this) { + case ApiKeys.cmpUserId: + return 'cmpUserId'; + case ApiKeys.cmpCustpassword: + return 'cmpCustpassword'; + case ApiKeys.channelCode: + return 'channelCode'; + case ApiKeys.porOrgacode: + return 'porOrgacode'; + case ApiKeys.pctCstycode: + return 'pctCstycode'; + case ApiKeys.cmpIdennumber: + return 'cmpIdennumber'; + case ApiKeys.cmpUserIdType: + return 'cmpUserIdType'; + case ApiKeys.arguments: + return 'arguments'; + case ApiKeys.cmpAccountno: + return 'cmpAccountno'; + case ApiKeys.cmpCustcode: + return 'cmpCustcode'; + case ApiKeys.phoneNo: + return 'phoneNo'; + case ApiKeys.obpPincode: + return 'obpPincode'; + case ApiKeys.newCustpassword: + return 'newCustpassword'; + } + } +} +*/ + +// class ApiKeys { +// static const String cmpUserId = 'cmpUserId'; +// static const String cmpCustpassword = 'cmpCustpassword'; +// static const String channelCode = 'channelCode'; +// static const String porOrgacode = 'porOrgacode'; +// static const String pctCstycode = 'pctCstycode'; +// static const String cmpIdennumber = 'cmpIdennumber'; +// static const String cmpUserIdType = 'cmpUserIdType'; +// static const String arguments = 'arguments'; +// static const String cmpAccountno = 'cmpAccountno'; +// static const String cmpCustcode = 'cmpCustcode'; +// static const String phoneNo = 'phoneNo'; +// static const String obpPincode = 'obpPincode'; +// static const String newCustpassword = 'newCustpassword'; +// } diff --git a/lib/app/core/enums/countryCode.dart b/lib/app/core/enums/countryCode.dart new file mode 100644 index 0000000..d7158de --- /dev/null +++ b/lib/app/core/enums/countryCode.dart @@ -0,0 +1,7 @@ +enum CountryCode { US, SA } + +extension CountryCodeExtension on CountryCode { + String get getKey { + return ["US", "SA"][index]; + } +} diff --git a/lib/app/core/enums/http_methods.dart b/lib/app/core/enums/http_methods.dart new file mode 100644 index 0000000..9225320 --- /dev/null +++ b/lib/app/core/enums/http_methods.dart @@ -0,0 +1 @@ +enum HttpMethod { GET, POST, PUT, DELETE,PATCH } diff --git a/lib/app/core/enums/languageCode.dart b/lib/app/core/enums/languageCode.dart new file mode 100644 index 0000000..f6fddc6 --- /dev/null +++ b/lib/app/core/enums/languageCode.dart @@ -0,0 +1,7 @@ +enum LanguageCode { ENGLISH, ARABIC } + +extension LanguageCodeExtension on LanguageCode { + String get getKey { + return ["en", "ar"][index]; + } +} diff --git a/lib/app/core/enums/request_constants.dart b/lib/app/core/enums/request_constants.dart new file mode 100644 index 0000000..8244737 --- /dev/null +++ b/lib/app/core/enums/request_constants.dart @@ -0,0 +1,8 @@ +class RequestConstants { + // static const String porOrgacode = "0004"; // Genish + static const String porOrgacode = "0005"; // BEMO + static const String pctCstycode = "I"; + static const String channelCode = "01"; + static const String plcLocacode = "plcLocacode"; + static const bool isOTPRequired = true; +} diff --git a/lib/app/core/enums/screen_type.dart b/lib/app/core/enums/screen_type.dart new file mode 100644 index 0000000..7405884 --- /dev/null +++ b/lib/app/core/enums/screen_type.dart @@ -0,0 +1 @@ +enum FieldTypes { multiLevelFields, otpField, multipleField } diff --git a/lib/app/core/extensions/build_context_ext.dart b/lib/app/core/extensions/build_context_ext.dart new file mode 100644 index 0000000..ac04d82 --- /dev/null +++ b/lib/app/core/extensions/build_context_ext.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../utils/logs_utils.dart'; + +extension BuildContextExt on BuildContext? { + // + + showSnakBar({required String msg}) { + if (msg.isEmpty) { + dp("Mess age is empty", msg); + return; + } + ScaffoldMessenger.of(this!).showSnackBar(SnackBar( + content: Text( + msg, + style: Get.context?.textTheme.bodyMedium!.copyWith( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + backgroundColor: Colors.white, + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + duration: const Duration(seconds: 4), + )); + } + + showGeneralDialog(List? children, {bool isShowOverly = false, bool dissmiss = true}) { + showDialog( + context: this!, + barrierDismissible: dissmiss, + barrierColor: isShowOverly ? Get.context.themeData.colorScheme.secondary.withOpacity(0.4) : null, + builder: (context) { + return SimpleDialog( + alignment: Alignment.center, + backgroundColor: Get.context.themeData.colorScheme.secondary, + children: children, + ); + }, + ); + } + + Size get getSize => MediaQuery.of(this!).size; + + double get getHeight => MediaQuery.of(this!).size.height; + + double get getWidth => MediaQuery.of(this!).size.width; + + TextTheme get textTheme => Theme.of(this!).textTheme; + + ThemeData get themeData => Theme.of(this!); + + bool get isSmall => MediaQuery.of(this!).size.height <= 690; + + bool get isVSmall => MediaQuery.of(this!).size.height <= 550; + + bool get isMedium => MediaQuery.of(this!).size.height < 750; +} diff --git a/lib/app/core/local_stoarge/app_storage.dart b/lib/app/core/local_stoarge/app_storage.dart new file mode 100644 index 0000000..67d1bbb --- /dev/null +++ b/lib/app/core/local_stoarge/app_storage.dart @@ -0,0 +1,169 @@ +import 'dart:convert'; +import 'package:hive/hive.dart'; + +class AppStorage { + // static const _storage = FlutterSecureStorage(); + // static Future> getAllData() async { + // final allData = await _storage.readAll(); + // return allData; + // } + // // Put methods + // static Future putString(String key, String value) async { + // await _storage.write(key: key, value: value); + // } + // + // static Future putInt(String key, int value) async { + // await _storage.write(key: key, value: value.toString()); + // } + // + // static Future putDouble(String key, double value) async { + // await _storage.write(key: key, value: value.toString()); + // } + // + // static Future putBoolean(String key, bool value) async { + // await _storage.write(key: key, value: value.toString()); + // } + // + // static Future putObject(String key, Object value) async { + // final jsonString = jsonEncode(value); + // await _storage.write(key: key, value: jsonString); + // } + // + // static Future putList(String key, List value) async { + // final jsonString = jsonEncode(value); + // await _storage.write(key: key, value: jsonString); + // } + // + // // Get methods with optional fallbacks + // static Future getString(String key, {String fallback = ''}) async { + // final value = await _storage.read(key: key); + // return value ?? fallback; + // } + // + // static Future getInt(String key, {int fallback = 0}) async { + // final value = await _storage.read(key: key); + // return value != null ? int.parse(value) : fallback; + // } + // + // static Future getDouble(String key, {double fallback = 0.0}) async { + // final value = await _storage.read(key: key); + // return value != null ? double.parse(value) : fallback; + // } + // + // static Future getBoolean(String key, {bool fallback = false}) async { + // final value = await _storage.read(key: key); + // return value != null && value.toLowerCase() == 'true' ? true : fallback; + // } + // + // static Future getObject(String key, {Object fallback = const {}}) async { + // final value = await _storage.read(key: key); + // return value != null ? jsonDecode(value) : fallback; + // } + // + // static Future> getList(String key, {List fallback = const []}) async { + // final value = await _storage.read(key: key); + // return value != null ? List.from(jsonDecode(value)) : fallback; + // } + +// Delete method (same as before) + + static Future putString(String key, String value) async { + final box = await Hive.openBox('appBox'); + await box.put(key, value); + await box.close(); + } + + static Future delete(String key) async { + final box = await Hive.openBox('appBox'); + await box.delete(key); + await box.close(); + } + + static Future putInt(String key, int value) async { + final box = await Hive.openBox('appBox'); + await box.put(key, value); + await box.close(); + } + + static Future putDouble(String key, double value) async { + final box = await Hive.openBox('appBox'); + await box.put(key, value); + await box.close(); + } + + static Future putBoolean(String key, bool value) async { + final box = await Hive.openBox('appBox'); + await box.put(key, value); + await box.close(); + } + + static Future putObject(String key, Object value) async { + final box = await Hive.openBox('appBox'); + await box.put(key, jsonEncode(value)); + await box.close(); + } + + static Future putList(String key, List value) async { + final box = await Hive.openBox('appBox'); + await box.put(key, jsonEncode(value)); + await box.close(); + } + + static Future getString(String key, {String fallback = ''}) async { + final box = await Hive.openBox('appBox'); + final value = box.get(key, defaultValue: fallback); + await box.close(); + return value; + } + + static Future getInt(String key, {int fallback = 0}) async { + final box = await Hive.openBox('appBox'); + final value = box.get(key, defaultValue: fallback); + await box.close(); + return value; + } + + static Future getDouble(String key, {double fallback = 0.0}) async { + final box = await Hive.openBox('appBox'); + final value = box.get(key, defaultValue: fallback); + await box.close(); + return value; + } + + static Future getBoolean(String key, {bool fallback = false}) async { + final box = await Hive.openBox('appBox'); + final value = box.get(key, defaultValue: fallback); + await box.close(); + return value; + } + + static Future getObject(String key, + {Object fallback = const {}}) async { + final box = await Hive.openBox('appBox'); + final value = box.get(key, defaultValue: fallback); + await box.close(); + return value != null ? jsonDecode(value) : fallback; + } + + static Future> getList(String key, + {List fallback = const []}) async { + final box = await Hive.openBox('appBox'); + final value = box.get(key, defaultValue: fallback); + await box.close(); + return value != null ? List.from(jsonDecode(value)) : fallback; + } + + static Future> getAllData() async { + final box = await Hive.openBox('appBox'); + final keys = box.keys.toList(); + final List allData = []; + + for (final key in keys) { + final value = box.get(key); + allData.add({'key': key, 'value': value}); + } + + await box.close(); + return allData; + } +} diff --git a/lib/app/core/utils/FingerPrintController.dart b/lib/app/core/utils/FingerPrintController.dart new file mode 100644 index 0000000..bf3f6ab --- /dev/null +++ b/lib/app/core/utils/FingerPrintController.dart @@ -0,0 +1,71 @@ +import 'dart:convert'; + +import 'package:get/get.dart'; +import 'package:local_auth/local_auth.dart'; + +import '../../models/finger_print_info.dart'; +import '../constants/app_contants.dart'; +import '../local_stoarge/app_storage.dart'; +import 'SessionCache.dart'; +// import 'package:local_auth/local_auth.dart'; + + +class FingerPrintController { + LocalAuthentication _localAuth = LocalAuthentication(); + RxBool isFingerPrintExistInDB = false.obs; + RxBool isFingerprintSupported = false.obs; + + FingerPrintController() { + _localAuth = LocalAuthentication(); + checkFingerprintSupport(); + checkIfExistDB(); + } + + Future checkIfExistDB() async { + String info = await AppStorage.getString(AppConstants.IS_FINGER_PRINT_ENABLED, fallback: ""); + isFingerPrintExistInDB.value = info.isNotEmpty; + } + + Future authenticate(Function(bool status)? callback, bool saveToDB) async { + try { + bool authenticated = await _localAuth.authenticate( + localizedReason: 'Authenticate to access the app', + options: const AuthenticationOptions( + stickyAuth: true, + biometricOnly: true, + useErrorDialogs: true, + ), + ); + if (authenticated) { + if (saveToDB) { + FingerPrintInfo fingerPrintInfo = FingerPrintInfo(); + fingerPrintInfo.porOrgacode = SessionCache.instance.userInfo.porOrgacode; + fingerPrintInfo.channelCode = SessionCache.instance.userInfo.channelCode; + fingerPrintInfo.cmpUserId = SessionCache.instance.userInfo.cmpUserId; + fingerPrintInfo.cmpCustpassword = SessionCache.instance.userInfo.cmpCustpassword; + await AppStorage.putString(AppConstants.IS_FINGER_PRINT_ENABLED, jsonEncode(fingerPrintInfo.toMap())); + isFingerPrintExistInDB.value = true; + isFingerprintSupported.value = true; + } + if (callback != null) { + callback(true); + } + } else { + if (callback != null) { + callback(false); + } + } + } catch (e) { + print(e); + } + } + + Future checkFingerprintSupport() async { + isFingerprintSupported.value = await _localAuth.isDeviceSupported(); + } + + Future clearFromDB() async { + await AppStorage.putString(AppConstants.IS_FINGER_PRINT_ENABLED, ""); + isFingerPrintExistInDB.value = false; + } +} diff --git a/lib/app/core/utils/SessionCache.dart b/lib/app/core/utils/SessionCache.dart new file mode 100644 index 0000000..9aa8de3 --- /dev/null +++ b/lib/app/core/utils/SessionCache.dart @@ -0,0 +1,79 @@ +import 'package:get/get.dart'; +import '../../models/DepositAccountResponse.dart'; +import '../../models/ExchangeRate.dart'; +import '../../models/GlsResponseModel.dart'; +import '../../models/UserInfo.dart'; +import 'FingerPrintController.dart'; + +class SessionCache { + static final SessionCache _instance = SessionCache._internal(); + + factory SessionCache() { + return _instance; + } + + SessionCache._internal(); + + FingerPrintController _fingerPrintController = FingerPrintController(); + + UserInfo userInfo = UserInfo(); + + RxList _depositAccountList = RxList.empty(); + + RxList _exchangeRateList = RxList.empty(); + RxList _glsAccountsList = RxList.empty(); + + // RxList _paymentPurposeList = RxList.empty(); + // RxList _loanAccountList = RxList.empty(); + // List _beneficiaryAccountList = []; + // List _favBeneficiaryAccountList = []; + + static SessionCache get instance => _instance; + + RxList get exchangeRateList => _exchangeRateList; + + RxList get glsAccountsList => _glsAccountsList; + + set glsAccountsList(RxList value) { + _glsAccountsList = value; + } + + set exchangeRateList(RxList value) { + _exchangeRateList = value; + } //RxList get paymentPurposeList => _paymentPurposeList; + + // set paymentPurposeList(RxList value) { + // _paymentPurposeList = value; + // } + + RxList get depositAccountList => _depositAccountList; + + // List get favBeneficiaryAccountList => _favBeneficiaryAccountList; + // + FingerPrintController get fingerPrintController => _fingerPrintController; + + // + // RxList get loanAccountList => _loanAccountList; + // + // List get beneficiaryAccountList => _beneficiaryAccountList; + // + // set favBeneficiaryAccountList(List value) { + // _favBeneficiaryAccountList = value; + // } + // + // set fingerPrintController(FingerPrintController value) { + // _fingerPrintController = value; + // } + + setDepositAccountList(RxList value) { + _depositAccountList = value; + } + +// set loanAccountList(RxList value) { +// _loanAccountList = value; +// } +// +// set beneficiaryAccountList(List value) { +// _beneficiaryAccountList = value; +// } +} diff --git a/lib/app/core/utils/app_utils.dart b/lib/app/core/utils/app_utils.dart new file mode 100644 index 0000000..e4cf4b5 --- /dev/null +++ b/lib/app/core/utils/app_utils.dart @@ -0,0 +1,93 @@ +import 'package:intl/intl.dart'; + +import '../../models/ExchangeRate.dart'; +import 'SessionCache.dart'; + + +class AppUtils { + /// Balance show format method + static String formatCurrency(num value) { + final currencyFormatter = NumberFormat.currency( + // locale: 'eu', + customPattern: '#,##,###', + symbol: '', // Set the currency symbol + decimalDigits: 2, // Set the number of decimal places + ); + + return currencyFormatter.format(value); + } + + bool isValidEmail(String email) { + final RegExp emailRegex = RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$'); + return emailRegex.hasMatch(email); + } + + static String formatDateTime(String dateTimeString, String format) { + DateTime dateTime = DateTime.parse(dateTimeString); + final formatter = DateFormat(format); + String formattedDateTime = formatter.format(dateTime); + return formattedDateTime; + } + + static String showAmountWithCurr(String amount, String currencyCode) { + ExchangeRate exchangeRate = SessionCache.instance.exchangeRateList.firstWhere((rate) => rate.pcrCurrcode == currencyCode, orElse: () => ExchangeRate.empty()); + return exchangeRate.pcrCurrshort.isEmpty ? '$currencyCode $amount' : '${exchangeRate.pcrCurrshort} $amount'; + } + + static String accountNumberFormatter(String accountNumber) { + return accountNumber; + } + + static bool isPasswordValid(String password, [int minLength = 8]) { + bool hasUppercase = password.contains(RegExp(r'[A-Z]')); + bool hasDigits = password.contains(RegExp(r'[0-9]')); + bool hasLowercase = password.contains(RegExp(r'[a-z]')); + bool hasSpecialCharacters = password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]')); + bool hasMinLength = password.length >= minLength; + return hasDigits & hasUppercase & hasLowercase & hasSpecialCharacters & hasMinLength; + } + + static String getInitials(String fullName) { + List words = fullName.split(' '); + if (words.isNotEmpty) { + String initials = words.map((word) => word.isNotEmpty ? word[0].toUpperCase() : '').join(); + return initials.length >= 2 ? initials.substring(0, 2) : initials; + } else { + return ''; + } + } + + static String formatPhoneNumber(String phoneNumber) { + if (phoneNumber.startsWith("0")) { + phoneNumber = "+92${phoneNumber.substring(1)}"; + } + if (phoneNumber.startsWith("3")) { + phoneNumber = "+92$phoneNumber"; + } + if (phoneNumber.startsWith("92")) { + phoneNumber = "+$phoneNumber"; + } + if (phoneNumber.contains("-")) { + phoneNumber = phoneNumber.replaceAll("-", ""); + } + phoneNumber = phoneNumber.replaceAll(" ", ""); + return phoneNumber; + } + + static String convertDateTime(String timestamp) { + // Parse the timestamp string into a DateTime object + DateTime dateTime = DateTime.parse(timestamp); + + // Format the DateTime object to display only the date and time + String formattedDateTime = + '${dateTime.year}-${dateTime.month.toString().padLeft(2, '0')}-${dateTime.day.toString().padLeft(2, '0')} ' + '${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}:${dateTime.second.toString().padLeft(2, '0')}'; + + return formattedDateTime; + } + + + static String showAmountWithCurrencyCode(String amount) { + return "Rs. " + amount; + } +} diff --git a/lib/app/core/utils/fields_utils.dart b/lib/app/core/utils/fields_utils.dart new file mode 100644 index 0000000..70a0bc3 --- /dev/null +++ b/lib/app/core/utils/fields_utils.dart @@ -0,0 +1,12 @@ +import 'package:flutter/services.dart'; + +class FieldUtils { + static const int userNameFieldLength = 100; + static const int transactionPinLength = 6; + static const int addressFieldLength = 250; + static const int phoneNumberFieldLength = 100; +} + +hideKeyBoard() { + SystemChannels.textInput.invokeMethod('TextInput.hide'); +} diff --git a/lib/app/core/utils/globle_keys.dart b/lib/app/core/utils/globle_keys.dart new file mode 100644 index 0000000..a47f241 --- /dev/null +++ b/lib/app/core/utils/globle_keys.dart @@ -0,0 +1 @@ +import 'package:flutter/material.dart'; diff --git a/lib/app/core/utils/logs_utils.dart b/lib/app/core/utils/logs_utils.dart new file mode 100644 index 0000000..c55117e --- /dev/null +++ b/lib/app/core/utils/logs_utils.dart @@ -0,0 +1,23 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; + +dp(msg, arg) { + // debugPrint("\n"); + + if (Platform.isAndroid) { + debugPrint("\u001b[1;32m $msg $arg"); + } else { + debugPrint("$msg $arg"); + } +} + +pe(msg, arg) { + if (Platform.isAndroid) { + debugPrint("\u001b[1;31m $msg "); + debugPrint("\u001b[1;31m $arg"); + } else { + debugPrint("$msg "); + debugPrint("$arg"); + } +} diff --git a/lib/app/core/utils/phone_number_utils.dart b/lib/app/core/utils/phone_number_utils.dart new file mode 100644 index 0000000..8e26ff6 --- /dev/null +++ b/lib/app/core/utils/phone_number_utils.dart @@ -0,0 +1,9 @@ +class PhoneNumberUtils { + static String phoneCodeText = '(+92) '; + static String phoneCode = '+92'; + + static int getPhoneNumberLength() { + return 12; + } + +} diff --git a/lib/app/core/utils/root_detector_device.dart b/lib/app/core/utils/root_detector_device.dart new file mode 100644 index 0000000..c311a4c --- /dev/null +++ b/lib/app/core/utils/root_detector_device.dart @@ -0,0 +1,45 @@ +import 'dart:io'; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:root_checker_plus/root_checker_plus.dart'; + +Future isDeviceRootedOrJailbroken() async { + if (Platform.isAndroid) { + bool? isRooted = await RootCheckerPlus.isRootChecker(); + return isRooted ?? false; + } else if (Platform.isIOS) { + return await _isJailbroken(); + } else { + return false; // Other platforms are not supported + } +} + +Future _isJailbroken() async { + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + IosDeviceInfo iosInfo = await deviceInfo.iosInfo; + + // List of common jailbreak indicators + List jailbreakIndicators = ['/Applications/Cydia.app', '/Library/MobileSubstrate/MobileSubstrate.dylib', '/bin/bash', '/usr/sbin/sshd', '/etc/apt', '/private/var/lib/apt/', '/private/var/lib/cydia', '/var/log/syslog']; + + // Check for the existence of jailbreak indicator files + for (String indicator in jailbreakIndicators) { + if (File(indicator).existsSync()) { + return true; + } + } + + // Check if we can write outside the app's sandbox + try { + File('/private/jailbreak.txt').writeAsStringSync('Jailbreak test'); + return true; + } catch (e) { + // If we cannot write outside the sandbox, it's likely not jailbroken + } + + // Check for suspicious environment variables + if (Platform.environment.containsKey('DYLD_INSERT_LIBRARIES')) { + return true; + } + + return false; +} diff --git a/lib/app/core/utils/simulator_check.dart b/lib/app/core/utils/simulator_check.dart new file mode 100644 index 0000000..6e3392b --- /dev/null +++ b/lib/app/core/utils/simulator_check.dart @@ -0,0 +1,17 @@ +import 'dart:io'; + +import 'package:device_info_plus/device_info_plus.dart'; + +Future isEmulator() async { + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + + if (Platform.isAndroid) { + AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + return !androidInfo.isPhysicalDevice; + } else if (Platform.isIOS) { + IosDeviceInfo iosInfo = await deviceInfo.iosInfo; + return !iosInfo.isPhysicalDevice; + } else { + return false; + } +} diff --git a/lib/app/core/utils/url_encryption.dart b/lib/app/core/utils/url_encryption.dart new file mode 100644 index 0000000..0a02eb1 --- /dev/null +++ b/lib/app/core/utils/url_encryption.dart @@ -0,0 +1,59 @@ +import 'package:encrypt/encrypt.dart' as encrypt; +import 'package:flutter_dotenv/flutter_dotenv.dart'; + +// class UrlEncryption { +// /// The singleton instance +// static final UrlEncryption _instance = UrlEncryption._internal(); +// +// /// Private constructor +// // UrlEncryption._internal() { +// // _init(); +// // } +// +// /// Factory constructor to return the same instance +// factory UrlEncryption() { +// return _instance; +// } +// +// /// Encryption key +// encrypt.Key? _key; +// +// /// Method to initialize the encryption key from environment variable +// // void _init() { +// // final keyString = dotenv.env['ENCRYPTION_KEY']; +// // if (keyString == null || keyString.length != 32) { +// // throw Exception('Invalid encryption key in environment variables.'); +// // } +// // _key = encrypt.Key.fromUtf8(keyString); +// // } +// +// /// Method to encrypt data +// String encryptData(String data) { +// if (_key == null) { +// throw Exception('Encryption key is not initialized.'); +// } +// final iv = encrypt.IV.fromLength(16); // Generate a random IV +// final encrypter = encrypt.Encrypter(encrypt.AES(_key!, mode: encrypt.AESMode.cbc)); +// +// final encrypted = encrypter.encrypt(data, iv: iv); +// final ivBase64 = iv.base64; +// final encryptedBase64 = encrypted.base64; +// +// return '$ivBase64:$encryptedBase64'; // Store IV and ciphertext together +// } +// +// /// Method to decrypt data +// String decryptData(String encryptedData) { +// if (_key == null) { +// throw Exception('Encryption key is not initialized.'); +// } +// final parts = encryptedData.split(':'); +// final iv = encrypt.IV.fromBase64(parts[0]); // Extract the IV +// final encrypted = encrypt.Encrypted.fromBase64(parts[1]); +// +// final encrypter = encrypt.Encrypter(encrypt.AES(_key!, mode: encrypt.AESMode.cbc)); +// final decrypted = encrypter.decrypt(encrypted, iv: iv); +// +// return decrypted; +// } +// } diff --git a/lib/app/custom_widgets/Fields/custom_dropdown_bottom_sheet.dart b/lib/app/custom_widgets/Fields/custom_dropdown_bottom_sheet.dart new file mode 100644 index 0000000..62bb384 --- /dev/null +++ b/lib/app/custom_widgets/Fields/custom_dropdown_bottom_sheet.dart @@ -0,0 +1,267 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../core/constants/translation_keys.dart'; +import '../../res/app_colors.dart'; +import '../custom_dropdown.dart'; +import '../custom_text.dart'; +import 'input_field.dart'; + +class CustomDropDownBottomSheet { + void showBottomSheet(BuildContext context, List options, + String type, Function(DropDown)? onItemSelected) { + Get.bottomSheet( + Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AppColors.colorGrey500, width: 1), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), topRight: Radius.circular(30))), + margin: EdgeInsets.only(left: 20, right: 20), + child: DialogDesign(options, type, (selectedOption) { + if (onItemSelected != null) { + onItemSelected(selectedOption); + } + }), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); + } +} + +@immutable +class DialogDesign extends StatelessWidget { + List options = []; + String type = ""; + Function(DropDown) onSelect; + + DialogDesign(this.options, this.type, this.onSelect); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Visibility( + visible: type == DropDownType.NORMAL, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textSelectOption), + style: Theme.of(context).textTheme.titleLarge?.copyWith( + color: AppColors.colorGrey700, + fontSize: 16, + fontWeight: FontWeight.w600), + ), + InkWell( + onTap: () { + Get.back(); + }, + child: CircleAvatar( + radius: 15, + backgroundColor: Colors.transparent, + child: Icon(Icons.close, + size: 20.0, color: Colors.blue)), + ), + ], + ), + SizedBox(height: 10.0), + ], + )), + FilterableBottomSheet( + options: options, type: type, onSelect: onSelect), + ], + ), + ); + } +} + +class FilterableBottomSheet extends StatefulWidget { + final List options; + final String type; + final Function(DropDown) onSelect; + + FilterableBottomSheet( + {required this.options, required this.onSelect, required this.type}); + + @override + _FilterableBottomSheetState createState() => _FilterableBottomSheetState(); +} + +class _FilterableBottomSheetState extends State { + TextEditingController _filterTextController = TextEditingController(); + List _filteredOptions = []; + + @override + void initState() { + super.initState(); + _filteredOptions.addAll(widget.options); + } + + void _updateFilteredList(String query) { + setState(() { + _filteredOptions.clear(); + if (query.isEmpty) { + _filteredOptions.addAll(widget.options); + } else { + query = query.toLowerCase(); + _filteredOptions.addAll(widget.options + .where((item) => item.label.toLowerCase().contains(query))); + } + }); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(10.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Visibility( + visible: widget.type == DropDownType.NORMAL, + child: Column( + children: [ + Container( + height: 40, + padding: EdgeInsets.symmetric(horizontal: 15.0), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon(Icons.search, + size: 20, color: AppColors.colorGrey700), + SizedBox(width: 5.0), + Expanded( + child: TextField( + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w500, fontSize: 14), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation( + TranslationKeys.textSearch), + ), + controller: _filterTextController, + onChanged: _updateFilteredList, + ), + ), + ], + ), + ), + SizedBox(height: 20.0), + ], + ), + ), + Container( + height: _filteredOptions.length <= 5 + ? (45 * _filteredOptions.length) + + (10 * (_filteredOptions.length - 1)) + : 300, + child: ListView.separated( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + itemCount: _filteredOptions.length, + itemBuilder: (context, index) { + return widget.type == DropDownType.SPECIAL + ? InkWell( + onTap: () { + widget.onSelect(_filteredOptions[index]); + Navigator.pop(context); + }, + child: Container( + height: 45, + decoration: BoxDecoration( + color: AppColors.colorGrey100, + borderRadius: + BorderRadius.all(Radius.circular(10))), + child: Padding( + padding: EdgeInsets.all(12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CustomText(_filteredOptions[index].label, + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith( + fontSize: 14, + fontWeight: FontWeight.w500, + color: AppColors.colorGrey700)), + Icon(Icons.arrow_forward_ios, + size: 14, color: AppColors.colorNavyBlue), + ], + ), + ), + ), + ) + : Padding( + padding: EdgeInsets.only(top: 5, bottom: 5), + child: InkWell( + onTap: () { + widget.onSelect(_filteredOptions[index]); + Navigator.pop(context); + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomText(_filteredOptions[index].label, + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith( + fontSize: 14, + fontWeight: FontWeight.w500, + color: AppColors.colorGrey700)), + SizedBox(height: 5), + Visibility( + visible: _filteredOptions[index].id.isNotEmpty, + child: Column( + children: [ + CustomText(_filteredOptions[index].id, + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith( + fontSize: 12, + fontWeight: FontWeight.w500, + color: AppColors.colorGrey600)), + ], + ), + ), + SizedBox(height: 5), + Divider( + thickness: 0.2, + color: AppColors.colorGrey600), + ], + ), + ), + ); + }, + separatorBuilder: (BuildContext context, int index) { + return SizedBox(height: 10); + }, + ), + ), + ], + ), + ); + } +} diff --git a/lib/app/custom_widgets/Fields/field_validations.dart b/lib/app/custom_widgets/Fields/field_validations.dart new file mode 100644 index 0000000..23df0ae --- /dev/null +++ b/lib/app/custom_widgets/Fields/field_validations.dart @@ -0,0 +1,26 @@ +import 'package:flutter/cupertino.dart'; + +import 'input_field.dart'; + +class FieldValidation { + static bool validateAll([List widgetList = const []]) { + bool isValid = true; + for (Widget widget in widgetList) { + if (widget is InputField) { + InputField inputFieldCustom = widget; + bool valid = inputFieldCustom.validate(inputFieldCustom.controller!.text); + if (!valid) { + isValid = false; + } + } + // if (widget is CustomDatePicker) { + // CustomDatePicker inputFieldCustom = widget; + // bool valid = inputFieldCustom.validate(inputFieldCustom.controller!.text); + // if (!valid) { + // isValid = false; + // } + // } + } + return isValid; + } +} diff --git a/lib/app/custom_widgets/Fields/input_field.dart b/lib/app/custom_widgets/Fields/input_field.dart new file mode 100644 index 0000000..689e196 --- /dev/null +++ b/lib/app/custom_widgets/Fields/input_field.dart @@ -0,0 +1,535 @@ +import 'dart:ui'; +import 'package:country_code_picker/country_code_picker.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:get/get.dart'; + +import '../../core/constants/translation_keys.dart'; +import '../../res/app_colors.dart'; +import '../../res/app_theme.dart'; +import '../custom_dropdown.dart'; +import '../custom_text.dart'; +import 'custom_dropdown_bottom_sheet.dart'; + + +class InputField extends GetView { + final FormFieldValidator? validator; + GlobalKey? refKey; + String labelText = ""; + String hintText = ""; + RxString errorTextMessage = "".obs; + final RxBool _passwordVisible = true.obs; + int? radius = 100; + EdgeInsetsGeometry? contentPadding = const EdgeInsets.symmetric(horizontal: 15, vertical: 15); + + // String errorText = ""; + + bool isRequired = true; + bool requiredPasswordIcon = false; + Function(String?)? onChanged; + FocusNode? focusNode = FocusNode(); + Function(DropDown?)? onItemSelected; + Rx selectedCountryCode = CountryCode().obs; + + Rx? selectedOption; + + // DropDown? selectedOption; + final bool enabled; + bool isDropDown = false; + bool isTopMarginRequired = true; + bool isCountryPicker = false; + bool isBoxDecoration = true; + bool showLabel = true; + String? dropDownType = DropDownType.NORMAL; + List? items; + final AutovalidateMode autovalidateMode; + final String? restorationId; + InputDecoration? decoration; + TextEditingController? controller; + TextInputType? keyboardType; + final TextInputAction? textInputAction; + final TextCapitalization textCapitalization; + final TextStyle? style; + final StrutStyle? strutStyle; + TextAlign textAlign; + final TextAlignVertical? textAlignVertical; + final TextDirection? textDirection; + final bool autofocus; + final String obscuringCharacter; + bool isPassword = false; + bool autocorrect = false; + final SmartDashesType? smartDashesType; + final SmartQuotesType? smartQuotesType; + final bool enableSuggestions; + int maxLines; + int minLines; + bool expands; + final int? maxLength; + final MaxLengthEnforcement? maxLengthEnforcement; + final VoidCallback? onEditingComplete; + final ValueChanged? onSubmitted; + final List? inputFormatters; + bool showCursor = true; + double cursorWidth = 5.0; + double cursorHeight = 15.0; + Radius cursorRadius = const Radius.circular(10.0); + Color cursorColor = AppThemeData.inputTextColor; + final BoxHeightStyle selectionHeightStyle; + final BoxWidthStyle selectionWidthStyle; + final Brightness? keyboardAppearance; + final EdgeInsets scrollPadding; + final bool enableInteractiveSelection; + Widget? prefixIcon; + Widget? suffixIcon; + final DragStartBehavior dragStartBehavior; + final Function()? onClick; + final TapRegionCallback? onTapOutside; + final MouseCursor? mouseCursor; + final InputCounterWidgetBuilder? buildCounter; + final ScrollPhysics? scrollPhysics; + final ScrollController? scrollController; + final Iterable? autofillHints; + final TextMagnifierConfiguration? magnifierConfiguration; + bool readOnly; + final ContentInsertionConfiguration? contentInsertionConfiguration; + SpellCheckConfiguration? spellCheckConfiguration; + final String? prefixText; + final String? prefixCode; + final double? inputFontSize; + final FontWeight? inputFontWeight; + final Color? inputColor; + + final Rx inputErrorColor = Rx(Colors.black); + final Rx inputErrorBorderColor = Rx(Colors.black); + RxBool isError = false.obs; + + InputField({ + this.refKey, + this.controller, + this.labelText = "", + this.hintText = "", + // this.errorText = "", + this.isRequired = true, + this.requiredPasswordIcon = false, + this.isBoxDecoration = true, + this.showLabel = true, + this.isTopMarginRequired = true, + this.isDropDown = false, + this.isCountryPicker = false, + this.dropDownType, + this.inputFontSize, + this.inputFontWeight, + this.inputColor, + this.validator, + this.contentPadding = const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + this.items, + this.radius = 100, + this.decoration, + this.focusNode, + this.onChanged, + this.onItemSelected, + this.prefixIcon, + this.suffixIcon, + this.selectedOption, + this.enabled = true, + this.autovalidateMode = AutovalidateMode.disabled, + this.restorationId, + this.readOnly = false, + this.isPassword = false, + this.textCapitalization = TextCapitalization.none, + this.scrollPadding = const EdgeInsets.all(20.0), + this.enableInteractiveSelection = true, + this.maxLengthEnforcement, + this.textAlign = TextAlign.start, + this.autofocus = false, + this.autocorrect = false, + this.cursorWidth = 5.0, + this.cursorHeight = 20.0, + this.cursorRadius = const Radius.circular(10.0), + this.keyboardType, + this.style, + this.textInputAction, + this.strutStyle, + this.textDirection, + this.maxLength, + this.onEditingComplete, + this.onSubmitted, + this.inputFormatters, + this.cursorColor = AppThemeData.inputTextColor, + this.keyboardAppearance, + this.buildCounter, + this.expands = false, + this.minLines = 1, + this.maxLines = 1, + this.showCursor = true, + this.onClick, + this.onTapOutside, + this.enableSuggestions = true, + this.textAlignVertical, + this.dragStartBehavior = DragStartBehavior.start, + this.scrollController, + this.scrollPhysics, + this.selectionWidthStyle = BoxWidthStyle.tight, + this.smartDashesType, + this.smartQuotesType, + this.selectionHeightStyle = BoxHeightStyle.tight, + this.autofillHints, + this.obscuringCharacter = '•', + this.mouseCursor, + this.magnifierConfiguration, + this.contentInsertionConfiguration, + this.spellCheckConfiguration, + this.prefixText, + this.prefixCode, + }) : errorTextMessage = "".obs { + // errorText = errorTextMessage.value; + } + + void setText(String text) { + controller!.text = text; + markFieldAsValid(); + } + + void clear() { + controller!.clear(); + markFieldAsValid(); + } + + void setError(String errorMessage) { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = errorMessage; + isError.value = true; + } + + void markFieldAsValid() { + inputErrorBorderColor.value = AppThemeData.inputBackgroundColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = ""; + isError.value = false; + } + + void markFieldAsInvalid() { + print("============================="); + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = TranslationKeys.makeTranslation(TranslationKeys.textErrorRequired); + isError.value = true; + } + + void setDropDownOption(DropDown option) { + selectedOption = Rx(option); + setText(selectedOption!.value.label); + markFieldAsValid(); + } + + bool validate(String value) { + if (isRequired) { + if (value.isEmpty) { + markFieldAsInvalid(); + return false; + } + markFieldAsValid(); + return true; + } + markFieldAsValid(); + return true; + } + + @override + Widget build(BuildContext context) { + return Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: isTopMarginRequired ? 15 : 0), + Visibility( + visible: isBoxDecoration && showLabel, + child: Column( + children: [ + CustomText(labelText, style: AppThemeData.labelStyle), + const SizedBox(height: 5), + ], + ), + ), + FormBuilderTextField( + key: refKey, + name: "", + focusNode: focusNode, + decoration: isCountryPicker ? countryCodeDecoration() : (isBoxDecoration ? boxedDecoration() : normalFieldDecoration()), + enabled: enabled, + autovalidateMode: autovalidateMode, + restorationId: restorationId, + readOnly: isDropDown ? true : readOnly, + + validator: (value) { + validate(value!); + return null; + }, + onChanged: (value) { + if (value!.isNotEmpty) { + markFieldAsValid(); + } + if (onChanged != null) { + onChanged!(value); + } + }, + textCapitalization: textCapitalization, + scrollPadding: scrollPadding, + enableInteractiveSelection: enableInteractiveSelection, + maxLengthEnforcement: maxLengthEnforcement, + textAlign: textAlign, + autofocus: isDropDown ? false : autofocus, + autocorrect: autocorrect, + keyboardType: keyboardType, + style: AppThemeData.inputStyle.copyWith(height: 1, fontSize: double.parse((inputFontSize ?? "0.0").toString()) == 0 ? AppThemeData.inputStyle.fontSize : double.parse((inputFontSize ?? "0.0").toString()), fontWeight: inputFontWeight ?? AppThemeData.inputStyle.fontWeight, color: inputColor ?? AppThemeData.inputStyle.color), + controller: controller, + textInputAction: textInputAction ?? TextInputAction.done, + strutStyle: strutStyle, + textDirection: textDirection, + maxLength: maxLength, + onEditingComplete: onEditingComplete, + onSubmitted: onSubmitted, + inputFormatters: inputFormatters, + cursorColor: cursorColor, + // cursorWidth: 1.5, + // cursorHeight: 15, + // cursorRadius: Radius.circular(10.0), + keyboardAppearance: keyboardAppearance, + buildCounter: buildCounter, + expands: expands, + maxLines: isPassword ? maxLines = 1 : maxLines, + obscureText: isPassword && _passwordVisible.value, + minLines: isPassword ? minLines = 1 : minLines, + showCursor: isDropDown ? false : showCursor, + onTap: () { + if (onClick != null) { + onClick!(); + } + if (isDropDown && items != null && items!.isNotEmpty) { + // + + FocusScope.of(context).requestFocus(FocusNode()); + + CustomDropDownBottomSheet().showBottomSheet(context, items!, dropDownType ?? DropDownType.NORMAL, (selectedItem) { + setText(selectedItem.label); + selectedOption = Rx(selectedItem); + if (onItemSelected != null) { + onItemSelected!(selectedItem); + } + }); + } + }, + onTapOutside: onTapOutside, + enableSuggestions: enableSuggestions, + textAlignVertical: textAlignVertical, + dragStartBehavior: dragStartBehavior, + scrollController: scrollController, + scrollPhysics: scrollPhysics, + selectionWidthStyle: selectionWidthStyle, + smartDashesType: smartDashesType, + smartQuotesType: smartQuotesType, + selectionHeightStyle: BoxHeightStyle.tight, + autofillHints: autofillHints, + obscuringCharacter: obscuringCharacter, + mouseCursor: mouseCursor, + magnifierConfiguration: magnifierConfiguration, + contentInsertionConfiguration: contentInsertionConfiguration, + spellCheckConfiguration: spellCheckConfiguration, + ), + ], + ); + }); + } + + InputDecoration normalFieldDecoration() { + return InputDecoration( + filled: true, + prefixIcon: prefixIcon, + fillColor: AppColors.transparent, + isDense: true, + contentPadding: const EdgeInsets.only(bottom: 5), + labelText: labelText, + labelStyle: AppThemeData.labelStyle, + errorStyle: AppThemeData.errorStyle.copyWith(color: inputErrorColor.value), + errorBorder: UnderlineInputBorder(borderSide: BorderSide(color: inputErrorBorderColor.value)), + focusedBorder: const UnderlineInputBorder(borderSide: BorderSide(color: AppThemeData.inputFocusedBorderColor, width: 1.5)), + enabledBorder: const UnderlineInputBorder(borderSide: BorderSide(color: AppThemeData.inputEnabledBorderColor, width: 1.5)), + errorText: errorTextMessage.value.isEmpty ? null : errorTextMessage.value, + hintText: hintText.isEmpty ? null : hintText, + hintStyle: AppThemeData.hintStyle, + prefixText: prefixText, + prefixStyle: AppThemeData.hintStyle, + suffixIcon: Icon( + Icons.arrow_forward_ios_outlined, + color: AppColors.colorGrey500, + size: isDropDown ? 22 : 0, + ), + ); + } + + InputDecoration boxedDecoration() { + return InputDecoration( + isDense: true, + contentPadding: contentPadding ?? const EdgeInsets.symmetric(horizontal: 15, vertical: 15) /*EdgeInsets.all(10)*/, + labelText: isBoxDecoration ? null : (labelText.isNotEmpty ? labelText : null), + labelStyle: AppThemeData.labelStyle, + prefixIcon: prefixIcon, + errorStyle: AppThemeData.errorStyle.copyWith(color: inputErrorColor.value), + // border: OutlineInputBorder(borderSide: BorderSide(color: inputErrorBorderColor.value), borderRadius: BorderRadius.all(Radius.circular(10))), + focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: inputErrorBorderColor.value), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + errorBorder: OutlineInputBorder(borderSide: BorderSide(color: inputErrorBorderColor.value), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + focusedBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputFocusedBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + enabledBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputEnabledBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + errorText: errorTextMessage.value.isEmpty ? null : errorTextMessage.value, + hintText: hintText.isEmpty ? null : hintText, + hintStyle: AppThemeData.hintStyle, + prefixText: prefixText, + // prefixStyle: AppThemeData.hintStyle, + suffixIcon: suffixIcon ?? addSuffixIcon(), + ); + } + + Widget? addSuffixIcon() { + if (requiredPasswordIcon) { + return IconButton( + icon: Icon(size: 18, color: AppColors.colorGrey500, _passwordVisible.value ? Icons.visibility : Icons.visibility_off_rounded), + onPressed: () { + _passwordVisible.value = !_passwordVisible.value; + }, + ); + } else if (isDropDown) { + return const Icon( + Icons.arrow_forward_ios_outlined, + color: AppColors.colorGrey500, + size: 22, + ); + } + return null; + } + + InputDecoration countryCodeDecoration() { + return InputDecoration( + prefixIcon: CountryCodePicker( + initialSelection: 'PK', + onInit: (code) { + selectedCountryCode.value = code!; + }, + showFlagDialog: true, + showCountryOnly: true, + countryFilter: const [ + 'pk', + 'us', + 'it', + ], + emptySearchBuilder: (context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 15), + CustomText("No Results", style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.inputLabelColor)), + ], + ); + }, + onChanged: (val) { + selectedCountryCode.value = val; + }, + + searchDecoration: InputDecoration( + filled: false, + fillColor: AppColors.transparent, + isDense: false, + alignLabelWithHint: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + errorStyle: AppThemeData.errorStyle.copyWith(color: AppThemeData.inputErrorColor), + errorBorder: const OutlineInputBorder(borderSide: BorderSide(color: AppThemeData.inputErrorBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(10))), + focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: AppThemeData.inputFocusedBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(10))), + enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: AppThemeData.inputEnabledBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(10))), + prefixStyle: AppThemeData.hintStyle, + ), + searchStyle: AppThemeData.inputStyle.copyWith(height: 1), + // textStyle: AppThemeData.inputStyle.copyWith(height: 1), + ), + isDense: true, + contentPadding: const EdgeInsets.all(10), + labelText: isBoxDecoration ? null : (labelText.isNotEmpty ? labelText : null), + labelStyle: AppThemeData.labelStyle, + errorStyle: AppThemeData.errorStyle.copyWith(color: inputErrorColor.value), + focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: inputErrorBorderColor.value), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + errorBorder: OutlineInputBorder(borderSide: BorderSide(color: inputErrorBorderColor.value), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + focusedBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputFocusedBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + enabledBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputEnabledBorderColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(radius == -1 ? 10 : double.parse(radius.toString())))), + // focusedErrorBorder: OutlineInputBorder( + // borderSide: BorderSide(color: inputErrorBorderColor.value), + // borderRadius: const BorderRadius.all(Radius.circular(10))), + // errorBorder: OutlineInputBorder( + // borderSide: BorderSide(color: inputErrorBorderColor.value), + // borderRadius: const BorderRadius.all(Radius.circular(10))), + // focusedBorder: const OutlineInputBorder( + // borderSide: BorderSide( + // color: AppThemeData.inputFocusedBorderColor, + // width: 1.5, + // ), + // borderRadius: BorderRadius.all(Radius.circular(10))), + // enabledBorder: const OutlineInputBorder( + // borderSide: BorderSide( + // color: AppThemeData.inputEnabledBorderColor, width: 1.5), + // borderRadius: BorderRadius.all(Radius.circular(10))), + errorText: errorTextMessage.value.isEmpty ? null : errorTextMessage.value, + hintText: hintText.isEmpty ? null : hintText, + hintStyle: AppThemeData.hintStyle, + prefixText: prefixText ?? "", + prefixStyle: AppThemeData.hintStyle, + suffixIcon: Icon( + Icons.arrow_forward_ios_outlined, + color: AppColors.colorGrey500, + size: isDropDown ? 22 : 0, + ), + ); + } + + String getCustomText({bool isCountryCodeRequired = false, bool isPrefixRequired = false}) { + if (isCountryCodeRequired) { + if (isCountryPicker) { + return selectedCountryCode.value.dialCode! + controller!.text; + } + return controller!.text; + } else if (isPrefixRequired) { + return (prefixCode ?? "") + controller!.text; + } + return controller!.text; + } +} + +class DropDownType { + static final String NORMAL = "01"; + static final String SPECIAL = "02"; +} + +class InputType { + static final int INT_MAX_VALUE_ = 9223372036854775807; + static final FilteringTextInputFormatter NUMBER = FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')); + static final FilteringTextInputFormatter NUMBER_DECIMAL = FilteringTextInputFormatter.allow(RegExp(r'^[0-9]*\.?[0-9]*$')); + + static List maxValueFilter(int maxNumber, bool isDecimal, int decimalPoint) { + return [ + FilteringTextInputFormatter.allow(isDecimal ? RegExp(r'^\d+\.?\d{0,2}') : RegExp(r'^\d+$')), + TextInputFormatter.withFunction((oldValue, newValue) { + if (newValue.text.isEmpty) { + return newValue.copyWith(text: '', selection: const TextSelection.collapsed(offset: 0)); + } + try { + final numericValue = double.parse(newValue.text); + if (numericValue <= maxNumber) { + return newValue; + } + } catch (e) { + return newValue; + } + return oldValue; + }), + ]; + } +} diff --git a/lib/app/custom_widgets/bottom_sheet.dart b/lib/app/custom_widgets/bottom_sheet.dart new file mode 100644 index 0000000..4d4b7ce --- /dev/null +++ b/lib/app/custom_widgets/bottom_sheet.dart @@ -0,0 +1,212 @@ +import 'package:flutter/material.dart'; + +import 'package:get/get.dart'; + +import '../core/constants/translation_keys.dart'; +import '../res/app_colors.dart'; + + +class OptionData { + String label = ""; + String code = ""; + Object dataObject = {}; + + OptionData(); + + OptionData.withData(this.label, this.code, this.dataObject); + + factory OptionData.fromJson(Map json) { + return OptionData.withData( + json['label'] ?? "", + json['code'] ?? "", + json['dataObject'], + ); + } + + Map toJson() { + return { + 'label': label, + 'code': code, + 'dataObject': dataObject, + }; + } + + @override + String toString() { + return 'OptionData{label: $label, code: $code, dataObject: $dataObject}'; + } +} + +class FilterableBottomSheet extends StatefulWidget { + final List options; + final Function(OptionData) onSelect; + + FilterableBottomSheet({required this.options, required this.onSelect}); + + @override + _FilterableBottomSheetState createState() => _FilterableBottomSheetState(); +} + +class _FilterableBottomSheetState extends State { + TextEditingController _filterTextController = TextEditingController(); + List _filteredOptions = []; + @override + void initState() { + super.initState(); + _filteredOptions.addAll(widget.options); + } + + void _updateFilteredList(String query) { + setState(() { + _filteredOptions.clear(); + if (query.isEmpty) { + _filteredOptions.addAll(widget.options); + } else { + query = query.toLowerCase(); + _filteredOptions.addAll(widget.options + .where((item) => item.label.toLowerCase().contains(query))); + } + }); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(1.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 40, + padding: EdgeInsets.symmetric(horizontal: 12.0), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon( + Icons.search, + size: 15.0, + color: Colors.grey[800], + ), + SizedBox(width: 5.0), + Expanded( + child: TextField( + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation( + TranslationKeys.textSearch), + ), + controller: _filterTextController, + onChanged: _updateFilteredList, + ), + ), + ], + ), + ), + SizedBox(height: 20.0), + Container( + height: 300, + child: ListView.builder( + physics: const BouncingScrollPhysics(), + itemCount: _filteredOptions.length, + itemBuilder: (context, index) { + return Padding( + padding: EdgeInsets.only(top: 5, bottom: 5), + child: InkWell( + onTap: () { + widget.onSelect(_filteredOptions[index]); + Navigator.pop(context); + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(_filteredOptions[index].label, + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(fontSize: 12)), + SizedBox(height: 5), + Visibility( + visible: _filteredOptions[index].code.isNotEmpty, + child: Column( + children: [ + Text(_filteredOptions[index].code, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(fontSize: 10)), + ], + ), + ), + SizedBox(height: 5), + Divider(thickness: 0.2, color: AppColors.colorText), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ); + } +} + +class DialogDesign extends StatelessWidget { + List options = []; + Function(OptionData) onSelect; + + DialogDesign(this.options, this.onSelect); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textSelectYourOption), + style: Theme.of(context).textTheme.titleLarge?.copyWith( + color: AppColors.titleColor, + fontSize: 12, + fontWeight: FontWeight.w600), + ), + InkWell( + onTap: () { + Get.back(); // Close the bottom sheet using Get + }, + child: CircleAvatar( + radius: 12.5, + backgroundColor: Colors.transparent, + child: Icon( + Icons.close, + size: 16.0, + color: Colors.blue, + ), + ), + ), + ], + ), + SizedBox(height: 10.0), + FilterableBottomSheet(options: options, onSelect: onSelect), + ], + ), + ); + } +} diff --git a/lib/app/custom_widgets/custom_app_bar.dart b/lib/app/custom_widgets/custom_app_bar.dart new file mode 100644 index 0000000..a5eeaad --- /dev/null +++ b/lib/app/custom_widgets/custom_app_bar.dart @@ -0,0 +1,126 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; + +import '../core/constants/app_assets.dart'; +import '../res/app_colors.dart'; + + +class DashBoardAppBar extends StatelessWidget implements PreferredSizeWidget { + final String? title; + final Color titleColor; + final Color backgroundColor; + final VoidCallback onBackButtonPressed; + final List? actions; + + const DashBoardAppBar({ + Key? key, + this.title = "", + this.titleColor = Colors.white, + this.backgroundColor = AppColors.colorPrimary, + required this.onBackButtonPressed, + this.actions, + }) : super(key: key); + + @override + Size get preferredSize => const Size.fromHeight(kToolbarHeight); + + @override + Widget build(BuildContext context) { + return AppBar( + backgroundColor: backgroundColor, + elevation: 0.0, + leadingWidth: 100, + leading: Container( + margin: const EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(50), + color: Colors.transparent, + ), + child: InkWell( + borderRadius: const BorderRadius.all(Radius.circular(50)), + splashColor: Colors.transparent, + onTap: onBackButtonPressed, + child: Padding( + padding: const EdgeInsets.all(7.0), + child: Transform( + alignment: Alignment.center, + transform: Matrix4.rotationY( + Directionality.of(context) == TextDirection.rtl ? 280 : 0), + child: SvgPicture.asset( + AppAssets.lg_back_arrow, + fit: BoxFit.cover, + )), + ), + ), + ), + title: Text( + title ?? "", + style: Theme.of(context) + .textTheme + .displayMedium + ?.copyWith(color: AppColors.white, fontSize: 20), + ), + actions: actions, + ); + // return ColoredBox( + // color: backgroundColor, + // child: Stack( + // children: [ + // Align( + // alignment: Directionality.of(context) == TextDirection.rtl + // ? Alignment.centerRight + // : Alignment.centerLeft, + // child: Container( + // margin: const EdgeInsets.all(10), + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(50), + // color: Colors.transparent, + // ), + // width: 66.0, + // height: 32.0, + // child: Material( + // color: Colors.transparent, + // child: InkWell( + // borderRadius: const BorderRadius.all(Radius.circular(50)), + // splashColor: Colors.transparent, + // onTap: onBackButtonPressed, + // child: Padding( + // padding: const EdgeInsets.all(7.0), + // child: Transform( + // alignment: Alignment.center, + // transform: Matrix4.rotationY( + // Directionality.of(context) == TextDirection.rtl ? 280 : 0), + // child: SvgPicture.asset( + // AppAssets.ic_back_arrow_appbar, + // fit: BoxFit.cover, + // )), + // ), + // ), + // ), + // ), + // ), + // Center( + // child: Text( + // title ?? "", + // style: Theme.of(context) + // .textTheme + // .displayMedium + // ?.copyWith(color: AppColors.white, fontSize: 20), + // ), + // ), + // Align( + // alignment: Directionality.of(context) == TextDirection.rtl + // ? Alignment.centerLeft + // : Alignment.centerRight, // Align to the right + // child: Center( + // child: Row( + // mainAxisAlignment: MainAxisAlignment.end, + // children: [...actions ?? []], + // ), + // ), + // ), + // ], + // ), + // ); + } +} diff --git a/lib/app/custom_widgets/custom_button.dart b/lib/app/custom_widgets/custom_button.dart new file mode 100644 index 0000000..f63659f --- /dev/null +++ b/lib/app/custom_widgets/custom_button.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +class CustomButton extends StatelessWidget { + final VoidCallback onPressed; + final String buttonText; + final Color buttonColor; + final EdgeInsets buttonPadding; + final EdgeInsets iconPadding; + final Widget? icon; + final TextStyle? textStyle; + final double radius; + final BorderSide? sideBorder; + const CustomButton({ + Key? key, + required this.onPressed, + required this.buttonText, + required this.buttonColor, + this.radius = 50, + this.buttonPadding = const EdgeInsets.symmetric(horizontal: 0, vertical: 0), + this.iconPadding = const EdgeInsets.only(right: 0), + this.icon, + this.textStyle, + this.sideBorder, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: onPressed, + style: ElevatedButton.styleFrom( + padding: buttonPadding, + backgroundColor: buttonColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(radius), + side: sideBorder ?? BorderSide.none, + ), + elevation: 0.0, + alignment: Alignment.center, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (icon != null) ...[ + Padding( + padding: iconPadding, + child: icon, + ), + ], + Text( + buttonText, + style: textStyle ?? + Theme.of(context).textTheme.labelLarge?.copyWith( + color: Colors.white, + ), + ), + ], + ), + ); + } +} diff --git a/lib/app/custom_widgets/custom_date_time_picker.dart b/lib/app/custom_widgets/custom_date_time_picker.dart new file mode 100644 index 0000000..8eaba34 --- /dev/null +++ b/lib/app/custom_widgets/custom_date_time_picker.dart @@ -0,0 +1,298 @@ +import 'dart:ui'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:get/get.dart'; + +import '../core/constants/translation_keys.dart'; +import '../res/app_colors.dart'; +import '../res/app_theme.dart'; +import 'custom_text.dart'; + + +class CustomDateTimePicker extends GetView { + final FormFieldValidator? validator; + GlobalKey? refKey; + String labelText = ""; + String hint = ""; + RxString errorTextMessage = "".obs; + String errorText = ""; + bool isRequired = true; + final bool enabled; + final AutovalidateMode autovalidateMode; + final String? restorationId; + InputDecoration? decoration; + TextEditingController? controller; + TextInputType keyboardType; + final TextInputAction? textInputAction; + final TextCapitalization textCapitalization; + final TextStyle? style; + final StrutStyle? strutStyle; + TextAlign textAlign; + final TextAlignVertical? textAlignVertical; + final TextDirection? textDirection; + final bool autofocus; + final String obscuringCharacter; + bool isPassword = false; + bool autocorrect = false; + final SmartDashesType? smartDashesType; + final SmartQuotesType? smartQuotesType; + final bool enableSuggestions; + int maxLines; + int minLines; + bool expands; + TextStyle? labelStyle; + final int? maxLength; + final MaxLengthEnforcement? maxLengthEnforcement; + final VoidCallback? onEditingComplete; + final ValueChanged? onSubmitted; + final List? inputFormatters; + bool showCursor = true; + double cursorWidth = 5.0; + double cursorHeight = 15.0; + Radius cursorRadius = const Radius.circular(10.0); + Color cursorColor = AppThemeData.inputTextColor; + final BoxHeightStyle selectionHeightStyle; + final BoxWidthStyle selectionWidthStyle; + final Brightness? keyboardAppearance; + final EdgeInsets scrollPadding; + final bool enableInteractiveSelection; + final DragStartBehavior dragStartBehavior; + final GestureTapCallback? onTap; + final TapRegionCallback? onTapOutside; + final MouseCursor? mouseCursor; + final InputCounterWidgetBuilder? buildCounter; + final ScrollPhysics? scrollPhysics; + final ScrollController? scrollController; + final Iterable? autofillHints; + final TextMagnifierConfiguration? magnifierConfiguration; + final bool readOnly; + final ContentInsertionConfiguration? contentInsertionConfiguration; + SpellCheckConfiguration? spellCheckConfiguration; + + final Rx fillColor = Rx(Colors.transparent); + final Rx inputErrorColor = Rx(Colors.black); + final Rx inputErrorBorderColor = Rx(Colors.black); + RxBool isError = false.obs; + + CustomDateTimePicker({ + this.refKey, + this.controller, + this.labelText = "", + this.hint = "", + this.errorText = "", + this.labelStyle, + this.isRequired = true, + this.validator, + this.decoration, + this.enabled = true, + this.autovalidateMode = AutovalidateMode.disabled, + this.restorationId, + this.readOnly = false, + this.isPassword = false, + this.textCapitalization = TextCapitalization.none, + this.scrollPadding = const EdgeInsets.all(20.0), + this.enableInteractiveSelection = true, + this.maxLengthEnforcement, + this.textAlign = TextAlign.start, + this.autofocus = false, + this.autocorrect = false, + this.cursorWidth = 5.0, + this.cursorHeight = 20.0, + this.cursorRadius = const Radius.circular(10.0), + this.keyboardType = TextInputType.text, + this.style, + this.textInputAction, + this.strutStyle, + this.textDirection, + this.maxLength, + this.onEditingComplete, + this.onSubmitted, + this.inputFormatters, + this.cursorColor = AppThemeData.inputTextColor, + this.keyboardAppearance, + this.buildCounter, + this.expands = false, + this.minLines = 1, + this.maxLines = 4, + this.showCursor = true, + this.onTap, + this.onTapOutside, + this.enableSuggestions = true, + this.textAlignVertical, + this.dragStartBehavior = DragStartBehavior.start, + this.scrollController, + this.scrollPhysics, + this.selectionWidthStyle = BoxWidthStyle.tight, + this.smartDashesType, + this.smartQuotesType, + this.selectionHeightStyle = BoxHeightStyle.tight, + this.autofillHints, + this.obscuringCharacter = '•', + this.mouseCursor, + this.magnifierConfiguration, + this.contentInsertionConfiguration, + this.spellCheckConfiguration, + }) : errorTextMessage = "".obs { + errorText = errorTextMessage.value; + } + + void setError(String errorMessage) { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + fillColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = errorMessage; + isError.value = true; + } + + void setTest(String errorMessage) { + this.controller!.text = errorMessage; + // inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + // inputErrorColor.value = AppThemeData.inputErrorColor; + // fillColor.value = AppThemeData.inputErrorColor; + // errorTextMessage.value = errorMessage; + // isError.value = true; + } + + void markFieldAsValid() { + inputErrorBorderColor.value = AppThemeData.inputBackgroundColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = ""; + fillColor.value = Colors.transparent; + isError.value = false; + } + + void markFieldAsInvalid() { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + fillColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = + TranslationKeys.makeTranslation(TranslationKeys.textErrorRequired); + isError.value = true; + } + + bool validate(String value) { + if (isRequired) { + if (value.isEmpty) { + markFieldAsInvalid(); + return false; + } + markFieldAsValid(); + return true; + } + markFieldAsValid(); + return true; + } + + @override + Widget build(BuildContext context) { + return Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Visibility( + visible: labelText.isNotEmpty, + child: Column( + children: [ + CustomText( + labelText, + style: labelStyle ?? AppThemeData.labelStyle, + ), + const SizedBox(height: 8), + ], + ), + ), + FormBuilderDateTimePicker( + key: refKey, + name: "", + initialEntryMode: DatePickerEntryMode.calendar, + inputType: InputType.date, + + initialDatePickerMode: DatePickerMode.day, + onChanged: (value) { + if (value.toString().isNotEmpty) { + markFieldAsValid(); + } + }, + // format: DateFormat('dd-yyyy-MM'), + currentDate: DateTime.now(), + firstDate: DateTime(1970), + lastDate: DateTime(2030), + decoration: InputDecoration( + suffixIcon: Container( + width: 30, + height: 30, + margin: const EdgeInsets.all(5), + child: const Icon(size: 18, Icons.calendar_month_rounded), + ), + filled: true, + fillColor: AppColors.colorGrey50, + isDense: true, + contentPadding: + const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + labelText: null, + // labelStyle: AppThemeData.labelStyle, + errorStyle: AppThemeData.errorStyle + .copyWith(color: inputErrorColor.value), + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppThemeData.inputEnabledBorderColor), + borderRadius: BorderRadius.circular(50)), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppThemeData.inputFocusedBorderColor), + borderRadius: BorderRadius.circular(50)), + border: OutlineInputBorder( + borderSide: + const BorderSide(color: AppThemeData.inputBorderColor), + borderRadius: BorderRadius.circular(50), + ), + errorBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppThemeData.inputErrorBorderColor), + borderRadius: BorderRadius.circular(50)), + errorText: errorTextMessage.value.isEmpty + ? null + : errorTextMessage.value, + hintText: hint, + hintStyle: AppThemeData.hintStyle, + ), + enabled: enabled, + autovalidateMode: autovalidateMode, + restorationId: restorationId, + + textCapitalization: textCapitalization, + scrollPadding: scrollPadding, + enableInteractiveSelection: enableInteractiveSelection, + textAlign: textAlign, + autofocus: autofocus, + autocorrect: autocorrect, + keyboardType: keyboardType, + style: AppThemeData.inputStyle.copyWith(height: 1), + controller: controller, + textInputAction: textInputAction, + strutStyle: strutStyle, + textDirection: textDirection, + maxLength: maxLength, + onEditingComplete: onEditingComplete, + inputFormatters: inputFormatters, + cursorColor: cursorColor, + keyboardAppearance: keyboardAppearance, + buildCounter: buildCounter, + expands: expands, + maxLines: isPassword ? maxLines = 1 : maxLines, + obscureText: isPassword, + minLines: isPassword ? minLines = 1 : minLines, + showCursor: showCursor, + mouseCursor: mouseCursor, + ), + ], + ); + }); + } + + String getText() { + return this.controller!.text; + } +} diff --git a/lib/app/custom_widgets/custom_dialog.dart b/lib/app/custom_widgets/custom_dialog.dart new file mode 100644 index 0000000..b6536ac --- /dev/null +++ b/lib/app/custom_widgets/custom_dialog.dart @@ -0,0 +1,605 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + +import '../core/constants/app_assets.dart'; +import '../core/constants/translation_keys.dart'; +import '../core/utils/app_utils.dart'; +import '../models/TransactionSubmitRequestModel.dart'; +import '../res/app_colors.dart'; +import '../res/app_dimensions.dart'; +import '../routes/app_pages.dart'; +import 'custom_button.dart'; + + +class CustomDialog { + /// SuccessFull Dialog...........Transactions + + static _showBasicDialog(Widget child) { + Get.dialog(responsiveWidget(child), barrierDismissible: false); + } + + /// Warning Dialog + static showWarningDialog({ + //required String title, + required String description, + // Function()? onTapPositive, + required Function() onTapNegative, + }) { + _showBasicDialog(Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: Directionality.of(Get.context!) == TextDirection.rtl ? Alignment.topLeft : Alignment.topRight, + child: GestureDetector( + onTap: () { + Navigator.of(Get.context!, rootNavigator: true).pop(); + }, + child: SvgPicture.asset( + AppAssets.ic_cross, + height: 14, + width: 14, + ))), + Container( + height: 40, + width: 40, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: Stack( + children: [ + SvgPicture.asset( + AppAssets.ic_featured, + ), + Center( + child: SvgPicture.asset( + AppAssets.ic_close, + height: 6, + width: 6, + ), + ), + ], + ), + ), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWarning), style: Theme.of(Get.context!).textTheme.titleMedium?.copyWith(color: AppColors.colorDialogBG)), + const SizedBox(height: 20), + Text(description, style: Theme.of(Get.context!).textTheme.bodyMedium), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CustomButton( + onPressed: () { + onTapNegative(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textYes), + buttonPadding: const EdgeInsets.symmetric(vertical: 5, horizontal: 30), + textStyle: const TextStyle(fontWeight: FontWeight.w600, fontSize: 16, color: AppColors.black), + buttonColor: AppColors.colorSkipBtn, + sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1.0), + ), + ], + ), + ], + ), + ], + ), + ), + ), + ), + )); + } + + /// Error Dialog + static showErrorDialog({ + //required String title, + required String description, + // Function()? onClosePress, + required Function() onTapNegative, + }) { + _showBasicDialog(Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Align( + alignment: Directionality.of(Get.context!) == TextDirection.rtl ? Alignment.topLeft : Alignment.topRight, + child: GestureDetector( + onTap: () { + Navigator.of(Get.context!, rootNavigator: true).pop(); + }, + child: SvgPicture.asset( + AppAssets.ic_cross, + height: 14, + width: 14, + ))), + Container( + height: 40, + width: 40, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: Stack( + children: [ + SvgPicture.asset( + AppAssets.ic_featured, + ), + Center( + child: SvgPicture.asset( + AppAssets.ic_close, + height: 6, + width: 6, + ), + ), + ], + ), + ), + const SizedBox(width: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textError), style: Theme.of(Get.context!).textTheme.titleMedium?.copyWith(color: AppColors.colorDialogBG)), + const SizedBox(height: 20), + Text(description, style: Theme.of(Get.context!).textTheme.bodyMedium), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CustomButton( + onPressed: () { + onTapNegative(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textOK), + buttonPadding: const EdgeInsets.symmetric(vertical: 5, horizontal: 30), + buttonColor: AppColors.colorButton, + //sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1.0), + ), + ], + ), + ], + ), + ], + ), + ), + ), + ), + )); + } + + /// Success Dialog + static showSuccessDialog({ + String? title, + required String description, + required Function() onTapPositive, + }) { + _showBasicDialog(Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: 60, + width: 60, + padding: const EdgeInsets.only(bottom: 5), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset( + AppAssets.ic_congratulations, + ), + ), + if (title != null) ...[ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text( + title, + style: Theme.of(Get.context!).textTheme.titleMedium?.copyWith(color: AppColors.colorGrey800), + ), + ), + const SizedBox(height: 10), + ], + Text(description, style: Theme.of(Get.context!).textTheme.bodyMedium), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () { + Navigator.of(Get.context!, rootNavigator: true).pop(); + onTapPositive(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + buttonColor: AppColors.colorButton, + ), + ), + ], + ), + ], + ), + ), + ), + ), + )); + } + + + /// Information Dialog + static showInfoDialog({ + required String title, + required String description, + required Function() onTapPositive, + }) { + _showBasicDialog(Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: 40, + width: 40, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: Stack( + children: [ + SvgPicture.asset( + AppAssets.ic_congratulations, + ), + Center( + child: SvgPicture.asset( + AppAssets.ic_correct_icon, + height: 22, + width: 22, + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textInform), style: Theme.of(Get.context!).textTheme.titleMedium?.copyWith(color: AppColors.colorDialogBG)), + ), + const SizedBox(height: 10), + Text(description, style: Theme.of(Get.context!).textTheme.bodyMedium), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () { + onTapPositive(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + buttonColor: AppColors.colorButton, + //sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1.0), + ), + ), + ], + ), + ], + ), + ), + ), + ), + )); + } + + /// Information Dialog + static showLogoutDialog({ + required Function() onTapPositive, + required Function() onTapNegative, + required BuildContext context, + }) { + _showBasicDialog(Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: 60, + width: 60, + padding: const EdgeInsets.only(bottom: 5), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset( + AppAssets.ic_congratulations, + ), + ), + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textLogOut), style: Theme.of(Get.context!).textTheme.titleMedium?.copyWith(color: AppColors.colorDialogBG)), + ), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textLogOutContent), style: Theme.of(Get.context!).textTheme.bodyMedium), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: CustomButton( + onPressed: onTapNegative, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textCancel), + buttonColor: AppColors.red, + buttonPadding: const EdgeInsets.symmetric(vertical: 10), + ), + ), + SizedBox(width: 15), + Expanded( + flex: 1, + child: CustomButton( + onPressed: onTapPositive, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textOK), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10), + ), + ), + ], + ), + ), + ], + ), + ], + ), + ), + ), + ), + )); + } + + /// Alert Dialog + static showAlertDialog({ + required Function() onTapPositive, + required Function() onTapNegative, + required BuildContext context, + }) { + _showBasicDialog(Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: 60, + width: 60, + padding: const EdgeInsets.only(bottom: 5), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: Image.asset( + AppAssets.ic_warning, + ), + ), + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textWarning), style: Theme.of(Get.context!).textTheme.titleMedium?.copyWith(color: AppColors.colorDialogBG)), + ), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWarningContent), style: Theme.of(Get.context!).textTheme.bodyMedium), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 1, + child: CustomButton( + onPressed: onTapNegative, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textCancel), + buttonColor: AppColors.red, + buttonPadding: const EdgeInsets.symmetric(vertical: 10), + ), + ), + const SizedBox(width: 15), + Expanded( + flex: 1, + child: CustomButton( + onPressed: onTapPositive, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textDelete), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10), + ), + ), + ], + ), + ), + ], + ), + ], + ), + ), + ), + ), + )); + } + + static showGeneralDialog({ + required String title, + required String description, + required Widget child, + }) { + _showBasicDialog(child); + } + + static void showTransactionSuccessDialog(BuildContext context, String endingBalance, String exchangeRate, TransactionSubmitRequestModel transactionSubmitRequestModel) { + Get.dialog( + responsiveWidget( + Stack( + children: [ + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Image.asset(AppAssets.ic_launcher, height: 80, width: 80), + Padding( + padding: const EdgeInsets.only(top: 20), + child: Align(alignment: Alignment.center, child: Text(TranslationKeys.makeTranslation(TranslationKeys.textSuccess), style: Theme.of(context).textTheme.titleMedium)), + ), + const SizedBox(height: 15), + Padding( + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 3, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textRecipient), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textMessage), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textEndingBalance), style: Theme.of(context).textTheme.bodySmall), + ], + ), + ), + const SizedBox(width: 20), + Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(transactionSubmitRequestModel.crMbmBkmstitle, style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(transactionSubmitRequestModel.otdTrancomment, style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(AppUtils.showAmountWithCurr(transactionSubmitRequestModel.sgtGntramtfc.toString(), transactionSubmitRequestModel.crPcrCurrcode), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(exchangeRate, style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text(endingBalance, style: Theme.of(context).textTheme.bodySmall), + ], + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 80), + child: CustomButton( + onPressed: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textOK), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ), + barrierDismissible: false, + ); + } +} diff --git a/lib/app/custom_widgets/custom_dropdown.dart b/lib/app/custom_widgets/custom_dropdown.dart new file mode 100644 index 0000000..c0e3f97 --- /dev/null +++ b/lib/app/custom_widgets/custom_dropdown.dart @@ -0,0 +1,178 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:get/get.dart'; + +import '../core/constants/translation_keys.dart'; +import '../res/app_colors.dart'; +import '../res/app_theme.dart'; +import 'custom_text.dart'; + + +@immutable +class CustomDropDown extends GetView { + RxList listData = RxList.empty(); + GlobalKey? refKey; + String labelText = ""; + RxString errorTextMessage = "".obs; + String errorText = ""; + bool isRequired = true; + final bool enabled; + InputDecoration? decoration; + TextStyle? labelStyle; + final TextStyle? style; + final AutovalidateMode autovalidateMode; + TextEditingController? controller; + TextInputType keyboardType; + final TextCapitalization textCapitalization; + final bool readOnly; + + final Rx inputErrorColor = Rx(Colors.black); + final Rx inputErrorBorderColor = Rx(Colors.black); + RxBool isError = false.obs; + DropDown? selectedOption = null; + + CustomDropDown({ + this.refKey, + required this.listData, + this.controller, + this.labelText = "", + this.errorText = "", + this.isRequired = true, + this.decoration, + this.enabled = true, + this.autovalidateMode = AutovalidateMode.disabled, + this.readOnly = false, + this.textCapitalization = TextCapitalization.none, + this.keyboardType = TextInputType.text, + this.style, + }) : errorTextMessage = "".obs { + errorText = errorTextMessage.value; + } + + DropDown? getSelectedOption() { + return selectedOption; + } + + void setError(String errorMessage) { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = errorMessage; + isError.value = true; + } + + void markFieldAsValid() { + inputErrorBorderColor.value = AppThemeData.inputBackgroundColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = ""; + isError.value = false; + } + + void markFieldAsInvalid() { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = TranslationKeys.makeTranslation(TranslationKeys.textErrorRequired); + isError.value = true; + } + + bool validate() { + if (isRequired) { + if (selectedOption == null) { + markFieldAsInvalid(); + return false; + } + markFieldAsValid(); + return true; + } + markFieldAsValid(); + return true; + } + + @override + Widget build(BuildContext context) { + return Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Visibility( + visible: labelText.isNotEmpty, + child: Column( + children: [ + CustomText( + labelText, + style: labelStyle ?? AppThemeData.labelStyle, + ), + const SizedBox(height: 8), + ], + ), + ), + FormBuilderDropdown( + name: '', + isDense: true, + isExpanded: false, + elevation: 2, + decoration: InputDecoration( + filled: true, + fillColor: AppColors.colorGrey50, + isDense: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 12), + labelText: null, + // labelStyle: AppThemeData.labelStyle, + errorStyle: AppThemeData.errorStyle.copyWith(color: inputErrorColor.value), + enabledBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputEnabledBorderColor), borderRadius: BorderRadius.circular(50)), + focusedBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputFocusedBorderColor), borderRadius: BorderRadius.circular(50)), + border: OutlineInputBorder( + borderSide: const BorderSide(color: AppThemeData.inputBorderColor), + borderRadius: BorderRadius.circular(50), + ), + errorBorder: OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputErrorBorderColor), borderRadius: BorderRadius.circular(50)), + errorText: errorTextMessage.value.isEmpty ? null : errorTextMessage.value, + // hintText: hint, + + hintStyle: AppThemeData.hintStyle, + ), + borderRadius: const BorderRadius.all(Radius.circular(5)), + dropdownColor: AppColors.colorGrey200, + focusColor: Colors.transparent, + + items: listData.map((data) { + return DropdownMenuItem( + value: data, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 0), + child: CustomText( + data.label, + style: AppThemeData.inputStyle.copyWith(height: 1), + ), + ), + ); + }).toList(), + onChanged: (val) { + selectedOption = val!; + markFieldAsValid(); + }, + onTap: () {}, + valueTransformer: (val) => val?.toString(), + ), + ], + ); + }); + } +} + +class DropDown { + String id = ""; + String label = ""; + dynamic data = {}; + + DropDown(this.id, this.label, [this.data = const {}]); + + DropDown.empty() + : this.id = "", + this.label = "", + this.data = {}; + + @override + String toString() { + return 'DropDown{id: $id, label: $label, data: $data}'; + } +} diff --git a/lib/app/custom_widgets/custom_input_field.dart b/lib/app/custom_widgets/custom_input_field.dart new file mode 100644 index 0000000..fa924b5 --- /dev/null +++ b/lib/app/custom_widgets/custom_input_field.dart @@ -0,0 +1,330 @@ +import 'dart:ui'; + +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:get/get.dart'; + +import '../core/constants/translation_keys.dart'; +import '../res/app_colors.dart'; +import '../res/app_theme.dart'; +import 'custom_text.dart'; + + +@immutable +class CustomInputFieldCustom extends GetView { + final FormFieldValidator? validator; + GlobalKey? refKey; + String labelText = ""; + String hint = ""; + RxString errorTextMessage = "".obs; + String errorText = ""; + bool isRequired = true; + final bool enabled; + final AutovalidateMode autovalidateMode; + final String? restorationId; + InputDecoration? decoration; + TextEditingController? controller; + TextInputType keyboardType; + EdgeInsets? padding = EdgeInsets.zero; + final TextInputAction? textInputAction; + final TextCapitalization textCapitalization; + final TextStyle? style; + final StrutStyle? strutStyle; + TextAlign textAlign; + final TextAlignVertical? textAlignVertical; + final TextDirection? textDirection; + final bool autofocus; + final String obscuringCharacter; + + bool isPassword = false; + bool requiredPasswordIcon = false; + bool autocorrect = false; + final SmartDashesType? smartDashesType; + final SmartQuotesType? smartQuotesType; + final bool enableSuggestions; + int maxLines; + int minLines; + bool expands; + TextStyle? labelStyle; + final int? maxLength; + final MaxLengthEnforcement? maxLengthEnforcement; + final VoidCallback? onEditingComplete; + final ValueChanged? onSubmitted; + final List? inputFormatters; + bool showCursor = true; + double cursorWidth = 5.0; + double cursorHeight = 15.0; + Radius cursorRadius = const Radius.circular(10.0); + Color cursorColor = AppThemeData.inputTextColor; + final BoxHeightStyle selectionHeightStyle; + final BoxWidthStyle selectionWidthStyle; + final Brightness? keyboardAppearance; + final EdgeInsets scrollPadding; + final bool enableInteractiveSelection; + final DragStartBehavior dragStartBehavior; + final GestureTapCallback? onTap; + final TapRegionCallback? onTapOutside; + final MouseCursor? mouseCursor; + final InputCounterWidgetBuilder? buildCounter; + final ScrollPhysics? scrollPhysics; + final ScrollController? scrollController; + final Iterable? autofillHints; + final TextMagnifierConfiguration? magnifierConfiguration; + final bool readOnly; + final ContentInsertionConfiguration? contentInsertionConfiguration; + SpellCheckConfiguration? spellCheckConfiguration; + + final Rx fillColor = Rx(Colors.transparent); + final Rx inputErrorColor = Rx(Colors.black); + final Rx inputErrorBorderColor = Rx(Colors.black); + RxBool isError = false.obs; + RxBool passwordVisible = false.obs; + + CustomInputFieldCustom({ + this.refKey, + this.controller, + this.labelText = "", + this.hint = "", + this.errorText = "", + this.isRequired = true, + this.validator, + this.labelStyle, + this.decoration, + this.padding, + this.enabled = true, + this.requiredPasswordIcon = false, + this.autovalidateMode = AutovalidateMode.disabled, + this.restorationId, + this.readOnly = false, + this.isPassword = false, + this.textCapitalization = TextCapitalization.none, + this.scrollPadding = const EdgeInsets.all(20.0), + this.enableInteractiveSelection = true, + this.maxLengthEnforcement, + this.textAlign = TextAlign.start, + this.autofocus = false, + this.autocorrect = false, + this.cursorWidth = 5.0, + this.cursorHeight = 20.0, + this.cursorRadius = const Radius.circular(10.0), + this.keyboardType = TextInputType.text, + this.style, + this.textInputAction, + this.strutStyle, + this.textDirection, + this.maxLength, + this.onEditingComplete, + this.onSubmitted, + this.inputFormatters, + this.cursorColor = AppThemeData.inputTextColor, + this.keyboardAppearance, + this.buildCounter, + this.expands = false, + this.minLines = 1, + this.maxLines = 4, + this.showCursor = true, + this.onTap, + this.onTapOutside, + this.enableSuggestions = true, + this.textAlignVertical, + this.dragStartBehavior = DragStartBehavior.start, + this.scrollController, + this.scrollPhysics, + this.selectionWidthStyle = BoxWidthStyle.tight, + this.smartDashesType, + this.smartQuotesType, + this.selectionHeightStyle = BoxHeightStyle.tight, + this.autofillHints, + this.obscuringCharacter = '•', + this.mouseCursor, + this.magnifierConfiguration, + this.contentInsertionConfiguration, + this.spellCheckConfiguration, + }) : errorTextMessage = "".obs { + errorText = errorTextMessage.value; + } + + void setError(String errorMessage) { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + fillColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = errorMessage; + isError.value = true; + } + + void markFieldAsValid() { + inputErrorBorderColor.value = AppThemeData.inputBackgroundColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = ""; + fillColor.value = Colors.transparent; + isError.value = false; + } + + void markFieldAsInvalid() { + inputErrorBorderColor.value = AppThemeData.inputErrorBorderColor; + inputErrorColor.value = AppThemeData.inputErrorColor; + fillColor.value = AppThemeData.inputErrorColor; + errorTextMessage.value = + TranslationKeys.makeTranslation(TranslationKeys.textErrorRequired); + isError.value = true; + } + + bool validate(String value) { + if (isRequired) { + if (value.isEmpty) { + markFieldAsInvalid(); + return false; + } + markFieldAsValid(); + return true; + } + markFieldAsValid(); + return true; + } + + @override + Widget build(BuildContext context) { + return Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Visibility( + visible: labelText.isNotEmpty, + child: Column( + children: [ + CustomText( + labelText, + style: labelStyle ?? AppThemeData.labelStyle, + ), + const SizedBox(height: 8), + ], + ), + ), + FormBuilderTextField( + key: refKey, + name: "", + + decoration: InputDecoration( + filled: true, + suffixIcon: Visibility( + visible: requiredPasswordIcon, + child: Container( + width: 30, + height: 30, + margin: const EdgeInsets.all(5), + child: IconButton( + icon: Icon( + size: 18, + passwordVisible.value + ? Icons.visibility + : Icons.visibility_off_rounded), + onPressed: () { + passwordVisible.value = !passwordVisible.value; + }, + ), + ), + ), + fillColor: AppColors.colorGrey50, + isDense: true, + contentPadding: padding ?? + const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + labelText: null, + errorStyle: AppThemeData.errorStyle + .copyWith(color: inputErrorColor.value), + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppThemeData.inputEnabledBorderColor), + borderRadius: BorderRadius.circular(50)), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppThemeData.inputFocusedBorderColor), + borderRadius: BorderRadius.circular(50)), + border: OutlineInputBorder( + borderSide: + const BorderSide(color: AppThemeData.inputBorderColor), + borderRadius: BorderRadius.circular(50), + ), + errorBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppThemeData.inputErrorBorderColor), + borderRadius: BorderRadius.circular(50)), + errorText: errorTextMessage.value.isEmpty + ? null + : errorTextMessage.value, + hintText: hint, + hintStyle: AppThemeData.hintStyle, + ), + enabled: enabled, + autovalidateMode: autovalidateMode, + restorationId: restorationId, + readOnly: readOnly, + validator: (value) { + validate(value!); + return null; + }, + onChanged: (value) { + if (value!.isNotEmpty) { + markFieldAsValid(); + } + }, + textCapitalization: textCapitalization, + scrollPadding: scrollPadding, + enableInteractiveSelection: enableInteractiveSelection, + maxLengthEnforcement: maxLengthEnforcement, + textAlign: textAlign, + autofocus: autofocus, + autocorrect: autocorrect, + keyboardType: keyboardType, + style: AppThemeData.inputStyle.copyWith(height: 1), + controller: controller, + textInputAction: textInputAction, + strutStyle: strutStyle, + textDirection: textDirection, + maxLength: maxLength, + onEditingComplete: onEditingComplete, + onSubmitted: onSubmitted, + inputFormatters: inputFormatters, + cursorColor: cursorColor, + cursorWidth: 1.5, + cursorHeight: 15, + cursorRadius: const Radius.circular(10.0), + keyboardAppearance: keyboardAppearance, + buildCounter: buildCounter, + expands: expands, + maxLines: isPassword ? maxLines = 1 : maxLines, + obscureText: isPassword && passwordVisible.value, + minLines: isPassword ? minLines = 1 : minLines, + showCursor: showCursor, + onTap: onTap, + onTapOutside: onTapOutside, + enableSuggestions: enableSuggestions, + textAlignVertical: textAlignVertical, + dragStartBehavior: dragStartBehavior, + scrollController: scrollController, + scrollPhysics: scrollPhysics, + selectionWidthStyle: selectionWidthStyle, + smartDashesType: smartDashesType, + smartQuotesType: smartQuotesType, + selectionHeightStyle: selectionHeightStyle, + autofillHints: autofillHints, + obscuringCharacter: obscuringCharacter, + mouseCursor: mouseCursor, + magnifierConfiguration: magnifierConfiguration, + contentInsertionConfiguration: contentInsertionConfiguration, + spellCheckConfiguration: spellCheckConfiguration, + ), + ], + ); + }); + } + + String getText() { + return controller!.text; + } + + void clear() { + controller!.clear(); + } +} diff --git a/lib/app/custom_widgets/custom_label.dart b/lib/app/custom_widgets/custom_label.dart new file mode 100644 index 0000000..8e58f78 --- /dev/null +++ b/lib/app/custom_widgets/custom_label.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; + +import 'package:google_fonts/google_fonts.dart'; + +import '../res/app_colors.dart'; + +class LabelText extends StatelessWidget { + final String text; + final EdgeInsets margin; + final Color labelColor; + final bool underLineColor; + final double fontSize; + final bool underline; + final FontWeight fontWeight; + final bool fontFamily; + final TextStyle? style; + LabelText( + this.text, { + this.margin = EdgeInsets.zero, + this.labelColor = AppColors.colorTitle, + this.underLineColor = false, + this.fontSize = 18, + this.underline = false, + this.fontWeight = FontWeight.w600, + this.fontFamily = false, + this.style, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Text( + text, + maxLines: 3, + textAlign: TextAlign.center, + style: style ?? + TextStyle( + color: labelColor, + fontSize: fontSize, + fontFamily: fontFamily ? GoogleFonts.roboto().toString() : "", + fontWeight: fontWeight, + decoration: + underline ? TextDecoration.underline : TextDecoration.none, + decorationColor: + underLineColor ? AppColors.colorTitle : Colors.transparent, + ), + ); + } +} diff --git a/lib/app/custom_widgets/custom_no_record.dart b/lib/app/custom_widgets/custom_no_record.dart new file mode 100644 index 0000000..f0cf07f --- /dev/null +++ b/lib/app/custom_widgets/custom_no_record.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class CustomNoRecord extends StatelessWidget { + final String title; + final String description; + final Widget? icon; + + const CustomNoRecord({ + Key? key, + required this.title, + required this.description, + this.icon, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(height: 40), + SvgPicture.asset("assets/uco/icons/ic_no_result.png",width: 100, height: 100,), + SizedBox(height: 10), + Text(title, + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontWeight: FontWeight.w500)), + SizedBox(height: 10), + Text(description, style: Theme.of(context).textTheme.bodySmall), + ], + ); + } +} diff --git a/lib/app/custom_widgets/custom_text.dart b/lib/app/custom_widgets/custom_text.dart new file mode 100644 index 0000000..e4596d5 --- /dev/null +++ b/lib/app/custom_widgets/custom_text.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +import '../res/app_colors.dart'; +import '../res/app_dimensions.dart'; +import '../res/app_theme.dart'; + + +class CustomText extends StatelessWidget { + final String text; + final EdgeInsets margin; + final EdgeInsets padding; + final Color labelColor; + final bool underLineColor; + final double fontSize; + final bool underline; + final TextStyle? style; + final FontWeight fontWeight; + final bool fontFamily; + final TextAlign textAlign; + final TextOverflow? overflow; + + const CustomText( + this.text, { + super.key, + this.margin = EdgeInsets.zero, + this.style = const TextStyle(), + this.padding = EdgeInsets.zero, + this.labelColor = AppThemeData.textFieldsColor, + this.underLineColor = false, + this.fontSize = -1, + this.underline = false, + this.fontWeight = FontWeight.w400, + this.fontFamily = false, + this.textAlign = TextAlign.start, + this.overflow, + }); + + @override + Widget build(BuildContext context) { + return Container( + margin: margin, + padding: padding, + child: Text( + text, + textAlign: textAlign, + overflow: overflow ?? TextOverflow.clip, + style: style ?? + Theme.of(context).textTheme.labelMedium?.copyWith( + color: labelColor, + fontFamily: fontFamily ? GoogleFonts.inter().toString() : "", + fontSize: + fontSize == -1 ? AppDimensions.customTextSize : fontSize, + fontWeight: fontWeight, + decoration: underline + ? TextDecoration.underline + : TextDecoration.none, + decorationColor: underLineColor + ? AppColors.titleColor + : Colors.transparent, + ), + ), + ); + } +} diff --git a/lib/app/custom_widgets/custom_toasty.dart b/lib/app/custom_widgets/custom_toasty.dart new file mode 100644 index 0000000..1d4443a --- /dev/null +++ b/lib/app/custom_widgets/custom_toasty.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +class Toasty { + static error(String msg) { + _showToast(msg, Colors.red); + } + + static success(String msg) { + _showToast(msg, Colors.green); + } + + static _showToast(String msg, Color bgColor) { + Fluttertoast.showToast(msg: msg, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, timeInSecForIosWeb: 1, backgroundColor: bgColor, textColor: Colors.white); + } +} diff --git a/lib/app/custom_widgets/date_picker.dart b/lib/app/custom_widgets/date_picker.dart new file mode 100644 index 0000000..53f85ec --- /dev/null +++ b/lib/app/custom_widgets/date_picker.dart @@ -0,0 +1,94 @@ +import 'package:calendar_date_picker2/calendar_date_picker2.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_rounded_date_picker/flutter_rounded_date_picker.dart'; +import 'package:get/get.dart'; + +import '../res/app_colors.dart'; + + +class DatePicker { + static Future showDatePicker(BuildContext context) async { + return await showRoundedDatePicker( + borderRadius: 10, + context: context, + onTapDay: (date, test) { + return true; + }, + textPositiveButton: "Yes", + theme: ThemeData( + primarySwatch: Colors.green, + ), + styleDatePicker: MaterialRoundedDatePickerStyle( + textStyleDayButton: + const TextStyle(fontSize: 25, color: Colors.white), + textStyleYearButton: const TextStyle( + fontSize: 15, + color: Colors.white, + ), + textStyleDayHeader: const TextStyle( + fontSize: 14, + color: AppColors.colorPrimary, + ), + backgroundHeader: AppColors.colorPrimary, + textStyleCurrentDayOnCalendar: const TextStyle( + fontSize: 12, color: Colors.grey, fontWeight: FontWeight.normal), + textStyleDayOnCalendar: + TextStyle(fontSize: 12, color: Colors.black.withOpacity(0.9)), + textStyleDayOnCalendarSelected: TextStyle( + fontSize: 12, + color: AppColors.white.withOpacity(0.9), + fontWeight: FontWeight.bold), + textStyleDayOnCalendarDisabled: + TextStyle(fontSize: 12, color: Colors.grey.withOpacity(0.1)), + textStyleMonthYearHeader: TextStyle( + fontSize: 12, + color: Colors.black.withOpacity(0.9), + fontWeight: FontWeight.bold), + + // paddingDatePicker: EdgeInsets.all(0), + // paddingMonthHeader: EdgeInsets.all(15), + paddingActionBar: const EdgeInsets.all(5), + paddingDateYearHeader: const EdgeInsets.all(10), + sizeArrow: 20, + colorArrowNext: Colors.black.withOpacity(0.9), + colorArrowPrevious: Colors.black.withOpacity(0.9), + marginLeftArrowPrevious: 8, + marginTopArrowPrevious: 8, + marginTopArrowNext: 8, + marginRightArrowNext: 8, + // textStyleButtonAction: TextStyle(fontSize: 208, color: Colors.white), + textStyleButtonPositive: const TextStyle( + fontSize: 15, color: Colors.white, fontWeight: FontWeight.bold), + textStyleButtonNegative: + TextStyle(fontSize: 15, color: Colors.white.withOpacity(0.5)), + decorationDateSelected: const BoxDecoration( + color: AppColors.colorPrimary, shape: BoxShape.circle), + backgroundPicker: AppColors.white.withOpacity(0.9), + backgroundActionBar: AppColors.colorPrimary.withOpacity(0.9), + // backgroundHeaderMonth: AppColors.primary.withOpacity(0.9), + ), + styleYearPicker: MaterialRoundedYearPickerStyle( + textStyleYear: const TextStyle(fontSize: 20, color: Colors.grey), + textStyleYearSelected: const TextStyle( + fontSize: 20, color: Colors.grey, fontWeight: FontWeight.bold), + heightYearRow: 30, + backgroundPicker: AppColors.colorPrimary.withOpacity(0.3), + )); + + // Toasty.success("--------->>> " + newDateTime.toString()); + } + + static Future?> showRangeDatePicker() async { + return showCalendarDatePicker2Dialog( + context: Get.context!, + config: CalendarDatePicker2WithActionButtonsConfig( + calendarType: CalendarDatePicker2Type.range, + allowSameValueSelection: false, + currentDate: DateTime.now(), + firstDate: DateTime(2020), + lastDate: DateTime.now().add(Duration(days: 1)), + ), + dialogSize: Size(Get.width, 150), + ); + } +} diff --git a/lib/app/custom_widgets/pop_dialog.dart b/lib/app/custom_widgets/pop_dialog.dart new file mode 100644 index 0000000..d0fed62 --- /dev/null +++ b/lib/app/custom_widgets/pop_dialog.dart @@ -0,0 +1,108 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:quickalert/models/quickalert_type.dart'; +import 'package:quickalert/widgets/quickalert_dialog.dart'; + +import '../core/constants/translation_keys.dart'; +import '../core/extensions/build_context_ext.dart'; +import '../res/app_colors.dart'; + + +class PopDialog { + static late BuildContext dialogContext; + + static successDialog( + BuildContext context, { + String title = "", + String description = "An Success occurred", + String positiveButtonText = "", + Function()? onPositiveTap, + }) { + QuickAlert.show( + context: context, + title: title.isEmpty ? TranslationKeys.makeTranslation(TranslationKeys.textSuccess) : title, + text: description, + confirmBtnColor: AppColors.colorButton, + confirmBtnTextStyle: Theme.of(context).textTheme.titleMedium?.copyWith(color: AppColors.colorSecondary), + confirmBtnText: positiveButtonText.isEmpty ? TranslationKeys.makeTranslation(TranslationKeys.textOK) : positiveButtonText, + onConfirmBtnTap: () { + Navigator.of(context, rootNavigator: true).pop(); + if (onPositiveTap != null) { + onPositiveTap(); + } + }, + disableBackBtn: true, + type: QuickAlertType.success, + barrierDismissible: false, + showConfirmBtn: true, + ); + } + + static warningDialog( + BuildContext context, { + String title = "", + String description = "", + String positiveButtonText = "", + String negativeButtonText = "", + Function()? onPositiveTap, + Function()? onNegativeTap, + }) { + QuickAlert.show( + showCancelBtn: true, + context: context, + title: title.isEmpty ? TranslationKeys.makeTranslation(TranslationKeys.textWarning) : title, + confirmBtnColor: AppColors.colorButton, + text: description, + confirmBtnTextStyle: Theme.of(context).textTheme.titleMedium?.copyWith(color: AppColors.colorSecondary), + confirmBtnText: positiveButtonText.isEmpty ? TranslationKeys.makeTranslation(TranslationKeys.textOK) : positiveButtonText, + cancelBtnText: negativeButtonText.isEmpty ? TranslationKeys.makeTranslation(TranslationKeys.textCancel) : negativeButtonText, + onCancelBtnTap: () { + Navigator.of(context, rootNavigator: true).pop(); + if (onNegativeTap != null) { + onNegativeTap(); + } + }, + onConfirmBtnTap: () { + Navigator.of(context, rootNavigator: true).pop(); + if (onPositiveTap != null) { + onPositiveTap(); + } + }, + disableBackBtn: true, + type: QuickAlertType.warning, + barrierDismissible: false, + showConfirmBtn: true, + ); + } + + static Card buildButton({ + required onTap, + required title, + required text, + required leadingImage, + }) { + return Card( + shape: const StadiumBorder(), + margin: const EdgeInsets.symmetric( + horizontal: 20, + ), + clipBehavior: Clip.antiAlias, + elevation: 1, + child: ListTile( + onTap: onTap, + leading: CircleAvatar( + backgroundImage: AssetImage( + leadingImage, + ), + ), + title: Text( + title ?? "", + ), + subtitle: Text(text ?? "", style: Get.context.textTheme.bodySmall), + trailing: const Icon( + Icons.keyboard_arrow_right_rounded, + ), + ), + ); + } +} diff --git a/lib/app/custom_widgets/responsive_widget.dart b/lib/app/custom_widgets/responsive_widget.dart new file mode 100644 index 0000000..59fc565 --- /dev/null +++ b/lib/app/custom_widgets/responsive_widget.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../routes/app_pages.dart'; + +showCutomBottomSheet(Widget child) { + Get.bottomSheet( + responsiveWidget( + InkWell( + splashColor: Colors.transparent, + highlightColor: Colors.transparent, + onTap: () { + Get.back(); + }, + child: Align( + alignment: Alignment.bottomCenter, + child: GestureDetector( + behavior: HitTestBehavior.deferToChild, + onTap: () {}, + child: child, + ), + ), + ), + ), + backgroundColor: Colors.transparent, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); +} diff --git a/lib/app/custom_widgets/widget_interactions.dart b/lib/app/custom_widgets/widget_interactions.dart new file mode 100644 index 0000000..b527460 --- /dev/null +++ b/lib/app/custom_widgets/widget_interactions.dart @@ -0,0 +1,43 @@ +// import 'package:mfsys_include_app/app/core/constants/app_constants.dart'; +// import 'package:mfsys_include_app/app/core/constants/widget_types.dart'; +// import 'package:mfsys_include_app/app/presentations/widgets/parent_widget.dart'; +// import 'package:mfsys_include_app/app/presentations/widgets/widget_operation.dart'; +// import 'package:uco_ciihive/app/core/constants/widget_types.dart'; +// import 'package:uco_ciihive/app/custom_widgets/custom_input_field.dart'; +// import 'package:uco_ciihive/app/custom_widgets/widget_operation.dart'; +// +// import 'custom_text_field.dart'; +// import 'otp_pin.dart'; +// +// class WidgetInteractions { +// static Map map = {}; +// +// WidgetInteractions._privateConstructor() { +// _registerWidgets(); +// } +// +// static WidgetInteractions instance = WidgetInteractions._privateConstructor(); +// +// _registerWidgets() { +// map[WidgetTypes.CUSTOM_EDIT_TEXT] = CustomInputFieldCustom(); +// } +// +// bool validateWidget(ParentWidget field, String type) { +// return map[type]!.validate(field); +// } +// +// Object getValue(ParentWidget field, String type) { +// return map[type]!.getValue(field); +// } +// +// static bool validateAll([List args = const []]) { +// bool hasError = false; +// for (ParentWidget inputField in args) { +// bool isError = WidgetInteractions.instance.validateWidget(inputField, inputField.tags[AppConstants.FIELD_TYPE].toString()); +// if (isError) { +// hasError = true; +// } +// } +// return hasError; +// } +// } diff --git a/lib/app/custom_widgets/widget_operation.dart b/lib/app/custom_widgets/widget_operation.dart new file mode 100644 index 0000000..e079f04 --- /dev/null +++ b/lib/app/custom_widgets/widget_operation.dart @@ -0,0 +1,7 @@ +import 'package:flutter/cupertino.dart'; + +abstract class WidgetOperations { + bool validate(Widget widget); + + Object getValue(Widget widget); +} diff --git a/lib/app/l10n/Arabic.dart b/lib/app/l10n/Arabic.dart new file mode 100644 index 0000000..bf8ed2e --- /dev/null +++ b/lib/app/l10n/Arabic.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; +import 'package:get/get_navigation/src/root/internacionalization.dart'; + +class Arabic extends Translations { + @override + Map> get keys => { + 'ar_SA': { + "textWelcomeToJoin": "Welcome to Join Us", + "textIntroDescription": "Send money through Send Money World with best and low rate to your family, friends in two mintes.", + }, + }; +} diff --git a/lib/app/l10n/English.dart b/lib/app/l10n/English.dart new file mode 100644 index 0000000..4a73ad9 --- /dev/null +++ b/lib/app/l10n/English.dart @@ -0,0 +1,382 @@ +import 'package:get/get.dart'; + +class English extends Translations { + @override + Map> get keys => { + 'en_US': { + "textWelcomeToJoin": "Welcome to Join Us", + "textIntroDescription": "Send money through Send Money World with best and low rate to your family, friends in two mintes.", + "textLogin": "Login", + "textInternetConnectivity": "No Internet Connectivity", + "textInternalAccountTransaction": "Internal Transaction", + "textReferenceCode": "Reference Code", + "textRegister": "Register", + "textFindUAgent": "UAgent", + "textQRPay": "QR Pay", + "textAddAccount": "Add Account", + "textCreateAccount": "Create Account", + "textHelp": "Help", + "textContactUs": "Contact Us", + "textGetInTouch": "Get In Touch", + "textEmail": "Email", + "textPhone": "Phone", + "textOTPDescription": "To verify your identity we sent a verification SMS Please enter the code we sent to", + "textOTP": "OTP", + "textOTPValid": "OTP is valid till:", + "textResend": "Resend", + "textVerify": "Verify", + "textCongratulations": "Congratulations!", + "textCongratulationsContent": "Congratulations! you received money successfully.", + "textOTPMessage": "Your OTP code has been verified via email. Thanks", + "textContinue": "Continue", + "textAccountTitle": "Bilal Sabir", + "textAccountSession": "Last Login 23-Apr-2024 ", + "textSuccess": "Success", + "textOK": "OK", + "textWarning": "Warning!!", + "textCancel": "Cancel", + "textReverse": "Reverse", + "textConformation": "Confirmation", + "textLogOutContent": "Are you sure you want to log out?", + "textManage": "Manage", + "textLogout": "Log Out", + "textVersion": "version 0.0.1", + "textMyAccount": "My Account", + "textBillManagement": "Bill Management", + "textChequeManagement": "Cheque Management", + "textBeneficiaryManagement": "Beneficiary Management", + "textUSend": "U-Send", + "textUReceived": "U-Received", + "textAgentLocation": "Agent Location", + "textAccountStatement": "Account Statement", + "textSupport": "Support", + "textUserProfile": "User Profile", + "textUserActivity": "User Activity", + "textLogOut": "Logout", + "textUCash": "U Cash", + "textUShop": "U-Shop", + "textOverView": "Overview", + "textDashboardWelcomeUser": "Welcome Ahsan Raja", + "textTotalAvailableFunds": "Total Available Funds", + "textTotalAvailableBalance": "\$1000.0", + "textTotalAvailableBalanceInWords": "Sixty Eight Thousand Nine Hundred", + "textAccountNumber": "12345***89", + "textPleaseSelectAccount": "Please Select Account", + "textStatementDetails": "Statement Details", + "textBalance": "Balance", + "textUPrimary": "UPrimary", + "textUSave": "USave", + "textUChaChing": "UChaChing", + "textAboutUs": "About Us", + "textCareer": "Career", + "textWHY": "WHY", + "textWHAT": "WHAT", + "textWHYDescription": "“Maricel Jacobe arrived at 6 a.m. at one Western Union outlet to collect some wired money on Monday, only to be told she was 729th in line. Six hours later she was still waiting her turn to pick up the \$25 family members in Manila had sent her. She will have to do it again the following day, she said, because her family could only send a little at a time. Like many people in the region, she had money but couldn’t access it because the island’s banking system has been largely shut down.", + "textWHATDescription": "UCO is Universal Cash Online, a patent protected financial technology solution by AIR 1, Inc. UCO lets its users and merchants send, receive, and spend cash both online and offline. UCO solves the issues caused by current payment solutions through its free mobile platform available to 6.8 billion mobile phone subscriptions worldwide, reducing cost; time; and inconvenience. You can manage funds across multiple currencies, family budgets, business finances; pay locally; buy globally, and more.", + "textWHO": "WHO", + "textWHODescription": "The UCO team members are experienced and tested executives capable of executing this impact oriented initiative of global magnitude. We have decades of expertise in financial and mobile technology, cybercrime prevention, security, compliance, consumer goods, marketing, and advertising. We are also backed by advisors who are former Fortune 50 chief officers in the areas of: technology, banking, and finance.", + "textApply": "Apply", + "textJobTitle": "Senior ui/ux designer", + "textOfficeAddress": "Islamabad, Pakistan", + "textJobSkills": "Photoshop, Adobe XD,Invision, Figma", + "textSelectPersonalAccount": "Select Personal Account", + "textRecipientDetail": "Recipient Detail", + "textPhoneNumber": "Phone Number", + "textRecipientCardName": "Recipient Name", + "textSelectCurrency": "Select Currency", + "textSendingAmount": "Sending amount", + "textExchangeRate": "Exchange rate", + "textMessageMemo": "Message/Memo", + "textSend": "Send", + "textClear": "Clear", + "textPermissionDenied": "Permission Denied", + "textMyProfile": "My Profile", + "textNotFound": "Not Found", + "textRecipient": "Recipient", + "textHome": "Home", + "textCurrency": "Currency", + "textMessage": "Message", + "textConfirm": "Confirm", + "textEndingBalance": "Ending Balance", + "textPendingRemittance": "Pending Remittance", + "textReceived": "U-Received", + "textPinCode": "Pin Code", + "textBack": "Back", + "textCancelDescription": "Are you Sure you want to Cancel", + "textYes": "Yes", + "textUserName": "User Name", + "textPassword": "Password", + "textConfirmPassword": "Confirm Password", + "textEmailID": "Email ID", + "textCellNumber": "Cell Number", + "textNext": "Next", + "textName": "Name", + "textAddress": "Address", + "textIdentityNumber": "Identity Number", + "textSSNTaxPayerID": "SSN/TaxPayer ID", + "textPassportAlienID": "Passport # Alien ID", + "textChooseDocumentType": "Choose Document Type", + "textCNIC": "CNIC", + "textDivingLicense": "Diving License", + "textPassport": "Passport", + "textFront": "Front", + "textSkipKYC": "Skip KYC", + "textDocumentsDescription": "Official Documents Accepted as Proof of identity", + "textSignUpDescriptionDailog": "Thank you so much! Your account as been successfully registered.", + "textNotRegisterUser": "New Register User ?", + "textRegisterNow": "Register Now!", + "textSingUp": "Sign Up", + "textUploadKYC": "Upload KYC", + "textTransactionHistory": "Transaction History", + "ERR_USER_0001": "Email Already Registered", + "ERR_USER_0002": "Old Password not allowed", + "ERR_USER_0004": "User not found", + "ERR_CONNECTION": "NO internet connection", + "ERR_USER_0003": "Invalid OTP", + "ERR_USER_0005": "Invalid Credentials", + "ERR_USER_0006": "Same password cannot be set as new password", + "ERR_USER_0007": "Application is pending", + "ERR_USER_0008": "Old pin is incorrect", + "ERR_USER_0009": "Account Not Found", + "ERR_DEP_B_0001": "Account has insufficient balance", + "ERR_USER_0010": "Same cr dr account not allowed", + "ERR_USER_0011": "Phone number already registered", + "ERR_TRN_0013": "Reference Number for the Transaction not valid", + "ERR_USER_0012": "Same transaction pin cant be set as new", + "ERR_USER_0013": "Beneficiary already exists", + "ERR_TRN_0014": "Invalid transaction amount", + "textUserActivityTitle": "User Activity", + "textUserActivityChannel": "Channel: ", + "textUserActivityDevice": "Device", + "changepassword": "Change Password", + "resetPasswordMessage": "Your Password is change successfully", + "textChangePassword": "Change Password", + "textSelectFromDateAndProceed": "Select from date first and then proceed", + + /// import from include app + "textMapLocationTitle": "Map Location", + "textNormalMap": "Normal", + "textSatelliteMap": "Satellite", + "textHybridMap": "Hybrid", + "textMapContactNumber": "Contact Number", + "transUtilityBill": "Bill Payments", + "transUtilityBillCategory": "Bill Payments", + "textSelectBillType": "Select Bill Type", + "transUtilityElectricity": "Electricity", + "transUtilityGas": "Gas", + "transUtilityInternet": "Internet", + "transUtilityPTCL": "PTCL", + "transUtilityWater": "Water", + "transUtilityCreditCard": "Credit Card", + "textSelectCompany": "Select Company", + "transUtilityAJKBARKIYAT": "AJK-BARKIYAT", + "transUtilityFESCO": "FESCO", + "transUtilityGBBARKIYAT": "GB-BARKIYAT", + "transUtilityGEPCO": "GEPCO", + "transUtilityHESCO": "HESCO", + "transUtilityIESCO": "IESCO", + "textChequeBookActivation": "Cheque Book Active", + "textChequeBookActivationDialogMsg": "Successfully Cheque Book Activation Request", + "textActivationContent": "Enter the cheque numbers of the first and last leaves of your cheque book", + "textAccount": "Account", + "textAccountNumber": "Account Number", + "textBillDetailCustomerName": "MUHAMMAD BILAL", + "textFirstLeaf": "Cheque Number of First Leaf", + "textLastLeaf": "Cheque Number of Last Leaf", + "textEnterChequeNumber": "Enter cheque number", + "textChequeRequestDetail": "Cheque Book Request", + "textChequeBookRequestContent": "Please check your Details according to your inputs", + "transPakGasAgency": "Pak Gas Agency", + "transSuiGas": "Sui Gas", + "transFiber": "Fiber", + "transMinerva": "Minerva", + "transNestle": "transNestle", + "transAquaFujitenma": "transAquaFujitenma", + "transZong": "Zong", + "transPepsiCo": "transPepsiCo", + "textLeave20": "20", + "textLeaves": "Leaves", + "textGet": "Get", + "textLeave100": "100", + "textLeave50": "50", + "textChange": "Change", + "textDeliveryAddress": "Delivery Address", + "textChequeBookRequestAddress": "Level-1, Block-A, STP-Software Technology Park, Service Road North, I – 9/3 Islamabad, Pakistan", + "textCharges": "Charges", + "textScheduleCharges": "As per schedule of the charges", + "textDate": "Date", + "textDateContent": "Dec 20, 2023", + "textRequestSummary": "Request Summary", + "textPurpose": "Purpose", + "textNumberofLeaves": "Number of Leaves", + "textChequeRequestTitle": "Cheque Request", + "textQueryContent": "Your cheque book will be delivered within 7 working days. For inquiries, call us at 111-825-888 or send us an email with your registered email address at customer.services@ubl.com.pk", + "textDeposit": "Deposit", + "textChequeDeposit": "Cheque Deposit", + "textChequeStatusContent": "Enter the cheque number to check its status", + "textDepositToChequing": "Deposit To Chequing", + "text1000": "\n\$1000", + "textMax300000": "Max:300000", + "textSelectAccount": "Select Account", + "textFrontOfCheque": "Front Of Cheque", + "textTryAgain": "Try Again", + "textChequeStatus": "Cheque Status", + "textChequeActivation": "Cheque Activation", + "textChequeRequest": "Cheque Request", + "textChequeRequestContent": "Please select the cheque book with leaves", + "textChequeStatusHistory": "Cheque Status History", + "textChequeStatusHistoryContent": "Enter the cheque number to check its status", + "textChequeStatusCheckNumber": "Check # xxxxxxx9083", + "textChequeStatusHistoryRefNo": "ref #IBE5BH8976CF", + "textChequeStatusHistorySuccess": "Success", + "textChequeStatusHistoryCancel": "Cancel", + "textPTCLLandLine": "PTCL Land Line", + "textSelectAccountDetails": "Select Account Details", + "textCreditCard": "Credit Card", + "textCreditCardNumber": "4025***********8892", + "textAmountDebit": "Amount Debit", + "textEnterConsumerName": "Enter Consumer Name", + "textTotalAmount": "Total Amount", + "textEnterAmount": "Enter Amount", + "textBillDetails": "Bill Details", + "textBillConsumerName": "Consumer Name", + "textBillAmount": "Bill Amount", + "textDueDate": "Due Date", + "textAmountDueAfterDueDate": "Amount Due After Due Date", + "textBillStatus": "Bill Status", + "textBillDetailZero": "0", + "textBillDetailDate": "02/19/24", + "textBillDetailUnPaid": "UnPaid", + "textPayNow": "Pay Now", + "textBillDetailContent": "Your Electricity Land Line bill is", + "textBillDetailBalance": "PKR 12394", + "textBillDetailBillAmount": "Amount", + "textBillDetailBillDueDate": "Due Date", + "textBillDetailBillAmountDue": "Amount Due", + "textBillDetailBillAfterDueDate": "After Due Date", + "textBillDetailBillStatus": "Bill Status", + "textProfileHey": "Hey,", + "textProfileUsername": "Username", + "textAppSettingTitle": "App Setting", + "textLanguagesTitle": "Languages", + "textDarkModeContent": "Tap to change your Theme Mode", + "textFingerPrintTitle": "FingerPrint", + "textFingerPrintContent": "Tap to unlock Fingerprint", + "textPasswordChangeTitle": "Change Password", + "textPasswordChangeContent": "Tap to change your Password", + "textTermOfService": "Term of Service", + "textPrivacy": "Privacy", + "textInviteFriends": "Invite Friends", + "textDialogConformation": "Conformation", + "textDialogContent": "Are you sure you want to log out?", + "textSignOut": "SignOut", + "textSearch": "Search...", + "textSelectYourOption": "Select Your Option", + "textLanguageEnglish": "English", + "textLanguageArabic": "Arabic", + "textLanguageUrdu": "Urdu", + "textNoSelect": "No Selection", + "textMyAccountTitle": "My Account", + "textMyAccountAccountTitle": "Account Title", + "textMyAccountAccountNumber": "Account Number", + "textMyAccountBranchCode": "Branch Code", + "textMyAccountAccountOpeningDate": "Account Opening Date", + "textAppSetting": "App Setting", + "textLoginTitle": "Login", + "textInvalidFingerprint": "Record not against your finger print, please login with credentials", + "textPasswordPattern": "Password requires: 8 + characters, upper/lower case letters, number, special character.", + "textDailyTransactionLimit": "Daily Transaction Limit", + "textChangeTransactionPin": "Change Pin", + "textQRSetting": "QR Setting", + "textTransactionLimit": "Transaction Limit", + "textTransactionPin": "Transaction Pin", + "textOldLimit": "Rs.1,000,000", + "textMaximumLengthContent": "The maximum limit that can be set is Rs. 10 million", + "textLimitNoteContent": "Note: If you do not have a Debit card, please call the contact center or send us an email at customer.", + "textCurrentDailyLimit": "Current Daily Limit", + "textDone": "Done", + "textPinOTPMessage": "Your Transaction Pin OTP has been Successfully updated! An update email and message has been sent to you.", + "textYourUCOQR": "Your UCO QR", + "textUCOQRContent": "Share this QR Code with sender or they can scan it from your phone to receive money through UCO", + "textQrAccountName": "Muhammad Bilal", + "textQrAccountNumber": "MSISDN: ********** 2222", + "textShareQRCode": "Share QR Code", + "textSavetoGallery": "Save to Gallery", + "textNotifications": "Notifications", + "textFilter": "Filter", + "textChequeNumber": "Cheque Number", + "textCreateTransactionPin": "Create Transaction Pin", + "textShare": "Share", + "textPleaseCreatenewtransactionpin": "Please Create a New Transaction Pin", + "textConfirmTransactionPin": "Please Confirm New Transaction Pin", + "textOldTransactionPin": "Please old Transaction Pin", + "textNotificationDetails": "Notification Details", + "textNotificationDetailsContent": "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account 03273653107. Fee: Rs. 0.0. Trx ID 27586324598.", + "textError": "Error!!", + "textDescription": "Something happened wrong! Please check it.", + "textInform": "Information!!", + "Continue": "Continue", + "textConfirmTransaction": "Confirm Transaction", + "textHowdoyouwanttopay": "How do you want to pay", + "textDebitCard": "Debit Card", + "textDebitCardContent": "10.78 GBP fee, so recipient gets 340839.71 PKR.Should arrive in seconds", + "textBankTransfer": "Bank Transfer", + "textGeneralLedger": "General Ledger", + "transAddMoney": "Add Money", + "textGLCode": "GL Code", + "textFaqs": "FAQ'S", + "textHowCanIHelpYou": "Hi, how can we help?", + "textExploreAllArticles": "Explore all topics", + "textFirstName": "First Name", + "textLastName": "Last Name", + "textBackofCheque": "Back of Cheque", + "textEnterEmail": "Email Address", + "textOurFee": "Our Fee", + "textTotalAmountWellConvert": "Total Amount We'll Convert", + "textGuaranteedExchnageRate": "Guaranteed Exchange Rate", + "textSelectYourGLSAccount": "Select Your GLS Account", + "textGlsAccounts": "Gls Accounts", + "textEnterMessage": "Enter Message", + "textWarningContent": "Are you sure you want to delete this Beneficiary.", + "textAddBeneficiary": "Add Beneficiary", + + // /// Double keys + // "textWHODescription": + // "The UCO team members are experienced and tested executives capable of executing this impact oriented initiative of global magnitude. We have decades of expertise in financial and mobile technology, cybercrime prevention, security, compliance, consumer goods, marketing, and advertising. We are also backed by advisors who are former Fortune 50 chief officers in the areas of: technology, banking, and finance.", + // "textApply": "Apply", + // "textJobTitle": "Senior ui/ux designer", + // "textOfficeAddress": "Islamabad, Pakistan", + // "textJobSkills": "Photoshop, Adobe XD,Invision, Figma", + // "textSelectPersonalAccount": "Select Personal Account", + // "textRecipientDetail": "Recipient Detail", + // "textPhoneNumber": "Phone Number", + // "textRecipientCardName": "Recipient CardName", + // "textSelectCurrency": "Select Currency", + // "textSendingAmount": "Sending Amount", + // "textExchangeRate": "Exchange Rate", + // "textMessageMemo": "Message/Memo", + // "textSend": "Send", + // "textClear": "Clear", + // "textPermissionDenied": "Permission Denied", + // "textMyProfile": "My Profile", + // "textNotFound": "Not Found", + // "textRecipient": "Recipient", + // "textHome": "Home", + // "textCurrency": "Currency", + // "textMessage": "Message", + // "textConfirm": "Confirm", + // "textEndingBalance": "Ending Balance", + // "textPendingRemittance": "Pending Remittance", + // "textReceived": "Received", + // "textPinCode": "Pin Code", + // "textBack": "Back", + // "textCancelDescription": "Are you Sure you want to Cancel", + // "textYes": "Yes", + "textErrorRequired": "This field is required", + "textPay": "Pay", + "textDelete": "Delete", + "textAddToBeneficiary": "Add To Beneficiary", + "textTransferAmount": "Transfer Amount", + }, + }; +} diff --git a/lib/app/models/AccountInquiryResponseModel.dart b/lib/app/models/AccountInquiryResponseModel.dart new file mode 100644 index 0000000..49c9263 --- /dev/null +++ b/lib/app/models/AccountInquiryResponseModel.dart @@ -0,0 +1,44 @@ +class AccountInquiryResponseModel { + String mbmBkmstitle = ""; + String mbmBkmsnumber = ""; + String pcrCurrcode = ""; + String pcrCurrdesc = ""; + String pcrCurrshort = ""; + + AccountInquiryResponseModel({ + this.mbmBkmstitle = "", + this.mbmBkmsnumber = "", + this.pcrCurrcode = "", + this.pcrCurrdesc = "", + this.pcrCurrshort = "", + }); + + static List fromList(List list) { + return list.map((item) => AccountInquiryResponseModel.fromMap(AccountInquiryResponseModel.fromMap(item as Map).toMap())).toList(); + } + + Map toMap() { + return { + 'mbmBkmstitle': this.mbmBkmstitle, + 'mbmBkmsnumber': this.mbmBkmsnumber, + 'pcrCurrcode': this.pcrCurrcode, + 'pcrCurrdesc': this.pcrCurrdesc, + 'pcrCurrshort': this.pcrCurrshort, + }; + } + + factory AccountInquiryResponseModel.fromMap(Map map) { + return AccountInquiryResponseModel( + mbmBkmstitle: map['mbmBkmstitle'] ?? "", + mbmBkmsnumber: map['mbmBkmsnumber'] ?? "", + pcrCurrcode: map['pcrCurrcode'] ?? "", + pcrCurrdesc: map['pcrCurrdesc'] ?? "", + pcrCurrshort: map['pcrCurrshort'] ?? "", + ); + } + + @override + String toString() { + return 'AccountInquiryResponseModel{mbmBkmstitle: $mbmBkmstitle, mbmBkmsnumber: $mbmBkmsnumber, pcrCurrcode: $pcrCurrcode, pcrCurrdesc: $pcrCurrdesc, pcrCurrshort: $pcrCurrshort}'; + } +} diff --git a/lib/app/models/AddNewAccountRequestModel.dart b/lib/app/models/AddNewAccountRequestModel.dart new file mode 100644 index 0000000..aaf0504 --- /dev/null +++ b/lib/app/models/AddNewAccountRequestModel.dart @@ -0,0 +1,34 @@ +class AddNewAccountRequestModel { + String porOrgacode = ""; + String email = ""; + String title = ""; + String dmpProdcode = ""; + String channelCode = ""; + + AddNewAccountRequestModel({this.porOrgacode = "", this.email = "", this.title = "", this.dmpProdcode = "", this.channelCode = ""}); + + Map toMap() { + return { + 'porOrgacode': this.porOrgacode, + 'email': this.email, + 'title': this.title, + 'dmpProdcode': this.dmpProdcode, + 'channelCode': this.channelCode, + }; + } + + factory AddNewAccountRequestModel.fromMap(Map map) { + return AddNewAccountRequestModel( + porOrgacode: map['porOrgacode'] ?? "", + email: map['email'] ?? "", + title: map['title'] ?? "", + dmpProdcode: map['dmpProdcode'] ?? "", + channelCode: map['channelCode'] ?? "", + ); + } + + @override + String toString() { + return 'AddNewAccountRequestModel{porOrgacode: $porOrgacode, email: $email, title: $title, dmpProdcode: $dmpProdcode, channelCode: $channelCode}'; + } +} diff --git a/lib/app/models/AuthenticationRequest.dart b/lib/app/models/AuthenticationRequest.dart new file mode 100644 index 0000000..988f497 --- /dev/null +++ b/lib/app/models/AuthenticationRequest.dart @@ -0,0 +1,47 @@ +class AuthenticationRequest { + String email = ""; + String password = ""; + bool isOtpRequired = false; + String porOrgacode = ""; + String channelCode = ""; + + AuthenticationRequest.empty() + : this.email = "", + this.password = "", + this.isOtpRequired = false, + this.porOrgacode = "", + this.channelCode = ""; + + AuthenticationRequest({ + this.email = "", + this.password = "", + this.isOtpRequired = false, + this.porOrgacode = "", + this.channelCode = "", + }); + + Map toMap() { + return { + 'email': email, + 'password': password, + 'isOtpRequired': isOtpRequired, + 'porOrgacode': porOrgacode, + 'channelCode': channelCode, + }; + } + + factory AuthenticationRequest.fromMap(Map map) { + return AuthenticationRequest( + email: map['email'], + password: map['password'], + isOtpRequired: map['isOtpRequired'], + porOrgacode: map['porOrgacode'], + channelCode: map['channelCode'], + ); + } + + @override + String toString() { + return 'AuthenticationRequest{email: $email, password: $password, isOtpRequired: $isOtpRequired, porOrgacode: $porOrgacode, channelCode: $channelCode}'; + } +} diff --git a/lib/app/models/AuthenticationResponse.dart b/lib/app/models/AuthenticationResponse.dart new file mode 100644 index 0000000..3423c09 --- /dev/null +++ b/lib/app/models/AuthenticationResponse.dart @@ -0,0 +1,52 @@ +class AuthenticationResponse { + String name = ""; + String cmpCuststatus = ""; + String cmpCustlastlogin = ""; + String cmpCustcode = ""; + // Role userRole = ""; + String jwtToken = ""; + String refreshToken = ""; + bool isKycVerified = false; + + AuthenticationResponse({ + this.name = "", + this.cmpCuststatus = "", + this.cmpCustlastlogin = "", + this.cmpCustcode = "", + //this.userRole = "", + this.jwtToken = "", + this.refreshToken = "", + this.isKycVerified = false, + }); + + Map toMap() { + return { + 'name': name, + 'cmpCuststatus': cmpCuststatus, + 'cmpCustlastlogin': cmpCustlastlogin, + 'cmpCustcode': cmpCustcode, + //'userRole': userRole.toMap(), // Assuming Role has a toMap method + 'jwtToken': jwtToken, + 'refreshToken': refreshToken, + 'isKycVerified': isKycVerified, + }; + } + + factory AuthenticationResponse.fromMap(Map map) { + return AuthenticationResponse( + name: map['name'] ?? "", + cmpCuststatus: map['cmpCuststatus'] ?? "", + cmpCustlastlogin: map['cmpCustlastlogin'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + // userRole: Role.fromMap(map['userRole']), // Assuming Role has a fromMap method + jwtToken: map['jwtToken'] ?? "", + refreshToken: map['refreshToken'] ?? "", + isKycVerified: map['isKycVerified'] ?? "", + ); + } + + @override + String toString() { + return 'AuthenticationResponse{name: $name, cmpCuststatus: $cmpCuststatus, cmpCustlastlogin: $cmpCustlastlogin, cmpCustcode: $cmpCustcode, /*userRole: userRole,*/ jwtToken: $jwtToken, refreshToken: $refreshToken, isKycVerified: $isKycVerified}'; + } +} diff --git a/lib/app/models/BeneficiaryAccountModel.dart b/lib/app/models/BeneficiaryAccountModel.dart new file mode 100644 index 0000000..dbba4f6 --- /dev/null +++ b/lib/app/models/BeneficiaryAccountModel.dart @@ -0,0 +1,61 @@ +class BeneficiaryAccountModel { + String porOrgacode = ""; + String email = ""; + String pcrCurrcode = ""; + String pcrCurrdesc = ""; + String pcrCurrshort = ""; + String mbmBkmstitleRef = ""; + String mbmBkmsnumberRef = ""; + String refPhoneNumber = ""; + String refEmail = ""; + String refNickName = ""; + + + BeneficiaryAccountModel({ + this.porOrgacode = "", + this.email = "", + this.pcrCurrcode = "", + this.pcrCurrdesc = "", + this.pcrCurrshort = "", + this.mbmBkmstitleRef = "", + this.mbmBkmsnumberRef = "", + this.refPhoneNumber = "", + this.refEmail = "", + this.refNickName = "", + }); + + Map toMap() { + return { + 'porOrgacode': this.porOrgacode, + 'email': this.email, + 'pcrCurrcode': this.pcrCurrcode, + 'pcrCurrdesc': this.pcrCurrdesc, + 'pcrCurrshort': this.pcrCurrshort, + 'mbmBkmstitleRef': this.mbmBkmstitleRef, + 'mbmBkmsnumberRef': this.mbmBkmsnumberRef, + 'refPhoneNumber': this.refPhoneNumber, + 'refEmail': this.refEmail, + 'refNickName': this.refNickName, + }; + } + + factory BeneficiaryAccountModel.fromMap(Map map) { + return BeneficiaryAccountModel( + porOrgacode: map['porOrgacode'] ?? "", + email: map['email'] ?? "", + pcrCurrcode: map['pcrCurrcode'] ?? "", + pcrCurrdesc: map['pcrCurrdesc'] ?? "", + pcrCurrshort: map['pcrCurrshort'] ?? "", + mbmBkmstitleRef: map['mbmBkmstitleRef'] ?? "", + mbmBkmsnumberRef: map['mbmBkmsnumberRef'] ?? "", + refPhoneNumber: map['refPhoneNumber'] ?? "", + refEmail: map['refEmail'] ?? "", + refNickName: map['refNickName'] ?? "", + ); + } + + @override + String toString() { + return 'BeneficiaryAccountModel{porOrgacode: $porOrgacode, email: $email, pcrCurrcode: $pcrCurrcode, pcrCurrdesc: $pcrCurrdesc, pcrCurrshort: $pcrCurrshort, mbmBkmstitleRef: $mbmBkmstitleRef, mbmBkmsnumberRef: $mbmBkmsnumberRef, refPhoneNumber: $refPhoneNumber, refEmail: $refEmail, refNickName: $refNickName}'; + } +} diff --git a/lib/app/models/Branch.dart b/lib/app/models/Branch.dart new file mode 100644 index 0000000..768a3a4 --- /dev/null +++ b/lib/app/models/Branch.dart @@ -0,0 +1,15 @@ +class Branch { + final String name; + final double latitude; + final double longitude; + final String contactNumber; + final String address; + + Branch({ + required this.name, + required this.latitude, + required this.longitude, + required this.contactNumber, + required this.address, + }); +} \ No newline at end of file diff --git a/lib/app/models/ChangePasswordRequest.dart b/lib/app/models/ChangePasswordRequest.dart new file mode 100644 index 0000000..d336afc --- /dev/null +++ b/lib/app/models/ChangePasswordRequest.dart @@ -0,0 +1,32 @@ +class ChangePasswordRequest { + String oldPassword = ""; + String newPassword = ""; + String email = ""; + + ChangePasswordRequest({ + this.oldPassword = "", + this.newPassword = "", + this.email = "", + }); + + Map toMap() { + return { + 'oldPassword': oldPassword, + 'newPassword': newPassword, + 'email': email, + }; + } + + factory ChangePasswordRequest.fromMap(Map map) { + return ChangePasswordRequest( + oldPassword: map['oldPassword'], + newPassword: map['newPassword'], + email: map['email'], + ); + } + + @override + String toString() { + return 'ChangePasswordRequest{oldPassword: $oldPassword, newPassword: $newPassword, email: $email}'; + } +} diff --git a/lib/app/models/ChangeTransactionPinRequest.dart b/lib/app/models/ChangeTransactionPinRequest.dart new file mode 100644 index 0000000..c596dba --- /dev/null +++ b/lib/app/models/ChangeTransactionPinRequest.dart @@ -0,0 +1,64 @@ +class ChangeTransactionPinRequest { + String oldTransPincode = ""; + String newTransPincode = ""; + String channelCode = ""; + String pctCstycode = ""; + String porOrgacode = ""; + String cmpCustcode = ""; + bool isOtpRequired = false; + String pinType = ""; + + ChangeTransactionPinRequest({ + this.oldTransPincode = "", + this.newTransPincode = "", + this.channelCode = "", + this.pctCstycode = "", + this.porOrgacode = "", + this.cmpCustcode = "", + this.isOtpRequired = false, + this.pinType = "", + }); + + ChangeTransactionPinRequest.empty() + : this.oldTransPincode = "", + this.newTransPincode = "", + this.channelCode = "", + this.pctCstycode = "", + this.porOrgacode = "", + this.cmpCustcode = "", + this.isOtpRequired = false, + this.pinType = ""; + + // Convert object to a Map + Map toMap() { + return { + 'oldTransPincode': oldTransPincode, + 'newTransPincode': newTransPincode, + 'channelCode': channelCode, + 'pctCstycode': pctCstycode, + 'porOrgacode': porOrgacode, + 'cmpCustcode': cmpCustcode, + 'isOtpRequire': isOtpRequired, + 'pinType': pinType, + }; + } + + // Create object from a Map + factory ChangeTransactionPinRequest.fromMap(Map map) { + return ChangeTransactionPinRequest( + oldTransPincode: map['oldTransPincode'] ?? '' , + newTransPincode: map['newTransPincode'] ?? '', + channelCode: map['channelCode'] ?? '', + pctCstycode: map['pctCstycode'] ?? '', + porOrgacode: map['porOrgacode'] ?? '', + cmpCustcode: map['cmpCustcode'] ?? '', + isOtpRequired: map['isOtpRequire'] ?? '', + pinType: map['pinType'], + ); + } + + @override + String toString() { + return 'ChangeTransactionPinRequest{oldTransPincode: $oldTransPincode, newTransPincode: $newTransPincode, channelCode: $channelCode, pctCstycode: $pctCstycode, porOrgacode: $porOrgacode, cmpCustcode: $cmpCustcode, isOtpRequired: $isOtpRequired, pinType: $pinType}'; + } +} diff --git a/lib/app/models/CreateTransactionPinOTPRequest.dart b/lib/app/models/CreateTransactionPinOTPRequest.dart new file mode 100644 index 0000000..c8a1c11 --- /dev/null +++ b/lib/app/models/CreateTransactionPinOTPRequest.dart @@ -0,0 +1,57 @@ +class CreateTransactionPinOTPRequest { + String newTransPincode = ""; + String channelCode = ""; + String pctCstycode = ""; + String porOrgacode = ""; + String cmpCustcode = ""; + bool isOtpRequire = false; + String pinType = ""; + + CreateTransactionPinOTPRequest({ + this.newTransPincode = "", + this.channelCode = "", + this.pctCstycode = "", + this.porOrgacode = "", + this.cmpCustcode = "", + this.isOtpRequire = false, + this.pinType = "", + }); + + CreateTransactionPinOTPRequest.empty() + : this.newTransPincode = "", + this.channelCode = "", + this.pctCstycode = "", + this.porOrgacode = "", + this.cmpCustcode = "", + this.isOtpRequire = false, + this.pinType = ""; + + Map toMap() { + return { + 'newTransPincode': newTransPincode, + 'channelCode': channelCode, + 'pctCstycode': pctCstycode, + 'porOrgacode': porOrgacode, + 'cmpCustcode': cmpCustcode, + 'isOtpRequire': isOtpRequire, + 'pinType': pinType, + }; + } + + factory CreateTransactionPinOTPRequest.fromMap(Map map) { + return CreateTransactionPinOTPRequest( + newTransPincode: map['newTransPincode'], + channelCode: map['channelCode'], + pctCstycode: map['pctCstycode'], + porOrgacode: map['porOrgacode'], + cmpCustcode: map['cmpCustcode'], + isOtpRequire: map['isOtpRequire'], + pinType: map['pinType'], + ); + } + + @override + String toString() { + return 'CreateTransactionPinOTPRequest{newTransPincode: $newTransPincode, channelCode: $channelCode, pctCstycode: $pctCstycode, porOrgacode: $porOrgacode, cmpCustcode: $cmpCustcode, isOtpRequire: $isOtpRequire, pinType: $pinType}'; + } +} diff --git a/lib/app/models/CreateTransactionPinRequest.dart b/lib/app/models/CreateTransactionPinRequest.dart new file mode 100644 index 0000000..14a26e0 --- /dev/null +++ b/lib/app/models/CreateTransactionPinRequest.dart @@ -0,0 +1,49 @@ +class CreateTransactionPinRequest { + String channelCode = ""; + String pctCstycode = ""; + String porOrgacode = ""; + String cmpCustcode = ""; + String email = ""; + String obpPincode = ""; + String pinType = ""; + + + CreateTransactionPinRequest({ + this.channelCode = "", + this.pctCstycode = "", + this.porOrgacode = "", + this.cmpCustcode = "", + this.email = "", + this.obpPincode = "", + this.pinType = "", + }); + + Map toMap() { + return { + 'channelCode': this.channelCode, + 'pctCstycode': this.pctCstycode, + 'porOrgacode': this.porOrgacode, + 'cmpCustcode': this.cmpCustcode, + 'email': this.email, + 'obpPincode': this.obpPincode, + 'pinType': this.pinType, + }; + } + + factory CreateTransactionPinRequest.fromMap(Map map) { + return CreateTransactionPinRequest( + channelCode: map['channelCode'] ?? "", + pctCstycode: map['pctCstycode'] ?? "", + porOrgacode: map['porOrgacode'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + email: map['email'] ?? "", + obpPincode: map['obpPincode'] ?? "", + pinType: map['pinType'] ?? "", + ); + } + + @override + String toString() { + return 'CreateTransactionPinRequest{channelCode: $channelCode, pctCstycode: $pctCstycode, porOrgacode: $porOrgacode, cmpCustcode: $cmpCustcode, email: $email, obpPincode: $obpPincode, pinType: $pinType}'; + } +} diff --git a/lib/app/models/DepositAccountResponse.dart b/lib/app/models/DepositAccountResponse.dart new file mode 100644 index 0000000..7ae8089 --- /dev/null +++ b/lib/app/models/DepositAccountResponse.dart @@ -0,0 +1,152 @@ +class DepositAccount { + String porOrgacode = ""; + String mbmBkmsnumber = ""; + String pcrCurrdesc = ""; + String pctCstycode = ""; + String mbmBkmstitle = ""; + double mbmBkmsbalance = 0.0; + String mbmBkmsopendate = ""; + String accountType = ""; + String transactionLimit = ""; + String dmpProddesc = ""; + String plcLocadesc = ""; + String pcrCurrcode = ""; + String cmpCustcode = ""; + String dmpProdcode = ""; + String plcLocacode = ""; + String padAdrsmobphone = ""; + String pasAcstcode = ""; + String pcrCurrshort = ""; + + + DepositAccount({ + this.porOrgacode = "", + this.mbmBkmsnumber = "", + this.pcrCurrdesc = "", + this.pctCstycode = "", + this.mbmBkmstitle = "", + this.mbmBkmsbalance = 0.0, + this.mbmBkmsopendate = "", + this.accountType = "", + this.transactionLimit = "", + this.dmpProddesc = "", + this.plcLocadesc = "", + this.pcrCurrcode = "", + this.cmpCustcode = "", + this.dmpProdcode = "", + this.plcLocacode = "", + this.padAdrsmobphone = "", + this.pasAcstcode = "", + this.pcrCurrshort = "", + }); + + DepositAccount.empty() + : this.porOrgacode = "", + this.mbmBkmsnumber = "", + this.pcrCurrdesc = "", + this.pctCstycode = "", + this.mbmBkmstitle = "", + this.mbmBkmsbalance = 0.0, + this.mbmBkmsopendate = "", + this.accountType = "", + this.transactionLimit = "", + this.dmpProddesc = "", + this.plcLocadesc = "", + this.pcrCurrcode = "", + this.cmpCustcode = "", + this.dmpProdcode = "", + this.plcLocacode = "", + this.padAdrsmobphone = "", + this.pasAcstcode = "", + this.pcrCurrshort = ""; + + factory DepositAccount.fromMap(Map map) { + return DepositAccount( + porOrgacode: map['porOrgacode'] ?? "", + mbmBkmsnumber: map['mbmBkmsnumber'] ?? "", + pcrCurrdesc: map['pcrCurrdesc'] ?? "", + pctCstycode: map['pctCstycode'] ?? "", + mbmBkmstitle: map['mbmBkmstitle'] ?? "", + mbmBkmsbalance: (map['mbmBkmsbalance'] ?? 0.0).toDouble(), + mbmBkmsopendate: map['mbmBkmsopendate'] ?? "", + accountType: map['accountType'] ?? "", + transactionLimit: map['transactionLimit'] ?? "", + dmpProddesc: map['dmpProddesc'] ?? "", + plcLocadesc: map['plcLocadesc'] ?? "", + pcrCurrcode: map['pcrCurrcode'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + dmpProdcode: map['dmpProdcode'] ?? "", + plcLocacode: map['plcLocacode'] ?? "", + padAdrsmobphone: map['padAdrsmobphone'] ?? "", + pasAcstcode: map['pasAcstcode'] ?? "", + pcrCurrshort: map['pcrCurrshort'] ?? "", + ); + } + + Map toMap() { + final Map data = { + 'porOrgacode': porOrgacode, + 'mbmBkmsnumber': mbmBkmsnumber, + 'pcrCurrdesc': pcrCurrdesc, + 'pctCstycode': pctCstycode, + 'mbmBkmstitle': mbmBkmstitle, + 'mbmBkmsbalance': mbmBkmsbalance, + 'mbmBkmsopendate': mbmBkmsopendate, + 'accountType': accountType, + 'transactionLimit': transactionLimit, + 'dmpProddesc': dmpProddesc, + 'plcLocadesc': plcLocadesc, + 'pcrCurrcode': pcrCurrcode, + 'cmpCustcode': cmpCustcode, + 'dmpProdcode': dmpProdcode, + 'plcLocacode': plcLocacode, + 'padAdrsmobphone': padAdrsmobphone, + 'pasAcstcode': pasAcstcode, + 'pcrCurrshort': pcrCurrshort, + }; + return data; + } + + DepositAccount copyWith({ + String? porOrgacode, + String? mbmBkmsnumber, + String? pcrCurrdesc, + String? pcrCurrCode, + String? pctCstycode, + String? mbmBkmstitle, + double? mbmBkmsbalance, + String? mbmBkmsopendate, + String? accountType, + String? transactionLimit, + String? dmpProddesc, + String? plcLocadesc, + String? pcrCurrcode, + String? cmpCustcode, + String? dmpProdcode, + String? plcLocacode, + String? padAdrsmobphone, + String? pasAcstcode, + String? pcrCurrshort, + }) { + return DepositAccount( + porOrgacode: porOrgacode ?? this.porOrgacode, + mbmBkmsnumber: mbmBkmsnumber ?? this.mbmBkmsnumber, + pcrCurrdesc: pcrCurrdesc ?? this.pcrCurrdesc, + pctCstycode: pctCstycode ?? this.pctCstycode, + mbmBkmstitle: mbmBkmstitle ?? this.mbmBkmstitle, + mbmBkmsbalance: mbmBkmsbalance ?? this.mbmBkmsbalance, + mbmBkmsopendate: mbmBkmsopendate ?? this.mbmBkmsopendate, + accountType: accountType ?? this.accountType, + transactionLimit: transactionLimit ?? this.transactionLimit, + dmpProddesc: dmpProddesc ?? this.dmpProddesc, + plcLocadesc: plcLocadesc ?? this.plcLocadesc, + pcrCurrcode: pcrCurrcode ?? this.pcrCurrcode, + cmpCustcode: cmpCustcode ?? this.cmpCustcode, + dmpProdcode: dmpProdcode ?? this.dmpProdcode, + plcLocacode: plcLocacode ?? this.plcLocacode, + padAdrsmobphone: padAdrsmobphone ?? this.padAdrsmobphone, + pasAcstcode: pasAcstcode ?? this.pasAcstcode, + pcrCurrshort: pcrCurrshort ?? this.pcrCurrshort, + ); + } +} diff --git a/lib/app/models/DepositAccountTransaction.dart b/lib/app/models/DepositAccountTransaction.dart new file mode 100644 index 0000000..17749d9 --- /dev/null +++ b/lib/app/models/DepositAccountTransaction.dart @@ -0,0 +1,61 @@ +class DepositAccountTransaction { + String tranID = ""; + String sgtGntrCreatedAt = ""; + String sgtGntrNarration = ""; + String sgtGntrvaluedate = ""; + String deposit = ""; + String withdrawal = ""; + String status = ""; + String sgtGntramt = ""; + + DepositAccountTransaction({ + this.tranID = "", + this.sgtGntrCreatedAt = "", + this.sgtGntrNarration = "", + this.sgtGntrvaluedate = "", + this.deposit = "", + this.withdrawal = "", + this.status = "", + this.sgtGntramt = "", + }); + + Map toMap() { + return { + 'tranID': tranID, + 'sgtGntrCreatedAt': sgtGntrCreatedAt, + 'sgtGntrNarration': sgtGntrNarration, + 'sgtGntrvaluedate': sgtGntrvaluedate, + 'deposit': deposit, + 'withdrawal': withdrawal, + 'status': status, + 'sgtGntramt': sgtGntramt, + }; + } + + factory DepositAccountTransaction.fromMap(Map map) { + return DepositAccountTransaction( + tranID: map['tranID'] ?? '', + sgtGntrCreatedAt: map['sgtGntrCreatedAt'] ?? '', + sgtGntrNarration: map['sgtGntrNarration'] ?? '', + sgtGntrvaluedate: map['sgtGntrvaluedate'] ?? '', + deposit: map['deposit'] ?? '', + withdrawal: map['withdrawal'] ?? '', + status: map['status'] ?? '', + sgtGntramt: map['sgtGntramt'] ?? '', + ); + } + + @override + String toString() { + return 'DepositAccountTransaction{' + 'tranID: $tranID, ' + 'sgtGntrCreatedAt: $sgtGntrCreatedAt, ' + 'sgtGntrNarration: $sgtGntrNarration, ' + 'sgtGntrvaluedate: $sgtGntrvaluedate, ' + 'deposit: $deposit, ' + 'withdrawal: $withdrawal, ' + 'status: $status, ' + 'sgtGntramt: $sgtGntramt' + '}'; + } +} diff --git a/lib/app/models/ExchangeRate.dart b/lib/app/models/ExchangeRate.dart new file mode 100644 index 0000000..abcea4e --- /dev/null +++ b/lib/app/models/ExchangeRate.dart @@ -0,0 +1,67 @@ +class ExchangeRate { + String petExrtdesc = ""; + String pcrCurrcode = ""; + double perEratrateact = 0.0; + String petExrtcode = ""; + String perEratdate = ""; + String pcrCurrshort = ""; + String porOrgacode = ""; + String pcrCurrdesc = ""; + bool pcrCurrbase = false; + + ExchangeRate({ + this.petExrtdesc = "", + this.pcrCurrcode = "", + this.perEratrateact = 0.0, + this.petExrtcode = "", + this.perEratdate = "", + this.pcrCurrshort = "", + this.porOrgacode = "", + this.pcrCurrdesc = "", + this.pcrCurrbase = false, + }); + + ExchangeRate.empty() + : this.petExrtdesc = "", + this.pcrCurrcode = "", + this.perEratrateact = 0.0, + this.petExrtcode = "", + this.perEratdate = "", + this.pcrCurrshort = "", + this.porOrgacode = "", + this.pcrCurrdesc = "", + this.pcrCurrbase = false; + + factory ExchangeRate.fromMap(Map json) { + return ExchangeRate( + petExrtdesc: json['petExrtdesc'] ?? "", + pcrCurrcode: json['pcrCurrcode'] ?? "", + perEratrateact: json['perEratrateact'] ?? 0.0, + petExrtcode: json['petExrtcode'] ?? "", + perEratdate: json['perEratdate'] ?? "", + pcrCurrshort: json['pcrCurrshort'] ?? "", + porOrgacode: json['porOrgacode'] ?? "", + pcrCurrdesc: json['pcrCurrdesc'] ?? "", + pcrCurrbase: json['pcrCurrbase'] ?? false, + ); + } + + Map toMap() { + return { + 'petExrtdesc': petExrtdesc, + 'pcrCurrcode': pcrCurrcode, + 'perEratrateact': perEratrateact, + 'petExrtcode': petExrtcode, + 'perEratdate': perEratdate, + 'pcrCurrshort': pcrCurrshort, + 'porOrgacode': porOrgacode, + 'pcrCurrdesc': pcrCurrdesc, + 'pcrCurrbase': pcrCurrbase, + }; + } + + @override + String toString() { + return 'ExchangeRate{petExrtdesc: $petExrtdesc, pcrCurrcode: $pcrCurrcode, perEratrateact: $perEratrateact, petExrtcode: $petExrtcode, perEratdate: $perEratdate, pcrCurrshort: $pcrCurrshort, porOrgacode: $porOrgacode, pcrCurrdesc: $pcrCurrdesc, pcrCurrbase: $pcrCurrbase}'; + } +} diff --git a/lib/app/models/GLACCAddMoneyRequestModel.dart b/lib/app/models/GLACCAddMoneyRequestModel.dart new file mode 100644 index 0000000..ee7d1e1 --- /dev/null +++ b/lib/app/models/GLACCAddMoneyRequestModel.dart @@ -0,0 +1,122 @@ +class GLACCAddMoneyRequestModel { + String porOrgacode = ""; + String pctCstycode = ""; + String channelCode = ""; + String cmpCustcode = ""; + String drPcaGlaccode = ""; + String drPcaGlacdesc = ""; + String crMbmBkmsnumber = ""; + String crMbmBkmstitle = ""; + String crPcrCurrcode = ""; + String crPcrCurrdesc = ""; + String crPcrCurrshort = ""; + String sgtGntrnarration = ""; + String dmpProdCode = ""; + String transType = ""; + String notificationId = ""; + String transMode = ""; + double sgtGntramtfc = 0.0; + String otdTrancomment = ""; + String obpPincode = ""; + String pinType = ""; + + GLACCAddMoneyRequestModel({ + this.porOrgacode = "", + this.pctCstycode = "", + this.channelCode = "", + this.cmpCustcode = "", + this.drPcaGlaccode = "", + this.drPcaGlacdesc = "", + this.crMbmBkmsnumber = "", + this.crMbmBkmstitle = "", + this.crPcrCurrcode = "", + this.crPcrCurrdesc = "", + this.crPcrCurrshort = "", + this.sgtGntrnarration = "", + this.dmpProdCode = "", + this.transType = "", + this.notificationId = "", + this.transMode = "", + this.sgtGntramtfc = 0.0, + this.otdTrancomment = "", + this.obpPincode = "", + this.pinType = "", + }); + + GLACCAddMoneyRequestModel.empty() + : this.porOrgacode = "", + this.pctCstycode = "", + this.channelCode = "", + this.cmpCustcode = "", + this.drPcaGlaccode = "", + this.drPcaGlacdesc = "", + this.crMbmBkmsnumber = "", + this.crMbmBkmstitle = "", + this.crPcrCurrcode = "", + this.crPcrCurrdesc = "", + this.crPcrCurrshort = "", + this.sgtGntrnarration = "", + this.dmpProdCode = "", + this.transType = "", + this.notificationId = "", + this.transMode = "", + this.sgtGntramtfc = 0.0, + this.otdTrancomment = "", + this.obpPincode = "", + this.pinType = ""; + + @override + String toString() { + return 'GLACCAddMoneyRequestModel{porOrgacode: $porOrgacode, pctCstycode: $pctCstycode, channelCode: $channelCode, cmpCustcode: $cmpCustcode, drPcaGlaccode: $drPcaGlaccode, drPcaGlacdesc: $drPcaGlacdesc, crMbmBkmsnumber: $crMbmBkmsnumber, crMbmBkmstitle: $crMbmBkmstitle, crPcrCurrcode: $crPcrCurrcode, crPcrCurrdesc: $crPcrCurrdesc, crPcrCurrshort: $crPcrCurrshort, sgtGntrnarration: $sgtGntrnarration, dmpProdCode: $dmpProdCode, transType: $transType, notificationId: $notificationId, transMode: $transMode, sgtGntramtfc: $sgtGntramtfc, otdTrancomment: $otdTrancomment, obpPincode: $obpPincode, pinType: $pinType}'; + } + + Map toMap() { + return { + 'porOrgacode': this.porOrgacode, + 'pctCstycode': this.pctCstycode, + 'channelCode': this.channelCode, + 'cmpCustcode': this.cmpCustcode, + 'drPcaGlaccode': this.drPcaGlaccode, + 'drPcaGlacdesc': this.drPcaGlacdesc, + 'crMbmBkmsnumber': this.crMbmBkmsnumber, + 'crMbmBkmstitle': this.crMbmBkmstitle, + 'crPcrCurrcode': this.crPcrCurrcode, + 'crPcrCurrdesc': this.crPcrCurrdesc, + 'crPcrCurrshort': this.crPcrCurrshort, + 'sgtGntrnarration': this.sgtGntrnarration, + 'dmpProdCode': this.dmpProdCode, + 'transType': this.transType, + 'notificationId': this.notificationId, + 'transMode': this.transMode, + 'sgtGntramtfc': this.sgtGntramtfc, + 'otdTrancomment': this.otdTrancomment, + 'obpPincode': this.obpPincode, + 'pinType': this.pinType, + }; + } + + factory GLACCAddMoneyRequestModel.fromMap(Map map) { + return GLACCAddMoneyRequestModel( + porOrgacode: map['porOrgacode'] ?? "", + pctCstycode: map['pctCstycode'] ?? "", + channelCode: map['channelCode'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + drPcaGlaccode: map['drPcaGlaccode'] ?? "", + drPcaGlacdesc: map['drPcaGlacdesc'] ?? "", + crMbmBkmsnumber: map['crMbmBkmsnumber'] ?? "", + crMbmBkmstitle: map['crMbmBkmstitle'] ?? "", + crPcrCurrcode: map['crPcrCurrcode'] ?? "", + crPcrCurrdesc: map['crPcrCurrdesc'] ?? "", + crPcrCurrshort: map['crPcrCurrshort'] ?? "", + sgtGntrnarration: map['sgtGntrnarration'] ?? "", + dmpProdCode: map['dmpProdCode'] ?? "", + transType: map['transType'] ?? "", + notificationId: map['notificationId'] ?? "", + transMode: map['transMode'] ?? "", + sgtGntramtfc: map['sgtGntramtfc'] ?? 0.0, + otdTrancomment: map['otdTrancomment'] ?? "", + obpPincode: map['obpPincode'] ?? "", + pinType: map['pinType'] ?? "", + ); + } +} diff --git a/lib/app/models/GenerateReportRequestModel.dart b/lib/app/models/GenerateReportRequestModel.dart new file mode 100644 index 0000000..2568e14 --- /dev/null +++ b/lib/app/models/GenerateReportRequestModel.dart @@ -0,0 +1,40 @@ +class GenerateReportRequestModel { + final String porOrgacode; + final String mbmBkmsnumber; + final String sgtGntrvaluedatefrom; + final String sgtGntrvaluedateto; + final String type; + + GenerateReportRequestModel({ + required this.porOrgacode, + required this.mbmBkmsnumber, + required this.sgtGntrvaluedatefrom, + required this.sgtGntrvaluedateto, + required this.type, + }); + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'mbmBkmsnumber': mbmBkmsnumber, + 'sgtGntrvaluedatefrom': sgtGntrvaluedatefrom, + 'sgtGntrvaluedateto': sgtGntrvaluedateto, + 'type': type, + }; + } + + factory GenerateReportRequestModel.fromMap(Map map) { + return GenerateReportRequestModel( + porOrgacode: map['porOrgacode'], + mbmBkmsnumber: map['mbmBkmsnumber'], + sgtGntrvaluedatefrom: map['sgtGntrvaluedatefrom'], + sgtGntrvaluedateto: map['sgtGntrvaluedateto'], + type: map['type'], + ); + } + + @override + String toString() { + return 'TransactionHistoryRequest{porOrgacode: $porOrgacode, mbmBkmsnumber: $mbmBkmsnumber, sgtGntrvaluedatefrom: $sgtGntrvaluedatefrom, sgtGntrvaluedateto: $sgtGntrvaluedateto, type: $type}'; + } +} diff --git a/lib/app/models/GlsResponseModel.dart b/lib/app/models/GlsResponseModel.dart new file mode 100644 index 0000000..9a260c2 --- /dev/null +++ b/lib/app/models/GlsResponseModel.dart @@ -0,0 +1,40 @@ +class GlsResponseModel { + String porOrgacode; + String pcaGlaccode; + String pcaGlacdesc; + String pcaGlacshort; + + GlsResponseModel({ + this.porOrgacode = "", + this.pcaGlaccode = "", + this.pcaGlacdesc = "", + this.pcaGlacshort = "", + }); + + factory GlsResponseModel.fromMap(Map map) { + return GlsResponseModel( + porOrgacode: map['porOrgacode'] ?? '', + pcaGlaccode: map['pcaGlaccode'] ?? '', + pcaGlacdesc: map['pcaGlacdesc'] ?? '', + pcaGlacshort: map['pcaGlacshort'] ?? '', + ); + } + + static List fromList(List list) { + return list.map((item) => GlsResponseModel.fromMap(item as Map)).toList(); + } + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'pcaGlaccode': pcaGlaccode, + 'pcaGlacdesc': pcaGlacdesc, + 'pcaGlacshort': pcaGlacshort, + }; + } + + @override + String toString() { + return 'GlsResponseModel{porOrgacode: $porOrgacode, pcaGlaccode: $pcaGlaccode, pcaGlacdesc: $pcaGlacdesc, pcaGlacshort: $pcaGlacshort}'; + } +} diff --git a/lib/app/models/LoginResponseModel.dart b/lib/app/models/LoginResponseModel.dart new file mode 100644 index 0000000..294936c --- /dev/null +++ b/lib/app/models/LoginResponseModel.dart @@ -0,0 +1,87 @@ +import 'dart:convert'; + +LoginResponseModel loginResponseModelFromJson(String str) => LoginResponseModel.fromJson(json.decode(str)); + +String loginResponseModelToJson(LoginResponseModel data) => json.encode(data.toJson()); + +class LoginResponseModel { + final String name; + final String cmpCuststatus; + final dynamic cmpCustlastlogin; + final String cmpCustcode; + final String userRole; + final String jwtToken; + final String refreshToken; + final String cmpCustImage; + final bool isKycVerified; + final bool isTranPinSet; + + LoginResponseModel({ + required this.name, + required this.cmpCuststatus, + required this.cmpCustlastlogin, + required this.cmpCustcode, + required this.userRole, + required this.jwtToken, + required this.refreshToken, + required this.cmpCustImage, + required this.isKycVerified, + required this.isTranPinSet, + }); + + LoginResponseModel copyWith({ + String? name, + String? cmpCuststatus, + dynamic cmpCustlastlogin, + String? cmpCustcode, + String? userRole, + String? jwtToken, + String? refreshToken, + String? cmpCustImage, + bool? isKycVerified, + bool? isTranPinSet, + }) => + LoginResponseModel( + name: name ?? this.name, + cmpCuststatus: cmpCuststatus ?? this.cmpCuststatus, + cmpCustlastlogin: cmpCustlastlogin ?? this.cmpCustlastlogin, + cmpCustcode: cmpCustcode ?? this.cmpCustcode, + userRole: userRole ?? this.userRole, + jwtToken: jwtToken ?? this.jwtToken, + refreshToken: refreshToken ?? this.refreshToken, + cmpCustImage: cmpCustImage ?? this.cmpCustImage, + isKycVerified: isKycVerified ?? this.isKycVerified, + isTranPinSet: isTranPinSet ?? this.isTranPinSet, + ); + + factory LoginResponseModel.fromJson(Map json) => LoginResponseModel( + name: json["name"], + cmpCuststatus: json["cmpCuststatus"], + cmpCustlastlogin: json["cmpCustlastlogin"], + cmpCustcode: json["cmpCustcode"], + userRole: json["userRole"], + jwtToken: json["jwtToken"], + refreshToken: json["refreshToken"], + cmpCustImage: json["cmpCustImage"], + isKycVerified: json["isKycVerified"], + isTranPinSet: json["isTranPinSet"], + ); + + Map toJson() => { + "name": name, + "cmpCuststatus": cmpCuststatus, + "cmpCustlastlogin": cmpCustlastlogin, + "cmpCustcode": cmpCustcode, + "userRole": userRole, + "jwtToken": jwtToken, + "refreshToken": refreshToken, + "cmpCustImage": cmpCustImage, + "isKycVerified": isKycVerified, + "isTranPinSet": isTranPinSet, + }; + + @override + String toString() { + return 'LoginResponseModel{name: $name, cmpCuststatus: $cmpCuststatus, cmpCustlastlogin: $cmpCustlastlogin, cmpCustcode: $cmpCustcode, userRole: $userRole, jwtToken: $jwtToken, refreshToken: $refreshToken, cmpCustImage: $cmpCustImage, isKycVerified: $isKycVerified, isTranPinSet: $isTranPinSet}'; + } +} diff --git a/lib/app/models/RefreshToken.dart b/lib/app/models/RefreshToken.dart new file mode 100644 index 0000000..988b286 --- /dev/null +++ b/lib/app/models/RefreshToken.dart @@ -0,0 +1,28 @@ +class RefreshToken { + String refreshToken = ""; + String accessToken = ""; + + RefreshToken({ + this.refreshToken = "", + this.accessToken = "", + }); + + Map toMap() { + return { + 'refreshToken': refreshToken, + 'accessToken': accessToken, + }; + } + + factory RefreshToken.fromMap(Map map) { + return RefreshToken( + refreshToken: map['refreshToken'], + accessToken: map['accessToken'], + ); + } + + @override + String toString() { + return 'RefreshToken{refreshToken: $refreshToken, accessToken: $accessToken}'; + } +} diff --git a/lib/app/models/RegisterRequest.dart b/lib/app/models/RegisterRequest.dart new file mode 100644 index 0000000..499a28c --- /dev/null +++ b/lib/app/models/RegisterRequest.dart @@ -0,0 +1,69 @@ +class RegisterRequest { + String email = ""; + String password = ""; + String username = ""; + String phone = ""; + String name = ""; + String userRole = ""; + String channelCode = ""; + String porOrgacode = ""; + bool isOtpRequired = false; + + RegisterRequest.empty() + : this.email = "", + this.password = "", + this.username = "", + this.phone = "", + this.name = "", + this.userRole = "", + this.channelCode = "", + this.porOrgacode = "", + this.isOtpRequired = false; + + RegisterRequest({ + this.email = "", + this.password = "", + this.username = "", + this.phone = "", + this.name = "", + this.userRole = "", + this.channelCode = "", + this.porOrgacode = "", + this.isOtpRequired = false, + }); + + Map toMap() { + return { + 'email': email, + 'password': password, + 'username': username, + 'phone': phone, + 'name': name, + 'userRole': userRole, + 'channelCode': channelCode, + 'porOrgacode': porOrgacode, + 'isOtpRequired': isOtpRequired, + }; + } + + factory RegisterRequest.fromMap(Map map) { + return RegisterRequest( + email: map['email'], + password: map['password'], + username: map['username'], + phone: map['phone'], + name: map['name'], + userRole: map['userRole'], + channelCode: map['channelCode'], + porOrgacode: map['porOrgacode'], + isOtpRequired: map['isOtpRequired'], + ); + } + + @override + String toString() { + return 'RegisterRequest{email: $email, password: $password, username: $username, phone: $phone, name: $name, userRole: $userRole, channelCode: $channelCode, porOrgacode: $porOrgacode, isOtpRequired: $isOtpRequired}'; + } + + +} diff --git a/lib/app/models/SendTransactionStep1ResponseModel.dart b/lib/app/models/SendTransactionStep1ResponseModel.dart new file mode 100644 index 0000000..2f50aa5 --- /dev/null +++ b/lib/app/models/SendTransactionStep1ResponseModel.dart @@ -0,0 +1,24 @@ +class SendTransactionStep1ResponseModel { + int notificationId = 0; + + SendTransactionStep1ResponseModel({ + this.notificationId = 0, + }); + + factory SendTransactionStep1ResponseModel.fromMap(Map json) { + return SendTransactionStep1ResponseModel( + notificationId: json['notificationId'] ?? 0, + ); + } + + Map toMap() { + return { + 'notificationId': notificationId, + }; + } + + @override + String toString() { + return 'SendTransactionStep1ResponseModel{notificationId: $notificationId}'; + } +} diff --git a/lib/app/models/SignupOtpRequest.dart b/lib/app/models/SignupOtpRequest.dart new file mode 100644 index 0000000..24e35ea --- /dev/null +++ b/lib/app/models/SignupOtpRequest.dart @@ -0,0 +1,62 @@ +class SignupOtpRequest { + String username = ""; + String obpPincode = ""; + String obpPintype = ""; + String email = ""; + String cmpCustcode = ""; + String pctCstycode = ""; + String channelCode = ""; + String porOrgacode = ""; + + SignupOtpRequest({ + this.username = "", + this.obpPincode = "", + this.obpPintype = "", + this.email = "", + this.cmpCustcode = "", + this.pctCstycode = "", + this.channelCode = "", + this.porOrgacode = "", + }); + + SignupOtpRequest.empty() + : this.obpPincode = "", + this.username = "", + this.obpPintype = "", + this.email = "", + this.cmpCustcode = "", + this.pctCstycode = "", + this.channelCode = "", + this.porOrgacode = ""; + + Map toMap() { + return { + 'username': username, + 'obpPincode': this.obpPincode, + 'obpPintype': this.obpPintype, + 'email': this.email, + 'cmpCustcode': this.cmpCustcode, + 'pctCstycode': this.pctCstycode, + 'channelCode': this.channelCode, + 'porOrgacode': this.porOrgacode, + }; + } + + factory SignupOtpRequest.fromMap(Map map) { + return SignupOtpRequest( + username: map['username'], + obpPincode: map['obpPincode'] ?? "", + obpPintype: map['obpPintype'] ?? "", + email: map['email'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + pctCstycode: map['pctCstycode'] ?? "", + channelCode: map['channelCode'] ?? "", + porOrgacode: map['porOrgacode'] ?? "", + ); + } + + @override + String toString() { + return 'SignupOtpRequest{obpPincode: $obpPincode, username: $username, obpPintype: $obpPintype, email: $email, cmpCustcode: $cmpCustcode, pctCstycode: $pctCstycode, channelCode: $channelCode, porOrgacode: $porOrgacode}'; + } +} diff --git a/lib/app/models/SignupStep3RequestModel.dart b/lib/app/models/SignupStep3RequestModel.dart new file mode 100644 index 0000000..a801b1a --- /dev/null +++ b/lib/app/models/SignupStep3RequestModel.dart @@ -0,0 +1,97 @@ +class SignupStep3RequestModel { + String username = ""; + String email = ""; + String phone = ""; + String name = ""; + String address = ""; + String identificationType = ""; + String identificationNumber = ""; + bool isKycAdded = false; + String kycType = ""; + String kycDocumentId1 = ""; + String kycDocumentId2 = ""; + String userRole = ""; + String channelCode = ""; + String porOrgacode = ""; + String dmpProdcode = ""; + + SignupStep3RequestModel.empty() + : this.username = "", + this.email = "", + this.phone = "", + this.name = "", + this.address = "", + this.identificationType = "", + this.identificationNumber = "", + this.isKycAdded = false, + this.kycType = "", + this.kycDocumentId1 = "", + this.kycDocumentId2 = "", + this.userRole = "", + this.channelCode = "", + this.porOrgacode = "", + this.dmpProdcode = ""; + + SignupStep3RequestModel({ + this.username = "", + this.email = "", + this.phone = "", + this.name = "", + this.address = "", + this.identificationType = "", + this.identificationNumber = "", + this.isKycAdded = false, + this.kycType = "", + this.kycDocumentId1 = "", // base64 encoded + this.kycDocumentId2 = "", // base64 encoded + this.userRole = "", + this.channelCode = "", + this.porOrgacode = "", + this.dmpProdcode = "", + }); + + Map toMap() { + return { + 'username': username, + 'email': email, + 'phone': phone, + 'name': name, + 'address': address, + 'identificationType': identificationType, + 'identificationNumber': identificationNumber, + 'isKycAdded': isKycAdded, + 'kycType': kycType, + 'kycDocumentId1': kycDocumentId1, + 'kycDocumentId2': kycDocumentId2, + 'userRole': userRole, + 'channelCode': channelCode, + 'porOrgacode': porOrgacode, + "dmpProdcode": dmpProdcode + }; + } + + factory SignupStep3RequestModel.fromMap(Map map) { + return SignupStep3RequestModel( + username: map['username'] ?? "", + email: map['email'] ?? "", + phone: map['phone'] ?? "", + name: map['name'] ?? "", + address: map['address'] ?? "", + identificationType: map['identificationType'] ?? "", + identificationNumber: map['identificationNumber'] ?? "", + isKycAdded: map['isKycAdded'] ?? false, + kycType: map['kycType'] ?? "", + kycDocumentId1: map['kycDocumentId1'] ?? "", + kycDocumentId2: map['kycDocumentId2'] ?? "", + userRole: map['userRole'] ?? "", + channelCode: map['channelCode'] ?? "", + porOrgacode: map['porOrgacode'] ?? "", + dmpProdcode: map["dmpProdcode"] ?? "", + ); + } + + @override + String toString() { + return 'SignupStep3RequestModel{username: $username, email: $email, phone: $phone, name: $name, address: $address, identificationType: $identificationType, identificationNumber: $identificationNumber, isKycAdded: $isKycAdded, kycType: $kycType, kycDocumentId1: $kycDocumentId1, kycDocumentId2: $kycDocumentId2, userRole: $userRole, channelCode: $channelCode, porOrgacode: $porOrgacode}'; + } +} diff --git a/lib/app/models/SubmitTransactionRequestModel.dart b/lib/app/models/SubmitTransactionRequestModel.dart new file mode 100644 index 0000000..8092533 --- /dev/null +++ b/lib/app/models/SubmitTransactionRequestModel.dart @@ -0,0 +1,50 @@ +class SubmitTransactionRequestModel { + final String porOrgacode; + final String pctCstycode; + final String channelCode; + final String cmpCustcode; + final String obpPincode; + final String otdTrancomment; + final String otdTranrequestid; + + SubmitTransactionRequestModel({ + required this.porOrgacode, + required this.pctCstycode, + required this.channelCode, + required this.cmpCustcode, + required this.obpPincode, + required this.otdTrancomment, + required this.otdTranrequestid, + }); + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'pctCstycode': pctCstycode, + 'channelCode': channelCode, + 'cmpCustcode': cmpCustcode, + 'obpPincode': obpPincode, + 'otdTrancomment': otdTrancomment, + 'otdTranrequestid': otdTranrequestid, + }; + } + + factory SubmitTransactionRequestModel.fromMap(Map map) { + return SubmitTransactionRequestModel( + porOrgacode: map['porOrgacode'], + pctCstycode: map['pctCstycode'], + channelCode: map['channelCode'], + cmpCustcode: map['cmpCustcode'], + obpPincode: map['obpPincode'], + otdTrancomment: map['otdTrancomment'], + otdTranrequestid: map['otdTranrequestid'], + ); + } + + @override + String toString() { + return 'TransactionRequestModel{porOrgacode: $porOrgacode, pctCstycode: $pctCstycode, ' + 'channelCode: $channelCode, cmpCustcode: $cmpCustcode, obpPincode: $obpPincode, ' + 'otdTrancomment: $otdTrancomment, otdTranrequestid: $otdTranrequestid}'; + } +} diff --git a/lib/app/models/SubmitTransactionResponseModel.dart b/lib/app/models/SubmitTransactionResponseModel.dart new file mode 100644 index 0000000..e8ee18a --- /dev/null +++ b/lib/app/models/SubmitTransactionResponseModel.dart @@ -0,0 +1,28 @@ +import 'dart:convert'; + +SubmitTransactionResponseModel submitTransactionResponseModelFromJson(String str) => SubmitTransactionResponseModel.fromJson(json.decode(str)); + +String submitTransactionResponseModelToJson(SubmitTransactionResponseModel data) => json.encode(data.toJson()); + +class SubmitTransactionResponseModel { + final String tranId; + + SubmitTransactionResponseModel({ + required this.tranId, + }); + + SubmitTransactionResponseModel copyWith({ + String? tranId, + }) => + SubmitTransactionResponseModel( + tranId: tranId ?? this.tranId, + ); + + factory SubmitTransactionResponseModel.fromJson(Map json) => SubmitTransactionResponseModel( + tranId: json["tranID"], + ); + + Map toJson() => { + "tranID": tranId, + }; +} diff --git a/lib/app/models/TransactionHistoryRequest.dart b/lib/app/models/TransactionHistoryRequest.dart new file mode 100644 index 0000000..ce18e29 --- /dev/null +++ b/lib/app/models/TransactionHistoryRequest.dart @@ -0,0 +1,40 @@ +class TransactionHistoryRequest { + String porOrgacode = ""; + String mbmBkmsnumber = ""; + String sgtGntrvaluedatefrom = ""; + String sgtGntrvaluedateto = ""; + String type = ""; + + TransactionHistoryRequest({ + this.porOrgacode = "", + this.mbmBkmsnumber = "", + this.sgtGntrvaluedatefrom = "", + this.sgtGntrvaluedateto = "", + this.type = "", + }); + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'mbmBkmsnumber': mbmBkmsnumber, + 'sgtGntrvaluedatefrom': sgtGntrvaluedatefrom, + 'sgtGntrvaluedateto': sgtGntrvaluedateto, + 'type': type, + }; + } + + factory TransactionHistoryRequest.fromMap(Map map) { + return TransactionHistoryRequest( + porOrgacode: map['porOrgacode'] ?? '', + mbmBkmsnumber: map['mbmBkmsnumber'] ?? '', + sgtGntrvaluedatefrom: map['sgtGntrvaluedatefrom'] ?? '', + sgtGntrvaluedateto: map['sgtGntrvaluedateto'] ?? '', + type: map['type'] ?? 'pdf', + ); + } + + @override + String toString() { + return 'TransactionHistoryRequest{porOrgacode: $porOrgacode, mbmBkmsnumber: $mbmBkmsnumber, sgtGntrvaluedatefrom: $sgtGntrvaluedatefrom, sgtGntrvaluedateto: $sgtGntrvaluedateto, type: $type}'; + } +} diff --git a/lib/app/models/TransactionPinRequestModel.dart b/lib/app/models/TransactionPinRequestModel.dart new file mode 100644 index 0000000..921f013 --- /dev/null +++ b/lib/app/models/TransactionPinRequestModel.dart @@ -0,0 +1,61 @@ +class TransactionPinRequestModel { + String porOrgacode = ""; + String pctCstycode = ""; + String channelCode = ""; + String cmpCustcode = ""; + String email = ""; + String pinType = ""; + String transPincode = ""; + bool isOtpRequired = false; + + TransactionPinRequestModel({ + this.porOrgacode = "", + this.pctCstycode = "", + this.channelCode = "", + this.cmpCustcode = "", + this.email = "", + this.pinType = "", + this.transPincode = "", + this.isOtpRequired = false, + }); + TransactionPinRequestModel.empty():this.porOrgacode = "", + this.pctCstycode = "", + this.channelCode = "", + this.cmpCustcode = "", + this.email = "", + this.pinType = "", + this.transPincode = "", + this.isOtpRequired = false; + + factory TransactionPinRequestModel.fromMap(Map map) { + return TransactionPinRequestModel( + porOrgacode: map['porOrgacode'] ?? "", + pctCstycode: map['pctCstycode'] ?? "", + channelCode: map['channelCode'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + email: map['email'] ?? "", + pinType: map['pinType'] ?? "", + transPincode: map['transPincode'] ?? "", + isOtpRequired: map['isOtpRequired'] ?? false, + ); + } + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'pctCstycode': pctCstycode, + 'channelCode': channelCode, + 'cmpCustcode': cmpCustcode, + 'email': email, + 'pinType': pinType, + 'transPincode': transPincode, + 'isOtpRequired': isOtpRequired, + }; + } + + @override + String toString() { + return 'TransactionPinRequestModel{porOrgacode: $porOrgacode, pctCstycode: $pctCstycode, channelCode: $channelCode, cmpCustcode: $cmpCustcode, email: $email, pinType: $pinType, transPincode: $transPincode, isOtpRequired: $isOtpRequired}'; + } +} + diff --git a/lib/app/models/TransactionPinResponseModel.dart b/lib/app/models/TransactionPinResponseModel.dart new file mode 100644 index 0000000..89c8669 --- /dev/null +++ b/lib/app/models/TransactionPinResponseModel.dart @@ -0,0 +1,28 @@ +class TransactionPinResponseModel { + double otdTranrequestid = 0.0; + String pinCode = ""; + + TransactionPinResponseModel({ + this.otdTranrequestid = 0, + this.pinCode = "", + }); + + Map toMap() { + return { + 'otdTranrequestid': otdTranrequestid, + 'pinCode': pinCode, + }; + } + + factory TransactionPinResponseModel.fromMap(Map map) { + return TransactionPinResponseModel( + otdTranrequestid: map['otdTranrequestid'] ?? 0, + pinCode: map['pinCode'] ?? '', + ); + } + + @override + String toString() { + return 'TransactionPinResponseModel{otdTranrequestid: $otdTranrequestid, pinCode: $pinCode}'; + } +} diff --git a/lib/app/models/TransactionRequestModel.dart b/lib/app/models/TransactionRequestModel.dart new file mode 100644 index 0000000..35d09f9 --- /dev/null +++ b/lib/app/models/TransactionRequestModel.dart @@ -0,0 +1,56 @@ +class TransactionRequestModel { + String porOrgacode = ""; + String pctCstycode = ""; + String channelCode = ""; + String cmpCustcode = ""; + String obpPincode = ""; + String otdTrancomment = ""; + String otdTranrequestid = ""; + + TransactionRequestModel({ + this.porOrgacode = "", + this.pctCstycode = "", + this.channelCode = "", + this.cmpCustcode = "", + this.obpPincode = "", + this.otdTrancomment = "", + this.otdTranrequestid = "", + }); + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'pctCstycode': pctCstycode, + 'channelCode': channelCode, + 'cmpCustcode': cmpCustcode, + 'obpPincode': obpPincode, + 'otdTrancomment': otdTrancomment, + 'otdTranrequestid': otdTranrequestid, + }; + } + + factory TransactionRequestModel.fromMap(Map map) { + return TransactionRequestModel( + porOrgacode: map['porOrgacode'] ?? '', + pctCstycode: map['pctCstycode'] ?? '', + channelCode: map['channelCode'] ?? '', + cmpCustcode: map['cmpCustcode'] ?? '', + obpPincode: map['obpPincode'] ?? '', + otdTrancomment: map['otdTrancomment'] ?? '', + otdTranrequestid: map['otdTranrequestid'] ?? '', + ); + } + + @override + String toString() { + return 'TransactionRequestModel{' + 'porOrgacode: $porOrgacode, ' + 'pctCstycode: $pctCstycode, ' + 'channelCode: $channelCode, ' + 'cmpCustcode: $cmpCustcode, ' + 'obpPincode: $obpPincode, ' + 'otdTrancomment: $otdTrancomment, ' + 'otdTranrequestid: $otdTranrequestid' + '}'; + } +} diff --git a/lib/app/models/TransactionResponseModel.dart b/lib/app/models/TransactionResponseModel.dart new file mode 100644 index 0000000..131ed32 --- /dev/null +++ b/lib/app/models/TransactionResponseModel.dart @@ -0,0 +1,22 @@ +class TransactionResponseModel { + String tranID = ""; + + TransactionResponseModel({this.tranID = ""}); + + Map toMap() { + return { + 'tranID': tranID, + }; + } + + factory TransactionResponseModel.fromMap(Map map) { + return TransactionResponseModel( + tranID: map['tranID'], + ); + } + + @override + String toString() { + return 'TransactionResponseModel{tranID: $tranID}'; + } +} diff --git a/lib/app/models/TransactionSubmitRequestModel.dart b/lib/app/models/TransactionSubmitRequestModel.dart new file mode 100644 index 0000000..9a5e203 --- /dev/null +++ b/lib/app/models/TransactionSubmitRequestModel.dart @@ -0,0 +1,147 @@ +class TransactionSubmitRequestModel { + String porOrgacode = ""; + String pctCstycode = ""; + String channelCode = ""; + String cmpCustcode = ""; + String drMbmBkmsnumber = ""; + String cmpRefcode = ""; + String drMbmBkmstitle = ""; + String drPcrCurrcode = ""; + String drPcrCurrdesc = ""; + String drPcrCurrshort = ""; + String crMbmBkmsnumber = ""; + String crMbmBkmstitle = ""; + String crPcrCurrcode = ""; + String crPcrCurrdesc = ""; + String crPcrCurrshort = ""; + String sgtGntrnarration = ""; + String dmpProdCode = ""; + String transType = ""; + String notificationId = ""; + String transMode = ""; + double sgtGntramtfc = 0; + String otdTrancomment = ""; + String pinType = ""; + String obpPincode = ""; + bool isOtpRequired = false; + + TransactionSubmitRequestModel({ + this.porOrgacode = "", + this.pctCstycode = "", + this.cmpRefcode = "", + this.channelCode = "", + this.cmpCustcode = "", + this.drMbmBkmsnumber = "", + this.drMbmBkmstitle = "", + this.drPcrCurrcode = "", + this.drPcrCurrdesc = "", + this.drPcrCurrshort = "", + this.crMbmBkmsnumber = "", + this.crMbmBkmstitle = "", + this.crPcrCurrcode = "", + this.crPcrCurrdesc = "", + this.crPcrCurrshort = "", + this.sgtGntrnarration = "", + this.dmpProdCode = "", + this.transType = "", + this.notificationId = "", + this.transMode = "", + this.sgtGntramtfc = 0, + this.otdTrancomment = "", + this.pinType = "", + this.obpPincode = "", + this.isOtpRequired = false, + }); + + TransactionSubmitRequestModel.empty() + : this.porOrgacode = "", + this.pctCstycode = "", + this.channelCode = "", + this.cmpRefcode = "", + this.cmpCustcode = "", + this.drMbmBkmsnumber = "", + this.drMbmBkmstitle = "", + this.drPcrCurrcode = "", + this.drPcrCurrdesc = "", + this.drPcrCurrshort = "", + this.crMbmBkmsnumber = "", + this.crMbmBkmstitle = "", + this.crPcrCurrcode = "", + this.crPcrCurrdesc = "", + this.crPcrCurrshort = "", + this.sgtGntrnarration = "", + this.dmpProdCode = "", + this.transType = "", + this.notificationId = "", + this.transMode = "", + this.sgtGntramtfc = 0, + this.otdTrancomment = "", + this.pinType = "", + this.obpPincode = "", + this.isOtpRequired = false; + + factory TransactionSubmitRequestModel.fromMap(Map json) { + return TransactionSubmitRequestModel( + porOrgacode: json['porOrgacode'] ?? "", + pctCstycode: json['pctCstycode'] ?? "", + channelCode: json['channelCode'] ?? "", + cmpCustcode: json['cmpCustcode'] ?? "", + cmpRefcode: json['cmpRefcode'] ?? "", + drMbmBkmsnumber: json['drMbmBkmsnumber'] ?? "", + drMbmBkmstitle: json['drMbmBkmstitle'] ?? "", + drPcrCurrcode: json['drPcrCurrcode'] ?? "", + drPcrCurrdesc: json['drPcrCurrdesc'] ?? "", + drPcrCurrshort: json['drPcrCurrshort'] ?? "", + crMbmBkmsnumber: json['crMbmBkmsnumber'] ?? "", + crMbmBkmstitle: json['crMbmBkmstitle'] ?? "", + crPcrCurrcode: json['crPcrCurrcode'] ?? "", + crPcrCurrdesc: json['crPcrCurrdesc'] ?? "", + crPcrCurrshort: json['crPcrCurrshort'] ?? "", + sgtGntrnarration: json['sgtGntrnarration'] ?? "", + dmpProdCode: json['dmpProdCode'] ?? "", + transType: json['transType'] ?? "", + notificationId: json['notificationId'] ?? "", + transMode: json['transMode'] ?? "", + sgtGntramtfc: json['sgtGntramtfc'] ?? 0.0, + otdTrancomment: json['otdTrancomment'] ?? "", + pinType: json['pinType'] ?? "", + obpPincode: json['obpPincode'] ?? "", + isOtpRequired: json['isOtpRequired'] ?? false, + ); + } + + Map toMap() { + return { + 'porOrgacode': porOrgacode, + 'pctCstycode': pctCstycode, + 'channelCode': channelCode, + 'cmpRefcode': cmpRefcode, + 'cmpCustcode': cmpCustcode, + 'drMbmBkmsnumber': drMbmBkmsnumber, + 'drMbmBkmstitle': drMbmBkmstitle, + 'drPcrCurrcode': drPcrCurrcode, + 'drPcrCurrdesc': drPcrCurrdesc, + 'drPcrCurrshort': drPcrCurrshort, + 'crMbmBkmsnumber': crMbmBkmsnumber, + 'crMbmBkmstitle': crMbmBkmstitle, + 'crPcrCurrcode': crPcrCurrcode, + 'crPcrCurrdesc': crPcrCurrdesc, + 'crPcrCurrshort': crPcrCurrshort, + 'sgtGntrnarration': sgtGntrnarration, + 'dmpProdCode': dmpProdCode, + 'transType': transType, + 'notificationId': notificationId, + 'transMode': transMode, + 'sgtGntramtfc': sgtGntramtfc, + 'otdTrancomment': otdTrancomment, + 'pinType': pinType, + 'obpPincode': obpPincode, + 'isOtpRequired': isOtpRequired, + }; + } + + @override + String toString() { + return 'TransactionSubmitRequestModel{porOrgacode: $porOrgacode, pctCstycode: $pctCstycode, channelCode: $channelCode, cmpCustcode: $cmpCustcode, drMbmBkmsnumber: $drMbmBkmsnumber, cmpRefcode: $cmpRefcode, drMbmBkmstitle: $drMbmBkmstitle, drPcrCurrcode: $drPcrCurrcode, drPcrCurrdesc: $drPcrCurrdesc, drPcrCurrshort: $drPcrCurrshort, crMbmBkmsnumber: $crMbmBkmsnumber, crMbmBkmstitle: $crMbmBkmstitle, crPcrCurrcode: $crPcrCurrcode, crPcrCurrdesc: $crPcrCurrdesc, crPcrCurrshort: $crPcrCurrshort, sgtGntrnarration: $sgtGntrnarration, dmpProdCode: $dmpProdCode, transType: $transType, notificationId: $notificationId, transMode: $transMode, sgtGntramtfc: $sgtGntramtfc, otdTrancomment: $otdTrancomment, pinType: $pinType, obpPincode: $obpPincode, isOtpRequired: $isOtpRequired}'; + } +} diff --git a/lib/app/models/TransactionSubmitResponseModel.dart b/lib/app/models/TransactionSubmitResponseModel.dart new file mode 100644 index 0000000..9b4cbf9 --- /dev/null +++ b/lib/app/models/TransactionSubmitResponseModel.dart @@ -0,0 +1,26 @@ +class TransactionSubmitResponseModel { + double mbmBkmsbalance = 0.0; + + TransactionSubmitResponseModel({ + this.mbmBkmsbalance = 0.0, + }); + + TransactionSubmitResponseModel.empty() : this.mbmBkmsbalance = 0.0; + + factory TransactionSubmitResponseModel.fromMap(Map json) { + return TransactionSubmitResponseModel( + mbmBkmsbalance: json['mbmBkmsbalance'] ?? 0.0, + ); + } + + Map toMap() { + return { + 'mbmBkmsbalance': mbmBkmsbalance, + }; + } + + @override + String toString() { + return 'TransactionSubmitResponseModel{mbmBkmsbalance: $mbmBkmsbalance}'; + } +} diff --git a/lib/app/models/UserActivity.dart b/lib/app/models/UserActivity.dart new file mode 100644 index 0000000..7220a39 --- /dev/null +++ b/lib/app/models/UserActivity.dart @@ -0,0 +1,48 @@ +class UserActivity { + int id; + String porOrgacode; + String cmpCustcode; + DateTime date; + String channel; + String deviceName; + String activity; + + UserActivity({ + required this.id, + required this.porOrgacode, + required this.cmpCustcode, + required this.date, + required this.channel, + required this.deviceName, + required this.activity, + }); + + Map toMap() { + return { + 'id': id, + 'porOrgacode': porOrgacode, + 'cmpCustcode': cmpCustcode, + 'date': date.toIso8601String(), + 'channel': channel, + 'deviceName': deviceName, + 'activity': activity, + }; + } + + factory UserActivity.fromMap(Map map) { + return UserActivity( + id: map['id'] ?? '', + porOrgacode: map['porOrgacode'] ?? '', + cmpCustcode: map['cmpCustcode'] ?? '', + date: DateTime.parse(map['date'] ?? ''), + channel: map['channel'] ?? '01', + deviceName: map['deviceName'] ?? '', + activity: map['activity'] ?? '', + ); + } + + @override + String toString() { + return 'LoginActivity{id: $id, porOrgacode: $porOrgacode, cmpCustcode: $cmpCustcode, date: $date, channel: $channel, deviceName: $deviceName, activity: $activity}'; + } +} diff --git a/lib/app/models/UserActivityResponseModel.dart b/lib/app/models/UserActivityResponseModel.dart new file mode 100644 index 0000000..03e2ece --- /dev/null +++ b/lib/app/models/UserActivityResponseModel.dart @@ -0,0 +1,19 @@ +import 'UserActivity.dart'; + +class UserActivityResponseModel { + List userActivity = []; + + UserActivityResponseModel({required this.userActivity}); + + factory UserActivityResponseModel.fromMap(dynamic list) { + return UserActivityResponseModel( + userActivity: List.from( + list.map((map) => UserActivity.fromMap(map)), + ), + ); + } + + List> toMap() { + return userActivity.map((transaction) => transaction.toMap()).toList(); + } +} \ No newline at end of file diff --git a/lib/app/models/UserInfo.dart b/lib/app/models/UserInfo.dart new file mode 100644 index 0000000..73382b4 --- /dev/null +++ b/lib/app/models/UserInfo.dart @@ -0,0 +1,51 @@ +import 'package:flutter/cupertino.dart'; +import 'package:get/get.dart'; +import 'package:json_annotation/json_annotation.dart'; + +// @JsonSerializable(includeIfNull: false) + + +class UserInfo { + String name; + String userRole; + String porOrgacode; + String pctCstycode; + String plcLocalcode; + String channelCode; + String cmpCustpassword; + String newCustpassword; + String cmpCustcode; + String cmpUserId; + String cmpCuststatus; + String jwtToken; + String refreshToken; + bool isKycVerified; + bool isTranPinSet; + String cmpCustlastlogin; + + + UserInfo({ + this.name = '', + this.refreshToken = '', + this.userRole = '', + this.cmpCustcode = '', + this.isKycVerified = false, + this.isTranPinSet = false, + this.cmpUserId = '', + this.porOrgacode = '', + this.channelCode = '', + /* this.cmpAccountno = ''*/ this.cmpCustlastlogin = '', + this.cmpCustpassword = '', + this.cmpCuststatus = '', + /* this.cmpFirstname = '', this.cmpIdennumber = '', this.cmpLastname = '', this.cmpUserIdType = ''*/ this.jwtToken = '', + this.newCustpassword = '', + /*this.obpPincode = '',*/ this.pctCstycode = '', + /* this.phoneNo = '',*/ this.plcLocalcode = '', + /*this.token = ''*/ + }); + + @override + String toString() { + return 'UserInfo{name: $name, userRole: $userRole, porOrgacode: $porOrgacode, pctCstycode: $pctCstycode, plcLocalcode: $plcLocalcode, channelCode: $channelCode, cmpCustpassword: $cmpCustpassword, newCustpassword: $newCustpassword, cmpCustcode: $cmpCustcode, cmpUserId: $cmpUserId, cmpCuststatus: $cmpCuststatus, jwtToken: $jwtToken, refreshToken: $refreshToken, isKycVerified: $isKycVerified, isTranPinSet: $isTranPinSet, cmpCustlastlogin: $cmpCustlastlogin}'; + } +} diff --git a/lib/app/models/VerifyLoginOtpRequest.dart b/lib/app/models/VerifyLoginOtpRequest.dart new file mode 100644 index 0000000..6749c75 --- /dev/null +++ b/lib/app/models/VerifyLoginOtpRequest.dart @@ -0,0 +1,40 @@ +class VerifyLoginOtpRequest { + String email = ""; + String password = ""; + String channelCode = ""; + String porOrgacode = ""; + String obpPincode = ""; + + VerifyLoginOtpRequest({ + this.email = "", + this.password = "", + this.channelCode = "", + this.porOrgacode = "", + this.obpPincode = "", + }); + + Map toMap() { + return { + 'email': this.email, + 'password': this.password, + 'channelCode': this.channelCode, + 'porOrgacode': this.porOrgacode, + 'obpPincode': this.obpPincode, + }; + } + + factory VerifyLoginOtpRequest.fromMap(Map map) { + return VerifyLoginOtpRequest( + email: map['email'] ?? "", + password: map['password'] ?? "", + channelCode: map['channelCode'] ?? "", + porOrgacode: map['porOrgacode'] ?? "", + obpPincode: map['obpPincode'] ?? "", + ); + } + + @override + String toString() { + return 'VerifyLoginOtpRequest{email: $email, password: $password, channelCode: $channelCode, porOrgacode: $porOrgacode, obpPincode: $obpPincode}'; + } +} diff --git a/lib/app/models/VerifySignupOtpRequest.dart b/lib/app/models/VerifySignupOtpRequest.dart new file mode 100644 index 0000000..b52fe3a --- /dev/null +++ b/lib/app/models/VerifySignupOtpRequest.dart @@ -0,0 +1,52 @@ +class VerifySignupOtpRequest { + String username = ""; + String email = ""; + String phone = ""; + String channelCode = ""; + String porOrgacode = ""; + String obpPincode = ""; + + VerifySignupOtpRequest({ + this.username = "", + this.email = "", + this.phone = "", + this.channelCode = "", + this.porOrgacode = "", + this.obpPincode = "", + }); + + VerifySignupOtpRequest.empty() + : this.username = "", + this.email = "", + this.phone = "", + this.channelCode = "", + this.porOrgacode = "", + this.obpPincode = ""; + + Map toMap() { + return { + 'username': username, + 'email': email, + 'phone': phone, + 'channelCode': channelCode, + 'porOrgacode': porOrgacode, + 'obpPincode': obpPincode, + }; + } + + factory VerifySignupOtpRequest.fromMap(Map map) { + return VerifySignupOtpRequest( + username: map['username'], + email: map['email'], + phone: map['phone'], + channelCode: map['channelCode'], + porOrgacode: map['porOrgacode'], + obpPincode: map['obpPincode'], + ); + } + + @override + String toString() { + return 'VerifySignupOtpRequest{username: $username, email: $email, phone: $phone, channelCode: $channelCode, porOrgacode: $porOrgacode, obpPincode: $obpPincode}'; + } +} diff --git a/lib/app/models/ViewBalanceRequestModel.dart b/lib/app/models/ViewBalanceRequestModel.dart new file mode 100644 index 0000000..c8e2cd1 --- /dev/null +++ b/lib/app/models/ViewBalanceRequestModel.dart @@ -0,0 +1,25 @@ +class ViewBalanceRequestModel { + String cmpCustcode = ""; + String mbmBkmsNumber = ""; + + ViewBalanceRequestModel({this.cmpCustcode = "", this.mbmBkmsNumber = ""}); + + Map toMap() { + return { + 'cmpCustcode': cmpCustcode, + 'mbmBkmsNumber': mbmBkmsNumber, + }; + } + + factory ViewBalanceRequestModel.fromMap(Map map) { + return ViewBalanceRequestModel( + cmpCustcode: map['cmpCustcode'], + mbmBkmsNumber: map['mbmBkmsNumber'], + ); + } + + @override + String toString() { + return 'ViewBalanceRequestModel{cmpCustcode: $cmpCustcode, mbmBkmsNumber: $mbmBkmsNumber}'; + } +} diff --git a/lib/app/models/ViewBalanceResponseModel.dart b/lib/app/models/ViewBalanceResponseModel.dart new file mode 100644 index 0000000..150afc2 --- /dev/null +++ b/lib/app/models/ViewBalanceResponseModel.dart @@ -0,0 +1,22 @@ +class ViewBalanceResponseModel { + String mbmBkmsbalance = ""; + + ViewBalanceResponseModel({this.mbmBkmsbalance = ""}); + + Map toMap() { + return { + 'mbmBkmsbalance': mbmBkmsbalance, + }; + } + + factory ViewBalanceResponseModel.fromMap(Map map) { + return ViewBalanceResponseModel( + mbmBkmsbalance: map['mbmBkmsbalance'], + ); + } + + @override + String toString() { + return 'ViewBalanceResponseModel{mbmBkmsbalance: $mbmBkmsbalance}'; + } +} diff --git a/lib/app/models/accept_receive_transaction.dart b/lib/app/models/accept_receive_transaction.dart new file mode 100644 index 0000000..05f0e36 --- /dev/null +++ b/lib/app/models/accept_receive_transaction.dart @@ -0,0 +1,46 @@ +class AcceptReceiveTransactionModel { + int id; + String cmpTranpin; + bool isAccepted; + String cmpCustcode; + String cmpRefcode; + String porOrgacode; + + AcceptReceiveTransactionModel({ + required this.id, + required this.cmpTranpin, + required this.isAccepted, + required this.cmpCustcode, + required this.cmpRefcode, + required this.porOrgacode, + }); + + /// Convert object to a Map + Map toMap() { + return { + 'id': id, + 'cmpTranpin': cmpTranpin, + 'isAccepted': isAccepted, + 'cmpCustcode': cmpCustcode, + 'cmpRefcode': cmpRefcode, + 'porOrgacode': porOrgacode, + }; + } + + /// Create object from a Map + factory AcceptReceiveTransactionModel.fromMap(Map map) { + return AcceptReceiveTransactionModel( + id: map['id'], + cmpTranpin: map['cmpTranpin'], + isAccepted: map['isAccepted'], + cmpCustcode: map['cmpCustcode'], + cmpRefcode: map['cmpRefcode'], + porOrgacode: map['porOrgacode'], + ); + } + + @override + String toString() { + return 'AcceptReceiveTransactionModel{id: $id, cmpTranpin: $cmpTranpin, isAccepted: $isAccepted, cmpCustcode: $cmpCustcode, cmpRefcode: $cmpRefcode, porOrgacode: $porOrgacode}'; + } +} diff --git a/lib/app/models/accountStatementResponseModel.dart b/lib/app/models/accountStatementResponseModel.dart new file mode 100644 index 0000000..0ca898d --- /dev/null +++ b/lib/app/models/accountStatementResponseModel.dart @@ -0,0 +1,125 @@ +class AccountStatementResponseModel { + int id = 0; + String porOrgacode = ""; + String drMbmBkmsnumber = ""; + String sgtReceiveNodeId = ""; + String sgtSentNodeId = ""; + bool batAcnttranReversed = false; + String crMbmBkmsnumber = ""; + String dmpProdcode = ""; + double crMbmBkmsbalance = 0.0; + double drMbmBkmsbalance = 0.0; + String drmbmBkmstitle = ""; + String cmpCustcode = ""; + String crMbmBkmstitle = ""; + String sgtSentGntrnumber = ""; + String drSgtGntrdate = ""; + String? crSgtGntrdate = ""; + double sgtGntramt = 0.0; + bool batAcnttranSend = false; + bool batAcnttranReceived = false; + String? sgtReceiveGntrnumber = ""; + String drpcrCurrdesc = ""; + String drPcrCurrcode = ""; + String drPcrCurrshort = ""; + String crPcrCurrdesc = ""; + String crPcrCurrcode = ""; + String crPcrCurrshort = ""; + + AccountStatementResponseModel({this.id = 0, this.porOrgacode = "", this.sgtReceiveNodeId = "" ,this.batAcnttranReversed = false, this.sgtSentNodeId ="",this.drMbmBkmsnumber = "", this.crMbmBkmsnumber = "", this.dmpProdcode = "", this.crMbmBkmsbalance = 0.0, this.drMbmBkmsbalance = 0.0, this.drmbmBkmstitle = "", this.cmpCustcode = "", this.crMbmBkmstitle = "", this.sgtSentGntrnumber = "", this.drSgtGntrdate = "", this.crSgtGntrdate = "", this.sgtGntramt = 0.0, this.batAcnttranSend = false, this.batAcnttranReceived = false, this.sgtReceiveGntrnumber = "", this.drpcrCurrdesc = "", this.drPcrCurrcode = "", this.drPcrCurrshort = "", this.crPcrCurrdesc = "", this.crPcrCurrcode = "", this.crPcrCurrshort = ""}); + + AccountStatementResponseModel.empty() + : this.id = 0, + this.porOrgacode = "", + this.drMbmBkmsnumber = "", + this.crMbmBkmsnumber = "", + this.sgtReceiveNodeId = "", + this.sgtSentNodeId = "", + this.batAcnttranReversed = false, + this.dmpProdcode = "", + this.crMbmBkmsbalance = 0.0, + this.drMbmBkmsbalance = 0.0, + this.drmbmBkmstitle = "", + this.batAcnttranSend = false, + this.cmpCustcode = "", + this.crMbmBkmstitle = "", + this.sgtSentGntrnumber = "", + this.drSgtGntrdate = "", + this.crSgtGntrdate = "", + this.sgtGntramt = 0.0, + this.batAcnttranReceived = false, + this.sgtReceiveGntrnumber = "", + this.drpcrCurrdesc = "", + this.drPcrCurrcode = "", + this.drPcrCurrshort = "", + this.crPcrCurrdesc = "", + this.crPcrCurrcode = "", + this.crPcrCurrshort = ""; + + Map toMap() { + return { + 'id': this.id, + 'porOrgacode': this.porOrgacode, + 'drMbmBkmsnumber': this.drMbmBkmsnumber, + 'sgtReceiveNodeId': this.sgtReceiveNodeId, + 'sgtSentNodeId': this.sgtSentNodeId, + 'batAcnttranReversed': this.batAcnttranReversed, + 'crMbmBkmsnumber': this.crMbmBkmsnumber, + 'dmpProdcode': this.dmpProdcode, + 'crMbmBkmsbalance': this.crMbmBkmsbalance, + 'drMbmBkmsbalance': this.drMbmBkmsbalance, + 'drmbmBkmstitle': this.drmbmBkmstitle, + 'cmpCustcode': this.cmpCustcode, + 'crMbmBkmstitle': this.crMbmBkmstitle, + 'sgtSentGntrnumber': this.sgtSentGntrnumber, + 'drSgtGntrdate': this.drSgtGntrdate, + 'crSgtGntrdate': this.crSgtGntrdate, + 'sgtGntramt': this.sgtGntramt, + 'batAcnttranSend': this.batAcnttranSend, + 'batAcnttranReceived': this.batAcnttranReceived, + 'sgtReceiveGntrnumber': this.sgtReceiveGntrnumber, + 'drpcrCurrdesc': this.drpcrCurrdesc, + 'drPcrCurrcode': this.drPcrCurrcode, + 'drPcrCurrshort': this.drPcrCurrshort, + 'crPcrCurrdesc': this.crPcrCurrdesc, + 'crPcrCurrcode': this.crPcrCurrcode, + 'crPcrCurrshort': this.crPcrCurrshort, + }; + } + + factory AccountStatementResponseModel.fromMap(Map map) { + return AccountStatementResponseModel( + id: map['id'] as int, + porOrgacode: map['porOrgacode'] ?? "", + drMbmBkmsnumber: map['drMbmBkmsnumber'] ?? "", + sgtReceiveNodeId : map['sgtReceiveNodeId'] ?? "", + sgtSentNodeId : map['sgtSentNodeId'] ?? "", + batAcnttranReversed : map['batAcnttranReversed'] ?? false, + crMbmBkmsnumber: map['crMbmBkmsnumber'] ?? "", + dmpProdcode: map['dmpProdcode'] ?? "", + crMbmBkmsbalance: map['crMbmBkmsbalance'] ?? 0.0, + drMbmBkmsbalance: map['drMbmBkmsbalance'] ?? 0.0, + drmbmBkmstitle: map['drmbmBkmstitle'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + crMbmBkmstitle: map['crMbmBkmstitle'] ?? "", + sgtSentGntrnumber: map['sgtSentGntrnumber'] ?? "", + drSgtGntrdate: map['drSgtGntrdate'] ?? "", + crSgtGntrdate: map['crSgtGntrdate'] ?? "", + sgtGntramt: map['sgtGntramt'] ?? 0.0, + batAcnttranSend: map['batAcnttranSend'] ?? false, + batAcnttranReceived: map['batAcnttranReceived'] ?? false, + sgtReceiveGntrnumber: map['sgtReceiveGntrnumber'] ?? "", + drpcrCurrdesc: map['drpcrCurrdesc'] ?? "", + drPcrCurrcode: map['drPcrCurrcode'] ?? "", + drPcrCurrshort: map['drPcrCurrshort'] ?? "", + crPcrCurrdesc: map['crPcrCurrdesc'] ?? "", + crPcrCurrcode: map['crPcrCurrcode'] ?? "", + crPcrCurrshort: map['crPcrCurrshort'] ?? "", + ); + } + + @override + String toString() { + return 'AccountStatementResponseModel{id: $id, porOrgacode: $porOrgacode, drMbmBkmsnumber: $drMbmBkmsnumber, sgtReceiveNodeId: $sgtReceiveNodeId, sgtSentNodeId: $sgtSentNodeId, batAcnttranReversed: $batAcnttranReversed, crMbmBkmsnumber: $crMbmBkmsnumber, dmpProdcode: $dmpProdcode, crMbmBkmsbalance: $crMbmBkmsbalance, drMbmBkmsbalance: $drMbmBkmsbalance, drmbmBkmstitle: $drmbmBkmstitle, cmpCustcode: $cmpCustcode, crMbmBkmstitle: $crMbmBkmstitle, sgtSentGntrnumber: $sgtSentGntrnumber, drSgtGntrdate: $drSgtGntrdate, crSgtGntrdate: $crSgtGntrdate, sgtGntramt: $sgtGntramt, batAcnttranSend: $batAcnttranSend, batAcnttranReceived: $batAcnttranReceived, sgtReceiveGntrnumber: $sgtReceiveGntrnumber, drpcrCurrdesc: $drpcrCurrdesc, drPcrCurrcode: $drPcrCurrcode, drPcrCurrshort: $drPcrCurrshort, crPcrCurrdesc: $crPcrCurrdesc, crPcrCurrcode: $crPcrCurrcode, crPcrCurrshort: $crPcrCurrshort}'; + } +} diff --git a/lib/app/models/account_statment_model.dart b/lib/app/models/account_statment_model.dart new file mode 100644 index 0000000..3ac8ad1 --- /dev/null +++ b/lib/app/models/account_statment_model.dart @@ -0,0 +1,43 @@ +// To parse this JSON data, do +// +// final accountStatment = accountStatmentFromJson(jsonString); + +import 'dart:convert'; + +List accountStatmentFromJson(String str) => + List.from( + json.decode(str).map((x) => AccountStatementModel.fromJson(x))); + +class AccountStatementModel { + final String? tranId; + final String? sgtGntrCreatedAt; + final String? sgtGntrNarration; + final String? sgtGntrvaluedate; + final String? deposit; + final String? withdrawal; + final String? status; + final String? sgtGntramt; + + AccountStatementModel({ + this.tranId, + this.sgtGntrCreatedAt, + this.sgtGntrNarration, + this.sgtGntrvaluedate, + this.deposit, + this.withdrawal, + this.status, + this.sgtGntramt, + }); + + factory AccountStatementModel.fromJson(Map json) => + AccountStatementModel( + tranId: json["tranID"], + sgtGntrCreatedAt: json["sgtGntrCreatedAt"], + sgtGntrNarration: json["sgtGntrNarration"], + sgtGntrvaluedate: json["sgtGntrvaluedate"], + deposit: json["deposit"], + withdrawal: json["withdrawal"], + status: json["status"], + sgtGntramt: json["sgtGntramt"], + ); +} diff --git a/lib/app/models/chanange_password_params.dart b/lib/app/models/chanange_password_params.dart new file mode 100644 index 0000000..45b674e --- /dev/null +++ b/lib/app/models/chanange_password_params.dart @@ -0,0 +1,36 @@ +// To parse this JSON data, do +// +// final changePasswordParams = changePasswordParamsFromJson(jsonString); + +import 'dart:convert'; + +ChangePasswordParams changePasswordParamsFromJson(String str) => + ChangePasswordParams.fromJson(json.decode(str)); + +String changePasswordParamsToJson(ChangePasswordParams data) => + json.encode(data.toJson()); + +class ChangePasswordParams { + final String? newPassword; + final String? email; + final String? oldPassword; + + ChangePasswordParams({ + this.newPassword, + this.email, + this.oldPassword, + }); + + factory ChangePasswordParams.fromJson(Map json) => + ChangePasswordParams( + newPassword: json["newPassword"], + email: json["email"], + oldPassword: json["oldPassword"], + ); + + Map toJson() => { + "newPassword": newPassword, + "email": email, + "oldPassword": oldPassword, + }; +} diff --git a/lib/app/models/create_transition_otp_model.dart b/lib/app/models/create_transition_otp_model.dart new file mode 100644 index 0000000..0985844 --- /dev/null +++ b/lib/app/models/create_transition_otp_model.dart @@ -0,0 +1,51 @@ +import 'dart:convert'; + +class CreateTransactionPinRequest { + String newTransPincode; + String channelCode; + String pctCstycode; + String porOrgacode; + String cmpCustcode; + bool isOtpRequired; + String pinType; + CreateTransactionPinRequest({ + required this.newTransPincode, + required this.channelCode, + required this.pctCstycode, + required this.porOrgacode, + required this.cmpCustcode, + required this.isOtpRequired, + required this.pinType, + }); + + Map toMap() { + final result = {}; + + result.addAll({'newTransPincode': newTransPincode}); + result.addAll({'channelCode': channelCode}); + result.addAll({'pctCstycode': pctCstycode}); + result.addAll({'porOrgacode': porOrgacode}); + result.addAll({'cmpCustcode': cmpCustcode}); + result.addAll({'isOtpRequired': isOtpRequired}); + result.addAll({'pinType': pinType}); + + return result; + } + + factory CreateTransactionPinRequest.fromMap(Map map) { + return CreateTransactionPinRequest( + newTransPincode: map['newTransPincode'] ?? '', + channelCode: map['channelCode'] ?? '', + pctCstycode: map['pctCstycode'] ?? '', + porOrgacode: map['porOrgacode'] ?? '', + cmpCustcode: map['cmpCustcode'] ?? '', + isOtpRequired: map['isOtpRequired'] ?? false, + pinType: map['pinType'] ?? '', + ); + } + + String toJson() => json.encode(toMap()); + + factory CreateTransactionPinRequest.fromJson(String source) => + CreateTransactionPinRequest.fromMap(json.decode(source)); +} diff --git a/lib/app/models/dashboard_response_model.dart b/lib/app/models/dashboard_response_model.dart new file mode 100644 index 0000000..b227bca --- /dev/null +++ b/lib/app/models/dashboard_response_model.dart @@ -0,0 +1,59 @@ + +import 'DepositAccountResponse.dart'; + +class DashBoardResponseModel { + List deposit = []; + + DashBoardResponseModel({required this.deposit}); + + factory DashBoardResponseModel.fromMap(dynamic map) { + return DashBoardResponseModel( + deposit: List.from( + ((map ?? []) as List).map((x) => DepositAccount.fromMap(x)) ?? [], + ), + ); + } + + Map toMap() { + return { + 'deposit': deposit.map((x) => x.toMap()).toList(), + }; + } +} + +class SampleDashboardData { + // static DashBoardResponseModel getDashboardModel(String responseFromServer) { + // String response = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000003\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":599501,\"accountBalance\":599501},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000004\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":580000,\"accountBalance\":580000},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000006\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"TDR- 6 Months\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":0,\"accountBalance\":0},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000012\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":0,\"accountBalance\":0},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000014\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":495000,\"accountBalance\":495000},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000016\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":499999,\"accountBalance\":499999}]}"; + // + // String oneLoanAndOneDeposit = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000016\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":499999,\"accountBalance\":499999}]}"; + // + // String oneLoanAndZeroDeposit = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[]}"; + // + // String zeroLoanAndOneDeposit = "{\"loan\":[],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000003\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":599501,\"accountBalance\":599501}]}"; + // + // String zeroLoanAndMultipleDeposit = + // "{\"loan\":[],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000003\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":599501,\"accountBalance\":599501},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000004\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":580000,\"accountBalance\":580000},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000006\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"TDR- 6 Months\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":0,\"accountBalance\":0}]}"; + // + // String multipleLoanAndZeroDeposit = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[]}"; + // + // String oneLoanAndMultipleDeposit = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000003\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":599501,\"accountBalance\":599501},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000004\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":580000,\"accountBalance\":580000},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000006\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"TDR- 6 Months\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":0,\"accountBalance\":0}]}"; + // + // String oneDepositAndMultipleLoan = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000003\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":599501,\"accountBalance\":599501}]}"; + // + // String multipleDepositAndMultipleLoan = + // "{\"loan\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000001\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Service & Pension Loan\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"01\",\"mbmBkmsbalance\":-46250,\"accountBalance\":-46250,\"schedule\":{\"scheduleDetail\":[{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":1,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,17],\"mlsLnshduedate\":[2023,8,18],\"mlsLnshprincipal\":3750,\"mlsLnshinterest\":1000,\"mlsLnshRunningprincipal\":3750,\"mlsLnshRunninginterest\":1000,\"mlsLnshinterestperday\":1000},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":2,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,8,19],\"mlsLnshduedate\":[2023,9,18],\"mlsLnshprincipal\":3850,\"mlsLnshinterest\":900,\"mlsLnshRunningprincipal\":7600,\"mlsLnshRunninginterest\":1900,\"mlsLnshinterestperday\":29.03},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":3,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,9,19],\"mlsLnshduedate\":[2023,10,18],\"mlsLnshprincipal\":3900,\"mlsLnshinterest\":850,\"mlsLnshRunningprincipal\":11500,\"mlsLnshRunninginterest\":2750,\"mlsLnshinterestperday\":28.33},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":4,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,10,19],\"mlsLnshduedate\":[2023,11,19],\"mlsLnshprincipal\":4000,\"mlsLnshinterest\":750,\"mlsLnshRunningprincipal\":15500,\"mlsLnshRunninginterest\":3500,\"mlsLnshinterestperday\":23.44},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":5,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,11,20],\"mlsLnshduedate\":[2023,12,17],\"mlsLnshprincipal\":4050,\"mlsLnshinterest\":700,\"mlsLnshRunningprincipal\":19550,\"mlsLnshRunninginterest\":4200,\"mlsLnshinterestperday\":25},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":6,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2023,12,18],\"mlsLnshduedate\":[2024,1,17],\"mlsLnshprincipal\":4150,\"mlsLnshinterest\":600,\"mlsLnshRunningprincipal\":23700,\"mlsLnshRunninginterest\":4800,\"mlsLnshinterestperday\":19.35},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":7,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,1,18],\"mlsLnshduedate\":[2024,2,18],\"mlsLnshprincipal\":4200,\"mlsLnshinterest\":550,\"mlsLnshRunningprincipal\":27900,\"mlsLnshRunninginterest\":5350,\"mlsLnshinterestperday\":17.19},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":8,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,2,19],\"mlsLnshduedate\":[2024,3,17],\"mlsLnshprincipal\":4300,\"mlsLnshinterest\":450,\"mlsLnshRunningprincipal\":32200,\"mlsLnshRunninginterest\":5800,\"mlsLnshinterestperday\":16.07},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":9,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,3,18],\"mlsLnshduedate\":[2024,4,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":350,\"mlsLnshRunningprincipal\":36600,\"mlsLnshRunninginterest\":6150,\"mlsLnshinterestperday\":10.94},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":10,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,4,19],\"mlsLnshduedate\":[2024,5,20],\"mlsLnshprincipal\":4450,\"mlsLnshinterest\":300,\"mlsLnshRunningprincipal\":41050,\"mlsLnshRunninginterest\":6450,\"mlsLnshinterestperday\":9.38},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":11,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,5,21],\"mlsLnshduedate\":[2024,6,18],\"mlsLnshprincipal\":4550,\"mlsLnshinterest\":200,\"mlsLnshRunningprincipal\":45600,\"mlsLnshRunninginterest\":6650,\"mlsLnshinterestperday\":6.9},{\"porOrgacode\":\"0006\",\"mbmBkmsnumber\":\"0000001\",\"mlsLnshtype\":\"R\",\"mlsLnshinstno\":12,\"plcLocacode\":\"2000\",\"mlsLnshstartdate\":[2024,6,19],\"mlsLnshduedate\":[2024,7,18],\"mlsLnshprincipal\":4400,\"mlsLnshinterest\":100,\"mlsLnshRunningprincipal\":50000,\"mlsLnshRunninginterest\":6750,\"mlsLnshinterestperday\":3.33}]}}],\"deposit\":[{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000003\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":599501,\"accountBalance\":599501},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000004\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"Current Deposit Account\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":580000,\"accountBalance\":580000},{\"porOrgacode\":\"0006\",\"failed\":false,\"mbmBkmsnumber\":\"0000006\",\"mbmBkmstitle\":\"Jahangir Babar Khan\",\"dmpProddesc\":\"TDR- 6 Months\",\"pcrCurrdesc\":\"Pakistani Rupees\",\"plcLocacode\":\"2000\",\"plcLocadesc\":\"Head Office\",\"pasAcstcode\":\"NORM\",\"mbmBkmsbalance\":0,\"accountBalance\":0}]}"; + // + // Map jsonMap = json.decode(zeroLoanAndMultipleDeposit); + // DashBoardResponseModel dashboardResponse = DashBoardResponseModel.fromMap(jsonMap); + // + // SessionCache.instance.depositAccountList.value = dashboardResponse.deposit; + // SessionCache.instance.loanAccountList.value = dashboardResponse.loan; + // return dashboardResponse; + // } +} diff --git a/lib/app/models/evaluated_cuency_model.dart b/lib/app/models/evaluated_cuency_model.dart new file mode 100644 index 0000000..ee37c39 --- /dev/null +++ b/lib/app/models/evaluated_cuency_model.dart @@ -0,0 +1,62 @@ +class EvaluatedCurrencyModel { + String pcrCurrcode = ""; + double sgtGntramtfc = 0.0; + double serviceCharges = 0.0; + double targetPerEratrateact = 0.0; + + EvaluatedCurrencyModel({ + this.pcrCurrcode = "", + this.sgtGntramtfc = 0.0, + this.serviceCharges = 0.0, + this.targetPerEratrateact = 0.0, + }); + + EvaluatedCurrencyModel.empty() + : this.pcrCurrcode = "", + this.sgtGntramtfc = 0.0, + this.serviceCharges = 0.0, + this.targetPerEratrateact = 0.0; + + Map toMap() { + return { + 'pcrCurrcode': this.pcrCurrcode, + 'sgtGntramtfc': this.sgtGntramtfc, + 'serviceCharges': this.serviceCharges, + 'targetPerEratrateact': this.targetPerEratrateact, + }; + } + + factory EvaluatedCurrencyModel.fromMap(Map map) { + return EvaluatedCurrencyModel( + pcrCurrcode: map['pcrCurrcode'] ?? "", + sgtGntramtfc: map['sgtGntramtfc'] ?? 0.0, + serviceCharges: map['serviceCharges'] ?? 0.0, + targetPerEratrateact: map['targetPerEratrateact'] ?? 0.0, + ); + } + + @override + String toString() { + return 'EvaluatedCurrencyModel{pcrCurrcode: $pcrCurrcode, sgtGntramtfc: $sgtGntramtfc, serviceCharges: $serviceCharges, targetPerEratrateact: $targetPerEratrateact}'; + } + +// Factory constructor to create an instance from a JSON map +// factory EvaluatedCurrencyModel.fromJson(Map json) { +// return EvaluatedCurrencyModel( +// pcrCurrcode: json['pcrCurrcode'] as String, +// sgtGntramtfc: (json['sgtGntramtfc'] as num).toDouble(), +// serviceCharges: (json['serviceCharges'] as num).toDouble(), +// targetPerEratrateact: (json['targetPerEratrateact'] as num).toDouble(), +// ); +// } +// +// // Method to convert an instance to a JSON map +// Map toJson() { +// return { +// 'pcrCurrcode': pcrCurrcode, +// 'sgtGntramtfc': sgtGntramtfc, +// 'serviceCharges': serviceCharges, +// 'targetPerEratrateact': targetPerEratrateact, +// }; +// } +} diff --git a/lib/app/models/finger_print_info.dart b/lib/app/models/finger_print_info.dart new file mode 100644 index 0000000..f0f7f0d --- /dev/null +++ b/lib/app/models/finger_print_info.dart @@ -0,0 +1,36 @@ +class FingerPrintInfo { + String porOrgacode; + String channelCode; + String cmpUserId; + String cmpCustpassword; + + FingerPrintInfo({ + this.porOrgacode = '', + this.channelCode = '', + this.cmpUserId = '', + this.cmpCustpassword = '', + }); + + Map toMap() { + return { + 'porOrgacode': this.porOrgacode, + 'channelCode': this.channelCode, + 'cmpUserId': this.cmpUserId, + 'cmpCustpassword': this.cmpCustpassword, + }; + } + + factory FingerPrintInfo.fromMap(Map map) { + return FingerPrintInfo( + porOrgacode: map['porOrgacode'] ?? "", + channelCode: map['channelCode'] ?? "", + cmpUserId: map['cmpUserId'] ?? "", + cmpCustpassword: map['cmpCustpassword'] ?? "", + ); + } + + @override + String toString() { + return '{porOrgacode: $porOrgacode, channelCode: $channelCode, cmpUserId: $cmpUserId, cmpCustpassword: $cmpCustpassword}'; + } +} diff --git a/lib/app/models/identity_drop_down_model.dart b/lib/app/models/identity_drop_down_model.dart new file mode 100644 index 0000000..520c2ce --- /dev/null +++ b/lib/app/models/identity_drop_down_model.dart @@ -0,0 +1,12 @@ +class IdentityDropDowModel { + identityType identity; + String label; + + IdentityDropDowModel({required this.identity, required this.label}); +} + +enum identityType { + identity, + ssntaxpayer, + passport, +} diff --git a/lib/app/models/login_request_model.dart b/lib/app/models/login_request_model.dart new file mode 100644 index 0000000..f775f00 --- /dev/null +++ b/lib/app/models/login_request_model.dart @@ -0,0 +1,35 @@ + + +import '../core/constants/api_keys.dart'; + +class LoginRequestModel { + final String username; + final String password; + final String channelCode; + final String porOrgacode; + + LoginRequestModel({ + required this.username, + required this.password, + required this.channelCode, + required this.porOrgacode, + }); + + factory LoginRequestModel.fromJson(Map json) { + return LoginRequestModel( + username: json[ApiKeys.cmpUserId], + password: json[ApiKeys.cmpCustpassword], + channelCode: json[ApiKeys.channelCode], + porOrgacode: json[ApiKeys.porOrgacode], + ); + } + + Map toJson() { + final Map data = {}; + data[ApiKeys.cmpUserId] = username; + data[ApiKeys.cmpCustpassword] = password; + data[ApiKeys.channelCode] = channelCode; + data[ApiKeys.porOrgacode] = porOrgacode; + return data; + } +} diff --git a/lib/app/models/product_model.dart b/lib/app/models/product_model.dart new file mode 100644 index 0000000..a9420e1 --- /dev/null +++ b/lib/app/models/product_model.dart @@ -0,0 +1,43 @@ +class ProductDepositModel { + String porOrgacode; + String dmpProdcode; + String dmpProddesc; + String dmpProdshort; + String pcrCurrcode; + bool dmpProdactive; + + ProductDepositModel({ + required this.porOrgacode, + required this.dmpProdcode, + required this.dmpProddesc, + required this.dmpProdshort, + required this.pcrCurrcode, + required this.dmpProdactive, + }); + + factory ProductDepositModel.fromJson(Map json) { + return ProductDepositModel( + porOrgacode: json['porOrgacode'], + dmpProdcode: json['dmpProdcode'], + dmpProddesc: json['dmpProddesc'], + dmpProdshort: json['dmpProdshort'], + pcrCurrcode: json['pcrCurrcode'], + dmpProdactive: json['dmpProdactive'], + ); + } + + Map toJson() { + return { + 'porOrgacode': porOrgacode, + 'dmpProdcode': dmpProdcode, + 'dmpProddesc': dmpProddesc, + 'dmpProdshort': dmpProdshort, + 'pcrCurrcode': pcrCurrcode, + 'dmpProdactive': dmpProdactive, + }; + } + + static List productListFromJson(List jsonList) { + return jsonList.map((json) => ProductDepositModel.fromJson(json)).toList(); + } +} diff --git a/lib/app/models/resen_ot_chanange_trans_pin.dart b/lib/app/models/resen_ot_chanange_trans_pin.dart new file mode 100644 index 0000000..c50d193 --- /dev/null +++ b/lib/app/models/resen_ot_chanange_trans_pin.dart @@ -0,0 +1,72 @@ +import 'dart:convert'; + +class ResendOtpChangeTransPin { + String? oldTransPincode; + String? newTransPincode; + String? channelCode; + String? pctCstycode; + String? porOrgacode; + String? cmpCustcode; + bool? isOtpRequire; + String? pinType; + + ResendOtpChangeTransPin({ + this.oldTransPincode, + this.newTransPincode, + this.channelCode, + this.pctCstycode, + this.porOrgacode, + this.cmpCustcode, + this.isOtpRequire, + this.pinType, + }); + + Map toMap() { + final result = {}; + + if (oldTransPincode != null) { + result.addAll({'oldTransPincode': oldTransPincode}); + } + if (newTransPincode != null) { + result.addAll({'newTransPincode': newTransPincode}); + } + if (channelCode != null) { + result.addAll({'channelCode': channelCode}); + } + if (pctCstycode != null) { + result.addAll({'pctCstycode': pctCstycode}); + } + if (porOrgacode != null) { + result.addAll({'porOrgacode': porOrgacode}); + } + if (cmpCustcode != null) { + result.addAll({'cmpCustcode': cmpCustcode}); + } + if (isOtpRequire != null) { + result.addAll({'isOtpRequire': isOtpRequire}); + } + if (pinType != null) { + result.addAll({'pinType': pinType}); + } + + return result; + } + + factory ResendOtpChangeTransPin.fromMap(Map map) { + return ResendOtpChangeTransPin( + oldTransPincode: map['oldTransPincode'], + newTransPincode: map['newTransPincode'], + channelCode: map['channelCode'], + pctCstycode: map['pctCstycode'], + porOrgacode: map['porOrgacode'], + cmpCustcode: map['cmpCustcode'], + isOtpRequire: map['isOtpRequire'], + pinType: map['pinType'], + ); + } + + String toJson() => json.encode(toMap()); + + factory ResendOtpChangeTransPin.fromJson(String source) => + ResendOtpChangeTransPin.fromMap(json.decode(source)); +} diff --git a/lib/app/models/resend_ot_login_model.dart b/lib/app/models/resend_ot_login_model.dart new file mode 100644 index 0000000..891b19c --- /dev/null +++ b/lib/app/models/resend_ot_login_model.dart @@ -0,0 +1,72 @@ +import 'dart:convert'; + +class ResendOtpLoginModel { + String? username; + String? channelCode; + String? porOrgacode; + String? email; + bool? isOtpRequire; + String? phone; + String? pinType; + String? userRole; + + ResendOtpLoginModel({ + this.username, + this.channelCode, + this.porOrgacode, + this.email, + this.isOtpRequire, + this.phone, + this.pinType, + this.userRole, + }); + + Map toMap() { + final result = {}; + + if (username != null) { + result.addAll({'username': username}); + } + if (channelCode != null) { + result.addAll({'channelCode': channelCode}); + } + if (porOrgacode != null) { + result.addAll({'porOrgacode': porOrgacode}); + } + if (email != null) { + result.addAll({'email': email}); + } + if (isOtpRequire != null) { + result.addAll({'isOtpRequire': isOtpRequire}); + } + if (phone != null) { + result.addAll({'phone': phone}); + } + if (pinType != null) { + result.addAll({'pinType': pinType}); + } + if (userRole != null) { + result.addAll({'userRole': userRole}); + } + + return result; + } + + factory ResendOtpLoginModel.fromMap(Map map) { + return ResendOtpLoginModel( + username: map['username'], + channelCode: map['channelCode'], + porOrgacode: map['porOrgacode'], + email: map['email'], + isOtpRequire: map['isOtpRequire'], + phone: map['phone'], + pinType: map['pinType'], + userRole: map['userRole'], + ); + } + + String toJson() => json.encode(toMap()); + + factory ResendOtpLoginModel.fromJson(String source) => + ResendOtpLoginModel.fromMap(json.decode(source)); +} diff --git a/lib/app/models/resend_otp_usend.dart b/lib/app/models/resend_otp_usend.dart new file mode 100644 index 0000000..5eab57d --- /dev/null +++ b/lib/app/models/resend_otp_usend.dart @@ -0,0 +1,66 @@ +import 'dart:convert'; + +class ResendOtpUsendModel { + String? porOrgacode; + String? pctCstycode; + String? channelCode; + String? cmpCustcode; + String? email; + String? pinType; + bool? isOtpRequired; + + ResendOtpUsendModel({ + this.porOrgacode, + this.pctCstycode, + this.channelCode, + this.cmpCustcode, + this.email, + this.pinType, + this.isOtpRequired, + }); + + Map toMap() { + final result = {}; + + if (porOrgacode != null) { + result.addAll({'porOrgacode': porOrgacode}); + } + if (pctCstycode != null) { + result.addAll({'pctCstycode': pctCstycode}); + } + if (channelCode != null) { + result.addAll({'channelCode': channelCode}); + } + if (cmpCustcode != null) { + result.addAll({'cmpCustcode': cmpCustcode}); + } + if (email != null) { + result.addAll({'email': email}); + } + if (pinType != null) { + result.addAll({'pinType': pinType}); + } + if (isOtpRequired != null) { + result.addAll({'isOtpRequired': isOtpRequired}); + } + + return result; + } + + factory ResendOtpUsendModel.fromMap(Map map) { + return ResendOtpUsendModel( + porOrgacode: map['porOrgacode'], + pctCstycode: map['pctCstycode'], + channelCode: map['channelCode'], + cmpCustcode: map['cmpCustcode'], + email: map['email'], + pinType: map['pinType'], + isOtpRequired: map['isOtpRequired'], + ); + } + + String toJson() => json.encode(toMap()); + + factory ResendOtpUsendModel.fromJson(String source) => + ResendOtpUsendModel.fromMap(json.decode(source)); +} diff --git a/lib/app/models/reverse_transaction_model.dart b/lib/app/models/reverse_transaction_model.dart new file mode 100644 index 0000000..a6dafc8 --- /dev/null +++ b/lib/app/models/reverse_transaction_model.dart @@ -0,0 +1,28 @@ +class ReverseTransactionModel { + String porOrgacode = ""; + String nodeId = ""; + String sgtGntrnumber = ""; + + ReverseTransactionModel({this.porOrgacode = "", this.nodeId = "", this.sgtGntrnumber = ""}); + + Map toMap() { + return { + 'porOrgacode': this.porOrgacode, + 'nodeId': this.nodeId, + 'sgtGntrnumber': this.sgtGntrnumber, + }; + } + + factory ReverseTransactionModel.fromMap(Map map) { + return ReverseTransactionModel( + porOrgacode: map['porOrgacode'] as String, + nodeId: map['nodeId'] as String, + sgtGntrnumber: map['sgtGntrnumber'] as String, + ); + } + + @override + String toString() { + return 'ReverseTransactionModel{porOrgacode: $porOrgacode, nodeId: $nodeId, sgtGntrnumber: $sgtGntrnumber}'; + } +} diff --git a/lib/app/models/u_recived_responce_model.dart b/lib/app/models/u_recived_responce_model.dart new file mode 100644 index 0000000..0a5dcb8 --- /dev/null +++ b/lib/app/models/u_recived_responce_model.dart @@ -0,0 +1,125 @@ +class UReceivedResponseData { + int id = 0; + String porOrgacode = ""; + String drMbmBkmsnumber = ""; + String crMbmBkmsnumber = ""; + String sgtReceiveNodeId = ""; + String sgtSentNodeId = ""; + bool batAcnttranReversed = false; + String dmpProdcode = ""; + String drmbmBkmstitle = ""; + String drpcrCurrdesc = ""; + String cmpCustcode = ""; + String drPcrCurrcode = ""; + String crMbmBkmstitle = ""; + String crPcrCurrdesc = ""; + String crPcrCurrcode = ""; + String sgtSentGntrnumber = ""; + String drSgtGntrdate = ""; + String crSgtGntrdate = ""; + double sgtGntramt = 0.0; + bool batAcnttranSend = false; + bool batAcnttranReceived = false; + String sgtReceiveGntrnumber = ""; + String drPcrCurrshort = ""; + String crPcrCurrshort = ""; + + // String daysToExpire = ""; + String expSgtGntrdate = ""; + + UReceivedResponseData({ + this.id = 0, + this.porOrgacode = "", + this.drMbmBkmsnumber = "", + this.crMbmBkmsnumber = "", + this.sgtReceiveNodeId = "", + this.sgtSentNodeId = "", + this.batAcnttranReversed = false, + this.dmpProdcode = "", + this.drmbmBkmstitle = "", + this.drpcrCurrdesc = "", + this.cmpCustcode = "", + this.drPcrCurrcode = "", + this.crMbmBkmstitle = "", + this.crPcrCurrdesc = "", + this.crPcrCurrcode = "", + this.sgtSentGntrnumber = "", + this.drSgtGntrdate = "", + this.crSgtGntrdate = "", + this.sgtGntramt = 0.0, + this.batAcnttranSend = false, + this.batAcnttranReceived = false, + this.sgtReceiveGntrnumber = "", + this.drPcrCurrshort = "", + this.crPcrCurrshort = "", + // this.daysToExpire = "", + this.expSgtGntrdate = "", + }); + + factory UReceivedResponseData.fromMap(Map map) { + return UReceivedResponseData( + id: map['id'] ?? 0, + porOrgacode: map['porOrgacode'] ?? "", + drMbmBkmsnumber: map['drMbmBkmsnumber'] ?? "", + crMbmBkmsnumber: map['crMbmBkmsnumber'] ?? "", + sgtReceiveNodeId: map['sgtReceiveNodeId'] ?? "", + sgtSentNodeId: map['sgtSentNodeId'] ?? "", + batAcnttranReversed: map['batAcnttranReversed'] ?? false, + dmpProdcode: map['dmpProdcode'] ?? "", + drmbmBkmstitle: map['drmbmBkmstitle'] ?? "", + drpcrCurrdesc: map['drpcrCurrdesc'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + drPcrCurrcode: map['drPcrCurrcode'] ?? "", + crMbmBkmstitle: map['crMbmBkmstitle'] ?? "", + crPcrCurrdesc: map['crPcrCurrdesc'] ?? "", + crPcrCurrcode: map['crPcrCurrcode'] ?? "", + sgtSentGntrnumber: map['sgtSentGntrnumber'] ?? "", + drSgtGntrdate: map['drSgtGntrdate'] ?? "", + crSgtGntrdate: map['crSgtGntrdate'] ?? "", + sgtGntramt: map['sgtGntramt'] ?? 0.0, + batAcnttranSend: map['batAcnttranSend'] ?? false, + batAcnttranReceived: map['batAcnttranReceived'] ?? false, + sgtReceiveGntrnumber: map['sgtReceiveGntrnumber'] ?? "", + drPcrCurrshort: map['drPcrCurrshort'] ?? "", + crPcrCurrshort: map['crPcrCurrshort'] ?? "", + // daysToExpire: map['daysToExpire'] ?? "", + expSgtGntrdate: map['expSgtGntrdate'] ?? "", + ); + } + + Map toMap() { + return { + 'id': id, + 'porOrgacode': porOrgacode, + 'drMbmBkmsnumber': drMbmBkmsnumber, + 'crMbmBkmsnumber': crMbmBkmsnumber, + 'sgtReceiveNodeId': sgtReceiveNodeId, + 'sgtSentNodeId': sgtSentNodeId, + 'batAcnttranReversed': batAcnttranReversed, + 'dmpProdcode': dmpProdcode, + 'drmbmBkmstitle': drmbmBkmstitle, + 'drpcrCurrdesc': drpcrCurrdesc, + 'cmpCustcode': cmpCustcode, + 'drPcrCurrcode': drPcrCurrcode, + 'crMbmBkmstitle': crMbmBkmstitle, + 'crPcrCurrdesc': crPcrCurrdesc, + 'crPcrCurrcode': crPcrCurrcode, + 'sgtSentGntrnumber': sgtSentGntrnumber, + 'drSgtGntrdate': drSgtGntrdate, + 'crSgtGntrdate': crSgtGntrdate, + 'sgtGntramt': sgtGntramt, + 'batAcnttranSend': batAcnttranSend, + 'batAcnttranReceived': batAcnttranReceived, + 'sgtReceiveGntrnumber': sgtReceiveGntrnumber, + 'drPcrCurrshort': drPcrCurrshort, + 'crPcrCurrshort': crPcrCurrshort, + // 'daysToExpire': daysToExpire, + 'expSgtGntrdate': expSgtGntrdate, + }; + } + + @override + String toString() { + return 'UReceivedResponseData{id: $id, porOrgacode: $porOrgacode, drMbmBkmsnumber: $drMbmBkmsnumber, crMbmBkmsnumber: $crMbmBkmsnumber, sgtReceiveNodeId: $sgtReceiveNodeId, sgtSentNodeId: $sgtSentNodeId, batAcnttranReversed: $batAcnttranReversed, dmpProdcode: $dmpProdcode, drmbmBkmstitle: $drmbmBkmstitle, drpcrCurrdesc: $drpcrCurrdesc, cmpCustcode: $cmpCustcode, drPcrCurrcode: $drPcrCurrcode, crMbmBkmstitle: $crMbmBkmstitle, crPcrCurrdesc: $crPcrCurrdesc, crPcrCurrcode: $crPcrCurrcode, sgtSentGntrnumber: $sgtSentGntrnumber, drSgtGntrdate: $drSgtGntrdate, crSgtGntrdate: $crSgtGntrdate, sgtGntramt: $sgtGntramt, batAcnttranSend: $batAcnttranSend, batAcnttranReceived: $batAcnttranReceived, sgtReceiveGntrnumber: $sgtReceiveGntrnumber, drPcrCurrshort: $drPcrCurrshort, crPcrCurrshort: $crPcrCurrshort, expSgtGntrdate: $expSgtGntrdate}'; + } +} diff --git a/lib/app/models/upload_user_profile_model.dart b/lib/app/models/upload_user_profile_model.dart new file mode 100644 index 0000000..eb9798c --- /dev/null +++ b/lib/app/models/upload_user_profile_model.dart @@ -0,0 +1,28 @@ +class UploadUserProfileModel { + String porOrgacode = ""; + String cmpCustcode = ""; + String cmpCustImage = ""; + + UploadUserProfileModel({this.porOrgacode = "", this.cmpCustcode = "", this.cmpCustImage = ""}); + + Map toMap() { + return { + 'porOrgacode': this.porOrgacode, + 'cmpCustcode': this.cmpCustcode, + 'cmpCustImage': this.cmpCustImage, + }; + } + + factory UploadUserProfileModel.fromMap(Map map) { + return UploadUserProfileModel( + porOrgacode: map['porOrgacode'] ?? "", + cmpCustcode: map['cmpCustcode'] ?? "", + cmpCustImage: map['cmpCustImage'] ?? "", + ); + } + + @override + String toString() { + return 'UploadUserProfileModel{porOrgacode: $porOrgacode, cmpCustcode: $cmpCustcode, cmpCustImage: $cmpCustImage}'; + } +} diff --git a/lib/app/modules/about_us/bindings/about_us_binding.dart b/lib/app/modules/about_us/bindings/about_us_binding.dart new file mode 100644 index 0000000..bb86c54 --- /dev/null +++ b/lib/app/modules/about_us/bindings/about_us_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/about_us_controller.dart'; + +class AboutUsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AboutUsController(), + ); + } +} diff --git a/lib/app/modules/about_us/controllers/about_us_controller.dart b/lib/app/modules/about_us/controllers/about_us_controller.dart new file mode 100644 index 0000000..2e4b3f2 --- /dev/null +++ b/lib/app/modules/about_us/controllers/about_us_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class AboutUsController extends GetxController { + //TODO: Implement AboutUsController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/about_us/views/about_us_view.dart b/lib/app/modules/about_us/views/about_us_view.dart new file mode 100644 index 0000000..82281c7 --- /dev/null +++ b/lib/app/modules/about_us/views/about_us_view.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../controllers/about_us_controller.dart'; + +class AboutUsView extends GetView { + const AboutUsView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textAboutUs), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textWHY), style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.colorPrimary)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWHYDescription), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWHAT), style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.colorPrimary)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWHATDescription), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWHO), style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.colorPrimary)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textWHODescription), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text("Version", style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + Text("1.0.0.3", style: Theme.of(context).textTheme.bodySmall), + ]), + ), + ), + ); + } +} diff --git a/lib/app/modules/account_statement/bindings/account_statement_binding.dart b/lib/app/modules/account_statement/bindings/account_statement_binding.dart new file mode 100644 index 0000000..5b63d57 --- /dev/null +++ b/lib/app/modules/account_statement/bindings/account_statement_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/account_statement_controller.dart'; + +class AccountStatementBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AccountStatementController(), + ); + } +} diff --git a/lib/app/modules/account_statement/controllers/account_statement_controller.dart b/lib/app/modules/account_statement/controllers/account_statement_controller.dart new file mode 100644 index 0000000..03cc80d --- /dev/null +++ b/lib/app/modules/account_statement/controllers/account_statement_controller.dart @@ -0,0 +1,319 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/dialogs/custom_loading.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../custom_widgets/date_picker.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/accountStatementResponseModel.dart'; + +class AccountStatementController extends GetxController { + late InputField depositAccountField; + RxBool isExpanded = false.obs; + bool isCredit = false; + bool isLoading = true; + RxInt selectedIndex = 0.obs; + + late CustomDropDown genderField; + + final AppRepositories repository = Get.find(); + + List accountNumberList = SessionCache.instance.depositAccountList.map((element) => element.mbmBkmsnumber).toList(); + + RxList accountStatement = RxList.empty(); + + RxList allAccountStatement = RxList.empty(); + + ///drop down + RxList allDepositAccounts = RxList.empty(); + + Rx selectedDepositAccount = DepositAccount.empty().obs; + + @override + void onInit() { + super.onInit(); + dp("Deposit List", accountStatement); + + for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + DepositAccount depositAccount = SessionCache.instance.depositAccountList.elementAt(i); + + allDepositAccounts.add( + DropDown(i.toString(), "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", depositAccount), + ); + } + + // + } + + @override + Future onReady() async { + super.onReady(); + isLoading = true; + update(); + // showLoader(); + + var accountNumber = Get.arguments; + + dp("Account number", accountNumber); + + Future.delayed(Duration.zero).then((value) { + if (accountNumber != null) { + // + + var selectDepositAcc = allDepositAccounts.firstWhere((e) => (e.data as DepositAccount).mbmBkmsnumber == accountNumber['accountNumber']); + + selectedDepositAccount.value = selectDepositAcc.data; + + depositAccountField.setText(selectDepositAcc.label); + } else { + // + + selectedDepositAccount.value = allDepositAccounts.first.data as DepositAccount; + + depositAccountField.setText(allDepositAccounts.first.label); + } + + fetchAccountStatementTransition(); + }); + } + + void updateSelectedDeposit(DropDown item) { + selectedDepositAccount.value = item.data as DepositAccount; + dp("Data update", item); + fetchAccountStatementTransition(); + } + + void addItemToTop(AccountStatementResponseModel newItem) { + accountStatement.insert(0, newItem); + } + + Future fetchAccountStatementTransition() async { + ServerResponse response = await repository.fetchAccountStatement(selectedDepositAccount.value.mbmBkmsnumber); + + if (response.isError) { + Toasty.error(response.errorMsg); + hideLoader(); + isLoading = false; + update(); + return; + } + + List list = List.from(((response.response ?? []) as List).map((x) => AccountStatementResponseModel.fromMap(x))); + + dp("------------------------", list.toString()); + + accountStatement.assignAll(list); + allAccountStatement.assignAll(list); + + hideLoader(); + + isLoading = false; + + update(); + } + + (DateTime, DateTime) weekFirstAndLastDate() { + // Get the current date + DateTime today = DateTime.now(); + +// Define the first day of the week (adjust if needed) + int firstDayOfWeek = MaterialLocalizations.of(Get.context!).firstDayOfWeekIndex; + +// Calculate the offset from today to the first day of the week + int daysOffset = today.weekday - firstDayOfWeek; + +// Handle negative offsets for weeks starting before current day + daysOffset = daysOffset < 0 ? daysOffset + DateTime.daysPerWeek : daysOffset; + +// Get the first date of the current week + DateTime firstDate = today.subtract(Duration(days: daysOffset)); + +// Get the last date of the current week + DateTime lastDate = firstDate.add(const Duration(days: DateTime.daysPerWeek - 1)); + +// Now you have both firstDate and lastDate representing the current week + return (firstDate, lastDate); + } + + (DateTime, DateTime) monthFirstAndLastDate() { + // + + DateTime today = DateTime.now(); + +// Get the year + int year = today.year; + +// Get the month + int month = today.month; + +// Create the first date of the month + DateTime firstDate = DateTime(year, month, 1); + +// Get the last day of the month (tricky part) + DateTime lastDate = DateTime(year, month + 1, 0); + return (firstDate, lastDate); + } + + var currentDate = DateTime.now(); + + // void updateRange(int i) { + // dp("Current selected", i); + // selectedIndex.value = i; + // accountStatement.assignAll(allAccountStatement); + // + // if (i == 1) { + // accountStatement.value = accountStatement.where((e) { + // DateTime date = DateTime.parse(e.drSgtGntrdate); + // dp("Date 1", date); + // return DateTime(date.year, date.month, date.day) == DateTime(currentDate.year, currentDate.month, currentDate.day); + // }).toList(); + // } + // if (i == 2) { + // // + // + // var weekDate = weekFirstAndLastDate(); + // + // dp("Week date", weekDate); + // + // accountStatement.value = accountStatement.where((e) => DateTime.parse(e.drSgtGntrdate).isAfter(weekDate.$1) && DateTime.parse(e.drSgtGntrdate).isBefore(weekDate.$2)).toList(); + // } + // if (i == 3) { + // accountStatement.value = accountStatement.where((e) { + // DateTime date = DateTime.parse(e.drSgtGntrdate); + // dp("Date 1", date); + // return date.month == currentDate.month && date.year == currentDate.year; + // }).toList(); + // } + // if (i == 4) { + // accountStatement.value = accountStatement.where((e) { + // DateTime date = DateTime.parse(e.drSgtGntrdate); + // dp("Date 1", date); + // return date.year == currentDate.year; + // }).toList(); + // } + // } + void updateRange(int i) { + dp("Current selected", i); + selectedIndex.value = i; + accountStatement.assignAll(allAccountStatement); + + /// Check All Transactions + if (i == 1) { + accountStatement.value = accountStatement.where((e) { + DateTime date = DateTime.parse(e.drSgtGntrdate); + dp("Date 1", date); + return DateTime(date.year, date.month, date.day) == DateTime(currentDate.year, currentDate.month, currentDate.day); + }).toList(); + } + + /// Check Week Transactions + if (i == 2) { + var weekDate = weekFirstAndLastDate(); + dp("Week date", weekDate); + + accountStatement.value = accountStatement.where((e) { + DateTime date = DateTime.parse(e.drSgtGntrdate); + return date.isAfter(weekDate.$1.subtract(const Duration(days: 1))) && date.isBefore(weekDate.$2.add(const Duration(days: 1))); + }).toList(); + } + + /// Month wise Transactions + if (i == 3) { + var monthDate = monthFirstAndLastDate(); + dp("Month date", monthDate); + + accountStatement.value = accountStatement.where((e) { + DateTime date = DateTime.parse(e.drSgtGntrdate); + return date.isAfter(monthDate.$1.subtract(const Duration(days: 1))) && date.isBefore(monthDate.$2.add(const Duration(days: 1))); + }).toList(); + } + + /// Yearly Transaction + if (i == 4) { + accountStatement.value = accountStatement.where((e) { + DateTime date = DateTime.parse(e.drSgtGntrdate); + dp("Date 1", date); + return date.year == currentDate.year; + }).toList(); + } + } + // void showDateRangePic() async { + // // + // accountStatement.assignAll(allAccountStatement); + // + // var range = await DatePicker.showRangeDatePicker(); + // + // dp("Date range", range?[0]); + // + // dp("Date range", range?[1]); + // + // if (range == null || range.isEmpty) { + // // Toasty.error("Range is not selected"); + // return; + // } + // + // var firstDate = DateTime(range[0]!.year, range[0]!.month, range[0]!.day, 24, 0, 0, 0); + // + // var lastDate = DateTime(range[1]!.year, range[1]!.month, range[1]!.day, 23, 0, 0, 0); + // + // dp("Las date", lastDate); + // + // accountStatement.value = accountStatement.where((e) { + // DateTime date = DateTime.parse(e.drSgtGntrdate); + // + // dp("Date 1", date); + // + // return date.isAfter(firstDate) && date.isBefore(lastDate); + // }).toList(); + // } + + void showDateRangePic() async { + accountStatement.assignAll(allAccountStatement); + + var range = await DatePicker.showRangeDatePicker(); + + if (range == null) { + // User clicked Cancel, do nothing + return; + } + + if (range.isEmpty || range.length != 2 || range[0] == null || range[1] == null) { + // Show error message if the range is not properly selected + Toasty.error("Please select both start and end dates."); + return; + } + + dp("Date range", range[0]); + dp("Date range", range[1]); + + var firstDate = DateTime(range[0]!.year, range[0]!.month, range[0]!.day, 0, 0, 0, 0); + var lastDate = DateTime(range[1]!.year, range[1]!.month, range[1]!.day, 23, 59, 59, 999); + + + // var currentDate = DateTime.now(); + // if (lastDate.isAfter(currentDate) || !lastDate.isAtSameMomentAs(currentDate)) { + // // Show error message if the to date is after the current date (excluding current date) + // Toasty.error("Please select a date range up to the current date."); + // return; + // } + + + dp("First date", firstDate); + dp("Last date", lastDate); + + accountStatement.value = accountStatement.where((e) { + DateTime date = DateTime.parse(e.drSgtGntrdate); + dp("Transaction date", date); + return date.isAfter(firstDate.subtract(Duration(milliseconds: 1))) && date.isBefore(lastDate.add(Duration(milliseconds: 1))); + }).toList(); + } + + +} diff --git a/lib/app/modules/account_statement/views/account_statement_view.dart b/lib/app/modules/account_statement/views/account_statement_view.dart new file mode 100644 index 0000000..8388b4e --- /dev/null +++ b/lib/app/modules/account_statement/views/account_statement_view.dart @@ -0,0 +1,145 @@ +import 'package:animated_toggle_switch/animated_toggle_switch.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/account_statement/views/shared/account_Statement_widget.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_no_record.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/account_statement_controller.dart'; + +class AccountStatementView extends GetView { + const AccountStatementView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textAccountStatement), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Obx(() { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + controller.depositAccountField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}depositAccountField"), + controller: FormFieldConstants.instance().getController("${className}depositAccountField"), + labelText: "Select From Account", + suffixIcon: const Icon(Icons.keyboard_arrow_down, size: 25), + isDropDown: true, + hintText: "Select from account", + dropDownType: DropDownType.SPECIAL, + items: controller.allDepositAccounts, + inputColor: Colors.black, + onItemSelected: (item) { + controller.updateSelectedDeposit(item!); + }, + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textStatementDetails, + ), + style: Theme.of(context).textTheme.titleSmall!.copyWith(fontSize: 14, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 15), + Row( + children: [ + Expanded( + flex: 10, + child: AnimatedToggleSwitch.size( + height: 30, + current: controller.selectedIndex.value, + style: ToggleStyle( + backgroundColor: AppColors.colorGrey350, + indicatorColor: AppColors.white, + borderColor: Colors.transparent, + borderRadius: BorderRadius.circular(10.0), + indicatorBorderRadius: const BorderRadius.only(topRight: Radius.circular(8.0), topLeft: Radius.circular(8.0), bottomRight: Radius.circular(8.0), bottomLeft: Radius.circular(8.0)), + ), + values: const [0, 1, 2, 3], + iconOpacity: 1.0, + selectedIconScale: 1.0, + indicatorSize: const Size.fromWidth(double.infinity), + iconAnimationType: AnimationType.onHover, + styleAnimationType: AnimationType.onHover, + spacing: 10.0, + customSeparatorBuilder: (context, local, global) { + final opacity = ((global.position - local.position).abs() - 0.5).clamp(0.0, 1.0); + return VerticalDivider( + indent: 10.0, + endIndent: 10.0, + color: Colors.white38.withOpacity(opacity), + ); + }, + customIconBuilder: (context, local, global) { + final text = const ['ALL', 'D', 'W', 'M', 'Y'][local.index]; + return Center( + child: Text( + text, + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.w400, + color: Color.lerp(Colors.black, AppColors.black, local.animationValue), + ), + ), + ); + }, + borderWidth: 0.0, + onChanged: (i) { + controller.updateRange(i); + }, + ), + ), + const SizedBox(width: 10), + GestureDetector( + onTap: () { + controller.showDateRangePic(); + }, + child: Container( + height: 30, + width: 30, + padding: const EdgeInsets.all(7.0), + decoration: const BoxDecoration( + color: AppColors.colorGrey350, + borderRadius: BorderRadius.only(topRight: Radius.circular(8.0), topLeft: Radius.circular(8.0), bottomRight: Radius.circular(8.0), bottomLeft: Radius.circular(8.0)), + ), + child: SvgPicture.asset(AppAssets.ic_filter_statement), + ), + ), + ], + ), + const SizedBox(height: 15), + controller.accountStatement.isNotEmpty + ? Expanded( + child: ListView.builder( + itemCount: controller.accountStatement.length, + itemBuilder: (context, index) { + return AccountStatementWidget( + onTap: () {}, + statment: controller.accountStatement[index], + ); + }, + ), + ) + : const Center( + child: CustomNoRecord(title: "No Record Found", description: "We couldn't find any activity at this moment"), + ), + ], + ), + ); + })); + } +} diff --git a/lib/app/modules/account_statement/views/shared/account_Statement_widget.dart b/lib/app/modules/account_statement/views/shared/account_Statement_widget.dart new file mode 100644 index 0000000..d150f36 --- /dev/null +++ b/lib/app/modules/account_statement/views/shared/account_Statement_widget.dart @@ -0,0 +1,134 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../../models/accountStatementResponseModel.dart'; +import '../../../../res/app_colors.dart'; +import '../../controllers/account_statement_controller.dart'; + +class AccountStatementWidget extends StatefulWidget { + // bool isCredit = false; + // String transactionAmount = ""; + // String transactionDate = ""; + // String accountBalance = ""; + // String transactionDetail = ""; + final AccountStatementResponseModel statment; + final Function()? onTap; + + const AccountStatementWidget({ + Key? key, + required this.statment, + this.onTap, + }) : super(key: key); + + @override + State createState() => _AccountStatementWidgetState(); +} + +class _AccountStatementWidgetState extends State { + // + + AccountStatementController accountStatementController = Get.find(); + + bool isExpanded = false; + + bool isDr(AccountStatementResponseModel statment) { + if (statment.drMbmBkmsnumber == accountStatementController.selectedDepositAccount.value.mbmBkmsnumber) { + return true; + } else { + return false; + } + } + + IconData statementIcon(AccountStatementResponseModel statment) { + if (statment.batAcnttranReversed) { + return Icons.redo; + } else if (statment.drMbmBkmsnumber == accountStatementController.selectedDepositAccount.value.mbmBkmsnumber) { + return Icons.arrow_upward_outlined; + } else { + return Icons.arrow_downward_outlined; + } + } + + Color statementColor(AccountStatementResponseModel statment) { + if (statment.batAcnttranReversed) { + return AppColors.colorGrey400; + } else if (statment.drMbmBkmsnumber == accountStatementController.selectedDepositAccount.value.mbmBkmsnumber) { + return AppColors.red; + } else { + return AppColors.colorButton; + } + } + @override + Widget build(BuildContext context) { + var statment = widget.statment; + return InkWell( + onTap: widget.onTap, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 3.0, horizontal: 3.0), + child: Card( + color: Colors.white, + elevation: 2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + child: ExpansionTile( + dense: false, + onExpansionChanged: (value) { + // accountStatementController.toggleExpansion(value); + isExpanded = value; + setState(() {}); + }, + maintainState: true, + //expandedAlignment: Alignment.topLeft, + expandedCrossAxisAlignment: CrossAxisAlignment.start, + childrenPadding: const EdgeInsets.only(left: 12, right: 10, bottom: 10), + tilePadding: const EdgeInsets.all(8.0), + collapsedShape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + collapsedBackgroundColor: AppColors.white, + shape: const Border(), + backgroundColor: AppColors.white, + expandedAlignment: Alignment.centerLeft, + leading: SizedBox( + height: 35, + width: 35, + child: CircleAvatar(backgroundColor: statementColor(statment) /*colorPrimary.withOpacity(0.7)*/, child: Padding(padding: EdgeInsets.all(2.0), child: Icon(color: AppColors.white, statementIcon(statment)))), + ), + trailing: isExpanded + ? const SizedBox() + : Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text("${statment.drPcrCurrshort} ${statment.sgtGntramt}", style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text("${isDr(statment) ? statment.drPcrCurrshort : statment.crPcrCurrshort} ${isDr(statment) ? statment.drMbmBkmsbalance : statment.crMbmBkmsbalance}", style: Theme.of(context).textTheme.bodySmall), + ], + ), + title: isExpanded + ? const SizedBox() + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(isDr(statment) ? statment.crMbmBkmstitle.toString() : statment.drmbmBkmstitle.toString(), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text(statment.drSgtGntrdate.toString().isEmpty ? "0" : statment.drSgtGntrdate.toString(), style: Theme.of(context).textTheme.bodySmall), + ], + ), + children: [ + Text("Amount: ${statment.drPcrCurrshort} ${statment.sgtGntramt.toString()}", style: Theme.of(context).textTheme.labelMedium!.copyWith(fontSize: 14, color: AppColors.colorTitle)), + const SizedBox(height: 5), + Text("Transaction-ID: ${statment.sgtSentGntrnumber.toString()}${statment.sgtSentNodeId}", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 5), + Text("Date: ${statment.drSgtGntrdate.toString().isEmpty ? "0" : statment.drSgtGntrdate.toString()}", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 5), + Text("${isDr(statment) ? "Receiver: " : "Sender: "} ${isDr(statment) ? statment.crMbmBkmstitle : statment.drmbmBkmstitle}", style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 3), + Text("Running-Balance: ${isDr(statment) ? statment.drPcrCurrshort : statment.crPcrCurrshort} ${isDr(statment) ? statment.drMbmBkmsbalance : statment.crMbmBkmsbalance}", style: Theme.of(context).textTheme.labelMedium!.copyWith(color: AppColors.colorTitle)), + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/add_money/bindings/add_money_binding.dart b/lib/app/modules/add_money/bindings/add_money_binding.dart new file mode 100644 index 0000000..c542028 --- /dev/null +++ b/lib/app/modules/add_money/bindings/add_money_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/add_money_controller.dart'; + +class AddMoneyBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AddMoneyController(), + ); + } +} diff --git a/lib/app/modules/add_money/bindings/add_money_otp_binding.dart b/lib/app/modules/add_money/bindings/add_money_otp_binding.dart new file mode 100644 index 0000000..941d958 --- /dev/null +++ b/lib/app/modules/add_money/bindings/add_money_otp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; +import '../controllers/add_money_otp_controller.dart'; + + +class AddMoneyOTPBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AddMoneyOTPController(), + ); + } +} diff --git a/lib/app/modules/add_money/bindings/payment_method_binding.dart b/lib/app/modules/add_money/bindings/payment_method_binding.dart new file mode 100644 index 0000000..0e4357b --- /dev/null +++ b/lib/app/modules/add_money/bindings/payment_method_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; +import '../controllers/payment_method_controller.dart'; + + +class PaymentMethodBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => PaymentMethodController(), + ); + } +} \ No newline at end of file diff --git a/lib/app/modules/add_money/controllers/add_money_controller.dart b/lib/app/modules/add_money/controllers/add_money_controller.dart new file mode 100644 index 0000000..26a434f --- /dev/null +++ b/lib/app/modules/add_money/controllers/add_money_controller.dart @@ -0,0 +1,283 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/add_money/controllers/payment_method_controller.dart'; + + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/Fields/field_validations.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/evaluated_cuency_model.dart'; +import '../../../models/product_model.dart'; +import '../../../routes/app_pages.dart'; +import '../views/shared/account_list_screen.dart'; + +class AddMoneyController extends GetxController { + final repository = Get.find(); + var paymnetController = Get.put(PaymentMethodController()); + TextEditingController recipientController = TextEditingController(); + TextEditingController pinPutController = TextEditingController(); + + Rx selectRecepientAccount = Rx(DepositAccount.empty()); + + List currencyList = []; + List allCurrencyList = []; + Rx selectedFromAccountCurrency = Rx(ProductDepositModel(porOrgacode: "", dmpProdcode: "", dmpProddesc: "", dmpProdshort: "", pcrCurrcode: "", dmpProdactive: false)); + + Rx evaluatedCurrencyModel = EvaluatedCurrencyModel.empty().obs; + + late InputField amountFeild; + + // late InputField convertedFeild; + + late InputField searchCurrency; + + late InputField searchAccount; + + List accountList = List.from(SessionCache.instance.depositAccountList); + + List allAccountList = List.from(SessionCache.instance.depositAccountList); + + @override + void onInit() { + getCurrencyList(); + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + + update(); + + amountFeild.clear(); + } + + @override + void dispose() { + amountFeild.clear(); + super.dispose(); + } + + searchCurrencyM() { + Future.delayed(const Duration(seconds: 1)).then( + (value) { + searchCurrency.clear(); + update(); + searchCurrency.controller!.addListener( + () { + searchCurrencyMethod(); + }, + ); + }, + ); + } + + searchAccountInit() { + Future.delayed(const Duration(seconds: 1)).then( + (value) { + searchAccount.clear(); + update(); + searchAccount.controller!.addListener( + () { + searchAccountMethod(); + }, + ); + }, + ); + } + + void updateReceipentAccount(DepositAccount e) { + selectRecepientAccount.value = e; + update(); + } + + void updateFromAccountCurrency(ProductDepositModel fromAccountCurrecncy) { + selectedFromAccountCurrency.value = fromAccountCurrecncy; + update(); + } + + void showDialog(BuildContext context) { + CustomDialog.showSuccessDialog( + description: "Thank you so much, your payment has been added.", + onTapPositive: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.offAndToNamed(Routes.DASHBOARD_SCREEN); + }); + } + + String getFlagWithCurrencyCode(String currencyCode) { + int currencyCodeInt = int.tryParse(currencyCode) ?? 0; + + if (currencyCodeInt == 586) { + return "assets/uco/icons/ic_pakistan.png"; + } else if (currencyCodeInt == 997) { + return "assets/uco/icons/usa.png"; + } else if (currencyCodeInt == 978) { + return "assets/uco/icons/euro_flag.png"; + } else { + return ""; + } + } + + getConversionAmount() async { + if (!validate()) { + return; + } + + if (selectRecepientAccount.value.pcrCurrcode.isEmpty) { + // Toasty.error("Please select recipient currency"); + return; + } + + var converionResponce = await repository.getConvertedCurrency( + selectedFromAccountCurrency.value.pcrCurrcode, + selectRecepientAccount.value.pcrCurrcode, + amountFeild.getCustomText(), + ); + + if (converionResponce.isError) { + Toasty.error(converionResponce.errorMsg); + return; + } + evaluatedCurrencyModel.value = EvaluatedCurrencyModel.fromMap(converionResponce.response); + recipientController.text = evaluatedCurrencyModel.value.sgtGntramtfc.toStringAsFixed(2); + } + + getCurrencyList() async { + // + var responce = await repository.getCurrencyList(); + if (responce.isError) { + Toasty.error(responce.errorMsg); + return; + } + currencyList = ProductDepositModel.productListFromJson(responce.response); + allCurrencyList.addAll(currencyList); + selectedFromAccountCurrency.value = currencyList.first; + + selectRecepientAccount.value = accountList.first; + update(); + } + + bool validate() { + if (selectRecepientAccount.value.pcrCurrcode.isEmpty || paymnetController.paymentMethod.value.title.isEmpty || paymnetController.paymentMethod.value.title.isEmpty) { + return false; + } + return FieldValidation.validateAll([amountFeild]); + } + + bool checkForNull() { + if (evaluatedCurrencyModel.value.pcrCurrcode == null || evaluatedCurrencyModel.value.serviceCharges == null || evaluatedCurrencyModel.value.sgtGntramtfc == null || evaluatedCurrencyModel.value.targetPerEratrateact == null) { + return true; + } + return false; + } + + Future navigateToNextScreen() async { + // if (!validate()) { + // if (amountFeild.getCustomText().trim().isEmpty) { + // Toasty.error("Please Input amount and then proceed"); + // return; + // } + // if (paymnetController.paymentMethod.value.title.isEmpty) { + // Toasty.error("Please select payment method and then proceed"); + // return; + // } + // } + await getConversionAmount(); + // GLACCAddMoneyRequestModel requestModel = GLACCAddMoneyRequestModel( + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // channelCode: RequestConstants.channelCode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // drPcaGlaccode: "", + // drPcaGlacdesc: "", + // crMbmBkmsnumber: selectRecepientAccount.value.mbmBkmsnumber, + // crMbmBkmstitle: selectRecepientAccount.value.mbmBkmstitle, + // crPcrCurrcode: selectRecepientAccount.value.pcrCurrcode, + // crPcrCurrdesc: selectRecepientAccount.value.pcrCurrdesc, + // crPcrCurrshort: selectRecepientAccount.value.pcrCurrshort, + // sgtGntrnarration: "", + // dmpProdCode: selectRecepientAccount.value.dmpProdcode, + // notificationId: "", + // transMode: "Online", + // sgtGntramtfc: double.parse(recipientController.text.isEmpty ? "0.0" : recipientController.text), + // otdTrancomment: "", + // obpPincode: "", + // transType: "", + // pinType: "", + // ); + + // TransactionPinRequestModel transactionPinRequestModel = TransactionPinRequestModel( + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // channelCode: RequestConstants.channelCode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // email: SessionCache.instance.userInfo.cmpUserId, + // pinType: "TRAN", + // transPincode: userTransactionPinField.getCustomText(), + // isOtpRequired: false, + // ); + + Get.toNamed( + Routes.GENERAL_LEDGER, + // arguments: { + // AppConstants.SEND_TRANS_STEP1_DATA: requestModel, + // AppConstants.EXCHANGE_RATE: evaluatedCurrencyModel.value, + // }, + ); + } + + void selectFromAccountCurrency() { + Get.to(() => AccountListScreen())!.then( + (value) { + getConversionAmount(); + }, + ); + } + + void searchCurrencyMethod() async { + var search = searchCurrency.getCustomText().toLowerCase(); + currencyList.clear(); + update(); + // await Future.delayed(Duration(milliseconds: 100)); + if (search.isNotEmpty) { + currencyList = allCurrencyList + .where( + (element) => element.dmpProddesc.toLowerCase().contains(search) || element.dmpProdshort.toLowerCase().contains(search) || element.dmpProddesc.toLowerCase().contains(search), + ) + .toList(); + } else { + currencyList.addAll(allCurrencyList); + } + + update(); + } + + void searchAccountMethod() async { + // + + var accountText = searchAccount.getCustomText().toLowerCase(); + + accountList.clear(); + + update(); + + if (accountText.isNotEmpty) { + // + + accountList = allAccountList + .where( + (element) => element.mbmBkmsnumber.toLowerCase().contains(accountText) || element.dmpProddesc.toLowerCase().contains(accountText) || element.pcrCurrcode.toLowerCase().contains(accountText) || element.mbmBkmstitle.toLowerCase().contains(accountText), + ) + .toList(); + } else { + accountList.addAll(allAccountList); + } + + update(); + } +} diff --git a/lib/app/modules/add_money/controllers/add_money_otp_controller.dart b/lib/app/modules/add_money/controllers/add_money_otp_controller.dart new file mode 100644 index 0000000..e2301fb --- /dev/null +++ b/lib/app/modules/add_money/controllers/add_money_otp_controller.dart @@ -0,0 +1,91 @@ +import 'package:flutter/cupertino.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../routes/app_pages.dart'; +import '../../general_ledger/controllers/general_ledger_controller.dart'; + + +class AddMoneyOTPController extends GetxController { + final AppRepositories repository = Get.find(); + + TextEditingController pinPutController = TextEditingController(); + + RxBool isResend = false.obs; + + CountdownController countdownController = + CountdownController(autoStart: true); + + // GLACCAddMoneyRequestModel transactionSubmitRequestModel = + // GLACCAddMoneyRequestModel.empty(); + // Rx evaluatedCurrencyModel = + // EvaluatedCurrencyModel.empty().obs; + + // @override + // void onInit() { + // super.onInit(); + // var arguments = Get.arguments; + // transactionSubmitRequestModel = (arguments != null + // ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? + // GLACCAddMoneyRequestModel.empty() + // : GLACCAddMoneyRequestModel.empty()); + // evaluatedCurrencyModel.value = (arguments != null + // ? arguments[AppConstants.EXCHANGE_RATE] ?? + // EvaluatedCurrencyModel.empty() + // : EvaluatedCurrencyModel.empty()); + // } + + Future validatePinAndNavigate() async { + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + // transactionSubmitRequestModel + // transactionSubmitRequestModel.pinType = "TRAN"; + // transactionSubmitRequestModel.obpPincode = pinPutController.text; + sendTransaction(); + } + + Future sendTransaction() async { + // ServerResponse response = + // await repository.sendAddMoneyTransaction(transactionSubmitRequestModel); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + Get.find().clearAll(); + + + + CustomDialog.showSuccessDialog( + title: "Congratulations!", + description: "Thank you so much, your payment has been added.", + onTapPositive: () { + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }); + } + + void resenOtp() async { + // + + if (!isResend.value) { + Fluttertoast.showToast(msg: "Please wait for 1 minute"); + return; + } + isResend.value = false; + countdownController.restart(); + Fluttertoast.showToast(msg: "OTP successfully send to your email address"); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/add_money/controllers/payment_method_controller.dart b/lib/app/modules/add_money/controllers/payment_method_controller.dart new file mode 100644 index 0000000..aa5141d --- /dev/null +++ b/lib/app/modules/add_money/controllers/payment_method_controller.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/constants/app_assets.dart'; +import '../../../res/app_colors.dart'; + + +class PaymentMethodController extends GetxController { + List paymentList = [ + PaymentMethod( + title: "Debit Card", + image: AppAssets.ic_debit_card, + content: + "10.78 GBP fee, so recipient gets 340839.71 PKR. Should arrive in seconds", + icon: const Icon(Icons.arrow_forward_ios_outlined, + size: 15, color: AppColors.colorGrey600)), + PaymentMethod( + title: "Credit Card", + image: AppAssets.ic_debit_card, + content: + "10.78 GBP fee, so recipient gets 340839.71 PKR. Should arrive in seconds", + icon: const Icon(Icons.arrow_forward_ios_outlined, + size: 15, color: AppColors.colorGrey600)), + PaymentMethod( + title: "Bank Transfer", + image: AppAssets.ic_bank, + content: + "6.63 GBP fee, so recipient gets 342269.61 PKR. Should arrive in seconds", + icon: const Icon(Icons.arrow_forward_ios_outlined, + size: 15, color: AppColors.colorGrey600)), + ]; + + Rx paymentMethod = Rx( + PaymentMethod(image: "", title: "", content: "", icon: Icon(Icons.abc))); + + updatePaymentMethod(PaymentMethod p) { + paymentMethod.value = p; + Get.back(); + } +} + +class PaymentMethod { + String title; + String content; + Icon icon; + String image; + + PaymentMethod( + {required this.image, + required this.title, + required this.content, + required this.icon}); +} diff --git a/lib/app/modules/add_money/views/add_money_view.dart b/lib/app/modules/add_money/views/add_money_view.dart new file mode 100644 index 0000000..c07d23b --- /dev/null +++ b/lib/app/modules/add_money/views/add_money_view.dart @@ -0,0 +1,278 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/add_money/views/shared/currency_list_screen.dart'; +import 'package:uco_mobile_poc/app/modules/add_money/views/shared/payment_method_view.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_theme.dart'; +import '../controllers/add_money_controller.dart'; + +class AddMoneyView extends GetView { + const AddMoneyView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + // + String className = runtimeType.toString().split('.').last; + + return Scaffold( + appBar: DashBoardAppBar( + title: "Add Money", + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.only(left: 20, right: 30, bottom: 10), + child: CustomButton( + onPressed: () { + controller.navigateToNextScreen(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.only(top: 12, bottom: 12), + ), + ) + ], + body: Padding( + padding: const EdgeInsets.only(left: 20, right: 20, top: 20), + child: SingleChildScrollView( + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text("You send exactly"), + const SizedBox(height: 8), + controller.amountFeild = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}amountFeild"), + controller: FormFieldConstants.instance().getController("${className}amountFeild"), + hintText: "Enter amount", + radius: 10, + inputFontSize: 20.0, + inputColor: AppColors.black, + inputFontWeight: FontWeight.w600, + keyboardType: const TextInputType.numberWithOptions(decimal: true), + inputFormatters: InputType.maxValueFilter(InputType.INT_MAX_VALUE_, true, 2), + isTopMarginRequired: false, + showLabel: false, + textInputAction: TextInputAction.done, + onChanged: (value) { + Future.delayed(const Duration(milliseconds: 500), () => controller.getConversionAmount()); + }, + onSubmitted: (value) { + controller.getConversionAmount(); + }, + suffixIcon: GestureDetector( + onTap: () { + controller.selectFromAccountCurrency(); + }, + child: Container( + color: AppColors.transparent, + child: SizedBox( + width: 130, + height: 60, + child: Row( + children: [ + // Image.asset(controller.getFlagWithCurrencyCode(controller.selectedFromAccountCurrency.value.pcrCurrcode), width: 22), + // const SizedBox(width: 6), + // Text( + // controller.selectedFromAccountCurrency.value.dmpProdshort, + // style: context.textTheme.bodyMedium!.copyWith(fontSize: 16, color: AppColors.colorPrimary, fontWeight: FontWeight.w600), + // ), + const SizedBox(width: 105), + Image.asset(AppAssets.drop_down_ic, width: 10, height: 10), + const SizedBox(width: 6), + ], + ), + ), + ), + ), + ), + const SizedBox(height: 17), + Text( + "Paying with", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.colorTitle), + ), + const SizedBox(height: 8), + InkWell( + onTap: () { + Get.to(() => const PaymentMethodView())!.then( + (value) { + controller.getConversionAmount(); + }, + ); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + color: AppColors.colorGrey200, + ), + padding: const EdgeInsets.only(left: 13, top: 17, bottom: 17, right: 15), + child: Row( + children: [ + Text( + controller.paymnetController.paymentMethod.value.title.isNotEmpty ? TranslationKeys.makeTranslation(controller.paymnetController.paymentMethod.value.title) : "Select a payment method", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 15, fontWeight: FontWeight.w500, color: AppColors.F0F0D), + ), + const Spacer(), + Card( + elevation: 0.0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50), side: BorderSide(color: AppColors.CFCFCF)), + child: Padding( + padding: const EdgeInsets.only( + left: 15, + right: 15, + top: 5, + bottom: 5, + ), + child: Center( + child: Text( + "Select", + style: context.textTheme.bodyLarge!.copyWith(fontSize: 11, fontWeight: FontWeight.w500), + ), + ), + ), + ), + ], + ), + ), + ), + const SizedBox(height: 17), + Text( + "Recipient Get", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.colorTitle), + ), + const SizedBox(height: 8), + Container( + height: 60, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: const BorderRadius.all(Radius.circular(10)), + border: Border.all(color: AppColors.colorGrey500, width: 1.5), + ), + child: Row( + // mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 4, + child: TextField( + style: AppThemeData.inputStyle.copyWith(height: 1, fontSize: 20.0, fontWeight: FontWeight.w600, color: AppColors.black), + controller: controller.recipientController, + decoration: const InputDecoration(border: InputBorder.none), + enabled: false, + ), + ), + GestureDetector( + onTap: () { + Get.to(() => CurrencyListScreen())!.then( + (value) { + controller.getConversionAmount(); + }, + ); + }, + child: Container( + color: Colors.transparent, + child: Row( + children: [ + Image.asset( + controller.getFlagWithCurrencyCode(controller.selectRecepientAccount.value.pcrCurrcode), + width: 22, + errorBuilder: (context, error, stackTrace) => const SizedBox(), + ), + const SizedBox(width: 6), + Text(controller.selectRecepientAccount.value.pcrCurrshort, style: context.textTheme.bodyMedium!.copyWith(fontSize: 16, color: AppColors.colorPrimary, fontWeight: FontWeight.w500)), + const SizedBox(width: 6), + Image.asset(AppAssets.drop_down_ic, width: 10, height: 10), + const SizedBox(width: 15), + ], + ), + ), + ), + ], + ), + ), + const SizedBox(height: 15), + ...(controller.checkForNull()) + ? [] + : [ + detailsTile(controller.evaluatedCurrencyModel.value.serviceCharges.toString(), "Our fee"), + + detailsTile(controller.evaluatedCurrencyModel.value.sgtGntramtfc!.toString(), "Total amount we’ll convert"), + + //{"title": "344.598", "subtitle": ""}, + detailsTile( + controller.evaluatedCurrencyModel.value.targetPerEratrateact.toString(), + "Guaranteed exchange rate (2h)", + subTitleStyle: Get.context?.textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.colorPrimary, decoration: TextDecoration.underline), + ), + const SizedBox(height: 35), + Text( + "Usually arrives in seconds. Because this is your first transfer, things may take a little longer.", + style: context.textTheme.bodyMedium!.copyWith( + fontSize: 15, + fontWeight: FontWeight.w400, + ), + ), + const SizedBox(height: 20), + ], + ], + ); + }), + ), + ), + ); + } + + Widget detailsTile(String title, String subTitle, {TextStyle? subTitleStyle}) { + return Padding( + padding: const EdgeInsets.only(top: 20), + child: Row( + children: [ + Container( + width: 13, + height: 13, + decoration: BoxDecoration(color: AppColors.colorTitle, borderRadius: BorderRadius.circular(20)), + ), + const SizedBox(width: 6), + Text( + title, + style: Get.context?.textTheme.bodyMedium!.copyWith( + fontSize: 14, + fontWeight: FontWeight.w700, + ), + ), + const Spacer(), + Text( + subTitle, + style: subTitleStyle ?? + Get.context?.textTheme.bodyMedium!.copyWith( + fontSize: 14, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ); + } +} + +showCurrencyBtm() { + Get.bottomSheet( + Container( + decoration: BoxDecoration(color: Colors.white, border: Border.all(color: AppColors.colorGrey800, width: 1), borderRadius: const BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30))), + margin: const EdgeInsets.only(left: 20, right: 20), + child: const Text("data"), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); +} diff --git a/lib/app/modules/add_money/views/shared/account_list_screen.dart b/lib/app/modules/add_money/views/shared/account_list_screen.dart new file mode 100644 index 0000000..5209a72 --- /dev/null +++ b/lib/app/modules/add_money/views/shared/account_list_screen.dart @@ -0,0 +1,118 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../../core/constants/form_field_constants.dart'; +import '../../../../custom_widgets/Fields/input_field.dart'; +import '../../../../custom_widgets/custom_app_bar.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../routes/app_pages.dart'; +import '../../controllers/add_money_controller.dart'; + +class AccountListScreen extends StatefulWidget { + AccountListScreen({super.key}); + + @override + State createState() => _AccountListScreenState(); +} + +class _AccountListScreenState extends State { + @override + void initState() { + Get.find().searchAccountInit(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return responsiveWidget( + Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only( + left: 20, + right: 20, + top: 20, + ), + child: GetBuilder(builder: (controller) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Choose account", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 15, fontWeight: FontWeight.w500, color: AppColors.titleColor), + ), + const SizedBox(height: 8), + const Divider(color: Colors.grey), + const SizedBox(height: 8), + controller.searchAccount = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}searchAccount"), + controller: FormFieldConstants.instance().getController("${className}searchAccount"), + hintText: "Search for a account", + prefixIcon: const Icon(Icons.search), + isDropDown: false, + showLabel: false, + isTopMarginRequired: false, + ), + const SizedBox(height: 8), + const Divider(color: Colors.grey), + const SizedBox(height: 8), + ...controller.currencyList + .map((e) => InkWell( + onTap: () { + controller.updateFromAccountCurrency(e); + Get.back(); + }, + child: currencyTile(e.dmpProdshort, "${e.dmpProddesc} (${e.dmpProdcode})", controller.getFlagWithCurrencyCode(e.pcrCurrcode)))) + .toList(), + ], + ); + }), + ), + ), + ), + ); + } + + Widget currencyTile(String title, String subTitle, String flag) { + return Padding( + padding: const EdgeInsets.only(top: 0), + child: SizedBox( + height: 60, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Image.asset( + flag, + height: 40, + width: 40, + ), + const SizedBox(width: 12), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: Get.context!.textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 2), + Text( + subTitle, + style: Get.context!.textTheme.bodyMedium!.copyWith(fontSize: 12, fontWeight: FontWeight.w400), + ), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/add_money/views/shared/currency_list_screen.dart b/lib/app/modules/add_money/views/shared/currency_list_screen.dart new file mode 100644 index 0000000..918f31e --- /dev/null +++ b/lib/app/modules/add_money/views/shared/currency_list_screen.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../../core/constants/form_field_constants.dart'; +import '../../../../core/utils/logs_utils.dart'; +import '../../../../custom_widgets/Fields/input_field.dart'; +import '../../../../custom_widgets/custom_app_bar.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../routes/app_pages.dart'; +import '../../controllers/add_money_controller.dart'; + +class CurrencyListScreen extends StatefulWidget { + CurrencyListScreen({super.key}); + + @override + State createState() => _CurrencyListScreenState(); +} + +class _CurrencyListScreenState extends State { + + @override + void initState() { + Get.find().searchCurrencyM(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return responsiveWidget( + Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: GetBuilder(builder: (controller) { + return Padding( + padding: const EdgeInsets.only( + left: 20, + right: 30, + top: 20, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Choose a currency", + style: context.textTheme.bodyMedium!.copyWith( + fontSize: 18, + fontWeight: FontWeight.w500, + color: AppColors.titleColor), + ), + const SizedBox(height: 14), + controller.searchCurrency = InputField( + refKey: FormFieldConstants.instance() + .getFormKey("${className}searchCurrency"), + controller: FormFieldConstants.instance() + .getController("${className}searchCurrency"), + hintText: "Search for a currency / country", + prefixIcon: const Icon(Icons.search), + isDropDown: false, + showLabel: false, + isTopMarginRequired: false, + ), + const SizedBox(height: 18), + Text( + "Popular currencies", + style: context.textTheme.bodyMedium!.copyWith( + fontSize: 14, + fontWeight: FontWeight.w400, + color: AppColors.colorTitle, + ), + ), + const Divider(color: Colors.grey), + ...controller.allAccountList + .map((e) => InkWell( + onTap: () { + dp("Click popular", "arg"); + controller.updateReceipentAccount(e); + Get.back(); + }, + child: currencyTile( + e.mbmBkmstitle, e.dmpProddesc, e.pcrCurrcode))) + .toList(), + ], + ), + ); + }), + ), + ); + } + + Widget currencyTile(String title, String subTitle, String flag) { + return Padding( + padding: const EdgeInsets.only(top: 0), + child: SizedBox( + height: 60, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Image.asset( + Get.find().getFlagWithCurrencyCode(flag), + height: 40, + width: 40, + ), + const SizedBox(width: 12), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: Get.context!.textTheme.bodyMedium! + .copyWith(fontSize: 14, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 2), + Text( + subTitle, + style: Get.context!.textTheme.bodyMedium! + .copyWith(fontSize: 12, fontWeight: FontWeight.w400), + ), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/add_money/views/shared/otp_add_money.dart b/lib/app/modules/add_money/views/shared/otp_add_money.dart new file mode 100644 index 0000000..7bf1801 --- /dev/null +++ b/lib/app/modules/add_money/views/shared/otp_add_money.dart @@ -0,0 +1,155 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + + +import '../../../../core/constants/app_assets.dart'; +import '../../../../core/constants/translation_keys.dart'; +import '../../../../custom_widgets/custom_app_bar.dart'; +import '../../../../custom_widgets/custom_button.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../res/app_dimensions.dart'; +import '../../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../../controllers/add_money_otp_controller.dart'; + +class AddMoneyOTPView extends GetView { + const AddMoneyOTPView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + //title: TranslationKeys.makeTranslation(TranslationKeys.textUReceived), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric( + horizontal: AppDimensions.screenHorizontalPadding, + vertical: AppDimensions.screenVerticalPadding), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textOTPDescription), + style: + Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + textInputAction: TextInputAction.done, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric( + vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textOTPValid), + style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, + height: 20, width: 20), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle( + fontSize: 12, + ), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.resenOtp(); + }, + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value + ? AppColors.colorPrimary + : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: + TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 0), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/add_money/views/shared/payment_method_view.dart b/lib/app/modules/add_money/views/shared/payment_method_view.dart new file mode 100644 index 0000000..4025311 --- /dev/null +++ b/lib/app/modules/add_money/views/shared/payment_method_view.dart @@ -0,0 +1,191 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + +import '../../../../core/constants/app_assets.dart'; +import '../../../../core/constants/translation_keys.dart'; +import '../../../../custom_widgets/custom_app_bar.dart'; +import '../../../../res/app_colors.dart'; +import '../../controllers/payment_method_controller.dart'; + + +class PaymentMethodView extends GetView { + const PaymentMethodView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + //title: TranslationKeys.makeTranslation(TranslationKeys.transUtilityBillCategory), + onBackButtonPressed: () { + Navigator.of(context).pop(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textHowdoyouwanttopay), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 16, color: AppColors.black)), + const SizedBox(height: 30), + Row( + children: [ + Align( + alignment: Alignment.topLeft, + child: Container( + height: 30, + width: 30, + decoration: const BoxDecoration( + color: AppColors.colorGrey300, + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset(AppAssets.ic_debit_card), + ), + ), + Expanded( + flex: 6, + child: Padding( + padding: const EdgeInsets.only(left: 10.0), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textDebitCard), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 16, color: AppColors.colorGrey900)), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textDebitCardContent), style: Theme.of(context).textTheme.bodySmall), + ]), + ), + ), + //const Spacer(), + const Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey600)], + ), + ), + ], + ), + const SizedBox(height: 30), + Row( + children: [ + Align( + alignment: Alignment.topLeft, + child: Container( + height: 30, + width: 30, + decoration: const BoxDecoration( + color: AppColors.colorGrey300, + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset(AppAssets.ic_debit_card), + ), + ), + Expanded( + flex: 6, + child: Padding( + padding: const EdgeInsets.only(left: 10.0), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textCreditCard), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 16, color: AppColors.colorGrey900)), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textDebitCardContent), style: Theme.of(context).textTheme.bodySmall), + ]), + ), + ), + //const Spacer(), + const Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey600)], + ), + ), + ], + ), + const SizedBox(height: 30), + InkWell( + onTap: () {}, + child: Row( + children: [ + Align( + alignment: Alignment.topLeft, + child: Container( + height: 30, + width: 30, + decoration: const BoxDecoration( + color: AppColors.colorGrey300, + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset(AppAssets.ic_bank_transfer), + ), + ), + Expanded( + flex: 6, + child: Padding( + padding: const EdgeInsets.only(left: 10.0), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textBankTransfer), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 16, color: AppColors.colorGrey900)), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textDebitCardContent), style: Theme.of(context).textTheme.bodySmall), + ]), + ), + ), + //const Spacer(), + const Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey600)], + ), + ), + ], + ), + ), + const SizedBox(height: 40), + Container(height: 1, width: double.infinity, color: AppColors.colorGrey350), + const SizedBox(height: 40), + InkWell( + onTap: () { + controller.updatePaymentMethod(PaymentMethod(image: AppAssets.ic_general_ledger, title: TranslationKeys.textGeneralLedger, content: "", icon: const Icon(Icons.abc))); + }, + child: Row( + children: [ + Align( + alignment: Alignment.topLeft, + child: Container( + height: 30, + width: 30, + decoration: const BoxDecoration( + color: AppColors.colorGrey300, + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset(AppAssets.ic_general_ledger), + ), + ), + Expanded( + flex: 6, + child: Padding( + padding: const EdgeInsets.only(left: 10.0), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textGeneralLedger), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 16, color: AppColors.colorGrey900)), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textDebitCardContent), style: Theme.of(context).textTheme.bodySmall), + ]), + ), + ), + //const Spacer(), + const Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey600)], + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/add_new_account/bindings/add_new_binding.dart b/lib/app/modules/add_new_account/bindings/add_new_binding.dart new file mode 100644 index 0000000..3e26b26 --- /dev/null +++ b/lib/app/modules/add_new_account/bindings/add_new_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/add_new_account_controller.dart'; + +class AddNewAccountBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AddNewAccountController(), + ); + } +} diff --git a/lib/app/modules/add_new_account/controllers/add_new_account_controller.dart b/lib/app/modules/add_new_account/controllers/add_new_account_controller.dart new file mode 100644 index 0000000..9e0a8ad --- /dev/null +++ b/lib/app/modules/add_new_account/controllers/add_new_account_controller.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/product_model.dart'; +import '../../../routes/app_pages.dart'; +import '../../dashboard/controllers/dashboard_screen_controller.dart'; + + +class AddNewAccountController extends GetxController { + BuildContext context = Get.context as BuildContext; + + late InputField currencyCodesField; + late InputField nameAddressField; + + DropDown dropDownValue = DropDown.empty(); + + List currencyList = []; + + List currencyListDropDown = []; + + final AppRepositories repository = Get.find(); + + void updateCurrency(DropDown? item) { + dropDownValue = item!; + update(); + } + + @override + void onInit() { + super.onInit(); + // getCurrencyList(); + } + + /// Validate Function of contorller + // bool validate() { + // bool isValid = FieldValidation.validateAll([nameAddressField, currencyCodesField]); + // return isValid; + // } + + /// Get Currency List Function + getCurrencyList() async { + try { + var productResponse = await repository.getCurrencyList(); + // + // if (productResponse.isError) { + // Toasty.error(productResponse.errorMsg); + // return; + // } + // + // currencyList = ProductDepositModel.productListFromJson(productResponse.response); + // + // currencyListDropDown = currencyList.map((e) => DropDown(e.dmpProdcode, e.dmpProddesc, e)).toList(); + // + // dropDownValue = currencyListDropDown.first; + // + // dp("DmpProductCode", currencyListDropDown); + + update(); + } catch (e, s) { + dp("Error in get product $e", s); + Toasty.error("Something went wrong, please try again"); + } + } + + /// New Create Account Request Function + void validateAndSendRequest() async { + // + + hideKeyBoard(); + + // if (!validate()) { + // Toasty.error("Please input and then proceed"); + // return; + // } + + // AddNewAccountRequestModel request = AddNewAccountRequestModel( + // title: nameAddressField.getCustomText(), + // porOrgacode: SessionCache.instance.userInfo.porOrgacode, + // channelCode: SessionCache.instance.userInfo.channelCode, + // dmpProdcode: dropDownValue.id, + // email: SessionCache.instance.userInfo.cmpUserId, + // ); + // + // ServerResponse response = await repository.addNewAccount(request); + // + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + + CustomDialog.showSuccessDialog( + description: "Thank you so much, Your new account has been created successfully", + onTapPositive: () { + transitionUpdate.value++; + + Navigator.of(context, rootNavigator: true).pop(); + + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }); + + clearText(); + } + + /// Clear Controller Function + clearText() { + nameAddressField.clear(); + currencyCodesField.clear(); + update(); + } +} diff --git a/lib/app/modules/add_new_account/views/add_new_account_view.dart b/lib/app/modules/add_new_account/views/add_new_account_view.dart new file mode 100644 index 0000000..427ce87 --- /dev/null +++ b/lib/app/modules/add_new_account/views/add_new_account_view.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/add_new_account_controller.dart'; + +class AddNewAccountView extends GetView { + const AddNewAccountView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + + return Scaffold( + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.only(left: 20, right: 30, bottom: 10), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textCreateAccount), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.only(top: 12, bottom: 12), + ), + ) + ], + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textAddAccount), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 20.0), + child: SingleChildScrollView( + child: Column( + children: [ + GetBuilder( + builder: (controller) { + return controller.currencyCodesField = InputField( + refKey: FormFieldConstants.instance().getFormKey("addNewAccountField"), + controller: FormFieldConstants.instance().getController("addNewAccountField"), + labelText: "Select Default Currency", + isDropDown: true, + hintText: "Select Default Currency", + dropDownType: DropDownType.SPECIAL, + items: controller.currencyListDropDown, + onItemSelected: (item) { + controller.updateCurrency(item); + }, + ); + }, + ), + controller.nameAddressField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}userNameField"), + controller: FormFieldConstants.instance().getController("${className}userNameField"), + hintText: "Enter account title", + labelText: "Account Title", + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.addressFieldLength)], + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + ), + // const SizedBox(height: 30), + // Padding( + // padding: const EdgeInsets.only(left: 20, right: 30, bottom: 10), + // child: CustomButton( + // onPressed: () { + // controller.validateAndSendRequest(); + // }, + // buttonText: TranslationKeys.makeTranslation(TranslationKeys.textCreateAccount), + // buttonColor: AppColors.colorButton, + // buttonPadding: const EdgeInsets.only(top: 12, bottom: 12), + // ), + // ) + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/agent_location/bindings/agent_location_binding.dart b/lib/app/modules/agent_location/bindings/agent_location_binding.dart new file mode 100644 index 0000000..2386f2d --- /dev/null +++ b/lib/app/modules/agent_location/bindings/agent_location_binding.dart @@ -0,0 +1,12 @@ +// import 'package:get/get.dart'; +// +// import '../controllers/agent_location_controller.dart'; +// +// class AgentLocationBinding extends Bindings { +// @override +// void dependencies() { +// Get.lazyPut( +// () => AgentLocationController(), +// ); +// } +// } diff --git a/lib/app/modules/agent_location/controllers/agent_location_controller.dart b/lib/app/modules/agent_location/controllers/agent_location_controller.dart new file mode 100644 index 0000000..a3b0e3e --- /dev/null +++ b/lib/app/modules/agent_location/controllers/agent_location_controller.dart @@ -0,0 +1,142 @@ +// import 'package:flutter/cupertino.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter/services.dart'; +// import 'package:flutter_svg/flutter_svg.dart'; +// import 'package:get/get.dart'; +// // import 'package:google_maps_flutter/google_maps_flutter.dart'; +// import 'package:uco_mobile_poc_project/app/core/constants/app_assets.dart'; +// import 'package:uco_mobile_poc_project/app/models/Branch.dart'; +// +// class AgentLocationController extends GetxController { +// final TextEditingController searchController = TextEditingController(); +// +// // BuildContext context = Get.context as BuildContext; +// // final RxSet markers = {}.obs; +// // final List mapType = ['Normal', 'Satellite', 'Hybrid'].obs; +// // BitmapDescriptor? myMarker; +// // Rx selectedMapType = MapType.normal.obs; +// // +// // /// Change Map Type +// // void changeMapType(MapType newMapType) { +// // selectedMapType.value = newMapType; +// // } +// // +// // @override +// // void onInit() { +// // super.onInit(); +// // +// // /// Initialize with some default markers +// // searchBranches('Normal'); +// // } +// // +// // void searchBranches(String branchName) { +// // /// Simulate fetching branch locations based on the city +// // /// Replace this with your actual logic to get branch locations +// // List branches = getBranches(branchName); +// // +// // /// Clear existing markers +// // markers.clear(); +// // +// // /// Add markers for each branch in the selected city +// // if (branches.isNotEmpty) { +// // branches.forEach((branch) async { +// // markers.add( +// // Marker( +// // markerId: MarkerId(branch.name), +// // position: LatLng(branch.latitude, branch.longitude), +// // icon: await BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen), +// // +// // onTap: () { +// // showCustomInfoWindow(branch); +// // }, +// // // infoWindow: InfoWindow( +// // // title: branch.name, +// // // snippet: branch.contactNumber, +// // // ), +// // ), +// // ); +// // }); +// // update(); +// // } +// // } +// +// /// Custom Info Window for marker +// void showCustomInfoWindow(Branch branch) { +// Clipboard.setData(ClipboardData(text: branch.name)); +// Clipboard.setData(ClipboardData(text: branch.contactNumber)); +// Clipboard.setData(ClipboardData(text: branch.address)); +// Get.defaultDialog( +// contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), +// title: branch.name, +// titlePadding: const EdgeInsets.only(top: 10), +// titleStyle: Theme.of(context).textTheme.titleSmall!.copyWith(fontWeight: FontWeight.w500), +// content: Column( +// crossAxisAlignment: CrossAxisAlignment.center, +// children: [ +// Row( +// crossAxisAlignment: CrossAxisAlignment.center, +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// Image.asset( +// AppAssets.lg_mfsys, // Replace with your logo image path +// width: 35, +// height: 35, +// ), +// const SizedBox(width: 10), +// Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// Row( +// children: [ +// const Icon( +// Icons.location_on, +// size: 13, +// color: Colors.blue, +// ), +// const SizedBox( +// height: 20, +// ), +// Padding( +// padding: const EdgeInsets.only(left: 10.0), +// child: Text('MFSYS Technologies', style: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 10, fontWeight: FontWeight.w400)), +// ), +// ], +// ), +// const SizedBox(height: 10), +// Row( +// children: [ +// const Icon( +// Icons.phone, // Replace with your desired icon +// size: 13, +// color: Colors.blue, +// ), +// const SizedBox(height: 8), +// Padding( +// padding: const EdgeInsets.only(left: 10.0), +// child: Text( +// style: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 10, fontWeight: FontWeight.w400), +// '(051) 41021712', +// ), +// ), +// ], +// ), +// ], +// ), +// ], +// ), +// ], +// ), +// ); +// } +// +// /// Branches List +// List getBranches(String cityName) { +// return [ +// Branch(name: 'MFSYS Technolog', latitude: 37.7749, longitude: -122.4194, contactNumber: '123-456-7890', address: "Main Branch I9/3"), +// Branch(name: 'MFSYS Technolog', latitude: 37.7831, longitude: -122.4039, contactNumber: '987-654-3210', address: "Main Branch I9/3"), +// Branch(name: 'MFSYS Technolog', latitude: 37.7841, longitude: -122.4539, contactNumber: '987-654-3210', address: "Main Branch I9/3"), +// Branch(name: 'Branch E', latitude: 37.7867, longitude: -122.4089, contactNumber: '987-654-3210', address: "Main Branch I9/3"), +// ]; +// } +// } diff --git a/lib/app/modules/agent_location/views/agent_location_view.dart b/lib/app/modules/agent_location/views/agent_location_view.dart new file mode 100644 index 0000000..f8affdc --- /dev/null +++ b/lib/app/modules/agent_location/views/agent_location_view.dart @@ -0,0 +1,95 @@ +// import 'package:flutter/material.dart'; +// import 'package:get/get.dart'; +// import 'package:google_maps_flutter/google_maps_flutter.dart'; +// import 'package:uco_mobile_poc_project/app/core/constants/translation_keys.dart'; +// import 'package:uco_mobile_poc_project/app/custom_widgets/custom_app_bar.dart'; +// import 'package:uco_mobile_poc_project/app/res/app_colors.dart'; +// +// import '../controllers/agent_location_controller.dart'; +// +// class AgentLocationView extends GetView { +// const AgentLocationView({Key? key}) : super(key: key); +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// appBar: DashBoardAppBar( +// title: TranslationKeys.makeTranslation(TranslationKeys.textMapLocationTitle), +// onBackButtonPressed: () { +// Get.back(); +// }, +// actions: [ +// PopupMenuButton( +// color: AppColors.white, +// icon: const Icon( +// Icons.more_vert, +// color: AppColors.white, // Set your desired color for the actions dots +// ), +// onSelected: (selectedMapType) { +// controller.changeMapType(selectedMapType); +// }, +// itemBuilder: (BuildContext context) { +// return [ +// PopupMenuItem( +// value: MapType.normal, +// child: Text( +// TranslationKeys.makeTranslation(TranslationKeys.textNormalMap), +// style: Theme.of(context).textTheme.titleSmall, +// ), +// ), +// PopupMenuItem( +// value: MapType.satellite, +// child: Text( +// TranslationKeys.makeTranslation(TranslationKeys.textSatelliteMap), +// style: Theme.of(context).textTheme.titleSmall, +// ), +// ), +// PopupMenuItem( +// value: MapType.hybrid, +// child: Text( +// TranslationKeys.makeTranslation(TranslationKeys.textHybridMap), +// style: Theme.of(context).textTheme.titleSmall, +// ), +// ), +// ]; +// }, +// ), +// ], +// ), +// body: Obx(() { +// return GoogleMap( +// mapType: controller.selectedMapType.value, +// initialCameraPosition: const CameraPosition( +// target: LatLng(37.7749, -122.4194), +// zoom: 12.0, +// ), +// markers: controller.markers.toSet(), +// onMapCreated: (GoogleMapController controller) { +// /// You can use the controller for further map customization +// }, +// onTap: (LatLng latLng) { +// /// Close any existing dialogs when tapping on the map +// // Get.back(); +// +// /// Find the tapped marker based on its position +// final tappedMarker = controller.markers.firstWhere( +// (marker) => marker.position == latLng, +// ); +// +// final tappedBranch = controller.getBranches(controller.mapType.first)[0]; +// Get.defaultDialog( +// title: tappedBranch.name, +// content: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Text('${TranslationKeys.makeTranslation(TranslationKeys.textMapContactNumber)} ${tappedBranch.contactNumber}'), +// Text('${TranslationKeys.makeTranslation(TranslationKeys.textMapContactNumber)} ${tappedBranch.contactNumber}'), +// ], +// ), +// ); +// }, +// ); +// }), +// ); +// } +// } diff --git a/lib/app/modules/app_intro/bindings/intro_screen_binding.dart b/lib/app/modules/app_intro/bindings/intro_screen_binding.dart new file mode 100644 index 0000000..d16f567 --- /dev/null +++ b/lib/app/modules/app_intro/bindings/intro_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/intro_screen_controller.dart'; + +class IntroScreenBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => IntroScreenController(), + ); + } +} diff --git a/lib/app/modules/app_intro/controllers/intro_screen_controller.dart b/lib/app/modules/app_intro/controllers/intro_screen_controller.dart new file mode 100644 index 0000000..0bc7ce6 --- /dev/null +++ b/lib/app/modules/app_intro/controllers/intro_screen_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class IntroScreenController extends GetxController { + //TODO: Implement IntroScreenController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/app_intro/views/intro_screen_view.dart b/lib/app/modules/app_intro/views/intro_screen_view.dart new file mode 100644 index 0000000..3ab3059 --- /dev/null +++ b/lib/app/modules/app_intro/views/intro_screen_view.dart @@ -0,0 +1,123 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:introduction_slider/source/presentation/pages/introduction_slider.dart'; +import 'package:introduction_slider/source/presentation/widgets/buttons.dart'; +import 'package:introduction_slider/source/presentation/widgets/dot_indicator.dart'; +import 'package:introduction_slider/source/presentation/widgets/introduction_slider_item.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/intro_screen_controller.dart'; + +class IntroScreenView extends GetView { + IntroScreenView({Key? key}) : super(key: key); + double imageWidthHeight = 180; + + @override + Widget build(BuildContext context) { + // + // dp("Width int screen", {MediaQuery.sizeOf(Get.context!).width}); + // dp("Height init screen ", MediaQuery.sizeOf(Get.context!).height); + + // dp("Display large ", Theme.of(Get.context!).textTheme.displayLarge); + + return Scaffold( + backgroundColor: AppColors.colorSecondary, + body: IntroductionSlider( + showStatusBar: true, + items: [ + IntroductionSliderItem( + logo: SvgPicture.asset( + AppAssets.img_global, + width: imageWidthHeight, + height: imageWidthHeight, + ), + title: Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textWelcomeToJoin), + style: Theme.of(context).textTheme.displayLarge!, + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation(TranslationKeys.textIntroDescription), + style: Theme.of(context).textTheme.bodyMedium!.copyWith(height: 1.8), + textAlign: TextAlign.center, + ), + ], + ), + ), + backgroundColor: AppColors.colorSecondary, + ), + IntroductionSliderItem( + logo: SvgPicture.asset( + AppAssets.img_slider, + width: imageWidthHeight, + height: imageWidthHeight, + ), + title: Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textWelcomeToJoin), style: Theme.of(context).textTheme.displayLarge), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation(TranslationKeys.textIntroDescription), + style: Theme.of(context).textTheme.bodyMedium!.copyWith(height: 1.8), + textAlign: TextAlign.center, + ), + ], + ), + ), + backgroundColor: AppColors.colorSecondary, + ), + ], + done: Done( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), + child: CustomButton( + onPressed: () { + Get.offAllNamed(Routes.LOGIN_SCREEN); + }, + buttonColor: AppColors.colorPrimaryLight, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.continueText), + textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.colorPrimaryDark), + buttonPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 35), + ), + ), + home: Container(), + ), + dotIndicator: const DotIndicator(size: 10, selectedColor: AppColors.colorPrimary), + // back: Back( + // child: Padding( + // padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + // child: CustomButton( + // onPressed: () { + // // Get.offAndToNamed(Routes.SIGN_UP_SCREEN_STEP1); + + // Get.back(); + // }, + // buttonColor: AppColors.colorPrimaryLight, + // buttonText: + // TranslationKeys.makeTranslation(TranslationKeys.textRegister), + // textStyle: Theme.of(context) + // .textTheme + // .titleSmall + // ?.copyWith(color: AppColors.colorPrimaryDark), + // buttonPadding: + // const EdgeInsets.symmetric(vertical: 7, horizontal: 25), + // ), + // ), + // ), + ), + ); + } +} diff --git a/lib/app/modules/app_setting/bindings/app_setting_binding.dart b/lib/app/modules/app_setting/bindings/app_setting_binding.dart new file mode 100644 index 0000000..aa8951e --- /dev/null +++ b/lib/app/modules/app_setting/bindings/app_setting_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/app_setting_controller.dart'; + +class AppSettingBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AppSettingController(), + ); + } +} diff --git a/lib/app/modules/app_setting/controllers/app_setting_controller.dart b/lib/app/modules/app_setting/controllers/app_setting_controller.dart new file mode 100644 index 0000000..efcb37d --- /dev/null +++ b/lib/app/modules/app_setting/controllers/app_setting_controller.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/constants/app_contants.dart'; +import '../../../core/local_stoarge/app_storage.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../routes/app_pages.dart'; + + +class AppSettingController extends GetxController { + static bool isDarkMode = false; + static RxBool isRTL = false.obs; + static RxString selectedLocale = "en".obs; + + // LocaleController localeController = LocaleController(); + + + + updateLanguage(Locale locale) async { + Get.updateLocale(locale); + // Get.find().saveLocale(locale.toString()); + // localeController.selectedLocale.value = locale.toString(); + AppSettingController.isRTL.value = Get.locale!.languageCode == "ar" || Get.locale!.languageCode == "ur"; + AppSettingController.selectedLocale.value = Get.locale!.languageCode; + await AppStorage.putString(AppConstants.SELECTED_LOCALE, AppSettingController.selectedLocale.value); + await AppStorage.putBoolean(AppConstants.IS_RTL, AppSettingController.isRTL.value); + Get.forceAppUpdate(); + update(); + } + + @override + void onInit() { + super.onInit(); + } + + void changeAppMode(bool value) async { + AppStorage.putBoolean(AppConstants.IS_DARK_MODE, value); + isDarkMode = value; + } + + void showLogoutDialog(BuildContext context) { + CustomDialog.showLogoutDialog( + context: context, + onTapPositive: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.offAllNamed(Routes.LOGIN_SCREEN); + }, + onTapNegative: () { + Navigator.of(context, rootNavigator: true).pop(); + }, + ); + } +} + +class AppSettings { + String title; + String description; + Icon icon; + Function() onTap; + + AppSettings({required this.title, required this.description, required this.icon, required this.onTap}); +} diff --git a/lib/app/modules/app_setting/views/app_setting_view.dart b/lib/app/modules/app_setting/views/app_setting_view.dart new file mode 100644 index 0000000..ebf2d3d --- /dev/null +++ b/lib/app/modules/app_setting/views/app_setting_view.dart @@ -0,0 +1,466 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/bottom_sheet.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/app_setting_controller.dart'; +import 'model/Language.dart'; + +class AppSettingView extends GetView { + const AppSettingView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textAppSettingTitle), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + showBottomSheet(context, "FROM_ACCOUNT", controller); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 10), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon(Icons.language, color: AppColors.colorPrimary, size: 18), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textLanguagesTitle), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 14, fontWeight: FontWeight.w400)), + const Spacer(), + const Padding( + padding: EdgeInsets.all(16.0), + child: Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey700), + ), + ], + ), + ), + ), + ), + ), + Visibility( + // visible: SessionCache.instance.fingerPrintController.isFingerprintSupported.value, + child: Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + // showBottomSheet( + // context, "FROM_ACCOUNT", controller); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 10), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon( + Icons.fingerprint_outlined, + color: AppColors.colorPrimary, + size: 15, + ), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textFingerPrintTitle), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w400)), + const Spacer(), + // Obx(() { + // return Switch( + // value: SessionCache.instance.fingerPrintController.isFingerprintSupported.value && SessionCache.instance.fingerPrintController.isFingerPrintExistInDB.value, + // onChanged: (bool value) { + // if (value) { + // SessionCache.instance.fingerPrintController.authenticate(null, true); + // } else { + // print("---------------->>>"); + // SessionCache.instance.fingerPrintController.clearFromDB(); + // } + // }, + // activeColor: AppColors.colorButton, + // ); + // }), + ], + ), + ), + ), + ), + ), + ), + Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + Get.toNamed(Routes.DAIL_TRANSACTION_LIMIT); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 0), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon( + Icons.monetization_on_outlined, + color: AppColors.colorPrimary, + size: 15, + ), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textDailyTransactionLimit), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w400)), + const Spacer(), + const Padding( + padding: EdgeInsets.all(16.0), + child: Icon( + Icons.arrow_forward_ios_outlined, + size: 15, + color: AppColors.colorGrey700, + ), + ), + ], + ), + ), + ), + ), + ), + Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + Get.toNamed(Routes.QR_SETTING); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 0), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon( + Icons.qr_code, + color: AppColors.colorPrimary, + size: 15, + ), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textQRSetting), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w400)), + const Spacer(), + const Padding( + padding: EdgeInsets.all(16.0), + child: Icon( + Icons.arrow_forward_ios_outlined, + size: 15, + color: AppColors.colorGrey700, + ), + ), + ], + ), + ), + ), + ), + ), + Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + Get.toNamed(Routes.CHANGE_TRANSACTION_PIN); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 0), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon( + Icons.password, + color: AppColors.colorPrimary, + size: 15, + ), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textChangeTransactionPin), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w400)), + const Spacer(), + const Padding( + padding: EdgeInsets.all(16.0), + child: Icon( + Icons.arrow_forward_ios_outlined, + size: 15, + color: AppColors.colorGrey700, + ), + ), + ], + ), + ), + ), + ), + ), + Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + Toasty.success("Transaction Pin Already Generate"); + // Get.toNamed(Routes.CREATE_TRANSACTION_PIN); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 0), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon( + Icons.password, + color: AppColors.colorPrimary, + size: 15, + ), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textCreateTransactionPin), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w400)), + const Spacer(), + const Padding( + padding: EdgeInsets.all(16.0), + child: Icon( + Icons.arrow_forward_ios_outlined, + size: 15, + color: AppColors.colorGrey700, + ), + ), + ], + ), + ), + ), + ), + ), + Expanded( + flex: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + child: InkWell( + onTap: () { + controller.showLogoutDialog(context); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 0), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 15, + child: Icon( + Icons.logout, + color: AppColors.colorPrimary, + size: 15, + ), + ), + ), + ), + Text(TranslationKeys.makeTranslation(TranslationKeys.textLogOut), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w400)), + const Spacer(), + const Padding( + padding: EdgeInsets.all(16.0), + child: Icon( + Icons.arrow_forward_ios_outlined, + size: 15, + color: AppColors.colorGrey700, + ), + ), + ], + ), + ), + ), + ), + ), + const Expanded(flex: 0, child: SizedBox(height: 15)), + ], + ), + ), + ); + } + + /// Change Language Function For Search Bar + void showBottomSheet(BuildContext context, String accountType, AppSettingController controller) { + // + + List options = []; + + for (int i = 0; i < Languages.supportedLanguages.length; i++) { + // + + Languages language = Languages.supportedLanguages[i]; + + options.add(OptionData.withData(language.lable, "", language)); + + // + } + + Get.bottomSheet( + Container( + decoration: BoxDecoration(color: Colors.white, border: Border.all(color: AppColors.colorGrey800, width: 1), borderRadius: const BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30))), + margin: const EdgeInsets.only(left: 20, right: 20), + child: DialogDesign(options, (selectedOption) { + Languages language = selectedOption.dataObject as Languages; + print("===========$language"); + controller.updateLanguage(language.locale); + }), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); + } +} + +class DialogDesign extends StatelessWidget { + List options = []; + Function(OptionData) onSelect; + + DialogDesign(this.options, this.onSelect); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textSelectYourOption), + style: Theme.of(context).textTheme.titleLarge?.copyWith(color: AppColors.titleColor, fontSize: 12, fontWeight: FontWeight.w600), + ), + InkWell( + onTap: () { + Get.back(); // Close the bottom sheet using Get + }, + child: const CircleAvatar( + radius: 12.5, + backgroundColor: Colors.transparent, + child: Icon( + Icons.close, + size: 16.0, + color: Colors.red, + ), + ), + ), + ], + ), + const SizedBox(height: 10.0), + FilterableBottomSheet(options: options, onSelect: onSelect), + ], + ), + ); + } +} diff --git a/lib/app/modules/app_setting/views/model/Language.dart b/lib/app/modules/app_setting/views/model/Language.dart new file mode 100644 index 0000000..5515381 --- /dev/null +++ b/lib/app/modules/app_setting/views/model/Language.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import '../../../../core/constants/translation_keys.dart'; + +class Languages { + String lable = ""; + Locale locale; + String code; + + Languages({required this.lable, required this.locale, required this.code}); + + static List supportedLanguages = [ + Languages(lable: TranslationKeys.makeTranslation(TranslationKeys.textLanguageEnglish), locale: const Locale('en', 'US'), code: "en"), + Languages(lable: TranslationKeys.makeTranslation(TranslationKeys.textLanguageArabic), locale: const Locale('ar', 'SA'), code: "ar"), + Languages(lable: TranslationKeys.makeTranslation(TranslationKeys.textLanguageUrdu), locale: const Locale('ur', 'PK'), code: "ur"), + ]; +} diff --git a/lib/app/modules/beneficiary_management/bindings/beneficiary_management_binding.dart b/lib/app/modules/beneficiary_management/bindings/beneficiary_management_binding.dart new file mode 100644 index 0000000..46d4c0c --- /dev/null +++ b/lib/app/modules/beneficiary_management/bindings/beneficiary_management_binding.dart @@ -0,0 +1,13 @@ +import 'package:get/get.dart'; + +import '../controllers/beneficiary_management_controller.dart'; + + +class BeneficiaryManagementBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => BeneficiaryManagementController(), + ); + } +} diff --git a/lib/app/modules/beneficiary_management/controllers/beneficiary_management_controller.dart b/lib/app/modules/beneficiary_management/controllers/beneficiary_management_controller.dart new file mode 100644 index 0000000..7e3d1c5 --- /dev/null +++ b/lib/app/modules/beneficiary_management/controllers/beneficiary_management_controller.dart @@ -0,0 +1,76 @@ +import 'package:get/get.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/BeneficiaryAccountModel.dart'; + + +class BeneficiaryManagementController extends GetxController { + final AppRepositories repository = Get.find(); + String className = ""; + var hasUpdated = false.obs; + + List allBeneficiary = []; + RxList filteredBeneficiaries = [].obs; + + /// Fetch All Beneficiary Function + Future fetchAllBeneficiary(String porOrgacode, String email) async { + try { + ServerResponse response = await repository.fetchAllBeneficiary(porOrgacode, email); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + // Assuming the response contains a list of beneficiary account data + List data = response.response; + if (data != null) { + List beneficiaryList = data.map((item) { + return BeneficiaryAccountModel.fromMap(item); + }).toList(); + + // Update the RxList with the fetched data + allBeneficiary.assignAll(beneficiaryList); + filteredBeneficiaries.assignAll(beneficiaryList); + } + } catch (e) { + Toasty.error('An error occurred while fetching beneficiary accounts.'); + } + } + + /// Delete Beneficiary Function + Future deleteSingleBeneficiary(String mbmBkmsnumberRef, String email, String porOrgacode) async { + ServerResponse response = await repository.deleteBeneficiary(mbmBkmsnumberRef, email, porOrgacode); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Toasty.success('Your Beneficiary account Delete successfully.'); + fetchBeneficiaries(); + } + + @override + void onInit() { + super.onInit(); + fetchBeneficiaries(); + } + + void fetchBeneficiaries() async { + await fetchAllBeneficiary(SessionCache.instance.userInfo.porOrgacode, SessionCache.instance.userInfo.cmpUserId); + dp("All Beneficiary List======== ", allBeneficiary.toString()); + } + + void filterBeneficiaries(String searchText) { + if (searchText.isEmpty) { + filteredBeneficiaries.assignAll(allBeneficiary); + } else { + filteredBeneficiaries.assignAll(allBeneficiary.where((beneficiary) { + return beneficiary.refNickName.toLowerCase().contains(searchText.toLowerCase()) || beneficiary.mbmBkmstitleRef.toLowerCase().contains(searchText.toLowerCase()) || beneficiary.mbmBkmsnumberRef.toLowerCase().contains(searchText.toLowerCase()); + }).toList()); + } + } + +} diff --git a/lib/app/modules/beneficiary_management/views/beneficiary_management_view.dart b/lib/app/modules/beneficiary_management/views/beneficiary_management_view.dart new file mode 100644 index 0000000..d4ffd50 --- /dev/null +++ b/lib/app/modules/beneficiary_management/views/beneficiary_management_view.dart @@ -0,0 +1,179 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/app_utils.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_no_record.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/beneficiary_management_controller.dart'; + +class BeneficiaryManagementView extends GetView { + const BeneficiaryManagementView({Key? key, this.showAppBar = true}) : super(key: key); + final bool showAppBar; + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + controller.className = className; + return Scaffold( + appBar: showAppBar + ? DashBoardAppBar( + title: "Beneficiary Management", + onBackButtonPressed: () { + Get.back(result: controller.hasUpdated.value); + }, + ) + : null, + floatingActionButton: InkWell( + onTap: () async { + var result = await Get.toNamed(Routes.NEW_BENEFICIARY); + if (result != null && result == true) { + controller.fetchBeneficiaries(); + controller.hasUpdated.value = true; + } + }, + child: Container( + height: 30, + width: 130, + decoration: const BoxDecoration(color: AppColors.colorButton, borderRadius: BorderRadius.all(Radius.circular(20.0))), + child: const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [Icon(Icons.add, size: 14, color: AppColors.white), SizedBox(width: 5), Text("Add Beneficiary", style: TextStyle(color: AppColors.white, fontWeight: FontWeight.w500, fontSize: 12))], + ), + ), + ), + body: SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: const InputDecoration( + suffixIconColor: AppColors.colorPrimary, + filled: true, + fillColor: AppColors.colorGrey200, + enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(width: 1, color: Colors.transparent)), + border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(width: 1, color: AppColors.colorGrey500)), + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(width: 1, style: BorderStyle.solid, color: Colors.transparent)), + hintText: 'Search By Beneficiary Name', + hintStyle: TextStyle(fontSize: 12, fontWeight: FontWeight.w400, color: AppColors.colorGrey500), + suffixIcon: Icon(Icons.search_rounded), + ), + onChanged: (value) { + controller.filterBeneficiaries(value); + }), + ), + Container( + height: 40, + width: double.infinity, + color: AppColors.FDF7F1, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 25.0, vertical: 10.0), + child: Text("Bank Transfer", style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black, fontWeight: FontWeight.w400, fontSize: 13)), + ), + ), + const SizedBox(height: 20.0), + Obx(() { + if (controller.filteredBeneficiaries.isEmpty) { + return const Center( + child: CustomNoRecord(title: "No Record Found", description: "We couldn't find any activity at this moment"), + ); + } else { + return ListView.separated( + shrinkWrap: true, + // physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + final beneficiary = controller.filteredBeneficiaries[index]; + return Column( + children: [ + Container( + width: double.infinity, + padding: const EdgeInsets.all(15.0), + decoration: const BoxDecoration( + color: AppColors.white, + borderRadius: BorderRadius.all(Radius.circular(8.0)), + ), + child: Row( + children: [ + CircleAvatar(radius: 20.0, backgroundColor: AppColors.colorGrey300, child: Text(AppUtils.getInitials(beneficiary.mbmBkmstitleRef), style: Theme.of(context).textTheme.titleSmall)), + const SizedBox(width: 10), + Expanded( + flex: 4, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(beneficiary.refNickName, style: Theme.of(context).textTheme.titleMedium?.copyWith(color: AppColors.colorGrey700, fontWeight: FontWeight.w500, fontSize: 14)), + const SizedBox(height: 5), + Text(beneficiary.mbmBkmstitleRef, style: Theme.of(context).textTheme.titleMedium?.copyWith(color: AppColors.colorGrey600, fontWeight: FontWeight.w400, fontSize: 12)), + const SizedBox(height: 5), + Text(beneficiary.mbmBkmsnumberRef, style: Theme.of(context).textTheme.titleMedium?.copyWith(color: AppColors.colorPrimary, fontWeight: FontWeight.w400, fontSize: 12)), + ], + ), + ), + Expanded( + flex: 1, + child: Align( + alignment: Alignment.centerRight, + child: PopupMenuButton( + padding: const EdgeInsets.all(0.0), + offset: const Offset(-25, 30), + color: AppColors.white, + icon: const Icon(Icons.more_vert_rounded, color: AppColors.colorGrey500), + onSelected: (value) {}, + itemBuilder: (context) => [ + _buildPopupMenuItem(context, "Pay", 0, () { + Get.toNamed(Routes.BENEFICIARY_TRANSFER_MONEY, arguments: [beneficiary]); + }), + _buildPopupMenuItem(context, "Delete", 1, () { + CustomDialog.showAlertDialog( + onTapPositive: () { + Navigator.of(context, rootNavigator: true).pop(); + controller.deleteSingleBeneficiary(beneficiary.mbmBkmsnumberRef, SessionCache.instance.userInfo.cmpUserId, SessionCache.instance.userInfo.porOrgacode); + }, + onTapNegative: () { + Navigator.of(context, rootNavigator: true).pop(); + }, + context: context); + }), + ], + ), + ), + ), + ], + ), + ), + ], + ); + }, + separatorBuilder: (BuildContext context, int index) { + return Container(height: 1, color: AppColors.black.withOpacity(0.2)); + }, + itemCount: controller.filteredBeneficiaries.length, + ); + } + }), + ], + ), + ), + ); + } + + /// For List Actions + PopupMenuItem _buildPopupMenuItem(BuildContext context, String text, int value, Function() onTap) { + return PopupMenuItem( + height: 10, + onTap: onTap, + value: value, + padding: const EdgeInsets.symmetric(vertical: 5.0), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 0.0, horizontal: 8.0), + child: Text(text, style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500)), + ), + ); + } +} diff --git a/lib/app/modules/beneficiary_transfer_money/bindings/beneficiary_transfer_binding.dart b/lib/app/modules/beneficiary_transfer_money/bindings/beneficiary_transfer_binding.dart new file mode 100644 index 0000000..25ad44d --- /dev/null +++ b/lib/app/modules/beneficiary_transfer_money/bindings/beneficiary_transfer_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; +import '../controllers/beneficiary_transfer_controller.dart'; + + +class BeneficiaryTransferBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => BeneficiaryTransferController(), + ); + } +} diff --git a/lib/app/modules/beneficiary_transfer_money/controllers/beneficiary_transfer_controller.dart b/lib/app/modules/beneficiary_transfer_money/controllers/beneficiary_transfer_controller.dart new file mode 100644 index 0000000..012d90e --- /dev/null +++ b/lib/app/modules/beneficiary_transfer_money/controllers/beneficiary_transfer_controller.dart @@ -0,0 +1,199 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/Fields/field_validations.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/BeneficiaryAccountModel.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/ExchangeRate.dart'; +import '../../../models/SendTransactionStep1ResponseModel.dart'; +import '../../../models/TransactionPinRequestModel.dart'; +import '../../../models/TransactionSubmitRequestModel.dart'; +import '../../../routes/app_pages.dart'; + +class BeneficiaryTransferController extends GetxController { + TextEditingController pinPutController = TextEditingController(); + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + RxBool isResend = false.obs; + + //drop down + RxList allFromAccounts = RxList.empty(); + Rx selectedFromAccount = DepositAccount.empty().obs; + + RxList allToAccounts = RxList.empty(); + Rx selectedToAccount = DepositAccount.empty().obs; + ExchangeRate? selectedExchangeRate; + + TextEditingController referenceCodeController = TextEditingController(); + + // fields + late InputField fromAccountField; + late InputField toAccountField; + late InputField sendingAmountField; + late InputField exchangeRateField; + late InputField messageField; + late InputField userTransactionPinField; + late InputField referenceCodeField; + + late String beneficiaryName; + List beneficiaryDetail = []; + + @override + void onInit() { + super.onInit(); + beneficiaryDetail = Get.arguments ?? []; + for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + DepositAccount depositAccount = SessionCache.instance.depositAccountList.elementAt(i); + allFromAccounts.add(DropDown(depositAccount.mbmBkmsnumber, "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", depositAccount)); + } + } + + @override + Future onReady() async { + super.onReady(); + disposeAllResources(); + onFromAccountSelection(allFromAccounts.elementAt(0)); + fromAccountField.setText((allFromAccounts.first.label)); + + /// For Set To Account Based on selected + if (beneficiaryDetail.isNotEmpty) { + toAccountField.setText(beneficiaryDetail.first.mbmBkmstitleRef); + } + + /// For Getting Exchange Rate + for (int i = 0; i < SessionCache.instance.exchangeRateList.length; i++) { + if (SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrcode == beneficiaryDetail.first.pcrCurrcode) { + selectedExchangeRate = SessionCache.instance.exchangeRateList.elementAt(i); + exchangeRateField.setText(selectedExchangeRate!.perEratrateact.toString()); + break; + } + } + } + + void onFromAccountSelection(DropDown value) { + if (value.id == selectedToAccount.value.mbmBkmsnumber) { + Toasty.error('This account is already selected'); + fromAccountField.setText(""); + selectedFromAccount.value = DepositAccount.empty(); + } else { + selectedFromAccount.value = value.data as DepositAccount; + } + } + + void disposeAllResources() { + fromAccountField.clear(); + toAccountField.clear(); + sendingAmountField.clear(); + exchangeRateField.clear(); + messageField.clear(); + userTransactionPinField.clear(); + referenceCodeField.clear(); + referenceCodeController.clear(); + } + + bool validate() { + bool isValid = FieldValidation.validateAll([ + fromAccountField, + toAccountField, + sendingAmountField, + exchangeRateField, + userTransactionPinField, + referenceCodeField, + ]); + if (pinPutController.text.isEmpty) { + return false; + } + if (referenceCodeController.text.isEmpty) { + return false; + } + return isValid; + } + + /// Send Transaction function + Future sendBeneficiaryTransaction({navigate = true}) async { + if (!validate()) { + Toasty.error("Please input and then proceed"); + return; + } + + TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel( + porOrgacode: RequestConstants.porOrgacode, + pctCstycode: RequestConstants.pctCstycode, + channelCode: RequestConstants.channelCode, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + drMbmBkmsnumber: selectedFromAccount.value.mbmBkmsnumber, + drMbmBkmstitle: selectedFromAccount.value.mbmBkmstitle, + drPcrCurrcode: selectedFromAccount.value.pcrCurrcode, + drPcrCurrdesc: selectedFromAccount.value.pcrCurrdesc, + drPcrCurrshort: selectedFromAccount.value.pcrCurrshort, + crMbmBkmsnumber: beneficiaryDetail.first.mbmBkmsnumberRef, + crMbmBkmstitle: beneficiaryDetail.first.mbmBkmstitleRef, + crPcrCurrcode: selectedExchangeRate!.pcrCurrcode, + crPcrCurrdesc: selectedExchangeRate!.pcrCurrdesc, + crPcrCurrshort: selectedExchangeRate!.pcrCurrshort, + sgtGntrnarration: "", + dmpProdCode: selectedFromAccount.value.dmpProdcode, + transType: "DR", + notificationId: "", + transMode: "Online", + sgtGntramtfc: double.parse(sendingAmountField.getCustomText().isEmpty ? "0.0" : sendingAmountField.getCustomText()), + otdTrancomment: messageField.getCustomText(), + isOtpRequired: false, + cmpRefcode: referenceCodeField.getCustomText(), + ); + + TransactionPinRequestModel transactionPinRequestModel = TransactionPinRequestModel( + porOrgacode: RequestConstants.porOrgacode, + pctCstycode: RequestConstants.pctCstycode, + channelCode: RequestConstants.channelCode, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + email: SessionCache.instance.userInfo.cmpUserId, + pinType: "TRAN", + transPincode: userTransactionPinField.getCustomText(), + isOtpRequired: false, + ); + + ServerResponse response = await repository.sendTransactionStep1(transactionPinRequestModel); + + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + SendTransactionStep1ResponseModel step1responseModel = SendTransactionStep1ResponseModel.fromMap(response.response); + transactionSubmitRequestModel.notificationId = step1responseModel.notificationId.toString(); + + if (navigate) { + Get.toNamed(Routes.BENEFICIARY_TRANSFER_MONEY_OTP, arguments: { + AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + AppConstants.SEND_TRANS_PIN_REQUEST: transactionPinRequestModel, + AppConstants.EXCHANGE_RATE: exchangeRateField.getCustomText(), + }); + } else { + Fluttertoast.showToast( + msg: "OTP successfully send to your email address", + ); + } + } + + void clearTransaction() { + toAccountField.clear(); + sendingAmountField.clear(); + exchangeRateField.clear(); + messageField.clear(); + userTransactionPinField.clear(); + pinPutController.clear(); + referenceCodeField.clear(); + referenceCodeController.clear(); + } +} diff --git a/lib/app/modules/beneficiary_transfer_money/views/beneficiary_transfer_view.dart b/lib/app/modules/beneficiary_transfer_money/views/beneficiary_transfer_view.dart new file mode 100644 index 0000000..3c669f5 --- /dev/null +++ b/lib/app/modules/beneficiary_transfer_money/views/beneficiary_transfer_view.dart @@ -0,0 +1,394 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; + + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/beneficiary_transfer_controller.dart'; + +class BeneficiaryTransferView extends GetView { + const BeneficiaryTransferView({Key? key, this.showAppBar = true}) : super(key: key); + final bool showAppBar; + + @override + Widget build(BuildContext context) { + + String className = runtimeType.toString().split('.').last; + + return Scaffold( + appBar: showAppBar + ? DashBoardAppBar( + title: "Beneficiary Payment", + /*TranslationKeys.makeTranslation(TranslationKeys.textUSend),*/ + onBackButtonPressed: () { + Get.back(); + }, + ) + : null, + body: Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Card( + color: AppColors.colorGrey50, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + controller.fromAccountField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}fromAccountField"), + controller: FormFieldConstants.instance().getController("${className}fromAccountField"), + labelText: "Select From Account", + isDropDown: true, + hintText: "Select from account", + dropDownType: DropDownType.SPECIAL, + isRequired: true, + items: controller.allFromAccounts, + onItemSelected: (item) { + // controller.updateSelectedDeposit(item!); + controller.onFromAccountSelection(item!); + }, + ), + controller.toAccountField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}toAccountField"), + controller: FormFieldConstants.instance().getController("${className}toAccountField"), + labelText: "To Account", + readOnly: true, + showCursor: false, + ), + Row( + children: [ + Expanded( + flex: 1, + child: controller.sendingAmountField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + textInputAction: TextInputAction.done, + refKey: FormFieldConstants.instance().getFormKey("${className}sendingAmountField"), + controller: FormFieldConstants.instance().getController("${className}sendingAmountField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), + isRequired: true, + keyboardType: const TextInputType.numberWithOptions(decimal: true), + inputFormatters: InputType.maxValueFilter(InputType.INT_MAX_VALUE_, true, 2), + ), + ), + const SizedBox(width: 10), + Expanded( + flex: 1, + child: controller.exchangeRateField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}exchangeRateField"), + controller: FormFieldConstants.instance().getController("${className}exchangeRateField"), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), + readOnly: true, + showCursor: false, + ), + ), + ], + ), + controller.userTransactionPinField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}userTransactionPinField"), + controller: FormFieldConstants.instance().getController("${className}userTransactionPinField"), + hintText: "Enter transaction pin", + labelText: "Transaction Pin", + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isRequired: true, + isPassword: true, + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + transactionPinDialog(context, controller); + }, + ), + controller.referenceCodeField = InputField( + enableInteractiveSelection: false, + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isRequired: true, + isPassword: true, + refKey: FormFieldConstants.instance().getFormKey("${className}referenceCodeField"), + controller: FormFieldConstants.instance().getController("${className}referenceCodeField"), + hintText: "Enter reference code", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + referenceCodeDialog(context, controller); + }, + ), + controller.messageField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + refKey: FormFieldConstants.instance().getFormKey("${className}messageField"), + controller: FormFieldConstants.instance().getController("${className}messageField"), + hintText: "Enter message", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textMessageMemo), + onSubmitted: (value) { + controller.sendBeneficiaryTransaction(); + }, + ), + const SizedBox(height: 20), + Row( + children: [ + Expanded( + flex: 1, + child: CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.sendBeneficiaryTransaction(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textSend), + buttonPadding: const EdgeInsets.symmetric(vertical: 11), + textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.white), + buttonColor: AppColors.colorButton, + ), + ), + // const SizedBox(width: 10), + // Expanded( + // flex: 1, + // child: CustomButton( + // onPressed: () { + // FocusScope.of(context).requestFocus(FocusNode()); + // controller.clearTransaction(); + // controller.disposeAllResources(); + // }, + // buttonPadding: const EdgeInsets.symmetric(vertical: 11), + // buttonText: TranslationKeys.makeTranslation(TranslationKeys.textClear), + // buttonColor: AppColors.colorSkipBtn, + // textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black), + // sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1), + // ), + // ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + ], + ), + ); + } + + /// Pin Dialog...........Transactions + void transactionPinDialog(BuildContext context, BeneficiaryTransferController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textTransactionPin), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.pinPutController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.userTransactionPinField.setText(controller.pinPutController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + /// Reference Dialog...........Transactions + void referenceCodeDialog(BuildContext context, BeneficiaryTransferController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.referenceCodeController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350, + ), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + textInputAction: TextInputAction.done, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.referenceCodeController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.referenceCodeField.setText(controller.referenceCodeController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } +} diff --git a/lib/app/modules/beneficiary_transfer_money_otp/bindings/beneficiary_transfer_otp_binding.dart b/lib/app/modules/beneficiary_transfer_money_otp/bindings/beneficiary_transfer_otp_binding.dart new file mode 100644 index 0000000..e2b7a35 --- /dev/null +++ b/lib/app/modules/beneficiary_transfer_money_otp/bindings/beneficiary_transfer_otp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; +import '../controllers/beneficiary_transfer_otp_controller.dart'; + + +class BeneficiaryTransferOtpBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => BeneficiaryTransferOtpController(), + ); + } +} diff --git a/lib/app/modules/beneficiary_transfer_money_otp/controllers/beneficiary_transfer_otp_controller.dart b/lib/app/modules/beneficiary_transfer_money_otp/controllers/beneficiary_transfer_otp_controller.dart new file mode 100644 index 0000000..cf2df59 --- /dev/null +++ b/lib/app/modules/beneficiary_transfer_money_otp/controllers/beneficiary_transfer_otp_controller.dart @@ -0,0 +1,75 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/BeneficiaryAccountModel.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/TransactionPinRequestModel.dart'; +import '../../../models/TransactionSubmitRequestModel.dart'; +import '../../../routes/app_pages.dart'; + + +class BeneficiaryTransferOtpController extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + + TextEditingController pinPutController = TextEditingController(); + TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel.empty(); + TransactionPinRequestModel pinRequestModel = TransactionPinRequestModel.empty(); + String exchangeRate = ""; + + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + + late DepositAccount fromAccount; + late DepositAccount toAccount; + late List beneficiaryList; + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + transactionSubmitRequestModel = (arguments != null ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? TransactionSubmitRequestModel.empty() : TransactionSubmitRequestModel.empty()); + pinRequestModel = (arguments != null ? arguments[AppConstants.SEND_TRANS_PIN_REQUEST] ?? TransactionPinRequestModel.empty() : TransactionPinRequestModel.empty()); + exchangeRate = (arguments != null ? arguments[AppConstants.EXCHANGE_RATE] ?? "" : ""); + } + + Future validatePinAndNavigate() async { + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + + transactionSubmitRequestModel.pinType = "TRAN"; + + transactionSubmitRequestModel.obpPincode = pinPutController.text; + + Get.toNamed(Routes.RECIPIENT_DETAILS, arguments: { + AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + AppConstants.EXCHANGE_RATE: exchangeRate, + }); + } + + Future sendBeneficiaryTransaction({navigate = true}) async { + ServerResponse response = await repository.sendTransactionStep1(pinRequestModel); + + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Toasty.success("OTP send successfully"); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/beneficiary_transfer_money_otp/views/beneficiary_transfer_otp_view.dart b/lib/app/modules/beneficiary_transfer_money_otp/views/beneficiary_transfer_otp_view.dart new file mode 100644 index 0000000..6a55c51 --- /dev/null +++ b/lib/app/modules/beneficiary_transfer_money_otp/views/beneficiary_transfer_otp_view.dart @@ -0,0 +1,138 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../controllers/beneficiary_transfer_otp_controller.dart'; + + + +class BeneficiaryTransferOtpView extends GetView { + const BeneficiaryTransferOtpView({Key? key, this.showAppBar = true}) : super(key: key); + final bool showAppBar; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + textInputAction: TextInputAction.done, + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle(fontSize: 12), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.sendBeneficiaryTransaction(navigate: false); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/bill_management/bindings/bill_management_binding.dart b/lib/app/modules/bill_management/bindings/bill_management_binding.dart new file mode 100644 index 0000000..3c39272 --- /dev/null +++ b/lib/app/modules/bill_management/bindings/bill_management_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/bill_management_controller.dart'; + +class BillManagementBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => BillManagementController(), + ); + } +} diff --git a/lib/app/modules/bill_management/controllers/bill_management_controller.dart b/lib/app/modules/bill_management/controllers/bill_management_controller.dart new file mode 100644 index 0000000..1e87838 --- /dev/null +++ b/lib/app/modules/bill_management/controllers/bill_management_controller.dart @@ -0,0 +1,6 @@ +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/bill_management/views/bill_management_view.dart'; + +class BillManagementController extends GetxController { + +} diff --git a/lib/app/modules/bill_management/views/bill_management_view.dart b/lib/app/modules/bill_management/views/bill_management_view.dart new file mode 100644 index 0000000..25e009d --- /dev/null +++ b/lib/app/modules/bill_management/views/bill_management_view.dart @@ -0,0 +1,149 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_label.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../../login/views/shared/bottom_sheet_login.dart'; +import '../controllers/bill_management_controller.dart'; + +class BillManagementView extends GetView { + const BillManagementView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.transUtilityBill), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textSelectBillType), style: Theme.of(context).textTheme.titleSmall!.copyWith(color: AppColors.colorTitle)), + ), + const SizedBox(height: 20), + Wrap( + children: [ + GridView.builder( + padding: const EdgeInsets.only(left: 15, right: 15, top: 0, bottom: 15), + itemCount: options.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + BottomSheetLogin bottomSheetLogin = options[index]; + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: bottomSheetLogin.onTap, + child: Container( + padding: const EdgeInsets.all(8), + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: AppColors.colorGrey350, width: 1), borderRadius: const BorderRadius.all(Radius.circular(10))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + bottomSheetLogin.icon, + width: 50, + ), + const SizedBox(height: 10), + Center( + child: LabelText(fontSize: 12, bottomSheetLogin.description), + ), + ], + ))); + }, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + childAspectRatio: 0.4 / 0.3, + crossAxisCount: 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + )), + ], + ), + ], + ), + ), + ), + ); + } + + static List options = [ + BottomSheetLogin( + billTypes: "${BillType.electricity}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityElectricity), + icon: AppAssets.ic_electricity, + onTap: () { + Get.toNamed(Routes.BILL_MANAGEMENT_CATEGORY, arguments: BillType.electricity); + }), + BottomSheetLogin( + billTypes: "${BillType.gas}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityGas), + icon: AppAssets.ic_gas, + onTap: () { + Get.toNamed(Routes.BILL_MANAGEMENT_CATEGORY, arguments: BillType.gas); + }), + BottomSheetLogin( + billTypes: "${BillType.internet}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityInternet), + icon: AppAssets.ic_internet, + onTap: () { + Get.toNamed(Routes.BILL_MANAGEMENT_CATEGORY, arguments: BillType.internet); + }), + BottomSheetLogin( + billTypes: "${BillType.water}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityWater), + icon: AppAssets.ic_water, + onTap: () { + Get.toNamed(Routes.BILL_MANAGEMENT_CATEGORY, arguments: BillType.water); + }), + // BottomSheetLogin( + // billTypes: "${BillType.creditCard}", + // description: TranslationKeys.makeTranslation( + // TranslationKeys.transUtilityCreditCard), + // icon: AppAssets.ic_card, + // onTap: () { + // Get.toNamed(Routes.BILL_MANAGEMENT_CATEGORY, + // arguments: BillType.creditCard); + // }), + ]; +} + +/// Enum to represent different bill types +enum BillType { + electricity, + gas, + internet, + ptcl, + water, + creditCard, + utilityAJKBARKIYAT, + utilityFESCO, + utilityGBBARKIYAT, + utilityIESCO, + utilityGEPCO, + utilityHESCO, + pakGasAgency, + suitGas, + fiber, + zong, + nestle, + aqua, + pepsiCo, + minerva, +} diff --git a/lib/app/modules/bill_management_category/bindings/bill_management_category_binding.dart b/lib/app/modules/bill_management_category/bindings/bill_management_category_binding.dart new file mode 100644 index 0000000..d35f5df --- /dev/null +++ b/lib/app/modules/bill_management_category/bindings/bill_management_category_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/bill_management_category_controller.dart'; + +class BillManagementCategoryBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => BillManagementCategoryController(), + ); + } +} diff --git a/lib/app/modules/bill_management_category/controllers/bill_management_category_controller.dart b/lib/app/modules/bill_management_category/controllers/bill_management_category_controller.dart new file mode 100644 index 0000000..1d105ce --- /dev/null +++ b/lib/app/modules/bill_management_category/controllers/bill_management_category_controller.dart @@ -0,0 +1,247 @@ +import 'package:get/get.dart'; + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../routes/app_pages.dart'; +import '../../bill_management/views/bill_management_view.dart'; +import '../../login/views/shared/bottom_sheet_login.dart'; + + +class BillManagementCategoryController extends GetxController { + List getOptions(BillType? selectedBillType) { + switch (selectedBillType) { + case BillType.electricity: + return optionsElectricity; + case BillType.gas: + return optionsGas; + case BillType.internet: + return optionsInternet; + case BillType.water: + return optionsWater; + default: + return []; + } + } + + String getBillTypeCategory(BillType? billType) { + switch (billType) { + case BillType.electricity: + return TranslationKeys.makeTranslation(TranslationKeys.transUtilityElectricity); + case BillType.gas: + return TranslationKeys.makeTranslation(TranslationKeys.transUtilityGas); + case BillType.internet: + return TranslationKeys.makeTranslation(TranslationKeys.transUtilityInternet); + case BillType.water: + return TranslationKeys.makeTranslation(TranslationKeys.transUtilityWater); + default: + return ''; + } + } + + /// Helper function to get category based on bill type + String getBillTypeCategoryS(BillType? billType) { + switch (billType) { + case BillType.electricity: + return 'Electricity Bill'; + case BillType.gas: + return 'Gas Bill'; + case BillType.internet: + return 'Internet Bill'; + case BillType.water: + return 'Water Bill'; + default: + return 'Unknown'; + } + } + + List optionsElectricity = [ + BottomSheetLogin( + billTypes: "${BillType.utilityAJKBARKIYAT}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityAJKBARKIYAT), + icon: AppAssets.ic_government, + onTap: () { + Get.toNamed( + Routes.UTILITY_BILLS_SELECTED_CATEGORY, + arguments: { + "billTypes": "${BillType.utilityAJKBARKIYAT}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transUtilityAJKBARKIYAT), + "icon": AppAssets.ic_government, + }, + ); + }), + BottomSheetLogin( + billTypes: "${BillType.utilityFESCO}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityFESCO), + icon: AppAssets.ic_multan, + onTap: () { + Get.toNamed( + Routes.UTILITY_BILLS_SELECTED_CATEGORY, + arguments: { + "billTypes": "${BillType.utilityFESCO}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transUtilityFESCO), + "icon": AppAssets.ic_multan, + }, + ); + }), + BottomSheetLogin( + billTypes: "${BillType.utilityGBBARKIYAT}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityGBBARKIYAT), + icon: AppAssets.ic_government, + onTap: () { + Get.toNamed( + Routes.UTILITY_BILLS_SELECTED_CATEGORY, + arguments: { + "billTypes": "${BillType.utilityGBBARKIYAT}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transUtilityGBBARKIYAT), + "icon": AppAssets.ic_government, + }, + ); + }), + BottomSheetLogin( + billTypes: "${BillType.utilityIESCO}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityGEPCO), + icon: AppAssets.ic_khan, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.utilityIESCO}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transUtilityGEPCO), + "icon": AppAssets.ic_khan, + }); + }), + BottomSheetLogin( + billTypes: "${BillType.utilityGEPCO}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityHESCO), + icon: AppAssets.ic_ke, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.utilityGEPCO}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transUtilityHESCO), + "icon": AppAssets.ic_ke, + }); + }), + BottomSheetLogin( + billTypes: "${BillType.utilityHESCO}", + description: TranslationKeys.makeTranslation(TranslationKeys.transUtilityIESCO), + icon: AppAssets.ic_kc, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.utilityHESCO}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transUtilityIESCO), + "icon": AppAssets.ic_kc, + }); + }), + ]; + + List optionsGas = [ + BottomSheetLogin( + billTypes: "${BillType.pakGasAgency}", + description: TranslationKeys.makeTranslation(TranslationKeys.transPakGasAgency), + icon: AppAssets.ic_government, + onTap: () { + Get.toNamed( + Routes.UTILITY_BILLS_SELECTED_CATEGORY, + arguments: { + "billTypes": "${BillType.pakGasAgency}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transPakGasAgency), + "icon": AppAssets.ic_government, + }, + ); + }), + BottomSheetLogin( + billTypes: "${BillType.suitGas}", + description: TranslationKeys.makeTranslation("Sui Gas"), + icon: AppAssets.ic_gas, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.suitGas}", + "description": TranslationKeys.makeTranslation("Sui Gas"), + "icon": AppAssets.ic_sui_gas, + }); + }), + ]; + + List optionsInternet = [ + BottomSheetLogin( + billTypes: "${BillType.fiber}", + description: TranslationKeys.makeTranslation(TranslationKeys.transFiber), + icon: AppAssets.ic_government, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.fiber}", + "description": + TranslationKeys.makeTranslation(TranslationKeys.transFiber), + "icon": AppAssets.ic_government, + }); + }), + BottomSheetLogin( + billTypes: "${BillType.zong}", + description: TranslationKeys.makeTranslation(TranslationKeys.transZong), + icon: AppAssets.ic_multan, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.zong}", + "description": + TranslationKeys.makeTranslation(TranslationKeys.transZong), + "icon": AppAssets.ic_multan, + }); + }), + ]; + + List optionsWater = [ + BottomSheetLogin( + billTypes: "${BillType.nestle}", + description: TranslationKeys.makeTranslation(TranslationKeys.transNestle), + icon: AppAssets.ic_government, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.nestle}", + "description": + TranslationKeys.makeTranslation(TranslationKeys.transNestle), + "icon": AppAssets.ic_government, + }); + }), + BottomSheetLogin( + billTypes: "${BillType.aqua}", + description: TranslationKeys.makeTranslation(TranslationKeys.transAquaFujitenma), + icon: AppAssets.ic_multan, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.aqua}", + "description": TranslationKeys.makeTranslation( + TranslationKeys.transAquaFujitenma), + "icon": AppAssets.ic_multan, + }); + }), + BottomSheetLogin( + billTypes: "${BillType.pepsiCo}", + description: TranslationKeys.makeTranslation(TranslationKeys.transPepsiCo), + icon: AppAssets.ic_government, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.pepsiCo}", + "description": + TranslationKeys.makeTranslation(TranslationKeys.transPepsiCo), + "icon": AppAssets.ic_government, + }); + }), + BottomSheetLogin( + billTypes: "${BillType.minerva}", + description: TranslationKeys.makeTranslation(TranslationKeys.transMinerva), + icon: AppAssets.ic_khan, + onTap: () { + Get.toNamed(Routes.UTILITY_BILLS_SELECTED_CATEGORY, arguments: { + "billTypes": "${BillType.minerva}", + "description": + TranslationKeys.makeTranslation(TranslationKeys.transMinerva), + "icon": AppAssets.ic_khan, + }); + }), + ]; +} diff --git a/lib/app/modules/bill_management_category/views/bill_management_category_view.dart b/lib/app/modules/bill_management_category/views/bill_management_category_view.dart new file mode 100644 index 0000000..6a92a33 --- /dev/null +++ b/lib/app/modules/bill_management_category/views/bill_management_category_view.dart @@ -0,0 +1,116 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_label.dart'; +import '../../../res/app_colors.dart'; +import '../../bill_management/views/bill_management_view.dart'; +import '../../login/views/shared/bottom_sheet_login.dart'; +import '../controllers/bill_management_category_controller.dart'; + +class BillManagementCategoryView extends GetView { + const BillManagementCategoryView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + BillType? selectedBillType = Get.arguments; + + String category = controller.getBillTypeCategory(selectedBillType); + + List options = controller.getOptions(selectedBillType); + + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(category), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Column( + children: [ + Container( + margin: const EdgeInsets.symmetric(horizontal: 30, vertical: 18), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 12.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation(TranslationKeys.textSelectCompany), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + Icon( + Icons.search, + size: 15.0, + color: Colors.grey[800], + ), + ], + ), + ), + Wrap( + children: [ + GridView.builder( + padding: const EdgeInsets.only( + left: 15, + right: 15, + top: 0, + bottom: 15, + ), + itemCount: options.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + BottomSheetLogin bottomSheetLogin = controller.getOptions(selectedBillType)[index]; + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: bottomSheetLogin.onTap, + child: Container( + padding: const EdgeInsets.all(8), + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: AppColors.colorGrey350, width: 1), borderRadius: const BorderRadius.all(Radius.circular(10))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image( + image: AssetImage(bottomSheetLogin.icon), + width: 50, + ), + const SizedBox(height: 10), + Center( + child: LabelText(fontSize: 12, bottomSheetLogin.description), + ), + ], + ))); + }, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + childAspectRatio: 0.4 / 0.3, + crossAxisCount: 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/career/bindings/career_binding.dart b/lib/app/modules/career/bindings/career_binding.dart new file mode 100644 index 0000000..5e3435b --- /dev/null +++ b/lib/app/modules/career/bindings/career_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/career_controller.dart'; + +class CareerBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => CareerController(), + ); + } +} diff --git a/lib/app/modules/career/controllers/career_controller.dart b/lib/app/modules/career/controllers/career_controller.dart new file mode 100644 index 0000000..5ddb2d0 --- /dev/null +++ b/lib/app/modules/career/controllers/career_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class CareerController extends GetxController { + //TODO: Implement CareerController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/career/views/career_view.dart b/lib/app/modules/career/views/career_view.dart new file mode 100644 index 0000000..24e0603 --- /dev/null +++ b/lib/app/modules/career/views/career_view.dart @@ -0,0 +1,110 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + +// import 'package:url_launcher/url_launcher.dart'; + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../controllers/career_controller.dart'; + +class CareerView extends GetView { + const CareerView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textCareer), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenVerticalPadding), + child: Column( + children: [ + Expanded( + child: ListView.builder( + itemCount: 1, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 0.0, vertical: 3), + child: Card( + elevation: 3, + color: AppColors.colorGrey100, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Container( + decoration: BoxDecoration(color: AppColors.colorText.withOpacity(0.03), borderRadius: const BorderRadius.all(Radius.circular(50))), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + children: [ + Image.asset(AppAssets.lg_mfsys, height: 25, width: 25), + ], + ), + ], + ), + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textJobTitle), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textOfficeAddress), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textJobSkills), style: Theme.of(context).textTheme.bodySmall), + ], + ), + ), + ], + ), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + InkWell( + onTap: (){ + // launch("mailto:info@mfsys.com.pk"); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 3), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorPrimary), + borderRadius: const BorderRadius.all(Radius.circular(5)), + ), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textApply), style: Theme.of(context).textTheme.bodySmall)), + ), + ], + ), + ], + ), + ), + ), + ), + ); + }, + )), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/change_transaction_pin/bindings/change_transaction_pin_binding.dart b/lib/app/modules/change_transaction_pin/bindings/change_transaction_pin_binding.dart new file mode 100644 index 0000000..efcffea --- /dev/null +++ b/lib/app/modules/change_transaction_pin/bindings/change_transaction_pin_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/change_transaction_pin_controller.dart'; + +class ChangeTransactionPinBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChangeTransactionPinController(), + ); + } +} diff --git a/lib/app/modules/change_transaction_pin/controllers/change_transaction_pin_controller.dart b/lib/app/modules/change_transaction_pin/controllers/change_transaction_pin_controller.dart new file mode 100644 index 0000000..618350a --- /dev/null +++ b/lib/app/modules/change_transaction_pin/controllers/change_transaction_pin_controller.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../routes/app_pages.dart'; + + +class ChangeTransactionPinController extends GetxController { + TextEditingController oldTransactionPinController = TextEditingController(); + TextEditingController newTransactionPinController = TextEditingController(); + TextEditingController confirmTransactionPinController = TextEditingController(); + + final AppRepositories repository = Get.find(); + + void validateAndSendRequest() async { + if (oldTransactionPinController.text.isEmpty) { + Toasty.error("Please input and then proceed!"); + return; + } + + if (newTransactionPinController.text.isEmpty) { + Toasty.error("Please input and then proceed!"); + return; + } + + if (confirmTransactionPinController.text.isEmpty) { + Toasty.error("Please input and then proceed!"); + return; + } + + // if (oldTransactionPinController.text != newTransactionPinController.text) { + // Toasty.error("Old and New Transaction Pin not match!"); + // return; + // } + + if (newTransactionPinController.text != confirmTransactionPinController.text) { + Toasty.error("New and Confirm Transaction Pin not match!"); + return; + } + + + // ChangeTransactionPinRequest request = ChangeTransactionPinRequest( + // oldTransPincode: oldTransactionPinController.text, + // newTransPincode: newTransactionPinController.text, + // channelCode: RequestConstants.channelCode, + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // isOtpRequired: false, + // pinType: AppConstants.PIN_TYPE_Transaction, + // + // ); + // + // ServerResponse response = await repository.changeTransactionPin(request); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + + Get.toNamed(Routes.CHANGE_TRANSACTION_PIN_OTP, + // arguments: { + // 'oldTransactionPin': oldTransactionPinController.text, + // 'newTransactionPin': newTransactionPinController.text, + // 'confirmTransactionPin': confirmTransactionPinController.text, + // AppConstants.CHANGE_TRANSACTION_PIN_OTP: request, + // }, + ); + + clearController(); + } + + void clearController() { + newTransactionPinController.clear(); + confirmTransactionPinController.clear(); + oldTransactionPinController.clear(); + } +} diff --git a/lib/app/modules/change_transaction_pin/views/change_transaction_pin_view.dart b/lib/app/modules/change_transaction_pin/views/change_transaction_pin_view.dart new file mode 100644 index 0000000..b526fb9 --- /dev/null +++ b/lib/app/modules/change_transaction_pin/views/change_transaction_pin_view.dart @@ -0,0 +1,241 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/change_transaction_pin_controller.dart'; + +class ChangeTransactionPinView extends GetView { + const ChangeTransactionPinView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textChangeTransactionPin, + ), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.only(right: 20.0, left: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textOldTransactionPin), + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 14, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 10), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.oldTransactionPinController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + textInputAction: TextInputAction.done, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textPleaseCreatenewtransactionpin), + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 14, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 10), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.confirmTransactionPinController, + showCursor: true, + textInputAction: TextInputAction.done, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textConfirmTransactionPin), + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 14, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 10), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.newTransactionPinController, + showCursor: true, + autoDismissKeyboard: false, + textInputAction: TextInputAction.done, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: + TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonColor: AppColors.colorButton, + buttonPadding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 0), + ), + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + // child: SizedBox( + // width: double.infinity, + // child: ElevatedButton( + // onPressed: () { + // controller.validateAndSendRequest(); + // }, + // style: ElevatedButton.styleFrom( + // backgroundColor: AppColors.colorButton, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(50), + // ), + // ), + // child: Padding( + // padding: const EdgeInsets.all(12.0), + // child: Text(TranslationKeys.makeTranslation(TranslationKeys.textNext), style: Theme.of(context).textTheme.labelMedium?.copyWith(color: AppColors.white)), + // ), + // ), + // ), + // ), + ], + persistentFooterAlignment: AlignmentDirectional.bottomCenter, + resizeToAvoidBottomInset: false, + backgroundColor: AppColors.colorSecondary, + ); + } +} diff --git a/lib/app/modules/change_transaction_pin_otp/bindings/change_transaction_pin_otp_binding.dart b/lib/app/modules/change_transaction_pin_otp/bindings/change_transaction_pin_otp_binding.dart new file mode 100644 index 0000000..fba415e --- /dev/null +++ b/lib/app/modules/change_transaction_pin_otp/bindings/change_transaction_pin_otp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/change_transaction_pin_otp_controller.dart'; + +class ChangeTransactionPinOtpBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChangeTransactionPinOtpController(), + ); + } +} diff --git a/lib/app/modules/change_transaction_pin_otp/controllers/change_transaction_pin_otp_controller.dart b/lib/app/modules/change_transaction_pin_otp/controllers/change_transaction_pin_otp_controller.dart new file mode 100644 index 0000000..d2a8140 --- /dev/null +++ b/lib/app/modules/change_transaction_pin_otp/controllers/change_transaction_pin_otp_controller.dart @@ -0,0 +1,93 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/ChangeTransactionPinRequest.dart'; +import '../../../models/resen_ot_chanange_trans_pin.dart'; +import '../../../routes/app_pages.dart'; + +class ChangeTransactionPinOtpController extends GetxController { + TextEditingController pinPutController = TextEditingController(); + final AppRepositories repository = Get.find(); + late String oldTransactionPin; + late String confirmTransactionPin; + late String newTransactionPin; + ChangeTransactionPinRequest changeTransactionPinOTPRequest = ChangeTransactionPinRequest(); + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + late bool isSomething; + late final request; + + @override + void onReady() { + super.onReady(); + var arguments = Get.arguments; + oldTransactionPin = arguments['oldTransactionPin']; + newTransactionPin = arguments['newTransactionPin']; + confirmTransactionPin = arguments['confirmTransactionPin']; + changeTransactionPinOTPRequest = arguments[AppConstants.CHANGE_TRANSACTION_PIN_OTP]; + + dp("oldTransactionPin>>>>", oldTransactionPin); + dp("newTransactionPin>>>>", newTransactionPin); + dp("confirmTransactionPin>>>>", confirmTransactionPin); + } + + void validateAndSendRequest() async { + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + // + // CreateTransactionPinRequest request = CreateTransactionPinRequest( + // channelCode: RequestConstants.channelCode, + // pctCstycode: RequestConstants.pctCstycode, + // porOrgacode: RequestConstants.porOrgacode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // email: SessionCache.instance.userInfo.cmpUserId, + // obpPincode: pinPutController.text, + // pinType: AppConstants.PIN_TYPE_Transaction, + // ); + // + // ServerResponse response = await repository.createTransactionPin(request); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + + clearController(); + CustomDialog.showSuccessDialog( + // title: "Congratulations!", + description: "Your Transaction pin successfully ! An send email and message have been sent to you.", + onTapPositive: () { + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }, + ); + } + + Future sendBeneficiaryTransaction({navigate = true}) async { + ServerResponse response = await repository.changeTransactionPin(changeTransactionPinOTPRequest); + + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Toasty.success("OTP send successfully"); + } + + void clearController() { + pinPutController.clear(); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/change_transaction_pin_otp/views/change_transaction_pin_otp_view.dart b/lib/app/modules/change_transaction_pin_otp/views/change_transaction_pin_otp_view.dart new file mode 100644 index 0000000..284832b --- /dev/null +++ b/lib/app/modules/change_transaction_pin_otp/views/change_transaction_pin_otp_view.dart @@ -0,0 +1,134 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../controllers/change_transaction_pin_otp_controller.dart'; + +class ChangeTransactionPinOtpView extends GetView { + const ChangeTransactionPinOtpView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + textInputAction: TextInputAction.done, + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle(fontSize: 12), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.sendBeneficiaryTransaction(navigate: false); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/cheque_activation/bindings/cheque_activation_binding.dart b/lib/app/modules/cheque_activation/bindings/cheque_activation_binding.dart new file mode 100644 index 0000000..dd26199 --- /dev/null +++ b/lib/app/modules/cheque_activation/bindings/cheque_activation_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_activation_controller.dart'; + +class ChequeActivationBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeActivationController(), + ); + } +} diff --git a/lib/app/modules/cheque_activation/controllers/cheque_activation_controller.dart b/lib/app/modules/cheque_activation/controllers/cheque_activation_controller.dart new file mode 100644 index 0000000..1e158f8 --- /dev/null +++ b/lib/app/modules/cheque_activation/controllers/cheque_activation_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class ChequeActivationController extends GetxController { + //TODO: Implement ChequeActivationController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/cheque_activation/views/cheque_activation_view.dart b/lib/app/modules/cheque_activation/views/cheque_activation_view.dart new file mode 100644 index 0000000..d1258a0 --- /dev/null +++ b/lib/app/modules/cheque_activation/views/cheque_activation_view.dart @@ -0,0 +1,138 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/cheque_activation_controller.dart'; + +class ChequeActivationView extends GetView { + const ChequeActivationView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textChequeBookActivation), + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: CustomButton( + buttonColor: AppColors.colorPrimary, + onPressed: () { + CustomDialog.showSuccessDialog( + description: "Your cheque is activated, successfully!", + onTapPositive: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.back(); + }); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + ), + ), + ], + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textActivationContent), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 20), + Card( + surfaceTintColor: Colors.white, + elevation: 3.0, + child: Container( + decoration: BoxDecoration(borderRadius: const BorderRadius.all(Radius.circular(10)), border: Border.all(color: AppColors.colorGrey350)), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + // crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center(child: Text(TranslationKeys.makeTranslation(TranslationKeys.textAccount), style: Theme.of(context).textTheme.titleSmall)), + Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailCustomerName), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textAccountNumber), style: Theme.of(context).textTheme.bodySmall), + ], + ), + ], + ), + ), + ), + ), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textFirstLeaf), style: Theme.of(context).textTheme.bodySmall), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 10), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation(TranslationKeys.textEnterChequeNumber), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textLastLeaf), style: Theme.of(context).textTheme.bodySmall), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 10), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation(TranslationKeys.textEnterChequeNumber), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/cheque_book_request_details/bindings/cheque_book_request_details_binding.dart b/lib/app/modules/cheque_book_request_details/bindings/cheque_book_request_details_binding.dart new file mode 100644 index 0000000..9d69cc9 --- /dev/null +++ b/lib/app/modules/cheque_book_request_details/bindings/cheque_book_request_details_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_book_request_details_controller.dart'; + +class ChequeBookRequestDetailsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeBookRequestDetailsController(), + ); + } +} diff --git a/lib/app/modules/cheque_book_request_details/controllers/cheque_book_request_details_controller.dart b/lib/app/modules/cheque_book_request_details/controllers/cheque_book_request_details_controller.dart new file mode 100644 index 0000000..e5ee2a5 --- /dev/null +++ b/lib/app/modules/cheque_book_request_details/controllers/cheque_book_request_details_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class ChequeBookRequestDetailsController extends GetxController { + //TODO: Implement ChequeBookRequestDetailsController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/cheque_book_request_details/views/cheque_book_request_details_view.dart b/lib/app/modules/cheque_book_request_details/views/cheque_book_request_details_view.dart new file mode 100644 index 0000000..b3f78d1 --- /dev/null +++ b/lib/app/modules/cheque_book_request_details/views/cheque_book_request_details_view.dart @@ -0,0 +1,334 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/cheque_book_request_details_controller.dart'; + +class ChequeBookRequestDetailsView + extends GetView { + const ChequeBookRequestDetailsView({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textChequeRequestDetail), + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: CustomButton( + buttonColor: AppColors.colorButton, + onPressed: () { + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }, + buttonText: + TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: + const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + ), + ), + ], + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textChequeBookRequestContent), + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontSize: 14, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 20), + Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border.all(color: AppColors.colorGrey350)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textLeave20), + style: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith( + fontWeight: FontWeight.w600, fontSize: 28)), + InkWell( + onTap: () { + Get.back(); + }, + child: Container( + decoration: BoxDecoration( + color: AppColors.colorButton, + borderRadius: BorderRadius.circular(50), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15.0, vertical: 4), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textChange), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColors.white)), + ), + ), + ), + ], + ), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textLeaves), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColors.colorGrey800)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDeliveryAddress), + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(color: AppColors.colorGrey800)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textChequeBookRequestAddress), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColors.colorGrey800)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textCharges), + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(color: AppColors.colorGrey800)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textScheduleCharges), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColors.colorGrey800)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation(TranslationKeys.textDate), + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(color: AppColors.colorGrey800)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDateContent), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColors.colorGrey800)), + ], + ), + ), + ], + ), + ), + ); + } + + /// SuccessFull Dialog...........Transactions + void showTransactionSuccess(BuildContext context) { + Get.dialog( + Dialog( + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(2), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + children: [ + Align( + alignment: Alignment.topRight, + child: InkWell( + onTap: () { + Navigator.of(context, rootNavigator: true).pop(); + }, + child: SvgPicture.asset( + AppAssets.ic_close, + height: 67, + width: 67, + ), + ), + ), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 0), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textRequestSummary), + style: Theme.of(context) + .textTheme + .titleMedium + ?.copyWith( + fontWeight: FontWeight.w700, fontSize: 24)), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textNumberofLeaves), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textLeave20), + style: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith( + fontWeight: FontWeight.w600, fontSize: 22)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 0), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDeliveryAddress), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textChequeBookRequestAddress), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 12)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textCharges), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textScheduleCharges), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDate), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 0, vertical: 5), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDateContent), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, vertical: 10), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textQueryContent), + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontWeight: FontWeight.w400, + fontSize: 10, + color: AppColors.colorGrey800)), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, vertical: 10), + child: CustomButton( + buttonColor: AppColors.colorPrimaryLight, + onPressed: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.offAndToNamed(Routes.CHEQUE_MANAGEMENT); + }, + buttonText: TranslationKeys.makeTranslation( + TranslationKeys.textDeposit), + ), + ), + ], + ), + ], + ), + ), + ), + ), + barrierDismissible: false); + } +} diff --git a/lib/app/modules/cheque_deposit/bindings/cheque_deposit_binding.dart b/lib/app/modules/cheque_deposit/bindings/cheque_deposit_binding.dart new file mode 100644 index 0000000..edc826a --- /dev/null +++ b/lib/app/modules/cheque_deposit/bindings/cheque_deposit_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_deposit_controller.dart'; + +class ChequeDepositBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeDepositController(), + ); + } +} diff --git a/lib/app/modules/cheque_deposit/controllers/cheque_deposit_controller.dart b/lib/app/modules/cheque_deposit/controllers/cheque_deposit_controller.dart new file mode 100644 index 0000000..9f09bc8 --- /dev/null +++ b/lib/app/modules/cheque_deposit/controllers/cheque_deposit_controller.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +class ChequeDepositController extends GetxController { + final List items = [ + '22222222', + '55555555', + '11111111', + '88888888', + ]; + RxString selectedValue = "22222222".obs; + +} diff --git a/lib/app/modules/cheque_deposit/views/cheque_deposit_view.dart b/lib/app/modules/cheque_deposit/views/cheque_deposit_view.dart new file mode 100644 index 0000000..8eecd71 --- /dev/null +++ b/lib/app/modules/cheque_deposit/views/cheque_deposit_view.dart @@ -0,0 +1,307 @@ +import 'package:dropdown_button2/dropdown_button2.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/cheque_deposit_controller.dart'; + +class ChequeDepositView extends GetView { + const ChequeDepositView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textChequeDeposit), + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterAlignment: AlignmentDirectional.bottomCenter, + resizeToAvoidBottomInset: false, + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: () { + Get.back(); + // showTransactionSuccess(context); + // controerll.cleanControllers(); + // Get.toNamed(Routes.CHEQUE_MANAGEMENT); + }, + style: ElevatedButton.styleFrom( + backgroundColor: AppColors.colorButton, + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + ), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textContinue), style: Theme.of(context).textTheme.labelMedium?.copyWith(color: AppColors.white)), + ), + ), + ), + ], + body: Padding( + padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textChequeStatusContent), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textDepositToChequing), style: Theme.of(context).textTheme.bodySmall), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 7), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation(TranslationKeys.text1000), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textMax300000), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, color: AppColors.colorText, fontSize: 8)), + ), + ], + ), + ), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textSelectAccount), style: Theme.of(context).textTheme.bodySmall), + Obx(() { + return Container( + width: double.infinity, + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 7), + height: 40, + //padding: EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton2( + isExpanded: true, + hint: Text( + 'Select Item', + style: TextStyle( + fontSize: 14, + color: Theme.of(context).hintColor, + ), + ), + items: controller.items + .map((String item) => DropdownMenuItem( + value: item, + child: Text( + item, + style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 12, fontWeight: FontWeight.w400, color: AppColors.colorText), + ), + )) + .toList(), + value: controller.selectedValue.value, + onChanged: (String? value) { + controller.selectedValue.value = value!; + }, + buttonStyleData: const ButtonStyleData( + padding: EdgeInsets.symmetric(horizontal: 16), + height: 40, + width: 140, + ), + ), + ), + ); + }), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textFrontOfCheque), style: Theme.of(context).textTheme.bodySmall), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBackofCheque), style: Theme.of(context).textTheme.bodySmall), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 7), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AppColors.colorGrey350), + borderRadius: BorderRadius.circular(5), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + const Align( + alignment: Alignment.topRight, + child: Padding( + padding: EdgeInsets.only(top: 5, right: 5), + child: Icon(Icons.close, color: AppColors.colorText, size: 20), + )), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 10), + child: SvgPicture.asset( + AppAssets.ic_camera, + height: 70, + width: 70, + ), + ), + ], + ), + ), + ], + ), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 7), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AppColors.colorGrey350), + borderRadius: BorderRadius.circular(5), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + const Align( + alignment: Alignment.topRight, + child: Padding( + padding: EdgeInsets.only(top: 5, right: 5), + child: Icon(Icons.close, color: AppColors.colorText, size: 20), + )), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 10), + child: SvgPicture.asset(AppAssets.ic_camera, height: 70, width: 70), + ), + ], + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textTryAgain), style: Theme.of(context).textTheme.bodySmall?.copyWith(color: AppColors.colorText, fontWeight: FontWeight.w400, fontSize: 8)), + Text(TranslationKeys.makeTranslation(TranslationKeys.textTryAgain), style: Theme.of(context).textTheme.bodySmall?.copyWith(color: AppColors.colorText, fontWeight: FontWeight.w400, fontSize: 8)), + ], + ), + ], + ), + ), + ); + } + void showTransactionSuccess(BuildContext context) { + Get.dialog( + Dialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(2), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + children: [ + Align( + alignment: Alignment.topRight, + child: InkWell( + onTap: () { + Navigator.of(context, rootNavigator: true).pop(); + }, + child: SvgPicture.asset( + AppAssets.ic_close, + height: 67, + width: 67, + ), + ), + ), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 0), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textRequestSummary), style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w700, fontSize: 24)), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textNumberofLeaves), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textLeave20), style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w600, fontSize: 22)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 0), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textDeliveryAddress), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textChequeBookRequestAddress), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textCharges), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textScheduleCharges), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textDate), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textDateContent), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 16)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textQueryContent), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 10, color: AppColors.colorGrey800)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: CustomButton( + buttonColor: AppColors.colorPrimaryLight, + onPressed: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.offAndToNamed(Routes.CHEQUE_MANAGEMENT); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textDeposit), + ), + ), + ], + ), + ], + ), + ), + ), + ), + barrierDismissible: false); + } + +} + diff --git a/lib/app/modules/cheque_management/bindings/cheque_management_binding.dart b/lib/app/modules/cheque_management/bindings/cheque_management_binding.dart new file mode 100644 index 0000000..777c605 --- /dev/null +++ b/lib/app/modules/cheque_management/bindings/cheque_management_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_management_controller.dart'; + +class ChequeManagementBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeManagementController(), + ); + } +} diff --git a/lib/app/modules/cheque_management/controllers/cheque_management_controller.dart b/lib/app/modules/cheque_management/controllers/cheque_management_controller.dart new file mode 100644 index 0000000..4e262f3 --- /dev/null +++ b/lib/app/modules/cheque_management/controllers/cheque_management_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class ChequeManagementController extends GetxController { + //TODO: Implement ChequeManagementController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/cheque_management/views/cheque_management_view.dart b/lib/app/modules/cheque_management/views/cheque_management_view.dart new file mode 100644 index 0000000..336a4dc --- /dev/null +++ b/lib/app/modules/cheque_management/views/cheque_management_view.dart @@ -0,0 +1,103 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../../login/views/shared/bottom_sheet_login.dart'; +import '../controllers/cheque_management_controller.dart'; + +class ChequeManagementView extends GetView { + const ChequeManagementView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textChequeManagement), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Wrap( + children: [ + GridView.builder( + padding: const EdgeInsets.only(left: 15, right: 15, top: 0, bottom: 15), + itemCount: options.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + BottomSheetLogin bottomSheetLogin = options[index]; + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: bottomSheetLogin.onTap, + child: Container( + padding: const EdgeInsets.all(8), + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: AppColors.colorGrey350, width: 1), borderRadius: const BorderRadius.all(Radius.circular(10))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + bottomSheetLogin.icon, + width: 50, + ), + const SizedBox(height: 10), + Center( + child: Text(bottomSheetLogin.description, style: Theme.of(context).textTheme.titleSmall), + ), + ], + ))); + }, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + childAspectRatio: 0.4 / 0.3, + crossAxisCount: 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + )), + ], + ), + ], + ), + ), + ), + ); + } + + static List options = [ + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textChequeStatus), + icon: AppAssets.ic_check_status, + onTap: () { + Get.toNamed(Routes.CHEQUE_STATUS); + }), + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textChequeDeposit), + icon: AppAssets.ic_cheque_deposit, + onTap: () { + Get.toNamed(Routes.CHEQUE_DEPOSIT); + }), + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textChequeActivation), + icon: AppAssets.ic_activation, + onTap: () { + Get.toNamed(Routes.CHEQUE_ACTIVATION); + }), + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textChequeRequest), + icon: AppAssets.ic_request, + onTap: () { + Get.toNamed(Routes.CHEQUE_REQUEST); + }), + ]; +} diff --git a/lib/app/modules/cheque_request/bindings/cheque_request_binding.dart b/lib/app/modules/cheque_request/bindings/cheque_request_binding.dart new file mode 100644 index 0000000..f7af196 --- /dev/null +++ b/lib/app/modules/cheque_request/bindings/cheque_request_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_request_controller.dart'; + +class ChequeRequestBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeRequestController(), + ); + } +} diff --git a/lib/app/modules/cheque_request/controllers/cheque_request_controller.dart b/lib/app/modules/cheque_request/controllers/cheque_request_controller.dart new file mode 100644 index 0000000..4a57f8a --- /dev/null +++ b/lib/app/modules/cheque_request/controllers/cheque_request_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class ChequeRequestController extends GetxController { + //TODO: Implement ChequeRequestController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/cheque_request/views/cheque_request_view.dart b/lib/app/modules/cheque_request/views/cheque_request_view.dart new file mode 100644 index 0000000..282c6df --- /dev/null +++ b/lib/app/modules/cheque_request/views/cheque_request_view.dart @@ -0,0 +1,125 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_label.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/cheque_request_controller.dart'; + +class ChequeRequestView extends GetView { + const ChequeRequestView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textChequeRequest), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textChequeRequestContent), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + ), + const SizedBox(height: 20), + Wrap( + children: [ + GridView.builder( + padding: const EdgeInsets.only(left: 10, right: 10, top: 0, bottom: 15), + itemCount: options.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + ChequeRequestModel bottomSheetLogin = options[index]; + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: bottomSheetLogin.onTap, + child: Container( + padding: const EdgeInsets.all(8), + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: AppColors.colorGrey350, width: 1), borderRadius: const BorderRadius.all(Radius.circular(10))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: LabelText(bottomSheetLogin.leave, labelColor: AppColors.colorGrey800, fontWeight: FontWeight.w600), + ), + const SizedBox(height: 5), + Center( + child: LabelText(bottomSheetLogin.description, labelColor: AppColors.colorGrey400, fontSize: 12), + ), + const SizedBox(height: 10), + Container( + decoration: BoxDecoration( + color: AppColors.colorGrey350, + borderRadius: BorderRadius.circular(50), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 4), + child: Text( + bottomSheetLogin.buttonText, + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: AppColors.black), + ), + ), + ), + ], + ))); + }, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + childAspectRatio: 0.4 / 0.3, + crossAxisCount: 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + )), + ], + ), + ], + ), + ), + ); + } + + static List options = [ + ChequeRequestModel( + leave: TranslationKeys.makeTranslation(TranslationKeys.textLeave20), + description: TranslationKeys.makeTranslation(TranslationKeys.textLeaves), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textGet), + onTap: () { + Get.toNamed(Routes.CHEQUE_BOOK_REQUEST_DETAILS); + }), + ChequeRequestModel( + leave: TranslationKeys.makeTranslation(TranslationKeys.textLeave50), + description: TranslationKeys.makeTranslation(TranslationKeys.textLeaves), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textGet), + onTap: () { + Get.toNamed(Routes.CHEQUE_BOOK_REQUEST_DETAILS); + }), + ChequeRequestModel( + leave: TranslationKeys.makeTranslation(TranslationKeys.textLeave100), + description: TranslationKeys.makeTranslation(TranslationKeys.textLeaves), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textGet), + onTap: () { + Get.toNamed(Routes.CHEQUE_BOOK_REQUEST_DETAILS); + }), + ]; +} + +class ChequeRequestModel { + String leave; + String description; + String buttonText; + Function()? onTap; + + ChequeRequestModel({required this.leave, required this.description, required this.buttonText, required this.onTap}); +} diff --git a/lib/app/modules/cheque_status/bindings/cheque_status_binding.dart b/lib/app/modules/cheque_status/bindings/cheque_status_binding.dart new file mode 100644 index 0000000..ea91147 --- /dev/null +++ b/lib/app/modules/cheque_status/bindings/cheque_status_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_status_controller.dart'; + +class ChequeStatusBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeStatusController(), + ); + } +} diff --git a/lib/app/modules/cheque_status/controllers/cheque_status_controller.dart b/lib/app/modules/cheque_status/controllers/cheque_status_controller.dart new file mode 100644 index 0000000..59a7070 --- /dev/null +++ b/lib/app/modules/cheque_status/controllers/cheque_status_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class ChequeStatusController extends GetxController { + //TODO: Implement ChequeStatusController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/cheque_status/views/cheque_status_view.dart b/lib/app/modules/cheque_status/views/cheque_status_view.dart new file mode 100644 index 0000000..10a2f6a --- /dev/null +++ b/lib/app/modules/cheque_status/views/cheque_status_view.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/cheque_status_controller.dart'; + +class ChequeStatusView extends GetView { + const ChequeStatusView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textChequeStatus), + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterAlignment: AlignmentDirectional.bottomCenter, + resizeToAvoidBottomInset: false, + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: SizedBox( + width: double.infinity, + child: CustomButton( + buttonColor: AppColors.colorButton, + onPressed: () { + Get.toNamed(Routes.CHEQUE_STATUS_HISTORY); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + ), + // ElevatedButton( + // onPressed: () { + // Get.toNamed(Routes.CHEQUE_STATUS_HISTORY); + // }, + // child: Text("Next", style: Theme.of(context).textTheme.labelMedium?.copyWith(color: AppColors.white)), + // style: ElevatedButton.styleFrom( + // backgroundColor: AppColors.btnColor, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(50), + // ), + // ), + // ), + ), + ), + ], + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textChequeStatusContent), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textChequeNumber), style: Theme.of(context).textTheme.bodySmall), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 18), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation(TranslationKeys.textEnterChequeNumber), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/cheque_status_history/bindings/cheque_status_history_binding.dart b/lib/app/modules/cheque_status_history/bindings/cheque_status_history_binding.dart new file mode 100644 index 0000000..ec3e074 --- /dev/null +++ b/lib/app/modules/cheque_status_history/bindings/cheque_status_history_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/cheque_status_history_controller.dart'; + +class ChequeStatusHistoryBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChequeStatusHistoryController(), + ); + } +} diff --git a/lib/app/modules/cheque_status_history/controllers/cheque_status_history_controller.dart b/lib/app/modules/cheque_status_history/controllers/cheque_status_history_controller.dart new file mode 100644 index 0000000..4f3f7e8 --- /dev/null +++ b/lib/app/modules/cheque_status_history/controllers/cheque_status_history_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class ChequeStatusHistoryController extends GetxController { + //TODO: Implement ChequeStatusHistoryController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/cheque_status_history/views/cheque_status_history_view.dart b/lib/app/modules/cheque_status_history/views/cheque_status_history_view.dart new file mode 100644 index 0000000..46bb17e --- /dev/null +++ b/lib/app/modules/cheque_status_history/views/cheque_status_history_view.dart @@ -0,0 +1,183 @@ +import 'package:flutter/material.dart'; + +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/cheque_status_history_controller.dart'; + +class ChequeStatusHistoryView extends GetView { + const ChequeStatusHistoryView({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textChequeStatusHistory), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textChequeStatusHistoryContent), + style: Theme.of(context).textTheme.bodySmall), + SizedBox(height: 20), + Card( + surfaceTintColor: Colors.white, + elevation: 2, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border( + left: BorderSide( + color: AppColors.colorPrimary, + width: 5.0, + ), + ), + ), + child: Card( + surfaceTintColor: Colors.white, + elevation: 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: + EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailCustomerName), + style: Theme.of(context).textTheme.titleSmall), + SizedBox(height: 5), + Text( + TranslationKeys.makeTranslation(TranslationKeys + .textChequeStatusCheckNumber), + style: Theme.of(context).textTheme.bodySmall), + SizedBox(height: 5), + Text( + TranslationKeys.makeTranslation(TranslationKeys + .textChequeStatusHistoryRefNo), + style: Theme.of(context).textTheme.bodySmall), + ], + ), + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + // crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: EdgeInsets.symmetric( + vertical: 8.0, horizontal: 8.0), + child: Row( + // mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.check, + color: AppColors.colorPrimary, size: 16), + SizedBox(width: 5), + Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textChequeStatusHistorySuccess), + style: + Theme.of(context).textTheme.bodySmall), + ], + ), + ) + ], + ), + ], + ), + ), + ), + ), + SizedBox(height: 10), + Card( + surfaceTintColor: Colors.white, + elevation: 2, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border( + left: BorderSide( + color: AppColors.colorPrimary, + width: 5.0, // specify the width of the border + ), + ), + ), + child: Card( + surfaceTintColor: Colors.white, + elevation: 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: + EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailCustomerName), + style: Theme.of(context).textTheme.titleSmall), + SizedBox(height: 5), + Text( + TranslationKeys.makeTranslation(TranslationKeys + .textChequeStatusCheckNumber), + style: Theme.of(context).textTheme.bodySmall), + SizedBox(height: 5), + Text( + TranslationKeys.makeTranslation(TranslationKeys + .textChequeStatusHistoryRefNo), + style: Theme.of(context).textTheme.bodySmall), + ], + ), + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + // crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: EdgeInsets.symmetric( + vertical: 8.0, horizontal: 8.0), + child: Row( + // mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.close, + color: AppColors.colorPrimary, size: 16), + SizedBox(width: 5), + Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textChequeStatusHistoryCancel), + style: + Theme.of(context).textTheme.bodySmall), + ], + ), + ) + ], + ), + ], + ), + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/contacts_screen/bindings/contacts_screen_binding.dart b/lib/app/modules/contacts_screen/bindings/contacts_screen_binding.dart new file mode 100644 index 0000000..fc4607e --- /dev/null +++ b/lib/app/modules/contacts_screen/bindings/contacts_screen_binding.dart @@ -0,0 +1,12 @@ +// import 'package:get/get.dart'; +// +// import '../controllers/contacts_screen_controller.dart'; +// +// class ContactsScreenBinding extends Bindings { +// @override +// void dependencies() { +// Get.lazyPut( +// () => ContactsScreenController(), +// ); +// } +// } diff --git a/lib/app/modules/contacts_screen/controllers/contacts_screen_controller.dart b/lib/app/modules/contacts_screen/controllers/contacts_screen_controller.dart new file mode 100644 index 0000000..3355367 --- /dev/null +++ b/lib/app/modules/contacts_screen/controllers/contacts_screen_controller.dart @@ -0,0 +1,105 @@ +// import 'package:flutter/cupertino.dart'; +// import 'package:flutter_contacts/flutter_contacts.dart'; +// import 'package:get/get.dart'; +// import 'package:permission_handler/permission_handler.dart'; +// import 'package:uco_mobile_poc_project/app/core/constants/app_contants.dart'; +// import 'package:uco_mobile_poc_project/app/core/constants/translation_keys.dart'; +// import 'package:uco_mobile_poc_project/app/core/dialogs/custom_loading.dart'; +// import 'package:uco_mobile_poc_project/app/custom_widgets/Fields/input_field.dart'; +// import 'package:uco_mobile_poc_project/app/custom_widgets/custom_toasty.dart'; +// +// class ContactsScreenController extends GetxController { +// static TextEditingController phoneController = TextEditingController(); +// Contact? selectedContact; +// +// List contactsList = []; +// RxList filteredContacts = [].obs; +// +// late InputField searchContacts; +// +// @override +// void onInit() { +// super.onInit(); +// _loadContacts(); +// } +// +// @override +// onReady() { +// super.onReady(); +// // searchContacts.controller?.addListener(() { +// // if (searchContacts.getCustomText().isEmpty) { +// // filteredContacts.assignAll(contactsList); +// // } else { +// // filteredContacts.value = contactsList.where((element) => element.name.first == searchContacts.getCustomText() || element.name.last == searchContacts.getCustomText()).toList(); +// // } +// // }); +// } +// +// Future _loadContacts() async { +// /// Check if the app has permission to access contacts +// var status = await Permission.contacts.status; +// // showLoader(); +// if (status.isGranted) { +// /// Permission is granted, load contacts +// try { +// contactsList = await FlutterContacts.getContacts(withProperties: true, withAccounts: true, withPhoto: true, sorted: true, withThumbnail: true); +// filteredContacts.assignAll(contactsList); +// hideLoader(); +// } catch (e) { +// print('Error loading contacts: $e'); +// hideLoader(); +// } +// } else { +// /// Permission is not granted, request permission +// await _requestPermissions(); +// hideLoader(); +// } +// hideLoader(); +// } +// +// Future _requestPermissions() async { +// /// Request contacts permission +// var status = await Permission.contacts.request(); +// if (!status.isGranted) { +// Toasty.error(TranslationKeys.makeTranslation(TranslationKeys.textPermissionDenied)); +// } else { +// /// Permission granted, load contacts +// await _loadContacts(); +// } +// } +// +// /// Function to filter contacts based on search query +// void filterContacts(String searchText) { +// if (searchText.isEmpty) { +// filteredContacts.assignAll(contactsList); +// } else { +// searchText = searchText.toLowerCase(); +// filteredContacts.assignAll(contactsList.where((contact) { +// // Check if either name or phone number matches the search text +// bool matchesName = contact.name.first.toLowerCase().contains(searchText) || +// (contact.name.last != null && contact.name.last!.toLowerCase().contains(searchText)); +// +// bool matchesPhoneNumber = false; +// for (var number in contact.phones) { +// if (number.number.toLowerCase().contains(searchText)) { +// matchesPhoneNumber = true; +// break; +// } +// } +// +// return matchesName || matchesPhoneNumber; +// }).toList()); +// } +// } +// /// Phone number pattern +// String flattenPhoneNumber(String phoneStr) { +// return phoneStr.replaceAllMapped(RegExp(r'^(\+)|\D'), (Match m) { +// return m[0] == "+" ? "+" : ""; +// }); +// } +// +// void handleContactSelection(Contact selectedContact) { +// Get.back(result: {AppConstants.SELECTED_CONTACT: selectedContact}); +// } +// +// } diff --git a/lib/app/modules/contacts_screen/views/contacts_screen_view.dart b/lib/app/modules/contacts_screen/views/contacts_screen_view.dart new file mode 100644 index 0000000..9a46c72 --- /dev/null +++ b/lib/app/modules/contacts_screen/views/contacts_screen_view.dart @@ -0,0 +1,107 @@ +// import 'package:flutter/material.dart'; +// import 'package:get/get.dart'; +// import 'package:uco_mobile_poc_project/app/core/constants/translation_keys.dart'; +// import 'package:uco_mobile_poc_project/app/custom_widgets/custom_no_record.dart'; +// import 'package:uco_mobile_poc_project/app/res/app_colors.dart'; +// import 'package:uco_mobile_poc_project/app/res/app_dimensions.dart'; +// +// import '../../../custom_widgets/custom_app_bar.dart'; +// import '../controllers/contacts_screen_controller.dart'; +// +// class ContactsScreenView extends GetView { +// const ContactsScreenView({Key? key}) : super(key: key); +// +// @override +// Widget build(BuildContext context) { +// String className = runtimeType.toString().split('.').last; +// return Scaffold( +// appBar: DashBoardAppBar( +// title: TranslationKeys.makeTranslation("Contacts"), +// onBackButtonPressed: () { +// Get.back(); +// }, +// ), +// body: Padding( +// padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// TextField( +// style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), +// decoration: const InputDecoration( +// suffixIconColor: AppColors.colorPrimary, +// filled: true, +// fillColor: AppColors.colorGrey200, +// enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(width: 1, color: Colors.transparent)), +// border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(width: 1, color: AppColors.colorGrey500)), +// focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(width: 1, style: BorderStyle.solid, color: Colors.transparent)), +// hintText: 'Search contact number', +// hintStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.colorGrey500), +// suffixIcon: Icon(Icons.search_rounded, size: 22), +// ), +// onChanged: (value) { +// controller.filterContacts(value); +// }), +// const SizedBox(height: 20), +// Text(TranslationKeys.makeTranslation("Contacts"), style: Theme.of(context).textTheme.bodyMedium), +// const SizedBox(height: 10), +// Obx(() { +// return controller.filteredContacts.isEmpty +// ? const Center( +// child: CustomNoRecord(title: "No Record Found", description: "We couldn't find any activity at this moment"), +// ) +// : Expanded( +// flex: 2, +// child: ListView.builder( +// itemCount: controller.filteredContacts.length, +// itemBuilder: (context, index) { +// final contact = controller.filteredContacts[index]; +// final phoneNumber = contact.phones.isNotEmpty ? contact.phones[0].number : 'No phone number'; +// return ListTile( +// onTap: () { +// controller.handleContactSelection(contact); +// }, +// title: Text(contact.displayName), +// subtitle: Text( +// phoneNumber, +// style: Theme.of(context).textTheme.bodySmall, +// ), +// leading: CircleAvatar( +// backgroundColor: AppColors.colorPrimary, +// backgroundImage: contact.photo != null ? MemoryImage(contact.photo!) : null, +// child: Text( +// getInitials(contact.displayName), +// style: Theme.of(context).textTheme.titleSmall?.copyWith(color: Colors.white), +// ), +// ), +// ); +// }, +// ), +// ); +// }), +// ], +// ), +// ), +// ); +// } +// +// String getInitials(String fullName) { +// if (fullName.isEmpty) { +// return ""; +// } +// +// // Split the full name into words +// List nameParts = fullName.trim().split(' '); +// +// // Check if there's at least a first and last name +// if (nameParts.length < 2) { +// return fullName.substring(0, 1).toUpperCase(); // Get first character +// } +// +// // Get first characters of first and last name +// String firstInitial = nameParts[0].substring(0, 1).toUpperCase(); +// String lastInitial = nameParts[nameParts.length - 1].substring(0, 1).toUpperCase(); +// +// return firstInitial + lastInitial; +// } +// } diff --git a/lib/app/modules/create_transaction_pin/bindings/create_transaction_pin_binding.dart b/lib/app/modules/create_transaction_pin/bindings/create_transaction_pin_binding.dart new file mode 100644 index 0000000..0b7adbf --- /dev/null +++ b/lib/app/modules/create_transaction_pin/bindings/create_transaction_pin_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/create_transaction_pin_controller.dart'; + +class CreateTransactionPinBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => CreateTransactionPinOTPControllerTest(), + ); + } +} diff --git a/lib/app/modules/create_transaction_pin/controllers/create_transaction_pin_controller.dart b/lib/app/modules/create_transaction_pin/controllers/create_transaction_pin_controller.dart new file mode 100644 index 0000000..178e139 --- /dev/null +++ b/lib/app/modules/create_transaction_pin/controllers/create_transaction_pin_controller.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/CreateTransactionPinOTPRequest.dart'; +import '../../../routes/app_pages.dart'; + + +class CreateTransactionPinOTPControllerTest extends GetxController { + final repository = Get.find(); + + TextEditingController newTransactionPinController = TextEditingController(); + TextEditingController confirmTransactionPinController = TextEditingController(); + + void validateAndSendRequest() async { + if (newTransactionPinController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + if (confirmTransactionPinController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + if (newTransactionPinController.text != confirmTransactionPinController.text) { + Toasty.error("Transaction Pin did not match"); + return; + } + + CreateTransactionPinOTPRequest request = CreateTransactionPinOTPRequest( + newTransPincode: newTransactionPinController.text, + pinType: AppConstants.PIN_TYPE_Transaction, + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + pctCstycode: RequestConstants.pctCstycode, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + isOtpRequire: false, + ); + + ServerResponse response = await repository.createTransactionPinOTP(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + Get.toNamed( + Routes.CREATE_TRANSACTION_PIN_OTP, + arguments: { + 'transactionPin': newTransactionPinController.text, + 'confirmTransactionPin': confirmTransactionPinController.text, + 'isSomething': false, + AppConstants.CREATE_TRANSACTION_PIN_OTP: request, + }, + ); + clearController(); + } + + void clearController() { + newTransactionPinController.clear(); + confirmTransactionPinController.clear(); + } +} diff --git a/lib/app/modules/create_transaction_pin/views/create_transaction_pin_view.dart b/lib/app/modules/create_transaction_pin/views/create_transaction_pin_view.dart new file mode 100644 index 0000000..20f5406 --- /dev/null +++ b/lib/app/modules/create_transaction_pin/views/create_transaction_pin_view.dart @@ -0,0 +1,158 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/create_transaction_pin_controller.dart'; + +class CreateTransactionPinView extends GetView { + const CreateTransactionPinView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textCreateTransactionPin), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textPleaseCreatenewtransactionpin), + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 14, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 20), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.newTransactionPinController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + textInputAction: TextInputAction.done, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textConfirmTransactionPin), + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 14, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 20), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.confirmTransactionPinController, + showCursor: true, + autoDismissKeyboard: false, + textInputAction: TextInputAction.done, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: + TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonColor: AppColors.colorButton, + buttonPadding: + const EdgeInsets.symmetric(vertical: 8, horizontal: 0), + ), + ), + ], + ); + } +} diff --git a/lib/app/modules/create_transaction_pin_otp/bindings/create_transaction_pin_otp_binding.dart b/lib/app/modules/create_transaction_pin_otp/bindings/create_transaction_pin_otp_binding.dart new file mode 100644 index 0000000..161333c --- /dev/null +++ b/lib/app/modules/create_transaction_pin_otp/bindings/create_transaction_pin_otp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/create_transaction_pin_otp_controller.dart'; + +class CreateTransactionPinOtpBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => CreateTransactionPinOtpController(), + ); + } +} diff --git a/lib/app/modules/create_transaction_pin_otp/controllers/create_transaction_pin_otp_controller.dart b/lib/app/modules/create_transaction_pin_otp/controllers/create_transaction_pin_otp_controller.dart new file mode 100644 index 0000000..472dc89 --- /dev/null +++ b/lib/app/modules/create_transaction_pin_otp/controllers/create_transaction_pin_otp_controller.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/CreateTransactionPinOTPRequest.dart'; +import '../../../models/CreateTransactionPinRequest.dart'; +import '../../../routes/app_pages.dart'; + + +class CreateTransactionPinOtpController extends GetxController { + TextEditingController pinPutController = TextEditingController(); + final AppRepositories repository = Get.find(); + late String newTransactionPin; + late String confirmTransactionPin; + CreateTransactionPinOTPRequest createTransactionPinOTPRequest = CreateTransactionPinOTPRequest(); + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + late bool isSomething; + late final request; + + @override + void onReady() { + super.onReady(); + var arguments = Get.arguments; + newTransactionPin = arguments['transactionPin']; + confirmTransactionPin = arguments['confirmTransactionPin']; + isSomething = arguments['isSomething']; + createTransactionPinOTPRequest = arguments[AppConstants.CREATE_TRANSACTION_PIN_OTP]; + + dp("newTransactionPin>>>>", newTransactionPin); + dp("confirmTransactionPin>>>>", confirmTransactionPin); + } + + void validateAndSendRequest() async { + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + + CreateTransactionPinRequest request = CreateTransactionPinRequest( + channelCode: RequestConstants.channelCode, + pctCstycode: RequestConstants.pctCstycode, + porOrgacode: RequestConstants.porOrgacode, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + email: SessionCache.instance.userInfo.cmpUserId, + obpPincode: pinPutController.text, + pinType: AppConstants.PIN_TYPE_Transaction, + ); + + ServerResponse response = await repository.createTransactionPin(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + clearController(); + CustomDialog.showSuccessDialog( + // title: "Congratulations!", + description: "Your Transaction pin successfully ! An send email and message have been sent to you.", + onTapPositive: () { + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }, + ); + } + + Future sendBeneficiaryTransaction({navigate = true}) async { + ServerResponse response = await repository.createTransactionPinOTP(createTransactionPinOTPRequest); + + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Toasty.success("OTP send successfully"); + } + + void clearController() { + pinPutController.clear(); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/create_transaction_pin_otp/views/create_transaction_pin_otp_view.dart b/lib/app/modules/create_transaction_pin_otp/views/create_transaction_pin_otp_view.dart new file mode 100644 index 0000000..b46417b --- /dev/null +++ b/lib/app/modules/create_transaction_pin_otp/views/create_transaction_pin_otp_view.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../controllers/create_transaction_pin_otp_controller.dart'; + +class CreateTransactionPinOtpView extends GetView { + const CreateTransactionPinOtpView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + textInputAction: TextInputAction.done, + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle(fontSize: 12), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.sendBeneficiaryTransaction(navigate: false); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/dail_transaction_limit/bindings/dail_transaction_limit_binding.dart b/lib/app/modules/dail_transaction_limit/bindings/dail_transaction_limit_binding.dart new file mode 100644 index 0000000..f3833b4 --- /dev/null +++ b/lib/app/modules/dail_transaction_limit/bindings/dail_transaction_limit_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/dail_transaction_limit_controller.dart'; + +class DailTransactionLimitBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => DailTransactionLimitController(), + ); + } +} diff --git a/lib/app/modules/dail_transaction_limit/controllers/dail_transaction_limit_controller.dart b/lib/app/modules/dail_transaction_limit/controllers/dail_transaction_limit_controller.dart new file mode 100644 index 0000000..7815f9b --- /dev/null +++ b/lib/app/modules/dail_transaction_limit/controllers/dail_transaction_limit_controller.dart @@ -0,0 +1,9 @@ +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; + +class DailTransactionLimitController extends GetxController { + late InputField newDailyLimit; + late InputField debitCardNumber; + late InputField atmPin; +} diff --git a/lib/app/modules/dail_transaction_limit/views/dail_transaction_limit_view.dart b/lib/app/modules/dail_transaction_limit/views/dail_transaction_limit_view.dart new file mode 100644 index 0000000..b89ee7c --- /dev/null +++ b/lib/app/modules/dail_transaction_limit/views/dail_transaction_limit_view.dart @@ -0,0 +1,128 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/dail_transaction_limit_controller.dart'; + +class DailTransactionLimitView extends GetView { + const DailTransactionLimitView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textTransactionLimit), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only(right: 20.0, left: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 20.0), + child: Container( + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey350), + borderRadius: const BorderRadius.all(Radius.circular(8.0)), + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: CircleAvatar( + backgroundColor: AppColors.colorGrey200, + minRadius: 30, + child: SvgPicture.asset(AppAssets.ic_money_management, height: 30, width: 30), + ), + ), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textOldLimit), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textCurrentDailyLimit), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 14, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + ], + ), + ), + ), + const SizedBox(height: 5), + controller.newDailyLimit = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}SetDailyLimitAmount"), + controller: FormFieldConstants.instance().getController("${className}SetDailyLimitAmount"), + // hintText: "Enter username", + labelText: "Set Daily Limit Amount", + keyboardType: TextInputType.text, + ), + controller.debitCardNumber = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}DebitCardNumber"), + controller: FormFieldConstants.instance().getController("${className}DebitCardNumber"), + labelText: "Debit Card Number", + keyboardType: TextInputType.text, + ), + controller.atmPin = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}ATMPin"), + controller: FormFieldConstants.instance().getController("${className}ATMPin"), + labelText: "ATMPin", + keyboardType: TextInputType.text, + ), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textMaximumLengthContent), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontSize: 12, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textLimitNoteContent), style: Theme.of(context).textTheme.bodySmall?.copyWith(fontSize: 12, fontWeight: FontWeight.w400)), + ], + ), + ), + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: CustomButton( + onPressed: () { + Get.offAndToNamed(Routes.APP_SETTING); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textDone), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 0), + ), + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + // child: SizedBox( + // width: double.infinity, + // child: ElevatedButton( + // onPressed: () { + // Get.offAndToNamed(Routes.APP_SETTING); + // }, + // style: ElevatedButton.styleFrom( + // backgroundColor: AppColors.colorButton, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(50), + // ), + // ), + // child: Padding( + // padding: const EdgeInsets.all(12.0), + // child: Text(TranslationKeys.makeTranslation(TranslationKeys.textDone), style: Theme.of(context).textTheme.labelMedium?.copyWith(color: AppColors.white)), + // ), + // ), + // ), + // ), + ], + persistentFooterAlignment: AlignmentDirectional.bottomCenter, + resizeToAvoidBottomInset: false, + backgroundColor: AppColors.colorSecondary, + ); + } +} diff --git a/lib/app/modules/dashboard/bindings/dashboard_screen_binding.dart b/lib/app/modules/dashboard/bindings/dashboard_screen_binding.dart new file mode 100644 index 0000000..c6b4df4 --- /dev/null +++ b/lib/app/modules/dashboard/bindings/dashboard_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/dashboard_screen_controller.dart'; + +class DashboardScreenBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => DashboardScreenController(), + ); + } +} diff --git a/lib/app/modules/dashboard/controllers/dashboard_screen_controller.dart b/lib/app/modules/dashboard/controllers/dashboard_screen_controller.dart new file mode 100644 index 0000000..3fa9793 --- /dev/null +++ b/lib/app/modules/dashboard/controllers/dashboard_screen_controller.dart @@ -0,0 +1,129 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; +import 'package:get/get.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/ExchangeRate.dart'; +import '../../../models/dashboard_response_model.dart'; +import '../../u_received/controllers/u_received_controller.dart'; +import '../../u_send/controllers/u_send_controller.dart'; + +RxInt transitionUpdate = RxInt(0); + +class DashboardScreenController extends GetxController { + BuildContext context = Get.context as BuildContext; + + final AppRepositories repository = Get.find(); + + RxBool isDrawerOpen = false.obs; + int curentIndex = 0; + + RxList depositeAccount = [DepositAccount.empty()].obs; + final ZoomDrawerController zoomController = ZoomDrawerController(); + + /// Change Icon method + void toggleDrawer() { + isDrawerOpen.value = !isDrawerOpen.value; + if (isDrawerOpen.value) { + zoomController.open!(); + } else { + zoomController.close!(); + } + } + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + fetchDepositAccounts(); + fetchExchangeRates(); + + transitionUpdate.listen( + (p0) { + fetchDepositAccounts(); + fetchExchangeRates(); + }, + ); + } + + @override + void onInit() { + super.onInit(); + // fingerPrintLogin(); + } + + // Future fingerPrintLogin() async { + // String info = await AppStorage.getString(AppConstants.IS_FINGER_PRINT_ENABLED, fallback: ""); + // if (info.isNotEmpty) { + // FingerPrintInfo fingerPrintInfo = FingerPrintInfo.fromMap(jsonDecode(info)); + // if (fingerPrintInfo.cmpUserId != SessionCache.instance.userInfo.cmpUserId || fingerPrintInfo.cmpCustpassword != SessionCache.instance.userInfo.cmpCustpassword) { + // // SessionCache.instance.fingerPrintController.clearFromDB(); + // } + // } + // } + + Future fetchDepositAccounts() async { + ServerResponse response = await repository.fetchAccountDetails(); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + DashBoardResponseModel dashboardResponse = DashBoardResponseModel.fromMap(response.response); + SessionCache.instance.depositAccountList.value = dashboardResponse.deposit; + depositeAccount.assignAll(SessionCache.instance.depositAccountList); + } + + Future fetchExchangeRates() async { + ServerResponse response = await repository.fetchExchangeRate(); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + SessionCache.instance.exchangeRateList.value = List.from(((response.response ?? []) as List).map((x) => ExchangeRate.fromMap(x))); + + SessionCache.instance.exchangeRateList.insert( + 0, + ExchangeRate( + petExrtdesc: "Official Rate", + pcrCurrcode: "586", + perEratrateact: 1.0, + petExrtcode: "3", + perEratdate: "2024-06-27", + pcrCurrshort: "PKR", + porOrgacode: "0006", + pcrCurrdesc: "Pakistani Rupees", + )); + } + + updatePage(int index) { + Get.put(UReceivedController()); + + curentIndex = index; + + update(); + if (index != 1) { + Get.find().clearTransaction(); + } + } + + /// Get Flag fucntion + String getFlagWithCurrencyCode(currencyCodeInt) { + if (currencyCodeInt == "586") { + return "assets/uco/icons/ic_pakistan.png"; + } else if (currencyCodeInt == "997") { + return "assets/uco/icons/usa.png"; + } else { + return "assets/uco/icons/euro_flag.png"; + } + + // else { + // return "assets/uco/icons/default_flag.png"; + // } + } +} diff --git a/lib/app/modules/dashboard/views/dashboard_screen_view.dart b/lib/app/modules/dashboard/views/dashboard_screen_view.dart new file mode 100644 index 0000000..3fa8c9f --- /dev/null +++ b/lib/app/modules/dashboard/views/dashboard_screen_view.dart @@ -0,0 +1,78 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; +import 'package:uco_mobile_poc/app/modules/dashboard/views/shared/drawer_data.dart'; +import 'package:uco_mobile_poc/app/modules/dashboard/views/shared/home_page.dart'; + +class DashboardScreenView extends StatefulWidget { + const DashboardScreenView({Key? key}) : super(key: key); + + @override + State createState() => _DashBoardViewState(); +} + +class _DashBoardViewState extends State with SingleTickerProviderStateMixin { + late AnimationController _animationController; + + bool _isDoubleTapped = false; + + @override + void initState() { + super.initState(); + + _animationController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 200), + ); + } + + void toggleAnimation() { + _animationController.isDismissed ? _animationController.forward() : _animationController.reverse(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + Future handleDoubleTab() async { + if (_isDoubleTapped) { + return true; // Allow the app to be exited + } else { + // Set _isDoubleTapped to true and display a message + setState(() { + _isDoubleTapped = true; + }); + // Reset _isDoubleTapped after 2 seconds + Timer(const Duration(seconds: 2), () { + setState(() { + _isDoubleTapped = false; + }); + }); + // Prevent the app from being exited + return false; + } + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () => handleDoubleTab(), + child: SafeArea( + child: Material( + child: ZoomDrawer( + menuScreen: DrawerData(), + mainScreen: MyHomePage(), + borderRadius: 24.0, + showShadow: true, + angle: 0.0, + openCurve: Curves.fastOutSlowIn, + closeCurve: Curves.easeInBack, + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/dashboard/views/shared/bottom_sheet_icon.dart b/lib/app/modules/dashboard/views/shared/bottom_sheet_icon.dart new file mode 100644 index 0000000..065c3cc --- /dev/null +++ b/lib/app/modules/dashboard/views/shared/bottom_sheet_icon.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import '../../../../res/app_colors.dart'; + + +class BottomSheetIcon extends StatelessWidget { + String title; + Function() onTap; + final String imageProvider; + double? width; + double? height; + + BottomSheetIcon( + {super.key, + required this.title, + required this.imageProvider, + required this.onTap, + this.height, + this.width}); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + imageProvider, + width: width, + height: height, + ), + const SizedBox(height: 3), + Text( + title, + style: Theme.of(context) + .textTheme + .labelSmall! + .copyWith(fontWeight: FontWeight.w500, color: AppColors.white), + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/dashboard/views/shared/drawer_data.dart b/lib/app/modules/dashboard/views/shared/drawer_data.dart new file mode 100644 index 0000000..37e956b --- /dev/null +++ b/lib/app/modules/dashboard/views/shared/drawer_data.dart @@ -0,0 +1,344 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + +// import 'package:url_launcher/url_launcher.dart'; + +import '../../../../core/constants/app_assets.dart'; +import '../../../../core/constants/app_contants.dart'; +import '../../../../core/constants/translation_keys.dart'; +import '../../../../core/utils/SessionCache.dart'; +import '../../../../custom_widgets/custom_dialog.dart'; +import '../../../../custom_widgets/custom_label.dart'; +import '../../../../custom_widgets/custom_toasty.dart'; +import '../../../../custom_widgets/responsive_widget.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../routes/app_pages.dart'; +import '../../../user_profile/controllers/user_profile_controller.dart'; +import '../../controllers/dashboard_screen_controller.dart'; + +class DrawerData extends GetView { + final Function()? toggleAnimation; + + DrawerData({super.key, this.toggleAnimation}); + UserProfileController userProfileController = Get.put(UserProfileController()); + + @override + Widget build(BuildContext context) { + List drawerList = DrawerList.getItemsList(context); + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(25), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + InkWell( + onTap: () { + // dp("Profile Pictures========", profilePic); + }, + child: Obx(() { + return CircleAvatar( + radius: 30, + backgroundColor: AppColors.colorPrimary, + child: Padding( + padding: const EdgeInsets.all(8), // Border radius + child: userProfileController.profilePic.isNotEmpty + ? ClipOval( + child: Image.memory( + base64Decode(userProfileController.profilePic.value), + height: 40, + width: 40, + fit: BoxFit.cover, + ), + ) + : const Icon(Icons.person, color: AppColors.white), + ), + ); + }), + ), + const SizedBox(width: 15), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text(SessionCache.instance.userInfo.name, style: Theme.of(context).textTheme.titleLarge), + const SizedBox(height: 2), + Text(SessionCache.instance.userInfo.cmpCustlastlogin != null ? SessionCache.instance.userInfo.cmpCustlastlogin : "N/A", + /*TranslationKeys.makeTranslation( + TranslationKeys.textAccountSession),*/ + style: Theme.of(context).textTheme.bodyMedium), + ], + ), + ], + ), + const SizedBox(height: 20), + ListView.builder( + itemCount: drawerList.length, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (ctx, index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: InkWell(onTap: () {}, child: Text(drawerList[index].label, style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 14, fontWeight: FontWeight.w600))), + ), + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + itemCount: drawerList[index].drawerList.length, + shrinkWrap: true, + itemBuilder: (ctx, innerIndex) { + return Padding(padding: const EdgeInsets.symmetric(vertical: 0), child: getDrawerWidget(drawerList[index].drawerList[innerIndex], context)); + }), + const SizedBox(height: 10) + ], + ); + }), + const SizedBox(height: 20), + ], + ), + ), + ); + } + + Widget getDrawerWidget(DrawerItem item, BuildContext context) { + return InkWell( + onTap: () { + switch (item.id) { + // case AppConstants.ID_MY_ACCOUNT: + // Get.toNamed(Routes.MY_ACCOUNT); + // break; + case AppConstants.ID_BILL_MANAGEMENT: + Get.toNamed(Routes.BILL_MANAGEMENT); + break; + case AppConstants.ID_CHEQUE_MANAGEMENT: + Get.toNamed(Routes.CHEQUE_MANAGEMENT); + break; + case AppConstants.ID_INTERNAL_TRANSACTION: + Get.toNamed(Routes.INTERNAL_ACCOUNT_TRANS); + break; + + case AppConstants.ID_BENEFICIARY_MANAGEMENT: + Get.toNamed(Routes.BENEFICIARY_MANAGEMENT); + break; + case AppConstants.ID_AGENT_LOCATION: + if (Platform.isIOS) { + Toasty.error("Coming soon"); + } else { + Get.toNamed(Routes.AGENT_LOCATION); + } + + break; + case AppConstants.ID_ACCOUNT_STATEMENT: + Get.toNamed(Routes.ACCOUNT_STATEMENT); + break; + case AppConstants.ID_SUPPORT: + showCutomBottomSheet(supportBottomSheet(context)); + break; + case AppConstants.ID_USER_PROFILE: + Get.toNamed(Routes.USER_PROFILE); + break; + case AppConstants.ID_PRIVACY_POLICY: + Get.toNamed(Routes.PRIVACY_POLICY); + break; + case AppConstants.ID_USER_ACTIVITY: + Get.toNamed(Routes.USER_ACTIVITY); + break; + case AppConstants.ID_APP_SETTING: + Get.toNamed(Routes.APP_SETTING); + break; + case AppConstants.ID_ABOUT_US: + Get.toNamed(Routes.ABOUT_US); + break; + case AppConstants.ID_CAREER: + Get.toNamed(Routes.CAREER); + break; + case AppConstants.ID_LOGOUT: + { + CustomDialog.showLogoutDialog( + context: context, + onTapPositive: () { + Navigator.of(context, rootNavigator: true).pop(); + Get.offAllNamed(Routes.LOGIN_SCREEN); + }, + onTapNegative: () { + Navigator.of(context, rootNavigator: true).pop(); + }, + ); + } + break; + default: + print("Print thisi is isiisisisisisisis"); + } + }, + child: Container( + padding: const EdgeInsets.all(8), + child: Row( + children: [ + SvgPicture.asset( + item.icon, + height: 20, + width: 20, + color: AppColors.colorPrimary, + ), + const SizedBox(width: 15), + Text(item.title, style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 15, fontWeight: FontWeight.w400)), + ], + ), + ), + ); + } + + /// Drawer Support Bottom Sheet Widget + + Container supportBottomSheet(BuildContext context) { + List supportBottomSheetList = [ + SupportBottomSheet( + image: AppAssets.ic_email, + title: TranslationKeys.makeTranslation(TranslationKeys.textEmail), + onTap: () { + // launch("mailto:info@mfsys.com.pk"); + }), + SupportBottomSheet( + image: AppAssets.ic_phone, + title: TranslationKeys.makeTranslation(TranslationKeys.textPhone), + onTap: () async { + // launch("tel:021213123123"); + }), + ]; + return Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey, width: 1), + borderRadius: const BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)), + ), + margin: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textGetInTouch), + style: Theme.of(context).textTheme.titleSmall, + ), + InkWell( + onTap: () { + Navigator.pop(context); + }, + child: SvgPicture.asset(AppAssets.ic_cross, height: 15, width: 15), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.all(10), + child: GridView.builder( + itemCount: supportBottomSheetList.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 15, + mainAxisSpacing: 15, + ), + itemBuilder: (context, index) { + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: supportBottomSheetList[index].onTap, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorText, width: 1), + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset("${supportBottomSheetList[index].image}", height: 50, width: 50), + const SizedBox(height: 20), + Center( + child: LabelText('${supportBottomSheetList[index].title}', style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 14)), + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ); + } +} + +class SupportBottomSheet { + String? image; + String? title; + Function()? onTap; + + SupportBottomSheet({this.image, this.title, this.onTap}); +} + +class DrawerList { + final String label; + final List drawerList; + + DrawerList(this.label, this.drawerList); + + static List getItemsList(BuildContext context) { + return [ + DrawerList(TranslationKeys.makeTranslation(TranslationKeys.textManage), [ + // DrawerItem( + // AppConstants.ID_MY_ACCOUNT, + // AppAssets.ic_user, + // TranslationKeys.makeTranslation(TranslationKeys.textMyAccount), + // () => Routes.USER_ACTIVITY), + DrawerItem(AppConstants.ID_BILL_MANAGEMENT, AppAssets.ic_bill, TranslationKeys.makeTranslation(TranslationKeys.textBillManagement), () => Routes.BILL_MANAGEMENT), + DrawerItem(AppConstants.ID_CHEQUE_MANAGEMENT, AppAssets.ic_cheque_management, TranslationKeys.makeTranslation(TranslationKeys.textChequeManagement), () => Routes.CHEQUE_MANAGEMENT), + DrawerItem(AppConstants.ID_INTERNAL_TRANSACTION, AppAssets.ic_u_cash, TranslationKeys.makeTranslation(TranslationKeys.textInternalAccountTransaction), () => Routes.U_SEND), + DrawerItem(AppConstants.ID_BENEFICIARY_MANAGEMENT, AppAssets.ic_u_recive, TranslationKeys.makeTranslation(TranslationKeys.textBeneficiaryManagement), () => Routes.U_RECEIVED), + DrawerItem(AppConstants.ID_AGENT_LOCATION, AppAssets.ic_location, TranslationKeys.makeTranslation(TranslationKeys.textAgentLocation), () => Routes.AGENT_LOCATION), + DrawerItem(AppConstants.ID_ACCOUNT_STATEMENT, AppAssets.ic_money_management, TranslationKeys.makeTranslation(TranslationKeys.textAccountStatement), () => Routes.ACCOUNT_STATEMENT), + ]), + DrawerList(TranslationKeys.makeTranslation(TranslationKeys.textSupport), [ + DrawerItem(AppConstants.ID_SUPPORT, AppAssets.ic_customer_service, TranslationKeys.makeTranslation(TranslationKeys.textSupport), () {}), + DrawerItem(AppConstants.ID_USER_PROFILE, AppAssets.ic_user, TranslationKeys.makeTranslation(TranslationKeys.textUserProfile), () => Routes.USER_PROFILE), + DrawerItem(AppConstants.ID_USER_ACTIVITY, AppAssets.ic_activity, TranslationKeys.makeTranslation(TranslationKeys.textUserActivity), () => Routes.USER_ACTIVITY), + DrawerItem(AppConstants.ID_ABOUT_US, AppAssets.ic_user, TranslationKeys.makeTranslation(TranslationKeys.textAboutUs), () => Routes.ABOUT_US), + DrawerItem(AppConstants.ID_APP_SETTING, AppAssets.ic_setting, TranslationKeys.makeTranslation(TranslationKeys.textAppSetting), () => Routes.APP_SETTING), + DrawerItem(AppConstants.ID_CAREER, AppAssets.ic_sub_accounts, TranslationKeys.makeTranslation(TranslationKeys.textCareer), () => Routes.CAREER), + ]), + DrawerList(TranslationKeys.makeTranslation(TranslationKeys.textLogOut), [ + DrawerItem( + AppConstants.ID_LOGOUT, + AppAssets.ic_logout, + TranslationKeys.makeTranslation(TranslationKeys.textLogout), + () {}, + ), + ]), + ]; + } +} + +class DrawerItem { + final String id; + final String icon; + final String title; + Function()? onTap; + + DrawerItem(this.id, this.icon, this.title, this.onTap); +} diff --git a/lib/app/modules/dashboard/views/shared/home_page.dart b/lib/app/modules/dashboard/views/shared/home_page.dart new file mode 100644 index 0000000..9d8f124 --- /dev/null +++ b/lib/app/modules/dashboard/views/shared/home_page.dart @@ -0,0 +1,139 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart'; +import 'package:get/get.dart'; + + +import '../../../../core/constants/translation_keys.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../routes/app_pages.dart'; +import '../../controllers/dashboard_screen_controller.dart'; +import 'drawer_data.dart'; +import 'main_dash_board.dart'; + +class MyHomePage extends StatelessWidget { + MyHomePage({super.key}); + + final DashboardScreenController dashBoardController = Get.put(DashboardScreenController()); + final MenuController menuController = Get.put(MenuController()); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).appBarTheme.backgroundColor, + centerTitle: true, + elevation: 0.0, + title: Text( + TranslationKeys.makeTranslation(TranslationKeys.textOverView), + style: Theme.of(context).textTheme.displaySmall!.copyWith( + color: AppColors.colorSecondary, + fontSize: 23, + fontFamily: "Poppins", + fontWeight: FontWeight.w500, + ), + ), + leading: Obx(() { + return Center( + child: Container( + color: Colors.transparent, + child: Material( + color: Colors.transparent, + child: Container( + decoration: BoxDecoration(borderRadius: BorderRadius.circular(50), color: Colors.transparent), + width: 40.0, + height: 40.0, + child: InkWell( + borderRadius: const BorderRadius.all(Radius.circular(50)), + splashColor: Colors.transparent, + onTap: () { + dashBoardController.toggleDrawer(); + }, + child: Icon( + dashBoardController.isDrawerOpen.value ? Icons.close : Icons.menu, + color: AppColors.colorSecondary, + )), + ), + ), + ), + ); + }), + actions: [ + Center( + child: Container( + color: Colors.transparent, + child: Material( + color: Colors.transparent, + child: Container( + decoration: BoxDecoration(borderRadius: BorderRadius.circular(50), color: Colors.transparent), + width: 40.0, + height: 40.0, + child: InkWell( + borderRadius: const BorderRadius.all(Radius.circular(50)), + splashColor: Colors.transparent, + onTap: () { + // dashBoardController.fetchDepositAccounts(); + // dashBoardController.fetchExchangeRates(); + }, + child: const Icon( + Icons.refresh_outlined, + color: AppColors.colorSecondary, + )), + ), + ), + ), + ), + Center( + child: Container( + color: Colors.transparent, + child: Material( + color: Colors.transparent, + child: Container( + decoration: BoxDecoration(borderRadius: BorderRadius.circular(50), color: Colors.transparent), + width: 40.0, + height: 40.0, + child: InkWell( + borderRadius: const BorderRadius.all(Radius.circular(50)), + splashColor: Colors.transparent, + onTap: () { + Get.toNamed(Routes.NOTIFICATIONS); + }, + child: const Icon( + Icons.notifications_none_outlined, + color: AppColors.colorSecondary, + )), + ), + ), + ), + ), + const SizedBox(width: 10) + ], + ), + body: ZoomDrawer( + controller: dashBoardController.zoomController, + menuScreen: DrawerData(), + mainScreen: DashBoardWithAllAccounts(), + openCurve: Curves.fastOutSlowIn, + showShadow: false, + slideWidth: MediaQuery.of(context).size.width * 0.7, + isRtl: Directionality.of(context) == TextDirection.rtl, + mainScreenTapClose: false, + mainScreenOverlayColor: Colors.transparent, + borderRadius: 10, + angle: 0.0, + menuScreenWidth: double.infinity, + moveMenuScreen: true, + style: DrawerStyle.defaultStyle, + //drawerShadowsBackgroundColor: Colors.yellow, + mainScreenAbsorbPointer: false, + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 10, + blurRadius: 4, + offset: const Offset(3, 3), // changes position of shadow + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/dashboard/views/shared/main_dash_board.dart b/lib/app/modules/dashboard/views/shared/main_dash_board.dart new file mode 100644 index 0000000..dc49c24 --- /dev/null +++ b/lib/app/modules/dashboard/views/shared/main_dash_board.dart @@ -0,0 +1,905 @@ +// import 'package:flutter/material.dart'; +// +// import 'package:get/get.dart'; +// import 'package:uco_ciihive/app/core/constants/app_assets.dart'; +// import 'package:uco_ciihive/app/core/constants/translation_keys.dart'; +// import 'package:uco_ciihive/app/modules/dashboard/controllers/dashboard_screen_controller.dart'; +// import 'package:uco_ciihive/app/modules/user_profile/controllers/user_profile_controller.dart'; +// import 'package:uco_ciihive/app/res/app_colors.dart'; +// import 'package:uco_ciihive/app/res/app_dimensions.dart'; +// import 'package:uco_ciihive/app/routes/app_pages.dart'; +// +// import 'bottom_sheet_icon.dart'; +// +// class DashBoardWithAllAccounts extends GetView { +// late MenuController? menuController; +// +// DashBoardWithAllAccounts({super.key, this.menuController}); +// +// final DashboardScreenController dashBoardController = Get.find(); +// +// @override +// Widget build(BuildContext Get.context!) { +// controller.Get.context! = Get.context!; +// return Scaffold( +// floatingActionButton: Padding( +// padding: EdgeInsets.symmetric(vertical: 20, horizontal: 30), +// child: SpeedDial( +// openBackgroundColor: AppColors.colorButton, +// closedBackgroundColor: AppColors.colorPrimaryLight, +// labelsBackgroundColor: AppColors.colorButton, +// labelsStyle: Theme.of(Get.context!).textTheme.bodyMedium?.copyWith(color: AppColors.colorPrimary), +// speedDialChildren: [ +// SpeedDialChild( +// backgroundColor: AppColors.colorButton, +// label: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// child: Padding( +// padding: const EdgeInsets.all(2.0), +// child: SvgPicture.asset( +// AppAssets.ic_u_send, +// color: Colors.white, +// ), +// ), +// onPressed: () { +// //Get.toNamed(Routes.DIRECT_PAYMENT); +// }, +// ), +// SpeedDialChild( +// backgroundColor: AppColors.colorButton, +// label: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: SvgPicture.asset( +// AppAssets.ic_u_send, +// color: Colors.white, +// ), +// ), +// onPressed: () { +// //Get.toNamed(Routes.NEW_BENEFICIARY); +// }, +// ), +// SpeedDialChild( +// backgroundColor: AppColors.colorButton, +// label: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: SvgPicture.asset( +// AppAssets.ic_u_send, +// color: Colors.white, +// ), +// ), +// onPressed: () { +// // Get.toNamed(Routes.OWN_TRANSFER); +// }, +// ), +// SpeedDialChild( +// backgroundColor: AppColors.colorButton, +// label: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: SvgPicture.asset( +// AppAssets.ic_u_send, +// color: Colors.white, +// ), +// ), +// onPressed: () { +// //Get.toNamed(Routes.ZAKAT); +// }, +// ), +// ], +// child: CustomText(TranslationKeys.makeTranslation(TranslationKeys.textHelp), style: Theme.of(Get.context!).textTheme.titleSmall?.copyWith(fontSize: 11, color: AppColors.colorSecondary)), +// ), +// ), +// body: Column( +// children: [ +// Expanded( +// child: SingleChildScrollView( +// child: Column( +// children: [ +// Stack( +// children: [ +// Container( +// height: 60, +// color: AppColors.colorPrimary, +// ), +// Align( +// alignment: Alignment.center, +// child: Padding( +// padding: EdgeInsets.only(top: 20), +// child: CircleAvatar( +// radius: 40.0, +// child: SvgPicture.asset( +// AppAssets.lg_round_uc_logo, +// height: 100, +// width: 100, +// fit: BoxFit.cover, +// ), +// ), +// ), +// ), +// ], +// ), +// SizedBox(height: 10), +// CustomText(TranslationKeys.makeTranslation(TranslationKeys.textDashboardWelcomeUser), style: Theme.of(Get.context!).textTheme.titleMedium), +// SizedBox(height: 10), +// Stack( +// children: [ +// Align( +// alignment: Alignment.center, +// child: Container( +// height: 230, +// width: 188, +// decoration: BoxDecoration( +// color: AppColors.colorGrey100, +// border: Border.all(color: AppColors.colorText.withOpacity(0.1), width: 1), +// borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), +// ), +// ), +// ), +// Align( +// alignment: Alignment.center, +// child: Padding( +// padding: EdgeInsets.only(top: 15.0), +// child: Container( +// height: 225, +// width: 188, +// decoration: BoxDecoration( +// color: AppColors.colorGrey200, +// border: Border.all(color: AppColors.colorText.withOpacity(0.2), width: 1), +// borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), +// ), +// ), +// ), +// ), +// Align( +// alignment: Alignment.center, +// child: Padding( +// padding: EdgeInsets.all(30.0), +// child: Container( +// height: 200, +// width: 212, +// decoration: BoxDecoration( +// color: AppColors.colorGrey50, +// border: Border.all(color: AppColors.colorButton, width: 2), +// borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), +// ), +// ), +// ), +// ), +// Align( +// alignment: Alignment.center, +// child: Padding( +// padding: EdgeInsets.only(top: 40.0), +// child: Container( +// height: 179, +// width: 190, +// decoration: BoxDecoration( +// color: AppColors.colorGrey50, +// border: Border.all(color: AppColors.colorPrimary, width: 2), +// borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard)), +// ), +// child: Padding( +// padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20), +// child: Column( +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// CustomText(TranslationKeys.makeTranslation(TranslationKeys.textTotalAvailableFunds), style: Theme.of(Get.context!).textTheme.bodySmall), +// SizedBox(height: 5), +// CustomText(TranslationKeys.makeTranslation(TranslationKeys.textTotalAvailableBalance), style: Theme.of(Get.context!).textTheme.titleLarge), +// SizedBox(height: 5), +// CustomText(TranslationKeys.makeTranslation(TranslationKeys.textTotalAvailableBalanceInWords), style: Theme.of(Get.context!).textTheme.bodySmall), +// SizedBox(height: 5), +// CustomText(TranslationKeys.makeTranslation(TranslationKeys.textAccountNumber), style: Theme.of(Get.context!).textTheme.bodySmall), +// ], +// ), +// ), +// ), +// ), +// ), +// ], +// ), +// SizedBox(height: 5), +// Stack( +// children: [ +// InkWell( +// onTap: () { +// Get.toNamed(Routes.TRANSACTION_HISTORY); +// }, +// child: Padding( +// padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0), +// child: Container( +// color: AppColors.colorGrey300, +// child: Row( +// children: [ +// Column(children: [ +// Container( +// decoration: const BoxDecoration( +// color: AppColors.colorPrimary, +// borderRadius: BorderRadius.zero, +// ), +// child: Padding( +// padding: const EdgeInsets.all(20.0), +// child: SvgPicture.asset(AppAssets.img_debet, color: AppColors.colorSecondary), +// ), +// ) +// ]), +// Padding( +// padding: EdgeInsets.symmetric(horizontal: 20), +// child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ +// CustomText( +// "Current Account", +// style: Theme.of(Get.context!).textTheme.titleSmall, +// ), +// SizedBox(height: 5), +// CustomText( +// "022379122*****95", +// style: Theme.of(Get.context!).textTheme.bodySmall, +// ), +// ]), +// ), +// ], +// ), +// ), +// ), +// ), +// Positioned( +// top: 20, +// right: 20, +// child: Align( +// alignment: Directionality.of(Get.context!) == TextDirection.rtl ? Alignment.bottomLeft : Alignment.bottomRight, +// child: Transform( +// alignment: Alignment.center, +// transform: Matrix4.rotationY(Directionality.of(Get.context!) == TextDirection.rtl ? 3.14159 : 0), +// child: SizedBox( +// height: 40, +// width: 40, +// child: SvgPicture.asset( +// fit: BoxFit.cover, +// AppAssets.img_round_dashboard_card, +// height: 35, +// width: 35, +// )), +// )), +// ), +// ], +// ), +// SizedBox(height: 20), +// Stack( +// children: [ +// Padding( +// padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0), +// child: Container( +// color: AppColors.colorGrey300, +// child: Row( +// children: [ +// Column(children: [ +// Container( +// decoration: const BoxDecoration( +// color: AppColors.colorPrimary, +// borderRadius: BorderRadius.zero, +// ), +// child: Padding( +// padding: const EdgeInsets.all(20.0), +// child: SvgPicture.asset(AppAssets.img_debet, color: AppColors.colorSecondary), +// ), +// ) +// ]), +// Padding( +// padding: EdgeInsets.symmetric(horizontal: 20), +// child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ +// CustomText( +// "Current Account", +// style: Theme.of(Get.context!).textTheme.titleSmall, +// ), +// SizedBox(height: 5), +// CustomText( +// "022379122*****95", +// style: Theme.of(Get.context!).textTheme.bodySmall, +// ), +// ]), +// ), +// ], +// ), +// ), +// ), +// Positioned( +// top: 20, +// right: 20, +// child: Align( +// alignment: Directionality.of(Get.context!) == TextDirection.rtl ? Alignment.bottomLeft : Alignment.bottomRight, +// child: Transform( +// alignment: Alignment.center, +// transform: Matrix4.rotationY(Directionality.of(Get.context!) == TextDirection.rtl ? 3.14159 : 0), +// child: SizedBox( +// height: 40, +// width: 40, +// child: SvgPicture.asset( +// fit: BoxFit.cover, +// AppAssets.img_round_dashboard_card, +// height: 35, +// width: 35, +// )), +// )), +// ), +// ], +// ), +// ], +// ), +// ), +// ), +// Container( +// padding: EdgeInsets.symmetric(horizontal: 20), +// child: Stack( +// alignment: Alignment.bottomCenter, +// children: [ +// Container( +// padding: EdgeInsets.symmetric(horizontal: 30, vertical: 10), +// margin: EdgeInsets.only(bottom: 10), +// width: double.infinity, +// decoration: BoxDecoration( +// color: AppColors.colorPrimary, +// borderRadius: BorderRadius.all( +// Radius.circular(10), +// ), +// ), +// child: Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// BottomSheetIcon( +// title: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// imageProvider: AppAssets.ic_u_send, +// onTap: () {}, +// ), +// BottomSheetIcon( +// title: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// imageProvider: AppAssets.ic_u_send, +// onTap: () {}, +// ), +// BottomSheetIcon( +// title: TranslationKeys.makeTranslation(TranslationKeys.textLogin), +// imageProvider: AppAssets.ic_u_send, +// onTap: () {}, +// ), +// SizedBox(width: 20), +// /* const SizedBox()*/ +// ], +// ), +// ), +// ], +// ), +// ) +// ], +// ), +// ); +// } +// } +// ======= + +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../../core/constants/app_assets.dart'; +import '../../../../core/constants/translation_keys.dart'; +import '../../../../core/utils/SessionCache.dart'; +import '../../../../core/utils/logs_utils.dart'; +import '../../../../custom_widgets/custom_no_record.dart'; +import '../../../../custom_widgets/custom_text.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../routes/app_pages.dart'; +import '../../../speed_dial/src/simple_speed_dial.dart'; +import '../../../u_received/views/u_received_view.dart'; +import '../../../u_send/views/u_send_view.dart'; +import '../../controllers/dashboard_screen_controller.dart'; +import 'bottom_sheet_icon.dart'; + +class DashBoardWithAllAccounts extends GetView { + late MenuController? menuController; + + DashBoardWithAllAccounts({super.key, this.menuController}); + + final DashboardScreenController dashBoardController = Get.find(); + + List widgetList = [ + const DashBoardPage(), + const USendView(showAppBar: false), + const UReceivedView(showAppBar: false), + const Center( + child: CustomNoRecord(title: "No Record Found", + description: "We couldn't find any activity at this moment"), + ) + ]; + + @override + Widget build(BuildContext context) { + controller.context = context; + + return KeyboardVisibilityBuilder(builder: (context, isKeyboardOpen) { + dp("OPen is", isKeyboardOpen); + + return Scaffold( + resizeToAvoidBottomInset: false, + floatingActionButton: isKeyboardOpen ? null : mainFloatingButton(), + floatingActionButtonLocation: FloatingActionButtonLocation.endDocked, + bottomNavigationBar: isKeyboardOpen + ? null + : Container( + height: 55, + clipBehavior: Clip.none, + padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 0), + margin: const EdgeInsets.only(bottom: 10, right: 20, left: 20), + decoration: const BoxDecoration( + color: AppColors.colorPrimary, + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + BottomSheetIcon( + title: TranslationKeys.makeTranslation(TranslationKeys.textHome), + imageProvider: AppAssets.ic_home_icon, + onTap: () { + dp("Click", " home dash board"); + controller.updatePage(0); + }, + width: 25, + height: 25, + ), + BottomSheetIcon( + title: TranslationKeys.makeTranslation(TranslationKeys.textUSend), + imageProvider: AppAssets.ic_u_cash, + onTap: () { + dp("Click", " home dash board"); + controller.updatePage(1); + }, + width: 25, + height: 25, + ), + BottomSheetIcon( + title: TranslationKeys.makeTranslation(TranslationKeys.textReceived), + imageProvider: AppAssets.ic_u_recive, + onTap: () { + controller.updatePage(2); + }, + width: 25, + height: 25, + ), + BottomSheetIcon( + title: TranslationKeys.makeTranslation(TranslationKeys.textUShop), + imageProvider: AppAssets.ic_u_shop, + onTap: () { + controller.fetchDepositAccounts(); + + controller.fetchExchangeRates(); + + controller.updatePage(3); + }, + width: 25, + height: 25, + ), + const SizedBox(width: 20), + /* const SizedBox()*/ + ], + ), + ), + body: GetBuilder( + builder: (controller) => widgetList[controller.curentIndex], + ), + ); + }); + } + + Widget mainFloatingButton() { + return SpeedDial( + openBackgroundColor: AppColors.colorButton, + closedBackgroundColor: AppColors.colorPrimaryLight, + labelsBackgroundColor: AppColors.colorButton, + labelsStyle: Get.context!.textTheme.bodyMedium?.copyWith( + color: AppColors.white, + fontSize: 16, + fontWeight: FontWeight.w600, + ), + speedDialChildren: [ + SpeedDialChild( + backgroundColor: AppColors.colorButton, + label: TranslationKeys.makeTranslation(TranslationKeys.textBillManagement), + child: SvgPicture.asset(AppAssets.ic_bill), + onPressed: () { + Get.toNamed(Routes.BILL_MANAGEMENT); + }, + ), + SpeedDialChild( + backgroundColor: AppColors.colorButton, + label: TranslationKeys.makeTranslation(TranslationKeys.textAccountStatement), + child: SvgPicture.asset(AppAssets.ic_money_management), + onPressed: () { + Get.toNamed(Routes.ACCOUNT_STATEMENT); + }, + ), + SpeedDialChild( + backgroundColor: AppColors.colorButton, + label: TranslationKeys.makeTranslation(TranslationKeys.textUserActivity), + child: SvgPicture.asset(AppAssets.ic_activity), + onPressed: () { + Get.toNamed(Routes.USER_ACTIVITY); + }, + ), + SpeedDialChild( + backgroundColor: AppColors.colorButton, + label: TranslationKeys.makeTranslation(TranslationKeys.textAddBeneficiary), + child: SvgPicture.asset(AppAssets.ic_u_recive, color: AppColors.colorPrimary), + onPressed: () { + Get.toNamed(Routes.BENEFICIARY_MANAGEMENT); + }, + ), + ], + child: SvgPicture.asset( + AppAssets.sending_icon, + )); + } +} + +class DashBoardPage extends StatelessWidget { + const DashBoardPage({super.key}); + + @override + Widget build(BuildContext context) { + return GetBuilder(builder: (controller) { + return Obx(() { + return Column( + children: [ + controller.depositeAccount.isEmpty + ? const Center( + child: Text("Data not found please try again"), + ) + : Expanded( + child: Column( + children: [ + Stack( + fit: StackFit.passthrough, + clipBehavior: Clip.none, + children: [ + Container( + height: 60, + color: AppColors.colorPrimary, + ), + Align( + alignment: Alignment.center, + child: Padding( + padding: const EdgeInsets.only(top: 20), + child: SvgPicture.asset(AppAssets.ic_dashboard_logo, height: 89, width: 79, fit: BoxFit.cover), + ), + ), + const Positioned(bottom: -10, left: 0, right: 0, child: AddMoneyAndKyc()), + ], + ), + const SizedBox(height: 27), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: CustomText( + "Welcome ${SessionCache.instance.userInfo.name}", + style: context.textTheme.titleMedium!.copyWith(fontSize: 21, fontWeight: FontWeight.w400), + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 30), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ...controller.depositeAccount + .map((depositAccount) => InkWell( + onTap: () { + Get.toNamed(Routes.ACCOUNT_STATEMENT, arguments: {"accountNumber": depositAccount.mbmBkmsnumber}); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 5.0), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), color: Colors.white, boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.3), // Adjust color and opacity + spreadRadius: 2.0, // Adjust for shadow diffusion + blurRadius: 4.0, // Adjust for shadow softness + offset: const Offset(0, 2), // Adjust for shadow position (x, y) + ), + BoxShadow( + color: Colors.grey.withOpacity(0.3), // Adjust color and opacity + spreadRadius: 2.0, // Adjust for shadow diffusion + blurRadius: 4.0, // Adjust for shadow softness + offset: const Offset(0, 0), // Adjust for shadow position (x, y) + ), + ]), + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + // flex: 3, + child: Padding( + padding: const EdgeInsets.only(top: 30.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomText( + "Total Balance", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 8), + SizedBox( + width: 160, + child: AutoSizeText( + "${depositAccount.pcrCurrshort} ${depositAccount.mbmBkmsbalance.toStringAsFixed(2)}", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 20, fontWeight: FontWeight.w400), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ), + const SizedBox(width: 30), + Flexible( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [Image.asset(controller.getFlagWithCurrencyCode(depositAccount.pcrCurrcode), width: 30, height: 30)], + ), + ) + ], + )), + ))) + .toList(), + const SizedBox(width: 10), + InkWell( + onTap: () { + Get.toNamed(Routes.ADD_NEW_ACCOUNT); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 14.0), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), color: Colors.white, boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.3), // Adjust color and opacity + spreadRadius: 2.0, // Adjust for shadow diffusion + blurRadius: 4.0, // Adjust for shadow softness + offset: const Offset(0, 2), // Adjust for shadow position (x, y) + ), + BoxShadow( + color: Colors.grey.withOpacity(0.3), // Adjust color and opacity + spreadRadius: 2.0, // Adjust for shadow diffusion + blurRadius: 4.0, // Adjust for shadow softness + offset: const Offset(0, 0), // Adjust for shadow position (x, y) + ), + ]), + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + flex: 3, + child: Padding( + padding: const EdgeInsets.only(top: 30.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomText( + TranslationKeys.makeTranslation(TranslationKeys.textAddAccount), + style: context.textTheme.titleSmall!.copyWith(fontSize: 15, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 5), + CustomText( + "40+ currencies", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w400), + overflow: TextOverflow.ellipsis, + ) + ], + ), + ), + ), + const SizedBox(width: 30), + Flexible( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + // height: 50, + // width: 50, + padding: const EdgeInsets.all(10.0), + decoration: BoxDecoration( + color: AppColors.colorGrey350, + borderRadius: BorderRadius.circular(50.0), + ), + child: Image.asset(AppAssets.ic_add_new_Account, height: 15, width: 15), + ) + ], + ), + ) + ], + )), + ), + ], + ), + ), + const SizedBox(height: 10), + controller.depositeAccount.isNotEmpty + ? Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 5.0), + child: ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: controller.depositeAccount.length, + itemBuilder: (context, index) { + return depositAccountItem(controller, context, index); + }, + separatorBuilder: (BuildContext context, int index) { + return const Padding(padding: EdgeInsets.symmetric(vertical: 10)); + }, + ), + ), + ), + ) + : const Center( + child: Text("No deposit accounts found."), + ) + ], + ), + ), + ], + ); + }); + }); + } + + GestureDetector depositAccountItem(DashboardScreenController controller, BuildContext context, int index) { + return GestureDetector( + onTap: () { + Get.toNamed(Routes.ACCOUNT_STATEMENT, arguments: {"accountNumber": controller.depositeAccount.elementAt(index).mbmBkmsnumber}); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0), + child: Container( + // padding: const EdgeInsets.all(5.0), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(0), color: Colors.white, boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.3), + spreadRadius: 2.0, + blurRadius: 4.0, + offset: const Offset(0, 2), + ), + BoxShadow( + color: Colors.grey.withOpacity(0.3), + spreadRadius: 2.0, + blurRadius: 4.0, + offset: const Offset(0, 0), + ), + ]), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(width: 7), + Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15), + child: Align(alignment: Alignment.bottomRight, child: Image.asset(controller.getFlagWithCurrencyCode(controller.depositeAccount.elementAt(index).pcrCurrcode), width: 40, height: 40, fit: BoxFit.cover)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 5), + child: Column(mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ + CustomText( + "${controller.depositeAccount.elementAt(index).mbmBkmstitle.toString()} (${controller.depositeAccount.elementAt(index).pcrCurrshort})", + style: Theme.of(Get.context!).textTheme.titleSmall!.copyWith(fontSize: 14, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 5), + CustomText( + controller.depositeAccount.elementAt(index).mbmBkmsnumber.toString(), + style: Theme.of(Get.context!).textTheme.titleSmall!.copyWith(fontSize: 10, fontWeight: FontWeight.w500), + ), + ]), + ), + Expanded( + flex: 3, + child: Align( + alignment: Alignment.centerRight, + child: CustomText( + "${controller.depositeAccount.elementAt(index).pcrCurrshort} ${controller.depositeAccount.elementAt(index).mbmBkmsbalance.toStringAsFixed(2)}", + style: context.textTheme.titleMedium!.copyWith(fontSize: 13, fontWeight: FontWeight.w400), + ), + ), + ), + Align( + alignment: Directionality.of(Get.context!) == TextDirection.rtl ? Alignment.bottomLeft : Alignment.bottomRight, + child: Padding( + padding: const EdgeInsets.only(top: 26), + child: SizedBox( + height: 55, + width: 55, + child: SvgPicture.asset( + fit: BoxFit.cover, + AppAssets.ic_desposit_account_arrow, + height: 45, + width: 40, + )), + )), + ], + ), + ), + ), + ); + } +} + +class AddMoneyAndKyc extends StatelessWidget { + const AddMoneyAndKyc({super.key}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(left: 22, right: 22), + child: Row( + children: [ + GestureDetector( + onTap: () { + Get.toNamed(Routes.ADD_MONEY); + }, + child: Container( + padding: const EdgeInsets.all(15.0), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(25), + border: Border.all(color: AppColors.ff444444), + ), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + child: Row( + children: [ + CustomText( + "Add Money", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w400), + ), + const SizedBox( + width: 4, + ), + const Icon(Icons.add, color: Colors.green, size: 15) + ], + ), + ), + ), + ), + const Spacer(), + Container( + decoration: BoxDecoration( + color: SessionCache.instance.userInfo.isKycVerified ? Colors.green : AppColors.ffF95846, + borderRadius: const BorderRadius.only(topLeft: Radius.circular(22), bottomRight: Radius.circular(22)), + ), + padding: const EdgeInsets.only(top: 5.5, bottom: 5.5, left: 12, right: 12), + child: Row( + children: [ + CustomText( + SessionCache.instance.userInfo.isKycVerified ? "KYC verified" : "KYC Unverified", + style: context.textTheme.bodyMedium!.copyWith( + fontSize: 11, + color: Colors.white, + fontWeight: FontWeight.w400, + ), + ), + const SizedBox(width: 4), + SvgPicture.asset( + SessionCache.instance.userInfo.isKycVerified ? AppAssets.ic_tick_option : AppAssets.ic_cross_white, + width: 15, + height: 15, + ) + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/faqs/bindings/faqs_binding.dart b/lib/app/modules/faqs/bindings/faqs_binding.dart new file mode 100644 index 0000000..75ffce8 --- /dev/null +++ b/lib/app/modules/faqs/bindings/faqs_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/faqs_controller.dart'; + +class FaqsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => FaqsController(), + ); + } +} diff --git a/lib/app/modules/faqs/bindings/faqs_first_screen_binding.dart b/lib/app/modules/faqs/bindings/faqs_first_screen_binding.dart new file mode 100644 index 0000000..fa3ad87 --- /dev/null +++ b/lib/app/modules/faqs/bindings/faqs_first_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/faqs_first_screen_controller.dart'; + +class FaqsFirstBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => FaqsFirstController(), + ); + } +} diff --git a/lib/app/modules/faqs/bindings/faqs_second_screen_binding.dart b/lib/app/modules/faqs/bindings/faqs_second_screen_binding.dart new file mode 100644 index 0000000..ea0c0f8 --- /dev/null +++ b/lib/app/modules/faqs/bindings/faqs_second_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/faqs_second_screen_controller.dart'; + +class FaqsSecondBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => FaqsSecondController(), + ); + } +} diff --git a/lib/app/modules/faqs/bindings/faqs_third_screen_binding.dart b/lib/app/modules/faqs/bindings/faqs_third_screen_binding.dart new file mode 100644 index 0000000..b527384 --- /dev/null +++ b/lib/app/modules/faqs/bindings/faqs_third_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/faqs_third_screen_controller.dart'; + +class FaqsThirdBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => FaqsThirdController(), + ); + } +} diff --git a/lib/app/modules/faqs/controllers/faqs_controller.dart b/lib/app/modules/faqs/controllers/faqs_controller.dart new file mode 100644 index 0000000..ca4f151 --- /dev/null +++ b/lib/app/modules/faqs/controllers/faqs_controller.dart @@ -0,0 +1,1218 @@ +import 'package:get/get.dart'; + +import '../views/model/FAQS.dart'; + +class FaqsController extends GetxController { + late FaqsModel faqsModel; + final searchText = ''.obs; + var filteredListSendingMoney = [].obs; + + @override + onInit() { + super.onInit(); + loadData(); + debounce(searchText, (_) => filterListSendingMoney(), time: const Duration(milliseconds: 300)); + } + + loadData() { + faqsModel = FaqsModel.fromMap(faqsJson); + filteredListSendingMoney.value = faqsModel.sendingMoney; + update(); + } + + void filterListSendingMoney() { + if (searchText.isEmpty) { + filteredListSendingMoney.value = faqsModel.sendingMoney; + } else { + filteredListSendingMoney.value = faqsModel.sendingMoney.where((item) => item.title.toLowerCase().contains(searchText.value.toLowerCase())).toList(); + } + } + + List get filteredSendingMoney { + if (searchText.value.isEmpty) { + return faqsModel.sendingMoney; + } else { + return faqsModel.sendingMoney.where((sendingMoney) => sendingMoney.title.toLowerCase().contains(searchText.value.toLowerCase()) || sendingMoney.description.toLowerCase().contains(searchText.value.toLowerCase()) || sendingMoney.questions.any((question) => question.title.toLowerCase().contains(searchText.value.toLowerCase()) || question.subQuestions.any((subQuestion) => subQuestion.title.toLowerCase().contains(searchText.value.toLowerCase()) || subQuestion.questionDetails.any((questionDetail) => questionDetail.question.toLowerCase().contains(searchText.value.toLowerCase()) || questionDetail.answer.toLowerCase().contains(searchText.value.toLowerCase()))))).toList(); + } + } +} + +/// Corrected JSON structure +var faqsJson = { + "Sending_money": [ + { + "title": "Sending money", + "description": "Setting up, paying for, editing, and cancelling transfers.", + "ImageProvider": "assets/uco/icons/ic_snding_money.svg", + "questions": [ + { + "title": "Sending money basics", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How long does a transfer take?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "Can I sendexact amounts?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How do you notify meabout a transfer?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How do I download a transfer receipt?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "Do I need to pay any tax on transfers?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How can I repeat a transfer?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "Can I send from someone else's bank account?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + ] + }, + { + "title": "Where is my money?", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Mistakes and editing your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Cancellations and refunds", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "We support these countries and currencies", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Ways to pay", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Verifying your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending money from your Wise account", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending large transfers", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Managing your recipients", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Rates and fees", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + ] + }, + { + "title": "Managing your account", + "description": "Setting up your account and getting verified.", + "ImageProvider": "assets/uco/icons/ic_manage_account.svg", + "questions": [ + { + "title": "Sending money basics", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How long does a transfer take?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + }, + ] + }, + { + "title": "Where is my money?", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Mistakes and editing your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Cancellations and refunds", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "We support these countries and currencies", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Ways to pay", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Verifying your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending money from your Wise account", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending large transfers", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Managing your recipients", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Rates and fees", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + ] + }, + { + "title": "Holding money", + "description": "Holding balances, setting up Direct Debits, and using \nInterest & Stocks.", + "ImageProvider": "assets/uco/icons/ic_holding_money.svg", + "questions": [ + { + "title": "Sending money basics", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How long does a transfer take?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + }, + ] + }, + { + "title": "Where is my money?", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Mistakes and editing your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Cancellations and refunds", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "We support these countries and currencies", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Ways to pay", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Verifying your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending money from your Wise account", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending large transfers", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Managing your recipients", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Rates and fees", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + ] + }, + { + "title": "Wise card", + "description": "Ordering, activating, spending, and troubleshooting.", + "ImageProvider": "assets/uco/icons/ic_wise_card.svg", + "questions": [ + { + "title": "Sending money basics", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How long does a transfer take?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + }, + ] + }, + { + "title": "Where is my money?", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Mistakes and editing your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Cancellations and refunds", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "We support these countries and currencies", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Ways to pay", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Verifying your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending money from your Wise account", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending large transfers", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Managing your recipients", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Rates and fees", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + ] + }, + { + "title": "Receiving money", + "description": "Using your account details to receive money.", + "ImageProvider": "assets/uco/icons/ic_receiving_money.svg", + "questions": [ + { + "title": "Sending money basics", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + { + "question": "How to send money with UCO", + "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password. \n\nWe’ll also need to verify you before you are able to send money. Check what information we need and how long verification takes here.", + "multiple_options": [ + { + "option_title": "1. Go to 'Send'", + "option_answer": "From the Home screen, select Send.", + }, + { + "option_title": "2. Choose where you want to send from", + "option_answer": "You can fund your transfer from either an account outside UCO or use available money on your UCO balance.", + }, + { + "option_title": "3. Enter how much you’d like to transfer", + "option_answer": "Select either the amount you’d like to send,or exactly how much you’d like your recipient to get, and chose the currency. \n\nIf you choose how much you send, the fees are added to that amount. If you choose how much your recipient gets, we'll show you how much you have to send including the fees. \n\nYou can choose to schedule this transfer by clicking the calendar icon next to Continue.", + }, + { + "option_title": "4. Let us know who you’re sending money to", + "option_answer": "You can search for an existing recipient from your list by typing the name, Wisetag, email or phone, or scrolling down the list. \n\nIf it's not an existing recipient, you can add one manually by clicking Add a recipient.", + }, + { + "option_title": "Add a new recipient", + "option_answer": "Select if you're sending to yourself, someone else, or a business. \n\nIf you have their bank details, check the box and add them in — we’ll send money to that account. \n\nIf you don’t have their bank details, just enter their email address.", + "built_point_1": "If they have an account with UCO, we’ll find the account they want to receive money into.", + "built_point_2": "If they don’t have an account with UCO, we’ll send them an email asking for their bank details.", + }, + { + "option_title": "5. Review the details of your transfer", + "option_answer": "Make sure everything looks right. You can add a reference for your recipient if you’d like.", + }, + { + "option_title": "6. Choose how to pay", + "option_answer": "The confirmation lets you check the details — your money isn't sent at this point. \n\nThere are multiple ways you can pay for your transfer. We’ll let you know the fees for each option, and how long it should take for the money to arrive. \n\nIt’s often cheapest to pay from your bank account. This means you’ll have to go to your online banking or your branch and send the money to UCO from there.", + }, + { + "option_title": "7. That’s it!", + "option_answer": "After we’ve received your money, we’ll confirm the transfer via email or in the app. And we’ll also let you and your recipient know when the money’s on its way. \n\nYour payments will appear under Transactions on the home screen, and you can even change the category from a drop-down list right under the amount, to keep your payments organised.", + }, + ], + }, + ] + }, + { + "title": "How long does a transfer take?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + }, + ] + }, + { + "title": "Where is my money?", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Mistakes and editing your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Cancellations and refunds", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "We support these countries and currencies", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Ways to pay", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Verifying your transfer", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending money from your Wise account", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Sending large transfers", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Managing your recipients", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + { + "title": "Rates and fees", + "sub_questions": [ + { + "title": "How do I send money with UCO?", + "questions_details": [ + {"question": "How do I send money with UCO?", "answer": "To send money with Wise, you’ll first need to sign up. We’ll ask for your email address, and you’ll create a password."} + ] + } + ] + }, + ] + }, + ] +}; diff --git a/lib/app/modules/faqs/controllers/faqs_first_screen_controller.dart b/lib/app/modules/faqs/controllers/faqs_first_screen_controller.dart new file mode 100644 index 0000000..f3dffd2 --- /dev/null +++ b/lib/app/modules/faqs/controllers/faqs_first_screen_controller.dart @@ -0,0 +1,27 @@ +import 'package:get/get.dart'; + +import '../views/model/FAQS.dart'; + +class FaqsFirstController extends GetxController { + late SendingMoney sendMoney; + final searchText = ''.obs; + RxList filteredListQuestions = [].obs; + @override + onInit() { + super.onInit(); + sendMoney = Get.arguments; + filteredListQuestions.value = sendMoney.questions; + debounce(searchText, (_) => filterListQuestions(), time: const Duration(milliseconds: 300)); + } + + void filterListQuestions() { + if (searchText.value.isEmpty) { + filteredListQuestions.value = sendMoney.questions; + } else { + filteredListQuestions.value = sendMoney.questions + .where((question) => + question.title.toLowerCase().contains(searchText.value.toLowerCase())) + .toList(); + } + } +} diff --git a/lib/app/modules/faqs/controllers/faqs_second_screen_controller.dart b/lib/app/modules/faqs/controllers/faqs_second_screen_controller.dart new file mode 100644 index 0000000..b2c56df --- /dev/null +++ b/lib/app/modules/faqs/controllers/faqs_second_screen_controller.dart @@ -0,0 +1,34 @@ +import 'package:get/get.dart'; + +import '../../../core/utils/logs_utils.dart'; +import '../views/model/FAQS.dart'; + + +class FaqsSecondController extends GetxController { + late Question question; + final searchText = ''.obs; + RxList filteredListSubQuestions = [].obs; + + @override + onInit() { + super.onInit(); + question = Get.arguments; + filteredListSubQuestions.value = question.subQuestions; + debounce(searchText, (_) => filterListQuestions(), time: const Duration(milliseconds: 300)); + } + + @override + void onReady() { + // TODO: implement onReady + super.onReady(); + dp("filteredListSubQuestions", filteredListSubQuestions.toString()); + } + + void filterListQuestions() { + if (searchText.value.isEmpty) { + filteredListSubQuestions.value = question.subQuestions; + } else { + filteredListSubQuestions.value = question.subQuestions.where((question) => question.title.toLowerCase().contains(searchText.value.toLowerCase())).toList(); + } + } +} diff --git a/lib/app/modules/faqs/controllers/faqs_third_screen_controller.dart b/lib/app/modules/faqs/controllers/faqs_third_screen_controller.dart new file mode 100644 index 0000000..b74a04e --- /dev/null +++ b/lib/app/modules/faqs/controllers/faqs_third_screen_controller.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/faqs/views/faqs_view.dart'; +import '../views/model/FAQS.dart'; + +class FaqsThirdController extends GetxController { + late SubQuestion subQuestion; + @override + onInit() { + super.onInit(); + subQuestion = Get.arguments; + } +} diff --git a/lib/app/modules/faqs/views/faqs_first_screen_view.dart b/lib/app/modules/faqs/views/faqs_first_screen_view.dart new file mode 100644 index 0000000..ede1339 --- /dev/null +++ b/lib/app/modules/faqs/views/faqs_first_screen_view.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/faqs_controller.dart'; +import '../controllers/faqs_first_screen_controller.dart'; + +class FaqsFirstScreenView extends GetView { + FaqsFirstScreenView({Key? key, this.description, this.title, this.shortTitle}) : super(key: key); + + var firstScreenController = Get.find(); + + String? title; + String? shortTitle; + String? description; + + @override + Widget build(BuildContext context) { + var faqs = controller.faqsModel; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textFaqs), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(firstScreenController.sendMoney.title, style: Theme + .of(context) + .textTheme + .titleSmall + ?.copyWith(color: AppColors.black, fontSize: 20, fontWeight: FontWeight.w500)), + Column(children: [ + Container( + margin: const EdgeInsets.only(left: 0, right: 0, bottom: 12, top: 17), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 12.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon(Icons.search, size: 15.0, color: Colors.grey[800]), + const SizedBox(width: 5.0), + Expanded( + child: TextField( + style: Theme + .of(context) + .textTheme + .bodySmall + ?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: const InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: 'search your query', + ), + onChanged: (value) => firstScreenController.searchText.value = value), + ), + ], + ), + ), + ]), + const SizedBox(height: 20), + Obx(() { + return Expanded( + child: ListView.builder( + itemCount: firstScreenController.filteredListQuestions.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: InkWell( + onTap: () { + Get.toNamed(Routes.FAQS_SECOND_SCREEN, arguments: firstScreenController.sendMoney.questions[index]); + }, + child: Padding( + padding: const EdgeInsets.only(bottom: 10.0), + child: Row( + children: [ + Text( + firstScreenController.filteredListQuestions[index].title, + style: context.textTheme.bodySmall!.copyWith(fontSize: 14, fontWeight: FontWeight.w500), + ), + const Spacer(), + const Padding(padding: EdgeInsets.all(0.0), child: Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey500)), + ], + ), + ), + ), + ); + }, + ), + ); + }), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/faqs/views/faqs_second_screen_view.dart b/lib/app/modules/faqs/views/faqs_second_screen_view.dart new file mode 100644 index 0000000..c15b2ad --- /dev/null +++ b/lib/app/modules/faqs/views/faqs_second_screen_view.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/faqs_controller.dart'; +import '../controllers/faqs_second_screen_controller.dart'; + +class FaqsSecondScreenView extends GetView { + FaqsSecondScreenView({Key? key, this.description, this.title, this.shortTitle}) : super(key: key); + + var secondScreenController = Get.find(); + + String? title; + String? shortTitle; + String? description; + + @override + Widget build(BuildContext context) { + var faqs = controller.faqsModel; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textFaqs), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(secondScreenController.question.title, style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black, fontSize: 20, fontWeight: FontWeight.w500)), + Column(children: [ + Container( + margin: const EdgeInsets.only(left: 0, right: 0, bottom: 12, top: 17), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 12.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon( + Icons.search, + size: 15.0, + color: Colors.grey[800], + ), + const SizedBox(width: 5.0), + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: const InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: 'search your query', + ), + onChanged: (value) => secondScreenController.searchText.value = value), + ), + ], + ), + ), + ]), + const SizedBox(height: 20), + Obx(() { + return Expanded( + child: ListView.builder( + itemCount: secondScreenController.filteredListSubQuestions.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.only(bottom: 15.0), + child: InkWell( + onTap: () { + Get.toNamed(Routes.FAQS_THIRD_SCREEN, arguments: secondScreenController.question.subQuestions[index]); + }, + child: Row( + children: [ + Text( + secondScreenController.filteredListSubQuestions[index].title, + style: context.textTheme.bodySmall!.copyWith(fontSize: 14, fontWeight: FontWeight.w500), + ), + const Spacer(), + const Padding(padding: EdgeInsets.all(0.0), child: Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey500)), + ], + ), + ), + ); + }, + ), + ); + }), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/faqs/views/faqs_third_screen_view.dart b/lib/app/modules/faqs/views/faqs_third_screen_view.dart new file mode 100644 index 0000000..bf7711b --- /dev/null +++ b/lib/app/modules/faqs/views/faqs_third_screen_view.dart @@ -0,0 +1,63 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/faqs_controller.dart'; +import '../controllers/faqs_third_screen_controller.dart'; + +class FaqsThirdScreenView extends GetView { + FaqsThirdScreenView({Key? key, this.description, this.title, this.shortTitle}) : super(key: key); + + var thirdScreenController = Get.find(); + + String? title; + String? shortTitle; + String? description; + + @override + Widget build(BuildContext context) { + var faqs = controller.faqsModel; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textFaqs), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(thirdScreenController.subQuestion.title, style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black, fontSize: 20, fontWeight: FontWeight.w500)), + const SizedBox(height: 10), + Text(faqs.sendingMoney.first.questions.first.subQuestions.first.questionDetails.first.answer, style: Theme.of(context).textTheme.bodySmall?.copyWith( fontSize: 12, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text("How to send money with UCO", style: Theme.of(context).textTheme.titleSmall?.copyWith( fontSize: 18, fontWeight: FontWeight.w500, color: AppColors.black)), + const SizedBox(height: 20), + Expanded( + flex: 4, + child: ListView.builder( + itemCount: controller.faqsModel.sendingMoney.first.questions.first.subQuestions.first.questionDetails.first.multipleOptions?.length, + itemBuilder: (context, index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(faqs.sendingMoney.first.questions.first.subQuestions.first.questionDetails.first.multipleOptions![index].optionTitle, style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black, fontSize: 12, fontWeight: FontWeight.w700)), + const SizedBox(height: 10), + Text(faqs.sendingMoney.first.questions.first.subQuestions.first.questionDetails.first.multipleOptions![index].optionAnswer, style: Theme.of(context).textTheme.bodySmall?.copyWith(fontSize: 12, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + ], + ); + },), + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/faqs/views/faqs_view.dart b/lib/app/modules/faqs/views/faqs_view.dart new file mode 100644 index 0000000..61e68f2 --- /dev/null +++ b/lib/app/modules/faqs/views/faqs_view.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/faqs_controller.dart'; + +class FaqsView extends GetView { + FaqsView({Key? key, this.description, this.title, this.shortTitle}) : super(key: key); + String? title; + String? shortTitle; + String? description; + + @override + Widget build(BuildContext context) { + var faqs = controller.faqsModel; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textFaqs), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textHowCanIHelpYou), style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black, fontSize: 20, fontWeight: FontWeight.w500)), + Column(children: [ + Container( + margin: const EdgeInsets.only(left: 0, right: 0, bottom: 12, top: 17), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 12.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon( + Icons.search, + size: 15.0, + color: Colors.grey[800], + ), + const SizedBox(width: 5.0), + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: const InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: 'search your query', + ), + onChanged: (value) => controller.searchText.value = value), + ), + ], + ), + ), + ]), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textExploreAllArticles), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontSize: 14, fontWeight: FontWeight.w400)), + const SizedBox(height: 20), + Container( + height: 1, + width: double.infinity, + color: AppColors.colorGrey350, + ), + const SizedBox(height: 30), + Obx(() { + return Expanded( + child: ListView.builder( + itemCount: controller.filteredListSendingMoney.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.only(bottom: 20.0), + child: InkWell( + onTap: () { + Get.toNamed(Routes.FAQS_FIRST_SCREEN, arguments: faqs.sendingMoney[index]); + }, + child: Row( + children: [ + SvgPicture.asset(faqs.sendingMoney[index].imageProvider, height: 40), + const SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + controller.filteredSendingMoney[index].title, + style: context.textTheme.bodyMedium!.copyWith(fontSize: 12, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 5), + Text( + controller.filteredSendingMoney[index].description, + style: context.textTheme.bodySmall!.copyWith(fontSize: 9, fontWeight: FontWeight.w400), + ), + ], + ), + const Spacer(), + const Padding(padding: EdgeInsets.all(0.0), child: Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey500)), + ], + ), + ), + ); + }, + ), + ); + }), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/faqs/views/model/FAQS.dart b/lib/app/modules/faqs/views/model/FAQS.dart new file mode 100644 index 0000000..b28d3ef --- /dev/null +++ b/lib/app/modules/faqs/views/model/FAQS.dart @@ -0,0 +1,187 @@ +class FaqsModel { + List sendingMoney; + + FaqsModel({required this.sendingMoney}); + + factory FaqsModel.fromMap(Map? map) { + return FaqsModel( + sendingMoney: List.from((map?['Sending_money'] ?? []).map((x) => SendingMoney.fromMap(x))), + ); + } + + Map toMap() { + return { + 'Sending_money': sendingMoney.map((x) => x.toMap()).toList(), + }; + } + + @override + String toString() { + return 'FaqsModel{sendingMoney: $sendingMoney}'; + } +} + +class SendingMoney { + String title; + String description; + String imageProvider; + List questions; + + SendingMoney({ + required this.title, + required this.description, + required this.imageProvider, + required this.questions, + }); + + factory SendingMoney.fromMap(Map? map) { + return SendingMoney( + title: map?['title'] ?? "", + description: map?['description'] ?? "", + imageProvider: map?['ImageProvider'] ?? "", + questions: List.from((map?['questions'] ?? []).map((x) => Question.fromMap(x))), + ); + } + + Map toMap() { + return { + 'title': title, + 'description': description, + 'ImageProvider': imageProvider, + 'questions': questions.map((x) => x.toMap()).toList(), + }; + } + + @override + String toString() { + return 'SendingMoney{title: $title, description: $description, imageProvider: $imageProvider, questions: $questions}'; + } +} + +class Question { + String title; + List subQuestions; + + Question({ + required this.title, + required this.subQuestions, + }); + + factory Question.fromMap(Map? map) { + return Question( + title: map?['title'] ?? "", + subQuestions: List.from((map?['sub_questions'] ?? []).map((x) => SubQuestion.fromMap(x))), + ); + } + + Map toMap() { + return { + 'title': title, + 'sub_questions': subQuestions.map((x) => x.toMap()).toList(), + }; + } + + @override + String toString() { + return 'Question{title: $title, subQuestions: $subQuestions}'; + } +} + +class SubQuestion { + String title; + List questionDetails; + + SubQuestion({ + required this.title, + required this.questionDetails, + }); + + factory SubQuestion.fromMap(Map? map) { + return SubQuestion( + title: map?['title'] ?? "", + questionDetails: List.from((map?['questions_details'] ?? []).map((x) => QuestionDetails.fromMap(x))), + ); + } + + Map toMap() { + return { + 'title': title, + 'questions_details': questionDetails.map((x) => x.toMap()).toList(), + }; + } + + @override + String toString() { + return 'SubQuestion{title: $title, questionDetails: $questionDetails}'; + } +} + +class QuestionDetails { + String question; + String answer; + List multipleOptions; + String? builtPoint1; + String? builtPoint2; + + QuestionDetails({ + required this.question, + required this.answer, + required this.multipleOptions, + this.builtPoint1, + this.builtPoint2, + }); + + factory QuestionDetails.fromMap(Map? map) { + return QuestionDetails( + question: map?['question'] ?? "", + answer: map?['answer'] ?? "", + multipleOptions: List.from((map?['multiple_options'] ?? []).map((x) => MultipleOption.fromMap(x))), + builtPoint1: map?['built_point_1'], + builtPoint2: map?['built_point_2'], + ); + } + + Map toMap() { + return { + 'question': question, + 'answer': answer, + 'multiple_options': multipleOptions.map((x) => x.toMap()).toList(), + 'built_point_1': builtPoint1, + 'built_point_2': builtPoint2, + }; + } + + @override + String toString() { + return 'QuestionDetails{question: $question, answer: $answer, multipleOptions: $multipleOptions, builtPoint1: $builtPoint1, builtPoint2: $builtPoint2}'; + } +} + +class MultipleOption { + String optionTitle; + String optionAnswer; + + MultipleOption({ + required this.optionTitle, + required this.optionAnswer, + }); + + factory MultipleOption.fromMap(Map? map) { + return MultipleOption( + optionTitle: map?['option_title'] ?? "", + optionAnswer: map?['option_answer'] ?? "", + ); + } + + Map toMap() { + return { + 'option_title': optionTitle, + 'option_answer': optionAnswer, + }; + } + + @override + String toString() { + return 'MultipleOption{optionTitle: $optionTitle, optionAnswer: $optionAnswer}'; + } +} diff --git a/lib/app/modules/general_ledger/bindings/general_ledger_binding.dart b/lib/app/modules/general_ledger/bindings/general_ledger_binding.dart new file mode 100644 index 0000000..4566a0d --- /dev/null +++ b/lib/app/modules/general_ledger/bindings/general_ledger_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/general_ledger_controller.dart'; + +class GeneralLedgerBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => GeneralLedgerController(), + ); + } +} diff --git a/lib/app/modules/general_ledger/controllers/general_ledger_controller.dart b/lib/app/modules/general_ledger/controllers/general_ledger_controller.dart new file mode 100644 index 0000000..97950ec --- /dev/null +++ b/lib/app/modules/general_ledger/controllers/general_ledger_controller.dart @@ -0,0 +1,222 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/GLACCAddMoneyRequestModel.dart'; +import '../../../models/GlsResponseModel.dart'; +import '../../../models/evaluated_cuency_model.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; + +class GeneralLedgerController extends GetxController { + final AppRepositories repository = Get.find(); + late InputField messageField; + late InputField glsAccounts; + late InputField userTransactionPinField; + TextEditingController pinPutController = TextEditingController(); + + RxList allGlsAccounts = RxList.empty(); + Rx selectedGlAccount = Rx(null); + GLACCAddMoneyRequestModel transactionSubmitRequestModel = GLACCAddMoneyRequestModel.empty(); + Rx evaluatedCurrencyModel = EvaluatedCurrencyModel.empty().obs; + + @override + void onInit() { + super.onInit(); + + // var arguments = Get.arguments; + // + // transactionSubmitRequestModel = (arguments != null ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? GLACCAddMoneyRequestModel.empty() : GLACCAddMoneyRequestModel.empty()); + // + // evaluatedCurrencyModel.value = (arguments != null ? arguments[AppConstants.EXCHANGE_RATE] ?? EvaluatedCurrencyModel.empty() : EvaluatedCurrencyModel.empty()); + // + // fetchAllGlsAccounts(); + } + + @override + void dispose() { + pinPutController.clear(); + super.dispose(); + } + + void updateSelectedDeposit(DropDown item) { + // selectedGlAccount.value = item; + } + + clearAll() { + messageField.clear(); + glsAccounts.clear(); + userTransactionPinField.clear(); + pinPutController.clear(); + selectedGlAccount = Rx(null); + } + + Future fetchAllGlsAccounts() async { + ServerResponse response = await repository.fetchGlsAccounts(); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + List list = List.from(((response.response ?? []) as List).map((x) => GlsResponseModel.fromMap(x)) ?? []); + SessionCache.instance.glsAccountsList.value = list; + allGlsAccounts.clear(); + for (int i = 0; i < list.length; i++) { + GlsResponseModel glsResponseModel = list.elementAt(i); + allGlsAccounts.add( + DropDown(i.toString(), "${glsResponseModel.pcaGlaccode} - ${glsResponseModel.pcaGlacdesc}", glsResponseModel), + ); + } + allGlsAccounts.refresh(); + } + + /// Pin Dialog...........Transactions + void transactionPinDialog(BuildContext context, GeneralLedgerController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textTransactionPin), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + textInputAction: TextInputAction.done, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.pinPutController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.userTransactionPinField.setText(controller.pinPutController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + // bool validate() { + // bool isValid = FieldValidation.validateAll([glsAccounts, userTransactionPinField]); + // return isValid; + // } + + Future handleNextClick() async { + // if (!validate()) { + // Toasty.error("Please input and then proceed"); + // return; + // } + + // TransactionPinRequestModel transactionPinRequestModel = TransactionPinRequestModel( + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // channelCode: RequestConstants.channelCode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // email: SessionCache.instance.userInfo.cmpUserId, + // pinType: "TRAN", + // transPincode: userTransactionPinField.getCustomText(), + // isOtpRequired: false, + // ); + // + // ServerResponse response = await repository.sendAddMoneyOtp(transactionPinRequestModel); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + // SendTransactionStep1ResponseModel step1responseModel = SendTransactionStep1ResponseModel.fromMap(response.response); + // transactionSubmitRequestModel.notificationId = step1responseModel.notificationId.toString(); + // + // GlsResponseModel responseModel = selectedGlAccount.value!.data as GlsResponseModel; + // transactionSubmitRequestModel.drPcaGlaccode = responseModel.pcaGlaccode; + // transactionSubmitRequestModel.drPcaGlacdesc = responseModel.pcaGlacdesc; + + Get.toNamed(Routes.OTP_ADD_MONEY, + // arguments: { + // AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + // AppConstants.EXCHANGE_RATE: evaluatedCurrencyModel.value, + // } + ); + } +} diff --git a/lib/app/modules/general_ledger/views/general_ledger_view.dart b/lib/app/modules/general_ledger/views/general_ledger_view.dart new file mode 100644 index 0000000..2fa1e32 --- /dev/null +++ b/lib/app/modules/general_ledger/views/general_ledger_view.dart @@ -0,0 +1,178 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/general_ledger_controller.dart'; + +class GeneralLedgerView extends GetView { + const GeneralLedgerView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.transAddMoney), + onBackButtonPressed: () { + Navigator.of(context).pop(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: CustomButton( + onPressed: () { + controller.handleNextClick(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.only(top: 12, bottom: 12), + ), + ) + ], + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + child: Column( + children: [ + // Text(TranslationKeys.makeTranslation(TranslationKeys.textSelectYourGLSAccount), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500, fontSize: 20)), + Card( + color: AppColors.colorGrey50, + margin: const EdgeInsets.symmetric(horizontal: 2, vertical: 10), + elevation: 5.0, + child: Container( + padding: const EdgeInsets.all(12), + decoration: const BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(10)) // Add border radius + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Text(TranslationKeys.makeTranslation(TranslationKeys.textConformation), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500, fontSize: 20)), + // const SizedBox(height: 10), + Row( + children: [ + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.all(0.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textTotalAmount), style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w500)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w500)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textCurrency), style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w500)), + ], + ), + )), + + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.all(0.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(controller.evaluatedCurrencyModel.value.sgtGntramtfc.toString(), style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(controller.evaluatedCurrencyModel.value.targetPerEratrateact.toString(), style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(getFlagWithCurrencyCode(controller.evaluatedCurrencyModel.value.pcrCurrcode.toString()), style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 14, fontWeight: FontWeight.w400)), + ], + ), + )), + + // Expanded( + // flex: 2, + // child: Padding( + // padding: const EdgeInsets.only(left: 12.0, right: 12.0), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.end, + // mainAxisAlignment: MainAxisAlignment.end, + // children: [ + // Text("sdd", style: Theme.of(context).textTheme.bodySmall), + // const SizedBox(height: 10), + // Text("sds", style: Theme.of(context).textTheme.bodySmall), + // const SizedBox(height: 10), + // Text("skks", style: Theme.of(context).textTheme.bodySmall), + // const SizedBox(height: 10), + // Text("sk", style: Theme.of(context).textTheme.bodySmall), + // ], + // ), + // )), + ], + ), + ], + )), + ), + controller.glsAccounts = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}depositAccountField"), + controller: FormFieldConstants.instance().getController("${className}depositAccountField"), + labelText: "Select GL Account", + textInputAction: TextInputAction.done, + suffixIcon: const Icon(Icons.keyboard_arrow_down, size: 25), + isDropDown: true, + hintText: "Select GL account", + dropDownType: DropDownType.SPECIAL, + items: controller.allGlsAccounts, + onItemSelected: (item) { + controller.updateSelectedDeposit(item!); + }, + ), + + controller.userTransactionPinField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}userTransactionPinField"), + controller: FormFieldConstants.instance().getController("${className}userTransactionPinField"), + hintText: "Enter transaction pin", + labelText: "Transaction Pin", + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isPassword: true, + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + controller.transactionPinDialog(context, controller); + }, + ), + + controller.messageField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + refKey: FormFieldConstants.instance().getFormKey("${className}messageField"), + controller: FormFieldConstants.instance().getController("${className}messageField"), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textEnterMessage), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textMessageMemo), + onSubmitted: (value) { + controller.handleNextClick(); + }, + ), + ], + ), + ), + ); + } + + String getFlagWithCurrencyCode(String currencyCode) { + int currencyCodeInt = int.tryParse(currencyCode) ?? 0; + + if (currencyCodeInt == 586) { + return "PKR"; + } else if (currencyCodeInt == 997) { + return "USD"; + } else if (currencyCodeInt == 978) { + return "EUR"; + } else { + return ""; + } + } +} diff --git a/lib/app/modules/internal_account_transaction/bindings/internal_transaction_binding.dart b/lib/app/modules/internal_account_transaction/bindings/internal_transaction_binding.dart new file mode 100644 index 0000000..b21e5f7 --- /dev/null +++ b/lib/app/modules/internal_account_transaction/bindings/internal_transaction_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/internal_transaction_controller.dart'; + +class InternalAccountTransBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => InternalAccountTransController(), + ); + } +} diff --git a/lib/app/modules/internal_account_transaction/controllers/internal_transaction_controller.dart b/lib/app/modules/internal_account_transaction/controllers/internal_transaction_controller.dart new file mode 100644 index 0000000..0f34b33 --- /dev/null +++ b/lib/app/modules/internal_account_transaction/controllers/internal_transaction_controller.dart @@ -0,0 +1,186 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/Fields/field_validations.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/ExchangeRate.dart'; +import '../../../routes/app_pages.dart'; + + +class InternalAccountTransController extends GetxController { + TextEditingController pinPutController = TextEditingController(); + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + + //drop down + RxList allFromAccounts = RxList.empty(); + Rx selectedFromAccount = DepositAccount.empty().obs; + + RxList allToAccounts = RxList.empty(); + Rx selectedToAccount = DepositAccount.empty().obs; + ExchangeRate? selectedExchangeRate; + + TextEditingController referenceCodeController = TextEditingController(); + + // fields + late InputField fromAccountField; + late InputField toAccountField; + late InputField sendingAmountField; + late InputField exchangeRateField; + late InputField messageField; + late InputField userTransactionPinField; + late InputField referenceCodeField; + + @override + void onInit() { + super.onInit(); + for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + DepositAccount depositAccount = SessionCache.instance.depositAccountList.elementAt(i); + allFromAccounts.add(DropDown(depositAccount.mbmBkmsnumber, "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", depositAccount)); + } + } + + @override + Future onReady() async { + super.onReady(); + disposeAllResources(); + onFromAccountSelection(allFromAccounts.elementAt(0)); + fromAccountField.setText((allFromAccounts.first.label)); + } + + void onFromAccountSelection(DropDown value) { + if (value.id == selectedToAccount.value.mbmBkmsnumber) { + Toasty.error('This account is already selected'); + fromAccountField.setText(""); + selectedFromAccount.value = DepositAccount.empty(); + } else { + selectedFromAccount.value = value.data as DepositAccount; + } + } + + void onToAccountSelection(DropDown value) { + if (value.id == selectedFromAccount.value.mbmBkmsnumber) { + Toasty.error('This account is already selected'); + toAccountField.setText(""); + selectedToAccount.value = DepositAccount.empty(); + } else { + selectedToAccount.value = value.data as DepositAccount; + } + + if (selectedToAccount.value.mbmBkmsnumber.isEmpty) { + return; + } + for (int i = 0; i < SessionCache.instance.exchangeRateList.length; i++) { + if (SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrcode == selectedToAccount.value.pcrCurrcode) { + selectedExchangeRate = SessionCache.instance.exchangeRateList.elementAt(i); + exchangeRateField.setText(selectedExchangeRate!.perEratrateact.toString()); + break; + } + } + } + + void disposeAllResources() { + fromAccountField.clear(); + toAccountField.clear(); + sendingAmountField.clear(); + exchangeRateField.clear(); + messageField.clear(); + userTransactionPinField.clear(); + referenceCodeField.clear(); + referenceCodeController.clear(); + } + + bool validate() { + bool isValid = FieldValidation.validateAll([ + fromAccountField, + toAccountField, + sendingAmountField, + exchangeRateField, + userTransactionPinField, + referenceCodeField, + ]); + if (pinPutController.text.isEmpty) { + return false; + } + if (referenceCodeController.text.isEmpty) { + return false; + } + return isValid; + } + + /// Send Transaction function + Future sendTransaction() async { + // if (!validate()) { + // Toasty.error("Please input and then proceed"); + // return; + // } + // + // TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel( + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // channelCode: RequestConstants.channelCode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // drMbmBkmsnumber: selectedFromAccount.value.mbmBkmsnumber, + // drMbmBkmstitle: selectedFromAccount.value.mbmBkmstitle, + // drPcrCurrcode: selectedFromAccount.value.pcrCurrcode, + // drPcrCurrdesc: selectedFromAccount.value.pcrCurrdesc, + // drPcrCurrshort: selectedFromAccount.value.pcrCurrshort, + // crMbmBkmsnumber: selectedToAccount.value.mbmBkmsnumber, + // crMbmBkmstitle: selectedToAccount.value.mbmBkmstitle, + // crPcrCurrcode: selectedExchangeRate!.pcrCurrcode, + // crPcrCurrdesc: selectedExchangeRate!.pcrCurrdesc, + // crPcrCurrshort: selectedExchangeRate!.pcrCurrshort, + // sgtGntrnarration: "", + // dmpProdCode: selectedFromAccount.value.dmpProdcode, + // transType: "DR", + // notificationId: "", + // transMode: "Online", + // sgtGntramtfc: double.parse(sendingAmountField.getCustomText().isEmpty ? "0.0" : sendingAmountField.getCustomText()), + // otdTrancomment: messageField.getCustomText(), + // isOtpRequired: false, + // cmpRefcode: referenceCodeField.getCustomText(), + // ); + // + // dp("********************>>>>>>>>>>>>******************", transactionSubmitRequestModel); + // TransactionPinRequestModel transactionPinRequestModel = TransactionPinRequestModel( + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // channelCode: RequestConstants.channelCode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // email: SessionCache.instance.userInfo.cmpUserId, + // pinType: "TRAN", + // transPincode: userTransactionPinField.getCustomText(), + // isOtpRequired: false, + // ); + // + // ServerResponse response = await repository.sendTransactionStep1(transactionPinRequestModel); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + // SendTransactionStep1ResponseModel step1responseModel = SendTransactionStep1ResponseModel.fromMap(response.response); + // transactionSubmitRequestModel.notificationId = step1responseModel.notificationId.toString(); + Get.toNamed(Routes.INTERNAL_TRANSACTION_OPT); + // arguments: { + // AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + // AppConstants.INTERNAL_TRANSACTION_PIN_REQUEST: transactionPinRequestModel, + // AppConstants.EXCHANGE_RATE: exchangeRateField.getCustomText(), + // }); + } + + void clearTransaction() { + toAccountField.clear(); + sendingAmountField.clear(); + exchangeRateField.clear(); + messageField.clear(); + userTransactionPinField.clear(); + pinPutController.clear(); + referenceCodeField.clear(); + referenceCodeController.clear(); + } +} diff --git a/lib/app/modules/internal_account_transaction/views/internal_transaction_view.dart b/lib/app/modules/internal_account_transaction/views/internal_transaction_view.dart new file mode 100644 index 0000000..5b643bb --- /dev/null +++ b/lib/app/modules/internal_account_transaction/views/internal_transaction_view.dart @@ -0,0 +1,402 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; + + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/internal_transaction_controller.dart'; + +class InternalAccountTransView extends GetView { + const InternalAccountTransView({Key? key, this.showAppBar = true}) : super(key: key); + + final bool showAppBar; + + @override + Widget build(BuildContext context) { + Get.put(InternalAccountTransController()); + + String className = runtimeType.toString().split('.').last; + + return Scaffold( + appBar: showAppBar + ? DashBoardAppBar( + title: "Internal Transfer", + /*TranslationKeys.makeTranslation(TranslationKeys.textUSend),*/ + onBackButtonPressed: () { + Get.back(); + }, + ) + : null, + body: Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Card( + color: AppColors.colorGrey50, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + controller.fromAccountField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}fromAccountField"), + controller: FormFieldConstants.instance().getController("${className}fromAccountField"), + labelText: "Select From Account", + isDropDown: true, + hintText: "Select from account", + dropDownType: DropDownType.SPECIAL, + isRequired: true, + items: controller.allFromAccounts, + onItemSelected: (item) { + // controller.updateSelectedDeposit(item!); + controller.onFromAccountSelection(item!); + }, + ), + controller.toAccountField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}toAccountField"), + controller: FormFieldConstants.instance().getController("${className}toAccountField"), + labelText: "Select To Account", + isDropDown: true, + hintText: "Select recipient detail", + dropDownType: DropDownType.SPECIAL, + items: controller.allFromAccounts, + onItemSelected: (item) { + //controller.updateSelectedDeposit(item!); + controller.onToAccountSelection(item!); + }, + ), + Row( + children: [ + Expanded( + flex: 1, + child: controller.sendingAmountField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + textInputAction: TextInputAction.done, + refKey: FormFieldConstants.instance().getFormKey("${className}sendingAmountField"), + controller: FormFieldConstants.instance().getController("${className}sendingAmountField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), + isRequired: true, + keyboardType: const TextInputType.numberWithOptions(decimal: true), + inputFormatters: InputType.maxValueFilter(InputType.INT_MAX_VALUE_, true, 2), + ), + ), + const SizedBox(width: 10), + Expanded( + flex: 1, + child: controller.exchangeRateField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}exchangeRateField"), + controller: FormFieldConstants.instance().getController("${className}exchangeRateField"), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), + readOnly: true, + showCursor: false, + ), + ), + ], + ), + controller.userTransactionPinField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}userTransactionPinField"), + controller: FormFieldConstants.instance().getController("${className}userTransactionPinField"), + hintText: "Enter transaction pin", + labelText: "Transaction Pin", + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isRequired: true, + isPassword: true, + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + transactionPinDialog(context, controller); + }, + ), + controller.referenceCodeField = InputField( + enableInteractiveSelection: false, + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isRequired: true, + isPassword: true, + refKey: FormFieldConstants.instance().getFormKey("${className}referenceCodeField"), + controller: FormFieldConstants.instance().getController("${className}referenceCodeField"), + hintText: "Enter reference code", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + referenceCodeDialog(context, controller); + }, + ), + controller.messageField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + refKey: FormFieldConstants.instance().getFormKey("${className}messageField"), + controller: FormFieldConstants.instance().getController("${className}messageField"), + hintText: "Enter message", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textMessageMemo), + onSubmitted: (value) { + controller.sendTransaction(); + }, + ), + const SizedBox(height: 20), + Row( + children: [ + Expanded( + flex: 1, + child: CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.sendTransaction(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textSend), + buttonPadding: const EdgeInsets.symmetric(vertical: 11), + textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.white), + buttonColor: AppColors.colorButton, + ), + ), + const SizedBox(width: 10), + Expanded( + flex: 1, + child: CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.clearTransaction(); + controller.disposeAllResources(); + }, + buttonPadding: const EdgeInsets.symmetric(vertical: 11), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textClear), + buttonColor: AppColors.colorSkipBtn, + textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black), + sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1), + ), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + ], + ), + ); + } + + /// Pin Dialog...........Transactions + void transactionPinDialog(BuildContext context, InternalAccountTransController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textTransactionPin), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.pinPutController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.userTransactionPinField.setText(controller.pinPutController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + /// Reference Dialog...........Transactions + void referenceCodeDialog(BuildContext context, InternalAccountTransController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.referenceCodeController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350, + ), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + textInputAction: TextInputAction.done, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.referenceCodeController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.referenceCodeField.setText(controller.referenceCodeController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } +} diff --git a/lib/app/modules/internal_transaction_otp/bindings/internal_transaction_otp_binding.dart b/lib/app/modules/internal_transaction_otp/bindings/internal_transaction_otp_binding.dart new file mode 100644 index 0000000..7cb3ae3 --- /dev/null +++ b/lib/app/modules/internal_transaction_otp/bindings/internal_transaction_otp_binding.dart @@ -0,0 +1,13 @@ +import 'package:get/get.dart'; + +import '../controllers/internal_transaction_otp_controller.dart'; + + +class InternalTransactionOtpBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => InternalTransactionOtpController(), + ); + } +} diff --git a/lib/app/modules/internal_transaction_otp/controllers/internal_transaction_otp_controller.dart b/lib/app/modules/internal_transaction_otp/controllers/internal_transaction_otp_controller.dart new file mode 100644 index 0000000..8a0c000 --- /dev/null +++ b/lib/app/modules/internal_transaction_otp/controllers/internal_transaction_otp_controller.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/BeneficiaryAccountModel.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/TransactionPinRequestModel.dart'; +import '../../../models/TransactionSubmitRequestModel.dart'; +import '../../../routes/app_pages.dart'; + + +class InternalTransactionOtpController extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + + TextEditingController pinPutController = TextEditingController(); + TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel.empty(); + TransactionPinRequestModel internalTransPinRequestModel = TransactionPinRequestModel.empty(); + String exchangeRate = ""; + + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + + late DepositAccount fromAccount; + late DepositAccount toAccount; + late List beneficiaryList; + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + transactionSubmitRequestModel = (arguments != null ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? TransactionSubmitRequestModel.empty() : TransactionSubmitRequestModel.empty()); + internalTransPinRequestModel = (arguments != null ? arguments[AppConstants.INTERNAL_TRANSACTION_PIN_REQUEST] ?? TransactionPinRequestModel.empty() : TransactionPinRequestModel.empty()); + exchangeRate = (arguments != null ? arguments[AppConstants.EXCHANGE_RATE] ?? "" : ""); + } + + Future validatePinAndNavigate() async { + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + + // transactionSubmitRequestModel.pinType = "TRAN"; + // + // transactionSubmitRequestModel.obpPincode = pinPutController.text; + + Get.toNamed(Routes.RECIPIENT_DETAILS, + // arguments: { + // AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + // AppConstants.EXCHANGE_RATE: exchangeRate, + // } + ); + } + + Future sendBeneficiaryTransaction({navigate = true}) async { + ServerResponse response = await repository.sendTransactionStep1(internalTransPinRequestModel); + + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Toasty.success("OTP send successfully"); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/internal_transaction_otp/views/internal_transaction_otp_view.dart b/lib/app/modules/internal_transaction_otp/views/internal_transaction_otp_view.dart new file mode 100644 index 0000000..d0d3add --- /dev/null +++ b/lib/app/modules/internal_transaction_otp/views/internal_transaction_otp_view.dart @@ -0,0 +1,137 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../controllers/internal_transaction_otp_controller.dart'; + +class InternalTransactionOtpView extends GetView { + const InternalTransactionOtpView({Key? key, this.showAppBar = true}) : super(key: key); + final bool showAppBar; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + textInputAction: TextInputAction.done, + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle(fontSize: 12), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.sendBeneficiaryTransaction(navigate: false); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/login/bindings/login_screen_binding.dart b/lib/app/modules/login/bindings/login_screen_binding.dart new file mode 100644 index 0000000..6bc2f56 --- /dev/null +++ b/lib/app/modules/login/bindings/login_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/login_screen_controller.dart'; + +class LoginScreenBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => LoginScreenController(), + ); + } +} diff --git a/lib/app/modules/login/controllers/login_screen_controller.dart b/lib/app/modules/login/controllers/login_screen_controller.dart new file mode 100644 index 0000000..c86c6c9 --- /dev/null +++ b/lib/app/modules/login/controllers/login_screen_controller.dart @@ -0,0 +1,135 @@ +import 'dart:convert'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/local_stoarge/app_storage.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/app_utils.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/Fields/field_validations.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/AuthenticationRequest.dart'; +import '../../../models/finger_print_info.dart'; +import '../../../routes/app_pages.dart'; +import '../../app_setting/controllers/app_setting_controller.dart'; + +class LoginScreenController extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + late InputField userNameInputField; + late InputField passwordInputField; + bool loginUsingFingerPrint = false; + + @override + Future onReady() async { + super.onReady(); + + if (kDebugMode) { + /// Ciihive server + // userNameInputField.setText("duck@gmail.com"); + // passwordInputField.setText("Test@123"); + + /// Local server + // userNameInputField.setText("nabeelx64@gmail.com"); + // passwordInputField.setText("App@123"); + } + } + + updateLanguage(Locale locale) async { + Get.updateLocale(locale); + // Get.find().saveLocale(locale.toString()); + // localeController.selectedLocale.value = locale.toString(); + AppSettingController.isRTL.value = Get.locale!.languageCode == "ar" || Get.locale!.languageCode == "ur"; + AppSettingController.selectedLocale.value = Get.locale!.languageCode; + await AppStorage.putString(AppConstants.SELECTED_LOCALE, AppSettingController.selectedLocale.value); + await AppStorage.putBoolean(AppConstants.IS_RTL, AppSettingController.isRTL.value); + Get.forceAppUpdate(); + update(); + } + + bool validate() { + bool isValid = FieldValidation.validateAll([userNameInputField, passwordInputField]); + return isValid; + } + + void validateAndLogin() async { + + + if (!validate()) { + Toasty.error("Please input and then proceed"); + return; + } + if (!AppUtils.isPasswordValid(passwordInputField.getCustomText(), 8)) { + Toasty.error( + TranslationKeys.makeTranslation(TranslationKeys.textPasswordPattern)); + return; + } + + AuthenticationRequest request = AuthenticationRequest( + email: userNameInputField.getCustomText(), + password: passwordInputField.getCustomText(), + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + isOtpRequired: false, + ); + + ServerResponse response = await repository.login(request); + dp("server response", response); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + Get.toNamed(Routes.O_T_P_SCREEN, + arguments: {AppConstants.SIGN_UP_FIRST_STEP_DATA: request}); + } + + void fingerPrintLogin() async { + String info = await AppStorage.getString(AppConstants.IS_FINGER_PRINT_ENABLED, fallback: ""); + if (info.isEmpty) { + Toasty.error(TranslationKeys.makeTranslation(TranslationKeys.textInvalidFingerprint)); + AppStorage.putString(AppConstants.IS_FINGER_PRINT_ENABLED, ""); + return; + } + + FingerPrintInfo fingerPrintInfo = FingerPrintInfo.fromMap(jsonDecode(info)); + + if (fingerPrintInfo.cmpUserId.isEmpty || fingerPrintInfo.cmpCustpassword.isEmpty) { + Toasty.error(TranslationKeys.makeTranslation(TranslationKeys.textInvalidFingerprint)); + + AppStorage.putString(AppConstants.IS_FINGER_PRINT_ENABLED, ""); + + return; + } + + SessionCache.instance.fingerPrintController.authenticate((status) async { + if (status) { + AuthenticationRequest request = AuthenticationRequest( + email: fingerPrintInfo.cmpUserId, + password: fingerPrintInfo.cmpCustpassword, + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + ); + + ServerResponse response = await repository.login(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Get.toNamed(Routes.O_T_P_SCREEN, arguments: { + AppConstants.SIGN_UP_FIRST_STEP_DATA: request, + 'loginUsingFingerPrint': loginUsingFingerPrint, + + }); + // showOtpInputDialog(context); + } + }, false); + } +} diff --git a/lib/app/modules/login/views/login_screen_view.dart b/lib/app/modules/login/views/login_screen_view.dart new file mode 100644 index 0000000..ebfe57f --- /dev/null +++ b/lib/app/modules/login/views/login_screen_view.dart @@ -0,0 +1,613 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_custom_clippers/flutter_custom_clippers.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/login/views/shared/login_widget.dart'; + +// import 'package:url_launcher/url_launcher.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/data/data_source_auth/remote_data_source/app_remote_data_source.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../custom_widgets/custom_label.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/login_screen_controller.dart'; + +class LoginScreenView extends GetView { + const LoginScreenView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + controller.context = context; + Get.lazyPut(() => AppRemoteDataSource()); + Get.lazyPut(() => AppRepositoriesImpl(remoteDataSource: Get.find())); + print("Width login ${MediaQuery.sizeOf(context).width} "); + + print("Height login ${MediaQuery.sizeOf(context).height} "); + + String className = runtimeType.toString().split('.').last; + return SafeArea( + child: Scaffold( + persistentFooterButtons: [ + BottomNavigationBar( + backgroundColor: AppColors.colorSecondary.withOpacity(0.1), + elevation: 0, + type: BottomNavigationBarType.fixed, + items: [ + // + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs(context, TranslationKeys.makeTranslation(TranslationKeys.textFindUAgent), AppAssets.ic_security, () { + Toasty.success("Coming Soon....."); + // Get.toNamed(Routes.O_T_P_SCREEN); + // LoginWidgets.showBottomSheet(context, BottomSheetLogin.options, (index) { + // BottomSheetLogin option = BottomSheetLogin.options[index]; + // if (option.description == TranslationKeys.makeTranslation(TranslationKeys.textLogin)) {} + // }); + }, context.textTheme.bodySmall!.copyWith(fontSize: 12)), + label: '', + ), + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs( + context, + TranslationKeys.makeTranslation( + TranslationKeys.textQRPay), + AppAssets.ic_QR, + () { + Get.toNamed(Routes.qrViewScreen); + }, + context.textTheme.bodySmall!.copyWith(fontSize: 12)), + label: '', + ), + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs(context, TranslationKeys.makeTranslation(TranslationKeys.textHelp), AppAssets.ic_client, () { + Get.toNamed(Routes.faqsViews); + // showModalBottomSheetWidget(Get.context!); + + // Toasty.success("Coming Soon....."); + }, context.textTheme.bodySmall!.copyWith(fontSize: 12)), + label: '', + ), + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs(context, TranslationKeys.makeTranslation(TranslationKeys.textContactUs), AppAssets.ic_contact_us, () { + showBottomSheet(context); + }, context.textTheme.bodySmall!.copyWith(fontSize: 12)), + label: '', + ), + ], + ), + ], + body: SingleChildScrollView( + child: Column( + children: [ + GestureDetector( + onTap: () { + showCurrencyDialog(context); + }, + child: Align( + alignment: Alignment.centerRight, + child: Padding( + padding: const EdgeInsets.only(right: 8.0, left: 8.0), + child: Container( + decoration: const BoxDecoration(color: AppColors.colorPrimary, borderRadius: BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20))), + height: 60, + width: 30, + child: Padding( + padding: const EdgeInsets.only(top: 28.0, left: 5, right: 5), + child: SvgPicture.asset(AppAssets.ic_arrow_down, height: 10, width: 10), + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Image.asset(AppAssets.uc_logo, height: 56, width: 130, fit: BoxFit.cover), + ), + const SizedBox(height: 20), + controller.userNameInputField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}userNameField"), + controller: FormFieldConstants.instance().getController("${className}userNameField"), + hintText: "enter email", + labelText: "Email", + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.userNameFieldLength)], + keyboardType: TextInputType.emailAddress, + ), + controller.passwordInputField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}passwordField"), + controller: FormFieldConstants.instance().getController("${className}passwordField"), + hintText: "enter password", + labelText: "Password", + keyboardType: TextInputType.visiblePassword, + requiredPasswordIcon: true, + isPassword: true, + onSubmitted: (value) { + controller.validateAndLogin(); + }, + ), + // controller.userNameField = CustomInputFieldCustom( + // refKey: FormFieldConstants.instance().getFormKey("${className}userNameField"), + // controller: FormFieldConstants.instance().getController("${className}userNameField"), + // labelText: "User Name", + // ), + // const SizedBox(height: 20), + // controller.passwordField = CustomInputFieldCustom( + // refKey: FormFieldConstants.instance().getFormKey("${className}passwordField"), + // controller: FormFieldConstants.instance().getController("${className}passwordField"), + // labelText: "Password", + // requiredPasswordIcon: true, + // isPassword: true, + // ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validateAndLogin(); + }, + buttonPadding: const EdgeInsets.symmetric(vertical: 8), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + buttonColor: AppColors.colorButton, + textStyle: const TextStyle(color: AppColors.white), + ), + ), + const SizedBox(height: 10), + GestureDetector( + onTap: () { + Get.toNamed(Routes.SIGN_UP_SCREEN_STEP1); + }, + child: Text.rich( + TextSpan( + text: TranslationKeys.makeTranslation(TranslationKeys.textNotRegisterUser), // First part of the text + style: Theme.of(context).textTheme.bodySmall, + children: [ + const WidgetSpan( + child: SizedBox(width: 8.0), // Adjust the width as needed for the space + ), + TextSpan( + text: TranslationKeys.makeTranslation(TranslationKeys.textRegisterNow), + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: AppColors.colorDialogBG, fontWeight: FontWeight.w400), + ), + ], + ), + ), + ), + const SizedBox(height: 30), + Obx(() { + return Visibility( + visible: SessionCache.instance.fingerPrintController.isFingerprintSupported.value && SessionCache.instance.fingerPrintController.isFingerPrintExistInDB.value, + child: Center( + child: SizedBox( + width: 65, + height: 65, + child: Material( + child: InkWell( + onTap: () { + controller.loginUsingFingerPrint = true; + controller.fingerPrintLogin(); + }, + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(100), // Set the border radius + ), + child: Container( + decoration: BoxDecoration(color: AppColors.colorGrey800.withOpacity(0.50), borderRadius: const BorderRadius.all(Radius.circular(100))), + child: const Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Icon( + color: AppColors.colorButton, + Icons.fingerprint_sharp, + size: 35.0, + ), + ), + ], + ), + ), + ), + ), + ), + ), + ); + }), + // controller.dateField = CustomDateTimePicker( + // refKey: FormFieldConstants.instance() + // .getFormKey("${className}dateField"), + // controller: FormFieldConstants.instance() + // .getController("${className}dateField"), + // labelText: "picker", + // ), + // SizedBox(height: 10), + // controller.genderField = CustomDropDown( + // listData: [DropDown(id: "id1", label: "Label1"), DropDown(id: "id2", label: "Label2"), DropDown(id: "id3", label: "Label3")].obs, + // labelText: "Gender", + // isRequired: true, + // ), + ], + ), + ) + ], + ), + )), + ); + } + + void showModalBottomSheetWidget(BuildContext context) { + List supportBottomSheetList = [ + SupportBottomSheet( + image: AppAssets.ic_email, + title: TranslationKeys.makeTranslation(TranslationKeys.textEmail), + onTap: () { + // launch("mailto:info@mfsys.com.pk"); + }), + SupportBottomSheet( + image: AppAssets.ic_phone, + title: TranslationKeys.makeTranslation(TranslationKeys.textPhone), + onTap: () async { + // launch("tel:021213123123"); + }), + ]; + showModalBottomSheet( + context: context, + useRootNavigator: true, + backgroundColor: Colors.transparent, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10))), + builder: (BuildContext context) { + return responsiveWidget( + Stack( + children: [ + Align( + alignment: Alignment.bottomCenter, + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + //border: Border.all(color: Colors.grey, width: 1), + borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)), + ), + margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 0), + padding: const EdgeInsets.only(top: 12), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textGetInTouch), + style: Theme.of(context).textTheme.titleSmall, + ), + InkWell( + onTap: () { + Navigator.pop(context); + }, + child: SvgPicture.asset(AppAssets.ic_cross, height: 15, width: 15), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.all(10), + child: GridView.builder( + itemCount: supportBottomSheetList.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 15, + mainAxisSpacing: 15, + ), + itemBuilder: (context, index) { + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: supportBottomSheetList[index].onTap, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 1), + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + "${supportBottomSheetList[index].image}", + ), + const SizedBox(height: 20), + Center( + child: LabelText("${supportBottomSheetList[index].title}"), + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ), + ), + ], + ), + ); + }, + ); + } + + /// Contact Us Bottom Sheet Widget + showBottomSheet(BuildContext context) { + List supportBottomSheetList = [ + SupportBottomSheet( + image: AppAssets.ic_email, + title: TranslationKeys.makeTranslation(TranslationKeys.textEmail), + onTap: () { + // launch("mailto:info@mfsys.com.pk"); + }), + SupportBottomSheet( + image: AppAssets.ic_phone, + title: TranslationKeys.makeTranslation(TranslationKeys.textPhone), + onTap: () async { + // launch("tel:021213123123"); + }), + ]; + + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + anchorPoint: Offset.zero, + builder: (BuildContext context) { + return responsiveWidget( + Container(height: 25,width: 30, color: Colors.red, child: Text("data"),clipBehavior: Clip.none,),); + }, + ); + + showModalBottomSheet( + context: context, + builder: (context) => + contactUsBottomSheet(context, supportBottomSheetList), + ); + + Get.bottomSheet( + contactUsBottomSheet(context, supportBottomSheetList), + useRootNavigator: true, + backgroundColor: Colors.transparent, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); + } + + Widget contactUsBottomSheet(BuildContext context, List supportBottomSheetList) { + return responsiveWidget( + Stack( + fit: StackFit.loose, + children: [ + Align( + alignment: Alignment.bottomCenter, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey, width: 1), + borderRadius: const BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)), + ), + margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 0), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textGetInTouch), + style: Theme.of(context).textTheme.titleSmall, + ), + InkWell( + onTap: () { + Navigator.pop(context); + }, + child: SvgPicture.asset( + AppAssets.ic_cross, + height: 15, + width: 15, + ), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.all(10), + margin: const EdgeInsets.only(bottom: 20), + child: GridView.builder( + itemCount: supportBottomSheetList.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 15, + mainAxisSpacing: 15, + ), + itemBuilder: (context, index) { + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: supportBottomSheetList[index].onTap, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 1), + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + "${supportBottomSheetList[index].image}", + height: 50, + width: 50, + ), + const SizedBox(height: 20), + Center( + child: LabelText( + "${supportBottomSheetList[index].title}", + style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 14), + ), + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ), + ), + ], + ), + ); + } + + void showCurrencyDialog(BuildContext loginScreenContext) { + showGeneralDialog( + context: loginScreenContext, + barrierDismissible: true, + transitionDuration: const Duration(milliseconds: 500), + barrierLabel: MaterialLocalizations.of(loginScreenContext).dialogLabel, + barrierColor: Colors.black.withOpacity(0.5), + pageBuilder: (context, _, __) { + return responsiveWidget( + Stack( + children: [ + Positioned( + top: 200, + right: 0, + child: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Align( + alignment: Alignment.centerRight, + child: Padding( + padding: const EdgeInsets.only(right: 5.0, left: 8.0), + child: Container( + decoration: const BoxDecoration(color: AppColors.colorPrimary, borderRadius: BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20))), + height: 70, + width: 30, + child: Padding( + padding: const EdgeInsets.only(top: 28.0, left: 5, right: 5), + child: SvgPicture.asset( + AppAssets.ic_arrow_down, + height: 10, + width: 10, + ), + ), + ), + ), + ), + ), + ), + Align( + alignment: Alignment.topCenter, + child: ClipPath( + clipper: MultipleRoundedCurveClipper(), + child: Card( + elevation: 2.0, + child: ListView( + shrinkWrap: true, + children: [ + Image.asset( + AppAssets.uc_logo, + height: 55, + width: 130, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textUPrimary), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textUCash), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textUSave), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text(TranslationKeys.makeTranslation(TranslationKeys.textUChaChing), style: Theme.of(context).textTheme.titleSmall), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text("\$1,800.00", style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text("\$500.00", style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text("\$1288.06", style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 5), + Text("\$120,000.00", style: Theme.of(context).textTheme.titleSmall), + const SizedBox( + height: 20, + ) + ], + ), + ), + ], + ), + ], + ), + ), + ), + ), + ], + ), + ); + }, + transitionBuilder: (context, animation, secondaryAnimation, child) { + return SlideTransition( + position: CurvedAnimation( + parent: animation, + curve: Curves.easeOut, + ).drive(Tween( + begin: const Offset(0, -1.0), + end: Offset.zero, + )), + child: child, + ); + }, + ); + } +} + +class SupportBottomSheet { + String? image; + String? title; + Function()? onTap; + + SupportBottomSheet({this.image, this.title, this.onTap}); +} diff --git a/lib/app/modules/login/views/shared/bottom_sheet_login.dart b/lib/app/modules/login/views/shared/bottom_sheet_login.dart new file mode 100644 index 0000000..bd81841 --- /dev/null +++ b/lib/app/modules/login/views/shared/bottom_sheet_login.dart @@ -0,0 +1,173 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import 'package:get/get.dart'; +import 'package:get/get_core/src/get_main.dart'; + +import '../../../../core/constants/translation_keys.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../routes/app_pages.dart'; + +// import 'package:url_launcher/url_launcher.dart'; + +class BottomSheetLogin { + String _description = ""; + String _icon = ""; + String billTypes = ""; + Function()? onTap; + + BottomSheetLogin({ + required String description, + required String icon, + required this.onTap, + this.billTypes = "", + }) { + _description = description; + _icon = icon; + this.billTypes = ""; + } + + String get description => _description; + + set description(String value) { + _description = value; + } + + String get icon => _icon; + + set icon(String value) { + _icon = value; + } + + static List options = [ + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + icon: "assets/icons/handIcon.png", + onTap: () { + Get.offAndToNamed(Routes.LOGIN_SCREEN); + }), + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + icon: "assets/icons/productIcon.png", + onTap: () { + Get.offAndToNamed(Routes.LOGIN_SCREEN); + }), + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + icon: "assets/icons/faqsIcon.png", + onTap: () { + Get.offAndToNamed(Routes.LOGIN_SCREEN); + }), + BottomSheetLogin( + description: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + icon: "assets/icons/ic_supportIcon.png", + onTap: () { + Get.back(); + showBottomSheet(); + }), + ]; + + /// Support Bottom Sheet Widget + static showBottomSheet() { + List supportBottomSheetList = [ + SupportBottomSheet( + image: "assets/icons/email_icon.png", + title: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + onTap: () { + // launch("mailto:info@mfsys.com.pk"); + }), + SupportBottomSheet( + image: "assets/icons/phone_icon.png", + title: TranslationKeys.makeTranslation(TranslationKeys.textLogin), + onTap: () { + // launch("tel:21213123123"); + }), + ]; + Get.bottomSheet( + Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey, width: 1), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), topRight: Radius.circular(10)), + ), + margin: EdgeInsets.symmetric(horizontal: 20), + child: Wrap( + children: [ + Padding( + padding: EdgeInsets.symmetric(vertical: 20, horizontal: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textLogin), + style: TextStyle( + color: AppColors.colorPrimary, + fontSize: 14, + fontWeight: FontWeight.w500), + ), + InkWell( + onTap: () { + Get.back(); + }, + child: SvgPicture.asset("assets/icons/ic_crossIcon.png")), + ], + ), + ), + Container( + padding: EdgeInsets.all(10), + child: GridView.builder( + itemCount: supportBottomSheetList.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 15, + mainAxisSpacing: 15, + ), + itemBuilder: (context, index) { + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + onTap: supportBottomSheetList[index].onTap, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 1), + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset("${supportBottomSheetList[index].image}"), + SizedBox(height: 20), + Center( + child: Text("Data"), + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ), + isScrollControlled: true, + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); + } +} + +class SupportBottomSheet { + String? image; + String? title; + Function()? onTap; + + SupportBottomSheet({this.image, this.title, this.onTap}); +} diff --git a/lib/app/modules/login/views/shared/expaanded_container.dart b/lib/app/modules/login/views/shared/expaanded_container.dart new file mode 100644 index 0000000..8f82785 --- /dev/null +++ b/lib/app/modules/login/views/shared/expaanded_container.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_custom_clippers/flutter_custom_clippers.dart'; +import '../../../../res/app_colors.dart'; + + +class ExpandedContainer extends StatelessWidget { + @override + Widget build(BuildContext context) { + return ClipPath( + clipper: MultipleRoundedCurveClipper(), + child: Container( + height: 200, + width: double.infinity, + color: AppColors.colorPrimaryLight, + child: Column( + children: [ + Text("data"), + Text("data"), + Text("data"), + Text("data"), + Text("data"), + Text("data"), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/login/views/shared/login_widget.dart b/lib/app/modules/login/views/shared/login_widget.dart new file mode 100644 index 0000000..2634a94 --- /dev/null +++ b/lib/app/modules/login/views/shared/login_widget.dart @@ -0,0 +1,116 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import '../../../../core/constants/translation_keys.dart'; +import '../../../../custom_widgets/custom_label.dart'; +import '../../../../res/app_colors.dart'; +import '../../../../res/app_dimensions.dart'; +import 'bottom_sheet_login.dart'; + +class LoginWidgets { + static Widget bottomTabs(BuildContext context, String text, String iconName, VoidCallback onPress, TextStyle textStyle) { + return SizedBox( + width: 95, + height: 75, + child: InkWell( + onTap: onPress, + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), // Set the border radius + ), + child: Container( + padding: const EdgeInsets.all(8), // Add padding as needed + decoration: BoxDecoration( + border: Border.all( + color: Colors.grey.withOpacity(0), + ), // Set border color + borderRadius: BorderRadius.circular(8), // Set border radius + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Image( + image: AssetImage(iconName), + width: 30, + height: 30, + ), + ), + const SizedBox(height: 3), + Expanded( + child: Center( + child: LabelText(text, style: textStyle), + ), + ), + ], + ), + ), + ), + ); + } + + static void showBottomSheet(BuildContext context, List options, Function onPress) { + + Get.bottomSheet( + isScrollControlled: true, + Container( + decoration: BoxDecoration(color: Colors.white, border: Border.all(color: AppColors.colorPrimary, width: 1), borderRadius: BorderRadius.only(topLeft: Radius.circular(AppDimensions.radiusCard), topRight: Radius.circular(AppDimensions.radiusCard))), + margin: EdgeInsets.only(left: AppDimensions.screenVerticalPadding, right: AppDimensions.screenVerticalPadding), + child: Wrap( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textLogin), style: Theme.of(context).textTheme.titleSmall), + InkWell( + onTap: () { + Navigator.pop(context); + }, + child: SvgPicture.asset("assets/icons/ic_crossIcon.png")), + ], + ), + ), + GridView.builder( + padding: const EdgeInsets.only(left: 15, right: 15, top: 0, bottom: 15), + itemCount: options.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + BottomSheetLogin bottomSheetLogin = options[index]; + return InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppDimensions.radiusCard), + ), + onTap: bottomSheetLogin.onTap, + child: Container( + padding: const EdgeInsets.all(8), + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: AppColors.colorPrimary, width: 1), borderRadius: BorderRadius.all(Radius.circular(AppDimensions.radiusCard))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image( + image: AssetImage(bottomSheetLogin.icon), + width: 50, + ), + const SizedBox(height: 20), + Center( + child: LabelText(bottomSheetLogin.description, labelColor: AppColors.colorTitle, fontSize: 18), + ), + ], + ))); + }, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + )), + ], + ), + ), + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(AppDimensions.radiusCard), topRight: Radius.circular(AppDimensions.radiusCard))), + ); + } +} diff --git a/lib/app/modules/login/views/shared/top_dialog.dart b/lib/app/modules/login/views/shared/top_dialog.dart new file mode 100644 index 0000000..20127bd --- /dev/null +++ b/lib/app/modules/login/views/shared/top_dialog.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; + +class TopDialog extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.transparent, + insetPadding: EdgeInsets.zero, + child: Stack( + alignment: Alignment.topCenter, + children: [ + Container( + margin: EdgeInsets.only(top: 60), + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Top Dialog Content', + style: TextStyle(fontSize: 20), + ), + SizedBox(height: 20), + ElevatedButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('Close'), + ), + ], + ), + ), + Positioned( + top: 0, + child: Container( + width: MediaQuery.of(context).size.width, + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: Colors.blue, + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + child: Text( + 'Top Dialog', + style: TextStyle(fontSize: 24, color: Colors.white), + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/app/modules/login_otp/bindings/o_t_p_screen_binding.dart b/lib/app/modules/login_otp/bindings/o_t_p_screen_binding.dart new file mode 100644 index 0000000..d1fd48e --- /dev/null +++ b/lib/app/modules/login_otp/bindings/o_t_p_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/o_t_p_screen_controller.dart'; + +class OTPScreenBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => OTPScreenController(), + ); + } +} diff --git a/lib/app/modules/login_otp/controllers/o_t_p_screen_controller.dart b/lib/app/modules/login_otp/controllers/o_t_p_screen_controller.dart new file mode 100644 index 0000000..31ed42f --- /dev/null +++ b/lib/app/modules/login_otp/controllers/o_t_p_screen_controller.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/AuthenticationRequest.dart'; +import '../../../models/LoginResponseModel.dart'; +import '../../../models/VerifyLoginOtpRequest.dart'; +import '../../../models/resend_ot_login_model.dart'; +import '../../../routes/app_pages.dart'; +import '../../user_profile/controllers/user_profile_controller.dart'; + + +class OTPScreenController extends GetxController { + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + TextEditingController pinPutController = TextEditingController(); + AuthenticationRequest firstStepData = AuthenticationRequest.empty(); + + RxBool isResend = false.obs; + bool loginUsingFingerPrint = false; + CountdownController countdownController = CountdownController(autoStart: true); + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + firstStepData = (arguments != null ? arguments[AppConstants.SIGN_UP_FIRST_STEP_DATA] ?? AuthenticationRequest.empty() : AuthenticationRequest.empty()); + loginUsingFingerPrint = arguments[1]; + pinPutController.text = ""; + } + + Future validatePinAndNavigate() async { + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + + VerifyLoginOtpRequest request = VerifyLoginOtpRequest( + email: firstStepData.email, + password: firstStepData.password, + obpPincode: pinPutController.text, + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + ); + + ServerResponse response = await repository.validateLoginPin(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + LoginResponseModel model = LoginResponseModel.fromJson(response.response); + + SessionCache.instance.userInfo.name = model.name.toString(); + SessionCache.instance.userInfo.cmpCuststatus = model.cmpCuststatus.toString(); + SessionCache.instance.userInfo.plcLocalcode = RequestConstants.plcLocacode.toString(); + SessionCache.instance.userInfo.cmpCustlastlogin = model.cmpCustlastlogin.toString(); + SessionCache.instance.userInfo.cmpCustcode = model.cmpCustcode.toString(); + SessionCache.instance.userInfo.jwtToken = model.jwtToken.toString(); + SessionCache.instance.userInfo.cmpUserId = firstStepData.email; + SessionCache.instance.userInfo.cmpCustpassword = firstStepData.password; + SessionCache.instance.userInfo.channelCode = RequestConstants.channelCode; + SessionCache.instance.userInfo.porOrgacode = RequestConstants.porOrgacode; + SessionCache.instance.userInfo.pctCstycode = RequestConstants.pctCstycode; + SessionCache.instance.userInfo.isKycVerified = model.isKycVerified; + SessionCache.instance.userInfo.isTranPinSet = model.isTranPinSet; + UserProfileController.cmpCustImage.value = model.cmpCustImage; + + if (!SessionCache.instance.userInfo.isTranPinSet) { + Get.offAndToNamed(Routes.CREATE_TRANSACTION_PIN); + return; + } + Get.offAndToNamed(Routes.DASHBOARD_SCREEN, /*arguments: {'loginUsingFingerPrint': loginUsingFingerPrint}*/); + } + + ///uco/changeTransactionPin + void resenOtp() async { + if (!isResend.value) { + Fluttertoast.showToast(msg: "Please wait for 1 minute"); + return; + } + + var responce = await repository.resentOtpLoginSignUp( + ResendOtpLoginModel( + userRole: 'USER', + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + email: firstStepData.email, + isOtpRequire: false, + phone: '', + pinType: 'C_TRANPIN', + username: firstStepData.email, + ), + ); + + if (responce.isError) { + Fluttertoast.showToast(msg: responce.errorMsg); + return; + } + + isResend.value = false; + + // countdownController.setOnRestart( + // () {}, + // ); + + countdownController.restart(); + + Fluttertoast.showToast(msg: "OTP send successfully"); + } + + void updateResend(bool send) { + isResend.value = send; + } +} + +String getTime(int totalSeconds) { + int minutes = totalSeconds ~/ 60; + int seconds = totalSeconds % 60; + return '$minutes : $seconds'; +} diff --git a/lib/app/modules/login_otp/views/o_t_p_screen_view.dart b/lib/app/modules/login_otp/views/o_t_p_screen_view.dart new file mode 100644 index 0000000..f2236b7 --- /dev/null +++ b/lib/app/modules/login_otp/views/o_t_p_screen_view.dart @@ -0,0 +1,186 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../controllers/o_t_p_screen_controller.dart'; + +class OTPScreenView extends GetView { + const OTPScreenView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + //title: TranslationKeys.makeTranslation(TranslationKeys.textUReceived), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + // PinCodeTextField( + // autoDisposeControllers: false, + // keyboardType: TextInputType.number, + // controller: controller.pinPutController, + // showCursor: true, + // autoDismissKeyboard: false, + // enablePinAutofill: true, + // length: 6, + // appContext: context, + // mainAxisAlignment: MainAxisAlignment.center, + // cursorColor: Colors.black.withOpacity(0.8), + // obscureText: false, + // animationType: AnimationType.fade, + // pinTheme: PinTheme( + // selectedColor: AppColors.colorGrey350, + // /*Colors.black.withOpacity(0.6),*/ + // inactiveColor: AppColors.colorGrey350, + // /*Colors.black.withOpacity(0.6),*/ + // activeColor: AppColors.colorGrey350, + // fieldOuterPadding: const EdgeInsets.all(5), + // shape: PinCodeFieldShape.box, + // borderRadius: BorderRadius.circular(5), + // fieldHeight: 40, + // fieldWidth: 43, + // activeFillColor: Colors.white, + // ), + // animationDuration: const Duration(milliseconds: 100), + // backgroundColor: Colors.transparent, + // enableActiveFill: false, + // onCompleted: (v) {}, + // onChanged: (value) {}, + // beforeTextPaste: (text) { + // return true; + // }, + // ), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + textInputAction: TextInputAction.done, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 20, width: 20), + const SizedBox(width: 5), + // TimerCountdown( + // spacerWidth: 5, + // enableDescriptions: false, + // format: CountDownTimerFormat.minutesSeconds, + // endTime: DateTime.now().add( + // const Duration(seconds: 8), + // ), + // onEnd: () { + // dp("Timer finished", ""); + // controller.updateResend(true); + // }, + // ), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle( + fontSize: 12, + ), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.resenOtp(); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/my_account/bindings/my_account_binding.dart b/lib/app/modules/my_account/bindings/my_account_binding.dart new file mode 100644 index 0000000..179ff62 --- /dev/null +++ b/lib/app/modules/my_account/bindings/my_account_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/my_account_controller.dart'; + +class MyAccountBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => MyAccountController(), + ); + } +} diff --git a/lib/app/modules/my_account/controllers/my_account_controller.dart b/lib/app/modules/my_account/controllers/my_account_controller.dart new file mode 100644 index 0000000..dc59180 --- /dev/null +++ b/lib/app/modules/my_account/controllers/my_account_controller.dart @@ -0,0 +1,84 @@ +import 'package:get/get.dart'; + +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/UserInfo.dart'; + + +class MyAccountController extends GetxController { + RxString fromAccountTitle = "".obs; + RxString fromAccountNumber = "".obs; + + RxInt selectedIndex = 0.obs; + RxString accountTitleText = "".obs; + RxString accountNumber = "".obs; + RxString accountIBNNumber = "".obs; + RxString branchCode = "".obs; + RxString accountOpeningDate = "".obs; + + /// show Selected indexBased String method + String getSelectedDisplayText() { + if (selectedIndex.value >= 0 && selectedIndex.value < dropdownItems.length) { + String fullText = dropdownItems[selectedIndex.value][0]; + return fullText.length > 20 ? fullText.substring(0, 20) + '...' : fullText; + } else { + return TranslationKeys.makeTranslation(TranslationKeys.textNoSelect); + } + } + + RxList totalAccount = RxList.empty(); + RxList dropdownItems = RxList.empty(); + RxList showAccountDetails = RxList.empty(); + UserInfo userInfo = UserInfo(); + + @override + void onInit() { + super.onInit(); + + DepositAccount selectAccount = DepositAccount(); + if (SessionCache.instance.depositAccountList.value.isNotEmpty) { + selectAccount = SessionCache.instance.depositAccountList.value[0]; + } + fromAccountTitle.value = selectAccount.mbmBkmstitle; + fromAccountNumber.value = selectAccount.mbmBkmsnumber; + accountTitleText.value = selectAccount.mbmBkmstitle; + accountNumber.value = selectAccount.mbmBkmsnumber; + //branchCode.value = selectAccount.plcLocadesc; + accountOpeningDate.value = selectAccount.mbmBkmsopendate; + + /// For Deposit Account List + for (int i = 0; i < SessionCache.instance.depositAccountList.value.length; i++) { + totalAccount.add(SessionCache.instance.depositAccountList.value[i].mbmBkmsnumber); + } + + /// For Loan Account List + // for (int i = 0; i < SessionCache.instance.loanAccountList.value.length; i++) { + // totalAccount.add(SessionCache.instance.loanAccountList.value[i].mbmBkmsnumber); + // } + + /// Assign to DropDown Items List + dropdownItems.assignAll(totalAccount); + print("The Total accounts lenght is ================== ${totalAccount}"); + + // for (int i = 0; i < SessionCache.instance.loanAccountList.value.length; i++) { + // showAccountDetails.add(SessionCache.instance.loanAccountList.value[i].mbmBkmstitle); + // showAccountDetails.add(SessionCache.instance.loanAccountList.value[i].plcLocadesc); + // } + for (int i = 0; i < SessionCache.instance.depositAccountList.value.length; i++) { + showAccountDetails.add(SessionCache.instance.depositAccountList.value[i].mbmBkmstitle); + //showAccountDetails.add(SessionCache.instance.depositAccountList.value[i].plcLocadesc); + } + } + + void setAccountDetails() { + accountTitleText.value = SessionCache.instance.depositAccountList.value[selectedIndex.value].mbmBkmstitle; + accountNumber.value = SessionCache.instance.depositAccountList.value[selectedIndex.value].mbmBkmsnumber; + accountIBNNumber.value = SessionCache.instance.depositAccountList.value[selectedIndex.value].mbmBkmsnumber; + //branchCode.value = SessionCache.instance.depositAccountList.value[selectedIndex.value].plcLocadesc; + // branchCode.value = SessionCache.instance.loanAccountList.value[selectedIndex.value].mbmBkmstitle; + // branchCode.value = SessionCache.instance.loanAccountList.value[selectedIndex.value].mbmBkmsnumber; + // branchCode.value = SessionCache.instance.loanAccountList.value[selectedIndex.value].mbmBkmsnumber; + // branchCode.value = SessionCache.instance.loanAccountList.value[selectedIndex.value].plcLocadesc; + } +} diff --git a/lib/app/modules/my_account/views/my_account_view.dart b/lib/app/modules/my_account/views/my_account_view.dart new file mode 100644 index 0000000..1ab99c7 --- /dev/null +++ b/lib/app/modules/my_account/views/my_account_view.dart @@ -0,0 +1,301 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +// import 'package:share_plus/share_plus.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/bottom_sheet.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../res/app_colors.dart'; +import '../../app_setting/controllers/app_setting_controller.dart'; +import '../controllers/my_account_controller.dart'; + +class MyAccountView extends GetView { + const MyAccountView({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: + TranslationKeys.makeTranslation(TranslationKeys.textMyAccountTitle), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Obx( + () { + return SingleChildScrollView( + child: Stack( + children: [ + Container( + height: 150, + decoration: BoxDecoration( + color: + AppColors.colorButton.withOpacity(0.98), + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(40)))), + Column( + children: [ + InkWell( + onTap: () { + showBottomSheet(context, controller); + }, + child: Card( + surfaceTintColor: Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + margin: const EdgeInsets.only( + left: 10, right: 10, top: 15, bottom: 10), + color: Colors.white, + elevation: 5.0, + child: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColors.colorPrimary, + border: Border.all(color: AppColors.white), + borderRadius: BorderRadius.circular(15.0)), + child: ListTile( + title: Text(controller.fromAccountTitle.value, + style: Theme.of(context) + .textTheme + .titleSmall + ?.copyWith(color: AppColors.white)), + subtitle: Padding( + padding: const EdgeInsets.only(top: 5.0), + child: Text(controller.fromAccountNumber.value, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: AppColors.white)), + ), + trailing: const Icon( + Icons.keyboard_arrow_down_sharp, + color: AppColors.white, + ), + ), + ), + ), + ), + const SizedBox( + height: 10, + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15.0, + ), + child: Card( + surfaceTintColor: Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + elevation: 5.0, + child: Stack( + children: [ + GestureDetector( + onTap: () { + String message = + 'Account Title: ${controller.accountTitleText.value}\nAccount Number: ${controller.accountNumber.value}\nBranch Code: ${controller.branchCode.value}'; + String subject = 'Subject for sharing'; + // Share.share(message, subject: subject); + }, + child: Align( + alignment: AppSettingController.isRTL.value + ? Alignment.topLeft + : Alignment.topRight, + child: const Padding( + padding: EdgeInsets.all(10.0), + child: CircleAvatar( + maxRadius: 10, + minRadius: 10, + backgroundColor: AppColors.transparent, + child: Icon(Icons.share, + size: 15, color: AppColors.colorPrimary), + ), + ), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 10), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textMyAccountAccountTitle), + style: + Theme.of(context).textTheme.bodyMedium, + ), + ), + const SizedBox(height: 5), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, bottom: 10), + child: Text( + controller.accountTitleText.value, + style: + Theme.of(context).textTheme.titleSmall, + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 10), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textMyAccountAccountNumber), + style: + Theme.of(context).textTheme.bodyMedium, + ), + ), + Row( + children: [ + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 10), + child: Text( + controller.accountNumber.value, + style: Theme.of(context) + .textTheme + .titleSmall, + ), + ), + const SizedBox(width: 20), + ], + ), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.only( + left: 15.0, right: 15.0, top: 10), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textMyAccountBranchCode), + style: Theme.of(context) + .textTheme + .bodyMedium), + ), + Padding( + padding: const EdgeInsets.only( + left: 15.0, + right: 15.0, + top: 10, + bottom: 10), + child: Text(controller.branchCode.value, + style: Theme.of(context) + .textTheme + .titleSmall), + ), + ], + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15.0, vertical: 15.0), + child: Card( + surfaceTintColor: Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + elevation: 5.0, + child: SizedBox( + height: 60, + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + padding: const EdgeInsets.only(left: 15.0, right: 15), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textMyAccountAccountOpeningDate), + style: + Theme.of(context).textTheme.bodyMedium), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: Text(controller.accountOpeningDate.value, + style: + Theme.of(context).textTheme.titleSmall), + ) + ], + ), + ), + ), + ), + ], + ), + ], + ), + ); + }, + ), + ); + } + + static void showBottomSheet( + BuildContext context, MyAccountController controller) { + List options = []; + for (int i = 0; + i < SessionCache.instance.depositAccountList.value.length; + i++) { + DepositAccount depositAccount = + SessionCache.instance.depositAccountList.value[i]; + options.add(OptionData.withData(depositAccount.mbmBkmstitle, + depositAccount.mbmBkmsnumber, depositAccount)); + } + // for (int i = 0; i < SessionCache.instance.loanAccountList.length; i++) { + // LoanAccount loanAccount = SessionCache.instance.loanAccountList[i]; + // options.add(OptionData.withData( + // loanAccount.mbmBkmstitle, loanAccount.mbmBkmsnumber, loanAccount)); + // } + + Get.bottomSheet( + Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AppColors.colorGrey800, width: 1), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(30), topRight: Radius.circular(30))), + margin: const EdgeInsets.only(left: 20, right: 20), + child: DialogDesign(options, (selectedOption) { + if (selectedOption.dataObject is DepositAccount) { + DepositAccount selectAccount = + selectedOption.dataObject as DepositAccount; + controller.fromAccountTitle.value = selectAccount.mbmBkmstitle; + controller.fromAccountNumber.value = selectAccount.mbmBkmsnumber; + controller.accountTitleText.value = selectAccount.mbmBkmstitle; + controller.accountNumber.value = selectAccount.mbmBkmsnumber; + // controller.branchCode.value = selectAccount.plcLocadesc; + controller.accountOpeningDate.value = selectAccount.mbmBkmsopendate; + } + // if (selectedOption.dataObject is LoanAccount) { + // LoanAccount selectAccount = + // selectedOption.dataObject as LoanAccount; + // controller.fromAccountTitle.value = selectAccount.mbmBkmstitle; + // controller.fromAccountNumber.value = selectAccount.mbmBkmsnumber; + // controller.accountTitleText.value = selectAccount.mbmBkmstitle; + // controller.accountNumber.value = selectAccount.mbmBkmsnumber; + // controller.branchCode.value = selectAccount.plcLocadesc; + // controller.accountOpeningDate.value = selectAccount.mbmBkmsopendate; + // } + }), + ), + backgroundColor: Colors.transparent, + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); + } +} diff --git a/lib/app/modules/new_beneficiary/bindings/new_beneficiary_binding.dart b/lib/app/modules/new_beneficiary/bindings/new_beneficiary_binding.dart new file mode 100644 index 0000000..6692c31 --- /dev/null +++ b/lib/app/modules/new_beneficiary/bindings/new_beneficiary_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/new_beneficiary_controller.dart'; + +class NewBeneficiaryBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => NewBeneficiaryController(), + ); + } +} diff --git a/lib/app/modules/new_beneficiary/controllers/new_beneficiary_controller.dart b/lib/app/modules/new_beneficiary/controllers/new_beneficiary_controller.dart new file mode 100644 index 0000000..1693b4f --- /dev/null +++ b/lib/app/modules/new_beneficiary/controllers/new_beneficiary_controller.dart @@ -0,0 +1,270 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +// import 'package:flutter_contacts/flutter_contacts.dart'; +import 'package:get/get.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/Fields/field_validations.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/AccountInquiryResponseModel.dart'; +import '../../../models/ExchangeRate.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; + +class NewBeneficiaryController extends GetxController { + String OPTION_PHONE = "01"; + String OPTION_EMAIL = "02"; + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + + RxList allRecipientDetailOptions = RxList.empty(); + Rx selectedRecipientDetailOption = DropDown.empty().obs; + + String className = ""; + late InputField selectRecipientDetailField; + late InputField identityPhoneNumberField; + late InputField identityEmailField; + late InputField recipientCardNameField; + late InputField accountNumberField; + late InputField nickNameField; + + // late InputField emailIDField; + // late InputField phoneNumberField; + + String receiverAccountNumber = ""; + String receiverAccountTitle = ""; + RxString currencySymbol = "".obs; + // Contact? selectedContact; + ExchangeRate? selectedExchangeRate; + + @override + void onInit() { + super.onInit(); + allRecipientDetailOptions.value = [ + DropDown(OPTION_PHONE, TranslationKeys.makeTranslation(TranslationKeys.textPhoneNumber)), + DropDown(OPTION_EMAIL, TranslationKeys.makeTranslation(TranslationKeys.textEmail)), + ]; + } + + /// Validate Method + bool validate() { + bool isValid = FieldValidation.validateAll([ + // accountTitleField, + // accountNumberField, + nickNameField, + selectRecipientDetailField + // identityEmailField, + // accountNumberField, + // emailIDField, + // phoneNumberField, + ]); + + if (selectedRecipientDetailOption.value.id == OPTION_PHONE) { + isValid = FieldValidation.validateAll([identityPhoneNumberField]); + } else if (selectedRecipientDetailOption.value.id == OPTION_EMAIL) { + isValid = FieldValidation.validateAll([identityEmailField]); + } + return isValid; + } + + /// Request Method + Future addToNewBeneficiary({navigate = true}) async { + if (!validate()) { + Toasty.error("Please input and then proceed"); + return; + } + // BeneficiaryAccountModel beneficiaryAccountModel = BeneficiaryAccountModel( + // porOrgacode: SessionCache.instance.userInfo.porOrgacode, + // email: SessionCache.instance.userInfo.cmpUserId, + // pcrCurrcode: selectedExchangeRate!.pcrCurrcode, + // pcrCurrdesc: selectedExchangeRate!.pcrCurrdesc, + // pcrCurrshort: selectedExchangeRate!.pcrCurrshort, + // mbmBkmstitleRef: receiverAccountTitle, + // mbmBkmsnumberRef: receiverAccountNumber, + // refPhoneNumber: "", + // refEmail: "", + // refNickName: nickNameField.getCustomText(), + // ); + // ServerResponse response = await repository.addNewBeneficiary(beneficiaryAccountModel); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + CustomDialog.showSuccessDialog( + description: "You are successfully add new Beneficiary", + onTapPositive: () { + Get.back(result: true); + }); + clearNewBeneficiaryControllers(); + } + + void updateRecipientDetail(DropDown? item) { + selectedRecipientDetailOption.value = item!; + } + + Future selectContact() async { + dynamic result = await Get.toNamed(Routes.CONTACTS_SCREEN); + + // if ((result != null && result[AppConstants.SELECTED_CONTACT] != null)) { + // selectedContact = result[AppConstants.SELECTED_CONTACT]; + // identityPhoneNumberField.setText(AppUtils.formatPhoneNumber(selectedContact!.phones.first.number) /*"${selectedContact!.displayName} (${AppUtils.formatPhoneNumber(selectedContact!.phones.first.number + ")")}"*/); + // } + } + + // void scanQr() async { + // Get.put(QrSettingController()); + // var scanResult = await Get.to(() => const QrScanScreen()); + // var resultJson = jsonDecode(scanResult); + // var accNumber = resultJson["phoneNumber"]; + // identityPhoneNumberField.setText(accNumber); + // verifyAccountAgainstIt(); + // } + + Future verifyAccountAgainstIt() async { + String valua = selectedRecipientDetailOption.value.id == OPTION_PHONE ? identityPhoneNumberField.getCustomText() : (selectedRecipientDetailOption.value.id == OPTION_EMAIL ? identityEmailField.getCustomText() : ""); + bool isValid = true; + if (selectedRecipientDetailOption.value.id == OPTION_PHONE) { + isValid = FieldValidation.validateAll([identityPhoneNumberField]); + } else if (selectedRecipientDetailOption.value.id == OPTION_EMAIL) { + isValid = FieldValidation.validateAll([identityEmailField]); + } + if (!isValid) { + Toasty.error("Please input and then proceed"); + return; + } + + ServerResponse response = await repository.fetchAccountInquiry(selectedRecipientDetailOption.value.id, valua); + + if (response.isError) { + if (selectedRecipientDetailOption.value.id == OPTION_PHONE) { + identityPhoneNumberField.setError(response.errorMsg); + } else { + identityEmailField.setError(response.errorMsg); + } + return; + } + List responseData = response.response ?? []; + List accountInquiryList; + accountInquiryList = AccountInquiryResponseModel.fromList(responseData); + + accountsDialog(accountInquiryList); + // AccountInquiryResponseModel transactionSubmitRequestModel = AccountInquiryResponseModel.fromMap(((response.response ?? {}) as Map).map((key, value) => MapEntry(key.toString(), value))); + } + + void updateSelectedCurrency(/*DropDown? item*/ AccountInquiryResponseModel model) { + print("************************model>> $model"); + + for (int i = 0; i < SessionCache.instance.exchangeRateList.length; i++) { + print("************************elementAt(i).pcrCurrcode>> ${SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrcode}"); + if (SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrcode == model.pcrCurrcode) { + currencySymbol.value = SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrshort; + selectedExchangeRate = SessionCache.instance.exchangeRateList.elementAt(i); + // exchangeRateField.setText(selectedExchangeRate!.perEratrateact.toString()); + break; + } + } + } + + void accountsDialog(List accountInquiryList) { + if (accountInquiryList.length == 1) { + receiverAccountTitle = accountInquiryList.first.mbmBkmstitle; + receiverAccountNumber = accountInquiryList.first.mbmBkmsnumber; + recipientCardNameField.setText(receiverAccountTitle); + updateSelectedCurrency(accountInquiryList.first); + return; + } + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textSelectAccount), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + ListView.separated( + shrinkWrap: true, + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + receiverAccountTitle = accountInquiryList[index].mbmBkmstitle; + receiverAccountNumber = accountInquiryList[index].mbmBkmsnumber; + recipientCardNameField.setText(receiverAccountTitle); + updateSelectedCurrency(accountInquiryList[index]); + Get.back(); + }, + child: Column(children: [ + Container( + height: 40, + width: double.infinity, + decoration: const BoxDecoration( + color: AppColors.colorGrey100, + borderRadius: BorderRadius.all(Radius.circular(8.0)), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("${accountInquiryList[index].mbmBkmstitle} (${accountInquiryList[index].pcrCurrshort})", style: Theme.of(context).textTheme.titleSmall), + Text(accountInquiryList[index].mbmBkmsnumber, style: Theme.of(context).textTheme.titleSmall), + ], + ), + ), + ), + ]), + ); + }, + separatorBuilder: (BuildContext context, int index) { + return const Padding(padding: EdgeInsets.symmetric(vertical: 5)); + }, + itemCount: accountInquiryList.length), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + /// Clear Controllers Method + void clearNewBeneficiaryControllers() { + // accountTitleField.clear(); + nickNameField.clear(); + selectRecipientDetailField.clear(); + identityPhoneNumberField.clear(); + recipientCardNameField.clear(); + identityEmailField.clear(); + // accountNumberField.clear(); + // emailIDField.clear(); + // phoneNumberField.clear(); + } +} diff --git a/lib/app/modules/new_beneficiary/views/new_beneficiary_view.dart b/lib/app/modules/new_beneficiary/views/new_beneficiary_view.dart new file mode 100644 index 0000000..df4b97a --- /dev/null +++ b/lib/app/modules/new_beneficiary/views/new_beneficiary_view.dart @@ -0,0 +1,238 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/new_beneficiary_controller.dart'; + +class NewBeneficiaryView extends GetView { + const NewBeneficiaryView({Key? key, this.showAppBar = true}) : super(key: key); + final bool showAppBar; + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + controller.className = className; + return Scaffold( + appBar: showAppBar + ? DashBoardAppBar( + title: "New Beneficiary", + onBackButtonPressed: () { + Get.back(); + controller.clearNewBeneficiaryControllers(); + }, + ) + : null, + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: SizedBox( + width: double.infinity, + child: CustomButton( + buttonColor: AppColors.colorButton, + onPressed: () { + controller.addToNewBeneficiary(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textAddToBeneficiary), + buttonPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + icon: const Icon(Icons.add, size: 18), + iconPadding: const EdgeInsets.only(right: 10.0), + ), + ), + ), + ], + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: Obx(() { + return Column( + children: [ + // controller.accountTitleField = InputField( + // refKey: FormFieldConstants.instance().getFormKey("${className}accountTitleField"), + // controller: FormFieldConstants.instance().getController("${className}accountTitleField"), + // labelText: "Account Title", + // hintText: "Enter your account name", + // ), + // controller.accountNumberField = InputField( + // refKey: FormFieldConstants.instance().getFormKey("${className}accountNumberField"), + // controller: FormFieldConstants.instance().getController("${className}accountNumberField"), + // labelText: "Account Number", + // hintText: "Enter your account number", + // ), + controller.selectRecipientDetailField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}selectRecipientDetailField"), + controller: FormFieldConstants.instance().getController("${className}selectRecipientDetailField"), + labelText: "Recipient Detail", + isDropDown: true, + hintText: "Select recipient detail", + dropDownType: DropDownType.SPECIAL, + items: controller.allRecipientDetailOptions, + onItemSelected: (item) { + controller.updateRecipientDetail(item); + }, + ), + Column( + children: [ + Visibility( + visible: controller.selectedRecipientDetailOption.value.id == controller.OPTION_PHONE, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 8, + child: controller.identityPhoneNumberField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + keyboardType: TextInputType.phone, + refKey: FormFieldConstants.instance().getFormKey("${className}identityPhoneNumberField"), + controller: FormFieldConstants.instance().getController("${className}identityPhoneNumberField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textPhoneNumber), + hintText: "Select phone number", + onChanged: (val) { + controller.recipientCardNameField.clear(); + }, + suffixIcon: SizedBox( + width: 70, + child: Row( + children: [ + GestureDetector( + onTap: () { + // controller.scanQr(); + }, + child: const Icon(Icons.qr_code, size: 25, color: AppColors.colorPrimary)), + const SizedBox( + width: 8, + ), + InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + onTap: () { + controller.selectContact(); + }, + child: Padding( + padding: const EdgeInsets.all(5.0), + child: SvgPicture.asset(AppAssets.ic_select_contact, height: 25, width: 25), + ), + ), + ], + ), + ), + // readOnly: true, + // showCursor: false, + onClick: () { + // controller.selectContact(); + }, + )), + const SizedBox(width: 10), + Expanded( + flex: 2, + child: Column( + children: [ + const SizedBox(height: 35), + CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.verifyAccountAgainstIt(); + }, + textStyle: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w500, color: Colors.white), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + buttonColor: AppColors.colorButton), + ], + ), + ) + ], + ), + ), + Visibility( + visible: controller.selectedRecipientDetailOption.value.id == controller.OPTION_EMAIL, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 8, + child: controller.identityEmailField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + textInputAction: TextInputAction.done, + keyboardType: TextInputType.emailAddress, + refKey: FormFieldConstants.instance().getFormKey("${className}identityEmailField"), + controller: FormFieldConstants.instance().getController("${className}identityEmailField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textEmail), + hintText: "Enter your email", + onChanged: (val) { + controller.recipientCardNameField.clear(); + }, + // readOnly: true, + // showCursor: false, + onClick: () { + // controller.selectContact(); + }, + )), + const SizedBox(width: 10), + Expanded( + flex: 2, + child: Column( + children: [ + const SizedBox(height: 35), + CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.verifyAccountAgainstIt(); + }, + textStyle: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w500, color: Colors.white), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + buttonColor: AppColors.colorButton), + ], + ), + ) + ], + ), + ), + ], + ), + controller.recipientCardNameField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}recipientCardNameField"), + controller: FormFieldConstants.instance().getController("${className}recipientCardNameField"), + labelText: TranslationKeys.makeTranslation("Account Title"), + hintText: "Account title", + readOnly: true, + showCursor: false, + ), + controller.nickNameField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}nickNameField"), + controller: FormFieldConstants.instance().getController("${className}nickNameField"), + labelText: "Nick Name", + hintText: "Enter your nick name", + ), + // controller.emailIDField = InputField( + // refKey: FormFieldConstants.instance().getFormKey("${className}emailIDField"), + // controller: FormFieldConstants.instance().getController("${className}emailIDField"), + // labelText: "Email ID", + // hintText: "Enter your email id", + // ), + // controller.phoneNumberField = InputField( + // refKey: FormFieldConstants.instance().getFormKey("${className}phoneNumberField"), + // controller: FormFieldConstants.instance().getController("${className}phoneNumberField"), + // labelText: "Phone Number", + // keyboardType: TextInputType.number, + // hintText: "Enter your phone number", + // ), + ], + ); + }), + ), + ), + ); + } +} diff --git a/lib/app/modules/new_beneficiary_otp/bindings/new_beneficiary_otp_binding.dart b/lib/app/modules/new_beneficiary_otp/bindings/new_beneficiary_otp_binding.dart new file mode 100644 index 0000000..40ba4a0 --- /dev/null +++ b/lib/app/modules/new_beneficiary_otp/bindings/new_beneficiary_otp_binding.dart @@ -0,0 +1,13 @@ +import 'package:get/get.dart'; + +import '../controllers/new_beneficiary_otp_controller.dart'; + + +class NewBeneficiaryOtpBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => NewBeneficiaryOtpController(), + ); + } +} diff --git a/lib/app/modules/new_beneficiary_otp/controllers/new_beneficiary_otp_controller.dart b/lib/app/modules/new_beneficiary_otp/controllers/new_beneficiary_otp_controller.dart new file mode 100644 index 0000000..cb73a0b --- /dev/null +++ b/lib/app/modules/new_beneficiary_otp/controllers/new_beneficiary_otp_controller.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/TransactionSubmitRequestModel.dart'; +import '../../../models/resend_otp_usend.dart'; +import '../../../routes/app_pages.dart'; + +class NewBeneficiaryOtpController extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + + TextEditingController pinPutController = TextEditingController(); + TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel.empty(); + String exchangeRate = ""; + + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + + @override + Future onReady() async { + super.onReady(); + // var arguments = Get.arguments; + // transactionSubmitRequestModel = (arguments != null ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? TransactionSubmitRequestModel.empty() : TransactionSubmitRequestModel.empty()); + // exchangeRate = (arguments != null ? arguments[AppConstants.EXCHANGE_RATE] ?? "" : ""); + } + + Future validatePinAndNavigate() async { + // + + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + + transactionSubmitRequestModel.pinType = "TRAN"; + + transactionSubmitRequestModel.obpPincode = pinPutController.text; + + CustomDialog.showSuccessDialog( + description: "You have successfully added the Beneficiary.", + onTapPositive: () { + Get.offAndToNamed(Routes.BENEFICIARY_MANAGEMENT); + }, + title: "Beneficiary Added"); + } + + void resenOtp() async { + // + + if (!isResend.value) { + Fluttertoast.showToast(msg: "Please wait for 1 minute"); + return; + } + + var responce = await repository.resendOtpUsend(ResendOtpUsendModel( + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + email: SessionCache.instance.userInfo.cmpUserId, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + isOtpRequired: false, + pctCstycode: SessionCache.instance.userInfo.pctCstycode, + pinType: 'C_TRANPIN', + )); + + if (responce.isError) { + Fluttertoast.showToast(msg: responce.errorMsg); + return; + } + + isResend.value = false; + + countdownController.restart(); + + Fluttertoast.showToast(msg: "OTP successfully send to your email address"); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/new_beneficiary_otp/views/new_beneficiary_otp_view.dart b/lib/app/modules/new_beneficiary_otp/views/new_beneficiary_otp_view.dart new file mode 100644 index 0000000..21ce47e --- /dev/null +++ b/lib/app/modules/new_beneficiary_otp/views/new_beneficiary_otp_view.dart @@ -0,0 +1,139 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../../u_send/controllers/u_send_controller.dart'; +import '../controllers/new_beneficiary_otp_controller.dart'; + +class NewBeneficiaryOtpView extends GetView { + const NewBeneficiaryOtpView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + textInputAction: TextInputAction.done, + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle( + fontSize: 12, + ), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + Get.find().sendTransaction(navigate: false); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/notifications/bindings/notifications_binding.dart b/lib/app/modules/notifications/bindings/notifications_binding.dart new file mode 100644 index 0000000..33ccb22 --- /dev/null +++ b/lib/app/modules/notifications/bindings/notifications_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/notifications_controller.dart'; + +class NotificationsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => NotificationsController(), + ); + } +} diff --git a/lib/app/modules/notifications/controllers/notifications_controller.dart b/lib/app/modules/notifications/controllers/notifications_controller.dart new file mode 100644 index 0000000..5b69a03 --- /dev/null +++ b/lib/app/modules/notifications/controllers/notifications_controller.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_custom_clippers/flutter_custom_clippers.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dialog.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/date_picker.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/res/app_dimensions.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../models/DepositAccountResponse.dart'; + +class NotificationsController extends GetxController { + RxString selectedAccountNumber = '123456789'.obs; + RxBool isExpanded = false.obs; + bool isCredit = false; + + RxList allDepositAccounts = RxList.empty(); + + Rx selectedDepositAccount = DepositAccount.empty().obs; + + List accountNumberList = ["123456789"]; + + List notificationList = [ + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + NotificationDetails( + description: + "Rs. 1320.0 sent to SHAHZAD AHMED with easypaisa account....", + dateTime: "12 Apr 2023 07:57:28 am"), + ]; + + late InputField depositAccountField; + + @override + void onInit() { + // + + // for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + // DepositAccount depositAccount = + // SessionCache.instance.depositAccountList.elementAt(i); + // + // allDepositAccounts.add( + // DropDown( + // i.toString(), + // "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", + // depositAccount), + // ); + // } + + // selectedDepositAccount.value = allDepositAccounts.first.data; + + super.onInit(); + } + + void updateSelectedDeposit(DropDown item) { + selectedDepositAccount.value = item.data as DepositAccount; + } + + void showDialogFunction(BuildContext context) { + CustomDialog.showInfoDialog( + title: TranslationKeys.makeTranslation( + TranslationKeys.textNotificationDetails), + description: TranslationKeys.makeTranslation( + TranslationKeys.textNotificationDetailsContent), + onTapPositive: () { + Navigator.of(context, rootNavigator: true).pop(); + }); + } + + void showDateRangePicker() async { + var date = await DatePicker.showRangeDatePicker(); + dp("Date is ", date); + } +} + +class NotificationDetails { + String description; + String dateTime; + + NotificationDetails({required this.description, required this.dateTime}); +} diff --git a/lib/app/modules/notifications/views/notifications_view.dart b/lib/app/modules/notifications/views/notifications_view.dart new file mode 100644 index 0000000..821a1ce --- /dev/null +++ b/lib/app/modules/notifications/views/notifications_view.dart @@ -0,0 +1,315 @@ +import 'package:dropdown_button2/dropdown_button2.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../controllers/notifications_controller.dart'; + +class NotificationsView extends GetView { + const NotificationsView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: + TranslationKeys.makeTranslation(TranslationKeys.textNotifications), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Stack( + children: [ + Container( + height: 25, + decoration: const BoxDecoration( + color: AppColors.colorPrimary, + )), + GestureDetector( + onTap: () { + controller.showDateRangePicker(); + }, + child: Padding( + padding: const EdgeInsets.all(0.0), + child: Card( + surfaceTintColor: Colors.white, + margin: const EdgeInsets.symmetric( + horizontal: 15, vertical: 10), + elevation: 5.0, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + //mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Align( + alignment: Alignment.center, + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textFilter), + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith( + fontSize: 14, + fontWeight: FontWeight.w400), + ), + ), + ), + Image.asset( + AppAssets.ic_sort, + height: 25, + ), + const SizedBox( + width: 10, + ) + ], + ), + ), + ), + ), + ), + ], + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), + // child: Align( + // alignment: Alignment.centerLeft, + // child: Text( + // TranslationKeys.makeTranslation( + // TranslationKeys.textPleaseSelectAccount), + // style: Theme.of(context) + // .textTheme + // .titleSmall + // ?.copyWith(color: AppColors.titleColor)), + // ), + // ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + child: controller.depositAccountField = InputField( + refKey: FormFieldConstants.instance() + .getFormKey("${className}depositAccountField"), + controller: FormFieldConstants.instance() + .getController("${className}depositAccountField"), + labelText: "Select From Account", + suffixIcon: const Icon(Icons.keyboard_arrow_down, size: 25), + isDropDown: true, + hintText: "Select from account", + dropDownType: DropDownType.SPECIAL, + isTopMarginRequired: false, + items: controller.allDepositAccounts, + onItemSelected: (item) { + controller.updateSelectedDeposit(item!); + }, + ), + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + // child: SizedBox( + // height: 35, + // child: InkWell( + // onTap: () {}, + // child: DropdownButtonHideUnderline( + // child: ButtonTheme( + // alignedDropdown: true, + // child: DropdownButton2( + // isExpanded: true, + // hint: Row( + // mainAxisAlignment: MainAxisAlignment.spaceAround, + // children: [ + // const Icon( + // Icons.list, + // size: 20, + // color: Colors.yellow, + // ), + // const SizedBox( + // width: 4, + // ), + // Text(controller.selectedAccountNumber.value), + // ], + // ), + // items: controller.accountNumberList + // .toSet() + // .map((String item) => DropdownMenuItem( + // value: item, + // child: Text( + // item, + // style: Theme.of(context) + // .textTheme + // .bodyMedium + // ?.copyWith( + // fontSize: 12, + // fontWeight: FontWeight.w400, + // color: AppColors.colorText), + // overflow: TextOverflow.ellipsis, + // ), + // )) + // .toList(), + // value: controller.selectedAccountNumber.value, + // onChanged: (String? newValue) { + // if (newValue != null) { + // controller.selectedAccountNumber.value = newValue; + // } + // }, + // buttonStyleData: ButtonStyleData( + // height: 41, + // padding: const EdgeInsets.symmetric( + // horizontal: 10, vertical: 5), + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(50), + // border: Border.all( + // color: AppColors.colorGrey350, + // ), + // color: AppColors.colorSecondary, + // ), + // elevation: 0, + // ), + // iconStyleData: IconStyleData( + // icon: SvgPicture.asset( + // AppAssets.ic_arrow_down, + // height: 15, + // width: 15, + // ), + // iconEnabledColor: AppColors.colorText, + // iconDisabledColor: AppColors.colorText, + // ), + // dropdownStyleData: DropdownStyleData( + // maxHeight: 150, + // width: 320, + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(7), + // color: AppColors.colorSecondary, + // ), + // offset: const Offset(-2, 0), + // scrollbarTheme: ScrollbarThemeData( + // radius: const Radius.circular(40), + // thickness: MaterialStateProperty.all(5), + // thumbVisibility: + // MaterialStateProperty.all(true), + // ), + // ), + // menuItemStyleData: const MenuItemStyleData( + // height: 30, + // padding: EdgeInsets.only(left: 14, right: 14), + // ), + // ), + // ), + // ), + // ), + // ), + // ), + Expanded( + flex: 4, + child: controller.notificationList.isEmpty + ? const Center( + child: Text("No notifications are found"), + ) + : ListView.builder( + itemCount: controller.notificationList.length, + itemBuilder: (context, index) { + return InkWell( + onTap: () { + controller.showDialogFunction(context); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15, vertical: 0), + child: Card( + elevation: 2.0, + color: AppColors.white, + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Column( + children: [ + Row( + children: [ + Text( + controller + .notificationList[0].description, + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontSize: 10, + fontWeight: FontWeight.w400), + ) + ], + ), + const SizedBox(height: 5), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + controller + .notificationList[0].dateTime, + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + fontSize: 10, + fontWeight: FontWeight.w400), + ), + ), + //const Expanded(child: SizedBox()), + Expanded( + child: Row( + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + Container( + height: 13, + width: 0.5, + color: AppColors.colorGrey800, + ), + const SizedBox( + width: 10, + ), + Text( + "Read more", + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith( + color: AppColors + .colorPrimary, + fontSize: 10, + fontWeight: + FontWeight.w400), + ), + ], + ), + ), + ], + ), + ], + ), + ), + ), + ), + ); + }, + ), + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/password_change/bindings/password_change_binding.dart b/lib/app/modules/password_change/bindings/password_change_binding.dart new file mode 100644 index 0000000..ebea3a3 --- /dev/null +++ b/lib/app/modules/password_change/bindings/password_change_binding.dart @@ -0,0 +1,11 @@ +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/modules/password_change/controllers/password_change_controller.dart'; + +class ChangePasswordBindings extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ChangePasswordController(), + ); + } +} diff --git a/lib/app/modules/password_change/controllers/password_change_controller.dart b/lib/app/modules/password_change/controllers/password_change_controller.dart new file mode 100644 index 0000000..73898b6 --- /dev/null +++ b/lib/app/modules/password_change/controllers/password_change_controller.dart @@ -0,0 +1,79 @@ +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/utils/SessionCache.dart'; +import 'package:uco_mobile_poc/app/core/utils/app_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/models/chanange_password_params.dart'; + +import '../../../core/config/server_response.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../custom_widgets/Fields/field_validations.dart'; +import '../../../custom_widgets/custom_dialog.dart'; +import '../../../custom_widgets/custom_toasty.dart'; + +class ChangePasswordController extends GetxController { + final AppRepositories repository = Get.find(); + late InputField oldPasswordField; + late InputField newPasswordField; + late InputField confirmNewPasswordField; + + bool validate() { + bool isValid = FieldValidation.validateAll([oldPasswordField, newPasswordField, confirmNewPasswordField]); + return isValid; + } + + changePassword() async { + if (!validate()) { + Toasty.error("Please input and then proceed"); + return; + } + + bool otherValidation = true; + if (!AppUtils.isPasswordValid(oldPasswordField.getCustomText(), 8)) { + oldPasswordField.setError(TranslationKeys.makeTranslation(TranslationKeys.textPasswordPattern)); + otherValidation = false; + } + if (!AppUtils.isPasswordValid(newPasswordField.getCustomText(), 8)) { + newPasswordField.setError(TranslationKeys.makeTranslation(TranslationKeys.textPasswordPattern)); + otherValidation = false; + } + if (!AppUtils.isPasswordValid(confirmNewPasswordField.getCustomText(), 8)) { + confirmNewPasswordField.setError(TranslationKeys.makeTranslation(TranslationKeys.textPasswordPattern)); + otherValidation = false; + } + if (!otherValidation) { + return; + } + + if (newPasswordField.getCustomText() != confirmNewPasswordField.getCustomText()) { + Toasty.error("Passwords didn't match"); + return; + } + + // ServerResponse response = await repository.changePassword( + // ChangePasswordParams( + // newPassword: newPasswordField.getCustomText(), + // oldPassword: oldPasswordField.getCustomText(), + // email: SessionCache.instance.userInfo.cmpUserId, + // ), + // ); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + + CustomDialog.showSuccessDialog( + // title: "Change Password", + description: " Password has been changed successfully", + onTapPositive: () { + clearFields(); + Get.back(); + }); + } + + void clearFields() { + oldPasswordField.clear(); + newPasswordField.clear(); + confirmNewPasswordField.clear(); + } +} diff --git a/lib/app/modules/password_change/views/password_change_view.dart b/lib/app/modules/password_change/views/password_change_view.dart new file mode 100644 index 0000000..55fd781 --- /dev/null +++ b/lib/app/modules/password_change/views/password_change_view.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/modules/password_change/controllers/password_change_controller.dart'; + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; + +class ChangePasswordScreen extends GetView { + const ChangePasswordScreen({super.key}); + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.changepassword), + onBackButtonPressed: () { + Get.back(); + controller.clearFields(); + }, + ), + body: GetBuilder(builder: (controller) { + return Padding( + padding: const EdgeInsets.only(right: 12.0, left: 12.0), + child: Column( + children: [ + const SizedBox(height: 20), + controller.oldPasswordField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}oldPassword"), + controller: FormFieldConstants.instance().getController("${className}oldPassword"), + hintText: "Enter old password", + labelText: "Old Password", + keyboardType: TextInputType.visiblePassword, + requiredPasswordIcon: true, + isPassword: true, + ), + controller.newPasswordField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}newPassword"), + controller: FormFieldConstants.instance().getController("${className}newPassword"), + hintText: "Enter new password", + labelText: "New Password", + keyboardType: TextInputType.visiblePassword, + requiredPasswordIcon: true, + isPassword: true, + ), + controller.confirmNewPasswordField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}confirmNewPasswordField"), + controller: FormFieldConstants.instance().getController("${className}confirmNewPasswordField"), + hintText: "Enter new password again", + labelText: "Confirm New Password", + keyboardType: TextInputType.visiblePassword, + requiredPasswordIcon: true, + isPassword: true, + ) + ], + ), + ); + }), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: CustomButton( + onPressed: () { + Get.find().changePassword(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textChangePassword), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 0), + ), + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + // child: SizedBox( + // width: double.infinity, + // child: ElevatedButton( + // onPressed: () { + // Get.find().changePassword(); + // }, + // style: ElevatedButton.styleFrom( + // backgroundColor: AppColors.colorButton, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(50), + // ), + // ), + // child: Padding( + // padding: const EdgeInsets.all(12.0), + // child: Text(TranslationKeys.makeTranslation(TranslationKeys.textChangePassword), style: Theme.of(context).textTheme.labelMedium?.copyWith(color: AppColors.white)), + // ), + // ), + // ), + // ), + ], + persistentFooterAlignment: AlignmentDirectional.bottomCenter, + resizeToAvoidBottomInset: false, + backgroundColor: AppColors.colorSecondary, + ); + } +} diff --git a/lib/app/modules/privacy_policy/bindings/privacy_policy_binding.dart b/lib/app/modules/privacy_policy/bindings/privacy_policy_binding.dart new file mode 100644 index 0000000..063281b --- /dev/null +++ b/lib/app/modules/privacy_policy/bindings/privacy_policy_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/privacy_policy_controller.dart'; + +class PrivacyPolicyBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => PrivacyPolicyController(), + ); + } +} diff --git a/lib/app/modules/privacy_policy/controllers/privacy_policy_controller.dart b/lib/app/modules/privacy_policy/controllers/privacy_policy_controller.dart new file mode 100644 index 0000000..1e2c33d --- /dev/null +++ b/lib/app/modules/privacy_policy/controllers/privacy_policy_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class PrivacyPolicyController extends GetxController { + //TODO: Implement PrivacyPolicyController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/privacy_policy/views/privacy_policy_view.dart b/lib/app/modules/privacy_policy/views/privacy_policy_view.dart new file mode 100644 index 0000000..076c3b4 --- /dev/null +++ b/lib/app/modules/privacy_policy/views/privacy_policy_view.dart @@ -0,0 +1,143 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import '../controllers/privacy_policy_controller.dart'; + +class PrivacyPolicyView extends GetView { + const PrivacyPolicyView({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: "Privacy Policy", + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.all(15), + child: Card( + surfaceTintColor: Colors.white, + elevation: 5.0, + child: /*ListView.builder( + itemBuilder: (context, index) { + return Column( + children: [ + Text(privacyPolicy.title, + style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + Text( + privacyPolicy.description, + style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 15), + ], + ); + },),*/ + + ListView( + // Wrap the Card with a ListView for vertical scrolling + children: [ + Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // first paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + SizedBox(height: 15), + + // second paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + SizedBox(height: 15), + + // third paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + SizedBox(height: 15), + + // forth paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + SizedBox(height: 15), + ], + ), + ), + ], + ), + ), + + /*Card( + surfaceTintColor: Colors.white, + elevation: 5.0, + child: ListView( + // Wrap the Card with a ListView for vertical scrolling + children: [ + Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // first paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 15), + + // second paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 15), + + // third paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 15), + + // forth paragraph + Text("Digital Banking Experience", + style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + Text( + "In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.", + style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 15), + // CustomButton( + ], + ), + ), + ], + ), + ),*/ + ), + ); + } +} diff --git a/lib/app/modules/qr_setting/bindings/qr_setting_binding.dart b/lib/app/modules/qr_setting/bindings/qr_setting_binding.dart new file mode 100644 index 0000000..01a74c9 --- /dev/null +++ b/lib/app/modules/qr_setting/bindings/qr_setting_binding.dart @@ -0,0 +1,12 @@ +// import 'package:get/get.dart'; +// +// import '../controllers/qr_setting_controller.dart'; +// +// class QrSettingBinding extends Bindings { +// @override +// void dependencies() { +// Get.lazyPut( +// () => QrSettingController(), +// ); +// } +// } diff --git a/lib/app/modules/qr_setting/controllers/qr_setting_controller.dart b/lib/app/modules/qr_setting/controllers/qr_setting_controller.dart new file mode 100644 index 0000000..72910c9 --- /dev/null +++ b/lib/app/modules/qr_setting/controllers/qr_setting_controller.dart @@ -0,0 +1,130 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; +// import 'package:image_gallery_saver/image_gallery_saver.dart'; +// import 'package:image_picker/image_picker.dart'; +import 'package:path_provider/path_provider.dart'; +// import 'package:qr_code_scanner/qr_code_scanner.dart'; +import 'package:screenshot/screenshot.dart'; +import 'package:share_plus/share_plus.dart'; +// import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:screenshot/screenshot.dart'; +// import 'package:screenshot/screenshot.dart'; +// import 'package:share_plus/share_plus.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +// import 'package:share_plus/share_plus.dart'; + + + +class QrSettingController extends GetxController { + // + // + final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); + + Barcode? result; + // + // QRViewController? qrController; + + ScreenshotController screenshotController = ScreenshotController(); + + List qrList = [ + QRSetting(name: "Muhammad Bilal", accountNumber: "MSISDN: ********** 2222"), + ]; + + Future saveAssetImage() async { + Uint8List? image = await screenshotController.capture(); + + if (image != null) { + // await ImageGallerySaver.saveImage(image); + Toasty.error("QR Image save successfully"); + } + } + + void shareQRImage() async { + try { + // + + var tempDir = await getTemporaryDirectory(); + + var image = await screenshotController.captureAndSave(tempDir.path); + + dp("Path ", image); + + if (image != null) { + Share.shareXFiles([XFile(image)]); + } + + // + } catch (e) { + if (kDebugMode) { + print('Error sharing asset image: $e'); + } + // Handle any errors + } + } + + void toggleFlash() { + // qrController?.toggleFlash(); + } + + Future? getFlashStatus() { + // return qrController?.getFlashStatus() ?? Future.value(false); + } + + Future scanfromImage() async { + + // var imagePath = await ImagePicker().pickImage(source: ImageSource.gallery); + + // var result = await qrController?.scanQrcodeFromImage(imagePath!.path); + + // qrController?.pauseCamera(); + // + // if (result != null && result.isNotEmpty) { + // Get.back(result: result.first); + // } else { + // Get.back(); + // Toasty.error("Please re scan data not fetch"); + // } + // + // dp("Result Image", result?.map((e) => e).toList()); + // + // dp("Result Image", result?.length); + } + + @override + void dispose() { + // qrController?.dispose(); + super.dispose(); + } + + // void onQRViewCreated(QRViewController p1) { + // // + // + // qrController = p1; + // + // update(); + // + // qrController?.scannedDataStream.listen((scanData) { + // result = scanData; + // + // qrController?.pauseCamera(); + // + // dp("Barcode result", result?.code); + // + // if (result != null) { + // Get.back(result: result!.code); + // } + // + // // + // }); + // } +} + +class QRSetting { + String name = ""; + String accountNumber = ""; + + QRSetting({this.name = "", this.accountNumber = ""}); +} diff --git a/lib/app/modules/qr_setting/views/qr_scan_screen.dart b/lib/app/modules/qr_setting/views/qr_scan_screen.dart new file mode 100644 index 0000000..8339422 --- /dev/null +++ b/lib/app/modules/qr_setting/views/qr_scan_screen.dart @@ -0,0 +1,322 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +// import 'package:qr_code_scanner/qr_code_scanner.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../controllers/qr_setting_controller.dart'; + +class QrScanScreen extends GetView { + const QrScanScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + title: "QR SCAN", + ), + body: GetBuilder(builder: (controller) { + return Column( + children: [ + // Expanded( + // flex: 5, + // child: QRView( + // key: controller.qrKey, + // onQRViewCreated: controller.onQRViewCreated, + // overlay: QrScannerOverlayShape(), + // ), + // ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + GestureDetector( + onTap: () async { + await controller.scanfromImage(); + }, + child: const Icon(Icons.image)), + GestureDetector( + onTap: () { + controller.toggleFlash(); + }, + child: FutureBuilder( + future: controller.getFlashStatus(), + builder: (context, snapshot) { + return Icon( + (snapshot.data ?? false) + ? Icons.flash_off + : Icons.flash_on, + ); + }, + ), + ), + ], + )), + ], + ); + }), + ); + } +} +// +// // import 'dart:async'; +// +// // import 'package:flutter/material.dart'; +// // import 'package:get/get.dart'; +// // import 'package:qr_flutter/qr_flutter.dart'; +// // import 'package:uco_ciihive/app/core/utils/logs_utils.dart'; +// // import 'package:uco_ciihive/app/custom_widgets/custom_app_bar.dart'; +// // import 'package:mobile_scanner/mobile_scanner.dart'; +// // import 'scanner_buttons.dart'; +// +// // class QrScanScreen extends StatefulWidget { +// // const QrScanScreen({super.key}); +// +// // @override +// // State createState() => _QrScanScreenState(); +// // } +// +// // class _QrScanScreenState extends State { +// // // +// +// // final MobileScannerController scanController = MobileScannerController( +// // formats: [BarcodeFormat.qrCode], +// // useNewCameraSelector: true, +// // facing: CameraFacing.back, +// // ); +// +// // StreamSubscription? _subscription; +// +// // late final AppLifecycleListener _listener; +// +// // Barcode? _barcode; +// +// // @override +// // void initState() { +// +// // initScanner(); +// // listenAppLifeState(); +// +// // super.initState(); +// // } +// +// // @override +// // Future dispose() async { +// // unawaited(_subscription?.cancel()); +// // _subscription = null; +// // _listener.dispose(); +// +// // super.dispose(); +// +// // await scanController.dispose(); +// // } +// +// // void listenAppLifeState() { +// // _listener = AppLifecycleListener( +// // onStateChange: _onStateChanged, +// // ); +// // } +// +// // void initScanner() { +// // _subscription = scanController.barcodes.listen(_handleBarcode); +// +// // unawaited(scanController.start()); +// // } +// +// // Future _onStateChanged(AppLifecycleState state) async { +// // dp("Scanner state", state.name); +// // switch (state) { +// // case AppLifecycleState.hidden: +// // case AppLifecycleState.paused: +// // case AppLifecycleState.detached: +// // return; +// // case AppLifecycleState.resumed: +// // _subscription = scanController.barcodes.listen(_handleBarcode); +// +// // unawaited(scanController.start()); +// // case AppLifecycleState.inactive: +// // unawaited(_subscription?.cancel()); +// // _subscription = null; +// // unawaited(scanController.stop()); +// // } +// // } +// +// // void _handleBarcode(BarcodeCapture barcodes) { +// // _barcode = barcodes.barcodes.firstOrNull; +// // dp("Barcode Result Raw", _barcode?.rawValue); +// // dp("Barcode Display Value", _barcode?.displayValue); +// +// // setState(() {}); +// // } +// +// // @override +// // Widget build(BuildContext context) { +// // final scanWindow = Rect.fromCenter( +// // center: MediaQuery.sizeOf(context).center(Offset.zero), +// // width: 200, +// // height: 200, +// // ); +// // return Scaffold( +// // appBar: DashBoardAppBar( +// // onBackButtonPressed: () { +// // Get.back(); +// // }, +// // ), +// // body: Stack( +// // fit: StackFit.expand, +// // children: [ +// // Center( +// // child: MobileScanner( +// // fit: BoxFit.contain, +// // controller: scanController, +// // scanWindow: scanWindow, +// // errorBuilder: (context, error, child) { +// // // return ScannerErrorWidget(error: error); +// // return const SizedBox( +// // child: Text("Error Widget"), +// // ); +// // }, +// // overlayBuilder: (context, constraints) { +// // return Padding( +// // padding: const EdgeInsets.all(16.0), +// // child: Align( +// // alignment: Alignment.bottomCenter, +// // child: +// // ScannedBarcodeLabel(barcodes: scanController.barcodes), +// // ), +// // ); +// // }, +// // ), +// // ), +// // ValueListenableBuilder( +// // valueListenable: scanController, +// // builder: (context, value, child) { +// // if (!value.isInitialized || +// // !value.isRunning || +// // value.error != null) { +// // return const SizedBox( +// // child: Text("No init Scanner"), +// // ); +// // } +// +// // return CustomPaint( +// // painter: ScannerOverlay(scanWindow: scanWindow), +// // ); +// // }, +// // ), +// // Align( +// // alignment: Alignment.bottomCenter, +// // child: Padding( +// // padding: const EdgeInsets.all(16.0), +// // child: Row( +// // mainAxisAlignment: MainAxisAlignment.spaceEvenly, +// // children: [ +// // ToggleFlashlightButton(controller: scanController), +// // SwitchCameraButton(controller: scanController), +// // ], +// // ), +// // ), +// // ), +// // ], +// // ), +// // ); +// // } +// // } +// +// // class ScannerOverlay extends CustomPainter { +// // const ScannerOverlay({ +// // required this.scanWindow, +// // this.borderRadius = 12.0, +// // }); +// +// // final Rect scanWindow; +// // final double borderRadius; +// +// // @override +// // void paint(Canvas canvas, Size size) { +// // // TODO: use `Offset.zero & size` instead of Rect.largest +// // // we need to pass the size to the custom paint widget +// // final backgroundPath = Path()..addRect(Rect.largest); +// +// // final cutoutPath = Path() +// // ..addRRect( +// // RRect.fromRectAndCorners( +// // scanWindow, +// // topLeft: Radius.circular(borderRadius), +// // topRight: Radius.circular(borderRadius), +// // bottomLeft: Radius.circular(borderRadius), +// // bottomRight: Radius.circular(borderRadius), +// // ), +// // ); +// +// // final backgroundPaint = Paint() +// // ..color = Colors.black.withOpacity(0.5) +// // ..style = PaintingStyle.fill +// // ..blendMode = BlendMode.dstOut; +// +// // final backgroundWithCutout = Path.combine( +// // PathOperation.difference, +// // backgroundPath, +// // cutoutPath, +// // ); +// +// // final borderPaint = Paint() +// // ..color = Colors.white +// // ..style = PaintingStyle.stroke +// // ..strokeWidth = 4.0; +// +// // final borderRect = RRect.fromRectAndCorners( +// // scanWindow, +// // topLeft: Radius.circular(borderRadius), +// // topRight: Radius.circular(borderRadius), +// // bottomLeft: Radius.circular(borderRadius), +// // bottomRight: Radius.circular(borderRadius), +// // ); +// +// // // First, draw the background, +// // // with a cutout area that is a bit larger than the scan window. +// // // Finally, draw the scan window itself. +// // canvas.drawPath(backgroundWithCutout, backgroundPaint); +// // canvas.drawRRect(borderRect, borderPaint); +// // } +// +// // @override +// // bool shouldRepaint(ScannerOverlay oldDelegate) { +// // return scanWindow != oldDelegate.scanWindow || +// // borderRadius != oldDelegate.borderRadius; +// // } +// // } +// +// // class ScannedBarcodeLabel extends StatelessWidget { +// // const ScannedBarcodeLabel({ +// // super.key, +// // required this.barcodes, +// // }); +// +// // final Stream barcodes; +// +// // @override +// // Widget build(BuildContext context) { +// // return StreamBuilder( +// // stream: barcodes, +// // builder: (context, snapshot) { +// // final scannedBarcodes = snapshot.data?.barcodes ?? []; +// +// // if (scannedBarcodes.isEmpty) { +// // return const Text( +// // 'Scan something!', +// // overflow: TextOverflow.fade, +// // style: TextStyle(color: Colors.wh'ite), +// // ); +// // } +// +// // return Text( +// // scannedBarcodes.first.displayValue ?? 'No display value.', +// // overflow: TextOverflow.fade, +// // style: const TextStyle(color: Colors.white), +// // ); +// // }, +// // ); +// // } +// // } diff --git a/lib/app/modules/qr_setting/views/qr_setting_view.dart b/lib/app/modules/qr_setting/views/qr_setting_view.dart new file mode 100644 index 0000000..7d0ed47 --- /dev/null +++ b/lib/app/modules/qr_setting/views/qr_setting_view.dart @@ -0,0 +1,116 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'package:screenshot/screenshot.dart'; +// import 'package:screenshot/screenshot.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/qr_setting_controller.dart'; + +class QrSettingView extends GetView { + const QrSettingView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textQRSetting), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0), + child: Column( + children: [ + const SizedBox(height: 20), + Align( + alignment: Alignment.center, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textYourUCOQR), + style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500, fontSize: 20), + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation(TranslationKeys.textUCOQRContent), + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 14), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + Screenshot( + controller: controller.screenshotController, + child: Container( + color: Colors.white, + padding: const EdgeInsets.all(12), + child: QrImageView( + data: jsonEncode({"phoneNumber": SessionCache.instance.depositAccountList.first.padAdrsmobphone}), + version: QrVersions.auto, + size: 200.0, + ), + ), + ), + const SizedBox(height: 20), + Text( + SessionCache.instance.depositAccountList.first.mbmBkmstitle, + style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500, fontSize: 20), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation(TranslationKeys.textQrAccountNumber), + style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w400, fontSize: 14), + textAlign: TextAlign.center, + ), + ], + ), + ), + persistentFooterButtons: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomButton( + onPressed: () { + controller.saveAssetImage(); + }, + icon: SvgPicture.asset( + AppAssets.ic_download, + height: 15, + width: 15, + ), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textSavetoGallery), + buttonColor: AppColors.colorButton, + textStyle: Theme.of(context).textTheme.bodyMedium?.copyWith(color: AppColors.white, fontWeight: FontWeight.w400, fontSize: 13), + iconPadding: const EdgeInsets.only(left: 5), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + ), + SizedBox( + child: CustomButton( + onPressed: () { + controller.shareQRImage(); + }, + iconPadding: const EdgeInsets.only(left: 5), + textStyle: Theme.of(context).textTheme.bodyMedium?.copyWith(color: AppColors.black, fontWeight: FontWeight.w400, fontSize: 13), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textShareQRCode), + buttonColor: AppColors.colorSkipBtn, + sideBorder: const BorderSide(width: 1, color: AppColors.colorBorderSkipBtn), + icon: SvgPicture.asset(AppAssets.ic_share, height: 15, width: 15), + ), + ), + ], + ), + ], + persistentFooterAlignment: AlignmentDirectional.bottomCenter, + resizeToAvoidBottomInset: false, + backgroundColor: AppColors.colorSecondary, + ); + } +} diff --git a/lib/app/modules/qr_setting/views/qr_view_screen.dart b/lib/app/modules/qr_setting/views/qr_view_screen.dart new file mode 100644 index 0000000..38956fb --- /dev/null +++ b/lib/app/modules/qr_setting/views/qr_view_screen.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'package:uco_mobile_poc/app/core/extensions/build_context_ext.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; + +class QrViewScreen extends StatelessWidget { + const QrViewScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SizedBox( + width: context.getWidth, + height: context.getHeight, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Text("Qr View Screen"), + const SizedBox( + height: 20, + ), + QrImageView( + data: ''' +{ +"channelCode":"01", +"porOrgacode":"0006", +"email":"", +"isOtpRequire":false, +"pinType":"C_TRANPIN" +} +''', + version: QrVersions.auto, + size: 200.0, + ), + const SizedBox( + height: 20, + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/qr_setting/views/scanner_buttons.dart b/lib/app/modules/qr_setting/views/scanner_buttons.dart new file mode 100644 index 0000000..3aa66c3 --- /dev/null +++ b/lib/app/modules/qr_setting/views/scanner_buttons.dart @@ -0,0 +1,169 @@ +import 'package:flutter/material.dart'; +// import 'package:image_picker/image_picker.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; + +class AnalyzeImageFromGalleryButton extends StatelessWidget { + const AnalyzeImageFromGalleryButton({required this.controller, super.key}); + + final MobileScannerController controller; + + @override + Widget build(BuildContext context) { + return IconButton( + color: Colors.white, + icon: const Icon(Icons.image), + iconSize: 32.0, + onPressed: () async { + // final ImagePicker picker = ImagePicker(); + // + // final XFile? image = await picker.pickImage( + // source: ImageSource.gallery, + // ); + + // if (image == null) { + // return; + // } + // + // final BarcodeCapture? barcodes = await controller.analyzeImage( + // image.path, + // ); + // + // if (!context.mounted) { + // return; + // } + + // final SnackBar snackbar = barcodes != null + // ? const SnackBar( + // content: Text('Barcode found!'), + // backgroundColor: Colors.green, + // ) + // : const SnackBar( + // content: Text('No barcode found!'), + // backgroundColor: Colors.red, + // ); + + // ScaffoldMessenger.of(context).showSnackBar(snackbar); + }, + ); + } +} + +class StartStopMobileScannerButton extends StatelessWidget { + const StartStopMobileScannerButton({required this.controller, super.key}); + + final MobileScannerController controller; + + @override + Widget build(BuildContext context) { + return ValueListenableBuilder( + valueListenable: controller, + builder: (context, state, child) { + if (!state.isInitialized || !state.isRunning) { + return IconButton( + color: Colors.white, + icon: const Icon(Icons.play_arrow), + iconSize: 32.0, + onPressed: () async { + await controller.start(); + }, + ); + } + + return IconButton( + color: Colors.white, + icon: const Icon(Icons.stop), + iconSize: 32.0, + onPressed: () async { + await controller.stop(); + }, + ); + }, + ); + } +} + +class SwitchCameraButton extends StatelessWidget { + const SwitchCameraButton({required this.controller, super.key}); + + final MobileScannerController controller; + + @override + Widget build(BuildContext context) { + return ValueListenableBuilder( + valueListenable: controller, + builder: (context, state, child) { + if (!state.isInitialized || !state.isRunning) { + return const SizedBox.shrink(); + } + + final int? availableCameras = state.availableCameras; + + if (availableCameras != null && availableCameras < 2) { + return const SizedBox.shrink(); + } + + final Widget icon; + + switch (state.cameraDirection) { + case CameraFacing.front: + icon = const Icon(Icons.camera_front); + case CameraFacing.back: + icon = const Icon(Icons.camera_rear); + } + + return IconButton( + iconSize: 32.0, + icon: icon, + onPressed: () async { + await controller.switchCamera(); + }, + ); + }, + ); + } +} + +class ToggleFlashlightButton extends StatelessWidget { + const ToggleFlashlightButton({required this.controller, super.key}); + + final MobileScannerController controller; + + @override + Widget build(BuildContext context) { + return ValueListenableBuilder( + valueListenable: controller, + builder: (context, state, child) { + if (!state.isInitialized || !state.isRunning) { + return const SizedBox.shrink(); + } + switch (state.torchState) { + case TorchState.off: + return IconButton( + color: Colors.white, + iconSize: 32.0, + icon: const Icon(Icons.flash_off), + onPressed: () async { + await controller.toggleTorch(); + }, + ); + case TorchState.on: + return IconButton( + color: Colors.white, + iconSize: 32.0, + icon: const Icon(Icons.flash_on), + onPressed: () async { + await controller.toggleTorch(); + }, + ); + case TorchState.unavailable: + return const Icon( + Icons.no_flash, + color: Colors.grey, + ); + case TorchState.auto: + throw UnimplementedError(); + } + }, + ); + } +} diff --git a/lib/app/modules/recipient_details/bindings/recipient_details_binding.dart b/lib/app/modules/recipient_details/bindings/recipient_details_binding.dart new file mode 100644 index 0000000..edc7baf --- /dev/null +++ b/lib/app/modules/recipient_details/bindings/recipient_details_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/recipient_details_controller.dart'; + +class RecipientDetailsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => RecipientDetailsController(), + ); + } +} diff --git a/lib/app/modules/recipient_details/controllers/recipient_details_controller.dart b/lib/app/modules/recipient_details/controllers/recipient_details_controller.dart new file mode 100644 index 0000000..9a2669d --- /dev/null +++ b/lib/app/modules/recipient_details/controllers/recipient_details_controller.dart @@ -0,0 +1,64 @@ +import 'dart:ffi'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_contants.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dialog.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/TransactionSubmitRequestModel.dart'; +import 'package:uco_mobile_poc/app/models/TransactionSubmitResponseModel.dart'; + +import '../../../routes/app_pages.dart'; +import '../../dashboard/controllers/dashboard_screen_controller.dart'; + +class RecipientDetailsController extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + + TextEditingController pinPutController = TextEditingController(); + Rx transactionSubmitRequestModel = + TransactionSubmitRequestModel + .empty() + .obs; + String exchangeRate = ""; + String endingBalance = ""; + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + transactionSubmitRequestModel.value = (arguments != null + ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? + TransactionSubmitRequestModel.empty() + : TransactionSubmitRequestModel.empty()); + exchangeRate = + (arguments != null ? arguments[AppConstants.EXCHANGE_RATE] ?? "" : ""); + } + + Future sendTransaction() async { + // ServerResponse response = await repository + // .sendTransactionStep2(transactionSubmitRequestModel.value); + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + // + // TransactionSubmitResponseModel responseModel = + // TransactionSubmitResponseModel.fromMap(response.response); + // + // transitionUpdate.value++; + // + // dp("Transition value is", transitionUpdate.value); + + // CustomDialog.showTransactionSuccessDialog( + // context, + // responseModel.mbmBkmsbalance.toString(), + // exchangeRate, + // transactionSubmitRequestModel.value, + // ); + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + } +} diff --git a/lib/app/modules/recipient_details/views/recipient_details_view.dart b/lib/app/modules/recipient_details/views/recipient_details_view.dart new file mode 100644 index 0000000..fb8e3fb --- /dev/null +++ b/lib/app/modules/recipient_details/views/recipient_details_view.dart @@ -0,0 +1,265 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; + +import '../controllers/recipient_details_controller.dart'; + +class RecipientDetailsView extends GetView { + const RecipientDetailsView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textConfirmTransaction), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Obx(() { + return Column( + children: [ + Stack(children: [ + Container( + height: 70, + decoration: + const BoxDecoration(color: AppColors.colorPrimary)), + Padding( + padding: const EdgeInsets.only(left: 20, right: 20), + child: Card( + color: AppColors.colorGrey50, + margin: + const EdgeInsets.symmetric(horizontal: 10, vertical: 20), + elevation: 5.0, + child: Container( + padding: const EdgeInsets.all(8), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(10)) // Add border radius + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textRecipient), + style: + Theme + .of(context) + .textTheme + .bodyMedium), + )), + Expanded( + flex: 4, + child: Padding( + padding: const EdgeInsets.only( + left: 12.0, right: 12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + controller.transactionSubmitRequestModel + .value.crMbmBkmstitle, + style: Theme + .of(context) + .textTheme + .titleSmall, + ), + const SizedBox(height: 5), + Text( + controller.transactionSubmitRequestModel + .value.crMbmBkmsnumber, + style: + Theme + .of(context) + .textTheme + .bodySmall, + ), + ], + ), + )), + ], + )), + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(top: 80, left: 20, right: 20), + child: Card( + color: AppColors.colorGrey50, + margin: + const EdgeInsets.symmetric(horizontal: 10, vertical: 20), + elevation: 5.0, + child: Container( + padding: const EdgeInsets.all(15), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(10)) // Add border radius + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textConformation), + style: Theme + .of(context) + .textTheme + .titleSmall + ?.copyWith( + fontWeight: FontWeight.w600, + fontSize: 20)), + const SizedBox(height: 10), + Row( + children: [ + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textAccountNumber), + style: Theme + .of(context) + .textTheme + .bodyMedium), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys + .textSendingAmount), + style: Theme + .of(context) + .textTheme + .bodyMedium), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textCurrency), + style: Theme + .of(context) + .textTheme + .bodyMedium), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textMessage), + style: Theme + .of(context) + .textTheme + .bodyMedium), + ], + ), + )), + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.only( + left: 12.0, right: 12.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + controller + .transactionSubmitRequestModel + .value + .crMbmBkmsnumber, + style: Theme + .of(context) + .textTheme + .bodySmall), + const SizedBox(height: 10), + Text( + controller + .transactionSubmitRequestModel + .value + .sgtGntramtfc + .toString(), + style: Theme + .of(context) + .textTheme + .bodySmall), + const SizedBox(height: 10), + Text( + controller + .transactionSubmitRequestModel + .value + .crPcrCurrdesc, + style: Theme + .of(context) + .textTheme + .bodySmall), + const SizedBox(height: 10), + Text( + controller + .transactionSubmitRequestModel + .value + .otdTrancomment, + style: Theme + .of(context) + .textTheme + .bodySmall), + ], + ), + )), + ], + ), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + CustomButton( + onPressed: () { + controller.sendTransaction(); + }, + buttonText: TranslationKeys.makeTranslation( + TranslationKeys.textConfirm), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric( + vertical: 5, horizontal: 20), + ), + CustomButton( + onPressed: () { + Get.back(); + }, + buttonText: TranslationKeys.makeTranslation( + TranslationKeys.textCancel), + buttonColor: AppColors.colorSkipBtn, + textStyle: Theme + .of(context) + .textTheme + .labelLarge + ?.copyWith(color: AppColors.black), + sideBorder: const BorderSide( + width: 1, + color: AppColors.colorBorderSkipBtn), + buttonPadding: const EdgeInsets.symmetric( + vertical: 5, horizontal: 20)), + ], + ), + ], + )), + ), + ), + ]), + ], + ); + }), + ); + } +} diff --git a/lib/app/modules/sample_fields/bindings/sample_fields_binding.dart b/lib/app/modules/sample_fields/bindings/sample_fields_binding.dart new file mode 100644 index 0000000..50f73aa --- /dev/null +++ b/lib/app/modules/sample_fields/bindings/sample_fields_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/sample_fields_controller.dart'; + +class SampleFieldsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SampleFieldsController(), + ); + } +} diff --git a/lib/app/modules/sample_fields/controllers/sample_fields_controller.dart b/lib/app/modules/sample_fields/controllers/sample_fields_controller.dart new file mode 100644 index 0000000..20dd819 --- /dev/null +++ b/lib/app/modules/sample_fields/controllers/sample_fields_controller.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_date_time_picker.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dropdown.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_input_field.dart'; + +class SampleFieldsController extends GetxController { + //TODO: Implement SampleFieldsController + late CustomInputFieldCustom userNameField; + + late CustomInputFieldCustom passwordField; + + late BuildContext context; + + late CustomDateTimePicker dateField; + + late CustomDropDown genderField; + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/sample_fields/views/sample_fields_view.dart b/lib/app/modules/sample_fields/views/sample_fields_view.dart new file mode 100644 index 0000000..606d7a0 --- /dev/null +++ b/lib/app/modules/sample_fields/views/sample_fields_view.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/constants/form_field_constants.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_date_time_picker.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dropdown.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/modules/login/views/shared/login_widget.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../controllers/sample_fields_controller.dart'; + +class SampleFieldsView extends GetView { + const SampleFieldsView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + controller.context = context; + String className = runtimeType.toString().split('.').last; + return Scaffold( + persistentFooterButtons: [ + BottomNavigationBar( + backgroundColor: AppColors.colorSecondary.withOpacity(0.1), + elevation: 0, + type: BottomNavigationBarType.fixed, + items: [ + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs( + context, + TranslationKeys.makeTranslation(TranslationKeys.textFindUAgent), + AppAssets.ic_cyber_security, + () { + Get.toNamed(Routes.O_T_P_SCREEN); + // LoginWidgets.showBottomSheet(context, BottomSheetLogin.options, (index) { + // BottomSheetLogin option = BottomSheetLogin.options[index]; + // if (option.description == TranslationKeys.makeTranslation(TranslationKeys.textLogin)) {} + // }); + }, + context.textTheme.bodySmall!.copyWith(fontSize: 12), + ), + label: '', + ), + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs(context, TranslationKeys.makeTranslation(TranslationKeys.textQRPay), AppAssets.ic_QR, () { + // LoginWidgets.showBottomSheet(context, BottomSheetLogin.options, (index) { + // BottomSheetLogin option = BottomSheetLogin.options[index]; + // if (option.description == TranslationKeys.makeTranslation(TranslationKeys.textLogin)) {} + // }); + Toasty.success("Coming Soon....."); + }, context.textTheme.bodySmall!.copyWith(fontSize: 12)), + label: '', + ), + BottomNavigationBarItem( + icon: LoginWidgets.bottomTabs(context, TranslationKeys.makeTranslation(TranslationKeys.textHelp), AppAssets.ic_client, () { + Toasty.success("Coming Soon....."); + }, context.textTheme.bodySmall!.copyWith(fontSize: 12)), + label: '', + ), + // BottomNavigationBarItem( + // icon: LoginWidgets.bottomTabs(context, TranslationKeys.makeTranslation(TranslationKeys.textContactUs), AppAssets.ic_contact_us, () { + // showBottomSheet(context); + // }), + // label: '', + // ), + ], + ), + ], + body: SingleChildScrollView( + child: Column( + children: [ + GestureDetector( + onTap: () { + // showCurrencyDialog(context); + }, + child: Align(alignment: Alignment.centerRight, child: Padding(padding: const EdgeInsets.only(right: 8.0, left: 8.0), child: Container(decoration: const BoxDecoration(color: AppColors.colorPrimary, borderRadius: BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20))), height: 60, width: 30, child: Padding(padding: const EdgeInsets.only(top: 28.0), child: SvgPicture.asset(AppAssets.ic_arrow_down, height: 20, width: 20)))))), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 0), + child: Column( + children: [ + const SizedBox(height: 20), + SvgPicture.asset(AppAssets.lg_logo_black, height: 100, width: 100), + const SizedBox(height: 10), + controller.userNameField = CustomInputFieldCustom( + refKey: FormFieldConstants.instance().getFormKey("${className}userNameField"), + controller: FormFieldConstants.instance().getController("${className}userNameField"), + labelText: "User Name", + ), + const SizedBox(height: 10), + controller.passwordField = CustomInputFieldCustom( + refKey: FormFieldConstants.instance().getFormKey("${className}passwordField"), + controller: FormFieldConstants.instance().getController("${className}passwordField"), + labelText: "Password", + requiredPasswordIcon: true, + isPassword: true, + ), + const SizedBox(height: 10), + controller.dateField = CustomDateTimePicker( + refKey: FormFieldConstants.instance().getFormKey("${className}dateField"), + controller: FormFieldConstants.instance().getController("${className}dateField"), + labelText: "picker", + ), + const SizedBox(height: 10), + controller.genderField = CustomDropDown( + listData: [DropDown("id1", "Label1"), DropDown("id2", "Label2"), DropDown("id3", "Label3")].obs, + labelText: "Gender", + isRequired: true, + ), + ], + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/sign_up/bindings/sign_up_screen_otp_binding.dart b/lib/app/modules/sign_up/bindings/sign_up_screen_otp_binding.dart new file mode 100644 index 0000000..ff6fc00 --- /dev/null +++ b/lib/app/modules/sign_up/bindings/sign_up_screen_otp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/sign_up_screen_otp_controller.dart'; + +class SignUpScreenOTPBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SignUpScreenOTPController(), + ); + } +} \ No newline at end of file diff --git a/lib/app/modules/sign_up/bindings/sign_up_screen_step1_binding.dart b/lib/app/modules/sign_up/bindings/sign_up_screen_step1_binding.dart new file mode 100644 index 0000000..6bed8c9 --- /dev/null +++ b/lib/app/modules/sign_up/bindings/sign_up_screen_step1_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/sign_up_screen_step1_controller.dart'; + +class SignUpScreenStep1Binding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SignUpScreenStep1Controller(), + ); + } +} diff --git a/lib/app/modules/sign_up/bindings/sign_up_screen_step2_binding.dart b/lib/app/modules/sign_up/bindings/sign_up_screen_step2_binding.dart new file mode 100644 index 0000000..cb238cc --- /dev/null +++ b/lib/app/modules/sign_up/bindings/sign_up_screen_step2_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/sign_up_screen_step2_controller.dart'; + +class SignUpScreenStep2Binding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SignUpScreenStep2Controller(), + ); + } +} diff --git a/lib/app/modules/sign_up/bindings/sign_up_screen_step3_binding.dart b/lib/app/modules/sign_up/bindings/sign_up_screen_step3_binding.dart new file mode 100644 index 0000000..41b03c3 --- /dev/null +++ b/lib/app/modules/sign_up/bindings/sign_up_screen_step3_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/sign_up_screen_step3_controller.dart'; + +class SignUpScreenStep3Binding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SignUpScreenStep3Controller(), + ); + } +} diff --git a/lib/app/modules/sign_up/controllers/sign_up_screen_otp_controller.dart b/lib/app/modules/sign_up/controllers/sign_up_screen_otp_controller.dart new file mode 100644 index 0000000..3c04c30 --- /dev/null +++ b/lib/app/modules/sign_up/controllers/sign_up_screen_otp_controller.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_contants.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/enums/request_constants.dart'; +import 'package:uco_mobile_poc/app/core/utils/fields_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/RegisterRequest.dart'; +import 'package:uco_mobile_poc/app/models/SignupOtpRequest.dart'; +import 'package:uco_mobile_poc/app/models/resend_ot_login_model.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../../../core/constants/form_field_constants.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; + +class SignUpScreenOTPController extends GetxController { + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + + late InputField firstNameField; + TextEditingController pinPutController = TextEditingController(); + + RegisterRequest firstStepData = RegisterRequest.empty(); + + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + firstStepData = (arguments != null ? arguments[AppConstants.SIGN_UP_FIRST_STEP_DATA] ?? RegisterRequest.empty() : RegisterRequest.empty()); + } + Future validatePinAndNavigate() async { + hideKeyBoard(); + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + SignupOtpRequest request = SignupOtpRequest( + username: firstStepData.username, + email: firstStepData.email, + obpPincode: pinPutController.text, + // obpPintype: AppConstants.PIN_TYPE_SIGNUP, + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + ); + + ServerResponse response = await repository.signupStep2(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Get.toNamed(Routes.SIGN_UP_SCREEN_STEP2, + arguments: { + AppConstants.SIGN_UP_FIRST_STEP_DATA: firstStepData, + } + ); + + clearControllersOTP(); + } + + void clearControllersOTP() { + pinPutController.clear(); + } + + void resenOtp() async { + + if (!isResend.value) { + Fluttertoast.showToast(msg: "Please wait for 1 minute"); + return; + } + + var responce = await repository.resentOtpLoginSignUp( + ResendOtpLoginModel( + userRole: firstStepData.userRole, + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + email: firstStepData.email, + isOtpRequire: false, + phone: firstStepData.phone, + pinType: 'C_TRANPIN', + username: firstStepData.email, + ), + ); + + if (responce.isError) { + Fluttertoast.showToast(msg: responce.errorMsg); + return; + } + + isResend.value = false; + + countdownController.setOnRestart( + () {}, + ); + + countdownController.restart(); + + Fluttertoast.showToast(msg: "OTP successfully send to your email address"); + } + + void updateResend(bool send) { + isResend.value = send; + } + @override + void onClose() { + FormFieldConstants.instance().clearKeysForScreen("SignUpScreenOTPView"); + super.onClose(); + } +} diff --git a/lib/app/modules/sign_up/controllers/sign_up_screen_step1_controller.dart b/lib/app/modules/sign_up/controllers/sign_up_screen_step1_controller.dart new file mode 100644 index 0000000..ee57b89 --- /dev/null +++ b/lib/app/modules/sign_up/controllers/sign_up_screen_step1_controller.dart @@ -0,0 +1,125 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:string_validator/string_validator.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_contants.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/enums/request_constants.dart'; +import 'package:uco_mobile_poc/app/core/utils/app_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/field_validations.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/RegisterRequest.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/utils/fields_utils.dart'; + +class SignUpScreenStep1Controller extends GetxController { + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + + late InputField firstNameField; + + late InputField lastNameField; + late InputField passwordField; + late InputField confirmPasswordField; + late InputField emailField; + late InputField phoneNumberField; + + /// map for country wise phone number length + final RxString selectedCountryCode = 'US'.obs; + final Map countryPhoneMap = { + 'US': 10, + 'PK': 11, + 'It': 11, + }; + + + bool validatePhoneNumber(String countryCode, String phoneNumber) { + if (countryPhoneMap.containsKey(countryCode)) { + return phoneNumber.length == countryPhoneMap[countryCode]; + } + return false; + } + + bool validate() { + bool isValid = FieldValidation.validateAll([firstNameField, passwordField, confirmPasswordField, emailField, phoneNumberField]); + return isValid; + } + + void validateAndSendRequest() async { + hideKeyBoard(); + if (!validate()) { + Toasty.error("Please input and then proceed"); + return; + } + bool otherValidation = true; + if (!AppUtils.isPasswordValid(passwordField.getCustomText(), 8)) { + passwordField.setError(TranslationKeys.makeTranslation(TranslationKeys.textPasswordPattern)); + otherValidation = false; + } + if (!AppUtils.isPasswordValid(confirmPasswordField.getCustomText(), 8)) { + confirmPasswordField.setError(TranslationKeys.makeTranslation(TranslationKeys.textPasswordPattern)); + otherValidation = false; + } + if (!isEmail(emailField.getCustomText())) { + emailField.setError("Invalid email"); + otherValidation = false; + } + if (!otherValidation) { + return; + } + if (passwordField.getCustomText() != confirmPasswordField.getCustomText()) { + Toasty.error("Passwords didn't matched"); + return; + } + + if (!validatePhoneNumber(selectedCountryCode.value, phoneNumberField.getCustomText())) { + Toasty.error("Invalid phone number length"); + return; + } + + RegisterRequest request = RegisterRequest( + email: emailField.getCustomText(), + password: passwordField.getCustomText(), + username: firstNameField.getCustomText(), + phone: phoneNumberField.getCustomText(isPrefixRequired: true, isCountryCodeRequired: true), + name: "", + channelCode: RequestConstants.channelCode, + userRole: AppConstants.ROLE_USER, + porOrgacode: RequestConstants.porOrgacode, + isOtpRequired: false, + ); + ServerResponse response = await repository.signupStep1(request); + + if (response.errorCode == "ERR_USER_0007") { + Get.toNamed(Routes.SIGN_UP_SCREEN_OTP, arguments: { + AppConstants.SIGN_UP_FIRST_STEP_DATA: request, + }); + return; + } + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + Get.toNamed(Routes.SIGN_UP_SCREEN_OTP, + arguments: { + AppConstants.SIGN_UP_FIRST_STEP_DATA: request, + } + ); + } + clearTextControllerStep1() { + firstNameField.clear(); + passwordField.clear(); + confirmPasswordField.clear(); + emailField.clear(); + phoneNumberField.clear(); + } + @override + void onClose() { + FormFieldConstants.instance().clearKeysForScreen("SignUpScreenStep1View"); + super.onClose(); + } +} diff --git a/lib/app/modules/sign_up/controllers/sign_up_screen_step2_controller.dart b/lib/app/modules/sign_up/controllers/sign_up_screen_step2_controller.dart new file mode 100644 index 0000000..0e689f1 --- /dev/null +++ b/lib/app/modules/sign_up/controllers/sign_up_screen_step2_controller.dart @@ -0,0 +1,241 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_contants.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/dialogs/custom_loading.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/field_validations.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dropdown.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/RegisterRequest.dart'; +import 'package:uco_mobile_poc/app/models/SignupStep3RequestModel.dart'; +import 'package:uco_mobile_poc/app/models/product_model.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/fields_utils.dart'; + +class SignUpScreenStep2Controller extends GetxController { + final String IDEN_NUMBER = "01"; + final String IDEN_TAX_PAYER_ID = "02"; + final String IDEN_PASSPORT = "03"; + + String dpmcode = ''; + + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + + late InputField firstNameField; + late InputField lastNameField; + late InputField nameAddressField; + late InputField selectIdentityTypeField; + late InputField identityNumberField; + late InputField taxPayerIdField; + late InputField passportField; + String? selectedCountryCode; + + + RxList identityDropdownList = [].obs; + DropDown? currentIdentityValue; + + RegisterRequest firstStepData = RegisterRequest.empty(); + + late InputField countryFeild; + + late InputField provinceFeild; + + late InputField cityFeild; + + late InputField currencyCodesFelid; + + var countryList = [ + {"name": "Pakistan", "code": "PK"}, + {"name": "United States of America", "code": "USA"} + ].map((e) => DropDown(e["code"]!, e["code"]!)).toList(); + + List provinceList = [ + { + "country": "PK", + "province": ["Sindh", "Punjab", "Gilgit Baltistan", "KPK", "Baluchistan"] + }, + { + "country": "USA", + "province": ["California", "Florida", "Hawaii"] + }, + ] + .expand( + (Map e) => (e["province"] as List) + .map((e1) => DropDown(e["country"]!, e1)), + ) + .toList(); + + + List currencyList = []; + List currencyListDropDown = []; + + List getProvinceList(String country) { + return provinceList + .where((element) => element.id == country) + .toList(); + } + + // getProvinceList(String country) { + // return provinceList + // .where((DropDown? element) => element!.id == country) + // .toList(); + // } + + List cityList = [ + { + "province": "Sindh", + "city": ["Karachi", "Ladkana"] + }, + { + "province": "Punjab", + "city": ["Lahore"] + }, + { + "province": "Gilgit Baltistan", + "city": ["Gilgit"] + }, + { + "province": "California", + "city": ["California"] + }, + { + "province": "Florida", + "city": ["Florida"] + }, + { + "province": "Hawaii", + "city": ["Hawaii"] + }, + ] + .expand( + (Map e) => (e["city"] as List) + .map((e1) => DropDown(e["province"]!, e1)), + ) + .toList(); + + @override + void onInit() { + super.onInit(); + identityDropdownList.value = [ + DropDown(IDEN_NUMBER, TranslationKeys.makeTranslation(TranslationKeys.textIdentityNumber)), + DropDown(IDEN_TAX_PAYER_ID, TranslationKeys.makeTranslation(TranslationKeys.textSSNTaxPayerID)), + DropDown(IDEN_PASSPORT, TranslationKeys.makeTranslation(TranslationKeys.textPassportAlienID)), + ]; + } + + @override + Future onReady() async { + super.onReady(); + getCurrencyList(); + var arguments = Get.arguments; + firstStepData = (arguments != null ? arguments[AppConstants.SIGN_UP_FIRST_STEP_DATA] ?? RegisterRequest.empty() : RegisterRequest.empty()); + } + + updateIdentityValue(DropDown? identityDropDowModel) { + currentIdentityValue = identityDropDowModel; + update(); + } + + bool validate() { + bool isValid = FieldValidation.validateAll([firstNameField, lastNameField, nameAddressField, selectIdentityTypeField, + currencyCodesFelid, + ]); + + if (currentIdentityValue != null) { + if (currentIdentityValue!.id == IDEN_NUMBER) { + isValid = isValid && FieldValidation.validateAll([identityNumberField]); + } else if (currentIdentityValue!.id == IDEN_TAX_PAYER_ID) { + isValid = isValid && FieldValidation.validateAll([taxPayerIdField]); + } else if (currentIdentityValue!.id == IDEN_PASSPORT) { + isValid = isValid && FieldValidation.validateAll([passportField]); + } + } + + return isValid; + } + + String getIdentification() { + if (currentIdentityValue!.id == IDEN_NUMBER) { + return identityNumberField.getCustomText(); + } else if (currentIdentityValue!.id == IDEN_TAX_PAYER_ID) { + return taxPayerIdField.getCustomText(); + } else if (currentIdentityValue!.id == IDEN_PASSPORT) { + return passportField.getCustomText(); + } + return ""; + } + + void validateAndSendRequest() async { + hideKeyBoard(); + if (!validate()) { + Toasty.error("Please input and then proceed"); + return; + } + + SignupStep3RequestModel signupStep3RequestModel = + SignupStep3RequestModel(username: firstStepData.username, + email: firstStepData.email, phone: firstStepData.phone, + channelCode: firstStepData.channelCode, porOrgacode: firstStepData.porOrgacode, + address: nameAddressField.getCustomText(), + name: '${firstNameField.getCustomText()} ${lastNameField.getCustomText()}', + identificationType: currentIdentityValue!.id, identificationNumber: getIdentification(), + userRole: AppConstants.ROLE_USER, isKycAdded: false, kycType: "", + kycDocumentId1: "", kycDocumentId2: "", dmpProdcode: dpmcode); + Get.toNamed(Routes.SIGN_UP_SCREEN_STEP3, + arguments: { + AppConstants.SIGN_UP_SECOND_STEP_DATA: signupStep3RequestModel, + } + ); + } + clearTextControllerStep2() { + firstNameField.clear(); + lastNameField.clear(); + nameAddressField.clear(); + selectIdentityTypeField.clear(); + identityNumberField.clear(); + taxPayerIdField.clear(); + passportField.clear(); + update(); + } + + void updateCurrency(DropDown? item) { + dpmcode = item!.id; + update(); + } + + getCurrencyList() async { + try { + var productResponce = await repository.getCurrencyList(); + + if (productResponce.isError) { + hideLoader(); + + Toasty.error(productResponce.errorMsg); + return; + } + + currencyList = ProductDepositModel.productListFromJson(productResponce.response); + + currencyListDropDown = currencyList.map((e) => DropDown(e.dmpProdcode, e.dmpProddesc, e)).toList(); + + hideLoader(); + + update(); + } catch (e, s) { + dp("Error in get product $e", s); + hideLoader(); + Toasty.error("Something went worng please try again"); + } + } + @override + void onClose() { + FormFieldConstants.instance().clearKeysForScreen("SignUpScreenStep2View"); + super.onClose(); + } +} diff --git a/lib/app/modules/sign_up/controllers/sign_up_screen_step3_controller.dart b/lib/app/modules/sign_up/controllers/sign_up_screen_step3_controller.dart new file mode 100644 index 0000000..d123eb3 --- /dev/null +++ b/lib/app/modules/sign_up/controllers/sign_up_screen_step3_controller.dart @@ -0,0 +1,170 @@ +// import 'package:camera/camera.dart'; +import 'package:camera/camera.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dialog.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dropdown.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/SignupStep3RequestModel.dart'; +import 'package:uco_mobile_poc/app/modules/sign_up/controllers/sign_up_screen_step1_controller.dart'; +import 'package:uco_mobile_poc/app/modules/sign_up/controllers/sign_up_screen_step2_controller.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/utils/fields_utils.dart'; +import 'sign_up_screen_otp_controller.dart'; + +enum signDocTypeScreen { cnic, passport, driving } + +class SignUpScreenStep3Controller extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + RxList documentTypeTabList = [].obs; + RxString frontPath = "".obs; + RxString backPath = "".obs; + + Rx docTypeScreen = signDocTypeScreen.cnic.obs; + SignupStep3RequestModel signupStep3RequestModel = SignupStep3RequestModel.empty(); + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + signupStep3RequestModel = (arguments != null ? arguments[AppConstants.SIGN_UP_SECOND_STEP_DATA] ?? SignupStep3RequestModel.empty() : SignupStep3RequestModel.empty()); + } + + updateDocTypeScreen(signDocTypeScreen type) { + if (type != docTypeScreen.value) { + frontPath.value = ""; + backPath.value = ""; + docTypeScreen.value = type; + } + } + + updateFrontPath(path) { + frontPath.value = path; + } + + updateBackPath(path) { + backPath.value = path; + } + + void updateDocs(String path, bool isFront, signDocTypeScreen docType) { + if (isFront) { + updateFrontPath(path); + } else { + updateBackPath(path); + } + } + + String getKycType() { + if (docTypeScreen == signDocTypeScreen.cnic) { + return AppConstants.IDEN_TYPE_CNIC; + } else if (docTypeScreen == signDocTypeScreen.passport) { + return AppConstants.IDEN_TYPE_PASSPORT; + } else if (docTypeScreen == signDocTypeScreen.driving) { + return AppConstants.IDEN_TYPE_DRIVING_LICIENCE; + } + return ""; + } + + void skipAndSubmit() { + signupStep3RequestModel.kycType = ""; + signupStep3RequestModel.isKycAdded = false; + signupStep3RequestModel.kycDocumentId1 = ""; + signupStep3RequestModel.kycDocumentId2 = ""; + sendRequest(); + } + + void validateAndSubmit() { + hideKeyBoard(); + if (frontPath.value.isEmpty) { + Toasty.error("Please upload front image"); + return; + } else if (docTypeScreen.value != signDocTypeScreen.passport) { + if (backPath.value.isEmpty) { + Toasty.error("Please upload back image"); + return; + } + } + + signupStep3RequestModel.kycType = getKycType(); + signupStep3RequestModel.isKycAdded = true; + signupStep3RequestModel.kycDocumentId1 = frontPath.value; + signupStep3RequestModel.kycDocumentId2 = backPath.value; + sendRequest(); + } + + Future sendRequest() async { + dp("=======sendRequest>>>>>>>", signupStep3RequestModel.toString()); + dp("=======sendRequest>>>>>>>", signupStep3RequestModel.porOrgacode + "Rehan"); + signupStep3RequestModel.porOrgacode = "0005"; + dp("=======sendRequest>>>>>>>", signupStep3RequestModel.porOrgacode + "Rehan"); + ServerResponse response = await repository.signupStep3(signupStep3RequestModel); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + CustomDialog.showSuccessDialog( + description: TranslationKeys.makeTranslation(TranslationKeys.textSignUpDescriptionDailog), + onTapPositive: () { + Get.back(); + // Get.offAndToNamed(Routes.LOGIN_SCREEN); + // step1Controller.clearTextControllerStep1(); + // otpController.clearControllersOTP(); + // step2Controller.clearTextControllerStep2(); + Get.delete(); + Get.delete(); + Get.delete(); + Get.offAllNamed(Routes.LOGIN_SCREEN); + }); + } + + var step1Controller = Get.find(); + var otpController = Get.find(); + var step2Controller = Get.find(); + + /// Flash Light work + late CameraController _controller; + late List cameras; + var isFlashOn = false.obs; + + @override + void onInit() { + super.onInit(); + initializeCamera(); + } + + Future initializeCamera() async { + cameras = await availableCameras(); + _controller = CameraController(cameras[0], ResolutionPreset.low, enableAudio: false); + await _controller.initialize(); + + // Restore flash state if it was previously on + if (_controller.value.flashMode == FlashMode.torch) { + isFlashOn(true); + } + } + + Future toggleFlashlight() async { + if (_controller.value.isInitialized) { + if (_controller.value.flashMode == FlashMode.off) { + await _controller.setFlashMode(FlashMode.torch); + isFlashOn(true); + } else { + await _controller.setFlashMode(FlashMode.off); + isFlashOn(false); + } + } + } + @override + void onClose() { + FormFieldConstants.instance().clearKeysForScreen("SignUpScreenStep3View"); + _controller.dispose(); + super.onClose(); + } +} diff --git a/lib/app/modules/sign_up/views/shared/camera_screen.dart b/lib/app/modules/sign_up/views/shared/camera_screen.dart new file mode 100644 index 0000000..fba8293 --- /dev/null +++ b/lib/app/modules/sign_up/views/shared/camera_screen.dart @@ -0,0 +1,95 @@ +import 'dart:io'; + +import 'package:camera/camera.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_camera_overlay_new/flutter_camera_overlay.dart'; +import 'package:flutter_camera_overlay_new/model.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; + +import '../../controllers/sign_up_screen_step3_controller.dart'; + +class CameraOverlayScreen extends StatelessWidget { + final bool isFront; + final signDocTypeScreen docType; + + CameraOverlayScreen({super.key, required this.isFront, required this.docType}); + + SignUpScreenStep3Controller controller = Get.find(); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + body: FutureBuilder?>( + future: availableCameras(), + builder: (context, snapshot) { + if (snapshot.hasData) { + if (snapshot.data == null) { + return const Align( + alignment: Alignment.center, + child: Text( + 'No camera found', + style: TextStyle(color: Colors.black), + )); + } + + return CameraOverlay( + snapshot.data!.first, + CardOverlay.byFormat(OverlayFormat.cardID1), + (XFile file) { + showDialog( + context: context, + barrierColor: Colors.black, + builder: (context) { + CardOverlay overlay = CardOverlay.byFormat(OverlayFormat.cardID1); + return AlertDialog( + actionsAlignment: MainAxisAlignment.center, + backgroundColor: Colors.black, + title: const Text('Capture', style: TextStyle(color: Colors.white), textAlign: TextAlign.center), + actions: [ + OutlinedButton(onPressed: () => Navigator.of(context).pop(), child: const Icon(Icons.close)), + OutlinedButton( + onPressed: () { + Get.put(SignUpScreenStep3Controller()).updateDocs(file.path, isFront, docType); + Navigator.of(context).pop(); + Navigator.pop(context); + }, + child: const Icon(Icons.done)), + ], + content: SizedBox( + width: double.infinity, + child: AspectRatio( + aspectRatio: 1.5, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fitWidth, + alignment: FractionalOffset.center, + image: FileImage( + File(file.path), + ), + )), + ), + ), + ), + ); + }, + ); + }, + info: 'Position your ID card within the rectangle and ensure the image is perfectly readable.', + label: 'Scanning ID Card', + ); + } else { + return const Align( + alignment: Alignment.center, + child: Text( + 'Fetching cameras', + style: TextStyle(color: Colors.black), + )); + } + }, + ), + ); + } +} diff --git a/lib/app/modules/sign_up/views/sign_up_screen_otp_view.dart b/lib/app/modules/sign_up/views/sign_up_screen_otp_view.dart new file mode 100644 index 0000000..b5052f3 --- /dev/null +++ b/lib/app/modules/sign_up/views/sign_up_screen_otp_view.dart @@ -0,0 +1,135 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../controllers/sign_up_screen_otp_controller.dart'; + +class SignUpScreenOTPView extends GetView { + const SignUpScreenOTPView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + controller.pinPutController.clear(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodyMedium?.copyWith(height: 1.3), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + textInputAction: TextInputAction.done, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), + style: Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle( + fontSize: 12, + ), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + controller.resenOtp(); + }, + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textResend), style: Theme.of(context).textTheme.titleSmall?.copyWith(color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey))), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/sign_up/views/sign_up_screen_step1_view.dart b/lib/app/modules/sign_up/views/sign_up_screen_step1_view.dart new file mode 100644 index 0000000..65cf3f8 --- /dev/null +++ b/lib/app/modules/sign_up/views/sign_up_screen_step1_view.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/form_field_constants.dart'; +import 'package:uco_mobile_poc/app/core/data/data_source_auth/remote_data_source/app_remote_data_source.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/utils/fields_utils.dart'; +import 'package:uco_mobile_poc/app/core/utils/phone_number_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/res/app_dimensions.dart'; + +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/app_utils.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/sign_up_screen_step1_controller.dart'; + +class SignUpScreenStep1View extends GetView { + const SignUpScreenStep1View({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + // Get.put(() => AppRemoteDataSource()); + // Get.lazyPut(() => AppRepositoriesImpl(remoteDataSource: Get.find())); + String className = runtimeType.toString().split('.').last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textSingUp), + onBackButtonPressed: () { + if (Navigator.canPop(context)) { + Get.back(); + controller.clearTextControllerStep1(); + } else { + SystemNavigator.pop(); + } + }, + ), + persistentFooterButtons: [ + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: const EdgeInsets.symmetric( + vertical: 10, + ), + buttonColor: AppColors.colorButton, + textStyle: const TextStyle(color: AppColors.white), + ), + ), + ], + body: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), + child: Column( + children: [ + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 8, + child: controller.firstNameField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}firstNameField"), + controller: FormFieldConstants.instance().getController("${className}firstNameField"), + hintText: "User Name", + labelText: TranslationKeys.makeTranslation("User Name"), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.userNameFieldLength)], + ), + ), + const Spacer(), + Expanded( + flex: 8, + child: controller.lastNameField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}lastNameField"), + controller: FormFieldConstants.instance().getController("${className}lastNameField"), + hintText: "Enter last name", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textLastName), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.userNameFieldLength)], + ), + ), + ], + ), + controller.passwordField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}passwordField"), + controller: FormFieldConstants.instance().getController("${className}passwordField"), + hintText: "Enter password", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textPassword), + keyboardType: TextInputType.visiblePassword, + requiredPasswordIcon: true, + isPassword: true, + ), + controller.confirmPasswordField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}confirmPasswordField"), + controller: FormFieldConstants.instance().getController("${className}confirmPasswordField"), + hintText: "Enter password", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textConfirmPassword), + keyboardType: TextInputType.visiblePassword, + requiredPasswordIcon: true, + isPassword: true, + ), + controller.emailField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}emailField"), + controller: FormFieldConstants.instance().getController("${className}emailField"), + hintText: "Enter email", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textEmailID), + ), + controller.phoneNumberField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}phoneNumberField"), + controller: FormFieldConstants.instance().getController("${className}phoneNumberField"), + hintText: "Enter phone number", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textCellNumber), + keyboardType: TextInputType.phone, + inputFormatters: [LengthLimitingTextInputFormatter(PhoneNumberUtils.getPhoneNumberLength()), InputType.NUMBER], + // prefixText:AppUtils.formatPhoneNumber(PhoneNumberUtils.phoneCode), + prefixCode: PhoneNumberUtils.phoneCode, + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + isCountryPicker: true, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/sign_up/views/sign_up_screen_step2_view.dart b/lib/app/modules/sign_up/views/sign_up_screen_step2_view.dart new file mode 100644 index 0000000..beb3f97 --- /dev/null +++ b/lib/app/modules/sign_up/views/sign_up_screen_step2_view.dart @@ -0,0 +1,253 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/form_field_constants.dart'; +import 'package:uco_mobile_poc/app/core/utils/fields_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/res/app_dimensions.dart'; + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_input_field.dart'; +import '../../../models/identity_drop_down_model.dart'; +import '../../../res/app_theme.dart'; +import '../controllers/sign_up_screen_step2_controller.dart'; + +class SignUpScreenStep2View extends GetView { + const SignUpScreenStep2View({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + var border = OutlineInputBorder(borderSide: const BorderSide(color: AppThemeData.inputEnabledBorderColor), borderRadius: BorderRadius.circular(50)); + var dropDowDecoration = InputDecoration( + border: border, + enabledBorder: border, + focusedBorder: border, + disabledBorder: border, + errorBorder: border, + ); + + String className = runtimeType.toString().split('.').last; + + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textSingUp), + onBackButtonPressed: () { + Get.back(); + controller.clearTextControllerStep2(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), + child: CustomButton( + onPressed: () { + controller.validateAndSendRequest(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: const EdgeInsets.symmetric(vertical: 12), + buttonColor: AppColors.colorButton, + textStyle: const TextStyle(color: AppColors.white), + ), + ), + ], + body: Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), + child: GetBuilder(builder: (controller) { + return SingleChildScrollView( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 8, + child: controller.firstNameField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}firstNameField"), + controller: FormFieldConstants.instance().getController("${className}firstNameField"), + hintText: "Enter first name", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textFirstName), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.userNameFieldLength)], + ), + ), + const Spacer(), + Expanded( + flex: 8, + child: controller.lastNameField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}lastNameField"), + controller: FormFieldConstants.instance().getController("${className}lastNameField"), + hintText: "Enter last name", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textLastName), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.userNameFieldLength)], + ), + ), + ], + ), + + controller.countryFeild = InputField( + refKey: FormFieldConstants.instance() + .getFormKey("${className}selectCountry"), + controller: FormFieldConstants.instance() + .getController("${className}selectCountry"), + labelText: "Select Country", + isDropDown: true, + hintText: "Select Country", + dropDownType: DropDownType.SPECIAL, + items: controller.countryList, + onItemSelected: (item) { + controller.selectedCountryCode = item?.id; + controller.update(); + }, + // onItemSelected: (item) {}, + ), + + controller.provinceFeild = InputField( + refKey: FormFieldConstants.instance() + .getFormKey("${className}provinceField"), + controller: FormFieldConstants.instance() + .getController("${className}provinceField"), + labelText: "Select Province", + isDropDown: true, + hintText: "Select Province", + dropDownType: DropDownType.SPECIAL, + items: controller.selectedCountryCode == null + ? [] + : controller.getProvinceList(controller.selectedCountryCode!), + onItemSelected: (item) {}, + // items: controller.getProvinceList('USA'), + // onItemSelected: (item) { + // controller.selectedCountryCode = item?.id; + // controller.update(); + // }, + // items: controller.getProvinceList("USA"), + // onItemSelected: (item) {}, + ), + + controller.cityFeild = InputField( + refKey: FormFieldConstants.instance() + .getFormKey("${className}cityField"), + controller: FormFieldConstants.instance() + .getController("${className}cityField"), + labelText: "Select City", + isDropDown: true, + hintText: "Select City", + dropDownType: DropDownType.SPECIAL, + items: controller.cityList, + onItemSelected: (item) { + controller.updateIdentityValue(item); + }, + ), + + controller.nameAddressField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}nameAddressField"), + controller: FormFieldConstants.instance().getController("${className}nameAddressField"), + hintText: "Enter address", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textAddress), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.addressFieldLength)], + ), + + controller.currencyCodesFelid = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}currencyCodesFelid"), + controller: FormFieldConstants.instance().getController("${className}currencyCodesFelid"), + labelText: "Select Default Currency", + isDropDown: true, + hintText: "Select Default Currency", + dropDownType: DropDownType.SPECIAL, + items: controller.currencyListDropDown as List?, + onItemSelected: (item) { + controller.updateCurrency(item); + }, + ), + + controller.selectIdentityTypeField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}selectIdentificationField"), + controller: FormFieldConstants.instance().getController("${className}selectIdentificationField"), + labelText: "Select Identification", + isDropDown: true, + hintText: "Select Identification", + dropDownType: DropDownType.SPECIAL, + items: controller.identityDropdownList, + onItemSelected: (item) { + controller.updateIdentityValue(item); + }, + ), + + Column( + children: [ + Visibility( + visible: controller.currentIdentityValue?.id == controller.IDEN_NUMBER, + child: controller.identityNumberField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}identityNumberField"), + controller: FormFieldConstants.instance().getController("${className}identityNumberField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textIdentityNumber), + hintText: "Enter Identity number", + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + ), + ), + Visibility( + visible: controller.currentIdentityValue?.id == controller.IDEN_TAX_PAYER_ID, + child: controller.taxPayerIdField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}taxPayerIdField"), + controller: FormFieldConstants.instance().getController("${className}taxPayerIdField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textSSNTaxPayerID), + hintText: "Enter taxpayer id", + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + ), + ), + Visibility( + visible: controller.currentIdentityValue?.id == controller.IDEN_PASSPORT, + child: controller.passportField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}passportField"), + controller: FormFieldConstants.instance().getController("${className}passportField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textPassportAlienID), + hintText: "Enter passport number", + onSubmitted: (value) { + controller.validateAndSendRequest(); + }, + ), + ), + ], + ), + + controller.currentIdentityValue?.id == identityType.identity + ? controller.identityNumberField = CustomInputFieldCustom( + refKey: FormFieldConstants.instance().getFormKey("${className}identityNumberField"), + controller: FormFieldConstants.instance().getController("${className}identityNumberField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textIdentityNumber), + ) as InputField + : const SizedBox(), + controller.currentIdentityValue?.id == identityType.passport + ? controller.taxPayerIdField = CustomInputFieldCustom( + refKey: FormFieldConstants.instance().getFormKey("${className}taxPayerIdField"), + controller: FormFieldConstants.instance().getController("${className}taxPayerIdField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textSSNTaxPayerID), + ) as InputField + : const SizedBox(), + controller.currentIdentityValue?.id == identityType.ssntaxpayer + ? controller.passportField = CustomInputFieldCustom( + refKey: FormFieldConstants.instance().getFormKey("${className}passportField"), + controller: FormFieldConstants.instance().getController("${className}passportField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textPassportAlienID), + ) as InputField + : const SizedBox(), + ], + ), + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/sign_up/views/sign_up_screen_step3_view.dart b/lib/app/modules/sign_up/views/sign_up_screen_step3_view.dart new file mode 100644 index 0000000..7e07699 --- /dev/null +++ b/lib/app/modules/sign_up/views/sign_up_screen_step3_view.dart @@ -0,0 +1,264 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/extensions/build_context_ext.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_text.dart'; +import 'package:uco_mobile_poc/app/modules/sign_up/views/shared/camera_screen.dart'; +import 'package:uco_mobile_poc/app/res/app_theme.dart'; + +import '../../../core/constants/translation_keys.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../controllers/sign_up_screen_step3_controller.dart'; + +class SignUpScreenStep3View extends GetView { + final String imagePath; + + const SignUpScreenStep3View({this.imagePath = "", Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return GetBuilder(builder: (controller) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textUploadKYC), + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.only(bottom: 10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CustomButton( + onPressed: () async { + controller.validateAndSubmit(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: const EdgeInsets.symmetric(vertical: 12, horizontal: 40), + buttonColor: AppColors.colorButton, + textStyle: const TextStyle(color: AppColors.white), + ), + const SizedBox(width: 15), + CustomButton( + onPressed: () { + controller.skipAndSubmit(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textSkipKYC), + icon: SvgPicture.asset(AppAssets.ic_next, height: 15, width: 15), + textStyle: Theme.of(context).textTheme.bodyMedium?.copyWith(color: AppColors.black, fontWeight: FontWeight.w400, fontSize: 13), + iconPadding: const EdgeInsets.only(left: 10), + buttonPadding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20), + sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1.0), + buttonColor: AppColors.colorSkipBtn), + ], + ), + ), + ], + body: Obx(() { + return Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding, horizontal: AppDimensions.screenHorizontalPadding), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomText(TranslationKeys.makeTranslation(TranslationKeys.textChooseDocumentType), style: AppThemeData.labelStyle), + const SizedBox(height: 5), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + CustomButton( + onPressed: () { + controller.updateDocTypeScreen(signDocTypeScreen.cnic); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textCNIC), + textStyle: context.textTheme.bodySmall?.copyWith(color: controller.docTypeScreen.value == signDocTypeScreen.cnic ? Colors.white : AppColors.colorTitle), + buttonPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20), + buttonColor: controller.docTypeScreen.value == signDocTypeScreen.cnic ? AppColors.colorPrimary : AppColors.colorPrimaryLight, + radius: 5, + ), + const SizedBox(width: 10), + CustomButton( + onPressed: () { + controller.updateDocTypeScreen(signDocTypeScreen.driving); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textDivingLicense), + textStyle: context.textTheme.bodySmall?.copyWith(color: controller.docTypeScreen.value == signDocTypeScreen.driving ? Colors.white : AppColors.colorTitle), + buttonPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20), + buttonColor: controller.docTypeScreen.value == signDocTypeScreen.driving ? AppColors.colorPrimary : AppColors.colorPrimaryLight, + radius: 5, + ), + const SizedBox(width: 10), + CustomButton( + onPressed: () { + controller.updateDocTypeScreen(signDocTypeScreen.passport); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textPassport), + textStyle: context.textTheme.bodySmall?.copyWith(color: controller.docTypeScreen.value == signDocTypeScreen.passport ? Colors.white : AppColors.colorTitle), + buttonPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20), + buttonColor: controller.docTypeScreen.value == signDocTypeScreen.passport ? AppColors.colorPrimary : AppColors.colorPrimaryLight, + radius: 5, + ), + ], + ), + const SizedBox(height: 10), + CustomText( + TranslationKeys.makeTranslation( + TranslationKeys.textDocumentsDescription, + ), + style: AppThemeData.labelStyle, + ), + const SizedBox(height: 20), + CNICScreen(docType: controller.docTypeScreen.value), + const SizedBox(height: 15), + ], + ), + ); + }), + ); + }); + } +} + +class CNICScreen extends StatelessWidget { + const CNICScreen({super.key, required this.docType}); + + final signDocTypeScreen docType; + + @override + Widget build(BuildContext context) { + return GetBuilder(builder: (controller) { + return Column( + children: [ + SizedBox( + height: 120, + child: Row( + children: [ + Expanded( + flex: 10, + child: GestureDetector( + onTap: () async { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CameraOverlayScreen( + isFront: true, + docType: docType, + ))).then((value) { + }); + }, + child: Card( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset(AppAssets.ic_camera, height: 41, width: 41, fit: BoxFit.cover), + const SizedBox(height: 10), + CustomText( + TranslationKeys.makeTranslation(TranslationKeys.textFront), + style: AppThemeData.labelStyle, + ), + ], + ), + ), + ), + ), + signDocTypeScreen.passport == docType + ? const SizedBox() + : const SizedBox( + width: 10, + ), + signDocTypeScreen.passport == docType + ? const SizedBox() + : Expanded( + flex: 10, + child: GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CameraOverlayScreen(isFront: false, docType: docType), + ), + ).then((value) => {}); + }, + child: Card( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset(AppAssets.ic_camera, height: 41, width: 41, fit: BoxFit.cover), + const SizedBox(height: 10), + CustomText( + TranslationKeys.makeTranslation(TranslationKeys.textBack), + style: AppThemeData.labelStyle, + ), + ], + ), + ), + ), + ), + ], + ), + ), + const SizedBox(height: 10), + Obx(() { + return SizedBox( + height: 200, + width: context.getWidth, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (controller.frontPath.value.isEmpty) + ? const Spacer() + : Expanded( + child: AspectRatio( + aspectRatio: 1.5, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fitWidth, + alignment: FractionalOffset.center, + image: FileImage( + File(controller.frontPath.value), + ), + )), + ), + ), + ), + + const SizedBox(width: 20), + + signDocTypeScreen.passport == docType + ? const SizedBox() + : (controller.backPath.value.isEmpty) + ? const Spacer() + : Expanded( + child: AspectRatio( + aspectRatio: 1.5, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.fitWidth, + alignment: FractionalOffset.center, + image: FileImage( + File(controller.backPath.value), + ), + )), + ), + ), + ), + ], + ), + ); + }), + ], + ); + } + ); + } + } diff --git a/lib/app/modules/speed_dial/src/simple_speed_dial.dart b/lib/app/modules/speed_dial/src/simple_speed_dial.dart new file mode 100644 index 0000000..d964965 --- /dev/null +++ b/lib/app/modules/speed_dial/src/simple_speed_dial.dart @@ -0,0 +1,372 @@ +import 'package:flutter/material.dart'; + +import 'package:uco_mobile_poc/app/res/app_colors.dart'; + +class SpeedDial extends StatefulWidget { + const SpeedDial({ + Key? key, + required this.child, + required this.speedDialChildren, + this.labelsStyle, + this.labelsBackgroundColor, + this.controller, + this.closedForegroundColor, + this.openForegroundColor, + this.closedBackgroundColor, + this.openBackgroundColor, + }) : super(key: key); + + final Widget child; + + /// A list of [SpeedDialChild] to display when the [SpeedDial] is open. + final List speedDialChildren; + + /// Specifies the [SpeedDialChild] label text style. + final TextStyle? labelsStyle; + + /// The background color of the labels. + final Color? labelsBackgroundColor; + + /// An animation controller for the [SpeedDial]. + /// + /// Provide an [AnimationController] to control the animations + /// from outside the [SpeedDial] widget. + final AnimationController? controller; + + /// The color of the [SpeedDial] button foreground when closed. + /// + /// The [SpeedDial] foreground will animate to this color when the user + /// closes the speed dial. + final Color? closedForegroundColor; + + /// The color of the [SpeedDial] button foreground when opened. + /// + /// The [SpeedDial] foreground will animate to this color when the user + /// opens the speed dial. + final Color? openForegroundColor; + + /// The color of the [SpeedDial] button background when closed. + /// + /// The [SpeedDial] background will animate to this color when the user + /// closes the speed dial. + final Color? closedBackgroundColor; + + /// The color of the [SpeedDial] button background when open. + /// + /// The [SpeedDial] background will animate to this color when the user + /// opens the speed dial. + final Color? openBackgroundColor; + + @override + State createState() { + return _SpeedDialState(); + } +} + +class _SpeedDialState extends State + with SingleTickerProviderStateMixin { + late AnimationController _animationController; + late Animation _backgroundColorAnimation; + late Animation _foregroundColorAnimation; + final List> _speedDialChildAnimations = + >[]; + + @override + void initState() { + _animationController = widget.controller ?? + AnimationController( + vsync: this, duration: const Duration(milliseconds: 100)); + _animationController.addListener(() { + if (mounted) { + setState(() {}); + } + }); + + _backgroundColorAnimation = ColorTween( + begin: widget.closedBackgroundColor, + end: widget.openBackgroundColor, + ).animate(_animationController); + + _foregroundColorAnimation = ColorTween( + begin: widget.closedForegroundColor, + end: widget.openForegroundColor, + ).animate(_animationController); + + final double fractionOfOneSpeedDialChild = + 1.0 / widget.speedDialChildren.length; + for (int speedDialChildIndex = 0; + speedDialChildIndex < widget.speedDialChildren.length; + ++speedDialChildIndex) { + final List> tweenSequenceItems = + >[]; + + final double firstWeight = + fractionOfOneSpeedDialChild * speedDialChildIndex; + if (firstWeight > 0.0) { + tweenSequenceItems.add(TweenSequenceItem( + tween: ConstantTween(0.0), + weight: firstWeight, + )); + } + + tweenSequenceItems.add(TweenSequenceItem( + tween: Tween(begin: 0.0, end: 1.0), + weight: fractionOfOneSpeedDialChild, + )); + + final double lastWeight = fractionOfOneSpeedDialChild * + (widget.speedDialChildren.length - 1 - speedDialChildIndex); + if (lastWeight > 0.0) { + tweenSequenceItems.add(TweenSequenceItem( + tween: ConstantTween(1.0), weight: lastWeight)); + } + + _speedDialChildAnimations.insert( + 0, + TweenSequence(tweenSequenceItems) + .animate(_animationController)); + } + + super.initState(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + // + + int speedDialChildAnimationIndex = 0; + + return _animationController.isDismissed + ? GestureDetector( + onTap: () { + if (_animationController.isDismissed) { + _animationController.forward(); + } else { + _animationController.reverse(); + } + }, + child: Container( + width: 60, + height: 60, + clipBehavior: Clip.none, + padding: const EdgeInsets.all(14), + margin: EdgeInsets.only( + top: 18, + right: Directionality.of(context) == TextDirection.ltr ? 16 : 0, + left: Directionality.of(context) == TextDirection.rtl ? 16 : 0, + ), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + // borderRadius: BorderRadius.circular(60), + border: Border.all(color: AppColors.colorPrimary, width: 2), + ), + child: widget.child, + ), + ) + : GestureDetector( + onTap: () { + if (_animationController.isDismissed) { + _animationController.forward(); + } else { + _animationController.reverse(); + } + }, + child: OverflowBox( + maxWidth: MediaQuery.sizeOf(context).width + 32, + child: Container( + color: Colors.black.withOpacity(0.4), + width: MediaQuery.sizeOf(context).width + 32, + child: Column( + mainAxisSize: _animationController.isDismissed + ? MainAxisSize.max + : MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + if (!_animationController.isDismissed) + Padding( + padding: EdgeInsets.only( + right: Directionality.of(context) == TextDirection.ltr + ? 24 + : 0, + left: Directionality.of(context) == TextDirection.rtl + ? 24 + : 0, + ), + child: GestureDetector( + onTap: () { + if (_animationController.isDismissed) { + _animationController.forward(); + } else { + _animationController.reverse(); + } + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: widget.speedDialChildren + .map((SpeedDialChild speedDialChild) { + final Widget speedDialChildWidget = Opacity( + opacity: _speedDialChildAnimations[ + speedDialChildAnimationIndex] + .value, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + if (speedDialChild.label != null) + Padding( + padding: const EdgeInsets.only( + right: 16.0 - 4.0), + child: GestureDetector( + onTap: () => _onTap(speedDialChild), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0), + child: Text( + speedDialChild.label!, + style: widget.labelsStyle, + ), + ), + ), + ), + ScaleTransition( + scale: _speedDialChildAnimations[ + speedDialChildAnimationIndex], + child: GestureDetector( + onTap: () => _onTap(speedDialChild), + child: Container( + width: 45, + height: 45, + clipBehavior: Clip.none, + padding: const EdgeInsets.all(10), + margin: EdgeInsets.only( + top: 18, + right: Directionality.of(context) == + TextDirection.ltr + ? 14 + : 0, + left: Directionality.of(context) == + TextDirection.rtl + ? 14 + : 0, + ), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + // borderRadius: BorderRadius.circular(60), + border: Border.all( + color: AppColors.colorPrimary, + width: 2), + ), + child: speedDialChild.child, + ), + ), + ), + ], + ), + ); + speedDialChildAnimationIndex++; + return speedDialChildWidget; + }).toList(), + ), + ), + ), + GestureDetector( + onTap: () { + if (_animationController.isDismissed) { + _animationController.forward(); + } else { + _animationController.reverse(); + } + }, + child: Container( + width: 60, + height: 60, + clipBehavior: Clip.none, + padding: const EdgeInsets.all(14), + margin: EdgeInsets.only( + top: 18, + right: Directionality.of(context) == TextDirection.ltr + ? 32 + : 0, + left: Directionality.of(context) == TextDirection.rtl + ? 32 + : 0, + ), + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + // borderRadius: BorderRadius.circular(60), + border: Border.all( + color: AppColors.colorPrimary, width: 2), + ), + child: widget.child, + ), + ), + SizedBox(height: 24), + ], + ), + ), + ), + ); + } + + void _onTap(SpeedDialChild speedDialChild) { + if (speedDialChild.closeSpeedDialOnPressed) { + _animationController.reverse(); + } + speedDialChild.onPressed.call(); + } + +// Padding( +// padding: const EdgeInsets.symmetric(vertical: 4.0), +// child: FloatingActionButton( +// heroTag: speedDialChildAnimationIndex, +// mini: true, +// foregroundColor: speedDialChild.foregroundColor, +// backgroundColor: speedDialChild.backgroundColor, +// onPressed: () => _onTap(speedDialChild), +// child: speedDialChild.child, +// ), +// ) +} + +class SpeedDialChild { + const SpeedDialChild({ + required this.child, + required this.onPressed, + this.foregroundColor, + this.backgroundColor, + this.label, + this.closeSpeedDialOnPressed = true, + }); + + /// A widget to display as the [SpeedDialChild]. + final Widget child; + + /// A callback to be executed when the [SpeedDialChild] is pressed. + final Function onPressed; + + /// The [SpeedDialChild] foreground color. + final Color? foregroundColor; + + /// The [SpeedDialChild] background color. + final Color? backgroundColor; + + /// The text displayed next to the [SpeedDialChild] when the [SpeedDial] is open. + final String? label; + + /// Whether the [SpeedDial] should close after the [onPressed] callback of + /// [SpeedDialChild] is called. + /// + /// Defaults to [true]. + final bool closeSpeedDialOnPressed; +} diff --git a/lib/app/modules/splash/bindings/splash_screen_binding.dart b/lib/app/modules/splash/bindings/splash_screen_binding.dart new file mode 100644 index 0000000..957064a --- /dev/null +++ b/lib/app/modules/splash/bindings/splash_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/splash_screen_controller.dart'; + +class SplashScreenBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SplashScreenController(), + ); + } +} diff --git a/lib/app/modules/splash/controllers/splash_screen_controller.dart b/lib/app/modules/splash/controllers/splash_screen_controller.dart new file mode 100644 index 0000000..d1f6c25 --- /dev/null +++ b/lib/app/modules/splash/controllers/splash_screen_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class SplashScreenController extends GetxController { + //TODO: Implement SplashScreenController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/splash/views/splash_screen_view.dart b/lib/app/modules/splash/views/splash_screen_view.dart new file mode 100644 index 0000000..fbee77b --- /dev/null +++ b/lib/app/modules/splash/views/splash_screen_view.dart @@ -0,0 +1,49 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/res/app_dimensions.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +class SplashScreenView extends StatefulWidget { + const SplashScreenView({Key? key}) : super(key: key); + + @override + State createState() => _SplashScreenViewState(); +} + +class _SplashScreenViewState extends State { + @override + void initState() { + super.initState(); + Timer(const Duration(seconds: 4), () => Get.offAllNamed(Routes.INTRO_SCREEN)); + } + + @override + Widget build(BuildContext context) { + dp("Width int splash", {MediaQuery.sizeOf(Get.context!).width}); + dp("Height init splash ", MediaQuery.sizeOf(Get.context!).height); + return Scaffold( + backgroundColor: AppColors.colorPrimary, + body: Padding( + padding: EdgeInsets.symmetric( + horizontal: AppDimensions.screenHorizontalPadding, + vertical: AppDimensions.screenVerticalPadding), + child: Center( + child: AnimatedCrossFade( + duration: const Duration(milliseconds: 2000), + firstChild: SvgPicture.asset(AppAssets.lg_uco_logo_white), + secondChild: const Text( + '', + ), + alignment: Alignment.center, + crossFadeState: CrossFadeState.showFirst), + ), + ), + ); + } +} diff --git a/lib/app/modules/transaction_history/bindings/transaction_history_binding.dart b/lib/app/modules/transaction_history/bindings/transaction_history_binding.dart new file mode 100644 index 0000000..e9d8d50 --- /dev/null +++ b/lib/app/modules/transaction_history/bindings/transaction_history_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/transaction_history_controller.dart'; + +class TransactionHistoryBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => TransactionHistoryController(), + ); + } +} diff --git a/lib/app/modules/transaction_history/controllers/transaction_history_controller.dart b/lib/app/modules/transaction_history/controllers/transaction_history_controller.dart new file mode 100644 index 0000000..1f012c2 --- /dev/null +++ b/lib/app/modules/transaction_history/controllers/transaction_history_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class TransactionHistoryController extends GetxController { + //TODO: Implement TransactionHistoryController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/transaction_history/shared/hository_list_widget.dart b/lib/app/modules/transaction_history/shared/hository_list_widget.dart new file mode 100644 index 0000000..4b36445 --- /dev/null +++ b/lib/app/modules/transaction_history/shared/hository_list_widget.dart @@ -0,0 +1,149 @@ +import 'package:flutter/material.dart'; + +import 'package:uco_mobile_poc/app/res/app_colors.dart'; + +class HistoryListViewWidget extends StatelessWidget { + bool isCredit = false; + String type = ""; + String title = ""; + String shortTitle = ""; + String description = ""; + String dateTime = ""; + String balance = ""; + String dateMonth = ""; + String dateOfMonth = ""; + String year = ""; + String transactionId = ""; + String transactionIdNumber = ""; + Function()? onTap; + + HistoryListViewWidget({ + Key? key, + this.isCredit = false, + this.type = "", + this.title = "", + this.dateTime = "", + this.balance = "", + this.shortTitle = "", + this.description = "", + this.year = "", + this.dateMonth = "", + this.dateOfMonth = "", + this.transactionId = "", + this.transactionIdNumber = "", + this.onTap, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 0.0, vertical: 3), + child: Card( + elevation: 3, + color: AppColors.colorGrey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Container( + /**/ decoration: BoxDecoration( + color: AppColors.colorText.withOpacity(0.03), + borderRadius: BorderRadius.all(Radius.circular(50))), + child: Padding( + padding: + EdgeInsets.only(left: 10.0, top: 5, right: 10.0, bottom: 5), + child: Column( + children: [ + Row( + children: [ + Container( + padding: EdgeInsets.only(top: 5), + decoration: BoxDecoration( + color: AppColors.colorGrey100, + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: Column( + children: [ + Text(dateMonth, + style: Theme.of(context).textTheme.labelSmall), + Text(dateOfMonth, + style: Theme.of(context).textTheme.titleMedium), + Container( + decoration: BoxDecoration( + color: AppColors.colorGrey300, + borderRadius: BorderRadius.only( + bottomRight: Radius.circular(10), + bottomLeft: Radius.circular(10)), + ), + padding: EdgeInsets.symmetric( + vertical: 3, horizontal: 15), + height: 20, + child: Text(year, + style: + Theme.of(context).textTheme.labelSmall), + ) + ], + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LimitedBox( + maxWidth: 120, + child: Text("\$ $balance", + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .titleSmall)), + Row( + children: [ + Container( + height: 25, + width: 2.2, + color: AppColors.colorButton, + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + LimitedBox( + maxWidth: 120, + child: Text("Transaction ID", + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .labelSmall)), + LimitedBox( + maxWidth: 120, + child: Text(transactionIdNumber, + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .labelSmall)), + ], + ), + ), + ], + ), + ], + ), + ), + const Expanded(child: SizedBox()), + Icon(Icons.arrow_forward_ios_outlined, + size: 20, color: AppColors.colorText), + ], + ), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/transaction_history/views/transaction_history_view.dart b/lib/app/modules/transaction_history/views/transaction_history_view.dart new file mode 100644 index 0000000..65dce9b --- /dev/null +++ b/lib/app/modules/transaction_history/views/transaction_history_view.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/modules/transaction_history/shared/hository_list_widget.dart'; +import 'package:uco_mobile_poc/app/res/app_dimensions.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; +import '../controllers/transaction_history_controller.dart'; + +class TransactionHistoryView extends GetView { + const TransactionHistoryView({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textTransactionHistory), + onBackButtonPressed: () { + Get.back(); + }, + ), + + // AppBar( + // title: const Text('TransactionHistoryView'), + // centerTitle: true, + // ), + body: Padding( + padding: EdgeInsets.symmetric( + vertical: AppDimensions.screenVerticalPadding, + horizontal: AppDimensions.screenHorizontalPadding), + child: ListView.builder( + itemCount: 1, + itemBuilder: (context, index) { + return HistoryListViewWidget( + onTap: () { + Get.toNamed(Routes.ACCOUNT_STATEMENT); + }, + dateMonth: "Mar", + dateOfMonth: "17", + balance: "100", + year: "2024", + transactionIdNumber: "12345", + ); + }, + ), + ), + ); + } +} diff --git a/lib/app/modules/u_received/bindings/u_received_binding.dart b/lib/app/modules/u_received/bindings/u_received_binding.dart new file mode 100644 index 0000000..1162990 --- /dev/null +++ b/lib/app/modules/u_received/bindings/u_received_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/u_received_controller.dart'; + +class UReceivedBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => UReceivedController(), + ); + } +} diff --git a/lib/app/modules/u_received/controllers/u_received_controller.dart b/lib/app/modules/u_received/controllers/u_received_controller.dart new file mode 100644 index 0000000..ae090d1 --- /dev/null +++ b/lib/app/modules/u_received/controllers/u_received_controller.dart @@ -0,0 +1,363 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/extensions/build_context_ext.dart'; +import 'package:uco_mobile_poc/app/core/utils/SessionCache.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dropdown.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/DepositAccountResponse.dart'; +import 'package:uco_mobile_poc/app/models/accept_receive_transaction.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../models/u_recived_responce_model.dart'; +import '../../dashboard/controllers/dashboard_screen_controller.dart'; + +class UReceivedController extends GetxController { + final AppRepositories repository = Get.find(); + BuildContext context = Get.context as BuildContext; + UReceivedResponseData? selectedTransaction; + RxList uReceivedData = RxList.empty(); + String className = ""; + late InputField depositAccountField; + late InputField referenceCodeField; + TextEditingController pinPutController = TextEditingController(); + + TextEditingController referenceCodeController = TextEditingController(); + + // late InputField userTransactionPinField; + RxList allDepositAccounts = RxList.empty(); + + Rx selectedDepositAccount = DepositAccount.empty().obs; + + @override + Future onReady() async { + super.onReady(); + + Future.delayed(Duration.zero).then((value) { + selectedDepositAccount.value = allDepositAccounts.first.data as DepositAccount; + + depositAccountField.setText(allDepositAccounts.first.label); + + getPendingTransition(); + }); + } + + @override + void onInit() { + super.onInit(); + + for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + DepositAccount depositAccount = SessionCache.instance.depositAccountList.elementAt(i); + + allDepositAccounts.add( + DropDown(i.toString(), "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", depositAccount), + ); + } + } + + void updateSelectedDeposit(DropDown item) { + selectedDepositAccount.value = item.data as DepositAccount; + getPendingTransition(); + + dp("Data update", item); + } + + Future getPendingTransition() async { + ServerResponse response = await repository.getPendingTransition(selectedDepositAccount.value.mbmBkmsnumber); + dp("=========== u received request ", response.toString()); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + uReceivedData.assignAll(List.from(((response.response ?? []) as List).map((x) => UReceivedResponseData.fromMap(x)))); + + transitionUpdate.value++; + + dp("=========== u received request ", uReceivedData.toString()); + } + + void transactionPinDialog(BuildContext context, UReceivedController controller) { + clearController(); + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textTransactionPin), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + textInputAction: TextInputAction.done, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Text(TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.referenceCodeController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350, + ), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + textInputAction: TextInputAction.done, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.pinPutController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + if (controller.referenceCodeController.text.length != 6) { + Toasty.error("Please input 6 digit reference number"); + return; + } + + Navigator.of(context, rootNavigator: true).pop(); + sendAcceptTransactionRequest(controller.pinPutController.text, controller.referenceCodeController.text); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + Future acceptTransaction(UReceivedResponseData data) async { + selectedTransaction = data; + transactionPinDialog(context, this); + } + + Future sendAcceptTransactionRequest(String pin, String referanceCode) async { + AcceptReceiveTransactionModel request = AcceptReceiveTransactionModel( + porOrgacode: SessionCache.instance.userInfo.porOrgacode, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + cmpTranpin: pin, + cmpRefcode: referanceCode, + id: selectedTransaction!.id, + isAccepted: true, + ); + + ServerResponse response = await repository.acceptReceiveTransaction(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + + showCongratulationDialogOtp(context); + } + + /// Reverse transaction method + Future reverseTransactionRequest(String sgtSentGntrnumber, String sgtSentNodeId) async { + // ReverseTransactionModel request = ReverseTransactionModel( + // porOrgacode: SessionCache.instance.userInfo.porOrgacode, + // nodeId: sgtSentNodeId, + // sgtGntrnumber: sgtSentGntrnumber, + // ); + + ServerResponse response = await repository.reverseTransaction(sgtSentNodeId, sgtSentGntrnumber); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + showCongratulationDialogOtp(context); + } + + void clearController() { + pinPutController.clear(); + referenceCodeController.clear(); + } + + void showCongratulationDialogOtp(BuildContext context) { + Get.dialog( + responsiveWidget( + SizedBox( + width: context.getWidth, + child: Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Container( + height: 60, + width: 60, + padding: const EdgeInsets.only(bottom: 5), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: SvgPicture.asset( + AppAssets.ic_congratulations, + ), + ), + Padding( + padding: const EdgeInsets.only(top: 10.0), + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textCongratulations), + style: Theme.of(context).textTheme.titleSmall, + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 20), + Text( + "Your transaction reverse successfully!", + style: Theme.of(context).textTheme.bodySmall, + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 60.0, right: 60.0), + child: CustomButton( + onPressed: () { + onPressDone(context); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + buttonColor: AppColors.colorButton, + //sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1.0), + ), + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + void onPressDone(BuildContext context) { + Navigator.of(context, rootNavigator: true).pop(); + clearController(); + getPendingTransition(); + transitionUpdate.value++; + } +} diff --git a/lib/app/modules/u_received/views/u_received_view.dart b/lib/app/modules/u_received/views/u_received_view.dart new file mode 100644 index 0000000..b699fa7 --- /dev/null +++ b/lib/app/modules/u_received/views/u_received_view.dart @@ -0,0 +1,153 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/constants/form_field_constants.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_no_record.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_text.dart'; +import 'package:uco_mobile_poc/app/models/u_recived_responce_model.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; + +import '../controllers/u_received_controller.dart'; + +class UReceivedView extends GetView { + const UReceivedView({Key? key, this.showAppBar = true}) : super(key: key); + final bool showAppBar; + + @override + Widget build(BuildContext context) { + String className = runtimeType.toString().split('.').last; + controller.className = className; + return Scaffold( + appBar: showAppBar + ? DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textUReceived), + onBackButtonPressed: () { + Get.back(); + }, + ) + : null, + body: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 0), + child: controller.depositAccountField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}depositAccountField"), + controller: FormFieldConstants.instance().getController("${className}depositAccountField"), + labelText: "Select Account", + suffixIcon: const Icon(Icons.keyboard_arrow_down, size: 25), + isDropDown: true, + hintText: "Select account", + dropDownType: DropDownType.SPECIAL, + items: controller.allDepositAccounts, + onItemSelected: (item) { + controller.updateSelectedDeposit(item!); + }, + ), + ), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: Text(TranslationKeys.makeTranslation(TranslationKeys.textPendingRemittance), style: Theme.of(context).textTheme.bodyMedium), + ), + controller.uReceivedData.isNotEmpty + ? Expanded( + flex: 1, + child: ListView.builder( + itemCount: controller.uReceivedData.length, + itemBuilder: (context, index) { + UReceivedResponseData data = controller.uReceivedData[index]; + return Padding( + padding: const EdgeInsets.symmetric(vertical: 3.0, horizontal: 15.0), + child: Container( + decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(5.0)), border: Border.all(color: AppColors.colorGrey350, width: 1.5)), + child: ExpansionTile( + collapsedBackgroundColor: Colors.white, + tilePadding: const EdgeInsets.symmetric(vertical: 0, horizontal: 10), + dense: false, + // onExpansionChanged: controller.toggleExpansion(), + maintainState: true, + expandedAlignment: Alignment.topLeft, + expandedCrossAxisAlignment: CrossAxisAlignment.start, + childrenPadding: const EdgeInsets.all(10), + //tilePadding: EdgeInsets.all(8.0), + collapsedShape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + // collapsedBackgroundColor: AppColors.colorGrey350, + shape: const Border(), + backgroundColor: AppColors.white, + leading: Padding( + padding: const EdgeInsets.only(top: 3.0), + child: Text("${data.drPcrCurrshort} ${data.sgtGntramt}", style: Theme.of(context).textTheme.bodyMedium?.copyWith(color: AppColors.colorDialogBG)), + ), + trailing: const Icon( + Icons.keyboard_arrow_down_outlined, + size: 25, + color: AppColors.colorGrey700, + ), + title: Text(data.drmbmBkmstitle ?? "-", style: Theme.of(context).textTheme.labelMedium), + children: [ + // Text("${data.drPcrCurrshort} ${data.sgtGntramt}", style: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.colorButton)), + // const SizedBox(height: 5), + // Row( + // children: [ + // Text("Memo: ", style: Theme.of(context).textTheme.labelSmall), + // Text(data..toString(), style: Theme.of(context).textTheme.labelSmall), + // ], + // ), + const SizedBox(height: 5), + Row( + children: [ + Text("Sent: ", style: Theme.of(context).textTheme.labelSmall), + Text(data.drSgtGntrdate.toString(), style: Theme.of(context).textTheme.labelSmall), + ], + ), + const SizedBox(height: 5), + Text("Expires Date: ${data.expSgtGntrdate} ", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 5), + Text("Transaction-ID: ${data.sgtSentGntrnumber.toString()}${data.sgtSentNodeId}", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 5), + Text("Sender: ${data.drmbmBkmstitle}", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + InkWell( + onTap: () { + controller.reverseTransactionRequest(data.sgtSentGntrnumber, data.sgtSentNodeId); + }, + child: Column( + children: [SvgPicture.asset(AppAssets.ic_cross_option, height: 22, width: 22), const SizedBox(height: 5), CustomText(TranslationKeys.makeTranslation(TranslationKeys.textReverse))], + ), + ), + const SizedBox(width: 30), + InkWell( + onTap: () { + controller.acceptTransaction(data); + }, + child: Column( + children: [SvgPicture.asset(AppAssets.ic_tick_option, height: 22, width: 22), const SizedBox(height: 5), CustomText(TranslationKeys.makeTranslation(TranslationKeys.textReceived))], + ), + ), + ], + ), + ], + ), + ), + ); + }, + ), + ) + : const Center(child: CustomNoRecord(title: "No Record Found", description: "We couldn't find any activity at this moment")), + ], + ); + }), + ); + } +} diff --git a/lib/app/modules/u_send/bindings/u_send_binding.dart b/lib/app/modules/u_send/bindings/u_send_binding.dart new file mode 100644 index 0000000..2d8f95c --- /dev/null +++ b/lib/app/modules/u_send/bindings/u_send_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/u_send_controller.dart'; + +class USendBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => USendController(), + ); + } +} diff --git a/lib/app/modules/u_send/controllers/u_send_controller.dart b/lib/app/modules/u_send/controllers/u_send_controller.dart new file mode 100644 index 0000000..91c0a2f --- /dev/null +++ b/lib/app/modules/u_send/controllers/u_send_controller.dart @@ -0,0 +1,394 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +// import 'package:flutter_contacts/contact.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:uco_mobile_poc/app/core/config/server_response.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_contants.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/data/repositories/app_repositories.dart'; +import 'package:uco_mobile_poc/app/core/enums/request_constants.dart'; +import 'package:uco_mobile_poc/app/core/utils/SessionCache.dart'; +import 'package:uco_mobile_poc/app/core/utils/app_utils.dart'; +import 'package:uco_mobile_poc/app/core/utils/logs_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/field_validations.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_dropdown.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/models/AccountInquiryResponseModel.dart'; +import 'package:uco_mobile_poc/app/models/DepositAccountResponse.dart'; +import 'package:uco_mobile_poc/app/models/ExchangeRate.dart'; +import 'package:uco_mobile_poc/app/models/SendTransactionStep1ResponseModel.dart'; +import 'package:uco_mobile_poc/app/models/TransactionPinRequestModel.dart'; +import 'package:uco_mobile_poc/app/models/TransactionSubmitRequestModel.dart'; +import 'package:uco_mobile_poc/app/modules/qr_setting/controllers/qr_setting_controller.dart'; +import 'package:uco_mobile_poc/app/modules/qr_setting/views/qr_scan_screen.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +class USendController extends GetxController { + TextEditingController pinPutController = TextEditingController(); + TextEditingController referenceCodeController = TextEditingController(); + final AppRepositories repository = Get.find(); + + BuildContext context = Get.context as BuildContext; + + String OPTION_PHONE = "01"; + + String OPTION_EMAIL = "02"; + + //drop down + RxList allDepositAccounts = RxList.empty(); + + Rx selectedDepositAccount = DepositAccount.empty().obs; + + RxList allRecipientDetailOptions = RxList.empty(); + Rx selectedRecipientDetailOption = DropDown.empty().obs; + + RxList allCurrencieList = RxList.empty(); + DropDown selectedCurrency = DropDown.empty(); + RxString currencySymbol = "".obs; + + // Contact? selectedContact; + ExchangeRate? selectedExchangeRate; + String receiverAccountNumber = ""; + String receiverAccountTitle = ""; + + // fields + late InputField depositAccountField; + late InputField selectRecipientDetailField; + + // late InputField selectCurrencyField; + late InputField identityPhoneNumberField; + late InputField identityEmailField; + late InputField recipientCardNameField; + late InputField sendingAmountField; + late InputField exchangeRateField; + late InputField messageField; + late InputField userTransactionPinField; + late InputField referenceCodeField; + + // @override + // void onInit() { + // super.onInit(); + // + // for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + // DepositAccount depositAccount = SessionCache.instance.depositAccountList.elementAt(i); + // + // allDepositAccounts.add(DropDown(i.toString(), "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", depositAccount)); + // } + // + // selectedDepositAccount.value = allDepositAccounts.first.data; + // + // allRecipientDetailOptions.value = [ + // DropDown(OPTION_PHONE, TranslationKeys.makeTranslation(TranslationKeys.textPhoneNumber)), + // DropDown(OPTION_EMAIL, TranslationKeys.makeTranslation(TranslationKeys.textEmail)), + // ]; + // + // for (int i = 0; i < SessionCache.instance.exchangeRateList.length; i++) { + // ExchangeRate exchangeRate = SessionCache.instance.exchangeRateList.elementAt(i); + // allCurrencieList.add(DropDown(exchangeRate.pcrCurrcode, exchangeRate.pcrCurrdesc, exchangeRate)); + // } + // } + + @override + Future onReady() async { + super.onReady(); + + disposeAllResources(); + + updateSelectedDeposit(allDepositAccounts.elementAt(0)); + + Future.delayed(Duration.zero).then((value) { + depositAccountField.setText((allDepositAccounts.first.label)); + }); + } + + void disposeAllResources() { + depositAccountField.clear(); + selectRecipientDetailField.clear(); + // selectCurrencyField.clear(); + identityPhoneNumberField.clear(); + identityEmailField.clear(); + recipientCardNameField.clear(); + sendingAmountField.clear(); + exchangeRateField.clear(); + messageField.clear(); + userTransactionPinField.clear(); + referenceCodeField.clear(); + referenceCodeController.clear(); + } + + void updateSelectedDeposit(DropDown item) { + selectedDepositAccount.value = item.data as DepositAccount; + } + + void updateSelectedCurrency(/*DropDown? item*/ AccountInquiryResponseModel model) { + print("************************model>> $model"); + + for (int i = 0; i < SessionCache.instance.exchangeRateList.length; i++) { + print("************************elementAt(i).pcrCurrcode>> ${SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrcode}"); + if (SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrcode == model.pcrCurrcode) { + currencySymbol.value = SessionCache.instance.exchangeRateList.elementAt(i).pcrCurrshort; + selectedExchangeRate = SessionCache.instance.exchangeRateList.elementAt(i); + exchangeRateField.setText(selectedExchangeRate!.perEratrateact.toString()); + break; + } + } + } + + void updateRecipientDetail(DropDown? item) { + selectedRecipientDetailOption.value = item!; + } + + Future selectContact() async { + dynamic result = await Get.toNamed(Routes.CONTACTS_SCREEN); + + // if ((result != null && result[AppConstants.SELECTED_CONTACT] != null)) { + // selectedContact = result[AppConstants.SELECTED_CONTACT]; + // identityPhoneNumberField.setText(AppUtils.formatPhoneNumber(selectedContact!.phones.first.number) /*"${selectedContact!.displayName} (${AppUtils.formatPhoneNumber(selectedContact!.phones.first.number + ")")}"*/); + // } + } + + bool validate() { + bool isValid = FieldValidation.validateAll([ + depositAccountField, + selectRecipientDetailField, + recipientCardNameField, + sendingAmountField, + exchangeRateField, + userTransactionPinField, + referenceCodeField, + ]); + if (selectedRecipientDetailOption.value.id == OPTION_PHONE) { + isValid = FieldValidation.validateAll([identityPhoneNumberField]); + } else if (selectedRecipientDetailOption.value.id == OPTION_EMAIL) { + isValid = FieldValidation.validateAll([identityEmailField]); + } + dp("Validate value", isValid); + if (pinPutController.text.isEmpty) { + return false; + } + if (referenceCodeController.text.isEmpty) { + return false; + } + return isValid; + } + + Future sendTransaction({navigate = true}) async { + // + + // if (!validate()) { + // Toasty.error("Please input and then proceed"); + // return; + // } + + // TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel( + // porOrgacode: RequestConstants.porOrgacode, + // pctCstycode: RequestConstants.pctCstycode, + // channelCode: RequestConstants.channelCode, + // cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + // drMbmBkmsnumber: selectedDepositAccount.value.mbmBkmsnumber, + // drMbmBkmstitle: selectedDepositAccount.value.mbmBkmstitle, + // drPcrCurrcode: selectedDepositAccount.value.pcrCurrcode, + // drPcrCurrdesc: selectedDepositAccount.value.pcrCurrdesc, + // drPcrCurrshort: selectedDepositAccount.value.pcrCurrshort, + // crMbmBkmsnumber: receiverAccountNumber, + // crMbmBkmstitle: receiverAccountTitle, + // crPcrCurrcode: selectedExchangeRate!.pcrCurrcode, + // crPcrCurrdesc: selectedExchangeRate!.pcrCurrdesc, + // crPcrCurrshort: selectedExchangeRate!.pcrCurrshort, + // sgtGntrnarration: "", + // dmpProdCode: selectedDepositAccount.value.dmpProdcode, + // transType: "DR", + // notificationId: "", + // transMode: "Online", + // sgtGntramtfc: double.parse(sendingAmountField.getCustomText().isEmpty ? "0.0" : sendingAmountField.getCustomText()), + // otdTrancomment: messageField.getCustomText(), + // isOtpRequired: false, + // cmpRefcode: referenceCodeField.getCustomText(), + // ); + + TransactionPinRequestModel transactionPinRequestModel = TransactionPinRequestModel( + porOrgacode: RequestConstants.porOrgacode, + pctCstycode: RequestConstants.pctCstycode, + channelCode: RequestConstants.channelCode, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + email: SessionCache.instance.userInfo.cmpUserId, + pinType: "TRAN", + transPincode: userTransactionPinField.getCustomText(), + isOtpRequired: false, + ); + + ServerResponse response = await repository.sendTransactionStep1(transactionPinRequestModel); + + // if (response.isError) { + // Toasty.error(response.errorMsg); + // return; + // } + // + // SendTransactionStep1ResponseModel step1responseModel = SendTransactionStep1ResponseModel.fromMap(response.response); + // transactionSubmitRequestModel.notificationId = step1responseModel.notificationId.toString(); + + if (navigate) { + Get.toNamed(Routes.U_SEND_OTP, + // arguments: { + // AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + // AppConstants.EXCHANGE_RATE: exchangeRateField.getCustomText(), + // } + ); + } else { + Fluttertoast.showToast( + msg: "OTP successfully send to your email address", + ); + } + } + + void clearTransaction() { + selectRecipientDetailField.clear(); + identityPhoneNumberField.clear(); + identityEmailField.clear(); + recipientCardNameField.clear(); + sendingAmountField.clear(); + exchangeRateField.clear(); + messageField.clear(); + userTransactionPinField.clear(); + pinPutController.clear(); + referenceCodeField.clear(); + referenceCodeController.clear(); + } + + Future verifyAccountAgainstIt() async { + String valua = selectedRecipientDetailOption.value.id == OPTION_PHONE ? identityPhoneNumberField.getCustomText() : (selectedRecipientDetailOption.value.id == OPTION_EMAIL ? identityEmailField.getCustomText() : ""); + + bool isValid = true; + + if (selectedRecipientDetailOption.value.id == OPTION_PHONE) { + isValid = FieldValidation.validateAll([identityPhoneNumberField]); + } else if (selectedRecipientDetailOption.value.id == OPTION_EMAIL) { + isValid = FieldValidation.validateAll([identityEmailField]); + } + if (!isValid) { + Toasty.error("Please input and then proceed"); + return; + } + ServerResponse response = await repository.fetchAccountInquiry(selectedRecipientDetailOption.value.id, valua); + + if (response.isError) { + if (selectedRecipientDetailOption.value.id == OPTION_PHONE) { + identityPhoneNumberField.setError(response.errorMsg); + } else { + identityEmailField.setError(response.errorMsg); + } + // Toasty.error(response.errorMsg); + return; + } + + List responseData = response.response ?? []; + + List accountInquiryList; + accountInquiryList = AccountInquiryResponseModel.fromList(responseData); + + accountsDialog(accountInquiryList); + // AccountInquiryResponseModel transactionSubmitRequestModel = AccountInquiryResponseModel.fromMap(((response.response ?? {}) as Map).map((key, value) => MapEntry(key.toString(), value))); + } + + // void scanQr() async { + // Get.put(QrSettingController()); + // + // var scanResult = await Get.to(() => const QrScanScreen()); + // + // var resultJson = jsonDecode(scanResult); + // + // var accNumber = resultJson["phoneNumber"]; + // + // dp("Phone", accNumber); + // + // identityPhoneNumberField.setText(accNumber); + // + // verifyAccountAgainstIt(); + // } + + /// Accounts Dialogs...........u-send + void accountsDialog(List accountInquiryList) { + if (accountInquiryList.length == 1) { + receiverAccountTitle = accountInquiryList.first.mbmBkmstitle; + receiverAccountNumber = accountInquiryList.first.mbmBkmsnumber; + recipientCardNameField.setText(receiverAccountTitle); + updateSelectedCurrency(accountInquiryList.first); + return; + } + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textSelectAccount), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + ListView.separated( + shrinkWrap: true, + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + receiverAccountTitle = accountInquiryList[index].mbmBkmstitle; + receiverAccountNumber = accountInquiryList[index].mbmBkmsnumber; + recipientCardNameField.setText(receiverAccountTitle); + updateSelectedCurrency(accountInquiryList[index]); + Get.back(); + }, + child: Column(children: [ + Container( + height: 40, + width: double.infinity, + decoration: const BoxDecoration( + color: AppColors.colorGrey100, + borderRadius: BorderRadius.all(Radius.circular(8.0)), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("${accountInquiryList[index].mbmBkmstitle} (${accountInquiryList[index].pcrCurrshort})", style: Theme.of(context).textTheme.titleSmall), + Text(accountInquiryList[index].mbmBkmsnumber, style: Theme.of(context).textTheme.titleSmall), + ], + ), + ), + ), + ]), + ); + }, + separatorBuilder: (BuildContext context, int index) { + return const Padding(padding: EdgeInsets.symmetric(vertical: 5)); + }, + itemCount: accountInquiryList.length), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } +} diff --git a/lib/app/modules/u_send/views/u_send_view.dart b/lib/app/modules/u_send/views/u_send_view.dart new file mode 100644 index 0000000..8c30e83 --- /dev/null +++ b/lib/app/modules/u_send/views/u_send_view.dart @@ -0,0 +1,582 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:uco_mobile_poc/app/core/constants/app_assets.dart'; +import 'package:uco_mobile_poc/app/core/constants/form_field_constants.dart'; +import 'package:uco_mobile_poc/app/core/constants/translation_keys.dart'; +import 'package:uco_mobile_poc/app/core/utils/fields_utils.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/Fields/input_field.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_app_bar.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_button.dart'; +import 'package:uco_mobile_poc/app/custom_widgets/custom_toasty.dart'; +import 'package:uco_mobile_poc/app/res/app_colors.dart'; +import 'package:uco_mobile_poc/app/routes/app_pages.dart'; + +import '../controllers/u_send_controller.dart'; + +class USendView extends GetView { + const USendView({Key? key, this.showAppBar = true}) : super(key: key); + + final bool showAppBar; + + @override + Widget build(BuildContext context) { + Get.put(USendController()); + + String className = runtimeType.toString().split('.').last; + + return Scaffold( + appBar: showAppBar + ? DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textUSend), + onBackButtonPressed: () { + Get.back(); + }, + ) + : null, + body: Obx(() { + return Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + child: Card( + color: AppColors.colorGrey50, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + controller.depositAccountField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}depositAccountField"), + controller: FormFieldConstants.instance().getController("${className}depositAccountField"), + labelText: "Select From Account", + isDropDown: true, + hintText: "Select from account", + dropDownType: DropDownType.SPECIAL, + isRequired: true, + items: controller.allDepositAccounts, + onItemSelected: (item) { + controller.updateSelectedDeposit(item!); + }, + ), + controller.selectRecipientDetailField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}selectRecipientDetailField"), + controller: FormFieldConstants.instance().getController("${className}selectRecipientDetailField"), + labelText: "Recipient Detail", + isDropDown: true, + hintText: "Select recipient detail", + dropDownType: DropDownType.SPECIAL, + items: controller.allRecipientDetailOptions, + onItemSelected: (item) { + controller.updateRecipientDetail(item); + }, + ), + Column( + children: [ + Visibility( + visible: controller.selectedRecipientDetailOption.value.id == controller.OPTION_PHONE, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 8, + child: controller.identityPhoneNumberField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + keyboardType: TextInputType.phone, + refKey: FormFieldConstants.instance().getFormKey("${className}identityPhoneNumberField"), + controller: FormFieldConstants.instance().getController("${className}identityPhoneNumberField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textPhoneNumber), + hintText: "Select phone number", + onChanged: (val) { + controller.recipientCardNameField.clear(); + }, + // isCountryPicker: true, + suffixIcon: SizedBox( + width: 70, + child: Row( + children: [ + GestureDetector( + onTap: () { + // controller.scanQr(); + }, + child: const Icon(Icons.qr_code, size: 25, color: AppColors.colorPrimary)), + const SizedBox( + width: 8, + ), + InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + onTap: () { + controller.selectContact(); + }, + child: Padding( + padding: const EdgeInsets.all(5.0), + child: SvgPicture.asset(AppAssets.ic_select_contact, height: 25, width: 25), + ), + ), + ], + ), + ), + // readOnly: true, + // showCursor: false, + onClick: () { + // controller.selectContact(); + }, + )), + const SizedBox(width: 10), + Expanded( + flex: 2, + child: Column( + children: [ + const SizedBox(height: 35), + CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.verifyAccountAgainstIt(); + }, + textStyle: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w500, color: Colors.white), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + buttonColor: AppColors.colorButton), + ], + ), + ) + ], + ), + ), + Visibility( + visible: controller.selectedRecipientDetailOption.value.id == controller.OPTION_EMAIL, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 8, + child: controller.identityEmailField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + textInputAction: TextInputAction.done, + keyboardType: TextInputType.emailAddress, + refKey: FormFieldConstants.instance().getFormKey("${className}identityEmailField"), + controller: FormFieldConstants.instance().getController("${className}identityEmailField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textEmail), + hintText: "Enter your email", + onChanged: (val) { + controller.recipientCardNameField.clear(); + }, + // readOnly: true, + // showCursor: false, + onClick: () { + // controller.selectContact(); + }, + )), + const SizedBox(width: 10), + Expanded( + flex: 2, + child: Column( + children: [ + const SizedBox(height: 35), + CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.verifyAccountAgainstIt(); + }, + textStyle: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w500, color: Colors.white), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + buttonColor: AppColors.colorButton), + ], + ), + ) + ], + ), + ), + ], + ), + controller.recipientCardNameField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}recipientCardNameField"), + controller: FormFieldConstants.instance().getController("${className}recipientCardNameField"), + labelText: TranslationKeys.makeTranslation("Account Title"), + hintText: "Account title", + readOnly: true, + showCursor: false, + ), + // controller.selectCurrencyField = InputField( + // refKey: FormFieldConstants.instance().getFormKey("${className}selectCurrencyField"), + // controller: FormFieldConstants.instance().getController("${className}selectCurrencyField"), + // labelText: "Select Currency", + // isDropDown: true, + // hintText: "Select currency field", + // dropDownType: DropDownType.SPECIAL, + // items: controller.allCurrencieList, + // onItemSelected: (item) { + // controller.updateSelectedCurrency(item); + // }, + // suffixIcon: SizedBox( + // width: 100, + // height: 25, + // child: Row( + // mainAxisAlignment: MainAxisAlignment.end, + // children: [ + // Image.asset(AppAssets.ic_arrow_down_icon, height: 15, width: 15, color: AppColors.colorGrey500), + // const SizedBox(width: 10), + // Row( + // mainAxisAlignment: MainAxisAlignment.end, + // children: [ + // Container( + // width: 50, + // decoration: const BoxDecoration( + // color: AppColors.colorPrimary, + // borderRadius: BorderRadius.only( + // topRight: Radius.circular(50), + // bottomRight: Radius.circular(50), + // ), + // ), + // child: Center( + // child: Text( + // controller.currencySymbol.value, + // style: const TextStyle(color: AppColors.white, fontSize: 12, fontWeight: FontWeight.w600), + // ), + // ), + // ), + // ], + // ), + // ], + // ), + // ), + // ), + Row( + children: [ + Expanded( + flex: 1, + child: controller.sendingAmountField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + textInputAction: TextInputAction.done, + refKey: FormFieldConstants.instance().getFormKey("${className}sendingAmountField"), + controller: FormFieldConstants.instance().getController("${className}sendingAmountField"), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textSendingAmount), + isRequired: true, + keyboardType: const TextInputType.numberWithOptions(decimal: true), + inputFormatters: InputType.maxValueFilter(InputType.INT_MAX_VALUE_, true, 2), + ), + ), + const SizedBox(width: 10), + Expanded( + flex: 1, + child: controller.exchangeRateField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}exchangeRateField"), + controller: FormFieldConstants.instance().getController("${className}exchangeRateField"), + hintText: TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), + labelText: TranslationKeys.makeTranslation(TranslationKeys.textExchangeRate), + readOnly: true, + showCursor: false, + ), + ), + ], + ), + controller.userTransactionPinField = InputField( + enableInteractiveSelection: false, + refKey: FormFieldConstants.instance().getFormKey("${className}userTransactionPinField"), + controller: FormFieldConstants.instance().getController("${className}userTransactionPinField"), + hintText: "Enter transaction pin", + labelText: "Transaction Pin", + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isRequired: true, + isPassword: true, + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + transactionPinDialog(context, controller); + }, + ), + controller.referenceCodeField = InputField( + enableInteractiveSelection: false, + readOnly: true, + showCursor: false, + requiredPasswordIcon: true, + isRequired: true, + isPassword: true, + refKey: FormFieldConstants.instance().getFormKey("${className}referenceCodeField"), + controller: FormFieldConstants.instance().getController("${className}referenceCodeField"), + hintText: "Enter reference code", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.transactionPinLength), InputType.NUMBER], + onClick: () { + referenceCodeDialog(context, controller); + }, + ), + controller.messageField = InputField( + enableInteractiveSelection: false, + maxLines: 1, + refKey: FormFieldConstants.instance().getFormKey("${className}messageField"), + controller: FormFieldConstants.instance().getController("${className}messageField"), + hintText: "Enter message", + labelText: TranslationKeys.makeTranslation(TranslationKeys.textMessageMemo), + onSubmitted: (value) { + controller.sendTransaction(); + }, + ), + const SizedBox(height: 20), + Row( + children: [ + Expanded( + flex: 1, + child: CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.sendTransaction(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textSend), + buttonPadding: const EdgeInsets.symmetric(vertical: 11), + textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.white), + buttonColor: AppColors.colorButton, + ), + ), + const SizedBox(width: 10), + Expanded( + flex: 1, + child: CustomButton( + onPressed: () { + FocusScope.of(context).requestFocus(FocusNode()); + controller.clearTransaction(); + }, + buttonPadding: const EdgeInsets.symmetric(vertical: 11), + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textClear), + buttonColor: AppColors.colorSkipBtn, + textStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: AppColors.black), + sideBorder: const BorderSide(color: AppColors.colorBorderSkipBtn, width: 1), + ), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + ], + ); + }), + ); + } + + /// Pin Dialog...........Transactions + void transactionPinDialog(BuildContext context, USendController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textTransactionPin), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350, + ), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + textInputAction: TextInputAction.done, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.pinPutController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.userTransactionPinField.setText(controller.pinPutController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } + + /// Reference Dialog...........Transactions + void referenceCodeDialog(BuildContext context, USendController controller) { + Get.dialog( + responsiveWidget( + Dialog( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(10), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textReferenceCode), style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 20), + Wrap( + children: [ + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.referenceCodeController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith( + fontSize: 35, + fontWeight: FontWeight.w600, + color: AppColors.colorGrey350, + ), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + textInputAction: TextInputAction.done, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 50, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 40, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + beforeTextPaste: (text) { + return true; + }, + ), + ], + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 80.0, right: 80.0), + child: CustomButton( + onPressed: () async { + if (controller.referenceCodeController.text.length != 6) { + Toasty.error("Please input 6 digit transaction pin"); + return; + } + controller.referenceCodeField.setText(controller.referenceCodeController.text); + Navigator.of(context, rootNavigator: true).pop(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textContinue), + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), + buttonColor: AppColors.colorButton), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ), + barrierDismissible: false, + ); + } +} diff --git a/lib/app/modules/u_send_otp/bindings/u_send_otp_binding.dart b/lib/app/modules/u_send_otp/bindings/u_send_otp_binding.dart new file mode 100644 index 0000000..2ed046e --- /dev/null +++ b/lib/app/modules/u_send_otp/bindings/u_send_otp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/u_send_otp_controller.dart'; + +class USendOtpBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => USendOtpController(), + ); + } +} diff --git a/lib/app/modules/u_send_otp/controllers/u_send_otp_controller.dart b/lib/app/modules/u_send_otp/controllers/u_send_otp_controller.dart new file mode 100644 index 0000000..205af8e --- /dev/null +++ b/lib/app/modules/u_send_otp/controllers/u_send_otp_controller.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:timer_count_down/timer_controller.dart'; + + +import '../../../core/constants/app_contants.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/enums/request_constants.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/TransactionSubmitRequestModel.dart'; +import '../../../models/resend_otp_usend.dart'; +import '../../../routes/app_pages.dart'; + +class USendOtpController extends GetxController { + BuildContext context = Get.context as BuildContext; + final AppRepositories repository = Get.find(); + + TextEditingController pinPutController = TextEditingController(); + TransactionSubmitRequestModel transactionSubmitRequestModel = TransactionSubmitRequestModel.empty(); + String exchangeRate = ""; + + RxBool isResend = false.obs; + + CountdownController countdownController = CountdownController(autoStart: true); + + @override + Future onReady() async { + super.onReady(); + var arguments = Get.arguments; + transactionSubmitRequestModel = (arguments != null ? arguments[AppConstants.SEND_TRANS_STEP1_DATA] ?? TransactionSubmitRequestModel.empty() : TransactionSubmitRequestModel.empty()); + exchangeRate = (arguments != null ? arguments[AppConstants.EXCHANGE_RATE] ?? "" : ""); + } + + Future validatePinAndNavigate() async { + + if (pinPutController.text.isEmpty) { + Toasty.error("Please input and then proceed"); + return; + } + + if (pinPutController.text.length != 6) { + Toasty.error("Please enter a valid OTP"); + return; + } + + // transactionSubmitRequestModel.pinType = "TRAN"; + // + // transactionSubmitRequestModel.obpPincode = pinPutController.text; + + Get.toNamed(Routes.RECIPIENT_DETAILS, + // arguments: { + // AppConstants.SEND_TRANS_STEP1_DATA: transactionSubmitRequestModel, + // AppConstants.EXCHANGE_RATE: exchangeRate, + // } + ); + } + + + + void resenOtp() async { + + if (!isResend.value) { + Fluttertoast.showToast(msg: "Please wait for 1 minute"); + return; + } + + var responce = await repository.resendOtpUsend(ResendOtpUsendModel( + channelCode: RequestConstants.channelCode, + porOrgacode: RequestConstants.porOrgacode, + email: SessionCache.instance.userInfo.cmpUserId, + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + isOtpRequired: false, + pctCstycode: SessionCache.instance.userInfo.pctCstycode, + pinType: 'C_TRANPIN', + )); + + if (responce.isError) { + Fluttertoast.showToast(msg: responce.errorMsg); + return; + } + + isResend.value = false; + + countdownController.restart(); + + Fluttertoast.showToast(msg: "OTP send successfully"); + } + + void updateResend(bool send) { + isResend.value = send; + } +} diff --git a/lib/app/modules/u_send_otp/views/u_send_otp_view.dart b/lib/app/modules/u_send_otp/views/u_send_otp_view.dart new file mode 100644 index 0000000..43f0f83 --- /dev/null +++ b/lib/app/modules/u_send_otp/views/u_send_otp_view.dart @@ -0,0 +1,137 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; +import 'package:timer_count_down/timer_count_down.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../res/app_dimensions.dart'; +import '../../login_otp/controllers/o_t_p_screen_controller.dart'; +import '../../u_send/controllers/u_send_controller.dart'; +import '../controllers/u_send_otp_controller.dart'; + +class USendOtpView extends GetView { + const USendOtpView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: AppDimensions.screenHorizontalPadding, vertical: AppDimensions.screenVerticalPadding), + child: Obx(() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.textOTPDescription), + style: Theme.of(context).textTheme.bodySmall?.copyWith(height: 1.3), + ), + const SizedBox(height: 20), + // LabelText(TranslationKeys.makeTranslation(TranslationKeys.textOTP)), + PinCodeTextField( + autoDisposeControllers: false, + keyboardType: TextInputType.number, + controller: controller.pinPutController, + showCursor: true, + autoDismissKeyboard: false, + enablePinAutofill: true, + length: 6, + hintCharacter: "0", + textInputAction: TextInputAction.done, + appContext: context, + hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 35, fontWeight: FontWeight.w600, color: AppColors.colorGrey350), + mainAxisAlignment: MainAxisAlignment.center, + cursorColor: Colors.black.withOpacity(0.8), + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + selectedColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + inactiveColor: AppColors.colorGrey350, + /*Colors.black.withOpacity(0.6),*/ + activeColor: AppColors.colorGrey350, + fieldOuterPadding: const EdgeInsets.all(5), + shape: PinCodeFieldShape.box, + borderRadius: BorderRadius.circular(5), + fieldHeight: 60, + inactiveFillColor: AppColors.white, + selectedFillColor: AppColors.white, + fieldWidth: 50, + activeFillColor: Colors.white, + ), + animationDuration: const Duration(milliseconds: 100), + backgroundColor: Colors.transparent, + enableActiveFill: true, + onCompleted: (v) {}, + onChanged: (value) {}, + onSubmitted: (value) { + controller.validatePinAndNavigate(); + }, + beforeTextPaste: (text) { + return true; + }, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: AppDimensions.screenVerticalPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textOTPValid), style: Theme.of(context).textTheme.bodySmall), + const SizedBox(width: 10), + SvgPicture.asset(AppAssets.ic_clock_circle, height: 15, width: 15), + const SizedBox(width: 5), + Countdown( + controller: controller.countdownController, + seconds: 60, + build: (_, double time) => Text( + getTime(time.toInt()), + style: const TextStyle(fontSize: 12), + ), + interval: const Duration(seconds: 1), + onFinished: () { + controller.updateResend(true); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + Get.put(USendController()).sendTransaction(navigate: false); + }, + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textResend), + style: Theme.of(context).textTheme.titleSmall?.copyWith( + color: controller.isResend.value ? AppColors.colorPrimary : Colors.grey, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: CustomButton( + onPressed: () { + controller.validatePinAndNavigate(); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textVerify), + buttonColor: AppColors.colorButton, + buttonPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0), + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/user_activity/bindings/user_activity_binding.dart b/lib/app/modules/user_activity/bindings/user_activity_binding.dart new file mode 100644 index 0000000..9850db9 --- /dev/null +++ b/lib/app/modules/user_activity/bindings/user_activity_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/user_activity_controller.dart'; + +class UserActivityBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => UserActivityController(), + ); + } +} diff --git a/lib/app/modules/user_activity/controllers/user_activity_controller.dart b/lib/app/modules/user_activity/controllers/user_activity_controller.dart new file mode 100644 index 0000000..e737648 --- /dev/null +++ b/lib/app/modules/user_activity/controllers/user_activity_controller.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:intl/intl.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../custom_widgets/date_picker.dart'; +import '../../../models/UserActivity.dart'; +import '../../../models/UserActivityResponseModel.dart'; + +class UserActivityController extends GetxController { + RxBool isLoading = true.obs; + final dateFormat = DateFormat('yyyy-MM-dd'); + late BuildContext context; + + RxString fromDate = "----:--:--".obs; + RxString toDate = "----:--:--".obs; + + RxList userActivities = RxList.empty(); + final AppRepositories repository = Get.find(); + + /// Method for fetch User Activity Data + void fetchUserActivityData() async { + ServerResponse userActivityResponse = + await repository.fetchUserActivity(fromDate.value, toDate.value); + dp("msg user activity--------show data", userActivityResponse.toString()); + dp("msg user activity--------show data", userActivityResponse.runtimeType); + UserActivityResponseModel transactionsHistoryResponse = + UserActivityResponseModel.fromMap(userActivityResponse.response); + if (userActivityResponse.isError) { + Toasty.error( + TranslationKeys.makeTranslation(userActivityResponse.errorMsg)); + isLoading.value = false; + return; + } + + userActivities.assignAll(transactionsHistoryResponse.userActivity); + isLoading.value = false; + dp("User activity length", userActivities.length); + dp("User activity length", userActivities.toString()); + update(); + return; + } + + @override + Future onInit() async { + super.onInit(); + fromDate.value = + dateFormat.format(DateTime.now().subtract(const Duration(days: 30))); + toDate.value = dateFormat.format(DateTime.now()); + fetchUserActivityData(); + } + + void selectFromDate() async { + DateTime? fromDateTime = await DatePicker.showDatePicker(context); + if (fromDateTime != null) { + fromDate.value = dateFormat.format(fromDateTime); + toDate.value = "----:--:--"; + } + } + + void selectToDate() async { + if (fromDate.value == "----:--:--") { + Toasty.error(TranslationKeys.makeTranslation( + TranslationKeys.textSelectFromDateAndProceed)); + return; + } + DateTime? toDateTime = await DatePicker.showDatePicker(context); + if (toDateTime != null) { + toDate.value = dateFormat.format(toDateTime); + fetchUserActivityData(); + } + } +} diff --git a/lib/app/modules/user_activity/views/shared/date_time_dialog.dart b/lib/app/modules/user_activity/views/shared/date_time_dialog.dart new file mode 100644 index 0000000..73b9196 --- /dev/null +++ b/lib/app/modules/user_activity/views/shared/date_time_dialog.dart @@ -0,0 +1,89 @@ +import 'package:flutter/material.dart'; + +import '../../../../res/app_colors.dart'; + + +class DateTimeDialog extends StatelessWidget { + const DateTimeDialog({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + height: 30, + width: 50, + color: AppColors.colorText, + child: Column( + children: [ + SizedBox( + height: 15, + width: 30, + child: Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0)), + //this right here + child: SizedBox( + height: 33, + width: 90, + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Align( + alignment: Alignment.topRight, + child: Padding( + padding: EdgeInsets.only(bottom: 10.0), + child: Icon(Icons.close, + size: 40, color: AppColors.colorButton), + )), + const SizedBox( + height: 2, + ), + const Center( + child: Text( + "To verify your identify we sent a verification SMS. Please, enter the code we sent to", + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: AppColors.colorText), + ), + ), + const SizedBox( + height: 2, + ), + const Center( + child: Text( + "b***k@gmail.com/9232**", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: AppColors.colorText), + ), + ), + const SizedBox( + height: 2, + ), + Center( + child: InkWell( + onTap: () {}, + child: const Text( + "RESEND OTP", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w400, + color: AppColors.colorPrimary), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/user_activity/views/user_activity_view.dart b/lib/app/modules/user_activity/views/user_activity_view.dart new file mode 100644 index 0000000..7706693 --- /dev/null +++ b/lib/app/modules/user_activity/views/user_activity_view.dart @@ -0,0 +1,192 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_no_record.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/user_activity_controller.dart'; + +class UserActivityView extends GetView { + const UserActivityView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + controller.context = context; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.textUserActivityTitle), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Obx(() { + return Column(children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Card( + surfaceTintColor: Colors.white, + margin: + const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + elevation: 5.0, + child: Container( + padding: const EdgeInsets.all(8), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(10)) // Add border radius + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: SizedBox( + width: 120, + child: Padding( + padding: const EdgeInsets.only(left: 0, right: 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.calendar_month_rounded, + size: 18.0, + color: Colors.black.withOpacity(0.6), + ), + const SizedBox( + width: 5, + ), + Text( + controller.fromDate.value, + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 12), + ), + ], + ), + ), + ), + onTap: () { + controller.selectFromDate(); + }, + ), + Container( + height: 30, // Adjust the height as needed + width: 1, // Adjust the width as needed + color: Colors.grey, // Adjust the color as needed + ), + InkWell( + child: SizedBox( + width: 120, + child: Padding( + padding: const EdgeInsets.only(left: 0, right: 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.calendar_month_rounded, + size: 18.0, + color: Colors.black.withOpacity(0.6), + ), + const SizedBox( + width: 5, + ), + Text( + controller.toDate.value, + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontSize: 12), + ), + ], + ), + ), + ), + onTap: () { + controller.selectToDate(); + }, + ), + ], + ), + ), + ), + ), + const SizedBox(height: 5), + controller.isLoading.value + ? const SizedBox() + : controller.userActivities.isNotEmpty + ? Expanded( + flex: 2, + child: ListView.builder( + itemCount: controller.userActivities.length, + itemBuilder: (context, index) { + return Padding( + padding: EdgeInsets.only( + left: 10, + right: 10, + top: index == 0 ? 10 : 5, + bottom: index == + controller.userActivities.length - 1 + ? 10 + : 5), + child: Card( + surfaceTintColor: Colors.white, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + controller.userActivities[index].date + .toString(), + style: Theme.of(context) + .textTheme + .bodyMedium), + const SizedBox( + height: 10, + ), + Text( + controller + .userActivities[index].activity, + style: Theme.of(context) + .textTheme + .titleSmall), + const SizedBox( + height: 5, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "${TranslationKeys.makeTranslation(TranslationKeys.textUserActivityChannel)} ${controller.userActivities[index]?.channel ?? ' Found'}", + style: Theme.of(context) + .textTheme + .bodyMedium), + Text( + TranslationKeys.makeTranslation( + "${TranslationKeys.makeTranslation(TranslationKeys.textUserActivityDevice)}: ${controller.userActivities[index].deviceName}"), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + color: AppColors + .minusColor)), + ]), + ], + ), + ), + ), + ); + }, + ), + ) + : const CustomNoRecord( + title: "No Record Found", + description: + "We couldn't find any activity at this moment") + ]); + })); + } +} diff --git a/lib/app/modules/user_activity/views/widgets/user_activity_widget.dart b/lib/app/modules/user_activity/views/widgets/user_activity_widget.dart new file mode 100644 index 0000000..84c4c30 --- /dev/null +++ b/lib/app/modules/user_activity/views/widgets/user_activity_widget.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; + +import 'package:get/get_state_manager/src/simple/get_view.dart'; + +import '../../../../core/constants/translation_keys.dart'; +import '../../../../models/UserActivity.dart'; +import '../../../../res/app_colors.dart'; +import '../../controllers/user_activity_controller.dart'; + +class UserActivityWidget extends GetView { + UserActivity userActivity; + + UserActivityWidget({required this.userActivity}); + + @override + Widget build(BuildContext context) { + return Card( + surfaceTintColor: Colors.white, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(userActivity.date.toString(), + style: Theme.of(context).textTheme.bodyMedium), + const SizedBox( + height: 10, + ), + Text(userActivity.activity, + style: Theme.of(context).textTheme.titleSmall), + const SizedBox( + height: 5, + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + "${TranslationKeys.makeTranslation(TranslationKeys.textUserActivityChannel)}: ${userActivity.channel}", + style: Theme.of(context).textTheme.bodyMedium), + Text( + TranslationKeys.makeTranslation( + "${TranslationKeys.makeTranslation(TranslationKeys.textUserActivityDevice)}: ${userActivity.deviceName}"), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: AppColors.minusColor)), + ]), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/user_profile/bindings/user_profile_binding.dart b/lib/app/modules/user_profile/bindings/user_profile_binding.dart new file mode 100644 index 0000000..243104b --- /dev/null +++ b/lib/app/modules/user_profile/bindings/user_profile_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/user_profile_controller.dart'; + +class UserProfileBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => UserProfileController(), + ); + } +} diff --git a/lib/app/modules/user_profile/controllers/user_profile_controller.dart b/lib/app/modules/user_profile/controllers/user_profile_controller.dart new file mode 100644 index 0000000..be6c54f --- /dev/null +++ b/lib/app/modules/user_profile/controllers/user_profile_controller.dart @@ -0,0 +1,253 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:image/image.dart' as img; +// import 'package:image_picker/image_picker.dart'; + + +import '../../../core/config/server_response.dart'; +import '../../../core/constants/app_contants.dart'; +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/data/repositories/app_repositories.dart'; +import '../../../core/local_stoarge/app_storage.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/fields_utils.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../custom_widgets/custom_dropdown.dart'; +import '../../../custom_widgets/custom_toasty.dart'; +import '../../../models/DepositAccountResponse.dart'; +import '../../../models/upload_user_profile_model.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../views/account_details_view.dart'; +import '../views/profile_details_view.dart'; +import '../views/user_profile_view.dart'; + +class UserProfileController extends GetxController { + final AppRepositories repository = Get.find(); + + static bool isDarkMode = false; + static RxString cmpCustImage = "".obs; + static RxString selectedLocale = "en".obs; + + // ImagePicker imagePicker = ImagePicker(); + + late InputField firstNameField; + late InputField depositAccountField; + // static String? profilePic; + var profilePic = ''.obs; + List listOfTitles = [ + "Personal Details", + "Login Name", + "Mobile Number", + "Email Address", + ]; + RxList allDepositAccounts = RxList.empty(); + + Rx selectedDepositAccount = DepositAccount.empty().obs; + + void updateSelectedDeposit(DropDown item) { + selectedDepositAccount.value = item.data as DepositAccount; + dp("Drop Down item View==========", item); + } + + @override + void onInit() { + loadProfilePic(); + super.onInit(); + + /// Deposit accounts assign to Drop Down list + // for (int i = 0; i < SessionCache.instance.depositAccountList.length; i++) { + // DepositAccount depositAccount = SessionCache.instance.depositAccountList.elementAt(i); + // dp("=========Desposit All accounts============", depositAccount.toString()); + // allDepositAccounts.add( + // DropDown(i.toString(), "${depositAccount.mbmBkmstitle} - ${depositAccount.mbmBkmsnumber}", depositAccount), + // ); + // } + } + + void uploadUserProfilePicture() async { + if (profilePic == null || profilePic!.isEmpty) { + Toasty.error("Please select an image to upload."); + return; + } + + hideKeyBoard(); + UploadUserProfileModel request = UploadUserProfileModel( + cmpCustcode: SessionCache.instance.userInfo.cmpCustcode, + porOrgacode: SessionCache.instance.userInfo.porOrgacode, + cmpCustImage: "", + ); + + ServerResponse response = await repository.uploadUserProfilePicture(request); + if (response.isError) { + Toasty.error(response.errorMsg); + return; + } + cmpCustImage.value = profilePic.value; + Toasty.success("Profile picture updated successfully."); + } + + updateLanguage(Locale locale) async { + Get.updateLocale(locale); + // Get.find().saveLocale(locale.toString()); + // localeController.selectedLocale.value = locale.toString(); + + UserProfileController.selectedLocale.value = Get.locale!.languageCode; + await AppStorage.putString(AppConstants.SELECTED_LOCALE, UserProfileController.selectedLocale.value); + await AppStorage.putBoolean(AppConstants.IS_RTL, Directionality.of(Get.context!) == TextDirection.rtl); + Get.forceAppUpdate(); + update(); + } + + void navigateTo(meuType title) { + if (title == meuType.personalDetails) { + Get.to(const ProfileDetailsView()); + } else if (title == meuType.bankAccountDetails) { + Get.to(() => const AccountDetailsView()); + } else if (title == meuType.inviteFriends) { + // + // Share.share("UCO Digital - Apps on Google Play"); + } else if (title == meuType.changePass) { + Get.toNamed(Routes.changePassword); + } + } + + // void updateProfilePic({required bool fromCamera}) async { + // XFile? imageResult; + // + // if (fromCamera) { + // imageResult = await imagePicker.pickImage(source: ImageSource.camera); + // } else { + // imageResult = await imagePicker.pickImage(source: ImageSource.gallery); + // } + // + // Get.back(); + // + // if (imageResult != null) { + // // Read the image file as bytes + // Uint8List imageBytes = await imageResult.readAsBytes(); + // + // // Check the image size + // // double sizeInMB = imageBytes.length / (1024 * 1024); + // // if (sizeInMB > 1) { + // // Toasty.error("Image is more than 1MB. Please select a smaller image."); + // // return; + // // } + // + // // Decode the image + // img.Image? image = img.decodeImage(imageBytes); + // if (image != null) { + // // Resize the image to reduce its size + // img.Image resizedImage = img.copyResize(image, width: 800); // Adjust the width as needed + // + // // Encode the resized image to base64 + // profilePic.value = base64Encode(img.encodeJpg(resizedImage)); + // + // AppStorage.putString(SessionCache.instance.userInfo.cmpUserId, profilePic.value); + // // uploadUserProfilePicture(); + // update(); + // } else { + // Toasty.error("Failed to decode image."); + // } + // } + // } + // void updateProfilePic({required bool fromCamera}) async { + // XFile? imageResult; + // + // if (fromCamera) { + // imageResult = await imagePicker.pickImage(source: ImageSource.camera); + // } else { + // imageResult = await imagePicker.pickImage(source: ImageSource.gallery); + // } + // + // Get.back(); + // + // if (imageResult != null) { + // // Read the image file as bytes + // Uint8List imageBytes = await imageResult.readAsBytes(); + // + // // Decode the image + // img.Image? image = img.decodeImage(imageBytes); + // if (image != null) { + // // Resize the image to reduce its size + // img.Image resizedImage = img.copyResize(image, width: 800); // Adjust the width as needed + // + // // Encode the resized image to base64 + // profilePic = base64Encode(img.encodeJpg(resizedImage)); + // + // AppStorage.putString("ProfileImage", profilePic!); + // uploadUserProfilePicture(); + // update(); + // } else { + // Toasty.error("Failed to decode image."); + // } + // } + // } + + void removeProfilePic() { + AppStorage.delete(SessionCache.instance.userInfo.cmpUserId); + profilePic.value = ''; + update(); + Get.back(); + } + + void loadProfilePic() async { + // profilePic.value = await AppStorage.getString(SessionCache.instance.userInfo.cmpUserId); + // update(); + String? pic = await AppStorage.getString(SessionCache.instance.userInfo.cmpUserId); + profilePic.value = pic; + } + + void updateName() { + Get.defaultDialog( + title: "Update user name", + contentPadding: const EdgeInsets.only(left: 14, right: 14, bottom: 4), + content: Column( + children: [ + const SizedBox(height: 8), + firstNameField = InputField( + refKey: FormFieldConstants.instance().getFormKey("nameFeils"), + controller: FormFieldConstants.instance().getController("firstNameField"), + hintText: "User Name", + labelText: TranslationKeys.makeTranslation("User Name"), + isTopMarginRequired: false, + showLabel: false, + inputFormatters: [LengthLimitingTextInputFormatter(FieldUtils.userNameFieldLength)], + ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + CustomButton( + onPressed: () { + if (firstNameField.getCustomText().isEmpty) { + firstNameField.setError("Enter user name"); + return; + } + + var newUserDetails = SessionCache.instance.depositAccountList.first.copyWith(mbmBkmstitle: firstNameField.getCustomText()); + + SessionCache.instance.setDepositAccountList([newUserDetails].obs); + + update(); + + Get.back(); + }, + buttonText: "Update", + buttonPadding: const EdgeInsets.symmetric(vertical: 5, horizontal: 30), + textStyle: const TextStyle(fontWeight: FontWeight.w600, fontSize: 16, color: AppColors.black), + buttonColor: AppColors.colorSkipBtn, + ) + ], + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/user_profile/views/account_details_view.dart b/lib/app/modules/user_profile/views/account_details_view.dart new file mode 100644 index 0000000..35dc15c --- /dev/null +++ b/lib/app/modules/user_profile/views/account_details_view.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:share_plus/share_plus.dart'; + + +import '../../../core/constants/form_field_constants.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/Fields/input_field.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../controllers/user_profile_controller.dart'; +import 'profile_details_view.dart'; + +class AccountDetailsView extends GetView { + const AccountDetailsView({super.key}); + + @override + Widget build(BuildContext context) { + String className = runtimeType + .toString() + .split('.') + .last; + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation("Account Detail"), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only(left: 14, right: 21), + child: Obx(() { + return Column( + children: [ + controller.depositAccountField = InputField( + refKey: FormFieldConstants.instance().getFormKey("${className}depositAccountField"), + controller: FormFieldConstants.instance().getController("${className}depositAccountField"), + labelText: "Select From Account", + suffixIcon: const Icon(Icons.keyboard_arrow_down, size: 25), + isDropDown: true, + hintText: "Select from account", + dropDownType: DropDownType.SPECIAL, + items: controller.allDepositAccounts, + inputColor: Colors.black, + onItemSelected: (item) { + controller.updateSelectedDeposit(item!); + }, + ), + const SizedBox(height: 20), + ProfileDetailsTile( + title: 'Personal Details', + subtitle: controller.selectedDepositAccount.value.mbmBkmstitle.isEmpty ? "----" : controller.selectedDepositAccount.value.mbmBkmstitle, + ), + ProfileDetailsTile( + title: 'Account Number', + subtitle: controller.selectedDepositAccount.value.mbmBkmsnumber.isEmpty ? "----" : controller.selectedDepositAccount.value.mbmBkmsnumber, + widget: shareButton( + () { + String message = 'Account Number: ${controller.selectedDepositAccount.value.mbmBkmsnumber}'; + String subject = 'Subject for sharing'; + Share.share(message, subject: subject); + }, + ), + ), + ProfileDetailsTile( + title: 'IBAN Number', + subtitle: controller.selectedDepositAccount.value.mbmBkmsnumber.isEmpty ? "----" : controller.selectedDepositAccount.value.mbmBkmsnumber, + widget: shareButton( + () { + String message = 'IBAN Number: ${controller.selectedDepositAccount.value.mbmBkmsnumber}'; + String subject = 'Subject for sharing'; + Share.share(message, subject: subject); + }, + ), + ), + ProfileDetailsTile( + title: 'Account Opening Date', + subtitle: controller.selectedDepositAccount.value.mbmBkmsopendate.isEmpty ? "----" : controller.selectedDepositAccount.value.mbmBkmsopendate, + ), + ProfileDetailsTile( + title: 'Currency', + subtitle: controller.selectedDepositAccount.value.pcrCurrshort.isEmpty ? "----" :controller.selectedDepositAccount.value.pcrCurrshort, + ), + ], + ); + }), + ), + ), + ); + } + + GestureDetector shareButton(Function()? onTap) { + return GestureDetector( + onTap: onTap, + child: Container( + width: 80, + decoration: BoxDecoration( + color: AppColors.f0f0f0, + border: Border.all( + color: AppColors.c0c0c0, + ), + borderRadius: BorderRadius.circular(12), + ), + padding: const EdgeInsets.all(4), + child: Row( + children: [ + const SizedBox(width: 12), + Text( + TranslationKeys.makeTranslation(TranslationKeys.textShare), + style: Get.context!.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w400), + ), + const SizedBox(width: 7), + const Icon(Icons.share, size: 12, color: AppColors.colorPrimary), + const SizedBox(width: 4), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/user_profile/views/profile_details_view.dart b/lib/app/modules/user_profile/views/profile_details_view.dart new file mode 100644 index 0000000..315a757 --- /dev/null +++ b/lib/app/modules/user_profile/views/profile_details_view.dart @@ -0,0 +1,145 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/user_profile_controller.dart'; + +class ProfileDetailsView extends GetView { + const ProfileDetailsView({super.key}); + + @override + Widget build(BuildContext context) { + return responsiveWidget( + Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation("Profile"), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.only(left: 14, right: 21), + child: GetBuilder(builder: (controller) { + return Column( + children: [ + const SizedBox(height: 5), + ProfileDetailsTile( + title: 'Personal Details', + subtitle: '' + // SessionCache.instance.depositAccountList.first.mbmBkmstitle, + ), + ProfileDetailsTile( + title: 'Login Name', + subtitle: '' + // SessionCache.instance.userInfo.name, + ), + ProfileDetailsTile( + title: 'Mobile Number', + subtitle: '' + // SessionCache.instance.depositAccountList.first.padAdrsmobphone, + ), + ProfileDetailsTile( + title: 'Email Address', + subtitle: '' + // SessionCache.instance.userInfo.cmpUserId, + ), + ], + ); + }), + ), + ), + ); + } + + Widget editButton(BuildContext context, {void Function()? onTap}) { + return GestureDetector( + onTap: onTap, + child: Container( + width: 65, + decoration: BoxDecoration( + color: AppColors.f0f0f0, + border: Border.all( + color: AppColors.c0c0c0, + ), + borderRadius: BorderRadius.circular(12), + ), + padding: const EdgeInsets.all(4), + child: Row( + children: [ + const SizedBox( + width: 10, + ), + Text( + "Edit", + style: context.textTheme.bodyMedium!.copyWith(fontSize: 11, fontWeight: FontWeight.w400), + ), + const SizedBox( + width: 7, + ), + const Icon( + Icons.edit, + size: 12, + color: AppColors.colorPrimary, + ), + const SizedBox( + width: 2, + ), + ], + ), + ), + ); + } +} + +class ProfileDetailsTile extends StatelessWidget { + const ProfileDetailsTile({ + super.key, + required this.title, + required this.subtitle, + this.widget, + }); + + final String title; + final String subtitle; + final Widget? widget; + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + border: Border.all( + color: AppColors.colorGrey350, + ), + borderRadius: BorderRadius.circular(8)), + height: widget == null ? 60 : 91, + width: Get.width, + padding: const EdgeInsets.only(left: 12, right: 14, top: 12), + margin: const EdgeInsets.only(top: 14), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: context.textTheme.bodyMedium!.copyWith(fontSize: 10, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 4), + // Text( + // // subtitle, + // style: context.textTheme.bodyMedium!.copyWith(fontSize: 15, fontWeight: FontWeight.w400), + // ), + const SizedBox(height: 8), + widget ?? const SizedBox(), + widget == null + ? const SizedBox() + : const SizedBox( + height: 8, + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/user_profile/views/user_profile_view.dart b/lib/app/modules/user_profile/views/user_profile_view.dart new file mode 100644 index 0000000..93c8ddf --- /dev/null +++ b/lib/app/modules/user_profile/views/user_profile_view.dart @@ -0,0 +1,269 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../core/utils/SessionCache.dart'; +import '../../../core/utils/logs_utils.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/user_profile_controller.dart'; + +enum meuType { personalDetails, bankAccountDetails, inviteFriends, changePass } + +var menuList = [ + {"title": "Personal Details", "icons": AppAssets.ic_manage_account, "type": meuType.personalDetails}, + {"title": "Bank Account Details", "icons": AppAssets.bankDetails, "type": meuType.bankAccountDetails}, + {"title": "Invite Friends to UCO Digital", "icons": AppAssets.inviteFriendsUco, "type": meuType.inviteFriends}, + {"title": "Change Password", "icons": AppAssets.changePassoword, "type": meuType.changePass}, +]; + +class UserProfileView extends GetView { + const UserProfileView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + var name; + + try { + name = SessionCache.instance.userInfo.name.substring(0, 1); + } catch (e) { + name = "SA"; + } + + return responsiveWidget( + Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.textMyProfile), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Padding( + padding: const EdgeInsets.only(left: 14, right: 21), + child: GetBuilder(builder: (controller) { + return Column( + children: [ + const SizedBox(height: 20), + Align( + alignment: Alignment.center, + child: Card( + color: AppColors.colorGrey200, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(120)), + child: Container( + width: 130, + height: 130, + margin: const EdgeInsets.all(12), + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey900), + borderRadius: BorderRadius.circular(120), + image: (controller.profilePic?.isEmpty ?? true) + ? null + : DecorationImage( + image: MemoryImage( + base64Decode(controller.profilePic.value), + ), + fit: BoxFit.cover)), + child: Stack( + clipBehavior: Clip.none, + children: [ + (controller.profilePic?.isEmpty ?? true) ? Center(child: Text(name)) : const Center(), + Positioned( + bottom: -17, + left: 130 / 2 - 14, + child: GestureDetector( + onTap: () { + showProfileUpdateSheet(); + }, + child: Container( + width: 35, + height: 35, + decoration: BoxDecoration(color: AppColors.white, borderRadius: BorderRadius.circular(120)), + child: const Icon( + Icons.camera_alt_outlined, + color: AppColors.colorPrimary, + size: 18, + ), + ), + )) + ], + ), + ), + ), + ), + const SizedBox( + height: 20, + ), + // const + ...menuList + .map((Map e) => ProfileMenuTile( + iconPath: e["icons"]!!, + onTap: (title) { + dp("Menu", e["type"]); + controller.navigateTo(e["type"]); + }, + title: e["title"]!, + )) + .toList() + ], + ); + }), + ), + ), + ); + } +} + +class ProfileMenuTile extends StatelessWidget { + const ProfileMenuTile({ + super.key, + required this.iconPath, + required this.title, + required this.onTap, + }); + + final String iconPath; + final String title; + final Function(String) onTap; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + onTap: () { + onTap(title); + }, + child: Container( + decoration: BoxDecoration( + border: Border.all(color: AppColors.colorGrey350), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(6.0), + child: Card( + elevation: 0.0, + color: AppColors.colorGrey200, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(22))), + child: SvgPicture.asset( + iconPath, + height: 30, + width: 30, + ), + ), + ), + Text( + title, + style: context.textTheme.bodyMedium!.copyWith(fontSize: 13, fontWeight: FontWeight.w400), + ), + const Spacer(), + const Padding(padding: EdgeInsets.all(16.0), child: Icon(Icons.arrow_forward_ios_outlined, size: 15, color: AppColors.colorGrey700)) + ], + ), + ), + ), + ); + } +} + +showProfileUpdateSheet() { + Get.bottomSheet( + responsiveWidget( + GetBuilder(builder: (controller) { + return Stack( + fit: StackFit.loose, + children: [ + Align( + alignment: Alignment.bottomCenter, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey, width: 1), + borderRadius: const BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)), + ), + margin: const EdgeInsets.symmetric(horizontal: 20), + padding: const EdgeInsets.only(left: 20, right: 30, top: 20, bottom: 20), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Spacer(), + InkWell( + onTap: () { + Navigator.pop(Get.context!); + }, + child: SvgPicture.asset(AppAssets.ic_cross, width: 15, height: 15), + ), + ], + ), + const CircleAvatar( + radius: 16, + backgroundColor: AppColors.colorGrey300, + child: Icon(Icons.camera_alt_outlined, color: AppColors.colorPrimary, size: 15), + ), + const SizedBox(height: 20), + SizedBox( + width: 150, + child: Text( + "Change \nProfile Picture", + style: Get.context!.textTheme.bodyMedium!.copyWith(fontSize: 16, fontWeight: FontWeight.w400, color: AppColors.black, height: 2), + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 20), + btnTileB("Choose From Photos", () { + dp("", ""); + // controller.updateProfilePic(fromCamera: false); + }), + btnTileB("Take a photo", () { + dp("", ""); + // controller.updateProfilePic(fromCamera: true); + }), + btnTileB("Remove Profile Picture", () { + dp("", ""); + controller.removeProfilePic(); + }, color: Colors.red, textColor: AppColors.white), + ], + ), + ), + ), + ], + ); + }), + ), + useRootNavigator: true, + backgroundColor: Colors.transparent, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10))), + ); +} + +Widget btnTileB(String title, Function() onTap, {Color color = AppColors.E5E9F2, Color textColor = AppColors.c212121}) { + return GestureDetector( + onTap: onTap, + child: SizedBox( + height: 45, + width: Get.width, + child: Card( + elevation: 0.0, + color: color, + child: Center( + child: Text( + title, + style: Get.context!.textTheme.bodyMedium!.copyWith(fontSize: 13, fontWeight: FontWeight.w400, color: textColor), + )), + ), + ), + ); +} diff --git a/lib/app/modules/utility_bills_payment/bindings/utility_bills_payment_binding.dart b/lib/app/modules/utility_bills_payment/bindings/utility_bills_payment_binding.dart new file mode 100644 index 0000000..4fd2484 --- /dev/null +++ b/lib/app/modules/utility_bills_payment/bindings/utility_bills_payment_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/utility_bills_payment_controller.dart'; + +class UtilityBillsPaymentBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => UtilityBillsPaymentController(), + ); + } +} diff --git a/lib/app/modules/utility_bills_payment/controllers/utility_bills_payment_controller.dart b/lib/app/modules/utility_bills_payment/controllers/utility_bills_payment_controller.dart new file mode 100644 index 0000000..7f4f2bd --- /dev/null +++ b/lib/app/modules/utility_bills_payment/controllers/utility_bills_payment_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class UtilityBillsPaymentController extends GetxController { + //TODO: Implement UtilityBillsPaymentController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/utility_bills_payment/views/utility_bills_payment_view.dart b/lib/app/modules/utility_bills_payment/views/utility_bills_payment_view.dart new file mode 100644 index 0000000..14c3087 --- /dev/null +++ b/lib/app/modules/utility_bills_payment/views/utility_bills_payment_view.dart @@ -0,0 +1,370 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/utility_bills_payment_controller.dart'; + +class UtilityBillsPaymentView extends GetView { + const UtilityBillsPaymentView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation( + TranslationKeys.transUtilityBillCategory), + onBackButtonPressed: () { + Navigator.of(context).pop(); + }, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Text( + TranslationKeys.makeTranslation( + TranslationKeys.textPTCLLandLine), + style: Theme.of(context).textTheme.titleSmall)), + const SizedBox(height: 20), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textSelectAccountDetails), + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontSize: 14, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 10), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 10.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation( + TranslationKeys.textCreditCard), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + const Icon(Icons.keyboard_arrow_down_sharp, + color: AppColors.colorText), + ], + ), + ), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 5), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 10.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation( + TranslationKeys.textCreditCardNumber), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + const Icon(Icons.credit_card_rounded, + color: AppColors.colorText), + ], + ), + ), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textAmountDebit), + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontSize: 13, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 10), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation( + TranslationKeys.textEnterConsumerName), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + ], + ), + ), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textTotalAmount), + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontSize: 13, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + Container( + margin: const EdgeInsets.symmetric(horizontal: 0, vertical: 10), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation( + TranslationKeys.textEnterAmount), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + ], + ), + ), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetails), + style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillConsumerName), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillAmount), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillAmount), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDueDate), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textDueDate), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textAmountDueAfterDueDate), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillStatus), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textTotalAmount), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailCustomerName), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailZero), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailDate), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailZero), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 50), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailUnPaid), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text( + TranslationKeys.makeTranslation( + TranslationKeys.textBillDetailZero), + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith( + fontSize: 12, + color: AppColors.colorText, + fontWeight: FontWeight.w400)), + ], + ), + ], + ), + CustomButton( + buttonColor: AppColors.colorButton, + onPressed: () { + Get.offAllNamed(Routes.DASHBOARD_SCREEN); + }, + buttonText: + TranslationKeys.makeTranslation(TranslationKeys.textPayNow), + buttonPadding: + const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/utility_bills_selected_category/bindings/utility_bills_selected_category_binding.dart b/lib/app/modules/utility_bills_selected_category/bindings/utility_bills_selected_category_binding.dart new file mode 100644 index 0000000..16cb75e --- /dev/null +++ b/lib/app/modules/utility_bills_selected_category/bindings/utility_bills_selected_category_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/utility_bills_selected_category_controller.dart'; + +class UtilityBillsSelectedCategoryBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => UtilityBillsSelectedCategoryController(), + ); + } +} diff --git a/lib/app/modules/utility_bills_selected_category/controllers/utility_bills_selected_category_controller.dart b/lib/app/modules/utility_bills_selected_category/controllers/utility_bills_selected_category_controller.dart new file mode 100644 index 0000000..affb675 --- /dev/null +++ b/lib/app/modules/utility_bills_selected_category/controllers/utility_bills_selected_category_controller.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../bill_management/views/bill_management_view.dart'; + +class UtilityBillsSelectedCategoryController extends GetxController { + + BillType? selectedBillType = Get.arguments; + late String description; + late AssetImage image; + + @override + void onReady() { + super.onReady(); + description = Get.arguments[1]; + image = Get.arguments[2]; + } +} diff --git a/lib/app/modules/utility_bills_selected_category/views/utility_bills_selected_category_view.dart b/lib/app/modules/utility_bills_selected_category/views/utility_bills_selected_category_view.dart new file mode 100644 index 0000000..0f975b0 --- /dev/null +++ b/lib/app/modules/utility_bills_selected_category/views/utility_bills_selected_category_view.dart @@ -0,0 +1,139 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/utility_bills_selected_category_controller.dart'; + +class UtilityBillsSelectedCategoryView extends GetView { + const UtilityBillsSelectedCategoryView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + var args = Get.arguments; + + var icon = args["icon"]; + + var type = args["billTypes"]; + + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.transUtilityBillCategory), + onBackButtonPressed: () { + Get.back(); + }, + ), + body: Column( + children: [ + Stack( + children: [ + Container(height: 50, decoration: BoxDecoration(color: AppColors.colorPrimary.withOpacity(0.98), borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(40)))), + Column(children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Card( + surfaceTintColor: Colors.white, + margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 20), + elevation: 5.0, + child: Container( + padding: const EdgeInsets.all(8), + decoration: const BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(10)) // Add border radius + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Image.asset(AppAssets.ic_government), + )), + Expanded( + flex: 4, + child: Padding( + padding: const EdgeInsets.only(left: 12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationKeys.makeTranslation(TranslationKeys.transUtilityElectricity), + style: Theme.of(context).textTheme.titleSmall, + ), + const SizedBox(height: 5), + Text( + TranslationKeys.makeTranslation(type), + style: Theme.of(context).textTheme.bodySmall, + ), + ], + ), + )), + Expanded(flex: 1, child: SvgPicture.asset(icon)), + ], + )), + ), + ), + // Align( + // alignment: AppSettingController.isRTL.value + // ? Alignment.centerRight + // : Alignment.centerLeft, + // child: Padding( + // padding: + // EdgeInsets.symmetric(horizontal: 20, vertical: 10), + // child: Text( + // TranslationKeys.makeTranslation( + // TranslationKeys.textEnterConsumerName), + // style: Theme.of(context).textTheme.titleSmall), + // )), + Container( + margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 18), + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(20.0), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextField( + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w400, fontSize: 12), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + border: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: TranslationKeys.makeTranslation(TranslationKeys.textEnterConsumerName), + ), + // onChanged: (value) => controller.filterList(value), + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: CustomButton( + buttonColor: AppColors.colorButton, + onPressed: () { + Get.toNamed( + Routes.UTILITY_BILLS_SELECTED_CATEGORY_DETAILS, + ); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + ), + ), + ]) + ], + ), + ], + ), + ); + } +} diff --git a/lib/app/modules/utility_bills_selected_category_details/bindings/utility_bills_selected_category_details_binding.dart b/lib/app/modules/utility_bills_selected_category_details/bindings/utility_bills_selected_category_details_binding.dart new file mode 100644 index 0000000..09d9a4d --- /dev/null +++ b/lib/app/modules/utility_bills_selected_category_details/bindings/utility_bills_selected_category_details_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/utility_bills_selected_category_details_controller.dart'; + +class UtilityBillsSelectedCategoryDetailsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => UtilityBillsSelectedCategoryDetailsController(), + ); + } +} diff --git a/lib/app/modules/utility_bills_selected_category_details/controllers/utility_bills_selected_category_details_controller.dart b/lib/app/modules/utility_bills_selected_category_details/controllers/utility_bills_selected_category_details_controller.dart new file mode 100644 index 0000000..926e9a7 --- /dev/null +++ b/lib/app/modules/utility_bills_selected_category_details/controllers/utility_bills_selected_category_details_controller.dart @@ -0,0 +1,23 @@ +import 'package:get/get.dart'; + +class UtilityBillsSelectedCategoryDetailsController extends GetxController { + //TODO: Implement UtilityBillsSelectedCategoryDetailsController + + final count = 0.obs; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + void increment() => count.value++; +} diff --git a/lib/app/modules/utility_bills_selected_category_details/views/utility_bills_selected_category_details_view.dart b/lib/app/modules/utility_bills_selected_category_details/views/utility_bills_selected_category_details_view.dart new file mode 100644 index 0000000..3903f9b --- /dev/null +++ b/lib/app/modules/utility_bills_selected_category_details/views/utility_bills_selected_category_details_view.dart @@ -0,0 +1,131 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; + + +import '../../../core/constants/app_assets.dart'; +import '../../../core/constants/translation_keys.dart'; +import '../../../custom_widgets/custom_app_bar.dart'; +import '../../../custom_widgets/custom_button.dart'; +import '../../../res/app_colors.dart'; +import '../../../routes/app_pages.dart'; +import '../controllers/utility_bills_selected_category_details_controller.dart'; + +class UtilityBillsSelectedCategoryDetailsView extends GetView { + const UtilityBillsSelectedCategoryDetailsView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DashBoardAppBar( + title: TranslationKeys.makeTranslation(TranslationKeys.transUtilityBillCategory), + onBackButtonPressed: () { + Get.back(); + }, + ), + persistentFooterButtons: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: CustomButton( + buttonColor: AppColors.colorButton, + onPressed: () { + Get.toNamed(Routes.UTILITY_BILLS_PAYMENT); + }, + buttonText: TranslationKeys.makeTranslation(TranslationKeys.textNext), + buttonPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + ), + ), + ], + body: SingleChildScrollView( + child: Stack( + children: [ + Container(height: 120, decoration: BoxDecoration(color: AppColors.colorPrimary.withOpacity(0.98), borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(40)))), + Stack( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Card( + surfaceTintColor: Colors.white, + margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 50), + elevation: 5.0, + child: Container( + // height: 360, + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 25), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: Column( + children: [ + const SizedBox(height: 15), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailContent), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 15), + Container( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 75), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: AppColors.colorGrey350, width: 1.0)), + child: Text( + TranslationKeys.makeTranslation(TranslationKeys.textBillDetailBalance), + style: Theme.of(context).textTheme.titleSmall!.copyWith(color: AppColors.colorText), + )), + const SizedBox(height: 15), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailCustomerName), style: Theme.of(context).textTheme.titleSmall), + const SizedBox(height: 15), + Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailBillAmount), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailBillDueDate), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailBillAmountDue), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailBillAfterDueDate), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15, color: AppColors.colorText, fontWeight: FontWeight.w400)), + SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailBillStatus), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15, color: AppColors.colorText, fontWeight: FontWeight.w400)), + ], + ), + const SizedBox(width: 20), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailZero), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailDate), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailZero), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailZero), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + const SizedBox(height: 10), + Text(TranslationKeys.makeTranslation(TranslationKeys.textBillDetailUnPaid), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 14, color: AppColors.colorText, fontWeight: FontWeight.w400)), + ], + ), + ], + ), + ), + ], + ), + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(top: 25.0), + child: Image.asset(AppAssets.ic_government), + ), + ], + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/res/app_colors.dart b/lib/app/res/app_colors.dart new file mode 100644 index 0000000..4c544ff --- /dev/null +++ b/lib/app/res/app_colors.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; + +class AppColors { + static const colorPrimary = Color(0xfff5831f); + static const colorPrimaryLight = Color(0xffffdcac); + static const colorPrimaryDark = Color(0xffbb5f0f); + + static const colorSecondary = Color(0xffffffff); + static const colorTitle = Color(0xff5A5A5A); + static const colorText = Color(0xff7a7a7a); + + static const colorButton = Color(0xff30a240); + static const colorSpamText = Color(0xfff69b4b); + static const colorDialogBG = Color(0xffe2791d); + static const colorDialog = Color(0xffffd7d2); + + // Generals + static const white = Colors.white; + static const yellow = Colors.yellow; + static const black = Colors.black; + static const red = Colors.red; + static const transparent = Colors.transparent; + + // Gray and black + static const Color colorGrey50 = Color(0xFFF8FAFC); + static const Color colorGrey100 = Color(0xFFF5F5F5); + static const Color colorGrey200 = Color(0xFFEEEEEE); + static const Color colorGrey300 = Color(0xFFE0E0E0); + static const Color colorGrey350 = Color(0xFFD6D6D6); + static const Color colorGrey400 = Color(0xFFBDBDBD); + static const Color colorGrey500 = Color(0xFF9E9E9E); + static const Color colorGrey600 = Color(0xFF757575); + static const Color colorGrey700 = Color(0xFF616161); + static const Color colorGrey800 = Color(0xFF424242); + static const Color colorGrey850 = Color(0xFF333333); + static const Color colorGrey900 = Color(0xFF212121); + + static const Color colorNavyBlue = Color(0xFF1C274C); + static const titleColor = colorGrey700; + + /// General + static const colorSkipBtn = Color(0xFFf3e7bc); + static const colorBorderSkipBtn = Color(0xFFB79D3E); + + static const toolbarBackgroundColor = Color(0xFF1565a6); + + static var minusColor = Colors.red; + // Input Text + static const hintColor = colorPrimary; + static const inputErrorColor = Colors.red; + static const inputTextColor = colorPrimary; + static const inputLabelColor = colorPrimary; + static const colorFontPrimary = black; + static const colorFontSecondary = Color(0xFF344054); + static const c0c0c0 = Color(0xFFC0C0C0); + static const f0f0f0 = Color(0xFFF0F0F0); + + static const E5E9F2 = Color(0xFFE5E9F2); + + static const c212121 = Color(0xff212121); + static const c878787 = Color(0xff878787); + static const ff444444 = Color(0xff444444); + static const ffF95846 = Color(0xffF95846); + + static var CFCFCF = Color(0xffCFCFCF); + + static var F0F0D = Color(0xff0F0F0D); + static const colorRed = Color(0xffff0000); + static const FDF7F1 = Color(0xffFDF7F1); + + +} diff --git a/lib/app/res/app_dimensions.dart b/lib/app/res/app_dimensions.dart new file mode 100644 index 0000000..27262b9 --- /dev/null +++ b/lib/app/res/app_dimensions.dart @@ -0,0 +1,14 @@ +class AppDimensions { + static double screenHorizontalPadding = 20; + static double screenVerticalPadding = 20; + static double radiusBottomSheet = 20; + static double radiusButton = 50; + static double radiusCard = 10; + static double elevation = 5.0; + + // Input + static double inputRadius = 20; + + // Text + static double customTextSize = 12; +} diff --git a/lib/app/res/app_theme.dart b/lib/app/res/app_theme.dart new file mode 100644 index 0000000..36914fa --- /dev/null +++ b/lib/app/res/app_theme.dart @@ -0,0 +1,204 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'app_colors.dart'; +import 'app_dimensions.dart'; + +/// Created by Waqas Khurshid on 12/09/2023. +class AppThemeData { + // input field + static const inputLabelColor = AppColors.colorGrey700; + static const inputTextColor = AppColors.colorGrey700; + static const inputBackgroundColor = AppColors.colorGrey700; + static const inputHintColor = AppColors.colorGrey500; + static const inputBorderColor = AppColors.colorGrey500; + static const inputFocusedBorderColor = AppColors.colorGrey500; + static const inputDisabledBorderColor = AppColors.colorGrey300; + static const inputEnabledBorderColor = AppColors.colorGrey500; + static const inputErrorBackgroundColor = AppColors.transparent; + static const inputErrorBorderColor = AppColors.red; + static const inputErrorColor = AppColors.red; + + static BorderRadius borderRadius = const BorderRadius.all(Radius.circular(50.0)); + static const TextStyle labelStyle = TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: inputLabelColor); + static const TextStyle inputStyle = TextStyle(fontSize: 12, fontWeight: FontWeight.w400, color: inputTextColor); + static const TextStyle hintStyle = TextStyle(fontSize: 12, fontWeight: FontWeight.w400, color: inputHintColor); + static TextStyle errorStyle = const TextStyle(fontSize: 10, fontWeight: FontWeight.w400, color: inputErrorColor); + + // *************** button ****************** + static double buttonRadius = 50; + static double buttonHorizontlePadding = 10; + static double buttonVerticalPadding = 10; + static const Color buttonBackgroundColor = AppColors.colorButton; + static final OutlinedBorder buttonBorder = RoundedRectangleBorder(borderRadius: BorderRadius.circular(buttonRadius)); + static const TextStyle buttonTextStyle = TextStyle(fontSize: 12, fontWeight: FontWeight.w400, color: AppColors.white); + +// *************** App Bar ****************** + static const TextStyle appBarTextStyle = TextStyle(fontWeight: FontWeight.w600, fontSize: 14, color: AppColors.white); + +// *************** CustomText ****************** + static const textFieldsColor = AppColors.colorGrey700; + static final TextStyle textFieldStyle = TextStyle(fontWeight: FontWeight.w600, fontSize: AppDimensions.customTextSize, color: textFieldsColor); +} + +ThemeData appTheme() { + return ThemeData( + useMaterial3: false, + fontFamily: 'Roboto', + + /// AppBar Theme + appBarTheme: AppBarTheme( + //color: AppColors.appBar, + centerTitle: true, + backgroundColor: AppColors.colorPrimary, + elevation: AppDimensions.elevation, + systemOverlayStyle: const SystemUiOverlayStyle( + statusBarColor: AppColors.colorPrimary, + ), + titleTextStyle: const TextStyle(fontWeight: FontWeight.w700, fontSize: 14, color: AppColors.colorTitle), + iconTheme: const IconThemeData(color: AppColors.colorSecondary), + ), + + /// Floating Action Button Design + floatingActionButtonTheme: const FloatingActionButtonThemeData(backgroundColor: Colors.transparent), + + /// Titles And Text Theme + textTheme: const TextTheme( + ///Display Large Style + displayLarge: TextStyle(fontSize: 23, fontWeight: FontWeight.w500, color: AppColors.colorTitle), + displayMedium: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: AppColors.colorTitle), + displaySmall: TextStyle(fontSize: 15, fontWeight: FontWeight.w500, color: AppColors.colorText), + + /// Display Titles Style + titleLarge: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: AppColors.colorTitle), + titleMedium: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.colorTitle), + titleSmall: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.colorTitle), + + /// Display Body Style + bodyLarge: TextStyle(fontSize: 16, fontWeight: FontWeight.w400, color: AppColors.colorTitle), + bodyMedium: TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.colorTitle), + bodySmall: TextStyle(fontSize: 12, fontWeight: FontWeight.w400, color: AppColors.colorText), + + /// Display Label Style + labelLarge: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: AppColors.colorTitle), + labelMedium: TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: AppColors.colorText), + labelSmall: TextStyle(fontSize: 10, fontWeight: FontWeight.w400, color: AppColors.colorTitle), + ), + + /// Dialog Theme + dialogTheme: const DialogThemeData(shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))), elevation: 5.0, backgroundColor: AppColors.colorSecondary), + + /// Card Theme + cardTheme: CardThemeData( + color: AppColors.colorGrey50, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppDimensions.radiusCard), + ), + elevation: AppDimensions.elevation, + ), + + /// Input Decoration Theme + inputDecorationTheme: InputDecorationTheme( + isDense: true, + // Reduces the overall height of the TextFormField + errorMaxLines: 1, + // Limits the error message to one line + contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + border: const OutlineInputBorder( + borderSide: BorderSide(color: AppColors.transparent), + ), + errorStyle: GoogleFonts.inter( + textStyle: const TextStyle(fontSize: 10, fontWeight: FontWeight.w400, color: AppColors.colorPrimary), + ), + disabledBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: AppColors.transparent, + )), + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: AppColors.transparent, + )), + focusedBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: AppColors.transparent, + )), + errorBorder: const OutlineInputBorder( + borderSide: BorderSide( + color: AppColors.transparent, + )), + labelStyle: GoogleFonts.inter( + textStyle: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + color: AppColors.colorText, + ), + ), + hintStyle: GoogleFonts.inter( + textStyle: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + color: AppColors.colorText, + ), + ), + iconColor: AppColors.colorButton), + + /// Divider Theme + dividerTheme: const DividerThemeData( + color: Colors.transparent, + ), + + /// Elevated Button Theme + elevatedButtonTheme: ElevatedButtonThemeData( + style: ButtonStyle( + minimumSize: MaterialStateProperty.all(Size(AppDimensions.screenVerticalPadding, AppDimensions.screenVerticalPadding)), + backgroundColor: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.pressed)) { + return Colors.white54; + } else if (states.contains(MaterialState.disabled)) { + return Colors.white70; + } + return Colors.white70; + }, + ), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppDimensions.radiusCard), + //side: BorderSide(color: borderColor ?? Colors.transparent), + ), + ), + ), + ), + + /// CheckBox Theme + checkboxTheme: CheckboxThemeData( + checkColor: MaterialStateProperty.all(AppColors.colorButton), + fillColor: MaterialStateProperty.all(AppColors.colorButton), + //splashRadius: 10, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(AppDimensions.radiusCard)), + visualDensity: VisualDensity.compact, + side: BorderSide( + color: AppColors.colorButton, + width: AppDimensions.radiusCard, + style: BorderStyle.solid, + // strokeAlign: StrokeAlign.center) + ), + ), + dropdownMenuTheme: const DropdownMenuThemeData(inputDecorationTheme: InputDecorationTheme())); +} + +/// check is TabletDevice or Mobile +/// if Device is Tablet Resolution then this occur otherwise mobile Resolution occur +bool isTabletDevice(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + double screenHeight = MediaQuery.of(context).size.height; + + /// Define a threshold size to consider as a tablet + double tabletThreshold = 600.0; + + return screenWidth > tabletThreshold && screenHeight > tabletThreshold; +} + +// dynamic isDarkMode() async { +// return await AppStorage.getBoolean(AppConstants.IS_DARK_MODE, fallback: false); +// } diff --git a/lib/app/res/suppoted_languages.dart b/lib/app/res/suppoted_languages.dart new file mode 100644 index 0000000..214b4d1 --- /dev/null +++ b/lib/app/res/suppoted_languages.dart @@ -0,0 +1,13 @@ +import 'package:get/get_navigation/src/root/internacionalization.dart'; + +import '../l10n/Arabic.dart'; +import '../l10n/English.dart'; + + +class SupportedLanguages extends Translations { + @override + Map> get keys => { + ...English().keys, + ...Arabic().keys, + }; +} diff --git a/lib/app/routes/app_pages.dart b/lib/app/routes/app_pages.dart new file mode 100644 index 0000000..7359bd6 --- /dev/null +++ b/lib/app/routes/app_pages.dart @@ -0,0 +1,507 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:responsive_framework/responsive_framework.dart' as r; + +import '../modules/about_us/bindings/about_us_binding.dart'; +import '../modules/about_us/views/about_us_view.dart'; +import '../modules/account_statement/bindings/account_statement_binding.dart'; +import '../modules/account_statement/views/account_statement_view.dart'; +import '../modules/add_money/bindings/add_money_binding.dart'; +import '../modules/add_money/bindings/add_money_otp_binding.dart'; +import '../modules/add_money/bindings/payment_method_binding.dart'; +import '../modules/add_money/views/add_money_view.dart'; +import '../modules/add_money/views/shared/currency_list_screen.dart'; +import '../modules/add_money/views/shared/otp_add_money.dart'; +import '../modules/add_money/views/shared/payment_method_view.dart'; +import '../modules/add_new_account/bindings/add_new_binding.dart'; +import '../modules/add_new_account/views/add_new_account_view.dart'; +import '../modules/agent_location/bindings/agent_location_binding.dart'; +import '../modules/agent_location/views/agent_location_view.dart'; +import '../modules/app_intro/bindings/intro_screen_binding.dart'; +import '../modules/app_intro/views/intro_screen_view.dart'; +import '../modules/app_setting/bindings/app_setting_binding.dart'; +import '../modules/app_setting/views/app_setting_view.dart'; +import '../modules/beneficiary_management/bindings/beneficiary_management_binding.dart'; +import '../modules/beneficiary_management/views/beneficiary_management_view.dart'; +import '../modules/beneficiary_transfer_money/bindings/beneficiary_transfer_binding.dart'; +import '../modules/beneficiary_transfer_money/views/beneficiary_transfer_view.dart'; +import '../modules/beneficiary_transfer_money_otp/bindings/beneficiary_transfer_otp_binding.dart'; +import '../modules/beneficiary_transfer_money_otp/views/beneficiary_transfer_otp_view.dart'; +import '../modules/bill_management/bindings/bill_management_binding.dart'; +import '../modules/bill_management/views/bill_management_view.dart'; +import '../modules/bill_management_category/bindings/bill_management_category_binding.dart'; +import '../modules/bill_management_category/views/bill_management_category_view.dart'; +import '../modules/career/bindings/career_binding.dart'; +import '../modules/career/views/career_view.dart'; +import '../modules/change_transaction_pin/bindings/change_transaction_pin_binding.dart'; +import '../modules/change_transaction_pin/views/change_transaction_pin_view.dart'; + +// import '../modules/change_transaction_pin_otp/bindings/change_transaction_pin_otp_binding.dart'; +// import '../modules/change_transaction_pin_otp/views/change_transaction_pin_otp_view.dart'; +import '../modules/change_transaction_pin_otp/bindings/change_transaction_pin_otp_binding.dart'; +import '../modules/change_transaction_pin_otp/views/change_transaction_pin_otp_view.dart'; +import '../modules/cheque_activation/bindings/cheque_activation_binding.dart'; +import '../modules/cheque_activation/views/cheque_activation_view.dart'; +import '../modules/cheque_book_request_details/bindings/cheque_book_request_details_binding.dart'; +import '../modules/cheque_book_request_details/views/cheque_book_request_details_view.dart'; +import '../modules/cheque_deposit/bindings/cheque_deposit_binding.dart'; +import '../modules/cheque_deposit/views/cheque_deposit_view.dart'; +import '../modules/cheque_management/bindings/cheque_management_binding.dart'; +import '../modules/cheque_management/views/cheque_management_view.dart'; +import '../modules/cheque_request/bindings/cheque_request_binding.dart'; +import '../modules/cheque_request/views/cheque_request_view.dart'; +import '../modules/cheque_status/bindings/cheque_status_binding.dart'; +import '../modules/cheque_status/views/cheque_status_view.dart'; +import '../modules/cheque_status_history/bindings/cheque_status_history_binding.dart'; +import '../modules/cheque_status_history/views/cheque_status_history_view.dart'; +import '../modules/contacts_screen/bindings/contacts_screen_binding.dart'; +import '../modules/contacts_screen/views/contacts_screen_view.dart'; +import '../modules/create_transaction_pin/bindings/create_transaction_pin_binding.dart'; +import '../modules/create_transaction_pin/views/create_transaction_pin_view.dart'; +import '../modules/create_transaction_pin_otp/bindings/create_transaction_pin_otp_binding.dart'; +import '../modules/create_transaction_pin_otp/views/create_transaction_pin_otp_view.dart'; +import '../modules/dail_transaction_limit/bindings/dail_transaction_limit_binding.dart'; +import '../modules/dail_transaction_limit/views/dail_transaction_limit_view.dart'; +import '../modules/dashboard/bindings/dashboard_screen_binding.dart'; +import '../modules/dashboard/views/dashboard_screen_view.dart'; +import '../modules/faqs/bindings/faqs_binding.dart'; +import '../modules/faqs/bindings/faqs_first_screen_binding.dart'; +import '../modules/faqs/bindings/faqs_second_screen_binding.dart'; +import '../modules/faqs/bindings/faqs_third_screen_binding.dart'; +import '../modules/faqs/views/faqs_first_screen_view.dart'; +import '../modules/faqs/views/faqs_second_screen_view.dart'; +import '../modules/faqs/views/faqs_third_screen_view.dart'; +import '../modules/faqs/views/faqs_view.dart'; +import '../modules/general_ledger/bindings/general_ledger_binding.dart'; +import '../modules/general_ledger/views/general_ledger_view.dart'; +import '../modules/internal_account_transaction/bindings/internal_transaction_binding.dart'; +import '../modules/internal_account_transaction/views/internal_transaction_view.dart'; +import '../modules/internal_transaction_otp/bindings/internal_transaction_otp_binding.dart'; +import '../modules/internal_transaction_otp/views/internal_transaction_otp_view.dart'; +import '../modules/login/bindings/login_screen_binding.dart'; +import '../modules/login/views/login_screen_view.dart'; +import '../modules/login_otp/bindings/o_t_p_screen_binding.dart'; +import '../modules/login_otp/views/o_t_p_screen_view.dart'; +import '../modules/my_account/bindings/my_account_binding.dart'; +import '../modules/my_account/views/my_account_view.dart'; +import '../modules/new_beneficiary/bindings/new_beneficiary_binding.dart'; +import '../modules/new_beneficiary/views/new_beneficiary_view.dart'; +import '../modules/new_beneficiary_otp/bindings/new_beneficiary_otp_binding.dart'; +import '../modules/new_beneficiary_otp/views/new_beneficiary_otp_view.dart'; +import '../modules/notifications/bindings/notifications_binding.dart'; +import '../modules/notifications/views/notifications_view.dart'; +import '../modules/password_change/bindings/password_change_binding.dart'; +import '../modules/password_change/views/password_change_view.dart'; +import '../modules/privacy_policy/bindings/privacy_policy_binding.dart'; +import '../modules/privacy_policy/views/privacy_policy_view.dart'; +import '../modules/qr_setting/bindings/qr_setting_binding.dart'; +import '../modules/qr_setting/views/qr_scan_screen.dart'; +import '../modules/qr_setting/views/qr_setting_view.dart'; +import '../modules/qr_setting/views/qr_view_screen.dart'; +import '../modules/recipient_details/bindings/recipient_details_binding.dart'; +import '../modules/recipient_details/views/recipient_details_view.dart'; +import '../modules/sample_fields/bindings/sample_fields_binding.dart'; +import '../modules/sample_fields/views/sample_fields_view.dart'; +import '../modules/sign_up/bindings/sign_up_screen_otp_binding.dart'; +import '../modules/sign_up/bindings/sign_up_screen_step1_binding.dart'; +import '../modules/sign_up/bindings/sign_up_screen_step2_binding.dart'; +import '../modules/sign_up/bindings/sign_up_screen_step3_binding.dart'; +import '../modules/sign_up/views/sign_up_screen_otp_view.dart'; +import '../modules/sign_up/views/sign_up_screen_step1_view.dart'; +import '../modules/sign_up/views/sign_up_screen_step2_view.dart'; +import '../modules/sign_up/views/sign_up_screen_step3_view.dart'; +import '../modules/splash/bindings/splash_screen_binding.dart'; +import '../modules/splash/views/splash_screen_view.dart'; +import '../modules/transaction_history/bindings/transaction_history_binding.dart'; +import '../modules/transaction_history/views/transaction_history_view.dart'; +import '../modules/u_received/bindings/u_received_binding.dart'; +import '../modules/u_received/views/u_received_view.dart'; +import '../modules/u_send/bindings/u_send_binding.dart'; +import '../modules/u_send/views/u_send_view.dart'; +import '../modules/u_send_otp/bindings/u_send_otp_binding.dart'; +import '../modules/u_send_otp/views/u_send_otp_view.dart'; +import '../modules/user_activity/bindings/user_activity_binding.dart'; +import '../modules/user_activity/views/user_activity_view.dart'; +import '../modules/user_profile/bindings/user_profile_binding.dart'; +import '../modules/user_profile/views/user_profile_view.dart'; +import '../modules/utility_bills_payment/bindings/utility_bills_payment_binding.dart'; +import '../modules/utility_bills_payment/views/utility_bills_payment_view.dart'; +import '../modules/utility_bills_selected_category/bindings/utility_bills_selected_category_binding.dart'; +import '../modules/utility_bills_selected_category/views/utility_bills_selected_category_view.dart'; +import '../modules/utility_bills_selected_category_details/bindings/utility_bills_selected_category_details_binding.dart'; +import '../modules/utility_bills_selected_category_details/views/utility_bills_selected_category_details_view.dart'; + +part 'app_routes.dart'; + +class AppPages { + AppPages._(); + + static String INITIAL = Routes.SPLASH_SCREEN; + + static final routes = [ + GetPage( + name: _Paths.SPLASH_SCREEN, + page: () => responsiveWidget(const SplashScreenView()), + binding: SplashScreenBinding(), + ), + GetPage( + name: _Paths.INTRO_SCREEN, + page: () => responsiveWidget(IntroScreenView()), + binding: IntroScreenBinding(), + ), + GetPage( + name: _Paths.LOGIN_SCREEN, + page: () => responsiveWidget(const LoginScreenView()), + binding: LoginScreenBinding(), + ), + GetPage( + name: _Paths.DASHBOARD_SCREEN, + page: () => responsiveWidget(const DashboardScreenView()), + binding: DashboardScreenBinding(), + ), + GetPage( + name: _Paths.SIGN_UP_SCREEN_STEP1, + page: () => responsiveWidget(const SignUpScreenStep1View()), + binding: SignUpScreenStep1Binding(), + ), + GetPage( + name: _Paths.SIGN_UP_SCREEN_STEP2, + page: () => responsiveWidget(const SignUpScreenStep2View()), + binding: SignUpScreenStep2Binding(), + ), + GetPage( + name: _Paths.SIGN_UP_SCREEN_STEP3, + page: () => responsiveWidget(const SignUpScreenStep3View()), + binding: SignUpScreenStep3Binding(), + ), + GetPage( + name: _Paths.SIGN_UP_SCREEN_OTP, + page: () => responsiveWidget(const SignUpScreenOTPView()), + binding: SignUpScreenOTPBinding(), + ), + GetPage( + name: _Paths.O_T_P_SCREEN, + page: () => responsiveWidget(const OTPScreenView()), + binding: OTPScreenBinding(), + ), + GetPage( + name: _Paths.MY_ACCOUNT, + page: () => responsiveWidget(const MyAccountView()), + binding: MyAccountBinding(), + ), + GetPage( + name: _Paths.BILL_MANAGEMENT, + page: () => responsiveWidget(const BillManagementView()), + binding: BillManagementBinding(), + ), + GetPage( + name: _Paths.CHEQUE_MANAGEMENT, + page: () => responsiveWidget(const ChequeManagementView()), + binding: ChequeManagementBinding(), + ), + GetPage( + name: _Paths.U_SEND, + page: () => responsiveWidget(const USendView()), + binding: USendBinding(), + ), + GetPage( + name: _Paths.INTERNAL_ACCOUNT_TRANS, + page: () => responsiveWidget(const InternalAccountTransView()), + binding: InternalAccountTransBinding(), + ), + GetPage( + name: _Paths.U_RECEIVED, + page: () => responsiveWidget(const UReceivedView()), + binding: UReceivedBinding(), + ), + GetPage( + name: _Paths.BENEFICIARY_MANAGEMENT, + page: () => responsiveWidget(const BeneficiaryManagementView()), + binding: BeneficiaryManagementBinding(), + ), + GetPage( + name: _Paths.NEW_BENEFICIARY, + page: () => responsiveWidget(const NewBeneficiaryView()), + binding: NewBeneficiaryBinding(), + ), + GetPage( + name: _Paths.NEW_BENEFICIARY_OPT, + page: () => responsiveWidget(const NewBeneficiaryOtpView()), + binding: NewBeneficiaryOtpBinding(), + ), + GetPage( + name: _Paths.BENEFICIARY_TRANSFER_MONEY, + page: () => responsiveWidget(const BeneficiaryTransferView()), + binding: BeneficiaryTransferBinding(), + ), + GetPage( + name: _Paths.BENEFICIARY_TRANSFER_MONEY_OTP, + page: () => responsiveWidget(const BeneficiaryTransferOtpView()), + binding: BeneficiaryTransferOtpBinding(), + ), + // GetPage( + // name: _Paths.AGENT_LOCATION, + // page: () => responsiveWidget(const AgentLocationView()), + // binding: AgentLocationBinding(), + // ), + GetPage( + name: _Paths.ACCOUNT_STATEMENT, + page: () => responsiveWidget(const AccountStatementView()), + binding: AccountStatementBinding(), + ), + GetPage( + name: _Paths.USER_PROFILE, + page: () => responsiveWidget(const UserProfileView()), + binding: UserProfileBinding(), + ), + GetPage( + name: _Paths.PRIVACY_POLICY, + page: () => responsiveWidget(const PrivacyPolicyView()), + binding: PrivacyPolicyBinding(), + ), + GetPage( + name: _Paths.USER_ACTIVITY, + page: () => responsiveWidget(const UserActivityView()), + binding: UserActivityBinding(), + ), + GetPage( + name: _Paths.TRANSACTION_HISTORY, + page: () => responsiveWidget(const TransactionHistoryView()), + binding: TransactionHistoryBinding(), + ), + GetPage( + name: _Paths.ABOUT_US, + page: () => responsiveWidget(const AboutUsView()), + binding: AboutUsBinding(), + ), + GetPage( + name: _Paths.CAREER, + page: () => responsiveWidget(const CareerView()), + binding: CareerBinding(), + ), + // GetPage( + // name: _Paths.CONTACTS_SCREEN, + // page: () => responsiveWidget(const ContactsScreenView()), + // binding: ContactsScreenBinding(), + // ), + GetPage( + name: _Paths.RECIPIENT_DETAILS, + page: () => responsiveWidget(const RecipientDetailsView()), + binding: RecipientDetailsBinding(), + ), + GetPage( + name: _Paths.U_SEND_OTP, + page: () => responsiveWidget(const USendOtpView()), + binding: USendOtpBinding(), + ), + GetPage( + name: _Paths.SAMPLE_FIELDS, + page: () => responsiveWidget(const SampleFieldsView()), + binding: SampleFieldsBinding(), + ), + GetPage( + name: _Paths.INTRO_SCREEN, + page: () => responsiveWidget(IntroScreenView()), + binding: IntroScreenBinding(), + ), + GetPage( + name: _Paths.changePassword, + page: () => responsiveWidget(const ChangePasswordScreen()), + binding: ChangePasswordBindings(), + ), + GetPage( + name: _Paths.faqsView, + page: () => responsiveWidget(FaqsView()), + binding: FaqsBinding(), + ), + GetPage( + name: _Paths.BILL_MANAGEMENT_CATEGORY, + page: () => responsiveWidget(const BillManagementCategoryView()), + binding: BillManagementCategoryBinding(), + ), + GetPage( + name: _Paths.UTILITY_BILLS_PAYMENT, + page: () => responsiveWidget(const UtilityBillsPaymentView()), + binding: UtilityBillsPaymentBinding(), + ), + GetPage( + name: _Paths.UTILITY_BILLS_SELECTED_CATEGORY, + page: () => responsiveWidget(const UtilityBillsSelectedCategoryView()), + binding: UtilityBillsSelectedCategoryBinding(), + ), + GetPage( + name: _Paths.UTILITY_BILLS_SELECTED_CATEGORY_DETAILS, + page: () => responsiveWidget(const UtilityBillsSelectedCategoryDetailsView()), + binding: UtilityBillsSelectedCategoryDetailsBinding(), + ), + GetPage( + name: _Paths.CHEQUE_ACTIVATION, + page: () => responsiveWidget(const ChequeActivationView()), + binding: ChequeActivationBinding(), + ), + GetPage( + name: _Paths.CHEQUE_BOOK_REQUEST_DETAILS, + page: () => responsiveWidget(const ChequeBookRequestDetailsView()), + binding: ChequeBookRequestDetailsBinding(), + ), + GetPage( + name: _Paths.CHEQUE_DEPOSIT, + page: () => responsiveWidget(const ChequeDepositView()), + binding: ChequeDepositBinding(), + ), + GetPage( + name: _Paths.CHEQUE_REQUEST, + page: () => responsiveWidget(const ChequeRequestView()), + binding: ChequeRequestBinding(), + ), + GetPage( + name: _Paths.CHEQUE_STATUS, + page: () => responsiveWidget(const ChequeStatusView()), + binding: ChequeStatusBinding(), + ), + GetPage( + name: _Paths.CHEQUE_STATUS_HISTORY, + page: () => responsiveWidget(const ChequeStatusHistoryView()), + binding: ChequeStatusHistoryBinding(), + ), + GetPage( + name: _Paths.APP_SETTING, + page: () => responsiveWidget(const AppSettingView()), + binding: AppSettingBinding(), + ), + GetPage( + name: _Paths.DAIL_TRANSACTION_LIMIT, + page: () => responsiveWidget(const DailTransactionLimitView()), + binding: DailTransactionLimitBinding(), + ), + GetPage( + name: _Paths.CHANGE_TRANSACTION_PIN, + page: () => responsiveWidget(const ChangeTransactionPinView()), + binding: ChangeTransactionPinBinding(), + ), + // GetPage( + // name: _Paths.CHANGE_TRANSACTION_PIN_OTP, + // page: () => responsiveWidget(const ChangeTransactionPinOtpView()), + // binding: ChangeTransactionPinOtpBinding(), + // ), + // GetPage( + // name: _Paths.QR_SETTING, + // page: () => responsiveWidget(const QrSettingView()), + // binding: QrSettingBinding(), + // ), + GetPage( + name: _Paths.NOTIFICATIONS, + page: () => responsiveWidget(const NotificationsView()), + binding: NotificationsBinding(), + ), + GetPage( + name: _Paths.CREATE_TRANSACTION_PIN, + page: () => responsiveWidget(const CreateTransactionPinView()), + binding: CreateTransactionPinBinding(), + ), + GetPage( + name: _Paths.CREATE_TRANSACTION_PIN_OTP, + page: () => responsiveWidget(const CreateTransactionPinOtpView()), + binding: CreateTransactionPinOtpBinding(), + ), + GetPage( + name: _Paths.qrViewScreen, + page: () => responsiveWidget(const QrViewScreen()), + ), + // GetPage( + // name: _Paths.qrScanView, + // page: () => responsiveWidget(const QrScanScreen()), + // binding: QrSettingBinding(), + // ), + GetPage( + name: _Paths.GENERAL_LEDGER, + page: () => responsiveWidget(const GeneralLedgerView()), + binding: GeneralLedgerBinding(), + ), + GetPage( + name: _Paths.PAYMENT_METHOD, + page: () => responsiveWidget(const PaymentMethodView()), + binding: PaymentMethodBinding(), + ), + GetPage( + name: _Paths.ADD_MONEY, + page: () => responsiveWidget(const AddMoneyView()), + binding: AddMoneyBinding(), + ), + GetPage( + name: _Paths.OTP_ADD_MONEY, + page: () => responsiveWidget(const AddMoneyOTPView()), + binding: AddMoneyOTPBinding(), + ), + GetPage( + name: _Paths.currencyListScreen, + page: () => responsiveWidget(CurrencyListScreen()), + ), + GetPage( + name: _Paths.FAQS_FIRST_SCREEN, + page: () => responsiveWidget(FaqsFirstScreenView()), + binding: FaqsFirstBinding(), + ), + GetPage( + name: _Paths.FAQS_SECOND_SCREEN, + page: () => responsiveWidget(FaqsSecondScreenView()), + binding: FaqsSecondBinding(), + ), + GetPage( + name: _Paths.FAQS_THIRD_SCREEN, + page: () => responsiveWidget(FaqsThirdScreenView()), + binding: FaqsThirdBinding(), + ), + GetPage( + name: _Paths.ADD_NEW_ACCOUNT, + page: () => responsiveWidget(const AddNewAccountView()), + binding: AddNewAccountBinding(), + ), + GetPage( + name: _Paths.CHANGE_TRANSACTION_PIN_OTP, + page: () => responsiveWidget(const ChangeTransactionPinOtpView()), + binding: ChangeTransactionPinOtpBinding(), + ), + GetPage( + name: _Paths.INTERNAL_TRANSACTION_OPT, + page: () => responsiveWidget(const InternalTransactionOtpView()), + binding: InternalTransactionOtpBinding(), + ), + ]; +} + +Widget responsiveWidget(Widget page, {double? value, Color? color}) { + // return page; + // dp("Width init", {MediaQuery.sizeOf(Get.context!).width}); + // dp("Height init ", MediaQuery.sizeOf(Get.context!).height); + + return r.MaxWidthBox( + maxWidth: 1300, + background: ColoredBox( + color: color ?? Colors.white, + ), + alignment: Alignment.bottomCenter, + child: r.ResponsiveScaledBox( + width: r.ResponsiveValue(Get.context!, conditionalValues: [ + //tested on device widht 184,203,165,170 + // height 361 + r.Condition.between(start: 0, end: 229, value: value ?? 470), + + r.Condition.between(start: 230, end: 320, value: value ?? 440), + //tested on device widht 360, 450=410 + r.Condition.between(start: 321, end: 480, value: value ?? 410), + // tested on device width = 540, 617 + r.Condition.between(start: 481, end: 640, value: value ?? 450), + // 952, 915 + r.Condition.between(start: 641, end: 960, value: value ?? 600), + // + r.Condition.between(start: 961, end: 1024, value: value ?? 650), + // 1030 , 1098, 1277 + r.Condition.between(start: 1025, end: 1280, value: value ?? 700), + // 1287 , + r.Condition.between(start: 1281, end: 1300, value: value ?? 750), + ]).value, + child: page, + ), + ); +} diff --git a/lib/app/routes/app_routes.dart b/lib/app/routes/app_routes.dart new file mode 100644 index 0000000..87f8d09 --- /dev/null +++ b/lib/app/routes/app_routes.dart @@ -0,0 +1,147 @@ +part of 'app_pages.dart'; +// DO NOT EDIT. This is code generated via package:get_cli/get_cli.dart + +abstract class Routes { + Routes._(); + + static const SPLASH_SCREEN = _Paths.SPLASH_SCREEN; + static const INTRO_SCREEN = _Paths.INTRO_SCREEN; + static const LOGIN_SCREEN = _Paths.LOGIN_SCREEN; + static const DASHBOARD_SCREEN = _Paths.DASHBOARD_SCREEN; + static const SIGN_UP_SCREEN_STEP1 = _Paths.SIGN_UP_SCREEN_STEP1; + static const SIGN_UP_SCREEN_STEP2 = _Paths.SIGN_UP_SCREEN_STEP2; + static const SIGN_UP_SCREEN_STEP3 = _Paths.SIGN_UP_SCREEN_STEP3; + static const SIGN_UP_SCREEN_OTP = _Paths.SIGN_UP_SCREEN_OTP; + static const O_T_P_SCREEN = _Paths.O_T_P_SCREEN; + static const MY_ACCOUNT = _Paths.MY_ACCOUNT; + static const BILL_MANAGEMENT = _Paths.BILL_MANAGEMENT; + static const CHEQUE_MANAGEMENT = _Paths.CHEQUE_MANAGEMENT; + static const U_SEND = _Paths.U_SEND; + static const INTERNAL_ACCOUNT_TRANS = _Paths.INTERNAL_ACCOUNT_TRANS; + static const U_RECEIVED = _Paths.U_RECEIVED; + static const BENEFICIARY_MANAGEMENT = _Paths.BENEFICIARY_MANAGEMENT; + static const NEW_BENEFICIARY = _Paths.NEW_BENEFICIARY; + static const NEW_BENEFICIARY_OPT = _Paths.NEW_BENEFICIARY_OPT; + static const BENEFICIARY_TRANSFER_MONEY = _Paths.BENEFICIARY_TRANSFER_MONEY; + static const BENEFICIARY_TRANSFER_MONEY_OTP = _Paths.BENEFICIARY_TRANSFER_MONEY_OTP; + static const AGENT_LOCATION = _Paths.AGENT_LOCATION; + static const ACCOUNT_STATEMENT = _Paths.ACCOUNT_STATEMENT; + static const USER_PROFILE = _Paths.USER_PROFILE; + static const PRIVACY_POLICY = _Paths.PRIVACY_POLICY; + static const USER_ACTIVITY = _Paths.USER_ACTIVITY; + static const TRANSACTION_HISTORY = _Paths.TRANSACTION_HISTORY; + static const ABOUT_US = _Paths.ABOUT_US; + static const CAREER = _Paths.CAREER; + static const CONTACTS_SCREEN = _Paths.CONTACTS_SCREEN; + static const RECIPIENT_DETAILS = _Paths.RECIPIENT_DETAILS; + static const U_SEND_OTP = _Paths.U_SEND_OTP; + static const SAMPLE_FIELDS = _Paths.SAMPLE_FIELDS; + static const changePassword = _Paths.changePassword; + + static const faqsViews = _Paths.faqsView; + static const BILL_MANAGEMENT_CATEGORY = _Paths.BILL_MANAGEMENT_CATEGORY; + static const UTILITY_BILLS_PAYMENT = _Paths.UTILITY_BILLS_PAYMENT; + static const UTILITY_BILLS_SELECTED_CATEGORY = _Paths.UTILITY_BILLS_SELECTED_CATEGORY; + static const UTILITY_BILLS_SELECTED_CATEGORY_DETAILS = _Paths.UTILITY_BILLS_SELECTED_CATEGORY_DETAILS; + static const CHEQUE_ACTIVATION = _Paths.CHEQUE_ACTIVATION; + static const CHEQUE_BOOK_REQUEST_DETAILS = _Paths.CHEQUE_BOOK_REQUEST_DETAILS; + static const CHEQUE_DEPOSIT = _Paths.CHEQUE_DEPOSIT; + static const CHEQUE_REQUEST = _Paths.CHEQUE_REQUEST; + static const CHEQUE_STATUS = _Paths.CHEQUE_STATUS; + static const CHEQUE_STATUS_HISTORY = _Paths.CHEQUE_STATUS_HISTORY; + static const APP_SETTING = _Paths.APP_SETTING; + static const DAIL_TRANSACTION_LIMIT = _Paths.DAIL_TRANSACTION_LIMIT; + static const CHANGE_TRANSACTION_PIN = _Paths.CHANGE_TRANSACTION_PIN; + static const CHANGE_TRANSACTION_PIN_OTP = _Paths.CHANGE_TRANSACTION_PIN_OTP; + static const QR_SETTING = _Paths.QR_SETTING; + static const NOTIFICATIONS = _Paths.NOTIFICATIONS; + static const CREATE_TRANSACTION_PIN = _Paths.CREATE_TRANSACTION_PIN; + static const TRANSACTION_PIN_OTP = _Paths.TRANSACTION_PIN_OTP; + static const CREATE_TRANSACTION_PIN_OTP = _Paths.CREATE_TRANSACTION_PIN_OTP; + static const qrViewScreen = _Paths.qrViewScreen; + static const qrScanView = _Paths.qrScanView; + static const PAYMENT_METHOD = _Paths.PAYMENT_METHOD; + static const GENERAL_LEDGER = _Paths.GENERAL_LEDGER; + static const OTP_ADD_MONEY = _Paths.OTP_ADD_MONEY; + static const currencyListScreen = _Paths.currencyListScreen; + static const ADD_MONEY = _Paths.ADD_MONEY; + static const ADD_MONEY_OTP = _Paths.ADD_MONEY_OTP; + static const FAQS_FIRST_SCREEN = _Paths.FAQS_FIRST_SCREEN; + static const FAQS_SECOND_SCREEN = _Paths.FAQS_SECOND_SCREEN; + static const FAQS_THIRD_SCREEN = _Paths.FAQS_THIRD_SCREEN; + static const ADD_NEW_ACCOUNT = _Paths.ADD_NEW_ACCOUNT; + static const INTERNAL_TRANSACTION_OPT = _Paths.INTERNAL_TRANSACTION_OPT; +} + +abstract class _Paths { + _Paths._(); + + static const SPLASH_SCREEN = '/splash-screen'; + static const INTRO_SCREEN = '/intro-screen'; + static const LOGIN_SCREEN = '/login-screen'; + static const DASHBOARD_SCREEN = '/dashboard-screen'; + static const SIGN_UP_SCREEN_STEP1 = '/sign-up-screen-step1'; + static const SIGN_UP_SCREEN_STEP2 = '/sign-up-screen-step2'; + static const SIGN_UP_SCREEN_STEP3 = '/sign-up-screen-step3'; + static const SIGN_UP_SCREEN_OTP = '/sign-up-screen-otp'; + static const O_T_P_SCREEN = '/o-t-p-screen'; + static const MY_ACCOUNT = '/my-account'; + static const BILL_MANAGEMENT = '/bill-management'; + static const CHEQUE_MANAGEMENT = '/cheque-management'; + static const U_SEND = '/u-send'; + static const INTERNAL_ACCOUNT_TRANS = '/internal-account-trans'; + static const U_RECEIVED = '/u-received'; + static const BENEFICIARY_MANAGEMENT = '/beneficiary-management'; + static const NEW_BENEFICIARY = '/new-beneficiary'; + static const NEW_BENEFICIARY_OPT = '/new-beneficiary-otp'; + static const BENEFICIARY_TRANSFER_MONEY = '/beneficiary-transfer-money'; + static const BENEFICIARY_TRANSFER_MONEY_OTP = '/beneficiary-transfer-money-otp'; + static const AGENT_LOCATION = '/agent-location'; + static const ACCOUNT_STATEMENT = '/account-statement'; + static const USER_PROFILE = '/user-profile'; + static const PRIVACY_POLICY = '/privacy-policy'; + static const USER_ACTIVITY = '/user-activity'; + static const TRANSACTION_HISTORY = '/transaction-history'; + static const ABOUT_US = '/about-us'; + static const CAREER = '/career'; + static const CONTACTS_SCREEN = '/contacts-screen'; + static const RECIPIENT_DETAILS = '/recipient-details'; + static const U_SEND_OTP = '/u-send-otp'; + static const SAMPLE_FIELDS = '/sample-fields'; + static const changePassword = '/change-password'; + static const qrViewScreen = '/qrViewScreen'; + static const qrScanView = '/qrScanView'; + + static const faqsView = '/faqs-view'; + static const BILL_MANAGEMENT_CATEGORY = '/bill-management-category'; + static const UTILITY_BILLS_PAYMENT = '/utility-bills-payment'; + static const UTILITY_BILLS_SELECTED_CATEGORY = '/utility-bills-selected-category'; + static const UTILITY_BILLS_SELECTED_CATEGORY_DETAILS = '/utility-bills-selected-category-details'; + + static const CHEQUE_ACTIVATION = '/cheque-activation'; + static const CHEQUE_BOOK_REQUEST_DETAILS = '/cheque-book-request-details'; + static const CHEQUE_DEPOSIT = '/cheque-deposit'; + static const CHEQUE_REQUEST = '/cheque-request'; + static const CHEQUE_STATUS = '/cheque-status'; + static const CHEQUE_STATUS_HISTORY = '/cheque-status-history'; + static const APP_SETTING = '/app-setting'; + static const DAIL_TRANSACTION_LIMIT = '/dail-transaction-limit'; + static const CHANGE_TRANSACTION_PIN = '/change-transaction-pin'; + static const CHANGE_TRANSACTION_PIN_OTP = '/change-transaction-pin-otp'; + static const INTERNAL_TRANSACTION_OPT = '/internal-transaction-otp'; + static const QR_SETTING = '/qr-setting'; + static const NOTIFICATIONS = '/notifications'; + static const CREATE_TRANSACTION_PIN = '/create-transaction-pin'; + static const TRANSACTION_PIN_OTP = '/transaction-pin-otp'; + static const CREATE_TRANSACTION_PIN_OTP = '/create-transaction-pin-otp'; + static const PAYMENT_METHOD = '/payment-method'; + static const GENERAL_LEDGER = '/general-ledger'; + static const OTP_ADD_MONEY = '/otp-add-money'; + static const ADD_MONEY = '/add-money'; + static const ADD_MONEY_OTP = '/add-money_otp'; + static const currencyListScreen = '/CurrencyListScreen'; + static const FAQS_FIRST_SCREEN = '/faqs-first-screen'; + static const FAQS_SECOND_SCREEN = '/faqs-second-screen'; + static const FAQS_THIRD_SCREEN = '/faqs-third-screen'; + static const ADD_NEW_ACCOUNT = '/add-new-account'; +} diff --git a/lib/main.dart b/lib/main.dart index 7b7f5b6..c695bfb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,122 +1,123 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +// import 'package:flutter_dotenv/flutter_dotenv.dart'; +// import 'package:flutter_windowmanager/flutter_windowmanager.dart'; +import 'package:get/get.dart'; +import 'package:hive_flutter/hive_flutter.dart'; +import 'package:loader_overlay/loader_overlay.dart'; +import 'package:responsive_framework/responsive_framework.dart'; +import 'app/bindings/dependency_injections.dart'; +import 'app/core/config/connectivity_service.dart'; +import 'app/core/utils/root_detector_device.dart'; +import 'app/core/utils/simulator_check.dart'; +import 'app/custom_widgets/custom_toasty.dart'; +import 'app/res/app_colors.dart'; +import 'app/res/app_theme.dart'; +import 'app/res/suppoted_languages.dart'; +import 'app/routes/app_pages.dart'; -void main() { - runApp(const MyApp()); -} - -class MyApp extends StatelessWidget { - const MyApp({super.key}); +void main() async { + SystemChrome.setSystemUIOverlayStyle( + const SystemUiOverlayStyle( + statusBarColor: AppColors.colorPrimary, + ), + ); + WidgetsFlutterBinding.ensureInitialized(); + // await dotenv.load(); + bool isRootedOrJailbroken = await isDeviceRootedOrJailbroken(); + bool isDeviceEmulator = await isEmulator(); + if (isRootedOrJailbroken || isDeviceEmulator) { + /// Display an error message and exit the app + String errorMessage = isDeviceEmulator ? "This app cannot run on emulators or simulators." : "Rooted or jailbroken device detected."; + Toasty.error(errorMessage); + SystemChannels.platform.invokeMethod('SystemNavigator.pop'); + return; + // runApp(const RootedOrJailbrokenDeviceApp()); + } else { + /// Retrieve and decrypt the URL + // final encryption = UrlEncryption(); + // String encryptedUrl = UrlEncryption().encryptData('https://uco.mfsys.ca'); + // print('Encrypted URL: $encryptedUrl'); + // + // String decryptedUrl = UrlEncryption().decryptData(encryptedUrl); + // print('Decrypted URL: $decryptedUrl'); - // This widget is the root of your application. - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - // This is the theme of your application. - // - // TRY THIS: Try running your application with "flutter run". You'll see - // the application has a purple toolbar. Then, without quitting the app, - // try changing the seedColor in the colorScheme below to Colors.green - // and then invoke "hot reload" (save your changes or press the "hot - // reload" button in a Flutter-supported IDE, or press "r" if you used - // the command line to start the app). - // - // Notice that the counter didn't reset back to zero; the application - // state is not lost during the reload. To reset the state, use hot - // restart instead. - // - // This works for code too, not just values: Most code changes can be - // tested with just a hot reload. - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), - ), - home: const MyHomePage(title: 'Flutter Demo Home Page'), - ); + // FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE); + await Hive.initFlutter(); + runApp(const MyApp(apiKey: '',)); } } -class MyHomePage extends StatefulWidget { - const MyHomePage({super.key, required this.title}); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; +class MyApp extends StatefulWidget { + final String apiKey; + const MyApp({Key? key, required this.apiKey}) : super(key: key); @override - State createState() => _MyHomePageState(); + State createState() => _MyAppState(); } -class _MyHomePageState extends State { - int _counter = 0; +class _MyAppState extends State { + ThemeData themeData = ThemeData(); + ConnectivityHelper connectivityHelper = ConnectivityHelper(); - void _incrementCounter() { + void changeTheme(ThemeMode themeMode) { setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; + themeMode = themeMode; }); } + @override + void initState() { + // TODO: implement initState + super.initState(); + connectivityHelper.checkNetworkConnectivity(); + } + @override Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. - return Scaffold( - appBar: AppBar( - // TRY THIS: Try changing the color here to a specific color (to - // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar - // change color while the other colors stay the same. - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - ), - body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. - child: Column( - // Column is also a layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). - // - // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" - // action in the IDE, or press "p" in the console), to see the - // wireframe for each widget. - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text('You have pushed the button this many times:'), - Text( - '$_counter', - style: Theme.of(context).textTheme.headlineMedium, - ), - ], + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + + SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(statusBarColor: AppColors.colorPrimary)); + + return GlobalLoaderOverlay( + useDefaultLoading: false, + overlayColor: Colors.black.withOpacity(0.2), + overlayWidgetBuilder: (progress) => const CircularProgressIndicator(), + child: GestureDetector( + onTap: () { + SystemChannels.textInput.invokeMethod('TextInput.hide'); + }, + child: GetMaterialApp( + theme: appTheme(), + defaultTransition: Transition.rightToLeftWithFade, + darkTheme: appTheme(), + debugShowCheckedModeBanner: false, + initialRoute: AppPages.INITIAL, + getPages: AppPages.routes, + initialBinding: DependencysInjections(), + locale: const Locale("en"), + translations: SupportedLanguages(), + fallbackLocale: const Locale('en', 'ar'), + builder: (context, child) { + return ResponsiveBreakpoints.builder( + child: BouncingScrollWrapper.builder(context, child!), + breakpoints: [ + const Breakpoint(start: 0, end: 229, name: "m1"), + const Breakpoint(start: 230, end: 320, name: "m2"), + const Breakpoint(start: 321, end: 480, name: "m3"), + const Breakpoint(start: 481, end: 640, name: "m4"), + const Breakpoint(start: 641, end: 960, name: "m5"), + const Breakpoint(start: 961, end: 1024, name: "m6"), + const Breakpoint(start: 1025, end: 1280, name: "m7"), + const Breakpoint(start: 1281, end: 1300, name: "m8"), + ], + ); + }, ), ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: const Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. ); } } diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..e79846c --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,1514 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" + url: "https://pub.dev" + source: hosted + version: "67.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" + url: "https://pub.dev" + source: hosted + version: "6.4.1" + animated_toggle_switch: + dependency: "direct main" + description: + name: animated_toggle_switch + sha256: faecb2339cde5e7d299389cf7e01cf35305a3ba212ae8ff51c02ce8385d1d273 + url: "https://pub.dev" + source: hosted + version: "0.8.7" + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" + url: "https://pub.dev" + source: hosted + version: "2.0.3" + archive: + dependency: transitive + description: + name: archive + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + url: "https://pub.dev" + source: hosted + version: "3.6.1" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + asn1lib: + dependency: transitive + description: + name: asn1lib + sha256: "9a8f69025044eb466b9b60ef3bc3ac99b4dc6c158ae9c56d25eeccf5bc56d024" + url: "https://pub.dev" + source: hosted + version: "1.6.5" + async: + dependency: transitive + description: + name: async + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + url: "https://pub.dev" + source: hosted + version: "2.13.0" + auto_size_text: + dependency: "direct main" + description: + name: auto_size_text + sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + back_button_interceptor: + dependency: transitive + description: + name: back_button_interceptor + sha256: "8354b03320043db546e3f446af171faaa71384100486444113628f7db1e7fe9b" + url: "https://pub.dev" + source: hosted + version: "7.0.3" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: "4f64382b97504dc2fcdf487d5aae33418e08b4703fc21249e4db6d804a4d0187" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + buttons_tabbar: + dependency: "direct main" + description: + name: buttons_tabbar + sha256: "3f0969c26574ef15c0c9ff1dee42c3c4b0d3563d2c8607804372490fb8b76896" + url: "https://pub.dev" + source: hosted + version: "1.3.8" + calendar_date_picker2: + dependency: "direct main" + description: + name: calendar_date_picker2 + sha256: "7ff3f372faff6814a2ba69427d116fb9a3d52e28644b9de4b06db6638fdac798" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + camera: + dependency: "direct main" + description: + name: camera + sha256: dfa8fc5a1adaeb95e7a54d86a5bd56f4bb0e035515354c8ac6d262e35cec2ec8 + url: "https://pub.dev" + source: hosted + version: "0.10.6" + camera_android: + dependency: transitive + description: + name: camera_android + sha256: "50c0d1c4b122163e3d7cdfcd6d4cd8078aac27d0f1cd1e7b3fa69e6b3f06f4b7" + url: "https://pub.dev" + source: hosted + version: "0.10.10+14" + camera_avfoundation: + dependency: transitive + description: + name: camera_avfoundation + sha256: "11b4aee2f5e5e038982e152b4a342c749b414aa27857899d20f4323e94cb5f0b" + url: "https://pub.dev" + source: hosted + version: "0.9.23+2" + camera_platform_interface: + dependency: transitive + description: + name: camera_platform_interface + sha256: "98cfc9357e04bad617671b4c1f78a597f25f08003089dd94050709ae54effc63" + url: "https://pub.dev" + source: hosted + version: "2.12.0" + camera_web: + dependency: transitive + description: + name: camera_web + sha256: "57f49a635c8bf249d07fb95eb693d7e4dda6796dedb3777f9127fb54847beba7" + url: "https://pub.dev" + source: hosted + version: "0.3.5+3" + characters: + dependency: transitive + description: + name: characters + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" + url: "https://pub.dev" + source: hosted + version: "2.0.4" + chunked_stream: + dependency: transitive + description: + name: chunked_stream + sha256: b2fde5f81d780f0c1699b8347cae2e413412ae947fc6e64727cc48c6bb54c95c + url: "https://pub.dev" + source: hosted + version: "1.4.2" + circular_buffer: + dependency: transitive + description: + name: circular_buffer + sha256: b3a315fef3fee7fe58879643fc8ce21c7c2449d01c1a8a396dc9e24687f335c4 + url: "https://pub.dev" + source: hosted + version: "0.12.0" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" + source: hosted + version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + connectivity_plus: + dependency: "direct main" + description: + name: connectivity_plus + sha256: b5e72753cf63becce2c61fd04dfe0f1c430cc5278b53a1342dc5ad839eab29ec + url: "https://pub.dev" + source: hosted + version: "6.1.5" + connectivity_plus_platform_interface: + dependency: transitive + description: + name: connectivity_plus_platform_interface + sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + country_code_picker: + dependency: "direct main" + description: + name: country_code_picker + sha256: "92818885f0e47486539f80463b66f649970506a91dd3c0731ca3ba5308324a4d" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" + url: "https://pub.dev" + source: hosted + version: "0.3.5+2" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + csv: + dependency: transitive + description: + name: csv + sha256: c6aa2679b2a18cb57652920f674488d89712efaf4d3fdf2e537215b35fc19d6c + url: "https://pub.dev" + source: hosted + version: "6.0.0" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + dart_console: + dependency: transitive + description: + name: dart_console + sha256: "03c23e1f9cc3ac02b608f834808003e6510a5b292a0449f43dfac1c78bd8ee85" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" + url: "https://pub.dev" + source: hosted + version: "2.3.6" + dbus: + dependency: transitive + description: + name: dbus + sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270 + url: "https://pub.dev" + source: hosted + version: "0.7.12" + dcli: + dependency: transitive + description: + name: dcli + sha256: "881e88bbad0ada4e3a085a0b55e05afa8e4199392c0c45ac18e3dedc37305b9b" + url: "https://pub.dev" + source: hosted + version: "6.1.2" + dcli_common: + dependency: transitive + description: + name: dcli_common + sha256: f8f77bea6a6d7e4ec2dc24cb4f274fc582938057c2cba44ed0650195ecfcd3ad + url: "https://pub.dev" + source: hosted + version: "6.1.2" + dcli_core: + dependency: transitive + description: + name: dcli_core + sha256: "29fb4833aa950900936646190b30315db511a853273b9fe31d360e5f72c7560b" + url: "https://pub.dev" + source: hosted + version: "6.1.2" + dcli_terminal: + dependency: transitive + description: + name: dcli_terminal + sha256: fb50860855c6b2841aed5bcfb315fa83d1401e109691b6585773a24c149dc4b0 + url: "https://pub.dev" + source: hosted + version: "6.1.2" + device_info_plus: + dependency: "direct main" + description: + name: device_info_plus + sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 + url: "https://pub.dev" + source: hosted + version: "10.1.2" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f + url: "https://pub.dev" + source: hosted + version: "7.0.3" + dio: + dependency: "direct main" + description: + name: dio + sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" + url: "https://pub.dev" + source: hosted + version: "4.0.6" + dropdown_button2: + dependency: "direct main" + description: + name: dropdown_button2 + sha256: b0fe8d49a030315e9eef6c7ac84ca964250155a6224d491c1365061bc974a9e1 + url: "https://pub.dev" + source: hosted + version: "2.3.9" + encrypt: + dependency: "direct main" + description: + name: encrypt + sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2" + url: "https://pub.dev" + source: hosted + version: "5.0.3" + equatable: + dependency: transitive + description: + name: equatable + sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b" + url: "https://pub.dev" + source: hosted + version: "2.0.8" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + url: "https://pub.dev" + source: hosted + version: "1.3.3" + ffi: + dependency: transitive + description: + name: ffi + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_camera_overlay_new: + dependency: "direct main" + description: + name: flutter_camera_overlay_new + sha256: e7bdf4724c2355331c89dbb390c429fdf8307aef168ff1c9a8c9e0ed401e0f2f + url: "https://pub.dev" + source: hosted + version: "0.0.1" + flutter_contacts: + dependency: "direct main" + description: + name: flutter_contacts + sha256: "388d32cd33f16640ee169570128c933b45f3259bddbfae7a100bb49e5ffea9ae" + url: "https://pub.dev" + source: hosted + version: "1.1.9+2" + flutter_custom_clippers: + dependency: "direct main" + description: + name: flutter_custom_clippers + sha256: "473e3daf61c2a6cee0ad137393259a25223239d519a131c7ec1cac04d06e5407" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + flutter_dotenv: + dependency: "direct main" + description: + name: flutter_dotenv + sha256: b7c7be5cd9f6ef7a78429cabd2774d3c4af50e79cb2b7593e3d5d763ef95c61b + url: "https://pub.dev" + source: hosted + version: "5.2.1" + flutter_form_builder: + dependency: "direct main" + description: + name: flutter_form_builder + sha256: "560eb5e367d81170c6ade1e7ae63ecc5167936ae2cdfaae8a345e91bce19d2f2" + url: "https://pub.dev" + source: hosted + version: "9.2.1" + flutter_keyboard_visibility: + dependency: "direct main" + description: + name: flutter_keyboard_visibility + sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_keyboard_visibility_linux: + dependency: transitive + description: + name: flutter_keyboard_visibility_linux + sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_keyboard_visibility_macos: + dependency: transitive + description: + name: flutter_keyboard_visibility_macos + sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_keyboard_visibility_platform_interface: + dependency: transitive + description: + name: flutter_keyboard_visibility_platform_interface + sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_keyboard_visibility_web: + dependency: transitive + description: + name: flutter_keyboard_visibility_web + sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_keyboard_visibility_windows: + dependency: transitive + description: + name: flutter_keyboard_visibility_windows + sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: ee8068e0e1cd16c4a82714119918efdeed33b3ba7772c54b5d094ab53f9b7fd1 + url: "https://pub.dev" + source: hosted + version: "2.0.33" + flutter_rounded_date_picker: + dependency: "direct main" + description: + name: flutter_rounded_date_picker + sha256: e6aa2dc5d3b44e8bbe85ef901be69eac59ba4136427f11f4c8b2a303e1e774e7 + url: "https://pub.dev" + source: hosted + version: "3.0.4" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "87fbd7c534435b6c5d9d98b01e1fd527812b82e68ddd8bd35fc45ed0fa8f0a95" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_timer_countdown: + dependency: "direct main" + description: + name: flutter_timer_countdown + sha256: "0c73e1593ad7949c007752199a17e7ed50bb581568743dbc32f061f49873219e" + url: "https://pub.dev" + source: hosted + version: "1.0.7" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_zoom_drawer: + dependency: "direct main" + description: + name: flutter_zoom_drawer + sha256: "8488e3c01de7adf066daa16643b7de5cdff26b2deb637cbfc10b1fcea7b66157" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: "90778fe0497fe3a09166e8cf2e0867310ff434b794526589e77ec03cf08ba8e8" + url: "https://pub.dev" + source: hosted + version: "8.2.14" + functional_data: + dependency: transitive + description: + name: functional_data + sha256: "76d17dc707c40e552014f5a49c0afcc3f1e3f05e800cd6b7872940bfe41a5039" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + get: + dependency: "direct main" + description: + name: get + sha256: e4e7335ede17452b391ed3b2ede016545706c01a02292a6c97619705e7d2a85e + url: "https://pub.dev" + source: hosted + version: "4.6.6" + get_cli: + dependency: "direct main" + description: + name: get_cli + sha256: bac338bb889f8e72ec4d977ef3fe937e82339cb3e437d73582441fb4e43ef26f + url: "https://pub.dev" + source: hosted + version: "1.9.1" + getwidget: + dependency: "direct main" + description: + name: getwidget + sha256: "91df14a8d80e21f3ec02759295b90cc8badb8a872b90d34ad4aeb4085d833b5c" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + globbing: + dependency: transitive + description: + name: globbing + sha256: "4f89cfaf6fa74c9c1740a96259da06bd45411ede56744e28017cc534a12b6e2d" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + sha256: eefe5ee217f331627d8bbcf01f91b21c730bf66e225d6dc8a148370b0819168d + url: "https://pub.dev" + source: hosted + version: "7.0.0" + hive: + dependency: transitive + description: + name: hive + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + hive_flutter: + dependency: "direct main" + description: + name: hive_flutter + sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc + url: "https://pub.dev" + source: hosted + version: "1.1.0" + hooks: + dependency: transitive + description: + name: hooks + sha256: "7a08a0d684cb3b8fb604b78455d5d352f502b68079f7b80b831c62220ab0a4f6" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + http: + dependency: transitive + description: + name: http + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" + url: "https://pub.dev" + source: hosted + version: "1.6.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + image: + dependency: "direct main" + description: + name: image + sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d + url: "https://pub.dev" + source: hosted + version: "4.3.0" + ini: + dependency: transitive + description: + name: ini + sha256: "12a76c53591ffdf86d1265be3f986888a6dfeb34a85957774bc65912d989a173" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + intl: + dependency: transitive + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" + introduction_slider: + dependency: "direct main" + description: + name: introduction_slider + sha256: "0262f79d4eab0a0d9ffcedbb82e1120bac37ad8b7685a51de45a5386e847641d" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + js: + dependency: transitive + description: + name: js + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" + url: "https://pub.dev" + source: hosted + version: "0.7.2" + json2yaml: + dependency: transitive + description: + name: json2yaml + sha256: da94630fbc56079426fdd167ae58373286f603371075b69bf46d848d63ba3e51 + url: "https://pub.dev" + source: hosted + version: "3.0.1" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + json_serializable: + dependency: "direct main" + description: + name: json_serializable + sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969 + url: "https://pub.dev" + source: hosted + version: "6.7.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + url: "https://pub.dev" + source: hosted + version: "11.0.2" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + url: "https://pub.dev" + source: hosted + version: "3.0.10" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + lints: + dependency: transitive + description: + name: lints + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" + url: "https://pub.dev" + source: hosted + version: "6.1.0" + lists: + dependency: transitive + description: + name: lists + sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + loader_overlay: + dependency: "direct main" + description: + name: loader_overlay + sha256: "02deeeed0d4eaaeeada6ce7bb13426d7548acad1f71e4884ec4a010e0e4824d6" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + local_auth: + dependency: "direct main" + description: + name: local_auth + sha256: "280421b416b32de31405b0a25c3bd42dfcef2538dfbb20c03019e02a5ed55ed0" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + local_auth_android: + dependency: transitive + description: + name: local_auth_android + sha256: a0bdfcc0607050a26ef5b31d6b4b254581c3d3ce3c1816ab4d4f4a9173e84467 + url: "https://pub.dev" + source: hosted + version: "1.0.56" + local_auth_darwin: + dependency: transitive + description: + name: local_auth_darwin + sha256: "699873970067a40ef2f2c09b4c72eb1cfef64224ef041b3df9fdc5c4c1f91f49" + url: "https://pub.dev" + source: hosted + version: "1.6.1" + local_auth_platform_interface: + dependency: transitive + description: + name: local_auth_platform_interface + sha256: f98b8e388588583d3f781f6806e4f4c9f9e189d898d27f0c249b93a1973dd122 + url: "https://pub.dev" + source: hosted + version: "1.1.0" + local_auth_windows: + dependency: transitive + description: + name: local_auth_windows + sha256: bc4e66a29b0fdf751aafbec923b5bed7ad6ed3614875d8151afe2578520b2ab5 + url: "https://pub.dev" + source: hosted + version: "1.0.11" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + url: "https://pub.dev" + source: hosted + version: "0.12.17" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + url: "https://pub.dev" + source: hosted + version: "1.17.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mobile_scanner: + dependency: "direct main" + description: + name: mobile_scanner + sha256: "0b466a0a8a211b366c2e87f3345715faef9b6011c7147556ad22f37de6ba3173" + url: "https://pub.dev" + source: hosted + version: "6.0.11" + native_synchronization_temp: + dependency: transitive + description: + name: native_synchronization_temp + sha256: f9ad36a5054c606db10e3dc0c9c352e6d0d56d08621af5c470abf9fa41da40fa + url: "https://pub.dev" + source: hosted + version: "0.7.1" + native_toolchain_c: + dependency: transitive + description: + name: native_toolchain_c + sha256: "89e83885ba09da5fdf2cdacc8002a712ca238c28b7f717910b34bcd27b0d03ac" + url: "https://pub.dev" + source: hosted + version: "0.17.4" + nm: + dependency: transitive + description: + name: nm + sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" + url: "https://pub.dev" + source: hosted + version: "9.3.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 + url: "https://pub.dev" + source: hosted + version: "2.1.3" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e + url: "https://pub.dev" + source: hosted + version: "2.2.22" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: "74e962b7fad7ff75959161bb2c0ad8fe7f2568ee82621c9c2660b751146bfe44" + url: "https://pub.dev" + source: hosted + version: "11.3.0" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc + url: "https://pub.dev" + source: hosted + version: "12.1.0" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 + url: "https://pub.dev" + source: hosted + version: "9.4.7" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24" + url: "https://pub.dev" + source: hosted + version: "0.1.3+5" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878 + url: "https://pub.dev" + source: hosted + version: "4.3.0" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" + url: "https://pub.dev" + source: hosted + version: "0.2.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" + url: "https://pub.dev" + source: hosted + version: "7.0.2" + pin_code_fields: + dependency: "direct main" + description: + name: pin_code_fields + sha256: "4c0db7fbc889e622e7c71ea54b9ee624bb70c7365b532abea0271b17ea75b729" + url: "https://pub.dev" + source: hosted + version: "8.0.1" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pointycastle: + dependency: "direct main" + description: + name: pointycastle + sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" + url: "https://pub.dev" + source: hosted + version: "3.9.1" + posix: + dependency: transitive + description: + name: posix + sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" + url: "https://pub.dev" + source: hosted + version: "6.0.3" + process_run: + dependency: transitive + description: + name: process_run + sha256: "4e789d1ac24da46fdb61269fd85b42a08f787c752cc16b65f4cad5e4c20d37f8" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + pubspec_lock: + dependency: transitive + description: + name: pubspec_lock + sha256: ed5fc1ecd0cdc0e14475a091afcb2c4cbb00e74cebff17635e9abbec18d76cc4 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + pubspec_manager: + dependency: transitive + description: + name: pubspec_manager + sha256: "416609635f6c53ab759223ae66e71282e61a863c13ec47d60381e4b8046c2a71" + url: "https://pub.dev" + source: hosted + version: "1.0.3" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + qr: + dependency: transitive + description: + name: qr + sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + qr_flutter: + dependency: "direct main" + description: + name: qr_flutter + sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097" + url: "https://pub.dev" + source: hosted + version: "4.1.0" + quickalert: + dependency: "direct main" + description: + name: quickalert + sha256: "0c21c9be68b9ae76082e1ad56db9f51202a38e617e08376f05375238277cfb5a" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + recase: + dependency: transitive + description: + name: recase + sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213 + url: "https://pub.dev" + source: hosted + version: "4.1.0" + responsive_framework: + dependency: "direct main" + description: + name: responsive_framework + sha256: "52367ab0c3479b3a5342dec3b74a3d47c4cc1b45bb5d38f720c2e002ebccd4ee" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + root_checker_plus: + dependency: "direct main" + description: + name: root_checker_plus + sha256: "79087f93413240ac4842859eef55f8a63b748b402c4353b3446a558b1a352d16" + url: "https://pub.dev" + source: hosted + version: "0.0.7" + scope: + dependency: transitive + description: + name: scope + sha256: "0b056e5b64ca16a2db9e1eb35cf7fd05a9e99a6b15140f82bfa651d081e4819b" + url: "https://pub.dev" + source: hosted + version: "5.1.0" + screenshot: + dependency: "direct main" + description: + name: screenshot + sha256: "63817697a7835e6ce82add4228e15d233b74d42975c143ad8cfe07009fab866b" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + settings_yaml: + dependency: transitive + description: + name: settings_yaml + sha256: "8fec1ab4c6ed5efb61cd336e8a86d62c24026d97b08646db00e959d9cc7b11a2" + url: "https://pub.dev" + source: hosted + version: "8.3.1" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: "14c8860d4de93d3a7e53af51bff479598c4e999605290756bbbe45cf65b37840" + url: "https://pub.dev" + source: hosted + version: "12.0.1" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a" + url: "https://pub.dev" + source: hosted + version: "6.1.0" + simple_speed_dial: + dependency: "direct main" + description: + name: simple_speed_dial + sha256: b8322649ac3a6ab1ed1153e005efe90d48e6cb5b2b4e264ca0997cf1e88006fa + url: "https://pub.dev" + source: hosted + version: "0.1.7" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c" + url: "https://pub.dev" + source: hosted + version: "1.3.5" + source_span: + dependency: transitive + description: + name: source_span + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" + url: "https://pub.dev" + source: hosted + version: "1.10.2" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + string_validator: + dependency: "direct main" + description: + name: string_validator + sha256: "54d4f42cd6878ae72793a58a529d9a18ebfdfbfebd9793bbe55c9b28935e8543" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + strings: + dependency: transitive + description: + name: strings + sha256: "052836499f03897d3860a603b330c1ea3c8a14177b21f34b15a1295f36024aae" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + stylish_bottom_bar: + dependency: "direct main" + description: + name: stylish_bottom_bar + sha256: "54970e4753b4273239b6dea0d1175c56beabcf39b5c65df4cbf86f1b86568d2b" + url: "https://pub.dev" + source: hosted + version: "1.0.3" + sum_types: + dependency: transitive + description: + name: sum_types + sha256: c0a0fad9a518d011987e1d9f27fc336194294e55dafdc3699363e52aa5776e09 + url: "https://pub.dev" + source: hosted + version: "0.3.5" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 + url: "https://pub.dev" + source: hosted + version: "3.4.0" + system_info2: + dependency: transitive + description: + name: system_info2 + sha256: b937736ecfa63c45b10dde1ceb6bb30e5c0c340e14c441df024150679d65ac43 + url: "https://pub.dev" + source: hosted + version: "4.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + url: "https://pub.dev" + source: hosted + version: "0.7.7" + timer_count_down: + dependency: "direct main" + description: + name: timer_count_down + sha256: d025d408c2654e497ca0bd4bde014bd7509d4c6397af4ed23a0f9b692bbcf337 + url: "https://pub.dev" + source: hosted + version: "2.2.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + unicode: + dependency: transitive + description: + name: unicode + sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1" + url: "https://pub.dev" + source: hosted + version: "0.3.1" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a + url: "https://pub.dev" + source: hosted + version: "3.2.2" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f + url: "https://pub.dev" + source: hosted + version: "2.4.2" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + uuid: + dependency: transitive + description: + name: uuid + sha256: a11b666489b1954e01d992f3d601b1804a33937b5a8fe677bd26b8a9f96f96e8 + url: "https://pub.dev" + source: hosted + version: "4.5.2" + validators2: + dependency: transitive + description: + name: validators2 + sha256: "4e9d7b13989d2a32b8e5ff21cec3e45b62a6eb826bc1d3deeb18963913c76e3a" + url: "https://pub.dev" + source: hosted + version: "5.1.0" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6 + url: "https://pub.dev" + source: hosted + version: "1.1.19" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" + url: "https://pub.dev" + source: hosted + version: "1.1.13" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "201e876b5d52753626af64b6359cd13ac6011b80728731428fd34bc840f71c9b" + url: "https://pub.dev" + source: hosted + version: "1.1.20" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" + source: hosted + version: "2.2.0" + version: + dependency: transitive + description: + name: version + sha256: "3d4140128e6ea10d83da32fef2fa4003fccbf6852217bb854845802f04191f94" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + url: "https://pub.dev" + source: hosted + version: "15.0.2" + watcher: + dependency: transitive + description: + name: watcher + sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + win32: + dependency: transitive + description: + name: win32 + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e + url: "https://pub.dev" + source: hosted + version: "5.15.0" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852" + url: "https://pub.dev" + source: hosted + version: "1.1.5" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" + url: "https://pub.dev" + source: hosted + version: "6.6.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" +sdks: + dart: ">=3.10.7 <4.0.0" + flutter: ">=3.38.4" diff --git a/pubspec.yaml b/pubspec.yaml index f13668d..2301600 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,7 +19,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ^3.9.2 + sdk: ^3.10.7 # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -34,6 +34,62 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 + get: 4.6.6 + google_fonts: 7.0.0 + hive_flutter: 1.1.0 + introduction_slider: 2.0.1 + flutter_custom_clippers: 2.1.0 + fluttertoast: ^8.2.12 + pin_code_fields: 8.0.1 + # url_launcher: ^6.3.2 + timer_count_down: 2.2.2 + flutter_timer_countdown: ^1.0.7 + flutter_zoom_drawer: 3.1.2 + quickalert: 1.0.2 + simple_speed_dial: 0.1.7 + stylish_bottom_bar: 1.0.3 + dropdown_button2: 2.3.9 + flutter_contacts: ^1.1.9+2 + permission_handler: 11.3.0 + flutter_form_builder: 9.2.1 + camera: ^0.10.5+2 + flutter_camera_overlay_new: 0.0.1 + flutter_svg: ^2.2.3 + responsive_framework: 1.4.0 + local_auth: 2.2.0 + dio: 4.0.6 + share_plus: ^12.0.1 + string_validator: 1.0.2 + country_code_picker: 3.0.0 + loader_overlay: 4.0.0 + getwidget: 4.0.0 + flutter_rounded_date_picker: 3.0.4 + calendar_date_picker2: 1.0.2 + json_serializable: 6.7.1 + buttons_tabbar: 1.3.8 + # google_maps_flutter: 2.14.0 + path_provider: 2.1.3 + # image_picker: ^1.2.1 + qr_flutter: ^4.1.0 + mobile_scanner: ^6.0.10 + screenshot: 3.0.0 + # image_gallery_saver: 2.0.1 + flutter_keyboard_visibility: 6.0.0 + # qr_code_scanner: + # git: + # url: https://github.com/liang-notes/qr_code_scanner + # ref: enable-scan-qrcode-from-gallery + animated_toggle_switch: ^0.8.2 + auto_size_text: ^3.0.0 + image: ^4.2.0 + connectivity_plus: ^6.0.3 + get_cli: ^1.8.0 + # flutter_windowmanager: ^0.2.0 + device_info_plus: ^10.1.0 + root_checker_plus: ^0.0.3 + encrypt: ^5.0.3 + pointycastle: ^3.9.1 + flutter_dotenv: ^5.1.0 dev_dependencies: flutter_test: @@ -44,7 +100,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^5.0.0 + flutter_lints: ^6.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec @@ -58,9 +114,13 @@ flutter: uses-material-design: true # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg + assets: + - assets/ + - assets/uco/ + - assets/uco/icons/ + - assets/uco/images/ + - assets/uco/logo/ + - assets/.en # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/to/resolution-aware-images @@ -73,11 +133,22 @@ flutter: # "family" key with the font family name, and a "fonts" key with a # list giving the asset and other descriptors for the font. For # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf + fonts: + - family: Inter + fonts: + - asset: fonts/Inter-Black.ttf + - asset: fonts/Inter-Bold.ttf + - asset: fonts/Inter-ExtraBold.ttf + - asset: fonts/Inter-ExtraLight.ttf + - asset: fonts/Inter-Light.ttf + - asset: fonts/Inter-Medium.ttf + - asset: fonts/Inter-Regular.ttf + - asset: fonts/Inter-SemiBold.ttf + - asset: fonts/Inter-Thin.ttf + - family: Poppins + fonts: + - asset: fonts/Poppins-Regular.ttf + - asset: fonts/Poppins-Medium.ttf # style: italic # - family: Trajan Pro # fonts: diff --git a/test/widget_test.dart b/test/widget_test.dart index ebd2222..f56e261 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -7,13 +7,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; - import 'package:uco_mobile_poc/main.dart'; + void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); + await tester.pumpWidget(const MyApp(apiKey: '',)); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget);